From 3f0bbee5ae5abea43b570199484141c1806b3a00 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 27 Jul 2013 00:49:34 -0700 Subject: [PATCH] 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 | 26 ++++++++++++++++---------- src/video/x11/SDL_x11sym.h | 2 +- src/video/x11/SDL_x11window.c | 5 +++-- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/video/x11/SDL_x11messagebox.c b/src/video/x11/SDL_x11messagebox.c index 38867f06a..f938ded8b 100644 --- a/src/video/x11/SDL_x11messagebox.c +++ b/src/video/x11/SDL_x11messagebox.c @@ -78,11 +78,11 @@ typedef struct TextLineData { const char *text; /* Text for this line */ } TextLineData; -typedef struct SDL_MessageBoxDataX11 { - XFontSet font_set; /* for UTF-8 systems */ - XFontStruct *font_struct; /* Latin1 (ASCII) fallback. */ - Window window; +typedef struct SDL_MessageBoxDataX11 +{ Display *display; + int screen; + Window window; long event_mask; Atom wm_protocols; Atom wm_delete_message; @@ -90,6 +90,8 @@ typedef struct SDL_MessageBoxDataX11 { int dialog_width; /* Dialog box width. */ int dialog_height; /* Dialog box height. */ + XFontSet font_set; /* for UTF-8 systems */ + XFontStruct *font_struct; /* Latin1 (ASCII) fallback. */ int xtext, ytext; /* Text position to start drawing at. */ int numlines; /* Count of Text lines. */ int text_height; /* Height for text lines. */ @@ -347,7 +349,7 @@ X11_MessageBoxShutdown( SDL_MessageBoxDataX11 *data ) if ( data->display ) { if ( data->window != None ) { - XUnmapWindow( data->display, data->window ); + XWithdrawWindow( data->display, data->window, data->screen ); XDestroyWindow( data->display, data->window ); data->window = None; } @@ -369,7 +371,12 @@ X11_MessageBoxCreateWindow( SDL_MessageBoxDataX11 *data ) const SDL_MessageBoxData *messageboxdata = data->messageboxdata; if ( messageboxdata->window ) { + SDL_DisplayData *displaydata = + (SDL_DisplayData *) SDL_GetDisplayForWindow(messageboxdata->window)->driverdata; windowdata = (SDL_WindowData *)messageboxdata->window->driverdata; + data->screen = displaydata->screen; + } else { + data->screen = DefaultScreen( display ); } data->event_mask = ExposureMask | @@ -378,7 +385,7 @@ X11_MessageBoxCreateWindow( SDL_MessageBoxDataX11 *data ) wnd_attr.event_mask = data->event_mask; data->window = XCreateWindow( - display, DefaultRootWindow( display ), + display, RootWindow(display, data->screen), 0, 0, data->dialog_width, data->dialog_height, 0, CopyFromParent, InputOutput, CopyFromParent, @@ -406,11 +413,10 @@ X11_MessageBoxCreateWindow( SDL_MessageBoxDataX11 *data ) XGetWindowAttributes(display, windowdata->xwindow, &attrib); x = attrib.x + ( attrib.width - data->dialog_width ) / 2; y = attrib.y + ( attrib.height - data->dialog_height ) / 3 ; - XTranslateCoordinates(display, windowdata->xwindow, DefaultRootWindow( display ), x, y, &x, &y, &dummy); + XTranslateCoordinates(display, windowdata->xwindow, RootWindow(display, data->screen), x, y, &x, &y, &dummy); } else { - int screen = DefaultScreen( display ); - x = ( DisplayWidth( display, screen ) - data->dialog_width ) / 2; - y = ( DisplayHeight( display, screen ) - data->dialog_height ) / 3 ; + x = ( DisplayWidth( display, data->screen ) - data->dialog_width ) / 2; + y = ( DisplayHeight( display, data->screen ) - data->dialog_height ) / 3 ; } XMoveWindow( display, data->window, x, y ); diff --git a/src/video/x11/SDL_x11sym.h b/src/video/x11/SDL_x11sym.h index 24ad5097f..79f61e0fb 100644 --- a/src/video/x11/SDL_x11sym.h +++ b/src/video/x11/SDL_x11sym.h @@ -125,9 +125,9 @@ SDL_X11_SYM(int,XUngrabPointer,(Display* a,Time b),(a,b),return) SDL_X11_SYM(int,XUngrabServer,(Display* a),(a),return) SDL_X11_SYM(int,XUninstallColormap,(Display* a,Colormap b),(a,b),return) SDL_X11_SYM(int,XUnloadFont,(Display* a,Font b),(a,b),return) -SDL_X11_SYM(int,XUnmapWindow,(Display* a,Window b),(a,b),return) 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) SDL_X11_SYM(int,XWindowEvent,(Display* a,Window b,long c,XEvent* d),(a,b,c,d),return) +SDL_X11_SYM(Status,XWithdrawWindow,(Display* a,Window b,int c),(a,b,c),return) SDL_X11_SYM(VisualID,XVisualIDFromVisual,(Visual* a),(a),return) #if SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY 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) diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 5bf6ee43a..f48496f1a 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -853,11 +853,12 @@ void X11_HideWindow(_THIS, SDL_Window * window) { SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata; Display *display = data->videodata->display; XEvent event; if (X11_IsWindowMapped(_this, window)) { - XUnmapWindow(display, data->xwindow); + XWithdrawWindow(display, data->xwindow, displaydata->screen); /* Blocking wait for "UnmapNotify" event */ XIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow); XFlush(display); @@ -1146,7 +1147,7 @@ X11_EndWindowFullscreenLegacy(_THIS, SDL_Window * window, SDL_VideoDisplay * _di SetWindowBordered(display, screen, data->xwindow, (window->flags & SDL_WINDOW_BORDERLESS) == 0); - XUnmapWindow(display, fswindow); + XWithdrawWindow(display, fswindow, screen); /* Wait to be unmapped. */ XIfEvent(display, &ev, &isUnmapNotify, (XPointer)&fswindow);