summaryrefslogtreecommitdiffstats
path: root/src/newt
diff options
context:
space:
mode:
Diffstat (limited to 'src/newt')
-rw-r--r--src/newt/classes/jogamp/newt/WindowImpl.java104
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java18
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/X11Window.java22
-rw-r--r--src/newt/native/WindowsWindow.c96
-rw-r--r--src/newt/native/X11Window.c306
5 files changed, 384 insertions, 162 deletions
diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java
index 7c8174a6f..75c3510b7 100644
--- a/src/newt/classes/jogamp/newt/WindowImpl.java
+++ b/src/newt/classes/jogamp/newt/WindowImpl.java
@@ -87,7 +87,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
protected CapabilitiesImmutable capsRequested = null;
protected CapabilitiesChooser capabilitiesChooser = null; // default null -> default
protected boolean fullscreen = false, hasFocus = false;
- protected int width = 128, height = 128, x = 0, y = 0; // client-area size/pos w/o insets
+ protected int width = 128, height = 128; // client-area size w/o insets, default: may be overwritten by user
+ protected int x = -1, y = -1; // client-area pos w/o insets, default: undefined (allow WM to choose if not set by user)
protected Insets insets = new Insets(); // insets of decoration (if top-level && decorated)
protected int nfs_width, nfs_height, nfs_x, nfs_y; // non fullscreen client-area size/pos w/o insets
@@ -257,9 +258,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window.createNative() START ("+getThreadName()+", "+this+")");
}
+ final boolean userPos = 0<=x && 0<=y; // user has specified a position
+
if( null != parentWindow &&
NativeSurface.LOCK_SURFACE_NOT_READY >= parentWindow.lockSurface() ) {
- throw new NativeWindowException("Parent surface lock: not ready: "+parentWindow);
+ throw new NativeWindowException("Parent surface lock: not ready: "+parentWindow);
+ }
+ if( !userPos && ( isUndecorated() || null != parentWindow ) ) {
+ // default child/undecorated window position is 0/0, if not set by user
+ x = 0; y = 0;
}
try {
if(validateParentWindowHandle()) {
@@ -267,11 +274,19 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
throw new InternalError("XXX");
}
if(canCreateNativeImpl()) {
+ final int _x = x, _y = y; // orig req pos
screen.addReference();
screenReferenceAdded = true;
createNativeImpl();
screen.addScreenModeListener(screenModeListenerImpl);
setTitleImpl(title);
+ waitForVisible(true, false);
+ if(userPos) {
+ // wait for user req position
+ waitForPosSize(_x, _y, -1, -1, false, TIMEOUT_NATIVEWINDOW);
+ } else {
+ waitForAnyPos(false, TIMEOUT_NATIVEWINDOW);
+ }
}
// always flag visible,
// allowing to retry if visible && !isNativeValid()
@@ -413,10 +428,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
* to insets and positioning a decorated window to 0/0, which would place the frame
* outside of the screen.</p>
*
- * @param x client-area position
- * @param y client-area position
- * @param width client-area size
- * @param height client-area size
+ * @param x client-area position, or <0 if unchanged
+ * @param y client-area position, or <0 if unchanged
+ * @param width client-area size, or <=0 if unchanged
+ * @param height client-area size, or <=0 if unchanged
* @param flags bitfield of change and status flags
*
* @see #sizeChanged(int,int)
@@ -1488,21 +1503,33 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
display.dispatchMessagesNative(); // status up2date
boolean wasVisible = isVisible();
- reconfigureWindowImpl(x, y, w, h,
- getReconfigureFlags( ( ( 0 != parentWindowHandle ) ? FLAG_CHANGE_PARENTING : 0 ) |
- FLAG_CHANGE_FULLSCREEN | FLAG_CHANGE_DECORATION, wasVisible) );
+ // Lock parentWindow only during reparenting (attempt)
+ final NativeWindow parentWindowLocked;
+ if( null != parentWindow ) {
+ parentWindowLocked = parentWindow;
+ if( NativeSurface.LOCK_SURFACE_NOT_READY >= parentWindowLocked.lockSurface() ) {
+ throw new NativeWindowException("Parent surface lock: not ready: "+parentWindow);
+ }
+ } else {
+ parentWindowLocked = null;
+ }
+ try {
+ reconfigureWindowImpl(x, y, w, h,
+ getReconfigureFlags( ( ( null != parentWindowLocked ) ? FLAG_CHANGE_PARENTING : 0 ) |
+ FLAG_CHANGE_FULLSCREEN | FLAG_CHANGE_DECORATION, wasVisible) );
+ } finally {
+ if(null!=parentWindowLocked) {
+ parentWindowLocked.unlockSurface();
+ }
+ }
display.dispatchMessagesNative(); // status up2date
-
+
if(wasVisible) {
- // visibility should be implicit if needed by native impl,
- // however .. this is a little fallback code
- if(!WindowImpl.this.waitForVisible(true, true, TIMEOUT_NATIVEWINDOW)) {
- setVisibleImpl(true, x, y, w, h);
- WindowImpl.this.waitForVisible(true, true, TIMEOUT_NATIVEWINDOW);
- display.dispatchMessagesNative(); // status up2date
- }
- // ensure size is set, request focus .. and done
+ setVisibleImpl(true, x, y, w, h);
+ WindowImpl.this.waitForVisible(true, false);
+ display.dispatchMessagesNative(); // status up2date
WindowImpl.this.waitForPosSize(-1, -1, w, h, false, TIMEOUT_NATIVEWINDOW);
+ display.dispatchMessagesNative(); // status up2date
requestFocusImpl(true);
display.dispatchMessagesNative(); // status up2date
@@ -2047,16 +2074,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
DisplayImpl display = (DisplayImpl) screen.getDisplay();
for(long sleep = timeOut; 0<sleep && this.visible != visible; sleep-=10 ) {
display.dispatchMessagesNative(); // status up2date
- try {
- Thread.sleep(10);
- } catch (InterruptedException ie) {}
+ try { Thread.sleep(10); } catch (InterruptedException ie) {}
sleep -=10;
}
if(this.visible != visible) {
+ final String msg = "Visibility not reached as requested within "+timeOut+"ms : requested "+visible+", is "+this.visible;
if(failFast) {
- throw new NativeWindowException("Visibility not reached as requested within "+timeOut+"ms : requested "+visible+", is "+this.visible);
+ throw new NativeWindowException(msg);
} else if (DEBUG_IMPLEMENTATION) {
- System.err.println("******* Visibility not reached as requested within "+timeOut+"ms : requested "+visible+", is "+this.visible);
+ System.err.println(msg);
}
}
return this.visible == visible;
@@ -2091,17 +2117,39 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
reached = true;
} else {
display.dispatchMessagesNative(); // status up2date
- try {
- Thread.sleep(10);
- } catch (InterruptedException ie) {}
+ try { Thread.sleep(10); } catch (InterruptedException ie) {}
+ sleep -=10;
+ }
+ }
+ if(!reached) {
+ final String msg = "Size/Pos not reached as requested within "+timeOut+"ms : requested "+x+"/"+y+" "+w+"x"+h+", is "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight();
+ if(failFast) {
+ throw new NativeWindowException(msg);
+ } else if (DEBUG_IMPLEMENTATION) {
+ System.err.println(msg);
+ }
+ }
+ return reached;
+ }
+
+ private boolean waitForAnyPos(boolean failFast, long timeOut) {
+ DisplayImpl display = (DisplayImpl) screen.getDisplay();
+ boolean reached = false;
+ for(long sleep = timeOut; !reached && 0<sleep; sleep-=10 ) {
+ if( 0<=getX() && 0<=getY() ) {
+ reached = true;
+ } else {
+ display.dispatchMessagesNative(); // status up2date
+ try { Thread.sleep(10); } catch (InterruptedException ie) {}
sleep -=10;
}
}
if(!reached) {
+ final String msg = "Any Pos not reached as requested within "+timeOut+"ms : is "+getX()+"/"+getY();
if(failFast) {
- throw new NativeWindowException("Size/Pos not reached as requested within "+timeOut+"ms : requested "+x+"/"+y+" "+w+"x"+h+", is "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight());
+ throw new NativeWindowException(msg);
} else if (DEBUG_IMPLEMENTATION) {
- System.err.println("********** Size/Pos not reached as requested within "+timeOut+"ms : requested "+x+"/"+y+" "+w+"x"+h+", is "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight());
+ System.err.println(msg);
}
}
return reached;
diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java b/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java
index a78014468..7dd67e62b 100644
--- a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java
+++ b/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java
@@ -156,14 +156,18 @@ public class WindowsWindow extends WindowImpl {
final InsetsImmutable i = getInsets();
// client position -> top-level window position
- x -= i.getLeftWidth() ;
- y -= i.getTopHeight() ;
- if( 0 > x ) { x = 0; }
- if( 0 > y ) { y = 0; }
+ if(0<=x && 0<=y) {
+ x -= i.getLeftWidth() ;
+ y -= i.getTopHeight() ;
+ if( 0 > x ) { x = 0; }
+ if( 0 > y ) { y = 0; }
+ }
- // client size -> top-level window size
- width += i.getTotalWidth();
- height += i.getTotalHeight();
+ if(0<width && 0<height) {
+ // client size -> top-level window size
+ width += i.getTotalWidth();
+ height += i.getTotalHeight();
+ }
}
reconfigureWindow0( getParentWindowHandle(), getWindowHandle(), x, y, width, height, flags);
diff --git a/src/newt/classes/jogamp/newt/driver/x11/X11Window.java b/src/newt/classes/jogamp/newt/driver/x11/X11Window.java
index 416bdbdf0..3c48ba4bf 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/X11Window.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/X11Window.java
@@ -34,6 +34,8 @@
package jogamp.newt.driver.x11;
import jogamp.nativewindow.x11.X11Util;
+import jogamp.newt.DisplayImpl;
+import jogamp.newt.DisplayImpl.DisplayRunnable;
import jogamp.newt.WindowImpl;
import javax.media.nativewindow.*;
import javax.media.nativewindow.x11.*;
@@ -99,7 +101,7 @@ public class X11Window extends WindowImpl {
getReconfigureFlagsAsString(null, flags));
}
- if(0 == ( FLAG_IS_UNDECORATED & flags)) {
+ if(0 == ( FLAG_IS_UNDECORATED & flags) && 0<=x && 0<=y) {
final InsetsImmutable i = getInsets();
// client position -> top-level window position
@@ -119,12 +121,18 @@ public class X11Window extends WindowImpl {
}
@Override
- protected void setTitleImpl(String title) {
- setTitle0(getDisplayEDTHandle(), getWindowHandle(), title);
+ protected void setTitleImpl(final String title) {
+ runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() {
+ public Object run(long dpy) {
+ setTitle0(dpy, getWindowHandle(), title);
+ return null;
+ }
+ });
}
- protected Point getLocationOnScreenImpl(int x, int y) {
- return X11Util.GetRelativeLocation( getDisplayEDTHandle(), getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y);
+ protected Point getLocationOnScreenImpl(final int x, final int y) {
+ // X11Util.GetRelativeLocation: locks display already !
+ return X11Util.GetRelativeLocation( getScreen().getDisplay().getHandle(), getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y);
}
protected void updateInsetsImpl(Insets insets) {
@@ -138,6 +146,10 @@ public class X11Window extends WindowImpl {
private final long getDisplayEDTHandle() {
return ((X11Display) getScreen().getDisplay()).getEDTHandle();
}
+ private final Object runWithLockedDisplayHandle(DisplayRunnable action) {
+ return ((DisplayImpl) getScreen().getDisplay()).runWithLockedDisplayHandle(action);
+ // return runWithTempDisplayHandle(action);
+ }
protected static native boolean initIDs0();
private native long CreateWindow0(long parentWindowHandle, long display, int screen_index,
diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c
index 900b5a037..1cb0f2036 100644
--- a/src/newt/native/WindowsWindow.c
+++ b/src/newt/native/WindowsWindow.c
@@ -1284,6 +1284,33 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_getNewtWnd
return (jlong) (intptr_t) wndProc;
}
+static void NewtWindow_setVisiblePosSize(HWND hwnd, BOOL top, BOOL visible,
+ int x, int y, int width, int height)
+{
+ UINT flags;
+ BOOL bRes;
+
+ DBG_PRINT("*** WindowsWindow: NewtWindow_setVisiblePosSize %d/%d %dx%d, top %d, visible %d\n",
+ x, y, width, height, top, visible);
+
+ if(visible) {
+ flags = SWP_SHOWWINDOW;
+ } else {
+ flags = SWP_NOACTIVATE | SWP_NOZORDER;
+ }
+ if(0>x || 0>y) {
+ flags |= SWP_NOMOVE;
+ }
+ if(0>=width || 0>=height ) {
+ flags |= SWP_NOSIZE;
+ }
+
+ SetWindowPos(hwnd, top ? HWND_TOPMOST : HWND_TOP, x, y, width, height, flags);
+
+ InvalidateRect(hwnd, NULL, TRUE);
+ UpdateWindow(hwnd);
+}
+
/*
* Class: jogamp_newt_driver_windows_WindowsWindow
* Method: CreateWindow
@@ -1301,6 +1328,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_CreateWind
int x=(int)jx, y=(int)jy;
int width=(int)defaultWidth, height=(int)defaultHeight;
HWND window = NULL;
+ int _x = x, _y = y; // pos for CreateWindow, might be tweaked
#ifdef UNICODE
wndClassName = NewtCommon_GetNullTerminatedStringChars(env, jWndClassName);
@@ -1310,6 +1338,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_CreateWind
wndName = (*env)->GetStringUTFChars(env, jWndName, NULL);
#endif
+
if(NULL!=parentWindow) {
if (!IsWindow(parentWindow)) {
DBG_PRINT("*** WindowsWindow: CreateWindow failure: Passed parentWindow %p is invalid\n", parentWindow);
@@ -1320,14 +1349,17 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_CreateWind
windowStyle |= WS_POPUP | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
} else {
windowStyle |= WS_OVERLAPPEDWINDOW;
- x = CW_USEDEFAULT;
- y = 0;
+ if(0>_x || 0>_y) {
+ // user didn't requested specific position, use WM default
+ _x = CW_USEDEFAULT;
+ _y = 0;
+ }
}
(void) visualID; // FIXME: use the visualID ..
window = CreateWindow(wndClassName, wndName, windowStyle,
- x, y, width, height,
+ _x, _y, width, height,
parentWindow, NULL,
(HINSTANCE) (intptr_t) hInstance,
NULL);
@@ -1348,7 +1380,37 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_CreateWind
#else
SetWindowLongPtr(window, GWLP_USERDATA, (intptr_t) wud);
#endif
- (void)UpdateInsets(env, wud->jinstance, window);
+
+ // gather and adjust position and size
+ {
+ RECT rc;
+ RECT * insets;
+ BOOL userPos = 0<=x && 0<=y ;
+
+ ShowWindow(window, SW_SHOW);
+ (*env)->CallVoidMethod(env, wud->jinstance, visibleChangedID, JNI_TRUE);
+
+ insets = UpdateInsets(env, wud->jinstance, window);
+ if(!userPos) {
+ GetWindowRect(window, &rc);
+ x = rc.left + insets->left; // client coords
+ y = rc.top + insets->top; // client coords
+ }
+ DBG_PRINT("*** WindowsWindow: CreateWindow client: %d/%d %dx%d (is user-pos %d)\n", x, y, width, height, userPos);
+
+ x -= insets->left; // top-level
+ y -= insets->top; // top-level
+ width += insets->left + insets->right; // top-level
+ height += insets->top + insets->bottom; // top-level
+ DBG_PRINT("*** WindowsWindow: CreateWindow top-level %d/%d %dx%d\n", x, y, width, height);
+
+ if(userPos) {
+ // mark pos as undef, which cases java to wait for WM reported pos
+ (*env)->CallVoidMethod(env, wud->jinstance, positionChangedID, -1, -1);
+ }
+ NewtWindow_setVisiblePosSize(window, (NULL == parentWindow) ? TRUE : FALSE /* top */,
+ TRUE, x, y, width, height);
+ }
}
#ifdef UNICODE
@@ -1377,28 +1439,6 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_MonitorFro
#endif
}
-void NewtWindow_setVisiblePosSize(JNIEnv *env, jobject obj, HWND hwnd,
- BOOL top, BOOL undecorated, BOOL visible,
- int x, int y, int width, int height)
-{
- UINT flags;
- BOOL bRes;
-
- DBG_PRINT("*** WindowsWindow: NewtWindow_setVisiblePosSize %d/%d %dx%d, top %d, undecorated %d, visible %d\n",
- x, y, width, height, top, undecorated, visible);
-
- if(visible) {
- flags = SWP_SHOWWINDOW;
- } else {
- flags = SWP_NOACTIVATE | SWP_NOZORDER;
- }
-
- SetWindowPos(hwnd, top ? HWND_TOPMOST : HWND_TOP, x, y, width, height, flags);
-
- InvalidateRect(hwnd, NULL, TRUE);
- UpdateWindow(hwnd);
-}
-
static jboolean NewtWindows_setFullScreen(jboolean fullscreen)
{
int flags = 0;
@@ -1488,8 +1528,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_reconfigure
SetParent(hwnd, hwndP );
}
- NewtWindow_setVisiblePosSize(env, obj, hwnd, (NULL == hwndP) ? JNI_TRUE : JNI_FALSE /* top */,
- TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_IS_VISIBLE(flags), x, y, width, height);
+ NewtWindow_setVisiblePosSize(hwnd, (NULL == hwndP) ? TRUE : FALSE /* top */,
+ TST_FLAG_IS_VISIBLE(flags), x, y, width, height);
if( TST_FLAG_CHANGE_VISIBILITY(flags) ) {
if( TST_FLAG_IS_VISIBLE(flags) ) {
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c
index 092f3f7d3..39e8f9476 100644
--- a/src/newt/native/X11Window.c
+++ b/src/newt/native/X11Window.c
@@ -336,10 +336,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_DisplayRelease0
if(dpy==NULL) {
NewtCommon_FatalError(env, "invalid display connection..");
}
+
// nothing to do to free the atoms !
(void) wm_javaobject_atom;
(void) wm_delete_atom;
+ XSync(dpy, True); // discard all pending events
DBG_PRINT("X11: X11Display_DisplayRelease dpy %p\n", dpy);
}
@@ -523,6 +525,14 @@ static Status NewtWindows_updateInsets(JNIEnv *env, jobject jwindow, Display *dp
return 0; // Error
}
+static void NewtWindows_setCWAbove(Display *dpy, Window w) {
+ XWindowChanges xwc;
+ memset(&xwc, 0, sizeof(XWindowChanges));
+ xwc.stack_mode = Above;
+ XConfigureWindow(dpy, w, CWStackMode, &xwc);
+ XSync(dpy, False);
+}
+
static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, Window w, jboolean force) {
XWindowAttributes xwa;
Window focus_return;
@@ -535,6 +545,7 @@ static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy,
if( JNI_TRUE==force || JNI_FALSE == (*env)->CallBooleanMethod(env, window, focusActionID) ) {
DBG_PRINT( "X11: XRaiseWindow dpy %p,win %pd\n", dpy, (void*)w);
XRaiseWindow(dpy, w);
+ NewtWindows_setCWAbove(dpy, w);
// Avoid 'BadMatch' errors from XSetInputFocus, ie if window is not viewable
XGetWindowAttributes(dpy, w, &xwa);
if(xwa.map_state == IsViewable) {
@@ -573,40 +584,112 @@ static void NewtWindows_setDecorations (Display *dpy, Window w, Bool decorated)
#define _NET_WM_STATE_REMOVE 0
#define _NET_WM_STATE_ADD 1
-static void NewtWindows_setFullscreen (Display *dpy, Window root, Window w, Bool fullscreen) {
+#define _NET_WM_ACTION_FULLSCREEN_SUPPORTED ( 1 << 0 )
+#define _NET_WM_ACTION_ABOVE_SUPPORTED ( 1 << 1 )
+
+/**
+ * Set fullscreen using Extended Window Manager Hints (EWMH)
+ *
+ * Be aware that _NET_WM_STATE_FULLSCREEN requires a mapped window
+ * which shall be on the top of the stack to wor reliable.
+ *
+ * The WM will internally save the size and position when entering FS
+ * and resets it when leaving FS.
+ * The same is assumed for the decoration state.
+ */
+static int NewtWindows_isFullscreenEWMHSupported (Display *dpy, Window w) {
+ 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 );
+ Atom * actions;
+ Atom type;
+ unsigned long action_len, remain;
+ int res = 0, form, i;
+ Status s;
+
+ if ( Success == (s = XGetWindowProperty(dpy, w, _NET_WM_ALLOWED_ACTIONS, 0, 1024, False, AnyPropertyType,
+ &type, &form, &action_len, &remain, (unsigned char**)&actions)) ) {
+ 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_ACTION_FULLSCREEN_SUPPORTED ;
+ } else if(_NET_WM_ACTION_ABOVE == actions[i]) {
+ DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: _NET_WM_ACTION_ABOVE (*)\n", i);
+ res |= _NET_WM_ACTION_ABOVE_SUPPORTED ;
+ }
+#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_ACTION_FULLSCREEN_SUPPORTED | _NET_WM_ACTION_ABOVE_SUPPORTED ;
+ return res;
+}
+
+static Bool NewtWindows_setFullscreenEWMH (Display *dpy, Window root, Window w, int emwhMask, Bool isVisible, Bool fullscreen) {
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 );
-
- Atom types[2]={0};
- int ntypes=0;
+ Status s = Success;
+
+ if(0 == emwhMask) {
+ return False;
+ }
- types[ntypes++] = _NET_WM_STATE_FULLSCREEN;
- types[ntypes++] = _NET_WM_STATE_ABOVE;
+ if(!isVisible) {
+ if(True==fullscreen) {
+ // Update Client State first (-> ABOVE)
+ Atom types[2]={0};
+ int ntypes=0;
- XEvent xev;
- memset ( &xev, 0, sizeof(xev) );
-
- xev.type = ClientMessage;
- xev.xclient.window = w;
- xev.xclient.message_type = _NET_WM_STATE;
- xev.xclient.format = 32;
-
- if(True==fullscreen) {
- xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
- xev.xclient.data.l[1] = _NET_WM_STATE_FULLSCREEN;
- xev.xclient.data.l[2] = _NET_WM_STATE_ABOVE;
- xev.xclient.data.l[3] = 1; //source indication for normal applications
- XChangeProperty( dpy, w, _NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, ntypes);
+ if( 0 != ( _NET_WM_ACTION_FULLSCREEN_SUPPORTED & emwhMask ) ) {
+ types[ntypes++] = _NET_WM_STATE_FULLSCREEN;
+ }
+ if( 0 != ( _NET_WM_ACTION_ABOVE_SUPPORTED & emwhMask ) ) {
+ types[ntypes++] = _NET_WM_STATE_ABOVE;
+ }
+ XChangeProperty( dpy, w, _NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, ntypes);
+ XSync(dpy, False);
+ DBG_PRINT( "X11: reconfigureWindow0 FULLSCREEN Old on:%d (xsend-status %d)\n", fullscreen, s);
+ }
} else {
- xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
- xev.xclient.data.l[1] = _NET_WM_STATE_FULLSCREEN;
- xev.xclient.data.l[2] = _NET_WM_STATE_ABOVE;
- xev.xclient.data.l[3] = 1; //source indication for normal applications
- }
+ if(fullscreen) {
+ NewtWindows_setCWAbove(dpy, w);
+ }
+ XEvent xev;
+ long mask = SubstructureNotifyMask | SubstructureRedirectMask ;
+ const int src_i = 1; //source indication for normal applications
+ 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;
+
+ xev.xclient.data.l[i++] = ( True == fullscreen ) ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE ;
+ if( 0 != ( _NET_WM_ACTION_FULLSCREEN_SUPPORTED & emwhMask ) ) {
+ xev.xclient.data.l[i++] = _NET_WM_STATE_FULLSCREEN;
+ }
+ if( 0 != ( _NET_WM_ACTION_ABOVE_SUPPORTED & emwhMask ) ) {
+ xev.xclient.data.l[i++] = _NET_WM_STATE_ABOVE;
+ }
+ xev.xclient.data.l[3] = src_i;
+ s = XSendEvent (dpy, root, False, mask, &xev );
+ }
XSync(dpy, False);
- XSendEvent (dpy, root, False, SubstructureRedirectMask | SubstructureNotifyMask, &xev );
+ DBG_PRINT( "X11: reconfigureWindow0 FULLSCREEN EWMH ON %d, emwhMask 0x%X, visible %d (xsend-status %d)\n", fullscreen, emwhMask, isVisible, s);
+ return Success == s;
}
#define USE_SENDIO_DIRECT 1
@@ -1369,6 +1452,35 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Window_initIDs0
return JNI_TRUE;
}
+static Bool WaitForMapNotify( Display *dpy, XEvent *event, XPointer arg ) {
+ return (event->type == MapNotify) && (event->xmap.window == (Window) arg);
+}
+
+static Bool WaitForUnmapNotify( Display *dpy, XEvent *event, XPointer arg ) {
+ return (event->type == UnmapNotify) && (event->xmap.window == (Window) arg);
+}
+
+static void NewtWindows_setPosSize(Display *dpy, Window w, jint x, jint y, jint width, jint height) {
+ if(width>0 && height>0 || x>=0 && y>=0) { // resize/position if requested
+ XWindowChanges xwc;
+ int flags = 0;
+
+ memset(&xwc, 0, sizeof(XWindowChanges));
+ if(0<=x && 0<=y) {
+ flags |= CWX | CWY;
+ xwc.x=x;
+ xwc.y=y;
+ }
+ if(0<width && 0<height) {
+ flags |= CWWidth | CWHeight;
+ xwc.width=width;
+ xwc.height=height;
+ }
+ XConfigureWindow(dpy, w, flags, &xwc);
+ XSync(dpy, False);
+ }
+}
+
/*
* Class: jogamp_newt_driver_x11_X11Window
* Method: CreateWindow
@@ -1466,16 +1578,24 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0
visual,
AllocNone);
- window = XCreateWindow(dpy,
- windowParent,
- x, y,
- width, height,
- 0, // border width
- depth,
- InputOutput,
- visual,
- attrMask,
- &xswa);
+ {
+ int _x = x, _y = y; // pos for CreateWindow, might be tweaked
+ if(0>_x || 0>_y) {
+ // user didn't requested specific position, use WM default
+ _x = 0;
+ _y = 0;
+ }
+ window = XCreateWindow(dpy,
+ windowParent,
+ _x, _y, // only a hint, WM most likely will override
+ width, height,
+ 0, // border width
+ depth,
+ InputOutput,
+ visual,
+ attrMask,
+ &xswa);
+ }
if(0==window) {
NewtCommon_throwNewRuntimeException(env, "could not create Window, bail out!");
@@ -1490,13 +1610,36 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0
XSync(dpy, False);
// since native creation happens at setVisible(true) ..
- // we can pre-map the window here to be able to gather the insets.
- XMapWindow(dpy, window);
- XSync(dpy, False);
+ // we can pre-map the window here to be able to gather the insets and position.
{
- // update insets
+ XEvent event;
int left, right, top, bottom;
+ Bool userPos = 0<=x && 0<=y ;
+
+ XMapWindow(dpy, window);
+ XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) window ); // wait to get proper insets values
+ (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_TRUE);
+
NewtWindows_updateInsets(env, jwindow, dpy, window, &left, &right, &top, &bottom);
+ if(!userPos) {
+ // get position from WM
+ int dest_x, dest_y;
+ Window child;
+ XTranslateCoordinates(dpy, window, windowParent, 0, 0, &dest_x, &dest_y, &child);
+ x = (int)dest_x; y = (int)dest_y;
+ }
+ DBG_PRINT("X11: [CreateWindow]: client: %d/%d %dx%d (is user-pos %d)\n", x, y, width, height, userPos);
+
+ x -= left; // top-level
+ y -= top; // top-level
+ if(0>x) { x = 0; }
+ if(0>y) { y = 0; }
+ DBG_PRINT("X11: [CreateWindow]: top-level: %d/%d\n", x, y);
+ if(userPos) {
+ // mark pos as undef, which cases java to wait for WM reported pos
+ (*env)->CallVoidMethod(env, jwindow, positionChangedID, -1, -1);
+ }
+ NewtWindows_setPosSize(dpy, window, x, y, width, height);
}
DBG_PRINT( "X11: [CreateWindow] created window %p on display %p\n", (void*)window, dpy);
@@ -1547,31 +1690,6 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_CloseWindow0
DBG_PRINT( "X11: CloseWindow END\n");
}
-static void NewtWindows_setPosSize(Display *dpy, int screen_index, Window w, jint x, jint y, jint width, jint height, Bool undecorated)
-{
- if(width>0 && height>0 || x>=0 && y>=0) { // resize/position if requested
- XWindowChanges xwc;
-
- DBG_PRINT( "X11: reconfigureWindow0 %d/%d %dx%d\n", x, y, width, height);
-
- memset(&xwc, 0, sizeof(XWindowChanges));
- xwc.x=x;
- xwc.y=y;
- xwc.width=width;
- xwc.height=height;
- XConfigureWindow(dpy, w, (CWX | CWY | CWWidth | CWHeight), &xwc);
- XSync(dpy, False);
- }
-}
-
-static Bool WaitForMapNotify( Display *dpy, XEvent *event, XPointer arg ) {
- return (event->type == MapNotify) && (event->xmap.window == (Window) arg);
-}
-
-static Bool WaitForUnmapNotify( Display *dpy, XEvent *event, XPointer arg ) {
- return (event->type == UnmapNotify) && (event->xmap.window == (Window) arg);
-}
-
/*
* Class: jogamp_newt_driver_x11_X11Window
* Method: reconfigureWindow0
@@ -1582,33 +1700,42 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0
jint x, jint y, jint width, jint height, jint flags)
{
Display * dpy = (Display *) (intptr_t) jdisplay;
- Screen * scrn = ScreenOfDisplay(dpy, (int)screen_index);
Window w = (Window)jwindow;
- Window root = XRootWindowOfScreen(scrn);
+ Window root = RootWindow(dpy, screen_index);
Window parent = (0!=jparent)?(Window)jparent:root;
- Window topParentParent;
- Window topParentWindow;
XEvent event;
- Bool tempInvisible = ( TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_PARENTING(flags) ) &&
- !TST_FLAG_CHANGE_VISIBILITY(flags) && TST_FLAG_IS_VISIBLE(flags) ;
+ 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 ;
+ int fsEWMHMask = TST_FLAG_CHANGE_FULLSCREEN(flags) ? NewtWindows_isFullscreenEWMHSupported(dpy, w) : 0;
displayDispatchErrorHandlerEnable(1, env);
- topParentParent = NewtWindows_getParent (dpy, parent);
- topParentWindow = NewtWindows_getParent (dpy, w);
-
- DBG_PRINT( "X11: reconfigureWindow0 dpy %p, scrn %d/%p, parent %p/%p (top %p), win %p (top %p), %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d, visibleChange %d, visible %d, tempInvisible %d\n",
- (void*)dpy, screen_index, (void*)scrn, (void*) jparent, (void*)parent, (void*) topParentParent, (void*)w, (void*)topParentWindow,
+ 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, visibleChange %d, visible %d, tempInvisible %d, fsEWMHMask %d\n",
+ (void*)dpy, screen_index, (void*) jparent, (void*)parent, (void*)w,
x, y, width, height,
TST_FLAG_CHANGE_PARENTING(flags), TST_FLAG_HAS_PARENT(flags),
TST_FLAG_CHANGE_DECORATION(flags), TST_FLAG_IS_UNDECORATED(flags),
TST_FLAG_CHANGE_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN(flags),
- TST_FLAG_CHANGE_VISIBILITY(flags), TST_FLAG_IS_VISIBLE(flags), tempInvisible);
+ TST_FLAG_CHANGE_VISIBILITY(flags), TST_FLAG_IS_VISIBLE(flags), tempInvisible, fsEWMHMask);
+
+ // FS Note: To toggle FS, utilizing the _NET_WM_STATE_FULLSCREEN WM state shall be enough.
+ // However, we have to consider other cases like reparenting and WM which don't support it.
+
+ if( fsEWMHMask && TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_CHANGE_PARENTING(flags) && isVisible ) {
+ NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHMask, isVisible, TST_FLAG_IS_FULLSCREEN(flags));
+ displayDispatchErrorHandlerEnable(0, env);
+ return;
+ }
+
+ if( fsEWMHMask && TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) { // FS off
+ NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHMask, isVisible, True);
+ }
if( tempInvisible ) {
DBG_PRINT( "X11: reconfigureWindow0 TEMP VISIBLE OFF\n");
XUnmapWindow(dpy, w);
XIfEvent( dpy, &event, WaitForUnmapNotify, (XPointer) w );
+ // no need to notify the java side .. just temp change
}
if( TST_FLAG_CHANGE_PARENTING(flags) && !TST_FLAG_HAS_PARENT(flags) ) {
@@ -1618,26 +1745,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0
XSync(dpy, False);
}
- if( TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags) ) { // FS on
- // TOP: in -> out
- DBG_PRINT( "X11: reconfigureWindow0 FULLSCREEN in->out\n");
- NewtWindows_setFullscreen(dpy, root, w, True );
- XSync(dpy, False);
- }
-
- DBG_PRINT( "X11: reconfigureWindow0 DECORATIONS\n");
+ DBG_PRINT( "X11: reconfigureWindow0 DECORATIONS %d\n", !TST_FLAG_IS_UNDECORATED(flags));
NewtWindows_setDecorations (dpy, w, TST_FLAG_IS_UNDECORATED(flags) ? False : True);
XSync(dpy, False);
- if( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) { // FS off
- // CHILD: out -> in
- DBG_PRINT( "X11: reconfigureWindow0 FULLSCREEN out->in\n");
- NewtWindows_setFullscreen(dpy, root, w, False );
- XSync(dpy, False);
- }
-
- DBG_PRINT( "X11: reconfigureWindow0 setPosSize\n");
- NewtWindows_setPosSize(dpy, screen_index, w, x, y, width, height, TST_FLAG_IS_UNDECORATED(flags) ? True : False);
+ DBG_PRINT( "X11: reconfigureWindow0 setPosSize %d/%d %dx%d\n", x, y, width, height);
+ NewtWindows_setPosSize(dpy, w, x, y, width, height);
if( TST_FLAG_CHANGE_PARENTING(flags) && TST_FLAG_HAS_PARENT(flags) ) {
// CHILD: out -> in
@@ -1650,6 +1763,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0
DBG_PRINT( "X11: reconfigureWindow0 TEMP VISIBLE ON\n");
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) ) {
@@ -1663,6 +1777,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0
XSync(dpy, False);
}
+ if( fsEWMHMask && TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags) ) { // FS on
+ NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHMask, isVisible, True);
+ }
+
displayDispatchErrorHandlerEnable(0, env);
DBG_PRINT( "X11: reconfigureWindow0 X\n");