diff options
author | Sven Gothel <[email protected]> | 2019-04-10 05:36:16 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2019-04-10 05:36:16 +0200 |
commit | ca7f0fb61b0a608b6e684a5bbde71f6ecb6e3fe0 (patch) | |
tree | 94a272f64d4343d223c914ecab68e379815a85f3 | |
parent | fc2edeb79e42897b926081769ad3cb3e509aed71 (diff) |
Bug 1358: 'Honor' SWT's projection of High-DPI Scaling (Reading hidden pixel dimensions)
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 :)
-rw-r--r-- | make/scripts/tests.sh | 5 | ||||
-rw-r--r-- | src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java | 46 | ||||
-rw-r--r-- | src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java | 56 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java | 63 |
4 files changed, 105 insertions, 65 deletions
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 47daa91e5..bad31647a 100644 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -118,6 +118,7 @@ function jrun() { #D_ARGS="-Djogamp.debug.ProcAddressHelper -Djogamp.debug.NativeLibrary -Djogamp.debug.NativeLibrary.Lookup -Djogamp.debug.JNILibLoader -Djogamp.debug.TempJarCache -Djogamp.debug.JarUtil -Djogl.glu.nojava=true" #D_ARGS="-Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all" + #D_ARGS="-Dnativewindow.debug.SWT" #D_ARGS="-Dnativewindow.debug.SWT -Dnativewindow.debug.X11Util -Dnewt.debug.Window" #D_ARGS="-Dnativewindow.debug=all -Dnewt.debug.Window" #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all -Djogamp.debug.Lock" @@ -761,7 +762,7 @@ function testawtswt() { #testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor02NewtGLWindow $* #testswt com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTGLn $* #testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $* -#testswt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasSWT $* +testswt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasSWT $* #testswt com.jogamp.opengl.test.junit.jogl.demos.es2.swt.TestGearsES2SWT $* #testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTEclipseGLCanvas01GLn $* #testswt com.jogamp.opengl.test.junit.jogl.swt.TestBug672NewtCanvasSWTSashForm $* @@ -814,7 +815,7 @@ function testawtswt() { #testawt com.jogamp.opengl.test.junit.newt.DemoCreateAndDisposeOnCloseNEWT $* #testawt com.jogamp.opengl.test.junit.newt.TestCloseNewtAWT #testawt com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol01AWT $* -testnoawt com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol02NEWT $* +#testnoawt com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol02NEWT $* #testawt com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol03NewtAWT $* #testawt com.jogamp.opengl.test.junit.newt.TestMultipleNewtCanvasAWT $* diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java index a34c8648a..5e90c4035 100644 --- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java +++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java @@ -114,13 +114,12 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS private final GLCapabilitiesImmutable capsRequested; private final GLCapabilitiesChooser capsChooser; - private volatile Rectangle clientArea; + private volatile Rectangle clientAreaPixels, clientAreaWindow; private volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access private volatile GLContextImpl context; // volatile: avoid locking for read-only access /* Native window surface */ private final boolean useX11GTK; - private volatile long gdkWindow; // either GDK child window .. private volatile long x11Window; // .. or X11 child window (for GL rendering) private final AbstractGraphicsScreen screen; @@ -154,7 +153,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS @Override public void run() { if (sendReshape) { - helper.reshape(GLCanvas.this, 0, 0, clientArea.width, clientArea.height); + helper.reshape(GLCanvas.this, 0, 0, clientAreaPixels.width, clientAreaPixels.height); sendReshape = false; } helper.display(GLCanvas.this); @@ -243,9 +242,6 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS if( 0 != x11Window) { SWTAccessor.destroyX11Window(screen.getDevice(), x11Window); x11Window = 0; - } else if( 0 != gdkWindow) { - SWTAccessor.destroyGDKWindow(gdkWindow); - gdkWindow = 0; } screen.getDevice().close(); } catch (final Throwable re) { @@ -349,7 +345,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS SWTAccessor.setRealized(this, true); - clientArea = GLCanvas.this.getClientArea(); + clientAreaPixels = SWTAccessor.getClientAreaInPixels(this); + clientAreaWindow = getClientArea(); /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite). * Note: SWT is owner of the native handle, hence closing operation will be a NOP. */ @@ -377,7 +374,6 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS this.capsChooser = capsChooser; // post create .. when ready - gdkWindow = 0; x11Window = 0; drawable = null; context = null; @@ -426,17 +422,17 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS @Override public final int getSurfaceWidth(final ProxySurface s) { - return clientArea.width; + return clientAreaPixels.width; } @Override public final int getSurfaceHeight(final ProxySurface s) { - return clientArea.height; + return clientAreaPixels.height; } @Override public String toString() { - return "SWTCanvasUpstreamSurfaceHook[upstream: "+GLCanvas.this.toString()+", "+clientArea.width+"x"+clientArea.height+"]"; + return "SWTCanvasUpstreamSurfaceHook[upstream: "+GLCanvas.this.toString()+", "+clientAreaPixels.width+"x"+clientAreaPixels.height+" [pixel], "+clientAreaWindow.width+"x"+clientAreaWindow.height+" [win]]"; } /** @@ -452,25 +448,27 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS }; protected final void updateSizeCheck() { - final Rectangle oClientArea = clientArea; - final Rectangle nClientArea = GLCanvas.this.getClientArea(); - if ( nClientArea != null && - ( nClientArea.width != oClientArea.width || nClientArea.height != oClientArea.height ) + final Rectangle oClientAreaPixels = clientAreaPixels; + final Rectangle nClientAreaPixels = SWTAccessor.getClientAreaInPixels(this); + + if ( nClientAreaPixels != null && + ( nClientAreaPixels.width != oClientAreaPixels.width || nClientAreaPixels.height != oClientAreaPixels.height ) ) { - clientArea = nClientArea; // write back new value + clientAreaPixels = nClientAreaPixels; // write back new value + clientAreaWindow = getClientArea(); final GLDrawableImpl _drawable = drawable; final boolean drawableOK = null != _drawable && _drawable.isRealized(); if(DEBUG) { final long dh = drawableOK ? _drawable.getHandle() : 0; - System.err.println(getThreadName()+": GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+nClientArea.x+"/"+nClientArea.y+" "+nClientArea.width+"x"+nClientArea.height+" - drawableHandle "+toHexString(dh)); + System.err.println(getThreadName()+": GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+nClientAreaPixels.x+"/"+nClientAreaPixels.y+" "+nClientAreaPixels.width+"x"+nClientAreaPixels.height+" - drawableHandle "+toHexString(dh)); } if( drawableOK ) { if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) { final RecursiveLock _lock = lock; _lock.lock(); try { - final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, nClientArea.width, nClientArea.height); + final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, nClientAreaPixels.width, nClientAreaPixels.height); if(_drawable != _drawableNew) { // write back drawable = _drawableNew; @@ -481,9 +479,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS } } if(0 != x11Window) { - SWTAccessor.resizeX11Window(screen.getDevice(), clientArea, x11Window); - } else if(0 != gdkWindow) { - SWTAccessor.resizeGDKWindow(clientArea, gdkWindow); + SWTAccessor.resizeX11Window(screen.getDevice(), clientAreaPixels, x11Window); } sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock } @@ -553,7 +549,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS return res; } private final void createDrawableImpl() { - final Rectangle nClientArea = clientArea; + final Rectangle nClientArea = clientAreaPixels; if(0 >= nClientArea.width || 0 >= nClientArea.height) { if(DEBUG) { System.err.println(getThreadName()+": SWT.GLCanvas.validate.X "+toHexString(hashCode())+": drawable could not be created: size < 0x0"); @@ -578,7 +574,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS if( VisualIDHolder.VID_UNDEFINED != visualID ) { // gdkWindow = SWTAccessor.createCompatibleGDKChildWindow(this, visualID, clientArea.width, clientArea.height); // nativeWindowHandle = SWTAccessor.gdk_window_get_xwindow(gdkWindow); - x11Window = SWTAccessor.createCompatibleX11ChildWindow(screen, this, visualID, clientArea.width, clientArea.height); + x11Window = SWTAccessor.createCompatibleX11ChildWindow(screen, this, visualID, clientAreaPixels.width, clientAreaPixels.height); nativeWindowHandle = x11Window; } else { throw new GLException("Could not choose valid visualID: "+toHexString(visualID)+", "+this); @@ -674,12 +670,12 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS @Override public int getSurfaceWidth() { - return clientArea.width; + return clientAreaPixels.width; } @Override public int getSurfaceHeight() { - return clientArea.height; + return clientAreaPixels.height; } @Override diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java index 48661170c..d99519878 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java @@ -35,7 +35,9 @@ import java.security.PrivilegedAction; import org.eclipse.swt.graphics.GCData; import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.internal.DPIUtil; import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Scrollable; import com.jogamp.nativewindow.AbstractGraphicsScreen; import com.jogamp.nativewindow.NativeWindowException; @@ -56,6 +58,8 @@ import jogamp.nativewindow.Debug; public class SWTAccessor { private static final boolean DEBUG = Debug.debug("SWT"); + private static final Method swt_scrollable_clientAreaInPixels; + private static final Field swt_control_handle; private static final boolean swt_uses_long_handles; @@ -139,6 +143,18 @@ public class SWTAccessor { isWindows = NativeWindowFactory.TYPE_WINDOWS == nwt; isX11 = NativeWindowFactory.TYPE_X11 == nwt; + Method m = null; + try { + m = Scrollable.class.getDeclaredMethod("getClientAreaInPixels"); + m.setAccessible(true); + } catch (final Exception ex) { + m = null; + if( DEBUG ) { + System.err.println("getClientAreaInPixels not implemented: "+ex.getMessage()); + } + } + swt_scrollable_clientAreaInPixels = m; + Field f = null; if( !isOSX ) { try { @@ -159,7 +175,7 @@ public class SWTAccessor { // System.err.println("SWT long handles: " + swt_uses_long_handles); // System.err.println("Platform 64bit: "+Platform.is64Bit()); - Method m=null; + m=null; try { m = ReflectionUtil.getMethod(Control.class, str_internal_new_GC, new Class[] { GCData.class }); } catch (final Exception ex) { @@ -167,6 +183,7 @@ public class SWTAccessor { } swt_control_internal_new_GC = m; + m=null; try { if(swt_uses_long_handles) { m = Control.class.getDeclaredMethod(str_internal_dispose_GC, new Class[] { long.class, GCData.class }); @@ -350,6 +367,43 @@ public class SWTAccessor { // /** + * Returns the unscaled {@link Scrollable#getClientArea()} in pixels. + * <p> + * If the package restricted method {@link Scrollable#getClientAreaInPixels()} + * is implemented, we return its result. + * </p> + * <p> + * Fallback is to return {@link DPIUtil#autoScaleUp(Rectangle) DPIUtil#autoScaleUp}({@link Scrollable#getClientArea()}), + * reverting {@link Scrollable#getClientArea()}'s {@link DPIUtil#autoScaleDown(Rectangle)}. + * </p> + * <p> + * Note to SWT's API spec writers: You need to allow access to the unscaled value, scale properties and define what is being scaled (fonts, images, ..). + * Further more the scale should be separate for x/y coordinates, as DPI differs here. + * </p> + * <p> + * Note to Eclipse authors: Scaling up the fonts and images hardly works on GTK/SWT/Eclipse. + * GDK_SCALE, GDK_DPI_SCALE and swt.autoScale produce inconsistent results with Eclipse. + * Broken High-DPI for .. some years now. + * </p> + * + * Requires SWT >= 3.105 (DPIUtil) + * + * @param s the {@link Scrollable} instance + * @return unscaled client area in pixels, see above + * @throws NativeWindowException during invocation of the method, if any + */ + public static Rectangle getClientAreaInPixels(final Scrollable s) throws NativeWindowException { + if( null == swt_scrollable_clientAreaInPixels ) { + return DPIUtil.autoScaleUp(s.getClientArea()); + } + try { + return (Rectangle) swt_scrollable_clientAreaInPixels.invoke(s); + } catch (final Throwable e) { + throw new NativeWindowException(e); + } + } + + /** * @param swtControl the SWT Control to retrieve the native widget-handle from * @return the native widget-handle * @throws NativeWindowException if the widget handle is null diff --git a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java index d30dbe6dc..bd5c43d6c 100644 --- a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java +++ b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java @@ -79,7 +79,7 @@ public class NewtCanvasSWT extends Canvas implements NativeWindowHolder, WindowC private WindowClosingMode newtChildClosingMode = WindowClosingMode.DISPOSE_ON_CLOSE; private final WindowClosingMode closingMode = WindowClosingMode.DISPOSE_ON_CLOSE; - private volatile Rectangle clientArea; + private volatile Rectangle clientAreaPixels, clientAreaWindow; private volatile SWTNativeWindow nativeWindow; private volatile Window newtChild = null; @@ -129,7 +129,8 @@ public class NewtCanvasSWT extends Canvas implements NativeWindowHolder, WindowC SWTAccessor.setRealized(this, true); - clientArea = getClientArea(); + clientAreaPixels = SWTAccessor.getClientAreaInPixels(this); + clientAreaWindow = getClientArea(); final AbstractGraphicsDevice device = SWTAccessor.getDevice(this); screen = SWTAccessor.getScreen(device, -1 /* default */); @@ -154,14 +155,14 @@ public class NewtCanvasSWT extends Canvas implements NativeWindowHolder, WindowC if( null != nativeWindow || validateNative() ) { if( newtChildReady ) { if( postSetSize ) { - newtChild.setSize(clientArea.width, clientArea.height); + newtChild.setSize(clientAreaPixels.width, clientAreaPixels.height); postSetSize = false; } if( postSetPos ) { - newtChild.setPosition(clientArea.x, clientArea.y); + newtChild.setPosition(clientAreaPixels.x, clientAreaPixels.y); postSetPos = false; } - newtChild.windowRepaint(0, 0, clientArea.width, clientArea.height); + newtChild.windowRepaint(0, 0, clientAreaPixels.width, clientAreaPixels.height); } } break; @@ -175,7 +176,7 @@ public class NewtCanvasSWT extends Canvas implements NativeWindowHolder, WindowC if( DEBUG ) { System.err.println("NewtCanvasSWT.Event.RESIZE, "+event); } - updateSizeCheck(); + updatePosSizeCheck(false); break; case SWT.Dispose: if( DEBUG ) { @@ -204,14 +205,14 @@ public class NewtCanvasSWT extends Canvas implements NativeWindowHolder, WindowC } if( SWTAccessor.isOSX ) { // Force newtChild to update its size and position (OSX only) - updatePosSizeCheck(x, y, width, height, true /* updatePos */); + updatePosSizeCheck(true /* updatePos */); } } /** assumes nativeWindow == null ! */ protected final boolean validateNative() { - updateSizeCheck(); - final Rectangle nClientArea = clientArea; + updatePosSizeCheck(false); + final Rectangle nClientArea = clientAreaPixels; if(0 >= nClientArea.width || 0 >= nClientArea.height) { return false; } @@ -249,46 +250,34 @@ public class NewtCanvasSWT extends Canvas implements NativeWindowHolder, WindowC return null != nativeWindow; } - protected final void updateSizeCheck() { - final Rectangle nClientArea = getClientArea(); - if( null != nClientArea ) { - updatePosSizeCheck(nClientArea.x, nClientArea.y, nClientArea.width, nClientArea.height, false /* updatePos */); - } - } - protected final void updatePosSizeCheck() { - final Rectangle nClientArea = getClientArea(); - if( null != nClientArea ) { - updatePosSizeCheck(nClientArea.x, nClientArea.y, nClientArea.width, nClientArea.height, true /* updatePos */); - } - } - protected final void updatePosSizeCheck(final int newX, final int newY, final int newWidth, final int newHeight, final boolean updatePos) { + protected final void updatePosSizeCheck(final boolean updatePos) { final boolean sizeChanged, posChanged; - final Rectangle nClientArea; + Rectangle nClientAreaPixels = SWTAccessor.getClientAreaInPixels(this); { - final Rectangle oClientArea = clientArea; - sizeChanged = newWidth != oClientArea.width || newHeight != oClientArea.height; - posChanged = newX != oClientArea.x || newY != oClientArea.y; + final Rectangle oClientAreaPixels = clientAreaPixels; + sizeChanged = nClientAreaPixels.width != oClientAreaPixels.width || nClientAreaPixels.height != oClientAreaPixels.height; + posChanged = nClientAreaPixels.x != oClientAreaPixels.x || nClientAreaPixels.y != oClientAreaPixels.y; if( sizeChanged || posChanged ) { - nClientArea = new Rectangle(updatePos ? newX : oClientArea.x, updatePos ? newY : oClientArea.y, newWidth, newHeight); - clientArea = nClientArea; + clientAreaPixels = nClientAreaPixels; + clientAreaWindow = getClientArea(); } else { - nClientArea = clientArea; + nClientAreaPixels = clientAreaPixels; } } if(DEBUG) { final long nsh = newtChildReady ? newtChild.getSurfaceHandle() : 0; - System.err.println("NewtCanvasSWT.updatePosSizeCheck: sizeChanged "+sizeChanged+", posChanged "+posChanged+", updatePos "+updatePos+", ("+Thread.currentThread().getName()+"): newtChildReady "+newtChildReady+", "+nClientArea.x+"/"+nClientArea.y+" "+nClientArea.width+"x"+nClientArea.height+" - surfaceHandle 0x"+Long.toHexString(nsh)); + System.err.println("NewtCanvasSWT.updatePosSizeCheck: sizeChanged "+sizeChanged+", posChanged "+posChanged+", updatePos "+updatePos+", ("+Thread.currentThread().getName()+"): newtChildReady "+newtChildReady+", "+nClientAreaPixels.x+"/"+nClientAreaPixels.y+" "+nClientAreaPixels.width+"x"+nClientAreaPixels.height+" - surfaceHandle 0x"+Long.toHexString(nsh)); } if( sizeChanged ) { if( newtChildReady ) { - newtChild.setSize(nClientArea.width, nClientArea.height); + newtChild.setSize(nClientAreaPixels.width, nClientAreaPixels.height); } else { postSetSize = true; } } if( updatePos && posChanged ) { if( newtChildReady ) { - newtChild.setPosition(nClientArea.x, nClientArea.y); + newtChild.setPosition(nClientAreaPixels.x, nClientAreaPixels.y); } else { postSetPos = true; } @@ -437,9 +426,9 @@ public class NewtCanvasSWT extends Canvas implements NativeWindowHolder, WindowC newtChild.setFocusAction(null); // no AWT focus traversal .. if(add) { - updateSizeCheck(); - final int w = clientArea.width; - final int h = clientArea.height; + updatePosSizeCheck(false); + final int w = clientAreaPixels.width; + final int h = clientAreaPixels.height; // set SWT EDT and start it { @@ -557,12 +546,12 @@ public class NewtCanvasSWT extends Canvas implements NativeWindowHolder, WindowC @Override public int getSurfaceWidth() { - return clientArea.width; + return clientAreaPixels.width; } @Override public int getSurfaceHeight() { - return clientArea.height; + return clientAreaPixels.height; } @Override |