Przeglądaj źródła

Add glfwSetWindowMaximizeCallback

Fixes #778.
Camilla Berglund 9 lat temu
rodzic
commit
c156b50e4c
14 zmienionych plików z 194 dodań i 30 usunięć
  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
   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: `GLFW_INCLUDE_VULKAN` could not be combined with the corresponding
           OpenGL and OpenGL ES header macros

+ 5 - 0
docs/news.dox

@@ -4,6 +4,11 @@
 
 @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
 

+ 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
 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
 glfwRestoreWindow(window);
@@ -769,6 +770,54 @@ int iconified = glfwGetWindowAttrib(window, GLFW_ICONIFIED);
 @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
 
 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);
 
+/*! @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.
  *
  *  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);
 
+/*! @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.
  *
  *  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              view;
 
+    GLFWbool        maximized;
+
     // The total sum of the distances the cursor has been warped
     // since the last cursor motion event was processed
     // 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)
         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 fbRect = [window->ns.view convertRectToBacking:contentRect];
 

+ 9 - 0
src/internal.h

@@ -378,6 +378,7 @@ struct _GLFWwindow
         GLFWwindowrefreshfun    refresh;
         GLFWwindowfocusfun      focus;
         GLFWwindowiconifyfun    iconify;
+        GLFWwindowmaximizefun   maximize;
         GLFWframebuffersizefun  fbsize;
         GLFWmousebuttonfun      mouseButton;
         GLFWcursorposfun        cursorPos;
@@ -856,6 +857,14 @@ void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height);
  */
 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.
  *  @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            iconified;
+    GLFWbool            maximized;
 
     // The last received cursor position, regardless of source
     int                 lastCursorPosX, lastCursorPosY;

+ 14 - 17
src/win32_window.c

@@ -693,36 +693,33 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
 
         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)
                 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));
             _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);
-            }
-            else if (restored)
-            {
-                window->win32.iconified = GLFW_FALSE;
-                if (window->monitor)
+                else
                     acquireMonitor(window);
             }
 
+            window->win32.iconified = iconified;
+            window->win32.maximized = maximized;
             return 0;
         }
 

+ 17 - 0
src/window.c

@@ -86,6 +86,12 @@ void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool 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)
 {
     if (window->callbacks.fbsize)
@@ -856,6 +862,17 @@ GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle,
     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,
                                                               GLFWframebuffersizefun cbfun)
 {

+ 2 - 0
src/x11_platform.h

@@ -112,6 +112,8 @@ typedef struct _GLFWwindowX11
     XIC             ic;
 
     GLFWbool        overrideRedirect;
+    GLFWbool        iconified;
+    GLFWbool        maximized;
 
     // Cached position and size used to filter out duplicate events
     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_HORZ;
+                window->x11.maximized = GLFW_TRUE;
             }
         }
 
@@ -1415,23 +1416,37 @@ static void processEvent(XEvent *event)
 
         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);
-                if (state == IconicState)
+                if (state != IconicState && state != NormalState)
+                    return;
+
+                const GLFWbool iconified = (state == IconicState);
+                if (window->x11.iconified != iconified)
                 {
                     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);
     printf("%08x to %i at %0.3f: Window was %s\n",
            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)
@@ -580,6 +588,7 @@ int main(int argc, char** argv)
         glfwSetWindowRefreshCallback(slots[i].window, window_refresh_callback);
         glfwSetWindowFocusCallback(slots[i].window, window_focus_callback);
         glfwSetWindowIconifyCallback(slots[i].window, window_iconify_callback);
+        glfwSetWindowMaximizeCallback(slots[i].window, window_maximize_callback);
         glfwSetMouseButtonCallback(slots[i].window, mouse_button_callback);
         glfwSetCursorPosCallback(slots[i].window, cursor_position_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",
            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)
@@ -266,6 +273,7 @@ int main(int argc, char** argv)
         glfwSetWindowSizeCallback(windows[i], window_size_callback);
         glfwSetWindowFocusCallback(windows[i], window_focus_callback);
         glfwSetWindowIconifyCallback(windows[i], window_iconify_callback);
+        glfwSetWindowMaximizeCallback(windows[i], window_maximize_callback);
         glfwSetWindowRefreshCallback(windows[i], window_refresh_callback);
 
         window_refresh_callback(windows[i]);