From 00498c7670b4e35ea992b5d4868e77b1ff7db55d Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Sun, 6 Nov 2022 13:30:48 +0100 Subject: [PATCH] implement support for wp-fractional-scale-v2 --- deps/wayland/fractional-scale-v2.xml | 129 +++++++++++++++++++++++++++ src/CMakeLists.txt | 1 + src/wl_init.c | 12 +++ src/wl_platform.h | 7 +- src/wl_window.c | 78 ++++++++++++---- 5 files changed, 207 insertions(+), 20 deletions(-) create mode 100644 deps/wayland/fractional-scale-v2.xml diff --git a/deps/wayland/fractional-scale-v2.xml b/deps/wayland/fractional-scale-v2.xml new file mode 100644 index 000000000..f77cebe3c --- /dev/null +++ b/deps/wayland/fractional-scale-v2.xml @@ -0,0 +1,129 @@ + + + + Copyright © 2022 Xaver Hugl + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + This protocol allows compositors and clients to communicate the + coordinate space their surfaces act in. + + + + + A global interface to create wp_fractional_scale_v2 interfaces. + + + + + Informs the server that the client will not be using this protocol + object anymore. This does not affect any other objects. + + + + + + + + + + Create an interface object for a wl_surface to communicate scale. + If the given wl_surface already has a wp_fractional_scale_v2 object + associated, the fractional_scale_exists protocol error is raised. + + + + + + + + + An additional interface for a wl_surface object that allows compositor and + client to communicate in a different coordinate space, in order to enable + them to accurately describe coordinates and sizes in pixels. + The two coordinate spaces in consideration are logical and pixels, where + logical coordinates describe the size content should have and pixels + describe the size of buffers. + + A scale of one equals a lack of scaling, where the communicated values + define both logical coordinates and pixels. + A scale greater than one describes that for every logical coordinate, + more than one pixel is used, and a scale less than one describes that + multiple logical coordinates make up one pixel. + In mathematical terms, logical coordinates can be obtained by dividing + the provided values by the currently active scale. + + The initial compositor and client coordinate scale factors are 1. + + + + + This event sets a scale factor for the associated wl_surface that + describes the coordinate system the compositor will use for events + following wp_fractional_scale_v2.scale_factor. + + The scale factor is encoded in a 8.24 fixed point format. + + The compositor must not send a scale of zero. + + The client should re-render and commit a new buffer with the new scale + as soon as possible, in order to avoid artifacts caused by the mismatch + in compositor and client scales. + + + + + + + This request sets a scale factor for the associated wl_surface that + describes the coordinate system the client uses for requests following + wp_fractional_scale_v2.set_scale_factor. + + The scale factor is encoded in a 8.24 fixed point format. + + If this scale factor does not match the scale factor provided by the + compositor with wp_fractional_scale_v2.scale_factor, the compositor may + apply transformations to the wl_surface that can result in blurriness + or other artifacts. + + If scale_8_24 is zero, the error invalid_scale will be raised. + + + + + + + The wl_surface's wp_fractional_scale_v2 object is destroyed, and the + associated scale is reset to 1. + + + + + + + + + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2cbe8a733..c3c907f7b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -105,6 +105,7 @@ if (GLFW_BUILD_WAYLAND) generate_wayland_protocol("fractional-scale-v1.xml") generate_wayland_protocol("xdg-activation-v1.xml") generate_wayland_protocol("xdg-decoration-unstable-v1.xml") + generate_wayland_protocol("fractional-scale-v2.xml") endif() if (WIN32 AND GLFW_BUILD_SHARED_LIBRARY) diff --git a/src/wl_init.c b/src/wl_init.c index ef9e45036..48b2dd03e 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -49,6 +49,7 @@ #include "fractional-scale-v1-client-protocol.h" #include "xdg-activation-v1-client-protocol.h" #include "idle-inhibit-unstable-v1-client-protocol.h" +#include "fractional-scale-v2-client-protocol.h" // NOTE: Versions of wayland-scanner prior to 1.17.91 named every global array of // wl_interface pointers 'types', making it impossible to combine several unmodified @@ -91,6 +92,10 @@ #include "idle-inhibit-unstable-v1-client-protocol-code.h" #undef types +#define types _glfw_fractional_scale_v2_types +#include "fractional-scale-v2-client-protocol-code.h" +#undef types + static void wmBaseHandlePing(void* userData, struct xdg_wm_base* wmBase, uint32_t serial) @@ -208,6 +213,13 @@ static void registryHandleGlobal(void* userData, &wp_fractional_scale_manager_v1_interface, 1); } + else if (strcmp(interface, wp_fractional_scale_manager_v2_interface.name) == 0) + { + _glfw.wl.fractionalScaleManager = + wl_registry_bind(registry, name, + &wp_fractional_scale_manager_v2_interface, + 1); + } } static void registryHandleGlobalRemove(void* userData, diff --git a/src/wl_platform.h b/src/wl_platform.h index c3e456931..ca067f813 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -398,8 +398,10 @@ typedef struct _GLFWwindowWayland size_t outputScaleSize; struct wp_viewport* scalingViewport; - uint32_t scalingNumerator; - struct wp_fractional_scale_v1* fractionalScale; + uint32_t fractionalScaleV1Numerator; + struct wp_fractional_scale_v1* fractionalScaleV1; + double fractionalScaleV2Factor; + struct wp_fractional_scale_v2* fractionalScaleV2; struct zwp_relative_pointer_v1* relativePointer; struct zwp_locked_pointer_v1* lockedPointer; @@ -440,6 +442,7 @@ typedef struct _GLFWlibraryWayland struct zwp_idle_inhibit_manager_v1* idleInhibitManager; struct xdg_activation_v1* activationManager; struct wp_fractional_scale_manager_v1* fractionalScaleManager; + struct wp_fractional_scale_manager_v2* fractionalScaleV2Manager; _GLFWofferWayland* offers; unsigned int offerCount; diff --git a/src/wl_window.c b/src/wl_window.c index 4220d17e0..9b2d6e661 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -51,6 +51,7 @@ #include "xdg-activation-v1-client-protocol.h" #include "idle-inhibit-unstable-v1-client-protocol.h" #include "fractional-scale-v1-client-protocol.h" +#include "fractional-scale-v2-client-protocol.h" #define GLFW_BORDER_SIZE 4 #define GLFW_CAPTION_HEIGHT 24 @@ -459,10 +460,15 @@ static void setContentAreaOpaque(_GLFWwindow* window) static void resizeFramebuffer(_GLFWwindow* window) { - if (window->wl.fractionalScale) + if (window->wl.fractionalScaleV2) { - window->wl.fbWidth = (window->wl.width * window->wl.scalingNumerator) / 120; - window->wl.fbHeight = (window->wl.height * window->wl.scalingNumerator) / 120; + window->wl.fbWidth = (window->wl.width * window->wl.fractionalScaleV2Factor) / 120; + window->wl.fbHeight = (window->wl.height * window->wl.fractionalScaleV2Factor) / 120; + } + else if (window->wl.fractionalScaleV1) + { + window->wl.fbWidth = (window->wl.width * window->wl.fractionalScaleV1Numerator) / 120; + window->wl.fbHeight = (window->wl.height * window->wl.fractionalScaleV1Numerator) / 120; } else { @@ -546,7 +552,7 @@ void _glfwUpdateBufferScaleFromOutputsWayland(_GLFWwindow* window) return; // When using fractional scaling, the buffer scale should remain at 1 - if (window->wl.fractionalScale) + if (window->wl.fractionalScaleV1 || window->wl.fractionalScaleV2) return; // Get the scale factor from the highest scale monitor. @@ -624,6 +630,30 @@ static const struct wl_surface_listener surfaceListener = surfaceHandleLeave }; +void handleScaleFactor(void *userData, + struct wp_fractional_scale_v2 *wp_fractional_scale_v2, + uint32_t scale_8_24) +{ + _GLFWwindow* window = userData; + + const double oldScale = window->wl.fractionalScaleV2Factor; + const double newScale = scale_8_24 / (double)(1UL << 24); + if (newScale != oldScale) { + window->wl.fractionalScaleV2Factor = newScale; + wp_fractional_scale_v2_set_scale_factor(wp_fractional_scale_v2, scale_8_24); + _glfwInputWindowContentScale(window, newScale, newScale); + // keep the effective size of the window the same + resizeWindow(window, + window->wl.width * newScale / oldScale, + window->wl.height * newScale / oldScale); + } +} + +static const struct wp_fractional_scale_v2_listener scaleListener = +{ + handleScaleFactor +}; + static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable) { if (enable && !window->wl.idleInhibitor && _glfw.wl.idleInhibitManager) @@ -688,7 +718,7 @@ void fractionalScaleHandlePreferredScale(void* userData, { _GLFWwindow* window = userData; - window->wl.scalingNumerator = numerator; + window->wl.fractionalScaleV1Numerator = numerator; _glfwInputWindowContentScale(window, numerator / 120.f, numerator / 120.f); resizeFramebuffer(window); @@ -1187,8 +1217,9 @@ static GLFWbool createNativeSurface(_GLFWwindow* window, window->wl.appId = _glfw_strdup(wndconfig->wl.appId); window->wl.bufferScale = 1; - window->wl.scalingNumerator = 120; + window->wl.fractionalScaleV1Numerator = 120; window->wl.scaleFramebuffer = wndconfig->scaleFramebuffer; + window->wl.fractionalScaleV2Factor = 1; window->wl.maximized = wndconfig->maximized; @@ -1196,7 +1227,12 @@ static GLFWbool createNativeSurface(_GLFWwindow* window, if (!window->wl.transparent) setContentAreaOpaque(window); - if (_glfw.wl.fractionalScaleManager) + if (_glfw.wl.fractionalScaleV2Manager) + { + window->wl.fractionalScaleV2 = wp_fractional_scale_manager_v2_get_fractional_scale(_glfw.wl.fractionalScaleV2Manager, window->wl.surface); + wp_fractional_scale_v2_add_listener(window->wl.fractionalScaleV2, &scaleListener, window); + } + else if (_glfw.wl.fractionalScaleManager) { if (window->wl.scaleFramebuffer) { @@ -1207,12 +1243,12 @@ static GLFWbool createNativeSurface(_GLFWwindow* window, window->wl.width, window->wl.height); - window->wl.fractionalScale = + window->wl.fractionalScaleV1 = wp_fractional_scale_manager_v1_get_fractional_scale( _glfw.wl.fractionalScaleManager, window->wl.surface); - wp_fractional_scale_v1_add_listener(window->wl.fractionalScale, + wp_fractional_scale_v1_add_listener(window->wl.fractionalScaleV1, &fractionalScaleListener, window); } @@ -2231,8 +2267,8 @@ void _glfwDestroyWindowWayland(_GLFWwindow* window) _glfw.wl.keyboardFocus = NULL; } - if (window->wl.fractionalScale) - wp_fractional_scale_v1_destroy(window->wl.fractionalScale); + if (window->wl.fractionalScaleV1) + wp_fractional_scale_v1_destroy(window->wl.fractionalScaleV1); if (window->wl.scalingViewport) wp_viewport_destroy(window->wl.scalingViewport); @@ -2417,12 +2453,18 @@ void _glfwGetWindowFrameSizeWayland(_GLFWwindow* window, void _glfwGetWindowContentScaleWayland(_GLFWwindow* window, float* xscale, float* yscale) { - if (window->wl.fractionalScale) + if (window->wl.fractionalScaleV2) { + if (xscale) + *xscale = window->wl.fractionalScaleV2Factor; + if (yscale) + *yscale = window->wl.fractionalScaleV2Factor; + } + else if (window->wl.fractionalScaleV1) { if (xscale) - *xscale = (float) window->wl.scalingNumerator / 120.f; + *xscale = (float) window->wl.fractionalScaleV1Numerator / 120.f; if (yscale) - *yscale = (float) window->wl.scalingNumerator / 120.f; + *yscale = (float) window->wl.fractionalScaleV1Numerator / 120.f; } else { @@ -2936,13 +2978,13 @@ static void relativePointerHandleRelativeMotion(void* userData, if (window->rawMouseMotion) { - xpos += wl_fixed_to_double(dxUnaccel); - ypos += wl_fixed_to_double(dyUnaccel); + xpos += wl_fixed_to_double(dxUnaccel) / window->wl.fractionalScaleV2Factor; + ypos += wl_fixed_to_double(dyUnaccel) / window->wl.fractionalScaleV2Factor; } else { - xpos += wl_fixed_to_double(dx); - ypos += wl_fixed_to_double(dy); + xpos += wl_fixed_to_double(dx) / window->wl.fractionalScaleV2Factor; + ypos += wl_fixed_to_double(dy) / window->wl.fractionalScaleV2Factor; } _glfwInputCursorPos(window, xpos, ypos);