vslavik / winsparkle

App update framework for Windows, inspired by Sparkle for macOS
http://winsparkle.org
Other
1.31k stars 267 forks source link

UI bug when moving an error alert between different-DPI displays #224

Open supersv opened 3 years ago

supersv commented 3 years ago

Steps to reproduce:

  1. Basic WinSparkle setup without a valid DSAPub key (to trigger the error alert).
  2. Check for Updates on a 100% (96 DPI) display - an alert is presented (Screenshot1).
  3. Move the alert to a 125% display - the alert message doesn't enlarge, AND the Cancel button is cut (Screenshot2).
  4. Move the app's main window to the 125% display and Check for Updates again - the alert looks somewhat better (the message is not enlarged, but the button is not cut at least) (Screenshot3).

I'm just starting out with WinSparkle, haven't gotten to its main UI yet, so perhaps this problem is applicable not only to its alerts.

Screenshot1

Screenshot2

Screenshot3

vslavik commented 3 years ago

It's possible this too is due to your application's configuration — did you try to reproduce in the bundled example?

It's also possible updating the bundled wx library would fix it. If not, a patch would be appreciated — this is a rare case within a rare case (multi-display and different-DPI) and hard to reproduce without the equipment you have.

codygray commented 3 years ago

This is not a WinSparkle issue, per se. Modern versions of Windows actually support per-monitor DPI, but for compatibility reasons, applications have to specifically indicate that they can handle this. If they do not indicate this, then Windows will try to scale their client areas automatically...which often results in sub-par results. The way you indicate to Windows that your application is per-monitor DPI aware is by adding an entry to your manifest. See: https://docs.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows

The manifest will indicate that your application's process supports per-monitor DPI. Assuming that WinSparkle runs in the same process as your application (albeit in a separate thread), it will inherit (and thus be subjected to) whatever settings are in your application's manifest. Chances are, your application's manifest is not indicating that your application is per-monitor DPI aware, so Windows is trying to scale WinSparkle's UI automatically instead of letting WinSparkle handle the scaling itself.

This, of course, assumes that WinSparkle is actually per-monitor DPI aware. If it is not, then this needs to be fixed in WinSparkle. In the ideal case, your application and WinSparkle will agree about their per-monitor DPI awareness, and thus you can just configure the process accordingly. If your application and WinSparkle do not agree about their per-monitor DPI awareness, then all is not lost---at least not with Windows 10 Anniversary Update, where you can actually specify DPI awareness per-thread, which means that WinSparkle's thread can use a different DPI awareness setting from your application's main UI thread. See https://docs.microsoft.com/en-us/windows/win32/hidpi/high-dpi-improvements-for-desktop-applications

Note that no special equipment should be required to reproduce. You need a minimum of two monitors (a laptop plus an external screen will work) and a modern version of Windows. Then, simply set one of the monitors to use a different DPI than the other monitor. And, while this seems like an esoteric configuration, it is actually more common than one would think: consider a notebook like a Microsoft Surface that uses a high-DPI display that has a cheap external display connected to it (which is using low DPI).

supersv commented 3 years ago

@codygray The app is fully DPI aware (per-monitor V2 on latest versions of Windows, and degrading gracefully). This is a WinSparkle problem (and/or its UI framework).

supersv commented 3 years ago

P.S. As for testing, Virtual Box with several virtual monitors configured at different DPI is enough. For real-life testing, a Hi-DPI notebook plus a regular (96 DPI) monitor is a pretty common setup.

vslavik commented 3 years ago

This is not a WinSparkle issue, per se.

Honestly, I think it is, as mentioned above - updating wxWidgets to a current version is likely to either fix it or considerably help with any remaining work.

at least not with Windows 10 Anniversary Update, where you can actually specify DPI awareness per-thread, which means that WinSparkle's thread can use a different DPI awareness setting from your application's main UI thread. See https://docs.microsoft.com/en-us/windows/win32/hidpi/high-dpi-improvements-for-desktop-applications

Thanks! It's good to know this option is there as the last resort.