Bug 1358

Summary: Incorrect OpenGL surface size on SWT GLCanvas and NewtCanvasSWT w/ High-DPI scaling
Product: [JogAmp] Jogl Reporter: Christian B <cmbspam>
Component: swtAssignee: Sven Gothel <sgothel>
Severity: normal CC: crougier, marcel.au, sgothel
Priority: P4    
Version: 2.4.0   
Hardware: All   
OS: all   
Type: DEFECT SCM Refs:
ca7f0fb61b0a608b6e684a5bbde71f6ecb6e3fe0 e6d53e29f05a6928192f6c4a988b2aa558be8d65 3b60cb464cea77a22f866155c14c8786dea360ba fb211581fefc994d1458a2a74801dfb937170f39 7d7d4e4f194ed25dc8b450e13ab67020c607445b 8caf3fab68dc890855961d22cb235d1c8f5c52c6 557f3d57cc2ca60678fe87df4b4a9c99c016e575
Workaround: TRUE
Bug Depends on:    
Bug Blocks: 674, 1373, 1378, 1421, 1422    
Attachments: Screenshot Wrong Position

Description Christian B 2018-01-30 09:26:19 CET
When using high DPI displays, it is usually required to scale up UI and Text to keep things readable. Eclipse and SWT work fine. However, the GLCanvas included in jogl has some issues. When using a scale factor of 200%, only the lower left quarter of the GLCanvas is used. The cause of this was fairly easy to track down. The method com.jogamp.opengl.swt.GLCanvas.updateSizeCheck() retrieves the size of the canvas by calling org.eclipse.swt.widgets.Scrollable.getClientArea(). A quick look at the code shows that this method returns the scaled size. This means that GLCanvas treats the canvas smaller than it actually is. 

Three possible workarounds:
1. Use reflection to access call org.eclipse.swt.widgets.Scrollable.getClientAreaInPixels()
2. Overwrite org.eclipse.swt.widgets.Scrollable.getClientArea() and use DPIUtil to scale the surface back to it's size in pixels.
3. Overwrite org.eclipse.swt.widgets.Scrollable.getClientArea(), read the current scaling from the system property "org.eclipse.swt.internal.deviceZoom" and scale the surface back to it's size in pixels. (untested)

I already have a thread about this in the jogl forum

jogl version is 2.3.2, designated as current on the download page. Tested with Eclipse Oxygen on Windows 7 and 10.
Comment 1 Sven Gothel 2019-04-10 05:36:48 CEST
Commit ca7f0fb61b0a608b6e684a5bbde71f6ecb6e3fe0

Christian reported this bug and described multiple pathways.

This change usese the following:
- access to getClientAreaInPixels w/ fallback of
- DPIUtil.autoScaleUp(getClientArea())

I hardly have tested this on Linux/GTK, even though I use a High DPI monitor,
maybe just because of it and Eclipse _poor_ state of proper UI presentation.

Christian: Please test this .. if buggy, reopen quick for release 2.4.0

SWT/GTK High-DPI is a PIA: 
- GDK_SCALE renders offscreen and scales the image (wow & ugly)
- GDK_DPI_SCALE works at least on the fonts properly
- swt.autoScale is pretty much like: What will be scaled?
  It scales some icons in Eclipse, not fonts and result in Eclipse 
  looks horrible.

Maybe I just made this patch to vent about this poor state of things.

Notable: KDE looks great and uses DPI, firefox some GDK_DPI_SCALE equivalent (OK)

One also wonders why there is only a single scale dimension, where DPI differs x/y!
But enough of my rant :)
Comment 2 Sven Gothel 2020-01-03 15:53:49 CET
Marcel reported: <http://forum.jogamp.org/JOGL-2-4-built-Newt-SWT-MacOSX-Wrong-Canvas-Size-tp4040233.html>

"when I execute my JOGL SWT Newt example with the latest JOGL built on MacOSX I see a wrong size and location calculation of the NewtCanvas, see screenshot below:


Example Source as Eclipse project with libraries here (Main class = JOGL2NewtSWTDemo):


It seems as if the width and the height of the newt canvas is exactly twice as big as the parent swt canvas size (Retina related?).

Also the top left 0,0 coordinates seems to be wrong (besides overlapping bug described in bug 1378).

Is there a way how I can change the size and origin of the NewtCanvasSWT at startup?

I tried, e.g., setSize method to no avail."
Comment 3 Sven Gothel 2020-01-03 15:56:01 CET
Marcel, was it this commit ca7f0fb61b0a608b6e684a5bbde71f6ecb6e3fe0
of Bug 1358 causing the regression? 

We may continue debating it in bugzilla and yes,
would be great to have this finally fixed.
Comment 4 Marcel Au 2020-01-03 17:27:44 CET
Hello Sven,

I searched the commit on Github and found a statement from Alexis Drogoul:


Which leads to a Gama platform about this issue.

Seeing the screenshots they had the same issue and already solved it?:

Comment 5 Marcel Au 2020-01-03 17:33:31 CET
They apparently used the DPIUtil method in their source and scale the canvas down,

Comment 6 Marcel Au 2020-01-03 18:18:51 CET
So my guess is thst the method updatePosSizeCheck (called from setBounds) in class NewtCanvasSWT.java must be scaled down for MacOSX Retina.


Comment 7 Sven Gothel 2020-01-04 02:19:13 CET
(In reply to Marcel Au from comment #4)

AlexisDrogoul commented on ca7f0fb on May 3, 2019


One issue of this commit is that the width and height of canvases are now systematically doubled when they are passed to reshape(...), as least on macOS with a Retina display. See for instance gama-platform/gama#2628 (comment), where all the displays are now wrong.

Was this the intended behaviour of this commit ? In that case, how do we come back to the "old" values ? Should we use some downscaling of DPIUtil ? Use another field of the Drawable ?

Thanks in advance for any clue,
Comment 8 Sven Gothel 2020-01-04 02:32:54 CET
(In reply to Marcel Au from comment #6)
> So my guess is thst the method updatePosSizeCheck (called from setBounds) in 
> class NewtCanvasSWT.java must be scaled down for MacOSX Retina.

Finally reviewed the code .. and gladly it rings a bell :)

'getClientAreaInPixels()' properly returns the size in pixel units,
either using swt_scrollable_clientAreaInPixels or DPIUtil.

    pixel-unit size = window-unit size * dpi-scale

Now this commit ca7f0fb61b0a608b6e684a5bbde71f6ecb6e3fe0 
does one thing wrong IMHO: Using the pixel-unit size for 
setting up the NEWT child window 'eh? :)

So while his pixel-unit size should work well for being using as
surface-size in pixel units for like GL reshape,
it would artificially double scale up the window :)

Now I have to dig out my MacOS Book w/ DPI screen and test this, 
partially reverting using window-units for window size operations.

Sounds reasonable?
Maybe you can test as well.
Comment 9 Marcel Au 2020-01-04 12:07:30 CET
Hello Sven,

sounds reasonable. I would be happy to test the changes.
will you make the changes available as a new build?
Comment 10 Sven Gothel 2020-01-04 16:57:00 CET
(In reply to Marcel Au from comment #9)
yes, I will kick-off another RC .. 
Will do this regularly on changes pre release for testing.
Comment 11 Sven Gothel 2020-01-04 17:23:02 CET
Split changes in most atomic commits to separate their individual semantics:


commit e6d53e29f05a6928192f6c4a988b2aa558be8d65

    Bug 1358: Add OSXUtil.GetWindowPixelScale(..)
    It is now possible to retrieve the pixel scale [NSWindow backingScaleFactor]
    after native creation by NEWT - as we have changed the lifecycly (all-in-one native method on AppKit)


commit 3b60cb464cea77a22f866155c14c8786dea360ba

    Bug 1358: NewtCanvasSWT High-DPI: Use window-units where required instead of pixel-units
    Commit ca7f0fb61b0a608b6e684a5bbde71f6ecb6e3fe0
    did one thing wrong: Using the pixel-unit size for
    NEWT child window operations where window-units are required.


commit fb211581fefc994d1458a2a74801dfb937170f39

    Bug 1358: NewtCanvasSWT High-DPI: Propagate pixelScale to NEWT-Child and utilize it for convertTo*Units(..)
    Detected pixelScale on SWT should be propagated to the NEWT Child
    using 'newtChild.setSurfaceScale(pixelScale)' to allow an impact.
    Also utilize computed pixel for converTo*Units(..) implementation.


commit 7d7d4e4f194ed25dc8b450e13ab67020c607445b

    Bug 1358: MacOS NEWT WindowDriver / NewtCanvasSWT High-DPI:
    Even w/ commit fb211581fefc994d1458a2a74801dfb937170f39, propagating the SWT pixelScale to NEWT-Child,
    hasPixelScale was never updated via updatePixelScale() through native callback [NSView viewDidChangeBackingProperties]!
    [NSView viewDidChangeBackingProperties] not being called on [created] child windows (NewtCanvasSWT)
    confused the overal pixelScale state, i.e. no hasPixelScale update via updatePixelScale(..).
    This change explicitly queries OSXUtil.GetWindowPixelScale(handle) (commit e6d53e29f05a6928192f6c4a988b2aa558be8d65)for:
    1) updateMaxScreenPixelScaleByWindowHandle(..), which now updates the actual hasPixelScale after native creation
    and for
    2) setSurfaceScale(..), which directly calls updatePixelScale(..) with the queried actual pixelScale
    instead of relying on the native callback [NSView viewDidChangeBackingProperties].


It goes w/o saying, the last commit was the most annoying issue at hand.
But I hope the explicit call to updatePixelScale(..) not relying on the 
NSView callback should resolve other issues as well.

I have tested using: com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTGLn
Comment 12 Sven Gothel 2020-01-05 01:26:35 CET
(In reply to Marcel Au from comment #9)

Its included here:

JogAmp Jbeil RC Build 2.4.0-rc-20200104


Changes to previous RC:


3) Bug 1358 <https://jogamp.org/bugzilla/show_bug.cgi?id=1358>
- fixed I hope, waiting for validation 

Comment 13 Marcel Au 2020-01-05 14:51:48 CET
Created attachment 835 [details]
Screenshot Wrong Position
Comment 14 Marcel Au 2020-01-05 14:53:26 CET
Hello Sven,

the size now works correctly. 

However if the NewtCanvasSWT is embedded in a tab the location is displayed in a wrong location.

The location position only works if the canvas is directly embedded in a composite.

In the example I have given this can be seen in a wrong y-location (see screenshot
in forum message whereas the location is not directly below the tab).

If the window is tiled it is far more wrong (see afore attached screenshot).
Comment 15 Marcel Au 2020-01-05 15:03:52 CET
With my example I mean of course the example linked in the forum message:


The afore attached screenshot in this bugzilla forum shows the consquences of  the wrong position calculation in an embedded application layout.

Somehow the correct corner coordinates of the embedded canvas are not calculated.
Comment 16 Sven Gothel 2020-01-05 15:07:19 CET
(In reply to Marcel Au from comment #14)

Therefor I can close this issue here: Scaling size.
The original commit fixing Christian's original report (comment 1) 
is still intact and valid and fixes served here also complete
my earlier patch: See comment 8 and comment 11.

We continue with Bug 1421: Scaled child window position.
Comment 17 Sven Gothel 2020-01-05 23:05:29 CET
jogl commit 8caf3fab68dc890855961d22cb235d1c8f5c52c6

Bug 1358: GLCanvas: Call new OSXUtil.SetWindowPixelScale(..) when GLCanvas gets realized on MacOS
This fixes GLCanvas's High-DPI scaled size issue on MacOS of Bug 1358.
Comment 18 Sven Gothel 2020-01-06 19:21:35 CET
Marcel found still issues on Windows and Linux re scaling,
see Bug 1421 comment 11 through Bug 1421 comment 16.
Comment 19 Sven Gothel 2020-01-06 19:23:46 CET
Please test and reproduce issue using Bug 1421 comment 17 work,
particularly the unit test TestGLCanvasSWTNewtCanvasSWTPosInTabs
Comment 20 Sven Gothel 2020-01-06 19:30:15 CET
replying to Bug 1421 comment 16

There is no native surfaceScale on linux or windows at all,
only on MacOS. Therefor NEWT has no setSurfaceScale(..) impact 
on these platforms.

The scale factor on linux and windows is artificial
and one always gets the pixel-unit via GTK/GDK and native.
This is also demonstrated in SWT's implementation, 
which simply does a dump autoScaleDown of pixel-unix -> window-unit.
Comment 21 Sven Gothel 2020-01-06 19:41:16 CET
(In reply to Sven Gothel from comment #20)
commit 557f3d57cc2ca60678fe87df4b4a9c99c016e575

Bug 1358: Merely simplifying the non MacOS getClientAreaInPixels() code path
This also demonstrates that on non MacOS, SWT's scale-factor is artificially imposed
on the actual pixel-units, as SWT's getClientArea() is simply returning:
Comment 22 Sven Gothel 2020-01-06 19:43:53 CET
(In reply to Sven Gothel from comment #21)
This artificial scaled-down window-unit clientArea,
should have no impact on NEWT Windows whatsoever
as we use clientAreaPixels for size and don't change 
the position for non-MacOS.
Comment 23 Sven Gothel 2020-01-06 22:31:56 CET
(In reply to Sven Gothel from comment #22)
Closing this issue again.

We shall create a new bug entry which may reference Bug 1358 and Bug 1421 
to tackle further open issues, like the mapping of SWT's dpi-scaling
on platforms other than MacOS where it is not actually implemented
in the native toolkits: Windows and Linux GTK.

Both latter may have high level artificial dpi-scaling for 
so called unaware applications to map the 75 dpi on 150 dpi or higher.
However, this is worth a new bug entry as we have exhausted the original issue reported here.
Comment 24 crougier 2020-05-27 13:32:02 CEST
we reported an issue with Jogl 2.3.2 and the com.jogamp.opengl.swt.GLCanvas, when it is resized only a part of the canvas is redrawn on Linux platforms: https://jogamp.org/bugzilla/show_bug.cgi?id=1395.
Following Julien Gouesse's advice, we tested 2.4.0-rc-20200306 thinking that the fix of this bug fixes our bug too (forum thread: http://forum.jogamp.org/Resizing-GLCanvas-does-not-redraw-immediately-td4040590.html).
Unfortunately the bug is still there :(
Maybe bug 1395 should be added to the list of issues regarding JOGL/SWT Windowing/Surface Interoperability (bug 674), what do you think ?