From 944bef5e70e0e8fe85a147fa7304c35f18d1957b Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Thu, 27 May 2010 14:25:37 +0200 Subject: Fix NativeWindow JAWT Code Generation and Bounds Access - Restructure: JAWT gluegen, use common jawt-common.cfg - Fix: Use proper capacity for GetDrawingSurface and GetDrawingSurfaceInfo - Fix: JAWTWindow maintains AWT bounds - Fix: JAWTWindow locking/unlocking decoupled with abstract implementation, which allows clear code and simpler unlock code. --- .../com/jogamp/newt/awt/NewtFactoryAWT.java | 139 +++++++++++++++++++++ .../com/jogamp/newt/impl/awt/AWTNewtFactory.java | 139 --------------------- 2 files changed, 139 insertions(+), 139 deletions(-) create mode 100644 src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java delete mode 100644 src/newt/classes/com/jogamp/newt/impl/awt/AWTNewtFactory.java (limited to 'src/newt') diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java new file mode 100644 index 000000000..e0f86b1a9 --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2010 Sven Gothel. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name Sven Gothel or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.newt.impl.awt; + +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.Component; +import java.awt.Canvas; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.awt.*; + +import com.jogamp.newt.event.awt.AWTParentWindowAdapter; +import com.jogamp.newt.Display; +import com.jogamp.newt.Screen; +import com.jogamp.newt.Window; +import com.jogamp.newt.NewtFactory; +import com.jogamp.common.util.ReflectionUtil; + +public class AWTNewtFactory extends NewtFactory { + + /** + * Wraps an AWT component into a {@link javax.media.nativewindow.NativeWindow} utilizing the {@link javax.media.nativewindow.NativeWindowFactory},
+ * using a configuration agnostic dummy {@link javax.media.nativewindow.DefaultGraphicsConfiguration}.
+ *

+ * The actual wrapping implementation is {@link com.jogamp.nativewindow.impl.jawt.JAWTWindow}.

+ *

+ * Purpose of this wrapping is to access the AWT window handle,
+ * not to actually render into it.
+ * Hence the dummy configuration only.

+ * + * @param awtCompObject must be of type java.awt.Component + */ + public static NativeWindow getNativeWindow(Object awtCompObject, Capabilities capsRequested) { + if(null==awtCompObject) { + throw new NativeWindowException("Null AWT Component"); + } + if( ! (awtCompObject instanceof java.awt.Component) ) { + throw new NativeWindowException("AWT Component not a java.awt.Component"); + } + return getNativeWindow( (java.awt.Component) awtCompObject, capsRequested ); + } + + public static NativeWindow getNativeWindow(java.awt.Component awtComp, Capabilities capsRequested) { + DefaultGraphicsConfiguration config = + AWTGraphicsConfiguration.create(awtComp, (Capabilities) capsRequested.clone(), capsRequested); + NativeWindow awtNative = NativeWindowFactory.getNativeWindow(awtComp, config); // a JAWTWindow + return awtNative; + } + + /** + * Creates a native NEWT child window to a AWT parent window.
+ *

+ * First we create a {@link javax.media.nativewindow.NativeWindow} presentation of the given {@link java.awt.Component}, + * utilizing {@link #getNativeWindow(java.awt.Component)}.
+ * The actual wrapping implementation is {@link com.jogamp.nativewindow.impl.jawt.JAWTWindow}.

+ *

+ * Second we create a child {@link com.jogamp.newt.Window}, + * utilizing {@link com.jogamp.newt.NewtFactory#createWindowImpl(java.lang.String, javax.media.nativewindow.NativeWindow, com.jogamp.newt.Screen, javax.media.nativewindow.Capabilities, boolean)}, + * passing the created {@link javax.media.nativewindow.NativeWindow}.

+ + *

+ * Third we attach a {@link com.jogamp.newt.event.awt.AWTParentWindowAdapter} to the given AWT component.
+ * The adapter passes window related events to our new child window, look at the implementation

+ * + *

+ * Forth we pass the parents visibility to the new Window

+ * + * @param awtParentObject must be of type java.awt.Component + * @param undecorated only impacts if the window is in top-level state, while attached to a parent window it's rendered undecorated always + * @return The successful created child window, or null if the AWT parent is not ready yet (no valid peers) + */ + public static Window createNativeChildWindow(Object awtParentObject, Capabilities newtCaps, boolean undecorated) { + if( null == awtParentObject ) { + throw new NativeWindowException("Null AWT Parent Component"); + } + if( ! (awtParentObject instanceof java.awt.Component) ) { + throw new NativeWindowException("AWT Parent Component not a java.awt.Component"); + } + java.awt.Component awtParent = (java.awt.Component) awtParentObject; + + // Generate a complete JAWT NativeWindow from the AWT Component + NativeWindow parent = getNativeWindow(awtParent, newtCaps); + if(null==parent) { + throw new NativeWindowException("Null NativeWindow from parent: "+awtParent); + } + + // Get parent's NativeWindow details + AWTGraphicsConfiguration parentConfig = (AWTGraphicsConfiguration) parent.getGraphicsConfiguration(); + AWTGraphicsScreen parentScreen = (AWTGraphicsScreen) parentConfig.getScreen(); + AWTGraphicsDevice parentDevice = (AWTGraphicsDevice) parentScreen.getDevice(); + + // Prep NEWT's Display and Screen according to the parent + final String type = NativeWindowFactory.getNativeWindowType(true); + Display display = NewtFactory.wrapDisplay(type, parentDevice.getHandle()); + Screen screen = NewtFactory.createScreen(type, display, parentScreen.getIndex()); + + // NEWT Window creation and add event handler for proper propagation AWT -> NEWT + // and copy size/visible state + Window window = NewtFactory.createWindowImpl(type, parent, screen, newtCaps, undecorated); + new AWTParentWindowAdapter(window).addTo(awtParent); + window.setSize(awtParent.getWidth(), awtParent.getHeight()); + window.setVisible(awtParent.isVisible()); + + return window; + } +} + diff --git a/src/newt/classes/com/jogamp/newt/impl/awt/AWTNewtFactory.java b/src/newt/classes/com/jogamp/newt/impl/awt/AWTNewtFactory.java deleted file mode 100644 index e0f86b1a9..000000000 --- a/src/newt/classes/com/jogamp/newt/impl/awt/AWTNewtFactory.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2010 Sven Gothel. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name Sven Gothel or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - */ - -package com.jogamp.newt.impl.awt; - -import java.awt.GraphicsConfiguration; -import java.awt.GraphicsDevice; -import java.awt.Component; -import java.awt.Canvas; - -import javax.media.opengl.*; -import javax.media.nativewindow.*; -import javax.media.nativewindow.awt.*; - -import com.jogamp.newt.event.awt.AWTParentWindowAdapter; -import com.jogamp.newt.Display; -import com.jogamp.newt.Screen; -import com.jogamp.newt.Window; -import com.jogamp.newt.NewtFactory; -import com.jogamp.common.util.ReflectionUtil; - -public class AWTNewtFactory extends NewtFactory { - - /** - * Wraps an AWT component into a {@link javax.media.nativewindow.NativeWindow} utilizing the {@link javax.media.nativewindow.NativeWindowFactory},
- * using a configuration agnostic dummy {@link javax.media.nativewindow.DefaultGraphicsConfiguration}.
- *

- * The actual wrapping implementation is {@link com.jogamp.nativewindow.impl.jawt.JAWTWindow}.

- *

- * Purpose of this wrapping is to access the AWT window handle,
- * not to actually render into it.
- * Hence the dummy configuration only.

- * - * @param awtCompObject must be of type java.awt.Component - */ - public static NativeWindow getNativeWindow(Object awtCompObject, Capabilities capsRequested) { - if(null==awtCompObject) { - throw new NativeWindowException("Null AWT Component"); - } - if( ! (awtCompObject instanceof java.awt.Component) ) { - throw new NativeWindowException("AWT Component not a java.awt.Component"); - } - return getNativeWindow( (java.awt.Component) awtCompObject, capsRequested ); - } - - public static NativeWindow getNativeWindow(java.awt.Component awtComp, Capabilities capsRequested) { - DefaultGraphicsConfiguration config = - AWTGraphicsConfiguration.create(awtComp, (Capabilities) capsRequested.clone(), capsRequested); - NativeWindow awtNative = NativeWindowFactory.getNativeWindow(awtComp, config); // a JAWTWindow - return awtNative; - } - - /** - * Creates a native NEWT child window to a AWT parent window.
- *

- * First we create a {@link javax.media.nativewindow.NativeWindow} presentation of the given {@link java.awt.Component}, - * utilizing {@link #getNativeWindow(java.awt.Component)}.
- * The actual wrapping implementation is {@link com.jogamp.nativewindow.impl.jawt.JAWTWindow}.

- *

- * Second we create a child {@link com.jogamp.newt.Window}, - * utilizing {@link com.jogamp.newt.NewtFactory#createWindowImpl(java.lang.String, javax.media.nativewindow.NativeWindow, com.jogamp.newt.Screen, javax.media.nativewindow.Capabilities, boolean)}, - * passing the created {@link javax.media.nativewindow.NativeWindow}.

- - *

- * Third we attach a {@link com.jogamp.newt.event.awt.AWTParentWindowAdapter} to the given AWT component.
- * The adapter passes window related events to our new child window, look at the implementation

- * - *

- * Forth we pass the parents visibility to the new Window

- * - * @param awtParentObject must be of type java.awt.Component - * @param undecorated only impacts if the window is in top-level state, while attached to a parent window it's rendered undecorated always - * @return The successful created child window, or null if the AWT parent is not ready yet (no valid peers) - */ - public static Window createNativeChildWindow(Object awtParentObject, Capabilities newtCaps, boolean undecorated) { - if( null == awtParentObject ) { - throw new NativeWindowException("Null AWT Parent Component"); - } - if( ! (awtParentObject instanceof java.awt.Component) ) { - throw new NativeWindowException("AWT Parent Component not a java.awt.Component"); - } - java.awt.Component awtParent = (java.awt.Component) awtParentObject; - - // Generate a complete JAWT NativeWindow from the AWT Component - NativeWindow parent = getNativeWindow(awtParent, newtCaps); - if(null==parent) { - throw new NativeWindowException("Null NativeWindow from parent: "+awtParent); - } - - // Get parent's NativeWindow details - AWTGraphicsConfiguration parentConfig = (AWTGraphicsConfiguration) parent.getGraphicsConfiguration(); - AWTGraphicsScreen parentScreen = (AWTGraphicsScreen) parentConfig.getScreen(); - AWTGraphicsDevice parentDevice = (AWTGraphicsDevice) parentScreen.getDevice(); - - // Prep NEWT's Display and Screen according to the parent - final String type = NativeWindowFactory.getNativeWindowType(true); - Display display = NewtFactory.wrapDisplay(type, parentDevice.getHandle()); - Screen screen = NewtFactory.createScreen(type, display, parentScreen.getIndex()); - - // NEWT Window creation and add event handler for proper propagation AWT -> NEWT - // and copy size/visible state - Window window = NewtFactory.createWindowImpl(type, parent, screen, newtCaps, undecorated); - new AWTParentWindowAdapter(window).addTo(awtParent); - window.setSize(awtParent.getWidth(), awtParent.getHeight()); - window.setVisible(awtParent.isVisible()); - - return window; - } -} - -- cgit v1.2.3 From c787f50d77e2491eb0d8201d534a6fa4885a929e Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Thu, 27 May 2010 14:34:52 +0200 Subject: Fix NativeWindow/NEWT Unique Display Naming, X11 use real NULL Display name Use proper (X11) Display names to avoid multiple Display instances. The problem was in case of 'wrapping' another X11 Display, a previous Display instance used 'nil' to reflect the null default Display but the wrapped instance (using a Display handle) the proper Display name. Now all (X11) Display's are using the proper Display name instead of a dummy 'nil' name. - Fix: NEWT null Display name is validated upfront, instead of changing it later - Fix: Nativewindow's X11Util gathers the systems NULL Display name and offers a validation method - Fix: NEWT X11 Display validates the NULL Display name properly --- .../com/jogamp/nativewindow/impl/x11/X11Util.java | 54 ++++++++++++---- src/newt/classes/com/jogamp/newt/Display.java | 74 +++++++++++++++------- .../com/jogamp/newt/impl/awt/AWTDisplay.java | 2 +- .../com/jogamp/newt/impl/intel/gdl/Display.java | 4 +- .../com/jogamp/newt/impl/macosx/MacDisplay.java | 2 +- .../newt/impl/opengl/broadcom/egl/Display.java | 6 +- .../com/jogamp/newt/impl/opengl/kd/KDDisplay.java | 7 +- .../jogamp/newt/impl/windows/WindowsDisplay.java | 2 +- .../com/jogamp/newt/impl/x11/X11Display.java | 19 ++---- 9 files changed, 108 insertions(+), 62 deletions(-) (limited to 'src/newt') diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java index 196e8f4e2..08b2ceec9 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java @@ -54,6 +54,8 @@ public class X11Util { private static final boolean DEBUG = Debug.debug("X11Util"); private static final boolean DEBUG_XDISPLAY_LOCK = false; + public static final String nullDisplayName; + static { NWJNILibLoader.loadNativeWindow("x11"); @@ -67,6 +69,18 @@ public class X11Util { // It seems like (Oracle's) AWT's Display locking is buggy. // initialize( ! NativeWindowFactory.isAWTAvailable() ) ; + + long dpy = X11Lib.XOpenDisplay(null); + XLockDisplay(dpy); + try { + nullDisplayName = X11Lib.XDisplayString(dpy); + } finally { + XUnlockDisplay(dpy); + } + X11Lib.XCloseDisplay(dpy); + if(DEBUG) { + System.out.println("X11 Display(NULL) <"+nullDisplayName+">"); + } } public static void initSingleton() { @@ -82,8 +96,6 @@ public class X11Util { private static ThreadLocal currentDisplayMap = new ThreadLocal(); - public static final String nullDeviceName = "nil" ; - public static class NamedDisplay extends RecursiveToolkitLock implements Cloneable { String name; long handle; @@ -98,7 +110,6 @@ public class X11Util { } public final String getName() { return name; } - public final String getNameSafe() { return null == name ? nullDeviceName : name; } public final long getHandle() { return handle; } public final int getRefCount() { return refCount; } public final boolean isUncloseable() { return unCloseable; } @@ -134,6 +145,20 @@ public class X11Util { return num; } + /** + * @return If name is null, it returns the previous queried NULL display name, + * otherwise the name. */ + public static String validateDisplayName(String name) { + return ( null == name ) ? nullDisplayName : name ; + } + + public static String validateDisplayName(String name, long handle) { + if(null==name && 0!=handle) { + name = getNameOfDisplay(handle); + } + return ( null == name ) ? nullDisplayName : name ; + } + /** Returns a clone of the thread local display map, you may {@link Object#wait()} on it */ public static Map getCurrentDisplayMap() { return (Map) ((HashMap)getCurrentDisplayMapImpl()).clone(); @@ -146,6 +171,7 @@ public class X11Util { /** Returns this thread named display. If it doesn not exist, it is being created, otherwise the reference count is increased */ public static long createThreadLocalDisplay(String name) { + name = validateDisplayName(name); NamedDisplay namedDpy = getCurrentDisplay(name); if(null==namedDpy) { long dpy = X11Lib.XOpenDisplay(name); @@ -179,6 +205,7 @@ public class X11Util { or the reference count goes below 0. */ public static long closeThreadLocalDisplay(String name) { + name = validateDisplayName(name); NamedDisplay namedDpy = getCurrentDisplay(name); if(null==namedDpy) { throw new RuntimeException("X11Util.Display: Display("+name+") with given name is not mapped to TLS in thread "+Thread.currentThread().getName()); @@ -220,18 +247,24 @@ public class X11Util { } public static boolean setSynchronizeDisplay(long handle, boolean onoff) { - String name; + boolean res=false; XLockDisplay(handle); - boolean res = X11Lib.XSynchronize(handle, onoff); - XUnlockDisplay(handle); + try { + res = X11Lib.XSynchronize(handle, onoff); + } finally { + XUnlockDisplay(handle); + } return res; } public static String getNameOfDisplay(long handle) { String name; XLockDisplay(handle); - name = X11Lib.XDisplayString(handle); - XUnlockDisplay(handle); + try { + name = X11Lib.XDisplayString(handle); + } finally { + XUnlockDisplay(handle); + } return name; } @@ -299,7 +332,7 @@ public class X11Util { Map displayMap = getCurrentDisplayMapImpl(); NamedDisplay oldDisplay = null; synchronized(displayMap) { - oldDisplay = (NamedDisplay) displayMap.put(newDisplay.getNameSafe(), newDisplay); + oldDisplay = (NamedDisplay) displayMap.put(newDisplay.getName(), newDisplay); displayMap.notifyAll(); } return oldDisplay; @@ -310,7 +343,7 @@ public class X11Util { private static NamedDisplay removeCurrentDisplay(NamedDisplay ndpy) { Map displayMap = getCurrentDisplayMapImpl(); synchronized(displayMap) { - NamedDisplay ndpyDel = (NamedDisplay) displayMap.remove(ndpy.getNameSafe()); + NamedDisplay ndpyDel = (NamedDisplay) displayMap.remove(ndpy.getName()); if(ndpyDel!=ndpy) { throw new RuntimeException("Wrong mapping req: "+ndpy+", got "+ndpyDel); } @@ -321,7 +354,6 @@ public class X11Util { /** Returns the thread local display mapped to the given name */ private static NamedDisplay getCurrentDisplay(String name) { - if(null==name) name=nullDeviceName; Map displayMap = getCurrentDisplayMapImpl(); return (NamedDisplay) displayMap.get(name); } diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java index 6705db970..674a45ded 100755 --- a/src/newt/classes/com/jogamp/newt/Display.java +++ b/src/newt/classes/com/jogamp/newt/Display.java @@ -127,17 +127,18 @@ public abstract class Display { /** Make sure to reuse a Display with the same name */ protected static Display create(String type, String name, final long handle) { try { - if(null==name && 0!=handle) { - name="wrapping-0x"+Long.toHexString(handle); // may change within implementation .. - } + Class displayClass = getDisplayClass(type); + Display tmpDisplay = (Display) displayClass.newInstance(); + name = tmpDisplay.validateDisplayName(name, handle); + if(DEBUG) { dumpDisplayMap("Display.create("+getFQName(type, name)+") BEGIN"); } Display display = getCurrentDisplay(type, name); if(null==display) { - Class displayClass = getDisplayClass(type); - display = (Display) displayClass.newInstance(); - display.name=name; + display = tmpDisplay; + tmpDisplay = null; + display.name = name; display.type=type; display.refCount=1; @@ -155,11 +156,11 @@ public abstract class Display { display.edt = display.edtUtil.start(); display.edtUtil.invokeAndWait(new Runnable() { public void run() { - f_dpy.createNative(handle); + f_dpy.createNative(); } } ); } else { - display.createNative(handle); + display.createNative(); } if(null==display.aDevice) { throw new RuntimeException("Display.createNative() failed to instanciate an AbstractGraphicsDevice"); @@ -169,6 +170,7 @@ public abstract class Display { System.err.println("Display.create("+getFQName(type, name)+") NEW: "+display+" "+Thread.currentThread()); } } else { + tmpDisplay = null; synchronized(display) { display.refCount++; if(DEBUG) { @@ -224,7 +226,7 @@ public abstract class Display { } } - protected abstract void createNative(long handle); + protected abstract void createNative(); protected abstract void closeNative(); public final String getType() { @@ -241,6 +243,13 @@ public abstract class Display { static final String nilString = "nil" ; + protected String validateDisplayName(String name, long handle) { + if(null==name && 0!=handle) { + name="wrapping-0x"+Long.toHexString(handle); + } + return ( null == name ) ? nilString : name ; + } + public static final String getFQName(String type, String name) { if(null==type) type=nilString; if(null==name) name=nilString; @@ -276,32 +285,49 @@ public abstract class Display { private LinkedList/**/ events = new LinkedList(); protected void dispatchMessages() { - NEWTEvent e; - do { + if(!events.isEmpty()) { synchronized(events) { - if (!events.isEmpty()) { - e = (NEWTEvent) events.removeFirst(); - } else { - e = null; - } - } - if (e != null) { - Object source = e.getSource(); - if(source instanceof Window) { - ((Window)source).sendEvent(e); - } else { - throw new RuntimeException("Event source not a NEWT Window: "+source.getClass().getName()+", "+source); + while (!events.isEmpty()) { + NEWTEvent e = (NEWTEvent) events.removeFirst(); + Object source = e.getSource(); + if(source instanceof Window) { + ((Window)source).sendEvent(e); + } else { + throw new RuntimeException("Event source not a NEWT Window: "+source.getClass().getName()+", "+source); + } } + events.notifyAll(); } - } while (e != null); + } dispatchMessagesNative(); } public void enqueueEvent(NEWTEvent e) { + enqueueEvent(false, e); + } + + public void enqueueEvent(boolean wait, NEWTEvent e) { synchronized(events) { + if(DEBUG) { + System.out.println("Display.enqueueEvent: START - wait "+wait+", "+e); + } events.addLast(e); } + if(wait && !events.isEmpty()) { + synchronized(events) { + while(!events.isEmpty()) { + try { + events.wait(); + } catch (InterruptedException ie) { + ie.printStackTrace(); + } + } + } + } + if(DEBUG) { + System.out.println("Display.enqueueEvent: END - wait "+wait+", "+e); + } } diff --git a/src/newt/classes/com/jogamp/newt/impl/awt/AWTDisplay.java b/src/newt/classes/com/jogamp/newt/impl/awt/AWTDisplay.java index b0b518c59..f54e66f07 100644 --- a/src/newt/classes/com/jogamp/newt/impl/awt/AWTDisplay.java +++ b/src/newt/classes/com/jogamp/newt/impl/awt/AWTDisplay.java @@ -44,7 +44,7 @@ public class AWTDisplay extends Display { public AWTDisplay() { } - protected void createNative(long handle) { + protected void createNative() { aDevice = (AWTGraphicsDevice) AWTGraphicsDevice.createDevice(null); // default } diff --git a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Display.java b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Display.java index ac27da9ef..d19aaf796 100644 --- a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Display.java +++ b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Display.java @@ -58,10 +58,10 @@ public class Display extends com.jogamp.newt.Display { public Display() { } - protected void createNative(long handle) { + protected void createNative() { synchronized(Display.class) { if(0==initCounter) { - displayHandle = (0 == handle) ? CreateDisplay() : handle; + displayHandle = CreateDisplay(); if(0==displayHandle) { throw new NativeWindowException("Couldn't initialize GDL Display"); } diff --git a/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java b/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java index 6e1119a9d..0c4362a9e 100755 --- a/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java +++ b/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java @@ -70,7 +70,7 @@ public class MacDisplay extends Display { MainThread.invoke(false, dispatchAction); } - protected void createNative(long handle) { + protected void createNative() { aDevice = new MacOSXGraphicsDevice(); } diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Display.java b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Display.java index c08499359..c2d323e56 100644 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Display.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Display.java @@ -56,10 +56,8 @@ public class Display extends com.jogamp.newt.Display { public Display() { } - protected void createNative(long handle) { - if( 0 == handle ) { - handle = CreateDisplay(Screen.fixedWidth, Screen.fixedHeight); - } + protected void createNative() { + long handle = CreateDisplay(Screen.fixedWidth, Screen.fixedHeight); if (handle == EGL.EGL_NO_DISPLAY) { throw new NativeWindowException("BC EGL CreateDisplay failed"); } diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDDisplay.java b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDDisplay.java index bb5f1cc7a..2ab30773f 100755 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDDisplay.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDDisplay.java @@ -57,12 +57,9 @@ public class KDDisplay extends Display { public KDDisplay() { } - protected void createNative(long handle) { + protected void createNative() { // FIXME: map name to EGL_*_DISPLAY - // FIXME: what do to with external handle ? - if(0==handle) { - handle = EGL.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY); - } + long handle = EGL.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY); if (handle == EGL.EGL_NO_DISPLAY) { throw new NativeWindowException("eglGetDisplay failed"); } diff --git a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsDisplay.java b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsDisplay.java index f75c11cfb..ef033d1c8 100755 --- a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsDisplay.java +++ b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsDisplay.java @@ -60,7 +60,7 @@ public class WindowsDisplay extends Display { public WindowsDisplay() { } - protected void createNative(long handle) { + protected void createNative() { aDevice = new WindowsGraphicsDevice(); } diff --git a/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java b/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java index 3b0868620..54fe0542b 100755 --- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java +++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java @@ -60,19 +60,12 @@ public class X11Display extends Display { public X11Display() { } - protected void createNative(long handle) { - if(0 != handle) { - // Can't use that Display handle directly, - // but we open up a new connection to the same Display by it's name - String newName = X11Util.getNameOfDisplay(handle); - if(DEBUG) { - System.out.println("Changing Display Name (provided handle): "+name+" -> 0x"+ - Long.toHexString(handle)+" : "+newName); - } - handle = 0; - name = newName; - } - handle= X11Util.createThreadLocalDisplay(name); + protected String validateDisplayName(String name, long handle) { + return X11Util.validateDisplayName(name, handle); + } + + protected void createNative() { + long handle= X11Util.createThreadLocalDisplay(name); if( 0 == handle ) { throw new RuntimeException("Error creating display: "+name); } -- cgit v1.2.3 From 811bd23ed37e392abb349f850a0b1dac635d021e Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 28 May 2010 16:53:08 +0200 Subject: NEWT: Fix AWT Parenting ; Multithreading Issues ; Semantics: destroy(), .. ; Misc. Due to incapabilities of the previous AWT/NEWT reparenting the implementation and spec had to be changed to support this feature. See the first 2 comments below. - Tested on GNU/Linux (OK), Windows (a few bugs left) - TODO: - Clarify the size/layout issue, ie who is responsible etc In the test, incl AWT/NEWT, we set the size on the GLWindow and ie pack the AWT Frame. - Fix remaining [Windows] bugs .. - Fix/Implement MacOSX port .. Fix AWT/NEWT reparenting: =========================== - Now NewtFactory's createWindow() method for parenting handles NativeWindow only and is no more responsible for creating a child window upon an AWT Component. See class com.jogamp.newt.awt.NewtCanvasAWT for NEWT/AWT parenting. - New com.jogamp.newt.awt.NewtCanvasAWT, responsible for handling AWT's reparent events via addNotify/removeNotify. Reparenting is implemented via the new NEWT Window's reparentWindow() method. Also sets the background erase to false, if supported. - Fix zero size semantics in Window (setSize/setVisible) Since a zero size window is not supported by many compoenent (Windowing system, OpenGL, ..) we use the visibility methodology to not show a 0x0 window. See Javadoc. AWT components may start with zero size. - New NEWT Window: reparentWindow(NativeWindow newParent, Screen newScreen) Allowing to change the parent of a window. Similar with the fullscreen toggle, but without size/position change. Native reparenting allows to keep alive the native window while changing the container, hence it is preferred to a destroy/create cycle. To benefit from the native reparenting, a NEWT implementation has to implement 'protected boolean reparentWindowImpl(long newWindowHandle)' and return true, otherwise reparenting will be 'emulated' via the expensive destroy/create cycle. - NEWT's Window references all of it's children, if any - NEWT's Window propagates setVisible/destroy actions to it's children. - Fix NEWT's destroy() semantics. A call of destroy() or destroy(false) shall only result in the destruction of the native window (handle) nothing more. A subsequent setVisible(true) shall allow the complete recreation of the Window into a usable state. A call of destroy(true) destroys all resources the Window holds, may include Screen/Display and OpenGL resources in case of GLWindow. This is necessary to allow proper reparenting, where a native window may become destroyed, but should be recreated via setVisible(true) later on. - Fix NEWT set[Size|Position|Fullscreen|Visible] synchronization. Use a recursive lock instead of the Window instance, otherwise arbitrary Window access via AWT's EDT, NEWT's EDT or other threads can block. Also removed a use pattern like: key.lock() try { EDT.invoke(action()); } finally { key.unlock(); } Where action() itself uses the same lock object (here key), the result is a deadlock. NativeWindow Changes: ====================== - We can use XInitThreads() now (concurrent threading support) in combination with AWT. Might have been some async in our NEWT locking in regards to AWT (sync()), and the X11 Display changes made in c787f50d77e2491eb0d8201d534a6fa4885a929e. - NativeWindow's window handle is _not_ transient like surface handle, fixed documentation. JOGL Changes: ============= - New 'isRealized()' method in GLDrawable. - Misc Fixes ============ - Fix NEWT set[Size|Position|Fullscreen|Visible] duplicate code Due to pure abstract signatures, the set[Size|Position|Fullscreen|Visible] implementations of X11, OSX, .. contained duplicate code and state handling (size, pos, ..). These are now decoupled, ie generic set[Size|Position|Fullscreen|Visible] implementations calling simple set[Size|Position|Fullscreen|Visible]Impl implementations. - Fix NEWT: Renamed setAutoDrawableClient(boolean) to setHandleDestroyNotify(boolean) The semantic of setAutoDrawableClient(boolean) defaults to false was too complicated and specific, hence changed to setHandleDestroyNotify(boolean) defaults to true since its more clear and the name refers the window itself.. - Fix NEWT: Removed GLWindow's unused global window list - Fix NEWT: Remove Window's unused event mask - Rename com.jogamp.newt.impl.awt.AWTNewtFactory -> com.jogamp.newt.awt.NewtFactoryAWT --- make/build-newt.xml | 2 +- make/scripts/java-run-all.sh | 1 + make/scripts/java-run-newt.sh | 1 + .../com/jogamp/opengl/impl/GLDrawableImpl.java | 4 +- .../com/jogamp/opengl/impl/GLPbufferImpl.java | 4 + .../com/jogamp/opengl/impl/egl/EGLDrawable.java | 2 +- .../classes/javax/media/opengl/GLDrawable.java | 3 + .../classes/javax/media/opengl/awt/GLCanvas.java | 4 + .../classes/javax/media/opengl/awt/GLJPanel.java | 4 + .../com/jogamp/test/junit/newt/KeyAction.java | 1 - .../test/junit/newt/TestGLWindows01NEWT.java | 220 +++++++ .../jogamp/test/junit/newt/TestParenting01AWT.java | 353 ++++++++--- .../test/junit/newt/TestParenting01NEWT.java | 283 ++++++--- .../jogamp/test/junit/newt/TestParenting02AWT.java | 260 ++++++++ .../test/junit/newt/TestParenting02NEWT.java | 231 +++++++ .../jogamp/test/junit/newt/TestWindows01NEWT.java | 29 +- .../com/jogamp/test/junit/newt/WindowAction.java | 1 - .../com/jogamp/nativewindow/impl/NullWindow.java | 4 - .../nativewindow/impl/RecursiveToolkitLock.java | 18 +- .../com/jogamp/nativewindow/impl/x11/X11Util.java | 11 +- .../javax/media/nativewindow/NativeWindow.java | 13 +- src/newt/classes/com/jogamp/newt/Display.java | 6 +- src/newt/classes/com/jogamp/newt/NewtFactory.java | 111 ++-- .../classes/com/jogamp/newt/OffscreenWindow.java | 14 +- src/newt/classes/com/jogamp/newt/Window.java | 698 ++++++++++++++++----- .../classes/com/jogamp/newt/awt/NewtCanvasAWT.java | 199 ++++++ .../com/jogamp/newt/awt/NewtFactoryAWT.java | 59 +- .../com/jogamp/newt/event/awt/AWTAdapter.java | 14 +- .../com/jogamp/newt/event/awt/AWTKeyAdapter.java | 5 + .../com/jogamp/newt/event/awt/AWTMouseAdapter.java | 6 + .../newt/event/awt/AWTParentWindowAdapter.java | 15 +- .../jogamp/newt/event/awt/AWTWindowAdapter.java | 103 ++- .../com/jogamp/newt/impl/awt/AWTWindow.java | 75 +-- .../com/jogamp/newt/impl/intel/gdl/Window.java | 41 +- .../com/jogamp/newt/impl/macosx/MacWindow.java | 136 ++-- .../newt/impl/opengl/broadcom/egl/Window.java | 18 +- .../com/jogamp/newt/impl/opengl/kd/KDWindow.java | 20 +- .../jogamp/newt/impl/windows/WindowsWindow.java | 90 ++- .../com/jogamp/newt/impl/x11/X11Window.java | 103 ++- .../classes/com/jogamp/newt/opengl/GLWindow.java | 242 +++---- src/newt/classes/com/jogamp/newt/util/EDTUtil.java | 8 +- src/newt/native/MacWindow.m | 31 +- src/newt/native/WindowsWindow.c | 63 +- src/newt/native/X11Window.c | 230 +++++-- 44 files changed, 2688 insertions(+), 1048 deletions(-) create mode 100755 src/junit/com/jogamp/test/junit/newt/TestGLWindows01NEWT.java create mode 100755 src/junit/com/jogamp/test/junit/newt/TestParenting02AWT.java create mode 100755 src/junit/com/jogamp/test/junit/newt/TestParenting02NEWT.java create mode 100644 src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java (limited to 'src/newt') diff --git a/make/build-newt.xml b/make/build-newt.xml index 08c0f308b..2cb848588 100644 --- a/make/build-newt.xml +++ b/make/build-newt.xml @@ -90,7 +90,7 @@ value="com/jogamp/newt/*, com/jogamp/newt/event/*, com/jogamp/newt/util/*, com/jogamp/newt/impl/*"/> + value="com/jogamp/newt/impl/awt/*, com/jogamp/newt/awt/*, com/jogamp/newt/event/awt/*"/> diff --git a/make/scripts/java-run-all.sh b/make/scripts/java-run-all.sh index 8c50d0933..0e5be242a 100755 --- a/make/scripts/java-run-all.sh +++ b/make/scripts/java-run-all.sh @@ -35,6 +35,7 @@ uname -a | grep -i Darwin && MOSX=1 # D_ARGS="-Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all -Djogl.debug.GLSLState" # D_ARGS="-Dnativewindow.debug.X11Util=true -Djogl.debug.GLDrawableFactory=true" # D_ARGS="-Dnativewindow.debug.X11Util=true" +# D_ARGS="-Dnewt.debug=all -Dnativewindow.debug=all" # D_ARGS="-Dnewt.debug=all" # D_ARGS="-Dnewt.debug.Window" # D_ARGS="-Djogl.debug=all" diff --git a/make/scripts/java-run-newt.sh b/make/scripts/java-run-newt.sh index 94f77143f..796e22da4 100755 --- a/make/scripts/java-run-newt.sh +++ b/make/scripts/java-run-newt.sh @@ -39,5 +39,6 @@ fi # D_ARGS="-Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all -Djogl.debug.GLSLState" # D_ARGS="-Dnativewindow.debug.X11Util=true -Djogl.debug.GLDrawableFactory=true" # D_ARGS="-Dnativewindow.debug.X11Util=true" +# D_ARGS="-Dnewt.debug=all" java $X_ARGS -Djava.awt.headless=true $D_ARGS com.jogamp.newt.util.MainThread $* 2>&1 | tee java-run-newt.log diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableImpl.java index 2fef8fd80..62b89a13e 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableImpl.java @@ -124,7 +124,7 @@ public abstract class GLDrawableImpl implements GLDrawable { } protected abstract void setRealizedImpl(); - public boolean getRealized() { + public boolean isRealized() { return realized; } @@ -153,7 +153,7 @@ public abstract class GLDrawableImpl implements GLDrawable { } public String toString() { - return getClass().getName()+"[Realized "+getRealized()+ + return getClass().getName()+"[Realized "+isRealized()+ ",\n\tFactory "+getFactory()+ ",\n\tWindow "+getNativeWindow()+"]"; } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java index dd8d980a6..1da19663a 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java @@ -86,6 +86,10 @@ public class GLPbufferImpl implements GLPbuffer { public void setRealized(boolean realized) { } + public boolean isRealized() { + return true; + } + public void setSize(int width, int height) { // FIXME throw new GLException("Not yet implemented"); diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawable.java index dcfe06bdc..2e24abcec 100755 --- a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawable.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawable.java @@ -213,7 +213,7 @@ public abstract class EGLDrawable extends GLDrawableImpl { } public String toString() { - return getClass().getName()+"[realized "+getRealized()+ + return getClass().getName()+"[realized "+isRealized()+ ",\n\tfactory "+getFactory()+ ",\n\twindow "+getNativeWindow()+ ",\n\teglSurface 0x"+Long.toHexString(eglSurface)+ diff --git a/src/jogl/classes/javax/media/opengl/GLDrawable.java b/src/jogl/classes/javax/media/opengl/GLDrawable.java index 0cde24ff9..469cc5170 100644 --- a/src/jogl/classes/javax/media/opengl/GLDrawable.java +++ b/src/jogl/classes/javax/media/opengl/GLDrawable.java @@ -123,6 +123,9 @@ public interface GLDrawable { */ public void setRealized(boolean realized); + /** @return true if this drawable is realized, otherwise false */ + public boolean isRealized(); + /** Returns the current width of this GLDrawable. */ public int getWidth(); diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index 53e79b8d9..9932f0cf9 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -283,6 +283,10 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { public void setRealized(boolean realized) { } + public boolean isRealized() { + return ( null != drawable ) ? drawable.isRealized() : false; + } + private Object closingListener = null; private Object closingListenerLock = new Object(); diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index e8de00629..eb8c68263 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -379,6 +379,10 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable { public void setRealized(boolean realized) { } + public boolean isRealized() { + return isInitialized; + } + public void setContext(GLContext ctx) { if (backend == null) { return; diff --git a/src/junit/com/jogamp/test/junit/newt/KeyAction.java b/src/junit/com/jogamp/test/junit/newt/KeyAction.java index 29b3d2ee2..3ca12a840 100644 --- a/src/junit/com/jogamp/test/junit/newt/KeyAction.java +++ b/src/junit/com/jogamp/test/junit/newt/KeyAction.java @@ -33,7 +33,6 @@ package com.jogamp.test.junit.newt; -import com.jogamp.opengl.util.Animator; import com.jogamp.newt.event.*; class KeyAction extends KeyAdapter { diff --git a/src/junit/com/jogamp/test/junit/newt/TestGLWindows01NEWT.java b/src/junit/com/jogamp/test/junit/newt/TestGLWindows01NEWT.java new file mode 100755 index 000000000..b96e74182 --- /dev/null +++ b/src/junit/com/jogamp/test/junit/newt/TestGLWindows01NEWT.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2010 Sven Gothel. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name Sven Gothel or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.test.junit.newt; + +import java.lang.reflect.*; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Test; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; + +import com.jogamp.opengl.util.Animator; +import com.jogamp.newt.*; +import com.jogamp.newt.opengl.*; +import java.io.IOException; + +import com.jogamp.test.junit.util.MiscUtils; +import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears; + +public class TestGLWindows01NEWT { + static GLProfile glp; + static int width, height; + static long duration = 100; // ms + + @BeforeClass + public static void initClass() { + width = 640; + height = 480; + glp = GLProfile.getDefault(); + } + + static GLWindow createWindow(Screen screen, GLCapabilities caps, int width, int height, boolean onscreen, boolean undecorated) { + Assert.assertNotNull(caps); + caps.setOnscreen(onscreen); + // System.out.println("Requested: "+caps); + + // + // Create native windowing resources .. X11/Win/OSX + // + GLWindow glWindow; + if(null!=screen) { + Window window = NewtFactory.createWindow(screen, caps, onscreen && undecorated); + Assert.assertNotNull(window); + glWindow = GLWindow.create(window); + } else { + glWindow = GLWindow.create(caps, onscreen && undecorated); + } + Assert.assertNotNull(glWindow); + Assert.assertEquals(false,glWindow.isNativeWindowValid()); + glWindow.setSize(width, height); + Assert.assertEquals(false,glWindow.isVisible()); + glWindow.setVisible(true); + Assert.assertEquals(true,glWindow.isVisible()); + Assert.assertEquals(true,glWindow.isNativeWindowValid()); + // Assert.assertEquals(width,glWindow.getWidth()); + // Assert.assertEquals(height,glWindow.getHeight()); + // System.out.println("Created: "+glWindow); + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + caps = (GLCapabilities) glWindow.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); + Assert.assertNotNull(caps); + Assert.assertTrue(caps.getGreenBits()>5); + Assert.assertTrue(caps.getBlueBits()>5); + Assert.assertTrue(caps.getRedBits()>5); + Assert.assertEquals(caps.isOnscreen(),onscreen); + + GLEventListener demo = new Gears(); + setDemoFields(demo, glWindow); + glWindow.addGLEventListener(demo); + + return glWindow; + } + + static void destroyWindow(GLWindow glWindow, boolean deep) { + if(null!=glWindow) { + glWindow.destroy(deep); + } + } + + @Test + public void testWindowNativeRecreate01Simple() throws InterruptedException { + GLCapabilities caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + GLWindow window = createWindow(null, caps, width, height, true /* onscreen */, false /* undecorated */); + + window.display(); + window.destroy(); + Assert.assertEquals(false,window.isNativeWindowValid()); + Assert.assertEquals(true,window.isVisible()); + + window.display(); + Assert.assertEquals(true,window.isNativeWindowValid()); + + Animator animator = new Animator(window); + animator.start(); + while(animator.isAnimating() && animator.getDuration()0 && !glWindow.isDestroyed()) { - glWindow.display(); - Thread.sleep(step); - duration -= step; - - while( null != ( event = (NEWTEvent) eventFifo.get() ) ) { - Window source = (Window) event.getSource(); - if(event instanceof KeyEvent) { - KeyEvent keyEvent = (KeyEvent) event; - switch(keyEvent.getKeyChar()) { - case 'q': - glWindow.destroy(); - break; - case 'f': - source.setFullscreen(!source.isFullscreen()); - break; - } - } + frame.dispose(); + glWindow1.destroy(true); + } + + @Test + public void testWindowParenting05ReparentAWTWinHopFrame2Frame() throws InterruptedException { + int x = 0; + int y = 0; + + NEWTEventFiFo eventFifo = new NEWTEventFiFo(); + + GLWindow glWindow1 = GLWindow.create(glCaps); + GLEventListener demo1 = new RedSquare(); + setDemoFields(demo1, glWindow1, false); + glWindow1.addGLEventListener(demo1); + glWindow1.setSize(600, 300); + + NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); + + Frame frame1 = new Frame("AWT Parent Frame"); + frame1.setLayout(new BorderLayout()); + frame1.add(new Button("North"), BorderLayout.NORTH); + frame1.add(new Button("South"), BorderLayout.SOUTH); + frame1.add(new Button("East"), BorderLayout.EAST); + frame1.add(new Button("West"), BorderLayout.WEST); + frame1.setSize(width, height); + frame1.setLocation(0, 0); + frame1.setVisible(true); + + Frame frame2 = new Frame("AWT Parent Frame"); + frame2.setLayout(new BorderLayout()); + frame2.add(new Button("North"), BorderLayout.NORTH); + frame2.add(new Button("South"), BorderLayout.SOUTH); + frame2.add(new Button("East"), BorderLayout.EAST); + frame2.add(new Button("West"), BorderLayout.WEST); + frame2.setSize(width, height); + frame2.setLocation(640, 480); + frame2.setVisible(true); + + frame1.add(newtCanvasAWT, BorderLayout.CENTER); + Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParentNativeWindow()); + frame1.pack(); + + Animator animator1 = new Animator(glWindow1); + animator1.start(); + + int state = 0; + while(animator1.isAnimating() && animator1.getDuration()<3*durationPerTest) { + Thread.sleep(durationPerTest); + switch(state) { + case 0: + frame1.remove(newtCanvasAWT); + frame2.add(newtCanvasAWT, BorderLayout.CENTER); + frame2.pack(); + break; + case 1: + frame2.remove(newtCanvasAWT); + frame1.add(newtCanvasAWT, BorderLayout.CENTER); + frame1.pack(); + break; } + state++; } - glWindow.destroy(); - if(useLayout) { - frame.remove(overlayedAWTComponent); - } - frame.dispose(); + + frame1.dispose(); + frame2.dispose(); + glWindow1.destroy(true); } public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) { Assert.assertNotNull(demo); Assert.assertNotNull(glWindow); - Window window = glWindow.getWindow(); + Window window = glWindow.getInnerWindow(); if(debug) { MiscUtils.setFieldIfExists(demo, "glDebug", true); MiscUtils.setFieldIfExists(demo, "glTrace", true); @@ -193,8 +364,22 @@ public class TestParenting01AWT { } } + static int atoi(String a) { + int i=0; + try { + durationPerTest = Integer.parseInt(a); + } catch (Exception ex) { ex.printStackTrace(); } + return i; + } + public static void main(String args[]) throws IOException { - durationPerTest = 5000; + for(int i=0; i0 && !shouldQuit) { - glWindow1.display(); - glWindow2.display(); - Thread.sleep(step); - duration -= step; - x += 1; - y += 1; - glWindow1.setPosition(x,y); - glWindow2.setPosition(glWindow1.getWidth()/2,glWindow1.getHeight()/2-y); - - while( null != ( event = (NEWTEvent) eventFifo.get() ) ) { - Window source = (Window) event.getSource(); - if(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY == event.getEventType()) { - shouldQuit = true; - } else if(event instanceof KeyEvent) { - KeyEvent keyEvent = (KeyEvent) event; - switch(keyEvent.getKeyChar()) { - case 'q': - shouldQuit = true; - break; - case 'f': - source.setFullscreen(!source.isFullscreen()); - break; - } - } + glWindow1.setVisible(true); + + Animator animator1 = new Animator(glWindow1); + animator1.start(); + Animator animator2 = new Animator(glWindow2); + animator2.start(); + + int state = 0; + while(animator1.isAnimating() && animator1.getDuration()<3*durationPerTest) { + Thread.sleep(durationPerTest); + switch(state) { + case 0: + glWindow2.reparentWindow(null, null); + Assert.assertEquals(true, glWindow2.isVisible()); + Assert.assertEquals(true, glWindow2.isNativeWindowValid()); + Assert.assertNull(glWindow2.getParentNativeWindow()); + break; + case 1: + glWindow2.reparentWindow(glWindow1, null); + Assert.assertEquals(true, glWindow2.isVisible()); + Assert.assertEquals(true, glWindow2.isNativeWindowValid()); + Assert.assertEquals(glWindow1,glWindow2.getParentNativeWindow()); + break; } + state++; } - destroyWindow(null, null, window2, glWindow2); - destroyWindow(display, screen, window1, glWindow1); + animator1.stop(); + animator2.stop(); + + glWindow1.destroy(true); } - public static void setDemoFields(GLEventListener demo, Window window, GLWindow glWindow, boolean debug) { + public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) { Assert.assertNotNull(demo); - Assert.assertNotNull(window); + Assert.assertNotNull(glWindow); + Window window = glWindow.getInnerWindow(); if(debug) { MiscUtils.setFieldIfExists(demo, "glDebug", true); MiscUtils.setFieldIfExists(demo, "glTrace", true); @@ -200,8 +267,22 @@ public class TestParenting01NEWT { } } + static int atoi(String a) { + int i=0; + try { + durationPerTest = Integer.parseInt(a); + } catch (Exception ex) { ex.printStackTrace(); } + return i; + } + public static void main(String args[]) throws IOException { - durationPerTest = 5000; + for(int i=0; i0 && !shouldQuit) { + glWindow.display(); + Thread.sleep(step); + duration -= step; + + while( null != ( event = (NEWTEvent) eventFifo.get() ) ) { + Window source = (Window) event.getSource(); + if(event instanceof KeyEvent) { + KeyEvent keyEvent = (KeyEvent) event; + switch(keyEvent.getKeyChar()) { + case 'q': + shouldQuit = true; + break; + case 'f': + source.setFullscreen(!source.isFullscreen()); + break; + } + } + } + } + System.out.println("+++++++++++++++++++ END"); + Thread.sleep(waitReparent); + + glWindow.destroy(); + if(useLayout) { + frame.remove(newtCanvasAWT); + } + frame.dispose(); + } + + public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) { + Assert.assertNotNull(demo); + Assert.assertNotNull(glWindow); + Window window = glWindow.getInnerWindow(); + if(debug) { + MiscUtils.setFieldIfExists(demo, "glDebug", true); + MiscUtils.setFieldIfExists(demo, "glTrace", true); + } + if(!MiscUtils.setFieldIfExists(demo, "window", window)) { + MiscUtils.setFieldIfExists(demo, "glWindow", glWindow); + } + } + + static int atoi(String a) { + int i=0; + try { + durationPerTest = Integer.parseInt(a); + } catch (Exception ex) { ex.printStackTrace(); } + return i; + } + + public static void main(String args[]) throws IOException { + for(int i=0; i0 && !shouldQuit) { + glWindow1.display(); + glWindow2.display(); + Thread.sleep(step); + duration -= step; + x += 1; + y += 1; + glWindow1.setPosition(x,y); + glWindow2.setPosition(glWindow1.getWidth()/2,glWindow1.getHeight()/2-y); + + while( null != ( event = (NEWTEvent) eventFifo.get() ) ) { + Window source = (Window) event.getSource(); + if(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY == event.getEventType()) { + shouldQuit = true; + } else if(event instanceof KeyEvent) { + KeyEvent keyEvent = (KeyEvent) event; + switch(keyEvent.getKeyChar()) { + case 'q': + shouldQuit = true; + break; + case 'f': + source.setFullscreen(!source.isFullscreen()); + break; + } + } + } + } + destroyWindow(null, null, window2, glWindow2); + destroyWindow(display, screen, window1, glWindow1); + } + + public static void setDemoFields(GLEventListener demo, Window window, GLWindow glWindow, boolean debug) { + Assert.assertNotNull(demo); + Assert.assertNotNull(window); + if(debug) { + MiscUtils.setFieldIfExists(demo, "glDebug", true); + MiscUtils.setFieldIfExists(demo, "glTrace", true); + } + if(!MiscUtils.setFieldIfExists(demo, "window", window)) { + MiscUtils.setFieldIfExists(demo, "glWindow", glWindow); + } + } + + static int atoi(String a) { + int i=0; + try { + durationPerTest = Integer.parseInt(a); + } catch (Exception ex) { ex.printStackTrace(); } + return i; + } + + public static void main(String args[]) throws IOException { + for(int i=0; i * - * The window handle, see {@link #getWindowHandle()}, - * and the surface handle, see {@link #lockSurface()},
- * shall be set and be valid after a successfull call, + * The surface handle, see {@link #lockSurface()},
+ * shall be set and valid after a successfull call, * ie a return value other than {@link #LOCK_SURFACE_NOT_READY}.

* * The semantics of the underlying native locked resource @@ -88,8 +87,7 @@ public interface NativeWindow extends SurfaceUpdatedListener { /** * Unlock the surface of this native window * - * Shall not modify the window handle, see {@link #getWindowHandle()}, - * or the surface handle, see {@link #lockSurface()}

+ * Shall not modify the surface handle, see {@link #lockSurface()}

* * @throws NativeWindowException if surface is not locked * @@ -140,11 +138,6 @@ public interface NativeWindow extends SurfaceUpdatedListener { /** * Returns the window handle for this NativeWindow.

* - * The window handle should be set/update by {@link #lockSurface()}, - * where {@link #unlockSurface()} is not allowed to modify it.
- * After {@link #unlockSurface()} it is no more guaranteed - * that the window handle is still valid.

- * * The window handle shall reflect the platform one * for all window related operations, e.g. open, close, resize.

* diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java index 674a45ded..113ec547e 100755 --- a/src/newt/classes/com/jogamp/newt/Display.java +++ b/src/newt/classes/com/jogamp/newt/Display.java @@ -146,7 +146,7 @@ public abstract class Display { final Display f_dpy = display; Thread current = Thread.currentThread(); display.edtUtil = new EDTUtil(current.getThreadGroup(), - "Display_"+display.getFQName()+"-"+current.getName(), + "Display_"+display.getFQName(), new Runnable() { public void run() { if(null!=f_dpy.getGraphicsDevice()) { @@ -253,7 +253,7 @@ public abstract class Display { public static final String getFQName(String type, String name) { if(null==type) type=nilString; if(null==name) name=nilString; - return type+":"+name; + return type+"_"+name; } public long getHandle() { @@ -277,7 +277,7 @@ public abstract class Display { } public String toString() { - return "NEWT-Display["+getFQName()+", refCount "+refCount+", "+aDevice+"]"; + return "NEWT-Display["+getFQName()+", refCount "+refCount+", hasEDT "+(null!=edtUtil)+", "+aDevice+"]"; } protected abstract void dispatchMessagesNative(); diff --git a/src/newt/classes/com/jogamp/newt/NewtFactory.java b/src/newt/classes/com/jogamp/newt/NewtFactory.java index 7860197ef..3959c6a8d 100755 --- a/src/newt/classes/com/jogamp/newt/NewtFactory.java +++ b/src/newt/classes/com/jogamp/newt/NewtFactory.java @@ -106,101 +106,80 @@ public abstract class NewtFactory { * Create a top level Window entity, incl native creation */ public static Window createWindow(Screen screen, Capabilities caps) { - return Window.create(NativeWindowFactory.getNativeWindowType(true), null, 0, screen, caps, false); + return createWindowImpl(NativeWindowFactory.getNativeWindowType(true), screen, caps, false); } /** * Create a top level Window entity, incl native creation */ public static Window createWindow(Screen screen, Capabilities caps, boolean undecorated) { - return Window.create(NativeWindowFactory.getNativeWindowType(true), null, 0, screen, caps, undecorated); + return createWindowImpl(NativeWindowFactory.getNativeWindowType(true), screen, caps, undecorated); } /** * Create a child Window entity attached to the given parent, incl native creation.
- * The Screen and Display information is regenrated utilizing the parents information.
+ * The Screen and Display information is regenerated utilizing the parents information.
*

- * In case parentWindowObject is a {@link javax.media.nativewindow.NativeWindow},
- * we create a child {@link com.jogamp.newt.Window}, - * utilizing {@link com.jogamp.newt.NewtFactory#createWindowImpl(java.lang.String, javax.media.nativewindow.NativeWindow, com.jogamp.newt.Screen, javax.media.nativewindow.Capabilities, boolean)}

. - *

- * In case parentWindowObject is even a {@link com.jogamp.newt.Window}, the following applies:
- * {@link com.jogamp.newt.event.WindowEvent#EVENT_WINDOW_RESIZED} is not propagated to the child window for e.g. layout
, + * In case parentWindowObject is a {@link com.jogamp.newt.Window} instance,
+ * the new window is added to it's list of children.
+ * This assures proper handling of visibility, creation and destruction.
+ * {@link com.jogamp.newt.event.WindowEvent#EVENT_WINDOW_RESIZED} is not propagated to the child window for layout
, * you have to add an appropriate {@link com.jogamp.newt.event.WindowListener} for this use case.
- * However, {@link com.jogamp.newt.event.WindowEvent#EVENT_WINDOW_DESTROY_NOTIFY} is propagated to the child window, so it will be closed properly.
* The parents visibility is passed to the new Window

*

* In case parentWindowObject is a different {@link javax.media.nativewindow.NativeWindow} implementation,
* you have to handle all events appropriatly.

*

- * In case parentWindowObject is a {@link java.awt.Component},
- * we utilize the {@link com.jogamp.newt.impl.awt.AWTNewtFactory#createNativeChildWindow(Object, com.jogamp.newt.Capabilities, boolean)} - * factory method.
- * The factory adds a {@link com.jogamp.newt.event.WindowListener} to propagate {@link com.jogamp.newt.event.WindowEvent}'s so - * your NEWT Window integrates into the AWT layout.
- * The parents visibility is passed to the new Window

* - * @param parentWindowObject either a NativeWindow or java.awt.Component + * @param parentWindowObject either a NativeWindow instance * @param undecorated only impacts if the window is in top-level state, while attached to a parent window it's rendered undecorated always - * - * @see com.jogamp.newt.NewtFactory#createWindow(long, com.jogamp.newt.Screen, javax.media.nativewindow.Capabilities, boolean) - * @see com.jogamp.newt.impl.awt.AWTNewtFactory#createNativeChildWindow(java.lang.Object, javax.media.nativewindow.Capabilities, boolean) */ - public static Window createWindow(Object parentWindowObject, Capabilities caps, boolean undecorated) { + public static Window createWindow(NativeWindow nParentWindow, Capabilities caps, boolean undecorated) { final String type = NativeWindowFactory.getNativeWindowType(true); - if(null==parentWindowObject) { - return createWindowImpl(type, null, null, caps, undecorated); + if(null==nParentWindow) { + return createWindowImpl(type, caps, undecorated); } - if(parentWindowObject instanceof NativeWindow) { - NativeWindow nParentWindow = (NativeWindow) parentWindowObject; - - Display display=null; - Screen screen=null; - Window parentWindow=null; - - if ( nParentWindow instanceof Window ) { - parentWindow = (Window) nParentWindow ; - Screen nParentScreen = parentWindow.getScreen(); - Display nParentDisplay = nParentScreen.getDisplay(); - display = NewtFactory.wrapDisplay(type, nParentDisplay.getHandle()); - screen = NewtFactory.createScreen(type, display, nParentScreen.getIndex()); - } else { - AbstractGraphicsConfiguration nParentConfig = nParentWindow.getGraphicsConfiguration(); - AbstractGraphicsScreen nParentScreen = nParentConfig.getScreen(); - AbstractGraphicsDevice nParentDevice = nParentScreen.getDevice(); - display = NewtFactory.wrapDisplay(type, nParentDevice.getHandle()); - screen = NewtFactory.createScreen(type, display, nParentScreen.getIndex()); - } - final Window win = createWindowImpl(type, nParentWindow, screen, caps, undecorated); - win.setSize(nParentWindow.getWidth(), nParentWindow.getHeight()); - if ( null != parentWindow ) { - parentWindow.addWindowListener(new WindowAdapter() { - public void windowDestroyNotify(WindowEvent e) { - win.sendEvent(e); - } - }); - win.setVisible(parentWindow.isVisible()); - } - return win; + Screen screen = null; + AbstractGraphicsConfiguration nParentConfig = nParentWindow.getGraphicsConfiguration(); + if(null!=nParentConfig) { + AbstractGraphicsScreen nParentScreen = nParentConfig.getScreen(); + AbstractGraphicsDevice nParentDevice = nParentScreen.getDevice(); + Display display = NewtFactory.wrapDisplay(type, nParentDevice.getHandle()); + screen = NewtFactory.createScreen(type, display, nParentScreen.getIndex()); } else { - if(ReflectionUtil.instanceOf(parentWindowObject, "java.awt.Component")) { - if(ReflectionUtil.isClassAvailable("com.jogamp.newt.impl.awt.AWTNewtFactory")) { - return (Window) ReflectionUtil.callStaticMethod( - "com.jogamp.newt.impl.awt.AWTNewtFactory", - "createNativeChildWindow", - new Class[] { Object.class, Capabilities.class, java.lang.Boolean.TYPE}, - new Object[] { parentWindowObject, caps, new Boolean(undecorated) } ); - } - } + Display display = NewtFactory.createDisplay(type, null); // local display + screen = NewtFactory.createScreen(type, display, 0); // screen 0 + } + final Window win = createWindowImpl(type, nParentWindow, screen, caps, undecorated); + + win.setSize(nParentWindow.getWidth(), nParentWindow.getHeight()); + if ( nParentWindow instanceof Window ) { + Window parentWindow = (Window) nParentWindow ; + parentWindow.getInnerWindow().addChild(win); + win.setVisible(parentWindow.isVisible()); } - throw new RuntimeException("No NEWT child Window factory method for parent object: "+parentWindowObject); + return win; } protected static Window createWindowImpl(String type, NativeWindow parentNativeWindow, Screen screen, Capabilities caps, boolean undecorated) { return Window.create(type, parentNativeWindow, 0, screen, caps, undecorated); } + protected static Window createWindowImpl(String type, long parentWindowHandle, Screen screen, Capabilities caps, boolean undecorated) { + return Window.create(type, null, parentWindowHandle, screen, caps, undecorated); + } + + protected static Window createWindowImpl(String type, Screen screen, Capabilities caps, boolean undecorated) { + return Window.create(type, null, 0, screen, caps, undecorated); + } + + protected static Window createWindowImpl(String type, Capabilities caps, boolean undecorated) { + Display display = NewtFactory.createDisplay(type, null); // local display + Screen screen = NewtFactory.createScreen(type, display, 0); // screen 0 + return Window.create(type, null, 0, screen, caps, undecorated); + } + /** * Create a child Window entity attached to the given parent, incl native creation
* @@ -208,7 +187,7 @@ public abstract class NewtFactory { * @param undecorated only impacts if the window is in top-level state, while attached to a parent window it's rendered undecorated always */ public static Window createWindow(long parentWindowHandle, Screen screen, Capabilities caps, boolean undecorated) { - return Window.create(NativeWindowFactory.getNativeWindowType(true), null, parentWindowHandle, screen, caps, undecorated); + return createWindowImpl(NativeWindowFactory.getNativeWindowType(true), parentWindowHandle, screen, caps, undecorated); } /** @@ -228,7 +207,7 @@ public abstract class NewtFactory { * @param undecorated only impacts if the window is in top-level state, while attached to a parent window it's rendered undecorated always */ public static Window createWindow(String type, Screen screen, Capabilities caps, boolean undecorated) { - return Window.create(type, null, 0, screen, caps, undecorated); + return createWindowImpl(type, null, screen, caps, undecorated); } public static Window createWindow(String type, Object[] cstrArguments, Screen screen, Capabilities caps, boolean undecorated) { diff --git a/src/newt/classes/com/jogamp/newt/OffscreenWindow.java b/src/newt/classes/com/jogamp/newt/OffscreenWindow.java index 5b957afa5..0f75fbfa9 100644 --- a/src/newt/classes/com/jogamp/newt/OffscreenWindow.java +++ b/src/newt/classes/com/jogamp/newt/OffscreenWindow.java @@ -71,7 +71,7 @@ public class OffscreenWindow extends Window implements SurfaceChangeable { surfaceHandle = 0; } - public synchronized void destroy() { + public synchronized void destroy(boolean deep) { surfaceHandle = 0; } @@ -83,7 +83,7 @@ public class OffscreenWindow extends Window implements SurfaceChangeable { return surfaceHandle; } - protected void setVisibleImpl() { + protected void setVisibleImpl(boolean visible) { } public void setSize(int width, int height) { @@ -92,14 +92,24 @@ public class OffscreenWindow extends Window implements SurfaceChangeable { this.height = height; } } + 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 boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { + shouldNotCallThis(); + return false; + } } diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index 978b7f068..bb3fa8982 100755 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -90,10 +90,6 @@ public abstract class Window implements NativeWindow protected static Window create(String type, NativeWindow parentNativeWindow, long parentWindowHandle, Screen screen, Capabilities caps, boolean undecorated) { try { - if(null==screen) { - Display display = NewtFactory.createDisplay(type, null); // local display - screen = NewtFactory.createScreen(type, display, 0); // screen 0 - } Class windowClass; if(caps.isOnscreen()) { windowClass = getWindowClass(type); @@ -101,7 +97,7 @@ public abstract class Window implements NativeWindow windowClass = OffscreenWindow.class; } Window window = (Window) windowClass.newInstance(); - window.invalidate(); + window.invalidate(true); window.parentNativeWindow = parentNativeWindow; window.parentWindowHandle = parentWindowHandle; window.screen = screen; @@ -126,7 +122,7 @@ public abstract class Window implements NativeWindow throw new NativeWindowException("WindowClass "+windowClass+" constructor mismatch at argument #"+argsChecked+"; Constructor: "+getTypeStrList(cstrArgumentTypes)+", arguments: "+getArgsStrList(cstrArguments)); } Window window = (Window) ReflectionUtil.createInstance( windowClass, cstrArgumentTypes, cstrArguments ) ; - window.invalidate(); + window.invalidate(true); window.screen = screen; window.caps = (Capabilities)caps.clone(); window.setUndecorated(undecorated); @@ -146,7 +142,7 @@ public abstract class Window implements NativeWindow protected Screen screen; - private NativeWindow parentNativeWindow; + protected NativeWindow parentNativeWindow; protected long parentWindowHandle; protected Capabilities caps; @@ -154,52 +150,81 @@ public abstract class Window implements NativeWindow protected long windowHandle; protected boolean fullscreen, visible; protected int width, height, x, y; - protected int eventMask; + + // non fullscreen dimensions .. + protected int nfs_width, nfs_height, nfs_x, nfs_y; protected String title = "Newt Window"; protected boolean undecorated = false; - private synchronized boolean createNative() { + private boolean createNative() { if( null==screen || 0!=windowHandle || !visible ) { - // NOP .. or already done return 0 != windowHandle ; } EDTUtil edtUtil = screen.getDisplay().getEDTUtil(); - if( null != edtUtil && !edtUtil.isCurrentThreadEDT() ) { + if( null != edtUtil && edtUtil.isRunning() && !edtUtil.isCurrentThreadEDT() ) { throw new NativeWindowException("EDT enabled but not on EDT"); } - if(DEBUG_WINDOW_EVENT) { - System.out.println("Window.createNative() START ("+Thread.currentThread()+", "+this+")"); + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window.createNative() START ("+Thread.currentThread()+", "+this+")"); } if(validateParentWindowHandle()) { createNativeImpl(); - setVisibleImpl(); + setVisibleImpl(true); } - if(DEBUG_WINDOW_EVENT) { - System.out.println("Window.createNative() END ("+Thread.currentThread()+", "+this+")"); + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window.createNative() END ("+Thread.currentThread()+", "+this+")"); } return 0 != windowHandle ; } private boolean validateParentWindowHandle() { - boolean ok = true; if(null!=parentNativeWindow) { + parentWindowHandle = getNativeWindowHandle(parentNativeWindow); + return 0 != parentWindowHandle ; + } + return true; + } + + private static long getNativeWindowHandle(NativeWindow nativeWindow) { + long handle = 0; + if(null!=nativeWindow) { + boolean ok = true; try { - parentNativeWindow.lockSurface(); + nativeWindow.lockSurface(); } catch (NativeWindowException nwe) { // parent native window not ready .. just skip action for now ok = false; + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window.getNativeWindowHandle: not successful yet: "+nwe); + } } if(ok) { - parentWindowHandle = parentNativeWindow.getWindowHandle(); - parentNativeWindow.unlockSurface(); - if(0==parentWindowHandle) { - throw new NativeWindowException("Parent native window handle is NULL, after succesful locking: "+parentNativeWindow); + handle = nativeWindow.getWindowHandle(); + nativeWindow.unlockSurface(); + if(0==handle) { + throw new NativeWindowException("Parent native window handle is NULL, after succesful locking: "+nativeWindow); + } + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window.getNativeWindowHandle: "+nativeWindow); } } } - return ok; + return handle; + } + + public void runOnEDTIfAvail(boolean wait, final Runnable task) { + Screen screen = getInnerWindow().getScreen(); + if(null==screen) { + throw new RuntimeException("Null screen of inner class: "+this); + } + EDTUtil edtUtil = screen.getDisplay().getEDTUtil(); + if(null!=edtUtil) { + edtUtil.invoke(wait, task); + } else { + task.run(); + } } /** @@ -209,6 +234,14 @@ public abstract class Window implements NativeWindow protected abstract void closeNative(); + public Capabilities getRequestedCapabilities() { + return (Capabilities)caps.clone(); + } + + public NativeWindow getParentNativeWindow() { + return parentNativeWindow; + } + public Screen getScreen() { return screen; } @@ -218,6 +251,8 @@ public abstract class Window implements NativeWindow sb.append(getClass().getName()+"[Config "+config+ "\n, "+screen+ + "\n, ParentWindow "+parentNativeWindow+ + "\n, ParentWindowHandle "+toHexString(parentWindowHandle)+ "\n, WindowHandle "+toHexString(getWindowHandle())+ "\n, SurfaceHandle "+toHexString(getSurfaceHandle())+ "\n, Pos "+getX()+"/"+getY()+", size "+getWidth()+"x"+getHeight()+ @@ -261,8 +296,12 @@ public abstract class Window implements NativeWindow undecorated = value; } + public boolean isUndecorated(boolean fullscreen) { + return 0 != parentWindowHandle || undecorated || fullscreen ; + } + public boolean isUndecorated() { - return undecorated; + return 0 != parentWindowHandle || undecorated || fullscreen ; } public void requestFocus() { @@ -273,16 +312,19 @@ public abstract class Window implements NativeWindow // /** Recursive and blocking lockSurface() implementation */ - public synchronized int lockSurface() { + public int lockSurface() { // We leave the ToolkitLock lock to the specializtion's discretion, // ie the implicit JAWTWindow in case of AWTWindow + if(isDestroyed() || !isNativeWindowValid()) { + return LOCK_SURFACE_NOT_READY; + } surfaceLock.lock(); screen.getDisplay().lockDisplay(); return LOCK_SUCCESS; } /** Recursive and unblocking unlockSurface() implementation */ - public synchronized void unlockSurface() throws NativeWindowException { + public void unlockSurface() throws NativeWindowException { surfaceLock.unlock( new Runnable() { public void run() { screen.getDisplay().unlockDisplay(); @@ -292,59 +334,84 @@ public abstract class Window implements NativeWindow // ie the implicit JAWTWindow in case of AWTWindow } - public synchronized boolean isSurfaceLocked() { + public boolean isSurfaceLocked() { return surfaceLock.isLocked(); } - public synchronized Thread getSurfaceLockOwner() { + public Thread getSurfaceLockOwner() { return surfaceLock.getOwner(); } - public synchronized Exception getLockedStack() { + public Exception getLockedStack() { return surfaceLock.getLockedStack(); } - public void destroy() { + /** + *

+ * destroys the window and children and releases + * windowing related resources.

+ *

+ * all other resources and states are kept intact, + * ie listeners, parent handles and size, position etc.

+ * + * @see #destroy(boolean) + * @see #invalidate() + */ + public final void destroy() { destroy(false); } - /** @param deep If true, the linked Screen and Display will be destroyed as well. */ - public void destroy(boolean deep) { - if(DEBUG_WINDOW_EVENT) { - System.out.println("Window.destroy() start (deep "+deep+" - "+Thread.currentThread()+", "+this+")"); - } - synchronized(surfaceUpdatedListeners) { - surfaceUpdatedListeners = new ArrayList(); - } - synchronized(windowListeners) { - windowListeners = new ArrayList(); + class DestroyAction implements Runnable { + boolean deep; + public DestroyAction(boolean deep) { + this.deep = deep; } - synchronized(mouseListeners) { - mouseListeners = new ArrayList(); - } - synchronized(keyListeners) { - keyListeners = new ArrayList(); - } - synchronized(this) { - destructionLock.lock(); + public void run() { + windowLock(); try { + if(DEBUG_WINDOW_EVENT) { + System.err.println("Window.destroy(deep: "+deep+") START "+Thread.currentThread()+", "+this); + } + + // Childs first .. + ArrayList listeners = null; + synchronized(childWindows) { + listeners = childWindows; + } + for(Iterator i = listeners.iterator(); i.hasNext(); ) { + NativeWindow nw = (NativeWindow) i.next(); + if(nw instanceof Window) { + ((Window)nw).destroy(deep); + } else { + nw.destroy(); + } + } + + // Now us .. + if(deep) { + synchronized(childWindows) { + childWindows = new ArrayList(); + } + synchronized(surfaceUpdatedListeners) { + surfaceUpdatedListeners = new ArrayList(); + } + synchronized(windowListeners) { + windowListeners = new ArrayList(); + } + synchronized(mouseListeners) { + mouseListeners = new ArrayList(); + } + synchronized(keyListeners) { + keyListeners = new ArrayList(); + } + } Display dpy = null; if( null != screen && 0 != windowHandle ) { Screen scr = screen; dpy = (null!=screen) ? screen.getDisplay() : null; - EDTUtil edtUtil = (null!=dpy) ? dpy.getEDTUtil() : null; - if(null!=edtUtil) { - final Window f_win = this; - edtUtil.invokeAndWait(new Runnable() { - public void run() { - f_win.closeNative(); - } - } ); - } else { - closeNative(); - } + closeNative(); } - invalidate(); + invalidate(deep); if(deep) { if(null!=screen) { screen.destroy(); @@ -353,34 +420,85 @@ public abstract class Window implements NativeWindow dpy.destroy(); } } + if(DEBUG_WINDOW_EVENT) { + System.err.println("Window.destroy(deep: "+deep+") END "+Thread.currentThread()+", "+this); + } } finally { - destructionLock.unlock(); + windowUnlock(); } } - if(DEBUG_WINDOW_EVENT) { - System.out.println("Window.destroy() end "+Thread.currentThread()); + } + + /** + * @param deep If true, all resources, ie listeners, parent handles, size, position + * and the referenced NEWT screen and display, will be destroyed as well. Be aware that if you call + * this method with deep = true, you will not be able to regenerate the Window. + * @see #destroy() + * @see #invalidate(boolean) + */ + public void destroy(boolean deep) { + if(!isDestroyed()) { + runOnEDTIfAvail(true, new DestroyAction(deep)); } } + /** + *

+ * render all native window information invalid, + * as if the native window was destroyed.

+ *

+ * all other resources and states are kept intact, + * ie listeners, parent handles and size, position etc.

+ * + * @see #destroy() + * @see #destroy(boolean) + * @see #invalidate(boolean) + */ public void invalidate() { - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - Exception e = new Exception("!!! Window Invalidate "+Thread.currentThread()); - e.printStackTrace(); + invalidate(false); + } + + /** + * @param deep if false only the native window handle is invalidated, otherwise all + * states (references and properties) are reset. Be aware that if you call + * this method with deep = true, you will not be able to regenerate the Window. + * @see #invalidate() + * @see #destroy() + * @see #destroy(boolean) + */ + public void invalidate(boolean deep) { + windowLock(); + try{ + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + String msg = new String("!!! Window Invalidate(deep: "+deep+") "+Thread.currentThread()); + System.err.println(msg); + //Exception e = new Exception(msg); + //e.printStackTrace(); + } + windowHandle = 0; + visible=false; + fullscreen=false; + + if(deep) { + screen = null; + parentWindowHandle = 0; + parentNativeWindow = null; + caps = null; + + // Default position and dimension will be re-set immediately by user + width = 128; + height = 128; + x=0; + y=0; + } + } finally { + windowUnlock(); } - screen = null; - parentNativeWindow = null; - parentWindowHandle = 0; - caps = null; - windowHandle = 0; - fullscreen=false; - visible=false; - eventMask = 0; + } - // Default position and dimension will be re-set immediately by user - width = 128; - height = 128; - x=0; - y=0; + /** @return true if the native window handle is valid and ready to operate */ + public boolean isNativeWindowValid() { + return 0 != windowHandle ; } public boolean isDestroyed() { @@ -391,10 +509,6 @@ public abstract class Window implements NativeWindow return false; } - protected void clearEventMask() { - eventMask=0; - } - public long getDisplayHandle() { return screen.getDisplay().getHandle(); } @@ -442,6 +556,14 @@ public abstract class Window implements NativeWindow return new Insets(0,0,0,0); } + /** Returns the most inner Window instance.
+ Currently only {@link com.jogamp.newt.opengl.GLWindow} + has an aggregation to an inner Window instance. + */ + public Window getInnerWindow() { + return this; + } + /** If this Window actually wraps one from another toolkit such as the AWT, this will return a non-null value. */ public Object getWrappedWindow() { @@ -468,7 +590,7 @@ public abstract class Window implements NativeWindow return fullscreen; } - private boolean autoDrawableMember = false; + private boolean handleDestroyNotify = true; /** If the implementation is capable of detecting a device change return true and clear the status/reason of the change. */ @@ -477,107 +599,258 @@ public abstract class Window implements NativeWindow } /** - * If set to true, - * certain action will be performed by the owning - * AutoDrawable, ie the destroy() call within windowDestroyNotify() + * If set to true, the default value, this NEWT Window implementation will + * handle the destruction (ie {@link #destroy()} call) within {@link #windowDestroyNotify()} implementation.
+ * If set to false, it's up to the caller/owner to handle destruction within {@link #windowDestroyNotify()}. */ - public void setAutoDrawableClient(boolean b) { - autoDrawableMember = b; + public void setHandleDestroyNotify(boolean b) { + handleDestroyNotify = b; } protected void windowDestroyNotify() { if(DEBUG_WINDOW_EVENT) { - System.out.println("Window.windowDestroyNotify start "+Thread.currentThread()); + System.err.println("Window.windowDestroyNotify START "+Thread.currentThread()); } sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); - if(!autoDrawableMember && !destructionLock.isLocked()) { + if(handleDestroyNotify && !isDestroyed()) { destroy(); } if(DEBUG_WINDOW_EVENT) { - System.out.println("Window.windowDestroyeNotify end "+Thread.currentThread()); + System.err.println("Window.windowDestroyeNotify END "+Thread.currentThread()); } } protected void windowDestroyed() { if(DEBUG_WINDOW_EVENT) { - System.out.println("Window.windowDestroyed "+Thread.currentThread()); + System.err.println("Window.windowDestroyed "+Thread.currentThread()); } - if(!destructionLock.isLocked()) { - invalidate(); + invalidate(); + } + + protected boolean reparentWindowImpl() { + // default implementation, no native reparenting support + return false; + } + + /** + * Change this window's parent window.
+ *

+ * In case the old parent is not null and a Window, + * this window is removed from it's list of children.
+ * In case the new parent is not null and a Window, + * this window is added to it's list of children.

+ * + * @param newParent the new parent NativeWindow. If null, this Window becomes a top level window. + * @param newScreen if not null and this window handle is not yet set + * this Screen is being used. + */ + public void reparentWindow(NativeWindow newParent, Screen newScreen) { + windowLock(); + try{ + if ( 0 == windowHandle && null != newScreen ) { + screen = newScreen; + } + long newParentHandle = 0 ; + if(null!=newParent) { + newParentHandle = getNativeWindowHandle(newParent); + if ( 0 == newParentHandle ) { + return; // bail out .. not ready yet + } + } + + if(DEBUG_IMPLEMENTATION) { + System.err.println("reparent: START ("+Thread.currentThread()+") windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+" -> "+toHexString(newParentHandle)+", visible "+visible+", parentNativeWindow "+(null!=parentNativeWindow)); + } + + if(null!=parentNativeWindow && parentNativeWindow instanceof Window) { + ((Window)parentNativeWindow).getInnerWindow().removeChild(this); + } + parentNativeWindow = newParent; + if(parentNativeWindow instanceof Window) { + ((Window)parentNativeWindow).getInnerWindow().addChild(this); + } + + if(newParentHandle != parentWindowHandle) { + parentWindowHandle = newParentHandle; + if(0!=parentWindowHandle) { + // reset position to 0/0 within parent space + // FIXME .. cache position ? + x = 0; + y = 0; + } + if(!reparentWindowImpl()) { + parentWindowHandle = 0; + + // do it the hard way .. reconstruction with setVisible(true) + if( 0 != windowHandle ) { + destroy(false); + } + } + } + + if(DEBUG_IMPLEMENTATION) { + System.err.println("reparentWindow: END ("+Thread.currentThread()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentNativeWindow "+(null!=parentNativeWindow)); + } + } finally { + windowUnlock(); + } + } + + class VisibleAction implements Runnable { + boolean visible; + public VisibleAction(boolean visible) { + this.visible = visible; + } + public void run() { + windowLock(); + try{ + if( !isDestroyed() ) { + ArrayList listeners = null; + synchronized(childWindows) { + listeners = childWindows; + } + if(!visible && listeners.size()>0) { + for(Iterator i = listeners.iterator(); i.hasNext(); ) { + NativeWindow nw = (NativeWindow) i.next(); + if(nw instanceof Window) { + ((Window)nw).setVisible(false); + } + } + } + if(0==windowHandle && visible) { + Window.this.visible = visible; + if( 00) { + for(Iterator i = listeners.iterator(); i.hasNext(); ) { + NativeWindow nw = (NativeWindow) i.next(); + if(nw instanceof Window) { + ((Window)nw).setVisible(true); + } + } + } + } + + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window setVisible: END ("+Thread.currentThread()+") "+x+"/"+y+" "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+Window.this.visible); + } + } finally { + windowUnlock(); + } } } /** *

- * setVisible makes the window visible if visible is true, - * otherwise the window becomes invisible.

+ * setVisible makes the window and children visible if visible is true, + * otherwise the window and children becomes invisible.

*

* The setVisible(true) is responsible to actual create the native window.

*

+ * Zero size semantics are respected, see {@link #setSize(int,int)}:
+ *

+     * if ( 0 == windowHandle && visible ) { 
+     *      this.visible = visible;
+     *      if( 0

+ *

* In case this window is a child window and a parent {@link javax.media.nativewindow.NativeWindow} is being used,
* the parent's {@link javax.media.nativewindow.NativeWindow} handle is retrieved via {@link javax.media.nativewindow.NativeWindow#getWindowHandle()}.
* If this action fails, ie if the parent {@link javax.media.nativewindow.NativeWindow} is not valid yet,
* no native window is created yet and setVisible(true) shall be repeated when it is.

*/ - public void setVisible(final boolean visible) { - setVisible(visible, false); - } - - public void setVisible(final boolean visible, boolean deferred) { - if(!isDestroyed()) { - EDTUtil edtUtil = screen.getDisplay().getEDTUtil(); - if(null!=edtUtil) { - edtUtil.invoke(deferred, new Runnable() { - public void run() { - setVisibleTask(visible); - } - }); - } else { - setVisibleTask(visible); - } - } - } - - private synchronized void setVisibleTask(final boolean visible) { + public void setVisible(boolean visible) { if(DEBUG_IMPLEMENTATION) { - System.err.println("setVisibleTask: START ("+Thread.currentThread()+") "+this.x+"/"+this.y+" "+this.width+"x"+this.height+", fs "+fullscreen+", windowHandle "+windowHandle+", visible: "+this.visible+" -> "+visible); - } - int didit = 0; - if(0==windowHandle && visible) { - this.visible = visible; - didit = 01; - if( createNative() ) { - didit = 11; - } - } else if(this.visible != visible) { - this.visible = visible; - didit = 2; - if(0 != windowHandle) { - setVisibleImpl(); - didit = 22; - } + String msg = new String("Window setVisible: START ("+Thread.currentThread()+") "+x+"/"+y+" "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+this.visible+" -> "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentNativeWindow "+(null!=parentNativeWindow)); + //System.err.println(msg); + Exception ee = new Exception(msg); + ee.printStackTrace(); } - if(DEBUG_IMPLEMENTATION) { - System.err.println("setVisibleTask: END ("+Thread.currentThread()+") didit "+didit+", "+this.x+"/"+this.y+" "+this.width+"x"+this.height+", fs "+fullscreen+", windowHandle "+windowHandle+", visible: "+visible); + if(!isDestroyed()) { + runOnEDTIfAvail(true, new VisibleAction(visible)); } } - - protected abstract void setVisibleImpl(); + protected abstract void setVisibleImpl(boolean visible); /** * Sets the size of the client area of the window, excluding decorations * Total size of the window will be * {@code width+insets.left+insets.right, height+insets.top+insets.bottom}
- * - * This call is ignored if in fullscreen mode.
+ *

+ * Zero size semantics are respected, see {@link #setVisible(boolean)}:
+ *

+     * if ( 0 != windowHandle && 0>=width*height && visible ) {
+     *      setVisible(false);
+     * } else if ( 0 == windowHandle && 0

+ *

+ * This call is ignored if in fullscreen mode.

* * @param width of the client area of the window * @param height of the client area of the window */ - public abstract void setSize(int width, int height); + public void setSize(int width, int height) { + int visibleAction = 0; // 1 invisible, 2 visible + windowLock(); + try{ + 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); + Exception e = new Exception(msg); + e.printStackTrace(); + } + if (width != this.width || this.height != height) { + if(!fullscreen) { + 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 && 00) { + setVisible( ( 1 == visibleAction ) ? false : true ); + } + } + protected abstract void setSizeImpl(int width, int height); /** * Sets the location of the top left corner of the window, including @@ -589,13 +862,103 @@ public abstract class Window implements NativeWindow * @param x coord of the top left corner * @param y coord of the top left corner */ - public abstract void setPosition(int x, int y); + public void setPosition(int x, int y) { + windowLock(); + 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; + } + } + } + } finally { + windowUnlock(); + } + } + protected abstract void setPositionImpl(int x, int y); + + public boolean setFullscreen(boolean fullscreen) { + windowLock(); + 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 { + 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()); + } + this.fullscreen = setFullscreenImpl(fullscreen, x, y, w, h); + } + return this.fullscreen; + } finally { + windowUnlock(); + } + } + protected abstract boolean setFullscreenImpl(boolean fullscreen, int x, int y, int widht, int height); - public abstract boolean setFullscreen(boolean fullscreen); + // + // Child Window Management + // + + private ArrayList childWindows = new ArrayList(); + + protected void removeChild(NativeWindow win) { + synchronized(childWindows) { + ArrayList newChildWindows = (ArrayList) childWindows.clone(); + newChildWindows.remove(win); + childWindows = newChildWindows; + } + } + + protected void addChild(NativeWindow win) { + if (win == null) { + return; + } + synchronized(childWindows) { + ArrayList newChildWindows = (ArrayList) childWindows.clone(); + newChildWindows.add(win); + childWindows = newChildWindows; + } + } + + // + // Generic Event Support + // + + public void sendEvent(NEWTEvent e) { + if(e instanceof WindowEvent) { + sendWindowEvent((WindowEvent)e); + } else if(e instanceof KeyEvent) { + sendKeyEvent((KeyEvent)e); + } else if(e instanceof MouseEvent) { + sendMouseEvent((MouseEvent)e); + } else if(e instanceof PaintEvent) { + sendPaintEvent((PaintEvent)e); + } + } // // SurfaceUpdatedListener Support // + private ArrayList surfaceUpdatedListeners = new ArrayList(); public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { @@ -643,22 +1006,6 @@ public abstract class Window implements NativeWindow } } - // - // Generic Event Support - // - - public void sendEvent(NEWTEvent e) { - if(e instanceof WindowEvent) { - sendWindowEvent((WindowEvent)e); - } else if(e instanceof KeyEvent) { - sendKeyEvent((KeyEvent)e); - } else if(e instanceof MouseEvent) { - sendMouseEvent((MouseEvent)e); - } else if(e instanceof PaintEvent) { - sendPaintEvent((PaintEvent)e); - } - } - // // MouseListener/Event Support // @@ -704,7 +1051,7 @@ public abstract class Window implements NativeWindow return; // .. invalid .. } if(DEBUG_MOUSE_EVENT) { - System.out.println("sendMouseEvent: "+MouseEvent.getEventTypeString(eventType)+ + System.err.println("sendMouseEvent: "+MouseEvent.getEventTypeString(eventType)+ ", mod "+modifiers+", pos "+x+"/"+y+", button "+button); } if(button<0||button>MouseEvent.BUTTON_NUMBER) { @@ -751,7 +1098,7 @@ public abstract class Window implements NativeWindow sendMouseEvent(e); if(null!=eClicked) { if(DEBUG_MOUSE_EVENT) { - System.out.println("sendMouseEvent: synthesized MOUSE_CLICKED event"); + System.err.println("sendMouseEvent: synthesized MOUSE_CLICKED event"); } sendMouseEvent(eClicked); } @@ -759,7 +1106,7 @@ public abstract class Window implements NativeWindow protected void sendMouseEvent(MouseEvent e) { if(DEBUG_MOUSE_EVENT) { - System.out.println("sendMouseEvent: event: "+e); + System.err.println("sendMouseEvent: event: "+e); } ArrayList listeners = null; @@ -840,7 +1187,7 @@ public abstract class Window implements NativeWindow protected void sendKeyEvent(KeyEvent e) { if(DEBUG_KEY_EVENT) { - System.out.println("sendKeyEvent: "+e); + System.err.println("sendKeyEvent: "+e); } ArrayList listeners = null; synchronized(keyListeners) { @@ -904,7 +1251,7 @@ public abstract class Window implements NativeWindow protected void sendWindowEvent(WindowEvent e) { if(DEBUG_WINDOW_EVENT) { - System.out.println("sendWindowEvent: "+e); + System.err.println("sendWindowEvent: "+e); } ArrayList listeners = null; synchronized(windowListeners) { @@ -1027,7 +1374,30 @@ public abstract class Window implements NativeWindow return sb.toString(); } - private RecursiveToolkitLock destructionLock = new RecursiveToolkitLock(); private RecursiveToolkitLock surfaceLock = new RecursiveToolkitLock(); + private RecursiveToolkitLock windowLock = new RecursiveToolkitLock(); + + private static final boolean TRACE_LOCK = false; + + protected final void windowLock() { + getInnerWindow().windowLock.lock(); + if(TRACE_LOCK) { + Exception e = new Exception("WINDOW LOCK SET: R "+getInnerWindow().windowLock.getRecursionCount()+", "+getInnerWindow().windowLock); + e.printStackTrace(); + } + } + protected final void windowUnlock() { + getInnerWindow().windowLock.unlock(); + if(TRACE_LOCK) { + Exception e = new Exception("WINDOW LOCK FREE: R "+getInnerWindow().windowLock.getRecursionCount()+", "+getInnerWindow().windowLock); + e.printStackTrace(); + } + } + protected final boolean windowIsLocked() { + return getInnerWindow().windowLock.isLocked(); + } + protected final void shouldNotCallThis() { + throw new NativeWindowException("Should not call this"); + } } diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java new file mode 100644 index 000000000..23269a93b --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2010 Sven Gothel. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name Sven Gothel or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.newt.awt; + +import java.lang.reflect.*; +import java.security.*; + +import java.awt.Canvas; + +import javax.media.nativewindow.*; +// import javax.media.nativewindow.awt.*; + +import com.jogamp.newt.event.awt.AWTAdapter; +import com.jogamp.newt.event.awt.AWTParentWindowAdapter; +import com.jogamp.newt.Screen; +import com.jogamp.newt.Window; +import com.jogamp.newt.impl.Debug; + +public class NewtCanvasAWT extends java.awt.Canvas { + public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window"); + + NativeWindow parent = null; + Window newtChild = null; + AWTAdapter awtAdapter = null; + + /** + * Instantiates a NewtCanvas without a NEWT child.
+ * @see #setNEWTChild(Window) + */ + public NewtCanvasAWT() { + super(); + } + + /** + * Instantiates a NewtCanvas with a NEWT child. + */ + public NewtCanvasAWT(Window child) { + super(); + setNEWTChild(child); + } + + /** sets a new NEWT child, provoking reparenting on the NEWT level. */ + public NewtCanvasAWT setNEWTChild(Window child) { + if(newtChild!=child) { + newtChild = child; + if(null!=parent) { + // reparent right away, addNotify has been called already + reparentWindow( (null!=newtChild) ? true : false ); + } + } + return this; + } + + /** @return the current NEWT child */ + public Window getNEWTChild() { + return newtChild; + } + + /** @return this AWT Canvas NativeWindow represention, may be null in case {@link #removeNotify()} has been called, + * or {@link #addNotify()} hasn't been called yet.*/ + public NativeWindow getNativeWindow() { return parent; } + + void setWindowAdapter(boolean attach) { + if(null!=awtAdapter) { + awtAdapter.removeFrom(this); + awtAdapter=null; + } + if(attach && null!=newtChild) { + awtAdapter = new AWTParentWindowAdapter(newtChild).addTo(this); + } + } + + public void addNotify() { + super.addNotify(); + disableBackgroundErase(); + if(DEBUG_IMPLEMENTATION) { + // if ( isShowing() == false ) -> Container was not visible yet. + // if ( isShowing() == true ) -> Container is already visible. + System.err.println("NewtCanvasAWT.addNotify: "+newtChild+", "+this+", visible "+isVisible()+", showing "+isShowing()+", displayable "+isDisplayable()); + } + reparentWindow(true); + } + + public void removeNotify() { + if(DEBUG_IMPLEMENTATION) { + System.err.println("NewtCanvasAWT.removeNotify: "+newtChild); + } + reparentWindow(false); + super.removeNotify(); + } + + void reparentWindow(boolean add) { + if(null==newtChild) { + return; // nop + } + + if(add) { + if(null!=newtChild) { + parent = NewtFactoryAWT.getNativeWindow(this, newtChild.getRequestedCapabilities()); + } + if(null!=parent) { + // 1st choice - NEWT size := AWT size + // 2nd choice - AWT size := NEWT size + if(0>=getWidth()*getHeight()) { + setSize(newtChild.getWidth(), newtChild.getHeight()); // #2 + } + Screen screen = null; + if( !newtChild.isNativeWindowValid() ) { + screen = NewtFactoryAWT.createCompatibleScreen(parent); + } + newtChild.reparentWindow(parent, screen); + if ( 0 < getWidth() * getHeight() ) { + newtChild.setSize(getWidth(), getHeight()); // #1 + newtChild.setVisible(true); + } + setWindowAdapter(true); + } + } else { + setWindowAdapter(false); + parent = null; + newtChild.setVisible(false); + newtChild.reparentWindow(null, null); + } + } + + // Disables the AWT's erasing of this Canvas's background on Windows + // in Java SE 6. This internal API is not available in previous + // releases, but the system property + // -Dsun.awt.noerasebackground=true can be specified to get similar + // results globally in previous releases. + private static boolean disableBackgroundEraseInitialized; + private static Method disableBackgroundEraseMethod; + private void disableBackgroundErase() { + if (!disableBackgroundEraseInitialized) { + try { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + try { + Class clazz = getToolkit().getClass(); + while (clazz != null && disableBackgroundEraseMethod == null) { + try { + disableBackgroundEraseMethod = + clazz.getDeclaredMethod("disableBackgroundErase", + new Class[] { Canvas.class }); + disableBackgroundEraseMethod.setAccessible(true); + } catch (Exception e) { + clazz = clazz.getSuperclass(); + } + } + } catch (Exception e) { + } + return null; + } + }); + } catch (Exception e) { + } + disableBackgroundEraseInitialized = true; + } + if (disableBackgroundEraseMethod != null) { + try { + disableBackgroundEraseMethod.invoke(getToolkit(), new Object[] { this }); + } catch (Exception e) { + // FIXME: workaround for 6504460 (incorrect backport of 6333613 in 5.0u10) + // throw new GLException(e); + } + } + } +} + diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java index e0f86b1a9..6409ab7a8 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java @@ -30,7 +30,7 @@ * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ -package com.jogamp.newt.impl.awt; +package com.jogamp.newt.awt; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; @@ -46,9 +46,12 @@ import com.jogamp.newt.Display; import com.jogamp.newt.Screen; import com.jogamp.newt.Window; import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.util.EDTUtil; +import com.jogamp.newt.impl.Debug; import com.jogamp.common.util.ReflectionUtil; -public class AWTNewtFactory extends NewtFactory { +public class NewtFactoryAWT extends NewtFactory { + public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window"); /** * Wraps an AWT component into a {@link javax.media.nativewindow.NativeWindow} utilizing the {@link javax.media.nativewindow.NativeWindowFactory},
@@ -76,46 +79,13 @@ public class AWTNewtFactory extends NewtFactory { DefaultGraphicsConfiguration config = AWTGraphicsConfiguration.create(awtComp, (Capabilities) capsRequested.clone(), capsRequested); NativeWindow awtNative = NativeWindowFactory.getNativeWindow(awtComp, config); // a JAWTWindow + if(DEBUG_IMPLEMENTATION) { + System.out.println("NewtFactoryAWT.getNativeWindow: "+awtComp+" -> "+awtNative); + } return awtNative; } - /** - * Creates a native NEWT child window to a AWT parent window.
- *

- * First we create a {@link javax.media.nativewindow.NativeWindow} presentation of the given {@link java.awt.Component}, - * utilizing {@link #getNativeWindow(java.awt.Component)}.
- * The actual wrapping implementation is {@link com.jogamp.nativewindow.impl.jawt.JAWTWindow}.

- *

- * Second we create a child {@link com.jogamp.newt.Window}, - * utilizing {@link com.jogamp.newt.NewtFactory#createWindowImpl(java.lang.String, javax.media.nativewindow.NativeWindow, com.jogamp.newt.Screen, javax.media.nativewindow.Capabilities, boolean)}, - * passing the created {@link javax.media.nativewindow.NativeWindow}.

- - *

- * Third we attach a {@link com.jogamp.newt.event.awt.AWTParentWindowAdapter} to the given AWT component.
- * The adapter passes window related events to our new child window, look at the implementation

- * - *

- * Forth we pass the parents visibility to the new Window

- * - * @param awtParentObject must be of type java.awt.Component - * @param undecorated only impacts if the window is in top-level state, while attached to a parent window it's rendered undecorated always - * @return The successful created child window, or null if the AWT parent is not ready yet (no valid peers) - */ - public static Window createNativeChildWindow(Object awtParentObject, Capabilities newtCaps, boolean undecorated) { - if( null == awtParentObject ) { - throw new NativeWindowException("Null AWT Parent Component"); - } - if( ! (awtParentObject instanceof java.awt.Component) ) { - throw new NativeWindowException("AWT Parent Component not a java.awt.Component"); - } - java.awt.Component awtParent = (java.awt.Component) awtParentObject; - - // Generate a complete JAWT NativeWindow from the AWT Component - NativeWindow parent = getNativeWindow(awtParent, newtCaps); - if(null==parent) { - throw new NativeWindowException("Null NativeWindow from parent: "+awtParent); - } - + public static Screen createCompatibleScreen(NativeWindow parent) { // Get parent's NativeWindow details AWTGraphicsConfiguration parentConfig = (AWTGraphicsConfiguration) parent.getGraphicsConfiguration(); AWTGraphicsScreen parentScreen = (AWTGraphicsScreen) parentConfig.getScreen(); @@ -124,16 +94,7 @@ public class AWTNewtFactory extends NewtFactory { // Prep NEWT's Display and Screen according to the parent final String type = NativeWindowFactory.getNativeWindowType(true); Display display = NewtFactory.wrapDisplay(type, parentDevice.getHandle()); - Screen screen = NewtFactory.createScreen(type, display, parentScreen.getIndex()); - - // NEWT Window creation and add event handler for proper propagation AWT -> NEWT - // and copy size/visible state - Window window = NewtFactory.createWindowImpl(type, parent, screen, newtCaps, undecorated); - new AWTParentWindowAdapter(window).addTo(awtParent); - window.setSize(awtParent.getWidth(), awtParent.getHeight()); - window.setVisible(awtParent.isVisible()); - - return window; + return NewtFactory.createScreen(type, display, parentScreen.getIndex()); } } diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java index 3abe6531a..e8497a741 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java @@ -31,6 +31,9 @@ */ package com.jogamp.newt.event.awt; +import com.jogamp.newt.util.EDTUtil; +import com.jogamp.newt.impl.Debug; + /** * Convenient adapter forwarding AWT events to NEWT via the event listener model.
*

@@ -102,6 +105,8 @@ package com.jogamp.newt.event.awt; */ public abstract class AWTAdapter implements java.util.EventListener { + public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window"); + com.jogamp.newt.event.NEWTEventListener newtListener; com.jogamp.newt.Window newtWindow; @@ -157,9 +162,16 @@ public abstract class AWTAdapter implements java.util.EventListener */ public abstract AWTAdapter addTo(java.awt.Component awtComponent); + /** @see #addTo(java.awt.Component) */ + public abstract AWTAdapter removeFrom(java.awt.Component awtComponent); + void enqueueEvent(com.jogamp.newt.event.NEWTEvent event) { + enqueueEvent(false, event); + } + + void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event) { try { - newtWindow.getScreen().getDisplay().enqueueEvent(event); + newtWindow.getScreen().getDisplay().enqueueEvent(wait, event); } catch (NullPointerException npe) { /* that's ok .. window might be down already */ } diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java index 64d4d8d86..d2b733f98 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java @@ -50,6 +50,11 @@ public class AWTKeyAdapter extends AWTAdapter implements java.awt.event.KeyListe return this; } + public AWTAdapter removeFrom(java.awt.Component awtComponent) { + awtComponent.removeKeyListener(this); + return this; + } + public void keyPressed(java.awt.event.KeyEvent e) { com.jogamp.newt.event.KeyEvent event = AWTNewtEventFactory.createKeyEvent(e, newtWindow); if(null!=newtListener) { diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTMouseAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTMouseAdapter.java index 7efcd123e..058a5f250 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTMouseAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTMouseAdapter.java @@ -51,6 +51,12 @@ public class AWTMouseAdapter extends AWTAdapter implements java.awt.event.MouseL return this; } + public AWTAdapter removeFrom(java.awt.Component awtComponent) { + awtComponent.removeMouseListener(this); + awtComponent.removeMouseMotionListener(this); + return this; + } + public void mouseClicked(java.awt.event.MouseEvent e) { com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, newtWindow); if(null!=newtListener) { diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java index 01f0457e3..d94a32a9c 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java @@ -42,9 +42,18 @@ public class AWTParentWindowAdapter extends AWTWindowAdapter } public void componentResized(java.awt.event.ComponentEvent e) { - // need to really resize the NEWT child window - java.awt.Component comp = e.getComponent(); - newtWindow.setSize(comp.getWidth(), comp.getHeight()); + // Need to resize the NEWT child window + // the resized event will be send via the native window feedback. + final java.awt.Component comp = e.getComponent(); + newtWindow.runOnEDTIfAvail(false, new Runnable() { + public void run() { + if( 0 < comp.getWidth() * comp.getHeight() ) { + newtWindow.setSize(comp.getWidth(), comp.getHeight()); + newtWindow.setVisible(comp.isVisible()); + } else { + newtWindow.setVisible(false); + } + }}); } public void componentMoved(java.awt.event.ComponentEvent e) { diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java index fd6ceddae..53ce03299 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java @@ -33,9 +33,9 @@ package com.jogamp.newt.event.awt; public class AWTWindowAdapter extends AWTAdapter - implements java.awt.event.ComponentListener, java.awt.event.WindowListener, java.awt.event.HierarchyListener + implements java.awt.event.ComponentListener, java.awt.event.WindowListener, + java.awt.event.HierarchyListener, java.awt.event.HierarchyBoundsListener { - java.awt.Component awtComponent; WindowClosingListener windowClosingListener; public AWTWindowAdapter(com.jogamp.newt.event.WindowListener newtListener) { @@ -51,16 +51,36 @@ public class AWTWindowAdapter } public AWTAdapter addTo(java.awt.Component awtComponent) { - this.awtComponent = awtComponent; + java.awt.Window win = getWindow(awtComponent); awtComponent.addComponentListener(this); awtComponent.addHierarchyListener(this); - addWindowClosingListenerTo(getWindow(awtComponent)); + awtComponent.addHierarchyBoundsListener(this); + if( null == windowClosingListener ) { + windowClosingListener = new WindowClosingListener(); + } + if( null != win ) { + win.addWindowListener(windowClosingListener); + } if(awtComponent instanceof java.awt.Window) { ((java.awt.Window)awtComponent).addWindowListener(this); } return this; } + public AWTAdapter removeFrom(java.awt.Component awtComponent) { + awtComponent.removeComponentListener(this); + awtComponent.removeHierarchyListener(this); + awtComponent.removeHierarchyBoundsListener(this); + java.awt.Window win = getWindow(awtComponent); + if( null != win && null != windowClosingListener ) { + win.removeWindowListener(windowClosingListener); + } + if(awtComponent instanceof java.awt.Window) { + ((java.awt.Window)awtComponent).removeWindowListener(this); + } + return this; + } + static java.awt.Window getWindow(java.awt.Component comp) { while( null != comp && !(comp instanceof java.awt.Window) ) { comp = comp.getParent(); @@ -71,15 +91,6 @@ public class AWTWindowAdapter return null; } - void addWindowClosingListenerTo(java.awt.Window win) { - if( null == windowClosingListener ) { - windowClosingListener = new WindowClosingListener(); - } - if( null != win ) { - win.addWindowListener(windowClosingListener); - } - } - public void componentResized(java.awt.event.ComponentEvent e) { com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow); if(null!=newtListener) { @@ -101,7 +112,11 @@ public class AWTWindowAdapter public void componentShown(java.awt.event.ComponentEvent e) { if(null==newtListener) { if(!newtWindow.isDestroyed()) { - newtWindow.setVisible(true, true /* deferred */); + newtWindow.runOnEDTIfAvail(false, new Runnable() { + public void run() { + newtWindow.setVisible(true); + } + }); } } } @@ -109,7 +124,11 @@ public class AWTWindowAdapter public void componentHidden(java.awt.event.ComponentEvent e) { if(null==newtListener) { if(!newtWindow.isDestroyed()) { - newtWindow.setVisible(false, true /* deferred */); + newtWindow.runOnEDTIfAvail(false, new Runnable() { + public void run() { + newtWindow.setVisible(false); + } + }); } } } @@ -145,27 +164,45 @@ public class AWTWindowAdapter public void hierarchyChanged(java.awt.event.HierarchyEvent e) { if( null == newtListener ) { long bits = e.getChangeFlags(); - java.awt.Component changed = e.getChanged(); + final java.awt.Component changed = e.getChanged(); if( 0 != ( java.awt.event.HierarchyEvent.SHOWING_CHANGED & bits ) ) { - final boolean visible = changed.isVisible(); - if(!newtWindow.isDestroyed()) { - newtWindow.setVisible(visible, true /* deferred */); + final boolean showing = changed.isShowing(); + if(DEBUG_IMPLEMENTATION) { + System.out.println("hierarchyChanged SHOWING_CHANGED: showing "+showing+", "+changed); } - } else if( 0 != ( java.awt.event.HierarchyEvent.PARENT_CHANGED & bits ) ) { - if(awtComponent == changed) { - java.awt.Window win = getWindow(changed); - if(null != win) { - addWindowClosingListenerTo(win); - } else { - java.awt.Component parent = e.getChangedParent(); - if(parent instanceof java.awt.Window) { - ((java.awt.Window)parent).removeWindowListener(this); - if( null != windowClosingListener ) { - ((java.awt.Window)parent).removeWindowListener(windowClosingListener); - } + if(!newtWindow.isDestroyed()) { + newtWindow.runOnEDTIfAvail(false, new Runnable() { + public void run() { + newtWindow.setVisible(showing); } - } + }); } + } + if( 0 != ( java.awt.event.HierarchyEvent.DISPLAYABILITY_CHANGED & bits ) ) { + final boolean displayability = changed.isDisplayable(); + if(DEBUG_IMPLEMENTATION) { + System.out.println("hierarchyChanged DISPLAYABILITY_CHANGED: displayability "+displayability+", "+changed); + } + } + } + } + + public void ancestorMoved(java.awt.event.HierarchyEvent e) { + if( null == newtListener ) { + final java.awt.Component changed = e.getChanged(); + final boolean showing = changed.isShowing(); + if(DEBUG_IMPLEMENTATION) { + System.out.println("ancestorMoved: showing "+showing+", "+changed); + } + } + } + + public void ancestorResized(java.awt.event.HierarchyEvent e) { + if( null == newtListener ) { + final java.awt.Component changed = e.getChanged(); + final boolean showing = changed.isShowing(); + if(DEBUG_IMPLEMENTATION) { + System.out.println("ancestorResized: showing "+showing+", "+changed); } } } @@ -176,7 +213,7 @@ public class AWTWindowAdapter if(null!=newtListener) { ((com.jogamp.newt.event.WindowListener)newtListener).windowDestroyNotify(event); } else { - enqueueEvent(event); + enqueueEvent(true, event); } } 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 b98a6fa20..f97625320 100644 --- a/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java @@ -176,7 +176,7 @@ public class AWTWindow extends Window { return res; } - protected void setVisibleImpl() { + protected void setVisibleImpl(final boolean visible) { runOnEDT(true, new Runnable() { public void run() { container.setVisible(visible); @@ -203,13 +203,7 @@ public class AWTWindow extends Window { ((AWTScreen)screen).setScreenSize(w, h); } - public void setSize(final int width, final int height) { - this.width = width; - this.height = height; - if(!fullscreen) { - nfs_width=width; - nfs_height=height; - } + 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() { @@ -237,55 +231,34 @@ public class AWTWindow extends Window { Insets(insets[0],insets[1],insets[2],insets[3]); } - public void setPosition(final int x, final int y) { - this.x = x; - this.y = y; - if(!fullscreen) { - nfs_x=x; - nfs_y=y; + protected void setPositionImpl(final int x, final int y) { + if(null!=container) { + runOnEDT(true, new Runnable() { + public void run() { + container.setLocation(x, y); + } + }); } - runOnEDT(true, new Runnable() { - public void run() { - container.setLocation(x, y); - } - }); } - public boolean setFullscreen(final boolean fullscreen) { - if(this.fullscreen!=fullscreen) { - final int x,y,w,h; - this.fullscreen=fullscreen; - if(fullscreen) { - x = 0; y = 0; - w = screen.getWidth(); - h = screen.getHeight(); - } else { - x = nfs_x; - y = nfs_y; - w = nfs_width; - h = nfs_height; - } - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - System.err.println("AWTWindow fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h); - } - /** 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(!container.isDisplayable()) { - frame.setUndecorated(undecorated||fullscreen); - } else { - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - System.err.println("AWTWindow can't undecorate already created frame"); - } + protected boolean setFullscreenImpl(final boolean fullscreen, final int x, final int y, final int w, final int h) { + /** 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(!container.isDisplayable()) { + frame.setUndecorated(isUndecorated(fullscreen)); + } else { + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + System.err.println("AWTWindow can't undecorate already created frame"); } } - container.setLocation(x, y); - container.setSize(w, h); } - }); - } - return true; + container.setLocation(x, y); + container.setSize(w, h); + } + }); + return fullscreen; } public Object getWrappedWindow() { 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 7b867db21..74cb53f7e 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 @@ -77,13 +77,13 @@ public class Window extends com.jogamp.newt.Window { } } - protected void setVisibleImpl() { + protected void setVisibleImpl(boolean visible) { if(visible) { ((Display)screen.getDisplay()).setFocus(this); } } - public void setSize(int width, int height) { + protected void setSizeImpl(int width, int height) { Screen screen = (Screen) getScreen(); if((x+width)>screen.getWidth()) { width=screen.getWidth()-x; @@ -91,18 +91,12 @@ public class Window extends com.jogamp.newt.Window { if((y+height)>screen.getHeight()) { height=screen.getHeight()-y; } - this.width = width; - this.height = height; - if(!fullscreen) { - nfs_width=width; - nfs_height=height; - } if(0!=surfaceHandle) { SetBounds0(surfaceHandle, screen.getWidth(), screen.getHeight(), x, y, width, height); } } - public void setPosition(int x, int y) { + protected void setPositionImpl(int x, int y) { Screen screen = (Screen) getScreen(); if((x+width)>screen.getWidth()) { x=screen.getWidth()-width; @@ -110,37 +104,14 @@ public class Window extends com.jogamp.newt.Window { if((y+height)>screen.getHeight()) { y=screen.getHeight()-height; } - this.x = x; - this.y = y; - if(!fullscreen) { - nfs_x=x; - nfs_y=y; - } if(0!=surfaceHandle) { SetBounds0(surfaceHandle, screen.getWidth(), screen.getHeight(), x, y, width, height); } } - public boolean setFullscreen(boolean fullscreen) { - if(this.fullscreen!=fullscreen) { - int x,y,w,h; - this.fullscreen=fullscreen; - if(fullscreen) { - x = 0; y = 0; - w = screen.getWidth(); - h = screen.getHeight(); - } else { - x = nfs_x; - y = nfs_y; - w = nfs_width; - h = nfs_height; - } - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - System.err.println("IntelGDL Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h); - } - if(0!=surfaceHandle) { - SetBounds0(surfaceHandle, screen.getWidth(), screen.getHeight(), x, y, w, h); - } + protected boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { + if(0!=surfaceHandle) { + SetBounds0(surfaceHandle, screen.getWidth(), screen.getHeight(), x, y, w, h); } return fullscreen; } 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 93c2b14bb..20a181096 100755 --- a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java @@ -153,12 +153,17 @@ public class MacWindow extends Window { public void run() { nsViewLock.lock(); try { - if(DEBUG_IMPLEMENTATION) System.out.println("MacWindow.CloseAction "+Thread.currentThread().getName()); + if(DEBUG_IMPLEMENTATION) { System.out.println("MacWindow.CloseAction "+Thread.currentThread().getName()); } if (windowHandle != 0) { close0(windowHandle); - windowHandle = 0; + } + } catch (Throwable t) { + if(DEBUG_IMPLEMENTATION) { + Exception e = new Exception("closeNative failed - "+Thread.currentThread().getName(), t); + e.printStackTrace(); } } finally { + windowHandle = 0; nsViewLock.unlock(); } } @@ -191,7 +196,7 @@ public class MacWindow extends Window { public void run() { nsViewLock.lock(); try { - createWindow(false); + createWindow(false, getX(), getY(), getWidth(), getHeight(), isFullscreen()); } finally { nsViewLock.unlock(); } @@ -229,30 +234,26 @@ public class MacWindow extends Window { nsViewLock.unlock(); } - class VisibleAction implements Runnable { - public void run() { - nsViewLock.lock(); - try { - if(DEBUG_IMPLEMENTATION) System.out.println("MacWindow.VisibleAction "+visible+" "+Thread.currentThread().getName()); - if (visible) { - createWindow(false); - if (windowHandle != 0) { - makeKeyAndOrderFront0(windowHandle); - } - } else { - if (windowHandle != 0) { - orderOut0(windowHandle); + protected void setVisibleImpl(final boolean visible) { + MainThread.invoke(true, new Runnable() { + public void run() { + nsViewLock.lock(); + try { + if (visible) { + createWindow(false, getX(), getY(), getWidth(), getHeight(), isFullscreen()); + if (windowHandle != 0) { + makeKeyAndOrderFront0(windowHandle); + } + } else { + if (windowHandle != 0) { + orderOut0(windowHandle); + } } + } finally { + nsViewLock.unlock(); } - } finally { - nsViewLock.unlock(); } - } - } - private VisibleAction visibleAction = new VisibleAction(); - - protected void setVisibleImpl() { - MainThread.invoke(true, visibleAction); + }); } class TitleAction implements Runnable { @@ -307,20 +308,9 @@ public class MacWindow extends Window { } private SizeAction sizeAction = new SizeAction(); - public void setSize(int width, int height) { - if (width != this.width || this.height != height) { - if(!fullscreen) { - nfs_width=width; - nfs_height=height; - if (0 != windowHandle) { - // this width/height will be set by sizeChanged, called by OSX - MainThread.invoke(true, sizeAction); - } else { - this.width=width; - this.height=height; - } - } - } + protected void setSizeImpl(int width, int height) { + // this width/height will be set by sizeChanged, called by OSX + MainThread.invoke(true, sizeAction); } class PositionAction implements Runnable { @@ -337,56 +327,28 @@ public class MacWindow extends Window { } private PositionAction positionAction = new PositionAction(); - public void setPosition(int x, int y) { - 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 positionChanged, called by OSX - MainThread.invoke(true, positionAction); - } else { - this.x=x; - this.y=y; - } - } - } + protected void setPositionImpl(int x, int y) { + // this x/y will be set by positionChanged, called by OSX + MainThread.invoke(true, positionAction); } - class FullscreenAction implements Runnable { - public void run() { - nsViewLock.lock(); - try { - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - System.err.println("MacWindow fs: "+fullscreen+" "+x+"/"+y+" "+width+"x"+height); - } - createWindow(true); - if (windowHandle != 0) { - makeKeyAndOrderFront0(windowHandle); + protected boolean setFullscreenImpl(final boolean fullscreen, final int x, final int y, final int w, final int h) { + MainThread.invoke(true, new Runnable() { + public void run() { + nsViewLock.lock(); + try { + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + System.err.println("MacWindow fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h); + } + createWindow(true, x, y, w, h, fullscreen); + if (windowHandle != 0) { + makeKeyAndOrderFront0(windowHandle); + } + } finally { + nsViewLock.unlock(); } - } finally { - nsViewLock.unlock(); } - } - } - private FullscreenAction fullscreenAction = new FullscreenAction(); - - public boolean setFullscreen(boolean fullscreen) { - if(this.fullscreen!=fullscreen) { - this.fullscreen=fullscreen; - if(fullscreen) { - x = 0; - y = 0; - width = screen.getWidth(); - height = screen.getHeight(); - } else { - x = nfs_x; - y = nfs_y; - width = nfs_width; - height = nfs_height; - } - MainThread.invoke(true, fullscreenAction); - } + }); return fullscreen; } @@ -538,7 +500,7 @@ public class MacWindow extends Window { super.sendKeyEvent(eventType, modifiers, key, keyChar); } - private void createWindow(boolean recreate) { + private void createWindow(boolean recreate, int x, int y, int width, int height, boolean fullscreen) { if(0!=windowHandle && !recreate) { return; } @@ -554,8 +516,8 @@ public class MacWindow extends Window { surfaceHandle = 0; } windowHandle = createWindow0(parentWindowHandle, - getX(), getY(), getWidth(), getHeight(), fullscreen, - (isUndecorated() ? + x, y, width, height, fullscreen, + (isUndecorated(fullscreen) ? NSBorderlessWindowMask : NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask), NSBackingStoreBuffered, 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 b25ed4ee8..7d3a0ac8c 100755 --- 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 @@ -70,32 +70,24 @@ public class Window extends com.jogamp.newt.Window { } } - protected void setVisibleImpl() { } + protected void setVisibleImpl(boolean visible) { } - public void setSize(int width, int height) { - System.err.println("setSize "+width+"x"+height+" n/a in BroadcomEGL"); - } - - void setSizeImpl(int width, int height) { + protected void setSizeImpl(int width, int height) { if(0!=windowHandle) { // n/a in BroadcomEGL System.err.println("BCEGL Window.setSizeImpl n/a in BroadcomEGL with realized window"); } else { - if(DEBUG_IMPLEMENTATION) { - Exception e = new Exception("BCEGL Window.setSizeImpl() "+this.width+"x"+this.height+" -> "+width+"x"+height); - e.printStackTrace(); - } this.width = width; this.height = height; } } - public void setPosition(int x, int y) { + protected void setPositionImpl(int x, int y) { // n/a in BroadcomEGL - System.err.println("setPosition n/a in BroadcomEGL"); + System.err.println("BCEGL Window.setPositionImpl n/a in BroadcomEGL"); } - public boolean setFullscreen(boolean fullscreen) { + protected boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { // n/a in BroadcomEGL System.err.println("setFullscreen n/a in BroadcomEGL"); return false; 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 f60abb7cd..54623996c 100755 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java @@ -85,30 +85,26 @@ public class KDWindow extends Window { } } - protected void setVisibleImpl() { + protected void setVisibleImpl(boolean visible) { setVisible0(eglWindowHandle, visible); - clearEventMask(); } - public void setSize(int width, int height) { + protected void setSizeImpl(int width, int height) { if(0!=eglWindowHandle) { setSize0(eglWindowHandle, width, height); } } - public void setPosition(int x, int y) { + protected void setPositionImpl(int x, int y) { // n/a in KD System.err.println("setPosition n/a in KD"); } - public boolean setFullscreen(boolean fullscreen) { - if(0!=eglWindowHandle && this.fullscreen!=fullscreen) { - this.fullscreen=fullscreen; - if(this.fullscreen) { - setFullScreen0(eglWindowHandle, true); - } else { - setFullScreen0(eglWindowHandle, false); - setSize0(eglWindowHandle, nfs_width, nfs_height); + protected boolean setFullscreenImpl(final boolean fullscreen, final int x, final int y, final int w, final int h) { + if(0!=eglWindowHandle) { + setFullScreen0(eglWindowHandle, fullscreen); + if(!fullscreen) { + setSize0(eglWindowHandle, w, h); } } return true; 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 dad3456d7..5e1b5a43c 100755 --- a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java @@ -131,13 +131,28 @@ public class WindowsWindow extends Window { protected void closeNative() { if (hdc != 0) { if(windowHandleClose != 0) { - ReleaseDC0(windowHandleClose, hdc); + try { + ReleaseDC0(windowHandleClose, hdc); + } catch (Throwable t) { + if(DEBUG_IMPLEMENTATION) { + Exception e = new Exception("closeNative failed - "+Thread.currentThread().getName(), t); + e.printStackTrace(); + } + } } hdc = 0; } if(windowHandleClose != 0) { - DestroyWindow0(windowHandleClose); - windowHandleClose = 0; + try { + DestroyWindow0(windowHandleClose); + } catch (Throwable t) { + if(DEBUG_IMPLEMENTATION) { + Exception e = new Exception("closeNative failed - "+Thread.currentThread().getName(), t); + e.printStackTrace(); + } + } finally { + windowHandleClose = 0; + } } } @@ -146,66 +161,32 @@ public class WindowsWindow extends Window { super.windowDestroyed(); } - protected void setVisibleImpl() { + protected void setVisibleImpl(boolean visible) { setVisible0(windowHandle, visible); } - // @Override - public void setSize(int width, int height) { - if (width != this.width || this.height != height) { - if(!fullscreen) { - nfs_width=width; - nfs_height=height; - if(0!=windowHandle) { - // this width/height will be set by sizeChanged, called by Windows - setSize0(parentWindowHandle, windowHandle, x, y, width, height); - } else { - this.width=width; - this.height=height; - } - } - } + protected void setSizeImpl(int width, int height) { + // this width/height will be set by sizeChanged, called by Windows + setSize0(parentWindowHandle, windowHandle, x, y, width, height); } - //@Override - public void setPosition(int x, int y) { - 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 positionChanged, called by Windows - setPosition0(parentWindowHandle, windowHandle, x , y /*, width, height*/); - } else { - this.x=x; - this.y=y; - } - } - } + protected void setPositionImpl(int x, int y) { + // this x/y will be set by positionChanged, called by Windows + setPosition0(parentWindowHandle, windowHandle, x , y /*, width, height*/); } - public boolean setFullscreen(boolean fullscreen) { - if(0!=windowHandle && (this.fullscreen!=fullscreen)) { - int x,y,w,h; - this.fullscreen=fullscreen; - if(fullscreen) { - x = 0; y = 0; - w = screen.getWidth(); - h = screen.getHeight(); - } else { - x = nfs_x; - y = nfs_y; - w = nfs_width; - h = nfs_height; - } - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - System.err.println("WindowsWindow fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h); - } - setFullscreen0(parentWindowHandle, windowHandle, x, y, w, h, undecorated, fullscreen); - } + protected boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { + setFullscreen0(fullscreen?0:parentWindowHandle, windowHandle, x, y, w, h, isUndecorated(fullscreen)); return fullscreen; } + protected boolean reparentWindowImpl() { + if(0!=windowHandle) { + reparentWindow0(fullscreen?0:parentWindowHandle, windowHandle, x, y, width, height, isUndecorated()); + } + return true; + } + // @Override public void requestFocus() { super.requestFocus(); @@ -245,7 +226,8 @@ public class WindowsWindow extends Window { 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 setFullscreen0(long parentWindowHandle, long windowHandle, int x, int y, int width, int height, boolean isUndecorated, boolean on); + private native void setFullscreen0(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 static native void setTitle0(long windowHandle, String title); private static native void requestFocus0(long windowHandle); 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 085d1cab7..a51eee241 100755 --- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java @@ -55,13 +55,12 @@ public class X11Window extends Window { if (config == null) { throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } - attachedToParent = 0 != parentWindowHandle ; X11GraphicsConfiguration x11config = (X11GraphicsConfiguration) config; long visualID = x11config.getVisualID(); long w = CreateWindow0(parentWindowHandle, display.getHandle(), screen.getIndex(), visualID, display.getJavaObjectAtom(), display.getWindowDeleteAtom(), - x, y, width, height, undecorated()); + x, y, width, height, isUndecorated()); if (w == 0 || w!=windowHandle) { throw new NativeWindowException("Error creating window: "+w); } @@ -72,9 +71,17 @@ public class X11Window extends Window { protected void closeNative() { if(0!=displayHandleClose && 0!=windowHandleClose && null!=getScreen() ) { X11Display display = (X11Display) getScreen().getDisplay(); - CloseWindow0(displayHandleClose, windowHandleClose, display.getJavaObjectAtom()); - windowHandleClose = 0; - displayHandleClose = 0; + try { + CloseWindow0(displayHandleClose, windowHandleClose, display.getJavaObjectAtom()); + } catch (Throwable t) { + if(DEBUG_IMPLEMENTATION) { + Exception e = new Exception("closeNative failed - "+Thread.currentThread().getName(), t); + e.printStackTrace(); + } + } finally { + windowHandleClose = 0; + displayHandleClose = 0; + } } } @@ -84,72 +91,33 @@ public class X11Window extends Window { super.windowDestroyed(); } - protected void setVisibleImpl() { + protected void setVisibleImpl(boolean visible) { setVisible0(getDisplayHandle(), windowHandle, visible); - clearEventMask(); } - public void setSize(int width, int height) { - if(DEBUG_IMPLEMENTATION) { - System.err.println("X11Window setSize: "+this.width+"x"+this.height+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+windowHandle); - } - if (width != this.width || this.height != height) { - if(!fullscreen) { - nfs_width=width; - nfs_height=height; - if(0!=windowHandle) { - // this width/height will be set by windowChanged, called by X11 - setSize0(getDisplayHandle(), windowHandle, width, height); - } else { - this.width = width; - this.height = height; - } - } - } + protected void setSizeImpl(int width, int height) { + // this width/height will be set by windowChanged, called by X11 + setSize0(getDisplayHandle(), windowHandle, width, height); } - public void setPosition(int x, int y) { - if(DEBUG_IMPLEMENTATION) { - System.err.println("X11Window setPosition: "+this.x+"/"+this.y+" -> "+x+"/"+y+", fs "+fullscreen+", windowHandle "+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 - setPosition0(parentWindowHandle, getDisplayHandle(), windowHandle, x, y); - } else { - this.x = x; - this.y = y; - } - } - } + protected void setPositionImpl(int x, int y) { + // this x/y will be set by windowChanged, called by X11 + setPosition0(parentWindowHandle, getDisplayHandle(), windowHandle, x, y); } - public boolean setFullscreen(boolean fullscreen) { - if(0!=windowHandle && this.fullscreen!=fullscreen) { - int x,y,w,h; - this.fullscreen=fullscreen; - if(fullscreen) { - x = 0; y = 0; - w = screen.getWidth(); - h = screen.getHeight(); - } 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+", "+undecorated()); - } - setPosSizeDecor0(fullscreen?0:parentWindowHandle, getDisplayHandle(), getScreenIndex(), windowHandle, x, y, w, h, undecorated()); - } + protected boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { + setPosSizeDecor0(fullscreen?0:parentWindowHandle, getDisplayHandle(), getScreenIndex(), windowHandle, x, y, w, h, isUndecorated(fullscreen)); return fullscreen; } - final boolean undecorated() { return attachedToParent || undecorated || fullscreen ; } + protected boolean reparentWindowImpl() { + if(0!=windowHandle) { + reparentWindow0(fullscreen?0:parentWindowHandle, getDisplayHandle(), getScreenIndex(), windowHandle, x, y, isUndecorated()); + // X11 reparent unmaps the window + setVisibleImpl(visible); + } + return true; + } // @Override public void requestFocus() { @@ -187,6 +155,8 @@ public class X11Window extends Window { private native void setTitle0(long display, long windowHandle, String title); private native void requestFocus0(long display, long windowHandle); 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); private void windowChanged(int newX, int newY, int newWidth, int newHeight) { if(width != newWidth || height != newHeight) { @@ -226,14 +196,17 @@ public class X11Window extends Window { } } + /** + * @param focusGained + */ + private void visibleChanged(boolean visible) { + // FIXME .. this.visible = visible ; + } + private void windowCreated(long windowHandle) { this.windowHandle = windowHandle; } private long windowHandleClose; private long displayHandleClose; - private boolean attachedToParent; - - // non fullscreen dimensions .. - private int nfs_width, nfs_height, nfs_x, nfs_y; } diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index b5d55aebd..2bb28466c 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -35,6 +35,7 @@ package com.jogamp.newt.opengl; import com.jogamp.newt.*; import com.jogamp.newt.event.*; +import com.jogamp.nativewindow.impl.RecursiveToolkitLock; import javax.media.nativewindow.*; import javax.media.opengl.*; import com.jogamp.opengl.impl.GLDrawableHelper; @@ -53,19 +54,15 @@ import java.util.*; *

*/ public class GLWindow extends Window implements GLAutoDrawable { - private static List/*GLWindow*/ glwindows = new ArrayList(); - - private boolean ownerOfWinScrDpy; private Window window; private boolean runPumpMessages; /** * Constructor. Do not call this directly -- use {@link #create()} instead. */ - protected GLWindow(Window window, boolean ownerOfWinScrDpy) { - this.ownerOfWinScrDpy = ownerOfWinScrDpy; + protected GLWindow(Window window) { this.window = window; - this.window.setAutoDrawableClient(true); + this.window.setHandleDestroyNotify(false); this.runPumpMessages = ( null == getScreen().getDisplay().getEDTUtil() ) ; window.addWindowListener(new WindowAdapter() { public void windowResized(WindowEvent e) { @@ -76,10 +73,6 @@ public class GLWindow extends Window implements GLAutoDrawable { sendDestroy = true; } }); - - List newglw = (List) ((ArrayList) glwindows).clone(); - newglw.add(this); - glwindows=newglw; } /** Creates a new GLWindow attaching the given window - not owning the Window. */ @@ -87,10 +80,10 @@ public class GLWindow extends Window implements GLAutoDrawable { return create(null, window, null, false); } - /** Creates a new GLWindow attaching a new native child Window of the given parentWindowObject + /** Creates a new GLWindow attaching a new native child Window of the given parentNativeWindow with the given GLCapabilities - owning the Window */ - public static GLWindow create(Object parentWindowObject, GLCapabilities caps) { - return create(parentWindowObject, null, caps, true); + public static GLWindow create(NativeWindow parentNativeWindow, GLCapabilities caps) { + return create(parentNativeWindow, null, caps, false); } /** Creates a new GLWindow attaching a new decorated Window on the local display, screen 0, with a @@ -106,27 +99,29 @@ public class GLWindow extends Window implements GLAutoDrawable { } /** Either or: window (prio), or caps and undecorated (2nd choice) */ - private static GLWindow create(Object parentWindowObject, Window window, + private static GLWindow create(NativeWindow parentNativeWindow, Window window, GLCapabilities caps, boolean undecorated) { - boolean ownerOfWinScrDpy=false; if (window == null) { if (caps == null) { caps = new GLCapabilities(null); // default .. } - ownerOfWinScrDpy = true; - window = NewtFactory.createWindow(parentWindowObject, caps, undecorated); + window = NewtFactory.createWindow(parentNativeWindow, caps, undecorated); } - return new GLWindow(window, ownerOfWinScrDpy); + return new GLWindow(window); } + public boolean isNativeWindowValid() { + return (null!=window)?window.isNativeWindowValid():false; + } + public boolean isDestroyed() { - return null == window ; + return (null!=window)?window.isDestroyed():true; } - public Window getWindow() { - return window; + public Window getInnerWindow() { + return window.getInnerWindow(); } /** @@ -162,67 +157,66 @@ public class GLWindow extends Window implements GLAutoDrawable { shouldNotCallThis(); } - protected void dispose(boolean regenerate, boolean sendEvent) { + protected void dispose() { if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) { - Exception e1 = new Exception("GLWindow.dispose("+regenerate+") "+Thread.currentThread()+", 1"); + Exception e1 = new Exception("GLWindow.dispose() "+Thread.currentThread()+", start: "+this); e1.printStackTrace(); } - if(sendEvent) { - sendDisposeEvent(); + if ( null != context && null != drawable && drawable.isRealized() ) { + helper.invokeGL(drawable, context, disposeAction, null); } if (context != null) { context.destroy(); + context = null; } if (drawable != null) { drawable.setRealized(false); - } - - if(regenerate) { - if(null==window) { - throw new GLException("GLWindow.dispose(true): null window"); - } - - // recreate GLDrawable, to reflect the new graphics configurations - NativeWindow nw; - if (window.getWrappedWindow() != null) { - nw = NativeWindowFactory.getNativeWindow(window.getWrappedWindow(), window.getGraphicsConfiguration()); - } else { - nw = window; - } - drawable = factory.createGLDrawable(nw); - drawable.setRealized(true); - context = drawable.createContext(null); - sendReshape = true; // ensure a reshape event is send .. + drawable = null; } if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) { - System.out.println("GLWindow.dispose("+regenerate+") "+Thread.currentThread()+", fin: "+this); + System.out.println("GLWindow.dispose() "+Thread.currentThread()+", fin: "+this); } } - public synchronized void destroy() { - destroy(true); - } - - /** @param sendDisposeEvent should be false in a [time,reliable] critical shutdown */ - public synchronized void destroy(boolean sendDisposeEvent) { - List newglw = (List) ((ArrayList) glwindows).clone(); - newglw.remove(this); - glwindows=newglw; + class DestroyAction implements Runnable { + boolean deep; + public DestroyAction(boolean deep) { + this.deep = deep; + } + public void run() { + windowLock(); + try { + if(null==window || window.isDestroyed()) { + return; // nop + } + dispose(); - dispose(false, sendDisposeEvent); + if(null!=window) { + window.destroy(deep); + } - if(null!=window) { - if(ownerOfWinScrDpy) { - window.destroy(true); + if(deep) { + helper=null; + } + } finally { + windowUnlock(); } } + } - drawable = null; - context = null; - window = null; + /** + * @param deep If true, all resources, ie listeners, parent handles, size, position + * and the referenced NEWT screen and display, will be destroyed as well. Be aware that if you call + * this method with deep = true, you will not be able to regenerate the Window. + * @see #destroy() + */ + public void destroy(boolean deep) { + if(!isDestroyed()) { + runOnEDTIfAvail(true, new DestroyAction(deep)); + } } public boolean getPerfLogEnabled() { return perfLog; } @@ -231,28 +225,61 @@ public class GLWindow extends Window implements GLAutoDrawable { perfLog = v; } - protected void setVisibleImpl() { + protected void setVisibleImpl(boolean visible) { shouldNotCallThis(); } - public void setVisible(final boolean visible) { - window.setVisible(visible); - if (visible && null == context && 0 != window.getWindowHandle()) { - NativeWindow nw; - if (window.getWrappedWindow() != null) { - nw = NativeWindowFactory.getNativeWindow(window.getWrappedWindow(), window.getGraphicsConfiguration()); - } else { - nw = window; + public void reparentWindow(NativeWindow newParent, Screen newScreen) { + window.reparentWindow(newParent, newScreen); + } + + class VisibleAction implements Runnable { + boolean visible; + public VisibleAction(boolean visible) { + this.visible = visible; + } + public void run() { + windowLock(); + try{ + window.setVisible(visible); + if (null == context && visible && 0 != window.getWindowHandle() && 0 %d/%d\n", + visibleRect.origin.x, + visibleRect.origin.y, + visibleRect.size.width, + visibleRect.size.height, + viewRect.origin.x, + viewRect.origin.y, + viewRect.size.width, + viewRect.size.height, + x, y); + } pt = NSMakePoint(visibleRect.origin.x + x, visibleRect.origin.y + visibleRect.size.height - y - d_pty); @@ -167,8 +180,6 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_macosx_MacDisplay_dispatchMessa NS_DURING - NSWindow* win = NULL; - NewtView* view = NULL; int num_events = 0; // Periodically take a break @@ -287,7 +298,17 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_macosx_MacWindow_createWindow0 backing: (NSBackingStoreType) bufferingType screen: screen] retain]; - NSWindow* parentWindow = (NSWindow*) ((intptr_t) parent); + NSObject *nsParentObj = (NSObject*) ((intptr_t) parent); + NSWindow* parentWindow = NULL; + if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSWindow class]] ) { + parentWindow = (NSWindow*) nsParentObj; + } else if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSView class]] ) { + NSView* view = (NSView*) nsParentObj; + parentWindow = [view window]; + fprintf(stderr, "createWindow0 - Parent is NSView : %p -> %p (win) \n", nsParentObj, parentWindow); + } else { + fprintf(stderr, "createWindow0 - Parent is neither NSWindow nor NSView : %p\n", nsParentObj); + } if(NULL!=parentWindow) { [parentWindow addChildWindow: window ordered: NSWindowAbove]; [window setParentWindow: parentWindow]; @@ -448,7 +469,7 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_macosx_MacWindow_changeContent [pool release]; - return oldView; + return (jlong) ((intptr_t) oldView); } /* diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index fabcab1c7..37fd9c621 100755 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -1034,7 +1034,7 @@ JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_windows_WindowsScreen_getHeight /* * Class: com_jogamp_newt_impl_windows_WindowsWindow - * Method: initIDs + * Method: initIDs0 * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_initIDs0 @@ -1282,10 +1282,10 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setPositi /* * Class: com_jogamp_newt_impl_windows_WindowsWindow * Method: setFullscreen - * Signature: (JIIIIZZ)V + * Signature: (JIIIIZ)V */ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setFullscreen0 - (JNIEnv *env, jobject obj, jlong parent, jlong window, jint x, jint y, jint width, jint height, jboolean bIsUndecorated, jboolean on) + (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; @@ -1293,10 +1293,55 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setFullsc HWND hWndInsertAfter; DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE; - if ( JNI_TRUE == on ) { - hwndP = NULL; // full-screen is top level + // order of call sequence: (MS documentation) + // SetParent(.., NULL), SetWindowLong ( WS_POPUP ) + // SetParent(.., PARENT), SetWindowLong ( WS_CHILD ) + if ( NULL == hwndP ) { + SetParent(hwnd, NULL); + } + + if(NULL!=hwndP) { + windowStyle |= WS_CHILD ; + } else if (bIsUndecorated) { + windowStyle |= WS_POPUP | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX; + } else { + windowStyle |= WS_OVERLAPPEDWINDOW; + } + SetWindowLong(hwnd, GWL_STYLE, windowStyle); + + if ( NULL != hwndP ) { + SetParent(hwnd, hwndP ); + } + + 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); + + NewtWindows_requestFocus ( hwnd ); + + (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height); +} + +/* + * 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) +{ + UINT flags; + HWND hwndP = (HWND) (intptr_t) parent; + HWND hwnd = (HWND) (intptr_t) window; + HWND hWndInsertAfter; + DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE; + // order of call sequence: (MS documentation) // SetParent(.., NULL), SetWindowLong ( WS_POPUP ) // SetParent(.., PARENT), SetWindowLong ( WS_CHILD ) @@ -1306,7 +1351,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setFullsc if(NULL!=hwndP) { windowStyle |= WS_CHILD ; - } else if (bIsUndecorated || on) { + } else if (bIsUndecorated) { windowStyle |= WS_POPUP | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX; } else { windowStyle |= WS_OVERLAPPEDWINDOW; @@ -1317,7 +1362,8 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setFullsc SetParent(hwnd, hwndP ); } - if(on==JNI_TRUE) { + /** + if ( NULL == hwndP ) { flags = SWP_SHOWWINDOW; hWndInsertAfter = HWND_TOPMOST; } else { @@ -1326,10 +1372,11 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setFullsc } SetWindowPos(hwnd, hWndInsertAfter, x, y, width, height, flags); + */ NewtWindows_requestFocus ( hwnd ); - (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height); + // (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height); } /* diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index abaa3594f..f77f54cd1 100755 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -69,6 +69,7 @@ #define DBG_PRINT6(str, arg1, arg2, arg3, arg4, arg5, arg6) fprintf(stderr, str, arg1, arg2, arg3, arg4, arg5, arg6); #define DBG_PRINT7(str, arg1, arg2, arg3, arg4, arg5, arg6, arg7) fprintf(stderr, str, arg1, arg2, arg3, arg4, arg5, arg6, arg7); #define DBG_PRINT8(str, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) fprintf(stderr, str, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + #define DBG_PRINT9(str, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) fprintf(stderr, str, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); #define DUMP_VISUAL_INFO(a,b) _dumpVisualInfo((a),(b)) @@ -105,6 +106,7 @@ #define DBG_PRINT6(str, arg1, arg2, arg3, arg4, arg5, arg6) #define DBG_PRINT7(str, arg1, arg2, arg3, arg4, arg5, arg6, arg7) #define DBG_PRINT8(str, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) + #define DBG_PRINT9(str, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) #define DUMP_VISUAL_INFO(a,b) @@ -173,6 +175,7 @@ static jclass newtWindowClz=NULL; static jmethodID windowChangedID = NULL; static jmethodID focusChangedID = NULL; +static jmethodID visibleChangedID = NULL; static jmethodID windowDestroyNotifyID = NULL; static jmethodID windowDestroyedID = NULL; static jmethodID windowCreatedID = NULL; @@ -312,6 +315,13 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_CompleteDisplay0 (*env)->CallVoidMethod(env, obj, displayCompletedID, javaObjectAtom, windowDeleteAtom); } +/** + * Window + */ + +// #define WINDOW_EVENT_MASK ( FocusChangeMask | StructureNotifyMask | ExposureMask | VisibilityNotify ) +#define WINDOW_EVENT_MASK ( FocusChangeMask | StructureNotifyMask | VisibilityNotify ) + static int putPtrIn32Long(unsigned long * dst, uintptr_t src) { int i=0; dst[i++] = (unsigned long) ( ( src >> 0 ) & 0xFFFFFFFF ) ; @@ -344,7 +354,7 @@ static void setJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlon (unsigned char *)&jogl_java_object_data, nitems_32); } -static jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom) { +static jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning) { Atom actual_type_return; int actual_format_return; int nitems_32 = ( sizeof(uintptr_t) == 8 ) ? 2 : 1 ; @@ -362,14 +372,18 @@ static jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, j &nitems_return, &bytes_after_return, &jogl_java_object_data_pp); if ( Success != res ) { - fprintf(stderr, "Warning: NEWT X11Window: Could not fetch Atom JOGL_JAVA_OBJECT window property (res %d) nitems_return %ld, bytes_after_return %ld, result 0!\n", res, nitems_return, bytes_after_return); + if(True==showWarning) { + fprintf(stderr, "Warning: NEWT X11Window: Could not fetch Atom JOGL_JAVA_OBJECT window property (res %d) nitems_return %ld, bytes_after_return %ld, result 0!\n", res, nitems_return, bytes_after_return); + } return NULL; } if(actual_type_return!=(Atom)javaObjectAtom || nitems_returnmap_state == IsViewable) { XSetInputFocus(dpy, w, RevertToParent, CurrentTime); - XSync(dpy, False); } +} + +static void NewtWindows_requestFocus1 (Display *dpy, Window w) { + XWindowAttributes xwa; + + XLockDisplay(dpy) ; + + XGetWindowAttributes(dpy, w, &xwa); + NewtWindows_requestFocus0 (dpy, w, &xwa); + XSync(dpy, False); XUnlockDisplay(dpy) ; } -/** changing this attribute while a window is established, - * didn't impact the decoration - only at window creation time. -static void NewtWindows_setOverrideRedirect (Display *dpy, Window w, Bool val) { +/** + * 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; - memset(&xswa, 0, sizeof(XSetWindowAttributes)); - xswa.override_redirect = val; - XChangeWindowAttributes(dpy, w, CWOverrideRedirect, &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 @@ -469,18 +504,26 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_DispatchMessages return ; } + DBG_PRINT3( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, evt.type); + displayDispatchErrorHandlerEnable(1, env); - jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom); + jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom, + #ifdef VERBOSE_ON + True + #else + False + #endif + ); displayDispatchErrorHandlerEnable(0, env); if(NULL==jwindow) { - fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for invalid X11 window %p\n", + fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n", (void*)dpy, evt.type, (void*)evt.xany.window); + XUnlockDisplay(dpy) ; - // DBG_PRINT1( "X11: DispatchMessages 0x%X - Leave 2\n", dpy); - return; + continue; } switch(evt.type) { @@ -497,11 +540,10 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_DispatchMessages } XUnlockDisplay(dpy) ; - // DBG_PRINT3( "X11: DispatchMessages 0x%X - Window %p, Event %d\n", dpy, jwindow, evt.type); switch(evt.type) { case ButtonPress: - NewtWindows_requestFocus ( dpy, evt.xany.window ); + NewtWindows_requestFocus1 ( dpy, evt.xany.window ); (*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*/); @@ -565,6 +607,16 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_DispatchMessages (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE); break; + case MapNotify: + DBG_PRINT1( "X11: event . MapNotify call 0x%X\n", (unsigned int)evt.xunmap.window); + // FIXME (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_TRUE); + break; + + case UnmapNotify: + DBG_PRINT1( "X11: event . UnmapNotify call 0x%X\n", (unsigned int)evt.xunmap.window); + // FIXME (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE); + break; + // unhandled events .. yet .. case VisibilityNotify: @@ -574,9 +626,6 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_DispatchMessages DBG_PRINT1( "X11: event . Expose call 0x%X\n", (unsigned int)evt.xexpose.window); /* FIXME: Might want to send a repaint event .. */ break; - case UnmapNotify: - DBG_PRINT1( "X11: event . UnmapNotify call 0x%X\n", (unsigned int)evt.xunmap.window); - break; default: DBG_PRINT3("X11: event . unhandled %d 0x%X call 0x%X\n", evt.type, evt.type, (unsigned int)evt.xunmap.window); } @@ -644,6 +693,7 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_x11_X11Window_initIDs0 { windowChangedID = (*env)->GetMethodID(env, clazz, "windowChanged", "(IIII)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"); windowCreatedID = (*env)->GetMethodID(env, clazz, "windowCreated", "(J)V"); @@ -652,6 +702,7 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_x11_X11Window_initIDs0 if (windowChangedID == NULL || focusChangedID == NULL || + visibleChangedID == NULL || windowDestroyNotifyID == NULL || windowDestroyedID == NULL || windowCreatedID == NULL || @@ -691,8 +742,6 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CreateWindow0 Screen* scrn; Atom wm_delete_atom; - DBG_PRINT5( "X11: CreateWindow %x/%d %dx%d, undeco %d\n", x, y, width, height, undecorated); - if(dpy==NULL) { _FatalError(env, "invalid display connection.."); } @@ -707,6 +756,11 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CreateWindow0 XSync(dpy, False); scrn = ScreenOfDisplay(dpy, scrn_idx); + if(0==windowParent) { + windowParent = XRootWindowOfScreen(scrn); + } + DBG_PRINT7( "X11: CreateWindow dpy %p, parent %p, %x/%d %dx%d, undeco %d\n", + (void*)dpy, (void*)windowParent, x, y, width, height, undecorated); // try given VisualID on screen memset(&visualTemplate, 0, sizeof(XVisualInfo)); @@ -721,8 +775,8 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CreateWindow0 XFree(pVisualQuery); pVisualQuery=NULL; } - DBG_PRINT5( "X11: [CreateWindow] trying given (dpy %p, screen %d, visualID: %d, parent 0x%X) found: %p\n", - dpy, scrn_idx, (int)visualID, (unsigned int)windowParent, visual); + DBG_PRINT5( "X11: [CreateWindow] trying given (dpy %p, screen %d, visualID: %d, parent %p) found: %p\n", + dpy, scrn_idx, (int)visualID, (void*)windowParent, visual); if (visual==NULL) { @@ -735,17 +789,12 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CreateWindow0 pVisualQuery=NULL; } - if(0==windowParent) { - windowParent = XRootWindowOfScreen(scrn); - } - - attrMask = ( CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect ) ; + attrMask = ( CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect ) ; memset(&xswa, 0, sizeof(xswa)); - xswa.override_redirect = ( JNI_TRUE == undecorated || 0 != parent ) ? True : False ; + xswa.override_redirect = ( 0 != parent ) ? True : False ; xswa.border_pixel = 0; xswa.background_pixel = 0; - xswa.event_mask = FocusChangeMask | ExposureMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask; xswa.colormap = XCreateColormap(dpy, windowParent, // XRootWindow(dpy, scrn_idx), visual, @@ -778,10 +827,12 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CreateWindow0 long xevent_mask = 0; xevent_mask |= ButtonPressMask | ButtonReleaseMask | PointerMotionMask; xevent_mask |= KeyPressMask | KeyReleaseMask; - xevent_mask |= FocusChangeMask | ExposureMask | StructureNotifyMask | VisibilityNotify ; + xevent_mask |= WINDOW_EVENT_MASK ; XSelectInput(dpy, window, xevent_mask); } + NewtWindows_setDecorations (dpy, window, ( JNI_TRUE == undecorated ) ? False : True ); + XSync(dpy, False); XUnlockDisplay(dpy) ; @@ -808,7 +859,9 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CloseWindow0 } XLockDisplay(dpy) ; - jwindow = getJavaWindowProperty(env, dpy, w, javaObjectAtom); + DBG_PRINT2( "X11: CloseWindow START dpy %p, win %p\n", (void*)dpy, (void*)w); + + jwindow = getJavaWindowProperty(env, dpy, w, javaObjectAtom, True); if(NULL==jwindow) { _throwNewRuntimeException(dpy, env, "could not fetch Java Window object, bail out!"); return; @@ -825,6 +878,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CloseWindow0 XDestroyWindow(dpy, w); XSync(dpy, False); + DBG_PRINT0( "X11: CloseWindow END\n"); XUnlockDisplay(dpy) ; (*env)->CallVoidMethod(env, obj, windowDestroyedID); @@ -884,10 +938,65 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_setSize0 XUnlockDisplay(dpy) ; } +/* + * Class: com_jogamp_newt_impl_x11_X11Window + * Method: setPosition0 + * Signature: (JJII)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) +{ + Display * dpy = (Display *) (intptr_t) display; + Window w = (Window)window; + XWindowChanges xwc; + + DBG_PRINT2( "X11: setPos0 . XConfigureWindow %d/%d\n", x, y); + if(dpy==NULL) { + _FatalError(env, "invalid display connection.."); + } + XLockDisplay(dpy) ; + + memset(&xwc, 0, sizeof(XWindowChanges)); + xwc.x=x; + xwc.y=y; + XConfigureWindow(dpy, w, CWX|CWY, &xwc); + XSync(dpy, False); + + XUnlockDisplay(dpy) ; +} + +static void NewtWindows_reparentWindow + (Display * dpy, Screen * scrn, Window w, XWindowAttributes *xwa, jlong jparent, jint x, jint y, jboolean undecorated) +{ + Window parent = (0!=jparent)?(Window)jparent:XRootWindowOfScreen(scrn); + + DBG_PRINT7( "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); + + // let parent ignore reparent request + NewtWindows_setOverrideRedirect0 (dpy, w, xwa, True); + if(JNI_TRUE == undecorated) { + NewtWindows_setDecorations (dpy, w, False); + } + XSync(dpy, False); + + XReparentWindow( dpy, w, parent, x, y ); + XRaiseWindow(dpy, w); + XSync(dpy, False); + + NewtWindows_setOverrideRedirect0 (dpy, w, xwa, ( 0 != jparent ) ? True : False ); + if(JNI_FALSE == undecorated) { + NewtWindows_setDecorations (dpy, w, True); + } + XSync(dpy, False); + + DBG_PRINT0( "X11: reparentWindow X\n"); +} + /* * Class: com_jogamp_newt_impl_x11_X11Window * Method: setPosSizeDecor0 - * Signature: (JIJIIIIIZ)V + * Signature: (JJIJIIIIZ)V */ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_setPosSizeDecor0 (JNIEnv *env, jobject obj, jlong jparent, jlong display, jint screen_index, jlong window, @@ -896,23 +1005,22 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_setPosSizeDecor0 Display * dpy = (Display *) (intptr_t) display; Window w = (Window)window; Screen * scrn = ScreenOfDisplay(dpy, (int)screen_index); - Window parent = (0!=jparent)?(Window)jparent:XRootWindowOfScreen(scrn); XWindowChanges xwc; + XWindowAttributes xwa; - DBG_PRINT5( "X11: setPosSizeDecor0 %d/%d %dx%d, undec %d\n", x, y, width, height, undecorated); + DBG_PRINT8( "X11: setPosSizeDecor0 dpy %p, parent %p, win %p, %d/%d %dx%d undec %d\n", + (void*)dpy, (void*) jparent, (void*)w, x, y, width, height, undecorated); if(dpy==NULL) { _FatalError(env, "invalid display connection.."); } XLockDisplay(dpy) ; - // we need to reparent the window, - // to allow a child window to go fullscreen and back. - XReparentWindow( dpy, w, parent, x, y ); - XRaiseWindow(dpy, w); + XSync(dpy, False); + XGetWindowAttributes(dpy, w, &xwa); - NewtWindows_setDecorations (dpy, w, ( JNI_TRUE == undecorated ) ? False : True ); + NewtWindows_reparentWindow(dpy, scrn, w, &xwa, jparent, x, y, undecorated); memset(&xwc, 0, sizeof(XWindowChanges)); xwc.x=x; @@ -922,35 +1030,39 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_setPosSizeDecor0 XConfigureWindow(dpy, w, CWX|CWY|CWWidth|CWHeight, &xwc); XSync(dpy, False); - NewtWindows_requestFocus ( dpy, w ); + NewtWindows_requestFocus0 ( dpy, w, &xwa ); + XSync(dpy, False); XUnlockDisplay(dpy) ; } /* * Class: com_jogamp_newt_impl_x11_X11Window - * Method: setPosition0 - * Signature: (JJII)V + * Method: reparentWindow0 + * Signature: (JJIJIIZ)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_reparentWindow0 + (JNIEnv *env, jobject obj, jlong jparent, jlong display, jint screen_index, jlong window, jint x, jint y, jboolean undecorated) { Display * dpy = (Display *) (intptr_t) display; Window w = (Window)window; - XWindowChanges xwc; + Screen * scrn = ScreenOfDisplay(dpy, (int)screen_index); + XWindowAttributes xwa; + + DBG_PRINT6( "X11: reparentWindow0 dpy %p, parent %p, win %p, %d/%d undec %d\n", + (void*)dpy, (void*) jparent, (void*)w, x, y, undecorated); - DBG_PRINT2( "X11: setPos0 . XConfigureWindow %d/%d\n", x, y); if(dpy==NULL) { _FatalError(env, "invalid display connection.."); } XLockDisplay(dpy) ; - memset(&xwc, 0, sizeof(XWindowChanges)); - xwc.x=x; - xwc.y=y; - XConfigureWindow(dpy, w, CWX|CWY, &xwc); XSync(dpy, False); + XGetWindowAttributes(dpy, w, &xwa); + + NewtWindows_reparentWindow(dpy, scrn, w, &xwa, jparent, x, y, undecorated); XUnlockDisplay(dpy) ; + DBG_PRINT0( "X11: reparentWindow0 X\n"); } /* -- cgit v1.2.3