Navigation Menu

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

Fix Screen API on Windows for HiDPI displays #539

Open
skrysmanski opened this issue Jul 20, 2015 · 5 comments
Open

Fix Screen API on Windows for HiDPI displays #539

skrysmanski opened this issue Jul 20, 2015 · 5 comments

Comments

@skrysmanski
Copy link

Currently, the screen api on Windows is pretty crazy.

For example, I have a two screen setup: one hidpi screen (3840 x 2160; primary) and one regular screen (1920 x 1080; secondary) with the following layout:

2015-07-20 22_57_01-screen resolution

However, System.Windows.Forms.Screen (as well as the win32 GetMonitorInfo() function) reports strange values:

2015-07-20 23_02_11-xwt debugging - microsoft visual studio

Note how the secondary screen has a strange height.

Using these values directly make the Xwt demo display the screens like this:

2015-07-20 22_53_23-xwt demo application

My DPI settings (running on Windows 8.1) look like this:

2015-07-20 23_05_19-display

I could find two links that may shed some light on this problem but I haven't yet got enough time to figure them out:

@sevoku
Copy link
Member

sevoku commented Jul 20, 2015

Really strange. I think Windows can't handle the dpi settings correctly, so the smaller screen is scaled in some strange way. I had a bad experience with Windows 8.1 the other way round. I have a normal 1920 screen, but after upgrading to 8.1 Windows switched into some strange HiDPI mode and the screen was not usable. I had to change the DPI setting and disable some checkbox to get the old setting back.

Have you tried to play around with the "Let me choose one scaling level for all my displays" check?

How does the relation between the Screen and the WPF dimensions look like? Is it the same as ScaleFactor? Then everything is ok.

@skrysmanski
Copy link
Author

I forgot to mention that both screen report a scale factor of 2 (i.e. 192 dpi).

So I went ahead and did some more testing. The second link from above was particular helpful. When running this application, the correct DPI value is reported for each monitor (192 for primary, 120 for secondary).

The root problem seems to be that WPF applications by default are only system DPI aware - not monitor-dependent DPI aware (see Comparison of DPI awareness levels).

The app from the second link enables monitor-depedent DPI awareness and thus can report the correct DPI values. (It also does this via GetDpiForMonitor() with MDT_EFFECTIVE_DPI.)

I also figured out how to interpret the screen rect values:

For an application that's only system DPI aware, all screens must have the same DPI value (192 in my case). However, the actual DPI values may differ (192 and 120 in my case). So, if you take this into account you get:

physicalScreenHeight = reportedScreenHeight / (reportedDPI / 96) * (realDPI / 96)

In my example, for the second screen, the backend reported a height of 1728. So, we get:

physicalScreenHeight = 1728 / (192 / 96) * (120 / 96) = 1080

This also works for the position of the screen. In my case, the screens now report as:

  • primary: X:0 Y:0 Width: 3840 Height: 2160 (as before)
  • secondary: X:-1920 Y:1080 Width: 1920 Height:1080

@sevoku
Copy link
Member

sevoku commented Jul 21, 2015

Ok, so the WPF Screen backend has no monitor-depedent DPI awareness, right? How does Gtk or Mac behave here? Are DPI values different for the screens?

@skrysmanski
Copy link
Author

Just check on my MacBook Retina. The reported resolution is the logical resolution - I think.

So, the MacBook's display (15'') has a physical resolution of 2880 x 1800.

I've setup my display to the "More space" setting:

screen shot 2015-07-23 at 12 12 15

At this setting, the screen API reports a resolution of 1920 x 1200.

However, the scale factor is wrongly reported as 2, as it should be 1.5 (if scale factor is interpreted as "physical resolution = reported resolution * scale factor").

I also check the middle option (Default) and the left option (Larger Text). Here are the results:

  • Default: 1440 x 900; scale factor: 2
  • Large Text: 1024 x 640; scale factor: 2 (should be: 2.8125)

So, the scale factor never changes. It's probably just "1 = non-retina" and "2 = retina".

@skrysmanski
Copy link
Author

I've created a C# only example for how to get per-monitor DPI in WPF.

https://github.com/skrysmanski/wpf-per-monitor-dpi-awareness

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

No branches or pull requests

2 participants