From 5a4df8ff1f629a692b2fc5de1b282da991d0bd44 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 13 Jul 2010 23:11:10 -0700 Subject: [PATCH] Lots of prep for the "real" way to support fullscreen mode on modern window managers. Unfortunately, this doesn't work. I also noticed that maximizing doesn't work as well. Also xprop hangs when trying to list properties of SDL windows.... ??? --- src/video/x11/SDL_x11events.c | 62 ++++++++++-- src/video/x11/SDL_x11modes.c | 5 +- src/video/x11/SDL_x11sym.h | 2 + src/video/x11/SDL_x11video.c | 53 ++++++++++- src/video/x11/SDL_x11video.h | 15 +++ src/video/x11/SDL_x11window.c | 174 ++++++++++++++++++++++------------ src/video/x11/SDL_x11window.h | 1 + 7 files changed, 242 insertions(+), 70 deletions(-) diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index e4d51bc6b..dc4f68da3 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -34,18 +34,19 @@ #include "SDL_timer.h" #include "SDL_syswm.h" -/*#define DEBUG_XEVENTS*/ +#define DEBUG_XEVENTS static void X11_DispatchEvent(_THIS) { SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; + Display *display = videodata->display; SDL_WindowData *data; XEvent xevent; int i; SDL_zero(xevent); /* valgrind fix. --ryan. */ - XNextEvent(videodata->display, &xevent); + XNextEvent(display, &xevent); /* filter events catchs XIM events and sends them to the correct handler */ @@ -80,6 +81,7 @@ X11_DispatchEvent(_THIS) if (!data) { return; } + #if 0 printf("type = %d display = %d window = %d\n", xevent.type, xevent.xany.display, xevent.xany.window); @@ -182,9 +184,8 @@ X11_DispatchEvent(_THIS) #if 0 if (videodata->key_layout[keycode] == SDLK_UNKNOWN) { int min_keycode, max_keycode; - XDisplayKeycodes(videodata->display, &min_keycode, - &max_keycode); - keysym = XKeycodeToKeysym(videodata->display, keycode, 0); + XDisplayKeycodes(display, &min_keycode, &max_keycode); + keysym = XKeycodeToKeysym(display, keycode, 0); fprintf(stderr, "The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL mailing list X11 KeyCode %d (%d), X11 KeySym 0x%X (%s).\n", keycode, keycode - min_keycode, keysym, @@ -289,9 +290,58 @@ X11_DispatchEvent(_THIS) } break; + case PropertyNotify:{ +#ifdef DEBUG_XEVENTS + char *name = XGetAtomName(display, xevent.xproperty.atom); + printf("PropertyNotify (atom = %s)\n", name ? name : "NULL"); + if (name) { + XFree(name); + } +#endif + if (xevent.xproperty.atom == videodata->_NET_WM_STATE) { + unsigned char *propdata; + int status, real_format; + Atom real_type; + unsigned long items_read, items_left, i; + +#ifdef DEBUG_XEVENTS + printf("_NET_WM_STATE: {"); +#endif + status = XGetWindowProperty(display, data->xwindow, videodata->_NET_WM_STATE, 0L, 8192L, False, XA_ATOM, &real_type, &real_format, &items_read, &items_left, &propdata); + if (status == Success) { + Atom *atoms = (Atom *)propdata; + for (i = 0; i < items_read; i++) { + if (atoms[i] == videodata->_NET_WM_STATE_HIDDEN) { +#ifdef DEBUG_XEVENTS + printf(" _NET_WM_STATE_HIDDEN"); +#endif + } + if (atoms[i] == videodata->_NET_WM_STATE_MAXIMIZED_HORZ) { +#ifdef DEBUG_XEVENTS + printf(" _NET_WM_STATE_MAXIMIZED_HORZ"); +#endif + } + if (atoms[i] == videodata->_NET_WM_STATE_MAXIMIZED_VERT) { +#ifdef DEBUG_XEVENTS + printf(" _NET_WM_STATE_MAXIMIZED_VERT"); +#endif + } + if (atoms[i] == videodata->_NET_WM_STATE_FULLSCREEN) { +#ifdef DEBUG_XEVENTS + printf(" _NET_WM_STATE_FULLSCREEN"); +#endif + } + } + } +#ifdef DEBUG_XEVENTS + printf(" }\n"); +#endif + } + } + break; + /* Copy the selection from XA_CUT_BUFFER0 to the requested property */ case SelectionRequest: { - Display *display = videodata->display; XSelectionRequestEvent *req; XEvent sevent; int seln_format; diff --git a/src/video/x11/SDL_x11modes.c b/src/video/x11/SDL_x11modes.c index 211bcb885..fe8f7b5ad 100644 --- a/src/video/x11/SDL_x11modes.c +++ b/src/video/x11/SDL_x11modes.c @@ -23,7 +23,7 @@ #include "SDL_x11video.h" -//#define X11MODES_DEBUG +#define X11MODES_DEBUG #undef SDL_VIDEO_DRIVER_X11_XINERAMA #undef SDL_VIDEO_DRIVER_X11_XRANDR #undef SDL_VIDEO_DRIVER_X11_VIDMODE @@ -253,6 +253,7 @@ CheckVidMode(Display * display, int *major, int *minor) return SDL_TRUE; } +static Bool SDL_NAME(XF86VidModeGetModeInfo) (Display * dpy, int scr, SDL_NAME(XF86VidModeModeInfo) * info) { @@ -296,6 +297,7 @@ save_mode(Display * display, SDL_DisplayData * data) &data->saved_view.y); } +/* static void restore_mode(Display * display, SDL_DisplayData * data) { @@ -313,6 +315,7 @@ restore_mode(Display * display, SDL_DisplayData * data) data->saved_view.y); } } +*/ #endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ void diff --git a/src/video/x11/SDL_x11sym.h b/src/video/x11/SDL_x11sym.h index 01dc8f6a0..38855b55e 100644 --- a/src/video/x11/SDL_x11sym.h +++ b/src/video/x11/SDL_x11sym.h @@ -67,12 +67,14 @@ SDL_X11_SYM(int,XFreeCursor,(Display* a,Cursor b),(a,b),return) SDL_X11_SYM(int,XFreeGC,(Display* a,GC b),(a,b),return) SDL_X11_SYM(int,XFreeModifiermap,(XModifierKeymap* a),(a),return) SDL_X11_SYM(int,XFreePixmap,(Display* a,Pixmap b),(a,b),return) +SDL_X11_SYM(char*,XGetAtomName,(Display *a,Atom b),(a,b),return) SDL_X11_SYM(int,XGetErrorDatabaseText,(Display* a,_Xconst char* b,_Xconst char* c,_Xconst char* d,char* e,int f),(a,b,c,d,e,f),return) SDL_X11_SYM(XImage*,XGetImage,(Display* a,Drawable b,int c,int d,unsigned int e,unsigned int f,unsigned long g, int h),(a,b,c,d,e,f,g,h),return) SDL_X11_SYM(XModifierKeymap*,XGetModifierMapping,(Display* a),(a),return) SDL_X11_SYM(int,XGetPointerControl,(Display* a,int* b,int* c,int* d),(a,b,c,d),return) SDL_X11_SYM(int,XGetRGBColormaps,(Display* a,Window b,XStandardColormap **c,int *d,Atom e),(a,b,c,d,e),return) SDL_X11_SYM(Window,XGetSelectionOwner,(Display* a,Atom b),(a,b),return) +SDL_X11_SYM(Status,XGetTextProperty,(Display *a,Window b,XTextProperty *c,Atom d),(a,b,c,d),return) SDL_X11_SYM(XVisualInfo*,XGetVisualInfo,(Display* a,long b,XVisualInfo* c,int* d),(a,b,c,d),return) SDL_X11_SYM(Status,XGetWindowAttributes,(Display* a,Window b,XWindowAttributes* c),(a,b,c),return) SDL_X11_SYM(int,XGetWindowProperty,(Display* a,Window b,Atom c,long d,long e,Bool f,Atom g,Atom* h,int* i,unsigned long* j,unsigned long *k,unsigned char **l),(a,b,c,d,e,f,g,h,i,j,k,l),return) diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index a3a8d2c72..894837e54 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -242,6 +242,43 @@ VideoBootStrap X11_bootstrap = { }; +static void +X11_CheckWindowManager(_THIS) +{ + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + Display *display = data->display; + Atom _NET_SUPPORTING_WM_CHECK; + int status, real_format; + Atom real_type; + unsigned long items_read, items_left; + unsigned char *propdata; + Window wm_window = 0; +#ifdef DEBUG_WINDOW_MANAGER + char *wm_name; +#endif + + _NET_SUPPORTING_WM_CHECK = XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", False); + status = XGetWindowProperty(display, DefaultRootWindow(display), _NET_SUPPORTING_WM_CHECK, 0L, 1L, False, XA_WINDOW, &real_type, &real_format, &items_read, &items_left, &propdata); + if (status == Success && items_read) { + wm_window = ((Window*)propdata)[0]; + } + XFree(propdata); + + if (!wm_window) { +#ifdef DEBUG_WINDOW_MANAGER + printf("Couldn't get _NET_SUPPORTING_WM_CHECK property\n"); +#endif + return; + } + data->net_wm = SDL_TRUE; + +#ifdef DEBUG_WINDOW_MANAGER + wm_name = X11_GetWindowTitle(_this, wm_window); + printf("Window manager: %s\n", wm_name); + SDL_free(wm_name); +#endif +} + int X11_VideoInit(_THIS) { @@ -259,8 +296,20 @@ X11_VideoInit(_THIS) #endif /* Look up some useful Atoms */ - data->WM_DELETE_WINDOW = - XInternAtom(data->display, "WM_DELETE_WINDOW", False); +#define GET_ATOM(X) data->X = XInternAtom(data->display, #X, False) + GET_ATOM(WM_DELETE_WINDOW); + GET_ATOM(_NET_WM_STATE); + GET_ATOM(_NET_WM_STATE_HIDDEN); + GET_ATOM(_NET_WM_STATE_MAXIMIZED_VERT); + GET_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ); + GET_ATOM(_NET_WM_STATE_FULLSCREEN); + GET_ATOM(_NET_WM_NAME); + GET_ATOM(_NET_WM_ICON_NAME); + GET_ATOM(_NET_WM_ICON); + GET_ATOM(UTF8_STRING); + + /* Detect the window manager */ + X11_CheckWindowManager(_this); if (X11_InitModes(_this) < 0) { return -1; diff --git a/src/video/x11/SDL_x11video.h b/src/video/x11/SDL_x11video.h index 34647ca51..d8929b1b4 100644 --- a/src/video/x11/SDL_x11video.h +++ b/src/video/x11/SDL_x11video.h @@ -68,7 +68,22 @@ typedef struct SDL_VideoData int numwindows; SDL_WindowData **windowlist; int windowlistlength; + + /* This is true for ICCCM2.0-compliant window managers */ + SDL_bool net_wm; + + /* Useful atoms */ Atom WM_DELETE_WINDOW; + Atom _NET_WM_STATE; + Atom _NET_WM_STATE_HIDDEN; + Atom _NET_WM_STATE_MAXIMIZED_VERT; + Atom _NET_WM_STATE_MAXIMIZED_HORZ; + Atom _NET_WM_STATE_FULLSCREEN; + Atom _NET_WM_NAME; + Atom _NET_WM_ICON_NAME; + Atom _NET_WM_ICON; + Atom UTF8_STRING; + SDL_scancode key_layout[256]; SDL_bool selection_waiting; } SDL_VideoData; diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 78d94dab2..305c2cf1b 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -42,6 +42,20 @@ #define _NET_WM_STATE_ADD 1l #define _NET_WM_STATE_TOGGLE 2l +static SDL_bool +X11_WindowIsOldstyleFullscreen(SDL_Window * window) +{ + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + SDL_VideoData *videodata = (SDL_VideoData *) data->videodata; + + /* ICCCM2.0-compliant window managers can handle fullscreen windows */ + if ((window->flags & SDL_WINDOW_FULLSCREEN) && !videodata->net_wm) { + return SDL_TRUE; + } else { + return SDL_FALSE; + } +} + static void X11_GetDisplaySize(_THIS, SDL_Window * window, int *w, int *h) { @@ -128,14 +142,10 @@ SetupWindowData(_THIS, SDL_Window * window, Window w, BOOL created) } { - Atom _NET_WM_STATE = - XInternAtom(data->videodata->display, "_NET_WM_STATE", False); - Atom _NET_WM_STATE_MAXIMIZED_VERT = - XInternAtom(data->videodata->display, - "_NET_WM_STATE_MAXIMIZED_VERT", False); - Atom _NET_WM_STATE_MAXIMIZED_HORZ = - XInternAtom(data->videodata->display, - "_NET_WM_STATE_MAXIMIZED_HORZ", False); + Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE; + Atom _NET_WM_STATE_MAXIMIZED_VERT = data->videodata->_NET_WM_STATE_MAXIMIZED_VERT; + Atom _NET_WM_STATE_MAXIMIZED_HORZ = data->videodata->_NET_WM_STATE_MAXIMIZED_HORZ; + Atom _NET_WM_STATE_FULLSCREEN = data->videodata->_NET_WM_STATE_FULLSCREEN; Atom actualType; int actualFormat; unsigned long i, numItems, bytesAfter; @@ -148,19 +158,21 @@ SetupWindowData(_THIS, SDL_Window * window, Window w, BOOL created) &propertyValue) == Success) { Atom *atoms = (Atom *) propertyValue; int maximized = 0; + int fullscreen = 0; for (i = 0; i < numItems; ++i) { if (atoms[i] == _NET_WM_STATE_MAXIMIZED_VERT) { maximized |= 1; } else if (atoms[i] == _NET_WM_STATE_MAXIMIZED_HORZ) { maximized |= 2; + } else if ( atoms[i] == _NET_WM_STATE_FULLSCREEN) { + fullscreen = 1; } - /* Might also want to check the following properties: - _NET_WM_STATE_ABOVE, _NET_WM_STATE_FULLSCREEN - */ } if (maximized == 3) { window->flags |= SDL_WINDOW_MAXIMIZED; + } else if (fullscreen == 1) { + window->flags |= SDL_WINDOW_FULLSCREEN; } XFree(propertyValue); } @@ -180,11 +192,6 @@ SetupWindowData(_THIS, SDL_Window * window, Window w, BOOL created) } else { window->flags &= ~SDL_WINDOW_RESIZABLE; } - if (style & WS_MAXIMIZE) { - window->flags |= SDL_WINDOW_MAXIMIZED; - } else { - window->flags &= ~SDL_WINDOW_MAXIMIZED; - } if (style & WS_MINIMIZE) { window->flags |= SDL_WINDOW_MINIMIZED; } else { @@ -225,6 +232,14 @@ X11_CreateWindow(_THIS, SDL_Window * window) XSizeHints *sizehints; XWMHints *wmhints; XClassHint *classhints; + SDL_bool oldstyle_fullscreen; + + /* ICCCM2.0-compliant window managers can handle fullscreen windows */ + if ((window->flags & SDL_WINDOW_FULLSCREEN) && !data->net_wm) { + oldstyle_fullscreen = SDL_TRUE; + } else { + oldstyle_fullscreen = SDL_FALSE; + } #if SDL_VIDEO_DRIVER_X11_XINERAMA /* FIXME @@ -265,7 +280,7 @@ X11_CreateWindow(_THIS, SDL_Window * window) depth = displaydata->depth; } - if (window->flags & SDL_WINDOW_FULLSCREEN) { + if (oldstyle_fullscreen) { xattr.override_redirect = True; } else { xattr.override_redirect = False; @@ -417,7 +432,6 @@ X11_CreateWindow(_THIS, SDL_Window * window) } /* OK, we got a colormap, now fill it in as best as we can */ - colorcells = SDL_malloc(visual->map_entries * sizeof(XColor)); if (NULL == colorcells) { SDL_SetError("out of memory in X11_CreateWindow"); @@ -494,7 +508,7 @@ X11_CreateWindow(_THIS, SDL_Window * window) visual, AllocNone); } - if ((window->flags & SDL_WINDOW_FULLSCREEN) + if (oldstyle_fullscreen || window->x == SDL_WINDOWPOS_CENTERED) { X11_GetDisplaySize(_this, window, &x, NULL); x = (x - window->w) / 2; @@ -503,7 +517,7 @@ X11_CreateWindow(_THIS, SDL_Window * window) } else { x = window->x; } - if ((window->flags & SDL_WINDOW_FULLSCREEN) + if (oldstyle_fullscreen || window->y == SDL_WINDOWPOS_CENTERED) { X11_GetDisplaySize(_this, window, NULL, &y); y = (y - window->h) / 2; @@ -539,12 +553,12 @@ X11_CreateWindow(_THIS, SDL_Window * window) sizehints = XAllocSizeHints(); if (sizehints) { if (!(window->flags & SDL_WINDOW_RESIZABLE) - || (window->flags & SDL_WINDOW_FULLSCREEN)) { + || oldstyle_fullscreen) { sizehints->min_width = sizehints->max_width = window->w; sizehints->min_height = sizehints->max_height = window->h; sizehints->flags = PMaxSize | PMinSize; } - if (!(window->flags & SDL_WINDOW_FULLSCREEN) + if (!oldstyle_fullscreen && window->x != SDL_WINDOWPOS_UNDEFINED && window->y != SDL_WINDOWPOS_UNDEFINED) { sizehints->x = x; @@ -555,7 +569,7 @@ X11_CreateWindow(_THIS, SDL_Window * window) XFree(sizehints); } - if (window->flags & (SDL_WINDOW_BORDERLESS | SDL_WINDOW_FULLSCREEN)) { + if ((window->flags & SDL_WINDOW_BORDERLESS) || oldstyle_fullscreen) { SDL_bool set; Atom WM_HINTS; @@ -643,23 +657,6 @@ X11_CreateWindow(_THIS, SDL_Window * window) } } - /* Tell KDE to keep fullscreen windows on top */ - if (window->flags & SDL_WINDOW_FULLSCREEN) { - XEvent ev; - - SDL_zero(ev); - ev.xclient.type = ClientMessage; - ev.xclient.window = RootWindow(data->display, displaydata->screen); - ev.xclient.message_type = - XInternAtom(data->display, "KWM_KEEP_ON_TOP", False); - ev.xclient.format = 32; - ev.xclient.data.l[0] = w; - ev.xclient.data.l[1] = CurrentTime; - XSendEvent(data->display, - RootWindow(data->display, displaydata->screen), False, - SubstructureRedirectMask, &ev); - } - /* Set the input hints so we get keyboard input */ wmhints = XAllocWMHints(); if (wmhints) { @@ -678,6 +675,26 @@ X11_CreateWindow(_THIS, SDL_Window * window) XFree(classhints); } + /* FIXME: Why doesn't this work? */ + if (window->flags & SDL_WINDOW_FULLSCREEN) { + Atom _NET_WM_STATE = data->_NET_WM_STATE; + Atom _NET_WM_STATE_FULLSCREEN = data->_NET_WM_STATE_FULLSCREEN; + XEvent e; + + e.xany.type = ClientMessage; + e.xclient.display = data->display; + e.xclient.window = w; + e.xclient.message_type = _NET_WM_STATE; + e.xclient.format = 32; + e.xclient.data.l[0] = _NET_WM_STATE_ADD; + e.xclient.data.l[1] = _NET_WM_STATE_FULLSCREEN; + e.xclient.data.l[2] = 0l; + + XSendEvent(data->display, + RootWindow(data->display, displaydata->screen), 0, + SubstructureNotifyMask | SubstructureRedirectMask, &e); + } + /* Allow the window to be deleted by the window manager */ XSetWMProtocols(data->display, w, &data->WM_DELETE_WINDOW, 1); @@ -716,7 +733,7 @@ X11_CreateWindowFrom(_THIS, SDL_Window * window, const void *data) { Window w = (Window) data; - /* FIXME: Query the title from the existing window */ + window->title = X11_GetWindowTitle(_this, w); if (SetupWindowData(_this, window, w, SDL_FALSE) < 0) { return -1; @@ -724,6 +741,36 @@ X11_CreateWindowFrom(_THIS, SDL_Window * window, const void *data) return 0; } +char * +X11_GetWindowTitle(_THIS, Window xwindow) +{ + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + Display *display = data->display; + int status, real_format; + Atom real_type; + unsigned long items_read, items_left; + unsigned char *propdata; + char *title = NULL; + + status = XGetWindowProperty(display, xwindow, data->_NET_WM_NAME, + 0L, 8192L, False, data->UTF8_STRING, &real_type, &real_format, + &items_read, &items_left, &propdata); + if (status == Success) { + title = SDL_strdup(SDL_static_cast(char*, propdata)); + XFree(propdata); + } else { + status = XGetWindowProperty(display, xwindow, XA_WM_NAME, + 0L, 8192L, False, XA_STRING, &real_type, &real_format, + &items_read, &items_left, &propdata); + if (status == Success) { + title = SDL_iconv_string("UTF-8", "", SDL_static_cast(char*, propdata), items_read+1); + } else { + title = SDL_strdup(""); + } + } + return title; +} + void X11_SetWindowTitle(_THIS, SDL_Window * window) { @@ -735,14 +782,8 @@ X11_SetWindowTitle(_THIS, SDL_Window * window) const char *icon = NULL; #ifdef X_HAVE_UTF8_STRING - Atom _NET_WM_NAME = 0; - Atom _NET_WM_ICON_NAME = 0; - - /* Look up some useful Atoms */ - if (SDL_X11_HAVE_UTF8) { - _NET_WM_NAME = XInternAtom(display, "_NET_WM_NAME", False); - _NET_WM_ICON_NAME = XInternAtom(display, "_NET_WM_ICON_NAME", False); - } + Atom _NET_WM_NAME = data->videodata->_NET_WM_NAME; + Atom _NET_WM_ICON_NAME = data->videodata->_NET_WM_ICON_NAME; #endif if (title != NULL) { @@ -803,7 +844,7 @@ X11_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon) { SDL_WindowData *data = (SDL_WindowData *) window->driverdata; Display *display = data->videodata->display; - Atom _NET_WM_ICON = XInternAtom(display, "_NET_WM_ICON", False); + Atom _NET_WM_ICON = data->videodata->_NET_WM_ICON; if (icon) { SDL_PixelFormat format; @@ -842,16 +883,20 @@ X11_SetWindowPosition(_THIS, SDL_Window * window) { SDL_WindowData *data = (SDL_WindowData *) window->driverdata; Display *display = data->videodata->display; + SDL_bool oldstyle_fullscreen; int x, y; - if ((window->flags & SDL_WINDOW_FULLSCREEN) + /* ICCCM2.0-compliant window managers can handle fullscreen windows */ + oldstyle_fullscreen = X11_WindowIsOldstyleFullscreen(window); + + if (oldstyle_fullscreen || window->x == SDL_WINDOWPOS_CENTERED) { X11_GetDisplaySize(_this, window, &x, NULL); x = (x - window->w) / 2; } else { x = window->x; } - if ((window->flags & SDL_WINDOW_FULLSCREEN) + if (oldstyle_fullscreen || window->y == SDL_WINDOWPOS_CENTERED) { X11_GetDisplaySize(_this, window, NULL, &y); y = (y - window->h) / 2; @@ -904,15 +949,14 @@ X11_SetWindowMaximized(_THIS, SDL_Window * window, SDL_bool maximized) SDL_DisplayData *displaydata = (SDL_DisplayData *) window->display->driverdata; Display *display = data->videodata->display; - Atom _NET_WM_STATE = XInternAtom(display, "_NET_WM_STATE", False); - Atom _NET_WM_STATE_MAXIMIZED_VERT = - XInternAtom(display, "_NET_WM_STATE_MAXIMIZED_VERT", False); - Atom _NET_WM_STATE_MAXIMIZED_HORZ = - XInternAtom(display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); + Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE; + Atom _NET_WM_STATE_MAXIMIZED_VERT = data->videodata->_NET_WM_STATE_MAXIMIZED_VERT; + Atom _NET_WM_STATE_MAXIMIZED_HORZ = data->videodata->_NET_WM_STATE_MAXIMIZED_HORZ; XEvent e; e.xany.type = ClientMessage; - e.xany.window = data->xwindow; + e.xclient.display = display; + e.xclient.window = data->xwindow; e.xclient.message_type = _NET_WM_STATE; e.xclient.format = 32; e.xclient.data.l[0] = @@ -920,7 +964,6 @@ X11_SetWindowMaximized(_THIS, SDL_Window * window, SDL_bool maximized) e.xclient.data.l[1] = _NET_WM_STATE_MAXIMIZED_VERT; e.xclient.data.l[2] = _NET_WM_STATE_MAXIMIZED_HORZ; e.xclient.data.l[3] = 0l; - e.xclient.data.l[4] = 0l; XSendEvent(display, RootWindow(display, displaydata->screen), 0, SubstructureNotifyMask | SubstructureRedirectMask, &e); @@ -935,7 +978,12 @@ X11_MaximizeWindow(_THIS, SDL_Window * window) void X11_MinimizeWindow(_THIS, SDL_Window * window) { - X11_HideWindow(_this, window); + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + SDL_DisplayData *displaydata = + (SDL_DisplayData *) window->display->driverdata; + Display *display = data->videodata->display; + + XIconifyWindow(display, data->xwindow, displaydata->screen); } void @@ -950,8 +998,12 @@ X11_SetWindowGrab(_THIS, SDL_Window * window) { SDL_WindowData *data = (SDL_WindowData *) window->driverdata; Display *display = data->videodata->display; + SDL_bool oldstyle_fullscreen; + + /* ICCCM2.0-compliant window managers can handle fullscreen windows */ + oldstyle_fullscreen = X11_WindowIsOldstyleFullscreen(window); - if ((window->flags & (SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_FULLSCREEN)) + if (((window->flags & SDL_WINDOW_INPUT_GRABBED) || oldstyle_fullscreen) && (window->flags & SDL_WINDOW_INPUT_FOCUS)) { /* Try to grab the mouse */ for (;;) { diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h index 055bf733f..06d2c268d 100644 --- a/src/video/x11/SDL_x11window.h +++ b/src/video/x11/SDL_x11window.h @@ -35,6 +35,7 @@ typedef struct extern int X11_CreateWindow(_THIS, SDL_Window * window); extern int X11_CreateWindowFrom(_THIS, SDL_Window * window, const void *data); +extern char *X11_GetWindowTitle(_THIS, Window xwindow); extern void X11_SetWindowTitle(_THIS, SDL_Window * window); extern void X11_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon); extern void X11_SetWindowPosition(_THIS, SDL_Window * window);