summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2013-07-02 15:10:20 +0200
committerSven Gothel <[email protected]>2013-07-02 15:10:20 +0200
commit205a17de1abec614d3d06386f873170fc1691e86 (patch)
tree8326756998569593e1c1d03c372c1e8e47126a81
parentc5662cf53b20a70180a6deed9b56c65dc76f8e4e (diff)
Fix Bug 770 and 771
Bug 770: X11Window.c: - Request focus _before_ enabling EWMH flags (fullscreen or above) after resize and temporary invisibility. This actually allows us to keep the focus after resize and repositioning! - Set _NET_WM_BYPASS_COMPOSITOR implicit analog to _NET_WM_STATE_FLAG_ABOVE - Clean up _NET_WM_* flag names, avoiding name space collisions, i.e. adding FLAG! - Remove dead _NET_WM_STATE setting via direct window property (not working anyways) - Remove dead code: FS_GRAB_KEYBOARD X11/WindowDriver.java: - Enable _NET_WM_STATE_FLAG_ABOVE temporarily if FLAG_IS_FULLSCREEN && !FLAG_IS_ALWAYSONTOP - Override focusChanged(..) to react on focus lost/gained in case of temporarily enabled _NET_WM_STATE_FLAG_ABOVE. If focus is lost, disable _NET_WM_STATE_FLAG_ABOVE, otherwise re-enable it. WindowImpl.java: - FullscreenAction.run: Always use 'FLAG_IS_FULLSCREEN_SPAN' +++ Bug 771: WindowImpl.java: - Keep fullscreenMonitors and fullscreenUseMainMonitor values intact, allowing them to be tracked. Remove duplicates in FullscreenAction class. - MonitorModeListenerImpl.monitorModeChanged: Add fullscreen path: If the changed monitor is part of fullscreenMonitors, recalculate the viewport union and reset position and fullscreen-size. - MonitorModeListenerImpl: Try to regain focus after successful mode change.
-rwxr-xr-xmake/scripts/tests-win.bat5
-rw-r--r--make/scripts/tests.sh9
-rw-r--r--src/newt/classes/jogamp/newt/WindowImpl.java98
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java38
-rw-r--r--src/newt/native/X11Window.c159
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02aNEWT.java177
6 files changed, 265 insertions, 221 deletions
diff --git a/make/scripts/tests-win.bat b/make/scripts/tests-win.bat
index 17ac9c784..a5d368c48 100755
--- a/make/scripts/tests-win.bat
+++ b/make/scripts/tests-win.bat
@@ -61,7 +61,7 @@ REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGe
REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWT -time 5000
REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelAWT %*
REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelsAWT %*
-scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasAWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasAWT %*
REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestLandscapeES2NewtCanvasAWT %*
REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT %*
@@ -119,7 +119,8 @@ REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.mm.TestScreenMode01aN
REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.mm.TestScreenMode01bNEWT %*
REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.mm.TestScreenMode01cNEWT %*
REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.mm.TestScreenMode01dNEWT %*
-REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.mm.TestScreenMode02sNEWT %*
+scripts\java-win.bat com.jogamp.opengl.test.junit.newt.mm.TestScreenMode02aNEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.mm.TestScreenMode02bNEWT %*
REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.mm.ManualScreenMode03sNEWT %*
REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple %*
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index 5acced4af..c0d15b84b 100644
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -135,7 +135,8 @@ function jrun() {
#D_ARGS="-Djogl.debug.EGLDisplayUtil -Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.GLDrawable"
#D_ARGS="-Djogl.debug.EGLDisplayUtil -Dnativewindow.debug.X11Util"
#D_ARGS="-Djogl.debug.GLDrawable"
- #D_ARGS="-Dnewt.debug.Screen"
+ #D_ARGS="-Dnewt.debug.Screen -Dnewt.debug.Window"
+ #D_ARGS="-Dnewt.debug.Window"
#D_ARGS="-Dnewt.test.Screen.disableRandR13"
#D_ARGS="-Dnewt.test.Screen.disableScreenMode -Dnewt.debug.Screen"
#D_ARGS="-Dnewt.debug.Screen -Djogl.debug.Animator"
@@ -175,7 +176,7 @@ function jrun() {
#D_ARGS="-Dnewt.debug.Window -Dnewt.debug.Display -Dnewt.debug.EDT -Djogl.debug.GLContext"
#D_ARGS="-Dnewt.debug.Window -Djogl.debug.Animator -Dnewt.debug.Screen"
#D_ARGS="-Dnativewindow.debug.JAWT -Dnewt.debug.Window"
- D_ARGS="-Dnewt.debug.Window.KeyEvent"
+ #D_ARGS="-Dnewt.debug.Window.KeyEvent"
#D_ARGS="-Dnewt.debug.Window.MouseEvent"
#D_ARGS="-Dnewt.debug.Window.MouseEvent -Dnewt.debug.Window.KeyEvent"
#D_ARGS="-Dnewt.debug.Window -Dnativewindow.debug=all"
@@ -400,13 +401,13 @@ function testawtswt() {
#testnoawt com.jogamp.opengl.test.junit.newt.TestGLWindowInvisiblePointer01NEWT $*
#testnoawt com.jogamp.opengl.test.junit.newt.TestDisplayLifecycle01NEWT
#testnoawt com.jogamp.opengl.test.junit.newt.TestDisplayLifecycle02NEWT
-testnoawt com.jogamp.opengl.test.junit.newt.mm.TestScreenMode00aNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.newt.mm.TestScreenMode00aNEWT $*
#testnoawt com.jogamp.opengl.test.junit.newt.mm.TestScreenMode00bNEWT $*
#testnoawt com.jogamp.opengl.test.junit.newt.mm.TestScreenMode01aNEWT $*
#testnoawt com.jogamp.opengl.test.junit.newt.mm.TestScreenMode01bNEWT $*
#testnoawt com.jogamp.opengl.test.junit.newt.mm.TestScreenMode01cNEWT $*
#testnoawt com.jogamp.opengl.test.junit.newt.mm.TestScreenMode01dNEWT $*
-#testnoawt com.jogamp.opengl.test.junit.newt.mm.TestScreenMode02aNEWT $*
+testnoawt com.jogamp.opengl.test.junit.newt.mm.TestScreenMode02aNEWT $*
#testnoawt com.jogamp.opengl.test.junit.newt.mm.TestScreenMode02bNEWT $*
#testnoawt com.jogamp.opengl.test.junit.newt.mm.ManualScreenMode03aNEWT $*
#testnoawt -Djava.awt.headless=true com.jogamp.opengl.test.junit.newt.TestGLWindows01NEWT $*
diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java
index 77ff21061..600035bf6 100644
--- a/src/newt/classes/jogamp/newt/WindowImpl.java
+++ b/src/newt/classes/jogamp/newt/WindowImpl.java
@@ -372,9 +372,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(isFullscreen()) {
synchronized(fullScreenAction) {
fullscreen = false; // trigger a state change
- fullScreenAction.init(true, fullscreenUseMainMonitor, fullscreenMonitors);
- fullscreenMonitors = null; // release references ASAP
- fullscreenUseMainMonitor = true;
+ fullScreenAction.init(true);
fullScreenAction.run();
}
} else {
@@ -892,17 +890,19 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
private class SetSizeAction implements Runnable {
int width, height;
+ boolean disregardFS;
- private SetSizeAction(int w, int h) {
+ private SetSizeAction(int w, int h, boolean disregardFS) {
this.width = w;
this.height = h;
+ this.disregardFS = disregardFS;
}
public final void run() {
final RecursiveLock _lock = windowLock;
_lock.lock();
try {
- if ( !isFullscreen() && ( getWidth() != width || getHeight() != height ) ) {
+ if ( ( disregardFS || !isFullscreen() ) && ( getWidth() != width || getHeight() != height ) ) {
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window setSize: START "+getWidth()+"x"+getHeight()+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible "+visible);
}
@@ -937,9 +937,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
+ private void setFullscreenSize(int width, int height) {
+ runOnEDTIfAvail(true, new SetSizeAction(width, height, true));
+ }
@Override
public void setSize(int width, int height) {
- runOnEDTIfAvail(true, new SetSizeAction(width, height));
+ runOnEDTIfAvail(true, new SetSizeAction(width, height, false));
}
@Override
public void setTopLevelSize(int width, int height) {
@@ -1850,25 +1853,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
private class FullScreenAction implements Runnable {
boolean fullscreen;
- List<MonitorDevice> monitors;
- boolean useMainMonitor;
- private boolean init(boolean fullscreen, boolean useMainMonitor, List<MonitorDevice> monitors) {
+ private boolean init(boolean fullscreen) {
if(isNativeValid()) {
this.fullscreen = fullscreen;
- if( isFullscreen() != fullscreen ) {
- this.monitors = monitors;
- this.useMainMonitor = useMainMonitor;
- return true;
- } else {
- this.monitors = null;
- this.useMainMonitor = true;
- return false;
- }
+ return isFullscreen() != fullscreen;
} else {
WindowImpl.this.fullscreen = fullscreen; // set current state for createNative(..)
- WindowImpl.this.fullscreenMonitors = monitors;
- WindowImpl.this.fullscreenUseMainMonitor = useMainMonitor;
return false;
}
}
@@ -1886,16 +1877,27 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
final RectangleImmutable viewport;
final int fs_span_flag;
if(fullscreen) {
- if( null == monitors ) {
- if( useMainMonitor ) {
- monitors = new ArrayList<MonitorDevice>();
- monitors.add( getMainMonitor() );
+ if( null == fullscreenMonitors ) {
+ if( fullscreenUseMainMonitor ) {
+ fullscreenMonitors = new ArrayList<MonitorDevice>();
+ fullscreenMonitors.add( getMainMonitor() );
} else {
- monitors = getScreen().getMonitorDevices();
+ fullscreenMonitors = getScreen().getMonitorDevices();
}
}
- fs_span_flag = monitors.size() > 1 ? FLAG_IS_FULLSCREEN_SPAN : 0 ;
- viewport = MonitorDevice.unionOfViewports(new Rectangle(), monitors);
+ /**
+ * 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);
nfs_x = getX();
nfs_y = getY();
nfs_width = getWidth();
@@ -1905,6 +1907,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
w = viewport.getWidth();
h = viewport.getHeight();
} else {
+ fullscreenUseMainMonitor = true;
+ fullscreenMonitors = null;
fs_span_flag = 0;
viewport = null;
x = nfs_x;
@@ -1926,16 +1930,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
}
- monitors = null; // clear references ASAP
- useMainMonitor = true;
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()+
", virtl-size: "+screen.getWidth()+"x"+screen.getHeight()+", monitorsViewport "+viewport);
}
- DisplayImpl display = (DisplayImpl) screen.getDisplay();
+ final DisplayImpl display = (DisplayImpl) screen.getDisplay();
display.dispatchMessagesNative(); // status up2date
- boolean wasVisible = isVisible();
+ final boolean wasVisible = isVisible();
// Lock parentWindow only during reparenting (attempt)
final NativeWindow parentWindowLocked;
@@ -1963,8 +1965,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
WindowImpl.this.waitForVisible(true, false);
display.dispatchMessagesNative(); // status up2date
WindowImpl.this.waitForSize(w, h, false, TIMEOUT_NATIVEWINDOW);
- display.dispatchMessagesNative(); // status up2date
-
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window fs done: " + WindowImpl.this);
}
@@ -1975,7 +1975,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
}
}
- private final FullScreenAction fullScreenAction = new FullScreenAction();
+ private final FullScreenAction fullScreenAction = new FullScreenAction();
@Override
public boolean setFullscreen(boolean fullscreen) {
@@ -1989,7 +1989,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
private boolean setFullscreenImpl(boolean fullscreen, boolean useMainMonitor, List<MonitorDevice> monitors) {
synchronized(fullScreenAction) {
- if( fullScreenAction.init(fullscreen, useMainMonitor, monitors) ) {
+ fullscreenMonitors = monitors;
+ fullscreenUseMainMonitor = useMainMonitor;
+ if( fullScreenAction.init(fullscreen) ) {
if(fullScreenAction.fsOn() && isOffscreenInstance(WindowImpl.this, parentWindow)) {
// enable fullscreen on offscreen instance
if(null != parentWindow) {
@@ -2008,8 +2010,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
nfs_parent = null;
}
- if(isVisible()) {
- requestFocus(true /* wait */, this.fullscreen /* skipFocusAction */, true /* force */);
+ if( fullscreen && isVisible() ) { // force focus on fullscreen
+ requestFocus(true /* wait */, true /* skipFocusAction */, true /* force */);
}
}
return this.fullscreen;
@@ -2018,10 +2020,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
private class MonitorModeListenerImpl implements MonitorModeListener {
boolean animatorPaused = false;
+ boolean hadFocus = false;
public void monitorModeChangeNotify(MonitorEvent me) {
+ hadFocus = hasFocus();
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.monitorModeChangeNotify: "+me);
+ System.err.println("Window.monitorModeChangeNotify: hadFocus "+hadFocus+", "+me);
}
if(null!=lifecycleHook) {
@@ -2031,7 +2035,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
public void monitorModeChanged(MonitorEvent me, boolean success) {
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.monitorModeChanged: "+me+", success: "+success);
+ System.err.println("Window.monitorModeChanged: hadFocus "+hadFocus+", "+me+", success: "+success);
}
if(success) {
@@ -2055,13 +2059,27 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
setSize(viewport.getWidth(), viewport.getHeight());
}
}
+ } else {
+ // If changed monitor is part of this fullscreen mode, reset size! (Bug 771)
+ final MonitorDevice md = me.getMonitor();
+ if( fullscreenMonitors.contains(md) ) {
+ final RectangleImmutable viewport = MonitorDevice.unionOfViewports(new Rectangle(), fullscreenMonitors);
+ if(DEBUG_IMPLEMENTATION) {
+ final RectangleImmutable rect = new Rectangle(getX(), getY(), getWidth(), getHeight());
+ System.err.println("Window.monitorModeChanged: FS Monitor Match: Fit window "+rect+" into new viewport union "+viewport+", provoked by "+md);
+ }
+ definePosition(viewport.getX(), viewport.getY()); // set pos for setVisible(..) or createNative(..) - reduce EDT roundtrip
+ setFullscreenSize(viewport.getWidth(), viewport.getHeight());
+ }
}
}
-
if(animatorPaused) {
lifecycleHook.resumeRenderingAction();
}
sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
+ if( hadFocus ) {
+ requestFocus(true);
+ }
}
}
private final MonitorModeListenerImpl monitorModeListenerImpl = new MonitorModeListenerImpl();
diff --git a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
index 786587d65..aec7f310e 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
@@ -133,7 +133,7 @@ public class WindowDriver extends WindowImpl {
}
}
- protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, final int flags) {
+ 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,18 +148,52 @@ 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));
+ }
+ } else {
+ tempAlwaysOnTop = false;
+ }
+ final int fflags = flags;
final DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
public Object run(long dpy) {
reconfigureWindow0( dpy, getScreenIndex(),
getParentWindowHandle(), getWindowHandle(), display.getWindowDeleteAtom(),
- _x, _y, width, height, flags);
+ _x, _y, width, height, fflags);
return null;
}
});
return true;
}
+ volatile boolean tempAlwaysOnTop = false;
+ /**
+ * <p>
+ * Deal w/ tempAlwaysOnTop.
+ * </p>
+ * {@inheritDoc}
+ */
+ protected void focusChanged(boolean defer, boolean focusGained) {
+ if( tempAlwaysOnTop && hasFocus() != focusGained && isNativeValid() ) {
+ final int flags = getReconfigureFlags(FLAG_CHANGE_ALWAYSONTOP, isVisible()) | ( focusGained ? FLAG_IS_ALWAYSONTOP : 0 );
+ final DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
+ runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
+ public Object run(long dpy) {
+ reconfigureWindow0( dpy, getScreenIndex(),
+ getParentWindowHandle(), getWindowHandle(), display.getWindowDeleteAtom(),
+ getX(), getY(), getWidth(), getHeight(), flags);
+ return null;
+ }
+ });
+ }
+ super.focusChanged(defer, focusGained);
+ }
+
+
protected void reparentNotify(long newParentWindowHandle) {
if(DEBUG_IMPLEMENTATION) {
final long p0 = getParentWindowHandle();
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c
index 3f50f27a4..4a95d0180 100644
--- a/src/newt/native/X11Window.c
+++ b/src/newt/native/X11Window.c
@@ -299,9 +299,8 @@ static void NewtWindows_setNormalWindowEWMH (Display *dpy, Window w) {
#define _NET_WM_STATE_REMOVE 0
#define _NET_WM_STATE_ADD 1
-
-#define _NET_WM_FULLSCREEN ( 1 << 0 )
-#define _NET_WM_ABOVE ( 1 << 1 )
+#define _NET_WM_STATE_FLAG_FULLSCREEN ( 1 << 0 )
+#define _NET_WM_STATE_FLAG_ABOVE ( 1 << 1 )
/**
* Set fullscreen using Extended Window Manager Hints (EWMH)
@@ -314,7 +313,9 @@ static void NewtWindows_setNormalWindowEWMH (Display *dpy, Window w) {
* and resets it when leaving FS.
* The same is assumed for the decoration state.
*/
-static int NewtWindows_isFullscreenEWMHSupported (Display *dpy, Window w) {
+static int NewtWindows_getSupportedStackingEWMHFlags(Display *dpy, Window w) {
+#ifdef VERBOSE_ON
+ // Code doesn't work reliable on KDE4 ...
Atom _NET_WM_ALLOWED_ACTIONS = XInternAtom( dpy, "_NET_WM_ALLOWED_ACTIONS", False );
Atom _NET_WM_ACTION_FULLSCREEN = XInternAtom( dpy, "_NET_WM_ACTION_FULLSCREEN", False );
Atom _NET_WM_ACTION_ABOVE = XInternAtom( dpy, "_NET_WM_ACTION_ABOVE", False );
@@ -329,86 +330,75 @@ static int NewtWindows_isFullscreenEWMHSupported (Display *dpy, Window w) {
for(i=0; i<action_len; i++) {
if(_NET_WM_ACTION_FULLSCREEN == actions[i]) {
DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: _NET_WM_ACTION_FULLSCREEN (*)\n", i);
- res |= _NET_WM_FULLSCREEN ;
+ res |= _NET_WM_STATE_FLAG_FULLSCREEN ;
} else if(_NET_WM_ACTION_ABOVE == actions[i]) {
DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: _NET_WM_ACTION_ABOVE (*)\n", i);
- res |= _NET_WM_ABOVE ;
+ res |= _NET_WM_STATE_FLAG_ABOVE ;
}
-#ifdef VERBOSE_ON
else {
char * astr = XGetAtomName(dpy, actions[i]);
DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: %s (unused)\n", i, astr);
XFree(astr);
}
-#endif
}
DBG_PRINT( "**************** X11: FS EWMH CHECK: 0x%X\n", res);
} else {
DBG_PRINT( "**************** X11: FS EWMH CHECK: XGetWindowProperty failed: %d\n", s);
}
- // above code doesn't work reliable on KDE4 ...
- res = _NET_WM_FULLSCREEN | _NET_WM_ABOVE ;
- return res;
+#endif
+ return _NET_WM_STATE_FLAG_FULLSCREEN | _NET_WM_STATE_FLAG_ABOVE ;
}
-static Bool NewtWindows_setFullscreenEWMH (Display *dpy, Window root, Window w, int ewmhFlags, Bool isVisible, Bool enable) {
+static Bool NewtWindows_setStackingEWMHFlags (Display *dpy, Window root, Window w, int ewmhFlags, Bool isVisible, Bool enable) {
Atom _NET_WM_STATE = XInternAtom( dpy, "_NET_WM_STATE", False );
Atom _NET_WM_STATE_ABOVE = XInternAtom( dpy, "_NET_WM_STATE_ABOVE", False );
Atom _NET_WM_STATE_FULLSCREEN = XInternAtom( dpy, "_NET_WM_STATE_FULLSCREEN", False );
- int ewmhMask = NewtWindows_isFullscreenEWMHSupported(dpy, w);
+ int ewmhMask = NewtWindows_getSupportedStackingEWMHFlags(dpy, w);
+ Bool changeFullscreen = 0 != ( ( _NET_WM_STATE_FLAG_FULLSCREEN & ewmhMask ) & ewmhFlags ) ;
+ Bool changeAbove = 0 != ( ( _NET_WM_STATE_FLAG_ABOVE & ewmhMask ) & ewmhFlags ) ;
Bool res = False;
if(0 == ewmhMask) {
return res;
}
- if(!isVisible && True==enable) {
- Atom types[2]={0};
- int ntypes=0;
-
- if( 0 != ( ( _NET_WM_FULLSCREEN & ewmhMask ) & ewmhFlags ) ) {
- types[ntypes++] = _NET_WM_STATE_FULLSCREEN;
- }
- if( 0 != ( ( _NET_WM_ABOVE & ewmhMask ) & ewmhFlags ) ) {
- types[ntypes++] = _NET_WM_STATE_ABOVE;
- }
- if(ntypes>0) {
- XChangeProperty( dpy, w, _NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, ntypes);
- XSync(dpy, False);
- res = True;
- }
- } else {
- if(enable) {
- NewtWindows_setCWAbove(dpy, w);
- }
- XEvent xev;
- long mask = SubstructureNotifyMask | SubstructureRedirectMask ;
- int i=0;
-
- memset ( &xev, 0, sizeof(xev) );
-
- xev.type = ClientMessage;
- xev.xclient.window = w;
- xev.xclient.message_type = _NET_WM_STATE;
- xev.xclient.format = 32;
+ // _NET_WM_STATE: fullscreen and/or above
+ if( changeFullscreen || changeAbove ) {
+ {
+ // _NET_WM_STATE as event to root window
+ XEvent xev;
+ long mask = SubstructureNotifyMask | SubstructureRedirectMask ;
+ int i=0;
- xev.xclient.data.l[i++] = ( True == enable ) ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE ;
- if( 0 != ( ( _NET_WM_FULLSCREEN & ewmhMask ) & ewmhFlags ) ) {
- xev.xclient.data.l[i++] = _NET_WM_STATE_FULLSCREEN;
- }
- if( 0 != ( ( _NET_WM_ABOVE & ewmhMask ) & ewmhFlags ) ) {
- xev.xclient.data.l[i++] = _NET_WM_STATE_ABOVE;
- }
- xev.xclient.data.l[3] = 1; //source indication for normal applications
+ memset ( &xev, 0, sizeof(xev) );
+
+ xev.type = ClientMessage;
+ xev.xclient.window = w;
+ xev.xclient.message_type = _NET_WM_STATE;
+ xev.xclient.format = 32;
+
+ xev.xclient.data.l[i++] = enable ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE ;
+ if( changeFullscreen ) {
+ xev.xclient.data.l[i++] = _NET_WM_STATE_FULLSCREEN;
+ }
+ if( changeAbove ) {
+ xev.xclient.data.l[i++] = _NET_WM_STATE_ABOVE;
+ }
+ xev.xclient.data.l[3] = 1; //source indication for normal applications
- if(i>0) {
XSendEvent ( dpy, root, False, mask, &xev );
- res = True;
}
+ // If ABOVE is changed, also change _NET_WM_BYPASS_COMPOSITOR!
+ if( changeAbove ) {
+ Atom _NET_WM_BYPASS_COMPOSITOR = XInternAtom( dpy, "_NET_WM_BYPASS_COMPOSITOR", False );
+ unsigned long value = enable ? 1 : 0;
+ XChangeProperty( dpy, w, _NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&value, 1);
+ }
+ XSync(dpy, False);
+ res = True;
}
- XSync(dpy, False);
- DBG_PRINT( "X11: reconfigureWindow0 FULLSCREEN EWMH ON %d, ewmhMask 0x%X, ewmhFlags 0x%X, visible %d: %d\n",
- enable, ewmhMask, ewmhFlags, isVisible, res);
+ DBG_PRINT( "X11: setStackingEWMHFlags ON %d, changeFullscreen %d, changeAbove %d, visible %d: %d\n",
+ enable, changeFullscreen, changeAbove, isVisible, res);
return res;
}
@@ -657,7 +647,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
NewtWindows_setPosSize(dpy, window, x, y, width, height);
if( TST_FLAG_IS_ALWAYSONTOP(flags) ) {
- NewtWindows_setFullscreenEWMH(dpy, root, window, _NET_WM_ABOVE, True, True);
+ NewtWindows_setStackingEWMHFlags(dpy, root, window, _NET_WM_STATE_FLAG_ABOVE, True, True);
}
}
@@ -720,15 +710,6 @@ static Bool WaitForReparentNotify( Display *dpy, XEvent *event, XPointer arg ) {
}
#endif
-/**
- * KDE cause lost input focus in fullscreen mode.
- * Using 'XGrabKeyboard(..)' would prevent the loss,
- * but also would disable WM task switcher etc.
- *
- * #define FS_GRAB_KEYBOARD 1
- *
- */
-
/*
* Class: jogamp_newt_driver_x11_WindowDriver
* Method: reconfigureWindow0
@@ -747,21 +728,22 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
XEvent event;
Bool isVisible = !TST_FLAG_CHANGE_VISIBILITY(flags) && TST_FLAG_IS_VISIBLE(flags) ;
Bool tempInvisible = ( TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_PARENTING(flags) ) && isVisible ;
+ // Bool tempInvisible = TST_FLAG_CHANGE_PARENTING(flags) && isVisible ;
int fsEWMHFlags = 0;
if( TST_FLAG_CHANGE_FULLSCREEN(flags) ) {
- if( !TST_FLAG_IS_FULLSCREEN_SPAN(flags) ) { // doesn't work w/ spanning across monitors
- fsEWMHFlags |= _NET_WM_FULLSCREEN;
+ if( !TST_FLAG_IS_FULLSCREEN_SPAN(flags) ) { // doesn't work w/ spanning across monitors. See also Bug 770 & Bug 771
+ fsEWMHFlags |= _NET_WM_STATE_FLAG_FULLSCREEN;
}
if( TST_FLAG_IS_FULLSCREEN(flags) ) {
if( TST_FLAG_IS_ALWAYSONTOP(flags) ) {
- fsEWMHFlags |= _NET_WM_ABOVE; // fs on, above on
- } // else { } // fs on, above off
+ fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // fs on, above on
+ } // else { } // fs on, above off
} else if( !TST_FLAG_IS_ALWAYSONTOP(flags) ) {
- fsEWMHFlags |= _NET_WM_ABOVE; // fs off, above off
- } // else { } // fs off, above on
+ fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // fs off, above off
+ } // else { } // fs off, above on
}
if( TST_FLAG_CHANGE_ALWAYSONTOP(flags) ) {
- fsEWMHFlags |= _NET_WM_ABOVE; // toggle above
+ fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // toggle above
}
DBG_PRINT( "X11: reconfigureWindow0 dpy %p, scrn %d, parent %p/%p, win %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d (span %d), alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d, tempInvisible %d, fsEWMHFlags %d\n",
@@ -780,21 +762,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
!TST_FLAG_IS_FULLSCREEN_SPAN(flags) &&
( TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_ALWAYSONTOP(flags) ) ) {
Bool enable = TST_FLAG_CHANGE_FULLSCREEN(flags) ? TST_FLAG_IS_FULLSCREEN(flags) : TST_FLAG_IS_ALWAYSONTOP(flags) ;
- if( NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, enable) ) {
+ if( NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, enable) ) {
if ( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) { // FS off - restore decoration
NewtWindows_setDecorations (dpy, w, TST_FLAG_IS_UNDECORATED(flags) ? False : True);
}
- #ifdef FS_GRAB_KEYBOARD
- if(TST_FLAG_CHANGE_FULLSCREEN(flags)) {
- if(TST_FLAG_IS_FULLSCREEN(flags)) {
- XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
- } else {
- XUngrabKeyboard(dpy, CurrentTime);
- }
- } else if(TST_FLAG_CHANGE_ALWAYSONTOP(flags) && !TST_FLAG_IS_ALWAYSONTOP(flags)) {
- XUngrabKeyboard(dpy, CurrentTime);
- }
- #endif
+ DBG_PRINT( "X11: reconfigureWindow0 X (fast)\n");
return;
}
}
@@ -808,10 +780,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) ||
( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && !TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // FS off
- NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, False);
- #ifdef FS_GRAB_KEYBOARD
- XUngrabKeyboard(dpy, CurrentTime);
- #endif
+ NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, False);
}
if( TST_FLAG_CHANGE_PARENTING(flags) && !TST_FLAG_HAS_PARENT(flags) ) {
@@ -844,9 +813,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
XMapRaised(dpy, w);
XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) w );
// no need to notify the java side .. just temp change
- }
-
- if( TST_FLAG_CHANGE_VISIBILITY(flags) ) {
+ } else if( TST_FLAG_CHANGE_VISIBILITY(flags) ) {
if( TST_FLAG_IS_VISIBLE(flags) ) {
DBG_PRINT( "X11: reconfigureWindow0 VISIBLE ON\n");
XMapRaised(dpy, w);
@@ -859,15 +826,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags) ) ||
( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // FS on
- NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, True);
- #ifdef FS_GRAB_KEYBOARD
- if(TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags)) {
- XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
- }
- #endif
+ NewtWindows_requestFocus (dpy, w, True);
+ NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, True);
}
- DBG_PRINT( "X11: reconfigureWindow0 X\n");
+ DBG_PRINT( "X11: reconfigureWindow0 X (full)\n");
}
/*
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02aNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02aNEWT.java
index 37ea499df..54c6bdd6c 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02aNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02aNEWT.java
@@ -55,7 +55,8 @@ import java.util.List;
import javax.media.nativewindow.util.Dimension;
/**
- * Tests MonitorMode change w/ changed rotation.
+ * Tests MonitorMode change w/ changed rotation,
+ * w/ and w/o fullscreen, pre and post MonitorMode change.
* <p>
* Also tests MonitorMode reset after last Screen is dereferenced,
* i.e. MonitorMode should be reinstated.
@@ -75,21 +76,14 @@ public class TestScreenMode02aNEWT extends UITestCase {
glp = GLProfile.getDefault();
}
- @AfterClass
- public static void releaseClass() throws InterruptedException {
- Thread.sleep(waitTimeShort);
- }
-
static GLWindow createWindow(Screen screen, GLCapabilities caps, int width, int height, boolean onscreen, boolean undecorated) {
Assert.assertNotNull(caps);
caps.setOnscreen(onscreen);
GLWindow window = GLWindow.create(screen, caps);
window.setSize(width, height);
- window.addGLEventListener(new GearsES2());
+ window.addGLEventListener(new GearsES2(1));
Assert.assertNotNull(window);
- window.setVisible(true);
- Assert.assertTrue(window.isVisible());
return window;
}
@@ -100,9 +94,26 @@ public class TestScreenMode02aNEWT extends UITestCase {
}
@Test
- public void testScreenRotationChange01() throws InterruptedException {
- Thread.sleep(waitTimeShort);
-
+ public void testScreenRotationChange01_PreWin() throws InterruptedException {
+ testScreenRotationChangeImpl(true, true, false);
+ }
+
+ @Test
+ public void testScreenRotationChange02_PreFull() throws InterruptedException {
+ testScreenRotationChangeImpl(true, true, true);
+ }
+
+ @Test
+ public void testScreenRotationChange11_PostWin() throws InterruptedException {
+ testScreenRotationChangeImpl(true, false, false);
+ }
+
+ @Test
+ public void testScreenRotationChange12_PostFull() throws InterruptedException {
+ testScreenRotationChangeImpl(true, false, true);
+ }
+
+ void testScreenRotationChangeImpl(boolean changeMode, boolean preVis, boolean fullscreen) throws InterruptedException {
GLCapabilities caps = new GLCapabilities(glp);
Assert.assertNotNull(caps);
Display display = NewtFactory.createDisplay(null); // local display
@@ -111,60 +122,92 @@ public class TestScreenMode02aNEWT extends UITestCase {
Assert.assertNotNull(screen);
GLWindow window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */);
Assert.assertNotNull(window);
-
- MonitorDevice monitor = window.getMainMonitor();
- List<MonitorMode> monitorModes = monitor.getSupportedModes();
- if(monitorModes.size()==1) {
- // no support ..
- System.err.println("Your platform has no ScreenMode change support, sorry");
- destroyWindow(window);
- return;
+ if( preVis ) {
+ window.setVisible(true);
+ if( fullscreen ) {
+ window.setFullscreen(true);
+ }
+ } else {
+ screen.createNative();
+ Assert.assertEquals(true,display.isNativeValid());
+ Assert.assertEquals(true,screen.isNativeValid());
}
- Assert.assertTrue(monitorModes.size()>0);
Animator animator = new Animator(window);
animator.start();
-
- MonitorMode mmCurrent = monitor.getCurrentMode();
- Assert.assertNotNull(mmCurrent);
- MonitorMode mmOrig = monitor.getOriginalMode();
+
+ final MonitorDevice monitor = window.getMainMonitor();
+ final MonitorMode mmOrig = monitor.getOriginalMode();
Assert.assertNotNull(mmOrig);
- System.err.println("[0] orig : "+mmOrig);
- System.err.println("[0] current: "+mmCurrent);
- Assert.assertEquals(mmCurrent, mmOrig);
-
- monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc
- Assert.assertNotNull(monitorModes);
- Assert.assertTrue(monitorModes.size()>0);
- monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 90);
- if(null==monitorModes || Platform.getOSType() == Platform.OSType.MACOS ) {
- // no rotation support ..
- System.err.println("Your platform has no rotation support, sorry");
- destroyWindow(window);
- return;
+ if(changeMode) {
+ List<MonitorMode> monitorModes = monitor.getSupportedModes();
+ if(monitorModes.size()==1) {
+ // no support ..
+ System.err.println("Your platform has no ScreenMode change support, sorry");
+ destroyWindow(window);
+ return;
+ }
+ Assert.assertTrue(monitorModes.size()>0);
+
+ final MonitorMode mmCurrent = monitor.getCurrentMode();
+ Assert.assertNotNull(mmCurrent);
+ System.err.println("[0] orig : "+mmOrig);
+ System.err.println("[0] current: "+mmCurrent);
+ Assert.assertEquals(mmCurrent, mmOrig);
+
+ monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+ monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 90);
+ if(null==monitorModes || Platform.getOSType() == Platform.OSType.MACOS ) {
+ // no rotation support ..
+ System.err.println("Your platform has no rotation support, sorry");
+ destroyWindow(window);
+ return;
+ }
+ monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(801, 601));
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+ monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate());
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+ monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes);
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+
+ MonitorMode mm = (MonitorMode) monitorModes.get(0);
+ System.err.println("[0] set current: "+mm);
+ monitor.setCurrentMode(mm);
+ Assert.assertTrue(monitor.isModeChangedByUs());
+ Assert.assertEquals(mm, monitor.getCurrentMode());
+ Assert.assertNotSame(mmOrig, monitor.getCurrentMode());
+ Assert.assertEquals(mm, monitor.queryCurrentMode());
}
- monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(801, 601));
- Assert.assertNotNull(monitorModes);
- Assert.assertTrue(monitorModes.size()>0);
- monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate());
- Assert.assertNotNull(monitorModes);
- Assert.assertTrue(monitorModes.size()>0);
- monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes);
- Assert.assertNotNull(monitorModes);
- Assert.assertTrue(monitorModes.size()>0);
-
- MonitorMode sm = (MonitorMode) monitorModes.get(0);
- System.err.println("[0] set current: "+sm);
- monitor.setCurrentMode(sm);
- Assert.assertTrue(monitor.isModeChangedByUs());
- Assert.assertEquals(sm, monitor.getCurrentMode());
- Assert.assertNotSame(mmOrig, monitor.getCurrentMode());
- Assert.assertEquals(sm, monitor.queryCurrentMode());
-
+
+ if( !preVis ) {
+ window.setVisible(true);
+ if( fullscreen ) {
+ window.setFullscreen(true);
+ }
+ }
+
Thread.sleep(waitTimeLong);
-
- // check reset ..
-
+
+ if( !preVis && fullscreen ) {
+ window.setFullscreen(false);
+ }
+
+ if(changeMode) {
+ monitor.setCurrentMode(mmOrig);
+ Assert.assertFalse(monitor.isModeChangedByUs());
+ Assert.assertEquals(mmOrig, monitor.getCurrentMode());
+ Thread.sleep(waitTimeShort);
+ }
+
+ if( preVis && fullscreen ) {
+ window.setFullscreen(false);
+ }
+
Assert.assertEquals(true,display.isNativeValid());
Assert.assertEquals(true,screen.isNativeValid());
Assert.assertEquals(true,window.isNativeValid());
@@ -178,22 +221,6 @@ public class TestScreenMode02aNEWT extends UITestCase {
Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false));
Assert.assertEquals(false,screen.isNativeValid());
Assert.assertEquals(false,display.isNativeValid());
-
- screen.createNative(); // trigger native re-creation
-
- Assert.assertEquals(true,display.isNativeValid());
- Assert.assertEquals(true,screen.isNativeValid());
-
- mmCurrent = monitor.getCurrentMode();
- System.err.println("[1] current/orig: "+mmCurrent);
-
- Assert.assertNotNull(mmCurrent);
- Assert.assertEquals(mmCurrent, mmOrig);
-
- screen.destroy();
-
- Assert.assertEquals(false,screen.isNativeValid());
- Assert.assertEquals(false,display.isNativeValid());
}
public static void main(String args[]) throws IOException {