mirror of
https://github.com/glfw/glfw.git
synced 2024-11-29 15:44:35 +00:00
implement support for wp-fractional-scale-v1
This commit is contained in:
parent
dd8a678a66
commit
32d7f3a54c
@ -113,6 +113,9 @@ if (GLFW_BUILD_WAYLAND)
|
||||
wayland_generate(
|
||||
"${WAYLAND_PROTOCOLS_BASE}/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml"
|
||||
"${GLFW_BINARY_DIR}/src/wayland-idle-inhibit-unstable-v1-client-protocol")
|
||||
wayland_generate(
|
||||
"${WAYLAND_PROTOCOLS_BASE}/staging/fractional-scale/fractional-scale-v1.xml"
|
||||
"${GLFW_BINARY_DIR}/src/wayland-fractional-scale-v1-client-protocol")
|
||||
endif()
|
||||
|
||||
if (WIN32 AND GLFW_BUILD_SHARED_LIBRARY)
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "wayland-relative-pointer-unstable-v1-client-protocol.h"
|
||||
#include "wayland-pointer-constraints-unstable-v1-client-protocol.h"
|
||||
#include "wayland-idle-inhibit-unstable-v1-client-protocol.h"
|
||||
#include "wayland-fractional-scale-v1-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
|
||||
@ -82,6 +83,10 @@
|
||||
#include "wayland-idle-inhibit-unstable-v1-client-protocol-code.h"
|
||||
#undef types
|
||||
|
||||
#define types _glfw_fractional_scale_types
|
||||
#include "wayland-fractional-scale-v1-client-protocol-code.h"
|
||||
#undef types
|
||||
|
||||
static void wmBaseHandlePing(void* userData,
|
||||
struct xdg_wm_base* wmBase,
|
||||
uint32_t serial)
|
||||
@ -180,6 +185,13 @@ static void registryHandleGlobal(void* userData,
|
||||
&zwp_idle_inhibit_manager_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,
|
||||
|
@ -122,7 +122,7 @@ static void outputHandleScale(void* userData,
|
||||
{
|
||||
if (window->wl.monitors[i] == monitor)
|
||||
{
|
||||
_glfwUpdateContentScaleWayland(window);
|
||||
_glfwUpdateIntegerContentScaleWayland(window);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -212,6 +212,7 @@ typedef struct _GLFWdecorationWayland
|
||||
struct wl_surface* surface;
|
||||
struct wl_subsurface* subsurface;
|
||||
struct wp_viewport* viewport;
|
||||
struct wp_fractional_scale_v1* fractionalScale;
|
||||
} _GLFWdecorationWayland;
|
||||
|
||||
typedef struct _GLFWofferWayland
|
||||
@ -262,7 +263,7 @@ typedef struct _GLFWwindowWayland
|
||||
|
||||
// We need to track the monitors the window spans on to calculate the
|
||||
// optimal scaling factor.
|
||||
int scale;
|
||||
int integerScale;
|
||||
_GLFWmonitor** monitors;
|
||||
int monitorsCount;
|
||||
int monitorsSize;
|
||||
@ -278,6 +279,9 @@ typedef struct _GLFWwindowWayland
|
||||
_GLFWdecorationWayland top, left, right, bottom;
|
||||
_GLFWdecorationSideWayland focus;
|
||||
} decorations;
|
||||
|
||||
double fractionalScale;
|
||||
struct wp_fractional_scale_v1* fractionalScaling;
|
||||
} _GLFWwindowWayland;
|
||||
|
||||
// Wayland-specific global data
|
||||
@ -300,6 +304,7 @@ typedef struct _GLFWlibraryWayland
|
||||
struct zwp_relative_pointer_manager_v1* relativePointerManager;
|
||||
struct zwp_pointer_constraints_v1* pointerConstraints;
|
||||
struct zwp_idle_inhibit_manager_v1* idleInhibitManager;
|
||||
struct wp_fractional_scale_manager_v1* fractionalScaleManager;
|
||||
|
||||
_GLFWofferWayland* offers;
|
||||
unsigned int offerCount;
|
||||
@ -514,7 +519,7 @@ GLFWbool _glfwGetGammaRampWayland(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
|
||||
void _glfwSetGammaRampWayland(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
|
||||
|
||||
void _glfwAddOutputWayland(uint32_t name, uint32_t version);
|
||||
void _glfwUpdateContentScaleWayland(_GLFWwindow* window);
|
||||
void _glfwUpdateIntegerContentScaleWayland(_GLFWwindow* window);
|
||||
|
||||
void _glfwAddSeatListenerWayland(struct wl_seat* seat);
|
||||
void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device);
|
||||
|
114
src/wl_window.c
114
src/wl_window.c
@ -50,6 +50,7 @@
|
||||
#include "wayland-relative-pointer-unstable-v1-client-protocol.h"
|
||||
#include "wayland-pointer-constraints-unstable-v1-client-protocol.h"
|
||||
#include "wayland-idle-inhibit-unstable-v1-client-protocol.h"
|
||||
#include "wayland-fractional-scale-v1-client-protocol.h"
|
||||
|
||||
#define GLFW_BORDER_SIZE 4
|
||||
#define GLFW_CAPTION_HEIGHT 24
|
||||
@ -192,7 +193,8 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void createFallbackDecoration(_GLFWdecorationWayland* decoration,
|
||||
static void createFallbackDecoration(_GLFWwindow *window,
|
||||
_GLFWdecorationWayland* decoration,
|
||||
struct wl_surface* parent,
|
||||
struct wl_buffer* buffer,
|
||||
int x, int y,
|
||||
@ -203,6 +205,11 @@ static void createFallbackDecoration(_GLFWdecorationWayland* decoration,
|
||||
wl_subcompositor_get_subsurface(_glfw.wl.subcompositor,
|
||||
decoration->surface, parent);
|
||||
wl_subsurface_set_position(decoration->subsurface, x, y);
|
||||
if (_glfw.wl.fractionalScaleManager)
|
||||
{
|
||||
decoration->fractionalScale = wp_fractional_scale_manager_v1_get_fractional_scale(_glfw.wl.fractionalScaleManager, decoration->surface);
|
||||
wp_fractional_scale_v1_set_scale_factor(decoration->fractionalScale, (uint32_t)(window->wl.fractionalScale * (double)(1UL << 24)));
|
||||
}
|
||||
decoration->viewport = wp_viewporter_get_viewport(_glfw.wl.viewporter,
|
||||
decoration->surface);
|
||||
wp_viewport_set_destination(decoration->viewport, width, height);
|
||||
@ -228,19 +235,19 @@ static void createFallbackDecorations(_GLFWwindow* window)
|
||||
if (!window->wl.decorations.buffer)
|
||||
return;
|
||||
|
||||
createFallbackDecoration(&window->wl.decorations.top, window->wl.surface,
|
||||
createFallbackDecoration(window, &window->wl.decorations.top, window->wl.surface,
|
||||
window->wl.decorations.buffer,
|
||||
0, -GLFW_CAPTION_HEIGHT,
|
||||
window->wl.width, GLFW_CAPTION_HEIGHT);
|
||||
createFallbackDecoration(&window->wl.decorations.left, window->wl.surface,
|
||||
createFallbackDecoration(window, &window->wl.decorations.left, window->wl.surface,
|
||||
window->wl.decorations.buffer,
|
||||
-GLFW_BORDER_SIZE, -GLFW_CAPTION_HEIGHT,
|
||||
GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT);
|
||||
createFallbackDecoration(&window->wl.decorations.right, window->wl.surface,
|
||||
createFallbackDecoration(window, &window->wl.decorations.right, window->wl.surface,
|
||||
window->wl.decorations.buffer,
|
||||
window->wl.width, -GLFW_CAPTION_HEIGHT,
|
||||
GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT);
|
||||
createFallbackDecoration(&window->wl.decorations.bottom, window->wl.surface,
|
||||
createFallbackDecoration(window, &window->wl.decorations.bottom, window->wl.surface,
|
||||
window->wl.decorations.buffer,
|
||||
-GLFW_BORDER_SIZE, window->wl.height,
|
||||
window->wl.width + GLFW_BORDER_SIZE * 2, GLFW_BORDER_SIZE);
|
||||
@ -306,9 +313,9 @@ static void setContentAreaOpaque(_GLFWwindow* window)
|
||||
|
||||
static void resizeWindow(_GLFWwindow* window)
|
||||
{
|
||||
int scale = window->wl.scale;
|
||||
int scaledWidth = window->wl.width * scale;
|
||||
int scaledHeight = window->wl.height * scale;
|
||||
int integerScale = window->wl.integerScale;
|
||||
int scaledWidth = window->wl.width * integerScale;
|
||||
int scaledHeight = window->wl.height * integerScale;
|
||||
|
||||
if (window->wl.egl.window)
|
||||
wl_egl_window_resize(window->wl.egl.window, scaledWidth, scaledHeight, 0, 0);
|
||||
@ -319,30 +326,44 @@ static void resizeWindow(_GLFWwindow* window)
|
||||
if (!window->wl.decorations.top.surface)
|
||||
return;
|
||||
|
||||
const uint32_t scale_8_24 = (uint32_t)(window->wl.fractionalScale * (double)(1UL << 24));
|
||||
|
||||
wl_subsurface_set_position(window->wl.decorations.top.subsurface,
|
||||
0, -GLFW_CAPTION_HEIGHT);
|
||||
if (window->wl.decorations.top.fractionalScale)
|
||||
wp_fractional_scale_v1_set_scale_factor(window->wl.decorations.top.fractionalScale, scale_8_24);
|
||||
wp_viewport_set_destination(window->wl.decorations.top.viewport,
|
||||
window->wl.width, GLFW_CAPTION_HEIGHT);
|
||||
wl_surface_commit(window->wl.decorations.top.surface);
|
||||
|
||||
wl_subsurface_set_position(window->wl.decorations.left.subsurface,
|
||||
-GLFW_BORDER_SIZE, -GLFW_CAPTION_HEIGHT);
|
||||
if (window->wl.decorations.left.fractionalScale)
|
||||
wp_fractional_scale_v1_set_scale_factor(window->wl.decorations.left.fractionalScale, scale_8_24);
|
||||
wp_viewport_set_destination(window->wl.decorations.left.viewport,
|
||||
GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT);
|
||||
wl_surface_commit(window->wl.decorations.left.surface);
|
||||
|
||||
wl_subsurface_set_position(window->wl.decorations.right.subsurface,
|
||||
window->wl.width, -GLFW_CAPTION_HEIGHT);
|
||||
if (window->wl.decorations.right.fractionalScale)
|
||||
wp_fractional_scale_v1_set_scale_factor(window->wl.decorations.right.fractionalScale, scale_8_24);
|
||||
wp_viewport_set_destination(window->wl.decorations.right.viewport,
|
||||
GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT);
|
||||
wl_surface_commit(window->wl.decorations.right.surface);
|
||||
|
||||
wl_subsurface_set_position(window->wl.decorations.bottom.subsurface,
|
||||
-GLFW_BORDER_SIZE, window->wl.height);
|
||||
if (window->wl.decorations.bottom.fractionalScale)
|
||||
wp_fractional_scale_v1_set_scale_factor(window->wl.decorations.bottom.fractionalScale, scale_8_24);
|
||||
wp_viewport_set_destination(window->wl.decorations.bottom.viewport,
|
||||
window->wl.width + GLFW_BORDER_SIZE * 2, GLFW_BORDER_SIZE);
|
||||
wl_surface_commit(window->wl.decorations.bottom.surface);
|
||||
}
|
||||
|
||||
void _glfwUpdateContentScaleWayland(_GLFWwindow* window)
|
||||
void _glfwUpdateIntegerContentScaleWayland(_GLFWwindow* window)
|
||||
{
|
||||
if (_glfw.wl.compositorVersion < WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION)
|
||||
if (_glfw.wl.compositorVersion < WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION || window->wl.fractionalScaling)
|
||||
return;
|
||||
|
||||
// Get the scale factor from the highest scale monitor.
|
||||
@ -352,9 +373,9 @@ void _glfwUpdateContentScaleWayland(_GLFWwindow* window)
|
||||
maxScale = _glfw_max(window->wl.monitors[i]->wl.scale, maxScale);
|
||||
|
||||
// Only change the framebuffer size if the scale changed.
|
||||
if (window->wl.scale != maxScale)
|
||||
if (window->wl.integerScale != maxScale)
|
||||
{
|
||||
window->wl.scale = maxScale;
|
||||
window->wl.integerScale = maxScale;
|
||||
wl_surface_set_buffer_scale(window->wl.surface, maxScale);
|
||||
_glfwInputWindowContentScale(window, maxScale, maxScale);
|
||||
resizeWindow(window);
|
||||
@ -378,7 +399,7 @@ static void surfaceHandleEnter(void* userData,
|
||||
|
||||
window->wl.monitors[window->wl.monitorsCount++] = monitor;
|
||||
|
||||
_glfwUpdateContentScaleWayland(window);
|
||||
_glfwUpdateIntegerContentScaleWayland(window);
|
||||
}
|
||||
|
||||
static void surfaceHandleLeave(void* userData,
|
||||
@ -398,7 +419,7 @@ static void surfaceHandleLeave(void* userData,
|
||||
}
|
||||
window->wl.monitors[--window->wl.monitorsCount] = NULL;
|
||||
|
||||
_glfwUpdateContentScaleWayland(window);
|
||||
_glfwUpdateIntegerContentScaleWayland(window);
|
||||
}
|
||||
|
||||
static const struct wl_surface_listener surfaceListener =
|
||||
@ -407,6 +428,31 @@ static const struct wl_surface_listener surfaceListener =
|
||||
surfaceHandleLeave
|
||||
};
|
||||
|
||||
|
||||
void handleScaleFactor(void *userData,
|
||||
struct wp_fractional_scale_v1 *wp_fractional_scale_v1,
|
||||
uint32_t scale_8_24)
|
||||
{
|
||||
_GLFWwindow* window = userData;
|
||||
|
||||
const double oldScale = window->wl.fractionalScale;
|
||||
const double newScale = scale_8_24 / (double)(1UL << 24);
|
||||
if (newScale != oldScale) {
|
||||
window->wl.fractionalScale = newScale;
|
||||
wp_fractional_scale_v1_set_scale_factor(wp_fractional_scale_v1, scale_8_24);
|
||||
_glfwInputWindowContentScale(window, newScale, newScale);
|
||||
// keep the effective size of the window the same
|
||||
window->wl.width = round(window->wl.width * newScale / oldScale);
|
||||
window->wl.height = round(window->wl.height * newScale / oldScale);
|
||||
resizeWindow(window);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct wp_fractional_scale_v1_listener scaleListener =
|
||||
{
|
||||
handleScaleFactor
|
||||
};
|
||||
|
||||
static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable)
|
||||
{
|
||||
if (enable && !window->wl.idleInhibitor && _glfw.wl.idleInhibitManager)
|
||||
@ -731,16 +777,24 @@ static GLFWbool createNativeSurface(_GLFWwindow* window,
|
||||
|
||||
window->wl.width = wndconfig->width;
|
||||
window->wl.height = wndconfig->height;
|
||||
window->wl.scale = 1;
|
||||
window->wl.integerScale = 1;
|
||||
window->wl.title = _glfw_strdup(wndconfig->title);
|
||||
window->wl.appId = _glfw_strdup(wndconfig->wl.appId);
|
||||
|
||||
window->wl.fractionalScale = 1;
|
||||
|
||||
window->wl.maximized = wndconfig->maximized;
|
||||
|
||||
window->wl.transparent = fbconfig->transparent;
|
||||
if (!window->wl.transparent)
|
||||
setContentAreaOpaque(window);
|
||||
|
||||
if (_glfw.wl.fractionalScaleManager)
|
||||
{
|
||||
window->wl.fractionalScaling = wp_fractional_scale_manager_v1_get_fractional_scale(_glfw.wl.fractionalScaleManager, window->wl.surface);
|
||||
wp_fractional_scale_v1_add_listener(window->wl.fractionalScaling, &scaleListener, window);
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
@ -758,7 +812,7 @@ static void setCursorImage(_GLFWwindow* window,
|
||||
buffer = cursorWayland->buffer;
|
||||
else
|
||||
{
|
||||
if (window->wl.scale > 1 && cursorWayland->cursorHiDPI)
|
||||
if (window->wl.integerScale > 1 && cursorWayland->cursorHiDPI)
|
||||
{
|
||||
wlCursor = cursorWayland->cursorHiDPI;
|
||||
scale = 2;
|
||||
@ -1106,7 +1160,7 @@ static void setCursor(_GLFWwindow* window, const char* name)
|
||||
struct wl_cursor_theme* theme = _glfw.wl.cursorTheme;
|
||||
int scale = 1;
|
||||
|
||||
if (window->wl.scale > 1 && _glfw.wl.cursorThemeHiDPI)
|
||||
if (window->wl.integerScale > 1 && _glfw.wl.cursorThemeHiDPI)
|
||||
{
|
||||
// We only support up to scale=2 for now, since libwayland-cursor
|
||||
// requires us to load a different theme for each size.
|
||||
@ -1995,10 +2049,13 @@ void _glfwSetWindowAspectRatioWayland(_GLFWwindow* window, int numer, int denom)
|
||||
void _glfwGetFramebufferSizeWayland(_GLFWwindow* window, int* width, int* height)
|
||||
{
|
||||
_glfwGetWindowSizeWayland(window, width, height);
|
||||
if (!window->wl.fractionalScaling)
|
||||
{
|
||||
if (width)
|
||||
*width *= window->wl.scale;
|
||||
*width *= window->wl.integerScale;
|
||||
if (height)
|
||||
*height *= window->wl.scale;
|
||||
*height *= window->wl.integerScale;
|
||||
}
|
||||
}
|
||||
|
||||
void _glfwGetWindowFrameSizeWayland(_GLFWwindow* window,
|
||||
@ -2021,10 +2078,17 @@ void _glfwGetWindowFrameSizeWayland(_GLFWwindow* window,
|
||||
void _glfwGetWindowContentScaleWayland(_GLFWwindow* window,
|
||||
float* xscale, float* yscale)
|
||||
{
|
||||
if (window->wl.fractionalScaling) {
|
||||
if (xscale)
|
||||
*xscale = (float) window->wl.scale;
|
||||
*xscale = window->wl.fractionalScale;
|
||||
if (yscale)
|
||||
*yscale = (float) window->wl.scale;
|
||||
*yscale = window->wl.fractionalScale;
|
||||
} else {
|
||||
if (xscale)
|
||||
*xscale = (float) window->wl.integerScale;
|
||||
if (yscale)
|
||||
*yscale = (float) window->wl.integerScale;
|
||||
}
|
||||
}
|
||||
|
||||
void _glfwIconifyWindowWayland(_GLFWwindow* window)
|
||||
@ -2467,13 +2531,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.fractionalScale;
|
||||
ypos += wl_fixed_to_double(dyUnaccel) / window->wl.fractionalScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
xpos += wl_fixed_to_double(dx);
|
||||
ypos += wl_fixed_to_double(dy);
|
||||
xpos += wl_fixed_to_double(dx) / window->wl.fractionalScale;
|
||||
ypos += wl_fixed_to_double(dy) / window->wl.fractionalScale;
|
||||
}
|
||||
|
||||
_glfwInputCursorPos(window, xpos, ypos);
|
||||
|
Loading…
Reference in New Issue
Block a user