mirror of
https://github.com/glfw/glfw.git
synced 2026-09-18 22:55:46 +00:00
Wayland: Add support for fractional scaling
This adds basic support for fractional-scale-v1. Note that this introduces a potential discrepancy between window and monitor content scales.
This commit is contained in:
@@ -101,6 +101,7 @@ if (GLFW_BUILD_WAYLAND)
|
||||
generate_wayland_protocol("idle-inhibit-unstable-v1.xml")
|
||||
generate_wayland_protocol("pointer-constraints-unstable-v1.xml")
|
||||
generate_wayland_protocol("relative-pointer-unstable-v1.xml")
|
||||
generate_wayland_protocol("fractional-scale-v1.xml")
|
||||
generate_wayland_protocol("xdg-activation-v1.xml")
|
||||
generate_wayland_protocol("xdg-decoration-unstable-v1.xml")
|
||||
endif()
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "viewporter-client-protocol.h"
|
||||
#include "relative-pointer-unstable-v1-client-protocol.h"
|
||||
#include "pointer-constraints-unstable-v1-client-protocol.h"
|
||||
#include "fractional-scale-v1-client-protocol.h"
|
||||
#include "xdg-activation-v1-client-protocol.h"
|
||||
#include "idle-inhibit-unstable-v1-client-protocol.h"
|
||||
|
||||
@@ -78,6 +79,10 @@
|
||||
#include "pointer-constraints-unstable-v1-client-protocol-code.h"
|
||||
#undef types
|
||||
|
||||
#define types _glfw_fractional_scale_types
|
||||
#include "fractional-scale-v1-client-protocol-code.h"
|
||||
#undef types
|
||||
|
||||
#define types _glfw_xdg_activation_types
|
||||
#include "xdg-activation-v1-client-protocol-code.h"
|
||||
#undef types
|
||||
@@ -189,6 +194,13 @@ static void registryHandleGlobal(void* userData,
|
||||
&xdg_activation_v1_interface,
|
||||
1);
|
||||
}
|
||||
else if (strcmp(interface, "wp_fractional_scale_manager_v1") == 0)
|
||||
{
|
||||
_glfw.wl.fractionalScaleManager =
|
||||
wl_registry_bind(registry, name,
|
||||
&wp_fractional_scale_manager_v1_interface,
|
||||
1);
|
||||
}
|
||||
}
|
||||
|
||||
static void registryHandleGlobalRemove(void* userData,
|
||||
@@ -969,6 +981,8 @@ void _glfwTerminateWayland(void)
|
||||
zwp_idle_inhibit_manager_v1_destroy(_glfw.wl.idleInhibitManager);
|
||||
if (_glfw.wl.activationManager)
|
||||
xdg_activation_v1_destroy(_glfw.wl.activationManager);
|
||||
if (_glfw.wl.fractionalScaleManager)
|
||||
wp_fractional_scale_manager_v1_destroy(_glfw.wl.fractionalScaleManager);
|
||||
if (_glfw.wl.registry)
|
||||
wl_registry_destroy(_glfw.wl.registry);
|
||||
if (_glfw.wl.display)
|
||||
|
||||
@@ -131,6 +131,8 @@ struct wl_output;
|
||||
#define xdg_wm_base_interface _glfw_xdg_wm_base_interface
|
||||
#define xdg_activation_v1_interface _glfw_xdg_activation_v1_interface
|
||||
#define xdg_activation_token_v1_interface _glfw_xdg_activation_token_v1_interface
|
||||
#define wl_surface_interface _glfw_wl_surface_interface
|
||||
#define wp_fractional_scale_v1_interface _glfw_wp_fractional_scale_v1_interface
|
||||
|
||||
#define GLFW_WAYLAND_WINDOW_STATE _GLFWwindowWayland wl;
|
||||
#define GLFW_WAYLAND_LIBRARY_WINDOW_STATE _GLFWlibraryWayland wl;
|
||||
@@ -395,6 +397,10 @@ typedef struct _GLFWwindowWayland
|
||||
size_t outputScaleCount;
|
||||
size_t outputScaleSize;
|
||||
|
||||
struct wp_viewport* scalingViewport;
|
||||
uint32_t scalingNumerator;
|
||||
struct wp_fractional_scale_v1* fractionalScale;
|
||||
|
||||
struct zwp_relative_pointer_v1* relativePointer;
|
||||
struct zwp_locked_pointer_v1* lockedPointer;
|
||||
struct zwp_confined_pointer_v1* confinedPointer;
|
||||
@@ -431,6 +437,7 @@ typedef struct _GLFWlibraryWayland
|
||||
struct zwp_pointer_constraints_v1* pointerConstraints;
|
||||
struct zwp_idle_inhibit_manager_v1* idleInhibitManager;
|
||||
struct xdg_activation_v1* activationManager;
|
||||
struct wp_fractional_scale_manager_v1* fractionalScaleManager;
|
||||
|
||||
_GLFWofferWayland* offers;
|
||||
unsigned int offerCount;
|
||||
|
||||
+80
-7
@@ -50,6 +50,7 @@
|
||||
#include "pointer-constraints-unstable-v1-client-protocol.h"
|
||||
#include "xdg-activation-v1-client-protocol.h"
|
||||
#include "idle-inhibit-unstable-v1-client-protocol.h"
|
||||
#include "fractional-scale-v1-client-protocol.h"
|
||||
|
||||
#define GLFW_BORDER_SIZE 4
|
||||
#define GLFW_CAPTION_HEIGHT 24
|
||||
@@ -312,8 +313,16 @@ static void setContentAreaOpaque(_GLFWwindow* window)
|
||||
|
||||
static void resizeFramebuffer(_GLFWwindow* window)
|
||||
{
|
||||
window->wl.fbWidth = window->wl.width * window->wl.bufferScale;
|
||||
window->wl.fbHeight = window->wl.height * window->wl.bufferScale;
|
||||
if (window->wl.fractionalScale)
|
||||
{
|
||||
window->wl.fbWidth = (window->wl.width * window->wl.scalingNumerator) / 120;
|
||||
window->wl.fbHeight = (window->wl.height * window->wl.scalingNumerator) / 120;
|
||||
}
|
||||
else
|
||||
{
|
||||
window->wl.fbWidth = window->wl.width * window->wl.bufferScale;
|
||||
window->wl.fbHeight = window->wl.height * window->wl.bufferScale;
|
||||
}
|
||||
|
||||
if (window->wl.egl.window)
|
||||
{
|
||||
@@ -333,6 +342,13 @@ static void resizeWindow(_GLFWwindow* window)
|
||||
{
|
||||
resizeFramebuffer(window);
|
||||
|
||||
if (window->wl.scalingViewport)
|
||||
{
|
||||
wp_viewport_set_destination(window->wl.scalingViewport,
|
||||
window->wl.width,
|
||||
window->wl.height);
|
||||
}
|
||||
|
||||
if (window->wl.fallback.decorations)
|
||||
{
|
||||
wp_viewport_set_destination(window->wl.fallback.top.viewport,
|
||||
@@ -372,6 +388,10 @@ void _glfwUpdateBufferScaleFromOutputsWayland(_GLFWwindow* window)
|
||||
if (!window->wl.scaleFramebuffer)
|
||||
return;
|
||||
|
||||
// When using fractional scaling, the buffer scale should remain at 1
|
||||
if (window->wl.fractionalScale)
|
||||
return;
|
||||
|
||||
// Get the scale factor from the highest scale monitor.
|
||||
int32_t maxScale = 1;
|
||||
|
||||
@@ -505,6 +525,25 @@ static void releaseMonitor(_GLFWwindow* window)
|
||||
}
|
||||
}
|
||||
|
||||
void fractionalScaleHandlePreferredScale(void* userData,
|
||||
struct wp_fractional_scale_v1* fractionalScale,
|
||||
uint32_t numerator)
|
||||
{
|
||||
_GLFWwindow* window = userData;
|
||||
|
||||
window->wl.scalingNumerator = numerator;
|
||||
_glfwInputWindowContentScale(window, numerator / 120.f, numerator / 120.f);
|
||||
resizeFramebuffer(window);
|
||||
|
||||
if (window->wl.visible)
|
||||
_glfwInputWindowDamage(window);
|
||||
}
|
||||
|
||||
const struct wp_fractional_scale_v1_listener fractionalScaleListener =
|
||||
{
|
||||
fractionalScaleHandlePreferredScale,
|
||||
};
|
||||
|
||||
static void xdgToplevelHandleConfigure(void* userData,
|
||||
struct xdg_toplevel* toplevel,
|
||||
int32_t width,
|
||||
@@ -980,9 +1019,11 @@ static GLFWbool createNativeSurface(_GLFWwindow* window,
|
||||
window->wl.height = wndconfig->height;
|
||||
window->wl.fbWidth = wndconfig->width;
|
||||
window->wl.fbHeight = wndconfig->height;
|
||||
window->wl.bufferScale = 1;
|
||||
window->wl.title = _glfw_strdup(wndconfig->title);
|
||||
window->wl.appId = _glfw_strdup(wndconfig->wl.appId);
|
||||
|
||||
window->wl.bufferScale = 1;
|
||||
window->wl.scalingNumerator = 120;
|
||||
window->wl.scaleFramebuffer = wndconfig->scaleFramebuffer;
|
||||
|
||||
window->wl.maximized = wndconfig->maximized;
|
||||
@@ -991,6 +1032,28 @@ static GLFWbool createNativeSurface(_GLFWwindow* window,
|
||||
if (!window->wl.transparent)
|
||||
setContentAreaOpaque(window);
|
||||
|
||||
if (_glfw.wl.fractionalScaleManager)
|
||||
{
|
||||
if (window->wl.scaleFramebuffer)
|
||||
{
|
||||
window->wl.scalingViewport =
|
||||
wp_viewporter_get_viewport(_glfw.wl.viewporter, window->wl.surface);
|
||||
|
||||
wp_viewport_set_destination(window->wl.scalingViewport,
|
||||
window->wl.width,
|
||||
window->wl.height);
|
||||
|
||||
window->wl.fractionalScale =
|
||||
wp_fractional_scale_manager_v1_get_fractional_scale(
|
||||
_glfw.wl.fractionalScaleManager,
|
||||
window->wl.surface);
|
||||
|
||||
wp_fractional_scale_v1_add_listener(window->wl.fractionalScale,
|
||||
&fractionalScaleListener,
|
||||
window);
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
@@ -2315,10 +2378,20 @@ void _glfwGetWindowFrameSizeWayland(_GLFWwindow* window,
|
||||
void _glfwGetWindowContentScaleWayland(_GLFWwindow* window,
|
||||
float* xscale, float* yscale)
|
||||
{
|
||||
if (xscale)
|
||||
*xscale = (float) window->wl.bufferScale;
|
||||
if (yscale)
|
||||
*yscale = (float) window->wl.bufferScale;
|
||||
if (window->wl.fractionalScale)
|
||||
{
|
||||
if (xscale)
|
||||
*xscale = (float) window->wl.scalingNumerator / 120.f;
|
||||
if (yscale)
|
||||
*yscale = (float) window->wl.scalingNumerator / 120.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (xscale)
|
||||
*xscale = (float) window->wl.bufferScale;
|
||||
if (yscale)
|
||||
*yscale = (float) window->wl.bufferScale;
|
||||
}
|
||||
}
|
||||
|
||||
void _glfwIconifyWindowWayland(_GLFWwindow* window)
|
||||
|
||||
Reference in New Issue
Block a user