X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=vid_glx.c;h=40cebe1b10cde7f910958db4b500a2e37be35797;hb=aed8b84afc34596c6ec9e4dd35ada467539fbd8c;hp=1dd9e1bff760b39e3a3d6cb9553c9949011f135a;hpb=4ee3e3c6cf65e316a2caa9a1cd4a12297980c253;p=xonotic%2Fdarkplaces.git diff --git a/vid_glx.c b/vid_glx.c index 1dd9e1bf..40cebe1b 100644 --- a/vid_glx.c +++ b/vid_glx.c @@ -17,22 +17,20 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -//#include -//#include -//#include -//#include -//#include -//#include #include #include #include #include +#include // TODO possibly ifdef this out on non-supporting systems... Solaris (as always)? #include +#include "quakedef.h" + #include #include +#include #include #if !defined(__APPLE__) && !defined(__MACH__) && !defined(SUNOS) @@ -40,7 +38,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #endif #include -#include "quakedef.h" +#include "nexuiz.xpm" +#include "darkplaces.xpm" // Tell startup code that we have a client int cl_available = true; @@ -90,18 +89,18 @@ Atom wm_delete_window_atom; static qboolean mouse_avail = true; +static qboolean vid_usingmousegrab = false; static qboolean vid_usingmouse = false; +static qboolean vid_usinghidecursor = false; static qboolean vid_usingvsync = false; static qboolean vid_usevsync = false; static qboolean vid_x11_hardwaregammasupported = false; +static qboolean vid_x11_dgasupported = false; static int vid_x11_gammarampsize = 0; -static float mouse_x, mouse_y; -static int p_mouse_x, p_mouse_y; #if !defined(__APPLE__) && !defined(SUNOS) -// FIXME: vid_dga_mouseaccel is poorly named, it is actually the multiplier for mouse movement, not an acceleration (which would be a power function or something) -cvar_t vid_dga = {CVAR_SAVE, "vid_dga", "1", "make use of DGA mouse input"}; -cvar_t vid_dga_mouseaccel = {0, "vid_dga_mouseaccel", "1", "speed of mouse when using DGA mouse input"}; +cvar_t vid_dgamouse = {CVAR_SAVE, "vid_dgamouse", "1", "make use of DGA mouse input"}; +static qboolean vid_usingdgamouse = false; #endif qboolean vidmode_ext = false; @@ -199,6 +198,7 @@ static int XLateKey(XKeyEvent *ev, char *ascii) case XK_Alt_L: case XK_Meta_L: + case XK_ISO_Level3_Shift: case XK_Alt_R: case XK_Meta_R: key = K_ALT; break; @@ -207,7 +207,7 @@ static int XLateKey(XKeyEvent *ev, char *ascii) case XK_Insert:key = K_INS; break; case XK_KP_Insert: key = K_KP_INS; break; - case XK_KP_Multiply: key = '*'; break; + case XK_KP_Multiply: key = K_KP_MULTIPLY; 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; @@ -250,13 +250,49 @@ static Cursor CreateNullCursor(Display *display, Window root) return cursor; } -static void IN_Activate (qboolean grab) +void VID_SetMouse(qboolean fullscreengrab, qboolean relative, qboolean hidecursor) { - if (!vidx11_display) +#if !defined(__APPLE__) && !defined(SUNOS) + qboolean usedgamouse; +#endif + + if (!vidx11_display || !win) return; - if (grab) + + if (relative) + fullscreengrab = true; + + if (!mouse_avail) + fullscreengrab = relative = hidecursor = false; + +#if !defined(__APPLE__) && !defined(SUNOS) + usedgamouse = relative && vid_dgamouse.integer; + if (!vid_x11_dgasupported) + usedgamouse = false; + if (fullscreengrab && vid_usingmouse && (vid_usingdgamouse != usedgamouse)) + VID_SetMouse(false, false, false); // ungrab first! +#endif + + if (vid_usingmousegrab != fullscreengrab) + { + vid_usingmousegrab = fullscreengrab; + cl_ignoremousemoves = 2; + if (fullscreengrab) + { + XGrabPointer(vidx11_display, win, True, 0, GrabModeAsync, GrabModeAsync, win, None, CurrentTime); + if (vid_grabkeyboard.integer || vid_isfullscreen) + XGrabKeyboard(vidx11_display, win, False, GrabModeAsync, GrabModeAsync, CurrentTime); + } + else + { + XUngrabPointer(vidx11_display, CurrentTime); + XUngrabKeyboard(vidx11_display, CurrentTime); + } + } + + if (relative) { - if (!vid_usingmouse && mouse_avail && win) + if (!vid_usingmouse) { XWindowAttributes attribs_1; XSetWindowAttributes attribs_2; @@ -265,37 +301,18 @@ static void IN_Activate (qboolean grab) attribs_2.event_mask = attribs_1.your_event_mask | KEY_MASK | MOUSE_MASK; XChangeWindowAttributes(vidx11_display, win, CWEventMask, &attribs_2); - // inviso cursor - XDefineCursor(vidx11_display, win, CreateNullCursor(vidx11_display, win)); - - XGrabPointer(vidx11_display, win, True, 0, GrabModeAsync, GrabModeAsync, win, None, CurrentTime); - #if !defined(__APPLE__) && !defined(SUNOS) - if (vid_dga.integer) + vid_usingdgamouse = usedgamouse; + if (usedgamouse) { - int MajorVersion, MinorVersion; - - if (!XF86DGAQueryVersion(vidx11_display, &MajorVersion, &MinorVersion)) - { - // unable to query, probably not supported - Con_Print( "Failed to detect XF86DGA Mouse\n" ); - Cvar_SetValueQuick(&vid_dga, 0); - XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, vid.width / 2, vid.height / 2); - } - else - { - XF86DGADirectVideo(vidx11_display, DefaultScreen(vidx11_display), XF86DGADirectMouse); - XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, 0, 0); - } + XF86DGADirectVideo(vidx11_display, DefaultScreen(vidx11_display), XF86DGADirectMouse); + XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, 0, 0); } else #endif XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, vid.width / 2, vid.height / 2); - XGrabKeyboard(vidx11_display, win, False, GrabModeAsync, GrabModeAsync, CurrentTime); - - mouse_x = mouse_y = 0; - cl_ignoremousemove = true; + cl_ignoremousemoves = 2; vid_usingmouse = true; } } @@ -304,21 +321,23 @@ static void IN_Activate (qboolean grab) if (vid_usingmouse) { #if !defined(__APPLE__) && !defined(SUNOS) - if (vid_dga.integer) + if (vid_usingdgamouse) XF86DGADirectVideo(vidx11_display, DefaultScreen(vidx11_display), 0); + vid_usingdgamouse = false; #endif - - XUngrabPointer(vidx11_display, CurrentTime); - XUngrabKeyboard(vidx11_display, CurrentTime); - - // inviso cursor - if (win) - XUndefineCursor(vidx11_display, win); - - cl_ignoremousemove = true; + cl_ignoremousemoves = 2; vid_usingmouse = false; } } + + if (vid_usinghidecursor != hidecursor) + { + vid_usinghidecursor = hidecursor; + if (hidecursor) + XDefineCursor(vidx11_display, win, CreateNullCursor(vidx11_display, win)); + else + XUndefineCursor(vidx11_display, win); + } } static keynum_t buttonremap[18] = @@ -376,28 +395,26 @@ static void HandleEvents(void) if (vid_usingmouse) { #if !defined(__APPLE__) && !defined(SUNOS) - if (vid_dga.integer == 1) + if (vid_usingdgamouse) { - mouse_x += event.xmotion.x_root * vid_dga_mouseaccel.value; - mouse_y += event.xmotion.y_root * vid_dga_mouseaccel.value; + in_mouse_x += event.xmotion.x_root; + in_mouse_y += event.xmotion.y_root; } else #endif { - if (!event.xmotion.send_event) { - mouse_x += event.xmotion.x - p_mouse_x; - mouse_y += event.xmotion.y - p_mouse_y; + in_mouse_x += event.xmotion.x - in_windowmouse_x; + in_mouse_y += event.xmotion.y - in_windowmouse_y; + //if (abs(vid.width/2 - event.xmotion.x) + abs(vid.height/2 - event.xmotion.y)) if (abs(vid.width/2 - event.xmotion.x) > vid.width / 4 || abs(vid.height/2 - event.xmotion.y) > vid.height / 4) dowarp = true; } - p_mouse_x = event.xmotion.x; - p_mouse_y = event.xmotion.y; } } - //else - // ui_mouseupdate(event.xmotion.x, event.xmotion.y); + in_windowmouse_x = event.xmotion.x; + in_windowmouse_y = event.xmotion.y; break; case ButtonPress: @@ -426,33 +443,44 @@ static void HandleEvents(void) // window changed size/location win_x = event.xconfigure.x; win_y = event.xconfigure.y; + if(vid_resizable.integer < 2) + { + vid.width = event.xconfigure.width; + vid.height = event.xconfigure.height; + } break; case DestroyNotify: // window has been destroyed - Sys_Quit(); + Sys_Quit(0); break; case ClientMessage: // window manager messages if ((event.xclient.format == 32) && ((unsigned int)event.xclient.data.l[0] == wm_delete_window_atom)) - Sys_Quit(); + Sys_Quit(0); break; case MapNotify: + if (vid.fullscreen) + break; // window restored vid_hidden = false; - vid_activewindow = false; VID_RestoreSystemGamma(); break; case UnmapNotify: + if (vid.fullscreen) + break; // window iconified/rolledup/whatever vid_hidden = true; - vid_activewindow = false; VID_RestoreSystemGamma(); break; case FocusIn: + if (vid.fullscreen) + break; // window is now the input focus vid_activewindow = true; break; case FocusOut: + if (vid.fullscreen) + break; // window is no longer the input focus vid_activewindow = false; VID_RestoreSystemGamma(); @@ -469,9 +497,16 @@ static void HandleEvents(void) if (dowarp) { /* move the mouse to the window center again */ - p_mouse_x = vid.width / 2; - p_mouse_y = vid.height / 2; - XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, p_mouse_x, p_mouse_y); + // we'll catch the warp motion by its send_event flag, updating the + // stored mouse position without adding any delta motion + XEvent event; + event.type = MotionNotify; + event.xmotion.display = vidx11_display; + event.xmotion.window = win; + event.xmotion.x = vid.width / 2; + event.xmotion.y = vid.height / 2; + XSendEvent(vidx11_display, win, False, PointerMotionMask, &event); + XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, vid.width / 2, vid.height / 2); } } @@ -493,12 +528,12 @@ static int GL_OpenLibrary(const char *name) { Con_Printf("Loading OpenGL driver %s\n", name); GL_CloseLibrary(); - if (!(prjobj = dlopen(name, RTLD_LAZY))) + if (!(prjobj = dlopen(name, RTLD_LAZY | RTLD_GLOBAL))) { Con_Printf("Unable to open symbol list for %s\n", name); return false; } - strcpy(gl_driver, name); + strlcpy(gl_driver, name, sizeof(gl_driver)); return true; } @@ -517,18 +552,16 @@ void VID_Shutdown(void) if (!ctx || !vidx11_display) return; - if (vidx11_display) - { - IN_Activate(false); - VID_RestoreSystemGamma(); - - // FIXME: glXDestroyContext here? - if (vid_isfullscreen) - XF86VidModeSwitchToMode(vidx11_display, vidx11_screen, &init_vidmode); - if (win) - XDestroyWindow(vidx11_display, win); - XCloseDisplay(vidx11_display); - } + VID_SetMouse(false, false, false); + VID_RestoreSystemGamma(); + + // FIXME: glXDestroyContext here? + if (vid_isfullscreen) + XF86VidModeSwitchToMode(vidx11_display, vidx11_screen, &init_vidmode); + if (win) + XDestroyWindow(vidx11_display, win); + XCloseDisplay(vidx11_display); + vid_hidden = true; vid_isfullscreen = false; vidx11_display = NULL; @@ -543,8 +576,7 @@ void signal_handler(int sig) { Con_Printf("Received signal %d, exiting...\n", sig); VID_RestoreSystemGamma(); - Sys_Quit(); - exit(0); + Sys_Quit(1); } void InitSig(void) @@ -561,10 +593,8 @@ void InitSig(void) signal(SIGTERM, signal_handler); } -void VID_Finish (qboolean allowmousegrab) +void VID_Finish (void) { - qboolean vid_usemouse; - vid_usevsync = vid_vsync.integer && !cls.timedemo && gl_videosyncavailable; if (vid_usingvsync != vid_usevsync && gl_videosyncavailable) { @@ -573,21 +603,14 @@ void VID_Finish (qboolean allowmousegrab) Con_Print("glXSwapIntervalSGI didn't accept the vid_vsync change, it will take effect on next vid_restart (GLX_SGI_swap_control does not allow turning off vsync)\n"); } -// handle the mouse state when windowed if that's changed - vid_usemouse = false; - if (allowmousegrab && vid_mouse.integer && !key_consoleactive && (key_dest != key_game || !cls.demoplayback)) - vid_usemouse = true; - if (!vid_activewindow) - vid_usemouse = false; - if (vid_isfullscreen) - vid_usemouse = true; - IN_Activate(vid_usemouse); - if (r_render.integer) { + CHECKGLERROR if (r_speeds.integer || gl_finish.integer) - qglFinish(); - qglXSwapBuffers(vidx11_display, win); + { + qglFinish();CHECKGLERROR + } + qglXSwapBuffers(vidx11_display, win);CHECKGLERROR } if (vid_x11_hardwaregammasupported) @@ -607,37 +630,48 @@ int VID_GetGamma(unsigned short *ramps, int rampsize) void VID_Init(void) { #if !defined(__APPLE__) && !defined(SUNOS) - Cvar_RegisterVariable (&vid_dga); - Cvar_RegisterVariable (&vid_dga_mouseaccel); + Cvar_RegisterVariable (&vid_dgamouse); #endif InitSig(); // trap evil signals // COMMANDLINEOPTION: Input: -nomouse disables mouse support (see also vid_mouse cvar) - if (COM_CheckParm ("-nomouse") || COM_CheckParm("-safe")) + if (COM_CheckParm ("-nomouse")) mouse_avail = false; } -void VID_BuildGLXAttrib(int *attrib, int stencil) +void VID_BuildGLXAttrib(int *attrib, qboolean stencil, qboolean stereobuffer, int samples) { *attrib++ = GLX_RGBA; - *attrib++ = GLX_RED_SIZE;*attrib++ = 1; - *attrib++ = GLX_GREEN_SIZE;*attrib++ = 1; - *attrib++ = GLX_BLUE_SIZE;*attrib++ = 1; + *attrib++ = GLX_RED_SIZE;*attrib++ = stencil ? 8 : 5; + *attrib++ = GLX_GREEN_SIZE;*attrib++ = stencil ? 8 : 5; + *attrib++ = GLX_BLUE_SIZE;*attrib++ = stencil ? 8 : 5; *attrib++ = GLX_DOUBLEBUFFER; - *attrib++ = GLX_DEPTH_SIZE;*attrib++ = 1; + *attrib++ = GLX_DEPTH_SIZE;*attrib++ = stencil ? 24 : 16; // if stencil is enabled, ask for alpha too if (stencil) { *attrib++ = GLX_STENCIL_SIZE;*attrib++ = 8; - *attrib++ = GLX_ALPHA_SIZE;*attrib++ = 1; + *attrib++ = GLX_ALPHA_SIZE;*attrib++ = 8; + } + if (stereobuffer) + *attrib++ = GLX_STEREO; + if (samples > 1) + { + *attrib++ = GLX_SAMPLE_BUFFERS_ARB; + *attrib++ = 1; + *attrib++ = GLX_SAMPLES_ARB; + *attrib++ = samples; } *attrib++ = None; } -int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate) +int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate, int stereobuffer, int samples) { int i; int attrib[32]; XSetWindowAttributes attr; + XClassHint *clshints; + XWMHints *wmhints; + XSizeHints *szhints; unsigned long mask; Window root; XVisualInfo *visinfo; @@ -667,6 +701,9 @@ int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate return false; } + // make autorepeat send keypress/keypress/.../keyrelease instead of intervening keyrelease + XkbSetDetectableAutoRepeat(vidx11_display, true, NULL); + vidx11_screen = DefaultScreen(vidx11_display); root = RootWindow(vidx11_display, vidx11_screen); @@ -691,8 +728,15 @@ int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate return false; } - VID_BuildGLXAttrib(attrib, bpp == 32); + VID_BuildGLXAttrib(attrib, bpp == 32, stereobuffer, samples); visinfo = qglXChooseVisual(vidx11_display, vidx11_screen, attrib); + if (!visinfo && (samples == 1)) + { + /* Some Mesa drivers reject sample buffers with 1 sample, so try + * entirely without one */ + VID_BuildGLXAttrib(attrib, bpp == 32, stereobuffer, 0); + visinfo = qglXChooseVisual(vidx11_display, vidx11_screen, attrib); + } if (!visinfo) { Con_Print("Couldn't get an RGB, Double-buffered, Depth visual\n"); @@ -775,7 +819,30 @@ int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; win = XCreateWindow(vidx11_display, root, 0, 0, width, height, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr); - XStoreName(vidx11_display, win, gamename); + + wmhints = XAllocWMHints(); + if(XpmCreatePixmapFromData(vidx11_display, win, + (gamemode == GAME_NEXUIZ) ? nexuiz_xpm : darkplaces_xpm, + &wmhints->icon_pixmap, &wmhints->icon_mask, NULL) == XpmSuccess) + wmhints->flags |= IconPixmapHint | IconMaskHint; + + clshints = XAllocClassHint(); + clshints->res_name = strdup(gamename); + clshints->res_class = strdup("DarkPlaces"); + + szhints = XAllocSizeHints(); + if(vid_resizable.integer == 0) + { + szhints->min_width = szhints->max_width = width; + szhints->min_height = szhints->max_height = height; + szhints->flags |= PMinSize | PMaxSize; + } + + XmbSetWMProperties(vidx11_display, win, gamename, gamename, (char **) com_argv, com_argc, szhints, wmhints, clshints); + XFree(clshints); + XFree(wmhints); + XFree(szhints); + //XStoreName(vidx11_display, win, gamename); XMapWindow(vidx11_display, win); // LordHavoc: making the close button on a window do the right thing @@ -816,9 +883,6 @@ int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate return false; } - gl_renderer = (const char *)qglGetString(GL_RENDERER); - gl_vendor = (const char *)qglGetString(GL_VENDOR); - gl_version = (const char *)qglGetString(GL_VERSION); gl_extensions = (const char *)qglGetString(GL_EXTENSIONS); gl_platform = "GLX"; gl_platformextensions = qglXQueryExtensionsString(vidx11_display, vidx11_screen); @@ -834,27 +898,47 @@ int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate // COMMANDLINEOPTION: MacOSX GLX: -novideosync disables GLX_SGI_swap_control gl_videosyncavailable = GL_CheckExtension("GLX_SGI_swap_control", swapcontrolfuncs, "-novideosync", false); + vid_usingmousegrab = false; vid_usingmouse = false; + vid_usinghidecursor = false; vid_usingvsync = false; vid_hidden = false; vid_activewindow = true; vid_x11_hardwaregammasupported = XF86VidModeGetGammaRampSize(vidx11_display, vidx11_screen, &vid_x11_gammarampsize) != 0; +#if !defined(__APPLE__) && !defined(SUNOS) + vid_x11_dgasupported = XF86DGAQueryVersion(vidx11_display, &MajorVersion, &MinorVersion); + if (!vid_x11_dgasupported) + Con_Print( "Failed to detect XF86DGA Mouse extension\n" ); +#endif GL_Init(); return true; } void Sys_SendKeyEvents(void) { + static qboolean sound_active = true; + + // enable/disable sound on focus gain/loss + if (!vid_hidden && (vid_activewindow || !snd_mutewhenidle.integer)) + { + if (!sound_active) + { + S_UnblockSound (); + sound_active = true; + } + } + else + { + if (sound_active) + { + S_BlockSound (); + sound_active = false; + } + } + HandleEvents(); } void IN_Move (void) { - if (mouse_avail) - { - in_mouse_x = mouse_x; - in_mouse_y = mouse_y; - } - mouse_x = 0; - mouse_y = 0; }