2004-08-22 22:29:09 +00:00
/*
Copyright ( C ) 1996 - 1997 Id Software , Inc .
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation ; either version 2
of the License , or ( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
2005-06-15 04:36:20 +00:00
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
2004-08-22 22:29:09 +00:00
See the GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
2013-03-12 22:54:12 +00:00
2014-03-30 00:39:37 +00:00
/*
Small note : anything concerning EGL in here is specific to egl - with - x11 .
if you want egl - with - framebuffer , look elsewhere .
*/
2013-03-12 22:54:12 +00:00
/*
X11 is a huge pile of shit . I don ' t mean just the old x11 protocol , but all the _current_ standards that don ' t even try to fix the issues too .
Its fucking retarded the crap that you have to do to get something to work .
timeouts to ensure alt + tab between two apps doesn ' t fuck up gamma ramps is NOT a nice thing to have to do .
_MOUSE_ grabs cause alt + tab to fuck up
if I use xinput2 to get raw mouse events ( so that I don ' t have to use some random hack to disable acceleration and risk failing to reset it on crashes ) , then the mouse still moves outside of our window , and trying to fire then looses focus . . .
xf86vm extension results in scrolling around a larger viewport . dependant upon the mouse position . even if we constrain the mouse to our window , it ' ll still scroll .
warping the pointer still triggers ' raw ' mouse move events . in what world does that make any sense ? ! ?
alt - tab task lists are a window in their own right . that ' s okay , but what ' s not okay is that they destroy that window without giving focus to the new window first , so the old one gets focus and that fucks everything up too . yay for timeouts .
to allow alt - tabbing with window managers that do not respect requests to not shove stuff on us , we have to hide ourselves completely and create a separate window that can still accept focus from the window manager . its fecking vile .
window managers reparent us too , in much the same way . which is a bad thing because we keep getting reparented and that makes a mess of focus events . its a nightmare .
the whole thing is bloody retarded .
none of these issues will be fixed by a compositing window manager , because there ' s still a window manager there .
*/
2004-08-22 22:29:09 +00:00
# include <termios.h>
# include <sys/ioctl.h>
# include <sys/stat.h>
2005-04-19 19:31:15 +00:00
# ifdef __linux__
2004-08-22 22:29:09 +00:00
# include <sys/vt.h>
# endif
# include <stdarg.h>
# include <stdio.h>
# include <signal.h>
# include <dlfcn.h>
# include "quakedef.h"
2013-03-12 22:47:42 +00:00
# include <X11/Xlib.h>
# include <X11/Xatom.h>
2016-07-12 00:40:13 +00:00
# include <X11/Xutil.h>
2004-08-22 22:29:09 +00:00
2016-07-12 00:40:13 +00:00
# ifdef VKQUAKE
# include "vk/vkrenderer.h"
2016-07-30 17:59:55 +00:00
static qboolean XVK_SetupSurface_XLib ( void ) ;
static qboolean XVK_SetupSurface_XCB ( void ) ;
2016-07-12 00:40:13 +00:00
# endif
# ifdef GLQUAKE
2004-08-22 22:29:09 +00:00
# include <GL/glx.h>
2011-02-06 20:56:39 +00:00
# ifdef USE_EGL
2011-03-24 14:35:24 +00:00
# include "gl_videgl.h"
2011-02-06 20:56:39 +00:00
# endif
2014-03-30 00:39:37 +00:00
# include "glquake.h"
2016-07-12 00:40:13 +00:00
# endif
2004-08-22 22:29:09 +00:00
# include <X11/keysym.h>
# include <X11/cursorfont.h>
static Display * vid_dpy = NULL ;
2012-10-14 10:57:11 +00:00
static Cursor vid_nullcursor ;
2004-08-22 22:29:09 +00:00
static Window vid_window ;
2013-03-12 22:47:42 +00:00
static Window vid_decoywindow ; //for legacy mode, this is a boring window that we can reparent into as needed
static Window vid_root ;
2016-07-12 00:40:13 +00:00
# ifdef GLQUAKE
2004-08-22 22:29:09 +00:00
static GLXContext ctx = NULL ;
2016-07-12 00:40:13 +00:00
# endif
2013-03-12 22:47:42 +00:00
static int scrnum ;
2014-03-30 00:39:37 +00:00
static long vid_x_eventmask ;
2013-03-12 22:49:04 +00:00
static enum
{
PSL_NONE ,
2016-07-12 00:40:13 +00:00
# ifdef GLQUAKE
2013-03-12 22:49:04 +00:00
# ifdef USE_EGL
PSL_EGL ,
# endif
2016-07-12 00:40:13 +00:00
PSL_GLX ,
# endif
# ifdef VKQUAKE
PSL_VULKAN ,
# endif
2013-03-12 22:49:04 +00:00
} currentpsl ;
2004-08-22 22:29:09 +00:00
2013-03-12 22:47:42 +00:00
extern cvar_t vid_conautoscale ;
2004-08-22 22:29:09 +00:00
2013-03-12 23:03:46 +00:00
extern int sys_parentleft ;
extern int sys_parenttop ;
extern int sys_parentwidth ;
extern int sys_parentheight ;
extern long sys_parentwindow ;
2004-08-22 22:29:09 +00:00
# define KEY_MASK (KeyPressMask | KeyReleaseMask)
# define MOUSE_MASK (ButtonPressMask | ButtonReleaseMask | \
PointerMotionMask )
2004-12-05 08:25:01 +00:00
# define X_MASK (KEY_MASK | MOUSE_MASK | ResizeRequest | StructureNotifyMask | FocusChangeMask | VisibilityChangeMask)
2004-08-22 22:29:09 +00:00
2014-03-30 00:39:37 +00:00
struct _XrmHashBucketRec ;
2013-03-12 23:04:11 +00:00
static struct
{
void * lib ;
int ( * pXChangeProperty ) ( Display * display , Window w , Atom property , Atom type , int format , int mode , unsigned char * data , int nelements ) ;
int ( * pXCloseDisplay ) ( Display * display ) ;
int ( * pXConvertSelection ) ( Display * display , Atom selection , Atom target , Atom property , Window requestor , Time time ) ;
Colormap ( * pXCreateColormap ) ( Display * display , Window w , Visual * visual , int alloc ) ;
GC ( * pXCreateGC ) ( Display * display , Drawable d , unsigned long valuemask , XGCValues * values ) ;
Pixmap ( * pXCreatePixmap ) ( Display * display , Drawable d , unsigned int width , unsigned int height , unsigned int depth ) ;
Cursor ( * pXCreatePixmapCursor ) ( Display * display , Pixmap source , Pixmap mask , XColor * foreground_color , XColor * background_color , unsigned int x , unsigned int y ) ;
Window ( * pXCreateWindow ) ( Display * display , Window parent , int x , int y , unsigned int width , unsigned int height , unsigned int border_width , int depth , unsigned int class , Visual * visual , unsigned long valuemask , XSetWindowAttributes * attributes ) ;
int ( * pXDefineCursor ) ( Display * display , Window w , Cursor cursor ) ;
int ( * pXDestroyWindow ) ( Display * display , Window w ) ;
int ( * pXFillRectangle ) ( Display * display , Drawable d , GC gc , int x , int y , unsigned int width , unsigned int height ) ;
int ( * pXFlush ) ( Display * display ) ;
int ( * pXFree ) ( void * data ) ;
int ( * pXFreeCursor ) ( Display * display , Cursor cursor ) ;
void ( * pXFreeEventData ) ( Display * display , XGenericEventCookie * cookie ) ;
int ( * pXFreeGC ) ( Display * display , GC gc ) ;
int ( * pXFreePixmap ) ( Display * display , Pixmap pixmap ) ;
char * ( * pXGetAtomName ) ( Display * display , Atom atom ) ;
Bool ( * pXGetEventData ) ( Display * display , XGenericEventCookie * cookie ) ;
Window ( * pXGetSelectionOwner ) ( Display * display , Atom selection ) ;
Status ( * pXGetWindowAttributes ) ( Display * display , Window w , XWindowAttributes * window_attributes_return ) ;
int ( * pXGetWindowProperty ) ( Display * display , Window w , Atom property , long long_offset , long long_length , Bool delete , Atom req_type , Atom * actual_type_return , int * actual_format_return , unsigned long * nitems_return , unsigned long * bytes_after_return , unsigned char * * prop_return ) ;
int ( * pXGrabKeyboard ) ( Display * display , Window grab_window , Bool owner_events , int pointer_mode , int keyboard_mode , Time time ) ;
int ( * pXGrabPointer ) ( Display * display , Window grab_window , Bool owner_events , unsigned int event_mask , int pointer_mode , int keyboard_mode , Window confine_to , Cursor cursor , Time time ) ;
Atom ( * pXInternAtom ) ( Display * display , char * atom_name , Bool only_if_exists ) ;
KeySym ( * pXLookupKeysym ) ( XKeyEvent * key_event , int index ) ;
int ( * pXLookupString ) ( XKeyEvent * event_struct , char * buffer_return , int bytes_buffer , KeySym * keysym_return , XComposeStatus * status_in_out ) ;
int ( * pXMapWindow ) ( Display * display , Window w ) ;
int ( * pXMoveResizeWindow ) ( Display * display , Window w , int x , int y , unsigned width , unsigned height ) ;
int ( * pXMoveWindow ) ( Display * display , Window w , int x , int y ) ;
int ( * pXNextEvent ) ( Display * display , XEvent * event_return ) ;
Display * ( * pXOpenDisplay ) ( char * display_name ) ;
int ( * pXPending ) ( Display * display ) ;
Bool ( * pXQueryExtension ) ( Display * display , const char * name , int * major_opcode_return , int * first_event_return , int * first_error_return ) ;
int ( * pXRaiseWindow ) ( Display * display , Window w ) ;
int ( * pXReparentWindow ) ( Display * display , Window w , Window parent , int x , int y ) ;
int ( * pXResizeWindow ) ( Display * display , Window w , unsigned width , unsigned height ) ;
int ( * pXSelectInput ) ( Display * display , Window w , long event_mask ) ;
Status ( * pXSendEvent ) ( Display * display , Window w , Bool propagate , long event_mask , XEvent * event_send ) ;
int ( * pXSetIconName ) ( Display * display , Window w , char * icon_name ) ;
int ( * pXSetInputFocus ) ( Display * display , Window focus , int revert_to , Time time ) ;
int ( * pXSetSelectionOwner ) ( Display * display , Atom selection , Window owner , Time time ) ;
void ( * pXSetWMNormalHints ) ( Display * display , Window w , XSizeHints * hints ) ;
Status ( * pXSetWMProtocols ) ( Display * display , Window w , Atom * protocols , int count ) ;
int ( * pXStoreName ) ( Display * display , Window w , char * window_name ) ;
int ( * pXSync ) ( Display * display , Bool discard ) ;
int ( * pXUndefineCursor ) ( Display * display , Window w ) ;
int ( * pXUngrabKeyboard ) ( Display * display , Time time ) ;
int ( * pXUngrabPointer ) ( Display * display , Time time ) ;
int ( * pXWarpPointer ) ( Display * display , Window src_w , Window dest_w , int src_x , int src_y , unsigned int src_width , unsigned int src_height , int dest_x , int dest_y ) ;
2014-03-30 00:39:37 +00:00
Status ( * pXMatchVisualInfo ) ( Display * display , int screen , int depth , int class , XVisualInfo * vinfo_return ) ;
char * ( * pXSetLocaleModifiers ) ( char * modifier_list ) ;
Bool ( * pXSupportsLocale ) ( void ) ;
XIM ( * pXOpenIM ) ( Display * display , struct _XrmHashBucketRec * db , char * res_name , char * res_class ) ;
2015-09-10 10:16:26 +00:00
char * ( * pXGetIMValues ) ( XIM im , . . . ) ;
2014-03-30 00:39:37 +00:00
XIC ( * pXCreateIC ) ( XIM im , . . . ) ;
void ( * pXSetICFocus ) ( XIC ic ) ;
char * ( * pXGetICValues ) ( XIC ic , . . . ) ;
Bool ( * pXFilterEvent ) ( XEvent * event , Window w ) ;
int ( * pXutf8LookupString ) ( XIC ic , XKeyPressedEvent * event , char * buffer_return , int bytes_buffer , KeySym * keysym_return , Status * status_return ) ;
int ( * pXwcLookupString ) ( XIC ic , XKeyPressedEvent * event , wchar_t * buffer_return , int bytes_buffer , KeySym * keysym_return , Status * status_return ) ;
void ( * pXDestroyIC ) ( XIC ic ) ;
Status ( * pXCloseIM ) ( XIM im ) ;
qboolean dounicode ;
XIC unicodecontext ;
XIM inputmethod ;
2013-03-12 23:04:11 +00:00
} x11 ;
2016-07-30 17:59:55 +00:00
2013-03-12 23:04:11 +00:00
static qboolean x11_initlib ( void )
{
2016-07-30 17:59:55 +00:00
static dllfunction_t x11_functable [ ] =
2013-03-12 23:04:11 +00:00
{
{ ( void * * ) & x11 . pXChangeProperty , " XChangeProperty " } ,
{ ( void * * ) & x11 . pXCloseDisplay , " XCloseDisplay " } ,
{ ( void * * ) & x11 . pXConvertSelection , " XConvertSelection " } ,
{ ( void * * ) & x11 . pXCreateColormap , " XCreateColormap " } ,
{ ( void * * ) & x11 . pXCreateGC , " XCreateGC " } ,
{ ( void * * ) & x11 . pXCreatePixmap , " XCreatePixmap " } ,
{ ( void * * ) & x11 . pXCreatePixmapCursor , " XCreatePixmapCursor " } ,
{ ( void * * ) & x11 . pXCreateWindow , " XCreateWindow " } ,
{ ( void * * ) & x11 . pXDefineCursor , " XDefineCursor " } ,
{ ( void * * ) & x11 . pXDestroyWindow , " XDestroyWindow " } ,
{ ( void * * ) & x11 . pXFillRectangle , " XFillRectangle " } ,
{ ( void * * ) & x11 . pXFlush , " XFlush " } ,
{ ( void * * ) & x11 . pXFree , " XFree " } ,
{ ( void * * ) & x11 . pXFreeCursor , " XFreeCursor " } ,
{ ( void * * ) & x11 . pXFreeGC , " XFreeGC " } ,
{ ( void * * ) & x11 . pXFreePixmap , " XFreePixmap " } ,
{ ( void * * ) & x11 . pXGetAtomName , " XGetAtomName " } ,
{ ( void * * ) & x11 . pXGetSelectionOwner , " XGetSelectionOwner " } ,
{ ( void * * ) & x11 . pXGetWindowAttributes , " XGetWindowAttributes " } ,
{ ( void * * ) & x11 . pXGetWindowProperty , " XGetWindowProperty " } ,
{ ( void * * ) & x11 . pXGrabKeyboard , " XGrabKeyboard " } ,
{ ( void * * ) & x11 . pXGrabPointer , " XGrabPointer " } ,
{ ( void * * ) & x11 . pXInternAtom , " XInternAtom " } ,
{ ( void * * ) & x11 . pXLookupKeysym , " XLookupKeysym " } ,
{ ( void * * ) & x11 . pXLookupString , " XLookupString " } ,
{ ( void * * ) & x11 . pXMapWindow , " XMapWindow " } ,
{ ( void * * ) & x11 . pXMoveResizeWindow , " XMoveResizeWindow " } ,
{ ( void * * ) & x11 . pXMoveWindow , " XMoveWindow " } ,
{ ( void * * ) & x11 . pXNextEvent , " XNextEvent " } ,
{ ( void * * ) & x11 . pXOpenDisplay , " XOpenDisplay " } ,
{ ( void * * ) & x11 . pXPending , " XPending " } ,
{ ( void * * ) & x11 . pXQueryExtension , " XQueryExtension " } ,
{ ( void * * ) & x11 . pXRaiseWindow , " XRaiseWindow " } ,
{ ( void * * ) & x11 . pXReparentWindow , " XReparentWindow " } ,
{ ( void * * ) & x11 . pXResizeWindow , " XResizeWindow " } ,
{ ( void * * ) & x11 . pXSelectInput , " XSelectInput " } ,
{ ( void * * ) & x11 . pXSendEvent , " XSendEvent " } ,
{ ( void * * ) & x11 . pXSetIconName , " XSetIconName " } ,
{ ( void * * ) & x11 . pXSetInputFocus , " XSetInputFocus " } ,
{ ( void * * ) & x11 . pXSetSelectionOwner , " XSetSelectionOwner " } ,
{ ( void * * ) & x11 . pXSetWMNormalHints , " XSetWMNormalHints " } ,
{ ( void * * ) & x11 . pXSetWMProtocols , " XSetWMProtocols " } ,
{ ( void * * ) & x11 . pXStoreName , " XStoreName " } ,
{ ( void * * ) & x11 . pXSync , " XSync " } ,
{ ( void * * ) & x11 . pXUndefineCursor , " XUndefineCursor " } ,
{ ( void * * ) & x11 . pXUngrabKeyboard , " XUngrabKeyboard " } ,
{ ( void * * ) & x11 . pXUngrabPointer , " XUngrabPointer " } ,
{ ( void * * ) & x11 . pXWarpPointer , " XWarpPointer " } ,
2014-03-30 00:39:37 +00:00
{ ( void * * ) & x11 . pXMatchVisualInfo , " XMatchVisualInfo " } ,
2013-03-12 23:04:11 +00:00
{ NULL , NULL }
} ;
if ( ! x11 . lib )
{
2013-11-21 23:02:28 +00:00
# ifdef __CYGWIN__
x11 . lib = Sys_LoadLibrary ( " cygX11-6.dll " , x11_functable ) ;
# else
2013-05-13 13:43:18 +00:00
x11 . lib = Sys_LoadLibrary ( " libX11.so.6 " , x11_functable ) ;
2013-11-21 23:02:28 +00:00
# endif
2013-05-13 13:43:18 +00:00
if ( ! x11 . lib )
x11 . lib = Sys_LoadLibrary ( " libX11 " , x11_functable ) ;
2013-03-12 23:04:11 +00:00
//these ones are extensions, and the reason we're doing this.
if ( x11 . lib )
{
2014-03-30 00:39:37 +00:00
//raw input (yay mouse deltas)
x11 . pXGetEventData = Sys_GetAddressForName ( x11 . lib , " XGetEventData " ) ;
x11 . pXFreeEventData = Sys_GetAddressForName ( x11 . lib , " XFreeEventData " ) ;
//internationalisation
x11 . pXSetLocaleModifiers = Sys_GetAddressForName ( x11 . lib , " XSetLocaleModifiers " ) ;
x11 . pXSupportsLocale = Sys_GetAddressForName ( x11 . lib , " XSupportsLocale " ) ;
x11 . pXOpenIM = Sys_GetAddressForName ( x11 . lib , " XOpenIM " ) ;
2015-09-10 10:16:26 +00:00
x11 . pXGetIMValues = Sys_GetAddressForName ( x11 . lib , " XGetIMValues " ) ;
2014-03-30 00:39:37 +00:00
x11 . pXCreateIC = Sys_GetAddressForName ( x11 . lib , " XCreateIC " ) ;
x11 . pXSetICFocus = Sys_GetAddressForName ( x11 . lib , " XSetICFocus " ) ;
x11 . pXGetICValues = Sys_GetAddressForName ( x11 . lib , " XGetICValues " ) ;
x11 . pXFilterEvent = Sys_GetAddressForName ( x11 . lib , " XFilterEvent " ) ;
x11 . pXutf8LookupString = Sys_GetAddressForName ( x11 . lib , " Xutf8LookupString " ) ;
x11 . pXwcLookupString = Sys_GetAddressForName ( x11 . lib , " XwcLookupString " ) ;
x11 . pXDestroyIC = Sys_GetAddressForName ( x11 . lib , " XDestroyIC " ) ;
x11 . pXCloseIM = Sys_GetAddressForName ( x11 . lib , " XCloseIM " ) ;
2013-03-12 23:04:11 +00:00
}
2013-05-13 13:43:18 +00:00
else
{
Con_Printf ( " Unable to load libX11 \n " ) ;
}
2013-03-12 23:04:11 +00:00
}
return ! ! x11 . lib ;
}
2004-08-22 22:29:09 +00:00
2016-07-30 17:59:55 +00:00
# ifdef VK_USE_PLATFORM_XCB_KHR
static struct
{
void * lib ;
xcb_connection_t * ( * pXGetXCBConnection ) ( Display * dpy ) ;
} x11xcb ;
static qboolean x11xcb_initlib ( void )
{
static dllfunction_t x11xcb_functable [ ] =
{
{ ( void * * ) & x11xcb . pXGetXCBConnection , " XGetXCBConnection " } ,
{ NULL , NULL }
} ;
if ( ! x11xcb . lib )
{
x11xcb . lib = Sys_LoadLibrary ( " libX11-xcb.so.1 " , x11xcb_functable ) ;
if ( ! x11xcb . lib )
x11xcb . lib = Sys_LoadLibrary ( " libX11-xcb " , x11xcb_functable ) ;
if ( ! x11xcb . lib )
Con_Printf ( " Unable to load libX11-xcb \n " ) ;
}
return ! ! x11xcb . lib ;
}
# endif
2013-03-12 22:54:12 +00:00
# define FULLSCREEN_VMODE 1 //using xf86 vidmode (we can actually change modes)
2013-03-12 22:47:42 +00:00
# define FULLSCREEN_VMODEACTIVE 2 //xf86 vidmode currently forced
# define FULLSCREEN_LEGACY 4 //override redirect used
# define FULLSCREEN_WM 8 //fullscreen hint used
# define FULLSCREEN_ACTIVE 16 //currently fullscreen
static int fullscreenflags ;
static int fullscreenwidth ;
static int fullscreenheight ;
void X_GoFullscreen ( void ) ;
void X_GoWindowed ( void ) ;
/*when alt-tabbing or whatever, the window manager creates a window, then destroys it again, resulting in weird focus events that trigger mode switches and grabs. using a timer reduces the weirdness and allows alt-tab to work properly. or at least better than it was working. that's the theory anyway*/
static unsigned int modeswitchtime ;
static int modeswitchpending ;
2013-03-12 22:54:12 +00:00
typedef struct
{
unsigned int dotclock ;
unsigned short hdisplay ;
unsigned short hsyncstart ;
unsigned short hsyncend ;
unsigned short htotal ;
unsigned short hskew ;
unsigned short vdisplay ;
unsigned short vsyncstart ;
unsigned short vsyncend ;
unsigned short vtotal ;
unsigned int flags ;
} XF86VidModeModeInfo ; //we don't touch this struct
static struct
{
int opcode , event , error ;
int vmajor , vminor ;
void * lib ;
Bool ( * pXF86VidModeQueryVersion ) ( Display * dpy , int * majorVersion , int * minorVersion ) ;
Bool ( * pXF86VidModeGetGammaRampSize ) ( Display * dpy , int screen , int * size ) ;
Bool ( * pXF86VidModeGetGammaRamp ) ( Display * dpy , int screen , int size , unsigned short * red , unsigned short * green , unsigned short * blue ) ;
Bool ( * pXF86VidModeSetGammaRamp ) ( Display * dpy , int screen , int size , unsigned short * red , unsigned short * green , unsigned short * blue ) ;
Bool ( * pXF86VidModeSetViewPort ) ( Display * dpy , int screen , int x , int y ) ;
Bool ( * pXF86VidModeSwitchToMode ) ( Display * dpy , int screen , XF86VidModeModeInfo * modeline ) ;
Bool ( * pXF86VidModeGetAllModeLines ) ( Display * dpy , int screen , int * modecount , XF86VidModeModeInfo * * * modelinesPtr ) ;
XF86VidModeModeInfo * * modes ;
int num_modes ;
int usemode ;
2016-07-28 15:57:22 +00:00
unsigned short originalramps [ 3 ] [ 2048 ] ;
2013-03-12 22:54:12 +00:00
qboolean originalapplied ; //states that the origionalramps arrays are valid, and contain stuff that we should revert to on close
2016-07-28 15:57:22 +00:00
int originalrampsize ;
2013-03-12 22:54:12 +00:00
} vm ;
static qboolean VMODE_Init ( void )
{
2016-07-30 17:59:55 +00:00
static dllfunction_t vm_functable [ ] =
2013-03-12 22:54:12 +00:00
{
{ ( void * * ) & vm . pXF86VidModeQueryVersion , " XF86VidModeQueryVersion " } ,
{ ( void * * ) & vm . pXF86VidModeGetGammaRampSize , " XF86VidModeGetGammaRampSize " } ,
{ ( void * * ) & vm . pXF86VidModeGetGammaRamp , " XF86VidModeGetGammaRamp " } ,
{ ( void * * ) & vm . pXF86VidModeSetGammaRamp , " XF86VidModeSetGammaRamp " } ,
{ ( void * * ) & vm . pXF86VidModeSetViewPort , " XF86VidModeSetViewPort " } ,
{ ( void * * ) & vm . pXF86VidModeSwitchToMode , " XF86VidModeSwitchToMode " } ,
{ ( void * * ) & vm . pXF86VidModeGetAllModeLines , " XF86VidModeGetAllModeLines " } ,
{ NULL , NULL }
} ;
vm . vmajor = 0 ;
vm . vminor = 0 ;
vm . usemode = - 1 ;
vm . originalapplied = false ;
if ( COM_CheckParm ( " -novmode " ) )
return false ;
2013-03-12 23:04:11 +00:00
if ( ! x11 . pXQueryExtension ( vid_dpy , " XFree86-VidModeExtension " , & vm . opcode , & vm . event , & vm . error ) )
2013-03-12 22:54:12 +00:00
{
2014-03-30 00:39:37 +00:00
Con_Printf ( " VidModeExtension extension not available. \n " ) ;
2013-03-12 22:54:12 +00:00
return false ;
}
if ( ! vm . lib )
vm . lib = Sys_LoadLibrary ( " libXxf86vm " , vm_functable ) ;
if ( vm . lib )
{
2014-03-30 00:39:37 +00:00
if ( vm . pXF86VidModeQueryVersion ( vid_dpy , & vm . vmajor , & vm . vminor ) )
2014-03-30 08:55:06 +00:00
Con_Printf ( " Using XF86-VidModeExtension Ver. %d.%d \n " , vm . vmajor , vm . vminor ) ;
2013-03-12 22:54:12 +00:00
else
2014-03-30 00:39:37 +00:00
{
Con_Printf ( " No XF86-VidModeExtension support \n " ) ;
2013-03-12 22:54:12 +00:00
vm . vmajor = 0 ;
2014-03-30 00:39:37 +00:00
vm . vminor = 0 ;
}
2013-03-12 22:54:12 +00:00
}
return vm . vmajor ;
}
2004-08-22 22:29:09 +00:00
extern cvar_t _windowed_mouse ;
2013-03-12 22:54:12 +00:00
static float old_windowed_mouse = 0 ;
static enum
{
XIM_ORIG ,
XIM_DGA ,
XIM_XI2 ,
} x11_input_method ;
# define XF86DGADirectMouse 0x0004
static struct
{
int opcode , event , error ;
void * lib ;
Status ( * pXF86DGADirectVideo ) ( Display * dpy , int screen , int enable ) ;
} dgam ;
static qboolean DGAM_Init ( void )
{
2016-07-30 17:59:55 +00:00
static dllfunction_t dgam_functable [ ] =
2013-03-12 22:54:12 +00:00
{
{ ( void * * ) & dgam . pXF86DGADirectVideo , " XF86DGADirectVideo " } ,
{ NULL , NULL }
} ;
2013-03-12 23:04:11 +00:00
if ( ! x11 . pXQueryExtension ( vid_dpy , " XFree86-DGA " , & dgam . opcode , & dgam . event , & dgam . error ) )
2013-03-12 22:54:12 +00:00
{
Con_Printf ( " DGA extension not available. \n " ) ;
return false ;
}
if ( ! dgam . lib )
dgam . lib = Sys_LoadLibrary ( " libXxf86dga " , dgam_functable ) ;
return ! ! dgam . lib ;
}
2013-03-12 22:58:55 +00:00
#if 0
2013-03-12 22:54:12 +00:00
# include <X11/extensions/XInput2.h>
2013-03-12 22:58:55 +00:00
# else
# define XISetMask(ptr, event) (((unsigned char*)(ptr))[(event)>>3] |= (1 << ((event) & 7)))
# define XIMaskIsSet(ptr, event) (((unsigned char*)(ptr))[(event)>>3] & (1 << ((event) & 7)))
# define XIMaskLen(event) (((event + 7) >> 3))
typedef struct {
2014-03-30 08:55:06 +00:00
int mask_len ;
unsigned char * mask ;
double * values ;
2013-03-12 22:58:55 +00:00
} XIValuatorState ;
typedef struct
{
2014-03-30 08:55:06 +00:00
int deviceid ;
int mask_len ;
unsigned char * mask ;
2013-03-12 22:58:55 +00:00
} XIEventMask ;
# define XIAllMasterDevices 1
# define XI_RawButtonPress 15
# define XI_RawButtonRelease 16
# define XI_RawMotion 17
# define XI_LASTEVENT XI_RawMotion
typedef struct {
2014-03-30 08:55:06 +00:00
int type ; /* GenericEvent */
unsigned long serial ; /* # of last request processed by server */
Bool send_event ; /* true if this came from a SendEvent request */
Display * display ; /* Display the event was read from */
int extension ; /* XI extension offset */
int evtype ; /* XI_RawKeyPress, XI_RawKeyRelease, etc. */
Time time ;
int deviceid ;
int sourceid ; /* Bug: Always 0. https://bugs.freedesktop.org//show_bug.cgi?id=34240 */
int detail ;
int flags ;
XIValuatorState valuators ;
double * raw_values ;
2013-03-12 22:58:55 +00:00
} XIRawEvent ;
# endif
2013-03-12 22:54:12 +00:00
static struct
{
int opcode , event , error ;
int vmajor , vminor ;
void * libxi ;
Status ( * pXIQueryVersion ) ( Display * display , int * major_version_inout , int * minor_version_inout ) ;
int ( * pXISelectEvents ) ( Display * dpy , Window win , XIEventMask * masks , int num_masks ) ;
} xi2 ;
static qboolean XI2_Init ( void )
{
2016-07-30 17:59:55 +00:00
static dllfunction_t xi2_functable [ ] =
2013-03-12 22:54:12 +00:00
{
{ ( void * * ) & xi2 . pXIQueryVersion , " XIQueryVersion " } ,
{ ( void * * ) & xi2 . pXISelectEvents , " XISelectEvents " } ,
{ NULL , NULL }
} ;
XIEventMask evm ;
unsigned char maskbuf [ XIMaskLen ( XI_LASTEVENT ) ] ;
2013-03-12 23:04:11 +00:00
if ( ! x11 . pXQueryExtension ( vid_dpy , " XInputExtension " , & xi2 . opcode , & xi2 . event , & xi2 . error ) )
2013-03-12 22:54:12 +00:00
{
Con_Printf ( " XInput extension not available. \n " ) ;
return false ;
}
if ( ! xi2 . libxi )
{
2014-03-30 00:39:37 +00:00
# ifdef __CYGWIN__
if ( ! xi2 . libxi )
xi2 . libxi = Sys_LoadLibrary ( " cygXi-6.dll " , xi2_functable ) ;
# endif
if ( ! xi2 . libxi )
xi2 . libxi = Sys_LoadLibrary ( " libXi.so.6 " , xi2_functable ) ;
2013-05-13 13:43:18 +00:00
if ( ! xi2 . libxi )
xi2 . libxi = Sys_LoadLibrary ( " libXi " , xi2_functable ) ;
2013-03-12 22:54:12 +00:00
if ( ! xi2 . libxi )
2013-03-12 22:58:55 +00:00
Con_Printf ( " XInput library not available or too old. \n " ) ;
2013-03-12 22:54:12 +00:00
}
if ( xi2 . libxi )
{
xi2 . vmajor = 2 ;
xi2 . vminor = 0 ;
if ( xi2 . pXIQueryVersion ( vid_dpy , & xi2 . vmajor , & xi2 . vminor ) )
{
Con_Printf ( " XInput library or server is too old \n " ) ;
return false ;
}
evm . deviceid = XIAllMasterDevices ;
evm . mask_len = sizeof ( maskbuf ) ;
evm . mask = maskbuf ;
memset ( maskbuf , 0 , sizeof ( maskbuf ) ) ;
XISetMask ( maskbuf , XI_RawMotion ) ;
XISetMask ( maskbuf , XI_RawButtonPress ) ;
XISetMask ( maskbuf , XI_RawButtonRelease ) ;
/* if (xi2.vmajor >= 2 && xi2.vminor >= 2)
{
2014-03-30 08:55:06 +00:00
XISetMask ( maskbuf , XI_RawTouchBegin ) ;
XISetMask ( maskbuf , XI_RawTouchUpdate ) ;
XISetMask ( maskbuf , XI_RawTouchEnd ) ;
2013-03-12 22:54:12 +00:00
}
*/ xi2 . pXISelectEvents ( vid_dpy , DefaultRootWindow ( vid_dpy ) , & evm , 1 ) ;
return true ;
}
return false ;
}
2004-08-22 22:29:09 +00:00
/*-----------------------------------------------------------------------*/
2013-03-12 22:47:42 +00:00
//qboolean is8bit = false;
//qboolean isPermedia = false;
2015-05-16 08:02:05 +00:00
extern qboolean sys_gracefulexit ;
2013-03-12 22:47:42 +00:00
# define SYS_CLIPBOARD_SIZE 512
char clipboard_buffer [ SYS_CLIPBOARD_SIZE ] ;
2004-08-22 22:29:09 +00:00
/*-----------------------------------------------------------------------*/
2016-07-12 00:40:13 +00:00
# ifdef GLQUAKE
2013-11-21 23:02:28 +00:00
static dllhandle_t * gllibrary ;
2004-08-22 22:29:09 +00:00
XVisualInfo * ( * qglXChooseVisual ) ( Display * dpy , int screen , int * attribList ) ;
void ( * qglXSwapBuffers ) ( Display * dpy , GLXDrawable drawable ) ;
Bool ( * qglXMakeCurrent ) ( Display * dpy , GLXDrawable drawable , GLXContext ctx ) ;
GLXContext ( * qglXCreateContext ) ( Display * dpy , XVisualInfo * vis , GLXContext shareList , Bool direct ) ;
void ( * qglXDestroyContext ) ( Display * dpy , GLXContext ctx ) ;
void * ( * qglXGetProcAddress ) ( char * name ) ;
void GLX_CloseLibrary ( void )
{
2013-11-21 23:02:28 +00:00
Sys_CloseLibrary ( gllibrary ) ;
2004-08-22 22:29:09 +00:00
gllibrary = NULL ;
}
qboolean GLX_InitLibrary ( char * driver )
{
2013-11-21 23:02:28 +00:00
dllfunction_t funcs [ ] =
{
{ ( void * ) & qglXChooseVisual , " glXChooseVisual " } ,
{ ( void * ) & qglXSwapBuffers , " glXSwapBuffers " } ,
{ ( void * ) & qglXMakeCurrent , " glXMakeCurrent " } ,
{ ( void * ) & qglXCreateContext , " glXCreateContext " } ,
{ ( void * ) & qglXDestroyContext , " glXDestroyContext " } ,
{ NULL , NULL }
} ;
2004-08-22 22:29:09 +00:00
if ( driver & & * driver )
2013-11-21 23:02:28 +00:00
gllibrary = Sys_LoadLibrary ( driver , funcs ) ;
2004-08-22 22:29:09 +00:00
else
gllibrary = NULL ;
2014-03-30 00:39:37 +00:00
# ifdef __CYGWIN__
if ( ! gllibrary )
gllibrary = Sys_LoadLibrary ( " cygGL-1.dll " , funcs ) ;
# endif
2004-12-22 13:47:57 +00:00
if ( ! gllibrary ) //I hate this.
2013-11-21 23:02:28 +00:00
gllibrary = Sys_LoadLibrary ( " libGL.so.1 " , funcs ) ;
2005-12-21 03:07:33 +00:00
if ( ! gllibrary )
2013-11-21 23:02:28 +00:00
gllibrary = Sys_LoadLibrary ( " libGL " , funcs ) ;
2004-08-22 22:29:09 +00:00
if ( ! gllibrary )
return false ;
2013-11-21 23:02:28 +00:00
qglXGetProcAddress = Sys_GetAddressForName ( gllibrary , " glXGetProcAddress " ) ;
2004-08-22 22:29:09 +00:00
if ( ! qglXGetProcAddress )
2013-11-21 23:02:28 +00:00
qglXGetProcAddress = Sys_GetAddressForName ( gllibrary , " glXGetProcAddressARB " ) ;
2004-08-22 22:29:09 +00:00
return true ;
}
void * GLX_GetSymbol ( char * name )
{
void * symb ;
2011-09-05 01:48:23 +00:00
2004-08-22 22:29:09 +00:00
if ( qglXGetProcAddress )
symb = qglXGetProcAddress ( name ) ;
else
symb = NULL ;
if ( ! symb )
2013-11-21 23:02:28 +00:00
symb = Sys_GetAddressForName ( gllibrary , name ) ;
2004-08-22 22:29:09 +00:00
return symb ;
}
2016-07-12 00:40:13 +00:00
# endif
2004-08-22 22:29:09 +00:00
2014-03-30 00:39:37 +00:00
static void X_ShutdownUnicode ( void )
{
if ( x11 . unicodecontext )
x11 . pXDestroyIC ( x11 . unicodecontext ) ;
2014-07-07 17:18:45 +00:00
x11 . unicodecontext = NULL ;
2014-03-30 00:39:37 +00:00
if ( x11 . inputmethod )
x11 . pXCloseIM ( x11 . inputmethod ) ;
2014-07-07 17:18:45 +00:00
x11 . inputmethod = NULL ;
2014-03-30 00:39:37 +00:00
x11 . dounicode = false ;
}
# include <locale.h>
static long X_InitUnicode ( void )
2004-08-22 22:29:09 +00:00
{
2014-03-30 00:39:37 +00:00
long requiredevents = 0 ;
X_ShutdownUnicode ( ) ;
2014-03-30 08:55:06 +00:00
if ( ! COM_CheckParm ( " -noxim " ) )
2014-03-30 00:39:37 +00:00
{
2015-09-10 10:16:26 +00:00
if ( x11 . pXSetLocaleModifiers & & x11 . pXSupportsLocale & & x11 . pXOpenIM & & x11 . pXGetIMValues & & x11 . pXCreateIC & & x11 . pXSetICFocus & & x11 . pXGetICValues & & x11 . pXFilterEvent & & ( x11 . pXutf8LookupString | | x11 . pXwcLookupString ) & & x11 . pXDestroyIC & & x11 . pXCloseIM )
2014-03-30 00:39:37 +00:00
{
2014-03-30 08:55:06 +00:00
setlocale ( LC_CTYPE , " " ) ; //just in case.
x11 . pXSetLocaleModifiers ( " " ) ;
if ( x11 . pXSupportsLocale ( ) )
2014-03-30 00:39:37 +00:00
{
2014-03-30 08:55:06 +00:00
x11 . inputmethod = x11 . pXOpenIM ( vid_dpy , NULL , NULL , NULL ) ;
if ( x11 . inputmethod )
2014-03-30 00:39:37 +00:00
{
2015-09-10 10:16:26 +00:00
XIMStyles * sup = NULL ;
XIMStyle st = 0 ;
int i ;
x11 . pXGetIMValues ( x11 . inputmethod , XNQueryInputStyle , & sup , NULL ) ;
for ( i = 0 ; sup & & i < sup - > count_styles ; i + + )
{ //each style will have one of each bis set.
# define prestyles (XIMPreeditNothing|XIMPreeditNone)
# define statusstyles (XIMStatusNothing|XIMStatusNone)
# define supstyles (prestyles|statusstyles)
if ( ( sup - > supported_styles [ i ] & supstyles ) ! = sup - > supported_styles [ i ] )
continue ;
if ( ( st & prestyles ) ! = ( sup - > supported_styles [ i ] & prestyles ) )
{
if ( ( sup - > supported_styles [ i ] & XIMPreeditNothing ) & & ! ( st & XIMPreeditNothing ) )
st = sup - > supported_styles [ i ] ;
else if ( ( sup - > supported_styles [ i ] & XIMPreeditNone ) & & ! ( st & ( XIMPreeditNone | XIMPreeditNothing ) ) )
st = sup - > supported_styles [ i ] ;
}
else
{
if ( ( sup - > supported_styles [ i ] & XIMStatusNothing ) & & ! ( st & XIMStatusNothing ) )
st = sup - > supported_styles [ i ] ;
else if ( ( sup - > supported_styles [ i ] & XIMStatusNone ) & & ! ( st & ( XIMStatusNone | XIMStatusNothing ) ) )
st = sup - > supported_styles [ i ] ;
}
}
x11 . pXFree ( sup ) ;
if ( st ! = 0 )
2014-03-30 08:55:06 +00:00
{
2015-09-10 10:16:26 +00:00
x11 . unicodecontext = x11 . pXCreateIC ( x11 . inputmethod ,
XNInputStyle , st ,
XNClientWindow , vid_window ,
XNFocusWindow , vid_window ,
NULL ) ;
if ( x11 . unicodecontext )
{
x11 . pXSetICFocus ( x11 . unicodecontext ) ;
x11 . dounicode = true ;
x11 . pXGetICValues ( x11 . unicodecontext , XNFilterEvents , & requiredevents , NULL ) ;
}
2014-03-30 08:55:06 +00:00
}
2014-03-30 00:39:37 +00:00
}
}
2015-09-10 10:16:26 +00:00
setlocale ( LC_CTYPE , " C " ) ;
2014-03-30 00:39:37 +00:00
}
}
2014-03-30 08:55:06 +00:00
Con_DPrintf ( " Unicode support: %s \n " , x11 . dounicode ? " available " : " unavailable " ) ;
2014-03-30 00:39:37 +00:00
return requiredevents ;
}
2014-03-30 08:55:06 +00:00
static void X_KeyEvent ( XKeyEvent * ev , qboolean pressed , qboolean filtered )
2014-03-30 00:39:37 +00:00
{
int i ;
2004-08-22 22:29:09 +00:00
int key ;
2009-07-07 21:32:54 +00:00
KeySym keysym , shifted ;
2014-03-30 00:39:37 +00:00
unsigned int unichar [ 64 ] ;
int unichars = 0 ;
2004-08-22 22:29:09 +00:00
key = 0 ;
2013-03-12 23:04:11 +00:00
keysym = x11 . pXLookupKeysym ( ev , 0 ) ;
2014-03-30 08:55:06 +00:00
if ( pressed & & ! filtered )
2013-05-13 13:43:18 +00:00
{
2014-03-30 00:39:37 +00:00
if ( x11 . dounicode )
{
Status status = XLookupNone ;
if ( x11 . pXutf8LookupString )
{
2014-03-30 08:55:06 +00:00
char buf1 [ 4 ] = { 0 } ;
2014-03-30 00:39:37 +00:00
char * buf = buf1 , * c ;
int count = x11 . pXutf8LookupString ( x11 . unicodecontext , ( XKeyPressedEvent * ) ev , buf1 , sizeof ( buf1 ) , NULL , & status ) ;
if ( status = = XBufferOverflow )
{
buf = alloca ( count + 1 ) ;
count = x11 . pXutf8LookupString ( x11 . unicodecontext , ( XKeyPressedEvent * ) ev , buf , count , NULL , & status ) ;
}
for ( c = buf ; c < & buf [ count ] ; )
{
int error ;
unsigned int uc = utf8_decode ( & error , c , & c ) ;
if ( uc )
unichar [ unichars + + ] = uc ;
}
}
else
{
//is allowed some weird encodings...
wchar_t buf1 [ 4 ] = { 0 } ;
wchar_t * buf = buf1 ;
int count = x11 . pXwcLookupString ( x11 . unicodecontext , ( XKeyPressedEvent * ) ev , buf , sizeof ( buf1 ) , & shifted , & status ) ;
if ( status = = XBufferOverflow )
{
buf = alloca ( sizeof ( wchar_t ) * ( count + 1 ) ) ;
count = x11 . pXwcLookupString ( x11 . unicodecontext , ( XKeyPressedEvent * ) ev , buf , count , NULL , & status ) ;
}
//if wchar_t is 16bit, then expect problems when we completely ignore surrogates. this is why we favour the utf8 route as it doesn't care whether wchar_t is defined as 16bit or 32bit.
for ( i = 0 ; i < count ; i + + )
if ( buf [ i ] )
unichar [ unichars + + ] = buf [ i ] ;
}
}
2013-05-13 13:43:18 +00:00
else
{
2014-03-30 00:39:37 +00:00
char buf [ 64 ] ;
if ( ( keysym & 0xff000000 ) = = 0x01000000 )
unichar [ unichars + + ] = keysym & 0x00ffffff ;
else
{
int count = x11 . pXLookupString ( ev , buf , sizeof ( buf ) , & shifted , 0 ) ;
for ( i = 0 ; i < count ; i + + )
if ( buf [ i ] )
unichar [ unichars + + ] = ( unsigned char ) buf [ i ] ;
}
2013-05-13 13:43:18 +00:00
}
}
2004-08-22 22:29:09 +00:00
switch ( keysym )
{
2013-05-03 04:28:08 +00:00
case XK_KP_Page_Up : key = K_KP_PGUP ; break ;
case XK_Page_Up : key = K_PGUP ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_KP_Page_Down : key = K_KP_PGDN ; break ;
case XK_Page_Down : key = K_PGDN ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_KP_Home : key = K_KP_HOME ; break ;
case XK_Home : key = K_HOME ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_KP_End : key = K_KP_END ; break ;
case XK_End : key = K_END ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_KP_Left : key = K_KP_LEFTARROW ; break ;
case XK_Left : key = K_LEFTARROW ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_KP_Right : key = K_KP_RIGHTARROW ; break ;
case XK_Right : key = K_RIGHTARROW ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_KP_Down : key = K_KP_DOWNARROW ; break ;
case XK_Down : key = K_DOWNARROW ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_KP_Up : key = K_KP_UPARROW ; break ;
case XK_Up : key = K_UPARROW ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_Escape : key = K_ESCAPE ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_KP_Enter : key = K_KP_ENTER ; break ;
case XK_Return : key = K_ENTER ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_Tab : key = K_TAB ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_F1 : key = K_F1 ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_F2 : key = K_F2 ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_F3 : key = K_F3 ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_F4 : key = K_F4 ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_F5 : key = K_F5 ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_F6 : key = K_F6 ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_F7 : key = K_F7 ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_F8 : key = K_F8 ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_F9 : key = K_F9 ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_F10 : key = K_F10 ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_F11 : key = K_F11 ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_F12 : key = K_F12 ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_BackSpace : key = K_BACKSPACE ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_KP_Delete : key = K_KP_DEL ; break ;
case XK_Delete : key = K_DEL ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_Pause : key = K_PAUSE ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_Shift_L : key = K_LSHIFT ; break ;
case XK_Shift_R : key = K_RSHIFT ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_Execute : key = K_LCTRL ; break ;
case XK_Control_L : key = K_LCTRL ; break ;
case XK_Control_R : key = K_RCTRL ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_Alt_L : key = K_LALT ; break ;
case XK_Meta_L : key = K_LALT ; break ;
case XK_Alt_R : key = K_RALT ; break ;
case XK_Meta_R : key = K_RALT ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_KP_Begin : key = K_KP_5 ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_KP_Insert : key = K_KP_INS ; break ;
case XK_Insert : key = K_INS ; break ;
2004-08-22 22:29:09 +00:00
2013-05-03 04:28:08 +00:00
case XK_KP_Multiply : key = K_KP_STAR ; break ;
case XK_KP_Add : key = K_KP_PLUS ; break ;
case XK_KP_Subtract : key = K_KP_MINUS ; break ;
case XK_KP_Divide : key = K_KP_SLASH ; break ;
2004-08-22 22:29:09 +00:00
#if 0
case 0x021 : key = ' 1 ' ; break ; /* [!] */
case 0x040 : key = ' 2 ' ; break ; /* [@] */
case 0x023 : key = ' 3 ' ; break ; /* [#] */
case 0x024 : key = ' 4 ' ; break ; /* [$] */
case 0x025 : key = ' 5 ' ; break ; /* [%] */
case 0x05e : key = ' 6 ' ; break ; /* [^] */
case 0x026 : key = ' 7 ' ; break ; /* [&] */
case 0x02a : key = ' 8 ' ; break ; /* [*] */
case 0x028 : key = ' 9 ' ; ; break ; /* [(] */
case 0x029 : key = ' 0 ' ; break ; /* [)] */
case 0x05f : key = ' - ' ; break ; /* [_] */
case 0x02b : key = ' = ' ; break ; /* [+] */
case 0x07c : key = ' \' ' ; break ; /* [|] */
case 0x07d : key = ' [ ' ; break ; /* [}] */
case 0x07b : key = ' ] ' ; break ; /* [{] */
case 0x022 : key = ' \' ' ; break ; /* ["] */
case 0x03a : key = ' ; ' ; break ; /* [:] */
case 0x03f : key = ' / ' ; break ; /* [?] */
case 0x03e : key = ' . ' ; break ; /* [>] */
case 0x03c : key = ' , ' ; break ; /* [<] */
# endif
default :
2013-05-13 13:43:18 +00:00
key = keysym ;
if ( key < 32 )
key = 0 ;
else if ( key > 127 )
key = 0 ;
else if ( key > = ' A ' & & key < = ' Z ' )
2004-08-22 22:29:09 +00:00
key = key - ' A ' + ' a ' ;
break ;
2005-06-15 04:36:20 +00:00
}
2004-08-22 22:29:09 +00:00
2014-03-30 00:39:37 +00:00
if ( unichars )
{
//we got some text, this is fun isn't it?
//the key value itself is sent with the last text char. this avoids multiple presses, and dead keys were already sent.
for ( i = 0 ; i < unichars - 1 ; i + + )
{
IN_KeyEvent ( 0 , pressed , 0 , unichar [ i ] ) ;
}
IN_KeyEvent ( 0 , pressed , key , unichar [ i ] ) ;
}
else
{
//no text available, just do the keypress
IN_KeyEvent ( 0 , pressed , key , 0 ) ;
}
2004-08-22 22:29:09 +00:00
}
static void install_grabs ( void )
{
2013-03-12 22:54:12 +00:00
//XGrabPointer can cause alt+tab type shortcuts to be skipped by the window manager. This means we don't want to use it unless we have no choice.
//the grab is purely to constrain the pointer to the window
2013-03-12 23:04:11 +00:00
if ( GrabSuccess ! = x11 . pXGrabPointer ( vid_dpy , DefaultRootWindow ( vid_dpy ) ,
2013-03-12 22:54:33 +00:00
True ,
0 ,
GrabModeAsync , GrabModeAsync ,
vid_window ,
None ,
CurrentTime ) )
Con_Printf ( " Pointer grab failed \n " ) ;
2013-03-12 22:54:12 +00:00
if ( x11_input_method = = XIM_DGA )
2008-05-13 11:16:20 +00:00
{
2013-03-12 22:54:12 +00:00
dgam . pXF86DGADirectVideo ( vid_dpy , DefaultScreen ( vid_dpy ) , XF86DGADirectMouse ) ;
2008-05-13 11:16:20 +00:00
}
else
{
2013-03-12 23:04:11 +00:00
x11 . pXWarpPointer ( vid_dpy , None , vid_window ,
2008-05-13 11:16:20 +00:00
0 , 0 , 0 , 0 ,
vid . width / 2 , vid . height / 2 ) ;
}
2004-08-22 22:29:09 +00:00
2013-03-12 23:04:11 +00:00
// x11.pXSync(vid_dpy, True);
2004-08-22 22:29:09 +00:00
}
static void uninstall_grabs ( void )
{
2013-03-12 22:54:12 +00:00
if ( x11_input_method = = XIM_DGA )
2011-01-27 01:34:08 +00:00
{
2013-03-12 22:54:12 +00:00
dgam . pXF86DGADirectVideo ( vid_dpy , DefaultScreen ( vid_dpy ) , 0 ) ;
2011-01-27 01:34:08 +00:00
}
2004-08-22 22:29:09 +00:00
2011-09-05 01:48:23 +00:00
if ( vid_dpy )
2013-03-12 23:04:11 +00:00
x11 . pXUngrabPointer ( vid_dpy , CurrentTime ) ;
2004-08-22 22:29:09 +00:00
2013-03-12 23:04:11 +00:00
// x11.pXSync(vid_dpy, True);
2004-08-22 22:29:09 +00:00
}
2013-03-12 22:47:42 +00:00
static void ClearAllStates ( void )
2005-01-24 03:07:16 +00:00
{
int i ;
2005-06-15 04:36:20 +00:00
2005-01-24 03:07:16 +00:00
// send an up event for each key, to make sure the server clears them all
for ( i = 0 ; i < 256 ; i + + )
{
2010-08-14 03:17:33 +00:00
Key_Event ( 0 , i , 0 , false ) ;
2005-01-24 03:07:16 +00:00
}
Key_ClearStates ( ) ;
// IN_ClearStates ();
}
2004-08-22 22:29:09 +00:00
static void GetEvent ( void )
{
2013-03-12 22:47:42 +00:00
XEvent event , rep ;
2004-08-22 22:29:09 +00:00
int b ;
2008-02-05 00:38:41 +00:00
qboolean x11violations = true ;
2013-03-12 22:47:42 +00:00
Window mw ;
2014-03-30 08:55:06 +00:00
qboolean filtered = false ;
2004-08-22 22:29:09 +00:00
2013-03-12 23:04:11 +00:00
x11 . pXNextEvent ( vid_dpy , & event ) ;
2004-08-22 22:29:09 +00:00
2014-03-30 00:39:37 +00:00
if ( x11 . dounicode )
if ( x11 . pXFilterEvent ( & event , vid_window ) )
2014-03-30 08:55:06 +00:00
filtered = true ;
2014-03-30 00:39:37 +00:00
2013-03-12 22:54:12 +00:00
switch ( event . type )
{
case GenericEvent :
2013-03-12 23:04:11 +00:00
if ( x11 . pXGetEventData ( vid_dpy , & event . xcookie ) )
2013-03-12 22:54:12 +00:00
{
if ( event . xcookie . extension = = xi2 . opcode )
{
switch ( event . xcookie . evtype )
{
case XI_RawButtonPress :
case XI_RawButtonRelease :
if ( old_windowed_mouse )
{
XIRawEvent * raw = event . xcookie . data ;
int button = raw - > detail ; //1-based
switch ( button )
{
case 1 : button = K_MOUSE1 ; break ;
case 2 : button = K_MOUSE3 ; break ;
case 3 : button = K_MOUSE2 ; break ;
case 4 : button = K_MWHEELUP ; break ; //so much for 'raw'.
case 5 : button = K_MWHEELDOWN ; break ;
case 6 : button = K_MOUSE4 ; break ;
case 7 : button = K_MOUSE5 ; break ;
case 8 : button = K_MOUSE6 ; break ;
case 9 : button = K_MOUSE7 ; break ;
case 10 : button = K_MOUSE8 ; break ;
case 11 : button = K_MOUSE9 ; break ;
case 12 : button = K_MOUSE10 ; break ;
default : button = 0 ; break ;
}
if ( button )
IN_KeyEvent ( raw - > deviceid , ( event . xcookie . evtype = = XI_RawButtonPress ) , button , 0 ) ;
}
break ;
case XI_RawMotion :
if ( old_windowed_mouse )
{
XIRawEvent * raw = event . xcookie . data ;
double * val , * raw_val ;
double rawx = 0 , rawy = 0 ;
int i ;
val = raw - > valuators . values ;
raw_val = raw - > raw_values ;
for ( i = 0 ; i < raw - > valuators . mask_len * 8 ; i + + )
{
if ( XIMaskIsSet ( raw - > valuators . mask , i ) )
{
if ( i = = 0 ) rawx = * raw_val ;
if ( i = = 1 ) rawy = * raw_val ;
val + + ;
raw_val + + ;
}
}
2014-03-30 08:55:06 +00:00
IN_MouseMove ( raw - > deviceid , false , rawx , rawy , 0 , 0 ) ;
2013-03-12 22:54:12 +00:00
}
break ;
default :
Con_Printf ( " Unknown xinput event %u! \n " , event . xcookie . evtype ) ;
break ;
}
}
else
Con_Printf ( " Unknown generic event! \n " ) ;
}
2013-03-12 23:04:11 +00:00
x11 . pXFreeEventData ( vid_dpy , & event . xcookie ) ;
2013-03-12 22:54:12 +00:00
break ;
2004-12-05 08:25:01 +00:00
case ResizeRequest :
2016-07-28 15:57:22 +00:00
# ifdef VKQUAKE
vk . neednewswapchain = true ;
# endif
2009-11-04 21:16:50 +00:00
vid . pixelwidth = event . xresizerequest . width ;
vid . pixelheight = event . xresizerequest . height ;
2014-03-30 08:55:06 +00:00
Cvar_ForceCallback ( & vid_conautoscale ) ;
2013-03-12 22:47:42 +00:00
// if (fullscreenflags & FULLSCREEN_ACTIVE)
2013-03-12 23:04:11 +00:00
// x11.pXMoveWindow(vid_dpy, vid_window, 0, 0);
2004-12-05 08:25:01 +00:00
break ;
case ConfigureNotify :
2013-03-12 22:47:42 +00:00
if ( event . xconfigurerequest . window = = vid_window )
{
2016-07-28 15:57:22 +00:00
# ifdef VKQUAKE
vk . neednewswapchain = true ;
# endif
2013-03-12 22:47:42 +00:00
vid . pixelwidth = event . xconfigurerequest . width ;
vid . pixelheight = event . xconfigurerequest . height ;
2014-03-30 08:55:06 +00:00
Cvar_ForceCallback ( & vid_conautoscale ) ;
2013-03-12 22:47:42 +00:00
}
else if ( event . xconfigurerequest . window = = vid_decoywindow )
{
if ( ! ( fullscreenflags & FULLSCREEN_ACTIVE ) )
2013-03-12 23:04:11 +00:00
x11 . pXResizeWindow ( vid_dpy , vid_window , event . xconfigurerequest . width , event . xconfigurerequest . height ) ;
2013-03-12 22:47:42 +00:00
}
// if (fullscreenflags & FULLSCREEN_ACTIVE)
2013-03-12 23:04:11 +00:00
// x11.pXMoveWindow(vid_dpy, vid_window, 0, 0);
2004-12-05 08:25:01 +00:00
break ;
2004-08-22 22:29:09 +00:00
case KeyPress :
2014-03-30 08:55:06 +00:00
X_KeyEvent ( & event . xkey , true , filtered ) ;
2009-07-07 21:32:54 +00:00
break ;
2004-08-22 22:29:09 +00:00
case KeyRelease :
2014-03-30 08:55:06 +00:00
X_KeyEvent ( & event . xkey , false , filtered ) ;
2004-08-22 22:29:09 +00:00
break ;
case MotionNotify :
2013-03-12 22:54:12 +00:00
if ( x11_input_method = = XIM_DGA & & old_windowed_mouse )
2004-08-22 22:29:09 +00:00
{
2012-10-14 09:00:49 +00:00
IN_MouseMove ( 0 , false , event . xmotion . x_root , event . xmotion . y_root , 0 , 0 ) ;
2004-08-22 22:29:09 +00:00
}
else
{
if ( old_windowed_mouse )
{
2013-03-12 22:54:12 +00:00
if ( x11_input_method ! = XIM_XI2 )
{
int cx = vid . pixelwidth / 2 , cy = vid . pixelheight / 2 ;
IN_MouseMove ( 0 , false , event . xmotion . x - cx , event . xmotion . y - cy , 0 , 0 ) ;
/* move the mouse to the window center again (disabling warp first so we don't see it*/
2014-03-30 00:39:37 +00:00
x11 . pXSelectInput ( vid_dpy , vid_window , vid_x_eventmask & ~ PointerMotionMask ) ;
2013-03-12 23:04:11 +00:00
x11 . pXWarpPointer ( vid_dpy , None , vid_window , 0 , 0 , 0 , 0 ,
2013-03-12 22:54:12 +00:00
cx , cy ) ;
2014-03-30 00:39:37 +00:00
x11 . pXSelectInput ( vid_dpy , vid_window , vid_x_eventmask ) ;
2013-03-12 22:54:12 +00:00
}
2004-08-22 22:29:09 +00:00
}
2012-10-14 10:57:11 +00:00
else
{
IN_MouseMove ( 0 , true , event . xmotion . x , event . xmotion . y , 0 , 0 ) ;
}
2004-08-22 22:29:09 +00:00
}
break ;
case ButtonPress :
2013-03-12 22:54:12 +00:00
if ( x11_input_method = = XIM_XI2 & & old_windowed_mouse )
break ; //no dupes!
2004-08-22 22:29:09 +00:00
b = - 1 ;
if ( event . xbutton . button = = 1 )
2008-02-05 00:38:41 +00:00
b = K_MOUSE1 ;
2004-08-22 22:29:09 +00:00
else if ( event . xbutton . button = = 2 )
2008-02-05 00:38:41 +00:00
b = K_MOUSE3 ;
2004-08-22 22:29:09 +00:00
else if ( event . xbutton . button = = 3 )
2008-02-05 00:38:41 +00:00
b = K_MOUSE2 ;
//note, the x11 protocol does not support a mousewheel
//we only support it because we follow convention. the actual protocol specifies 4+5 as regular buttons
2005-11-21 21:07:45 +00:00
else if ( event . xbutton . button = = 4 )
2008-02-05 00:38:41 +00:00
b = x11violations ? K_MWHEELUP : K_MOUSE4 ;
2005-11-21 21:07:45 +00:00
else if ( event . xbutton . button = = 5 )
2008-02-05 00:38:41 +00:00
b = x11violations ? K_MWHEELDOWN : K_MOUSE5 ;
//note, the x11 protocol does not support more than 5 mouse buttons
//which is a bit of a shame, but hey.
else if ( event . xbutton . button = = 6 )
b = x11violations ? K_MOUSE4 : - 1 ;
else if ( event . xbutton . button = = 7 )
b = x11violations ? K_MOUSE5 : - 1 ;
else if ( event . xbutton . button = = 8 )
b = x11violations ? K_MOUSE6 : - 1 ;
else if ( event . xbutton . button = = 9 )
b = x11violations ? K_MOUSE7 : - 1 ;
else if ( event . xbutton . button = = 10 )
b = x11violations ? K_MOUSE8 : - 1 ;
else if ( event . xbutton . button = = 11 )
b = x11violations ? K_MOUSE9 : - 1 ;
else if ( event . xbutton . button = = 12 )
b = x11violations ? K_MOUSE10 : - 1 ;
2004-08-22 22:29:09 +00:00
if ( b > = 0 )
2012-10-14 09:00:49 +00:00
IN_KeyEvent ( 0 , true , b , 0 ) ;
2013-03-12 22:47:42 +00:00
/*
if ( fullscreenflags & FULLSCREEN_LEGACY )
if ( fullscreenflags & FULLSCREEN_VMODE )
2016-02-10 23:23:43 +00:00
if ( ! vid . activeapp )
2005-11-21 21:07:45 +00:00
{ //KDE doesn't seem to like us, in that you can't alt-tab back or click to activate.
//This allows us to steal input focus back from the window manager
2013-03-12 23:04:11 +00:00
x11 . pXSetInputFocus ( vid_dpy , vid_window , RevertToParent , CurrentTime ) ;
2005-11-21 21:07:45 +00:00
}
2013-03-12 22:47:42 +00:00
*/
2004-08-22 22:29:09 +00:00
break ;
case ButtonRelease :
b = - 1 ;
if ( event . xbutton . button = = 1 )
2008-02-05 00:38:41 +00:00
b = K_MOUSE1 ;
2004-08-22 22:29:09 +00:00
else if ( event . xbutton . button = = 2 )
2008-02-05 00:38:41 +00:00
b = K_MOUSE3 ;
2004-08-22 22:29:09 +00:00
else if ( event . xbutton . button = = 3 )
2008-02-05 00:38:41 +00:00
b = K_MOUSE2 ;
//note, the x11 protocol does not support a mousewheel
//we only support it because we follow convention. the actual protocol specifies 4+5 as regular buttons
2005-11-21 21:07:45 +00:00
else if ( event . xbutton . button = = 4 )
2008-02-05 00:38:41 +00:00
b = x11violations ? K_MWHEELUP : K_MOUSE4 ;
2005-11-21 21:07:45 +00:00
else if ( event . xbutton . button = = 5 )
2008-02-05 00:38:41 +00:00
b = x11violations ? K_MWHEELDOWN : K_MOUSE5 ;
//note, the x11 protocol does not support more than 5 mouse buttons
//which is a bit of a shame, but hey.
else if ( event . xbutton . button = = 6 )
b = x11violations ? K_MOUSE4 : - 1 ;
else if ( event . xbutton . button = = 7 )
b = x11violations ? K_MOUSE5 : - 1 ;
else if ( event . xbutton . button = = 8 )
b = x11violations ? K_MOUSE6 : - 1 ;
else if ( event . xbutton . button = = 9 )
b = x11violations ? K_MOUSE7 : - 1 ;
else if ( event . xbutton . button = = 10 )
b = x11violations ? K_MOUSE8 : - 1 ;
else if ( event . xbutton . button = = 11 )
b = x11violations ? K_MOUSE9 : - 1 ;
else if ( event . xbutton . button = = 12 )
b = x11violations ? K_MOUSE10 : - 1 ;
2004-08-22 22:29:09 +00:00
if ( b > = 0 )
2012-10-14 09:00:49 +00:00
IN_KeyEvent ( 0 , false , b , 0 ) ;
2004-08-22 22:29:09 +00:00
break ;
case FocusIn :
2013-03-12 22:47:42 +00:00
//activeapp is if the game window is focused
2016-02-10 23:23:43 +00:00
vid . activeapp = true ;
2013-03-12 22:47:42 +00:00
//but change modes to track the desktop window
// if (!(fullscreenflags & FULLSCREEN_ACTIVE) || event.xfocus.window != vid_decoywindow)
2005-11-21 21:07:45 +00:00
{
2013-03-12 22:47:42 +00:00
modeswitchpending = 1 ;
modeswitchtime = Sys_Milliseconds ( ) + 1500 ; /*fairly slow, to make sure*/
2005-11-21 21:07:45 +00:00
}
2013-03-12 22:47:42 +00:00
//we we're focusing onto the game window and we're currently fullscreen, hide the other one so alt-tab won't select that instead of a real alternate app.
// if ((fullscreenflags & FULLSCREEN_ACTIVE) && (fullscreenflags & FULLSCREEN_LEGACY) && event.xfocus.window == vid_window)
2013-03-12 23:04:11 +00:00
// x11.pXUnmapWindow(vid_dpy, vid_decoywindow);
2004-08-22 22:29:09 +00:00
break ;
case FocusOut :
2013-03-12 22:47:42 +00:00
//if we're already active, the decoy window shouldn't be focused anyway.
if ( ( fullscreenflags & FULLSCREEN_ACTIVE ) & & event . xfocus . window = = vid_decoywindow )
{
break ;
}
2013-03-12 22:54:12 +00:00
if ( vm . originalapplied )
2016-07-28 15:57:22 +00:00
vm . pXF86VidModeSetGammaRamp ( vid_dpy , scrnum , vm . originalrampsize , vm . originalramps [ 0 ] , vm . originalramps [ 1 ] , vm . originalramps [ 2 ] ) ;
2005-11-21 21:07:45 +00:00
2013-03-12 22:47:42 +00:00
mw = vid_window ;
if ( ( fullscreenflags & FULLSCREEN_LEGACY ) & & ( fullscreenflags & FULLSCREEN_ACTIVE ) )
mw = vid_decoywindow ;
2014-09-21 03:35:38 +00:00
if ( event . xfocus . window = = mw | | event . xfocus . window = = vid_window )
2013-03-12 22:47:42 +00:00
{
2016-02-10 23:23:43 +00:00
vid . activeapp = false ;
2013-03-12 22:47:42 +00:00
if ( old_windowed_mouse )
2005-11-21 21:07:45 +00:00
{
2013-03-12 22:47:42 +00:00
Con_DPrintf ( " uninstall grabs \n " ) ;
uninstall_grabs ( ) ;
2013-03-12 23:04:11 +00:00
x11 . pXUndefineCursor ( vid_dpy , vid_window ) ;
2013-03-12 22:47:42 +00:00
old_windowed_mouse = false ;
2005-11-21 21:07:45 +00:00
}
2013-03-12 22:47:42 +00:00
ClearAllStates ( ) ;
2005-11-21 21:07:45 +00:00
}
2013-03-12 22:47:42 +00:00
modeswitchpending = - 1 ;
modeswitchtime = Sys_Milliseconds ( ) + 100 ; /*fairly fast, so we don't unapply stuff when switching to other progs with delays*/
2011-01-29 19:53:38 +00:00
break ;
case ClientMessage :
{
2013-03-12 23:04:11 +00:00
char * name = x11 . pXGetAtomName ( vid_dpy , event . xclient . message_type ) ;
2011-01-29 19:53:38 +00:00
if ( ! strcmp ( name , " WM_PROTOCOLS " ) & & event . xclient . format = = 32 )
{
2013-03-12 23:04:11 +00:00
char * protname = x11 . pXGetAtomName ( vid_dpy , event . xclient . data . l [ 0 ] ) ;
2011-01-29 19:53:38 +00:00
if ( ! strcmp ( protname , " WM_DELETE_WINDOW " ) )
2013-03-12 22:47:42 +00:00
{
Cmd_ExecuteString ( " menu_quit prompt " , RESTRICT_LOCAL ) ;
2013-03-12 23:04:11 +00:00
x11 . pXSetInputFocus ( vid_dpy , vid_window , RevertToParent , CurrentTime ) ;
2013-03-12 22:47:42 +00:00
}
2011-01-29 19:53:38 +00:00
else
Con_Printf ( " Got message %s \n " , protname ) ;
2013-03-12 23:04:11 +00:00
x11 . pXFree ( protname ) ;
2011-01-29 19:53:38 +00:00
}
else
Con_Printf ( " Got message %s \n " , name ) ;
2013-03-12 23:04:11 +00:00
x11 . pXFree ( name ) ;
2011-01-29 19:53:38 +00:00
}
break ;
2004-08-22 22:29:09 +00:00
2013-03-12 22:47:42 +00:00
# if 1
case SelectionRequest : //needed for copy-to-clipboard
2004-08-22 22:29:09 +00:00
{
2013-03-12 23:04:11 +00:00
Atom xa_string = x11 . pXInternAtom ( vid_dpy , " UTF8_STRING " , false ) ;
2013-03-12 22:47:42 +00:00
memset ( & rep , 0 , sizeof ( rep ) ) ;
if ( event . xselectionrequest . property = = None )
2013-03-12 23:04:11 +00:00
event . xselectionrequest . property = x11 . pXInternAtom ( vid_dpy , " foobar2000 " , false ) ;
2013-03-12 22:47:42 +00:00
if ( event . xselectionrequest . property ! = None & & event . xselectionrequest . target = = xa_string )
{
2013-03-12 23:04:11 +00:00
x11 . pXChangeProperty ( vid_dpy , event . xselectionrequest . requestor , event . xselectionrequest . property , event . xselectionrequest . target , 8 , PropModeReplace , ( void * ) clipboard_buffer , strlen ( clipboard_buffer ) ) ;
2013-03-12 22:47:42 +00:00
rep . xselection . property = event . xselectionrequest . property ;
}
else
{
rep . xselection . property = None ;
}
rep . xselection . type = SelectionNotify ;
rep . xselection . serial = 0 ;
rep . xselection . send_event = true ;
rep . xselection . display = rep . xselection . display ;
rep . xselection . requestor = event . xselectionrequest . requestor ;
rep . xselection . selection = event . xselectionrequest . selection ;
rep . xselection . target = event . xselectionrequest . target ;
rep . xselection . time = event . xselectionrequest . time ;
2013-03-12 23:04:11 +00:00
x11 . pXSendEvent ( vid_dpy , event . xselectionrequest . requestor , 0 , 0 , & rep ) ;
2004-08-22 22:29:09 +00:00
}
2013-03-12 22:47:42 +00:00
break ;
# endif
default :
// Con_Printf("%x\n", event.type);
break ;
2004-08-22 22:29:09 +00:00
}
}
void GLVID_Shutdown ( void )
{
2011-09-05 01:48:23 +00:00
if ( ! vid_dpy )
2004-08-22 22:29:09 +00:00
return ;
2013-03-12 23:04:11 +00:00
x11 . pXUngrabKeyboard ( vid_dpy , CurrentTime ) ;
2004-08-22 22:29:09 +00:00
if ( old_windowed_mouse )
uninstall_grabs ( ) ;
2013-03-12 22:54:12 +00:00
if ( vm . originalapplied )
2016-07-28 15:57:22 +00:00
vm . pXF86VidModeSetGammaRamp ( vid_dpy , scrnum , vm . originalrampsize , vm . originalramps [ 0 ] , vm . originalramps [ 1 ] , vm . originalramps [ 2 ] ) ;
2013-03-12 22:49:04 +00:00
2014-03-30 00:39:37 +00:00
X_ShutdownUnicode ( ) ;
2013-03-12 22:49:04 +00:00
switch ( currentpsl )
{
2016-07-12 00:40:13 +00:00
# ifdef GLQUAKE
2013-03-12 22:49:04 +00:00
# ifdef USE_EGL
case PSL_EGL :
EGL_Shutdown ( ) ;
break ;
# endif
case PSL_GLX :
if ( ctx )
{
qglXDestroyContext ( vid_dpy , ctx ) ;
ctx = NULL ;
}
break ;
2016-07-12 00:40:13 +00:00
# endif
# ifdef VKQUAKE
case PSL_VULKAN :
VK_Shutdown ( ) ;
break ;
# endif
2013-03-12 22:49:04 +00:00
case PSL_NONE :
break ;
}
2004-08-22 22:29:09 +00:00
if ( vid_window )
2013-03-12 23:04:11 +00:00
x11 . pXDestroyWindow ( vid_dpy , vid_window ) ;
2012-10-14 10:57:11 +00:00
if ( vid_nullcursor )
2013-03-12 23:04:11 +00:00
x11 . pXFreeCursor ( vid_dpy , vid_nullcursor ) ;
2013-03-12 22:47:42 +00:00
if ( vid_dpy )
{
if ( fullscreenflags & FULLSCREEN_VMODEACTIVE )
2013-03-12 22:54:12 +00:00
vm . pXF86VidModeSwitchToMode ( vid_dpy , scrnum , vm . modes [ 0 ] ) ;
2013-03-12 22:47:42 +00:00
fullscreenflags & = ~ FULLSCREEN_VMODEACTIVE ;
2011-01-30 01:32:30 +00:00
2013-03-12 22:54:12 +00:00
if ( vm . modes )
2013-03-12 23:04:11 +00:00
x11 . pXFree ( vm . modes ) ;
2013-03-12 22:54:12 +00:00
vm . modes = NULL ;
vm . num_modes = 0 ;
2004-08-22 22:29:09 +00:00
}
2013-03-12 23:04:11 +00:00
x11 . pXCloseDisplay ( vid_dpy ) ;
2005-12-05 21:22:36 +00:00
vid_dpy = NULL ;
2004-08-22 22:29:09 +00:00
vid_window = ( Window ) NULL ;
2013-03-12 22:49:04 +00:00
currentpsl = PSL_NONE ;
2004-08-22 22:29:09 +00:00
}
void GLVID_DeInit ( void ) //FIXME:....
{
GLVID_Shutdown ( ) ;
}
static Cursor CreateNullCursor ( Display * display , Window root )
{
2014-03-30 08:55:06 +00:00
Pixmap cursormask ;
XGCValues xgc ;
GC gc ;
XColor dummycolour ;
Cursor cursor ;
cursormask = x11 . pXCreatePixmap ( display , root , 1 , 1 , 1 /*depth*/ ) ;
xgc . function = GXclear ;
gc = x11 . pXCreateGC ( display , cursormask , GCFunction , & xgc ) ;
x11 . pXFillRectangle ( display , cursormask , gc , 0 , 0 , 1 , 1 ) ;
dummycolour . pixel = 0 ;
dummycolour . red = 0 ;
dummycolour . flags = 04 ;
cursor = x11 . pXCreatePixmapCursor ( display , cursormask , cursormask ,
& dummycolour , & dummycolour , 0 , 0 ) ;
x11 . pXFreePixmap ( display , cursormask ) ;
x11 . pXFreeGC ( display , gc ) ;
return cursor ;
2004-08-22 22:29:09 +00:00
}
2016-07-28 15:57:22 +00:00
qboolean GLVID_ApplyGammaRamps ( unsigned int rampcount , unsigned short * ramps )
2004-08-22 22:29:09 +00:00
{
2005-01-24 03:07:16 +00:00
extern qboolean gammaworks ;
2013-06-23 03:59:48 +00:00
//extern cvar_t vid_hardwaregamma;
2005-06-15 04:36:20 +00:00
2013-05-13 13:43:18 +00:00
//if we don't know the original ramps yet, don't allow changing them, because we're probably invalid anyway, and even if it worked, it'll break something later.
if ( ! vm . originalapplied )
return false ;
2005-01-24 03:07:16 +00:00
2016-07-28 15:57:22 +00:00
if ( ramps | | rampcount ! = vm . originalrampsize )
2005-01-24 03:07:16 +00:00
{
2013-05-13 13:43:18 +00:00
//hardwaregamma==1 skips hardware gamma when we're not fullscreen, in favour of software glsl based gamma.
2016-02-10 23:23:43 +00:00
// if (vid_hardwaregamma.value == 1 && !vid.activeapp && !(fullscreenflags & FULLSCREEN_ACTIVE))
2013-05-13 13:43:18 +00:00
// return false;
2016-02-10 23:23:43 +00:00
// if (!vid.activeapp)
2013-05-13 13:43:18 +00:00
// return false;
// if (!vid_hardwaregamma.value)
// return false;
//we have hardware gamma applied - if we're doing a BF, we don't want to reset to the default gamma if it randomly fails (yuck)
2005-01-24 03:07:16 +00:00
if ( gammaworks )
2016-07-28 15:57:22 +00:00
vm . pXF86VidModeSetGammaRamp ( vid_dpy , scrnum , rampcount , & ramps [ 0 ] , & ramps [ rampcount ] , & ramps [ rampcount * 2 ] ) ;
2013-05-13 13:43:18 +00:00
else
2016-07-28 15:57:22 +00:00
gammaworks = ! ! vm . pXF86VidModeSetGammaRamp ( vid_dpy , scrnum , rampcount , & ramps [ 0 ] , & ramps [ rampcount ] , & ramps [ rampcount * 2 ] ) ;
2013-05-13 13:43:18 +00:00
return gammaworks ;
2005-01-24 03:07:16 +00:00
}
else
2004-08-22 22:29:09 +00:00
{
2016-07-28 15:57:22 +00:00
vm . pXF86VidModeSetGammaRamp ( vid_dpy , scrnum , vm . originalrampsize , vm . originalramps [ 0 ] , vm . originalramps [ 1 ] , vm . originalramps [ 2 ] ) ;
2013-05-13 13:43:18 +00:00
return true ;
2004-08-22 22:29:09 +00:00
}
}
2014-03-30 00:39:37 +00:00
void GLVID_SwapBuffers ( void )
2004-08-22 22:29:09 +00:00
{
2013-03-12 22:49:04 +00:00
switch ( currentpsl )
{
2016-07-12 00:40:13 +00:00
# ifdef GLQUAKE
2011-02-06 20:56:39 +00:00
# ifdef USE_EGL
2013-03-12 22:49:04 +00:00
case PSL_EGL :
2014-03-30 08:55:06 +00:00
EGL_BeginRendering ( ) ;
2013-03-12 22:49:04 +00:00
break ;
2011-02-06 20:56:39 +00:00
# endif
2013-03-12 22:49:04 +00:00
case PSL_GLX :
//we don't need to flush, XSawpBuffers does it for us.
//chances are, it's version is more suitable anyway. At least there's the chance that it might be.
qglXSwapBuffers ( vid_dpy , vid_window ) ;
break ;
2016-07-12 00:40:13 +00:00
# endif
# ifdef VKQUAKE
case PSL_VULKAN :
break ;
# endif
2014-03-30 08:55:06 +00:00
default :
case PSL_NONE :
break ;
2013-03-12 22:49:04 +00:00
}
2004-08-22 22:29:09 +00:00
}
2013-03-12 22:47:42 +00:00
# include "bymorphed.h"
void X_StoreIcon ( Window wnd )
{
int i ;
unsigned long data [ 64 * 64 + 2 ] ;
unsigned int * indata = ( unsigned int * ) icon . pixel_data ;
2014-03-30 00:39:37 +00:00
unsigned int inwidth = icon . width ;
unsigned int inheight = icon . height ;
//FIXME: support loading an icon from the filesystem.
2013-03-12 23:04:11 +00:00
Atom propname = x11 . pXInternAtom ( vid_dpy , " _NET_WM_ICON " , false ) ;
Atom proptype = x11 . pXInternAtom ( vid_dpy , " CARDINAL " , false ) ;
2013-03-12 22:47:42 +00:00
2014-03-30 00:39:37 +00:00
data [ 0 ] = inwidth ;
data [ 1 ] = inheight ;
2013-03-12 22:47:42 +00:00
for ( i = 0 ; i < data [ 0 ] * data [ 1 ] ; i + + )
data [ i + 2 ] = indata [ i ] ;
2013-03-12 23:04:11 +00:00
x11 . pXChangeProperty ( vid_dpy , wnd , propname , proptype , 32 , PropModeReplace , ( void * ) data , data [ 0 ] * data [ 1 ] + 2 ) ;
2013-03-12 22:47:42 +00:00
}
void X_GoFullscreen ( void )
{
XEvent xev ;
//for NETWM window managers
memset ( & xev , 0 , sizeof ( xev ) ) ;
xev . type = ClientMessage ;
xev . xclient . window = vid_window ;
2013-03-12 23:04:11 +00:00
xev . xclient . message_type = x11 . pXInternAtom ( vid_dpy , " _NET_WM_STATE " , False ) ;
2013-03-12 22:47:42 +00:00
xev . xclient . format = 32 ;
xev . xclient . data . l [ 0 ] = 1 ; //add
2013-03-12 23:04:11 +00:00
xev . xclient . data . l [ 1 ] = x11 . pXInternAtom ( vid_dpy , " _NET_WM_STATE_FULLSCREEN " , False ) ;
2013-03-12 22:47:42 +00:00
xev . xclient . data . l [ 2 ] = 0 ;
2014-09-21 03:35:38 +00:00
//for any other window managers, and broken NETWM
x11 . pXMoveResizeWindow ( vid_dpy , vid_window , 0 , 0 , fullscreenwidth , fullscreenheight ) ;
2013-03-12 23:04:11 +00:00
x11 . pXSync ( vid_dpy , False ) ;
x11 . pXSendEvent ( vid_dpy , DefaultRootWindow ( vid_dpy ) , False , SubstructureNotifyMask , & xev ) ;
x11 . pXSync ( vid_dpy , False ) ;
x11 . pXMoveResizeWindow ( vid_dpy , vid_window , 0 , 0 , fullscreenwidth , fullscreenheight ) ;
x11 . pXSync ( vid_dpy , False ) ;
2014-09-21 03:35:38 +00:00
Con_Printf ( " Gone fullscreen \n " ) ;
2013-03-12 22:47:42 +00:00
}
void X_GoWindowed ( void )
{
XEvent xev ;
2013-03-12 23:04:11 +00:00
x11 . pXFlush ( vid_dpy ) ;
x11 . pXSync ( vid_dpy , False ) ;
2013-03-12 22:47:42 +00:00
memset ( & xev , 0 , sizeof ( xev ) ) ;
xev . type = ClientMessage ;
xev . xclient . window = vid_window ;
2013-03-12 23:04:11 +00:00
xev . xclient . message_type = x11 . pXInternAtom ( vid_dpy , " _NET_WM_STATE " , False ) ;
2013-03-12 22:47:42 +00:00
xev . xclient . format = 32 ;
xev . xclient . data . l [ 0 ] = 0 ; //remove
2013-03-12 23:04:11 +00:00
xev . xclient . data . l [ 1 ] = x11 . pXInternAtom ( vid_dpy , " _NET_WM_STATE_FULLSCREEN " , False ) ;
2013-03-12 22:47:42 +00:00
xev . xclient . data . l [ 2 ] = 0 ;
2013-03-12 23:04:11 +00:00
x11 . pXSendEvent ( vid_dpy , DefaultRootWindow ( vid_dpy ) , False , SubstructureNotifyMask , & xev ) ;
x11 . pXSync ( vid_dpy , False ) ;
2013-03-12 22:47:42 +00:00
2014-09-21 03:35:38 +00:00
x11 . pXMoveResizeWindow ( vid_dpy , vid_window , 0 , 0 , 640 , 480 ) ;
Con_Printf ( " Gone windowed \n " ) ;
2013-03-12 22:47:42 +00:00
}
qboolean X_CheckWMFullscreenAvailable ( void )
{
//root window must have _NET_SUPPORTING_WM_CHECK which is a Window created by the WM
//the WM's window must have _NET_WM_NAME set, which is the name of the window manager
//if we can find those, then the window manager has not crashed.
//if we can then find _NET_WM_STATE_FULLSCREEN in the _NET_SUPPORTED atom list on the root, then we can get fullscreen mode from the WM
//and we'll have no alt-tab issues whatsoever.
2013-03-12 23:04:11 +00:00
Atom xa_net_supporting_wm_check = x11 . pXInternAtom ( vid_dpy , " _NET_SUPPORTING_WM_CHECK " , False ) ;
Atom xa_net_wm_name = x11 . pXInternAtom ( vid_dpy , " _NET_WM_NAME " , False ) ;
Atom xa_net_supported = x11 . pXInternAtom ( vid_dpy , " _NET_SUPPORTED " , False ) ;
Atom xa_net_wm_state_fullscreen = x11 . pXInternAtom ( vid_dpy , " _NET_WM_STATE_FULLSCREEN " , False ) ;
2013-03-12 22:47:42 +00:00
Window wmwindow ;
unsigned char * prop ;
unsigned long bytes_after , nitems ;
Atom type ;
int format ;
qboolean success = false ;
unsigned char * wmname ;
int i ;
2014-09-08 23:26:22 +00:00
2015-06-15 07:40:58 +00:00
if ( COM_CheckParm ( " -nowmfullscreen " ) )
2014-09-08 23:26:22 +00:00
{
Con_Printf ( " Window manager fullscreen support disabled. Will attempt to hide from it instead. \n " ) ;
return success ;
}
2013-03-12 22:47:42 +00:00
2013-03-12 23:04:11 +00:00
if ( x11 . pXGetWindowProperty ( vid_dpy , vid_root , xa_net_supporting_wm_check , 0 , 16384 , False , AnyPropertyType , & type , & format , & nitems , & bytes_after , & prop ) ! = Success | | prop = = NULL )
2013-03-12 22:47:42 +00:00
{
Con_Printf ( " Window manager not identified \n " ) ;
return success ;
}
wmwindow = * ( Window * ) prop ;
2013-03-12 23:04:11 +00:00
x11 . pXFree ( prop ) ;
2013-03-12 22:47:42 +00:00
2013-03-12 23:04:11 +00:00
if ( x11 . pXGetWindowProperty ( vid_dpy , wmwindow , xa_net_wm_name , 0 , 16384 , False , AnyPropertyType , & type , & format , & nitems , & bytes_after , & wmname ) ! = Success | | wmname = = NULL )
2013-03-12 22:47:42 +00:00
{
Con_Printf ( " Window manager crashed or something \n " ) ;
return success ;
}
else
{
2013-03-12 23:04:11 +00:00
if ( x11 . pXGetWindowProperty ( vid_dpy , vid_root , xa_net_supported , 0 , 16384 , False , AnyPropertyType , & type , & format , & nitems , & bytes_after , & prop ) ! = Success | | prop = = NULL )
2013-03-12 22:47:42 +00:00
{
Con_Printf ( " Window manager \" %s \" support nothing \n " , wmname ) ;
}
else
{
for ( i = 0 ; i < nitems ; i + + )
{
2013-03-12 23:04:11 +00:00
// Con_Printf("supported: %s\n", x11.pXGetAtomName(vid_dpy, ((Atom*)prop)[i]));
2013-03-12 22:47:42 +00:00
if ( ( ( Atom * ) prop ) [ i ] = = xa_net_wm_state_fullscreen )
{
success = true ;
break ;
}
}
if ( ! success )
Con_Printf ( " Window manager \" %s \" does not appear to support fullscreen \n " , wmname ) ;
2014-09-21 03:35:38 +00:00
else if ( ! strcmp ( wmname , " Fluxbox " ) )
{
Con_Printf ( " Window manager \" %s \" claims to support fullscreen, but is known buggy \n " , wmname ) ;
success = false ;
}
2013-03-12 22:47:42 +00:00
else
Con_Printf ( " Window manager \" %s \" supports fullscreen \n " , wmname ) ;
2013-03-12 23:04:11 +00:00
x11 . pXFree ( prop ) ;
2013-03-12 22:47:42 +00:00
}
2013-03-12 23:04:11 +00:00
x11 . pXFree ( wmname ) ;
2013-03-12 22:47:42 +00:00
}
return success ;
}
2013-03-12 23:03:46 +00:00
Window X_CreateWindow ( qboolean override , XVisualInfo * visinfo , unsigned int width , unsigned int height , qboolean fullscreen )
2004-08-22 22:29:09 +00:00
{
2013-03-12 23:03:46 +00:00
Window wnd , parent ;
2013-03-12 22:47:42 +00:00
XSetWindowAttributes attr ;
XSizeHints szhints ;
unsigned int mask ;
Atom prots [ 1 ] ;
2013-03-12 23:03:46 +00:00
int x , y ;
2013-03-12 22:47:42 +00:00
/* window attributes */
attr . background_pixel = 0 ;
attr . border_pixel = 0 ;
2013-03-12 23:04:11 +00:00
attr . colormap = x11 . pXCreateColormap ( vid_dpy , vid_root , visinfo - > visual , AllocNone ) ;
2014-03-30 00:39:37 +00:00
attr . event_mask = vid_x_eventmask = X_MASK ;
2013-03-12 22:47:42 +00:00
attr . backing_store = NotUseful ;
attr . save_under = False ;
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWBackingStore | CWSaveUnder ;
// override redirect prevents the windowmanager from finding out about us, and thus will not apply borders to our window.
if ( override )
{
mask | = CWOverrideRedirect ;
attr . override_redirect = True ;
}
memset ( & szhints , 0 , sizeof ( szhints ) ) ;
szhints . flags = PMinSize ;
szhints . min_width = 320 ;
szhints . min_height = 200 ;
szhints . x = 0 ;
szhints . y = 0 ;
szhints . width = width ;
szhints . height = height ;
2013-03-12 23:03:46 +00:00
if ( sys_parentwindow & & ! fullscreen )
{
x = ( sys_parentwidth - width ) / 2 ;
y = ( sys_parentheight - height ) / 2 ;
parent = sys_parentwindow ;
}
else
{
parent = vid_root ;
x = 0 ;
y = 0 ;
}
2013-03-12 23:04:11 +00:00
wnd = x11 . pXCreateWindow ( vid_dpy , parent , x , y , width , height ,
2013-03-12 22:47:42 +00:00
0 , visinfo - > depth , InputOutput ,
visinfo - > visual , mask , & attr ) ;
/*ask the window manager to stop triggering bugs in Xlib*/
2013-03-12 23:04:11 +00:00
prots [ 0 ] = x11 . pXInternAtom ( vid_dpy , " WM_DELETE_WINDOW " , False ) ;
x11 . pXSetWMProtocols ( vid_dpy , wnd , prots , sizeof ( prots ) / sizeof ( prots [ 0 ] ) ) ;
x11 . pXSetWMNormalHints ( vid_dpy , wnd , & szhints ) ;
2013-03-12 22:47:42 +00:00
/*set caption*/
2013-03-12 23:04:11 +00:00
x11 . pXStoreName ( vid_dpy , wnd , " FTE QuakeWorld " ) ;
x11 . pXSetIconName ( vid_dpy , wnd , " FTEQW " ) ;
2013-03-12 22:47:42 +00:00
X_StoreIcon ( wnd ) ;
/*make it visible*/
2013-03-12 23:04:11 +00:00
x11 . pXMapWindow ( vid_dpy , wnd ) ;
2013-03-12 22:47:42 +00:00
return wnd ;
2004-08-22 22:29:09 +00:00
}
2013-03-12 22:49:04 +00:00
qboolean X11VID_Init ( rendererstate_t * info , unsigned char * palette , int psl )
2004-08-22 22:29:09 +00:00
{
2013-03-12 22:47:42 +00:00
int width = info - > width ; //can override these if vmode isn't available
int height = info - > height ;
2014-10-07 13:50:58 +00:00
int rate = info - > rate ;
2004-08-22 22:29:09 +00:00
int i ;
2016-07-12 00:40:13 +00:00
# ifdef GLQUAKE
2004-08-22 22:29:09 +00:00
int attrib [ ] = {
GLX_RGBA ,
2016-07-12 00:40:13 +00:00
GLX_RED_SIZE , 4 ,
GLX_GREEN_SIZE , 4 ,
GLX_BLUE_SIZE , 4 ,
2004-08-22 22:29:09 +00:00
GLX_DOUBLEBUFFER ,
2016-07-12 00:40:13 +00:00
GLX_DEPTH_SIZE , 16 ,
GLX_STENCIL_SIZE , 4 ,
2004-08-22 22:29:09 +00:00
None
} ;
2016-07-12 00:40:13 +00:00
# endif
# if defined(USE_EGL) || defined(VKQUAKE)
2011-02-06 20:56:39 +00:00
XVisualInfo vinfodef ;
# endif
2004-08-22 22:29:09 +00:00
XVisualInfo * visinfo ;
2009-11-04 21:16:50 +00:00
qboolean fullscreen = false ;
2004-08-22 22:29:09 +00:00
2013-03-12 23:04:11 +00:00
if ( ! x11_initlib ( ) )
return false ;
2004-08-22 22:29:09 +00:00
if ( info - > fullscreen )
fullscreen = true ;
2013-03-12 22:49:04 +00:00
currentpsl = psl ;
switch ( currentpsl )
2004-12-22 13:47:57 +00:00
{
2016-07-12 00:40:13 +00:00
# ifdef GLQUAKE
2013-03-12 22:49:04 +00:00
# ifdef USE_EGL
case PSL_EGL :
2013-11-21 23:02:28 +00:00
if ( ! EGL_LoadLibrary ( info - > subrenderer ) )
2013-03-12 22:49:04 +00:00
{
Con_Printf ( " couldn't load EGL library \n " ) ;
return false ;
}
break ;
# endif
case PSL_GLX :
2013-11-21 23:02:28 +00:00
if ( ! GLX_InitLibrary ( info - > subrenderer ) )
2013-03-12 22:49:04 +00:00
{
Con_Printf ( " Couldn't intialise GLX \n Either your drivers are not installed or you need to specify the library name with the gl_driver cvar \n " ) ;
return false ;
}
break ;
2016-07-12 00:40:13 +00:00
# endif
# ifdef VKQUAKE
case PSL_VULKAN :
{
dllfunction_t func [ ] =
{
{ ( void * ) & vkGetInstanceProcAddr , " vkGetInstanceProcAddr " } ,
{ NULL , NULL }
} ;
if ( ! Sys_LoadLibrary ( " libvulkan.so.1 " , func ) )
{
if ( ! Sys_LoadLibrary ( " libvulkan.so " , func ) )
{
Con_Printf ( " Couldn't intialise libvulkan.so \n vulkan loader is not installed \n " ) ;
return false ;
}
}
}
break ;
# endif
2013-03-12 22:49:04 +00:00
case PSL_NONE :
2004-12-22 13:47:57 +00:00
return false ;
}
2005-06-15 04:36:20 +00:00
2004-08-22 22:29:09 +00:00
if ( ! vid_dpy )
2013-03-12 23:04:11 +00:00
vid_dpy = x11 . pXOpenDisplay ( NULL ) ;
2004-08-22 22:29:09 +00:00
if ( ! vid_dpy )
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Error: couldn't open the X display \n " ) ;
2006-04-15 03:31:23 +00:00
return false ;
2004-08-22 22:29:09 +00:00
}
scrnum = DefaultScreen ( vid_dpy ) ;
2013-03-12 22:47:42 +00:00
vid_root = RootWindow ( vid_dpy , scrnum ) ;
2004-08-22 22:29:09 +00:00
2013-03-12 22:54:12 +00:00
VMODE_Init ( ) ;
2004-08-22 22:29:09 +00:00
2013-03-12 22:47:42 +00:00
fullscreenflags = 0 ;
2013-03-12 22:54:12 +00:00
vm . usemode = - 1 ;
2014-10-07 13:50:58 +00:00
if ( vm . vmajor & & ! COM_CheckParm ( " -current " ) )
2004-08-22 22:29:09 +00:00
{
2014-10-07 13:50:58 +00:00
int best_fit , best_dist , dist , x , y , z , r ;
2004-08-22 22:29:09 +00:00
2013-03-12 22:54:12 +00:00
vm . pXF86VidModeGetAllModeLines ( vid_dpy , scrnum , & vm . num_modes , & vm . modes ) ;
2004-08-22 22:29:09 +00:00
// Are we going fullscreen? If so, let's change video mode
if ( fullscreen )
{
best_dist = 9999999 ;
best_fit = - 1 ;
2013-03-12 22:54:12 +00:00
for ( i = 0 ; i < vm . num_modes ; i + + )
2004-08-22 22:29:09 +00:00
{
2014-10-07 13:50:58 +00:00
//fixme: check this formula. should be the full refresh rate
r = vm . modes [ i ] - > dotclock * 1000 / ( vm . modes [ i ] - > htotal * vm . modes [ i ] - > vtotal ) ;
2013-03-12 22:54:12 +00:00
if ( width > vm . modes [ i ] - > hdisplay | |
2014-10-07 13:50:58 +00:00
height > vm . modes [ i ] - > vdisplay | |
rate > r )
2004-08-22 22:29:09 +00:00
continue ;
2013-03-12 22:54:12 +00:00
x = width - vm . modes [ i ] - > hdisplay ;
y = height - vm . modes [ i ] - > vdisplay ;
2014-10-07 13:50:58 +00:00
z = rate - r ;
dist = ( x * x ) + ( y * y ) + ( z * z ) ;
2004-08-22 22:29:09 +00:00
if ( dist < best_dist )
{
best_dist = dist ;
best_fit = i ;
}
}
2013-03-12 22:47:42 +00:00
if ( best_fit ! = - 1 )
2004-08-22 22:29:09 +00:00
{
// change to the mode
2013-03-12 22:54:12 +00:00
if ( vm . pXF86VidModeSwitchToMode ( vid_dpy , scrnum , vm . modes [ vm . usemode = best_fit ] ) )
2013-03-12 22:47:42 +00:00
{
2013-03-12 22:54:12 +00:00
width = vm . modes [ best_fit ] - > hdisplay ;
height = vm . modes [ best_fit ] - > vdisplay ;
2013-03-12 22:47:42 +00:00
// Move the viewport to top left
2013-03-12 22:54:12 +00:00
vm . pXF86VidModeSetViewPort ( vid_dpy , scrnum , 0 , 0 ) ;
2013-03-12 23:04:11 +00:00
x11 . pXSync ( vid_dpy , False ) ;
2004-08-22 22:29:09 +00:00
2013-03-12 22:47:42 +00:00
fullscreenflags | = FULLSCREEN_VMODE | FULLSCREEN_VMODEACTIVE ;
}
else
2013-03-12 22:54:12 +00:00
Con_Printf ( " Failed to apply mode %i*%i \n " , vm . modes [ best_fit ] - > hdisplay , vm . modes [ best_fit ] - > vdisplay ) ;
2004-08-22 22:29:09 +00:00
}
}
}
2013-03-12 22:47:42 +00:00
if ( fullscreen )
{
if ( ! ( fullscreenflags & FULLSCREEN_VMODE ) )
{
//if we can't actually change the mode, our fullscreen is the size of the root window
XWindowAttributes xwa ;
2013-03-12 23:04:11 +00:00
x11 . pXGetWindowAttributes ( vid_dpy , DefaultRootWindow ( vid_dpy ) , & xwa ) ;
2013-03-12 22:47:42 +00:00
width = xwa . width ;
height = xwa . height ;
}
2013-03-12 22:54:12 +00:00
//window managers fuck up too much if we change the video mode and request the windowmanager make us fullscreen.
if ( ( ! ( fullscreenflags & FULLSCREEN_VMODE ) | | vm . usemode < = 0 ) & & X_CheckWMFullscreenAvailable ( ) )
2013-03-12 22:47:42 +00:00
fullscreenflags | = FULLSCREEN_WM ;
else
2013-11-21 23:02:28 +00:00
fullscreenflags | = FULLSCREEN_LEGACY ;
2013-03-12 22:47:42 +00:00
}
2013-03-12 23:03:46 +00:00
else if ( sys_parentwindow )
{
if ( width < 64 | | width > sys_parentwidth )
width = sys_parentwidth ;
if ( height < 64 | | height > sys_parentheight )
height = sys_parentheight ;
}
2009-07-12 18:57:40 +00:00
2013-03-12 22:49:04 +00:00
switch ( currentpsl )
2011-02-06 20:56:39 +00:00
{
2016-07-12 00:40:13 +00:00
# ifdef GLQUAKE
2013-03-12 22:49:04 +00:00
# ifdef USE_EGL
case PSL_EGL :
visinfo = & vinfodef ;
2013-03-12 23:04:11 +00:00
if ( ! x11 . pXMatchVisualInfo ( vid_dpy , scrnum , info - > bpp , TrueColor , visinfo ) )
// if (!x11.pXMatchVisualInfo(vid_dpy, scrnum, DefaultDepth(vid_dpy, scrnum), TrueColor, &visinfo))
2013-03-12 22:49:04 +00:00
{
Sys_Error ( " Couldn't choose visual for EGL \n " ) ;
}
break ;
2011-02-06 20:56:39 +00:00
# endif
2013-03-12 22:49:04 +00:00
case PSL_GLX :
visinfo = qglXChooseVisual ( vid_dpy , scrnum , attrib ) ;
if ( ! visinfo )
{
2016-07-12 00:40:13 +00:00
Sys_Error ( " X11VID_Init: Error couldn't get an RGB, Double-buffered, Depth visual \n " ) ;
2013-03-12 22:49:04 +00:00
}
break ;
2016-07-12 00:40:13 +00:00
# endif
# ifdef VKQUAKE
case PSL_VULKAN :
visinfo = & vinfodef ;
if ( ! x11 . pXMatchVisualInfo ( vid_dpy , scrnum , info - > bpp , TrueColor , visinfo ) )
// if (!x11.pXMatchVisualInfo(vid_dpy, scrnum, DefaultDepth(vid_dpy, scrnum), TrueColor, &visinfo))
{
Sys_Error ( " Couldn't choose visual for vulkan \n " ) ;
}
break ;
# endif
2013-03-12 22:49:48 +00:00
default :
2013-03-12 22:49:04 +00:00
case PSL_NONE :
2013-03-12 22:49:48 +00:00
visinfo = NULL ;
2013-03-12 22:49:04 +00:00
break ; //erm
}
2011-02-06 20:56:39 +00:00
2016-02-10 23:23:43 +00:00
vid . activeapp = false ;
2013-03-12 22:47:42 +00:00
if ( fullscreenflags & FULLSCREEN_LEGACY )
{
2013-03-12 23:03:46 +00:00
vid_decoywindow = X_CreateWindow ( false , visinfo , 640 , 480 , false ) ;
vid_window = X_CreateWindow ( true , visinfo , width , height , fullscreen ) ;
2013-03-12 22:47:42 +00:00
}
else
2013-03-12 23:03:46 +00:00
vid_window = X_CreateWindow ( false , visinfo , width , height , fullscreen ) ;
2011-02-06 20:56:39 +00:00
2014-03-30 00:39:37 +00:00
vid_x_eventmask | = X_InitUnicode ( ) ;
x11 . pXSelectInput ( vid_dpy , vid_window , vid_x_eventmask ) ;
2013-03-12 22:47:42 +00:00
CL_UpdateWindowTitle ( ) ;
/*make it visible*/
2011-01-29 19:53:38 +00:00
2013-11-21 23:02:28 +00:00
if ( fullscreenflags & FULLSCREEN_VMODE )
2013-03-12 22:47:42 +00:00
{
2013-03-12 23:04:11 +00:00
x11 . pXRaiseWindow ( vid_dpy , vid_window ) ;
x11 . pXWarpPointer ( vid_dpy , None , vid_window , 0 , 0 , 0 , 0 , 0 , 0 ) ;
x11 . pXFlush ( vid_dpy ) ;
2004-08-22 22:29:09 +00:00
// Move the viewport to top left
2013-03-12 22:54:12 +00:00
vm . pXF86VidModeSetViewPort ( vid_dpy , scrnum , 0 , 0 ) ;
2004-08-22 22:29:09 +00:00
}
2012-10-14 10:57:11 +00:00
vid_nullcursor = CreateNullCursor ( vid_dpy , vid_window ) ;
2004-08-22 22:29:09 +00:00
2013-03-12 23:04:11 +00:00
x11 . pXFlush ( vid_dpy ) ;
2005-06-15 04:36:20 +00:00
2013-03-12 22:54:12 +00:00
if ( vm . vmajor > = 2 )
2005-04-18 05:41:39 +00:00
{
int rampsize = 256 ;
2013-03-12 22:54:12 +00:00
vm . pXF86VidModeGetGammaRampSize ( vid_dpy , scrnum , & rampsize ) ;
2016-07-28 15:57:22 +00:00
if ( rampsize > countof ( vm . originalramps [ 0 ] ) )
2005-04-18 05:41:39 +00:00
{
2013-03-12 22:54:12 +00:00
vm . originalapplied = false ;
2007-10-29 06:06:20 +00:00
Con_Printf ( " Gamma ramps are not of 256 components (but %i). \n " , rampsize ) ;
2005-04-18 05:41:39 +00:00
}
else
2016-07-28 15:57:22 +00:00
{
vm . originalrampsize = vid . gammarampsize = rampsize ;
vm . originalapplied = vm . pXF86VidModeGetGammaRamp ( vid_dpy , scrnum , vm . originalrampsize , vm . originalramps [ 0 ] , vm . originalramps [ 1 ] , vm . originalramps [ 2 ] ) ;
}
2005-04-18 05:41:39 +00:00
}
else
2013-03-12 22:54:12 +00:00
vm . originalapplied = false ;
2004-08-22 22:29:09 +00:00
2013-03-12 22:49:04 +00:00
switch ( currentpsl )
2005-04-18 05:35:23 +00:00
{
2016-07-12 00:40:13 +00:00
# ifdef GLQUAKE
2013-03-12 22:49:04 +00:00
case PSL_GLX :
ctx = qglXCreateContext ( vid_dpy , visinfo , NULL , True ) ;
if ( ! ctx )
{
Con_Printf ( " Failed to create GLX context. \n " ) ;
GLVID_Shutdown ( ) ;
return false ;
}
2004-08-22 22:29:09 +00:00
2013-03-12 22:49:04 +00:00
if ( ! qglXMakeCurrent ( vid_dpy , vid_window , ctx ) )
{
Con_Printf ( " glXMakeCurrent failed \n " ) ;
GLVID_Shutdown ( ) ;
return false ;
}
2011-02-06 20:56:39 +00:00
2013-03-12 22:49:04 +00:00
GL_Init ( & GLX_GetSymbol ) ;
break ;
# ifdef USE_EGL
case PSL_EGL :
2014-03-30 00:39:37 +00:00
if ( ! EGL_Init ( info , palette , ( EGLNativeWindowType ) vid_window , ( EGLNativeDisplayType ) vid_dpy ) )
2013-03-12 23:00:29 +00:00
{
Con_Printf ( " Failed to create EGL context. \n " ) ;
GLVID_Shutdown ( ) ;
return false ;
}
2013-03-12 22:49:04 +00:00
GL_Init ( & EGL_Proc ) ;
break ;
2016-07-12 00:40:13 +00:00
# endif
# endif
# ifdef VKQUAKE
case PSL_VULKAN :
2016-07-30 17:59:55 +00:00
# ifdef VK_USE_PLATFORM_XLIB_KHR
2016-08-25 00:12:14 +00:00
if ( VK_Init ( info , VK_KHR_XLIB_SURFACE_EXTENSION_NAME , XVK_SetupSurface_XLib , NULL ) )
2016-07-30 17:59:55 +00:00
break ;
# endif
# ifdef VK_USE_PLATFORM_XCB_KHR
2016-08-25 00:12:14 +00:00
if ( x11xcb_initlib ( ) & & VK_Init ( info , VK_KHR_XCB_SURFACE_EXTENSION_NAME , XVK_SetupSurface_XCB , NULL ) )
2016-07-30 17:59:55 +00:00
break ;
# endif
Con_Printf ( " Failed to create a vulkan context. \n " ) ;
GLVID_Shutdown ( ) ;
return false ;
2011-02-06 20:56:39 +00:00
# endif
2013-03-12 22:49:04 +00:00
case PSL_NONE :
break ;
}
2011-02-06 20:56:39 +00:00
2013-03-12 22:47:42 +00:00
//probably going to be resized in the event handler
vid . pixelwidth = fullscreenwidth = width ;
vid . pixelheight = fullscreenheight = height ;
2004-08-22 22:29:09 +00:00
vid . numpages = 2 ;
2013-03-12 22:47:42 +00:00
Con_SafePrintf ( " Video mode %dx%d initialized. \n " , width , height ) ;
if ( fullscreenflags & FULLSCREEN_WM )
X_GoFullscreen ( ) ;
if ( fullscreenflags & FULLSCREEN_LEGACY )
2013-03-12 23:04:11 +00:00
x11 . pXMoveResizeWindow ( vid_dpy , vid_window , 0 , 0 , fullscreenwidth , fullscreenheight ) ;
2013-03-12 22:47:42 +00:00
if ( fullscreenflags )
fullscreenflags | = FULLSCREEN_ACTIVE ;
2004-08-22 22:29:09 +00:00
2013-03-12 22:54:12 +00:00
// TODO: make this into a cvar, like "in_dgamouse", instead of parameters
if ( ! COM_CheckParm ( " -noxi2 " ) & & XI2_Init ( ) )
{
x11_input_method = XIM_XI2 ;
2014-03-30 00:39:37 +00:00
Con_DPrintf ( " Using XInput2 \n " ) ;
2013-03-12 22:54:12 +00:00
}
else if ( ! COM_CheckParm ( " -nodga " ) & & ! COM_CheckParm ( " -nomdga " ) & & DGAM_Init ( ) )
{
x11_input_method = XIM_DGA ;
2014-03-30 00:39:37 +00:00
Con_DPrintf ( " Using DGA mouse \n " ) ;
2013-03-12 22:54:12 +00:00
}
else
{
x11_input_method = XIM_ORIG ;
2014-03-30 00:39:37 +00:00
Con_DPrintf ( " Using X11 mouse \n " ) ;
2013-03-12 22:54:12 +00:00
}
2014-09-21 03:35:38 +00:00
x11 . pXRaiseWindow ( vid_dpy , vid_window ) ;
if ( fullscreenflags & FULLSCREEN_LEGACY )
x11 . pXMoveResizeWindow ( vid_dpy , vid_window , 0 , 0 , fullscreenwidth , fullscreenheight ) ;
2004-08-22 22:29:09 +00:00
if ( Cvar_Get ( " vidx_grabkeyboard " , " 0 " , 0 , " Additional video options " ) - > value )
2013-03-12 23:04:11 +00:00
x11 . pXGrabKeyboard ( vid_dpy , vid_window ,
2004-08-22 22:29:09 +00:00
False ,
GrabModeAsync , GrabModeAsync ,
CurrentTime ) ;
2014-09-21 03:35:38 +00:00
else if ( fullscreenflags & FULLSCREEN_LEGACY )
x11 . pXSetInputFocus ( vid_dpy , vid_window , RevertToNone , CurrentTime ) ;
2004-08-22 22:29:09 +00:00
return true ;
}
2016-07-12 00:40:13 +00:00
# ifdef GLQUAKE
2013-03-12 22:49:04 +00:00
qboolean GLVID_Init ( rendererstate_t * info , unsigned char * palette )
{
return X11VID_Init ( info , palette , PSL_GLX ) ;
}
2013-03-12 22:49:26 +00:00
# ifdef USE_EGL
2013-03-12 22:49:04 +00:00
qboolean EGLVID_Init ( rendererstate_t * info , unsigned char * palette )
{
return X11VID_Init ( info , palette , PSL_EGL ) ;
}
2013-03-12 22:49:26 +00:00
# endif
2016-07-12 00:40:13 +00:00
# endif
# ifdef VKQUAKE
static qboolean VKVID_Init ( rendererstate_t * info , unsigned char * palette )
{
return X11VID_Init ( info , palette , PSL_VULKAN ) ;
}
# endif
2004-08-22 22:29:09 +00:00
void Sys_SendKeyEvents ( void )
{
2013-03-12 23:03:46 +00:00
# ifndef CLIENTONLY
//this is stupid
SV_GetConsoleCommands ( ) ;
# endif
2015-05-16 08:02:05 +00:00
if ( sys_gracefulexit )
2013-03-12 22:47:42 +00:00
{
Cbuf_AddText ( " \n quit \n " , RESTRICT_LOCAL ) ;
2015-05-16 08:02:05 +00:00
sys_gracefulexit = false ;
2013-03-12 22:47:42 +00:00
}
if ( vid_dpy & & vid_window )
{
qboolean wantwindowed ;
2013-03-12 23:04:11 +00:00
while ( x11 . pXPending ( vid_dpy ) )
2004-08-22 22:29:09 +00:00
GetEvent ( ) ;
2013-03-12 22:47:42 +00:00
if ( modeswitchpending & & modeswitchtime < Sys_Milliseconds ( ) )
{
if ( old_windowed_mouse )
{
Con_DPrintf ( " uninstall grabs \n " ) ;
uninstall_grabs ( ) ;
2013-03-12 23:04:11 +00:00
x11 . pXUndefineCursor ( vid_dpy , vid_window ) ;
2013-03-12 22:47:42 +00:00
old_windowed_mouse = false ;
}
2013-03-12 22:54:12 +00:00
if ( modeswitchpending > 0 & & ! ( fullscreenflags & FULLSCREEN_ACTIVE ) )
2013-03-12 22:47:42 +00:00
{
//entering fullscreen mode
if ( fullscreenflags & FULLSCREEN_VMODE )
{
if ( ! ( fullscreenflags & FULLSCREEN_VMODEACTIVE ) )
{
// change to the mode
2013-03-12 22:54:12 +00:00
vm . pXF86VidModeSwitchToMode ( vid_dpy , scrnum , vm . modes [ vm . usemode ] ) ;
2013-03-12 22:47:42 +00:00
fullscreenflags | = FULLSCREEN_VMODEACTIVE ;
// Move the viewport to top left
}
2013-03-12 22:54:12 +00:00
vm . pXF86VidModeSetViewPort ( vid_dpy , scrnum , 0 , 0 ) ;
2013-03-12 22:47:42 +00:00
}
Cvar_ForceCallback ( & v_gamma ) ;
/*release the mouse now, because we're paranoid about clip regions*/
if ( fullscreenflags & FULLSCREEN_WM )
X_GoFullscreen ( ) ;
if ( fullscreenflags & FULLSCREEN_LEGACY )
{
2013-03-12 23:04:11 +00:00
x11 . pXMoveWindow ( vid_dpy , vid_window , 0 , 0 ) ;
x11 . pXReparentWindow ( vid_dpy , vid_window , vid_root , 0 , 0 ) ;
//x11.pXUnmapWindow(vid_dpy, vid_decoywindow);
2013-03-12 22:47:42 +00:00
//make sure we have it
2013-03-12 23:04:11 +00:00
x11 . pXSetInputFocus ( vid_dpy , vid_window , RevertToParent , CurrentTime ) ;
x11 . pXRaiseWindow ( vid_dpy , vid_window ) ;
x11 . pXMoveResizeWindow ( vid_dpy , vid_window , 0 , 0 , fullscreenwidth , fullscreenheight ) ;
2013-03-12 22:47:42 +00:00
}
if ( fullscreenflags )
fullscreenflags | = FULLSCREEN_ACTIVE ;
}
if ( modeswitchpending < 0 )
{
//leave fullscreen mode
if ( ! COM_CheckParm ( " -stayactive " ) )
{ //a parameter that leaves the program fullscreen if you taskswitch.
//sounds pointless, works great with two moniters. :D
if ( fullscreenflags & FULLSCREEN_VMODE )
{
2013-03-12 22:54:12 +00:00
if ( vm . originalapplied )
2016-07-28 15:57:22 +00:00
vm . pXF86VidModeSetGammaRamp ( vid_dpy , scrnum , vm . originalrampsize , vm . originalramps [ 0 ] , vm . originalramps [ 1 ] , vm . originalramps [ 2 ] ) ;
2013-03-12 22:47:42 +00:00
if ( fullscreenflags & FULLSCREEN_VMODEACTIVE )
{
2013-03-12 22:54:12 +00:00
vm . pXF86VidModeSwitchToMode ( vid_dpy , scrnum , vm . modes [ 0 ] ) ;
2013-03-12 22:47:42 +00:00
fullscreenflags & = ~ FULLSCREEN_VMODEACTIVE ;
}
}
}
if ( fullscreenflags & FULLSCREEN_WM )
X_GoWindowed ( ) ;
if ( fullscreenflags & FULLSCREEN_LEGACY )
{
2013-03-12 23:04:11 +00:00
x11 . pXMapWindow ( vid_dpy , vid_decoywindow ) ;
x11 . pXReparentWindow ( vid_dpy , vid_window , vid_decoywindow , 0 , 0 ) ;
x11 . pXResizeWindow ( vid_dpy , vid_decoywindow , 640 , 480 ) ;
2013-03-12 22:47:42 +00:00
}
fullscreenflags & = ~ FULLSCREEN_ACTIVE ;
}
2014-03-30 08:55:06 +00:00
modeswitchpending = 0 ;
2013-03-12 22:47:42 +00:00
}
if ( modeswitchpending )
return ;
wantwindowed = ! ! _windowed_mouse . value ;
2016-02-10 23:23:43 +00:00
if ( ! vid . activeapp )
2013-03-12 22:47:42 +00:00
wantwindowed = false ;
if ( Key_MouseShouldBeFree ( ) & & ! fullscreenflags )
wantwindowed = false ;
if ( old_windowed_mouse ! = wantwindowed )
{
old_windowed_mouse = wantwindowed ;
if ( ! wantwindowed )
{
Con_DPrintf ( " uninstall grabs \n " ) ;
/* ungrab the pointer */
uninstall_grabs ( ) ;
2013-03-12 23:04:11 +00:00
x11 . pXUndefineCursor ( vid_dpy , vid_window ) ;
2013-03-12 22:47:42 +00:00
}
else
{
Con_DPrintf ( " install grabs \n " ) ;
/* grab the pointer */
2013-03-12 22:54:12 +00:00
install_grabs ( ) ;
2013-03-12 22:47:42 +00:00
/*hide the cursor*/
2013-03-12 23:04:11 +00:00
x11 . pXDefineCursor ( vid_dpy , vid_window , vid_nullcursor ) ;
2013-03-12 22:47:42 +00:00
}
}
2004-08-22 22:29:09 +00:00
}
}
void Force_CenterView_f ( void )
{
2012-07-06 21:34:23 +00:00
cl . playerview [ 0 ] . viewangles [ PITCH ] = 0 ;
2004-08-22 22:29:09 +00:00
}
2006-05-10 22:12:20 +00:00
2012-10-14 09:00:49 +00:00
//these are done from the x11 event handler. we don't support evdev.
void INS_Move ( float * movements , int pnum )
2004-08-22 22:29:09 +00:00
{
}
2012-10-14 09:00:49 +00:00
void INS_Commands ( void )
2004-08-22 22:29:09 +00:00
{
}
2012-10-14 09:00:49 +00:00
void INS_Init ( void )
2004-08-22 22:29:09 +00:00
{
}
2012-10-14 09:00:49 +00:00
void INS_ReInit ( void )
2004-08-22 22:29:09 +00:00
{
}
2012-10-14 09:00:49 +00:00
void INS_Shutdown ( void )
2004-08-22 22:29:09 +00:00
{
}
2016-07-21 19:27:59 +00:00
void INS_EnumerateDevices ( void * ctx , void ( * callback ) ( void * ctx , const char * type , const char * devicename , unsigned int * qdevid ) )
2015-04-14 23:12:17 +00:00
{
}
2004-08-22 22:29:09 +00:00
2016-07-12 00:40:13 +00:00
void GLVID_SetCaption ( const char * text )
2007-03-28 12:57:05 +00:00
{
2016-07-12 00:40:13 +00:00
x11 . pXStoreName ( vid_dpy , vid_window , ( char * ) text ) ;
2007-03-28 12:57:05 +00:00
}
2013-03-12 22:49:04 +00:00
# ifdef USE_EGL
# include "shader.h"
# include "gl_draw.h"
rendererinfo_t eglrendererinfo =
{
2014-03-30 00:39:37 +00:00
" EGL(X11) " ,
2013-03-12 22:49:04 +00:00
{
" egl "
} ,
QR_OPENGL ,
GLDraw_Init ,
GLDraw_DeInit ,
2014-10-05 20:04:11 +00:00
GL_UpdateFiltering ,
GL_LoadTextureMips ,
2013-03-12 22:49:04 +00:00
GL_DestroyTexture ,
GLR_Init ,
GLR_DeInit ,
GLR_RenderView ,
EGLVID_Init ,
GLVID_DeInit ,
2014-03-30 00:39:37 +00:00
GLVID_SwapBuffers ,
GLVID_ApplyGammaRamps ,
2013-03-12 22:49:04 +00:00
2014-09-02 02:44:43 +00:00
NULL ,
NULL ,
NULL ,
2013-03-12 22:49:04 +00:00
GLVID_SetCaption , //setcaption
2014-03-30 00:39:37 +00:00
GLVID_GetRGBInfo ,
2013-03-12 22:49:04 +00:00
GLSCR_UpdateScreen ,
GLBE_SelectMode ,
GLBE_DrawMesh_List ,
GLBE_DrawMesh_Single ,
GLBE_SubmitBatch ,
GLBE_GetTempBatch ,
GLBE_DrawWorld ,
GLBE_Init ,
GLBE_GenBrushModelVBO ,
GLBE_ClearVBO ,
GLBE_UploadAllLightmaps ,
GLBE_SelectEntity ,
GLBE_SelectDLight ,
2014-03-30 00:39:37 +00:00
GLBE_Scissor ,
2013-03-12 22:49:04 +00:00
GLBE_LightCullModel ,
2014-03-30 00:39:37 +00:00
GLBE_VBO_Begin ,
2014-03-30 08:55:06 +00:00
GLBE_VBO_Data ,
GLBE_VBO_Finish ,
GLBE_VBO_Destroy ,
2014-03-30 00:39:37 +00:00
2014-03-30 08:55:06 +00:00
GLBE_RenderToTextureUpdate2d ,
2014-03-30 00:39:37 +00:00
2013-03-12 22:49:04 +00:00
" "
} ;
# endif
2013-03-12 22:47:42 +00:00
2016-07-12 00:40:13 +00:00
# ifdef VKQUAKE
2016-07-30 17:59:55 +00:00
# ifdef VK_USE_PLATFORM_XLIB_KHR
static qboolean XVK_SetupSurface_XLib ( void )
2016-07-12 00:40:13 +00:00
{
VkXlibSurfaceCreateInfoKHR inf = { VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR } ;
inf . flags = 0 ;
inf . dpy = vid_dpy ;
inf . window = vid_window ;
if ( VK_SUCCESS = = vkCreateXlibSurfaceKHR ( vk . instance , & inf , vkallocationcb , & vk . surface ) )
return true ;
return false ;
}
2016-07-30 17:59:55 +00:00
# endif
# ifdef VK_USE_PLATFORM_XCB_KHR
static qboolean XVK_SetupSurface_XCB ( void )
{
VkXcbSurfaceCreateInfoKHR inf = { VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR } ;
inf . flags = 0 ;
inf . connection = x11xcb . pXGetXCBConnection ( vid_dpy ) ;
inf . window = vid_window ;
if ( VK_SUCCESS = = vkCreateXcbSurfaceKHR ( vk . instance , & inf , vkallocationcb , & vk . surface ) )
return true ;
return false ;
}
# endif
2016-07-12 00:40:13 +00:00
rendererinfo_t vkrendererinfo =
{
" Vulkan(X11) " ,
{
" vk " ,
" xvk " ,
" vulkan "
} ,
QR_VULKAN ,
VK_Draw_Init ,
VK_Draw_Shutdown ,
VK_UpdateFiltering ,
VK_LoadTextureMips ,
VK_DestroyTexture ,
VK_R_Init ,
VK_R_DeInit ,
VK_R_RenderView ,
VKVID_Init ,
GLVID_DeInit ,
GLVID_SwapBuffers ,
GLVID_ApplyGammaRamps ,
NULL ,
NULL ,
NULL ,
GLVID_SetCaption , //setcaption
VKVID_GetRGBInfo ,
VK_SCR_UpdateScreen ,
VKBE_SelectMode ,
VKBE_DrawMesh_List ,
VKBE_DrawMesh_Single ,
VKBE_SubmitBatch ,
VKBE_GetTempBatch ,
VKBE_DrawWorld ,
VKBE_Init ,
VKBE_GenBrushModelVBO ,
VKBE_ClearVBO ,
VKBE_UploadAllLightmaps ,
VKBE_SelectEntity ,
VKBE_SelectDLight ,
VKBE_Scissor ,
VKBE_LightCullModel ,
VKBE_VBO_Begin ,
VKBE_VBO_Data ,
VKBE_VBO_Finish ,
VKBE_VBO_Destroy ,
VKBE_RenderToTextureUpdate2d ,
" "
} ;
# endif
2013-03-12 22:47:42 +00:00
# if 1
char * Sys_GetClipboard ( void )
{
2013-03-12 23:04:11 +00:00
Atom xa_clipboard = x11 . pXInternAtom ( vid_dpy , " PRIMARY " , false ) ;
Atom xa_string = x11 . pXInternAtom ( vid_dpy , " UTF8_STRING " , false ) ;
Window clipboardowner = x11 . pXGetSelectionOwner ( vid_dpy , xa_clipboard ) ;
2013-03-12 22:47:42 +00:00
if ( clipboardowner ! = None & & clipboardowner ! = vid_window )
{
int fmt ;
Atom type ;
unsigned long nitems , bytesleft ;
unsigned char * data ;
2013-03-12 23:04:11 +00:00
x11 . pXConvertSelection ( vid_dpy , xa_clipboard , xa_string , None , vid_window , CurrentTime ) ;
x11 . pXFlush ( vid_dpy ) ;
x11 . pXGetWindowProperty ( vid_dpy , vid_window , xa_string , 0 , 0 , False , AnyPropertyType , & type , & fmt , & nitems , & bytesleft , & data ) ;
2013-03-12 22:47:42 +00:00
return data ;
}
2014-03-30 08:55:06 +00:00
return clipboard_buffer ;
2013-03-12 22:47:42 +00:00
}
void Sys_CloseClipboard ( char * bf )
{
if ( bf = = clipboard_buffer )
return ;
2013-03-12 23:04:11 +00:00
x11 . pXFree ( bf ) ;
2013-03-12 22:47:42 +00:00
}
void Sys_SaveClipboard ( char * text )
{
2013-03-12 23:04:11 +00:00
Atom xa_clipboard = x11 . pXInternAtom ( vid_dpy , " PRIMARY " , false ) ;
2014-03-30 08:55:06 +00:00
Q_strncpyz ( clipboard_buffer , text , SYS_CLIPBOARD_SIZE ) ;
2013-03-12 23:04:11 +00:00
x11 . pXSetSelectionOwner ( vid_dpy , xa_clipboard , vid_window , CurrentTime ) ;
2013-03-12 22:47:42 +00:00
}
# endif
2013-03-12 23:04:11 +00:00
qboolean X11_GetDesktopParameters ( int * width , int * height , int * bpp , int * refreshrate )
{
2014-03-30 08:55:06 +00:00
Display * xtemp ;
int scr ;
2013-03-12 23:04:11 +00:00
if ( ! x11_initlib ( ) )
return false ;
2014-03-30 08:55:06 +00:00
xtemp = x11 . pXOpenDisplay ( NULL ) ;
2013-03-12 23:04:11 +00:00
2014-03-30 08:55:06 +00:00
if ( ! xtemp )
return false ;
2013-03-12 23:04:11 +00:00
2014-03-30 08:55:06 +00:00
scr = DefaultScreen ( xtemp ) ;
2013-03-12 23:04:11 +00:00
2014-03-30 08:55:06 +00:00
* width = DisplayWidth ( xtemp , scr ) ;
* height = DisplayHeight ( xtemp , scr ) ;
* bpp = DefaultDepth ( xtemp , scr ) ;
* refreshrate = 0 ;
2013-03-12 23:04:11 +00:00
2014-03-30 08:55:06 +00:00
x11 . pXCloseDisplay ( xtemp ) ;
2013-03-12 23:04:11 +00:00
2014-03-30 08:55:06 +00:00
return true ;
2013-03-12 23:04:11 +00:00
}
2016-07-30 17:59:55 +00:00