Add initial draft of high DPI overview
Add a topic covering high DPI support.
This commit is contained in:
@@ -99,5 +99,6 @@ topics related to building applications with wxWidgets.
|
|||||||
@li @subpage overview_windowdeletion
|
@li @subpage overview_windowdeletion
|
||||||
@li @subpage overview_envvars
|
@li @subpage overview_envvars
|
||||||
@li @subpage overview_customwidgets
|
@li @subpage overview_customwidgets
|
||||||
|
@li @subpage overview_high_dpi
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
121
docs/doxygen/overviews/high_dpi.md
Normal file
121
docs/doxygen/overviews/high_dpi.md
Normal file
@@ -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
|
Reference in New Issue
Block a user