aboutsummaryrefslogtreecommitdiffstats
path: root/src/newt
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2012-05-01 09:21:14 +0200
committerSven Gothel <[email protected]>2012-05-01 09:21:14 +0200
commit4e0eb391d6c64f956ea5c87c0385ab48a24b2175 (patch)
tree69f0f45c73fc7fe2a95a678e75fa5fb4262911db /src/newt
parent5742b1faa210401470032ef129e56a83c47fd046 (diff)
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)
Diffstat (limited to 'src/newt')
-rwxr-xr-xsrc/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java9
-rwxr-xr-xsrc/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java27
-rw-r--r--src/newt/classes/jogamp/newt/WindowImpl.java42
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java5
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java14
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/X11Window.java8
-rw-r--r--src/newt/native/KDWindow.c8
-rw-r--r--src/newt/native/MacWindow.m5
-rw-r--r--src/newt/native/NewtMacWindow.h8
-rw-r--r--src/newt/native/NewtMacWindow.m35
-rw-r--r--src/newt/native/WindowsWindow.c4
-rw-r--r--src/newt/native/X11Display.c9
-rw-r--r--src/newt/native/X11Window.c5
13 files changed, 138 insertions, 41 deletions
diff --git a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java
index a052f6f97..82562636b 100755
--- a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java
+++ b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java
@@ -36,6 +36,7 @@ import java.awt.event.KeyListener;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
+import javax.media.nativewindow.WindowClosingProtocol;
import javax.media.opengl.FPSCounter;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
@@ -64,7 +65,7 @@ import com.jogamp.newt.opengl.GLWindow;
* </p>
*
* <p>
- * Example of an applet tag using GearsES2 in an undecorated, translucent and always-on-top window:
+ * Example of an applet tag using GearsES2 in an undecorated, translucent, closeable and always-on-top window:
* <pre>
&lt;applet width=1 height=1&gt;
&lt;param name="java_arguments" value="-Dsun.java2d.noddraw=true"&gt;
@@ -73,6 +74,7 @@ import com.jogamp.newt.opengl.GLWindow;
&lt;param name="gl_swap_interval" value="1"&gt;
&lt;param name="gl_undecorated" value="true"&gt;
&lt;param name="gl_alwaysontop" value="true"&gt;
+ &lt;param name="gl_closeable" value="true"&gt;
&lt;param name="gl_alpha" value="1"&gt;
&lt;param name="gl_multisamplebuffer" value="0"&gt;
&lt;param name="gl_opaque" value="false"&gt;
@@ -115,6 +117,7 @@ public class JOGLNewtApplet1Run extends Applet {
boolean glTrace=false;
boolean glUndecorated=false;
boolean glAlwaysOnTop=false;
+ boolean glCloseable=false;
boolean glOpaque=true;
int glAlphaBits=0;
int glNumMultisampleBuffer=0;
@@ -128,6 +131,7 @@ public class JOGLNewtApplet1Run extends Applet {
glTrace = JOGLNewtAppletBase.str2Bool(getParameter("gl_trace"), glTrace);
glUndecorated = JOGLNewtAppletBase.str2Bool(getParameter("gl_undecorated"), glUndecorated);
glAlwaysOnTop = JOGLNewtAppletBase.str2Bool(getParameter("gl_alwaysontop"), glAlwaysOnTop);
+ glCloseable = JOGLNewtAppletBase.str2Bool(getParameter("gl_closeable"), glCloseable);
glOpaque = JOGLNewtAppletBase.str2Bool(getParameter("gl_opaque"), glOpaque);
glAlphaBits = JOGLNewtAppletBase.str2Int(getParameter("gl_alpha"), glAlphaBits);
glNumMultisampleBuffer = JOGLNewtAppletBase.str2Int(getParameter("gl_multisamplebuffer"), glNumMultisampleBuffer);
@@ -157,6 +161,7 @@ public class JOGLNewtApplet1Run extends Applet {
System.err.println("glTrace: "+glTrace);
System.err.println("glUndecorated: "+glUndecorated);
System.err.println("glAlwaysOnTop: "+glAlwaysOnTop);
+ System.err.println("glCloseable: "+glCloseable);
System.err.println("glOpaque: "+glOpaque);
System.err.println("glAlphaBits: "+glAlphaBits);
System.err.println("glNumMultisampleBuffer: "+glNumMultisampleBuffer);
@@ -166,6 +171,7 @@ public class JOGLNewtApplet1Run extends Applet {
base = new JOGLNewtAppletBase(glEventListenerClazzName,
glSwapInterval,
glNoDefaultKeyListener,
+ glCloseable,
glDebug,
glTrace);
@@ -181,6 +187,7 @@ public class JOGLNewtApplet1Run extends Applet {
glWindow.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, System.err);
glWindow.setUndecorated(glUndecorated);
glWindow.setAlwaysOnTop(glAlwaysOnTop);
+ glWindow.setDefaultCloseOperation(glCloseable ? WindowClosingProtocol.DISPOSE_ON_CLOSE : WindowClosingProtocol.DO_NOTHING_ON_CLOSE);
container.setLayout(new BorderLayout());
if(appletDebugTestBorder) {
container.add(new Button("North"), BorderLayout.NORTH);
diff --git a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java
index 67da50210..9ffc24372 100755
--- a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java
+++ b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java
@@ -32,6 +32,7 @@ import java.security.AccessController;
import java.security.PrivilegedAction;
import javax.media.nativewindow.NativeWindow;
+import javax.media.nativewindow.WindowClosingProtocol;
import javax.media.opengl.FPSCounter;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
@@ -43,8 +44,10 @@ import jogamp.newt.Debug;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.KeyListener;
import com.jogamp.newt.event.MouseListener;
+import com.jogamp.newt.event.WindowAdapter;
import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.event.WindowListener;
+import com.jogamp.newt.event.WindowUpdateEvent;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.util.Animator;
@@ -58,6 +61,7 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
String glEventListenerClazzName;
int glSwapInterval;
boolean noDefaultKeyListener;
+ boolean glClosable;
boolean glDebug;
boolean glTrace;
@@ -70,12 +74,14 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
public JOGLNewtAppletBase(String glEventListenerClazzName,
int glSwapInterval,
boolean noDefaultKeyListener,
+ boolean glClosable,
boolean glDebug,
boolean glTrace) {
this.glEventListenerClazzName=glEventListenerClazzName;
this.glSwapInterval=glSwapInterval;
this.noDefaultKeyListener = noDefaultKeyListener;
+ this.glClosable = glClosable;
this.glDebug = glDebug;
this.glTrace = glTrace;
}
@@ -152,9 +158,25 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
init(Thread.currentThread().getThreadGroup(), glWindow);
}
- public void init(ThreadGroup tg, GLWindow glWindow) {
+ public void init(ThreadGroup tg, final GLWindow glWindow) {
isValid = false;
this.glWindow = glWindow;
+ this.glWindow.addWindowListener(new WindowAdapter() {
+ // Closing action: back to parent!
+ @Override
+ public void windowDestroyNotify(WindowEvent e) {
+ if( WindowClosingProtocol.DO_NOTHING_ON_CLOSE == glWindow.getDefaultCloseOperation() ) {
+ if(null == glWindow.getParent()) {
+ // we may be called directly by the native EDT
+ new Thread(new Runnable() {
+ public void run() {
+ // try { Thread.sleep(10); } catch (InterruptedException e) { }
+ glWindow.reparentWindow(awtParent);
+ }
+ }).start();
+ }
+ }
+ } } );
glEventListener = createInstance(glEventListenerClazzName);
if(null == glEventListener) {
@@ -277,6 +299,9 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
glWindow.reparentWindow(awtParent);
} else {
glWindow.reparentWindow(null);
+ if(glClosable) {
+ glWindow.setDefaultCloseOperation(WindowClosingProtocol.DISPOSE_ON_CLOSE);
+ }
}
}
}
diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java
index 3d465e45c..5e393f7c5 100644
--- a/src/newt/classes/jogamp/newt/WindowImpl.java
+++ b/src/newt/classes/jogamp/newt/WindowImpl.java
@@ -66,6 +66,7 @@ import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.SurfaceUpdatedListener;
+import javax.media.nativewindow.WindowClosingProtocol;
import javax.media.nativewindow.util.DimensionImmutable;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.InsetsImmutable;
@@ -428,12 +429,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
* The implementation should invoke the referenced java state callbacks
* to notify this Java object of state changes.</p>
*
- * @see #windowDestroyNotify()
+ * @see #windowDestroyNotify(boolean)
* @see #focusChanged(boolean, boolean)
* @see #visibleChanged(boolean, boolean)
* @see #sizeChanged(int,int)
* @see #positionChanged(boolean,int, int)
- * @see #windowDestroyNotify()
+ * @see #windowDestroyNotify(boolean)
*/
protected abstract void createNativeImpl();
@@ -908,16 +909,18 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
System.err.println("Window.destroy() END "+getThreadName()/*+", "+WindowImpl.this*/);
}
} finally {
+ // update states before release window lock
+ setWindowHandle(0);
+ visible = false;
+ fullscreen = false;
+ hasFocus = false;
+ parentWindowHandle = 0;
+
windowLock.unlock();
}
if(animatorPaused) {
lifecycleHook.resumeRenderingAction();
}
- setWindowHandle(0);
- visible = false;
- fullscreen = false;
- hasFocus = false;
- parentWindowHandle = 0;
// these refs shall be kept alive - resurrection via setVisible(true)
/**
@@ -1525,8 +1528,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
/**
* If set to true, the default value, this NEWT Window implementation will
- * handle the destruction (ie {@link #destroy()} call) within {@link #windowDestroyNotify()} implementation.<br>
- * If set to false, it's up to the caller/owner to handle destruction within {@link #windowDestroyNotify()}.
+ * handle the destruction (ie {@link #destroy()} call) within {@link #windowDestroyNotify(boolean)} implementation.<br>
+ * If set to false, it's up to the caller/owner to handle destruction within {@link #windowDestroyNotify(boolean)}.
*/
public void setHandleDestroyNotify(boolean b) {
handleDestroyNotify = b;
@@ -2498,21 +2501,34 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
- protected void windowDestroyNotify() {
+ /**
+ * Triggered by implementation's WM events or programmatically
+ *
+ * @param force if true, overrides {@link #setDefaultCloseOperation(int)} with {@link WindowClosingProtocol#DISPOSE_ON_CLOSE}
+ * and hence force destruction. Otherwise is follows the user settings.
+ * @return true if this window is no more valid and hence has been destroyed, otherwise false.
+ */
+ protected boolean windowDestroyNotify(boolean force) {
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.windowDestroyNotify START "+getThreadName());
+ System.err.println("Window.windowDestroyNotify(force: "+force+") START "+getThreadName()+": "+this);
+ }
+ if(force) {
+ setDefaultCloseOperation(WindowClosingProtocol.DISPOSE_ON_CLOSE);
}
// send synced destroy notifications
enqueueWindowEvent(true, WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
- if(handleDestroyNotify && DISPOSE_ON_CLOSE == defaultCloseOperation) {
+ if(handleDestroyNotify && DISPOSE_ON_CLOSE == getDefaultCloseOperation()) {
destroy();
}
+
+ final boolean destroyed = !isNativeValid();
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.windowDestroyeNotify END "+getThreadName());
+ System.err.println("Window.windowDestroyNotify(force: "+force+") END "+getThreadName()+": destroyed "+destroyed+", "+this);
}
+ return destroyed;
}
public void windowRepaint(int x, int y, int width, int height) {
diff --git a/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java b/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java
index 4547db831..63d5f7003 100644
--- a/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java
+++ b/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java
@@ -329,8 +329,7 @@ public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 {
if(0!=surfaceHandle && androidFormat != aFormat ) {
// re-create
Log.d(MD.TAG, "surfaceChanged (destroy old)");
- windowDestroyNotify();
- if(isNativeValid()) {
+ if(!windowDestroyNotify(true)) {
destroy();
}
surfaceHandle = 0;
@@ -371,7 +370,7 @@ public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 {
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(MD.TAG, "surfaceDestroyed");
- windowDestroyNotify();
+ windowDestroyNotify(true); // actually too late .. however ..
}
public void surfaceRedrawNeeded(SurfaceHolder holder) {
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java
index c926d44ee..b45c60e69 100644
--- a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java
+++ b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java
@@ -77,19 +77,19 @@ public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverCl
protected void closeNativeImpl() {
try {
if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.CloseAction "+Thread.currentThread().getName()); }
- if (getWindowHandle() != 0) {
- close0(getWindowHandle());
+ final long handle = getWindowHandle();
+ setWindowHandle(0);
+ surfaceHandle = 0;
+ sscSurfaceHandle = 0;
+ isOffscreenInstance = false;
+ if (0 != handle) {
+ close0(handle);
}
} catch (Throwable t) {
if(DEBUG_IMPLEMENTATION) {
Exception e = new Exception("Warning: closeNative failed - "+Thread.currentThread().getName(), t);
e.printStackTrace();
}
- } finally {
- setWindowHandle(0);
- surfaceHandle = 0;
- sscSurfaceHandle = 0;
- isOffscreenInstance = false;
}
}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/X11Window.java b/src/newt/classes/jogamp/newt/driver/x11/X11Window.java
index 703b18272..143b94a57 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/X11Window.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/X11Window.java
@@ -117,8 +117,10 @@ public class X11Window extends WindowImpl {
// client position -> top-level window position
x -= i.getLeftWidth() ;
y -= i.getTopHeight() ;
- }
- reconfigureWindow0( getDisplayEDTHandle(), getScreenIndex(), getParentWindowHandle(), getWindowHandle(),
+ }
+ final X11Display display = (X11Display) getScreen().getDisplay();
+ reconfigureWindow0( getDisplayEDTHandle(), getScreenIndex(),
+ getParentWindowHandle(), getWindowHandle(), display.getWindowDeleteAtom(),
x, y, width, height, flags);
return true;
@@ -243,7 +245,7 @@ public class X11Window extends WindowImpl {
int x, int y, int width, int height, boolean autoPosition, int flags);
private native void CloseWindow0(long display, long windowHandle, long javaObjectAtom, long windowDeleteAtom);
private native void reconfigureWindow0(long display, int screen_index, long parentWindowHandle, long windowHandle,
- int x, int y, int width, int height, int flags);
+ long windowDeleteAtom, int x, int y, int width, int height, int flags);
private native void requestFocus0(long display, long windowHandle, boolean force);
private static native void setTitle0(long display, long windowHandle, String title);
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) ) {