Hopefully improved legacy fullscreen handling (it works now on my Ubuntu Unity system)
1.1 --- a/src/video/x11/SDL_x11window.c Thu Sep 27 14:38:56 2012 -0700
1.2 +++ b/src/video/x11/SDL_x11window.c Thu Sep 27 17:17:33 2012 -0700
1.3 @@ -54,7 +54,15 @@
1.4 }
1.5 static Bool isConfigureNotify(Display *dpy, XEvent *ev, XPointer win)
1.6 {
1.7 - return ev->type == ConfigureNotify && ev->xunmap.window == *((Window*)win);
1.8 + return ev->type == ConfigureNotify && ev->xconfigure.window == *((Window*)win);
1.9 +}
1.10 +static Bool isFocusIn(Display *dpy, XEvent *ev, XPointer win)
1.11 +{
1.12 + return ev->type == FocusIn && ev->xfocus.window == *((Window*)win);
1.13 +}
1.14 +static Bool isFocusOut(Display *dpy, XEvent *ev, XPointer win)
1.15 +{
1.16 + return ev->type == FocusOut && ev->xfocus.window == *((Window*)win);
1.17 }
1.18
1.19 static SDL_bool
1.20 @@ -1002,13 +1010,6 @@
1.21
1.22 X11_GetDisplayBounds(_this, _display, &rect);
1.23
1.24 - /* Ungrab the input so that we can move the mouse around */
1.25 - XUngrabPointer(display, CurrentTime);
1.26 -
1.27 - #if SDL_VIDEO_DRIVER_X11_XINERAMA
1.28 - /* !!! FIXME: there was some Xinerama code in 1.2 here to set x,y to the origin of a specific screen. */
1.29 - #endif
1.30 -
1.31 SDL_zero(xattr);
1.32 xattr.override_redirect = True;
1.33 xattrmask |= CWOverrideRedirect;
1.34 @@ -1025,11 +1026,12 @@
1.35 visual, xattrmask, &xattr);
1.36
1.37 XSelectInput(display, data->fswindow, StructureNotifyMask);
1.38 -
1.39 XSetWindowBackground(display, data->fswindow, 0);
1.40 XClearWindow(display, data->fswindow);
1.41 + XMapRaised(display, data->fswindow);
1.42
1.43 - XMapRaised(display, data->fswindow);
1.44 + /* Make sure the fswindow is in view by warping mouse to the corner */
1.45 + XWarpPointer(display, None, root, 0, 0, 0, 0, rect.x, rect.y);
1.46
1.47 /* Wait to be mapped, filter Unmap event out if it arrives. */
1.48 XIfEvent(display, &ev, &isMapNotify, (XPointer)&data->fswindow);
1.49 @@ -1040,22 +1042,14 @@
1.50 XF86VidModeLockModeSwitch(display, screen, True);
1.51 }
1.52 #endif
1.53 -
1.54 XInstallColormap(display, data->colormap);
1.55
1.56 SetWindowBordered(display, displaydata->screen, data->xwindow, SDL_FALSE);
1.57 - XFlush(display);
1.58 - //XIfEvent(display, &ev, &isConfigureNotify, (XPointer)&data->xwindow);
1.59
1.60 /* Center actual window within our cover-the-screen window. */
1.61 rect.x += (rect.w - window->w) / 2;
1.62 rect.y += (rect.h - window->h) / 2;
1.63 XReparentWindow(display, data->xwindow, data->fswindow, rect.x, rect.y);
1.64 - XRaiseWindow(display, data->xwindow);
1.65 -
1.66 - /* Make sure the fswindow is in view by warping mouse to the corner */
1.67 - XWarpPointer(display, None, root, 0, 0, 0, 0, 0, 0);
1.68 - XFlush(display);
1.69
1.70 /* Center mouse in the window. */
1.71 rect.x += (window->w / 2);
1.72 @@ -1063,25 +1057,14 @@
1.73 XWarpPointer(display, None, root, 0, 0, 0, 0, rect.x, rect.y);
1.74
1.75 /* Wait to be mapped, filter Unmap event out if it arrives. */
1.76 - XIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->xwindow);
1.77 XIfEvent(display, &ev, &isMapNotify, (XPointer)&data->xwindow);
1.78 + XCheckIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->xwindow);
1.79
1.80 - /* Wait to be visible, or XSetInputFocus() triggers an X error. */
1.81 - while (SDL_TRUE) {
1.82 - XWindowAttributes attr;
1.83 - XSync(display, False);
1.84 - XGetWindowAttributes(display, data->xwindow, &attr);
1.85 - if (attr.map_state == IsViewable)
1.86 - break;
1.87 - }
1.88 -
1.89 - XSetInputFocus(display, data->xwindow, RevertToParent, CurrentTime);
1.90 + /* Set the input focus because we're about to grab input */
1.91 window->flags |= SDL_WINDOW_INPUT_FOCUS;
1.92 SDL_SetKeyboardFocus(data->window);
1.93
1.94 X11_SetWindowGrab(_this, window);
1.95 -
1.96 - XSync(display, False);
1.97 }
1.98
1.99 static void
1.100 @@ -1092,12 +1075,14 @@
1.101 Display *display = data->videodata->display;
1.102 const int screen = displaydata->screen;
1.103 Window root = RootWindow(display, screen);
1.104 + Window fswindow = data->fswindow;
1.105 XEvent ev;
1.106
1.107 - if (!data->fswindow)
1.108 + if (!data->fswindow) {
1.109 return; /* already not fullscreen, I hope. */
1.110 + }
1.111
1.112 - XReparentWindow(display, data->xwindow, root, window->x, window->y);
1.113 + data->fswindow = None;
1.114
1.115 #if SDL_VIDEO_DRIVER_X11_VIDMODE
1.116 if ( displaydata->use_vidmode ) {
1.117 @@ -1105,24 +1090,22 @@
1.118 }
1.119 #endif
1.120
1.121 - XUnmapWindow(display, data->fswindow);
1.122 - /* Wait to be unmapped. */
1.123 - XIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->fswindow);
1.124 - XDestroyWindow(display, data->fswindow);
1.125 - data->fswindow = 0;
1.126 + X11_SetWindowGrab(_this, window);
1.127
1.128 - /* catch these events so we know the window is back in business. */
1.129 + XReparentWindow(display, data->xwindow, root, window->x, window->y);
1.130 +
1.131 + /* flush these events so they don't confuse normal event handling */
1.132 XIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->xwindow);
1.133 XIfEvent(display, &ev, &isMapNotify, (XPointer)&data->xwindow);
1.134
1.135 - XSync(display, True); /* Flush spurious mode change events */
1.136 -
1.137 - X11_SetWindowGrab(_this, window);
1.138 -
1.139 SetWindowBordered(display, screen, data->xwindow,
1.140 (window->flags & SDL_WINDOW_BORDERLESS) == 0);
1.141
1.142 - XFlush(display);
1.143 + XUnmapWindow(display, fswindow);
1.144 +
1.145 + /* Wait to be unmapped. */
1.146 + XIfEvent(display, &ev, &isUnmapNotify, (XPointer)&fswindow);
1.147 + XDestroyWindow(display, fswindow);
1.148 }
1.149
1.150
1.151 @@ -1241,6 +1224,8 @@
1.152
1.153 if (((window->flags & SDL_WINDOW_INPUT_GRABBED) || oldstyle_fullscreen)
1.154 && (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
1.155 + XEvent ev;
1.156 +
1.157 /* Try to grab the mouse */
1.158 for (;;) {
1.159 int result =
1.160 @@ -1258,6 +1243,11 @@
1.161 /* Now grab the keyboard */
1.162 XGrabKeyboard(display, data->xwindow, True, GrabModeAsync,
1.163 GrabModeAsync, CurrentTime);
1.164 +
1.165 + /* flush these events so they don't confuse normal event handling */
1.166 + XSync(display, False);
1.167 + XIfEvent(display, &ev, &isFocusIn, (XPointer)&data->xwindow);
1.168 + XIfEvent(display, &ev, &isFocusOut, (XPointer)&data->xwindow);
1.169 } else {
1.170 XUngrabPointer(display, CurrentTime);
1.171 XUngrabKeyboard(display, CurrentTime);