implement support for wp-fractional-scale-v2

This commit is contained in:
Xaver Hugl 2022-11-06 13:30:48 +01:00 committed by Xaver Hugl
parent 8e15281d34
commit 00498c7670
5 changed files with 207 additions and 20 deletions

129
deps/wayland/fractional-scale-v2.xml vendored Normal file
View File

@ -0,0 +1,129 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="fractional_scale_v2">
<copyright>
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.
</copyright>
<description summary="Protocol for fractional scaling">
This protocol allows compositors and clients to communicate the
coordinate space their surfaces act in.
</description>
<interface name="wp_fractional_scale_manager_v2" version="1">
<description summary="creates surface scale interfaces">
A global interface to create wp_fractional_scale_v2 interfaces.
</description>
<request name="destroy" type="destructor">
<description summary="release the global">
Informs the server that the client will not be using this protocol
object anymore. This does not affect any other objects.
</description>
</request>
<enum name="error">
<entry name="fractional_scale_exists" value="0"
summary="wp_fractional_scale_v2 for the surface already exists"/>
</enum>
<request name="get_fractional_scale">
<description summary="create an interface to enable fractional scaling">
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.
</description>
<arg name="id" type="new_id" interface="wp_fractional_scale_v2"
summary="the new scale interface"/>
<arg name="surface" type="object" interface="wl_surface"
summary="the surface"/>
</request>
</interface>
<interface name="wp_fractional_scale_v2" version="1">
<description summary="interface for fractional scaling">
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.
</description>
<event name="scale_factor">
<description summary="set the compositor coordinate space scale factor">
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.
</description>
<arg name="scale_8_24" type="uint" summary="surface scale factor"/>
</event>
<request name="set_scale_factor">
<description summary="set the client coordinate space scale factor">
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.
</description>
<arg name="scale_8_24" type="uint" summary="surface scale factor"/>
</request>
<request name="destroy" type="destructor">
<description summary="remove the scale interface from the surface">
The wl_surface's wp_fractional_scale_v2 object is destroyed, and the
associated scale is reset to 1.
</description>
</request>
<enum name="error">
<entry name="invalid_scale" value="0"
summary="scale value is not valid"/>
</enum>
</interface>
</protocol>

View File

@ -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)

View File

@ -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,

View File

@ -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;

View File

@ -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);