From efa9297a41fb88b1c34ea3835d16463607e7a9a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Tue, 8 Nov 2022 20:33:29 +0100 Subject: [PATCH] Wayland: Simplify per-window ouput scales tracking This replaces (one case of) manual management of weak links between windows and monitors, both objects with complex life times, with wl_object pointers used as opaque key values. --- src/wl_monitor.c | 13 ++++++----- src/wl_platform.h | 16 ++++++++----- src/wl_window.c | 57 +++++++++++++++++++++++++---------------------- 3 files changed, 48 insertions(+), 38 deletions(-) diff --git a/src/wl_monitor.c b/src/wl_monitor.c index c847eb7e..0b1a3d8d 100644 --- a/src/wl_monitor.c +++ b/src/wl_monitor.c @@ -114,14 +114,15 @@ static void outputHandleScale(void* userData, { struct _GLFWmonitor* monitor = userData; - monitor->wl.scale = factor; + monitor->wl.contentScale = factor; for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next) { - for (int i = 0; i < window->wl.monitorsCount; i++) + for (int i = 0; i < window->wl.scaleCount; i++) { - if (window->wl.monitors[i] == monitor) + if (window->wl.scales[i].output == monitor->wl.output) { + window->wl.scales[i].factor = monitor->wl.contentScale; _glfwUpdateContentScaleWayland(window); break; } @@ -187,7 +188,7 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version) // The actual name of this output will be set in the geometry handler _GLFWmonitor* monitor = _glfwAllocMonitor("", 0, 0); - monitor->wl.scale = 1; + monitor->wl.contentScale = 1; monitor->wl.output = output; monitor->wl.name = name; @@ -218,9 +219,9 @@ void _glfwGetMonitorContentScaleWayland(_GLFWmonitor* monitor, float* xscale, float* yscale) { if (xscale) - *xscale = (float) monitor->wl.scale; + *xscale = (float) monitor->wl.contentScale; if (yscale) - *yscale = (float) monitor->wl.scale; + *yscale = (float) monitor->wl.contentScale; } void _glfwGetMonitorWorkareaWayland(_GLFWmonitor* monitor, diff --git a/src/wl_platform.h b/src/wl_platform.h index 81e6b5d7..24006312 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -225,6 +225,12 @@ typedef struct _GLFWofferWayland GLFWbool text_uri_list; } _GLFWofferWayland; +typedef struct _GLFWscaleWayland +{ + struct wl_output* output; + int factor; +} _GLFWscaleWayland; + // Wayland-specific per-window data // typedef struct _GLFWwindowWayland @@ -266,10 +272,10 @@ typedef struct _GLFWwindowWayland // We need to track the monitors the window spans on to calculate the // optimal scaling factor. - int scale; - _GLFWmonitor** monitors; - int monitorsCount; - int monitorsSize; + int contentScale; + _GLFWscaleWayland* scales; + int scaleCount; + int scaleSize; struct zwp_relative_pointer_v1* relativePointer; struct zwp_locked_pointer_v1* lockedPointer; @@ -428,7 +434,7 @@ typedef struct _GLFWmonitorWayland int x; int y; - int scale; + int contentScale; } _GLFWmonitorWayland; // Wayland-specific per-cursor data diff --git a/src/wl_window.c b/src/wl_window.c index 5b194e89..5d23cda0 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -307,7 +307,7 @@ static void setContentAreaOpaque(_GLFWwindow* window) static void resizeWindow(_GLFWwindow* window) { - int scale = window->wl.scale; + int scale = window->wl.contentScale; int scaledWidth = window->wl.width * scale; int scaledHeight = window->wl.height * scale; @@ -352,13 +352,13 @@ void _glfwUpdateContentScaleWayland(_GLFWwindow* window) // Get the scale factor from the highest scale monitor. int maxScale = 1; - for (int i = 0; i < window->wl.monitorsCount; i++) - maxScale = _glfw_max(window->wl.monitors[i]->wl.scale, maxScale); + for (int i = 0; i < window->wl.scaleCount; i++) + maxScale = _glfw_max(window->wl.scales[i].factor, maxScale); // Only change the framebuffer size if the scale changed. - if (window->wl.scale != maxScale) + if (window->wl.contentScale != maxScale) { - window->wl.scale = maxScale; + window->wl.contentScale = maxScale; wl_surface_set_buffer_scale(window->wl.surface, maxScale); _glfwInputWindowContentScale(window, maxScale, maxScale); resizeWindow(window); @@ -377,16 +377,20 @@ static void surfaceHandleEnter(void* userData, _GLFWwindow* window = userData; _GLFWmonitor* monitor = wl_output_get_user_data(output); + if (!window || !monitor) + return; - if (window->wl.monitorsCount + 1 > window->wl.monitorsSize) + if (window->wl.scaleCount + 1 > window->wl.scaleSize) { - ++window->wl.monitorsSize; - window->wl.monitors = - _glfw_realloc(window->wl.monitors, - window->wl.monitorsSize * sizeof(_GLFWmonitor*)); + window->wl.scaleSize++; + window->wl.scales = + _glfw_realloc(window->wl.scales, + window->wl.scaleSize * sizeof(_GLFWscaleWayland)); } - window->wl.monitors[window->wl.monitorsCount++] = monitor; + window->wl.scaleCount++; + window->wl.scales[window->wl.scaleCount - 1].factor = monitor->wl.contentScale; + window->wl.scales[window->wl.scaleCount - 1].output = output; _glfwUpdateContentScaleWayland(window); } @@ -399,17 +403,16 @@ static void surfaceHandleLeave(void* userData, return; _GLFWwindow* window = userData; - _GLFWmonitor* monitor = wl_output_get_user_data(output); - GLFWbool found = GLFW_FALSE; - for (int i = 0; i < window->wl.monitorsCount - 1; ++i) + for (int i = 0; i < window->wl.scaleCount; i++) { - if (monitor == window->wl.monitors[i]) - found = GLFW_TRUE; - if (found) - window->wl.monitors[i] = window->wl.monitors[i + 1]; + if (window->wl.scales[i].output == output) + { + window->wl.scales[i] = window->wl.scales[window->wl.scaleCount - 1]; + window->wl.scaleCount--; + break; + } } - window->wl.monitors[--window->wl.monitorsCount] = NULL; _glfwUpdateContentScaleWayland(window); } @@ -743,7 +746,7 @@ static GLFWbool createNativeSurface(_GLFWwindow* window, window->wl.width = wndconfig->width; window->wl.height = wndconfig->height; - window->wl.scale = 1; + window->wl.contentScale = 1; window->wl.title = _glfw_strdup(wndconfig->title); window->wl.appId = _glfw_strdup(wndconfig->wl.appId); @@ -770,7 +773,7 @@ static void setCursorImage(_GLFWwindow* window, buffer = cursorWayland->buffer; else { - if (window->wl.scale > 1 && cursorWayland->cursorHiDPI) + if (window->wl.contentScale > 1 && cursorWayland->cursorHiDPI) { wlCursor = cursorWayland->cursorHiDPI; scale = 2; @@ -1126,7 +1129,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.contentScale > 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. @@ -1908,7 +1911,7 @@ void _glfwDestroyWindowWayland(_GLFWwindow* window) _glfw_free(window->wl.title); _glfw_free(window->wl.appId); - _glfw_free(window->wl.monitors); + _glfw_free(window->wl.scales); } void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title) @@ -2038,9 +2041,9 @@ void _glfwGetFramebufferSizeWayland(_GLFWwindow* window, int* width, int* height { _glfwGetWindowSizeWayland(window, width, height); if (width) - *width *= window->wl.scale; + *width *= window->wl.contentScale; if (height) - *height *= window->wl.scale; + *height *= window->wl.contentScale; } void _glfwGetWindowFrameSizeWayland(_GLFWwindow* window, @@ -2064,9 +2067,9 @@ void _glfwGetWindowContentScaleWayland(_GLFWwindow* window, float* xscale, float* yscale) { if (xscale) - *xscale = (float) window->wl.scale; + *xscale = (float) window->wl.contentScale; if (yscale) - *yscale = (float) window->wl.scale; + *yscale = (float) window->wl.contentScale; } void _glfwIconifyWindowWayland(_GLFWwindow* window)