Implemented X11 maximized state control
authorSam Lantinga <slouken@libsdl.org>
Thu, 19 Feb 2009 06:48:25 +0000
changeset 3077 9b58f26ede81
parent 3076 085e46423377
child 3078 81d15ace9129
Implemented X11 maximized state control
src/video/x11/SDL_x11sym.h
src/video/x11/SDL_x11window.c
--- a/src/video/x11/SDL_x11sym.h	Thu Feb 19 04:41:09 2009 +0000
+++ b/src/video/x11/SDL_x11sym.h	Thu Feb 19 06:48:25 2009 +0000
@@ -70,6 +70,7 @@
 SDL_X11_SYM(XVisualInfo*,XGetVisualInfo,(Display* a,long b,XVisualInfo* c,int* d),(a,b,c,d),return)
 SDL_X11_SYM(XWMHints*,XGetWMHints,(Display* a,Window b),(a,b),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)
 SDL_X11_SYM(int,XGrabKeyboard,(Display* a,Window b,Bool c,int d,int e,Time f),(a,b,c,d,e,f),return)
 SDL_X11_SYM(int,XGrabPointer,(Display* a,Window b,Bool c,unsigned int d,int e,int f,Window g,Cursor h,Time i),(a,b,c,d,e,f,g,h,i),return)
 SDL_X11_SYM(int,XGrabServer,(Display* a),(a),return)
--- a/src/video/x11/SDL_x11window.c	Thu Feb 19 04:41:09 2009 +0000
+++ b/src/video/x11/SDL_x11window.c	Thu Feb 19 06:48:25 2009 +0000
@@ -31,6 +31,10 @@
 #include "SDL_x11gamma.h"
 #include "../Xext/extensions/StdCmap.h"
 
+#define _NET_WM_STATE_REMOVE    0l
+#define _NET_WM_STATE_ADD       1l
+#define _NET_WM_STATE_TOGGLE    2l
+
 static void
 X11_GetDisplaySize(_THIS, SDL_Window * window, int *w, int *h)
 {
@@ -116,6 +120,40 @@
             window->flags &= ~SDL_WINDOW_SHOWN;
         }
     }
+
+    {
+        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 actualType;
+        int actualFormat;
+        unsigned long i, numItems, bytesAfter;
+        unsigned char *propertyValue = NULL;
+        long maxLength = 1024;
+
+        if (XGetWindowProperty(data->videodata->display, w, _NET_WM_STATE,
+            0l, maxLength, False, XA_ATOM, &actualType, &actualFormat,
+            &numItems, &bytesAfter, &propertyValue) == Success) {
+            Atom *atoms = (Atom *)propertyValue;
+            int maximized = 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;
+                }
+                /* Might also want to check the following properties:
+                   _NET_WM_STATE_ABOVE, _NET_WM_STATE_FULLSCREEN
+                */
+            }
+            if (maximized == 3) {
+                window->flags |= SDL_WINDOW_MAXIMIZED;
+            }
+            XFree(propertyValue);
+        }
+    }
+
     /* FIXME: How can I tell?
        {
        DWORD style = GetWindowLong(hwnd, GWL_STYLE);
@@ -857,10 +895,36 @@
     XRaiseWindow(display, data->window);
 }
 
+static void
+X11_SetWindowMaximized(_THIS, SDL_Window * window, SDL_bool maximized)
+{
+    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+    SDL_DisplayData *displaydata =
+        (SDL_DisplayData *) SDL_GetDisplayFromWindow(window)->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);
+    XEvent e;
+
+    e.xany.type = ClientMessage;
+    e.xany.window = data->window;
+    e.xclient.message_type = _NET_WM_STATE;
+    e.xclient.format = 32;
+    e.xclient.data.l[0] = maximized ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
+    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);
+}
+
 void
 X11_MaximizeWindow(_THIS, SDL_Window * window)
 {
-    /* FIXME: is this even possible? */
+    X11_SetWindowMaximized(_this, window, SDL_TRUE);
 }
 
 void
@@ -872,6 +936,7 @@
 void
 X11_RestoreWindow(_THIS, SDL_Window * window)
 {
+    X11_SetWindowMaximized(_this, window, SDL_FALSE);
     X11_ShowWindow(_this, window);
 }