diff options
author | Sven Gothel <[email protected]> | 2010-10-21 04:24:06 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2010-10-21 04:24:06 +0200 |
commit | 18bf27fa86da1f26fd085565f501736816d2f2e9 (patch) | |
tree | ca44458e4bb00b7969b77473ad93cd826c5ca6a7 /src/newt | |
parent | 6da90f18da639f942bce9dec7fdd9a6c43e22145 (diff) |
NEWT: Fix / Stabilize Fullscreen/Decoration/Reparenting Mode Changes
- setSizeImpl/setPositionImpl/reparent -> reconfigureWindowImpl
- setVisible(boolean) is state checked (500ms) for better reliability
on resource creation. Guarantees valid surface.
- reparentWindow: start pos of child -> top is current position on screen
- reparentWindow: Recheck success (setVisible), if failed fall back to recreate,
which gets rid of a lost child windows (1/20) ..
- reparentWindow: if size failed, reconfigure for size again
- add toggle decoration
- unify nfs_ size/pos state
- WindowsWindow.c/X11Window.c: Unify size/pos settings
- X11Window.c:
- NewtWindows_setFullscreen: use 'root of screen' instead of 'default root of display'
- Adding SubstructureNotifyMask incl event semantics
- Parse ReparentNotify (debugging of reparenting)
Misc:
- Add native getLocationOnScreen() impl to avoid possible AWT deadlock
- setSize/setPosition/setFullScreen -> EDT
- More documentation on expected native implementation semantics
Diffstat (limited to 'src/newt')
-rw-r--r-- | src/newt/classes/com/jogamp/newt/Window.java | 3 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/impl/OffscreenWindow.java | 22 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/impl/WindowImpl.java | 574 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java | 52 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java | 50 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java | 55 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java | 39 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java | 47 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java | 70 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java | 74 | ||||
-rw-r--r-- | src/newt/native/KDWindow.c | 11 | ||||
-rw-r--r-- | src/newt/native/NewtMacWindow.m | 23 | ||||
-rw-r--r-- | src/newt/native/WindowsWindow.c | 379 | ||||
-rw-r--r-- | src/newt/native/X11Window.c | 507 |
14 files changed, 1146 insertions, 760 deletions
diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index 4bdcd67a4..7e1a55b21 100644 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -48,6 +48,9 @@ public interface Window extends NativeWindow { public static final boolean DEBUG_WINDOW_EVENT = Debug.debug("Window.WindowEvent"); public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window"); + /** A 500ms timeout while waiting for a native action response, ie {@link #setVisible(boolean)}. */ + public static final long TIMEOUT_NATIVEWINDOW = 500; + // // Lifecycle // diff --git a/src/newt/classes/com/jogamp/newt/impl/OffscreenWindow.java b/src/newt/classes/com/jogamp/newt/impl/OffscreenWindow.java index 95c326ce4..f3c7b8415 100644 --- a/src/newt/classes/com/jogamp/newt/impl/OffscreenWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/OffscreenWindow.java @@ -86,7 +86,9 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { return surfaceHandle; } - protected void setVisibleImpl(boolean visible) { + protected void setVisibleImpl(boolean visible, int x, int y, int width, int height) { + sizeChanged(width, height, false); + visibleChanged(visible); } protected void requestFocusImpl(boolean reparented) { @@ -94,27 +96,19 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { public void setSize(int width, int height) { if(!visible) { - this.width = width; - this.height = height; + sizeChanged(width, height, false); } } - protected void setSizeImpl(int width, int height) { - shouldNotCallThis(); - } - public void setPosition(int x, int y) { // nop } - protected void setPositionImpl(int x, int y) { - shouldNotCallThis(); - } - public boolean setFullscreen(boolean fullscreen) { // nop return false; } - protected void reconfigureWindowImpl(int x, int y, int width, int height) { + protected boolean reconfigureWindowImpl(int x, int y, int width, int height, boolean parentChange, int fullScreenChange, int decorationChange) { shouldNotCallThis(); + return false; } public Point getLocationOnScreen(Point storage) { @@ -125,5 +119,9 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { } return new Point(0,0); } + + protected Point getLocationOnScreenImpl(int x, int y) { + return new Point(x,y); + } } diff --git a/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java b/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java index a0879a634..631c1b1c0 100644 --- a/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java +++ b/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java @@ -171,12 +171,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer protected Capabilities caps; protected boolean fullscreen, visible, hasFocus; protected int width, height, x, y; - - // non fullscreen dimensions .. - protected int nfs_width, nfs_height, nfs_x, nfs_y; + protected int nfs_width, nfs_height, nfs_x, nfs_y; // non fullscreen dimensions .. protected String title = "Newt Window"; protected boolean undecorated = false; + private boolean handleDestroyNotify = true; private final void destroyScreen() { screenReferenced = false; @@ -194,9 +193,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } private boolean createNative() { - if( null==screen || 0!=windowHandle || !visible ) { - return 0 != windowHandle ; - } if(DEBUG_IMPLEMENTATION) { System.err.println("Window.createNative() START ("+getThreadName()+", "+this+")"); } @@ -211,7 +207,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer screen.addReference(); } createNativeImpl(); - setVisibleImpl(true); + setVisibleImpl(true, x, y, width, height); } } finally { if(null!=parentWindow) { @@ -271,22 +267,68 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer // Window: Native implementation // + /** + * The native implementation must set the native windowHandle.<br> + * + * The implementation should invoke the referenced java state callbacks + * to notify this Java object of state changes. + * + * @see #windowDestroyNotify() + * @see #focusChanged(boolean) + * @see #visibleChanged(boolean) + * @see #sizeChanged(int,int) + * @see #positionChanged(int,int) + * @see #windowDestroyNotify() + */ protected abstract void createNativeImpl(); protected abstract void closeNativeImpl(); - protected abstract void requestFocusImpl(boolean reparented); - - protected abstract void setVisibleImpl(boolean visible); - - protected abstract void setSizeImpl(int width, int height); + /** + * The native implementation must invoke {@link #focusChanged(boolean)} + * to change the focus state, if <code>force == false</code>. + * This may happen asynchronous within {@link #TIMEOUT_NATIVEWINDOW}. + * + * @param force if true, bypass {@link #focusChanged(boolean)} and force focus request + */ + protected abstract void requestFocusImpl(boolean force); - protected abstract void setPositionImpl(int x, int y); + /** + * The native implementation must invoke {@link #visibleChanged(boolean)} + * to change the visibility state. This may happen asynchronous within + * {@link #TIMEOUT_NATIVEWINDOW}. + */ + protected abstract void setVisibleImpl(boolean visible, int x, int y, int width, int height); - protected abstract void reconfigureWindowImpl(int x, int y, int width, int height); + /** + * The native implementation should invoke the referenced java state callbacks + * to notify this Java object of state changes. + * + * @param x -1 if no position change requested, otherwise greater than zero + * @param y -1 if no position change requested, otherwise greater than zero + * @param width -1 if no size change requested, otherwise greater than zero + * @param height -1 if no size change requested, otherwise greater than zero + * @param parentChange true if reparenting requested, otherwise false + * @param fullScreenChange 0 if unchanged, -1 fullscreen off, 1 fullscreen on + * @param decorationChange 0 if unchanged, -1 undecorated, 1 decorated + * + * @see #sizeChanged(int,int) + * @see #positionChanged(int,int) + */ + protected abstract boolean reconfigureWindowImpl(int x, int y, int width, int height, + boolean parentChange, int fullScreenChange, int decorationChange); protected void setTitleImpl(String title) {} + /** + * Return screen coordinates of the given coordinates + * or null, in which case a NativeWindow traversal shall being used + * as demonstrated in {@link #getLocationOnScreen(javax.media.nativewindow.util.Point)}. + * + * @return if not null, the screen location of the given coordinates + */ + protected abstract Point getLocationOnScreenImpl(int x, int y); + //---------------------------------------------------------------------- // NativeSurface // @@ -371,12 +413,31 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } public Point getLocationOnScreen(Point storage) { + if(isNativeValid()) { + Point d; + windowLock.lock(); + try { + d = getLocationOnScreenImpl(0, 0); + } finally { + windowLock.unlock(); + } + if(null!=d) { + if(null!=storage) { + storage.translate(d.getX(),d.getY()); + return storage; + } + return d; + } + // fall through intended .. + } + if(null!=storage) { storage.translate(getX(),getY()); } else { storage = new Point(getX(),getY()); } if(null!=parentWindow) { + // traverse through parent list .. parentWindow.getLocationOnScreen(storage); } return storage; @@ -398,27 +459,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer return screen; } - public void setVisible(boolean visible) { - if(isValid()) { - if( 0==windowHandle && visible && 0>=width*height ) { - // fast-path: not realized yet, make visible, but zero size - return; - } - VisibleAction va = new VisibleAction(visible); - runOnEDTIfAvail(true, va); - if( va.getChanged() ) { - sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener - } - - } - } - class VisibleAction implements Runnable { boolean visible; boolean nativeWindowCreated; boolean madeVisible; - public VisibleAction(boolean visible) { + public VisibleAction (boolean visible) { this.visible = visible; this.nativeWindowCreated = false; this.madeVisible = false; @@ -446,14 +492,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } if(0==windowHandle && visible) { - WindowImpl.this.visible = visible; if( 0<width*height ) { nativeWindowCreated = createNative(); + WindowImpl.this.waitForVisible(visible, true); + madeVisible = visible; } } else if(WindowImpl.this.visible != visible) { - WindowImpl.this.visible = visible; if(0 != windowHandle) { - setVisibleImpl(visible); + setVisibleImpl(visible, x, y, width, height); + WindowImpl.this.waitForVisible(visible, true); madeVisible = visible; } } @@ -481,58 +528,78 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } - public void setSize(int width, int height) { - int visibleAction = 0; // 1 invisible, 2 visible - windowLock.lock(); - try{ - if ( !fullscreen && ( width != this.width || this.height != height ) ) { - if(DEBUG_IMPLEMENTATION) { - String msg = new String("Window setSize: START "+this.width+"x"+this.height+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible "+visible); - System.err.println(msg); - } - nfs_width=width; - nfs_height=height; - if ( 0 != windowHandle && 0>=width*height && visible ) { - visibleAction=1; // invisible - this.width = 0; - this.height = 0; - } else if ( 0 == windowHandle && 0<width*height && visible ) { - visibleAction = 2; // visible - this.width = width; - this.height = height; - } else if ( 0 != windowHandle ) { - // this width/height will be set by windowChanged, called by the native implementation - setSizeImpl(width, height); - } else { - this.width = width; - this.height = height; - } - if(DEBUG_IMPLEMENTATION) { - System.err.println("Window setSize: END "+this.width+"x"+this.height+", visibleAction "+visibleAction); - } + public void setVisible(boolean visible) { + if(isValid()) { + if( 0==windowHandle && visible && 0>=width*height ) { + // fast-path: not realized yet, make visible, but zero size + return; } - } finally { - windowLock.unlock(); + VisibleAction visibleAction = new VisibleAction(visible); + runOnEDTIfAvail(true, visibleAction); + if( visibleAction.getChanged() ) { + sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener + } + } + } + + class SetSizeActionImpl implements Runnable { + int visibleAction = 0; // 1 invisible, 2 visible (create) + int width, height; + + public int getVisibleAction() { + return visibleAction; } - if(visibleAction>0) { - setVisible( ( 1 == visibleAction ) ? false : true ); + public SetSizeActionImpl(int w, int h) { + width = w; + height = h; + } + public void run() { + windowLock.lock(); + try { + if ( !fullscreen && ( width != WindowImpl.this.width || WindowImpl.this.height != height ) ) { + if(DEBUG_IMPLEMENTATION) { + String msg = new String("Window setSize: START "+WindowImpl.this.width+"x"+WindowImpl.this.height+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible "+visible); + System.err.println(msg); + } + if ( 0 != windowHandle && 0>=width*height && visible ) { + visibleAction=1; // invisible + WindowImpl.this.width = 0; + WindowImpl.this.height = 0; + } else if ( 0 == windowHandle && 0<width*height && visible ) { + visibleAction = 2; // visible (create) + WindowImpl.this.width = width; + WindowImpl.this.height = height; + } else if ( 0 != windowHandle ) { + // this width/height will be set by windowChanged, called by the native implementation + reconfigureWindowImpl(x, y, width, height, false, 0, 0); + } else { + WindowImpl.this.width = width; + WindowImpl.this.height = height; + } + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window setSize: END "+WindowImpl.this.width+"x"+WindowImpl.this.height+", visibleAction "+visibleAction); + } + } + } finally { + windowLock.unlock(); + } } } - public void destroy(boolean unrecoverable) { - if( isValid() ) { - if(DEBUG_IMPLEMENTATION) { - String msg = new String("Window.destroy(unrecoverable: "+unrecoverable+") START "+getThreadName()/*+", "+this*/); - System.err.println(msg); - //Exception ee = new Exception(msg); - //ee.printStackTrace(); + public void setSize(int width, int height) { + if(isValid()) { + SetSizeActionImpl setSizeAction = new SetSizeActionImpl(width, height); + runOnEDTIfAvail(true, setSizeAction); + switch(setSizeAction.getVisibleAction()) { + case 1: setVisible(false); break; + case 2: setVisible(true); break; } - runOnEDTIfAvail(true, new DestroyAction(unrecoverable)); } } class DestroyAction implements Runnable { boolean unrecoverable; + public DestroyAction(boolean unrecoverable) { this.unrecoverable = unrecoverable; } @@ -592,6 +659,19 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } + public void destroy(boolean unrecoverable) { + if( isValid() ) { + if(DEBUG_IMPLEMENTATION) { + String msg = new String("Window.destroy(unrecoverable: "+unrecoverable+") START "+getThreadName()/*+", "+this*/); + System.err.println(msg); + //Exception ee = new Exception(msg); + //ee.printStackTrace(); + } + DestroyAction destroyAction = new DestroyAction(unrecoverable); + runOnEDTIfAvail(true, destroyAction); + } + } + /** * <p> * render all native window information invalid, @@ -618,7 +698,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer */ protected void invalidate(boolean unrecoverable) { windowLock.lock(); - try{ + try { if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { String msg = new String("!!! Window Invalidate(unrecoverable: "+unrecoverable+") "+getThreadName()); System.err.println(msg); @@ -667,6 +747,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer boolean wasVisible; boolean displayChanged = false; + // mirror pos/size so native change notification can get overwritten + int x = WindowImpl.this.x; + int y = WindowImpl.this.y; + int width = WindowImpl.this.width; + int height = WindowImpl.this.height; + windowLock.lock(); try { wasVisible = isVisible(); @@ -679,10 +765,22 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer long newParentWindowHandle = 0 ; if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.reparent: START ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+", visible "+wasVisible+", old parentWindow: "+Display.hashCode(parentWindow)+", new parentWindow: "+Display.hashCode(newParentWindow)+", forceDestroyCreate "+forceDestroyCreate+", DEBUG_TEST_REPARENT_INCOMPATIBLE "+DEBUG_TEST_REPARENT_INCOMPATIBLE); + System.err.println("Window.reparent: START ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+", visible "+wasVisible+", old parentWindow: "+Display.hashCode(parentWindow)+", new parentWindow: "+Display.hashCode(newParentWindow)+", forceDestroyCreate "+forceDestroyCreate+", DEBUG_TEST_REPARENT_INCOMPATIBLE "+DEBUG_TEST_REPARENT_INCOMPATIBLE+" "+x+"/"+y+" "+width+"x"+height); } if(null!=newParentWindow) { + // reset position to 0/0 within parent space + x = 0; + y = 0; + + // refit if size is bigger than parent + if( width > newParentWindow.getWidth() ) { + width = newParentWindow.getWidth(); + } + if( height > newParentWindow.getHeight() ) { + height = newParentWindow.getHeight(); + } + // Case: Child Window newParentWindowHandle = getNativeWindowHandle(newParentWindow); if(0 == newParentWindowHandle) { @@ -740,6 +838,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer reparentAction = ACTION_UNCHANGED; } } else { + if( null != parentWindow ) { + // child -> top + // put client to current parent+child position + Point p = getLocationOnScreen(null); + x = p.getX(); + y = p.getY(); + } + // Case: Top Window if( 0 == getParentWindowHandle() ) { // Already Top Window @@ -789,45 +895,59 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } if( ACTION_NATIVE_REPARENTING == reparentAction ) { - if(0!=parentWindowHandle) { - // reset position to 0/0 within parent space - // FIXME .. cache position ? - x = 0; - y = 0; - } DisplayImpl display = (DisplayImpl) screen.getDisplay(); - display.dispatchMessages(); // status up2date + display.dispatchMessagesNative(); // status up2date if(wasVisible) { - visible = false; - setVisibleImpl(false); - display.dispatchMessages(); // status up2date + setVisibleImpl(false, x, y, width, height); + WindowImpl.this.waitForVisible(false, true); } // Lock parentWindow only during reparenting (attempt) NativeWindow parentWindowLocked = null; if( null != parentWindow ) { parentWindowLocked = parentWindow; - if(NativeSurface.LOCK_SURFACE_NOT_READY >= parentWindowLocked.lockSurface() ) { + if( NativeSurface.LOCK_SURFACE_NOT_READY >= parentWindowLocked.lockSurface() ) { throw new NativeWindowException("Parent surface lock: not ready: "+parentWindow); } } boolean ok = false; try { - ok = reparentWindowImpl(); + // 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, true, 0, isUndecorated()?-1:1); } finally { if(null!=parentWindowLocked) { parentWindowLocked.unlockSurface(); } } + // set visible again, and revalidate 'ok', + // since it has been experience that in some cases the reparented window gets hidden + if(ok) { + display.dispatchMessagesNative(); // status up2date + if(wasVisible) { + setVisibleImpl(true, x, y, width, height); + ok = WindowImpl.this.waitForVisible(true, false); + display.dispatchMessagesNative(); // status up2date + if( WindowImpl.this.x != x || + WindowImpl.this.y != y || + WindowImpl.this.width != width || + WindowImpl.this.height != height ) + { + // reset pos/size .. due to some native impl flakyness + reconfigureWindowImpl(x, y, width, height, false, 0, 0); + display.dispatchMessagesNative(); // status up2date + } + } + } + if(ok) { - display.dispatchMessages(); // status up2date if(wasVisible) { - visible = true; - setVisibleImpl(true); - display.dispatchMessages(); // status up2date requestFocusImpl(true); - display.dispatchMessages(); // status up2date + display.dispatchMessagesNative(); // status up2date } } else { // native reparent failed -> try creation @@ -839,15 +959,22 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } + // write back mirrored values, ensuring persitence + // 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.hashCode(parentWindow)); + System.err.println("Window.reparentWindow: END ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+ Display.hashCode(parentWindow)+" "+x+"/"+y+" "+width+"x"+height); } } finally { windowLock.unlock(); } if( ACTION_NATIVE_CREATION == reparentAction && wasVisible ) { - // This may run on the the Display/Screen connection, + // This may run on the Display/Screen connection, // hence a new EDT task runOnEDTIfAvail(true, reparentActionRecreate); } @@ -884,24 +1011,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer ReparentActionImpl reparentAction = new ReparentActionImpl(newParent, forceDestroyCreate); runOnEDTIfAvail(true, reparentAction); reparentActionStrategy = reparentAction.getStrategy(); - boolean sizeSignaled=false; - if(null!=newParent) { - // refit if size is bigger than parent - int w = getWidth(); - int h = getHeight(); - if(w>newParent.getWidth()) { - w=newParent.getWidth(); - sizeSignaled=true; - } - if(h>newParent.getHeight()) { - h=newParent.getHeight(); - sizeSignaled=true; - } - if(sizeSignaled) { - setSize(w, h); - } - } - if( !sizeSignaled && isVisible() ) { + if( isVisible() ) { sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener } } finally { @@ -935,22 +1045,70 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } - public void setUndecorated(boolean value) { - if(!fullscreen && this.undecorated != value) { - undecorated = value; - if( 0 != windowHandle ) { - reconfigureWindowImpl(x, y, width, height); - requestFocus(); + class DecorationActionImpl implements Runnable { + boolean undecorated; + + public DecorationActionImpl(boolean undecorated) { + this.undecorated = undecorated; + } + + public void run() { + windowLock.lock(); + try { + if(!fullscreen && isNativeValid() && WindowImpl.this.undecorated != undecorated) { + WindowImpl.this.undecorated = undecorated; + // mirror pos/size so native change notification can get overwritten + int x = WindowImpl.this.x; + int y = WindowImpl.this.y; + int width = WindowImpl.this.width; + int height = WindowImpl.this.height; + + if( 0 != windowHandle ) { + DisplayImpl display = (DisplayImpl) screen.getDisplay(); + display.dispatchMessagesNative(); // status up2date + boolean wasVisible = isVisible(); + setVisibleImpl(false, x, y, width, height); + WindowImpl.this.waitForVisible(false, true); + display.dispatchMessagesNative(); // status up2date + reconfigureWindowImpl(x, y, width, height, false, 0, undecorated?-1:1); + display.dispatchMessagesNative(); // status up2date + if(wasVisible) { + setVisibleImpl(true, x, y, width, height); + WindowImpl.this.waitForVisible(true, true); + display.dispatchMessagesNative(); // status up2date + if( WindowImpl.this.x != x || + WindowImpl.this.y != y || + WindowImpl.this.width != width || + WindowImpl.this.height != height ) + { + // reset pos/size .. due to some native impl flakyness + reconfigureWindowImpl(x, y, width, height, false, 0, 0); + display.dispatchMessagesNative(); // status up2date + } + requestFocusImpl(true); + display.dispatchMessagesNative(); // status up2date + } + } + } + } finally { + windowLock.unlock(); } } } + public void setUndecorated(boolean value) { + if(isValid()) { + DecorationActionImpl decorationAction = new DecorationActionImpl(value); + runOnEDTIfAvail(true, decorationAction); + sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener + } + } + public boolean isUndecorated() { return 0 != parentWindowHandle || undecorated || fullscreen ; } public void requestFocus() { - // enqueueRequestFocus(false); // FIXME: or shall we wait ? enqueueRequestFocus(true); } @@ -1083,12 +1241,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer class RequestFocusAction implements Runnable { public void run() { + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window.RequestFocusAction: ("+getThreadName()+"): "+hasFocus+" -> true - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)); + } WindowImpl.this.requestFocusImpl(false); } } RequestFocusAction requestFocusAction = new RequestFocusAction(); - public void enqueueRequestFocus(boolean wait) { + protected void enqueueRequestFocus(boolean wait) { runOnEDTIfAvail(wait, requestFocusAction); } @@ -1117,67 +1278,100 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } protected FocusRunnable focusAction = null; - private boolean handleDestroyNotify = true; + class SetPositionActionImpl implements Runnable { + int x, y; - public void setPosition(int x, int y) { - windowLock.lock(); - try{ - if(DEBUG_IMPLEMENTATION) { - System.err.println("Window setPosition: "+this.x+"/"+this.y+" -> "+x+"/"+y+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)); - } - if ( this.x != x || this.y != y ) { - if(!fullscreen) { - nfs_x=x; - nfs_y=y; - if(0!=windowHandle) { - // this x/y will be set by windowChanged, called by X11 - setPositionImpl(x, y); - } else { - this.x = x; - this.y = y; + public SetPositionActionImpl(int x, int y) { + this.x = x; + this.y = y; + } + public void run() { + windowLock.lock(); + try { + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window setPosition: "+WindowImpl.this.x+"/"+WindowImpl.this.y+" -> "+x+"/"+y+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)); + } + if ( WindowImpl.this.x != x || WindowImpl.this.y != y ) { + if(!fullscreen) { + if(0!=windowHandle) { + // this.x/this.y will be set by windowChanged, called by the native implementation + reconfigureWindowImpl(x, y, -1, -1, false, 0, 0); + } else { + WindowImpl.this.x = x; + WindowImpl.this.y = y; + } } } + } finally { + windowLock.unlock(); } - } finally { - windowLock.unlock(); } } - public boolean setFullscreen(boolean fullscreen) { - boolean action = false; - windowLock.lock(); - try{ - if(0!=windowHandle && this.fullscreen!=fullscreen) { - int x,y,w,h; - if(fullscreen) { - x = 0; y = 0; - w = screen.getWidth(); - h = screen.getHeight(); - } else { - if(0!=parentWindowHandle) { - x=0; - y=0; + public void setPosition(int x, int y) { + if(isValid()) { + SetPositionActionImpl setPositionAction = new SetPositionActionImpl(x, y); + runOnEDTIfAvail(true, setPositionAction); + } + } + + class FullScreenActionImpl implements Runnable { + boolean fullscreen; + + public FullScreenActionImpl (boolean fullscreen) { + this.fullscreen = fullscreen; + } + + public void run() { + windowLock.lock(); + try { + if(isNativeValid() && WindowImpl.this.fullscreen != fullscreen) { + int x,y,w,h; + WindowImpl.this.fullscreen = fullscreen; + if(fullscreen) { + x = 0; y = 0; + w = screen.getWidth(); + h = screen.getHeight(); + nfs_width = width; + nfs_height = height; + nfs_x = x; + nfs_y = y; } else { x = nfs_x; y = nfs_y; + w = nfs_width; + h = nfs_height; + } + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + System.err.println("X11Window 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, width, height); + WindowImpl.this.waitForVisible(false, true); + display.dispatchMessagesNative(); // status up2date + reconfigureWindowImpl(x, y, w, h, getParentWindowHandle()!=0, fullscreen?1:-1, isUndecorated()?-1:1); + display.dispatchMessagesNative(); // status up2date + if(wasVisible) { + setVisibleImpl(true, x, y, width, height); + WindowImpl.this.waitForVisible(true, true); + display.dispatchMessagesNative(); // status up2date + requestFocusImpl(true); + display.dispatchMessagesNative(); // status up2date } - w = nfs_width; - h = nfs_height; - } - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - System.err.println("X11Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()+", "+screen); } - this.fullscreen = fullscreen; - reconfigureWindowImpl(x, y, w, h); - action = true; + } finally { + windowLock.unlock(); } - } finally { - windowLock.unlock(); } - if(action) { - requestFocus(); - } - if( isVisible() ) { + } + + public boolean setFullscreen(boolean fullscreen) { + if(isValid()) { + FullScreenActionImpl fullScreenAction = new FullScreenActionImpl(fullscreen); + runOnEDTIfAvail(true, fullScreenAction); sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener } return this.fullscreen; @@ -1654,7 +1848,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer */ protected void focusChanged(boolean focusGained) { if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.focusChanged: ("+getThreadName()+"): "+focusGained+" - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)); + System.err.println("Window.focusChanged: ("+getThreadName()+"): "+this.hasFocus+" -> "+focusGained+" - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)); } hasFocus = focusGained; if (focusGained) { @@ -1667,23 +1861,36 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer protected void visibleChanged(boolean visible) { if(DEBUG_IMPLEMENTATION) { System.err.println("Window.visibleChanged ("+getThreadName()+"): "+this.visible+" -> "+visible+" - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)); - // Exception e = new Exception("Window.visibleChanged ("+getThreadName()+"): "+this.visible+" -> "+visible+" - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)); - // e.printStackTrace(); } this.visible = visible ; } - protected void sizeChanged(int newWidth, int newHeight) { - if(width != newWidth || height != newHeight) { + private boolean waitForVisible(boolean visible, boolean failFast) { + DisplayImpl display = (DisplayImpl) screen.getDisplay(); + for(long sleep = TIMEOUT_NATIVEWINDOW; 0<sleep && this.visible != visible; sleep-=10 ) { + display.dispatchMessagesNative(); // status up2date + try { + Thread.sleep(10); + } catch (InterruptedException ie) {} + sleep -=10; + } + if(this.visible != visible) { + if(failFast) { + throw new NativeWindowException("Visibility not reached as requested within "+TIMEOUT_NATIVEWINDOW+"ms : requested "+visible+", is "+this.visible); + } else if (DEBUG_IMPLEMENTATION) { + System.err.println("******* Visibility not reached as requested within "+TIMEOUT_NATIVEWINDOW+"ms : requested "+visible+", is "+this.visible); + } + } + return this.visible == visible; + } + + protected void sizeChanged(int newWidth, int newHeight, boolean force) { + if(force || width != newWidth || height != newHeight) { if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.sizeChanged: ("+getThreadName()+"): "+width+"x"+height+" -> "+newWidth+"x"+newHeight+" - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)); + System.err.println("Window.sizeChanged: ("+getThreadName()+"): force "+force+", "+width+"x"+height+" -> "+newWidth+"x"+newHeight+" - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)); } width = newWidth; height = newHeight; - if(!fullscreen) { - nfs_width=width; - nfs_height=height; - } if(isNativeValid()) { sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); } @@ -1697,10 +1904,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } x = newX; y = newY; - if(!fullscreen) { - nfs_x=x; - nfs_y=y; - } sendWindowEvent(WindowEvent.EVENT_WINDOW_MOVED); } } @@ -1731,6 +1934,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer public void windowRepaint(int x, int y, int width, int height) { if(DEBUG_IMPLEMENTATION) { System.err.println("Window.windowRepaint "+getThreadName()+" - "+x+"/"+y+" "+width+"x"+height); + // Exception ee = new Exception("Window.windowRepaint: "+" - "+x+"/"+y+" "+width+"x"+height); + // ee.printStackTrace(); } if(0>width) { width=this.width; @@ -1746,11 +1951,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } - protected boolean reparentWindowImpl() { - // default implementation, no native reparenting support - return false; - } - protected int getWindowLockRecursionCount() { return windowLock.getRecursionCount(); } diff --git a/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java b/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java index 5abff047f..edd851451 100644 --- a/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java @@ -46,6 +46,7 @@ import com.jogamp.newt.impl.WindowImpl; import java.awt.Insets; import javax.media.nativewindow.*; import javax.media.nativewindow.awt.*; +import javax.media.nativewindow.util.Point; /** An implementation of the Newt Window class built using the AWT. This is provided for convenience of porting to platforms @@ -74,8 +75,6 @@ public class AWTWindow extends WindowImpl { private Container container = null; private Frame frame = null; // same instance as container, just for impl. convenience private AWTCanvas canvas; - // non fullscreen dimensions .. - private int nfs_width, nfs_height, nfs_x, nfs_y; protected void requestFocusImpl(boolean reparented) { runOnEDT(true, new Runnable() { @@ -176,13 +175,14 @@ public class AWTWindow extends WindowImpl { return res; } - protected void setVisibleImpl(final boolean visible) { + protected void setVisibleImpl(final boolean visible, int x, int y, int width, int height) { runOnEDT(true, new Runnable() { public void run() { container.setVisible(visible); } }); + reconfigureWindowImpl(x, y, width, height, false, 0, 0); config = canvas.getAWTGraphicsConfiguration(); if (config == null) { @@ -190,6 +190,7 @@ public class AWTWindow extends WindowImpl { } updateDeviceData(); + visibleChanged(visible); } private void updateDeviceData() { @@ -203,19 +204,6 @@ public class AWTWindow extends WindowImpl { ((AWTScreen)getScreen()).setScreenSize(w, h); } - protected void setSizeImpl(final int width, final int height) { - if(null!=container) { - /** An AWT event on setSize() would bring us in a deadlock situation, hence invokeLater() */ - runOnEDT(false, new Runnable() { - public void run() { - Insets insets = container.getInsets(); - container.setSize(width + insets.left + insets.right, - height + insets.top + insets.bottom); - } - }); - } - } - public javax.media.nativewindow.util.Insets getInsets() { final int insets[] = new int[] { 0, 0, 0, 0 }; runOnEDT(true, new Runnable() { @@ -230,21 +218,11 @@ public class AWTWindow extends WindowImpl { return new javax.media.nativewindow.util.Insets(insets[0],insets[1],insets[2],insets[3]); } - protected void setPositionImpl(final int x, final int y) { - if(null!=container) { - runOnEDT(true, new Runnable() { - public void run() { - container.setLocation(x, y); - } - }); - } - } - - protected void reconfigureWindowImpl(final int x, final int y, final int width, final int height) { + protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, final boolean parentChange, final int fullScreenChange, final int decorationChange) { /** An AWT event on setSize() would bring us in a deadlock situation, hence invokeLater() */ runOnEDT(false, new Runnable() { public void run() { - if(null!=frame) { + if(decorationChange!=0 && null!=frame) { if(!container.isDisplayable()) { frame.setUndecorated(isUndecorated()); } else { @@ -253,12 +231,26 @@ public class AWTWindow extends WindowImpl { } } } - container.setLocation(x, y); - container.setSize(width, height); + int _x=(x>=0)?x:AWTWindow.this.x; + int _y=(x>=0)?y:AWTWindow.this.y; + int _w=(width>0)?width:AWTWindow.this.width; + int _h=(height>0)?height:AWTWindow.this.height; + + container.setLocation(_x, _y); + Insets insets = container.getInsets(); + container.setSize(_w + insets.left + insets.right, + _h + insets.top + insets.bottom); } }); + return true; } + protected Point getLocationOnScreenImpl(int x, int y) { + java.awt.Point ap = canvas.getLocationOnScreen(); + ap.translate(x, y); + return new Point((int)(ap.getX()+0.5),(int)(ap.getY()+0.5)); + } + public Object getWrappedWindow() { return canvas; } diff --git a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java index 040fa15a9..749be8506 100644 --- a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java @@ -34,6 +34,7 @@ package com.jogamp.newt.impl.intel.gdl; import javax.media.nativewindow.*; +import javax.media.nativewindow.util.Point; public class Window extends com.jogamp.newt.impl.WindowImpl { static { @@ -77,42 +78,40 @@ public class Window extends com.jogamp.newt.impl.WindowImpl { } } - protected void setVisibleImpl(boolean visible) { + protected void setVisibleImpl(boolean visible, int x, int y, int width, int height) { + reconfigureWindowImpl(x, y, width, height, false, 0, 0); if(visible) { ((Display)getScreen().getDisplay()).setFocus(this); } + this.visibleChanged(visible); } - protected void setSizeImpl(int width, int height) { + protected boolean reconfigureWindowImpl(int x, int y, int width, int height, boolean parentChange, int fullScreenChange, int decorationChange) { Screen screen = (Screen) getScreen(); - if((x+width)>screen.getWidth()) { - width=screen.getWidth()-x; - } - if((y+height)>screen.getHeight()) { - height=screen.getHeight()-y; - } - if(0!=surfaceHandle) { - SetBounds0(surfaceHandle, screen.getWidth(), screen.getHeight(), x, y, width, height); - } - } - protected void setPositionImpl(int x, int y) { - Screen screen = (Screen) getScreen(); - if((x+width)>screen.getWidth()) { - x=screen.getWidth()-width; + int _x=(x>=0)?x:this.x; + int _y=(x>=0)?y:this.y; + int _w=(width>0)?width:this.width; + int _h=(height>0)?height:this.height; + + if(_w>screen.getWidth()) { + _w=screen.getWidth(); } - if((y+height)>screen.getHeight()) { - y=screen.getHeight()-height; + if(_h>screen.getHeight()) { + _h=screen.getHeight(); } - if(0!=surfaceHandle) { - SetBounds0(surfaceHandle, screen.getWidth(), screen.getHeight(), x, y, width, height); + if((_x+_w)>screen.getWidth()) { + _x=screen.getWidth()-_w; + } + if((_y+_h)>screen.getHeight()) { + _y=screen.getHeight()-_h; } - } - protected void reconfigureWindowImpl(int x, int y, int width, int height) { if(0!=surfaceHandle) { - SetBounds0(surfaceHandle, getScreen().getWidth(), getScreen().getHeight(), x, y, width, height); + SetBounds0(surfaceHandle, getScreen().getWidth(), getScreen().getHeight(), _x, _y, _w, _h); } + + return true; } protected void requestFocusImpl(boolean reparented) { @@ -123,6 +122,10 @@ public class Window extends com.jogamp.newt.impl.WindowImpl { return surfaceHandle; } + protected Point getLocationOnScreenImpl(int x, int y) { + return new Point(x,y); + } + //---------------------------------------------------------------------- // Internals only // @@ -140,5 +143,4 @@ public class Window extends com.jogamp.newt.impl.WindowImpl { } private long surfaceHandle; - private int nfs_width, nfs_height, nfs_x, nfs_y; } diff --git a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java index 15cadb05f..59b41c2aa 100644 --- a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java @@ -40,6 +40,7 @@ import com.jogamp.common.util.locks.RecursiveLock; import com.jogamp.newt.event.*; import com.jogamp.newt.impl.*; import javax.media.nativewindow.util.Insets; +import javax.media.nativewindow.util.Point; public class MacWindow extends WindowImpl { @@ -194,11 +195,11 @@ public class MacWindow extends WindowImpl { nsViewLock.unlock(); } - protected void setVisibleImpl(final boolean visible) { + protected void setVisibleImpl(boolean visible, int x, int y, int width, int height) { nsViewLock.lock(); try { if (visible) { - createWindow(false, getX(), getY(), getWidth(), getHeight(), isFullscreen()); + createWindow(false, x, y, width, height, isFullscreen()); if (getWindowHandle() != 0) { makeKeyAndOrderFront0(getWindowHandle()); } @@ -207,6 +208,7 @@ public class MacWindow extends WindowImpl { orderOut0(getWindowHandle()); } } + visibleChanged(visible); } finally { nsViewLock.unlock(); } @@ -232,39 +234,38 @@ public class MacWindow extends WindowImpl { } } - protected void setSizeImpl(int width, int height) { - // this width/height will be set by sizeChanged, called by OSX - nsViewLock.lock(); - try { - setContentSize0(getWindowHandle(), width, height); - } finally { - nsViewLock.unlock(); - } - } - - protected void setPositionImpl(int x, int y) { - // this x/y will be set by positionChanged, called by OSX - nsViewLock.lock(); - try { - setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), x, y); - } finally { - nsViewLock.unlock(); - } - } - - protected void reconfigureWindowImpl(int x, int y, int width, int height) { + protected boolean reconfigureWindowImpl(int x, int y, int width, int height, boolean parentChange, int fullScreenChange, int decorationChange) { nsViewLock.lock(); try { if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - System.err.println("MacWindow reconfig: "+fullscreen+" "+x+"/"+y+" "+width+"x"+height); + System.err.println("MacWindow reconfig: parentChange "+parentChange+", fullScreenChange "+fullScreenChange+", decorationChange "+decorationChange+" "+x+"/"+y+" "+width+"x"+height); } - createWindow(true, x, y, width, height, fullscreen); - if (getWindowHandle() != 0) { - makeKeyAndOrderFront0(getWindowHandle()); + int _x=(x>=0)?x:this.x; + int _y=(x>=0)?y:this.y; + int _w=(width>0)?width:this.width; + int _h=(height>0)?height:this.height; + + if(decorationChange!=0 || parentChange || fullScreenChange!=0) { + createWindow(true, _x, _y, _w, _h, fullScreenChange>0); + if (getWindowHandle() != 0) { + makeKeyAndOrderFront0(getWindowHandle()); + } + } else { + if(x>=0 || y>=0) { + setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), _x, _y); + } + if(width>0 || height>0) { + setContentSize0(getWindowHandle(), _w, _h); + } } } finally { nsViewLock.unlock(); } + return true; + } + + protected Point getLocationOnScreenImpl(int x, int y) { + return null; } private void insetsChanged(int left, int top, int right, int bottom) { diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java index 9f5e7b7c1..ad903731b 100644 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java @@ -37,6 +37,7 @@ import com.jogamp.opengl.impl.egl.*; import javax.media.nativewindow.*; import javax.media.opengl.GLCapabilities; import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.util.Point; public class Window extends com.jogamp.newt.impl.WindowImpl { static { @@ -70,7 +71,10 @@ public class Window extends com.jogamp.newt.impl.WindowImpl { } } - protected void setVisibleImpl(boolean visible) { } + protected void setVisibleImpl(boolean visible, int x, int y, int width, int height) { + reconfigureWindowImpl(x, y, width, height, false, 0, 0); + visibleChanged(visible); + } protected void requestFocusImpl(boolean reparented) { } @@ -84,16 +88,37 @@ public class Window extends com.jogamp.newt.impl.WindowImpl { } } - protected void setPositionImpl(int x, int y) { - // n/a in BroadcomEGL - System.err.println("BCEGL Window.setPositionImpl n/a in BroadcomEGL"); + protected boolean reconfigureWindowImpl(int x, int y, int width, int height, + boolean parentChange, int fullScreenChange, int decorationChange) { + if(0!=getWindowHandle()) { + if(0!=fullScreenChange) { + if( fullScreenChange > 0 ) { + // n/a in BroadcomEGL + System.err.println("setFullscreen n/a in BroadcomEGL"); + return false; + } + } + } + if(width>0 || height>0) { + if(0!=getWindowHandle()) { + // n/a in BroadcomEGL + System.err.println("BCEGL Window.setSizeImpl n/a in BroadcomEGL with realized window"); + } else { + this.width=(width>0)?width:this.width; + this.height=(height>0)?height:this.height; + } + } + if(x>=0 || y>=0) { + System.err.println("BCEGL Window.setPositionImpl n/a in BroadcomEGL"); + } + return true; } - protected void reconfigureWindowImpl(int x, int y, int width, int height) { - // n/a in BroadcomEGL - System.err.println("setFullscreen n/a in BroadcomEGL"); + protected Point getLocationOnScreenImpl(int x, int y) { + return new Point(x,y); } + public boolean surfaceSwap() { SwapWindow(getDisplayHandle(), getWindowHandle()); return true; diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java index 6930741b8..f0bc8587b 100644 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java @@ -41,11 +41,10 @@ import javax.media.nativewindow.*; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLProfile; import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.util.Point; public class KDWindow extends WindowImpl { private static final String WINDOW_CLASS_NAME = "NewtWindow"; - // non fullscreen dimensions .. - private int nfs_width, nfs_height, nfs_x, nfs_y; static { KDDisplay.initSingleton(); @@ -85,30 +84,40 @@ public class KDWindow extends WindowImpl { } } - protected void setVisibleImpl(boolean visible) { + protected void setVisibleImpl(boolean visible, int x, int y, int width, int height) { setVisible0(eglWindowHandle, visible); + reconfigureWindowImpl(x, y, width, height, false, 0, 0); + visibleChanged(visible); } protected void requestFocusImpl(boolean reparented) { } - protected void setSizeImpl(int width, int height) { + protected boolean reconfigureWindowImpl(int x, int y, int width, int height, + boolean parentChange, int fullScreenChange, int decorationChange) { if(0!=eglWindowHandle) { - setSize0(eglWindowHandle, width, height); + if(0!=fullScreenChange) { + boolean fs = fullScreenChange > 0; + setFullScreen0(eglWindowHandle, fs); + if(fs) { + return true; + } + } + // int _x=(x>=0)?x:this.x; + // int _y=(x>=0)?y:this.y; + int _w=(width>0)?width:this.width; + int _h=(height>0)?height:this.height; + if(width>0 || height>0) { + setSize0(eglWindowHandle, _w, _h); + } + if(x>=0 || y>=0) { + System.err.println("setPosition n/a in KD"); + } } + return true; } - protected void setPositionImpl(int x, int y) { - // n/a in KD - System.err.println("setPosition n/a in KD"); - } - - protected void reconfigureWindowImpl(int x, int y, int width, int height) { - if(0!=eglWindowHandle) { - setFullScreen0(eglWindowHandle, fullscreen); - if(!fullscreen) { - setSize0(eglWindowHandle, width, height); - } - } + protected Point getLocationOnScreenImpl(int x, int y) { + return new Point(x,y); } //---------------------------------------------------------------------- @@ -127,11 +136,11 @@ public class KDWindow extends WindowImpl { windowUserData=userData; } - protected void sizeChanged(int newWidth, int newHeight) { + protected void sizeChanged(int newWidth, int newHeight, boolean force) { if(fullscreen) { ((KDScreen)getScreen()).setScreenSize(width, height); } - super.sizeChanged(newWidth, newHeight); + super.sizeChanged(newWidth, newHeight, force); } private long eglWindowHandle; diff --git a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java index 3ade599da..daa09b034 100644 --- a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java @@ -37,6 +37,7 @@ package com.jogamp.newt.impl.windows; import javax.media.nativewindow.*; import com.jogamp.newt.impl.WindowImpl; import javax.media.nativewindow.util.Insets; +import javax.media.nativewindow.util.Point; public class WindowsWindow extends WindowImpl { @@ -142,31 +143,20 @@ public class WindowsWindow extends WindowImpl { super.windowDestroyed(); } - protected void setVisibleImpl(boolean visible) { - setVisible0(getWindowHandle(), visible); + protected void setVisibleImpl(boolean visible, int x, int y, int width, int height) { + setVisible0(getWindowHandle(), visible, (getParentWindowHandle()==0)?true:false, x, y, width, height); + visibleChanged(visible); } - protected void setSizeImpl(int width, int height) { - // this width/height will be set by sizeChanged, called by Windows - setSize0(getParentWindowHandle(), getWindowHandle(), x, y, width, height); - } - - protected void setPositionImpl(int x, int y) { - // this x/y will be set by positionChanged, called by Windows - setPosition0(getParentWindowHandle(), getWindowHandle(), x , y /*, width, height*/); - } - - protected void reconfigureWindowImpl(int x, int y, int width, int height) { - reconfigureWindow0(fullscreen?0:getParentWindowHandle(), getWindowHandle(), x, y, width, height, isUndecorated()); - } - - protected boolean reparentWindowImpl() { - reparentWindow0(fullscreen?0:getParentWindowHandle(), getWindowHandle(), x, y, width, height, isUndecorated()); + protected boolean reconfigureWindowImpl(int x, int y, int width, int height, + boolean parentChange, int fullScreenChange, int decorationChange) { + reconfigureWindow0( (fullScreenChange>0)?0:getParentWindowHandle(), + getWindowHandle(), x, y, width, height, isVisible(), parentChange, fullScreenChange, decorationChange); return true; } - protected void requestFocusImpl(boolean reparented) { - requestFocus0(getWindowHandle(), reparented); + protected void requestFocusImpl(boolean force) { + requestFocus0(getWindowHandle(), force); } protected void setTitleImpl(final String title) { @@ -177,34 +167,42 @@ public class WindowsWindow extends WindowImpl { return (Insets)insets.clone(); } + protected Point getLocationOnScreenImpl(int x, int y) { + return (Point) getRelativeLocation0( getWindowHandle(), 0 /*root win*/, x, y); + } + //---------------------------------------------------------------------- // Internals only // protected static native boolean initIDs0(); - private native long CreateWindow0(long parentWindowHandle, + private native long CreateWindow0(long parentWindowHandle, int wndClassAtom, String wndName, long hInstance, long visualID, boolean isUndecorated, int x, int y, int width, int height); - private native void DestroyWindow0(long windowHandle); - private native long GetDC0(long windowHandle); - private native void ReleaseDC0(long windowHandle, long hdc); - private native long MonitorFromWindow0(long windowHandle); - private static native void setVisible0(long windowHandle, boolean visible); - private native void setSize0(long parentWindowHandle, long windowHandle, int x, int y, int width, int height); - private static native void setPosition0(long parentWindowHandle, long windowHandle, int x, int y /*, int width, int height*/); - private native void reconfigureWindow0(long parentWindowHandle, long windowHandle, - int x, int y, int width, int height, boolean isUndecorated); - private native void reparentWindow0(long parentWindowHandle, long windowHandle, int x, int y, int width, int height, boolean isUndecorated); + private native void DestroyWindow0(long windowHandle); + private native long GetDC0(long windowHandle); + private native void ReleaseDC0(long windowHandle, long hdc); + private native long MonitorFromWindow0(long windowHandle); + private native void setVisible0(long windowHandle, boolean visible, boolean top, int x, int y, int width, int height); + private native void reconfigureWindow0(long parentWindowHandle, long windowHandle, + int x, int y, int width, int height, boolean isVisible, + boolean parentChange, int fullScreenChange, int decorationChange); private static native void setTitle0(long windowHandle, String title); - private native void requestFocus0(long windowHandle, boolean reparented); + private native void requestFocus0(long windowHandle, boolean force); + private native Object getRelativeLocation0(long src_win, long dest_win, int src_x, int src_y); private void insetsChanged(int left, int top, int right, int bottom) { if (left != -1 && top != -1 && right != -1 && bottom != -1) { - insets.left = left; - insets.top = top; - insets.right = right; - insets.bottom = bottom; + if (left != insets.left || top != insets.top || right != insets.right || bottom != insets.bottom) { + insets.left = left; + insets.top = top; + insets.right = right; + insets.bottom = bottom; + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window.insetsChanged: "+insets); + } + } } } } diff --git a/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java b/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java index 3b3cd07ae..53b222189 100644 --- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java @@ -38,6 +38,7 @@ import com.jogamp.newt.event.*; import com.jogamp.newt.impl.WindowImpl; import javax.media.nativewindow.*; import javax.media.nativewindow.x11.*; +import javax.media.nativewindow.util.Point; public class X11Window extends WindowImpl { private static final String WINDOW_CLASS_NAME = "NewtWindow"; @@ -62,10 +63,11 @@ public class X11Window extends WindowImpl { display.getHandle(), screen.getIndex(), visualID, display.getJavaObjectAtom(), display.getWindowDeleteAtom(), x, y, width, height, isUndecorated()); - if (w == 0 || w!=getWindowHandle()) { + if (w == 0) { throw new NativeWindowException("Error creating window: "+w); } - windowHandleClose = getWindowHandle(); + setWindowHandle(w); + windowHandleClose = w; } protected void closeNativeImpl() { @@ -90,62 +92,60 @@ public class X11Window extends WindowImpl { super.windowDestroyed(); } - protected void setVisibleImpl(boolean visible) { - setVisible0(getDisplayHandle(), getWindowHandle(), visible); + protected void setVisibleImpl(boolean visible, int x, int y, int width, int height) { + setVisible0(getDisplayHandle(), getWindowHandle(), visible, x, y, width, height); } - protected void setSizeImpl(int width, int height) { - // this width/height will be set by windowChanged, called by X11 - setSize0(getDisplayHandle(), getWindowHandle(), width, height); - } - - protected void setPositionImpl(int x, int y) { - setPosition0(getParentWindowHandle(), getDisplayHandle(), getWindowHandle(), x, y); - } + protected boolean reconfigureWindowImpl(int x, int y, int width, int height, + boolean parentChange, int fullScreenChange, int decorationChange) { + reparentHandle=0; + reparentCount=0; + long reqNewParentHandle = ( fullScreenChange > 0 ) ? 0 : getParentWindowHandle() ; - protected void reconfigureWindowImpl(int x, int y, int width, int height) { - reconfigureWindow0(fullscreen?0:getParentWindowHandle(), getDisplayHandle(), getScreenIndex(), getWindowHandle(), - x, y, width, height, isUndecorated(), isVisible(), isFullscreen()); - } + reconfigureWindow0( getDisplayHandle(), getScreenIndex(), reqNewParentHandle, getWindowHandle(), + x, y, width, height, isVisible(), parentChange, fullScreenChange, decorationChange); - protected boolean reparentWindowImpl() { - if(0!=getWindowHandle()) { - reparentWindow0(fullscreen?0:getParentWindowHandle(), getDisplayHandle(), getScreenIndex(), getWindowHandle(), - x, y, isUndecorated(), isVisible()); - } return true; } - protected void requestFocusImpl(boolean reparented) { - requestFocus0(getDisplayHandle(), getWindowHandle(), reparented); + protected void requestFocusImpl(boolean force) { + requestFocus0(getDisplayHandle(), getWindowHandle(), force); } protected void setTitleImpl(String title) { setTitle0(getDisplayHandle(), getWindowHandle(), title); } + protected Point getLocationOnScreenImpl(int x, int y) { + return (Point) getRelativeLocation0( getDisplayHandle(), getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y); + } + //---------------------------------------------------------------------- // Internals only // protected static native boolean initIDs0(); - private native long CreateWindow0(long parentWindowHandle, long display, int screen_index, + private native long CreateWindow0(long parentWindowHandle, long display, int screen_index, long visualID, long javaObjectAtom, long windowDeleteAtom, int x, int y, int width, int height, boolean undecorated); - private native void CloseWindow0(long display, long windowHandle, long javaObjectAtom, long windowDeleteAtom); - private native void setVisible0(long display, long windowHandle, boolean visible); - private native void setSize0(long display, long windowHandle, int width, int height); - private native void reconfigureWindow0(long parentWindowHandle, long display, int screen_index, long windowHandle, - int x, int y, int width, int height, boolean undecorated, boolean isVisible, boolean fullscreen); - private native void setTitle0(long display, long windowHandle, String title); - private native void requestFocus0(long display, long windowHandle, boolean reparented); - private native void setPosition0(long parentWindowHandle, long display, long windowHandle, int x, int y); - private native void reparentWindow0(long parentWindowHandle, long display, int screen_index, long windowHandle, - int x, int y, boolean undecorated, boolean isVisible); - - private void windowCreated(long windowHandle) { - setWindowHandle(windowHandle); + private native void CloseWindow0(long display, long windowHandle, long javaObjectAtom, long windowDeleteAtom); + private native void setVisible0(long display, long windowHandle, boolean visible, int x, int y, int width, int height); + private native void reconfigureWindow0(long display, int screen_index, long parentWindowHandle, long windowHandle, + int x, int y, int width, int height, boolean isVisible, + boolean parentChange, int fullScreenChange, int decorationChange); + private native void setTitle0(long display, long windowHandle, String title); + private native void requestFocus0(long display, long windowHandle, boolean force); + private native Object getRelativeLocation0(long display, int screen_index, long src_win, long dest_win, int src_x, int src_y); + + private void windowReparented(long gotParentHandle) { + reparentHandle = gotParentHandle; + reparentCount++; + if(DEBUG_IMPLEMENTATION) { + System.err.println("******** new parent ("+reparentCount+"): " + toHexString(reparentHandle) ); + } } private long windowHandleClose; + private volatile long reparentHandle; + private volatile int reparentCount; } diff --git a/src/newt/native/KDWindow.c b/src/newt/native/KDWindow.c index 75a2fe1a1..b574731c2 100644 --- a/src/newt/native/KDWindow.c +++ b/src/newt/native/KDWindow.c @@ -93,6 +93,7 @@ typedef struct { static jmethodID windowCreatedID = NULL; static jmethodID sizeChangedID = NULL; +static jmethodID visibleChangedID = NULL; static jmethodID windowDestroyNotifyID = NULL; static jmethodID windowDestroyedID = NULL; static jmethodID sendMouseEventID = NULL; @@ -150,7 +151,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_opengl_kd_KDDisplay_DispatchMes KDint32 v[2]; if(!kdGetWindowPropertyiv(kdWindow, KD_WINDOWPROPERTY_SIZE, v)) { DBG_PRINT( "event window size change : src: %p %dx%d\n", userData, v[0], v[1]); - (*env)->CallVoidMethod(env, javaWindow, sizeChangedID, (jint) v[0], (jint) v[1]); + (*env)->CallVoidMethod(env, javaWindow, sizeChangedID, (jint) v[0], (jint) v[1], JNI_FALSE); } else { DBG_PRINT( "event window size change error: src: %p %dx%d\n", userData, v[0], v[1]); } @@ -164,6 +165,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_opengl_kd_KDDisplay_DispatchMes KDboolean visible; kdGetWindowPropertybv(kdWindow, KD_WINDOWPROPERTY_VISIBILITY, &visible); DBG_PRINT( "event window visibility: src: %p, v:%d\n", userData, visible); + (*env)->CallVoidMethod(env, javaWindow, visibleChangedID, visible?JNI_TRUE:JNI_FALSE); } break; default: @@ -209,13 +211,15 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_opengl_kd_KDWindow_initIDs #endif #endif windowCreatedID = (*env)->GetMethodID(env, clazz, "windowCreated", "(J)V"); - sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(II)V"); + sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(IIZ)V"); + visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V"); sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V"); sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); if (windowCreatedID == NULL || sizeChangedID == NULL || + visibleChangedID == NULL || windowDestroyNotifyID == NULL || windowDestroyedID == NULL || sendMouseEventID == NULL || @@ -309,6 +313,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_opengl_kd_KDWindow_setVisible0 KDboolean v = (visible==JNI_TRUE)?KD_TRUE:KD_FALSE; kdSetWindowPropertybv(w, KD_WINDOWPROPERTY_VISIBILITY, &v); DBG_PRINT( "[setVisible] v=%d\n", visible); + (*env)->CallVoidMethod(env, obj, visibleChangedID, visible); // FIXME: or send via event ? } JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_opengl_kd_KDWindow_setFullScreen0 @@ -332,6 +337,6 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_opengl_kd_KDWindow_setSize0 DBG_PRINT( "[setSize] v=%dx%d, res=%d\n", width, height, res); (void)res; - (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height); + (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height, JNI_FALSE); } diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index da31a686e..9f9442e9d 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -100,12 +100,23 @@ jint GetDeltaY(NSEvent *event, jint javaMods) { } } -/** FIXME: Tried child window: message reception .. - (void)viewWillDraw { fprintf(stderr, "*************** viewWillDraw: 0x%p", javaWindowObject); fflush(stderr); [super viewWillDraw]; -} */ +} + +- (void)viewDidHide +{ + (*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE); + [super viewDidHide]; +} + +- (void)viewDidUnhide +{ + (*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_TRUE); + [super viewDidUnhide]; +} @end @@ -113,6 +124,7 @@ static jmethodID sendMouseEventID = NULL; static jmethodID sendKeyEventID = NULL; static jmethodID insetsChangedID = NULL; static jmethodID sizeChangedID = NULL; +static jmethodID visibleChangedID = NULL; static jmethodID positionChangedID = NULL; static jmethodID focusChangedID = NULL; static jmethodID windowDestroyNotifyID = NULL; @@ -124,13 +136,14 @@ static jmethodID windowDestroyedID = NULL; { sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V"); sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); - sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(II)V"); + sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(IIZ)V"); + visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V"); insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(IIII)V"); positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(II)V"); focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(Z)V"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V"); - if (sendMouseEventID && sendKeyEventID && sizeChangedID && insetsChangedID && + if (sendMouseEventID && sendKeyEventID && sizeChangedID && visibleChangedID && insetsChangedID && positionChangedID && focusChangedID && windowDestroyedID && windowDestroyNotifyID) { return YES; @@ -398,7 +411,7 @@ static jint mods2JavaMods(NSUInteger mods) (*env)->CallVoidMethod(env, javaWindowObject, sizeChangedID, (jint) contentRect.size.width, - (jint) contentRect.size.height); + (jint) contentRect.size.height, JNI_FALSE); } - (void)windowDidMove: (NSNotification*) notification diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index e1250811c..44f90bc0e 100644 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -109,6 +109,26 @@ #define STD_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) +static void _FatalError(JNIEnv *env, const char* msg, ...) +{ + char buffer[512]; + va_list ap; + + va_start(ap, msg); + vsnprintf(buffer, sizeof(buffer), msg, ap); + va_end(ap); + + fprintf(stderr, "%s\n", buffer); + (*env)->FatalError(env, buffer); +} + +static const char * const ClazzNamePoint = "javax/media/nativewindow/util/Point"; +static const char * const ClazzAnyCstrName = "<init>"; +static const char * const ClazzNamePointCstrSignature = "(II)V"; + +static jclass pointClz = NULL; +static jmethodID pointCstr = NULL; + static jmethodID insetsChangedID = NULL; static jmethodID sizeChangedID = NULL; static jmethodID positionChangedID = NULL; @@ -124,7 +144,7 @@ static jmethodID sendKeyEventID = NULL; static jmethodID focusActionID = NULL; static jmethodID enqueueRequestFocusID = NULL; -static RECT* UpdateInsets(JNIEnv *env, HWND hwnd, jobject window); +static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd); typedef struct { JNIEnv* jenv; @@ -600,18 +620,15 @@ static int WmKeyUp(JNIEnv *env, jobject window, UINT wkey, UINT repCnt, return 0; } -static void NewtWindows_requestFocus (JNIEnv *env, jobject window, HWND hwnd, BOOL reparented) { +static void NewtWindows_requestFocus (JNIEnv *env, jobject window, HWND hwnd, jboolean force) { HWND pHwnd, current; pHwnd = GetParent(hwnd); current = GetFocus(); - DBG_PRINT("*** WindowsWindow: requestFocus.S parent %p, window %p, isCurrent %d, reparented %d\n", - (void*) pHwnd, (void*)hwnd, current==hwnd, (int) reparented); - if(reparented || current!=hwnd) { - if( reparented || JNI_FALSE == (*env)->CallBooleanMethod(env, window, focusActionID) ) { + DBG_PRINT("*** WindowsWindow: requestFocus.S parent %p, window %p, isCurrent %d\n", + (void*) pHwnd, (void*)hwnd, current==hwnd); + if( JNI_TRUE==force || current!=hwnd) { + if( JNI_TRUE==force || JNI_FALSE == (*env)->CallBooleanMethod(env, window, focusActionID) ) { UINT flags = SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; - if(reparented) { - flags |= SWP_FRAMECHANGED; - } SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, flags); SetForegroundWindow(hwnd); // Slightly Higher Priority SetFocus(hwnd);// Sets Keyboard Focus To Window @@ -626,7 +643,64 @@ static void NewtWindows_requestFocus (JNIEnv *env, jobject window, HWND hwnd, BO DBG_PRINT("*** WindowsWindow: requestFocus.XX\n"); } -static RECT * UpdateInsets(JNIEnv *env, HWND hwnd, jobject window) +#if 0 + +static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd) +{ + // being naughty here + static RECT m_insets = { 0, 0, 0, 0 }; + RECT outside; + RECT inside; + POINT *rp_inside = (POINT *) (void *) &inside; + int dx, dy, dw, dh; + + if (IsIconic(hwnd)) { + m_insets.left = m_insets.top = m_insets.right = m_insets.bottom = -1; + return FALSE; + } + + m_insets.left = m_insets.top = m_insets.right = m_insets.bottom = 0; + + GetClientRect(hwnd, &inside); + GetWindowRect(hwnd, &outside); + + DBG_PRINT("*** WindowsWindow: UpdateInsets (a1) window %p, Inside CC: %d/%d - %d/%d %dx%d\n", + (void*)hwnd, + (int)inside.left, (int)inside.top, (int)inside.right, (int)inside.bottom, + (int)(inside.right - inside.left), (int)(inside.bottom - inside.top)); + DBG_PRINT("*** WindowsWindow: UpdateInsets (a1) window %p, Outside SC: %d/%d - %d/%d %dx%d\n", + (void*)hwnd, + (int)outside.left, (int)outside.top, (int)outside.right, (int)outside.bottom, + (int)(outside.right - outside.left), (int)(outside.bottom - outside.top)); + + // xform client -> screen coord + ClientToScreen(hwnd, rp_inside); + ClientToScreen(hwnd, rp_inside+1); + + DBG_PRINT("*** WindowsWindow: UpdateInsets (a2) window %p, Inside SC: %d/%d - %d/%d %dx%d\n", + (void*)hwnd, + (int)inside.left, (int)inside.top, (int)inside.right, (int)inside.bottom, + (int)(inside.right - inside.left), (int)(inside.bottom - inside.top)); + + m_insets.top = inside.top - outside.top; + m_insets.bottom = outside.bottom - inside.bottom; + m_insets.left = inside.left - outside.left; + m_insets.right = outside.right - inside.right; + + DBG_PRINT("*** WindowsWindow: UpdateInsets (1.0) window %p, %d/%d - %d/%d %dx%d\n", + (void*)hwnd, + (int)m_insets.left, (int)m_insets.top, (int)m_insets.right, (int)m_insets.bottom, + (int)(m_insets.right-m_insets.left), (int)(m_insets.top-m_insets.bottom)); + + (*env)->CallVoidMethod(env, window, insetsChangedID, + m_insets.left, m_insets.top, + m_insets.right, m_insets.bottom); + return &m_insets; +} + +#else + +static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd) { // being naughty here static RECT m_insets = { 0, 0, 0, 0 }; @@ -690,13 +764,16 @@ static RECT * UpdateInsets(JNIEnv *env, HWND hwnd, jobject window) return &m_insets; } -static void WmSize(JNIEnv *env, HWND wnd, jobject window, UINT type) +#endif + +static void WmSize(JNIEnv *env, jobject window, HWND wnd, UINT type) { RECT rc; int w, h; + BOOL isVisible = IsWindowVisible(wnd); // make sure insets are up to date - (void)UpdateInsets(env, wnd, window); + (void)UpdateInsets(env, window, wnd); if (type == SIZE_MINIMIZED) { // TODO: deal with minimized window sizing @@ -709,9 +786,11 @@ static void WmSize(JNIEnv *env, HWND wnd, jobject window, UINT type) w = rc.right - rc.left; h = rc.bottom - rc.top; - DBG_PRINT("*** WindowsWindow: WmSize window %p, %dx%d\n", (void*)wnd, w, h); + DBG_PRINT("*** WindowsWindow: WmSize window %p, %dx%d, visible %d\n", (void*)wnd, w, h, isVisible); - (*env)->CallVoidMethod(env, window, sizeChangedID, w, h); + if(isVisible) { + (*env)->CallVoidMethod(env, window, sizeChangedID, w, h, JNI_FALSE); + } } static LRESULT CALLBACK wndProc(HWND wnd, UINT message, @@ -795,14 +874,14 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, break; case WM_SIZE: - WmSize(env, wnd, window, (UINT)wParam); + WmSize(env, window, wnd, (UINT)wParam); break; case WM_SETTINGCHANGE: if (wParam == SPI_SETNONCLIENTMETRICS) { // make sure insets are updated, we don't need to resize the window // because the size of the client area doesn't change - (void)UpdateInsets(env, wnd, window); + (void)UpdateInsets(env, window, wnd); } else { useDefWindowProc = 1; } @@ -935,7 +1014,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, // ignore erase background (*env)->CallVoidMethod(env, window, windowRepaintID, 0, 0, -1, -1); useDefWindowProc = 0; - res = 1; + res = 1; // OpenGL, etc .. erases the background, hence we claim to have just done this break; @@ -1073,8 +1152,25 @@ JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_windows_WindowsScreen_getHeight JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_initIDs0 (JNIEnv *env, jclass clazz) { + if(NULL==pointClz) { + jclass c = (*env)->FindClass(env, ClazzNamePoint); + if(NULL==c) { + _FatalError(env, "NEWT WindowsWindows: can't find %s", ClazzNamePoint); + } + pointClz = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + if(NULL==pointClz) { + _FatalError(env, "NEWT WindowsWindows: can't use %s", ClazzNamePoint); + } + pointCstr = (*env)->GetMethodID(env, pointClz, ClazzAnyCstrName, ClazzNamePointCstrSignature); + if(NULL==pointCstr) { + _FatalError(env, "NEWT WindowsWindows: can't fetch %s.%s %s", + ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature); + } + } + insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(IIII)V"); - sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(II)V"); + sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(IIZ)V"); positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(II)V"); focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(Z)V"); visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V"); @@ -1170,7 +1266,7 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_CreateWi SetWindowLongPtr(window, GWLP_USERDATA, (intptr_t) wud); #endif - UpdateInsets(env, window, obj); + UpdateInsets(env, obj, window); } #ifdef UNICODE @@ -1232,109 +1328,115 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_MonitorF #endif } -/* - * Class: com_jogamp_newt_impl_windows_WindowsWindow - * Method: setVisible0 - * Signature: (JZ)V +/*** + * returns bits: 1: size change, 2: pos change */ -JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setVisible0 - (JNIEnv *_env, jclass clazz, jlong window, jboolean visible) +int NewtWindow_setVisiblePosSize(JNIEnv *env, jobject obj, HWND hwnd, jboolean top, jboolean visible, + int x, int y, int width, int height) { - HWND hwnd = (HWND) (intptr_t) window; - DBG_PRINT("*** WindowsWindow: setVisible window %p, visible: %d\n", hwnd, (int)visible); - if (visible) { - SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE); - ShowWindow(hwnd, SW_SHOW); + UINT flags; + HWND hWndInsertAfter; + BOOL bRes; + int iRes=0; + int wwidth = width; // final window width + int wheight = height; // final window height + + DBG_PRINT("*** WindowsWindow: NewtWindow_setVisiblePosSize %d/%d %dx%d, top %d, visible %d\n", + x, y, width, height, (int)top, (int)visible); + + if(JNI_TRUE == visible) { + flags = SWP_SHOWWINDOW; } else { - ShowWindow(hwnd, SW_HIDE); + flags = SWP_NOACTIVATE | SWP_NOZORDER; } -} -/* - * Class: com_jogamp_newt_impl_windows_WindowsWindow - * Method: setSize0 - * Signature: (JIIII)V - */ -JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setSize0 - (JNIEnv *env, jobject obj, jlong parent, jlong window, jint x, jint y, jint width, jint height) -{ - HWND hwndP = (HWND) (intptr_t) parent; - HWND hwnd = (HWND) (intptr_t) window; - int nWidth=width, nHeight=height; - int nX=x, nY=y; + if(0>x || 0>y ) { + flags |= SWP_NOMOVE; + } else { + iRes |= 2; + } + if(0>=width || 0>=height ) { + flags |= SWP_NOSIZE; + } else { + iRes |= 1; + } - if(NULL==hwndP) { - // since width, height are the size of the client area, we need to add - // insets - RECT *pInsets = UpdateInsets(env, hwnd, obj); + if(JNI_TRUE == top) { + hWndInsertAfter = HWND_TOPMOST; + if ( 0 == ( flags & SWP_NOSIZE ) ) { - RECT r; - GetWindowRect(hwnd, &r); + // since width, height are the size of the client area, we need to add insets + RECT *pInsets = UpdateInsets(env, obj, hwnd); - nWidth = width + pInsets->left + pInsets->right; - nHeight = height + pInsets->top + pInsets->bottom; - nX=r.left; nY=r.top; // FIXME: really ? + wwidth += pInsets->left + pInsets->right; + wheight += pInsets->top + pInsets->bottom; + } + DBG_PRINT("*** WindowsWindow: NewtWindow_setVisiblePosSize top size w/ insets: %d/%d %dx%d\n", x, y, wwidth, wheight); + } else { + hWndInsertAfter = HWND_TOP; + DBG_PRINT("*** WindowsWindow: NewtWindow_setVisiblePosSize client size: %d/%d %dx%d\n", x, y, wwidth, wheight); } - DBG_PRINT("*** WindowsWindow: setSize parent %p, window %p, %d/%d %dx%d -> %d/%d %dx%d\n", - hwndP, hwnd, x, y, width, height, nX, nY, nWidth, nHeight); + SetWindowPos(hwnd, hWndInsertAfter, x, y, wwidth, wheight, flags); - MoveWindow(hwnd, nX, nY, nWidth, nHeight, TRUE); + InvalidateRect(hwnd, NULL, TRUE); + UpdateWindow(hwnd); // we report back the size of client area - (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height); + (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height, JNI_FALSE); + + return iRes; } /* * Class: com_jogamp_newt_impl_windows_WindowsWindow - * Method: setPosition0 - * Signature: (JJII)V + * Method: setVisible0 + * Signature: (JZ)V */ -JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setPosition0 - (JNIEnv *env, jclass clazz, jlong parent, jlong window, jint x, jint y/*, jint width, jint height*/) +JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setVisible0 + (JNIEnv *env, jobject obj, jlong window, jboolean visible, jboolean top, jint x, jint y, jint width, jint height) { - HWND hwndP = (HWND) (intptr_t) parent; HWND hwnd = (HWND) (intptr_t) window; - - if(NULL==hwndP) { - DBG_PRINT("*** WindowsWindow: setPosition.1 parent %p, window %p, %d/%d\n", hwndP, hwnd, x, y); - - // Top Level Window .. SetWindowPos -> no need to do insets .. - SetWindowPos(hwnd, hwndP, x, y, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER); + DBG_PRINT("*** WindowsWindow: setVisible window %p, visible: %d, top %d, %d/%d %dx%d\n", + hwnd, (int)visible, (int)top, x, y, width, height); + if (visible) { + NewtWindow_setVisiblePosSize(env, obj, hwnd, top, visible, x, y, width, height); + ShowWindow(hwnd, SW_SHOW); } else { - RECT rc; - int w, h; - - GetClientRect(hwnd, &rc); - w = rc.right - rc.left; - h = rc.bottom - rc.top; - - DBG_PRINT("*** WindowsWindow: setPosition.2 parent %p, window %p, %d/%d, %dx%d\n", - hwndP, hwnd, x, y, /* width, height,*/ w, h); - - // Child Window .. must use MoveWindow, no insets (no decoration) - MoveWindow(hwnd, x, y, w, h, FALSE); + ShowWindow(hwnd, SW_HIDE); } } -static void NewtWindows_reparentWindow(JNIEnv *env, jobject obj, HWND hwndP, HWND hwnd, BOOL visible, - jint x, jint y, jint width, jint height, jboolean bIsUndecorated) +/* + * Class: com_jogamp_newt_impl_windows_WindowsWindow + * Method: reconfigureWindow0 + * Signature: (JIIIIZZII)V + */ +JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_reconfigureWindow0 + (JNIEnv *env, jobject obj, jlong parent, jlong window, jint x, jint y, jint width, jint height, + jboolean visible, jboolean parentChange, jint fullScreenChange, jint decorationChange) { - UINT flags; - HWND hWndInsertAfter; + HWND hwndP = (HWND) (intptr_t) parent; + HWND hwnd = (HWND) (intptr_t) window; DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN ; + BOOL styleChange = ( 0 != decorationChange || 0 != fullScreenChange || JNI_TRUE == parentChange ) ? TRUE : FALSE ; + UINT flags = SWP_SHOWWINDOW; + HWND hWndInsertAfter; + + DBG_PRINT("*** WindowsWindow: reconfigureWindow0 parent %p, window %p, %d/%d %dx%d, parentChange %d, fullScreenChange %d, visible %d, decorationChange %d -> styleChange %d\n", + parent, window, x, y, width, height, parentChange, fullScreenChange, visible, decorationChange, styleChange); - DBG_PRINT("*** WindowsWindow: reparentWindow.1 parent %p, window %p, %d/%d %dx%d undeco %d\n", (void*)hwndP, (void*)hwnd, x, y, width, height, bIsUndecorated); if (!IsWindow(hwnd)) { - DBG_PRINT("*** WindowsWindow: reparentWindow failure: Passed window %p is invalid\n", (void*)hwnd); + DBG_PRINT("*** WindowsWindow: reconfigureWindow0 failure: Passed window %p is invalid\n", (void*)hwnd); return; } + if (NULL!=hwndP && !IsWindow(hwndP)) { - DBG_PRINT("*** WindowsWindow: reparentWindow failure: Passed parent window %p is invalid\n", (void*)hwndP); + DBG_PRINT("*** WindowsWindow: reconfigureWindow0 failure: Passed parent window %p is invalid\n", (void*)hwndP); return; } - if(visible) { + if(JNI_TRUE == visible) { windowStyle |= WS_VISIBLE ; } @@ -1342,74 +1444,30 @@ static void NewtWindows_reparentWindow(JNIEnv *env, jobject obj, HWND hwndP, HWN // TOP: SetParent(.., NULL); Clear WS_CHILD [, Set WS_POPUP] // CHILD: Set WS_CHILD [, Clear WS_POPUP]; SetParent(.., PARENT) // - if ( NULL == hwndP ) { + if ( JNI_TRUE == parentChange && NULL == hwndP ) { SetParent(hwnd, NULL); - DBG_PRINT("*** WindowsWindow: reparentWindow.2\n"); } - if(NULL!=hwndP) { - windowStyle |= WS_CHILD ; - } else if (bIsUndecorated) { - windowStyle |= WS_POPUP | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX; - } else { - windowStyle |= WS_OVERLAPPEDWINDOW; + if ( styleChange ) { + if(NULL!=hwndP) { + windowStyle |= WS_CHILD ; + } else if ( decorationChange < 0 || 0 < fullScreenChange ) { + windowStyle |= WS_POPUP | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX; + } else { + windowStyle |= WS_OVERLAPPEDWINDOW; + } + SetWindowLong(hwnd, GWL_STYLE, windowStyle); + SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER ); } - SetWindowLong(hwnd, GWL_STYLE, windowStyle); - DBG_PRINT("*** WindowsWindow: reparentWindow.3\n"); - if ( NULL != hwndP ) { + if ( JNI_TRUE == parentChange && NULL != hwndP ) { SetParent(hwnd, hwndP ); - DBG_PRINT("*** WindowsWindow: reparentWindow.4\n"); } - DBG_PRINT("*** WindowsWindow: reparentWindow.X\n"); -} - -/* - * Class: com_jogamp_newt_impl_windows_WindowsWindow - * Method: reconfigureWindow0 - * Signature: (JIIIIZ)V - */ -JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_reconfigureWindow0 - (JNIEnv *env, jobject obj, jlong parent, jlong window, jint x, jint y, jint width, jint height, jboolean bIsUndecorated) -{ - UINT flags; - HWND hwndP = (HWND) (intptr_t) parent; - HWND hwnd = (HWND) (intptr_t) window; - HWND hWndInsertAfter; - BOOL isVisible = IsWindowVisible(hwnd); - - DBG_PRINT("*** WindowsWindow: reconfigureWindow0.1 parent %p, window %p, %d/%d %dx%d undeco %d visible\n", - parent, window, x, y, width, height, bIsUndecorated, isVisible); - - NewtWindows_reparentWindow(env, obj, hwndP, hwnd, FALSE, x, y, width, height, bIsUndecorated); - - if ( NULL == hwndP ) { - flags = SWP_SHOWWINDOW; - hWndInsertAfter = HWND_TOPMOST; - } else { - flags = SWP_NOACTIVATE | SWP_NOZORDER; - hWndInsertAfter = 0; - } - SetWindowPos(hwnd, hWndInsertAfter, x, y, width, height, flags); + NewtWindow_setVisiblePosSize(env, obj, hwnd, (NULL == hwndP) ? JNI_TRUE : JNI_FALSE /* top */, visible, + x, y, width, height); DBG_PRINT("*** WindowsWindow: reconfigureWindow0.X\n"); - (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height); // resize necessary .. -} - -/* - * Class: com_jogamp_newt_impl_windows_WindowsWindow - * Method: reparentWindow0 - * Signature: (JIIIIZ)V - */ -JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_reparentWindow0 - (JNIEnv *env, jobject obj, jlong parent, jlong window, jint x, jint y, jint width, jint height, jboolean bIsUndecorated) -{ - HWND hwndP = (HWND) (intptr_t) parent; - HWND hwnd = (HWND) (intptr_t) window; - BOOL isVisible = IsWindowVisible(hwnd); - - NewtWindows_reparentWindow(env, obj, hwndP, hwnd, FALSE, x, y, width, height, bIsUndecorated); } /* @@ -1433,12 +1491,33 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setTitle0 /* * Class: com_jogamp_newt_impl_windows_WindowsWindow * Method: requestFocus - * Signature: (J)V + * Signature: (JZ)V */ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_requestFocus0 - (JNIEnv *env, jobject obj, jlong window, jboolean bReparented) + (JNIEnv *env, jobject obj, jlong window, jboolean force) { - DBG_PRINT("*** WindowsWindow: RequestFocus0: reparented %d\n", (int)bReparented); - NewtWindows_requestFocus ( env, obj, (HWND) (intptr_t) window, bReparented ) ; + DBG_PRINT("*** WindowsWindow: RequestFocus0\n"); + NewtWindows_requestFocus ( env, obj, (HWND) (intptr_t) window, force) ; +} + +/* + * Class: com_jogamp_newt_impl_windows_WindowsWindows + * Method: getRelativeLocation0 + * Signature: (JJII)Ljavax/media/nativewindow/util/Point; + */ +JNIEXPORT jobject JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_getRelativeLocation0 + (JNIEnv *env, jobject obj, jlong jsrc_win, jlong jdest_win, jint src_x, jint src_y) +{ + HWND src_win = (HWND) (intptr_t) jsrc_win; + HWND dest_win = (HWND) (intptr_t) jdest_win; + POINT dest = { src_x, src_y } ; + int res; + + res = MapWindowPoints(src_win, dest_win, &dest, 1); + + DBG_PRINT("*** WindowsWindow: getRelativeLocation0: %p %d/%d -> %p %d/%d - ok: %d\n", + (void*)src_win, src_x, src_y, (void*)dest_win, (int)dest.x, (int)dest.y, res); + + return (*env)->NewObject(env, pointClz, pointCstr, (jint)dest.x, (jint)dest.y); } diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index 1394b5410..0cdf6ae57 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -146,12 +146,20 @@ static void _FatalError(JNIEnv *env, const char* msg, ...) } static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException"; + +static const char * const ClazzNameNewtWindow = "com/jogamp/newt/Window"; + +static const char * const ClazzNamePoint = "javax/media/nativewindow/util/Point"; +static const char * const ClazzAnyCstrName = "<init>"; +static const char * const ClazzNamePointCstrSignature = "(II)V"; + static jclass runtimeExceptionClz=NULL; -static const char * const ClazzNameNewtWindow = - "com/jogamp/newt/Window"; static jclass newtWindowClz=NULL; +static jclass pointClz = NULL; +static jmethodID pointCstr = NULL; + static jmethodID sizeChangedID = NULL; static jmethodID positionChangedID = NULL; static jmethodID focusChangedID = NULL; @@ -159,7 +167,7 @@ static jmethodID visibleChangedID = NULL; static jmethodID windowDestroyNotifyID = NULL; static jmethodID windowDestroyedID = NULL; static jmethodID windowRepaintID = NULL; -static jmethodID windowCreatedID = NULL; +static jmethodID windowReparentedID = NULL; static jmethodID enqueueMouseEventID = NULL; static jmethodID sendMouseEventID = NULL; static jmethodID enqueueKeyEventID = NULL; @@ -169,6 +177,7 @@ static jmethodID enqueueRequestFocusID = NULL; static jmethodID displayCompletedID = NULL; + static void _throwNewRuntimeException(Display * unlockDisplay, JNIEnv *env, const char* msg, ...) { char buffer[512]; @@ -256,6 +265,22 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_x11_X11Display_initIDs0 } } + if(NULL==pointClz) { + c = (*env)->FindClass(env, ClazzNamePoint); + if(NULL==c) { + _FatalError(env, "NEWT X11Windows: can't find %s", ClazzNamePoint); + } + pointClz = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + if(NULL==pointClz) { + _FatalError(env, "NEWT X11Windows: can't use %s", ClazzNamePoint); + } + pointCstr = (*env)->GetMethodID(env, pointClz, ClazzAnyCstrName, ClazzNamePointCstrSignature); + if(NULL==pointCstr) { + _FatalError(env, "NEWT X11Windows: can't fetch %s.%s %s", + ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature); + } + } return JNI_TRUE; } @@ -298,7 +323,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_CompleteDisplay0 * Window */ -#define WINDOW_EVENT_MASK ( FocusChangeMask | StructureNotifyMask | ExposureMask ) +#define WINDOW_EVENT_MASK ( FocusChangeMask | SubstructureNotifyMask | StructureNotifyMask | ExposureMask ) static int putPtrIn32Long(unsigned long * dst, uintptr_t src) { int i=0; @@ -377,32 +402,43 @@ static jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, j return jwindow; } -/** -static Window NewtWindows_getParent (Display *dpy, Window w) { - Window root_return=0; - Window parent_return=0; +/** @return zero if fails, non zero if OK */ +static Status NewtWindows_getRootAndParent (Display *dpy, Window w, Window * root_return, Window * parent_return) { Window *children_return=NULL; unsigned int nchildren_return=0; - Status res = XQueryTree(dpy, w, &root_return, &parent_return, &children_return, &nchildren_return); + Status res = XQueryTree(dpy, w, root_return, parent_return, &children_return, &nchildren_return); if(NULL!=children_return) { XFree(children_return); } - if(0!=res) { + return res; +} +static Window NewtWindows_getRoot (Display *dpy, Window w) { + Window root_return; + Window parent_return; + if( 0 != NewtWindows_getRootAndParent(dpy, w, &root_return, &parent_return) ) { + return root_return; + } + return 0; +} +static Window NewtWindows_getParent (Display *dpy, Window w) { + Window root_return; + Window parent_return; + if( 0 != NewtWindows_getRootAndParent(dpy, w, &root_return, &parent_return) ) { return parent_return; } return 0; -} */ +} + -static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, Window w, - Bool reparented) { +static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, Window w, jboolean force) { XWindowAttributes xwa; Window focus_return; int revert_to_return; XGetInputFocus(dpy, &focus_return, &revert_to_return); - if(reparented || focus_return!=w) { - if( reparented || JNI_FALSE == (*env)->CallBooleanMethod(env, window, focusActionID) ) { + if( JNI_TRUE==force || focus_return!=w) { + if( JNI_TRUE==force || JNI_FALSE == (*env)->CallBooleanMethod(env, window, focusActionID) ) { XRaiseWindow(dpy, w); // Avoid 'BadMatch' errors from XSetInputFocus, ie if window is not viewable XGetWindowAttributes(dpy, w, &xwa); @@ -414,32 +450,6 @@ static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, XSync(dpy, False); } -/** - * Changing this attribute while a window is established, - * returns the previous value. - */ -static Bool NewtWindows_setOverrideRedirect0 (Display *dpy, Window w, XWindowAttributes *xwa, Bool newVal) { - Bool oldVal = xwa->override_redirect; - XSetWindowAttributes xswa; - - if(oldVal != newVal) { - memset(&xswa, 0, sizeof(XSetWindowAttributes)); - xswa.override_redirect = newVal; - XChangeWindowAttributes(dpy, w, CWOverrideRedirect, &xswa); - } - return oldVal; -} - -static Bool NewtWindows_setOverrideRedirect1 (Display *dpy, Window w, Bool newVal) { - XWindowAttributes xwa; - Bool oldVal; - - XSync(dpy, False); - XGetWindowAttributes(dpy, w, &xwa); - - return NewtWindows_setOverrideRedirect0 (dpy, w, &xwa, newVal); -} - #define MWM_HINTS_DECORATIONS (1L << 1) #define PROP_MWM_HINTS_ELEMENTS 5 @@ -466,7 +476,7 @@ 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 w, Bool fullscreen) { +static void NewtWindows_setFullscreen (Display *dpy, Window root, Window w, 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 ); @@ -496,11 +506,13 @@ static void NewtWindows_setFullscreen (Display *dpy, Window w, Bool 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); - XSendEvent (dpy, DefaultRootWindow(dpy), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev ); + XSync(dpy, False); + XSendEvent (dpy, root, False, SubstructureRedirectMask | SubstructureNotifyMask, &xev ); } +#define USE_SENDIO_DIRECT 1 + /* * Class: com_jogamp_newt_impl_x11_X11Display * Method: DispatchMessages @@ -545,7 +557,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_DispatchMessages return ; } - DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, evt.type); + // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, evt.type); displayDispatchErrorHandlerEnable(1, env); @@ -581,30 +593,64 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_DispatchMessages switch(evt.type) { case ButtonPress: (*env)->CallVoidMethod(env, jwindow, enqueueRequestFocusID, JNI_FALSE); + #ifdef USE_SENDIO_DIRECT (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, (jint) evt.xbutton.state, (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); + #else + (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, + JNI_FALSE, + (jint) EVENT_MOUSE_PRESSED, + (jint) evt.xbutton.state, + (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); + #endif break; case ButtonRelease: + #ifdef USE_SENDIO_DIRECT (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, (jint) evt.xbutton.state, (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); + #else + (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, + JNI_FALSE, + (jint) EVENT_MOUSE_RELEASED, + (jint) evt.xbutton.state, + (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); + #endif break; case MotionNotify: + #ifdef USE_SENDIO_DIRECT (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, (jint) evt.xmotion.state, (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/); + #else + (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, + JNI_FALSE, + (jint) EVENT_MOUSE_MOVED, + (jint) evt.xmotion.state, + (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/); + #endif break; case KeyPress: + #ifdef USE_SENDIO_DIRECT (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED, (jint) evt.xkey.state, X11KeySym2NewtVKey(keySym), (jchar) keyChar); + #else + (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, + JNI_FALSE, + (jint) EVENT_KEY_PRESSED, + (jint) evt.xkey.state, + X11KeySym2NewtVKey(keySym), (jchar) keyChar); + #endif + break; case KeyRelease: + #ifdef USE_SENDIO_DIRECT (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED, (jint) evt.xkey.state, @@ -614,69 +660,132 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_DispatchMessages (jint) EVENT_KEY_TYPED, (jint) evt.xkey.state, (jint) -1, (jchar) keyChar); + #else + (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, + JNI_FALSE, + (jint) EVENT_KEY_RELEASED, + (jint) evt.xkey.state, + X11KeySym2NewtVKey(keySym), (jchar) keyChar); + + (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, + JNI_FALSE, + (jint) EVENT_KEY_TYPED, + (jint) evt.xkey.state, + (jint) -1, (jchar) keyChar); + #endif + break; case DestroyNotify: - DBG_PRINT( "X11: event . DestroyNotify call 0x%X\n", (unsigned int)evt.xdestroywindow.window); - (*env)->CallVoidMethod(env, jwindow, windowDestroyedID); + DBG_PRINT( "X11: event . DestroyNotify call %p, parent %p, child-event: %d\n", + (void*)evt.xdestroywindow.window, (void*)evt.xdestroywindow.event, evt.xdestroywindow.window != evt.xdestroywindow.event); + if ( evt.xdestroywindow.window == evt.xdestroywindow.event ) { + // ignore child destroy notification + (*env)->CallVoidMethod(env, jwindow, windowDestroyedID); + } break; case CreateNotify: - DBG_PRINT( "X11: event . CreateNotify call 0x%X\n", (unsigned int)evt.xcreatewindow.window); - (*env)->CallVoidMethod(env, jwindow, windowCreatedID); + DBG_PRINT( "X11: event . CreateNotify call %p, parent %p, child-event: 1\n", + (void*)evt.xcreatewindow.window, (void*) evt.xcreatewindow.parent); break; case ConfigureNotify: - DBG_PRINT( "X11: event . ConfigureNotify call 0x%X (parent 0x%X, above 0x%X) %d/%d %dx%d %d\n", - (unsigned int)evt.xconfigure.window, (unsigned int)evt.xconfigure.event, (unsigned int)evt.xconfigure.above, + DBG_PRINT( "X11: event . ConfigureNotify call %p (parent %p, above %p) %d/%d %dx%d %d, child-event: %d\n", + (void*)evt.xconfigure.window, (void*)evt.xconfigure.event, (void*)evt.xconfigure.above, evt.xconfigure.x, evt.xconfigure.y, evt.xconfigure.width, evt.xconfigure.height, - evt.xconfigure.override_redirect); - (*env)->CallVoidMethod(env, jwindow, sizeChangedID, - (jint) evt.xconfigure.width, (jint) evt.xconfigure.height); - (*env)->CallVoidMethod(env, jwindow, positionChangedID, - (jint) evt.xconfigure.x, (jint) evt.xconfigure.y); + evt.xconfigure.override_redirect, evt.xconfigure.window != evt.xconfigure.event); + if ( evt.xconfigure.window == evt.xconfigure.event ) { + // ignore child window change notification + (*env)->CallVoidMethod(env, jwindow, sizeChangedID, + (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, JNI_FALSE); + (*env)->CallVoidMethod(env, jwindow, positionChangedID, + (jint) evt.xconfigure.x, (jint) evt.xconfigure.y); + } break; case ClientMessage: if (evt.xclient.send_event==True && evt.xclient.data.l[0]==(Atom)wmDeleteAtom) { - DBG_PRINT( "X11: event . ClientMessage call 0x%X type 0x%X !!!\n", (unsigned int)evt.xclient.window, (unsigned int)evt.xclient.message_type); + DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X !!!\n", + (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type); (*env)->CallVoidMethod(env, jwindow, windowDestroyNotifyID); // Called by Window.java: CloseWindow(); } break; case FocusIn: - DBG_PRINT( "X11: event . FocusIn call 0x%X\n", (unsigned int)evt.xvisibility.window); + DBG_PRINT( "X11: event . FocusIn call %p\n", (void*)evt.xvisibility.window); (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_TRUE); break; case FocusOut: - DBG_PRINT( "X11: event . FocusOut call 0x%X\n", (unsigned int)evt.xvisibility.window); + DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xvisibility.window); (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE); break; case Expose: - DBG_PRINT( "X11: event . Expose call 0x%X %d/%d %dx%d\n", (unsigned int)evt.xexpose.window, - evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height); + DBG_PRINT( "X11: event . Expose call %p %d/%d %dx%d count %d\n", (void*)evt.xexpose.window, + evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height, evt.xexpose.count); - if (evt.xexpose.width > 0 && evt.xexpose.height > 0) { + if (evt.xexpose.count == 0 && evt.xexpose.width > 0 && evt.xexpose.height > 0) { (*env)->CallVoidMethod(env, jwindow, windowRepaintID, evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height); } break; case MapNotify: - DBG_PRINT( "X11: event . MapNotify call Event 0x%X, Window 0x%X, override_redirect %d\n", - (unsigned int)evt.xmap.event, (unsigned int)evt.xmap.window, (int)evt.xmap.override_redirect); - (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_TRUE); + DBG_PRINT( "X11: event . MapNotify call Event %p, Window %p, override_redirect %d, child-event: %d\n", + (void*)evt.xmap.event, (void*)evt.xmap.window, (int)evt.xmap.override_redirect, + evt.xmap.event!=evt.xmap.window); + if( evt.xmap.event == evt.xmap.window ) { + // ignore child window notification + (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_TRUE); + } break; case UnmapNotify: - DBG_PRINT( "X11: event . UnmapNotify call Event 0x%X, Window 0x%X, from_configure %d\n", - (unsigned int)evt.xunmap.event, (unsigned int)evt.xunmap.window, (int)evt.xunmap.from_configure); - (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE); + DBG_PRINT( "X11: event . UnmapNotify call Event %p, Window %p, from_configure %d, child-event: %d\n", + (void*)evt.xunmap.event, (void*)evt.xunmap.window, (int)evt.xunmap.from_configure, + evt.xunmap.event!=evt.xunmap.window); + if( evt.xunmap.event == evt.xunmap.window ) { + // ignore child window notification + (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE); + } + break; + + case ReparentNotify: + { + jlong parentResult; // 0 if root, otherwise proper value + Window winRoot, winTopParent; + #ifdef VERBOSE_ON + Window oldParentRoot, oldParentTopParent; + Window parentRoot, parentTopParent; + if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.event, &oldParentRoot, &oldParentTopParent) ) { + oldParentRoot=0; oldParentTopParent = 0; + } + if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.parent, &parentRoot, &parentTopParent) ) { + parentRoot=0; parentTopParent = 0; + } + #endif + if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.window, &winRoot, &winTopParent) ) { + winRoot=0; winTopParent = 0; + } + if(evt.xreparent.parent == winRoot) { + parentResult = 0; // our java indicator for root window + } else { + parentResult = (jlong) (intptr_t) evt.xreparent.parent; + } + #ifdef VERBOSE_ON + DBG_PRINT( "X11: event . ReparentNotify: call OldParent %p (root %p, top %p), NewParent %p (root %p, top %p), Window %p (root %p, top %p)\n", + (void*)evt.xreparent.event, (void*)oldParentRoot, (void*)oldParentTopParent, + (void*)evt.xreparent.parent, (void*)parentRoot, (void*)parentTopParent, + (void*)evt.xreparent.window, (void*)winRoot, (void*)winTopParent); + #endif + + (*env)->CallVoidMethod(env, jwindow, windowReparentedID, parentResult); + } break; // unhandled events .. yet .. default: - DBG_PRINT("X11: event . unhandled %d 0x%X call 0x%X\n", evt.type, evt.type, (unsigned int)evt.xunmap.window); + DBG_PRINT("X11: event . unhandled %d 0x%X call %p\n", (int)evt.type, (unsigned int)evt.type, (void*)evt.xunmap.window); } } } @@ -741,14 +850,14 @@ JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getHeight0 JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_x11_X11Window_initIDs0 (JNIEnv *env, jclass clazz) { - sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(II)V"); + sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(IIZ)V"); positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(II)V"); focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(Z)V"); visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V"); windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(IIII)V"); - windowCreatedID = (*env)->GetMethodID(env, clazz, "windowCreated", "(J)V"); + windowReparentedID = (*env)->GetMethodID(env, clazz, "windowReparented", "(J)V"); enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZIIIIII)V"); sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V"); enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZIIIC)V"); @@ -763,7 +872,7 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_x11_X11Window_initIDs0 windowDestroyNotifyID == NULL || windowDestroyedID == NULL || windowRepaintID == NULL || - windowCreatedID == NULL || + windowReparentedID == NULL || enqueueMouseEventID == NULL || sendMouseEventID == NULL || enqueueKeyEventID == NULL || @@ -819,6 +928,9 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CreateWindow0 if(0==windowParent) { windowParent = XRootWindowOfScreen(scrn); } + if( XRootWindowOfScreen(scrn) != XRootWindow(dpy, scrn_idx) ) { + _FatalError(env, "XRoot Malfunction: %p != %p"+XRootWindowOfScreen(scrn), XRootWindow(dpy, scrn_idx)); + } DBG_PRINT( "X11: CreateWindow dpy %p, parent %p, %x/%d %dx%d, undeco %d\n", (void*)dpy, (void*)windowParent, x, y, width, height, undecorated); @@ -853,7 +965,8 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CreateWindow0 CWBorderPixel | CWColormap | CWOverrideRedirect ) ; memset(&xswa, 0, sizeof(xswa)); - xswa.override_redirect = ( 0 != parent ) ? True : False ; + // xswa.override_redirect = ( 0 != parent ) ? False : True; + xswa.override_redirect = False; // use the window manager, always xswa.border_pixel = 0; xswa.background_pixel = 0; xswa.backing_store=NotUseful; /* NotUseful, WhenMapped, Always */ @@ -861,7 +974,7 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CreateWindow0 xswa.backing_pixel=0; /* value to use in restoring planes */ xswa.colormap = XCreateColormap(dpy, - windowParent, // XRootWindow(dpy, scrn_idx), + windowParent, visual, AllocNone); @@ -900,9 +1013,7 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CreateWindow0 NewtWindows_setDecorations(dpy, window, ( JNI_TRUE == undecorated ) ? False : True ); XSync(dpy, False); - DBG_PRINT( "X11: [CreateWindow] created window 0x%X on display %p\n", (unsigned int)window, dpy); - (*env)->CallVoidMethod(env, obj, windowCreatedID, (jlong) window); - + DBG_PRINT( "X11: [CreateWindow] created window %p on display %p\n", (void*)window, dpy); return (jlong) window; } @@ -951,13 +1062,30 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CloseWindow0 (*env)->CallVoidMethod(env, obj, windowDestroyedID); } +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; + unsigned int mod_flags = ( (x>=0)?CWX:0 ) | ( (y>=0)?CWY:0 ) | + ( (width>0)?CWWidth:0 ) | ( (height>0)?CWHeight:0 ) ; + DBG_PRINT( "X11: reconfigureWindow0 pos/size mod: 0x%X\n", mod_flags); + memset(&xwc, 0, sizeof(XWindowChanges)); + xwc.x=x; + xwc.y=y; + xwc.width=width; + xwc.height=height; + XConfigureWindow(dpy, w, mod_flags, &xwc); + XSync(dpy, False); + } +} + /* * Class: com_jogamp_newt_impl_x11_X11Window * Method: setVisible0 - * Signature: (JJZ)V + * Signature: (JJZIIII)V */ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_setVisible0 - (JNIEnv *env, jobject obj, jlong display, jlong window, jboolean visible) + (JNIEnv *env, jobject obj, jlong display, jlong window, jboolean visible, jint x, jint y, jint width, jint height) { Display * dpy = (Display *) (intptr_t) display; Window w = (Window)window; @@ -973,178 +1101,77 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_setVisible0 XUnmapWindow(dpy, w); } XSync(dpy, False); -} - -/* - * Class: com_jogamp_newt_impl_x11_X11Window - * Method: setSize0 - * Signature: (JJII)V - */ -JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_setSize0 - (JNIEnv *env, jobject obj, jlong display, jlong window, jint width, jint height) -{ - Display * dpy = (Display *) (intptr_t) display; - Window w = (Window)window; - XWindowChanges xwc; - - DBG_PRINT( "X11: setSize0 %dx%d\n", width, height); - if(dpy==NULL) { - _FatalError(env, "invalid display connection.."); - } - - memset(&xwc, 0, sizeof(XWindowChanges)); - xwc.width=width; - xwc.height=height; - XConfigureWindow(dpy, w, CWWidth|CWHeight, &xwc); - - XSync(dpy, False); + NewtWindows_setPosSize(dpy, w, x, y, width, height); } /* * Class: com_jogamp_newt_impl_x11_X11Window - * Method: setPosition0 - * Signature: (JJII)V + * Method: reconfigureWindow0 + * Signature: (JIJJIIIIZZII)V */ -JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_setPosition0 - (JNIEnv *env, jobject obj, jlong parent, jlong display, jlong window, jint x, jint y) +JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_reconfigureWindow0 + (JNIEnv *env, jobject obj, jlong jdisplay, jint screen_index, jlong jparent, jlong jwindow, + jint x, jint y, jint width, jint height, jboolean isVisible, jboolean parentChange, jint fullscreenChange, jint decorationChange) { - Display * dpy = (Display *) (intptr_t) display; - Window w = (Window)window; - XWindowChanges xwc; - - DBG_PRINT( "X11: setPos0 . XConfigureWindow %d/%d\n", x, y); - if(dpy==NULL) { - _FatalError(env, "invalid display connection.."); - } + Display * dpy = (Display *) (intptr_t) jdisplay; + Screen * scrn = ScreenOfDisplay(dpy, (int)screen_index); + Window w = (Window)jwindow; + Window root = XRootWindowOfScreen(scrn); + Window parent = (0!=jparent)?(Window)jparent:root; + Window topParentParent; + Window topParentWindow; + Bool moveIntoParent = False; - memset(&xwc, 0, sizeof(XWindowChanges)); - xwc.x=x; - xwc.y=y; - XConfigureWindow(dpy, w, CWX|CWY, &xwc); - XSync(dpy, False); -} + displayDispatchErrorHandlerEnable(1, env); -static void NewtWindows_reparentWindow - (JNIEnv *env, jobject obj, - Display * dpy, Screen * scrn, Window w, XWindowAttributes *xwa, jlong jparent, - jint x, jint y, jboolean undecorated, jboolean isVisible) -{ - Window parent = (0!=jparent)?(Window)jparent:XRootWindowOfScreen(scrn); + topParentParent = NewtWindows_getParent (dpy, parent); + topParentWindow = NewtWindows_getParent (dpy, w); - DBG_PRINT( "X11: reparentWindow dpy %p, parent %p/%p, win %p, %d/%d undec %d\n", - (void*)dpy, (void*) jparent, (void*)parent, (void*)w, x, y, undecorated); + DBG_PRINT( "X11: reconfigureWindow0 dpy %p, scrn %d/%p, parent %p/%p (top %p), win %p (top %p), %d/%d %dx%d visible %d, parentChange %d, fullscreenChange %d, decorationChange %d\n", + (void*)dpy, screen_index, (void*)scrn, (void*) jparent, (void*)parent, (void*) topParentParent, (void*)w, (void*)topParentWindow, + x, y, width, height, isVisible, parentChange, fullscreenChange, decorationChange); - if(JNI_TRUE == isVisible) { + if(parentChange && JNI_TRUE == isVisible) { // unmap window if visible, reduce X11 internal signaling (WM unmap) XUnmapWindow(dpy, w); XSync(dpy, False); } - if(0 != jparent) { - // move into parent .. - NewtWindows_setDecorations (dpy, w, False); - XSync(dpy, False); - NewtWindows_setOverrideRedirect0 (dpy, w, xwa, True); + if(0 > fullscreenChange ) { // FS off + NewtWindows_setFullscreen(dpy, root, w, False ); XSync(dpy, False); } - XReparentWindow( dpy, w, parent, x, y ); - XSync(dpy, False); - - if(0 == jparent) - { - // move out of parent .. - NewtWindows_setOverrideRedirect0 (dpy, w, xwa, False); - XSync(dpy, False); - NewtWindows_setDecorations (dpy, w, (JNI_TRUE == undecorated) ? False : True); + if(parentChange) { + if(0 != jparent) { // move into parent .. + moveIntoParent = True; + NewtWindows_setDecorations (dpy, w, False); + XSync(dpy, False); + } + XReparentWindow( dpy, w, parent, x, y ); // actual reparent call XSync(dpy, False); } - if(JNI_TRUE == isVisible) { - XMapRaised(dpy, w); + if(!moveIntoParent && 0!=decorationChange) { + NewtWindows_setDecorations (dpy, w, (0 < decorationChange) ? True : False); XSync(dpy, False); } - DBG_PRINT( "X11: reparentWindow X\n"); -} - -/* - * Class: com_jogamp_newt_impl_x11_X11Window - * Method: reconfigureWindow0 - * Signature: (JJIJIIIIZ)V - */ -JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_reconfigureWindow0 - (JNIEnv *env, jobject obj, jlong jparent, jlong display, jint screen_index, jlong window, - jint x, jint y, jint width, jint height, jboolean undecorated, jboolean isVisible, jboolean isFullscreen) -{ - Display * dpy = (Display *) (intptr_t) display; - Window w = (Window)window; - Screen * scrn = ScreenOfDisplay(dpy, (int)screen_index); - - XWindowChanges xwc; - XWindowAttributes xwa; - - DBG_PRINT( "X11: reconfigureWindow0 dpy %p, parent %p, win %p, %d/%d %dx%d undec %d, visible %d, fullscreen %d\n", - (void*)dpy, (void*) jparent, (void*)w, x, y, width, height, undecorated, isVisible,isFullscreen); - - if(dpy==NULL) { - _FatalError(env, "invalid display connection.."); - } + NewtWindows_setPosSize(dpy, w, x, y, width, height); - - XSync(dpy, False); - XGetWindowAttributes(dpy, w, &xwa); - - if(JNI_FALSE == isFullscreen ) { - NewtWindows_setFullscreen(dpy, w, False ); - XSync(dpy, False); + if(0 < fullscreenChange ) { // FS on + NewtWindows_setFullscreen(dpy, root, w, True ); + XSync(dpy, False); } - NewtWindows_reparentWindow(env, obj, dpy, scrn, w, &xwa, jparent, x, y, undecorated, isVisible); - XSync(dpy, False); - - 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); - - if(JNI_TRUE == isFullscreen ) { - NewtWindows_setFullscreen(dpy, w, True ); - XSync(dpy, False); - } -} - -/* - * Class: com_jogamp_newt_impl_x11_X11Window - * Method: reparentWindow0 - * Signature: (JJIJIIZ)V - */ -JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_reparentWindow0 - (JNIEnv *env, jobject obj, jlong jparent, jlong display, jint screen_index, jlong window, jint x, jint y, - jboolean undecorated, jboolean isVisible) -{ - Display * dpy = (Display *) (intptr_t) display; - Window w = (Window)window; - Screen * scrn = ScreenOfDisplay(dpy, (int)screen_index); - XWindowAttributes xwa; - - DBG_PRINT( "X11: reparentWindow0 dpy %p, parent %p, win %p, %d/%d undec %d, visible %d\n", - (void*)dpy, (void*) jparent, (void*)w, x, y, undecorated, isVisible); - - if(dpy==NULL) { - _FatalError(env, "invalid display connection.."); + if(parentChange && JNI_TRUE == isVisible) { // map window + XMapRaised(dpy, w); + XSync(dpy, False); } - XSync(dpy, False); - XGetWindowAttributes(dpy, w, &xwa); - - NewtWindows_reparentWindow(env, obj, dpy, scrn, w, &xwa, jparent, x, y, undecorated, isVisible); - XSync(dpy, False); + displayDispatchErrorHandlerEnable(0, env); - DBG_PRINT( "X11: reparentWindow0 X\n"); + DBG_PRINT( "X11: reconfigureWindow0 X\n"); } /* @@ -1153,9 +1180,9 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_reparentWindow0 * Signature: (JJ)V */ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_requestFocus0 - (JNIEnv *env, jobject obj, jlong display, jlong window, jboolean bReparented) + (JNIEnv *env, jobject obj, jlong display, jlong window, jboolean force) { - NewtWindows_requestFocus ( env, obj, (Display *) (intptr_t) display, (Window)window, bReparented ) ; + NewtWindows_requestFocus ( env, obj, (Display *) (intptr_t) display, (Window)window, force ) ; } /* @@ -1210,3 +1237,37 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_setTitle0 } + +/* + * Class: com_jogamp_newt_impl_x11_X11Window + * Method: getRelativeLocation0 + * Signature: (JIJJII)Ljavax/media/nativewindow/util/Point; + */ +JNIEXPORT jobject JNICALL Java_com_jogamp_newt_impl_x11_X11Window_getRelativeLocation0 + (JNIEnv *env, jobject obj, jlong jdisplay, jint screen_index, jlong jsrc_win, jlong jdest_win, jint src_x, jint src_y) +{ + Display * dpy = (Display *) (intptr_t) jdisplay; + Screen * scrn = ScreenOfDisplay(dpy, (int)screen_index); + Window root = XRootWindowOfScreen(scrn); + Window src_win = (Window)jsrc_win; + Window dest_win = (Window)jdest_win; + int dest_x=-1; + int dest_y=-1; + Window child; + Bool res; + + if( 0 == jdest_win ) { dest_win = root; } + if( 0 == jsrc_win ) { src_win = root; } + + displayDispatchErrorHandlerEnable(1, env); + + res = XTranslateCoordinates(dpy, src_win, dest_win, src_x, src_y, &dest_x, &dest_y, &child); + + displayDispatchErrorHandlerEnable(0, env); + + DBG_PRINT( "X11: getRelativeLocation0: %p %d/%d -> %p %d/%d - ok: %d\n", + (void*)src_win, src_x, src_y, (void*)dest_win, dest_x, dest_y, (int)res); + + return (*env)->NewObject(env, pointClz, pointCstr, (jint)dest_x, (jint)dest_y); +} + |