Summary: | Support High-DPI across Platforms and Modules | ||
---|---|---|---|
Product: | [JogAmp] General | Reporter: | Sven Gothel <sgothel> |
Component: | generic | Assignee: | Sven Gothel <sgothel> |
Status: | VERIFIED FIXED | ||
Severity: | major | ||
Priority: | P4 | ||
Version: | 2.5.0 | ||
Hardware: | All | ||
OS: | all | ||
Type: | FEATURE | SCM Refs: |
cfc35549810d3a0fb5eeb866c9450417e48cd8a1
43dc472c4797f34e4079028a5eb04bc420c11c2a
1d4c077b29a69fd13526dfd25d00ee87c0d5b3fe
ab6d84721e2a15550289e14b751e06701bd68726
6eb13066996e94b2fe40bf64e74ea43d8f4e9171
97b79ad351e48e7d3c6f9c95bacdf4f9d5d158ef
7982cc52344c025c40da45fd4b946056a63bc855
309cd9fb55d57739f08147840165910f59c4b432
cfe56e9e6bda15873fefce6f03d343ccdfc51f9b
9d1e7c9adca97780a5b45b135c5693cffee218fc
fd575243e2c8754bc4580526de05462761c320ab
e01bfdc83c70ca63d52dee086a5c8584d7662252
80ccc1f98f0c1391acc6d27de82eac97ca1c27b9
900c35c6a49e0d53e38dd07da709bf81e28abd3e
|
Workaround: | --- | ||
Bug Depends on: | 741, 1120, 1130, 1322, 1351, 1358, 1374, 1421, 1422 | ||
Bug Blocks: |
Description
Sven Gothel
2019-04-04 21:00:49 CEST
It shall be noted that the overall High-DPI problem only exists due to applications using fixed dimensions in pixel-space instead of using normalized vectors, millimeters and actual DPI. With the availability of high resolution monitors beyond the historical ~80 dpi capability, High-DPI screens of 160 dpi and higher became available. Hence pixel sized artifacts and whole windows were 'shrunk' when based on ~80 dpi screens by: 160/80 on both dimensions. Meaning the content was cut to quarter size roughly in total. Hence Apple introduced their 'pixelScale' to their OSX with the advent of their first High-DPI screen Retina. They simply set 'pixelScale' to 2 to multiply the window dimensions and even created a mode to scale the pixel framebuffer content to the actual double sized framebuffer target. The latter soothed the GPU requirements as their performance was lagging the boosted DPI. GPU's would need to cover 4x more pixels. Today this should not matter really anymore and users are advised to use a 'good' screen layout based on the monitor size and DPI. The content should be rendered at native full resolution of course, which also helps with natural anti-aliasing. However, many OS and toolkit API's are using a fixed 90 DPI pixel based layout optionally or by default. Hence our NativeWindow specification uses 'window units': /** * Returns the width of the client area excluding insets (window decorations) in window units. * @return width of the client area in window units * @see NativeSurface#getSurfaceWidth() */ public int getWidth(); and our NativeSurface is using actual 'pixel units' /** * Returns the width of the client area excluding insets (window decorations) in pixel units. * @return width of the client area in pixel units * @see NativeWindow#getWidth() * @see #convertToWindowUnits(int[]) */ public int getSurfaceWidth(); +++ OSX uses a monitor related 'float[2] pixelScale', which we have adopted in bug 1120 and OSX High-DPI fix in bug 741. Our groundwork for High-DPI support indeed has been done for bug 741. +++ See also: AWT Java 9+ related: 'JEP 263: HiDPI Graphics on Windows and Linux' https://bugs.openjdk.java.net/browse/JDK-8055212 We have added support for Windows and X11, reading the respective UI 'soft' scale factor of the respective OS setting as explained in Bug 1374 Comment 7. Remaining task would be the following, noted in Bug 1374 Comment 12: +++ Requirement of mapping window-units <-> pixel-units taking the monitor viewport layout into account. X11/Windows: A simple scaling of the window-units position is not suitable due to multiple monitors, i.e. a window-units gap will be created and fullscreen/spanning coordinates will be wrong. TODO: Implement seamless conversion of units incl. monitor viewport mapping - X11, Windows: Recalculate monitor window-units viewport (native is pixels) - MacOS Recalculate monitor pixel-units viewport (native is 'points', aka window-units) Impact will be to have the ability to use either pixel- or window-units for positioning and size and hence be fully platform independent. NEWT Soft-PixelScale (Windows and X11) p1 - p6 - cfc35549810d3a0fb5eeb866c9450417e48cd8a1 - 43dc472c4797f34e4079028a5eb04bc420c11c2a - 1d4c077b29a69fd13526dfd25d00ee87c0d5b3fe - ab6d84721e2a15550289e14b751e06701bd68726 - 6eb13066996e94b2fe40bf64e74ea43d8f4e9171 - 97b79ad351e48e7d3c6f9c95bacdf4f9d5d158ef +++ commit cfc35549810d3a0fb5eeb866c9450417e48cd8a1 NEWT Soft-PixelScale (p1): WindowImpl: Separate window and pixel units for size and position via atomic-replacable int arrays NEWT's Soft-PixelScale supports software pixel-scale by multiplying the underlying surface pixel-size with the scale-factor and dividing the window position and size by same scale-factor. Hence the window position and size space is kept virtually steady at virtually assumed DPI 96 at higher actual screen DPI and the surface size is adjusted. +++ This window- and pixel-unit separation also includes all callbacks for the native driver implementations, hence the changes native code - allowing to determine whether window- or pixel-units were given. +++ commit 43dc472c4797f34e4079028a5eb04bc420c11c2a NEWT Soft-PixelScale (p2): MonitorDevice: Add getOrientationTo(..) to determine the orientation of this monitor to the other incl. the 'move_diff' move_diff int[2] to store the move delta for each axis from this-monitor to the other This will be utilized when a NEWT window moved across monitors to signal the move_diff, which helps to properly adjust the new position. Tested: All 4 monitor crossings right_of, left_of, above and below. TODO: Test and support a 'diagonal' move, i.e. move_diff on both axis. +++ commit 97b79ad351e48e7d3c6f9c95bacdf4f9d5d158ef NEWT Soft-PixelScale (p6): Implement Soft-PixelScale for X11 and Windows ... (working state) Both: - Using Soft-PixelScale mode, i.e. converting all given window-units to pixel-units for native GDI/X11 ops - Using scaled pixel-sized surface - Adjusting NEWT's Monitor's window-unit viewport value to pixel-scale For X11: - Using global scale factor from environment variable, either: "GDK_SCALE", "QT_SCALE_FACTOR" or "SOFT_SCALE". The latter is for testing only. See https://wiki.archlinux.org/title/HiDPI For Windows: - Using actual monitor's pixel-scale via native SHC API (Shellscaling API, shcore.dll) Misc: - SurfaceScaleUtils.getGlobalPixelScaleEnv() reads a float value from given env names, first come, first serve - MonitorModeProps.streamInMonitorDevice(..): Add `invscale_wuviewport` argument to scale wuvieport for soft-pixel-scale - TestGearsNEWT: Enhance GL2 demo to be suitable for manual tests, this since my Windows KVM machine doesn't support ES2 - TestGLContextDrawableSwitch10NEWT: Add a few more test constraints .. working Tested: - Manually on a Windows virtual machine (KVM) using - 2 virtualized 'Video QXL' cards and - and 'remote-viewer' to see the 2 monitors since `Virtual Machine Manager` build-in doesn't support - remote-viewer spice://localhost:5917 - Manually on a Linux machine w/ SOFT_SCALE - Both, X11 and Windows - Place window on each monitor - Move window across monitors w/ pixel-scale change (or not) - TODO: Test and fix utilization with AWT, i.e. NewtCanvasAWT commit 7982cc52344c025c40da45fd4b946056a63bc855 (tag: v2.4.0, soft_scale_2) NEWT Soft-PixelScale (p7): get{Global->}PixelScaleEnv(..): Support per monitor values w/ QT_SCREEN_SCALE_FACTORS syntax, use for X11 Per-monitor values are parsed if value is not a float and stored in a given Map<String,float[2]>, parallel to a detected global_pixel_scale_xy. The per-monitor value syntax matches QT_SCREEN_SCALE_FACTORS, i.e. the regular expression '(<string>=<float>;)+', e.g. QT_SCREEN_SCALE_FACTORS='DP-1=1.25;DP-2=1.25;HDMI-1=1.25;' The per-monitor value is preferred and on X11 stored within the MonitorDevice, matching the MonitorDevice's name. The following env-var names are searched on X11: "QT_SCREEN_SCALE_FACTORS", "QT_SCALE_FACTOR", "GDK_SCALE", "SOFT_SCALE" commit 309cd9fb55d57739f08147840165910f59c4b432 HiDPI: TestGearsES2NEWT: Show MonitorDevice properties, validating pixelScale commit cfe56e9e6bda15873fefce6f03d343ccdfc51f9b HiDPI: NEWT/MacOS: WindowDriver.sizeScreenPosInsetsChanged() is called w/ client-area in windowUnits (*fix regression*) commit 9d1e7c9adca97780a5b45b135c5693cffee218fc HiDPI AWT/NEWT: Propagate AWT enforced pixelScale via setSurfaceScale() blocking native change by monitor-pixelScale (Windows, X11) commit fd575243e2c8754bc4580526de05462761c320ab SurfaceScaleUtils: Remove unused isZero(..) commit e01bfdc83c70ca63d52dee086a5c8584d7662252 HiDPI: Revert WindowImpl.applySoftPixelScale()'s if( DEBUG...) { ..; dumpStack(); } commit 80ccc1f98f0c1391acc6d27de82eac97ca1c27b9 HiDPI: Complete testing on Windows (AWT, NEWT, AWT+NEWT): AWT pixel scale propagated properly to our AWT GLCanvas and NEWT +++ commit 900c35c6a49e0d53e38dd07da709bf81e28abd3e HiDPI: Revise AWT GLCanvas/GLJPanel ScalableSurface: No setSurfaceScale(), have AWT toolkit define pixelScale only (simplification) This aligns with Glenn's initial AWT patch commit e5e7514d649cd7dd28bbb8e04b72338dc09c2c83, i.e. removing redundancies... Tested on Linux, Windows and MacOS w/ GLCanvas, GLJPanel and GLWindow using pixelScale values: - Linux: 1, 2 - Windows: 1, 1.25, 2 - MacOS: 1, 2 Additional reference https://forum.jogamp.org/DPI-scaling-not-working-td4042206.html#a4042603 |