Fixed bug 1526 - X11 - XUnmapWindow should not be called directly
authorSam Lantinga <slouken@libsdl.org>
Sat, 27 Jul 2013 00:49:34 -0700
changeset 7522b186724247dd
parent 7521 03bca9a4180d
child 7523 9e9ab1dc3811
Fixed bug 1526 - X11 - XUnmapWindow should not be called directly

driedfruit

In X11_HideWindow, we call XUnmapWindow to unmap. According to ICCCN2.0, this should never happen, and XWithdrawWindow should be called instead.

http://www.tronche.com/gui/x/icccm/sec-4.html#s-4.1.4

"The reason for requiring the client to send a synthetic UnmapNotify event is to ensure that the window manager gets some notification of the client's desire to change state, ***even though the window may already be unmapped when the desire is expressed***."

Additionally, this can be observed at http://cgit.freedesktop.org/xorg/lib/libX11/tree/src/Withdraw.c#n65

Failure to comply leads to "MapNotify" event never appearing on non-reparenting WMs after subsequent show-hide-show requests. (I'm currently observing this behavior, thus my bug report).
src/video/x11/SDL_x11messagebox.c
src/video/x11/SDL_x11sym.h
src/video/x11/SDL_x11window.c
     1.1 --- a/src/video/x11/SDL_x11messagebox.c	Fri Jul 26 13:30:24 2013 -0700
     1.2 +++ b/src/video/x11/SDL_x11messagebox.c	Sat Jul 27 00:49:34 2013 -0700
     1.3 @@ -78,11 +78,11 @@
     1.4      const char *text;                   /* Text for this line */
     1.5  } TextLineData;
     1.6  
     1.7 -typedef struct SDL_MessageBoxDataX11 {
     1.8 -    XFontSet font_set;                  /* for UTF-8 systems */
     1.9 -    XFontStruct *font_struct;            /* Latin1 (ASCII) fallback. */
    1.10 +typedef struct SDL_MessageBoxDataX11
    1.11 +{
    1.12 +    Display *display;
    1.13 +    int screen;
    1.14      Window window;
    1.15 -    Display *display;
    1.16      long event_mask;
    1.17      Atom wm_protocols;
    1.18      Atom wm_delete_message;
    1.19 @@ -90,6 +90,8 @@
    1.20      int dialog_width;                   /* Dialog box width. */
    1.21      int dialog_height;                  /* Dialog box height. */
    1.22  
    1.23 +    XFontSet font_set;                  /* for UTF-8 systems */
    1.24 +    XFontStruct *font_struct;           /* Latin1 (ASCII) fallback. */
    1.25      int xtext, ytext;                   /* Text position to start drawing at. */
    1.26      int numlines;                       /* Count of Text lines. */
    1.27      int text_height;                    /* Height for text lines. */
    1.28 @@ -347,7 +349,7 @@
    1.29  
    1.30      if ( data->display ) {
    1.31          if ( data->window != None ) {
    1.32 -            XUnmapWindow( data->display, data->window );
    1.33 +            XWithdrawWindow( data->display, data->window, data->screen );
    1.34              XDestroyWindow( data->display, data->window );
    1.35              data->window = None;
    1.36          }
    1.37 @@ -369,7 +371,12 @@
    1.38      const SDL_MessageBoxData *messageboxdata = data->messageboxdata;
    1.39  
    1.40      if ( messageboxdata->window ) {
    1.41 +        SDL_DisplayData *displaydata =
    1.42 +            (SDL_DisplayData *) SDL_GetDisplayForWindow(messageboxdata->window)->driverdata;
    1.43          windowdata = (SDL_WindowData *)messageboxdata->window->driverdata;
    1.44 +        data->screen = displaydata->screen;
    1.45 +    } else {
    1.46 +        data->screen = DefaultScreen( display );
    1.47      }
    1.48  
    1.49      data->event_mask = ExposureMask |
    1.50 @@ -378,7 +385,7 @@
    1.51      wnd_attr.event_mask = data->event_mask;
    1.52  
    1.53      data->window = XCreateWindow(
    1.54 -                       display, DefaultRootWindow( display ),
    1.55 +                       display, RootWindow(display, data->screen),
    1.56                         0, 0,
    1.57                         data->dialog_width, data->dialog_height,
    1.58                         0, CopyFromParent, InputOutput, CopyFromParent,
    1.59 @@ -406,11 +413,10 @@
    1.60          XGetWindowAttributes(display, windowdata->xwindow, &attrib);
    1.61          x = attrib.x + ( attrib.width - data->dialog_width ) / 2;
    1.62          y = attrib.y + ( attrib.height - data->dialog_height ) / 3 ;
    1.63 -        XTranslateCoordinates(display, windowdata->xwindow, DefaultRootWindow( display ), x, y, &x, &y, &dummy);
    1.64 +        XTranslateCoordinates(display, windowdata->xwindow, RootWindow(display, data->screen), x, y, &x, &y, &dummy);
    1.65      } else {
    1.66 -        int screen = DefaultScreen( display );
    1.67 -        x = ( DisplayWidth( display, screen ) - data->dialog_width ) / 2;
    1.68 -        y = ( DisplayHeight( display, screen ) - data->dialog_height ) / 3 ;
    1.69 +        x = ( DisplayWidth( display, data->screen ) - data->dialog_width ) / 2;
    1.70 +        y = ( DisplayHeight( display, data->screen ) - data->dialog_height ) / 3 ;
    1.71      }
    1.72      XMoveWindow( display, data->window, x, y );
    1.73  
     2.1 --- a/src/video/x11/SDL_x11sym.h	Fri Jul 26 13:30:24 2013 -0700
     2.2 +++ b/src/video/x11/SDL_x11sym.h	Sat Jul 27 00:49:34 2013 -0700
     2.3 @@ -125,9 +125,9 @@
     2.4  SDL_X11_SYM(int,XUngrabServer,(Display* a),(a),return)
     2.5  SDL_X11_SYM(int,XUninstallColormap,(Display* a,Colormap b),(a,b),return)
     2.6  SDL_X11_SYM(int,XUnloadFont,(Display* a,Font b),(a,b),return)
     2.7 -SDL_X11_SYM(int,XUnmapWindow,(Display* a,Window b),(a,b),return)
     2.8  SDL_X11_SYM(int,XWarpPointer,(Display* a,Window b,Window c,int d,int e,unsigned int f,unsigned int g,int h,int i),(a,b,c,d,e,f,g,h,i),return)
     2.9  SDL_X11_SYM(int,XWindowEvent,(Display* a,Window b,long c,XEvent* d),(a,b,c,d),return)
    2.10 +SDL_X11_SYM(Status,XWithdrawWindow,(Display* a,Window b,int c),(a,b,c),return)
    2.11  SDL_X11_SYM(VisualID,XVisualIDFromVisual,(Visual* a),(a),return)
    2.12  #if SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY
    2.13  SDL_X11_SYM(XExtDisplayInfo*,XextAddDisplay,(XExtensionInfo* a,Display* b,_Xconst char* c,XExtensionHooks* d,int e,XPointer f),(a,b,c,d,e,f),return)
     3.1 --- a/src/video/x11/SDL_x11window.c	Fri Jul 26 13:30:24 2013 -0700
     3.2 +++ b/src/video/x11/SDL_x11window.c	Sat Jul 27 00:49:34 2013 -0700
     3.3 @@ -853,11 +853,12 @@
     3.4  X11_HideWindow(_THIS, SDL_Window * window)
     3.5  {
     3.6      SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
     3.7 +    SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
     3.8      Display *display = data->videodata->display;
     3.9      XEvent event;
    3.10  
    3.11      if (X11_IsWindowMapped(_this, window)) {
    3.12 -        XUnmapWindow(display, data->xwindow);
    3.13 +        XWithdrawWindow(display, data->xwindow, displaydata->screen);
    3.14          /* Blocking wait for "UnmapNotify" event */
    3.15          XIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow);
    3.16          XFlush(display);
    3.17 @@ -1146,7 +1147,7 @@
    3.18      SetWindowBordered(display, screen, data->xwindow,
    3.19                        (window->flags & SDL_WINDOW_BORDERLESS) == 0);
    3.20  
    3.21 -    XUnmapWindow(display, fswindow);
    3.22 +    XWithdrawWindow(display, fswindow, screen);
    3.23  
    3.24      /* Wait to be unmapped. */
    3.25      XIfEvent(display, &ev, &isUnmapNotify, (XPointer)&fswindow);