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
/*
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>
2004-08-22 22:29:09 +00:00
# include "glquake.h"
# 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
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 ;
2004-08-22 22:29:09 +00:00
static GLXContext ctx = NULL ;
2013-03-12 22:47:42 +00:00
static int scrnum ;
2013-03-12 22:49:04 +00:00
static enum
{
PSL_NONE ,
# ifdef USE_EGL
PSL_EGL ,
# endif
PSL_GLX
} 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
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 ) ;
} x11 ;
static qboolean x11_initlib ( void )
{
dllfunction_t x11_functable [ ] =
{
{ ( 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 " } ,
{ NULL , NULL }
} ;
if ( ! x11 . lib )
{
2013-05-13 13:43:18 +00:00
x11 . lib = Sys_LoadLibrary ( " libX11.so.6 " , x11_functable ) ;
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 )
{
x11 . pXGetEventData = Sys_GetAddressForName ( x11 . lib , " XGetEventData " ) ;
x11 . pXFreeEventData = Sys_GetAddressForName ( x11 . lib , " XFreeEventData " ) ;
}
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
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 ;
unsigned short originalramps [ 3 ] [ 256 ] ;
qboolean originalapplied ; //states that the origionalramps arrays are valid, and contain stuff that we should revert to on close
} vm ;
static qboolean VMODE_Init ( void )
{
dllfunction_t vm_functable [ ] =
{
{ ( 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
{
Con_Printf ( " DGA extension not available. \n " ) ;
return false ;
}
if ( ! vm . lib )
vm . lib = Sys_LoadLibrary ( " libXxf86vm " , vm_functable ) ;
if ( vm . lib )
{
if ( vm . pXF86VidModeQueryVersion ( vid_dpy , & vm . vmajor , & vm . vminor ) )
Con_Printf ( " Using XF86-VidModeExtension Ver. %d.%d \n " , vm . vmajor , vm . vminor ) ;
else
{
Con_Printf ( " No XF86-VidModeExtension support \n " ) ;
vm . vmajor = 0 ;
vm . vminor = 0 ;
}
}
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 )
{
dllfunction_t dgam_functable [ ] =
{
{ ( 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 {
int mask_len ;
unsigned char * mask ;
double * values ;
} XIValuatorState ;
typedef struct
{
int deviceid ;
int mask_len ;
unsigned char * mask ;
} XIEventMask ;
# define XIAllMasterDevices 1
# define XI_RawButtonPress 15
# define XI_RawButtonRelease 16
# define XI_RawMotion 17
# define XI_LASTEVENT XI_RawMotion
typedef struct {
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 ;
} 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 )
{
dllfunction_t xi2_functable [ ] =
{
{ ( 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 )
{
2013-05-13 13:43:18 +00:00
xi2 . libxi = Sys_LoadLibrary ( " libXi.so.6 " , xi2_functable ) ;
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)
{
XISetMask ( maskbuf , XI_RawTouchBegin ) ;
XISetMask ( maskbuf , XI_RawTouchUpdate ) ;
XISetMask ( maskbuf , XI_RawTouchEnd ) ;
}
*/ 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;
2005-01-24 03:07:16 +00:00
qboolean ActiveApp = false ;
2013-03-12 22:47:42 +00:00
static qboolean gracefulexit ;
# define SYS_CLIPBOARD_SIZE 512
char clipboard_buffer [ SYS_CLIPBOARD_SIZE ] ;
2004-08-22 22:29:09 +00:00
/*-----------------------------------------------------------------------*/
static void * gllibrary ;
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 )
{
dlclose ( gllibrary ) ;
gllibrary = NULL ;
}
qboolean GLX_InitLibrary ( char * driver )
{
if ( driver & & * driver )
2005-12-15 19:15:39 +00:00
gllibrary = dlopen ( driver , RTLD_LAZY ) ;
2004-08-22 22:29:09 +00:00
else
gllibrary = NULL ;
2004-12-22 13:47:57 +00:00
if ( ! gllibrary ) //I hate this.
2005-12-15 19:15:39 +00:00
gllibrary = dlopen ( " libGL.so.1 " , RTLD_LAZY ) ;
2005-12-21 03:07:33 +00:00
if ( ! gllibrary )
gllibrary = dlopen ( " libGL.so " , RTLD_LAZY ) ;
2004-08-22 22:29:09 +00:00
if ( ! gllibrary )
return false ;
qglXChooseVisual = dlsym ( gllibrary , " glXChooseVisual " ) ;
qglXSwapBuffers = dlsym ( gllibrary , " glXSwapBuffers " ) ;
qglXMakeCurrent = dlsym ( gllibrary , " glXMakeCurrent " ) ;
qglXCreateContext = dlsym ( gllibrary , " glXCreateContext " ) ;
qglXDestroyContext = dlsym ( gllibrary , " glXDestroyContext " ) ;
qglXGetProcAddress = dlsym ( gllibrary , " glXGetProcAddress " ) ;
if ( ! qglXGetProcAddress )
qglXGetProcAddress = dlsym ( gllibrary , " glXGetProcAddressARB " ) ;
if ( ! qglXSwapBuffers & & ! qglXDestroyContext & & ! qglXCreateContext & & ! qglXMakeCurrent & & ! qglXChooseVisual )
return false ;
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 )
symb = dlsym ( gllibrary , name ) ;
return symb ;
}
2009-07-07 21:32:54 +00:00
static int XLateKey ( XKeyEvent * ev , unsigned int * unicode )
2004-08-22 22:29:09 +00:00
{
int key ;
char buf [ 64 ] ;
2009-07-07 21:32:54 +00:00
KeySym keysym , shifted ;
2004-08-22 22:29:09 +00:00
key = 0 ;
2013-03-12 23:04:11 +00:00
keysym = x11 . pXLookupKeysym ( ev , 0 ) ;
2009-07-07 21:32:54 +00:00
if ( unicode )
2013-05-13 13:43:18 +00:00
{
if ( ( keysym & 0xff000000 ) = = 0x01000000 )
* unicode = keysym & 0x00ffffff ;
else
{
x11 . pXLookupString ( ev , buf , sizeof buf , & shifted , 0 ) ;
* unicode = ( unsigned char ) buf [ 0 ] ;
}
}
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
return key ;
}
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 ;
2009-07-07 21:32:54 +00:00
unsigned int uc ;
2008-02-05 00:38:41 +00:00
qboolean x11violations = true ;
2013-03-12 22:47:42 +00:00
Window mw ;
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
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 + + ;
}
}
IN_MouseMove ( raw - > deviceid , false , rawx , rawy , 0 , 0 ) ;
}
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 :
2009-11-04 21:16:50 +00:00
vid . pixelwidth = event . xresizerequest . width ;
vid . pixelheight = event . xresizerequest . height ;
2013-03-12 22:47:42 +00:00
Cvar_ForceCallback ( & vid_conautoscale ) ;
// 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 )
{
vid . pixelwidth = event . xconfigurerequest . width ;
vid . pixelheight = event . xconfigurerequest . height ;
Cvar_ForceCallback ( & vid_conautoscale ) ;
}
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 :
2009-07-07 21:32:54 +00:00
b = XLateKey ( & event . xkey , & uc ) ;
2010-08-14 03:17:33 +00:00
Key_Event ( 0 , b , uc , true ) ;
2009-07-07 21:32:54 +00:00
break ;
2004-08-22 22:29:09 +00:00
case KeyRelease :
2009-07-07 21:32:54 +00:00
b = XLateKey ( & event . xkey , NULL ) ;
2010-08-14 03:17:33 +00:00
Key_Event ( 0 , b , 0 , false ) ;
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*/
2013-03-12 23:04:11 +00:00
x11 . pXSelectInput ( vid_dpy , vid_window , X_MASK & ~ PointerMotionMask ) ;
x11 . pXWarpPointer ( vid_dpy , None , vid_window , 0 , 0 , 0 , 0 ,
2013-03-12 22:54:12 +00:00
cx , cy ) ;
2013-03-12 23:04:11 +00:00
x11 . pXSelectInput ( vid_dpy , vid_window , X_MASK ) ;
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 )
2005-11-21 21:07:45 +00:00
if ( ! ActiveApp )
{ //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
2005-01-24 03:07:16 +00:00
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 )
vm . pXF86VidModeSetGammaRamp ( vid_dpy , scrnum , 256 , 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 ;
if ( event . xfocus . window = = mw )
{
ActiveApp = false ;
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 )
{
2005-12-05 21:22:36 +00:00
printf ( " GLVID_Shutdown \n " ) ;
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 )
vm . pXF86VidModeSetGammaRamp ( vid_dpy , scrnum , 256 , vm . originalramps [ 0 ] , vm . originalramps [ 1 ] , vm . originalramps [ 2 ] ) ;
2013-03-12 22:49:04 +00:00
switch ( currentpsl )
{
# ifdef USE_EGL
case PSL_EGL :
EGL_Shutdown ( ) ;
break ;
# endif
case PSL_GLX :
if ( ctx )
{
qglXDestroyContext ( vid_dpy , ctx ) ;
ctx = NULL ;
}
break ;
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 ( ) ;
}
2013-03-12 22:47:42 +00:00
void signal_handler_graceful ( int sig )
{
gracefulexit = true ;
// signal(sig, signal_handler);
}
2004-08-22 22:29:09 +00:00
void InitSig ( void )
{
2013-03-12 22:47:42 +00:00
signal ( SIGINT , signal_handler_graceful ) ;
2004-08-22 22:29:09 +00:00
}
static Cursor CreateNullCursor ( Display * display , Window root )
{
2005-06-15 04:36:20 +00:00
Pixmap cursormask ;
2004-08-22 22:29:09 +00:00
XGCValues xgc ;
GC gc ;
XColor dummycolour ;
Cursor cursor ;
2013-03-12 23:04:11 +00:00
cursormask = x11 . pXCreatePixmap ( display , root , 1 , 1 , 1 /*depth*/ ) ;
2004-08-22 22:29:09 +00:00
xgc . function = GXclear ;
2013-03-12 23:04:11 +00:00
gc = x11 . pXCreateGC ( display , cursormask , GCFunction , & xgc ) ;
x11 . pXFillRectangle ( display , cursormask , gc , 0 , 0 , 1 , 1 ) ;
2004-08-22 22:29:09 +00:00
dummycolour . pixel = 0 ;
dummycolour . red = 0 ;
dummycolour . flags = 04 ;
2013-03-12 23:04:11 +00:00
cursor = x11 . pXCreatePixmapCursor ( display , cursormask , cursormask ,
2004-08-22 22:29:09 +00:00
& dummycolour , & dummycolour , 0 , 0 ) ;
2013-03-12 23:04:11 +00:00
x11 . pXFreePixmap ( display , cursormask ) ;
x11 . pXFreeGC ( display , gc ) ;
2004-08-22 22:29:09 +00:00
return cursor ;
}
2013-05-13 13:43:18 +00:00
qboolean GLVID_ApplyGammaRamps ( 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
2013-05-13 13:43:18 +00:00
if ( ramps )
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.
// if (vid_hardwaregamma.value == 1 && !ActiveApp && !(fullscreenflags & FULLSCREEN_ACTIVE))
// return false;
// if (!ActiveApp)
// 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 )
2013-05-13 13:43:18 +00:00
vm . pXF86VidModeSetGammaRamp ( vid_dpy , scrnum , 256 , & ramps [ 0 ] , & ramps [ 256 ] , & ramps [ 512 ] ) ;
else
gammaworks = ! ! vm . pXF86VidModeSetGammaRamp ( vid_dpy , scrnum , 256 , & ramps [ 0 ] , & ramps [ 256 ] , & ramps [ 512 ] ) ;
return gammaworks ;
2005-01-24 03:07:16 +00:00
}
else
2004-08-22 22:29:09 +00:00
{
2013-05-13 13:43:18 +00:00
vm . pXF86VidModeSetGammaRamp ( vid_dpy , scrnum , 256 , vm . originalramps [ 0 ] , vm . originalramps [ 1 ] , vm . originalramps [ 2 ] ) ;
return true ;
2004-08-22 22:29:09 +00:00
}
}
/*
= = = = = = = = = = = = = = = = =
GL_BeginRendering
= = = = = = = = = = = = = = = = =
*/
2009-11-05 03:07:52 +00:00
void GL_BeginRendering ( void )
2004-08-22 22:29:09 +00:00
{
2013-03-12 22:49:04 +00:00
switch ( currentpsl )
{
2011-02-06 20:56:39 +00:00
# ifdef USE_EGL
2013-03-12 22:49:04 +00:00
case PSL_EGL :
EGL_BeginRendering ( ) ;
break ;
2011-02-06 20:56:39 +00:00
# endif
2013-03-12 22:49:04 +00:00
case PSL_GLX :
case PSL_NONE :
break ;
}
2004-08-22 22:29:09 +00:00
}
void GL_EndRendering ( void )
{
2013-03-12 22:49:04 +00:00
switch ( currentpsl )
{
2011-02-06 20:56:39 +00:00
# ifdef USE_EGL
2013-03-12 22:49:04 +00:00
case PSL_EGL :
EGL_EndRendering ( ) ;
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 ;
case PSL_NONE :
break ;
}
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 ;
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
data [ 0 ] = icon . width ;
data [ 1 ] = icon . height ;
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 ;
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 ) ;
2013-03-12 22:47:42 +00:00
//for any other window managers, and broken NETWM
2013-03-12 23:04:11 +00:00
x11 . pXMoveResizeWindow ( vid_dpy , vid_window , 0 , 0 , fullscreenwidth , fullscreenheight ) ;
x11 . pXSync ( vid_dpy , False ) ;
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
2013-03-12 23:04:11 +00:00
//x11.pXMoveResizeWindow(vid_dpy, vid_window, 0, 0, 640, 480);
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 ;
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 ) ;
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 ) ;
2013-03-12 22:47:42 +00:00
attr . event_mask = X_MASK ;
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 ;
2004-08-22 22:29:09 +00:00
int i ;
int attrib [ ] = {
GLX_RGBA ,
GLX_RED_SIZE , 1 ,
GLX_GREEN_SIZE , 1 ,
GLX_BLUE_SIZE , 1 ,
GLX_DOUBLEBUFFER ,
GLX_DEPTH_SIZE , 1 ,
2011-01-28 00:40:02 +00:00
GLX_STENCIL_SIZE , 8 ,
2004-08-22 22:29:09 +00:00
None
} ;
2011-02-06 20:56:39 +00:00
# ifdef USE_EGL
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
{
2013-03-12 22:49:04 +00:00
# ifdef USE_EGL
case PSL_EGL :
if ( ! EGL_LoadLibrary ( info - > glrenderer ) )
{
Con_Printf ( " couldn't load EGL library \n " ) ;
return false ;
}
break ;
# endif
case PSL_GLX :
if ( ! GLX_InitLibrary ( info - > glrenderer ) )
{
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 ;
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 ;
if ( vm . vmajor )
2004-08-22 22:29:09 +00:00
{
int best_fit , best_dist , dist , x , y ;
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
{
2013-03-12 22:54:12 +00:00
if ( width > vm . modes [ i ] - > hdisplay | |
height > vm . modes [ i ] - > vdisplay )
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 ;
2004-08-22 22:29:09 +00:00
dist = ( x * x ) + ( y * y ) ;
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
fullscreenflags | = FULLSCREEN_LEGACY ;
}
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
{
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 )
{
Sys_Error ( " qkHack: Error couldn't get an RGB, Double-buffered, Depth visual \n " ) ;
}
break ;
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
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
2013-03-12 22:47:42 +00:00
CL_UpdateWindowTitle ( ) ;
/*make it visible*/
2011-01-29 19:53:38 +00:00
2013-03-12 22:47:42 +00:00
if ( fullscreen & FULLSCREEN_VMODE )
{
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 ) ;
2005-04-18 05:41:39 +00:00
if ( rampsize ! = 256 )
{
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
2013-03-12 22:54:12 +00:00
vm . originalapplied = vm . pXF86VidModeGetGammaRamp ( vid_dpy , scrnum , 256 , 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
{
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 :
2013-03-12 23:00:29 +00:00
if ( ! EGL_Init ( info , palette , vid_window , vid_dpy ) )
{
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 ;
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
InitSig ( ) ; // trap evil signals
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 ;
Con_Printf ( " Using XInput2 \n " ) ;
}
else if ( ! COM_CheckParm ( " -nodga " ) & & ! COM_CheckParm ( " -nomdga " ) & & DGAM_Init ( ) )
{
x11_input_method = XIM_DGA ;
Con_Printf ( " Using DGA mouse \n " ) ;
}
else
{
x11_input_method = XIM_ORIG ;
Con_Printf ( " Using X11 mouse \n " ) ;
}
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 ) ;
else
2013-03-12 23:04:11 +00:00
x11 . pXSetInputFocus ( vid_dpy , vid_window , RevertToParent , CurrentTime ) ;
x11 . pXRaiseWindow ( vid_dpy , vid_window ) ;
2013-03-12 22:47:42 +00:00
if ( fullscreenflags & FULLSCREEN_LEGACY )
2013-03-12 23:04:11 +00:00
x11 . pXMoveResizeWindow ( vid_dpy , vid_window , 0 , 0 , fullscreenwidth , fullscreenheight ) ;
2004-08-22 22:29:09 +00:00
return true ;
}
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
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
2013-03-12 22:47:42 +00:00
if ( gracefulexit )
{
Cbuf_AddText ( " \n quit \n " , RESTRICT_LOCAL ) ;
gracefulexit = false ;
}
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 )
vm . pXF86VidModeSetGammaRamp ( vid_dpy , scrnum , 256 , 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 ;
}
modeswitchpending = 0 ;
}
if ( modeswitchpending )
return ;
wantwindowed = ! ! _windowed_mouse . value ;
if ( ! ActiveApp )
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
{
}
2004-11-29 05:52:57 +00:00
void GL_DoSwap ( void ) { }
2007-03-28 12:57:05 +00:00
void GLVID_SetCaption ( char * text )
{
2013-03-12 23:04:11 +00:00
x11 . pXStoreName ( vid_dpy , vid_window , 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 =
{
" EGL " ,
{
" egl "
} ,
QR_OPENGL ,
GLDraw_Init ,
GLDraw_DeInit ,
GL_LoadTextureFmt ,
GL_LoadTexture8Pal24 ,
GL_LoadTexture8Pal32 ,
GL_LoadCompressed ,
GL_FindTexture ,
GL_AllocNewTexture ,
GL_UploadFmt ,
GL_DestroyTexture ,
GLR_Init ,
GLR_DeInit ,
GLR_RenderView ,
GLR_NewMap ,
GLR_PreNewMap ,
Surf_AddStain ,
Surf_LessenStains ,
RMod_Init ,
RMod_Shutdown ,
RMod_ClearAll ,
RMod_ForName ,
RMod_FindName ,
RMod_Extradata ,
RMod_TouchModel ,
RMod_NowLoadExternal ,
RMod_Think ,
Mod_GetTag ,
Mod_TagNumForName ,
Mod_SkinNumForName ,
Mod_FrameNumForName ,
Mod_FrameDuration ,
EGLVID_Init ,
GLVID_DeInit ,
GLVID_SetPalette ,
GLVID_ShiftPalette ,
GLVID_GetRGBInfo ,
GLVID_SetCaption , //setcaption
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 ,
GLBE_LightCullModel ,
" "
} ;
# 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 ;
}
return clipboard_buffer ;
}
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 ) ;
2013-03-12 22:47:42 +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 )
{
Display * xtemp ;
int scr ;
if ( ! x11_initlib ( ) )
return false ;
xtemp = x11 . pXOpenDisplay ( NULL ) ;
if ( ! xtemp )
return false ;
scr = DefaultScreen ( xtemp ) ;
* width = DisplayWidth ( xtemp , scr ) ;
* height = DisplayHeight ( xtemp , scr ) ;
* bpp = DefaultDepth ( xtemp , scr ) ;
* refreshrate = 0 ;
x11 . pXCloseDisplay ( xtemp ) ;
return true ;
}