From 4e0eb391d6c64f956ea5c87c0385ab48a24b2175 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Tue, 1 May 2012 09:21:14 +0200 Subject: Fix Bug 560 and NEWT window closing behavior in general for all platforms. - NEWT/WindowImpl: - 'void windowDestroyNotify()' -> 'boolean windowDestroyNotify(boolean force)', allowing to signal a forced close, as well as replying whether the window has been closed. (called by native code) - destroy(): set states before releasing the window lock - NEWT/X11: Pass windowDeleteAtom for reconfigure window, in case of reparenting child to top-level - NEWT/OSX: - Add 'BOOL windowShouldClose()' impl., ie. having a chance to reject the close attempt - Common impl. for 'windowShouldClose' and 'windowWillClose' -> 'windowClosingImpl' utilizing new 'windowDestroyNotify' code (see above). Fixes bug 560. - NEWT/JOGLNewtApplet1Run: Refine out-of browser window behavior for window-close button - default: move NEWT window back to browser parent - closeable: close NEWT window - jogl-test-applets: Add NApplet-Closeable test (Applet out-of browser window is closable) --- src/newt/native/KDWindow.c | 8 +++++--- src/newt/native/MacWindow.m | 5 +++++ src/newt/native/NewtMacWindow.h | 8 ++++++++ src/newt/native/NewtMacWindow.m | 35 +++++++++++++++++++++++++++++++---- src/newt/native/WindowsWindow.c | 4 ++-- src/newt/native/X11Display.c | 9 ++++++--- src/newt/native/X11Window.c | 5 ++++- 7 files changed, 61 insertions(+), 13 deletions(-) (limited to 'src/newt/native') diff --git a/src/newt/native/KDWindow.c b/src/newt/native/KDWindow.c index e6bc7952e..dc999138c 100644 --- a/src/newt/native/KDWindow.c +++ b/src/newt/native/KDWindow.c @@ -114,8 +114,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_KDDisplay_DispatchMessages break; case KD_EVENT_WINDOW_CLOSE: { - DBG_PRINT( "event window close : src: %p\n", userData); - (*env)->CallVoidMethod(env, javaWindow, windowDestroyNotifyID); + jboolean closed; + DBG_PRINT( "event window close : src: %p .. \n", userData); + closed = (*env)->CallBooleanMethod(env, javaWindow, windowDestroyNotifyID, JNI_FALSE); + DBG_PRINT( "event window close : src: %p, closed %d\n", userData, (int)closed); } break; case KD_EVENT_WINDOWPROPERTY_CHANGE: @@ -189,7 +191,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_kd_KDWindow_initIDs windowCreatedID = (*env)->GetMethodID(env, clazz, "windowCreated", "(J)V"); sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V"); visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V"); - windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); + windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z"); sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V"); sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); if (windowCreatedID == NULL || diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index 5a35973cd..64871f11d 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -705,6 +705,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_close0 DBG_PRINT( "windowClose.0 - %p,%d, destroyNotifySent %d, view %p,%d, parent %p\n", mWin, getRetainCount(mWin), destroyNotifySent, mView, getRetainCount(mView), pWin); + [mWin setUnrealized]; + if(NULL!=mView) { // cleanup view jobject javaWindowObject = [mView getJavaWindowObject]; @@ -763,6 +765,9 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_lockSurface0 (JNIEnv *env, jclass clazz, jlong window) { NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); + if(NO == [mWin isRealized]) { + return JNI_FALSE; + } NewtView * mView = (NewtView *) [mWin contentView]; return [mView softLock] == YES ? JNI_TRUE : JNI_FALSE; /** deadlocks, since we render independent of focus diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h index aa460ea88..c0912ad3c 100644 --- a/src/newt/native/NewtMacWindow.h +++ b/src/newt/native/NewtMacWindow.h @@ -110,6 +110,7 @@ BOOL mouseVisible; BOOL mouseInside; BOOL cursorIsHidden; + BOOL realized; NSPoint lastInsideMousePosition; @public int cachedInsets[4]; // l, r, t, b @@ -125,6 +126,8 @@ isFullscreenWindow:(BOOL)isfs; - (void) release; - (void) dealloc; +- (void) setUnrealized; +- (BOOL) isRealized; - (void) updateInsets: (JNIEnv*) env; - (void) attachToParent: (NSWindow*) parent; @@ -166,5 +169,10 @@ - (void) rightMouseUp: (NSEvent*) theEvent; - (void) otherMouseDown: (NSEvent*) theEvent; - (void) otherMouseUp: (NSEvent*) theEvent; +- (void) windowDidResize: (NSNotification*) notification; +- (void) windowDidMove: (NSNotification*) notification; +- (BOOL) windowClosingImpl: (BOOL) force; +- (BOOL) windowShouldClose: (id) sender; +- (void) windowWillClose: (NSNotification*) notification; @end diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index 187aec7fb..f914467af 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -337,7 +337,7 @@ static jmethodID windowRepaintID = NULL; insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V"); positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(ZII)V"); focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V"); - windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); + windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z"); windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V"); requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V"); if (enqueueMouseEventID && sendMouseEventID && enqueueKeyEventID && sendKeyEventID && sizeChangedID && visibleChangedID && insetsChangedID && @@ -372,6 +372,7 @@ static jmethodID windowRepaintID = NULL; mouseVisible = YES; mouseInside = NO; cursorIsHidden = NO; + realized = YES; return res; } @@ -393,6 +394,16 @@ static jmethodID windowRepaintID = NULL; [super dealloc]; } +- (void) setUnrealized +{ + realized = NO; +} + +- (BOOL) isRealized +{ + return realized; +} + - (void) updateInsets: (JNIEnv*) env { NSView* nsview = [self contentView]; @@ -942,8 +953,19 @@ static jint mods2JavaMods(NSUInteger mods) } } +- (BOOL)windowShouldClose: (id) sender +{ + return [self windowClosingImpl: NO]; +} + - (void)windowWillClose: (NSNotification*) notification { + [self windowClosingImpl: YES]; +} + +- (BOOL) windowClosingImpl: (BOOL) force +{ + jboolean closed = JNI_FALSE; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [self cursorHide: NO]; @@ -969,17 +991,22 @@ static jint mods2JavaMods(NSUInteger mods) return; } - [view setDestroyNotifySent: true]; - (*env)->CallVoidMethod(env, javaWindowObject, windowDestroyNotifyID); + [view setDestroyNotifySent: true]; // earmark assumption of being closed + closed = (*env)->CallBooleanMethod(env, javaWindowObject, windowDestroyNotifyID, force ? JNI_TRUE : JNI_FALSE); + if(!force && !closed) { + // not closed on java side, not force -> clear flag + [view setDestroyNotifySent: false]; + } if (shallBeDetached) { (*jvmHandle)->DetachCurrentThread(jvmHandle); } - DBG_PRINT( "*************** windowWillClose.X: %p\n", (void *)(intptr_t)javaWindowObject); + DBG_PRINT( "*************** windowWillClose.X: %p, closed %d\n", (void *)(intptr_t)javaWindowObject, (int)closed); } else { DBG_PRINT( "*************** windowWillClose (skip)\n"); } [pool release]; + return JNI_TRUE == closed ? YES : NO ; } @end diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index 97fe6f28d..6d9c04dc3 100644 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -810,7 +810,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, // Java::DestroyWindow(wnd) _or_ window-close-button -> // WM_CLOSE -> Java::windowDestroyNotify -> W_DESTROY case WM_CLOSE: - (*env)->CallVoidMethod(env, window, windowDestroyNotifyID); + (*env)->CallBooleanMethod(env, window, windowDestroyNotifyID, JNI_FALSE); break; case WM_DESTROY: @@ -1297,7 +1297,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_initIDs positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(ZII)V"); focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V"); visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V"); - windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); + windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z"); windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V"); enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZIIIIII)V"); sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V"); diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c index 9b99aebb5..88ac0df7e 100644 --- a/src/newt/native/X11Display.c +++ b/src/newt/native/X11Display.c @@ -266,7 +266,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Display_initIDs0 focusChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "focusChanged", "(ZZ)V"); visibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChanged", "(ZZ)V"); reparentNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "reparentNotify", "(J)V"); - windowDestroyNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowDestroyNotify", "()V"); + windowDestroyNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowDestroyNotify", "(Z)Z"); windowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowRepaint", "(ZIIII)V"); enqueueMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "enqueueMouseEvent", "(ZIIIIII)V"); sendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEvent", "(IIIIII)V"); @@ -563,9 +563,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_DispatchMessages0 break; case ClientMessage: if (evt.xclient.send_event==True && evt.xclient.data.l[0]==wm_delete_atom) { // windowDeleteAtom - DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X\n", + jboolean closed; + DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X ..\n", (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type); - (*env)->CallVoidMethod(env, jwindow, windowDestroyNotifyID); + closed = (*env)->CallBooleanMethod(env, jwindow, windowDestroyNotifyID, JNI_FALSE); + DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X, closed: %d\n", + (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type, (int)closed); // Called by Window.java: CloseWindow(); num_events = 0; // end loop in case of destroyed display } diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index 9d4ff5aaa..0f93b3e76 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -730,11 +730,13 @@ static Bool WaitForReparentNotify( Display *dpy, XEvent *event, XPointer arg ) { * Signature: (JIJJIIIII)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0 - (JNIEnv *env, jobject obj, jlong jdisplay, jint screen_index, jlong jparent, jlong jwindow, + (JNIEnv *env, jobject obj, jlong jdisplay, jint screen_index, + jlong jparent, jlong jwindow, jlong windowDeleteAtom, jint x, jint y, jint width, jint height, jint flags) { Display * dpy = (Display *) (intptr_t) jdisplay; Window w = (Window)jwindow; + Atom wm_delete_atom = (Atom)windowDeleteAtom; Window root = RootWindow(dpy, screen_index); Window parent = (0!=jparent)?(Window)jparent:root; XEvent event; @@ -810,6 +812,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0 XReparentWindow( dpy, w, parent, x, y ); // actual reparent call // XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) w ); XSync(dpy, False); + XSetWMProtocols(dpy, w, &wm_delete_atom, 1); // windowDeleteAtom } if( TST_FLAG_CHANGE_DECORATION(flags) ) { -- cgit v1.2.3