[gtk3/wayland] Fix GdkMonitor sizes on Mutter without fractional scaling.

This is the gtk3 version of !6722.

This fixes a problem that is apparent in
https://bugzilla.mozilla.org/show_bug.cgi?id=1869724, but that also
reproduces on any GTK application as described in
https://bugzilla.mozilla.org/show_bug.cgi?id=1869724#c16.

xdg_output sizes might be physical if the compositor doesn't scale them,
it seems. So to report the correct logical geometry in GDK pixels, we
need to detect this case. We do this by checking whether the wl_output
size matches the xdg_output size.
This commit is contained in:
Emilio Cobos Álvarez
2024-01-08 14:44:57 +01:00
parent 40fe09855b
commit 09373bf7ee
2 changed files with 47 additions and 38 deletions

View File

@ -1552,17 +1552,43 @@ should_expect_xdg_output_done (GdkWaylandMonitor *monitor)
static void
apply_monitor_change (GdkWaylandMonitor *monitor)
{
GDK_NOTE (MISC,
g_message ("monitor %d changed position %d %d, size %d %d",
monitor->id, monitor->output_geometry.x,
monitor->output_geometry.y,
monitor->output_geometry.width,
monitor->output_geometry.height));
GdkDisplay *display = GDK_MONITOR (monitor)->display;
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (gdk_display_get_default_screen (display));
GDK_NOTE (MISC,
g_message ("monitor %d changed position %d %d, size %d %d",
monitor->id,
monitor->x, monitor->y,
monitor->width, monitor->height));
GdkRectangle logical_geometry;
gboolean needs_scaling = FALSE;
gdk_monitor_set_position (GDK_MONITOR (monitor), monitor->x, monitor->y);
gdk_monitor_set_size (GDK_MONITOR (monitor), monitor->width, monitor->height);
if (monitor_has_xdg_output(monitor))
{
logical_geometry = monitor->xdg_output_geometry;
needs_scaling =
logical_geometry.width == monitor->output_geometry.width ||
logical_geometry.height == monitor->output_geometry.height;
}
else
{
logical_geometry = monitor->output_geometry;
needs_scaling = TRUE;
}
if (needs_scaling)
{
int scale = gdk_monitor_get_scale_factor (GDK_MONITOR (monitor));
logical_geometry.y /= scale;
logical_geometry.x /= scale;
logical_geometry.width /= scale;
logical_geometry.height /= scale;
}
gdk_monitor_set_position (GDK_MONITOR (monitor), logical_geometry.x, logical_geometry.y);
gdk_monitor_set_size (GDK_MONITOR (monitor), logical_geometry.width, logical_geometry.height);
gdk_monitor_set_connector (GDK_MONITOR (monitor), monitor->name);
monitor->wl_output_done = FALSE;
monitor->xdg_output_done = FALSE;
@ -1582,8 +1608,9 @@ xdg_output_handle_logical_position (void *data,
GDK_NOTE (MISC,
g_message ("handle logical position xdg-output %d, position %d %d",
monitor->id, x, y));
monitor->x = x;
monitor->y = y;
monitor->xdg_output_geometry.x = x;
monitor->xdg_output_geometry.y = y;
}
static void
@ -1597,8 +1624,9 @@ xdg_output_handle_logical_size (void *data,
GDK_NOTE (MISC,
g_message ("handle logical size xdg-output %d, size %d %d",
monitor->id, width, height));
monitor->width = width;
monitor->height = height;
monitor->xdg_output_geometry.width = width;
monitor->xdg_output_geometry.height = height;
}
static void
@ -1685,8 +1713,8 @@ output_handle_geometry (void *data,
g_message ("handle geometry output %d, position %d %d, phys. size %d %d, subpixel layout %s, manufacturer %s, model %s, transform %s",
monitor->id, x, y, physical_width, physical_height, subpixel_to_string (subpixel), make, model, transform_to_string (transform)));
monitor->x = x;
monitor->y = y;
monitor->output_geometry.x = x;
monitor->output_geometry.y = y;
switch (transform)
{
@ -1731,29 +1759,13 @@ output_handle_scale (void *data,
int32_t scale)
{
GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data;
GdkRectangle previous_geometry;
int previous_scale;
int width;
int height;
GDK_NOTE (MISC,
g_message ("handle scale output %d, scale %d", monitor->id, scale));
gdk_monitor_get_geometry (GDK_MONITOR (monitor), &previous_geometry);
previous_scale = gdk_monitor_get_scale_factor (GDK_MONITOR (monitor));
/* Set the scale from wl_output protocol, regardless of xdg-output support */
gdk_monitor_set_scale_factor (GDK_MONITOR (monitor), scale);
if (monitor_has_xdg_output (monitor))
return;
width = previous_geometry.width * previous_scale;
height = previous_geometry.height * previous_scale;
monitor->width = width / scale;
monitor->height = height / scale;
if (should_update_monitor (monitor))
apply_monitor_change (monitor);
}
@ -1767,7 +1779,6 @@ output_handle_mode (void *data,
int refresh)
{
GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data;
int scale;
GDK_NOTE (MISC,
g_message ("handle mode output %d, size %d %d, rate %d",
@ -1776,9 +1787,8 @@ output_handle_mode (void *data,
if ((flags & WL_OUTPUT_MODE_CURRENT) == 0)
return;
scale = gdk_monitor_get_scale_factor (GDK_MONITOR (monitor));
monitor->width = width / scale;
monitor->height = height / scale;
monitor->output_geometry.width = width;
monitor->output_geometry.height = height;
gdk_monitor_set_refresh_rate (GDK_MONITOR (monitor), refresh);
if (should_update_monitor (monitor) || !monitor_has_xdg_output (monitor))