Răsfoiți Sursa

Add glfwSetWindowMaximizeCallback

Fixes #778.
Camilla Berglund 9 ani în urmă
părinte
comite
c156b50e4c
14 a modificat fișierele cu 194 adăugiri și 30 ștergeri
  1. 2 0
      README.md
  2. 5 0
      docs/news.dox
  3. 50 1
      docs/window.dox
  4. 41 0
      include/GLFW/glfw3.h
  5. 2 0
      src/cocoa_platform.h
  6. 7 0
      src/cocoa_window.m
  7. 9 0
      src/internal.h
  8. 1 0
      src/win32_platform.h
  9. 14 17
      src/win32_window.c
  10. 17 0
      src/window.c
  11. 2 0
      src/x11_platform.h
  12. 25 10
      src/x11_window.c
  13. 10 1
      tests/events.c
  14. 9 1
      tests/iconify.c

+ 2 - 0
README.md

@@ -102,6 +102,8 @@ information on what to include when reporting a bug.
 
 
 - Added `glfwGetKeyScancode` function that allows retrieving platform dependent
 - Added `glfwGetKeyScancode` function that allows retrieving platform dependent
   scancodes for keys (#830)
   scancodes for keys (#830)
+- Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for
+  receiving window maximization events (#778)
 - Bugfix: Calling `glfwMaximizeWindow` on a full screen window was not ignored
 - Bugfix: Calling `glfwMaximizeWindow` on a full screen window was not ignored
 - Bugfix: `GLFW_INCLUDE_VULKAN` could not be combined with the corresponding
 - Bugfix: `GLFW_INCLUDE_VULKAN` could not be combined with the corresponding
           OpenGL and OpenGL ES header macros
           OpenGL and OpenGL ES header macros

+ 5 - 0
docs/news.dox

@@ -4,6 +4,11 @@
 
 
 @section news_33 New features in 3.3
 @section news_33 New features in 3.3
 
 
+@subsection news_33_maximize Window maximization callback
+
+GLFW now supports window maximization notifications with @ref
+glfwSetWindowMaximizeCallback.
+
 
 
 @subsection news_33_keyscancode Platform-specific key scancode query
 @subsection news_33_keyscancode Platform-specific key scancode query
 
 

+ 50 - 1
docs/window.dox

@@ -730,7 +730,8 @@ glfwIconifyWindow(window);
 When a full screen window is iconified, the original video mode of its monitor
 When a full screen window is iconified, the original video mode of its monitor
 is restored until the user or application restores the window.
 is restored until the user or application restores the window.
 
 
-Iconified windows can be restored with @ref glfwRestoreWindow.
+Iconified windows can be restored with @ref glfwRestoreWindow.  This function
+also restores windows from maximization.
 
 
 @code
 @code
 glfwRestoreWindow(window);
 glfwRestoreWindow(window);
@@ -769,6 +770,54 @@ int iconified = glfwGetWindowAttrib(window, GLFW_ICONIFIED);
 @endcode
 @endcode
 
 
 
 
+@subsection window_maximize Window maximization
+
+Windows can be maximized (i.e. zoomed) with @ref glfwMaximizeWindow.
+
+@code
+glfwMaximizeWindow(window);
+@endcode
+
+Full screen windows cannot be maximized and passing a full screen window to this
+function does nothing.
+
+Maximized windows can be restored with @ref glfwRestoreWindow.  This function
+also restores windows from iconification.
+
+@code
+glfwRestoreWindow(window);
+@endcode
+
+If you wish to be notified when a window is maximized or restored, whether by
+the user, system or your own code, set a maximize callback.
+
+@code
+glfwSetWindowMaximizeCallback(window, window_maximize_callback);
+@endcode
+
+The callback function receives changes in the maximization state of the window.
+
+@code
+void window_maximize_callback(GLFWwindow* window, int maximized)
+{
+    if (maximized)
+    {
+        // The window was maximized
+    }
+    else
+    {
+        // The window was restored
+    }
+}
+@endcode
+
+You can also get the current maximization state with @ref glfwGetWindowAttrib.
+
+@code
+int maximized = glfwGetWindowAttrib(window, GLFW_MAXIMIZED);
+@endcode
+
+
 @subsection window_hide Window visibility
 @subsection window_hide Window visibility
 
 
 Windowed mode windows can be hidden with @ref glfwHideWindow.
 Windowed mode windows can be hidden with @ref glfwHideWindow.

+ 41 - 0
include/GLFW/glfw3.h

@@ -921,6 +921,24 @@ typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int);
  */
  */
 typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int);
 typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int);
 
 
+/*! @brief The function signature for window maximize/restore callbacks.
+ *
+ *  This is the function signature for window maximize/restore callback
+ *  functions.
+ *
+ *  @param[in] window The window that was maximized or restored.
+ *  @param[in] iconified `GLFW_TRUE` if the window was maximized, or
+ *  `GLFW_FALSE` if it was restored.
+ *
+ *  @sa @ref window_maximize
+ *  @sa glfwSetWindowMaximizeCallback
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup window
+ */
+typedef void (* GLFWwindowmaximizefun)(GLFWwindow*,int);
+
 /*! @brief The function signature for framebuffer resize callbacks.
 /*! @brief The function signature for framebuffer resize callbacks.
  *
  *
  *  This is the function signature for framebuffer resize callback
  *  This is the function signature for framebuffer resize callback
@@ -2705,6 +2723,29 @@ GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwi
  */
  */
 GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* window, GLFWwindowiconifyfun cbfun);
 GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* window, GLFWwindowiconifyfun cbfun);
 
 
+/*! @brief Sets the maximize callback for the specified window.
+ *
+ *  This function sets the maximization callback of the specified window, which
+ *  is called when the window is maximized or restored.
+ *
+ *  @param[in] window The window whose callback to set.
+ *  @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ *  callback.
+ *  @return The previously set callback, or `NULL` if no callback was set or the
+ *  library had not been [initialized](@ref intro_init).
+ *
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref window_maximize
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup window
+ */
+GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* window, GLFWwindowmaximizefun cbfun);
+
 /*! @brief Sets the framebuffer resize callback for the specified window.
 /*! @brief Sets the framebuffer resize callback for the specified window.
  *
  *
  *  This function sets the framebuffer resize callback of the specified window,
  *  This function sets the framebuffer resize callback of the specified window,

+ 2 - 0
src/cocoa_platform.h

@@ -75,6 +75,8 @@ typedef struct _GLFWwindowNS
     id              delegate;
     id              delegate;
     id              view;
     id              view;
 
 
+    GLFWbool        maximized;
+
     // The total sum of the distances the cursor has been warped
     // The total sum of the distances the cursor has been warped
     // since the last cursor motion event was processed
     // since the last cursor motion event was processed
     // This is kept to counteract Cocoa doing the same internally
     // This is kept to counteract Cocoa doing the same internally

+ 7 - 0
src/cocoa_window.m

@@ -238,6 +238,13 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
     if (_glfw.ns.disabledCursorWindow == window)
     if (_glfw.ns.disabledCursorWindow == window)
         centerCursor(window);
         centerCursor(window);
 
 
+    const int maximized = [window->ns.object isZoomed];
+    if (window->ns.maximized != maximized)
+    {
+        window->ns.maximized = maximized;
+        _glfwInputWindowMaximize(window, maximized);
+    }
+
     const NSRect contentRect = [window->ns.view frame];
     const NSRect contentRect = [window->ns.view frame];
     const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
     const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
 
 

+ 9 - 0
src/internal.h

@@ -378,6 +378,7 @@ struct _GLFWwindow
         GLFWwindowrefreshfun    refresh;
         GLFWwindowrefreshfun    refresh;
         GLFWwindowfocusfun      focus;
         GLFWwindowfocusfun      focus;
         GLFWwindowiconifyfun    iconify;
         GLFWwindowiconifyfun    iconify;
+        GLFWwindowmaximizefun   maximize;
         GLFWframebuffersizefun  fbsize;
         GLFWframebuffersizefun  fbsize;
         GLFWmousebuttonfun      mouseButton;
         GLFWmousebuttonfun      mouseButton;
         GLFWcursorposfun        cursorPos;
         GLFWcursorposfun        cursorPos;
@@ -856,6 +857,14 @@ void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height);
  */
  */
 void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified);
 void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified);
 
 
+/*! @brief Notifies shared code of a window maximization event.
+ *  @param[in] window The window that received the event.
+ *  @param[in] maximized `GLFW_TRUE` if the window was maximized, or
+ *  `GLFW_FALSE` if it was restored.
+ *  @ingroup event
+ */
+void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized);
+
 /*! @brief Notifies shared code of a window damage event.
 /*! @brief Notifies shared code of a window damage event.
  *  @param[in] window The window that received the event.
  *  @param[in] window The window that received the event.
  */
  */

+ 1 - 0
src/win32_platform.h

@@ -235,6 +235,7 @@ typedef struct _GLFWwindowWin32
 
 
     GLFWbool            cursorTracked;
     GLFWbool            cursorTracked;
     GLFWbool            iconified;
     GLFWbool            iconified;
+    GLFWbool            maximized;
 
 
     // The last received cursor position, regardless of source
     // The last received cursor position, regardless of source
     int                 lastCursorPosX, lastCursorPosY;
     int                 lastCursorPosX, lastCursorPosY;

+ 14 - 17
src/win32_window.c

@@ -693,36 +693,33 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
 
 
         case WM_SIZE:
         case WM_SIZE:
         {
         {
-            const GLFWbool iconified =
-                !window->win32.iconified && wParam == SIZE_MINIMIZED;
-            const GLFWbool restored =
-                window->win32.iconified &&
-                (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED);
+            const GLFWbool iconified = wParam == SIZE_MINIMIZED;
+            const GLFWbool maximized = wParam == SIZE_MAXIMIZED ||
+                                       (window->win32.maximized &&
+                                        wParam != SIZE_RESTORED);
 
 
             if (_glfw.win32.disabledCursorWindow == window)
             if (_glfw.win32.disabledCursorWindow == window)
                 updateClipRect(window);
                 updateClipRect(window);
 
 
-            if (iconified)
-                _glfwInputWindowIconify(window, GLFW_TRUE);
-            else if (restored)
-                _glfwInputWindowIconify(window, GLFW_FALSE);
+            if (window->win32.iconified != iconified)
+                _glfwInputWindowIconify(window, iconified);
+
+            if (window->win32.maximized != maximized)
+                _glfwInputWindowMaximize(window, maximized);
 
 
             _glfwInputFramebufferSize(window, LOWORD(lParam), HIWORD(lParam));
             _glfwInputFramebufferSize(window, LOWORD(lParam), HIWORD(lParam));
             _glfwInputWindowSize(window, LOWORD(lParam), HIWORD(lParam));
             _glfwInputWindowSize(window, LOWORD(lParam), HIWORD(lParam));
 
 
-            if (iconified)
+            if (window->monitor && window->win32.iconified != iconified)
             {
             {
-                window->win32.iconified = GLFW_TRUE;
-                if (window->monitor)
+                if (iconified)
                     releaseMonitor(window);
                     releaseMonitor(window);
-            }
-            else if (restored)
-            {
-                window->win32.iconified = GLFW_FALSE;
-                if (window->monitor)
+                else
                     acquireMonitor(window);
                     acquireMonitor(window);
             }
             }
 
 
+            window->win32.iconified = iconified;
+            window->win32.maximized = maximized;
             return 0;
             return 0;
         }
         }
 
 

+ 17 - 0
src/window.c

@@ -86,6 +86,12 @@ void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified)
         window->callbacks.iconify((GLFWwindow*) window, iconified);
         window->callbacks.iconify((GLFWwindow*) window, iconified);
 }
 }
 
 
+void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized)
+{
+    if (window->callbacks.maximize)
+        window->callbacks.maximize((GLFWwindow*) window, maximized);
+}
+
 void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height)
 void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height)
 {
 {
     if (window->callbacks.fbsize)
     if (window->callbacks.fbsize)
@@ -856,6 +862,17 @@ GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle,
     return cbfun;
     return cbfun;
 }
 }
 
 
+GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* handle,
+                                                            GLFWwindowmaximizefun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.maximize, cbfun);
+    return cbfun;
+}
+
 GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle,
 GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle,
                                                               GLFWframebuffersizefun cbfun)
                                                               GLFWframebuffersizefun cbfun)
 {
 {

+ 2 - 0
src/x11_platform.h

@@ -112,6 +112,8 @@ typedef struct _GLFWwindowX11
     XIC             ic;
     XIC             ic;
 
 
     GLFWbool        overrideRedirect;
     GLFWbool        overrideRedirect;
+    GLFWbool        iconified;
+    GLFWbool        maximized;
 
 
     // Cached position and size used to filter out duplicate events
     // Cached position and size used to filter out duplicate events
     int             width, height;
     int             width, height;

+ 25 - 10
src/x11_window.c

@@ -559,6 +559,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
             {
             {
                 states[count++] = _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT;
                 states[count++] = _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT;
                 states[count++] = _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ;
                 states[count++] = _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ;
+                window->x11.maximized = GLFW_TRUE;
             }
             }
         }
         }
 
 
@@ -1415,23 +1416,37 @@ static void processEvent(XEvent *event)
 
 
         case PropertyNotify:
         case PropertyNotify:
         {
         {
-            if (event->xproperty.atom == _glfw.x11.WM_STATE &&
-                event->xproperty.state == PropertyNewValue)
+            if (event->xproperty.state != PropertyNewValue)
+                return;
+
+            if (event->xproperty.atom == _glfw.x11.WM_STATE)
             {
             {
                 const int state = getWindowState(window);
                 const int state = getWindowState(window);
-                if (state == IconicState)
+                if (state != IconicState && state != NormalState)
+                    return;
+
+                const GLFWbool iconified = (state == IconicState);
+                if (window->x11.iconified != iconified)
                 {
                 {
                     if (window->monitor)
                     if (window->monitor)
-                        releaseMonitor(window);
+                    {
+                        if (iconified)
+                            releaseMonitor(window);
+                        else
+                            acquireMonitor(window);
+                    }
 
 
-                    _glfwInputWindowIconify(window, GLFW_TRUE);
+                    window->x11.iconified = iconified;
+                    _glfwInputWindowIconify(window, iconified);
                 }
                 }
-                else if (state == NormalState)
+            }
+            else if (event->xproperty.atom == _glfw.x11.NET_WM_STATE)
+            {
+                const GLFWbool maximized = _glfwPlatformWindowMaximized(window);
+                if (window->x11.maximized != maximized)
                 {
                 {
-                    if (window->monitor)
-                        acquireMonitor(window);
-
-                    _glfwInputWindowIconify(window, GLFW_FALSE);
+                    window->x11.maximized = maximized;
+                    _glfwInputWindowMaximize(window, maximized);
                 }
                 }
             }
             }
 
 

+ 10 - 1
tests/events.c

@@ -322,7 +322,15 @@ static void window_iconify_callback(GLFWwindow* window, int iconified)
     Slot* slot = glfwGetWindowUserPointer(window);
     Slot* slot = glfwGetWindowUserPointer(window);
     printf("%08x to %i at %0.3f: Window was %s\n",
     printf("%08x to %i at %0.3f: Window was %s\n",
            counter++, slot->number, glfwGetTime(),
            counter++, slot->number, glfwGetTime(),
-           iconified ? "iconified" : "restored");
+           iconified ? "iconified" : "uniconified");
+}
+
+static void window_maximize_callback(GLFWwindow* window, int maximized)
+{
+    Slot* slot = glfwGetWindowUserPointer(window);
+    printf("%08x to %i at %0.3f: Window was %s\n",
+           counter++, slot->number, glfwGetTime(),
+           maximized ? "maximized" : "unmaximized");
 }
 }
 
 
 static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
 static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
@@ -580,6 +588,7 @@ int main(int argc, char** argv)
         glfwSetWindowRefreshCallback(slots[i].window, window_refresh_callback);
         glfwSetWindowRefreshCallback(slots[i].window, window_refresh_callback);
         glfwSetWindowFocusCallback(slots[i].window, window_focus_callback);
         glfwSetWindowFocusCallback(slots[i].window, window_focus_callback);
         glfwSetWindowIconifyCallback(slots[i].window, window_iconify_callback);
         glfwSetWindowIconifyCallback(slots[i].window, window_iconify_callback);
+        glfwSetWindowMaximizeCallback(slots[i].window, window_maximize_callback);
         glfwSetMouseButtonCallback(slots[i].window, mouse_button_callback);
         glfwSetMouseButtonCallback(slots[i].window, mouse_button_callback);
         glfwSetCursorPosCallback(slots[i].window, cursor_position_callback);
         glfwSetCursorPosCallback(slots[i].window, cursor_position_callback);
         glfwSetCursorEnterCallback(slots[i].window, cursor_enter_callback);
         glfwSetCursorEnterCallback(slots[i].window, cursor_enter_callback);

+ 9 - 1
tests/iconify.c

@@ -131,7 +131,14 @@ static void window_iconify_callback(GLFWwindow* window, int iconified)
 {
 {
     printf("%0.2f Window %s\n",
     printf("%0.2f Window %s\n",
            glfwGetTime(),
            glfwGetTime(),
-           iconified ? "iconified" : "restored");
+           iconified ? "iconified" : "uniconified");
+}
+
+static void window_maximize_callback(GLFWwindow* window, int maximized)
+{
+    printf("%0.2f Window %s\n",
+           glfwGetTime(),
+           maximized ? "maximized" : "unmaximized");
 }
 }
 
 
 static void window_refresh_callback(GLFWwindow* window)
 static void window_refresh_callback(GLFWwindow* window)
@@ -266,6 +273,7 @@ int main(int argc, char** argv)
         glfwSetWindowSizeCallback(windows[i], window_size_callback);
         glfwSetWindowSizeCallback(windows[i], window_size_callback);
         glfwSetWindowFocusCallback(windows[i], window_focus_callback);
         glfwSetWindowFocusCallback(windows[i], window_focus_callback);
         glfwSetWindowIconifyCallback(windows[i], window_iconify_callback);
         glfwSetWindowIconifyCallback(windows[i], window_iconify_callback);
+        glfwSetWindowMaximizeCallback(windows[i], window_maximize_callback);
         glfwSetWindowRefreshCallback(windows[i], window_refresh_callback);
         glfwSetWindowRefreshCallback(windows[i], window_refresh_callback);
 
 
         window_refresh_callback(windows[i]);
         window_refresh_callback(windows[i]);