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
# 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 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 ;
if ( ! XQueryExtension ( vid_dpy , " XFree86-VidModeExtension " , & vm . opcode , & vm . event , & vm . error ) )
{
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 }
} ;
if ( ! XQueryExtension ( vid_dpy , " XFree86-DGA " , & dgam . opcode , & dgam . event , & dgam . error ) )
{
Con_Printf ( " DGA extension not available. \n " ) ;
return false ;
}
if ( ! dgam . lib )
dgam . lib = Sys_LoadLibrary ( " libXxf86dga " , dgam_functable ) ;
return ! ! dgam . lib ;
}
# include <X11/extensions/XInput2.h>
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 ) ] ;
if ( ! XQueryExtension ( vid_dpy , " XInputExtension " , & xi2 . opcode , & xi2 . event , & xi2 . error ) )
{
Con_Printf ( " XInput extension not available. \n " ) ;
return false ;
}
if ( ! xi2 . libxi )
{
xi2 . libxi = Sys_LoadLibrary ( " libXi " , xi2_functable ) ;
if ( ! xi2 . libxi )
Con_Printf ( " XInput library not available. \n " ) ;
}
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 ;
2009-07-07 21:32:54 +00:00
keysym = XLookupKeysym ( ev , 0 ) ;
XLookupString ( ev , buf , sizeof buf , & shifted , 0 ) ;
if ( unicode )
* unicode = buf [ 0 ] ;
2004-08-22 22:29:09 +00:00
switch ( keysym )
{
2005-06-15 04:36:20 +00:00
case XK_KP_Page_Up :
2004-08-22 22:29:09 +00:00
case XK_Page_Up : key = K_PGUP ; break ;
2005-06-15 04:36:20 +00:00
case XK_KP_Page_Down :
2004-08-22 22:29:09 +00:00
case XK_Page_Down : key = K_PGDN ; break ;
2005-06-15 04:36:20 +00:00
case XK_KP_Home :
2004-08-22 22:29:09 +00:00
case XK_Home : key = K_HOME ; break ;
2005-06-15 04:36:20 +00:00
case XK_KP_End :
2004-08-22 22:29:09 +00:00
case XK_End : key = K_END ; break ;
2005-06-15 04:36:20 +00:00
case XK_KP_Left :
2004-08-22 22:29:09 +00:00
case XK_Left : key = K_LEFTARROW ; break ;
2005-06-15 04:36:20 +00:00
case XK_KP_Right :
2004-08-22 22:29:09 +00:00
case XK_Right : key = K_RIGHTARROW ; break ;
2005-06-15 04:36:20 +00:00
case XK_KP_Down :
2004-08-22 22:29:09 +00:00
case XK_Down : key = K_DOWNARROW ; break ;
2005-06-15 04:36:20 +00:00
case XK_KP_Up :
2004-08-22 22:29:09 +00:00
case XK_Up : key = K_UPARROW ; break ;
case XK_Escape : key = K_ESCAPE ; break ;
2005-06-15 04:36:20 +00:00
case XK_KP_Enter :
2004-08-22 22:29:09 +00:00
case XK_Return : key = K_ENTER ; break ;
case XK_Tab : key = K_TAB ; break ;
case XK_F1 : key = K_F1 ; break ;
case XK_F2 : key = K_F2 ; break ;
case XK_F3 : key = K_F3 ; break ;
case XK_F4 : key = K_F4 ; break ;
case XK_F5 : key = K_F5 ; break ;
case XK_F6 : key = K_F6 ; break ;
case XK_F7 : key = K_F7 ; break ;
case XK_F8 : key = K_F8 ; break ;
case XK_F9 : key = K_F9 ; break ;
case XK_F10 : key = K_F10 ; break ;
case XK_F11 : key = K_F11 ; break ;
case XK_F12 : key = K_F12 ; break ;
case XK_BackSpace : key = K_BACKSPACE ; break ;
2005-06-15 04:36:20 +00:00
case XK_KP_Delete :
2004-08-22 22:29:09 +00:00
case XK_Delete : key = K_DEL ; break ;
case XK_Pause : key = K_PAUSE ; break ;
case XK_Shift_L :
case XK_Shift_R : key = K_SHIFT ; break ;
2005-06-15 04:36:20 +00:00
case XK_Execute :
case XK_Control_L :
2004-08-22 22:29:09 +00:00
case XK_Control_R : key = K_CTRL ; break ;
2005-06-15 04:36:20 +00:00
case XK_Alt_L :
case XK_Meta_L :
case XK_Alt_R :
2004-08-22 22:29:09 +00:00
case XK_Meta_R : key = K_ALT ; break ;
case XK_KP_Begin : key = ' 5 ' ; break ;
2005-06-15 04:36:20 +00:00
case XK_KP_Insert :
2004-08-22 22:29:09 +00:00
case XK_Insert : key = K_INS ; break ;
case XK_KP_Multiply : key = ' * ' ; break ;
case XK_KP_Add : key = ' + ' ; break ;
case XK_KP_Subtract : key = ' - ' ; break ;
case XK_KP_Divide : key = ' / ' ; break ;
#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 :
key = * ( unsigned char * ) buf ;
if ( key > = ' A ' & & key < = ' Z ' )
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 22:54:33 +00:00
if ( GrabSuccess ! = XGrabPointer ( vid_dpy , DefaultRootWindow ( vid_dpy ) ,
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
{
XWarpPointer ( vid_dpy , None , vid_window ,
0 , 0 , 0 , 0 ,
vid . width / 2 , vid . height / 2 ) ;
}
2004-08-22 22:29:09 +00:00
// XSync(vid_dpy, True);
}
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 )
XUngrabPointer ( vid_dpy , CurrentTime ) ;
2004-08-22 22:29:09 +00:00
// XSync(vid_dpy, True);
}
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
XNextEvent ( vid_dpy , & event ) ;
2013-03-12 22:54:12 +00:00
switch ( event . type )
{
case GenericEvent :
if ( XGetEventData ( vid_dpy , & event . xcookie ) )
{
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 " ) ;
}
XFreeEventData ( vid_dpy , & event . xcookie ) ;
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)
// XMoveWindow(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 ) )
XResizeWindow ( vid_dpy , vid_window , event . xconfigurerequest . width , event . xconfigurerequest . height ) ;
}
// if (fullscreenflags & FULLSCREEN_ACTIVE)
// XMoveWindow(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*/
XSelectInput ( vid_dpy , vid_window , X_MASK & ~ PointerMotionMask ) ;
XWarpPointer ( vid_dpy , None , vid_window , 0 , 0 , 0 , 0 ,
cx , cy ) ;
XSelectInput ( vid_dpy , vid_window , X_MASK ) ;
}
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
XSetInputFocus ( vid_dpy , vid_window , RevertToParent , CurrentTime ) ;
}
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)
// XUnmapWindow(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 ( ) ;
XUndefineCursor ( vid_dpy , vid_window ) ;
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 :
{
char * name = XGetAtomName ( vid_dpy , event . xclient . message_type ) ;
if ( ! strcmp ( name , " WM_PROTOCOLS " ) & & event . xclient . format = = 32 )
{
char * protname = XGetAtomName ( vid_dpy , event . xclient . data . l [ 0 ] ) ;
if ( ! strcmp ( protname , " WM_DELETE_WINDOW " ) )
2013-03-12 22:47:42 +00:00
{
Cmd_ExecuteString ( " menu_quit prompt " , RESTRICT_LOCAL ) ;
XSetInputFocus ( vid_dpy , vid_window , RevertToParent , CurrentTime ) ;
}
2011-01-29 19:53:38 +00:00
else
Con_Printf ( " Got message %s \n " , protname ) ;
XFree ( protname ) ;
}
else
Con_Printf ( " Got message %s \n " , name ) ;
XFree ( name ) ;
}
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 22:47:42 +00:00
Atom xa_string = XInternAtom ( vid_dpy , " UTF8_STRING " , false ) ;
memset ( & rep , 0 , sizeof ( rep ) ) ;
if ( event . xselectionrequest . property = = None )
event . xselectionrequest . property = XInternAtom ( vid_dpy , " foobar2000 " , false ) ;
if ( event . xselectionrequest . property ! = None & & event . xselectionrequest . target = = xa_string )
{
XChangeProperty ( vid_dpy , event . xselectionrequest . requestor , event . xselectionrequest . property , event . xselectionrequest . target , 8 , PropModeReplace , ( void * ) clipboard_buffer , strlen ( clipboard_buffer ) ) ;
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 ;
XSendEvent ( 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 ;
XUngrabKeyboard ( vid_dpy , CurrentTime ) ;
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 )
XDestroyWindow ( vid_dpy , vid_window ) ;
2012-10-14 10:57:11 +00:00
if ( vid_nullcursor )
XFreeCursor ( 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 )
XFree ( vm . modes ) ;
vm . modes = NULL ;
vm . num_modes = 0 ;
2004-08-22 22:29:09 +00:00
}
2005-12-05 21:22:36 +00:00
XCloseDisplay ( vid_dpy ) ;
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 ( ) ;
}
void signal_handler ( int sig )
{
printf ( " Received signal %d, exiting... \n " , sig ) ;
Sys_Quit ( ) ;
exit ( 0 ) ;
}
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 )
{
signal ( SIGHUP , signal_handler ) ;
2013-03-12 22:47:42 +00:00
signal ( SIGINT , signal_handler_graceful ) ;
2004-08-22 22:29:09 +00:00
signal ( SIGQUIT , signal_handler ) ;
signal ( SIGILL , signal_handler ) ;
signal ( SIGTRAP , signal_handler ) ;
# ifndef __CYGWIN__
signal ( SIGIOT , signal_handler ) ;
# endif
signal ( SIGBUS , signal_handler ) ;
signal ( SIGFPE , signal_handler ) ;
signal ( SIGSEGV , signal_handler ) ;
signal ( SIGTERM , signal_handler ) ;
}
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 ;
cursormask = XCreatePixmap ( display , root , 1 , 1 , 1 /*depth*/ ) ;
xgc . function = GXclear ;
gc = XCreateGC ( display , cursormask , GCFunction , & xgc ) ;
XFillRectangle ( display , cursormask , gc , 0 , 0 , 1 , 1 ) ;
dummycolour . pixel = 0 ;
dummycolour . red = 0 ;
dummycolour . flags = 04 ;
cursor = XCreatePixmapCursor ( display , cursormask , cursormask ,
& dummycolour , & dummycolour , 0 , 0 ) ;
XFreePixmap ( display , cursormask ) ;
XFreeGC ( display , gc ) ;
return cursor ;
}
2005-01-24 03:07:16 +00:00
void GLVID_ShiftPalette ( unsigned char * palette )
2004-08-22 22:29:09 +00:00
{
2005-01-24 03:07:16 +00:00
extern qboolean gammaworks ;
extern cvar_t vid_hardwaregamma ;
extern unsigned short ramps [ 3 ] [ 256 ] ;
2005-06-15 04:36:20 +00:00
2005-01-24 03:07:16 +00:00
// VID_SetPalette (palette);
2013-03-12 22:54:12 +00:00
if ( vm . originalapplied & & ActiveApp & & vid_hardwaregamma . value ) //this is needed because ATI drivers don't work properly (or when task-switched out).
2005-01-24 03:07:16 +00:00
{
if ( gammaworks )
{ //we have hardware gamma applied - if we're doing a BF, we don't want to reset to the default gamma (yuck)
2013-03-12 22:54:12 +00:00
vm . pXF86VidModeSetGammaRamp ( vid_dpy , scrnum , 256 , ramps [ 0 ] , ramps [ 1 ] , ramps [ 2 ] ) ;
2005-01-24 03:07:16 +00:00
return ;
}
2013-03-12 22:54:12 +00:00
gammaworks = ! ! vm . pXF86VidModeSetGammaRamp ( vid_dpy , scrnum , 256 , ramps [ 0 ] , ramps [ 1 ] , ramps [ 2 ] ) ;
2005-01-24 03:07:16 +00:00
}
else
gammaworks = false ;
2004-08-22 22:29:09 +00:00
}
void GLVID_SetPalette ( unsigned char * palette )
{
qbyte * pal ;
unsigned r , g , b ;
unsigned short i ;
unsigned * table ;
extern qbyte gammatable [ 256 ] ;
//
// 8 8 8 encoding
//
2013-03-12 22:47:42 +00:00
Con_DPrintf ( " Converting 8to24 \n " ) ;
2004-08-22 22:29:09 +00:00
pal = palette ;
table = d_8to24rgbtable ;
for ( i = 0 ; i < 256 ; i + + )
{
r = gammatable [ pal [ 0 ] ] ;
g = gammatable [ pal [ 1 ] ] ;
b = gammatable [ pal [ 2 ] ] ;
pal + = 3 ;
2005-06-15 04:36:20 +00:00
2005-12-06 21:52:38 +00:00
* table + + = BigLong ( ( r < < 24 ) | ( g < < 16 ) | ( b < < 8 ) | 255 ) ;
2004-08-22 22:29:09 +00:00
}
2005-12-06 21:52:38 +00:00
d_8to24rgbtable [ 255 ] & = BigLong ( 0xffffff00 ) ; // 255 is transparent
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 ;
Atom propname = XInternAtom ( vid_dpy , " _NET_WM_ICON " , false ) ;
Atom proptype = XInternAtom ( vid_dpy , " CARDINAL " , false ) ;
data [ 0 ] = icon . width ;
data [ 1 ] = icon . height ;
for ( i = 0 ; i < data [ 0 ] * data [ 1 ] ; i + + )
data [ i + 2 ] = indata [ i ] ;
XChangeProperty ( vid_dpy , wnd , propname , proptype , 32 , PropModeReplace , ( void * ) data , data [ 0 ] * data [ 1 ] + 2 ) ;
}
void X_GoFullscreen ( void )
{
XEvent xev ;
//for NETWM window managers
memset ( & xev , 0 , sizeof ( xev ) ) ;
xev . type = ClientMessage ;
xev . xclient . window = vid_window ;
xev . xclient . message_type = XInternAtom ( vid_dpy , " _NET_WM_STATE " , False ) ;
xev . xclient . format = 32 ;
xev . xclient . data . l [ 0 ] = 1 ; //add
xev . xclient . data . l [ 1 ] = XInternAtom ( vid_dpy , " _NET_WM_STATE_FULLSCREEN " , False ) ;
xev . xclient . data . l [ 2 ] = 0 ;
XSync ( vid_dpy , False ) ;
XSendEvent ( vid_dpy , DefaultRootWindow ( vid_dpy ) , False , SubstructureNotifyMask , & xev ) ;
XSync ( vid_dpy , False ) ;
//for any other window managers, and broken NETWM
XMoveResizeWindow ( vid_dpy , vid_window , 0 , 0 , fullscreenwidth , fullscreenheight ) ;
XSync ( vid_dpy , False ) ;
}
void X_GoWindowed ( void )
{
XEvent xev ;
XFlush ( vid_dpy ) ;
XSync ( vid_dpy , False ) ;
memset ( & xev , 0 , sizeof ( xev ) ) ;
xev . type = ClientMessage ;
xev . xclient . window = vid_window ;
xev . xclient . message_type = XInternAtom ( vid_dpy , " _NET_WM_STATE " , False ) ;
xev . xclient . format = 32 ;
xev . xclient . data . l [ 0 ] = 0 ; //remove
xev . xclient . data . l [ 1 ] = XInternAtom ( vid_dpy , " _NET_WM_STATE_FULLSCREEN " , False ) ;
xev . xclient . data . l [ 2 ] = 0 ;
XSendEvent ( vid_dpy , DefaultRootWindow ( vid_dpy ) , False , SubstructureNotifyMask , & xev ) ;
XSync ( vid_dpy , False ) ;
//XMoveResizeWindow(vid_dpy, vid_window, 0, 0, 640, 480);
}
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.
Atom xa_net_supporting_wm_check = XInternAtom ( vid_dpy , " _NET_SUPPORTING_WM_CHECK " , False ) ;
Atom xa_net_wm_name = XInternAtom ( vid_dpy , " _NET_WM_NAME " , False ) ;
Atom xa_net_supported = XInternAtom ( vid_dpy , " _NET_SUPPORTED " , False ) ;
Atom xa_net_wm_state_fullscreen = XInternAtom ( vid_dpy , " _NET_WM_STATE_FULLSCREEN " , False ) ;
Window wmwindow ;
unsigned char * prop ;
unsigned long bytes_after , nitems ;
Atom type ;
int format ;
qboolean success = false ;
unsigned char * wmname ;
int i ;
if ( XGetWindowProperty ( vid_dpy , vid_root , xa_net_supporting_wm_check , 0 , 16384 , False , AnyPropertyType , & type , & format , & nitems , & bytes_after , & prop ) ! = Success | | prop = = NULL )
{
Con_Printf ( " Window manager not identified \n " ) ;
return success ;
}
wmwindow = * ( Window * ) prop ;
XFree ( prop ) ;
if ( XGetWindowProperty ( vid_dpy , wmwindow , xa_net_wm_name , 0 , 16384 , False , AnyPropertyType , & type , & format , & nitems , & bytes_after , & wmname ) ! = Success | | wmname = = NULL )
{
Con_Printf ( " Window manager crashed or something \n " ) ;
return success ;
}
else
{
if ( XGetWindowProperty ( vid_dpy , vid_root , xa_net_supported , 0 , 16384 , False , AnyPropertyType , & type , & format , & nitems , & bytes_after , & prop ) ! = Success | | prop = = NULL )
{
Con_Printf ( " Window manager \" %s \" support nothing \n " , wmname ) ;
}
else
{
for ( i = 0 ; i < nitems ; i + + )
{
// Con_Printf("supported: %s\n", XGetAtomName(vid_dpy, ((Atom*)prop)[i]));
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 ) ;
XFree ( prop ) ;
}
XFree ( wmname ) ;
}
return success ;
}
Window X_CreateWindow ( qboolean override , XVisualInfo * visinfo , unsigned int width , unsigned int height )
2004-08-22 22:29:09 +00:00
{
2013-03-12 22:47:42 +00:00
Window wnd ;
XSetWindowAttributes attr ;
XSizeHints szhints ;
unsigned int mask ;
Atom prots [ 1 ] ;
/* window attributes */
attr . background_pixel = 0 ;
attr . border_pixel = 0 ;
attr . colormap = XCreateColormap ( vid_dpy , vid_root , visinfo - > visual , AllocNone ) ;
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 ;
wnd = XCreateWindow ( vid_dpy , vid_root , 0 , 0 , width , height ,
0 , visinfo - > depth , InputOutput ,
visinfo - > visual , mask , & attr ) ;
/*ask the window manager to stop triggering bugs in Xlib*/
prots [ 0 ] = XInternAtom ( vid_dpy , " WM_DELETE_WINDOW " , False ) ;
XSetWMProtocols ( vid_dpy , wnd , prots , sizeof ( prots ) / sizeof ( prots [ 0 ] ) ) ;
XSetWMNormalHints ( vid_dpy , wnd , & szhints ) ;
/*set caption*/
XStoreName ( vid_dpy , wnd , " FTE QuakeWorld " ) ;
XSetIconName ( vid_dpy , wnd , " FTEQW " ) ;
X_StoreIcon ( wnd ) ;
/*make it visible*/
XMapWindow ( vid_dpy , wnd ) ;
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
if ( info - > fullscreen )
fullscreen = true ;
S_Startup ( ) ;
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 )
vid_dpy = XOpenDisplay ( NULL ) ;
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 22:47:42 +00:00
XSync ( 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 ;
XGetWindowAttributes ( vid_dpy , DefaultRootWindow ( vid_dpy ) , & xwa ) ;
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 ;
}
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 ;
if ( ! XMatchVisualInfo ( vid_dpy , scrnum , info - > bpp , TrueColor , visinfo ) )
// if (!XMatchVisualInfo(vid_dpy, scrnum, DefaultDepth(vid_dpy, scrnum), TrueColor, &visinfo))
{
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 )
{
vid_decoywindow = X_CreateWindow ( false , visinfo , 640 , 480 ) ;
vid_window = X_CreateWindow ( true , visinfo , width , height ) ;
}
else
vid_window = X_CreateWindow ( false , visinfo , width , height ) ;
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 )
{
2004-08-22 22:29:09 +00:00
XRaiseWindow ( vid_dpy , vid_window ) ;
XWarpPointer ( vid_dpy , None , vid_window , 0 , 0 , 0 , 0 , 0 , 0 ) ;
XFlush ( vid_dpy ) ;
// 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
XFlush ( 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 :
EGL_Init ( info , palette , vid_window , vid_dpy ) ;
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
GLVID_SetPalette ( palette ) ;
GLVID_ShiftPalette ( palette ) ;
2011-12-05 15:23:40 +00:00
qglGetIntegerv ( GL_STENCIL_BITS , & gl_stencilbits ) ;
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 )
XMoveResizeWindow ( vid_dpy , vid_window , 0 , 0 , fullscreenwidth , fullscreenheight ) ;
if ( fullscreenflags )
fullscreenflags | = FULLSCREEN_ACTIVE ;
2004-08-22 22:29:09 +00:00
vid . recalc_refdef = 1 ; // force a surface cache flush
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 )
2012-10-14 10:57:11 +00:00
XGrabKeyboard ( vid_dpy , vid_window ,
2004-08-22 22:29:09 +00:00
False ,
GrabModeAsync , GrabModeAsync ,
CurrentTime ) ;
else
XSetInputFocus ( vid_dpy , vid_window , RevertToParent , CurrentTime ) ;
XRaiseWindow ( vid_dpy , vid_window ) ;
2013-03-12 22:47:42 +00:00
if ( fullscreenflags & FULLSCREEN_LEGACY )
XMoveResizeWindow ( 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 22:47:42 +00:00
if ( gracefulexit )
{
Cbuf_AddText ( " \n quit \n " , RESTRICT_LOCAL ) ;
gracefulexit = false ;
}
if ( vid_dpy & & vid_window )
{
qboolean wantwindowed ;
2005-06-15 04:36:20 +00:00
while ( XPending ( 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 ( ) ;
XUndefineCursor ( vid_dpy , vid_window ) ;
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 )
{
XMoveWindow ( vid_dpy , vid_window , 0 , 0 ) ;
XReparentWindow ( vid_dpy , vid_window , vid_root , 0 , 0 ) ;
//XUnmapWindow(vid_dpy, vid_decoywindow);
//make sure we have it
XSetInputFocus ( vid_dpy , vid_window , RevertToParent , CurrentTime ) ;
XRaiseWindow ( vid_dpy , vid_window ) ;
XMoveResizeWindow ( vid_dpy , vid_window , 0 , 0 , fullscreenwidth , fullscreenheight ) ;
}
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 )
{
XMapWindow ( vid_dpy , vid_decoywindow ) ;
XReparentWindow ( vid_dpy , vid_window , vid_decoywindow , 0 , 0 ) ;
XResizeWindow ( vid_dpy , vid_decoywindow , 640 , 480 ) ;
}
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 ( ) ;
XUndefineCursor ( vid_dpy , vid_window ) ;
}
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*/
XDefineCursor ( vid_dpy , vid_window , vid_nullcursor ) ;
}
}
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 )
{
XStoreName ( vid_dpy , vid_window , text ) ;
}
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 )
{
Atom xa_clipboard = XInternAtom ( vid_dpy , " PRIMARY " , false ) ;
Atom xa_string = XInternAtom ( vid_dpy , " UTF8_STRING " , false ) ;
Window clipboardowner = XGetSelectionOwner ( vid_dpy , xa_clipboard ) ;
if ( clipboardowner ! = None & & clipboardowner ! = vid_window )
{
int fmt ;
Atom type ;
unsigned long nitems , bytesleft ;
unsigned char * data ;
XConvertSelection ( vid_dpy , xa_clipboard , xa_string , None , vid_window , CurrentTime ) ;
XFlush ( vid_dpy ) ;
XGetWindowProperty ( vid_dpy , vid_window , xa_string , 0 , 0 , False , AnyPropertyType , & type , & fmt , & nitems , & bytesleft , & data ) ;
return data ;
}
return clipboard_buffer ;
}
void Sys_CloseClipboard ( char * bf )
{
if ( bf = = clipboard_buffer )
return ;
XFree ( bf ) ;
}
void Sys_SaveClipboard ( char * text )
{
Atom xa_clipboard = XInternAtom ( vid_dpy , " PRIMARY " , false ) ;
Q_strncpyz ( clipboard_buffer , text , SYS_CLIPBOARD_SIZE ) ;
XSetSelectionOwner ( vid_dpy , xa_clipboard , vid_window , CurrentTime ) ;
}
# endif