diff options
Diffstat (limited to 'src/newt')
-rw-r--r-- | src/newt/classes/jogamp/newt/WindowImpl.java | 141 | ||||
-rw-r--r-- | src/newt/native/WindowsWindow.c | 12 | ||||
-rw-r--r-- | src/newt/native/X11Window.c | 67 |
3 files changed, 138 insertions, 82 deletions
diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index 611af3d21..86aa548d0 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -692,9 +692,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } finally { windowLock.unlock(); } - if( nativeWindowCreated || madeVisible ) { - sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener - } } private class VisibleAction implements Runnable { @@ -799,7 +796,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer return; // nop } - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + if(DEBUG_IMPLEMENTATION) { String msg = "!!! Window DestroyAction() "+getThreadName(); System.err.println(msg); } @@ -1084,11 +1081,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } boolean ok = false; try { - // write back mirrored values, to be able to detect satisfaction - WindowImpl.this.x = x; - WindowImpl.this.y = y; - WindowImpl.this.width = width; - WindowImpl.this.height = height; ok = reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(FLAG_CHANGE_PARENTING | FLAG_CHANGE_DECORATION, isVisible())); } finally { if(null!=parentWindowLocked) { @@ -1103,15 +1095,17 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer setVisibleImpl(true, x, y, width, height); ok = WindowImpl.this.waitForVisible(true, false); display.dispatchMessagesNative(); // status up2date + if(ok) { + ok = WindowImpl.this.waitForPosSize(-1, -1, width, height, false, TIMEOUT_NATIVEWINDOW); + } + if(ok) { + requestFocusImpl(true); + display.dispatchMessagesNative(); // status up2date + } } } - if(ok) { - if(wasVisible) { - requestFocusImpl(true); - display.dispatchMessagesNative(); // status up2date - } - } else { + if(!ok) { // native reparent failed -> try creation if(DEBUG_IMPLEMENTATION) { System.err.println("Window.reparent: native reparenting failed ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+" -> "+toHexString(newParentWindowHandle)+" - Trying recreation"); @@ -1120,33 +1114,20 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer reparentAction = ACTION_NATIVE_CREATION ; } } - - // write back mirrored values, ensuring persistence - // and not relying on native messaging - WindowImpl.this.x = x; - WindowImpl.this.y = y; - WindowImpl.this.width = width; - WindowImpl.this.height = height; - + if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.reparentWindow: END ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+ Display.hashCodeNullSafe(parentWindow)+" "+x+"/"+y+" "+width+"x"+height); + System.err.println("Window.reparentWindow: END-1 ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+ Display.hashCodeNullSafe(parentWindow)+" "+x+"/"+y+" "+width+"x"+height); } } finally { windowLock.unlock(); } - if(wasVisible) { - switch (reparentAction) { - case ACTION_NATIVE_REPARENTING: - // trigger a resize/relayout and repaint to listener - sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); - break; - - case ACTION_NATIVE_CREATION: - // This may run on the new Display/Screen connection, hence a new EDT task - runOnEDTIfAvail(true, reparentActionRecreate); - break; - } + if(wasVisible && ACTION_NATIVE_CREATION == reparentAction) { + // This may run on the new Display/Screen connection, hence a new EDT task + runOnEDTIfAvail(true, reparentActionRecreate); + } + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window.reparentWindow: END-X ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+ Display.hashCodeNullSafe(parentWindow)+" "+x+"/"+y+" "+width+"x"+height); } } } @@ -1238,14 +1219,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer DisplayImpl display = (DisplayImpl) screen.getDisplay(); display.dispatchMessagesNative(); // status up2date reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(FLAG_CHANGE_DECORATION, isVisible())); - display.dispatchMessagesNative(); // status up2date + display.dispatchMessagesNative(); // status up2date } } } } finally { windowLock.unlock(); } - sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener } } @@ -1352,12 +1332,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer sb.append(getClass().getName()+"[Config "+config+ "\n, "+screen+ "\n, ParentWindow "+parentWindow+ - "\n, ParentWindowHandle "+toHexString(parentWindowHandle)+ + "\n, ParentWindowHandle "+toHexString(parentWindowHandle)+" ("+(0!=getParentWindowHandle())+")"+ "\n, WindowHandle "+toHexString(getWindowHandle())+ "\n, SurfaceHandle "+toHexString(getSurfaceHandle())+ " (lockedExt window "+isWindowLockedByOtherThread()+", surface "+isSurfaceLockedByOtherThread()+")"+ "\n, Pos "+getX()+"/"+getY()+", size "+getWidth()+"x"+getHeight()+ "\n, Visible "+isVisible()+ - "\n, Undecorated "+undecorated+ + "\n, Undecorated "+undecorated+" ("+isUndecorated()+")"+ "\n, Fullscreen "+fullscreen+ "\n, WrappedWindow "+getWrappedWindow()+ "\n, ChildWindows "+childWindows.size()); @@ -1498,43 +1478,55 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer y = nfs_y; w = nfs_width; h = nfs_height; + + if(null!=parentWindow) { + // reset position to 0/0 within parent space + x = 0; + y = 0; + + // refit if size is bigger than parent + if( w > parentWindow.getWidth() ) { + w = parentWindow.getWidth(); + } + if( h > parentWindow.getHeight() ) { + h = parentWindow.getHeight(); + } + } } - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + if(DEBUG_IMPLEMENTATION) { System.err.println("Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()+", "+screen); } DisplayImpl display = (DisplayImpl) screen.getDisplay(); display.dispatchMessagesNative(); // status up2date boolean wasVisible = isVisible(); - setVisibleImpl(false, x, y, w, h); - WindowImpl.this.waitForVisible(false, true); - display.dispatchMessagesNative(); // status up2date - // write back mirrored values, to be able to detect satisfaction - WindowImpl.this.x = x; - WindowImpl.this.y = y; - WindowImpl.this.width = w; - WindowImpl.this.height = h; - reconfigureWindowImpl(x, y, width, height, + reconfigureWindowImpl(x, y, w, h, getReconfigureFlags( ( ( 0 != parentWindowHandle ) ? FLAG_CHANGE_PARENTING : 0 ) | - FLAG_CHANGE_FULLSCREEN | FLAG_CHANGE_DECORATION, isVisible()) ); + FLAG_CHANGE_FULLSCREEN | FLAG_CHANGE_DECORATION, wasVisible) ); display.dispatchMessagesNative(); // status up2date if(wasVisible) { - setVisibleImpl(true, x, y, w, h); - WindowImpl.this.waitForVisible(true, true, Screen.SCREEN_MODE_CHANGE_TIMEOUT); - display.dispatchMessagesNative(); // status up2date + // 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 + WindowImpl.this.waitForPosSize(-1, -1, w, h, false, TIMEOUT_NATIVEWINDOW); requestFocusImpl(true); display.dispatchMessagesNative(); // status up2date - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - System.err.println("Window fs done"); + + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window fs done: " + WindowImpl.this); } } } } finally { windowLock.unlock(); } - sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener } } @@ -1549,7 +1541,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer boolean animatorPaused = false; public void screenModeChangeNotify(ScreenMode sm) { - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + if(DEBUG_IMPLEMENTATION) { System.err.println("Window.screenModeChangeNotify: "+sm); } @@ -1559,7 +1551,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } public void screenModeChanged(ScreenMode sm, boolean success) { - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + if(DEBUG_IMPLEMENTATION) { System.err.println("Window.screenModeChanged: "+sm+", success: "+success); } @@ -1574,7 +1566,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer if(animatorPaused) { lifecycleHook.resumeRenderingAction(); } - sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener } } @@ -2005,7 +1996,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } protected void consumeWindowEvent(WindowEvent e) { - if(DEBUG_WINDOW_EVENT) { + if(DEBUG_IMPLEMENTATION) { System.err.println("consumeWindowEvent: "+e+", visible "+isVisible()+" "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()); } for(int i = 0; i < windowListeners.size(); i++ ) { @@ -2101,6 +2092,34 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } + private boolean waitForPosSize(int x, int y, int w, int h, boolean failFast, long timeOut) { + DisplayImpl display = (DisplayImpl) screen.getDisplay(); + final boolean wpos = x>=0 && y>=0; + final boolean wsiz = w>0 && h>0; + boolean reached = false; + for(long sleep = timeOut; !reached && 0<sleep; sleep-=10 ) { + if( ( wpos && x==getX() && y==getY() || !wpos ) && + ( wsiz && w==getWidth() && h==getHeight() || !wsiz ) ) { + // reached pos/size + reached = true; + } else { + display.dispatchMessagesNative(); // status up2date + try { + Thread.sleep(10); + } catch (InterruptedException ie) {} + sleep -=10; + } + } + if(!reached) { + 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()); + } 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()); + } + } + return reached; + } + /** Triggered by implementation's WM events to update the position. */ protected void positionChanged(int newX, int newY) { if( 0==parentWindowHandle && ( x != newX || y != newY ) ) { diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index 9e635ef40..900b5a037 100644 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -1452,19 +1452,17 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_reconfigure windowStyle |= WS_VISIBLE ; } - if( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) { // FS off - NewtWindows_setFullScreen(JNI_FALSE); - } - // order of call sequence: (MS documentation) // TOP: SetParent(.., NULL); Clear WS_CHILD [, Set WS_POPUP] // CHILD: Set WS_CHILD [, Clear WS_POPUP]; SetParent(.., PARENT) // if( TST_FLAG_CHANGE_PARENTING(flags) && NULL == hwndP ) { + // TOP: in -> out SetParent(hwnd, NULL); } if( TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags) ) { // FS on + // TOP: in -> out NewtWindows_setFullScreen(JNI_TRUE); } @@ -1480,7 +1478,13 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_reconfigure SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER ); } + if( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) { // FS off + // CHILD: out -> in + NewtWindows_setFullScreen(JNI_FALSE); + } + if ( TST_FLAG_CHANGE_PARENTING(flags) && NULL != hwndP ) { + // CHILD: out -> in SetParent(hwnd, hwndP ); } diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index b6c239479..8d47f544a 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -1567,6 +1567,14 @@ static void NewtWindows_setPosSize(Display *dpy, int screen_index, Window w, jin } } +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 @@ -1583,56 +1591,81 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0 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) ; 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\n", + 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, 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)); + TST_FLAG_CHANGE_VISIBILITY(flags), TST_FLAG_IS_VISIBLE(flags), tempInvisible); - if( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) { // FS off - NewtWindows_setFullscreen(dpy, root, w, False ); + if( tempInvisible ) { + DBG_PRINT( "X11: reconfigureWindow0 TEMP VISIBLE OFF\n"); + XUnmapWindow(dpy, w); + XIfEvent( dpy, &event, WaitForUnmapNotify, (XPointer) w ); + } + + if( TST_FLAG_CHANGE_PARENTING(flags) && !TST_FLAG_HAS_PARENT(flags) ) { + // TOP: in -> out + DBG_PRINT( "X11: reconfigureWindow0 PARENTING in->out\n"); + XReparentWindow( dpy, w, parent, x, y ); // actual reparent call XSync(dpy, False); } - if( TST_FLAG_CHANGE_DECORATION(flags) && TST_FLAG_IS_UNDECORATED(flags) ) { - NewtWindows_setDecorations (dpy, w, 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); } - if( TST_FLAG_CHANGE_PARENTING(flags) ) { - XReparentWindow( dpy, w, parent, x, y ); // actual reparent call + DBG_PRINT( "X11: reconfigureWindow0 DECORATIONS\n"); + 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); - if( TST_FLAG_CHANGE_DECORATION(flags) && !TST_FLAG_IS_UNDECORATED(flags) ) { - NewtWindows_setDecorations (dpy, w, True); + if( TST_FLAG_CHANGE_PARENTING(flags) && TST_FLAG_HAS_PARENT(flags) ) { + // CHILD: out -> in + DBG_PRINT( "X11: reconfigureWindow0 PARENTING out->in\n"); + XReparentWindow( dpy, w, parent, x, y ); // actual reparent call XSync(dpy, False); } + if( tempInvisible ) { + DBG_PRINT( "X11: reconfigureWindow0 TEMP VISIBLE ON\n"); + XMapRaised(dpy, w); + XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) w ); + } + if( TST_FLAG_CHANGE_VISIBILITY(flags) ) { if( TST_FLAG_IS_VISIBLE(flags) ) { + DBG_PRINT( "X11: reconfigureWindow0 VISIBLE ON\n"); XMapRaised(dpy, w); } else { + DBG_PRINT( "X11: reconfigureWindow0 VISIBLE OFF\n"); XUnmapWindow(dpy, w); } XSync(dpy, False); } - NewtWindows_setPosSize(dpy, screen_index, w, x, y, width, height, TST_FLAG_IS_UNDECORATED(flags) ? True : False); - - if( TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags) ) { // FS on - NewtWindows_setFullscreen(dpy, root, w, True ); - XSync(dpy, False); - } - displayDispatchErrorHandlerEnable(0, env); DBG_PRINT( "X11: reconfigureWindow0 X\n"); |