From 811bd23ed37e392abb349f850a0b1dac635d021e Mon Sep 17 00:00:00 2001
From: Sven Gothel
- * In case
- * In case
* In case
- * In case
+ * destroys the window and children and releases
+ * windowing related resources.
+ * all other resources and states are kept intact,
+ * ie listeners, parent handles and size, position etc.
+ * render all native window information invalid,
+ * as if the native window was destroyed.
+ * all other resources and states are kept intact,
+ * ie listeners, parent handles and size, position etc.
+ * In case the old parent is not null and a Window,
+ * this window is removed from it's list of children.
- *
- * The Screen and Display information is regenrated utilizing the parents information.
+ * The Screen and Display information is regenerated utilizing the parents information.
* parentWindowObject
is a {@link javax.media.nativewindow.NativeWindow},
- * we create a child {@link com.jogamp.newt.Window},
- * utilizing {@link com.jogamp.newt.NewtFactory#createWindowImpl(java.lang.String, javax.media.nativewindow.NativeWindow, com.jogamp.newt.Screen, javax.media.nativewindow.Capabilities, boolean)}parentWindowObject
is even a {@link com.jogamp.newt.Window}, the following applies:
- * {@link com.jogamp.newt.event.WindowEvent#EVENT_WINDOW_RESIZED} is not propagated to the child window for e.g. layout
,
+ * In case parentWindowObject
is a {@link com.jogamp.newt.Window} instance,
+ * the new window is added to it's list of children.
+ * This assures proper handling of visibility, creation and destruction.
+ * {@link com.jogamp.newt.event.WindowEvent#EVENT_WINDOW_RESIZED} is not propagated to the child window for layout
,
* you have to add an appropriate {@link com.jogamp.newt.event.WindowListener} for this use case.
- * However, {@link com.jogamp.newt.event.WindowEvent#EVENT_WINDOW_DESTROY_NOTIFY} is propagated to the child window, so it will be closed properly.
* The parents visibility is passed to the new WindowparentWindowObject
is a different {@link javax.media.nativewindow.NativeWindow} implementation,
* you have to handle all events appropriatly.parentWindowObject
is a {@link java.awt.Component},
- * we utilize the {@link com.jogamp.newt.impl.awt.AWTNewtFactory#createNativeChildWindow(Object, com.jogamp.newt.Capabilities, boolean)}
- * factory method.
- * The factory adds a {@link com.jogamp.newt.event.WindowListener} to propagate {@link com.jogamp.newt.event.WindowEvent}'s so
- * your NEWT Window integrates into the AWT layout.
- * The parents visibility is passed to the new Window
*
@@ -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() {
+ /**
+ *
+ Currently only {@link com.jogamp.newt.opengl.GLWindow}
+ has an aggregation to an inner Window instance.
+ */
+ public Window getInnerWindow() {
+ return this;
+ }
+
/** If this Window actually wraps one from another toolkit such as
the AWT, this will return a non-null value. */
public Object getWrappedWindow() {
@@ -468,7 +590,7 @@ public abstract class Window implements NativeWindow
return fullscreen;
}
- private boolean autoDrawableMember = false;
+ private boolean handleDestroyNotify = true;
/** If the implementation is capable of detecting a device change
return true and clear the status/reason of the change. */
@@ -477,107 +599,258 @@ public abstract class Window implements NativeWindow
}
/**
- * If set to true,
- * certain action will be performed by the owning
- * AutoDrawable, ie the destroy() call within windowDestroyNotify()
+ * If set to true, the default value, this NEWT Window implementation will
+ * handle the destruction (ie {@link #destroy()} call) within {@link #windowDestroyNotify()} implementation.
+ * If set to false, it's up to the caller/owner to handle destruction within {@link #windowDestroyNotify()}.
*/
- public void setAutoDrawableClient(boolean b) {
- autoDrawableMember = b;
+ public void setHandleDestroyNotify(boolean b) {
+ handleDestroyNotify = b;
}
protected void windowDestroyNotify() {
if(DEBUG_WINDOW_EVENT) {
- System.out.println("Window.windowDestroyNotify start "+Thread.currentThread());
+ System.err.println("Window.windowDestroyNotify START "+Thread.currentThread());
}
sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
- if(!autoDrawableMember && !destructionLock.isLocked()) {
+ if(handleDestroyNotify && !isDestroyed()) {
destroy();
}
if(DEBUG_WINDOW_EVENT) {
- System.out.println("Window.windowDestroyeNotify end "+Thread.currentThread());
+ System.err.println("Window.windowDestroyeNotify END "+Thread.currentThread());
}
}
protected void windowDestroyed() {
if(DEBUG_WINDOW_EVENT) {
- System.out.println("Window.windowDestroyed "+Thread.currentThread());
+ System.err.println("Window.windowDestroyed "+Thread.currentThread());
}
- if(!destructionLock.isLocked()) {
- invalidate();
+ invalidate();
+ }
+
+ protected boolean reparentWindowImpl() {
+ // default implementation, no native reparenting support
+ return false;
+ }
+
+ /**
+ * Change this window's parent window.
+ *
+ * In case the new parent is not null and a Window,
+ * this window is added to it's list of children.setVisible
makes the window visible if visible
is true,
- * otherwise the window becomes invisible.setVisible
makes the window and children visible if visible
is true,
+ * otherwise the window and children becomes invisible.
* The setVisible(true)
is responsible to actual create the native window.
+ * Zero size semantics are respected, see {@link #setSize(int,int)}:
+ *
+ * if ( 0 == windowHandle && visible ) { + * this.visible = visible; + * if( 0+ * * In case this window is a child window and a parent {@link javax.media.nativewindow.NativeWindow} is being used,
*/ - 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}
* the parent's {@link javax.media.nativewindow.NativeWindow} handle is retrieved via {@link javax.media.nativewindow.NativeWindow#getWindowHandle()}.
* If this action fails, ie if the parent {@link javax.media.nativewindow.NativeWindow} is not valid yet,
* no native window is created yet andsetVisible(true)
shall be repeated when it is.
- * - * This call is ignored if in fullscreen mode.
+ *+ * Zero size semantics are respected, see {@link #setVisible(boolean)}:
+ *+ * if ( 0 != windowHandle && 0>=width*height && visible ) { + * setVisible(false); + * } else if ( 0 == windowHandle && 0+ * + * This call is ignored if in fullscreen mode.
* * @param width of the client area of the window * @param height of the client area of the window */ - public abstract void setSize(int width, int height); + public void setSize(int width, int height) { + int visibleAction = 0; // 1 invisible, 2 visible + windowLock(); + try{ + if(DEBUG_IMPLEMENTATION) { + String msg = new String("Window setSize: START "+this.width+"x"+this.height+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible "+visible); + //System.err.println(msg); + Exception e = new Exception(msg); + e.printStackTrace(); + } + if (width != this.width || this.height != height) { + if(!fullscreen) { + nfs_width=width; + nfs_height=height; + if ( 0 != windowHandle && 0>=width*height && visible ) { + visibleAction=1; // invisible + this.width = 0; + this.height = 0; + } else if ( 0 == windowHandle && 00) { + setVisible( ( 1 == visibleAction ) ? false : true ); + } + } + protected abstract void setSizeImpl(int width, int height); /** * Sets the location of the top left corner of the window, including @@ -589,13 +862,103 @@ public abstract class Window implements NativeWindow * @param x coord of the top left corner * @param y coord of the top left corner */ - public abstract void setPosition(int x, int y); + public void setPosition(int x, int y) { + windowLock(); + try{ + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window setPosition: "+this.x+"/"+this.y+" -> "+x+"/"+y+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)); + } + if ( this.x != x || this.y != y ) { + if(!fullscreen) { + nfs_x=x; + nfs_y=y; + if(0!=windowHandle) { + // this x/y will be set by windowChanged, called by X11 + setPositionImpl(x, y); + } else { + this.x = x; + this.y = y; + } + } + } + } finally { + windowUnlock(); + } + } + protected abstract void setPositionImpl(int x, int y); + + public boolean setFullscreen(boolean fullscreen) { + windowLock(); + try{ + if(0!=windowHandle && this.fullscreen!=fullscreen) { + int x,y,w,h; + if(fullscreen) { + x = 0; y = 0; + w = screen.getWidth(); + h = screen.getHeight(); + } else { + x = nfs_x; + y = nfs_y; + w = nfs_width; + h = nfs_height; + } + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + System.err.println("X11Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()); + } + this.fullscreen = setFullscreenImpl(fullscreen, x, y, w, h); + } + return this.fullscreen; + } finally { + windowUnlock(); + } + } + protected abstract boolean setFullscreenImpl(boolean fullscreen, int x, int y, int widht, int height); - public abstract boolean setFullscreen(boolean fullscreen); + // + // Child Window Management + // + + private ArrayList childWindows = new ArrayList(); + + protected void removeChild(NativeWindow win) { + synchronized(childWindows) { + ArrayList newChildWindows = (ArrayList) childWindows.clone(); + newChildWindows.remove(win); + childWindows = newChildWindows; + } + } + + protected void addChild(NativeWindow win) { + if (win == null) { + return; + } + synchronized(childWindows) { + ArrayList newChildWindows = (ArrayList) childWindows.clone(); + newChildWindows.add(win); + childWindows = newChildWindows; + } + } + + // + // Generic Event Support + // + + public void sendEvent(NEWTEvent e) { + if(e instanceof WindowEvent) { + sendWindowEvent((WindowEvent)e); + } else if(e instanceof KeyEvent) { + sendKeyEvent((KeyEvent)e); + } else if(e instanceof MouseEvent) { + sendMouseEvent((MouseEvent)e); + } else if(e instanceof PaintEvent) { + sendPaintEvent((PaintEvent)e); + } + } // // SurfaceUpdatedListener Support // + private ArrayList surfaceUpdatedListeners = new ArrayList(); public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { @@ -643,22 +1006,6 @@ public abstract class Window implements NativeWindow } } - // - // Generic Event Support - // - - public void sendEvent(NEWTEvent e) { - if(e instanceof WindowEvent) { - sendWindowEvent((WindowEvent)e); - } else if(e instanceof KeyEvent) { - sendKeyEvent((KeyEvent)e); - } else if(e instanceof MouseEvent) { - sendMouseEvent((MouseEvent)e); - } else if(e instanceof PaintEvent) { - sendPaintEvent((PaintEvent)e); - } - } - // // MouseListener/Event Support // @@ -704,7 +1051,7 @@ public abstract class Window implements NativeWindow return; // .. invalid .. } if(DEBUG_MOUSE_EVENT) { - System.out.println("sendMouseEvent: "+MouseEvent.getEventTypeString(eventType)+ + System.err.println("sendMouseEvent: "+MouseEvent.getEventTypeString(eventType)+ ", mod "+modifiers+", pos "+x+"/"+y+", button "+button); } if(button<0||button>MouseEvent.BUTTON_NUMBER) { @@ -751,7 +1098,7 @@ public abstract class Window implements NativeWindow sendMouseEvent(e); if(null!=eClicked) { if(DEBUG_MOUSE_EVENT) { - System.out.println("sendMouseEvent: synthesized MOUSE_CLICKED event"); + System.err.println("sendMouseEvent: synthesized MOUSE_CLICKED event"); } sendMouseEvent(eClicked); } @@ -759,7 +1106,7 @@ public abstract class Window implements NativeWindow protected void sendMouseEvent(MouseEvent e) { if(DEBUG_MOUSE_EVENT) { - System.out.println("sendMouseEvent: event: "+e); + System.err.println("sendMouseEvent: event: "+e); } ArrayList listeners = null; @@ -840,7 +1187,7 @@ public abstract class Window implements NativeWindow protected void sendKeyEvent(KeyEvent e) { if(DEBUG_KEY_EVENT) { - System.out.println("sendKeyEvent: "+e); + System.err.println("sendKeyEvent: "+e); } ArrayList listeners = null; synchronized(keyListeners) { @@ -904,7 +1251,7 @@ public abstract class Window implements NativeWindow protected void sendWindowEvent(WindowEvent e) { if(DEBUG_WINDOW_EVENT) { - System.out.println("sendWindowEvent: "+e); + System.err.println("sendWindowEvent: "+e); } ArrayList listeners = null; synchronized(windowListeners) { @@ -1027,7 +1374,30 @@ public abstract class Window implements NativeWindow return sb.toString(); } - private RecursiveToolkitLock destructionLock = new RecursiveToolkitLock(); private RecursiveToolkitLock surfaceLock = new RecursiveToolkitLock(); + private RecursiveToolkitLock windowLock = new RecursiveToolkitLock(); + + private static final boolean TRACE_LOCK = false; + + protected final void windowLock() { + getInnerWindow().windowLock.lock(); + if(TRACE_LOCK) { + Exception e = new Exception("WINDOW LOCK SET: R "+getInnerWindow().windowLock.getRecursionCount()+", "+getInnerWindow().windowLock); + e.printStackTrace(); + } + } + protected final void windowUnlock() { + getInnerWindow().windowLock.unlock(); + if(TRACE_LOCK) { + Exception e = new Exception("WINDOW LOCK FREE: R "+getInnerWindow().windowLock.getRecursionCount()+", "+getInnerWindow().windowLock); + e.printStackTrace(); + } + } + protected final boolean windowIsLocked() { + return getInnerWindow().windowLock.isLocked(); + } + protected final void shouldNotCallThis() { + throw new NativeWindowException("Should not call this"); + } } diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java new file mode 100644 index 000000000..23269a93b --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2010 Sven Gothel. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name Sven Gothel or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.newt.awt; + +import java.lang.reflect.*; +import java.security.*; + +import java.awt.Canvas; + +import javax.media.nativewindow.*; +// import javax.media.nativewindow.awt.*; + +import com.jogamp.newt.event.awt.AWTAdapter; +import com.jogamp.newt.event.awt.AWTParentWindowAdapter; +import com.jogamp.newt.Screen; +import com.jogamp.newt.Window; +import com.jogamp.newt.impl.Debug; + +public class NewtCanvasAWT extends java.awt.Canvas { + public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window"); + + NativeWindow parent = null; + Window newtChild = null; + AWTAdapter awtAdapter = null; + + /** + * Instantiates a NewtCanvas without a NEWT child.
+ * @see #setNEWTChild(Window) + */ + public NewtCanvasAWT() { + super(); + } + + /** + * Instantiates a NewtCanvas with a NEWT child. + */ + public NewtCanvasAWT(Window child) { + super(); + setNEWTChild(child); + } + + /** sets a new NEWT child, provoking reparenting on the NEWT level. */ + public NewtCanvasAWT setNEWTChild(Window child) { + if(newtChild!=child) { + newtChild = child; + if(null!=parent) { + // reparent right away, addNotify has been called already + reparentWindow( (null!=newtChild) ? true : false ); + } + } + return this; + } + + /** @return the current NEWT child */ + public Window getNEWTChild() { + return newtChild; + } + + /** @return this AWT Canvas NativeWindow represention, may be null in case {@link #removeNotify()} has been called, + * or {@link #addNotify()} hasn't been called yet.*/ + public NativeWindow getNativeWindow() { return parent; } + + void setWindowAdapter(boolean attach) { + if(null!=awtAdapter) { + awtAdapter.removeFrom(this); + awtAdapter=null; + } + if(attach && null!=newtChild) { + awtAdapter = new AWTParentWindowAdapter(newtChild).addTo(this); + } + } + + public void addNotify() { + super.addNotify(); + disableBackgroundErase(); + if(DEBUG_IMPLEMENTATION) { + // if ( isShowing() == false ) -> Container was not visible yet. + // if ( isShowing() == true ) -> Container is already visible. + System.err.println("NewtCanvasAWT.addNotify: "+newtChild+", "+this+", visible "+isVisible()+", showing "+isShowing()+", displayable "+isDisplayable()); + } + reparentWindow(true); + } + + public void removeNotify() { + if(DEBUG_IMPLEMENTATION) { + System.err.println("NewtCanvasAWT.removeNotify: "+newtChild); + } + reparentWindow(false); + super.removeNotify(); + } + + void reparentWindow(boolean add) { + if(null==newtChild) { + return; // nop + } + + if(add) { + if(null!=newtChild) { + parent = NewtFactoryAWT.getNativeWindow(this, newtChild.getRequestedCapabilities()); + } + if(null!=parent) { + // 1st choice - NEWT size := AWT size + // 2nd choice - AWT size := NEWT size + if(0>=getWidth()*getHeight()) { + setSize(newtChild.getWidth(), newtChild.getHeight()); // #2 + } + Screen screen = null; + if( !newtChild.isNativeWindowValid() ) { + screen = NewtFactoryAWT.createCompatibleScreen(parent); + } + newtChild.reparentWindow(parent, screen); + if ( 0 < getWidth() * getHeight() ) { + newtChild.setSize(getWidth(), getHeight()); // #1 + newtChild.setVisible(true); + } + setWindowAdapter(true); + } + } else { + setWindowAdapter(false); + parent = null; + newtChild.setVisible(false); + newtChild.reparentWindow(null, null); + } + } + + // Disables the AWT's erasing of this Canvas's background on Windows + // in Java SE 6. This internal API is not available in previous + // releases, but the system property + // -Dsun.awt.noerasebackground=true can be specified to get similar + // results globally in previous releases. + private static boolean disableBackgroundEraseInitialized; + private static Method disableBackgroundEraseMethod; + private void disableBackgroundErase() { + if (!disableBackgroundEraseInitialized) { + try { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + try { + Class clazz = getToolkit().getClass(); + while (clazz != null && disableBackgroundEraseMethod == null) { + try { + disableBackgroundEraseMethod = + clazz.getDeclaredMethod("disableBackgroundErase", + new Class[] { Canvas.class }); + disableBackgroundEraseMethod.setAccessible(true); + } catch (Exception e) { + clazz = clazz.getSuperclass(); + } + } + } catch (Exception e) { + } + return null; + } + }); + } catch (Exception e) { + } + disableBackgroundEraseInitialized = true; + } + if (disableBackgroundEraseMethod != null) { + try { + disableBackgroundEraseMethod.invoke(getToolkit(), new Object[] { this }); + } catch (Exception e) { + // FIXME: workaround for 6504460 (incorrect backport of 6333613 in 5.0u10) + // throw new GLException(e); + } + } + } +} + diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java index e0f86b1a9..6409ab7a8 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java @@ -30,7 +30,7 @@ * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ -package com.jogamp.newt.impl.awt; +package com.jogamp.newt.awt; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; @@ -46,9 +46,12 @@ import com.jogamp.newt.Display; import com.jogamp.newt.Screen; import com.jogamp.newt.Window; import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.util.EDTUtil; +import com.jogamp.newt.impl.Debug; import com.jogamp.common.util.ReflectionUtil; -public class AWTNewtFactory extends NewtFactory { +public class NewtFactoryAWT extends NewtFactory { + public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window"); /** * Wraps an AWT component into a {@link javax.media.nativewindow.NativeWindow} utilizing the {@link javax.media.nativewindow.NativeWindowFactory},
@@ -76,46 +79,13 @@ public class AWTNewtFactory extends NewtFactory { DefaultGraphicsConfiguration config = AWTGraphicsConfiguration.create(awtComp, (Capabilities) capsRequested.clone(), capsRequested); NativeWindow awtNative = NativeWindowFactory.getNativeWindow(awtComp, config); // a JAWTWindow + if(DEBUG_IMPLEMENTATION) { + System.out.println("NewtFactoryAWT.getNativeWindow: "+awtComp+" -> "+awtNative); + } return awtNative; } - /** - * Creates a native NEWT child window to a AWT parent window.
- *- * First we create a {@link javax.media.nativewindow.NativeWindow} presentation of the given {@link java.awt.Component}, - * utilizing {@link #getNativeWindow(java.awt.Component)}.
- *
- * The actual wrapping implementation is {@link com.jogamp.nativewindow.impl.jawt.JAWTWindow}.- * Second we create a child {@link com.jogamp.newt.Window}, - * utilizing {@link com.jogamp.newt.NewtFactory#createWindowImpl(java.lang.String, javax.media.nativewindow.NativeWindow, com.jogamp.newt.Screen, javax.media.nativewindow.Capabilities, boolean)}, - * passing the created {@link javax.media.nativewindow.NativeWindow}.
- - *- * Third we attach a {@link com.jogamp.newt.event.awt.AWTParentWindowAdapter} to the given AWT component.
- * - *
- * The adapter passes window related events to our new child window, look at the implementation- * Forth we pass the parents visibility to the new Window
- * - * @param awtParentObject must be of type java.awt.Component - * @param undecorated only impacts if the window is in top-level state, while attached to a parent window it's rendered undecorated always - * @return The successful created child window, or null if the AWT parent is not ready yet (no valid peers) - */ - public static Window createNativeChildWindow(Object awtParentObject, Capabilities newtCaps, boolean undecorated) { - if( null == awtParentObject ) { - throw new NativeWindowException("Null AWT Parent Component"); - } - if( ! (awtParentObject instanceof java.awt.Component) ) { - throw new NativeWindowException("AWT Parent Component not a java.awt.Component"); - } - java.awt.Component awtParent = (java.awt.Component) awtParentObject; - - // Generate a complete JAWT NativeWindow from the AWT Component - NativeWindow parent = getNativeWindow(awtParent, newtCaps); - if(null==parent) { - throw new NativeWindowException("Null NativeWindow from parent: "+awtParent); - } - + public static Screen createCompatibleScreen(NativeWindow parent) { // Get parent's NativeWindow details AWTGraphicsConfiguration parentConfig = (AWTGraphicsConfiguration) parent.getGraphicsConfiguration(); AWTGraphicsScreen parentScreen = (AWTGraphicsScreen) parentConfig.getScreen(); @@ -124,16 +94,7 @@ public class AWTNewtFactory extends NewtFactory { // Prep NEWT's Display and Screen according to the parent final String type = NativeWindowFactory.getNativeWindowType(true); Display display = NewtFactory.wrapDisplay(type, parentDevice.getHandle()); - Screen screen = NewtFactory.createScreen(type, display, parentScreen.getIndex()); - - // NEWT Window creation and add event handler for proper propagation AWT -> NEWT - // and copy size/visible state - Window window = NewtFactory.createWindowImpl(type, parent, screen, newtCaps, undecorated); - new AWTParentWindowAdapter(window).addTo(awtParent); - window.setSize(awtParent.getWidth(), awtParent.getHeight()); - window.setVisible(awtParent.isVisible()); - - return window; + return NewtFactory.createScreen(type, display, parentScreen.getIndex()); } } diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java index 3abe6531a..e8497a741 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java @@ -31,6 +31,9 @@ */ package com.jogamp.newt.event.awt; +import com.jogamp.newt.util.EDTUtil; +import com.jogamp.newt.impl.Debug; + /** * Convenient adapter forwarding AWT events to NEWT via the event listener model.
*@@ -102,6 +105,8 @@ package com.jogamp.newt.event.awt; */ public abstract class AWTAdapter implements java.util.EventListener { + public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window"); + com.jogamp.newt.event.NEWTEventListener newtListener; com.jogamp.newt.Window newtWindow; @@ -157,9 +162,16 @@ public abstract class AWTAdapter implements java.util.EventListener */ public abstract AWTAdapter addTo(java.awt.Component awtComponent); + /** @see #addTo(java.awt.Component) */ + public abstract AWTAdapter removeFrom(java.awt.Component awtComponent); + void enqueueEvent(com.jogamp.newt.event.NEWTEvent event) { + enqueueEvent(false, event); + } + + void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event) { try { - newtWindow.getScreen().getDisplay().enqueueEvent(event); + newtWindow.getScreen().getDisplay().enqueueEvent(wait, event); } catch (NullPointerException npe) { /* that's ok .. window might be down already */ } diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java index 64d4d8d86..d2b733f98 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java @@ -50,6 +50,11 @@ public class AWTKeyAdapter extends AWTAdapter implements java.awt.event.KeyListe return this; } + public AWTAdapter removeFrom(java.awt.Component awtComponent) { + awtComponent.removeKeyListener(this); + return this; + } + public void keyPressed(java.awt.event.KeyEvent e) { com.jogamp.newt.event.KeyEvent event = AWTNewtEventFactory.createKeyEvent(e, newtWindow); if(null!=newtListener) { diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTMouseAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTMouseAdapter.java index 7efcd123e..058a5f250 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTMouseAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTMouseAdapter.java @@ -51,6 +51,12 @@ public class AWTMouseAdapter extends AWTAdapter implements java.awt.event.MouseL return this; } + public AWTAdapter removeFrom(java.awt.Component awtComponent) { + awtComponent.removeMouseListener(this); + awtComponent.removeMouseMotionListener(this); + return this; + } + public void mouseClicked(java.awt.event.MouseEvent e) { com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, newtWindow); if(null!=newtListener) { diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java index 01f0457e3..d94a32a9c 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java @@ -42,9 +42,18 @@ public class AWTParentWindowAdapter extends AWTWindowAdapter } public void componentResized(java.awt.event.ComponentEvent e) { - // need to really resize the NEWT child window - java.awt.Component comp = e.getComponent(); - newtWindow.setSize(comp.getWidth(), comp.getHeight()); + // Need to resize the NEWT child window + // the resized event will be send via the native window feedback. + final java.awt.Component comp = e.getComponent(); + newtWindow.runOnEDTIfAvail(false, new Runnable() { + public void run() { + if( 0 < comp.getWidth() * comp.getHeight() ) { + newtWindow.setSize(comp.getWidth(), comp.getHeight()); + newtWindow.setVisible(comp.isVisible()); + } else { + newtWindow.setVisible(false); + } + }}); } public void componentMoved(java.awt.event.ComponentEvent e) { diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java index fd6ceddae..53ce03299 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java @@ -33,9 +33,9 @@ package com.jogamp.newt.event.awt; public class AWTWindowAdapter extends AWTAdapter - implements java.awt.event.ComponentListener, java.awt.event.WindowListener, java.awt.event.HierarchyListener + implements java.awt.event.ComponentListener, java.awt.event.WindowListener, + java.awt.event.HierarchyListener, java.awt.event.HierarchyBoundsListener { - java.awt.Component awtComponent; WindowClosingListener windowClosingListener; public AWTWindowAdapter(com.jogamp.newt.event.WindowListener newtListener) { @@ -51,16 +51,36 @@ public class AWTWindowAdapter } public AWTAdapter addTo(java.awt.Component awtComponent) { - this.awtComponent = awtComponent; + java.awt.Window win = getWindow(awtComponent); awtComponent.addComponentListener(this); awtComponent.addHierarchyListener(this); - addWindowClosingListenerTo(getWindow(awtComponent)); + awtComponent.addHierarchyBoundsListener(this); + if( null == windowClosingListener ) { + windowClosingListener = new WindowClosingListener(); + } + if( null != win ) { + win.addWindowListener(windowClosingListener); + } if(awtComponent instanceof java.awt.Window) { ((java.awt.Window)awtComponent).addWindowListener(this); } return this; } + public AWTAdapter removeFrom(java.awt.Component awtComponent) { + awtComponent.removeComponentListener(this); + awtComponent.removeHierarchyListener(this); + awtComponent.removeHierarchyBoundsListener(this); + java.awt.Window win = getWindow(awtComponent); + if( null != win && null != windowClosingListener ) { + win.removeWindowListener(windowClosingListener); + } + if(awtComponent instanceof java.awt.Window) { + ((java.awt.Window)awtComponent).removeWindowListener(this); + } + return this; + } + static java.awt.Window getWindow(java.awt.Component comp) { while( null != comp && !(comp instanceof java.awt.Window) ) { comp = comp.getParent(); @@ -71,15 +91,6 @@ public class AWTWindowAdapter return null; } - void addWindowClosingListenerTo(java.awt.Window win) { - if( null == windowClosingListener ) { - windowClosingListener = new WindowClosingListener(); - } - if( null != win ) { - win.addWindowListener(windowClosingListener); - } - } - public void componentResized(java.awt.event.ComponentEvent e) { com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow); if(null!=newtListener) { @@ -101,7 +112,11 @@ public class AWTWindowAdapter public void componentShown(java.awt.event.ComponentEvent e) { if(null==newtListener) { if(!newtWindow.isDestroyed()) { - newtWindow.setVisible(true, true /* deferred */); + newtWindow.runOnEDTIfAvail(false, new Runnable() { + public void run() { + newtWindow.setVisible(true); + } + }); } } } @@ -109,7 +124,11 @@ public class AWTWindowAdapter public void componentHidden(java.awt.event.ComponentEvent e) { if(null==newtListener) { if(!newtWindow.isDestroyed()) { - newtWindow.setVisible(false, true /* deferred */); + newtWindow.runOnEDTIfAvail(false, new Runnable() { + public void run() { + newtWindow.setVisible(false); + } + }); } } } @@ -145,27 +164,45 @@ public class AWTWindowAdapter public void hierarchyChanged(java.awt.event.HierarchyEvent e) { if( null == newtListener ) { long bits = e.getChangeFlags(); - java.awt.Component changed = e.getChanged(); + final java.awt.Component changed = e.getChanged(); if( 0 != ( java.awt.event.HierarchyEvent.SHOWING_CHANGED & bits ) ) { - final boolean visible = changed.isVisible(); - if(!newtWindow.isDestroyed()) { - newtWindow.setVisible(visible, true /* deferred */); + final boolean showing = changed.isShowing(); + if(DEBUG_IMPLEMENTATION) { + System.out.println("hierarchyChanged SHOWING_CHANGED: showing "+showing+", "+changed); } - } else if( 0 != ( java.awt.event.HierarchyEvent.PARENT_CHANGED & bits ) ) { - if(awtComponent == changed) { - java.awt.Window win = getWindow(changed); - if(null != win) { - addWindowClosingListenerTo(win); - } else { - java.awt.Component parent = e.getChangedParent(); - if(parent instanceof java.awt.Window) { - ((java.awt.Window)parent).removeWindowListener(this); - if( null != windowClosingListener ) { - ((java.awt.Window)parent).removeWindowListener(windowClosingListener); - } + if(!newtWindow.isDestroyed()) { + newtWindow.runOnEDTIfAvail(false, new Runnable() { + public void run() { + newtWindow.setVisible(showing); } - } + }); } + } + if( 0 != ( java.awt.event.HierarchyEvent.DISPLAYABILITY_CHANGED & bits ) ) { + final boolean displayability = changed.isDisplayable(); + if(DEBUG_IMPLEMENTATION) { + System.out.println("hierarchyChanged DISPLAYABILITY_CHANGED: displayability "+displayability+", "+changed); + } + } + } + } + + public void ancestorMoved(java.awt.event.HierarchyEvent e) { + if( null == newtListener ) { + final java.awt.Component changed = e.getChanged(); + final boolean showing = changed.isShowing(); + if(DEBUG_IMPLEMENTATION) { + System.out.println("ancestorMoved: showing "+showing+", "+changed); + } + } + } + + public void ancestorResized(java.awt.event.HierarchyEvent e) { + if( null == newtListener ) { + final java.awt.Component changed = e.getChanged(); + final boolean showing = changed.isShowing(); + if(DEBUG_IMPLEMENTATION) { + System.out.println("ancestorResized: showing "+showing+", "+changed); } } } @@ -176,7 +213,7 @@ public class AWTWindowAdapter if(null!=newtListener) { ((com.jogamp.newt.event.WindowListener)newtListener).windowDestroyNotify(event); } else { - enqueueEvent(event); + enqueueEvent(true, event); } } diff --git a/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java b/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java index b98a6fa20..f97625320 100644 --- a/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java @@ -176,7 +176,7 @@ public class AWTWindow extends Window { return res; } - protected void setVisibleImpl() { + protected void setVisibleImpl(final boolean visible) { runOnEDT(true, new Runnable() { public void run() { container.setVisible(visible); @@ -203,13 +203,7 @@ public class AWTWindow extends Window { ((AWTScreen)screen).setScreenSize(w, h); } - public void setSize(final int width, final int height) { - this.width = width; - this.height = height; - if(!fullscreen) { - nfs_width=width; - nfs_height=height; - } + protected void setSizeImpl(final int width, final int height) { if(null!=container) { /** An AWT event on setSize() would bring us in a deadlock situation, hence invokeLater() */ runOnEDT(false, new Runnable() { @@ -237,55 +231,34 @@ public class AWTWindow extends Window { Insets(insets[0],insets[1],insets[2],insets[3]); } - public void setPosition(final int x, final int y) { - this.x = x; - this.y = y; - if(!fullscreen) { - nfs_x=x; - nfs_y=y; + protected void setPositionImpl(final int x, final int y) { + if(null!=container) { + runOnEDT(true, new Runnable() { + public void run() { + container.setLocation(x, y); + } + }); } - runOnEDT(true, new Runnable() { - public void run() { - container.setLocation(x, y); - } - }); } - public boolean setFullscreen(final boolean fullscreen) { - if(this.fullscreen!=fullscreen) { - final int x,y,w,h; - this.fullscreen=fullscreen; - if(fullscreen) { - x = 0; y = 0; - w = screen.getWidth(); - h = screen.getHeight(); - } else { - x = nfs_x; - y = nfs_y; - w = nfs_width; - h = nfs_height; - } - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - System.err.println("AWTWindow fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h); - } - /** An AWT event on setSize() would bring us in a deadlock situation, hence invokeLater() */ - runOnEDT(false, new Runnable() { - public void run() { - if(null!=frame) { - if(!container.isDisplayable()) { - frame.setUndecorated(undecorated||fullscreen); - } else { - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - System.err.println("AWTWindow can't undecorate already created frame"); - } + protected boolean setFullscreenImpl(final boolean fullscreen, final int x, final int y, final int w, final int h) { + /** An AWT event on setSize() would bring us in a deadlock situation, hence invokeLater() */ + runOnEDT(false, new Runnable() { + public void run() { + if(null!=frame) { + if(!container.isDisplayable()) { + frame.setUndecorated(isUndecorated(fullscreen)); + } else { + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + System.err.println("AWTWindow can't undecorate already created frame"); } } - container.setLocation(x, y); - container.setSize(w, h); } - }); - } - return true; + container.setLocation(x, y); + container.setSize(w, h); + } + }); + return fullscreen; } public Object getWrappedWindow() { diff --git a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java index 7b867db21..74cb53f7e 100644 --- a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java @@ -77,13 +77,13 @@ public class Window extends com.jogamp.newt.Window { } } - protected void setVisibleImpl() { + protected void setVisibleImpl(boolean visible) { if(visible) { ((Display)screen.getDisplay()).setFocus(this); } } - public void setSize(int width, int height) { + protected void setSizeImpl(int width, int height) { Screen screen = (Screen) getScreen(); if((x+width)>screen.getWidth()) { width=screen.getWidth()-x; @@ -91,18 +91,12 @@ public class Window extends com.jogamp.newt.Window { if((y+height)>screen.getHeight()) { height=screen.getHeight()-y; } - this.width = width; - this.height = height; - if(!fullscreen) { - nfs_width=width; - nfs_height=height; - } if(0!=surfaceHandle) { SetBounds0(surfaceHandle, screen.getWidth(), screen.getHeight(), x, y, width, height); } } - public void setPosition(int x, int y) { + protected void setPositionImpl(int x, int y) { Screen screen = (Screen) getScreen(); if((x+width)>screen.getWidth()) { x=screen.getWidth()-width; @@ -110,37 +104,14 @@ public class Window extends com.jogamp.newt.Window { if((y+height)>screen.getHeight()) { y=screen.getHeight()-height; } - this.x = x; - this.y = y; - if(!fullscreen) { - nfs_x=x; - nfs_y=y; - } if(0!=surfaceHandle) { SetBounds0(surfaceHandle, screen.getWidth(), screen.getHeight(), x, y, width, height); } } - public boolean setFullscreen(boolean fullscreen) { - if(this.fullscreen!=fullscreen) { - int x,y,w,h; - this.fullscreen=fullscreen; - if(fullscreen) { - x = 0; y = 0; - w = screen.getWidth(); - h = screen.getHeight(); - } else { - x = nfs_x; - y = nfs_y; - w = nfs_width; - h = nfs_height; - } - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - System.err.println("IntelGDL Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h); - } - if(0!=surfaceHandle) { - SetBounds0(surfaceHandle, screen.getWidth(), screen.getHeight(), x, y, w, h); - } + protected boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { + if(0!=surfaceHandle) { + SetBounds0(surfaceHandle, screen.getWidth(), screen.getHeight(), x, y, w, h); } return fullscreen; } diff --git a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java index 93c2b14bb..20a181096 100755 --- a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java @@ -153,12 +153,17 @@ public class MacWindow extends Window { public void run() { nsViewLock.lock(); try { - if(DEBUG_IMPLEMENTATION) System.out.println("MacWindow.CloseAction "+Thread.currentThread().getName()); + if(DEBUG_IMPLEMENTATION) { System.out.println("MacWindow.CloseAction "+Thread.currentThread().getName()); } if (windowHandle != 0) { close0(windowHandle); - windowHandle = 0; + } + } catch (Throwable t) { + if(DEBUG_IMPLEMENTATION) { + Exception e = new Exception("closeNative failed - "+Thread.currentThread().getName(), t); + e.printStackTrace(); } } finally { + windowHandle = 0; nsViewLock.unlock(); } } @@ -191,7 +196,7 @@ public class MacWindow extends Window { public void run() { nsViewLock.lock(); try { - createWindow(false); + createWindow(false, getX(), getY(), getWidth(), getHeight(), isFullscreen()); } finally { nsViewLock.unlock(); } @@ -229,30 +234,26 @@ public class MacWindow extends Window { nsViewLock.unlock(); } - class VisibleAction implements Runnable { - public void run() { - nsViewLock.lock(); - try { - if(DEBUG_IMPLEMENTATION) System.out.println("MacWindow.VisibleAction "+visible+" "+Thread.currentThread().getName()); - if (visible) { - createWindow(false); - if (windowHandle != 0) { - makeKeyAndOrderFront0(windowHandle); - } - } else { - if (windowHandle != 0) { - orderOut0(windowHandle); + protected void setVisibleImpl(final boolean visible) { + MainThread.invoke(true, new Runnable() { + public void run() { + nsViewLock.lock(); + try { + if (visible) { + createWindow(false, getX(), getY(), getWidth(), getHeight(), isFullscreen()); + if (windowHandle != 0) { + makeKeyAndOrderFront0(windowHandle); + } + } else { + if (windowHandle != 0) { + orderOut0(windowHandle); + } } + } finally { + nsViewLock.unlock(); } - } finally { - nsViewLock.unlock(); } - } - } - private VisibleAction visibleAction = new VisibleAction(); - - protected void setVisibleImpl() { - MainThread.invoke(true, visibleAction); + }); } class TitleAction implements Runnable { @@ -307,20 +308,9 @@ public class MacWindow extends Window { } private SizeAction sizeAction = new SizeAction(); - public void setSize(int width, int height) { - if (width != this.width || this.height != height) { - if(!fullscreen) { - nfs_width=width; - nfs_height=height; - if (0 != windowHandle) { - // this width/height will be set by sizeChanged, called by OSX - MainThread.invoke(true, sizeAction); - } else { - this.width=width; - this.height=height; - } - } - } + protected void setSizeImpl(int width, int height) { + // this width/height will be set by sizeChanged, called by OSX + MainThread.invoke(true, sizeAction); } class PositionAction implements Runnable { @@ -337,56 +327,28 @@ public class MacWindow extends Window { } private PositionAction positionAction = new PositionAction(); - public void setPosition(int x, int y) { - if ( this.x != x || this.y != y ) { - if(!fullscreen) { - nfs_x=x; - nfs_y=y; - if (0 != windowHandle) { - // this x/y will be set by positionChanged, called by OSX - MainThread.invoke(true, positionAction); - } else { - this.x=x; - this.y=y; - } - } - } + protected void setPositionImpl(int x, int y) { + // this x/y will be set by positionChanged, called by OSX + MainThread.invoke(true, positionAction); } - class FullscreenAction implements Runnable { - public void run() { - nsViewLock.lock(); - try { - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - System.err.println("MacWindow fs: "+fullscreen+" "+x+"/"+y+" "+width+"x"+height); - } - createWindow(true); - if (windowHandle != 0) { - makeKeyAndOrderFront0(windowHandle); + protected boolean setFullscreenImpl(final boolean fullscreen, final int x, final int y, final int w, final int h) { + MainThread.invoke(true, new Runnable() { + public void run() { + nsViewLock.lock(); + try { + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + System.err.println("MacWindow fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h); + } + createWindow(true, x, y, w, h, fullscreen); + if (windowHandle != 0) { + makeKeyAndOrderFront0(windowHandle); + } + } finally { + nsViewLock.unlock(); } - } finally { - nsViewLock.unlock(); } - } - } - private FullscreenAction fullscreenAction = new FullscreenAction(); - - public boolean setFullscreen(boolean fullscreen) { - if(this.fullscreen!=fullscreen) { - this.fullscreen=fullscreen; - if(fullscreen) { - x = 0; - y = 0; - width = screen.getWidth(); - height = screen.getHeight(); - } else { - x = nfs_x; - y = nfs_y; - width = nfs_width; - height = nfs_height; - } - MainThread.invoke(true, fullscreenAction); - } + }); return fullscreen; } @@ -538,7 +500,7 @@ public class MacWindow extends Window { super.sendKeyEvent(eventType, modifiers, key, keyChar); } - private void createWindow(boolean recreate) { + private void createWindow(boolean recreate, int x, int y, int width, int height, boolean fullscreen) { if(0!=windowHandle && !recreate) { return; } @@ -554,8 +516,8 @@ public class MacWindow extends Window { surfaceHandle = 0; } windowHandle = createWindow0(parentWindowHandle, - getX(), getY(), getWidth(), getHeight(), fullscreen, - (isUndecorated() ? + x, y, width, height, fullscreen, + (isUndecorated(fullscreen) ? NSBorderlessWindowMask : NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask), NSBackingStoreBuffered, diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java index b25ed4ee8..7d3a0ac8c 100755 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java @@ -70,32 +70,24 @@ public class Window extends com.jogamp.newt.Window { } } - protected void setVisibleImpl() { } + protected void setVisibleImpl(boolean visible) { } - public void setSize(int width, int height) { - System.err.println("setSize "+width+"x"+height+" n/a in BroadcomEGL"); - } - - void setSizeImpl(int width, int height) { + protected void setSizeImpl(int width, int height) { if(0!=windowHandle) { // n/a in BroadcomEGL System.err.println("BCEGL Window.setSizeImpl n/a in BroadcomEGL with realized window"); } else { - if(DEBUG_IMPLEMENTATION) { - Exception e = new Exception("BCEGL Window.setSizeImpl() "+this.width+"x"+this.height+" -> "+width+"x"+height); - e.printStackTrace(); - } this.width = width; this.height = height; } } - public void setPosition(int x, int y) { + protected void setPositionImpl(int x, int y) { // n/a in BroadcomEGL - System.err.println("setPosition n/a in BroadcomEGL"); + System.err.println("BCEGL Window.setPositionImpl n/a in BroadcomEGL"); } - public boolean setFullscreen(boolean fullscreen) { + protected boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { // n/a in BroadcomEGL System.err.println("setFullscreen n/a in BroadcomEGL"); return false; diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java index f60abb7cd..54623996c 100755 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java @@ -85,30 +85,26 @@ public class KDWindow extends Window { } } - protected void setVisibleImpl() { + protected void setVisibleImpl(boolean visible) { setVisible0(eglWindowHandle, visible); - clearEventMask(); } - public void setSize(int width, int height) { + protected void setSizeImpl(int width, int height) { if(0!=eglWindowHandle) { setSize0(eglWindowHandle, width, height); } } - public void setPosition(int x, int y) { + protected void setPositionImpl(int x, int y) { // n/a in KD System.err.println("setPosition n/a in KD"); } - public boolean setFullscreen(boolean fullscreen) { - if(0!=eglWindowHandle && this.fullscreen!=fullscreen) { - this.fullscreen=fullscreen; - if(this.fullscreen) { - setFullScreen0(eglWindowHandle, true); - } else { - setFullScreen0(eglWindowHandle, false); - setSize0(eglWindowHandle, nfs_width, nfs_height); + protected boolean setFullscreenImpl(final boolean fullscreen, final int x, final int y, final int w, final int h) { + if(0!=eglWindowHandle) { + setFullScreen0(eglWindowHandle, fullscreen); + if(!fullscreen) { + setSize0(eglWindowHandle, w, h); } } return true; diff --git a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java index dad3456d7..5e1b5a43c 100755 --- a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java @@ -131,13 +131,28 @@ public class WindowsWindow extends Window { protected void closeNative() { if (hdc != 0) { if(windowHandleClose != 0) { - ReleaseDC0(windowHandleClose, hdc); + try { + ReleaseDC0(windowHandleClose, hdc); + } catch (Throwable t) { + if(DEBUG_IMPLEMENTATION) { + Exception e = new Exception("closeNative failed - "+Thread.currentThread().getName(), t); + e.printStackTrace(); + } + } } hdc = 0; } if(windowHandleClose != 0) { - DestroyWindow0(windowHandleClose); - windowHandleClose = 0; + try { + DestroyWindow0(windowHandleClose); + } catch (Throwable t) { + if(DEBUG_IMPLEMENTATION) { + Exception e = new Exception("closeNative failed - "+Thread.currentThread().getName(), t); + e.printStackTrace(); + } + } finally { + windowHandleClose = 0; + } } } @@ -146,66 +161,32 @@ public class WindowsWindow extends Window { super.windowDestroyed(); } - protected void setVisibleImpl() { + protected void setVisibleImpl(boolean visible) { setVisible0(windowHandle, visible); } - // @Override - public void setSize(int width, int height) { - if (width != this.width || this.height != height) { - if(!fullscreen) { - nfs_width=width; - nfs_height=height; - if(0!=windowHandle) { - // this width/height will be set by sizeChanged, called by Windows - setSize0(parentWindowHandle, windowHandle, x, y, width, height); - } else { - this.width=width; - this.height=height; - } - } - } + protected void setSizeImpl(int width, int height) { + // this width/height will be set by sizeChanged, called by Windows + setSize0(parentWindowHandle, windowHandle, x, y, width, height); } - //@Override - public void setPosition(int x, int y) { - if ( this.x != x || this.y != y ) { - if(!fullscreen) { - nfs_x=x; - nfs_y=y; - if(0!=windowHandle) { - // this x/y will be set by positionChanged, called by Windows - setPosition0(parentWindowHandle, windowHandle, x , y /*, width, height*/); - } else { - this.x=x; - this.y=y; - } - } - } + protected void setPositionImpl(int x, int y) { + // this x/y will be set by positionChanged, called by Windows + setPosition0(parentWindowHandle, windowHandle, x , y /*, width, height*/); } - public boolean setFullscreen(boolean fullscreen) { - if(0!=windowHandle && (this.fullscreen!=fullscreen)) { - int x,y,w,h; - this.fullscreen=fullscreen; - if(fullscreen) { - x = 0; y = 0; - w = screen.getWidth(); - h = screen.getHeight(); - } else { - x = nfs_x; - y = nfs_y; - w = nfs_width; - h = nfs_height; - } - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - System.err.println("WindowsWindow fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h); - } - setFullscreen0(parentWindowHandle, windowHandle, x, y, w, h, undecorated, fullscreen); - } + protected boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { + setFullscreen0(fullscreen?0:parentWindowHandle, windowHandle, x, y, w, h, isUndecorated(fullscreen)); return fullscreen; } + protected boolean reparentWindowImpl() { + if(0!=windowHandle) { + reparentWindow0(fullscreen?0:parentWindowHandle, windowHandle, x, y, width, height, isUndecorated()); + } + return true; + } + // @Override public void requestFocus() { super.requestFocus(); @@ -245,7 +226,8 @@ public class WindowsWindow extends Window { private static native void setVisible0(long windowHandle, boolean visible); private native void setSize0(long parentWindowHandle, long windowHandle, int x, int y, int width, int height); private static native void setPosition0(long parentWindowHandle, long windowHandle, int x, int y /*, int width, int height*/); - private native void setFullscreen0(long parentWindowHandle, long windowHandle, int x, int y, int width, int height, boolean isUndecorated, boolean on); + private native void setFullscreen0(long parentWindowHandle, long windowHandle, int x, int y, int width, int height, boolean isUndecorated); + private native void reparentWindow0(long parentWindowHandle, long windowHandle, int x, int y, int width, int height, boolean isUndecorated); private static native void setTitle0(long windowHandle, String title); private static native void requestFocus0(long windowHandle); diff --git a/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java b/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java index 085d1cab7..a51eee241 100755 --- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java @@ -55,13 +55,12 @@ public class X11Window extends Window { if (config == null) { throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } - attachedToParent = 0 != parentWindowHandle ; X11GraphicsConfiguration x11config = (X11GraphicsConfiguration) config; long visualID = x11config.getVisualID(); long w = CreateWindow0(parentWindowHandle, display.getHandle(), screen.getIndex(), visualID, display.getJavaObjectAtom(), display.getWindowDeleteAtom(), - x, y, width, height, undecorated()); + x, y, width, height, isUndecorated()); if (w == 0 || w!=windowHandle) { throw new NativeWindowException("Error creating window: "+w); } @@ -72,9 +71,17 @@ public class X11Window extends Window { protected void closeNative() { if(0!=displayHandleClose && 0!=windowHandleClose && null!=getScreen() ) { X11Display display = (X11Display) getScreen().getDisplay(); - CloseWindow0(displayHandleClose, windowHandleClose, display.getJavaObjectAtom()); - windowHandleClose = 0; - displayHandleClose = 0; + try { + CloseWindow0(displayHandleClose, windowHandleClose, display.getJavaObjectAtom()); + } catch (Throwable t) { + if(DEBUG_IMPLEMENTATION) { + Exception e = new Exception("closeNative failed - "+Thread.currentThread().getName(), t); + e.printStackTrace(); + } + } finally { + windowHandleClose = 0; + displayHandleClose = 0; + } } } @@ -84,72 +91,33 @@ public class X11Window extends Window { super.windowDestroyed(); } - protected void setVisibleImpl() { + protected void setVisibleImpl(boolean visible) { setVisible0(getDisplayHandle(), windowHandle, visible); - clearEventMask(); } - public void setSize(int width, int height) { - if(DEBUG_IMPLEMENTATION) { - System.err.println("X11Window setSize: "+this.width+"x"+this.height+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+windowHandle); - } - if (width != this.width || this.height != height) { - if(!fullscreen) { - nfs_width=width; - nfs_height=height; - if(0!=windowHandle) { - // this width/height will be set by windowChanged, called by X11 - setSize0(getDisplayHandle(), windowHandle, width, height); - } else { - this.width = width; - this.height = height; - } - } - } + protected void setSizeImpl(int width, int height) { + // this width/height will be set by windowChanged, called by X11 + setSize0(getDisplayHandle(), windowHandle, width, height); } - public void setPosition(int x, int y) { - if(DEBUG_IMPLEMENTATION) { - System.err.println("X11Window setPosition: "+this.x+"/"+this.y+" -> "+x+"/"+y+", fs "+fullscreen+", windowHandle "+windowHandle); - } - if ( this.x != x || this.y != y ) { - if(!fullscreen) { - nfs_x=x; - nfs_y=y; - if(0!=windowHandle) { - // this x/y will be set by windowChanged, called by X11 - setPosition0(parentWindowHandle, getDisplayHandle(), windowHandle, x, y); - } else { - this.x = x; - this.y = y; - } - } - } + protected void setPositionImpl(int x, int y) { + // this x/y will be set by windowChanged, called by X11 + setPosition0(parentWindowHandle, getDisplayHandle(), windowHandle, x, y); } - public boolean setFullscreen(boolean fullscreen) { - if(0!=windowHandle && this.fullscreen!=fullscreen) { - int x,y,w,h; - this.fullscreen=fullscreen; - if(fullscreen) { - x = 0; y = 0; - w = screen.getWidth(); - h = screen.getHeight(); - } else { - x = nfs_x; - y = nfs_y; - w = nfs_width; - h = nfs_height; - } - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - System.err.println("X11Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+undecorated()); - } - setPosSizeDecor0(fullscreen?0:parentWindowHandle, getDisplayHandle(), getScreenIndex(), windowHandle, x, y, w, h, undecorated()); - } + protected boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { + setPosSizeDecor0(fullscreen?0:parentWindowHandle, getDisplayHandle(), getScreenIndex(), windowHandle, x, y, w, h, isUndecorated(fullscreen)); return fullscreen; } - final boolean undecorated() { return attachedToParent || undecorated || fullscreen ; } + protected boolean reparentWindowImpl() { + if(0!=windowHandle) { + reparentWindow0(fullscreen?0:parentWindowHandle, getDisplayHandle(), getScreenIndex(), windowHandle, x, y, isUndecorated()); + // X11 reparent unmaps the window + setVisibleImpl(visible); + } + return true; + } // @Override public void requestFocus() { @@ -187,6 +155,8 @@ public class X11Window extends Window { private native void setTitle0(long display, long windowHandle, String title); private native void requestFocus0(long display, long windowHandle); private native void setPosition0(long parentWindowHandle, long display, long windowHandle, int x, int y); + private native void reparentWindow0(long parentWindowHandle, long display, int screen_index, long windowHandle, + int x, int y, boolean undecorated); private void windowChanged(int newX, int newY, int newWidth, int newHeight) { if(width != newWidth || height != newHeight) { @@ -226,14 +196,17 @@ public class X11Window extends Window { } } + /** + * @param focusGained + */ + private void visibleChanged(boolean visible) { + // FIXME .. this.visible = visible ; + } + private void windowCreated(long windowHandle) { this.windowHandle = windowHandle; } private long windowHandleClose; private long displayHandleClose; - private boolean attachedToParent; - - // non fullscreen dimensions .. - private int nfs_width, nfs_height, nfs_x, nfs_y; } diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index b5d55aebd..2bb28466c 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -35,6 +35,7 @@ package com.jogamp.newt.opengl; import com.jogamp.newt.*; import com.jogamp.newt.event.*; +import com.jogamp.nativewindow.impl.RecursiveToolkitLock; import javax.media.nativewindow.*; import javax.media.opengl.*; import com.jogamp.opengl.impl.GLDrawableHelper; @@ -53,19 +54,15 @@ import java.util.*; *
*/ public class GLWindow extends Window implements GLAutoDrawable { - private static List/*GLWindow*/ glwindows = new ArrayList(); - - private boolean ownerOfWinScrDpy; private Window window; private boolean runPumpMessages; /** * Constructor. Do not call this directly -- use {@link #create()} instead. */ - protected GLWindow(Window window, boolean ownerOfWinScrDpy) { - this.ownerOfWinScrDpy = ownerOfWinScrDpy; + protected GLWindow(Window window) { this.window = window; - this.window.setAutoDrawableClient(true); + this.window.setHandleDestroyNotify(false); this.runPumpMessages = ( null == getScreen().getDisplay().getEDTUtil() ) ; window.addWindowListener(new WindowAdapter() { public void windowResized(WindowEvent e) { @@ -76,10 +73,6 @@ public class GLWindow extends Window implements GLAutoDrawable { sendDestroy = true; } }); - - List newglw = (List) ((ArrayList) glwindows).clone(); - newglw.add(this); - glwindows=newglw; } /** Creates a new GLWindow attaching the given window - not owning the Window. */ @@ -87,10 +80,10 @@ public class GLWindow extends Window implements GLAutoDrawable { return create(null, window, null, false); } - /** Creates a new GLWindow attaching a new native child Window of the given
parentWindowObject
+ /** Creates a new GLWindow attaching a new native child Window of the givenparentNativeWindow
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