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.
This commit is contained in:
Camilla Löwy 2022-11-08 20:33:29 +01:00
parent 91c837ace5
commit efa9297a41
3 changed files with 48 additions and 38 deletions

View File

@ -114,14 +114,15 @@ static void outputHandleScale(void* userData,
{ {
struct _GLFWmonitor* monitor = userData; struct _GLFWmonitor* monitor = userData;
monitor->wl.scale = factor; monitor->wl.contentScale = factor;
for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next) 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); _glfwUpdateContentScaleWayland(window);
break; 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 // The actual name of this output will be set in the geometry handler
_GLFWmonitor* monitor = _glfwAllocMonitor("", 0, 0); _GLFWmonitor* monitor = _glfwAllocMonitor("", 0, 0);
monitor->wl.scale = 1; monitor->wl.contentScale = 1;
monitor->wl.output = output; monitor->wl.output = output;
monitor->wl.name = name; monitor->wl.name = name;
@ -218,9 +219,9 @@ void _glfwGetMonitorContentScaleWayland(_GLFWmonitor* monitor,
float* xscale, float* yscale) float* xscale, float* yscale)
{ {
if (xscale) if (xscale)
*xscale = (float) monitor->wl.scale; *xscale = (float) monitor->wl.contentScale;
if (yscale) if (yscale)
*yscale = (float) monitor->wl.scale; *yscale = (float) monitor->wl.contentScale;
} }
void _glfwGetMonitorWorkareaWayland(_GLFWmonitor* monitor, void _glfwGetMonitorWorkareaWayland(_GLFWmonitor* monitor,

View File

@ -225,6 +225,12 @@ typedef struct _GLFWofferWayland
GLFWbool text_uri_list; GLFWbool text_uri_list;
} _GLFWofferWayland; } _GLFWofferWayland;
typedef struct _GLFWscaleWayland
{
struct wl_output* output;
int factor;
} _GLFWscaleWayland;
// Wayland-specific per-window data // Wayland-specific per-window data
// //
typedef struct _GLFWwindowWayland typedef struct _GLFWwindowWayland
@ -266,10 +272,10 @@ typedef struct _GLFWwindowWayland
// We need to track the monitors the window spans on to calculate the // We need to track the monitors the window spans on to calculate the
// optimal scaling factor. // optimal scaling factor.
int scale; int contentScale;
_GLFWmonitor** monitors; _GLFWscaleWayland* scales;
int monitorsCount; int scaleCount;
int monitorsSize; int scaleSize;
struct zwp_relative_pointer_v1* relativePointer; struct zwp_relative_pointer_v1* relativePointer;
struct zwp_locked_pointer_v1* lockedPointer; struct zwp_locked_pointer_v1* lockedPointer;
@ -428,7 +434,7 @@ typedef struct _GLFWmonitorWayland
int x; int x;
int y; int y;
int scale; int contentScale;
} _GLFWmonitorWayland; } _GLFWmonitorWayland;
// Wayland-specific per-cursor data // Wayland-specific per-cursor data

View File

@ -307,7 +307,7 @@ static void setContentAreaOpaque(_GLFWwindow* window)
static void resizeWindow(_GLFWwindow* window) static void resizeWindow(_GLFWwindow* window)
{ {
int scale = window->wl.scale; int scale = window->wl.contentScale;
int scaledWidth = window->wl.width * scale; int scaledWidth = window->wl.width * scale;
int scaledHeight = window->wl.height * scale; int scaledHeight = window->wl.height * scale;
@ -352,13 +352,13 @@ void _glfwUpdateContentScaleWayland(_GLFWwindow* window)
// Get the scale factor from the highest scale monitor. // Get the scale factor from the highest scale monitor.
int maxScale = 1; int maxScale = 1;
for (int i = 0; i < window->wl.monitorsCount; i++) for (int i = 0; i < window->wl.scaleCount; i++)
maxScale = _glfw_max(window->wl.monitors[i]->wl.scale, maxScale); maxScale = _glfw_max(window->wl.scales[i].factor, maxScale);
// Only change the framebuffer size if the scale changed. // 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); wl_surface_set_buffer_scale(window->wl.surface, maxScale);
_glfwInputWindowContentScale(window, maxScale, maxScale); _glfwInputWindowContentScale(window, maxScale, maxScale);
resizeWindow(window); resizeWindow(window);
@ -377,16 +377,20 @@ static void surfaceHandleEnter(void* userData,
_GLFWwindow* window = userData; _GLFWwindow* window = userData;
_GLFWmonitor* monitor = wl_output_get_user_data(output); _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.scaleSize++;
window->wl.monitors = window->wl.scales =
_glfw_realloc(window->wl.monitors, _glfw_realloc(window->wl.scales,
window->wl.monitorsSize * sizeof(_GLFWmonitor*)); 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); _glfwUpdateContentScaleWayland(window);
} }
@ -399,17 +403,16 @@ static void surfaceHandleLeave(void* userData,
return; return;
_GLFWwindow* window = userData; _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]) if (window->wl.scales[i].output == output)
found = GLFW_TRUE; {
if (found) window->wl.scales[i] = window->wl.scales[window->wl.scaleCount - 1];
window->wl.monitors[i] = window->wl.monitors[i + 1]; window->wl.scaleCount--;
break;
}
} }
window->wl.monitors[--window->wl.monitorsCount] = NULL;
_glfwUpdateContentScaleWayland(window); _glfwUpdateContentScaleWayland(window);
} }
@ -743,7 +746,7 @@ static GLFWbool createNativeSurface(_GLFWwindow* window,
window->wl.width = wndconfig->width; window->wl.width = wndconfig->width;
window->wl.height = wndconfig->height; window->wl.height = wndconfig->height;
window->wl.scale = 1; window->wl.contentScale = 1;
window->wl.title = _glfw_strdup(wndconfig->title); window->wl.title = _glfw_strdup(wndconfig->title);
window->wl.appId = _glfw_strdup(wndconfig->wl.appId); window->wl.appId = _glfw_strdup(wndconfig->wl.appId);
@ -770,7 +773,7 @@ static void setCursorImage(_GLFWwindow* window,
buffer = cursorWayland->buffer; buffer = cursorWayland->buffer;
else else
{ {
if (window->wl.scale > 1 && cursorWayland->cursorHiDPI) if (window->wl.contentScale > 1 && cursorWayland->cursorHiDPI)
{ {
wlCursor = cursorWayland->cursorHiDPI; wlCursor = cursorWayland->cursorHiDPI;
scale = 2; scale = 2;
@ -1126,7 +1129,7 @@ static void setCursor(_GLFWwindow* window, const char* name)
struct wl_cursor_theme* theme = _glfw.wl.cursorTheme; struct wl_cursor_theme* theme = _glfw.wl.cursorTheme;
int scale = 1; 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 // We only support up to scale=2 for now, since libwayland-cursor
// requires us to load a different theme for each size. // 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.title);
_glfw_free(window->wl.appId); _glfw_free(window->wl.appId);
_glfw_free(window->wl.monitors); _glfw_free(window->wl.scales);
} }
void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title) void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title)
@ -2038,9 +2041,9 @@ void _glfwGetFramebufferSizeWayland(_GLFWwindow* window, int* width, int* height
{ {
_glfwGetWindowSizeWayland(window, width, height); _glfwGetWindowSizeWayland(window, width, height);
if (width) if (width)
*width *= window->wl.scale; *width *= window->wl.contentScale;
if (height) if (height)
*height *= window->wl.scale; *height *= window->wl.contentScale;
} }
void _glfwGetWindowFrameSizeWayland(_GLFWwindow* window, void _glfwGetWindowFrameSizeWayland(_GLFWwindow* window,
@ -2064,9 +2067,9 @@ void _glfwGetWindowContentScaleWayland(_GLFWwindow* window,
float* xscale, float* yscale) float* xscale, float* yscale)
{ {
if (xscale) if (xscale)
*xscale = (float) window->wl.scale; *xscale = (float) window->wl.contentScale;
if (yscale) if (yscale)
*yscale = (float) window->wl.scale; *yscale = (float) window->wl.contentScale;
} }
void _glfwIconifyWindowWayland(_GLFWwindow* window) void _glfwIconifyWindowWayland(_GLFWwindow* window)