diff --git a/src/x11_init.c b/src/x11_init.c index 04b1b104..5bc77529 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -318,40 +318,6 @@ static void updateKeyCodeLUT(void) } -//======================================================================== -// Retrieve a single window property of the specified type -// Inspired by fghGetWindowProperty from freeglut -//======================================================================== - -static unsigned long getWindowProperty(Window window, - Atom property, - Atom type, - unsigned char** value) -{ - Atom actualType; - int actualFormat; - unsigned long itemCount, bytesAfter; - - XGetWindowProperty(_glfw.x11.display, - window, - property, - 0, - LONG_MAX, - False, - type, - &actualType, - &actualFormat, - &itemCount, - &bytesAfter, - value); - - if (actualType != type) - return 0; - - return itemCount; -} - - //======================================================================== // Check whether the specified atom is supported //======================================================================== @@ -394,10 +360,10 @@ static void detectEWMH(void) return; // Then we look for the _NET_SUPPORTING_WM_CHECK property of the root window - if (getWindowProperty(_glfw.x11.root, - supportingWmCheck, - XA_WINDOW, - (unsigned char**) &windowFromRoot) != 1) + if (_glfwGetWindowProperty(_glfw.x11.root, + supportingWmCheck, + XA_WINDOW, + (unsigned char**) &windowFromRoot) != 1) { XFree(windowFromRoot); return; @@ -405,10 +371,10 @@ static void detectEWMH(void) // It should be the ID of a child window (of the root) // Then we look for the same property on the child window - if (getWindowProperty(*windowFromRoot, - supportingWmCheck, - XA_WINDOW, - (unsigned char**) &windowFromChild) != 1) + if (_glfwGetWindowProperty(*windowFromRoot, + supportingWmCheck, + XA_WINDOW, + (unsigned char**) &windowFromChild) != 1) { XFree(windowFromRoot); XFree(windowFromChild); @@ -433,10 +399,10 @@ static void detectEWMH(void) // Now we need to check the _NET_SUPPORTED property of the root window // It should be a list of supported WM protocol and state atoms - atomCount = getWindowProperty(_glfw.x11.root, - wmSupported, - XA_ATOM, - (unsigned char**) &supportedAtoms); + atomCount = _glfwGetWindowProperty(_glfw.x11.root, + wmSupported, + XA_ATOM, + (unsigned char**) &supportedAtoms); // See which of the atoms we support that are supported by the WM @@ -484,7 +450,8 @@ static GLboolean initDisplay(void) _glfw.x11.screen = DefaultScreen(_glfw.x11.display); _glfw.x11.root = RootWindow(_glfw.x11.display, _glfw.x11.screen); - // Find or create the protocol atom for window close notifications + // Find or create window manager atoms + _glfw.x11.WM_STATE = XInternAtom(_glfw.x11.display, "WM_STATE", False); _glfw.x11.WM_DELETE_WINDOW = XInternAtom(_glfw.x11.display, "WM_DELETE_WINDOW", False); diff --git a/src/x11_platform.h b/src/x11_platform.h index 2d671a92..80f38470 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -123,6 +123,7 @@ typedef struct _GLFWlibraryX11 Cursor cursor; // Window manager atoms + Atom WM_STATE; Atom WM_DELETE_WINDOW; Atom NET_WM_NAME; Atom NET_WM_ICON_NAME; @@ -252,4 +253,10 @@ Atom _glfwWriteSelection(XSelectionRequestEvent* request); // Event processing void _glfwProcessPendingEvents(void); +// Window support +unsigned long _glfwGetWindowProperty(Window window, + Atom property, + Atom type, + unsigned char** value); + #endif // _x11_platform_h_ diff --git a/src/x11_window.c b/src/x11_window.c index 4599797a..c9beaddb 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -35,6 +35,7 @@ #include #include #include +#include // Action for EWMH client messages #define _NET_WM_STATE_REMOVE 0 @@ -105,7 +106,7 @@ static GLboolean createWindow(_GLFWwindow* window, wa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | ExposureMask | FocusChangeMask | VisibilityChangeMask | - EnterWindowMask | LeaveWindowMask; + EnterWindowMask | LeaveWindowMask | PropertyChangeMask; if (wndconfig->monitor == NULL) { @@ -666,7 +667,6 @@ static void processEvent(XEvent *event) return; _glfwInputWindowVisibility(window, GL_TRUE); - _glfwInputWindowIconify(window, GL_FALSE); break; } @@ -677,7 +677,6 @@ static void processEvent(XEvent *event) return; _glfwInputWindowVisibility(window, GL_FALSE); - _glfwInputWindowIconify(window, GL_TRUE); break; } @@ -719,6 +718,37 @@ static void processEvent(XEvent *event) break; } + case PropertyNotify: + { + window = findWindow(event->xproperty.window); + if (window == NULL) + return; + + if (event->xproperty.atom == _glfw.x11.WM_STATE && + event->xproperty.state == PropertyNewValue) + { + struct { + CARD32 state; + Window icon; + } *state = NULL; + + if (_glfwGetWindowProperty(window->x11.handle, + _glfw.x11.WM_STATE, + _glfw.x11.WM_STATE, + (unsigned char**) &state) >= 2) + { + if (state->state == IconicState) + _glfwInputWindowIconify(window, GL_TRUE); + else if (state->state == NormalState) + _glfwInputWindowIconify(window, GL_FALSE); + } + + XFree(state); + } + + break; + } + case SelectionClear: { // The ownership of the clipboard selection was lost @@ -785,6 +815,45 @@ static void processEvent(XEvent *event) } } + +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +//======================================================================== +// Retrieve a single window property of the specified type +// Inspired by fghGetWindowProperty from freeglut +//======================================================================== + +unsigned long _glfwGetWindowProperty(Window window, + Atom property, + Atom type, + unsigned char** value) +{ + Atom actualType; + int actualFormat; + unsigned long itemCount, bytesAfter; + + XGetWindowProperty(_glfw.x11.display, + window, + property, + 0, + LONG_MAX, + False, + type, + &actualType, + &actualFormat, + &itemCount, + &bytesAfter, + value); + + if (actualType != type) + return 0; + + return itemCount; +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// //////////////////////////////////////////////////////////////////////////