diff options
author | Sven Gothel <[email protected]> | 2010-12-23 06:26:47 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2010-12-23 06:26:47 +0100 |
commit | e7778124162aef7004e040dded5de1eaf5e1ece4 (patch) | |
tree | b750b24a7d3e5c3e008701760af7e9b74b43f4b4 /src | |
parent | 1c2a11a54949188d6704558f7fa38ecf8e811118 (diff) |
NEWT: Add WindowListener.windowDestroyed() ; Remove WindowImpl.windowDestroyed()
Add WindowListener.windowDestroyed()
To expose a proper window lifecycle, ie destroy-notify and destroyed,
this notification is added.
This will be used at least in unit tests, where we verify destruction.
Remove WindowImpl.windowDestroyed():
This native hook (planned to be called by native destroy notification)
is unreliable or not supported for all platforms.
NEWT relies on the pre destroy native hooks and handles the final
destroy notification itself.
Diffstat (limited to 'src')
16 files changed, 158 insertions, 58 deletions
diff --git a/src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java index 88b165a8d..8542820c4 100644 --- a/src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java @@ -52,6 +52,10 @@ public class TraceWindowAdapter implements WindowListener { System.err.println(e); if(null!=downstream) { downstream.windowDestroyNotify(e); } } + public void windowDestroyed(WindowEvent e) { + System.err.println(e); + if(null!=downstream) { downstream.windowDestroyed(e); } + } public void windowGainedFocus(WindowEvent e) { System.err.println(e); if(null!=downstream) { downstream.windowGainedFocus(e); } diff --git a/src/newt/classes/com/jogamp/newt/event/WindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/WindowAdapter.java index a1ad43a13..b9e487e9b 100644 --- a/src/newt/classes/com/jogamp/newt/event/WindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/WindowAdapter.java @@ -36,6 +36,8 @@ public abstract class WindowAdapter implements WindowListener } public void windowDestroyNotify(WindowEvent e) { } + public void windowDestroyed(WindowEvent e) { + } public void windowGainedFocus(WindowEvent e) { } public void windowLostFocus(WindowEvent e) { diff --git a/src/newt/classes/com/jogamp/newt/event/WindowEvent.java b/src/newt/classes/com/jogamp/newt/event/WindowEvent.java index 2742e0d95..f3d62d8c6 100644 --- a/src/newt/classes/com/jogamp/newt/event/WindowEvent.java +++ b/src/newt/classes/com/jogamp/newt/event/WindowEvent.java @@ -46,6 +46,7 @@ public class WindowEvent extends NEWTEvent { public static final int EVENT_WINDOW_GAINED_FOCUS = 103; public static final int EVENT_WINDOW_LOST_FOCUS = 104; public static final int EVENT_WINDOW_REPAINT = 105; + public static final int EVENT_WINDOW_DESTROYED = 106; public WindowEvent(int eventType, Object source, long when) { super(eventType, source, when); @@ -54,11 +55,12 @@ public class WindowEvent extends NEWTEvent { public static String getEventTypeString(int type) { switch(type) { case EVENT_WINDOW_RESIZED: return "WINDOW_RESIZED"; - case EVENT_WINDOW_MOVED: return "WINDOW_MOVED"; - case EVENT_WINDOW_DESTROY_NOTIFY: return "EVENT_WINDOW_DESTROY_NOTIFY"; - case EVENT_WINDOW_GAINED_FOCUS: return "EVENT_WINDOW_GAINED_FOCUS"; - case EVENT_WINDOW_LOST_FOCUS: return "EVENT_WINDOW_LOST_FOCUS"; - case EVENT_WINDOW_REPAINT: return "EVENT_WINDOW_REPAINT"; + case EVENT_WINDOW_MOVED: return "WINDOW_MOVED"; + case EVENT_WINDOW_DESTROY_NOTIFY: return "EVENT_WINDOW_DESTROY_NOTIFY"; + case EVENT_WINDOW_GAINED_FOCUS: return "EVENT_WINDOW_GAINED_FOCUS"; + case EVENT_WINDOW_LOST_FOCUS: return "EVENT_WINDOW_LOST_FOCUS"; + case EVENT_WINDOW_REPAINT: return "EVENT_WINDOW_REPAINT"; + case EVENT_WINDOW_DESTROYED: return "EVENT_WINDOW_DESTROYED"; default: return "unknown (" + type + ")"; } } diff --git a/src/newt/classes/com/jogamp/newt/event/WindowListener.java b/src/newt/classes/com/jogamp/newt/event/WindowListener.java index 0d201a2a4..e841a06cf 100644 --- a/src/newt/classes/com/jogamp/newt/event/WindowListener.java +++ b/src/newt/classes/com/jogamp/newt/event/WindowListener.java @@ -44,6 +44,9 @@ public interface WindowListener extends NEWTEventListener { /** Window will be destroyed. Release of resources is recommended. */ public void windowDestroyNotify(WindowEvent e); + /** Window has been destroyed.*/ + public void windowDestroyed(WindowEvent e); + /** Window gained focus. */ public void windowGainedFocus(WindowEvent e); diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTNewtEventFactory.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTNewtEventFactory.java index 8e33285bf..20c0d15d1 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTNewtEventFactory.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTNewtEventFactory.java @@ -39,7 +39,7 @@ class AWTNewtEventFactory { map.setKeyNotFoundValue(-1); // n/a map.put(java.awt.event.WindowEvent.WINDOW_OPENED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_OPENED); map.put(java.awt.event.WindowEvent.WINDOW_CLOSING, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); - // n/a map.put(java.awt.event.WindowEvent.WINDOW_CLOSED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_CLOSED); + map.put(java.awt.event.WindowEvent.WINDOW_CLOSED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DESTROYED); // n/a map.put(java.awt.event.WindowEvent.WINDOW_ICONIFIED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_ICONIFIED); // n/a map.put(java.awt.event.WindowEvent.WINDOW_DEICONIFIED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DEICONIFIED); map.put(java.awt.event.WindowEvent.WINDOW_ACTIVATED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS); diff --git a/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java b/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java index e04bd1208..9dace822f 100644 --- a/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java +++ b/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java @@ -759,11 +759,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } if(null!=lifecycleHook) { + // send synced destroy notification for proper cleanup, eg GLWindow/OpenGL lifecycleHook.destroyActionInLock(); } closeAndInvalidate(); + // send synced destroyed notification + sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROYED); + if(DEBUG_IMPLEMENTATION) { System.err.println("Window.destroy() END "+getThreadName()/*+", "+WindowImpl.this*/); } @@ -2028,6 +2032,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer case WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY: l.windowDestroyNotify(e); break; + case WindowEvent.EVENT_WINDOW_DESTROYED: + l.windowDestroyed(e); + break; case WindowEvent.EVENT_WINDOW_GAINED_FOCUS: l.windowGainedFocus(e); break; @@ -2119,7 +2126,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer System.err.println("Window.windowDestroyNotify START "+getThreadName()); } - enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); + // send synced destroy notifications + enqueueWindowEvent(true, WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); if(handleDestroyNotify && DISPOSE_ON_CLOSE == defaultCloseOperation && isValid()) { destroy(); @@ -2130,13 +2138,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } - protected void windowDestroyed() { - if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.windowDestroyed "+getThreadName()); - } - closeAndInvalidate(); - } - public void windowRepaint(int x, int y, int width, int height) { if(DEBUG_IMPLEMENTATION) { System.err.println("Window.windowRepaint "+getThreadName()+" - "+x+"/"+y+" "+width+"x"+height); 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 c01139b78..e789a0dc9 100644 --- a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java @@ -166,7 +166,6 @@ public class MacWindow extends WindowImpl { setWindowHandle(0); nsViewLock.unlock(); } - windowDestroyed(); // No OSX hook for DidClose, so do it here } public final long getSurfaceHandle() { 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 9bc4667c5..5ab0a5b79 100644 --- a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java @@ -140,11 +140,6 @@ public class WindowsWindow extends WindowImpl { } } - protected void windowDestroyed() { - windowHandleClose = 0; - super.windowDestroyed(); - } - protected void setVisibleImpl(boolean visible, int x, int y, int width, int height) { setVisible0(getWindowHandle(), visible, (getParentWindowHandle()==0)?true:false, x, y, width, height); visibleChanged(visible); 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 73c6eb351..b8f1a0c95 100644 --- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java @@ -87,11 +87,6 @@ public class X11Window extends WindowImpl { } } - protected void windowDestroyed() { - windowHandleClose = 0; - super.windowDestroyed(); - } - protected void setVisibleImpl(boolean visible, int x, int y, int width, int height) { setVisible0(getDisplayHandle(), getWindowHandle(), visible, x, y, width, height); } diff --git a/src/newt/native/KDWindow.c b/src/newt/native/KDWindow.c index 33af4d963..50ad22b5a 100644 --- a/src/newt/native/KDWindow.c +++ b/src/newt/native/KDWindow.c @@ -94,7 +94,6 @@ static jmethodID windowCreatedID = NULL; static jmethodID sizeChangedID = NULL; static jmethodID visibleChangedID = NULL; static jmethodID windowDestroyNotifyID = NULL; -static jmethodID windowDestroyedID = NULL; static jmethodID sendMouseEventID = NULL; static jmethodID sendKeyEventID = NULL; @@ -137,8 +136,6 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_opengl_kd_KDDisplay_DispatchMes { DBG_PRINT( "event window close : src: %p\n", userData); (*env)->CallVoidMethod(env, javaWindow, windowDestroyNotifyID); - // Called by Window.java: DestroyWindow(wnd); - // (*env)->CallVoidMethod(env, javaWindow, windowDestroyedID); } break; case KD_EVENT_WINDOWPROPERTY_CHANGE: @@ -213,14 +210,12 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_opengl_kd_KDWindow_initIDs sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(IIZ)V"); visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); - windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V"); sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V"); sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); if (windowCreatedID == NULL || sizeChangedID == NULL || visibleChangedID == NULL || windowDestroyNotifyID == NULL || - windowDestroyedID == NULL || sendMouseEventID == NULL || sendKeyEventID == NULL) { DBG_PRINT( "initIDs failed\n" ); diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index 2d8a84b4b..cba69498a 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -80,7 +80,6 @@ static jmethodID visibleChangedID = NULL; static jmethodID positionChangedID = NULL; static jmethodID focusChangedID = NULL; static jmethodID windowDestroyNotifyID = NULL; -static jmethodID windowDestroyedID = NULL; @implementation NewtView - (void) setJNIEnv: (JNIEnv*) theEnv @@ -142,9 +141,8 @@ static jmethodID windowDestroyedID = NULL; positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(II)V"); focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(Z)V"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); - windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V"); if (sendMouseEventID && sendKeyEventID && sizeChangedID && visibleChangedID && insetsChangedID && - positionChangedID && focusChangedID && windowDestroyedID && windowDestroyNotifyID) + positionChangedID && focusChangedID && windowDestroyNotifyID) { return YES; } @@ -456,7 +454,6 @@ static jint mods2JavaMods(NSUInteger mods) (*env)->CallVoidMethod(env, javaWindowObject, windowDestroyNotifyID); // Can't issue call here - locked window state, done from Java method - // (*env)->CallVoidMethod(env, javaWindowObject, windowDestroyedID); // No OSX hook for DidClose, so do it here // EOL .. (*env)->DeleteGlobalRef(env, javaWindowObject); diff --git a/src/newt/native/WindowEvent.h b/src/newt/native/WindowEvent.h index 6274f9443..05491b43c 100644 --- a/src/newt/native/WindowEvent.h +++ b/src/newt/native/WindowEvent.h @@ -2,11 +2,12 @@ #ifndef _WINDOW_EVENT_H_ #define _WINDOW_EVENT_H_ -#define EVENT_WINDOW_RESIZED = 100; -#define EVENT_WINDOW_MOVED = 101; -#define EVENT_WINDOW_DESTROY_NOTIFY = 102; -#define EVENT_WINDOW_GAINED_FOCUS = 103; -#define EVENT_WINDOW_LOST_FOCUS = 104; -#define EVENT_WINDOW_REPAINT = 105; // TODO +#define EVENT_WINDOW_RESIZED 100 +#define EVENT_WINDOW_MOVED 101 +#define EVENT_WINDOW_DESTROY_NOTIFY 102 +#define EVENT_WINDOW_GAINED_FOCUS 103 +#define EVENT_WINDOW_LOST_FOCUS 104 +#define EVENT_WINDOW_REPAINT 105 +#define EVENT_WINDOW_DESTROYED 106 #endif diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index cafdaeef8..998743e75 100644 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -124,7 +124,6 @@ static jmethodID positionChangedID = NULL; static jmethodID focusChangedID = NULL; static jmethodID visibleChangedID = NULL; static jmethodID windowDestroyNotifyID = NULL; -static jmethodID windowDestroyedID = NULL; static jmethodID windowRepaintID = NULL; static jmethodID enqueueMouseEventID = NULL; static jmethodID sendMouseEventID = NULL; @@ -820,8 +819,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, // // The signal pipeline for destruction is: // Java::DestroyWindow(wnd) _or_ window-close-button -> - // WM_CLOSE -> Java::windowDestroyNotify -> W_DESTROY -> Java::windowDestroyed -> - // Java::CleanupWindowResources() + // WM_CLOSE -> Java::windowDestroyNotify -> W_DESTROY case WM_CLOSE: (*env)->CallVoidMethod(env, window, windowDestroyNotifyID); break; @@ -834,7 +832,6 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, SetWindowLongPtr(wnd, GWLP_USERDATA, (intptr_t) NULL); #endif free(wud); wud=NULL; - (*env)->CallVoidMethod(env, window, windowDestroyedID); (*env)->DeleteGlobalRef(env, window); } break; @@ -1267,7 +1264,6 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_initI focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(Z)V"); visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); - windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V"); windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(IIII)V"); enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZIIIIII)V"); sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V"); @@ -1282,7 +1278,6 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_initI focusChangedID == NULL || visibleChangedID == NULL || windowDestroyNotifyID == NULL || - windowDestroyedID == NULL || windowRepaintID == NULL || enqueueMouseEventID == NULL || sendMouseEventID == NULL || diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index 15418269e..d30e5de59 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -147,7 +147,6 @@ static jmethodID positionChangedID = NULL; static jmethodID focusChangedID = NULL; static jmethodID visibleChangedID = NULL; static jmethodID windowDestroyNotifyID = NULL; -static jmethodID windowDestroyedID = NULL; static jmethodID windowRepaintID = NULL; static jmethodID windowReparentedID = NULL; static jmethodID enqueueMouseEventID = NULL; @@ -624,7 +623,6 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_DispatchMessages (void*)evt.xdestroywindow.window, (void*)evt.xdestroywindow.event, evt.xdestroywindow.window != evt.xdestroywindow.event); if ( evt.xdestroywindow.window == evt.xdestroywindow.event ) { // ignore child destroy notification - (*env)->CallVoidMethod(env, jwindow, windowDestroyedID); } break; case CreateNotify: @@ -1191,7 +1189,6 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_x11_X11Window_initIDs0 focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(Z)V"); visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); - windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V"); windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(IIII)V"); windowReparentedID = (*env)->GetMethodID(env, clazz, "windowReparented", "(J)V"); enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZIIIIII)V"); @@ -1206,7 +1203,6 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_x11_X11Window_initIDs0 focusChangedID == NULL || visibleChangedID == NULL || windowDestroyNotifyID == NULL || - windowDestroyedID == NULL || windowRepaintID == NULL || windowReparentedID == NULL || enqueueMouseEventID == NULL || @@ -1394,8 +1390,6 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CloseWindow0 (*env)->DeleteGlobalRef(env, jwindow); DBG_PRINT( "X11: CloseWindow END\n"); - - (*env)->CallVoidMethod(env, obj, windowDestroyedID); } static void NewtWindows_setPosSize(Display *dpy, Window w, jint x, jint y, jint width, jint height) diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/WindowAction.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/WindowAction.java index bb4008e57..05793b96e 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/WindowAction.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/WindowAction.java @@ -40,5 +40,8 @@ class WindowAction extends WindowAdapter { public void windowDestroyNotify(WindowEvent e) { eventFifo.put(e); } + public void windowDestroyed(WindowEvent e) { + eventFifo.put(e); + } } diff --git a/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java b/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java index 9812be5f2..4a2a181ed 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java +++ b/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java @@ -40,6 +40,7 @@ import java.awt.Rectangle; import java.awt.Robot; import java.awt.Toolkit; import java.awt.event.InputEvent; +import javax.media.opengl.awt.GLCanvas; import javax.swing.JFrame; public class AWTRobotUtil { @@ -348,22 +349,135 @@ public class AWTRobotUtil { } /** - * Programmatically issue windowClosing on AWT or NEWT + * + * @return True if the Component becomes realized (not displayable, native invalid) within TIME_OUT + */ + public static boolean waitForRealized(Object obj, boolean realized) throws InterruptedException { + int wait; + if(obj instanceof GLCanvas) { + GLCanvas comp = (GLCanvas) obj; + for (wait=0; wait<POLL_DIVIDER && realized != comp.isRealized(); wait++) { + Thread.sleep(TIME_OUT/POLL_DIVIDER); + } + } else if (obj instanceof Component) { + Component comp = (Component) obj; + for (wait=0; wait<POLL_DIVIDER && realized != comp.isDisplayable(); wait++) { + Thread.sleep(TIME_OUT/POLL_DIVIDER); + } + } else if(obj instanceof com.jogamp.newt.Window) { + com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj; + for (wait=0; wait<POLL_DIVIDER && realized != win.isNativeValid(); wait++) { + Thread.sleep(TIME_OUT/POLL_DIVIDER); + } + } else { + throw new RuntimeException("Neither AWT nor NEWT: "+obj); + } + return wait<POLL_DIVIDER; + } + + /** + * Programmatically issue windowClosing on AWT or NEWT. + * Wait until the window is closing within TIME_OUT. * * @param obj either an AWT Window (Frame, JFrame) or NEWT Window + * @param willClose indicating that the window will close, hence this method waits for the window to be closed + * @return True if the Window is closing and closed (if willClose is true), each within TIME_OUT * @throws InterruptedException */ - public static void closeWindow(Object obj) throws InterruptedException { + public static boolean closeWindow(Object obj, boolean willClose) throws InterruptedException, InvocationTargetException { + WindowClosingListener closingListener = addClosingListener(obj); if(obj instanceof java.awt.Window) { - java.awt.Window win = (java.awt.Window) obj; + final java.awt.Window win = (java.awt.Window) obj; Toolkit tk = Toolkit.getDefaultToolkit(); - EventQueue evtQ = tk.getSystemEventQueue(); - evtQ.postEvent(new java.awt.event.WindowEvent(win, java.awt.event.WindowEvent.WINDOW_CLOSING)); + final EventQueue evtQ = tk.getSystemEventQueue(); + EventQueue.invokeAndWait(new Runnable() { + public void run() { + evtQ.postEvent(new java.awt.event.WindowEvent(win, java.awt.event.WindowEvent.WINDOW_CLOSING)); + } }); } else if(obj instanceof com.jogamp.newt.Window) { com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj; WindowImplAccess.windowDestroyNotify(win); } - Thread.sleep(200); + int wait; + for (wait=0; wait<POLL_DIVIDER && !closingListener.isWindowClosing(); wait++) { + Thread.sleep(TIME_OUT/POLL_DIVIDER); + } + if(wait<POLL_DIVIDER && willClose) { + for (wait=0; wait<POLL_DIVIDER && !closingListener.isWindowClosed(); wait++) { + Thread.sleep(TIME_OUT/POLL_DIVIDER); + } + } + return wait<POLL_DIVIDER; } + + public static WindowClosingListener addClosingListener(Object obj) throws InterruptedException { + WindowClosingListener cl = null; + if(obj instanceof java.awt.Window) { + java.awt.Window win = (java.awt.Window) obj; + AWTWindowClosingAdapter acl = new AWTWindowClosingAdapter(); + win.addWindowListener(acl); + cl = acl; + } else if(obj instanceof com.jogamp.newt.Window) { + com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj; + NEWTWindowClosingAdapter ncl = new NEWTWindowClosingAdapter(); + win.addWindowListener(ncl); + cl = ncl; + } else { + throw new RuntimeException("Neither AWT nor NEWT: "+obj); + } + return cl; + } + public static interface WindowClosingListener { + void reset(); + public boolean isWindowClosing(); + public boolean isWindowClosed(); + } + static class AWTWindowClosingAdapter + extends java.awt.event.WindowAdapter implements WindowClosingListener + { + volatile boolean closing = false; + volatile boolean closed = false; + + public void reset() { + closing = false; + closed = false; + } + public boolean isWindowClosing() { + return closing; + } + public boolean isWindowClosed() { + return closed; + } + public void windowClosing(java.awt.event.WindowEvent e) { + closing = true; + } + public void windowClosed(java.awt.event.WindowEvent e) { + closed = true; + } + } + static class NEWTWindowClosingAdapter + extends com.jogamp.newt.event.WindowAdapter implements WindowClosingListener + { + volatile boolean closing = false; + volatile boolean closed = false; + + public void reset() { + closing = false; + closed = false; + } + public boolean isWindowClosing() { + return closing; + } + public boolean isWindowClosed() { + return closed; + } + public void windowDestroyNotify(com.jogamp.newt.event.WindowEvent e) { + closing = true; + } + public void windowDestroyed(com.jogamp.newt.event.WindowEvent e) { + closed = true; + } + } + } |