Переглянути джерело

Add glfwSetWindowContentScaleCallback

Related to #677.
Related to #1115.
Camilla Löwy 7 роки тому
батько
коміт
370eac3c48
10 змінених файлів з 120 додано та 3 видалено
  1. 3 2
      README.md
  2. 3 0
      docs/news.dox
  3. 17 0
      docs/window.dox
  4. 43 0
      include/GLFW/glfw3.h
  5. 2 1
      src/cocoa_platform.h
  6. 10 0
      src/cocoa_window.m
  7. 9 0
      src/internal.h
  8. 8 0
      src/win32_window.c
  9. 17 0
      src/window.c
  10. 8 0
      tests/events.c

+ 3 - 2
README.md

@@ -136,8 +136,9 @@ information on what to include when reporting a bug.
   gamepad mapping (#900)
 - Added `glfwGetGamepadState` function, `GLFW_GAMEPAD_*` and `GLFWgamepadstate`
   for retrieving gamepad input state (#900)
-- Added `glfwGetWindowContentScale` and `glfwGetMonitorContentScale` for
-  DPI-aware rendering (#235,#439,#677,#845,#898)
+- Added `glfwGetWindowContentScale`, `glfwGetMonitorContentScale` and
+  `glfwSetWindowContentScaleCallback` for DPI-aware rendering
+  (#235,#439,#677,#845,#898)
 - Added `glfwRequestWindowAttention` function for requesting attention from the
   user (#732,#988)
 - Added `glfwGetKeyScancode` function that allows retrieving platform dependent

+ 3 - 0
docs/news.dox

@@ -64,6 +64,9 @@ GLFW now supports querying the window and monitor content scale, i.e. the ratio
 between the current DPI and the platform's default DPI, with @ref
 glfwGetWindowContentScale and @ref glfwGetMonitorContentScale.
 
+Changes of the content scale of a window can be received with the window content
+scale callback, set with @ref glfwSetWindowCloseCallback.
+
 @see @ref window_scale
 
 

+ 17 - 0
docs/window.dox

@@ -695,6 +695,23 @@ On systems where each monitors can have its own content scale, the window
 content scale will depend on which monitor the system considers the window to be
 on.
 
+If you wish to be notified when the content scale of a window changes, whether
+because of a system setting change or because it was moved to a monitor with
+a different scale, set a content scale callback.
+
+@code
+glfwSetWindowContentScaleCallback(window, window_content_scale_callback);
+@endcode
+
+The callback function receives the new content scale of the window.
+
+@code
+void window_content_scale_callback(GLFWwindow* window, float xscale, float yscale)
+{
+    set_interface_scale(xscale, yscale);
+}
+@endcode
+
 
 @subsection window_sizelimits Window size limits
 

+ 43 - 0
include/GLFW/glfw3.h

@@ -1278,6 +1278,24 @@ typedef void (* GLFWwindowmaximizefun)(GLFWwindow*,int);
  */
 typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int);
 
+/*! @brief The function signature for window content scale callbacks.
+ *
+ *  This is the function signature for window content scale callback
+ *  functions.
+ *
+ *  @param[in] window The window whose content scale changed.
+ *  @param[in] xscale The new x-axis content scale of the window.
+ *  @param[in] yscale The new y-axis content scale of the window.
+ *
+ *  @sa @ref window_scale
+ *  @sa @ref glfwSetWindowContentScaleCallback
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup window
+ */
+typedef void (* GLFWwindowcontentscalefun)(GLFWwindow*,float,float);
+
 /*! @brief The function signature for mouse button callbacks.
  *
  *  This is the function signature for mouse button callback functions.
@@ -2913,6 +2931,7 @@ GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* window, int* left, int* top, int
  *  @thread_safety This function must only be called from the main thread.
  *
  *  @sa @ref window_scale
+ *  @sa @ref glfwSetWindowContentScaleCallback
  *  @sa @ref glfwGetMonitorContentScale
  *
  *  @since Added in version 3.3.
@@ -3575,6 +3594,30 @@ GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* window,
  */
 GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window, GLFWframebuffersizefun cbfun);
 
+/*! @brief Sets the window content scale callback for the specified window.
+ *
+ *  This function sets the window content scale callback of the specified window,
+ *  which is called when the content scale of the specified window changes.
+ *
+ *  @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_scale
+ *  @sa @ref glfwGetWindowContentScale
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup window
+ */
+GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* window, GLFWwindowcontentscalefun cbfun);
+
 /*! @brief Processes all pending events.
  *
  *  This function processes only those events that are already in the event

+ 2 - 1
src/cocoa_platform.h

@@ -88,9 +88,10 @@ typedef struct _GLFWwindowNS
 
     GLFWbool        maximized;
 
-    // Cached window and framebuffer sizes used to filter out duplicate events
+    // Cached window properties to filter out duplicate events
     int             width, height;
     int             fbWidth, fbHeight;
+    float           xscale, yscale;
 
     // The total sum of the distances the cursor has been warped
     // since the last cursor motion event was processed

+ 10 - 0
src/cocoa_window.m

@@ -574,6 +574,16 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
         window->ns.fbHeight = fbRect.size.height;
         _glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
     }
+
+    const float xscale = fbRect.size.width / contentRect.size.width;
+    const float yscale = fbRect.size.height / contentRect.size.height;
+
+    if (xscale != window->ns.xscale || yscale != window->ns.yscale)
+    {
+        window->ns.xscale = xscale;
+        window->ns.yscale = yscale;
+        _glfwInputWindowContentScale(window, xscale, yscale);
+    }
 }
 
 - (void)drawRect:(NSRect)rect

+ 9 - 0
src/internal.h

@@ -437,6 +437,7 @@ struct _GLFWwindow
         GLFWwindowiconifyfun    iconify;
         GLFWwindowmaximizefun   maximize;
         GLFWframebuffersizefun  fbsize;
+        GLFWwindowcontentscalefun scale;
         GLFWmousebuttonfun      mouseButton;
         GLFWcursorposfun        cursorPos;
         GLFWcursorenterfun      cursorEnter;
@@ -754,6 +755,14 @@ void _glfwInputWindowSize(_GLFWwindow* window, int width, int height);
  */
 void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height);
 
+/*! @brief Notifies shared code that a window content scale has changed.
+ *  @param[in] window The window that received the event.
+ *  @param[in] xscale The new x-axis content scale of the window.
+ *  @param[in] yscale The new y-axis content scale of the window.
+ *  @ingroup event
+ */
+void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscale);
+
 /*! @brief Notifies shared code that a window has been iconified or restored.
  *  @param[in] window The window that received the event.
  *  @param[in] iconified `GLFW_TRUE` if the window was iconified, or

+ 8 - 0
src/win32_window.c

@@ -996,6 +996,14 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
             return 0;
         }
 
+        case WM_DPICHANGED:
+        {
+            const float xscale = HIWORD(wParam) / 96.f;
+            const float yscale = LOWORD(wParam) / 96.f;
+            _glfwInputWindowContentScale(window, xscale, yscale);
+            break;
+        }
+
         case WM_SETCURSOR:
         {
             if (LOWORD(lParam) == HTCLIENT)

+ 17 - 0
src/window.c

@@ -94,6 +94,12 @@ void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height)
         window->callbacks.fbsize((GLFWwindow*) window, width, height);
 }
 
+void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscale)
+{
+    if (window->callbacks.scale)
+        window->callbacks.scale((GLFWwindow*) window, xscale, yscale);
+}
+
 void _glfwInputWindowDamage(_GLFWwindow* window)
 {
     if (window->callbacks.refresh)
@@ -1013,6 +1019,17 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle
     return cbfun;
 }
 
+GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* handle,
+                                                                    GLFWwindowcontentscalefun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.scale, cbfun);
+    return cbfun;
+}
+
 GLFWAPI void glfwPollEvents(void)
 {
     _GLFW_REQUIRE_INIT();

+ 8 - 0
tests/events.c

@@ -293,6 +293,13 @@ static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
     glViewport(0, 0, width, height);
 }
 
+static void window_content_scale_callback(GLFWwindow* window, float xscale, float yscale)
+{
+    Slot* slot = glfwGetWindowUserPointer(window);
+    printf("%08x to %i at %0.3f: Window content scale: %0.3f %0.3f\n",
+           counter++, slot->number, glfwGetTime(), xscale, yscale);
+}
+
 static void window_close_callback(GLFWwindow* window)
 {
     Slot* slot = glfwGetWindowUserPointer(window);
@@ -599,6 +606,7 @@ int main(int argc, char** argv)
         glfwSetWindowPosCallback(slots[i].window, window_pos_callback);
         glfwSetWindowSizeCallback(slots[i].window, window_size_callback);
         glfwSetFramebufferSizeCallback(slots[i].window, framebuffer_size_callback);
+        glfwSetWindowContentScaleCallback(slots[i].window, window_content_scale_callback);
         glfwSetWindowCloseCallback(slots[i].window, window_close_callback);
         glfwSetWindowRefreshCallback(slots[i].window, window_refresh_callback);
         glfwSetWindowFocusCallback(slots[i].window, window_focus_callback);