Skip to content
New issue

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

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

Already on GitHub? # to your account

Fix display scaling on linux #9390

Open
HermanKirshin opened this issue Nov 9, 2022 · 17 comments
Open

Fix display scaling on linux #9390

HermanKirshin opened this issue Nov 9, 2022 · 17 comments

Comments

@HermanKirshin
Copy link
Contributor

HermanKirshin commented Nov 9, 2022

Related to #4826

I have tested how application is displayed in 7 different desktop environments on real hardware with multiple monitors (combination of high-dpi and low-dpi), some of them cover 90% of cases I think. Here are the results:

Default Avalonia behavior:

  • Gnome
    Always rendered in 100%
    incorrect (Scale settings does not affect, looks too small on HiDpi displays)
  • KDE, XFCE, MATE, LXQt, Deepin
    always rendered 200% on HiDpi display and 100% on LowDpi display
    incorrect, displays may be configured to 150% and app will be bigger than expected, and on low dpi smaller than expected.
    on virtual machine always rendered 100% because virtual monitor does not report physical size and HiDpi detection logic fails
  • Cinnamon
    if all monitors set to 100% then rendered 200% on HiDpi monitor and 100% on LoDpi monitor
    incorrect, HiDpi may be configured to 100 or 150 and app will be bigger than expected, and on low dpi smaller than expected.
    Configure HiDpi to 125% and LoDpi to 100% then displayed on HiDpi in 62% and on LoDpi in 50%
    Configure HiDpi to 100% and LoDpi to 200% then displayed on HiDpi in 50% and on LoDpi in 100%
    incorrect, app looks even smaller while all other apps are displayed correctly (unlike XFCE where everything looks weird)

I have looked into X11Screens code, ant it does very strange things.

Conclusion - looks like there is NO linux setups where avalonia apps are scaled correctly, while majority of up-to-date apps are displayed as expected respecting scale factors from system settings.

Missing such fundamental feature is a serious flaw, because most other UI frameworks are capable to do it. If they can, why we cannot? It is possible to get with high probability correct values from system, that will cover majority of cases, here is some prototype:
https://github.com/HermanKirshin/LinuxDisplayScale/blob/main/Program.cs

Currently I use this to setup AVALONIA_SCREEN_SCALE_FACTORS before calling AppBuilder

Also here is some investigation summary about desktop environments https://github.com/HermanKirshin/LinuxDisplayScale/blob/main/linux_scale_info.txt

@kekekeks
Copy link
Member

kekekeks commented Nov 9, 2022

X11 does not support per display scaling. Any values you set in your system settings in your Wayland-powered DE are invisible to X11 apps. Technically nothing prevents DE authors from providing per-display DPI information to X11 apps, but they deliberately choose not to.

Avalonia currently has the same behavior as Qt5 in automatic DPI mode which is DPI detection based on display EDID with an environment variable override. EDID information is incorrect with XWayland.

TL;DR: Wait for a Wayland backend to be ready or switch to pure X11 session

@HermanKirshin
Copy link
Contributor Author

HermanKirshin commented Nov 9, 2022

Wayland support will not fix wrong behavior on all other DE

Screenshot from 2022-11-09 09-06-54

@kekekeks
Copy link
Member

kekekeks commented Nov 9, 2022

You are running a Wayland session. Your Qt app is running with Wayland support.

@timunie
Copy link
Contributor

timunie commented Nov 9, 2022

If you want to try out the Wayland backend, you can find the PR here: #8352

Any feedback about it would be very helpful I think.

@kekekeks should we mark this issue as by-design and move it to Q&A?

@HermanKirshin
Copy link
Contributor Author

HermanKirshin commented Nov 9, 2022

@kekekeks Why do you think that it is Wayland session?

Screenshot 2022-11-09 094548

@timunie Behavior is wrong on both Wayland and x11. In initital post Wayland is present only in Gnome.
And anyway automatically trying to set scaling based only on physical dpi ignoring any system settings is not a good solution. Maybe user wants to have 200% on low-dpi display? And it will not work.
Also it will not work on virtual machines, because they do not report correct physical size.

@timunie
Copy link
Contributor

timunie commented Nov 9, 2022

@HermanKirshin I think you are right 👍

@HermanKirshin
Copy link
Contributor Author

Made some important refactorings in scale factor detection algorithm https://github.com/HermanKirshin/LinuxDisplayScale

@kekekeks
Copy link
Member

After taking a look at heuristics in your repo, I'm not sure we can use those. We might just follow what Qt6 does, which is just reading Xft.dpi from Xresources with an option to enable EDID-based detection via environment variable.

@HermanKirshin
Copy link
Contributor Author

HermanKirshin commented Nov 20, 2022

That would be not perfect but good enough, because
Xft.dpi will respect system settings perfectly on KDE (in any configuration - pure X11, Wayland with X11 scaled by system, Wayland with X11 scaled by themselves) and Cinnamon (both with and without fractional scaling enabled), both in multi-monitor scenarios with different settings. These two environments today have the best scaling support out of the box.

It will work on Gnome+Wayland but unlike KDE will not respect mixed monitor settings
and still will not work in Ubuntu without messing with configs because it does not change Xft.dpi on settings change.

It will not respect system settings on MATE, XFCE, LXQt and some others, but I think they are not frequent choice for HiDpi configurations.

It will work same way both on real and virtual machines.

So I think reading Xft.dpi is way more better approach than current magic with EDID, because unlike EDID it at least works and moreover - it will handle correctly at least half of cases.

@HermanKirshin
Copy link
Contributor Author

And why trying to also read values from libgtk is not an option?

@kekekeks
Copy link
Member

kekekeks commented Nov 20, 2022

Attempting to use GTK from the UI thread will break our native dialogs since they require a separate GTK-powered event loop on a background thread.

@HermanKirshin
Copy link
Contributor Author

But calling it using GtkInteropHelper.RunOnGLibThread with preceding XInitThreads works fine and does not break native dialogs

@Lordfirespeed
Copy link

Any update on this ?

@anyoneyun
Copy link

Any updates?

@kekekeks
Copy link
Member

Avalonia currently reads Xft.dpi value from XRDB, which is the only thing we can do since WM/DE authors simply refuse to provide accurate per-monitor scaling information for X11 apps.

Avalonia also respects QT environment variables (QT_SCREEN_SCALE_FACTOR/QT_AUTO_SCREEN_SCALE_FACTOR) for configuring per-monitor scaling, so if you set such envs in /etc/profile those should work.

@l0b0
Copy link

l0b0 commented Sep 30, 2024

Avalonia currently reads Xft.dpi value from XRDB, which is the only thing we can do since WM/DE authors simply refuse to provide accurate per-monitor scaling information for X11 apps.

Avalonia also respects QT environment variables (QT_SCREEN_SCALE_FACTOR/QT_AUTO_SCREEN_SCALE_FACTOR) for configuring per-monitor scaling, so if you set such envs in /etc/profile those should work.

Is this something which needs to be programmed into each application? I've tried a few things to get Scarab to scale, but none of these seem to work:

  • xrdb -query | rg '^Xft.dpi' reports 192 (2x scaling in GNOME+Wayland), but Scarab is not scaled.
  • QT_SCREEN_SCALE_FACTOR=2 Scarab does not change anything.
  • QT_AUTO_SCREEN_SCALE_FACTOR=1 Scarab does not change anything.

@teohhanhui
Copy link

@l0b0 Have you tried:

XFT_DPI=$(xrdb -get Xft.dpi)
AVALONIA_GLOBAL_SCALE_FACTOR=$(echo "scale=2; $XFT_DPI/96" | bc)
export AVALONIA_GLOBAL_SCALE_FACTOR

l0b0 added a commit to l0b0/nixpkgs that referenced this issue Oct 14, 2024
l0b0 added a commit to l0b0/nixpkgs that referenced this issue Oct 14, 2024
Sets `AVALONIA_GLOBAL_SCALE_FACTOR` to the GNOME desktop scaling factor
based on
<AvaloniaUI/Avalonia#9390 (comment)>.
l0b0 added a commit to l0b0/nixpkgs that referenced this issue Oct 14, 2024
Sets `AVALONIA_GLOBAL_SCALE_FACTOR` to the GNOME desktop scaling factor
based on
<AvaloniaUI/Avalonia#9390 (comment)>,
falling back to the X FreeType DPI setting if the former is not
available.
l0b0 added a commit to l0b0/nixpkgs that referenced this issue Oct 14, 2024
Sets `AVALONIA_GLOBAL_SCALE_FACTOR` to the GNOME desktop scaling factor
based on
<AvaloniaUI/Avalonia#9390 (comment)>,
falling back to the X FreeType DPI setting if the former is not
available.
l0b0 added a commit to l0b0/nixpkgs that referenced this issue Nov 6, 2024
Sets `AVALONIA_GLOBAL_SCALE_FACTOR` to the GNOME desktop scaling factor
based on
<AvaloniaUI/Avalonia#9390 (comment)>,
falling back to the X FreeType DPI setting if the former is not
available.

Does not include `gsettings` and `xrdb` in build inputs, since these
should be available on the relevant platforms.

Bash does not support decimal/floating point arithmetic, so this *does*
include `bc` in the runtime dependencies.
l0b0 added a commit to l0b0/nixpkgs that referenced this issue Nov 10, 2024
Sets `AVALONIA_GLOBAL_SCALE_FACTOR` to the GNOME desktop scaling factor
based on
<AvaloniaUI/Avalonia#9390 (comment)>,
falling back to the X FreeType DPI setting if the former is not
available.

Does not include `gsettings` and `xrdb` in build inputs, since these
should be available on the relevant platforms.

Bash does not support decimal/floating point arithmetic, so this *does*
include `bc` in the runtime dependencies.
l0b0 added a commit to l0b0/nixpkgs that referenced this issue Nov 10, 2024
Sets `AVALONIA_GLOBAL_SCALE_FACTOR` to the GNOME desktop scaling factor
based on
<AvaloniaUI/Avalonia#9390 (comment)>,
falling back to the X FreeType DPI setting if the former is not
available.

Does not include `gsettings` and `xrdb` in build inputs, since these
should be available on the relevant platforms.

Bash does not support decimal/floating point arithmetic, so this *does*
include `bc` in the runtime dependencies.
l0b0 added a commit to l0b0/nixpkgs that referenced this issue Nov 10, 2024
Sets `AVALONIA_GLOBAL_SCALE_FACTOR` to the GNOME desktop scaling factor
based on
<AvaloniaUI/Avalonia#9390 (comment)>,
falling back to the X FreeType DPI setting if the former is not
available.

Does not include `gsettings` and `xrdb` in build inputs, since these
should be available on the relevant platforms.

Bash does not support decimal/floating point arithmetic, so this *does*
include `bc` in the runtime dependencies.
l0b0 added a commit to l0b0/nixpkgs that referenced this issue Nov 10, 2024
Sets `AVALONIA_GLOBAL_SCALE_FACTOR` to the GNOME desktop scaling factor
based on
<AvaloniaUI/Avalonia#9390 (comment)>,
falling back to the X FreeType DPI setting if the former is not
available.

Does not include `gsettings` and `xrdb` in build inputs, since these
should be available on the relevant platforms.

Bash does not support decimal/floating point arithmetic, so this *does*
include `bc` in the runtime dependencies.
# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

No branches or pull requests

8 participants