Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HiDPI scaling on Xwayland outside Gnome broken (for some multi-monitor geometries) #409

Open
oxan opened this issue Jun 28, 2024 · 3 comments
Assignees

Comments

@oxan
Copy link

oxan commented Jun 28, 2024

Environment: PHPStorm 2024.1.4 on JBR 17.0.11 1-b1207.24, amd64, Ubuntu 24.04, KDE 5.27.11.

Situation:

  • Running JBR as an X11 application within Xwayland (i.e. not using the native Wayland support).
  • One external regular display (2560x1440) and one internal hi-DPI display (3840x2400). The (Wayland) scale factor for the internal display is set to 2x, while the external display is unscaled.
  • Xwayland is set to Hi-DPI, e.g. using KDE's "Legacy Applications (X11)" > "Apply scaling themselves" option in Display Configuration. This gives an Xft.dpi of 192. The Xwayland (Xinerama) screen for the external display will have double the native resolution (5120x2880), and will be downscaled by the Wayland compositor.
  • Consider the situation where the external screen is configured to be above the internal screen, with the internal screen centered below it. The geometry in Wayland will be the external screen of 2560x1440 at (0,0) with scale = 1, and the internal screen of 1920x1200 at (320,1440) with scale = 2. In Xwayland, the geometry will be the external screen of 5120x2800 at (0, 0) and the internal screen of 3840x2400 at (640, 2880).

Symptoms:

  • JBR applications will show fine on the internal screen, but be tiny on the external screen.
  • Show HiDPI info on the internal screen will show:
Per-monitor DPI-aware : enabled
Monitor resolution : 1920x1200
Monitor scale : 2.0
User (IDE) scale : 1.0
Xft.DPI : 192
GSettings scale factor : 2.0
GDK_SCALE : undefined
GDK_DPI_SCALE : undefined
  • Show HiDPI info on the external screen will show:
Per-monitor DPI-aware : enabled
Monitor resolution : 5120x2880
Monitor scale : 1.0
User (IDE) scale : 1.0
Xft.DPI : 192
GSettings scale factor : 1.0
GDK_SCALE : undefined
GDK_DPI_SCALE : undefined

Root cause:

  • The "Monitor scale" for the external screen is incorrectly set to 1.0. In this situation, because the compositor downsamples, JBR should render at 2.0 scale. This is also what all other X11 applications do, JBR is the only application I've encountered showing this behaviour.
  • The "Monitor scale" comes from X11GraphicsDevice.getNativeScaleFactor(). This method first checks the waylandMonitorScales array, and uses the value from there if it's not empty. This array is initialized on startup from X11GraphicsEnvironment.updateWaylandMonitorScaling(). It queries both the X server (XWayland) and the Wayland compositor for display information, matches them based on geometry on the Wayland and X side and, if they match, uses the scale factor from Wayland.
  • Bonus: because in this situation the Wayland and X displays have a different geometry, that matching is completely broken, but that actually saves us in certain scenarios where it can't find a match. For example, if the internal screen is put on top of the external screens, the screen positions on the Wayland side are now (0, 1200) and (320, 0) for respectively the external and internal screen, while on the Xwayland side they'll be (0, 2400) and (640, 0). In this case there'll be no match between the geometries for any screens, the Wayland scale factor will be ignored, and everything will work fine.

Solution:

  • To be honest I don't see any reason why JBR would need to take the scale factor of the displays in Wayland into account when running as an X application. Just use the settings from the X environment (i.e. Xft.dpi) and everything should work fine.
  • If that's not possible for whatever reason, the isMonitorFramebufferScalingEnabled() check should be updated to be generic instead of GNOME-specific.

Workaround:

  • Don't let JBR talk to the Wayland compositor, for example by putting a fake libwayland-client.so.0 on the library path:
touch empty.c
gcc -shared -fpic -o libwayland-client.so.0 empty.c
export LD_LIBRARY_PATH=$(pwd)
phpstorm
  • Alternatively, set the Mutter GSettings key that JBR checks for. This only works as long as the Mutter GSettings schema is installed (mutter-common package on Debian/Ubuntu):
gsettings set 'org.gnome.mutter' 'experimental-features' "['scale-monitor-framebuffer']"
@oxan oxan changed the title HiDPI scaling on Xwayland broken for some multi-monitor geometries HiDPI scaling on Xwayland outside Gnome broken (for some multi-monitor geometries) Jun 28, 2024
@nadia-tarashkevich
Copy link

@maciex
Copy link

maciex commented Jul 1, 2024

The workaround in the OPs post worked for me, but the UI is then kind of blurry.

@YaaZ
Copy link
Member

YaaZ commented Jul 22, 2024

The reason for reading Wayland scales in XWayland mode was to enable per-monitor scaling, while stll running on X toolkit, before the Wayland toolkit was ready. Now we got the Wayland toolkit working, so we're going to revert these problematic changes soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants