From fa6e868a72b8fb3de8c96afbd71ab4d3ad33f6b6 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Thu, 4 Jul 2013 14:46:28 +0200 Subject: Revisit Bug 770 and Bug 771: Only use FLAG_IS_FULLSCREEN_SPAN if required; At MonitoMode change, reset fullscreen if FLAG_IS_FULLSCREEN_SPAN is supported. - Bug 770: Only use FLAG_IS_FULLSCREEN_SPAN if required - If X11 WindowDriver _and_ virtual-screen-size > fullscreenViewport, - else we still use _NET_WM_STATE_FULLSCREEN on X11! - Bug 771: At MonitoMode change, reset fullscreen if FLAG_IS_FULLSCREEN_SPAN is supported - Since we may still use _NET_WM_STATE_FULLSCREEN on X11: - Pause fullscreen at monitorModeChangeNotify(..) - Resume fullscreen at monitorModeChanged(..) --- src/newt/classes/jogamp/newt/ScreenImpl.java | 10 ++-- src/newt/classes/jogamp/newt/WindowImpl.java | 67 ++++++++++++++++------ src/newt/classes/jogamp/newt/driver/x11/RandR.java | 6 +- .../classes/jogamp/newt/driver/x11/RandR11.java | 7 +++ .../classes/jogamp/newt/driver/x11/RandR13.java | 46 +++------------ .../jogamp/newt/driver/x11/ScreenDriver.java | 34 ++++++++--- .../jogamp/newt/driver/x11/WindowDriver.java | 47 +++++++++++---- 7 files changed, 135 insertions(+), 82 deletions(-) (limited to 'src/newt') diff --git a/src/newt/classes/jogamp/newt/ScreenImpl.java b/src/newt/classes/jogamp/newt/ScreenImpl.java index 422d5b06c..c02f4f288 100644 --- a/src/newt/classes/jogamp/newt/ScreenImpl.java +++ b/src/newt/classes/jogamp/newt/ScreenImpl.java @@ -284,12 +284,12 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener { vOriginSize.setWidth(usrSize.getWidth()); vOriginSize.setHeight(usrSize.getHeight()); if(DEBUG) { - System.err.println("User virtual screen viewport "+vOriginSize); + System.err.println("Update user virtual screen viewport @ "+Thread.currentThread().getName()+": "+vOriginSize); } } else { calcVirtualScreenOriginAndSize(vOriginSize); if(DEBUG) { - System.err.println("Detected virtual screen viewport "+vOriginSize); + System.err.println("Updated virtual screen viewport @ "+Thread.currentThread().getName()+": "+vOriginSize); } } } @@ -396,7 +396,7 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener { @Override public void monitorModeChangeNotify(MonitorEvent me) { if(DEBUG) { - System.err.println("monitorModeChangeNotify: "+me); + System.err.println("monitorModeChangeNotify @ "+Thread.currentThread().getName()+": "+me); } for(int i=0; i "+newViewport); + System.err.println("Screen.updateMonitorViewport["+i+"] @ "+Thread.currentThread().getName()+": "+monitor.getViewport()+" -> "+newViewport); } if( null != newViewport ) { monitor.setViewportValue(newViewport); @@ -424,7 +424,7 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener { updateVirtualScreenOriginAndSize(); } if(DEBUG) { - System.err.println("monitorModeChanged: success "+success+", "+me); + System.err.println("monitorModeChangeNotify @ "+Thread.currentThread().getName()+": success "+success+", "+me); } for(int i=0; i fullscreenMonitors = null; private boolean fullscreenUseMainMonitor = true; + private boolean fullscreenUseSpanningMode = true; // spanning mode: fake full screen, only on certain platforms private boolean autoPosition = true; // default: true (allow WM to choose top-level position, if not set by user) private int nfs_width, nfs_height, nfs_x, nfs_y; // non fullscreen client-area size/pos w/o insets @@ -251,6 +252,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer fullscreen = false; fullscreenMonitors = null; fullscreenUseMainMonitor = true; + fullscreenUseSpanningMode = false; hasFocus = false; parentWindowHandle = 0; } @@ -560,6 +562,16 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer * @see #positionChanged(boolean,int, int) */ protected abstract boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags); + + /** + * Tests whether a single reconfigure flag is supported by implementation. + *

+ * Default is all but {@link #FLAG_IS_FULLSCREEN_SPAN} + *

+ */ + protected boolean isReconfigureFlagSupported(int changeFlags) { + return 0 == ( changeFlags & FLAG_IS_FULLSCREEN_SPAN ); + } protected int getReconfigureFlags(int changeFlags, boolean visible) { return changeFlags |= ( ( 0 != getParentWindowHandle() ) ? FLAG_HAS_PARENT : 0 ) | @@ -1018,6 +1030,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer fullscreen = false; fullscreenMonitors = null; fullscreenUseMainMonitor = true; + fullscreenUseSpanningMode = false; hasFocus = false; parentWindowHandle = 0; @@ -1874,7 +1887,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer int x,y,w,h; - final RectangleImmutable viewport; + final RectangleImmutable sviewport = screen.getViewport(); + final RectangleImmutable viewport; final int fs_span_flag; if(fullscreen) { if( null == fullscreenMonitors ) { @@ -1885,19 +1899,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer fullscreenMonitors = getScreen().getMonitorDevices(); } } - /** - * Bug 770: - * _NET_WM_STATE_FULLSCREEN may result in ConfigureNotify event w/ virtual screen size, instead of monitor-mode size (NV + Fglrx). - * ConfigureNotify reflects the actual size of the window and is being propagated - * to NEWT and the GLEventListener. - * With Mesa/Intel open-source driver, the correct desired monitor mode size is reported - * at least on one test machine here. - * - * Bug 771: Implementation requires not to use _NET_WM_STATE_FULLSCREEN! - */ - // fs_span_flag = monitors.size() > 1 ? FLAG_IS_FULLSCREEN_SPAN : 0 ; - fs_span_flag = FLAG_IS_FULLSCREEN_SPAN; viewport = MonitorDevice.unionOfViewports(new Rectangle(), fullscreenMonitors); + if( isReconfigureFlagSupported(FLAG_IS_FULLSCREEN_SPAN) && + ( fullscreenMonitors.size() > 1 || sviewport.compareTo(viewport) > 0 ) ) { + fullscreenUseSpanningMode = true; + fs_span_flag = FLAG_IS_FULLSCREEN_SPAN; + } else { + fullscreenUseSpanningMode = false; + fs_span_flag = 0; + } nfs_x = getX(); nfs_y = getY(); nfs_width = getWidth(); @@ -1908,6 +1918,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer h = viewport.getHeight(); } else { fullscreenUseMainMonitor = true; + fullscreenUseSpanningMode = false; fullscreenMonitors = null; fs_span_flag = 0; viewport = null; @@ -1932,7 +1943,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } if(DEBUG_IMPLEMENTATION) { System.err.println("Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()+ - ", virtl-size: "+screen.getWidth()+"x"+screen.getHeight()+", monitorsViewport "+viewport); + ", virtl-screenSize: "+sviewport+", monitorsViewport "+viewport+ + ", spanning "+fullscreenUseSpanningMode+" @ "+Thread.currentThread().getName()); } final DisplayImpl display = (DisplayImpl) screen.getDisplay(); @@ -1991,6 +2003,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer synchronized(fullScreenAction) { fullscreenMonitors = monitors; fullscreenUseMainMonitor = useMainMonitor; + fullscreenUseSpanningMode = false; if( fullScreenAction.init(fullscreen) ) { if(fullScreenAction.fsOn() && isOffscreenInstance(WindowImpl.this, parentWindow)) { // enable fullscreen on offscreen instance @@ -2021,21 +2034,33 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private class MonitorModeListenerImpl implements MonitorModeListener { boolean animatorPaused = false; boolean hadFocus = false; + boolean fullscreenPaused = false; + List _fullscreenMonitors = null; + boolean _fullscreenUseMainMonitor = true; public void monitorModeChangeNotify(MonitorEvent me) { hadFocus = hasFocus(); if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.monitorModeChangeNotify: hadFocus "+hadFocus+", "+me); + System.err.println("Window.monitorModeChangeNotify: hadFocus "+hadFocus+", "+me+" @ "+Thread.currentThread().getName()); } if(null!=lifecycleHook) { animatorPaused = lifecycleHook.pauseRenderingAction(); } + if( fullscreen && isReconfigureFlagSupported(FLAG_IS_FULLSCREEN_SPAN) ) { + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window.monitorModeChangeNotify: FS Pause"); + } + fullscreenPaused = true; + _fullscreenMonitors = fullscreenMonitors; + _fullscreenUseMainMonitor = fullscreenUseMainMonitor; + setFullscreenImpl(false, true, null); + } } public void monitorModeChanged(MonitorEvent me, boolean success) { if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.monitorModeChanged: hadFocus "+hadFocus+", "+me+", success: "+success); + System.err.println("Window.monitorModeChanged: hadFocus "+hadFocus+", "+me+", success: "+success+" @ "+Thread.currentThread().getName()); } if(success) { @@ -2043,7 +2068,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer // Didn't pass above notify method. probably detected screen change after it happened. animatorPaused = lifecycleHook.pauseRenderingAction(); } - if( !fullscreen ) { + if( !fullscreen && !fullscreenPaused ) { // Simply move/resize window to fit in virtual screen if required final RectangleImmutable viewport = screen.getViewport(); if( viewport.getWidth() > 0 && viewport.getHeight() > 0 ) { // failsafe @@ -2059,6 +2084,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer setSize(viewport.getWidth(), viewport.getHeight()); } } + } else if( fullscreenPaused ){ + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window.monitorModeChanged: FS Restore"); + } + setFullscreenImpl(true, _fullscreenUseMainMonitor, _fullscreenMonitors); + fullscreenPaused = false; + _fullscreenMonitors = null; + _fullscreenUseMainMonitor = true; } else { // If changed monitor is part of this fullscreen mode, reset size! (Bug 771) final MonitorDevice md = me.getMonitor(); diff --git a/src/newt/classes/jogamp/newt/driver/x11/RandR.java b/src/newt/classes/jogamp/newt/driver/x11/RandR.java index 769ebe225..e39a6c63a 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/RandR.java +++ b/src/newt/classes/jogamp/newt/driver/x11/RandR.java @@ -29,6 +29,8 @@ package jogamp.newt.driver.x11; import java.util.List; +import javax.media.nativewindow.util.RectangleImmutable; + import jogamp.newt.MonitorModeProps; import com.jogamp.common.util.VersionNumber; @@ -78,5 +80,7 @@ public interface RandR { int[] getMonitorDeviceProps(final long dpy, final ScreenDriver screen, MonitorModeProps.Cache cache, final int crt_idx); int[] getMonitorDeviceViewport(final long dpy, final ScreenDriver screen, final int crt_idx); int[] getCurrentMonitorModeProps(final long dpy, final ScreenDriver screen, final int crt_idx); - boolean setCurrentMonitorMode(final long dpy, final ScreenDriver screen, MonitorDevice monitor, final MonitorMode mode); + boolean setCurrentMonitorMode(final long dpy, final ScreenDriver screen, MonitorDevice monitor, final MonitorMode mode); + + public void updateScreenViewport(final long dpy, final ScreenDriver screen, RectangleImmutable viewport); } diff --git a/src/newt/classes/jogamp/newt/driver/x11/RandR11.java b/src/newt/classes/jogamp/newt/driver/x11/RandR11.java index 58468e112..877607f72 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/RandR11.java +++ b/src/newt/classes/jogamp/newt/driver/x11/RandR11.java @@ -27,6 +27,8 @@ */ package jogamp.newt.driver.x11; +import javax.media.nativewindow.util.RectangleImmutable; + import jogamp.newt.MonitorModeProps; import jogamp.newt.ScreenImpl; @@ -333,6 +335,11 @@ class RandR11 implements RandR { } return done; } + + @Override + public final void updateScreenViewport(final long dpy, final ScreenDriver screen, RectangleImmutable viewport) { + // nop + } /** @return int[] { rot1, .. } */ private static native int[] getAvailableScreenRotations0(long display, int screen_index); diff --git a/src/newt/classes/jogamp/newt/driver/x11/RandR13.java b/src/newt/classes/jogamp/newt/driver/x11/RandR13.java index 375cffe42..ac83fc5f2 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/RandR13.java +++ b/src/newt/classes/jogamp/newt/driver/x11/RandR13.java @@ -29,6 +29,8 @@ package jogamp.newt.driver.x11; import java.util.Iterator; +import javax.media.nativewindow.util.RectangleImmutable; + import jogamp.newt.MonitorModeProps; import com.jogamp.common.util.IntLongHashMap; @@ -235,54 +237,20 @@ class RandR13 implements RandR { } finally { releaseScreenResourceHandle(screenResources); } - /*** - * TODO: Would need a complete re-layout of crt positions, - * which is _not_ implicit by XRandR .. sadly. - * - if( res ) { - updateScreenViewport(dpy, screen, monitor); - } */ return res; } - /** See above .. - private final void updateScreenViewport(final long dpy, final ScreenDriver screen, MonitorDevice monitor) { + @Override + public final void updateScreenViewport(final long dpy, final ScreenDriver screen, final RectangleImmutable viewport) { final int screen_idx = screen.getIndex(); final long screenResources = getScreenResourceHandle(dpy, screen_idx); try { - RectangleImmutable newViewp = null; - final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, monitor.getId()); - try { - final int[] vprops = getMonitorViewport0(monitorInfo); - if( null != vprops ) { - newViewp = new Rectangle(vprops[0], vprops[1], vprops[2], vprops[3]); - } - System.err.println("XXX setScreenViewport: newVp "+newViewp); - } finally { - releaseMonitorInfoHandle(monitorInfo); - } - if( null != newViewp ) { - final List monitors = screen.getMonitorDevices(); - final ArrayList viewports = new ArrayList(); - for(int i=0; i "+newScrnViewp); - setScreenViewport0(dpy, screen_idx, screenResources, newScrnViewp.getX(), newScrnViewp.getY(), newScrnViewp.getWidth(), newScrnViewp.getHeight()); - } + setScreenViewport0(dpy, screen_idx, screenResources, viewport.getX(), viewport.getY(), viewport.getWidth(), viewport.getHeight()); } finally { dumpInfo0(dpy, screen_idx, screenResources); releaseScreenResourceHandle(screenResources); - } - } */ + } + } private static native long getScreenResources0(long display, int screen_index); private static native void freeScreenResources0(long screenResources); diff --git a/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java index 19a69a3f9..1335f5697 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java +++ b/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java @@ -38,6 +38,7 @@ import java.util.List; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.util.Rectangle; +import javax.media.nativewindow.util.RectangleImmutable; import jogamp.nativewindow.x11.X11Util; import jogamp.newt.Debug; @@ -218,14 +219,31 @@ public class ScreenDriver extends ScreenImpl { @Override protected void calcVirtualScreenOriginAndSize(final Rectangle vOriginSize) { - runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable() { - public Object run(long dpy) { - vOriginSize.setX(0); - vOriginSize.setY(0); - vOriginSize.setWidth(getWidth0(dpy, screen_idx)); - vOriginSize.setHeight(getHeight0(dpy, screen_idx)); - return null; - } } ); + final RectangleImmutable ov = (RectangleImmutable) getViewport().cloneMutable(); + /** + if( null != rAndR && rAndR.getVersion().compareTo(RandR.version130) >= 0 && getMonitorDevices().size()>0 ) { + super.calcVirtualScreenOriginAndSize(vOriginSize); + if( DEBUG ) { + System.err.println("X11Screen.calcVirtualScreenOriginAndSize: UpdatingViewport "+ov+" -> "+vOriginSize); + } + runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable() { + public Object run(long dpy) { + rAndR.updateScreenViewport(dpy, ScreenDriver.this, vOriginSize); + return null; + } } ); + } else */ { + runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable() { + public Object run(long dpy) { + vOriginSize.setX(0); + vOriginSize.setY(0); + vOriginSize.setWidth(getWidth0(dpy, screen_idx)); + vOriginSize.setHeight(getHeight0(dpy, screen_idx)); + return null; + } } ); + if( DEBUG ) { + System.err.println("X11Screen.calcVirtualScreenOriginAndSize: Querying X11: "+ov+" -> "+vOriginSize); + } + } } //---------------------------------------------------------------------- diff --git a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java index aec7f310e..4786ea04f 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java @@ -65,6 +65,7 @@ public class WindowDriver extends WindowImpl { public WindowDriver() { } + @Override protected void createNativeImpl() { final ScreenDriver screen = (ScreenDriver) getScreen(); final DisplayDriver display = (DisplayDriver) screen.getDisplay(); @@ -109,6 +110,7 @@ public class WindowDriver extends WindowImpl { } } + @Override protected void closeNativeImpl() { if(0!=windowHandleClose && null!=getScreen() ) { DisplayDriver display = (DisplayDriver) getScreen().getDisplay(); @@ -133,6 +135,18 @@ public class WindowDriver extends WindowImpl { } } + /** + *

+ * X11 Window supports {@link #FLAG_IS_FULLSCREEN_SPAN} + *

+ * {@inheritDoc} + */ + @Override + protected boolean isReconfigureFlagSupported(int changeFlags) { + return true; // all flags! + } + + @Override protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, int flags) { if(DEBUG_IMPLEMENTATION) { System.err.println("X11Window reconfig: "+x+"/"+y+" "+width+"x"+height+", "+ getReconfigureFlagsAsString(null, flags)); @@ -148,14 +162,16 @@ public class WindowDriver extends WindowImpl { _x = x; _y = y; } - if( 0 != ( FLAG_IS_FULLSCREEN & flags) && 0 == ( FLAG_IS_ALWAYSONTOP & flags) ) { - tempAlwaysOnTop = true; - flags |= FLAG_IS_ALWAYSONTOP; - if(DEBUG_IMPLEMENTATION) { - System.err.println("X11Window reconfig.2: temporary "+getReconfigureFlagsAsString(null, flags)); + if( 0 != ( FLAG_CHANGE_FULLSCREEN & flags ) ) { + if( 0 != ( FLAG_IS_FULLSCREEN & flags) && 0 != ( FLAG_IS_FULLSCREEN_SPAN & flags) && 0 == ( FLAG_IS_ALWAYSONTOP & flags) ) { + tempFSAlwaysOnTop = true; + flags |= FLAG_IS_ALWAYSONTOP; + if(DEBUG_IMPLEMENTATION) { + System.err.println("X11Window reconfig.2: temporary "+getReconfigureFlagsAsString(null, flags)); + } + } else { + tempFSAlwaysOnTop = false; } - } else { - tempAlwaysOnTop = false; } final int fflags = flags; final DisplayDriver display = (DisplayDriver) getScreen().getDisplay(); @@ -169,7 +185,7 @@ public class WindowDriver extends WindowImpl { }); return true; } - volatile boolean tempAlwaysOnTop = false; + volatile boolean tempFSAlwaysOnTop = false; /** *

@@ -177,9 +193,13 @@ public class WindowDriver extends WindowImpl { *

* {@inheritDoc} */ + @Override protected void focusChanged(boolean defer, boolean focusGained) { - if( tempAlwaysOnTop && hasFocus() != focusGained && isNativeValid() ) { + if( tempFSAlwaysOnTop && hasFocus() != focusGained && isNativeValid() ) { final int flags = getReconfigureFlags(FLAG_CHANGE_ALWAYSONTOP, isVisible()) | ( focusGained ? FLAG_IS_ALWAYSONTOP : 0 ); + if(DEBUG_IMPLEMENTATION) { + System.err.println("X11Window reconfig.3 (focus): temporary "+getReconfigureFlagsAsString(null, flags)); + } final DisplayDriver display = (DisplayDriver) getScreen().getDisplay(); runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable() { public Object run(long dpy) { @@ -192,8 +212,7 @@ public class WindowDriver extends WindowImpl { } super.focusChanged(defer, focusGained); } - - + protected void reparentNotify(long newParentWindowHandle) { if(DEBUG_IMPLEMENTATION) { final long p0 = getParentWindowHandle(); @@ -201,6 +220,7 @@ public class WindowDriver extends WindowImpl { } } + @Override protected void requestFocusImpl(final boolean force) { runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable() { public Object run(long dpy) { @@ -248,6 +268,7 @@ public class WindowDriver extends WindowImpl { }); } + @Override protected Point getLocationOnScreenImpl(final int x, final int y) { return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable() { public Point run(long dpy) { @@ -256,6 +277,7 @@ public class WindowDriver extends WindowImpl { } ); } + @Override protected void updateInsetsImpl(Insets insets) { // nop - using event driven insetsChange(..) } @@ -304,7 +326,8 @@ public class WindowDriver extends WindowImpl { } super.doMouseEvent(enqueue, wait, eventType, modifiers, x, y, button, rotationXYZ, rotationScale); } - + + /** Called by native TK */ protected final void sendKeyEvent(short eventType, int modifiers, short keyCode, short keySym, char keyChar0, String keyString) { // handleKeyEvent(true, false, eventType, modifiers, keyCode, keyChar); final boolean isModifierKey = KeyEvent.isModifierKey(keyCode); -- cgit v1.2.3