Skip to content

Commit 9477974

Browse files
committed
[GTK] Use primary monitor for device zoom on multi-monitor setups
Display._getDeviceZoom(long) ignored its monitor argument and always queried the monitor at virtual coordinate (0,0), so every monitor returned by getMonitors() reported the (0,0) monitor's scale factor on X11/Xwayland. Device.getDeviceZoom() did the same on GTK3 for the initial Display zoom. On mixed-DPI multi-monitor setups this caused shells opened on a non-(0,0) monitor to be sized for the wrong scale: e.g. a HiDPI laptop panel sitting at the top-left of the virtual screen made shells on a standard-density secondary monitor render at 2x. Honor the passed monitor handle in _getDeviceZoom and pick the GDK primary monitor for the initial zoom on GTK3, falling back to the (0,0) monitor only when no primary is available (e.g. on Wayland). Fixes #3273
1 parent 81a811a commit 9477974

2 files changed

Lines changed: 24 additions & 6 deletions

File tree

bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Device.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.eclipse.swt.internal.gtk.*;
2424
import org.eclipse.swt.internal.gtk3.*;
2525
import org.eclipse.swt.internal.gtk4.*;
26+
import org.eclipse.swt.widgets.*;
2627

2728
/**
2829
* This class is the abstract superclass of all device objects,
@@ -1107,7 +1108,7 @@ protected int getDeviceZoom() {
11071108
long surface = GTK4.gtk_native_get_surface(GTK4.gtk_widget_get_native(shellHandle));
11081109
monitor = GDK.gdk_display_get_monitor_at_surface(display, surface);
11091110
} else {
1110-
monitor = GDK.gdk_display_get_monitor_at_point(display, 0, 0);
1111+
monitor = Display.getPrimaryMonitor(display);
11111112
}
11121113

11131114
// GDK can return null monitor in some cases thus play safe

bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6256,19 +6256,36 @@ long gdk_device_get_surface_at_position (double[] win_x, double[] win_y) {
62566256
return GDK.gdk_device_get_surface_at_position (device, win_x, win_y);
62576257
}
62586258

6259-
static int _getDeviceZoom (long monitor_num) {
6259+
static int _getDeviceZoom (long monitor) {
62606260
/*
62616261
* We can hard-code 96 as gdk_screen_get_resolution will always return -1
62626262
* if gdk_screen_set_resolution has not been called.
62636263
*/
62646264
int dpi = 96;
6265-
long display = GDK.gdk_display_get_default();
6266-
long monitor = GDK.gdk_display_get_monitor_at_point(display, 0, 0);
6267-
int scale = GDK.gdk_monitor_get_scale_factor(monitor);
6268-
dpi = dpi * scale;
6265+
if (monitor == 0) {
6266+
monitor = getPrimaryMonitor(GDK.gdk_display_get_default());
6267+
}
6268+
if (monitor != 0) {
6269+
int scale = GDK.gdk_monitor_get_scale_factor(monitor);
6270+
dpi = dpi * scale;
6271+
}
62696272
return DPIUtil.mapDPIToZoom (dpi);
62706273
}
62716274

6275+
/**
6276+
* Returns the GDK primary monitor handle, falling back to the monitor at
6277+
* virtual coordinate (0,0) when no primary monitor is reported (e.g. on Wayland).
6278+
*
6279+
* @noreference This method is not intended to be referenced by clients.
6280+
*/
6281+
public static long getPrimaryMonitor(long display) {
6282+
long monitor = GDK.gdk_display_get_primary_monitor(display);
6283+
if (monitor == 0) {
6284+
monitor = GDK.gdk_display_get_monitor_at_point(display, 0, 0);
6285+
}
6286+
return monitor;
6287+
}
6288+
62726289
static boolean isActivateShellOnForceFocus() {
62736290
return "true".equals(System.getProperty("org.eclipse.swt.internal.activateShellOnForceFocus", "true")); //$NON-NLS-1$
62746291
}

0 commit comments

Comments
 (0)