diff options
author | Sven Gothel <[email protected]> | 2023-10-02 19:42:42 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2023-10-02 19:42:42 +0200 |
commit | f842843df2c77f5badaace6858d3336151ce0827 (patch) | |
tree | 1e0e9c6b689fccc580507f9a2809f785986466b1 /src/newt/native | |
parent | b0893eda1035bcb1c6a88e52dac6cd00dfedf696 (diff) |
Bug 1468 - SIGSEGV on use after free when destroying NEWT Window/Display via a native dispatch'ed event like key/mouse/touch input
SIGSEGV on use after free of native X11 Display* at XEventsQueued in DisplayDriver.DispatchMessages0.
This potentially happens when an application destroys
the NEWT Window/Display from an action being called directly
from DisplayDriver.DispatchMessages0 (itself), i.e. keyboard or mouse input.
DisplayDriver.DispatchMessages0 stays in the event loop and the next
XEventsQueued call causes a SIGSEGV due to already deleted
display driver connection and hence invalid native X11 Display*.
This issue also exist for other Windowing System drivers,
where the native (dispatch) method sticks to a loop
and still (re)uses the window or display handle.
One is WindowsWindow, where touch events are looped,
but such handler could have closed the window.
Querying the status of a window / display instance before dispatching
is not be good enough
- resource could already be GC'ed, so we also would need to query jobject status
- would imply an addition Java callback
+++
This fix: Having the Java callbacks return
a boolean with the value Window.isNativeValid().
This way the dispatch logic
- can bail out right away w/o using the resource anymore
- must be reviewed by myself due to changed Call{Void->Boolean}*(..)
invocation change.
This review shall resolve potential similar issues.
+++
Tested on X11/Linux/GNU, Windows and MacOS
with new TestDestroyGLAutoDrawableNewtAWT,
which tests all destruction invocation variants.
Diffstat (limited to 'src/newt/native')
-rw-r--r-- | src/newt/native/IOSNewtUIWindow.m | 40 | ||||
-rw-r--r-- | src/newt/native/KDWindow.c | 41 | ||||
-rw-r--r-- | src/newt/native/MacNewtNSWindow.m | 60 | ||||
-rw-r--r-- | src/newt/native/WindowsWindow.c | 207 | ||||
-rw-r--r-- | src/newt/native/X11Display.c | 221 | ||||
-rw-r--r-- | src/newt/native/X11Window.c | 23 | ||||
-rw-r--r-- | src/newt/native/bcm_vc_iv.c | 4 | ||||
-rw-r--r-- | src/newt/native/drm_gbm.c | 2 |
8 files changed, 362 insertions, 236 deletions
diff --git a/src/newt/native/IOSNewtUIWindow.m b/src/newt/native/IOSNewtUIWindow.m index 6e3e362a7..2efd7a25c 100644 --- a/src/newt/native/IOSNewtUIWindow.m +++ b/src/newt/native/IOSNewtUIWindow.m @@ -1,5 +1,5 @@ /** - * Copyright 2019 JogAmp Community. All rights reserved. + * Copyright 2019-2023 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -219,7 +219,7 @@ static jmethodID windowRepaintID = NULL; CGRect viewFrame = [self frame]; - (*env)->CallVoidMethod(env, javaWindowObject, windowRepaintID, JNI_TRUE /* defer */, + (*env)->CallBooleanMethod(env, javaWindowObject, windowRepaintID, JNI_TRUE /* defer */, (int)dirtyRect.origin.x, (int)viewFrame.size.height - (int)dirtyRect.origin.y, (int)dirtyRect.size.width, (int)dirtyRect.size.height); @@ -440,16 +440,16 @@ static jmethodID windowRepaintID = NULL; + (BOOL) initNatives: (JNIEnv*) env forClass: (jclass) clazz { - sendTouchScreenEventID = (*env)->GetMethodID(env, clazz, "sendTouchScreenEvent", "(SI[I[S[I[I[I[FF)V"); + sendTouchScreenEventID = (*env)->GetMethodID(env, clazz, "sendTouchScreenEvent", "(SI[I[S[I[I[I[FF)Z"); sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZZIIZ)Z"); updatePixelScaleID = (*env)->GetMethodID(env, clazz, "updatePixelScale", "(ZFFFZ)V"); - visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V"); - insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V"); - sizeScreenPosInsetsChangedID = (*env)->GetMethodID(env, clazz, "sizeScreenPosInsetsChanged", "(ZIIIIIIIIZZ)V"); - screenPositionChangedID = (*env)->GetMethodID(env, clazz, "screenPositionChanged", "(ZII)V"); - focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V"); + visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)Z"); + insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)Z"); + sizeScreenPosInsetsChangedID = (*env)->GetMethodID(env, clazz, "sizeScreenPosInsetsChanged", "(ZIIIIIIIIZZ)Z"); + screenPositionChangedID = (*env)->GetMethodID(env, clazz, "screenPositionChanged", "(ZII)Z"); + focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)Z"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z"); - windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V"); + windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)Z"); requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V"); if (sendTouchScreenEventID && sizeChangedID && updatePixelScaleID && visibleChangedID && insetsChangedID && sizeScreenPosInsetsChangedID && @@ -691,7 +691,7 @@ static jmethodID windowRepaintID = NULL; DBG_PRINT( "updateInsets: [ l %d, r %d, t %d, b %d ]\n", cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]); if( NULL != env && NULL != javaWin ) { - (*env)->CallVoidMethod(env, javaWin, insetsChangedID, JNI_FALSE, cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]); + (*env)->CallBooleanMethod(env, javaWin, insetsChangedID, JNI_FALSE, cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]); } } @@ -709,13 +709,13 @@ static jmethodID windowRepaintID = NULL; DBG_PRINT( "updatePos: [ x %d, y %d ]\n", (jint) pS.x, (jint) pS.y); if( NULL != env && NULL != javaWin ) { - (*env)->CallVoidMethod(env, javaWin, sizeScreenPosInsetsChangedID, defer, - (jint) pS.x, (jint) pS.y, - (jint) frameRect.size.width, (jint) frameRect.size.height, - cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3], - JNI_FALSE, // force - withinLiveResize - ); + (*env)->CallBooleanMethod(env, javaWin, sizeScreenPosInsetsChangedID, defer, + (jint) pS.x, (jint) pS.y, + (jint) frameRect.size.width, (jint) frameRect.size.height, + cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3], + JNI_FALSE, // force + withinLiveResize + ); } } @@ -799,7 +799,7 @@ static jmethodID windowRepaintID = NULL; return; } - (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE); + (*env)->CallBooleanMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE); // detaching thread not required - daemon // NewtCommon_ReleaseJNIEnv(shallBeDetached); @@ -823,7 +823,7 @@ static jmethodID windowRepaintID = NULL; DBG_PRINT("visibilityChanged: null JNIEnv\n"); return; } - (*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, (visible == YES) ? JNI_TRUE : JNI_FALSE); + (*env)->CallBooleanMethod(env, javaWindowObject, visibleChangedID, (visible == YES) ? JNI_TRUE : JNI_FALSE); // detaching thread not required - daemon // NewtCommon_ReleaseJNIEnv(shallBeDetached); @@ -922,7 +922,7 @@ static jmethodID windowRepaintID = NULL; CGPoint p0 = { 0, 0 }; p0 = [self getLocationOnScreen: p0]; DBG_PRINT( "windowDidMove: [ x %d, y %d ]\n", (jint) p0.x, (jint) p0.y); - (*env)->CallVoidMethod(env, javaWindowObject, screenPositionChangedID, JNI_TRUE, (jint) p0.x, (jint) p0.y); + (*env)->CallBooleanMethod(env, javaWindowObject, screenPositionChangedID, JNI_TRUE, (jint) p0.x, (jint) p0.y); // detaching thread not required - daemon // NewtCommon_ReleaseJNIEnv(shallBeDetached); diff --git a/src/newt/native/KDWindow.c b/src/newt/native/KDWindow.c index 972267088..db34560a8 100644 --- a/src/newt/native/KDWindow.c +++ b/src/newt/native/KDWindow.c @@ -87,10 +87,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_DisplayDriver_DispatchMessages (JNIEnv *env, jobject obj) { const KDEvent * evt; - int numEvents = 0; + int num_events = 100; // Periodically take a break - while( numEvents<100 && NULL!=(evt=kdWaitEvent(0)) ) { + while( num_events > 0 && NULL!=(evt=kdWaitEvent(0)) ) { KDWindow *kdWindow; jobject javaWindow; JOGLKDUserdata * userData = (JOGLKDUserdata *)(intptr_t)evt->userptr; @@ -102,7 +102,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_DisplayDriver_DispatchMessages javaWindow = userData->javaWindow; DBG_PRINT( "[DispatchMessages]: userData %p, evt type: 0x%X\n", userData, evt->type); - numEvents++; + num_events--; // FIXME: support resize and window re-positioning events @@ -120,6 +120,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_DisplayDriver_DispatchMessages 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); + num_events=0; // end loop } break; case KD_EVENT_WINDOWPROPERTY_CHANGE: @@ -131,7 +132,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_DisplayDriver_DispatchMessages KDint32 v[2]; if(!kdGetWindowPropertyiv(kdWindow, KD_WINDOWPROPERTY_SIZE, v)) { DBG_PRINT( "event window size change : src: %p %dx%d\n", userData, v[0], v[1]); - (*env)->CallBooleanMethod(env, javaWindow, sizeChangedID, JNI_FALSE, JNI_FALSE, (jint) v[0], (jint) v[1], JNI_FALSE); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, javaWindow, sizeChangedID, JNI_FALSE, JNI_FALSE, (jint) v[0], (jint) v[1], JNI_FALSE) ) { + num_events=0; // end loop + } } else { DBG_PRINT( "event window size change error: src: %p %dx%d\n", userData, v[0], v[1]); } @@ -145,7 +148,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_DisplayDriver_DispatchMessages KDboolean visible; kdGetWindowPropertybv(kdWindow, KD_WINDOWPROPERTY_VISIBILITY, &visible); DBG_PRINT( "event window visibility: src: %p, v:%d\n", userData, visible); - (*env)->CallVoidMethod(env, javaWindow, visibleChangedID, visible?JNI_TRUE:JNI_FALSE); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, javaWindow, visibleChangedID, visible?JNI_TRUE:JNI_FALSE) ) { + num_events=0; // end loop + } } break; default: @@ -161,15 +166,19 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_DisplayDriver_DispatchMessages // time = ev->timestamp if(KD_INPUT_POINTER_SELECT==ptr->index) { DBG_PRINT( "event mouse click: src: %p, s:%d, (%d,%d)\n", userData, ptr->select, ptr->x, ptr->y); - (*env)->CallVoidMethod(env, javaWindow, sendMouseEventID, - (ptr->select==0) ? (jshort) EVENT_MOUSE_RELEASED : (jshort) EVENT_MOUSE_PRESSED, - (jint) 0, - (jint) ptr->x, (jint) ptr->y, (short)1, 0.0f); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, javaWindow, sendMouseEventID, + (ptr->select==0) ? (jshort) EVENT_MOUSE_RELEASED : (jshort) EVENT_MOUSE_PRESSED, + (jint) 0, + (jint) ptr->x, (jint) ptr->y, (short)1, 0.0f) ) { + num_events=0; // end loop + } } else { DBG_PRINT( "event mouse: src: %d, s:%p, i:0x%X (%d,%d)\n", userData, ptr->select, ptr->index, ptr->x, ptr->y); - (*env)->CallVoidMethod(env, javaWindow, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED, - 0, - (jint) ptr->x, (jint) ptr->y, (jshort)0, 0.0f); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, javaWindow, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED, + 0, + (jint) ptr->x, (jint) ptr->y, (jshort)0, 0.0f) ) { + num_events=0; // end loop + } } } break; @@ -192,10 +201,10 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_kd_WindowDriver_initIDs #endif windowCreatedID = (*env)->GetMethodID(env, clazz, "windowCreated", "(J)V"); sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZZIIZ)Z"); - visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V"); + visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)Z"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z"); - sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(SIIISF)V"); - sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(SISSC)V"); + sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(SIIISF)Z"); + sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(SISSC)Z"); if (windowCreatedID == NULL || sizeChangedID == NULL || visibleChangedID == NULL || @@ -277,7 +286,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_WindowDriver_setVisible0 KDboolean v = (visible==JNI_TRUE)?KD_TRUE:KD_FALSE; kdSetWindowPropertybv(w, KD_WINDOWPROPERTY_VISIBILITY, &v); DBG_PRINT( "[setVisible] v=%d\n", visible); - (*env)->CallVoidMethod(env, obj, visibleChangedID, visible); + (*env)->CallBooleanMethod(env, obj, visibleChangedID, visible); } JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_WindowDriver_setFullScreen0 diff --git a/src/newt/native/MacNewtNSWindow.m b/src/newt/native/MacNewtNSWindow.m index e543f96e1..73bcaddcc 100644 --- a/src/newt/native/MacNewtNSWindow.m +++ b/src/newt/native/MacNewtNSWindow.m @@ -1,6 +1,6 @@ /* + * Copyright (c) 2011-2023 JogAmp Community. All rights reserved. * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2011 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -377,7 +377,7 @@ static jmethodID windowRepaintID = NULL; NSRect viewFrame = [self frame]; - (*env)->CallVoidMethod(env, javaWindowObject, windowRepaintID, JNI_TRUE /* defer */, + (*env)->CallBooleanMethod(env, javaWindowObject, windowRepaintID, JNI_TRUE /* defer */, (int)dirtyRect.origin.x, (int)viewFrame.size.height - (int)dirtyRect.origin.y, (int)dirtyRect.size.width, (int)dirtyRect.size.height); @@ -398,7 +398,7 @@ static jmethodID windowRepaintID = NULL; return; } - (*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE); + (*env)->CallBooleanMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE); // detaching thread not required - daemon // NewtCommon_ReleaseJNIEnv(shallBeDetached); @@ -419,7 +419,7 @@ static jmethodID windowRepaintID = NULL; return; } - (*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_TRUE); + (*env)->CallBooleanMethod(env, javaWindowObject, visibleChangedID, JNI_TRUE); // detaching thread not required - daemon // NewtCommon_ReleaseJNIEnv(shallBeDetached); @@ -727,10 +727,10 @@ static jmethodID windowRepaintID = NULL; NSPoint location = [self screenPos2NewtClientWinPos: [NSEvent mouseLocation]]; - (*env)->CallVoidMethod(env, javaWindowObject, enqueueMouseEventID, JNI_FALSE, - evType, javaMods[0], - (jint) location.x, (jint) location.y, - javaButtonNum, scrollDeltaY); + (*env)->CallBooleanMethod(env, javaWindowObject, enqueueMouseEventID, JNI_FALSE, + evType, javaMods[0], + (jint) location.x, (jint) location.y, + javaButtonNum, scrollDeltaY); // detaching thread not required - daemon // NewtCommon_ReleaseJNIEnv(shallBeDetached); @@ -809,8 +809,8 @@ static jmethodID windowRepaintID = NULL; DBG_PRINT("sendKeyEvent: %d/%d code 0x%X, char 0x%X, mods 0x%X/0x%X -> keySymChar 0x%X\n", i, len, (int)keyCode, (int)keyChar, (int)mods, (int)javaMods, (int)keySymChar); - (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE, - evType, javaMods, keyCode, (jchar)keyChar, (jchar)keySymChar); + (*env)->CallBooleanMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE, + evType, javaMods, keyCode, (jchar)keyChar, (jchar)keySymChar); } } else { // non-printable chars @@ -818,8 +818,8 @@ static jmethodID windowRepaintID = NULL; DBG_PRINT("sendKeyEvent: code 0x%X\n", (int)keyCode); - (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE, - evType, javaMods, keyCode, keyChar, keyChar); + (*env)->CallBooleanMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE, + evType, javaMods, keyCode, keyChar, keyChar); } // detaching thread not required - daemon @@ -875,17 +875,17 @@ NS_ENDHANDLER + (BOOL) initNatives: (JNIEnv*) env forClass: (jclass) clazz { - enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZSIIISF)V"); - enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZSISCC)V"); + enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZSIIISF)Z"); + enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZSISCC)Z"); sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZZIIZ)Z"); updatePixelScaleID = (*env)->GetMethodID(env, clazz, "updatePixelScale", "(ZFFFZ)V"); - visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V"); - insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V"); - sizeScreenPosInsetsChangedID = (*env)->GetMethodID(env, clazz, "sizeScreenPosInsetsChanged", "(ZIIIIIIIIZZ)V"); - screenPositionChangedID = (*env)->GetMethodID(env, clazz, "screenPositionChanged", "(ZII)V"); - focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V"); + visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)Z"); + insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)Z"); + sizeScreenPosInsetsChangedID = (*env)->GetMethodID(env, clazz, "sizeScreenPosInsetsChanged", "(ZIIIIIIIIZZ)Z"); + screenPositionChangedID = (*env)->GetMethodID(env, clazz, "screenPositionChanged", "(ZII)Z"); + focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)Z"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z"); - windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V"); + windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)Z"); requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V"); if (enqueueMouseEventID && enqueueKeyEventID && sizeChangedID && updatePixelScaleID && visibleChangedID && insetsChangedID && sizeScreenPosInsetsChangedID && @@ -1015,7 +1015,7 @@ NS_ENDHANDLER DBG_PRINT( "updateInsets: [ l %d, r %d, t %d, b %d ]\n", cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]); if( NULL != env && NULL != javaWin ) { - (*env)->CallVoidMethod(env, javaWin, insetsChangedID, JNI_FALSE, cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]); + (*env)->CallBooleanMethod(env, javaWin, insetsChangedID, JNI_FALSE, cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]); } } @@ -1035,13 +1035,13 @@ NS_ENDHANDLER DBG_PRINT( "updatePos: [ x %d, y %d ]\n", (jint) p0.x, (jint) p0.y); if( NULL != env && NULL != javaWin ) { - (*env)->CallVoidMethod(env, javaWin, sizeScreenPosInsetsChangedID, defer, - (jint) p0.x, (jint) p0.y, - (jint) contentRect.size.width, (jint) contentRect.size.height, - cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3], - JNI_FALSE, // force - withinLiveResize - ); + (*env)->CallBooleanMethod(env, javaWin, sizeScreenPosInsetsChangedID, defer, + (jint) p0.x, (jint) p0.y, + (jint) contentRect.size.width, (jint) contentRect.size.height, + cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3], + JNI_FALSE, // force + withinLiveResize + ); } } @@ -1214,7 +1214,7 @@ NS_ENDHANDLER return; } - (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE); + (*env)->CallBooleanMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE); // detaching thread not required - daemon // NewtCommon_ReleaseJNIEnv(shallBeDetached); @@ -1373,7 +1373,7 @@ NS_ENDHANDLER NSPoint p0 = { 0, 0 }; p0 = [self getLocationOnScreen: p0]; DBG_PRINT( "windowDidMove: [ x %d, y %d ]\n", (jint) p0.x, (jint) p0.y); - (*env)->CallVoidMethod(env, javaWindowObject, screenPositionChangedID, JNI_TRUE, (jint) p0.x, (jint) p0.y); + (*env)->CallBooleanMethod(env, javaWindowObject, screenPositionChangedID, JNI_TRUE, (jint) p0.x, (jint) p0.y); // detaching thread not required - daemon // NewtCommon_ReleaseJNIEnv(shallBeDetached); diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index 4ce5567e1..201304dd9 100644 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -1,6 +1,6 @@ /* + * Copyright (c) 2010-2023 JogAmp Community. All rights reserved. * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2010 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -246,7 +246,7 @@ typedef struct { int supportsMTouch; } WindowUserData; -static void UpdateInsets(JNIEnv *env, WindowUserData *wud, HWND hwnd); +static jboolean UpdateInsets(JNIEnv *env, WindowUserData *wud, HWND hwnd); typedef struct { USHORT javaKey; @@ -594,9 +594,9 @@ static int WmKeyDown(JNIEnv *env, jobject window, USHORT wkey, WORD repCnt, BYTE modifiers = GetModifiers( javaVKeyUS ); - (*env)->CallVoidMethod(env, window, sendKeyEventID, - (jshort) EVENT_KEY_PRESSED, - (jint) modifiers, (jshort) javaVKeyUS, (jshort) javaVKeyXX, (jchar) utf16Char); + (*env)->CallBooleanMethod(env, window, sendKeyEventID, + (jshort) EVENT_KEY_PRESSED, + (jint) modifiers, (jshort) javaVKeyUS, (jshort) javaVKeyXX, (jchar) utf16Char); return 0; } @@ -612,9 +612,9 @@ static int WmKeyUp(JNIEnv *env, jobject window, USHORT wkey, WORD repCnt, BYTE s modifiers = GetModifiers( javaVKeyUS ); - (*env)->CallVoidMethod(env, window, sendKeyEventID, - (jshort) EVENT_KEY_RELEASED, - (jint) modifiers, (jshort) javaVKeyUS, (jshort) javaVKeyXX, (jchar) utf16Char); + (*env)->CallBooleanMethod(env, window, sendKeyEventID, + (jshort) EVENT_KEY_RELEASED, + (jint) modifiers, (jshort) javaVKeyUS, (jshort) javaVKeyXX, (jchar) utf16Char); return 0; } @@ -700,7 +700,7 @@ static jboolean NewtWindows_setFullScreen(jboolean fullscreen) return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettings(&dm, flags) ) ? JNI_TRUE : JNI_FALSE; } -static void UpdateInsets(JNIEnv *env, WindowUserData *wud, HWND hwnd) { +static jboolean UpdateInsets(JNIEnv *env, WindowUserData *wud, HWND hwnd) { jobject window = wud->jinstance; RECT outside; RECT inside; @@ -708,7 +708,7 @@ static void UpdateInsets(JNIEnv *env, WindowUserData *wud, HWND hwnd) { if (IsIconic(hwnd)) { wud->insets.left = wud->insets.top = wud->insets.right = wud->insets.bottom = -1; - return; + return JNI_TRUE; } wud->insets.left = wud->insets.top = wud->insets.right = wud->insets.bottom = 0; @@ -760,9 +760,10 @@ static void UpdateInsets(JNIEnv *env, WindowUserData *wud, HWND hwnd) { (void*)hwnd, strategy, (int)wud->insets.left, (int)wud->insets.right, (int)wud->insets.top, (int)wud->insets.bottom, (int) ( wud->insets.left + wud->insets.right ), (int) (wud->insets.top + wud->insets.bottom), wud->isInCreation); if( !wud->isInCreation ) { - (*env)->CallVoidMethod(env, window, insetsChangedID, - JNI_FALSE, (int)wud->insets.left, (int)wud->insets.right, (int)wud->insets.top, (int)wud->insets.bottom); + return (*env)->CallBooleanMethod(env, window, insetsChangedID, + JNI_FALSE, (int)wud->insets.left, (int)wud->insets.right, (int)wud->insets.top, (int)wud->insets.bottom); } + return JNI_TRUE; } static void WmSize(JNIEnv *env, WindowUserData * wud, HWND wnd, UINT type) @@ -793,7 +794,10 @@ static void WmSize(JNIEnv *env, WindowUserData * wud, HWND wnd, UINT type) } // make sure insets are up to date - UpdateInsets(env, wud, wnd); + if( JNI_FALSE == UpdateInsets(env, wud, wnd) ) { + DBG_PRINT( "WindowsWindow: WmSize.X window %p - Leave J, UpdateInsets\n", (void*)wnd); + return; + } GetClientRect(wnd, &rc); @@ -807,9 +811,15 @@ static void WmSize(JNIEnv *env, WindowUserData * wud, HWND wnd, UINT type) if( !wud->isInCreation ) { if( maxChanged ) { jboolean v = wud->isMaximized ? JNI_TRUE : JNI_FALSE; - (*env)->CallVoidMethod(env, window, maximizedChangedID, v, v); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, window, maximizedChangedID, v, v) ) { + DBG_PRINT( "WindowsWindow: WmSize.X window %p - Leave J, maximized\n", (void*)wnd); + return; + } + } + if( JNI_FALSE == (*env)->CallBooleanMethod(env, window, sizeChangedID, JNI_FALSE, JNI_FALSE, wud->width, wud->height, JNI_FALSE) ) { + DBG_PRINT( "WindowsWindow: WmSize.X window %p - Leave J, sizeChanged\n", (void*)wnd); + return; } - (*env)->CallBooleanMethod(env, window, sizeChangedID, JNI_FALSE, JNI_FALSE, wud->width, wud->height, JNI_FALSE); } } @@ -904,9 +914,9 @@ static BOOL SafeShowCursor(BOOL show) { return b; } -static void sendTouchScreenEvent(JNIEnv *env, jobject window, - short eventType, int modifiers, int actionIdx, - int count, jshort* pointerNames, jint* x, jint* y, jfloat* pressure, float maxPressure) { +static jboolean sendTouchScreenEvent(JNIEnv *env, jobject window, + short eventType, int modifiers, int actionIdx, + int count, jshort* pointerNames, jint* x, jint* y, jfloat* pressure, float maxPressure) { jshortArray jNames = (*env)->NewShortArray(env, count); if (jNames == NULL) { NewtCommon_throwNewRuntimeException(env, "Could not allocate short array (names) of size %d", count); @@ -931,9 +941,9 @@ static void sendTouchScreenEvent(JNIEnv *env, jobject window, } (*env)->SetFloatArrayRegion(env, jPressure, 0, count, pressure); - (*env)->CallVoidMethod(env, window, sendTouchScreenEventID, - (jshort)eventType, (jint)modifiers, (jint)actionIdx, - jNames, jX, jY, jPressure, (jfloat)maxPressure); + return (*env)->CallBooleanMethod(env, window, sendTouchScreenEventID, + (jshort)eventType, (jint)modifiers, (jint)actionIdx, + jNames, jX, jY, jPressure, (jfloat)maxPressure); } // #define DO_ERASEBKGND 1 @@ -1062,7 +1072,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP DBG_PRINT("*** WindowsWindow: WM_SHOWWINDOW window %p: %d, at-init %d\n", wnd, wParam==TRUE, wud->isInCreation); wud->visible = wParam==TRUE; if( !wud->isInCreation ) { - (*env)->CallVoidMethod(env, window, visibleChangedID, wParam==TRUE?JNI_TRUE:JNI_FALSE); + (*env)->CallBooleanMethod(env, window, visibleChangedID, wParam==TRUE?JNI_TRUE:JNI_FALSE); } break; @@ -1082,12 +1092,14 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP if (GetUpdateRect(wnd, NULL, TRUE /* erase background */)) { DBG_PRINT("*** WindowsWindow: WM_PAINT.0 (dirty)\n"); // WM_ERASEBKGND sent! + } #else if (GetUpdateRect(wnd, NULL, FALSE /* do not erase background */)) { DBG_PRINT("*** WindowsWindow: WM_PAINT.0 (dirty)\n"); ValidateRect(wnd, NULL); // clear all! + } #endif - } else { + else { DBG_PRINT("*** WindowsWindow: WM_PAINT.0 (clean)\n"); } } else { @@ -1095,7 +1107,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP DBG_PRINT("*** WindowsWindow: WM_PAINT.1 (dirty)\n"); // Let NEWT render the whole client area by issueing repaint for it, w/o looping through erase background ValidateRect(wnd, NULL); // clear all! - (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1); + (*env)->CallBooleanMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1); } else { DBG_PRINT("*** WindowsWindow: WM_PAINT.1 (clean)\n"); // shall not happen ? @@ -1129,7 +1141,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP // ignore erase background, but let NEWT render the whole client area DBG_PRINT("*** WindowsWindow: WM_ERASEBKGND.1 (repaint)\n"); ValidateRect(wnd, NULL); // clear all! - (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1); + (*env)->CallBooleanMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1); res = 1; // return 1 == done, OpenGL, etc .. erases the background, hence we claim to have just done this } break; @@ -1183,7 +1195,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP DBG_PRINT("*** WindowsWindow: WM_SETFOCUS window %p, lost %p, at-init %d\n", wnd, (HWND)wParam, wud->isInCreation); wud->focused = TRUE; if( !wud->isInCreation ) { - (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_TRUE); + (*env)->CallBooleanMethod(env, window, focusChangedID, JNI_FALSE, JNI_TRUE); } useDefWindowProc = 1; break; @@ -1199,7 +1211,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP } wud->focused = FALSE; if( !wud->isInCreation ) { - (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_FALSE); + (*env)->CallBooleanMethod(env, window, focusChangedID, JNI_FALSE, JNI_FALSE); } useDefWindowProc = 1; } else { @@ -1261,11 +1273,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP NewtWindows_trackPointerLeave(wnd); } (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); - (*env)->CallVoidMethod(env, window, sendMouseEventID, - (jshort) EVENT_MOUSE_PRESSED, - GetModifiers( 0 ), - (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), - (jshort) 1, (jfloat) 0.0f); + (*env)->CallBooleanMethod(env, window, sendMouseEventID, + (jshort) EVENT_MOUSE_PRESSED, + GetModifiers( 0 ), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), + (jshort) 1, (jfloat) 0.0f); useDefWindowProc = 1; } } @@ -1288,11 +1300,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP wud->pointerInside = 1; NewtWindows_trackPointerLeave(wnd); } - (*env)->CallVoidMethod(env, window, sendMouseEventID, - (jshort) EVENT_MOUSE_RELEASED, - GetModifiers( 0 ), - (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), - (jshort) 1, (jfloat) 0.0f); + (*env)->CallBooleanMethod(env, window, sendMouseEventID, + (jshort) EVENT_MOUSE_RELEASED, + GetModifiers( 0 ), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), + (jshort) 1, (jfloat) 0.0f); useDefWindowProc = 1; } } @@ -1308,11 +1320,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP NewtWindows_trackPointerLeave(wnd); } (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); - (*env)->CallVoidMethod(env, window, sendMouseEventID, - (jshort) EVENT_MOUSE_PRESSED, - GetModifiers( 0 ), - (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), - (jshort) 2, (jfloat) 0.0f); + (*env)->CallBooleanMethod(env, window, sendMouseEventID, + (jshort) EVENT_MOUSE_PRESSED, + GetModifiers( 0 ), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), + (jshort) 2, (jfloat) 0.0f); useDefWindowProc = 1; } } @@ -1332,11 +1344,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP wud->pointerInside = 1; NewtWindows_trackPointerLeave(wnd); } - (*env)->CallVoidMethod(env, window, sendMouseEventID, - (jshort) EVENT_MOUSE_RELEASED, - GetModifiers( 0 ), - (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), - (jshort) 2, (jfloat) 0.0f); + (*env)->CallBooleanMethod(env, window, sendMouseEventID, + (jshort) EVENT_MOUSE_RELEASED, + GetModifiers( 0 ), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), + (jshort) 2, (jfloat) 0.0f); useDefWindowProc = 1; } } @@ -1352,11 +1364,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP NewtWindows_trackPointerLeave(wnd); } (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); - (*env)->CallVoidMethod(env, window, sendMouseEventID, - (jshort) EVENT_MOUSE_PRESSED, - GetModifiers( 0 ), - (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), - (jshort) 3, (jfloat) 0.0f); + (*env)->CallBooleanMethod(env, window, sendMouseEventID, + (jshort) EVENT_MOUSE_PRESSED, + GetModifiers( 0 ), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), + (jshort) 3, (jfloat) 0.0f); useDefWindowProc = 1; } } @@ -1376,11 +1388,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP wud->pointerInside = 1; NewtWindows_trackPointerLeave(wnd); } - (*env)->CallVoidMethod(env, window, sendMouseEventID, - (jshort) EVENT_MOUSE_RELEASED, - GetModifiers( 0 ), - (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), - (jshort) 3, (jfloat) 0.0f); + (*env)->CallBooleanMethod(env, window, sendMouseEventID, + (jshort) EVENT_MOUSE_RELEASED, + GetModifiers( 0 ), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), + (jshort) 3, (jfloat) 0.0f); useDefWindowProc = 1; } } @@ -1401,11 +1413,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP NewtWindows_trackPointerLeave(wnd); SetCursor(wud->setPointerHandle); } - (*env)->CallVoidMethod(env, window, sendMouseEventID, - (jshort) EVENT_MOUSE_MOVED, - modifiers, - (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), - (jshort) 0, (jfloat) 0.0f); + (*env)->CallBooleanMethod(env, window, sendMouseEventID, + (jshort) EVENT_MOUSE_MOVED, + modifiers, + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), + (jshort) 0, (jfloat) 0.0f); } useDefWindowProc = 1; } @@ -1416,11 +1428,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp); if( 0 == wud->touchDownCount ) { wud->pointerInside = 0; - (*env)->CallVoidMethod(env, window, sendMouseEventID, - (jshort) EVENT_MOUSE_EXITED, - 0, - (jint) -1, (jint) -1, // fake - (jshort) 0, (jfloat) 0.0f); + (*env)->CallBooleanMethod(env, window, sendMouseEventID, + (jshort) EVENT_MOUSE_EXITED, + 0, + (jint) -1, (jint) -1, // fake + (jshort) 0, (jfloat) 0.0f); useDefWindowProc = 1; } } @@ -1446,11 +1458,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP break; } DBG_PRINT("*** WindowsWindow: WM_HSCROLL 0x%X, rotation %f, mods 0x%X\n", sb, rotation, modifiers); - (*env)->CallVoidMethod(env, window, sendMouseEventID, - (jshort) EVENT_MOUSE_WHEEL_MOVED, - modifiers, - (jint) 0, (jint) 0, - (jshort) 1, (jfloat) rotation); + (*env)->CallBooleanMethod(env, window, sendMouseEventID, + (jshort) EVENT_MOUSE_WHEEL_MOVED, + modifiers, + (jint) 0, (jint) 0, + (jshort) 1, (jfloat) rotation); useDefWindowProc = 1; break; } @@ -1475,11 +1487,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP DBG_PRINT("*** WindowsWindow: WM_MOUSEWHEEL %d/%d, rotation %f, vKeys 0x%X, mods 0x%X\n", (int)eventPt.x, (int)eventPt.y, rotationOrTilt, vKeys, modifiers); } - (*env)->CallVoidMethod(env, window, sendMouseEventID, - (jshort) EVENT_MOUSE_WHEEL_MOVED, - modifiers, - (jint) eventPt.x, (jint) eventPt.y, - (jshort) 1, (jfloat) rotationOrTilt); + (*env)->CallBooleanMethod(env, window, sendMouseEventID, + (jshort) EVENT_MOUSE_WHEEL_MOVED, + modifiers, + (jint) eventPt.x, (jint) eventPt.y, + (jshort) 1, (jfloat) rotationOrTilt); useDefWindowProc = 1; break; } @@ -1563,35 +1575,37 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP #endif } wud->pointerInside = allPInside; + jboolean winOK = JNI_TRUE; + if( sendFocus ) { (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); } int sentCount = 0, updownCount=0, moveCount=0; // Primary first, if available! if( 0 <= actionIdx ) { - sendTouchScreenEvent(env, window, eventType[actionIdx], modifiers, actionIdx, - cInputs, pointerNames, x, y, pressure, maxPressure); + winOK = sendTouchScreenEvent(env, window, eventType[actionIdx], modifiers, actionIdx, + cInputs, pointerNames, x, y, pressure, maxPressure); sentCount++; } // 1 Move second .. - for (i=0; i < cInputs; i++) { + for (i=0; i < cInputs && JNI_TRUE == winOK; i++) { short et = eventType[i]; if( (jshort) EVENT_MOUSE_MOVED == et ) { if( i != actionIdx && 0 == moveCount ) { - sendTouchScreenEvent(env, window, et, modifiers, i, - cInputs, pointerNames, x, y, pressure, maxPressure); + winOK = sendTouchScreenEvent(env, window, et, modifiers, i, + cInputs, pointerNames, x, y, pressure, maxPressure); sentCount++; } moveCount++; } } // Up and downs last - for (i=0; i < cInputs; i++) { + for (i=0; i < cInputs && JNI_TRUE == winOK; i++) { short et = eventType[i]; if( (jshort) EVENT_MOUSE_MOVED != et ) { if( i != actionIdx ) { - sendTouchScreenEvent(env, window, et, modifiers, i, - cInputs, pointerNames, x, y, pressure, maxPressure); + winOK = sendTouchScreenEvent(env, window, et, modifiers, i, + cInputs, pointerNames, x, y, pressure, maxPressure); sentCount++; } updownCount++; @@ -1614,7 +1628,6 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP useDefWindowProc = 1; } - if (useDefWindowProc) { return DefWindowProc(wnd, message, wParam, lParam); } @@ -2162,18 +2175,18 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_initIDs0 { NewtCommon_init(env); - insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V"); + insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)Z"); sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZZIIZ)Z"); - maximizedChangedID = (*env)->GetMethodID(env, clazz, "maximizedChanged", "(ZZ)V"); + maximizedChangedID = (*env)->GetMethodID(env, clazz, "maximizedChanged", "(ZZ)Z"); positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(ZZII)Z"); - focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V"); - visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V"); - sizePosInsetsFocusVisibleChangedID = (*env)->GetMethodID(env, clazz, "sizePosInsetsFocusVisibleChanged", "(ZZIIIIIIIIIIZ)V"); + focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)Z"); + visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)Z"); + sizePosInsetsFocusVisibleChangedID = (*env)->GetMethodID(env, clazz, "sizePosInsetsFocusVisibleChanged", "(ZZIIIIIIIIIIZ)Z"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z"); - windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V"); - sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(SIIISF)V"); - sendTouchScreenEventID = (*env)->GetMethodID(env, clazz, "sendTouchScreenEvent", "(SII[S[I[I[FF)V"); - sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(SISSC)V"); + windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)Z"); + sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(SIIISF)Z"); + sendTouchScreenEventID = (*env)->GetMethodID(env, clazz, "sendTouchScreenEvent", "(SII[S[I[I[FF)Z"); + sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(SISSC)Z"); requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V"); if (insetsChangedID == NULL || @@ -2448,9 +2461,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_InitWindow0 wud->xpos, wud->ypos, wud->width, wud->height, wud->focused, wud->visible); if( wud->isMaximized ) { - (*env)->CallVoidMethod(env, wud->jinstance, maximizedChangedID, JNI_TRUE, JNI_TRUE); + (*env)->CallBooleanMethod(env, wud->jinstance, maximizedChangedID, JNI_TRUE, JNI_TRUE); } - (*env)->CallVoidMethod(env, wud->jinstance, sizePosInsetsFocusVisibleChangedID, JNI_FALSE, JNI_FALSE, + (*env)->CallBooleanMethod(env, wud->jinstance, sizePosInsetsFocusVisibleChangedID, JNI_FALSE, JNI_FALSE, (jint)wud->xpos, (jint)wud->ypos, (jint)wud->width, (jint)wud->height, (jint)wud->insets.left, (jint)wud->insets.right, (jint)wud->insets.top, (jint)wud->insets.bottom, diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c index a2fba9b7f..9ab49088a 100644 --- a/src/newt/native/X11Display.c +++ b/src/newt/native/X11Display.c @@ -40,6 +40,7 @@ jmethodID insetsVisibleChangedID = NULL; static const char * const ClazzNameX11NewtWindow = "jogamp/newt/driver/x11/WindowDriver"; static jmethodID displayCompletedID = NULL; +static jmethodID isNativeValidID = NULL; static jmethodID sendRRScreenChangeNotifyID = NULL; static jmethodID getCurrentThreadNameID = NULL; @@ -250,27 +251,29 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0 // displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJJIII)V"); // Variant using XKB displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJIII)V"); - sendRRScreenChangeNotifyID = (*env)->GetMethodID(env, clazz, "sendRRScreenChangeNotify", "(J)V"); + isNativeValidID = (*env)->GetMethodID(env, clazz, "isNativeValidAsync", "()Z"); + sendRRScreenChangeNotifyID = (*env)->GetMethodID(env, clazz, "sendRRScreenChangeNotify", "(J)Z"); getCurrentThreadNameID = (*env)->GetStaticMethodID(env, X11NewtWindowClazz, "getCurrentThreadName", "()Ljava/lang/String;"); dumpStackID = (*env)->GetStaticMethodID(env, X11NewtWindowClazz, "dumpStack", "()V"); - insetsChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "insetsChanged", "(ZIIII)V"); + insetsChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "insetsChanged", "(ZIIII)Z"); sizeChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sizeChanged", "(ZZIIZ)Z"); positionChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "positionChanged", "(ZZII)Z"); - focusVisibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "focusVisibleChanged", "(ZII)V"); - visibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChanged", "(Z)V"); - insetsVisibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "insetsVisibleChanged", "(ZIIIII)V"); - sizePosMaxInsetsVisibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sizePosMaxInsetsVisibleChanged", "(ZZIIIIIIIIIIIZ)V"); - reparentNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "reparentNotify", "(J)V"); + focusVisibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "focusVisibleChanged", "(ZII)Z"); + visibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChanged", "(Z)Z"); + insetsVisibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "insetsVisibleChanged", "(ZIIIII)Z"); + sizePosMaxInsetsVisibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sizePosMaxInsetsVisibleChanged", "(ZZIIIIIIIIIIIZ)Z"); + reparentNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "reparentNotify", "(J)Z"); windowDestroyNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowDestroyNotify", "(Z)Z"); - windowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowRepaint", "(ZIIII)V"); - visibleChangedWindowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChangedWindowRepaint", "(ZIIIII)V"); - sendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEvent", "(SIIISF)V"); - sendMouseEventRequestFocusID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEventRequestFocus", "(SIIISF)V"); - visibleChangedSendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChangedSendMouseEvent", "(ZISIIISF)V"); - sendTouchScreenEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendTouchScreenEvent", "(SII[S[I[I[FF)V"); - sendKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendKeyEvent", "(SISSCLjava/lang/String;)V"); + windowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowRepaint", "(ZIIII)Z"); + visibleChangedWindowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChangedWindowRepaint", "(ZIIIII)Z"); + sendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEvent", "(SIIISF)Z"); + sendMouseEventRequestFocusID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEventRequestFocus", "(SIIISF)Z"); + visibleChangedSendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChangedSendMouseEvent", "(ZISIIISF)Z"); + sendTouchScreenEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendTouchScreenEvent", "(SII[S[I[I[FF)Z"); + sendKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendKeyEvent", "(SISSCLjava/lang/String;)Z"); if (displayCompletedID == NULL || + isNativeValidID == NULL || sendRRScreenChangeNotifyID == NULL || getCurrentThreadNameID == NULL || dumpStackID == NULL || @@ -391,10 +394,10 @@ static int NewtWindows_updateVisibility(JNIEnv *env, Display *dpy, JavaWindow *j return visibleChange; } -static void sendTouchScreenEvent(JNIEnv *env, JavaWindow *jw, - short eventType, // MouseEvent.EVENT_MOUSE_PRESSED, MouseEvent.EVENT_MOUSE_RELEASED, MouseEvent.EVENT_MOUSE_MOVED - int modifiers, // 0! - int actionId) // index of multiple-pointer arrays representing the pointer which triggered the event +static jboolean sendTouchScreenEvent(JNIEnv *env, JavaWindow *jw, + short eventType, // MouseEvent.EVENT_MOUSE_PRESSED, MouseEvent.EVENT_MOUSE_RELEASED, MouseEvent.EVENT_MOUSE_MOVED + int modifiers, // 0! + int actionId) // index of multiple-pointer arrays representing the pointer which triggered the event { jshort pointerNames[XI_TOUCHCOORD_COUNT]; jint x[XI_TOUCHCOORD_COUNT]; @@ -445,10 +448,11 @@ static void sendTouchScreenEvent(JNIEnv *env, JavaWindow *jw, } (*env)->SetFloatArrayRegion(env, jPressure, 0, cnt, pressure); - (*env)->CallVoidMethod(env, jw->jwindow, sendTouchScreenEventID, - (jshort)eventType, (jint)modifiers, (jint)actionIdx, - jNames, jX, jY, jPressure, (jfloat)1.0f); + jboolean res = (*env)->CallBooleanMethod(env, jw->jwindow, sendTouchScreenEventID, + (jshort)eventType, (jint)modifiers, (jint)actionIdx, + jNames, jX, jY, jPressure, (jfloat)1.0f); NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: XI: Exception occured at sendTouchScreenEvent(..)"); + return res; } /* @@ -467,6 +471,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage int autoRepeatModifiers = 0; if ( NULL == dpy ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 0\n", dpy); return; } @@ -489,12 +494,25 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage jstring keyString = NULL; char text[255]; + // Don't use explicit Java callback, we simply break loop if regular Java callback on event returns JNI_FALSE + #if 0 + if( JNIInvalidRefType == (*env)->GetObjectRefType(env, obj) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 1, invalidated DisplayDriver Object %p\n", dpy, obj); + return; + } + if( JNI_FALSE == (*env)->CallBooleanMethod(env, obj, isNativeValidID) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 2, closed DisplayDriver %p\n", dpy, obj); + return; + } + NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: Exception occured at isNativeValid()"); + #endif + // XEventsQueued(dpy, X): // QueuedAlready == XQLength(): No I/O Flush or system call doesn't work on some cards (eg ATI) ?) // QueuedAfterFlush == XPending(): I/O Flush only if no already queued events are available // QueuedAfterReading : QueuedAlready + if queue==0, attempt to read more .. if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) { - // DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 1\n", dpy); + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 3\n", dpy); return; } @@ -502,13 +520,17 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage num_events--; if(dpy!=evt.xany.display) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 4, wrong display\n", dpy); NewtCommon_throwNewRuntimeException(env, "wrong display, bail out!"); return ; } if( randr_event_base > 0 && RRScreenChangeNotify == ( evt.type - randr_event_base ) ) { DBG_PRINT( "X11: DispatchMessages dpy %p, Event RRScreenChangeNotify %p\n", (void*)dpy, (void*)&evt); - (*env)->CallVoidMethod(env, obj, sendRRScreenChangeNotifyID, (jlong)(intptr_t)&evt); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, obj, sendRRScreenChangeNotifyID, (jlong)(intptr_t)&evt) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, RRScreen\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: RR: Exception occured at sendRRScreenChangeNotify(..)"); continue; // next event } @@ -523,13 +545,16 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage XGenericEventCookie *evtCookie = &evt.xcookie; // hacks: https://keithp.com/blogs/Cursor_tracking/ int isXiEvent = GenericEvent == evtCookie->type && xi_opcode == evtCookie->extension && XGetEventData(dpy, evtCookie); XIDeviceEvent *xiDevEv; + int xiDetail; Window windowPointer; if( !isXiEvent ) { xiDevEv = NULL; + xiDetail = 0; windowPointer = evt.xany.window; DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)windowPointer, (int)evt.type); } else { xiDevEv = evtCookie->data; + xiDetail = xiDevEv->detail; windowPointer = xiDevEv->event; } @@ -563,7 +588,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage } DBG_PRINT( "X11: XI event - XI_TouchBegin Window %p, devid %d, touchid[%d] %d @ %d/%d\n", (void*)windowPointer, xiDevEv->deviceid, i, jw->xiTouchCoords[i].id, jw->xiTouchCoords[i].x, jw->xiTouchCoords[i].y); - sendTouchScreenEvent(env, jw, EVENT_MOUSE_PRESSED, 0, xiDevEv->detail % 32767); + XFreeEventData(dpy, evtCookie); + if( JNI_FALSE == sendTouchScreenEvent(env, jw, EVENT_MOUSE_PRESSED, 0, xiDetail % 32767) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, touch-begin\n", dpy); + num_events = 0; // end loop in case of destroyed display + } break; case XI_TouchUpdate: @@ -576,7 +605,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage } DBG_PRINT( "X11: XI event - XI_TouchUpdate: Window %p, devid %d, touchid[%d] %d @ %d/%d\n", (void*)windowPointer, xiDevEv->deviceid, i, jw->xiTouchCoords[i].id, jw->xiTouchCoords[i].x, jw->xiTouchCoords[i].y); - sendTouchScreenEvent(env, jw, EVENT_MOUSE_MOVED, 0, xiDevEv->detail % 32767); + XFreeEventData(dpy, evtCookie); + if( JNI_FALSE == sendTouchScreenEvent(env, jw, EVENT_MOUSE_MOVED, 0, xiDetail % 32767) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, touch-update\n", dpy); + num_events = 0; // end loop in case of destroyed display + } break; case XI_TouchEnd: @@ -587,14 +620,20 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage } DBG_PRINT( "X11: XI event - XI_TouchEnd: Window %p, devid %d, touchid[%d] %d @ %d/%d\n", (void*)windowPointer, xiDevEv->deviceid, i, jw->xiTouchCoords[i].id, jw->xiTouchCoords[i].x, jw->xiTouchCoords[i].y); - sendTouchScreenEvent(env, jw, EVENT_MOUSE_RELEASED, 0, xiDevEv->detail % 32767); + XFreeEventData(dpy, evtCookie); + if( JNI_FALSE == sendTouchScreenEvent(env, jw, EVENT_MOUSE_RELEASED, 0, xiDetail % 32767) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, touch-end\n", dpy); + num_events = 0; // end loop in case of destroyed display + } if ( i < XI_TOUCHCOORD_COUNT ) { jw->xiTouchCoords[i].id = -1; } break; + + default: + XFreeEventData(dpy, evtCookie); } } - XFreeEventData(dpy, evtCookie); continue; // next event, skip evt.type handling below } @@ -686,21 +725,30 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage switch(evt.type) { case ButtonPress: - (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventRequestFocusID, (jshort) EVENT_MOUSE_PRESSED, - modifiers, - (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jshort) evt.xbutton.button, 0.0f /*rotation*/); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, sendMouseEventRequestFocusID, (jshort) EVENT_MOUSE_PRESSED, + modifiers, + (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jshort) evt.xbutton.button, 0.0f /*rotation*/) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, press-mouseEvent\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: ButtonPress: Exception occured at sendMouseEventRequestFocus(..)"); break; case ButtonRelease: - (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_RELEASED, - modifiers, - (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jshort) evt.xbutton.button, 0.0f /*rotation*/); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_RELEASED, + modifiers, + (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jshort) evt.xbutton.button, 0.0f /*rotation*/) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, release-mouseEvent\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: ButtonRelease: Exception occured at sendMouseEvent(..)"); break; case MotionNotify: - (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED, - modifiers, - (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jshort) 0, 0.0f /*rotation*/); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED, + modifiers, + (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jshort) 0, 0.0f /*rotation*/) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, motion-mouseEvent\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: MotionNotify: Exception occured at sendMouseEvent(..)"); break; case EnterNotify: @@ -708,9 +756,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage { uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw); int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "EnterNotify"); - (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedSendMouseEventID, JNI_FALSE, (jint)visibleChange, - (jshort) EVENT_MOUSE_ENTERED, modifiers, - (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, visibleChangedSendMouseEventID, JNI_FALSE, (jint)visibleChange, + (jshort) EVENT_MOUSE_ENTERED, modifiers, + (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, enter-mouseEvent\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: EnterNotify: Exception occured at visibleChangedSendMouseEvent(..)"); } break; @@ -719,9 +770,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage { uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw); int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "LeaveNotify"); - (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedSendMouseEventID, JNI_FALSE, (jint)visibleChange, - (jshort) EVENT_MOUSE_EXITED, modifiers, - (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, visibleChangedSendMouseEventID, JNI_FALSE, (jint)visibleChange, + (jshort) EVENT_MOUSE_EXITED, modifiers, + (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, leave-mouseEvent\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: LeaveNotify: Exception occured at visibleChangedSendMouseEvent(..)"); } break; @@ -730,13 +784,19 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage XRefreshKeyboardMapping(&evt.xmapping); break; case KeyPress: - (*env)->CallVoidMethod(env, jw->jwindow, sendKeyEventID, (jshort) EVENT_KEY_PRESSED, - modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar, keyString); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, sendKeyEventID, (jshort) EVENT_KEY_PRESSED, + modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar, keyString) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, press-keyEvent\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: KeyPress: Exception occured at sendKeyEvent(..)"); break; case KeyRelease: - (*env)->CallVoidMethod(env, jw->jwindow, sendKeyEventID, (jshort) EVENT_KEY_RELEASED, - modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar, keyString); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, sendKeyEventID, (jshort) EVENT_KEY_RELEASED, + modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar, keyString) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, release-keyEvent\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: KeyRelease: Exception occured at sendKeyEvent(..)"); break; case DestroyNotify: @@ -787,14 +847,17 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "ConfigureNotify"); NewtWindows_updateInsets(dpy, jw, False /* wait */, &left, &right, &top, &bottom); Bool maxChanged = NewtWindows_updateMaximized(dpy, jw, netWMState); - (*env)->CallVoidMethod(env, jw->jwindow, sizePosMaxInsetsVisibleChangedID, JNI_FALSE, JNI_FALSE, - (jint) x_pos, (jint) y_pos, - (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, - (jint)(maxChanged ? ( jw->maxHorz ? 1 : 0 ) : -1), - (jint)(maxChanged ? ( jw->maxVert ? 1 : 0 ) : -1), - (jint)left, (jint)right, (jint)top, (jint)bottom, - (jint)visibleChange, - JNI_FALSE); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, sizePosMaxInsetsVisibleChangedID, JNI_FALSE, JNI_FALSE, + (jint) x_pos, (jint) y_pos, + (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, + (jint)(maxChanged ? ( jw->maxHorz ? 1 : 0 ) : -1), + (jint)(maxChanged ? ( jw->maxVert ? 1 : 0 ) : -1), + (jint)left, (jint)right, (jint)top, (jint)bottom, + (jint)visibleChange, + JNI_FALSE) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, sizePosMaxInsetsVis\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: ConfigureNotify: Exception occured at sizePosMaxInsetsVisibleChanged(..)"); } break; @@ -808,6 +871,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage closed = (*env)->CallBooleanMethod(env, jw->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); + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 5, windowDeleteAtom received\n", dpy); // Called by Window.java: CloseWindow(); num_events = 0; // end loop in case of destroyed display } @@ -818,7 +882,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage { uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw); int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "FocusIn"); - (*env)->CallVoidMethod(env, jw->jwindow, focusVisibleChangedID, JNI_FALSE, (jint)1, (jint)visibleChange); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, focusVisibleChangedID, JNI_FALSE, (jint)1, (jint)visibleChange) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, focus-in\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: FocusIn: Exception occured at focusVisibleChanged(..)"); } break; @@ -828,7 +895,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage { uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw); int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "FocusOut"); - (*env)->CallVoidMethod(env, jw->jwindow, focusVisibleChangedID, JNI_FALSE, (jint)0, (jint)visibleChange); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, focusVisibleChangedID, JNI_FALSE, (jint)0, (jint)visibleChange) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, focus-out\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: FocusOut: Exception occured at focusVisibleChanged(..)"); } break; @@ -840,7 +910,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw); int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "VisibilityNotify"); if( 0 <= visibleChange ) { - (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedID, 0 < visibleChange ? JNI_TRUE : JNI_FALSE); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, visibleChangedID, 0 < visibleChange ? JNI_TRUE : JNI_FALSE) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, vis-notify\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: VisibilityNotify: Exception occured at visibleChanged(..)"); } #endif @@ -852,14 +925,20 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage DBG_PRINT( "X11: event . Expose call %p %d/%d %dx%d count %d\n", (void*)evt.xexpose.window, evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height, evt.xexpose.count); if (evt.xexpose.count == 0 && evt.xexpose.width > 0 && evt.xexpose.height > 0) { - (*env)->CallVoidMethod(env, jw->jwindow, windowRepaintID, JNI_FALSE, - evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, windowRepaintID, JNI_FALSE, + evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, expose\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: Expose: Exception occured at windowRepaint(..)"); #if 0 uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw); int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "Expose"); - (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedWindowRepaintID, JNI_FALSE, (jint)visibleChange, - evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, visibleChangedWindowRepaintID, JNI_FALSE, (jint)visibleChange, + evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, focus-in-vis-repaint\n", dpy); + num_events = 0; // end loop in case of destroyed display + } #endif } break; @@ -874,10 +953,16 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage // insets: negative values are ignored int left=-1, right=-1, top=-1, bottom=-1; if( NewtWindows_updateInsets(dpy, jw, False /* wait */, &left, &right, &top, &bottom) ) { - (*env)->CallVoidMethod(env, jw->jwindow, insetsVisibleChangedID, JNI_FALSE, left, right, top, bottom, 1); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, insetsVisibleChangedID, JNI_FALSE, left, right, top, bottom, 1) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, map-insets\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: MapNotify: Exception occured at insetsVisibleChanged(..)"); } else { - (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedID, JNI_TRUE); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, visibleChangedID, JNI_TRUE) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, map\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: MapNotify: Exception occured at visibleChanged(..)"); } } @@ -890,7 +975,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage if( evt.xunmap.event == evt.xunmap.window ) { // ignore child window notification jw->isMapped = False; - (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedID, JNI_FALSE); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, visibleChangedID, JNI_FALSE) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, unmap\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: UnmapNotify: Exception occured at visibleChanged(..)"); } break; @@ -924,7 +1012,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage (void*)evt.xreparent.parent, (void*)parentRoot, (void*)parentTopParent, (void*)evt.xreparent.window, (void*)winRoot, (void*)winTopParent); #endif - (*env)->CallVoidMethod(env, jw->jwindow, reparentNotifyID, (jlong)evt.xreparent.parent); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, reparentNotifyID, (jlong)evt.xreparent.parent) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, reparent-notify\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: ReparentNotify: Exception occured at reparentNotify(..)"); } break; diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index b53b596cc..142c59137 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -382,16 +382,15 @@ static Status NewtWindows_getFrameExtends(Display *dpy, JavaWindow *javaWin, Boo } if( wait && tD < TIMEOUT_MS && evtCount < MAX_ATTEMPTS ) { // wait for next X event to arrive, then we may try again + evtCount++; #if 0 XEvent e; XPeekEvent(dpy, &e); // FIXME: Blocks if queue is empty - evtCount++; DBG_PRINT( "NEWT FrameExtends: Waiting: #%d %ldms: evt %d, window %p (this=%d)\n", evtCount, tD, e.type, (void*)e.xany.window, (javaWin->window == e.xany.window)); #else struct timespec req = { .tv_sec = 0, .tv_nsec = 1000000L }; // 1ms nanosleep(&req, NULL); - evtCount++; DBG_PRINT( "NEWT FrameExtends: Waiting: #%d %ldms ...\n", evtCount, tD ); #endif } else { @@ -635,6 +634,19 @@ static void NewtWindows_sendNET_WM_DESKTOP(Display *dpy, Window root, JavaWindow XSendEvent ( dpy, root, False, SubstructureNotifyMask | SubstructureRedirectMask, &xev ); } +static void NewtWindows_sendDeleteAtom(Display *dpy, JavaWindow * w) { + XEvent xev; + memset ( &xev, 0, sizeof(xev) ); + + xev.type = ClientMessage; + xev.xclient.window = w->window; + xev.xclient.message_type = w->javaObjectAtom; + xev.xclient.format = 32; + xev.xclient.data.l[0] = w->windowDeleteAtom; + xev.xclient.data.l[1] = 1; //source indication for normal applications + XSendEvent ( dpy, w->window, False, 0, &xev ); +} + /** * Set fullscreen using Extended Window Manager Hints (EWMH) @@ -1099,7 +1111,7 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_WindowDriver_GetSupportedReco * Signature: (JJ)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0 - (JNIEnv *env, jobject obj, jlong display, jlong javaWindow /*, jlong kbdHandle*/, // XKB disabled for now + (JNIEnv *env, jobject obj, jobject displayDriver, jlong display, jlong javaWindow /*, jlong kbdHandle*/, // XKB disabled for now jint randr_event_base, jint randr_error_base, jint xi_opcode) { Display * dpy = (Display *) (intptr_t) display; @@ -1135,8 +1147,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0 XUnmapWindow(dpy, jw->window); jw->isMapped=False; - // Drain all events related to this window .. - Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, obj, display, + // Notify potential running dispatcher and drain all events related to this window .. + NewtWindows_sendDeleteAtom(dpy, jw); + Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, displayDriver, display, (jlong)(intptr_t)jw->javaObjectAtom, (jlong)(intptr_t)jw->windowDeleteAtom /*, kbdHandle */, // XKB disabled for now randr_event_base, randr_error_base, xi_opcode); diff --git a/src/newt/native/bcm_vc_iv.c b/src/newt/native/bcm_vc_iv.c index 03a52c787..3a853fc5c 100644 --- a/src/newt/native/bcm_vc_iv.c +++ b/src/newt/native/bcm_vc_iv.c @@ -332,7 +332,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_initID { sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZZIIZ)Z"); positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(ZZII)Z"); - visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V"); + visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)Z"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z"); if (sizeChangedID == NULL || positionChangedID == NULL || @@ -397,7 +397,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_CreateWin vc_dispmanx_update_submit_sync( dispman_update ); - (*env)->CallVoidMethod(env, obj, visibleChangedID, JNI_TRUE); + (*env)->CallBooleanMethod(env, obj, visibleChangedID, JNI_TRUE); DBG_PRINT( "BCM.Display Window.Create.X %p, element %p\n", (void*)(intptr_t)dispman_display, (void*)(intptr_t)p->handle); diff --git a/src/newt/native/drm_gbm.c b/src/newt/native/drm_gbm.c index 7f2b7de88..722c11a49 100644 --- a/src/newt/native/drm_gbm.c +++ b/src/newt/native/drm_gbm.c @@ -223,7 +223,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_egl_gbm_WindowDriver_initIDs { sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZZIIZ)Z"); positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(ZZII)Z"); - visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V"); + visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)Z"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z"); if (sizeChangedID == NULL || positionChangedID == NULL || |