diff --git a/docs/doxygen/mainpages/topics.h b/docs/doxygen/mainpages/topics.h index 7a0a6228b5..ceb5b4c6ea 100644 --- a/docs/doxygen/mainpages/topics.h +++ b/docs/doxygen/mainpages/topics.h @@ -99,5 +99,6 @@ topics related to building applications with wxWidgets. @li @subpage overview_windowdeletion @li @subpage overview_envvars @li @subpage overview_customwidgets +@li @subpage overview_high_dpi */ diff --git a/docs/doxygen/overviews/high_dpi.md b/docs/doxygen/overviews/high_dpi.md new file mode 100644 index 0000000000..83daf480f6 --- /dev/null +++ b/docs/doxygen/overviews/high_dpi.md @@ -0,0 +1,121 @@ +High DPI Support in wxWidgets {#overview_high_dpi} +============================= +[TOC] + +[comment]: # (Not sure if the first 2 sections are really worth keeping) + +Terms and Definitions +===================== + +Many modern displays have much higher pixel density than used to be the norm, +resulting in much higher values of DPI (dots, i.e. pixels, per inch) than the +traditionally used values. While the DPI reported by the system is not exactly +the same as the actual pixel density, i.e. it doesn't exactly correspond to the +number of pixels on the screen divided by the screen physical dimension in +inches, it still needs to change to roughly correspond to it. + +This system DPI value is typically expressed using a scaling factor, by which +the baseline DPI value is multiplied. For example, MSW systems may use 125% or +150% scaling, meaning that they use DPI of 120 or 144 respectively, as baseline +DPI value is 96. Similarly, Linux systems may use "2x" scaling, resulting in +DPI value of 192. Macs are slightly different, as even they also may use "2x" +scaling, the effective DPI corresponding to it is 144, as the baseline value on +this platform is 72. + + +The Problem with High DPI Displays +================================== + +If high DPI displays were treated in the same way as normal ones, existing +applications would look tiny of them. For example, a square window 500 pixels +in size would take half of a standard 1920×1080 ("Full HD") display vertically, +but only a quarter on a 3840×2160 ("4K UHD") display. To prevent this from +happening, most platforms automatically scale the windows by the scaling +factor, defined above, when displaying them on high DPI displays. In this +example, scaling factor is 2 and so the actual size of the window on screen +would become 1000 when automatic scaling is in effect. + +Automatic scaling is convenient, but doesn't really allow the application to +use the extra pixels available on the display. Visually, this means that the +scaled application appears blurry, in contrast to sharper applications using +the full display resolution, so a better solution is needed. + + +Pixel Values in High DPI +======================== + +Some systems automatically scale all the coordinates by the DPI scaling factor, +however not all systems supported by wxWidgets do it -- notably, MSW does not. +This means that "logical pixels", in which all coordinates and sizes are +expressed in wxWidgets API, do _not_ have the same meaning on all platforms +when using high DPI displays. To hide this difference from the application, +wxWidgets provides "device-independent pixels", abbreviated as "DIP", that are +always of the same size on all displays and all platforms. + +Thus, the first thing do when preparing your application for high DPI support +is to stop using raw pixel values. Actually, using any pixel values is not +recommended and replacing them with the values based on the text metrics, i.e. +obtained using wxWindow::GetTextExtent(), or expressing them in dialog units +(see wxWindow::ConvertDialogToPixels()) is preferable. However the simplest +change is to just replace the pixel values with the values in DIP: for this, +just use wxWindow::FromDIP() to convert from one to the other. + +For example, if you have the existing code: +```cpp +myFrame->SetClientSize(wxSize(400, 300)); +``` +you can just replace it with +```cpp +myFrame->SetClientSize(myFrame->FromDIP(wxSize(400, 300))); +``` + + +Physical Pixels +=============== + +In addition to (logical) pixels and DIPs discussed above, you may also need to +work in physical pixel coordinates, corresponding to the actual display pixels. +Physical pixels are never scaled, on any platform, and must be used when +drawing graphics elements to ensure that the best possible resolution is used. +For example, all operations on wxGLCanvas use physical pixels. + +To convert between logical and physical pixels, you can use +wxWindow::GetContentScaleFactor(): this is a value greater than or equal to 1, +so a value in logical pixels needs to be multiplied by it in order to obtain +the value in physical pixels. + +For example, in a wxGLCanvas created with the size of 100 (logical) pixels, the +rightmost physical pixel coordinate will be `100*GetContentScaleFactor()`. + + + +Platform-Specific Build Issues +============================== + +Generally speaking, all systems handle applications not specifically marked as +being "DPI-aware" by emulating low-resolution display for them and scaling them +up, resulting in blurry graphics and fonts, but globally preserving the +application appearance. For the best results, the application needs to be +explicitly marked as DPI-aware in a platform-dependent way. + +MSW +--- + +The behaviour of the application when running on a high-DPI display depends on +the values in its [manifest][1]. If your application include `wx/msw/wx.rc` +from its resource file, you need to predefine `wxUSE_DPI_AWARE_MANIFEST` to +opt-in into high DPI support: define it as `1` for minimal DPI awareness and +`2` for full, per-monitor DPI awareness supported by Windows 10 version 1703 or +later. + +[1]: https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests + + +macOS +----- + +DPI-aware applications must set their `NSPrincipalClass` to `wxNSApplication` +(or at least `NSApplication`) in their `Info.plist` file. Also see Apple [high +resolution guidelines][2] for more information. + +[2]: https://developer.apple.com/library/archive/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html