diff options
author | Sven Gothel <[email protected]> | 2010-05-28 16:53:08 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2010-05-28 16:53:08 +0200 |
commit | 811bd23ed37e392abb349f850a0b1dac635d021e (patch) | |
tree | c4faf8f5728eabd0fd9ed8a28816ab361984a9b7 /src/newt/classes/com/jogamp | |
parent | c787f50d77e2491eb0d8201d534a6fa4885a929e (diff) |
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
Diffstat (limited to 'src/newt/classes/com/jogamp')
20 files changed, 1212 insertions, 751 deletions
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.<br> - * The Screen and Display information is regenrated utilizing the parents information.<br> + * The Screen and Display information is regenerated utilizing the parents information.<br> * <p> - * In case <code>parentWindowObject</code> is a {@link javax.media.nativewindow.NativeWindow},<br> - * 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)}<br></p>. - * <p> - * In case <code>parentWindowObject</code> is even a {@link com.jogamp.newt.Window}, the following applies:<br> - * {@link com.jogamp.newt.event.WindowEvent#EVENT_WINDOW_RESIZED} is not propagated to the child window for e.g. layout<br>, + * In case <code>parentWindowObject</code> is a {@link com.jogamp.newt.Window} instance,<br> + * the new window is added to it's list of children.<br> + * This assures proper handling of visibility, creation and destruction.<br> + * {@link com.jogamp.newt.event.WindowEvent#EVENT_WINDOW_RESIZED} is not propagated to the child window for layout<br>, * you have to add an appropriate {@link com.jogamp.newt.event.WindowListener} for this use case.<br> - * However, {@link com.jogamp.newt.event.WindowEvent#EVENT_WINDOW_DESTROY_NOTIFY} is propagated to the child window, so it will be closed properly.<br> * The parents visibility is passed to the new Window<br></p> * <p> * In case <code>parentWindowObject</code> is a different {@link javax.media.nativewindow.NativeWindow} implementation,<br> * you have to handle all events appropriatly.<br></p> * <p> - * In case <code>parentWindowObject</code> is a {@link java.awt.Component},<br> - * we utilize the {@link com.jogamp.newt.impl.awt.AWTNewtFactory#createNativeChildWindow(Object, com.jogamp.newt.Capabilities, boolean)} - * factory method.<br> - * 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.<br> - * The parents visibility is passed to the new Window<br></p> * - * @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<br> * @@ -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() { + /** + * <p> + * destroys the window and children and releases + * windowing related resources.<br></p> + * <p> + * all other resources and states are kept intact, + * ie listeners, parent handles and size, position etc.<br></p> + * + * @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)); } } + /** + * <p> + * render all native window information invalid, + * as if the native window was destroyed.<br></p> + * <p> + * all other resources and states are kept intact, + * ie listeners, parent handles and size, position etc.<br></p> + * + * @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.<br> + 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.<br> + * 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.<br> + * <P> + * In case the old parent is not null and a Window, + * this window is removed from it's list of children.<br> + * In case the new parent is not null and a Window, + * this window is added to it's list of children.<br></P> + * + * @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( 0<width*height ) { + createNative(); + } + } else if(Window.this.visible != visible) { + Window.this.visible = visible; + if(0 != windowHandle) { + setVisibleImpl(visible); + } + } + if(0!=windowHandle && visible && listeners.size()>0) { + 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(); + } } } /** * <p> - * <code>setVisible</code> makes the window visible if <code>visible</code> is true, - * otherwise the window becomes invisible.<br></p> + * <code>setVisible</code> makes the window and children visible if <code>visible</code> is true, + * otherwise the window and children becomes invisible.<br></p> * <p> * The <code>setVisible(true)</code> is responsible to actual create the native window.<br></p> * <p> + * Zero size semantics are respected, see {@link #setSize(int,int)}:<br> + * <pre> + * if ( 0 == windowHandle && visible ) { + * this.visible = visible; + * if( 0<width*height ) { + * createNative(); + * } + * } else if ( this.visible != visible ) { + * this.visible = visible; + * setNativeSizeImpl(); + * } + * </pre></p> + * <p> * In case this window is a child window and a parent {@link javax.media.nativewindow.NativeWindow} is being used,<br> * the parent's {@link javax.media.nativewindow.NativeWindow} handle is retrieved via {@link javax.media.nativewindow.NativeWindow#getWindowHandle()}.<br> * If this action fails, ie if the parent {@link javax.media.nativewindow.NativeWindow} is not valid yet,<br> * no native window is created yet and <code>setVisible(true)</code> shall be repeated when it is.<br></p> */ - 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}<br> - * - * This call is ignored if in fullscreen mode.<br> + * <p> + * Zero size semantics are respected, see {@link #setVisible(boolean)}:<br> + * <pre> + * if ( 0 != windowHandle && 0>=width*height && visible ) { + * setVisible(false); + * } else if ( 0 == windowHandle && 0<width*height && visible ) { + * setVisible(true); + * } else { + * // as expected .. + * } + * </pre></p> + * <p> + * This call is ignored if in fullscreen mode.<br></p> * * @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 && 0<width*height && visible ) { + visibleAction = 2; // visible + this.width = width; + this.height = height; + } else if ( 0 != windowHandle ) { + // this width/height will be set by windowChanged, called by X11 + setSizeImpl(width, height); + } else { + this.width = width; + this.height = height; + } + } + } + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window setSize: END "+this.width+"x"+this.height+", visibleAction "+visibleAction); + } + } finally { + windowUnlock(); + } + if(visibleAction>0) { + 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.<br> + * @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},<br> @@ -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.<br> - * <p> - * First we create a {@link javax.media.nativewindow.NativeWindow} presentation of the given {@link java.awt.Component}, - * utilizing {@link #getNativeWindow(java.awt.Component)}.<br> - * The actual wrapping implementation is {@link com.jogamp.nativewindow.impl.jawt.JAWTWindow}.<br></p> - * <p> - * 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}.<br></p> - - * <p> - * Third we attach a {@link com.jogamp.newt.event.awt.AWTParentWindowAdapter} to the given AWT component.<br> - * The adapter passes window related events to our new child window, look at the implementation<br></p> - * - * <p> - * Forth we pass the parents visibility to the new Window<br></p> - * - * @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.<br> * <p> @@ -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.*; * <p> */ 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 <code>parentWindowObject</code> + /** Creates a new GLWindow attaching a new native child Window of the given <code>parentNativeWindow</code> 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<getWidth()*getHeight()) { + NativeWindow nw; + if (window.getWrappedWindow() != null) { + nw = NativeWindowFactory.getNativeWindow(window.getWrappedWindow(), window.getGraphicsConfiguration()); + } else { + nw = window; + } + GLCapabilities glCaps = (GLCapabilities) nw.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); + if(null==factory) { + factory = GLDrawableFactory.getFactory(glCaps.getGLProfile()); + } + if(null==drawable) { + drawable = factory.createGLDrawable(nw); + } + drawable.setRealized(true); + context = drawable.createContext(null); + sendReshape = true; // ensure a reshape event is send .. + } + } finally { + windowUnlock(); } - GLCapabilities glCaps = (GLCapabilities) nw.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); - factory = GLDrawableFactory.getFactory(glCaps.getGLProfile()); - drawable = factory.createGLDrawable(nw); - drawable.setRealized(true); - context = drawable.createContext(null); - sendReshape = true; // ensure a reshape event is send .. } } + public void setVisible(boolean visible) { + if(!isDestroyed()) { + runOnEDTIfAvail(true, new VisibleAction(visible)); + } + } + + public Capabilities getRequestedCapabilities() { + return window.getRequestedCapabilities(); + } + + public NativeWindow getParentNativeWindow() { + return window.getParentNativeWindow(); + } + public Screen getScreen() { return window.getScreen(); } @@ -277,21 +304,31 @@ public class GLWindow extends Window implements GLAutoDrawable { window.requestFocus(); } + public Insets getInsets() { + return window.getInsets(); + } + public void setSize(int width, int height) { window.setSize(width, height); } + protected void setSizeImpl(int width, int height) { + shouldNotCallThis(); + } public void setPosition(int x, int y) { window.setPosition(x, y); } - - public Insets getInsets() { - return window.getInsets(); + protected void setPositionImpl(int x, int y) { + shouldNotCallThis(); } public boolean setFullscreen(boolean fullscreen) { return window.setFullscreen(fullscreen); } + protected boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { + shouldNotCallThis(); + return false; + } public boolean isVisible() { return window.isVisible(); @@ -317,6 +354,10 @@ public class GLWindow extends Window implements GLAutoDrawable { return window.isFullscreen(); } + public void sendEvent(NEWTEvent e) { + window.sendEvent(e); + } + public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { window.addSurfaceUpdatedListener(l); } @@ -333,10 +374,6 @@ public class GLWindow extends Window implements GLAutoDrawable { window.surfaceUpdated(updater, window, when); } - public void sendEvent(NEWTEvent e) { - window.sendEvent(e); - } - public void addMouseListener(MouseListener l) { window.addMouseListener(l); } @@ -437,14 +474,11 @@ public class GLWindow extends Window implements GLAutoDrawable { setVisible(true); } - if( null != context ) { + if( window.isNativeWindowValid() && null != context ) { if(runPumpMessages) { window.getScreen().getDisplay().pumpMessages(); } - if(window.hasDeviceChanged() && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED) { - dispose(true, true); - } - if (sendDestroy) { + if(sendDestroy || window.hasDeviceChanged() && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED) { destroy(); sendDestroy=false; } else if ( window.isVisible() ) { @@ -456,12 +490,6 @@ public class GLWindow extends Window implements GLAutoDrawable { } } - private void sendDisposeEvent() { - if(drawable!=null && context != null) { - helper.invokeGL(drawable, context, disposeAction, null); - } - } - /** This implementation uses a static value */ public void setAutoSwapBufferMode(boolean onOrOff) { helper.setAutoSwapBufferMode(onOrOff); @@ -555,24 +583,24 @@ public class GLWindow extends Window implements GLAutoDrawable { // NativeWindow/Window methods // - public synchronized int lockSurface() throws NativeWindowException { + public int lockSurface() throws NativeWindowException { if(null!=drawable) return drawable.getNativeWindow().lockSurface(); - return NativeWindow.LOCK_SURFACE_NOT_READY; + return window.lockSurface(); } - public synchronized void unlockSurface() { + public void unlockSurface() { if(null!=drawable) drawable.getNativeWindow().unlockSurface(); - else throw new NativeWindowException("NEWT-GLWindow not locked"); + else window.unlockSurface(); } - public synchronized boolean isSurfaceLocked() { + public boolean isSurfaceLocked() { if(null!=drawable) return drawable.getNativeWindow().isSurfaceLocked(); - return false; + return window.isSurfaceLocked(); } - public synchronized Exception getLockedStack() { + public Exception getLockedStack() { if(null!=drawable) return drawable.getNativeWindow().getLockedStack(); - return null; + return window.getLockedStack(); } public boolean surfaceSwap() { @@ -614,6 +642,10 @@ public class GLWindow extends Window implements GLAutoDrawable { public void setRealized(boolean realized) { } + public boolean isRealized() { + return ( null != drawable ) ? drawable.isRealized() : false; + } + public GLCapabilities getChosenGLCapabilities() { if (drawable == null) { throw new GLException("No drawable yet"); @@ -629,12 +661,4 @@ public class GLWindow extends Window implements GLAutoDrawable { return drawable.getGLProfile(); } - - //---------------------------------------------------------------------- - // Internals only below this point - // - - private void shouldNotCallThis() { - throw new NativeWindowException("Should not call this"); - } } diff --git a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java index e6af747c8..235132460 100644 --- a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java +++ b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java @@ -54,7 +54,7 @@ public class EDTUtil { public EDTUtil(ThreadGroup tg, String name, Runnable pumpMessages) { this.threadGroup = tg; - this.name=new String("EDT-"+name); + this.name=new String(Thread.currentThread().getName()+"-"+"EDT-"+name); this.pumpMessages=pumpMessages; } @@ -123,15 +123,15 @@ public class EDTUtil { } public void invokeAndWait(Runnable task) { - invoke(false, task); + invoke(true, task); } - public void invoke(boolean deferred, Runnable task) { + public void invoke(boolean wait, Runnable task) { if(task == null) { return; } invokeLater(task); - if(!deferred) { + if(wait) { waitOnWorker(); } } |