diff options
author | Sven Gothel <[email protected]> | 2015-08-10 16:16:13 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2015-08-10 16:16:13 +0200 |
commit | 2d837a7a7130702ad36b694875613fae77c7ef06 (patch) | |
tree | f9027493d91511e9f799a852d3058d9fb29f9645 /src/newt/native | |
parent | 1e4bfc26e2f220e046f42f7d26c05e4971bc509d (diff) |
Bug 1188, Bug 1186: NEWT Window: Support non-resizable, minimize, maximize, alwaysOnBottom and sticky/all-desktop (Part 1)
Change also implements Bug 1186: 'NEWT Window: Use a Bitfield holding all state flags and expose it accordingly',
since it is essential for an efficient implementation.
Part 1:
- Bug 1186
- Using Bitfield, holding public (Window) and private state bits/mask
- Bug 1188
- Window adds:
- [is|set]AlwaysOnBottom(..),
- [is|set]Resizable(..),
- [is|set]Sticky(..),
- [is|set]Maximized(..),
- isChildWindow(),
- Full implementation for X11
- TODO: Implement for OSX and Windows
- Manual tests:
- TestGearsES2NEWT, TestGearsES2NEWTSimple and TestGearsES2NewtCanvasAWT
utilize new NewtDemoListener, which has a key-listener to perform
all [new] actions. See source code of NewtDemoListener.
Diffstat (limited to 'src/newt/native')
-rw-r--r-- | src/newt/native/MacWindow.m | 24 | ||||
-rw-r--r-- | src/newt/native/Window.h | 62 | ||||
-rw-r--r-- | src/newt/native/WindowsWindow.c | 4 | ||||
-rw-r--r-- | src/newt/native/X11AllowedWMActions.c | 131 | ||||
-rw-r--r-- | src/newt/native/X11Common.h | 16 | ||||
-rw-r--r-- | src/newt/native/X11Display.c | 48 | ||||
-rw-r--r-- | src/newt/native/X11Event.c | 58 | ||||
-rw-r--r-- | src/newt/native/X11Window.c | 920 | ||||
-rw-r--r-- | src/newt/native/XCBEvent.c | 50 |
9 files changed, 914 insertions, 399 deletions
diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index 5593cd682..b59e19e4e 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -1438,6 +1438,30 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setAlwaysOnTo /* * Class: jogamp_newt_driver_macosx_WindowDriver + * Method: setAlwaysOnBottom0 + * Signature: (JZ)V + */ +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setAlwaysOnBottom0 + (JNIEnv *env, jobject unused, jlong window, jboolean abottom) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + + DBG_PRINT( "setAlwaysOnBottom0 - window: %p, abottom %d (START)\n", win, (int)abottom); + + if(abottom) { + [win setLevel:NSScreenSaverWindowLevel]; // ?? + } else { + [win setLevel:NSNormalWindowLevel]; + } + + DBG_PRINT( "setAlwaysOnBottom0 - window: %p, abottom %d (END)\n", win, (int)abottom); + + [pool release]; +} + +/* + * Class: jogamp_newt_driver_macosx_WindowDriver * Method: getLocationOnScreen0 * Signature: (JII)Lcom/jogamp/nativewindow/util/Point; */ diff --git a/src/newt/native/Window.h b/src/newt/native/Window.h index d9ee5fd1f..ada886d24 100644 --- a/src/newt/native/Window.h +++ b/src/newt/native/Window.h @@ -29,30 +29,60 @@ #ifndef _WINDOW_H_ #define _WINDOW_H_ -#define FLAG_CHANGE_PARENTING ( 1 << 0 ) -#define FLAG_CHANGE_DECORATION ( 1 << 1 ) -#define FLAG_CHANGE_FULLSCREEN ( 1 << 2 ) -#define FLAG_CHANGE_ALWAYSONTOP ( 1 << 3 ) -#define FLAG_CHANGE_VISIBILITY ( 1 << 4 ) +#define FLAG_CHANGE_VISIBILITY ( 1 << 31 ) +#define FLAG_CHANGE_VISIBILITY_FAST ( 1 << 30 ) +#define FLAG_CHANGE_PARENTING ( 1 << 29 ) +#define FLAG_CHANGE_DECORATION ( 1 << 28 ) +#define FLAG_CHANGE_ALWAYSONTOP ( 1 << 27 ) +#define FLAG_CHANGE_ALWAYSONBOTTOM ( 1 << 26 ) +#define FLAG_CHANGE_STICKY ( 1 << 25 ) +#define FLAG_CHANGE_RESIZABLE ( 1 << 24 ) +#define FLAG_CHANGE_MAXIMIZED_VERT ( 1 << 23 ) +#define FLAG_CHANGE_MAXIMIZED_HORZ ( 1 << 22 ) +#define FLAG_CHANGE_FULLSCREEN ( 1 << 21 ) -#define FLAG_HAS_PARENT ( 1 << 8 ) -#define FLAG_IS_UNDECORATED ( 1 << 9 ) -#define FLAG_IS_FULLSCREEN ( 1 << 10 ) -#define FLAG_IS_FULLSCREEN_SPAN ( 1 << 11 ) -#define FLAG_IS_ALWAYSONTOP ( 1 << 12 ) -#define FLAG_IS_VISIBLE ( 1 << 13 ) +#define FLAG_IS_VISIBLE ( 1 << 0 ) +#define FLAG_IS_AUTOPOSITION ( 1 << 1 ) +#define FLAG_IS_CHILD ( 1 << 2 ) +#define FLAG_IS_FOCUSED ( 1 << 3 ) +#define FLAG_IS_UNDECORATED ( 1 << 4 ) +#define FLAG_IS_ALWAYSONTOP ( 1 << 5 ) +#define FLAG_IS_ALWAYSONBOTTOM ( 1 << 6 ) +#define FLAG_IS_STICKY ( 1 << 7 ) +#define FLAG_IS_RESIZABLE ( 1 << 8 ) +#define FLAG_IS_MAXIMIZED_VERT ( 1 << 9 ) +#define FLAG_IS_MAXIMIZED_HORZ ( 1 << 10 ) +#define FLAG_IS_FULLSCREEN ( 1 << 11 ) +#define FLAG_IS_FULLSCREEN_SPAN ( 1 << 12 ) +#define TST_FLAG_CHANGE_VISIBILITY(f) ( 0 != ( (f) & FLAG_CHANGE_VISIBILITY ) ) +#define TST_FLAG_CHANGE_VISIBILITY_FAST(f) ( 0 != ( (f) & FLAG_CHANGE_VISIBILITY_FAST ) ) #define TST_FLAG_CHANGE_PARENTING(f) ( 0 != ( (f) & FLAG_CHANGE_PARENTING ) ) #define TST_FLAG_CHANGE_DECORATION(f) ( 0 != ( (f) & FLAG_CHANGE_DECORATION ) ) -#define TST_FLAG_CHANGE_FULLSCREEN(f) ( 0 != ( (f) & FLAG_CHANGE_FULLSCREEN ) ) #define TST_FLAG_CHANGE_ALWAYSONTOP(f) ( 0 != ( (f) & FLAG_CHANGE_ALWAYSONTOP ) ) -#define TST_FLAG_CHANGE_VISIBILITY(f) ( 0 != ( (f) & FLAG_CHANGE_VISIBILITY ) ) +#define TST_FLAG_CHANGE_ALWAYSONBOTTOM(f) ( 0 != ( (f) & FLAG_CHANGE_ALWAYSONBOTTOM ) ) +#define TST_FLAG_CHANGE_ALWAYSONANY(f) ( 0 != ( (f) & ( FLAG_CHANGE_ALWAYSONTOP | FLAG_CHANGE_ALWAYSONBOTTOM ) ) ) +#define TST_FLAG_CHANGE_STICKY(f) ( 0 != ( (f) & FLAG_CHANGE_STICKY ) ) +#define TST_FLAG_CHANGE_RESIZABLE(f) ( 0 != ( (f) & FLAG_CHANGE_RESIZABLE ) ) +#define TST_FLAG_CHANGE_MAXIMIZED_VERT(f) ( 0 != ( (f) & FLAG_CHANGE_MAXIMIZED_VERT ) ) +#define TST_FLAG_CHANGE_MAXIMIZED_HORZ(f) ( 0 != ( (f) & FLAG_CHANGE_MAXIMIZED_HORZ ) ) +#define TST_FLAG_CHANGE_MAXIMIZED_ANY(f) ( 0 != ( (f) & ( FLAG_CHANGE_MAXIMIZED_VERT | FLAG_CHANGE_MAXIMIZED_HORZ ) ) ) +#define TST_FLAG_CHANGE_FULLSCREEN(f) ( 0 != ( (f) & FLAG_CHANGE_FULLSCREEN ) ) -#define TST_FLAG_HAS_PARENT(f) ( 0 != ( (f) & FLAG_HAS_PARENT ) ) +#define TST_FLAG_IS_VISIBLE(f) ( 0 != ( (f) & FLAG_IS_VISIBLE ) ) +#define TST_FLAG_IS_AUTOPOSITION(f) ( 0 != ( (f) & FLAG_IS_AUTOPOSITION ) ) +#define TST_FLAG_IS_CHILD(f) ( 0 != ( (f) & FLAG_IS_CHILD ) ) +#define TST_FLAG_IS_FOCUSED(f) ( 0 != ( (f) & FLAG_IS_FOCUSED ) ) #define TST_FLAG_IS_UNDECORATED(f) ( 0 != ( (f) & FLAG_IS_UNDECORATED ) ) +#define TST_FLAG_IS_ALWAYSONTOP(f) ( 0 != ( (f) & FLAG_IS_ALWAYSONTOP ) ) +#define TST_FLAG_IS_ALWAYSONBOTTOM(f) ( 0 != ( (f) & FLAG_IS_ALWAYSONBOTTOM ) ) +#define TST_FLAG_IS_ALWAYSONANY(f) ( 0 != ( (f) & ( FLAG_IS_ALWAYSONTOP | FLAG_IS_ALWAYSONBOTTOM ) ) ) +#define TST_FLAG_IS_STICKY(f) ( 0 != ( (f) & FLAG_IS_STICKY ) ) +#define TST_FLAG_IS_RESIZABLE(f) ( 0 != ( (f) & FLAG_IS_RESIZABLE ) ) +#define TST_FLAG_IS_MAXIMIZED_VERT(f) ( 0 != ( (f) & FLAG_IS_MAXIMIZED_VERT ) ) +#define TST_FLAG_IS_MAXIMIZED_HORZ(f) ( 0 != ( (f) & FLAG_IS_MAXIMIZED_HORZ ) ) +#define TST_FLAG_IS_MAXIMIZED_ANY(f) ( 0 != ( (f) & ( FLAG_IS_MAXIMIZED_VERT | FLAG_IS_MAXIMIZED_HORZ ) ) ) #define TST_FLAG_IS_FULLSCREEN(f) ( 0 != ( (f) & FLAG_IS_FULLSCREEN ) ) #define TST_FLAG_IS_FULLSCREEN_SPAN(f) ( 0 != ( (f) & FLAG_IS_FULLSCREEN_SPAN ) ) -#define TST_FLAG_IS_ALWAYSONTOP(f) ( 0 != ( (f) & FLAG_IS_ALWAYSONTOP ) ) -#define TST_FLAG_IS_VISIBLE(f) ( 0 != ( (f) & FLAG_IS_VISIBLE ) ) #endif diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index 8c29978f0..ad4111ec7 100644 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -2297,9 +2297,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW #endif - DBG_PRINT( "*** WindowsWindow: reconfigureWindow0 parent %p, window %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d, alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d -> styleChange %d, isChild %d, isFullscreen %d\n", + DBG_PRINT( "*** WindowsWindow: reconfigureWindow0 parent %p, window %p, %d/%d %dx%d, parentChange %d, isChild %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d, alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d -> styleChange %d, isChild %d, isFullscreen %d\n", parent, window, x, y, width, height, - TST_FLAG_CHANGE_PARENTING(flags), TST_FLAG_HAS_PARENT(flags), + TST_FLAG_CHANGE_PARENTING(flags), TST_FLAG_IS_CHILD(flags), TST_FLAG_CHANGE_DECORATION(flags), TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_CHANGE_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN(flags), TST_FLAG_CHANGE_ALWAYSONTOP(flags), TST_FLAG_IS_ALWAYSONTOP(flags), diff --git a/src/newt/native/X11AllowedWMActions.c b/src/newt/native/X11AllowedWMActions.c new file mode 100644 index 000000000..47448cba9 --- /dev/null +++ b/src/newt/native/X11AllowedWMActions.c @@ -0,0 +1,131 @@ + +#ifdef VERBOSE_ON + #define _NET_WM_ACTION_FLAG_RESERVED ( 1 << 0 ) /* for the ATOM COMMAND */ + #define _NET_WM_ACTION_FLAG_MOVE ( 1 << 1 ) + #define _NET_WM_ACTION_FLAG_RESIZE ( 1 << 2 ) + #define _NET_WM_ACTION_FLAG_MINIMIZE ( 1 << 3 ) + #define _NET_WM_ACTION_FLAG_SHADE ( 1 << 4 ) + #define _NET_WM_ACTION_FLAG_STICK ( 1 << 5 ) + #define _NET_WM_ACTION_FLAG_MAXIMIZE_HORZ ( 1 << 6 ) + #define _NET_WM_ACTION_FLAG_MAXIMIZE_VERT ( 1 << 7 ) + #define _NET_WM_ACTION_FLAG_FULLSCREEN ( 1 << 8 ) + #define _NET_WM_ACTION_FLAG_CHANGE_DESKTOP ( 1 << 9 ) + #define _NET_WM_ACTION_FLAG_CLOSE ( 1 << 10 ) + #define _NET_WM_ACTION_FLAG_ABOVE ( 1 << 11 ) + #define _NET_WM_ACTION_FLAG_BELOW ( 1 << 12 ) + #define _NET_WM_ACTION_FLAG_ALL ( ( 1 << 13 ) - 1 ) + static const char * _NET_WM_AACTION_NAMES[] = { + "_NET_WM_ALLOWED_ACTIONS", + "_NET_WM_ACTION_MOVE", + "_NET_WM_ACTION_RESIZE", + "_NET_WM_ACTION_MINIMIZE", + "_NET_WM_ACTION_SHADE", + "_NET_WM_ACTION_STICK", + "_NET_WM_ACTION_MAXIMIZE_HORZ", + "_NET_WM_ACTION_MAXIMIZE_VERT", + "_NET_WM_ACTION_FULLSCREEN", + "_NET_WM_ACTION_CHANGE_DESKTOP", + "_NET_WM_ACTION_CLOSE", + "_NET_WM_ACTION_ABOVE", + "_NET_WM_ACTION_BELOW" + }; + static const int _NET_WM_AACTION_COUNT = sizeof(_NET_WM_AACTION_NAMES)/sizeof(const char *); + static const int _UNDEF_AACTION_MAX = 16; + static int NewtWindows_getAllowedWindowActionEWMH(Display *dpy, const Atom * allDefinedActions, const Atom action, const int num) { + int i; + for(i=1; i<_NET_WM_AACTION_COUNT; i++) { + if( action == allDefinedActions[i] ) { + DBG_PRINT( "...... [%d] -> [%d/%d]: %s\n", num, i, _NET_WM_AACTION_COUNT, _NET_WM_AACTION_NAMES[i]); + return 1 << i; + } + } + #ifdef VERBOSE_ON + char * astr = XGetAtomName(dpy, action); + DBG_PRINT( "...... [%d] -> [_/%d]: %s (undef)\n", num, _NET_WM_AACTION_COUNT, astr); + XFree(astr); + #endif + return 0; + } + static int NewtWindows_getAllowedWindowActionsEWMH1(Display *dpy, Window w, Atom * _NET_WM_AACTIONS) { + Atom * actions = NULL; + Atom type = 0; + unsigned long action_len = 0, remain = 0; + int res = 0, form = 0, i = 0; + Status s; + + XSync(dpy, False); + DBG_PRINT( "**************** X11: AACTIONS EWMH CHECK for Window: %p:\n", w); + if ( Success == (s = XGetWindowProperty(dpy, w, _NET_WM_AACTIONS[0], 0, 1024, False, AnyPropertyType, + &type, &form, &action_len, &remain, (unsigned char**)&actions)) ) { + if( NULL != actions ) { + for(i=0; i<action_len; i++) { + res |= NewtWindows_getAllowedWindowActionEWMH(dpy, _NET_WM_AACTIONS, actions[i], i); + } + XFree(actions); + } + DBG_PRINT( "**************** X11: AACTIONS EWMH CHECK: 0x%X\n", res); + } else { + DBG_PRINT( "**************** X11: AACTIONS EWMH CHECK: XGetWindowProperty failed: %d\n", s); + res = _NET_WM_ACTION_FLAG_FULLSCREEN; // default .. + } + return res; + } + static int NewtWindows_getAllowedWindowActionsEWMH0(Display *dpy, Window w) { + Atom _NET_WM_AACTIONS[_NET_WM_AACTION_COUNT]; + if( 0 == XInternAtoms( dpy, (char **)_NET_WM_AACTION_NAMES, _NET_WM_AACTION_COUNT, False, _NET_WM_AACTIONS) ) { + // error + DBG_PRINT( "**************** X11: AACTIONS EWMH CHECK: XInternAtoms failed\n"); + return _NET_WM_ACTION_FLAG_FULLSCREEN; // default .. + } + return NewtWindows_getAllowedWindowActionsEWMH1(dpy, w, _NET_WM_AACTIONS); + } + static int NewtWindows_setAllowedWindowActionsEWMH(Display *dpy, Window w, int new_action_mask) { + Atom _NET_WM_AACTIONS[_NET_WM_AACTION_COUNT]; + if( 0 == XInternAtoms( dpy, (char **)_NET_WM_AACTION_NAMES, _NET_WM_AACTION_COUNT, False, _NET_WM_AACTIONS) ) { + // error + DBG_PRINT( "**************** X11: AACTIONS EWMH SET: XInternAtoms failed\n"); + return _NET_WM_ACTION_FLAG_FULLSCREEN; // default .. + } + Atom * actions = NULL; + Atom type = 0; + unsigned long action_len = 0, remain = 0; + int res = 0, form = 0, i = 0, j = 0; + Status s; + Atom _NET_WM_NEWACTIONS[_NET_WM_AACTION_COUNT+_UNDEF_AACTION_MAX]; // +_UNDEF_AACTION_MAX undefined props + + DBG_PRINT( "**************** X11: AACTIONS EWMH SET for Window: %p:\n", w); + if ( Success == (s = XGetWindowProperty(dpy, w, _NET_WM_AACTIONS[0], 0, 1024, False, AnyPropertyType, + &type, &form, &action_len, &remain, (unsigned char**)&actions)) ) { + if( NULL != actions ) { + for(i=0; i<action_len; i++) { + const int r = NewtWindows_getAllowedWindowActionEWMH(dpy, _NET_WM_AACTIONS, actions[i], i); + if( 0 == r && j < _UNDEF_AACTION_MAX ) { + // conserve undefined action + _NET_WM_NEWACTIONS[j++] = actions[i]; + } + res |= r; + } + XFree(actions); + } + DBG_PRINT( "**************** X11: AACTIONS EWMH SET: Has 0x%X\n", res); + for(i=1; i<_NET_WM_AACTION_COUNT; i++) { + const int m = 1 << i; + if( 0 != ( m & new_action_mask ) ) { + // requested + _NET_WM_NEWACTIONS[j++] = _NET_WM_AACTIONS[i]; + res |= m; + } + } + DBG_PRINT( "**************** X11: AACTIONS EWMH SET: New 0x%X\n", res); + XChangeProperty( dpy, w, _NET_WM_AACTIONS[0], XA_ATOM, 32, PropModeReplace, (unsigned char*)_NET_WM_NEWACTIONS, j); + XSync(dpy, False); + const int res2 = NewtWindows_getAllowedWindowActionsEWMH1(dpy, w, _NET_WM_AACTIONS); + DBG_PRINT( "**************** X11: AACTIONS EWMH SET: Val 0x%X\n", res2); + } else { + DBG_PRINT( "**************** X11: AACTIONS EWMH SET: XGetWindowProperty failed: %d\n", s); + res = _NET_WM_ACTION_FLAG_FULLSCREEN; // default .. + } + return res; + } +#endif + diff --git a/src/newt/native/X11Common.h b/src/newt/native/X11Common.h index e58cdb755..309e62683 100644 --- a/src/newt/native/X11Common.h +++ b/src/newt/native/X11Common.h @@ -71,11 +71,23 @@ extern jclass X11NewtWindowClazz; extern jmethodID insetsChangedID; extern jmethodID visibleChangedID; +extern jmethodID minMaxSizeChangedID; -jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning); +typedef struct { + Window window; + jobject jwindow; + Atom * allAtoms; + Atom javaObjectAtom; + Atom windowDeleteAtom; + uint32_t supportedAtoms; + uint32_t lastDesktop; +} JavaWindow; + +JavaWindow * getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning); Status NewtWindows_getRootAndParent (Display *dpy, Window w, Window * root_return, Window * parent_return); -Status NewtWindows_updateInsets(JNIEnv *env, jobject jwindow, Display *dpy, Window window, int *left, int *right, int *top, int *bottom); +Status NewtWindows_updateInsets(JNIEnv *env, Display *dpy, JavaWindow * w, int *left, int *right, int *top, int *bottom); +void NewtWindows_updateMinMaxSize(JNIEnv *env, Display *dpy, JavaWindow * w); #endif /* _X11COMMON_H_ */ diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c index b79c1ee95..0ba454a00 100644 --- a/src/newt/native/X11Display.c +++ b/src/newt/native/X11Display.c @@ -35,6 +35,7 @@ jclass X11NewtWindowClazz = NULL; jmethodID insetsChangedID = NULL; jmethodID visibleChangedID = NULL; +jmethodID minMaxSizeChangedID = NULL; static const char * const ClazzNameX11NewtWindow = "jogamp/newt/driver/x11/WindowDriver"; @@ -253,6 +254,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0 positionChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "positionChanged", "(ZII)V"); focusChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "focusChanged", "(ZZ)V"); visibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChanged", "(ZZ)V"); + minMaxSizeChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "minMaxSizeChanged", "(IIII)V"); reparentNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "reparentNotify", "(J)V"); windowDestroyNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowDestroyNotify", "(Z)Z"); windowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowRepaint", "(ZIIII)V"); @@ -269,6 +271,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0 positionChangedID == NULL || focusChangedID == NULL || visibleChangedID == NULL || + minMaxSizeChangedID == NULL || reparentNotifyID == NULL || windowDestroyNotifyID == NULL || windowRepaintID == NULL || @@ -377,7 +380,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage // Periodically take a break while( num_events > 0 ) { - jobject jwindow = NULL; + JavaWindow *jw = NULL; XEvent evt; KeySym keySym = 0; KeyCode keyCode = 0; @@ -418,7 +421,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, (int)evt.type); - jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom, + jw = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom, #ifdef VERBOSE_ON True #else @@ -426,7 +429,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage #endif ); - if(NULL==jwindow) { + if(NULL==jw) { fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n", (void*)dpy, evt.type, (void*)evt.xany.window); continue; } @@ -519,30 +522,30 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage switch(evt.type) { case ButtonPress: - (*env)->CallVoidMethod(env, jwindow, requestFocusID, JNI_FALSE); - (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_PRESSED, + (*env)->CallVoidMethod(env, jw->jwindow, requestFocusID, JNI_FALSE); + (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_PRESSED, modifiers, (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jshort) evt.xbutton.button, 0.0f /*rotation*/); break; case ButtonRelease: - (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_RELEASED, + (*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*/); break; case MotionNotify: - (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED, + (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED, modifiers, (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jshort) 0, 0.0f /*rotation*/); break; case EnterNotify: DBG_PRINT( "X11: event . EnterNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y); - (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_ENTERED, + (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_ENTERED, modifiers, (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/); break; case LeaveNotify: DBG_PRINT( "X11: event . LeaveNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y); - (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_EXITED, + (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_EXITED, modifiers, (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/); break; @@ -551,11 +554,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage XRefreshKeyboardMapping(&evt.xmapping); break; case KeyPress: - (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jshort) EVENT_KEY_PRESSED, + (*env)->CallVoidMethod(env, jw->jwindow, sendKeyEventID, (jshort) EVENT_KEY_PRESSED, modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar, keyString); break; case KeyRelease: - (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jshort) EVENT_KEY_RELEASED, + (*env)->CallVoidMethod(env, jw->jwindow, sendKeyEventID, (jshort) EVENT_KEY_RELEASED, modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar, keyString); break; case DestroyNotify: @@ -579,11 +582,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage { // update insets int left, right, top, bottom; - NewtWindows_updateInsets(env, jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom); + NewtWindows_updateInsets(env, dpy, jw, &left, &right, &top, &bottom); } - (*env)->CallVoidMethod(env, jwindow, sizeChangedID, JNI_FALSE, + NewtWindows_updateMinMaxSize(env, dpy, jw); + (*env)->CallVoidMethod(env, jw->jwindow, sizeChangedID, JNI_FALSE, (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, JNI_FALSE); - (*env)->CallVoidMethod(env, jwindow, positionChangedID, JNI_FALSE, + (*env)->CallVoidMethod(env, jw->jwindow, positionChangedID, JNI_FALSE, (jint) evt.xconfigure.x, (jint) evt.xconfigure.y); } break; @@ -592,7 +596,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage jboolean closed; DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X ..\n", (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type); - closed = (*env)->CallBooleanMethod(env, jwindow, windowDestroyNotifyID, JNI_FALSE); + 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); // Called by Window.java: CloseWindow(); @@ -602,12 +606,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage case FocusIn: DBG_PRINT( "X11: event . FocusIn call %p\n", (void*)evt.xvisibility.window); - (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE, JNI_TRUE); + (*env)->CallVoidMethod(env, jw->jwindow, focusChangedID, JNI_FALSE, JNI_TRUE); break; case FocusOut: DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xvisibility.window); - (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE, JNI_FALSE); + (*env)->CallVoidMethod(env, jw->jwindow, focusChangedID, JNI_FALSE, JNI_FALSE); break; case Expose: @@ -615,7 +619,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage 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, jwindow, windowRepaintID, JNI_FALSE, + (*env)->CallVoidMethod(env, jw->jwindow, windowRepaintID, JNI_FALSE, evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height); } break; @@ -629,9 +633,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage { // update insets int left, right, top, bottom; - NewtWindows_updateInsets(env, jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom); + NewtWindows_updateInsets(env, dpy, jw, &left, &right, &top, &bottom); } - (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE); + (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE); } break; @@ -641,7 +645,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage evt.xunmap.event!=evt.xunmap.window); if( evt.xunmap.event == evt.xunmap.window ) { // ignore child window notification - (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_FALSE); + (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedID, JNI_FALSE, JNI_FALSE); } break; @@ -674,7 +678,7 @@ 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, jwindow, reparentNotifyID, (jlong)evt.xreparent.parent); + (*env)->CallVoidMethod(env, jw->jwindow, reparentNotifyID, (jlong)evt.xreparent.parent); } break; diff --git a/src/newt/native/X11Event.c b/src/newt/native/X11Event.c index 32a55c67c..d0567c16b 100644 --- a/src/newt/native/X11Event.c +++ b/src/newt/native/X11Event.c @@ -12,7 +12,7 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, // Periodically take a break while( num_events > 0 ) { - jobject jwindow = NULL; + JavaWindow *w = NULL; XEvent evt; KeySym keySym = 0; jint modifiers = 0; @@ -45,7 +45,7 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, (int)evt.type); - jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom, + w = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom, #ifdef VERBOSE_ON True #else @@ -53,7 +53,7 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, #endif ); - if(NULL==jwindow) { + if(NULL==w) { fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n", (void*)dpy, evt.type, (void*)evt.xany.window); continue; } @@ -99,35 +99,35 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, switch(evt.type) { case ButtonPress: - (*env)->CallVoidMethod(env, jwindow, requestFocusID, JNI_FALSE); + (*env)->CallVoidMethod(env, w->jwindow, requestFocusID, JNI_FALSE); #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, + (*env)->CallVoidMethod(env, w->jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, modifiers, (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/); #else - (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED, + (*env)->CallVoidMethod(env, w->jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED, modifiers, (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/); #endif break; case ButtonRelease: #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, + (*env)->CallVoidMethod(env, w->jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, modifiers, (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/); #else - (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED, + (*env)->CallVoidMethod(env, w->jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED, modifiers, (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/); #endif break; case MotionNotify: #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, + (*env)->CallVoidMethod(env, w->jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, modifiers, (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0.0f /*rotation*/); #else - (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED, + (*env)->CallVoidMethod(env, w->jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED, modifiers, (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0.0f /*rotation*/); #endif @@ -135,11 +135,11 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, case EnterNotify: DBG_PRINT( "X11: event . EnterNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y); #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_ENTERED, + (*env)->CallVoidMethod(env, w->jwindow, sendMouseEventID, (jint) EVENT_MOUSE_ENTERED, modifiers, (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/); #else - (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_ENTERED, + (*env)->CallVoidMethod(env, w->jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_ENTERED, modifiers, (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/); #endif @@ -147,31 +147,31 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, case LeaveNotify: DBG_PRINT( "X11: event . LeaveNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y); #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_EXITED, + (*env)->CallVoidMethod(env, w->jwindow, sendMouseEventID, (jint) EVENT_MOUSE_EXITED, modifiers, (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/); #else - (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_EXITED, + (*env)->CallVoidMethod(env, w->jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_EXITED, modifiers, (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/); #endif break; case KeyPress: #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED, + (*env)->CallVoidMethod(env, w->jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED, modifiers, keySym, (jchar) -1); #else - (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED, + (*env)->CallVoidMethod(env, w->jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED, modifiers, keySym, (jchar) -1); #endif break; case KeyRelease: #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED, + (*env)->CallVoidMethod(env, w->jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED, modifiers, keySym, (jchar) -1); #else - (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED, + (*env)->CallVoidMethod(env, w->jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED, modifiers, keySym, (jchar) -1); #endif @@ -197,11 +197,11 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, { // update insets int left, right, top, bottom; - NewtWindows_updateInsets(env, jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom); + NewtWindows_updateInsets(env, w->jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom); } - (*env)->CallVoidMethod(env, jwindow, sizeChangedID, JNI_FALSE, + (*env)->CallVoidMethod(env, w->jwindow, sizeChangedID, JNI_FALSE, (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, JNI_FALSE); - (*env)->CallVoidMethod(env, jwindow, positionChangedID, JNI_FALSE, + (*env)->CallVoidMethod(env, w->jwindow, positionChangedID, JNI_FALSE, (jint) evt.xconfigure.x, (jint) evt.xconfigure.y); } break; @@ -210,7 +210,7 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, jboolean closed; DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X ..\n", (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type); - closed = (*env)->CallBooleanMethod(env, jwindow, windowDestroyNotifyID, JNI_FALSE); + closed = (*env)->CallBooleanMethod(env, w->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(); @@ -220,12 +220,12 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, case FocusIn: DBG_PRINT( "X11: event . FocusIn call %p\n", (void*)evt.xvisibility.window); - (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE, JNI_TRUE); + (*env)->CallVoidMethod(env, w->jwindow, focusChangedID, JNI_FALSE, JNI_TRUE); break; case FocusOut: DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xvisibility.window); - (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE, JNI_FALSE); + (*env)->CallVoidMethod(env, w->jwindow, focusChangedID, JNI_FALSE, JNI_FALSE); break; case Expose: @@ -233,7 +233,7 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, 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, jwindow, windowRepaintID, JNI_FALSE, + (*env)->CallVoidMethod(env, w->jwindow, windowRepaintID, JNI_FALSE, evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height); } break; @@ -247,9 +247,9 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, { // update insets int left, right, top, bottom; - NewtWindows_updateInsets(env, jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom); + NewtWindows_updateInsets(env, w->jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom); } - (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE); + (*env)->CallVoidMethod(env, w->jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE); } break; @@ -259,7 +259,7 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, evt.xunmap.event!=evt.xunmap.window); if( evt.xunmap.event == evt.xunmap.window ) { // ignore child window notification - (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_FALSE); + (*env)->CallVoidMethod(env, w->jwindow, visibleChangedID, JNI_FALSE, JNI_FALSE); } break; @@ -292,7 +292,7 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, (void*)evt.xreparent.parent, (void*)parentRoot, (void*)parentTopParent, (void*)evt.xreparent.window, (void*)winRoot, (void*)winTopParent); #endif - (*env)->CallVoidMethod(env, jwindow, reparentNotifyID, (jlong)evt.xreparent.parent); + (*env)->CallVoidMethod(env, w->jwindow, reparentNotifyID, (jlong)evt.xreparent.parent); } break; diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index e640b0c20..ca768240f 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -82,27 +82,176 @@ static uintptr_t getPtrOut32Long(unsigned long * src) { return res; } -static void setJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, jobject jwindow) { - unsigned long jogl_java_object_data[2]; // X11 is based on 'unsigned long' - int nitems_32 = putPtrIn32Long( jogl_java_object_data, (uintptr_t) jwindow); +#define _NET_WM_STATE_REMOVE 0 +#define _NET_WM_STATE_ADD 1 - { - jobject test = (jobject) getPtrOut32Long(jogl_java_object_data); - if( ! (jwindow==test) ) { - NewtCommon_FatalError(env, "Internal Error .. Encoded Window ref not the same %p != %p !", jwindow, test); +#define _MASK_NET_WM_STATE ( 1 << 0 ) +#define _MASK_NET_WM_STATE_MODAL ( 1 << 1 ) +#define _MASK_NET_WM_STATE_STICKY ( 1 << 2 ) +#define _MASK_NET_WM_STATE_MAXIMIZED_VERT ( 1 << 3 ) +#define _MASK_NET_WM_STATE_MAXIMIZED_HORZ ( 1 << 4 ) +#define _MASK_NET_WM_STATE_SHADED ( 1 << 5 ) +#define _MASK_NET_WM_STATE_HIDDEN ( 1 << 8 ) +#define _MASK_NET_WM_STATE_FULLSCREEN ( 1 << 9 ) +#define _MASK_NET_WM_STATE_ABOVE ( 1 << 10 ) +#define _MASK_NET_WM_STATE_BELOW ( 1 << 11 ) +#define _MASK_NET_WM_STATE_DEMANDS_ATTENTION ( 1 << 12 ) +#define _MASK_NET_WM_STATE_FOCUSED ( 1 << 13 ) +#define _MASK_NET_WM_BYPASS_COMPOSITOR ( 1 << 14 ) +#define _MASK_NET_WM_DESKTOP ( 1 << 15 ) +#define _MASK_NET_CURRENT_DESKTOP ( 1 << 16 ) +#define _MASK_NET_WM_WINDOW_TYPE ( 1 << 17 ) +#define _MASK_NET_WM_WINDOW_TYPE_NORMAL ( 1 << 18 ) +#define _MASK_NET_WM_WINDOW_TYPE_POPUP_MENU ( 1 << 19 ) +#define _MASK_NET_FRAME_EXTENTS ( 1 << 20 ) +#define _MASK_NET_SUPPORTED ( 1 << 21 ) +#define _MASK_WM_CHANGE_STATE ( 1 << 22 ) +#define _MASK_MOTIF_WM_HINTS ( 1 << 23 ) + +#define _NET_WM_STATE_IDX 0 +#define _NET_WM_STATE_MODAL_IDX 1 +#define _NET_WM_STATE_STICKY_IDX 2 +#define _NET_WM_STATE_MAXIMIZED_VERT_IDX 3 +#define _NET_WM_STATE_MAXIMIZED_HORZ_IDX 4 +#define _NET_WM_STATE_SHADED_IDX 5 +#define _NET_WM_STATE_SKIP_TASKBAR_IDX 6 +#define _NET_WM_STATE_SKIP_PAGER_IDX 7 +#define _NET_WM_STATE_HIDDEN_IDX 8 +#define _NET_WM_STATE_FULLSCREEN_IDX 9 +#define _NET_WM_STATE_ABOVE_IDX 10 +#define _NET_WM_STATE_BELOW_IDX 11 +#define _NET_WM_STATE_DEMANDS_ATTENTION_IDX 12 +#define _NET_WM_STATE_FOCUSED_IDX 13 +#define _NET_WM_BYPASS_COMPOSITOR_IDX 14 +#define _NET_WM_DESKTOP_IDX 15 +#define _NET_CURRENT_DESKTOP_IDX 16 +#define _NET_WM_WINDOW_TYPE_IDX 17 +#define _NET_WM_WINDOW_TYPE_NORMAL_IDX 18 +#define _NET_WM_WINDOW_TYPE_POPUP_MENU_IDX 19 +#define _NET_FRAME_EXTENTS_IDX 20 +#define _NET_SUPPORTED_IDX 21 +#define _WM_CHANGE_STATE_IDX 22 +#define _MOTIF_WM_HINTS_IDX 23 +static const char * _ALL_ATOM_NAMES[] = { + /* 0 */ "_NET_WM_STATE", + /* 1 */ "_NET_WM_STATE_MODAL", + /* 2 */ "_NET_WM_STATE_STICKY", + /* 3 */ "_NET_WM_STATE_MAXIMIZED_VERT", + /* 4 */ "_NET_WM_STATE_MAXIMIZED_HORZ", + /* 5 */ "_NET_WM_STATE_SHADED", + /* 6 */ "_NET_WM_STATE_SKIP_TASKBAR", + /* 7 */ "_NET_WM_STATE_SKIP_PAGER", + /* 8 */ "_NET_WM_STATE_HIDDEN", + /* 9 */ "_NET_WM_STATE_FULLSCREEN", + /* 10 */ "_NET_WM_STATE_ABOVE", + /* 11 */ "_NET_WM_STATE_BELOW", + /* 12 */ "_NET_WM_STATE_DEMANDS_ATTENTION", + /* 13 */ "_NET_WM_STATE_FOCUSED", + /* 14 */ "_NET_WM_BYPASS_COMPOSITOR", + /* 15 */ "_NET_WM_DESKTOP", + /* 16 */ "_NET_CURRENT_DESKTOP", + /* 17 */ "_NET_WM_WINDOW_TYPE", + /* 18 */ "_NET_WM_WINDOW_TYPE_NORMAL", + /* 19 */ "_NET_WM_WINDOW_TYPE_POPUP_MENU", + /* 20 */ "_NET_FRAME_EXTENTS", + /* 21 */ "_NET_SUPPORTED", + /* 22 */ "WM_CHANGE_STATE", + /* 23 */ "_MOTIF_WM_HINTS" +}; +static const uint32_t _ALL_ATOM_COUNT = (uint32_t)(sizeof(_ALL_ATOM_NAMES)/sizeof(const char *)); + +static uint32_t NewtWindows_getSupportedFeatureEWMH(Display *dpy, const Atom * allAtoms, const Atom action, const int num, Bool verbose) { + uint32_t i; + for(i=1; i<_ALL_ATOM_COUNT; i++) { + if( action == allAtoms[i] ) { + if(verbose) { + fprintf(stderr, "...... [%d] -> [%d/%d]: %s\n", num, i, _ALL_ATOM_COUNT, _ALL_ATOM_NAMES[i]); + } + return 1U << i; } } + if(verbose) { + char * astr = XGetAtomName(dpy, action); + fprintf(stderr, "...... [%d] -> [_/%d]: %s (undef)\n", num, _ALL_ATOM_COUNT, astr); + XFree(astr); + } + return 0; +} +static uint32_t NewtWindows_getSupportedFeaturesEWMH(Display *dpy, Window root, Atom * allAtoms, Bool verbose) { + Atom * actions = NULL; + Atom type = 0; + unsigned long action_len = 0, remain = 0; + int form = 0, i = 0; + uint32_t res = 0; + Status s; + XSync(dpy, False); + if ( Success == (s = XGetWindowProperty(dpy, root, allAtoms[_NET_SUPPORTED_IDX], 0, 1024, False, AnyPropertyType, + &type, &form, &action_len, &remain, (unsigned char**)&actions)) ) { + if( NULL != actions ) { + for(i=0; i<action_len; i++) { + res |= NewtWindows_getSupportedFeatureEWMH(dpy, allAtoms, actions[i], i, verbose); + } + XFree(actions); + } + if(verbose) { + fprintf(stderr, "**************** X11: Feature EWMH CHECK: 0x%X\n", res); + } + } else if(verbose) { + fprintf(stderr, "**************** X11: Feature EWMH CHECK: XGetWindowProperty failed: %d\n", s); + } + return res; +} + +static JavaWindow* createJavaWindowProperty(JNIEnv *env, Display *dpy, Window root, Window window, + jlong javaObjectAtom, jlong windowDeleteAtom, jobject obj, Bool verbose) { + jobject jwindow = (*env)->NewGlobalRef(env, obj); + JavaWindow * res; + { + Atom * allAtoms = calloc(_ALL_ATOM_COUNT, sizeof(Atom)); + if( 0 == XInternAtoms( dpy, (char **)_ALL_ATOM_NAMES, _ALL_ATOM_COUNT, False, allAtoms) ) { + // error + fprintf(stderr, "**************** X11: XInternAtoms failed\n"); + return NULL; + } + res = calloc(1, sizeof(JavaWindow)); + res->window = window; + res->jwindow = jwindow; + res->allAtoms = allAtoms; + res->javaObjectAtom = (Atom)javaObjectAtom; + res->windowDeleteAtom = (Atom)windowDeleteAtom; + res->supportedAtoms = NewtWindows_getSupportedFeaturesEWMH(dpy, root, allAtoms, verbose); + res->lastDesktop = 0; //undef + } + unsigned long jogl_java_object_data[2]; // X11 is based on 'unsigned long' + int nitems_32 = putPtrIn32Long( jogl_java_object_data, (uintptr_t) res); + { + JavaWindow * test = (JavaWindow *) getPtrOut32Long(jogl_java_object_data); + if( res != test ) { + NewtCommon_FatalError(env, "Internal Error .. Encoded Window ref not the same %p != %p !", res, test); + } + } XChangeProperty( dpy, window, (Atom)javaObjectAtom, (Atom)javaObjectAtom, 32, PropModeReplace, (unsigned char *)&jogl_java_object_data, nitems_32); + return res; } - -jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning) { +static void destroyJavaWindow(JNIEnv *env, JavaWindow *w) { + if( NULL != w ) { + (*env)->DeleteGlobalRef(env, w->jwindow); + w->jwindow = 0; + if( NULL != w->allAtoms ) { + free(w->allAtoms); + w->allAtoms = NULL; + } + free(w); + } +} +JavaWindow * getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning) { Atom actual_type = 0; int actual_format = 0; int nitems_32 = ( sizeof(uintptr_t) == 8 ) ? 2 : 1 ; unsigned char * jogl_java_object_data_pp = NULL; - jobject jwindow = 0; + JavaWindow * res = NULL; { unsigned long nitems= 0; @@ -133,15 +282,15 @@ jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong ja } } - jwindow = (jobject) getPtrOut32Long( (unsigned long *) jogl_java_object_data_pp ) ; + res = (JavaWindow *) getPtrOut32Long( (unsigned long *) jogl_java_object_data_pp ) ; XFree(jogl_java_object_data_pp); #ifdef VERBOSE_ON - if(JNI_FALSE == (*env)->IsInstanceOf(env, jwindow, X11NewtWindowClazz)) { - NewtCommon_throwNewRuntimeException(env, "fetched Atom NEWT_JAVA_OBJECT window is not a NEWT Window: javaWindow 0x%X !", jwindow); + if(JNI_FALSE == (*env)->IsInstanceOf(env, res->jwindow, X11NewtWindowClazz)) { + NewtCommon_throwNewRuntimeException(env, "fetched Atom NEWT_JAVA_OBJECT window is not a NEWT Window: javaWindow 0x%X !", res->jwindow); } #endif - return jwindow; + return res; } /** @return zero if fails, non zero if OK */ @@ -190,19 +339,18 @@ static Status NewtWindows_getWindowPositionRelative2Parent (Display *dpy, Window } return 0; // Error } -static Status NewtWindows_getFrameExtends(Display *dpy, Window window, int *left, int *right, int *top, int *bottom) { +static Status NewtWindows_getFrameExtends(Display *dpy, JavaWindow *w, int *left, int *right, int *top, int *bottom) { Atom actual_type = 0; int actual_format = 0; int nitems_32 = 4; // l, r, t, b unsigned char * frame_extends_data_pp = NULL; { - Atom _NET_FRAME_EXTENTS = XInternAtom( dpy, "_NET_FRAME_EXTENTS", False ); unsigned long nitems = 0; unsigned long bytes_after = 0; int res; - res = XGetWindowProperty(dpy, window, _NET_FRAME_EXTENTS, 0, nitems_32, False, + res = XGetWindowProperty(dpy, w->window, w->allAtoms[_NET_FRAME_EXTENTS_IDX], 0, nitems_32, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &frame_extends_data_pp); @@ -241,46 +389,44 @@ static Status NewtWindows_getFrameExtends(Display *dpy, Window window, int *left #define MWM_HINTS_DECORATIONS (1L << 1) #define PROP_MWM_HINTS_ELEMENTS 5 -static void NewtWindows_setDecorations (Display *dpy, Window w, Bool decorated) { +static void NewtWindows_setDecorations (Display *dpy, JavaWindow *w, Bool decorated) { #ifdef DECOR_USE_MWM unsigned long mwmhints[PROP_MWM_HINTS_ELEMENTS] = { MWM_HINTS_DECORATIONS, 0, decorated, 0, 0 }; // flags, functions, decorations, input_mode, status - Atom _MOTIF_WM_HINTS = XInternAtom( dpy, "_MOTIF_WM_HINTS", False ); #endif #ifdef DECOR_USE_EWMH - Atom _NET_WM_WINDOW_TYPE = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE", False ); Atom types[3]={0}; int ntypes=0; if(True==decorated) { - types[ntypes++] = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False ); + types[ntypes++] = w->allAtoms[_NET_WM_WINDOW_TYPE_NORMAL_IDX]; } else { - types[ntypes++] = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE_POPUP_MENU", False ); + types[ntypes++] = w->allAtoms[_NET_WM_WINDOW_TYPE_POPUP_MENU_IDX]; } #endif #ifdef DECOR_USE_MWM - XChangeProperty( dpy, w, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropModeReplace, (unsigned char *)&mwmhints, PROP_MWM_HINTS_ELEMENTS); + XChangeProperty( dpy, w->window, w->allAtoms[_MOTIF_WM_HINTS_IDX], w->allAtoms[_MOTIF_WM_HINTS_IDX], 32, PropModeReplace, + (unsigned char *)&mwmhints, PROP_MWM_HINTS_ELEMENTS); #endif #ifdef DECOR_USE_EWMH - XChangeProperty( dpy, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, ntypes); + XChangeProperty( dpy, w->window, w->allAtoms[_NET_WM_WINDOW_TYPE_IDX], XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, ntypes); #endif XSync(dpy, False); } -static Bool NewtWindows_hasDecorations (Display *dpy, Window w) { +static Bool NewtWindows_hasDecorations (Display *dpy, JavaWindow * w) { Bool decor = False; #ifdef DECOR_USE_MWM - Atom _MOTIF_WM_HINTS = XInternAtom( dpy, "_MOTIF_WM_HINTS", False ); unsigned char *wm_data = NULL; Atom wm_type = 0; int wm_format = 0; unsigned long wm_nitems = 0, wm_bytes_after = 0; - if( Success == XGetWindowProperty(dpy, w, _MOTIF_WM_HINTS, 0, PROP_MWM_HINTS_ELEMENTS, False, AnyPropertyType, + if( Success == XGetWindowProperty(dpy, w->window, w->allAtoms[_MOTIF_WM_HINTS_IDX], 0, PROP_MWM_HINTS_ELEMENTS, False, AnyPropertyType, &wm_type, &wm_format, &wm_nitems, &wm_bytes_after, &wm_data) ) { if(wm_type != None && NULL != wm_data && wm_nitems >= PROP_MWM_HINTS_ELEMENTS) { // unsigned long mwmhints[PROP_MWM_HINTS_ELEMENTS] = { MWM_HINTS_DECORATIONS, 0, decorated, 0, 0 }; // flags, functions, decorations, input_mode, status @@ -292,22 +438,184 @@ static Bool NewtWindows_hasDecorations (Display *dpy, Window w) { } } #endif - return decor; } -static void NewtWindows_setNormalWindowEWMH (Display *dpy, Window w) { - Atom _NET_WM_WINDOW_TYPE = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE", False ); - Atom types[1]={0}; - types[0] = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False ); - XChangeProperty( dpy, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, 1); +static void NewtWindows_requestFocus (Display *dpy, JavaWindow * jw, Bool force) { + XWindowAttributes xwa; + Window focus_return; + int revert_to_return; + + XSync(dpy, False); + XGetInputFocus(dpy, &focus_return, &revert_to_return); + DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d, hasFocus %d\n", dpy, (void*)jw->window, force, focus_return==jw->window); + + if( True==force || focus_return!=jw->window) { + DBG_PRINT( "X11: XRaiseWindow dpy %p, win %p\n", dpy, (void*)jw->window); + XRaiseWindow(dpy, jw->window); + NewtWindows_setCWAbove(dpy, jw->window); + // Avoid 'BadMatch' errors from XSetInputFocus, ie if window is not viewable + XGetWindowAttributes(dpy, jw->window, &xwa); + DBG_PRINT( "X11: XSetInputFocus dpy %p,win %p, isViewable %d\n", dpy, (void*)jw->window, (xwa.map_state == IsViewable)); + if(xwa.map_state == IsViewable) { + XSetInputFocus(dpy, jw->window, RevertToParent, CurrentTime); + } + } + DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d - FIN\n", dpy, (void*)jw->window, force); XSync(dpy, False); } -#define _NET_WM_STATE_REMOVE 0 -#define _NET_WM_STATE_ADD 1 -#define _NET_WM_STATE_FLAG_FULLSCREEN ( 1 << 0 ) -#define _NET_WM_STATE_FLAG_ABOVE ( 1 << 1 ) +Status NewtWindows_updateInsets(JNIEnv *env, Display *dpy, JavaWindow * w, int *left, int *right, int *top, int *bottom) { + if(0 != NewtWindows_getFrameExtends(dpy, w, left, right, top, bottom)) { + DBG_PRINT( "NewtWindows_updateInsets: insets by _NET_FRAME_EXTENTS [ l %d, r %d, t %d, b %d ]\n", + *left, *right, *top, *bottom); + (*env)->CallVoidMethod(env, w->jwindow, insetsChangedID, JNI_FALSE, *left, *right, *top, *bottom); + return 1; // OK + } + + Bool hasDecor = NewtWindows_hasDecorations (dpy, w); + if(hasDecor) { + // The following logic only works if window is top-level _and_ the WM + // has 'decorated' our client window w/ another parent window _within_ the actual 'framed' window. + Window parent = NewtWindows_getParent(dpy, w->window); + if(0 != NewtWindows_getWindowPositionRelative2Parent (dpy, parent, left, top)) { + *right = *left; *bottom = *top; + DBG_PRINT( "NewtWindows_updateInsets: insets by parent position [ l %d, r %d, t %d, b %d ]\n", + *left, *right, *top, *bottom); + (*env)->CallVoidMethod(env, w->jwindow, insetsChangedID, JNI_FALSE, *left, *right, *top, *bottom); + return 1; // OK + } + } + DBG_PRINT( "NewtWindows_updateInsets: cannot determine insets - hasDecor %d\n", hasDecor); + return 0; // Error +} + +void NewtWindows_updateMinMaxSize(JNIEnv *env, Display *dpy, JavaWindow * w) { + XSizeHints * xsh = XAllocSizeHints(); + long xsh_bits = 0; + int min_width=-1, min_height=-1; + int max_width=-1, max_height=-1; + if( NULL != xsh ) { + xsh->flags = 0; + xsh->min_width=0; + xsh->min_height=0; + xsh->max_width=0; + xsh->max_height=0; + if( 0 != XGetWMNormalHints(dpy, w->window, xsh, &xsh_bits) ) { + // OK + if( 0 != ( xsh_bits & PMinSize ) ) { + min_width = xsh->min_width; + min_height = xsh->min_height; + } + if( 0 != ( xsh_bits & PMaxSize ) ) { + max_width = xsh->max_width; + max_height = xsh->max_height; + } + DBG_PRINT( "NewtWindows_updateMinMaxSize: XGetWMNormalHints 0x%X / 0x%X for window %p on display %p\n", xsh_bits, xsh->flags, (void*)w->window, dpy); + (*env)->CallVoidMethod(env, w->jwindow, minMaxSizeChangedID, min_width, min_height, max_width, max_height); + } else { + DBG_PRINT( "NewtWindows_updateMinMaxSize: XGetWMNormalHints failed (0x%X / 0x%X) for window %p on display %p\n", xsh_bits, xsh->flags, (void*)w->window, dpy); + } + XFree(xsh); + } +} + +static void NewtWindows_setMinMaxSize(Display *dpy, JavaWindow *w, int min_width, int min_height, int max_width, int max_height) { + XSizeHints * xsh = XAllocSizeHints(); + if( NULL != xsh ) { + if( -1 != min_width && -1 != min_height && -1 != max_width && -1 != max_height ) { + xsh->flags = PMinSize | PMaxSize; + xsh->min_width=min_width; + xsh->min_height=min_height; + xsh->max_width=max_width; + xsh->max_height=max_height; + } +#if 0 + XSetWMNormalHints(dpy, w->window, xsh); +#else + XSetWMSizeHints(dpy, w->window, xsh, XA_WM_NORMAL_HINTS); +#endif + XFree(xsh); + } +} + +static void NewtWindows_setWindowTypeEWMH (Display *dpy, JavaWindow * w, int typeIdx) { + Atom types[1]={0}; + if( _NET_WM_WINDOW_TYPE_NORMAL_IDX == typeIdx ) { + types[0] = w->allAtoms[_NET_WM_WINDOW_TYPE_NORMAL_IDX]; + } // else { } + if( 0 != types[0] ) { + XChangeProperty( dpy, w->window, w->allAtoms[_NET_WM_WINDOW_TYPE_IDX], XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, 1); + XSync(dpy, False); + } +} + +static void NewtWindows_sendNET_WM_STATE(Display *dpy, Window root, JavaWindow *w, int prop1Idx, int prop2Idx, Bool enable) { + XEvent xev; + int i=0; + + memset ( &xev, 0, sizeof(xev) ); + + xev.type = ClientMessage; + xev.xclient.window = w->window; + xev.xclient.message_type = w->allAtoms[_NET_WM_STATE_IDX]; + xev.xclient.format = 32; + + xev.xclient.data.l[i++] = enable ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE ; + if( 0 < prop1Idx ) { + xev.xclient.data.l[i++] = w->allAtoms[prop1Idx]; + } + if( 0 < prop2Idx ) { + xev.xclient.data.l[i++] = w->allAtoms[prop2Idx]; + } + xev.xclient.data.l[3] = 1; //source indication for normal applications + + XSendEvent ( dpy, root, False, SubstructureNotifyMask | SubstructureRedirectMask, &xev ); +} +static unsigned long NewtWindows_getDesktopNum(Display *dpy, Window root, JavaWindow * w) { + unsigned long res = 0; + unsigned long * data_pp = NULL; + + Atom actual_type = 0; + int actual_format = 0; + unsigned long nitems= 0; + unsigned long bytes_after= 0; + + if( Success == XGetWindowProperty(dpy, w->window, w->allAtoms[_NET_WM_DESKTOP_IDX], 0, 1, False, + AnyPropertyType, &actual_type, &actual_format, + &nitems, &bytes_after, (unsigned char **)&data_pp) ) + { + if(XA_CARDINAL==actual_type && 32==actual_format && 1<=nitems && NULL!=data_pp) { + res = *data_pp; + DBG_PRINT("Info: NEWT X11Window: _NET_WM_DESKTOP: %ld\n", res); + } else { + DBG_PRINT("Warning: NEWT X11Window: Fetch _NET_WM_DESKTOP failed: nitems %ld, bytes_after %ld, actual_type %ld, actual_format %d, data_pp %p\n", + nitems, bytes_after, (long)actual_type, actual_format, data_pp); + if( NULL != data_pp ) { + DBG_PRINT("Warning: *data_pp = %ld\n", *data_pp); + } + } + if(NULL!=data_pp) { + XFree(data_pp); + } + } else { + DBG_PRINT("Warning: NEWT X11Window: Could not fetch _NET_WM_DESKTOP, nitems %ld, bytes_after %ld, result 0!\n", nitems, bytes_after); + } + return res; +} +static void NewtWindows_sendNET_WM_DESKTOP(Display *dpy, Window root, JavaWindow * w, unsigned long deskNum) { + XEvent xev; + memset ( &xev, 0, sizeof(xev) ); + + xev.type = ClientMessage; + xev.xclient.window = w->window; + xev.xclient.message_type = w->allAtoms[_NET_WM_DESKTOP_IDX]; + xev.xclient.format = 32; + xev.xclient.data.l[0] = deskNum; + xev.xclient.data.l[1] = 1; //source indication for normal applications + XSendEvent ( dpy, root, False, SubstructureNotifyMask | SubstructureRedirectMask, &xev ); +} + /** * Set fullscreen using Extended Window Manager Hints (EWMH) @@ -320,151 +628,98 @@ static void NewtWindows_setNormalWindowEWMH (Display *dpy, Window w) { * and resets it when leaving FS. * The same is assumed for the decoration state. */ -static int NewtWindows_getSupportedStackingEWMHFlags(Display *dpy, Window w) { -#ifdef VERBOSE_ON - // Code doesn't work reliable on KDE4 ... - Atom _NET_WM_ALLOWED_ACTIONS = XInternAtom( dpy, "_NET_WM_ALLOWED_ACTIONS", False ); - Atom _NET_WM_ACTION_FULLSCREEN = XInternAtom( dpy, "_NET_WM_ACTION_FULLSCREEN", False ); - Atom _NET_WM_ACTION_ABOVE = XInternAtom( dpy, "_NET_WM_ACTION_ABOVE", False ); - Atom * actions = NULL; - Atom type = 0; - unsigned long action_len = 0, remain = 0; - int res = 0, form = 0, i = 0; - Status s; - - if ( Success == (s = XGetWindowProperty(dpy, w, _NET_WM_ALLOWED_ACTIONS, 0, 1024, False, AnyPropertyType, - &type, &form, &action_len, &remain, (unsigned char**)&actions)) ) { - if( NULL != actions ) { - for(i=0; i<action_len; i++) { - if(_NET_WM_ACTION_FULLSCREEN == actions[i]) { - DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: _NET_WM_ACTION_FULLSCREEN (*)\n", i); - res |= _NET_WM_STATE_FLAG_FULLSCREEN ; - } else if(_NET_WM_ACTION_ABOVE == actions[i]) { - DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: _NET_WM_ACTION_ABOVE (*)\n", i); - res |= _NET_WM_STATE_FLAG_ABOVE ; - } - else { - char * astr = XGetAtomName(dpy, actions[i]); - DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: %s (unused)\n", i, astr); - XFree(astr); - } - } - XFree(actions); - } - DBG_PRINT( "**************** X11: FS EWMH CHECK: 0x%X\n", res); - } else { - DBG_PRINT( "**************** X11: FS EWMH CHECK: XGetWindowProperty failed: %d\n", s); +static void NewtWindows_setStackingEWMHFlags (Display *dpy, Window root, JavaWindow * w, int ewmhFlags, Bool enable) { + if( 0 == ewmhFlags ) { + return; } -#endif - return _NET_WM_STATE_FLAG_FULLSCREEN | _NET_WM_STATE_FLAG_ABOVE ; -} - -static Bool NewtWindows_setStackingEWMHFlags (Display *dpy, Window root, Window w, int ewmhFlags, Bool isVisible, Bool enable) { - Atom _NET_WM_STATE = XInternAtom( dpy, "_NET_WM_STATE", False ); - Atom _NET_WM_STATE_ABOVE = XInternAtom( dpy, "_NET_WM_STATE_ABOVE", False ); - Atom _NET_WM_STATE_FULLSCREEN = XInternAtom( dpy, "_NET_WM_STATE_FULLSCREEN", False ); - int ewmhMask = NewtWindows_getSupportedStackingEWMHFlags(dpy, w); - Bool changeFullscreen = 0 != ( ( _NET_WM_STATE_FLAG_FULLSCREEN & ewmhMask ) & ewmhFlags ) ; - Bool changeAbove = 0 != ( ( _NET_WM_STATE_FLAG_ABOVE & ewmhMask ) & ewmhFlags ) ; - Bool res = False; - - if(0 == ewmhMask) { - return res; - } - - // _NET_WM_STATE: fullscreen and/or above - if( changeFullscreen || changeAbove ) { - { - // _NET_WM_STATE as event to root window - XEvent xev; - long mask = SubstructureNotifyMask | SubstructureRedirectMask ; - int i=0; - - memset ( &xev, 0, sizeof(xev) ); - - xev.type = ClientMessage; - xev.xclient.window = w; - xev.xclient.message_type = _NET_WM_STATE; - xev.xclient.format = 32; - - xev.xclient.data.l[i++] = enable ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE ; - if( changeFullscreen ) { - xev.xclient.data.l[i++] = _NET_WM_STATE_FULLSCREEN; - } - if( changeAbove ) { - xev.xclient.data.l[i++] = _NET_WM_STATE_ABOVE; - } - xev.xclient.data.l[3] = 1; //source indication for normal applications - - XSendEvent ( dpy, root, False, mask, &xev ); + Bool changeSticky = 0 != ( _MASK_NET_WM_STATE_STICKY & ewmhFlags ) ; + Bool changeFullscreen = 0 != ( _MASK_NET_WM_STATE_FULLSCREEN & ewmhFlags ) ; + Bool changeAbove = 0 != ( _MASK_NET_WM_STATE_ABOVE & ewmhFlags ) ; + Bool changeBelow = 0 != ( _MASK_NET_WM_STATE_BELOW & ewmhFlags ) ; + Bool changeMaxVert = 0 != ( _MASK_NET_WM_STATE_MAXIMIZED_VERT & ewmhFlags ) ; + Bool changeMaxHorz = 0 != ( _MASK_NET_WM_STATE_MAXIMIZED_HORZ & ewmhFlags ) ; + + if( changeSticky ) { + unsigned long deskNum; + if( enable ) { + w->lastDesktop = NewtWindows_getDesktopNum(dpy, root, w); + deskNum = 0xFFFFFFFFU; + } else { + deskNum = w->lastDesktop; + } + NewtWindows_sendNET_WM_STATE(dpy, root, w, _NET_WM_STATE_STICKY_IDX, 0, enable); + NewtWindows_sendNET_WM_DESKTOP(dpy, root, w, deskNum); + } else if( changeFullscreen || changeAbove || changeBelow ) { + int prop2Idx; + if( changeAbove ) { + prop2Idx = _NET_WM_STATE_ABOVE_IDX; + } else if( changeBelow ) { + prop2Idx = _NET_WM_STATE_BELOW_IDX; + } else { + prop2Idx = 0; } + NewtWindows_sendNET_WM_STATE(dpy, root, w, + changeFullscreen ? _NET_WM_STATE_FULLSCREEN_IDX : 0, + prop2Idx, + enable); // Also change _NET_WM_BYPASS_COMPOSITOR! // A value of 0 indicates no preference. // A value of 1 hints the compositor to disabling compositing of this window. // A value of 2 hints the compositor to not disabling compositing of this window - { - Atom _NET_WM_BYPASS_COMPOSITOR = XInternAtom( dpy, "_NET_WM_BYPASS_COMPOSITOR", False ); + if( changeFullscreen ) { unsigned long value = enable ? 1 : 0; - XChangeProperty( dpy, w, _NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&value, 1); + XChangeProperty( dpy, w->window, w->allAtoms[_NET_WM_BYPASS_COMPOSITOR_IDX], XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&value, 1); } - XSync(dpy, False); - res = True; + } else if( changeMaxVert || changeMaxHorz ) { + NewtWindows_sendNET_WM_STATE(dpy, root, w, + changeMaxVert ? _NET_WM_STATE_MAXIMIZED_VERT_IDX : 0, + changeMaxHorz ? _NET_WM_STATE_MAXIMIZED_HORZ_IDX : 0, + enable); } - DBG_PRINT( "X11: setStackingEWMHFlags ON %d, changeFullscreen %d, changeAbove %d, visible %d: %d\n", - enable, changeFullscreen, changeAbove, isVisible, res); - return res; + XSync(dpy, False); + DBG_PRINT( "X11: setStackingEWMHFlags ON %d, change[Sticky %d, Fullscreen %d, Above %d, Below %d, MaxV %d, MaxH %d]\n", + enable, changeSticky, changeFullscreen, changeAbove, changeBelow, changeMaxVert, changeMaxHorz); } - -Status NewtWindows_updateInsets(JNIEnv *env, jobject jwindow, Display *dpy, Window window, int *left, int *right, int *top, int *bottom) { - if(0 != NewtWindows_getFrameExtends(dpy, window, left, right, top, bottom)) { - DBG_PRINT( "NewtWindows_updateInsets: insets by _NET_FRAME_EXTENTS [ l %d, r %d, t %d, b %d ]\n", - *left, *right, *top, *bottom); - (*env)->CallVoidMethod(env, jwindow, insetsChangedID, JNI_FALSE, *left, *right, *top, *bottom); - return 1; // OK - } - - Bool hasDecor = NewtWindows_hasDecorations (dpy, window); - if(hasDecor) { - // The following logic only works if window is top-level _and_ the WM - // has 'decorated' our client window w/ another parent window _within_ the actual 'framed' window. - Window parent = NewtWindows_getParent(dpy, window); - if(0 != NewtWindows_getWindowPositionRelative2Parent (dpy, parent, left, top)) { - *right = *left; *bottom = *top; - DBG_PRINT( "NewtWindows_updateInsets: insets by parent position [ l %d, r %d, t %d, b %d ]\n", - *left, *right, *top, *bottom); - (*env)->CallVoidMethod(env, jwindow, insetsChangedID, JNI_FALSE, *left, *right, *top, *bottom); - return 1; // OK - } - } - DBG_PRINT( "NewtWindows_updateInsets: cannot determine insets - hasDecor %d\n", hasDecor); - return 0; // Error +static Bool WaitForMapNotify( Display *dpy, XEvent *event, XPointer arg ) { + return (event->type == MapNotify) && (event->xmap.window == (Window) arg); } -static void NewtWindows_requestFocus (Display *dpy, Window w, Bool force) { - XWindowAttributes xwa; - Window focus_return; - int revert_to_return; - - XSync(dpy, False); - XGetInputFocus(dpy, &focus_return, &revert_to_return); - DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d, hasFocus %d\n", dpy, (void*)w, force, focus_return==w); +static Bool WaitForUnmapNotify( Display *dpy, XEvent *event, XPointer arg ) { + return (event->type == UnmapNotify) && (event->xmap.window == (Window) arg); +} - if( True==force || focus_return!=w) { - DBG_PRINT( "X11: XRaiseWindow dpy %p, win %p\n", dpy, (void*)w); - XRaiseWindow(dpy, w); - NewtWindows_setCWAbove(dpy, w); - // Avoid 'BadMatch' errors from XSetInputFocus, ie if window is not viewable - XGetWindowAttributes(dpy, w, &xwa); - DBG_PRINT( "X11: XSetInputFocus dpy %p,win %p, isViewable %d\n", dpy, (void*)w, (xwa.map_state == IsViewable)); - if(xwa.map_state == IsViewable) { - XSetInputFocus(dpy, w, RevertToParent, CurrentTime); +static void NewtWindows_setVisible(Display *dpy, Window root, JavaWindow* jw, Bool visible, Bool useWM, Bool waitForMapNotify) { + XEvent event; + if( !visible && useWM && 0 != ( _MASK_NET_WM_STATE_HIDDEN & jw->supportedAtoms ) ) { + XEvent xev; + memset ( &xev, 0, sizeof(xev) ); + xev.type = ClientMessage; + xev.xclient.window = jw->window; + xev.xclient.message_type = jw->allAtoms[_WM_CHANGE_STATE_IDX]; + xev.xclient.format = 32; + xev.xclient.data.l[0] = IconicState; + XSendEvent ( dpy, root, False, SubstructureNotifyMask | SubstructureRedirectMask, &xev ); + // NewtWindows_sendNET_WM_STATE(dpy, root, jw, _NET_WM_STATE_HIDDEN_IDX, 0, !visible); + if(waitForMapNotify) { + XIfEvent( dpy, &event, WaitForUnmapNotify, (XPointer) jw->window ); + } + } else { + if( visible ) { + XMapRaised(dpy, jw->window); + if(waitForMapNotify) { + XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) jw->window ); + } + } else { + XUnmapWindow(dpy, jw->window); + if(waitForMapNotify) { + XIfEvent( dpy, &event, WaitForUnmapNotify, (XPointer) jw->window ); + } } } - DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d - FIN\n", dpy, (void*)w, force); - XSync(dpy, False); } + /** * Window */ @@ -480,15 +735,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_WindowDriver_initIDs0 return JNI_TRUE; } -static Bool WaitForMapNotify( Display *dpy, XEvent *event, XPointer arg ) { - return (event->type == MapNotify) && (event->xmap.window == (Window) arg); -} - -static Bool WaitForUnmapNotify( Display *dpy, XEvent *event, XPointer arg ) { - return (event->type == UnmapNotify) && (event->xmap.window == (Window) arg); -} - -static void NewtWindows_setPosSize(Display *dpy, Window w, jint x, jint y, jint width, jint height) { +static void NewtWindows_setPosSize(Display *dpy, JavaWindow* w, jint x, jint y, jint width, jint height) { if( ( width>0 && height>0 ) || ( x>=0 && y>=0 ) ) { // resize/position if requested XWindowChanges xwc; int flags = CWX | CWY; @@ -502,27 +749,27 @@ static void NewtWindows_setPosSize(Display *dpy, Window w, jint x, jint y, jint xwc.width=width; xwc.height=height; } - XConfigureWindow(dpy, w, flags, &xwc); + XConfigureWindow(dpy, w->window, flags, &xwc); XSync(dpy, False); } } static void NewtWindows_setIcon(Display *dpy, Window w, int data_size, const unsigned char * data_ptr) { - Atom _NET_WM_ICON = XInternAtom(dpy, "_NET_WM_ICON", False); - Atom CARDINAL = XInternAtom(dpy, "CARDINAL", False); - XChangeProperty(dpy, w, _NET_WM_ICON, CARDINAL, 32, PropModeReplace, data_ptr, data_size); + Atom _NET_WM_ICON = XInternAtom( dpy, "_NET_WM_ICON", False ); + XChangeProperty(dpy, w, _NET_WM_ICON, XA_CARDINAL, 32, PropModeReplace, data_ptr, data_size); } /* * Class: jogamp_newt_driver_x11_WindowDriver * Method: CreateWindow */ -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0 +JNIEXPORT jlongArray JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0 (JNIEnv *env, jobject obj, jlong parent, jlong display, jint screen_index, jint visualID, jlong javaObjectAtom, jlong windowDeleteAtom, - jint x, jint y, jint width, jint height, jboolean autoPosition, int flags, - jint pixelDataSize, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct) + jint x, jint y, jint width, jint height, int flags, + jint pixelDataSize, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, + jboolean verbose) { Display * dpy = (Display *)(intptr_t)display; Atom wm_delete_atom = (Atom)windowDeleteAtom; @@ -530,7 +777,9 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0 Window root = RootWindow(dpy, scrn_idx); Window windowParent = (Window) parent; Window window = 0; - jobject jwindow = 0; + JavaWindow * javaWindow = NULL; + jlong handles[2]; + jlongArray jhandles; XVisualInfo visualTemplate; XVisualInfo *pVisualQuery = NULL; @@ -558,9 +807,10 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0 if(0==windowParent) { windowParent = root; } - DBG_PRINT( "X11: CreateWindow dpy %p, screen %d, visualID 0x%X, parent %p, %d/%d %dx%d, undeco %d, alwaysOnTop %d, autoPosition %d\n", + DBG_PRINT( "X11: CreateWindow dpy %p, screen %d, visualID 0x%X, parent %p, %d/%d %dx%d, undeco %d, alwaysOn[Top %d, Bottom %d], autoPos %d, resizable %d\n", (void*)dpy, scrn_idx, (int)visualID, (void*)windowParent, x, y, width, height, - TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_IS_ALWAYSONTOP(flags), autoPosition); + TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_IS_ALWAYSONTOP(flags), TST_FLAG_IS_ALWAYSONBOTTOM(flags), + TST_FLAG_IS_AUTOPOSITION(flags), TST_FLAG_IS_RESIZABLE(flags)); // try given VisualID on screen memset(&visualTemplate, 0, sizeof(XVisualInfo)); @@ -608,7 +858,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0 { int _x = x, _y = y; // pos for CreateWindow, might be tweaked - if(JNI_TRUE == autoPosition) { + if( TST_FLAG_IS_AUTOPOSITION(flags) ) { // user didn't requested specific position, use WM default _x = 0; _y = 0; @@ -631,11 +881,10 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0 } XSetWMProtocols(dpy, window, &wm_delete_atom, 1); // windowDeleteAtom - jwindow = (*env)->NewGlobalRef(env, obj); - setJavaWindowProperty(env, dpy, window, javaObjectAtom, jwindow); + javaWindow = createJavaWindowProperty(env, dpy, root, window, javaObjectAtom, windowDeleteAtom, obj, verbose); - NewtWindows_setNormalWindowEWMH(dpy, window); - NewtWindows_setDecorations(dpy, window, TST_FLAG_IS_UNDECORATED(flags) ? False : True ); + NewtWindows_setWindowTypeEWMH(dpy, javaWindow, _NET_WM_WINDOW_TYPE_NORMAL_IDX); + NewtWindows_setDecorations(dpy, javaWindow, TST_FLAG_IS_UNDECORATED(flags) ? False : True ); // since native creation happens at setVisible(true) .. // we can pre-map the window here to be able to gather the insets and position. @@ -664,30 +913,54 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0 } // send insets before visibility, allowing java code a proper sync point! - NewtWindows_updateInsets(env, jwindow, dpy, window, &left, &right, &top, &bottom); - (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE); + NewtWindows_updateInsets(env, dpy, javaWindow, &left, &right, &top, &bottom); + (*env)->CallVoidMethod(env, javaWindow->jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE); - if(JNI_TRUE == autoPosition) { + if( TST_FLAG_IS_AUTOPOSITION(flags) ) { // get position from WM int dest_x, dest_y; Window child; XTranslateCoordinates(dpy, window, windowParent, 0, 0, &dest_x, &dest_y, &child); x = (int)dest_x; y = (int)dest_y; } - DBG_PRINT("X11: [CreateWindow]: client: %d/%d %dx%d (autoPosition %d)\n", x, y, width, height, autoPosition); + DBG_PRINT("X11: [CreateWindow]: client: %d/%d %dx%d, autoPos %d\n", x, y, width, height, TST_FLAG_IS_AUTOPOSITION(flags)); x -= left; // top-level y -= top; // top-level DBG_PRINT("X11: [CreateWindow]: top-level: %d/%d\n", x, y); - NewtWindows_setPosSize(dpy, window, x, y, width, height); + NewtWindows_setPosSize(dpy, javaWindow, x, y, width, height); if( TST_FLAG_IS_ALWAYSONTOP(flags) ) { - NewtWindows_setStackingEWMHFlags(dpy, root, window, _NET_WM_STATE_FLAG_ABOVE, True, True); + NewtWindows_setStackingEWMHFlags(dpy, root, javaWindow, _MASK_NET_WM_STATE_ABOVE, True); + } else if( TST_FLAG_IS_ALWAYSONBOTTOM(flags) ) { + NewtWindows_setStackingEWMHFlags(dpy, root, javaWindow, _MASK_NET_WM_STATE_BELOW, True); + } + if( TST_FLAG_IS_STICKY(flags) ) { + NewtWindows_setStackingEWMHFlags(dpy, root, javaWindow, _MASK_NET_WM_STATE_STICKY, True); + } + if( TST_FLAG_IS_MAXIMIZED_ANY(flags) ) { + int cmd = 0; + if( TST_FLAG_IS_MAXIMIZED_VERT(flags) ) { + cmd = _MASK_NET_WM_STATE_MAXIMIZED_VERT; + } + if( TST_FLAG_IS_MAXIMIZED_HORZ(flags) ) { + cmd |= _MASK_NET_WM_STATE_MAXIMIZED_HORZ; + } + NewtWindows_setStackingEWMHFlags(dpy, root, javaWindow, cmd, True); + } + if( !TST_FLAG_IS_RESIZABLE(flags) ) { + NewtWindows_setMinMaxSize(dpy, javaWindow, width, height, width, height); } } - - DBG_PRINT( "X11: [CreateWindow] created window %p on display %p\n", (void*)window, dpy); - return (jlong) window; + handles[0] = (jlong)(intptr_t)window; + handles[1] = (jlong)(intptr_t)javaWindow; + jhandles = (*env)->NewLongArray(env, 2); + if (jhandles == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate long array of size 2"); + } + (*env)->SetLongArrayRegion(env, jhandles, 0, 2, handles); + DBG_PRINT( "X11: [CreateWindow] created window %p -> %p on display %p\n", (void*)window, (void*)javaWindow, dpy); + return jhandles; } /* @@ -696,47 +969,53 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0 * Signature: (JJ)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0 - (JNIEnv *env, jobject obj, jlong display, jlong window, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/, // XKB disabled for now + (JNIEnv *env, jobject obj, jlong display, jlong javaWindow /*, jlong kbdHandle*/, // XKB disabled for now jint randr_event_base, jint randr_error_base) { Display * dpy = (Display *) (intptr_t) display; - Window w = (Window)window; - jobject jwindow; + JavaWindow * jw, * jw0; XWindowAttributes xwa; + DBG_PRINT( "X11: CloseWindow START dpy %p, win %p\n", (void*)dpy, (void*)javaWindow); if(dpy==NULL) { NewtCommon_FatalError(env, "invalid display connection.."); } - - DBG_PRINT( "X11: CloseWindow START dpy %p, win %p\n", (void*)dpy, (void*)w); - - jwindow = getJavaWindowProperty(env, dpy, w, javaObjectAtom, True); - if(NULL==jwindow) { + jw = (JavaWindow*)(intptr_t)javaWindow; + if(jw==NULL) { + NewtCommon_FatalError(env, "invalid JavaWindow connection.."); + } + jw0 = getJavaWindowProperty(env, dpy, jw->window, jw->javaObjectAtom, True); + if(NULL==jw) { NewtCommon_throwNewRuntimeException(env, "could not fetch Java Window object, bail out!"); return; } - if ( JNI_FALSE == (*env)->IsSameObject(env, jwindow, obj) ) { + if ( jw != jw0 ) { + NewtCommon_throwNewRuntimeException(env, "Internal Error .. JavaWindow not the same!"); + return; + } + if ( JNI_FALSE == (*env)->IsSameObject(env, jw->jwindow, obj) ) { NewtCommon_throwNewRuntimeException(env, "Internal Error .. Window global ref not the same!"); return; } XSync(dpy, False); memset(&xwa, 0, sizeof(XWindowAttributes)); - XGetWindowAttributes(dpy, w, &xwa); // prefetch colormap to be destroyed after window destruction - XSelectInput(dpy, w, 0); - XUnmapWindow(dpy, w); + XGetWindowAttributes(dpy, jw->window, &xwa); // prefetch colormap to be destroyed after window destruction + XSelectInput(dpy, jw->window, 0); + XUnmapWindow(dpy, jw->window); // Drain all events related to this window .. - Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, obj, display, javaObjectAtom, windowDeleteAtom /*, kbdHandle */, // XKB disabled for now - randr_event_base, randr_error_base); + Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, obj, display, + (jlong)(intptr_t)jw->javaObjectAtom, (jlong)(intptr_t)jw->windowDeleteAtom /*, kbdHandle */, // XKB disabled for now + randr_event_base, randr_error_base); - XDestroyWindow(dpy, w); + XDestroyWindow(dpy, jw->window); if( None != xwa.colormap ) { XFreeColormap(dpy, xwa.colormap); } XSync(dpy, True); // discard all events now, no more handler - (*env)->DeleteGlobalRef(env, jwindow); + destroyJavaWindow(env, jw); DBG_PRINT( "X11: CloseWindow END\n"); } @@ -764,12 +1043,12 @@ static Bool WaitForReparentNotify( Display *dpy, XEvent *event, XPointer arg ) { */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindow0 (JNIEnv *env, jobject obj, jlong jdisplay, jint screen_index, - jlong jparent, jlong jwindow, jlong windowDeleteAtom, + jlong jparent, jlong javaWindow, 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; + JavaWindow *jw = (JavaWindow*)(intptr_t)javaWindow; + Atom wm_delete_atom = jw->windowDeleteAtom; Window root = RootWindow(dpy, screen_index); Window parent = (0!=jparent)?(Window)jparent:root; XEvent event; @@ -779,34 +1058,45 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo int fsEWMHFlags = 0; if( TST_FLAG_CHANGE_FULLSCREEN(flags) ) { if( !TST_FLAG_IS_FULLSCREEN_SPAN(flags) ) { // doesn't work w/ spanning across monitors. See also Bug 770 & Bug 771 - fsEWMHFlags |= _NET_WM_STATE_FLAG_FULLSCREEN; + fsEWMHFlags |= _MASK_NET_WM_STATE_FULLSCREEN; } if( TST_FLAG_IS_FULLSCREEN(flags) ) { if( TST_FLAG_IS_ALWAYSONTOP(flags) ) { - fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // fs on, above on + fsEWMHFlags |= _MASK_NET_WM_STATE_ABOVE; // fs on, above on + } else if( TST_FLAG_IS_ALWAYSONBOTTOM(flags) ) { + fsEWMHFlags |= _MASK_NET_WM_STATE_BELOW; // fs on, below on } // else { } // fs on, above off } else if( !TST_FLAG_IS_ALWAYSONTOP(flags) ) { - fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // fs off, above off - } // else { } // fs off, above on + fsEWMHFlags |= _MASK_NET_WM_STATE_ABOVE; // fs off, above off + } else if( !TST_FLAG_IS_ALWAYSONBOTTOM(flags) ) { + fsEWMHFlags |= _MASK_NET_WM_STATE_BELOW; // fs off, below off + } // else { } // fs off, above/below on } else if( TST_FLAG_CHANGE_PARENTING(flags) ) { // Fix for Unity WM, i.e. _remove_ persistent previous states - fsEWMHFlags |= _NET_WM_STATE_FLAG_FULLSCREEN; // fs off + fsEWMHFlags |= _MASK_NET_WM_STATE_FULLSCREEN; // fs off if( !TST_FLAG_IS_ALWAYSONTOP(flags) ) { - fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // above off + fsEWMHFlags |= _MASK_NET_WM_STATE_ABOVE; // above off + } else if( !TST_FLAG_IS_ALWAYSONBOTTOM(flags) ) { + fsEWMHFlags |= _MASK_NET_WM_STATE_BELOW; // below off } } else if( TST_FLAG_CHANGE_ALWAYSONTOP(flags) ) { - fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // toggle above + fsEWMHFlags |= _MASK_NET_WM_STATE_ABOVE; // toggle above + } else if( TST_FLAG_CHANGE_ALWAYSONBOTTOM(flags) ) { + fsEWMHFlags |= _MASK_NET_WM_STATE_BELOW; // toggle below } - DBG_PRINT( "X11: reconfigureWindow0 dpy %p, scrn %d, parent %p/%p, win %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d (span %d), alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d, tempInvisible %d, fsEWMHFlags %d\n", - (void*)dpy, screen_index, (void*) jparent, (void*)parent, (void*)w, + DBG_PRINT( "X11: reconfigureWindow0 dpy %p, scrn %d, parent %p/%p, win %p, %d/%d %dx%d, parentChange %d, isChild %d, undecorated[change %d, val %d], fullscreen[change %d, val %d (span %d)], alwaysOn[Top[change %d, val %d], Bottom[change %d, val %d]], visible[change %d, val %d, tempInvisible %d], resizable[change %d, val %d], sticky[change %d, val %d], fsEWMHFlags %d\n", + (void*)dpy, screen_index, (void*) jparent, (void*)parent, (void*)jw->window, x, y, width, height, - TST_FLAG_CHANGE_PARENTING(flags), TST_FLAG_HAS_PARENT(flags), + TST_FLAG_CHANGE_PARENTING(flags), TST_FLAG_IS_CHILD(flags), TST_FLAG_CHANGE_DECORATION(flags), TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_CHANGE_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN_SPAN(flags), - TST_FLAG_CHANGE_ALWAYSONTOP(flags), TST_FLAG_IS_ALWAYSONTOP(flags), - TST_FLAG_CHANGE_VISIBILITY(flags), TST_FLAG_IS_VISIBLE(flags), - tempInvisible, fsEWMHFlags); + TST_FLAG_CHANGE_ALWAYSONTOP(flags), TST_FLAG_IS_ALWAYSONTOP(flags), + TST_FLAG_CHANGE_ALWAYSONBOTTOM(flags), TST_FLAG_IS_ALWAYSONBOTTOM(flags), + TST_FLAG_CHANGE_VISIBILITY(flags), TST_FLAG_IS_VISIBLE(flags), tempInvisible, + TST_FLAG_CHANGE_RESIZABLE(flags), TST_FLAG_IS_RESIZABLE(flags), + TST_FLAG_CHANGE_STICKY(flags), TST_FLAG_IS_STICKY(flags), + fsEWMHFlags); // FS Note: To toggle FS, utilizing the _NET_WM_STATE_FULLSCREEN WM state should be enough. // However, we have to consider other cases like reparenting and WM which don't support it. @@ -815,93 +1105,128 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo !TST_FLAG_IS_FULLSCREEN_SPAN(flags) && ( TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_ALWAYSONTOP(flags) ) ) { Bool enable = TST_FLAG_CHANGE_FULLSCREEN(flags) ? TST_FLAG_IS_FULLSCREEN(flags) : TST_FLAG_IS_ALWAYSONTOP(flags) ; - if( NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, enable) ) { - if ( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) { // FS off - restore decoration - NewtWindows_setDecorations (dpy, w, TST_FLAG_IS_UNDECORATED(flags) ? False : True); - } - DBG_PRINT( "X11: reconfigureWindow0 X (fs.atop.fast)\n"); - return; + NewtWindows_setStackingEWMHFlags(dpy, root, jw, fsEWMHFlags, enable); + if ( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) { // FS off - restore decoration + NewtWindows_setDecorations (dpy, jw, TST_FLAG_IS_UNDECORATED(flags) ? False : True); } + DBG_PRINT( "X11: reconfigureWindow0 X (fs.atop.fast)\n"); + return; } #endif - // Toggle ALWAYSONTOP (only) w/o visibility or window stacking sideffects - if( isVisible && fsEWMHFlags && TST_FLAG_CHANGE_ALWAYSONTOP(flags) && - !TST_FLAG_CHANGE_PARENTING(flags) && !TST_FLAG_CHANGE_FULLSCREEN(flags) ) { - if( NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, TST_FLAG_IS_ALWAYSONTOP(flags)) ) { - DBG_PRINT( "X11: reconfigureWindow0 X (atop.fast)\n"); - return; - } + // Toggle ALWAYSONTOP/BOTTOM (only) w/o visibility or window stacking sideffects + if( isVisible && fsEWMHFlags && TST_FLAG_CHANGE_ALWAYSONANY(flags) && + !TST_FLAG_CHANGE_PARENTING(flags) && !TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_CHANGE_RESIZABLE(flags) ) { + NewtWindows_setStackingEWMHFlags(dpy, root, jw, fsEWMHFlags, TST_FLAG_IS_ALWAYSONANY(flags)); + DBG_PRINT( "X11: reconfigureWindow0 X (atop.fast)\n"); + return; } if( tempInvisible ) { DBG_PRINT( "X11: reconfigureWindow0 TEMP VISIBLE OFF\n"); - XUnmapWindow(dpy, w); - XIfEvent( dpy, &event, WaitForUnmapNotify, (XPointer) w ); + NewtWindows_setVisible(dpy, root, jw, False /* visible */, False /* useWM */, True /* wait */); // no need to notify the java side .. just temp change } - if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) || // FS off - ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && !TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // AlwaysOnTop off - NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, False); + if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) || // FS off + ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && !TST_FLAG_IS_ALWAYSONTOP(flags) ) || // AlwaysOnTop off + ( TST_FLAG_CHANGE_ALWAYSONBOTTOM(flags) && !TST_FLAG_IS_ALWAYSONBOTTOM(flags) ) ) ) { // AlwaysOnBottom off + NewtWindows_setStackingEWMHFlags(dpy, root, jw, fsEWMHFlags, False); } - if( TST_FLAG_CHANGE_PARENTING(flags) && !TST_FLAG_HAS_PARENT(flags) ) { + if( TST_FLAG_CHANGE_PARENTING(flags) && !TST_FLAG_IS_CHILD(flags) ) { // TOP: in -> out DBG_PRINT( "X11: reconfigureWindow0 PARENTING in->out\n"); - XReparentWindow( dpy, w, parent, x, y ); // actual reparent call + XReparentWindow( dpy, jw->window, parent, x, y ); // actual reparent call #ifdef REPARENT_WAIT_FOR_REPARENT_NOTIFY - XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) w ); + XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) jw->window ); #endif XSync(dpy, False); - XSetWMProtocols(dpy, w, &wm_delete_atom, 1); // windowDeleteAtom + XSetWMProtocols(dpy, jw->window, &wm_delete_atom, 1); // windowDeleteAtom // Fix for Unity WM, i.e. _remove_ persistent previous states - NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, False); + NewtWindows_setStackingEWMHFlags(dpy, root, jw, fsEWMHFlags, False); } if( TST_FLAG_CHANGE_DECORATION(flags) ) { DBG_PRINT( "X11: reconfigureWindow0 DECORATIONS %d\n", !TST_FLAG_IS_UNDECORATED(flags)); - NewtWindows_setDecorations (dpy, w, TST_FLAG_IS_UNDECORATED(flags) ? False : True); + NewtWindows_setDecorations (dpy, jw, TST_FLAG_IS_UNDECORATED(flags) ? False : True); } - DBG_PRINT( "X11: reconfigureWindow0 setPosSize %d/%d %dx%d\n", x, y, width, height); - NewtWindows_setPosSize(dpy, w, x, y, width, height); + if( TST_FLAG_CHANGE_MAXIMIZED_ANY(flags) ) { + int cmd = 0; + if( TST_FLAG_CHANGE_MAXIMIZED_VERT(flags) && + TST_FLAG_CHANGE_MAXIMIZED_HORZ(flags) && + TST_FLAG_IS_MAXIMIZED_VERT(flags) == TST_FLAG_IS_MAXIMIZED_HORZ(flags) ) { + // max-both on or off + cmd = _MASK_NET_WM_STATE_MAXIMIZED_VERT | + _MASK_NET_WM_STATE_MAXIMIZED_HORZ; + NewtWindows_setStackingEWMHFlags(dpy, root, jw, cmd, TST_FLAG_IS_MAXIMIZED_ANY(flags)?True:False); + } else { + // max each on or off + if( TST_FLAG_CHANGE_MAXIMIZED_VERT(flags) ) { + cmd = _MASK_NET_WM_STATE_MAXIMIZED_VERT; + NewtWindows_setStackingEWMHFlags(dpy, root, jw, cmd, TST_FLAG_IS_MAXIMIZED_VERT(flags)?True:False); + } + if( TST_FLAG_CHANGE_MAXIMIZED_HORZ(flags) ) { + cmd = _MASK_NET_WM_STATE_MAXIMIZED_HORZ; + NewtWindows_setStackingEWMHFlags(dpy, root, jw, cmd, TST_FLAG_IS_MAXIMIZED_HORZ(flags)?True:False); + } + } + } else { + if( !TST_FLAG_IS_MAXIMIZED_ANY(flags) ) { + DBG_PRINT( "X11: reconfigureWindow0 setPosSize %d/%d %dx%d\n", x, y, width, height); + NewtWindows_setPosSize(dpy, jw, x, y, width, height); + } + } - if( TST_FLAG_CHANGE_PARENTING(flags) && TST_FLAG_HAS_PARENT(flags) ) { + if( TST_FLAG_CHANGE_PARENTING(flags) && TST_FLAG_IS_CHILD(flags) ) { // CHILD: out -> in DBG_PRINT( "X11: reconfigureWindow0 PARENTING out->in\n"); - XReparentWindow( dpy, w, parent, x, y ); // actual reparent call + XReparentWindow( dpy, jw->window, parent, x, y ); // actual reparent call #ifdef REPARENT_WAIT_FOR_REPARENT_NOTIFY - XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) w ); + XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) jw->window ); #endif XSync(dpy, False); } if( tempInvisible ) { DBG_PRINT( "X11: reconfigureWindow0 TEMP VISIBLE ON\n"); - XMapRaised(dpy, w); - XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) w ); + NewtWindows_setVisible(dpy, root, jw, True /* visible */, False /* useWM */, True /* wait */); // no need to notify the java side .. just temp change } else if( TST_FLAG_CHANGE_VISIBILITY(flags) ) { + Bool useWM = TST_FLAG_CHANGE_VISIBILITY_FAST(flags) ? False : True; if( TST_FLAG_IS_VISIBLE(flags) ) { DBG_PRINT( "X11: reconfigureWindow0 VISIBLE ON\n"); - XMapRaised(dpy, w); + NewtWindows_setVisible(dpy, root, jw, True /* visible */, useWM, False /* wait */); XSync(dpy, False); - // WM may disregard pos/size XConfigureWindow requests for invisible windows! - DBG_PRINT( "X11: reconfigureWindow0 setPosSize.2 %d/%d %dx%d\n", x, y, width, height); - NewtWindows_setPosSize(dpy, w, x, y, width, height); + if( !TST_FLAG_IS_MAXIMIZED_ANY(flags) ) { + // WM may disregard pos/size XConfigureWindow requests for invisible windows! + DBG_PRINT( "X11: reconfigureWindow0 setPosSize.2 %d/%d %dx%d\n", x, y, width, height); + NewtWindows_setPosSize(dpy, jw, x, y, width, height); + } } else { DBG_PRINT( "X11: reconfigureWindow0 VISIBLE OFF\n"); - XUnmapWindow(dpy, w); + NewtWindows_setVisible(dpy, root, jw, False /* visible */, useWM, False /* wait */); XSync(dpy, False); } } - if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags) ) || // FS on - ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // AlwaysOnTop on - NewtWindows_requestFocus (dpy, w, True); - NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, True); + if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags) ) || // FS on + ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && TST_FLAG_IS_ALWAYSONTOP(flags) ) || // AlwaysOnTop on + ( TST_FLAG_CHANGE_ALWAYSONBOTTOM(flags) && TST_FLAG_IS_ALWAYSONBOTTOM(flags) ) ) ) { // AlwaysOnBottom on + NewtWindows_requestFocus (dpy, jw, True); + NewtWindows_setStackingEWMHFlags(dpy, root, jw, fsEWMHFlags, True); + } + if( TST_FLAG_CHANGE_STICKY(flags) ) { + NewtWindows_setStackingEWMHFlags(dpy, root, jw, _MASK_NET_WM_STATE_STICKY, TST_FLAG_IS_STICKY(flags)?True:False); + } + if( TST_FLAG_CHANGE_RESIZABLE(flags) ) { + if( !TST_FLAG_IS_RESIZABLE(flags) ) { + NewtWindows_setMinMaxSize(dpy, jw, width, height, width, height); + } else { + // NewtWindows_setMinMaxSize(dpy, jw, 0, 0, 32767, 32767); // FIXME: .. + NewtWindows_setMinMaxSize(dpy, jw, -1, -1, -1, -1); // FIXME: .. + } } - DBG_PRINT( "X11: reconfigureWindow0 X (full)\n"); } @@ -911,20 +1236,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo * Signature: (JJZ)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_requestFocus0 - (JNIEnv *env, jobject obj, jlong display, jlong window, jboolean force) -{ - NewtWindows_requestFocus ( (Display *) (intptr_t) display, (Window)window, JNI_TRUE==force?True:False ) ; -} - -/* - * Class: jogamp_newt_driver_x11_WindowDriver - * Method: getParentWindow0 - * Signature: (JJ)J - */ -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_getParentWindow0 - (JNIEnv *env, jclass clazz, jlong display, jlong window) + (JNIEnv *env, jobject obj, jlong display, jlong javaWindow, jboolean force) { - return (jlong) NewtWindows_getParent ((Display *) (intptr_t) display, (Window)window); + NewtWindows_requestFocus ( (Display *) (intptr_t) display, (JavaWindow*)(intptr_t)javaWindow, JNI_TRUE==force?True:False ) ; } /* @@ -933,10 +1247,10 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_getParentWindow * Signature: (JJLjava/lang/String;)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setTitle0 - (JNIEnv *env, jclass clazz, jlong display, jlong window, jstring title) + (JNIEnv *env, jclass clazz, jlong display, jlong javaWindow, jstring title) { Display * dpy = (Display *) (intptr_t) display; - Window w = (Window)window; + JavaWindow *jw = (JavaWindow*)(intptr_t)javaWindow; #if 1 const char* title_str; @@ -944,7 +1258,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setTitle0 title_str = (*env)->GetStringUTFChars(env, title, NULL); if(NULL != title_str) { DBG_PRINT( "X11: setTitle: <%s> SET\n", title_str); - XStoreName(dpy, w, title_str); + XStoreName(dpy, jw->window, title_str); (*env)->ReleaseStringUTFChars(env, title, title_str); } else { DBG_PRINT( "X11: setTitle: NULL - NOT SET (1)\n"); @@ -965,7 +1279,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setTitle0 } if(NULL!=text_prop.value) { DBG_PRINT( "X11: setTitle: <%s> SET\n", str_list[0]); - XSetWMName(dpy, w, &text_prop); + XSetWMName(dpy, jw->window, &text_prop); XFree(text_prop.value); } else { DBG_PRINT( "X11: setTitle: <%s> NOT SET (1)\n", str_list[0]); @@ -984,18 +1298,18 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setTitle0 * Signature: (JJILjava/lang/Object;I)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setPointerIcon0 - (JNIEnv *env, jclass clazz, jlong display, jlong window, jlong handle) + (JNIEnv *env, jclass clazz, jlong display, jlong javaWindow, jlong handle) { Display * dpy = (Display *) (intptr_t) display; - Window w = (Window)window; + JavaWindow *jw = (JavaWindow*)(intptr_t)javaWindow; if( 0 == handle ) { DBG_PRINT( "X11: setPointerIcon0: reset\n"); - XUndefineCursor(dpy, w); + XUndefineCursor(dpy, jw->window); } else { Cursor c = (Cursor) (intptr_t) handle; DBG_PRINT( "X11: setPointerIcon0: %p\n", (void*)c); - XDefineCursor(dpy, w, c); + XDefineCursor(dpy, jw->window, c); } } @@ -1005,28 +1319,28 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setPointerIcon0 * Signature: (JJZ)Z */ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setPointerVisible0 - (JNIEnv *env, jclass clazz, jlong display, jlong window, jboolean mouseVisible) + (JNIEnv *env, jclass clazz, jlong display, jlong javaWindow, jboolean mouseVisible) { static char noData[] = { 0,0,0,0,0,0,0,0 }; static XColor black = { 0 }; Display * dpy = (Display *) (intptr_t) display; - Window w = (Window)window; + JavaWindow *jw = (JavaWindow*)(intptr_t)javaWindow; DBG_PRINT( "X11: setPointerVisible0: %d\n", mouseVisible); if(JNI_TRUE == mouseVisible) { - XUndefineCursor(dpy, w); + XUndefineCursor(dpy, jw->window); } else { Pixmap bitmapNoData; Cursor invisibleCursor; - bitmapNoData = XCreateBitmapFromData(dpy, w, noData, 8, 8); + bitmapNoData = XCreateBitmapFromData(dpy, jw->window, noData, 8, 8); if(None == bitmapNoData) { return JNI_FALSE; } invisibleCursor = XCreatePixmapCursor(dpy, bitmapNoData, bitmapNoData, &black, &black, 0, 0); - XDefineCursor(dpy, w, invisibleCursor); + XDefineCursor(dpy, jw->window, invisibleCursor); XFreeCursor(dpy, invisibleCursor); XFreePixmap(dpy, bitmapNoData); } @@ -1039,17 +1353,17 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setPointerVi * Signature: (JJZ)Z */ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_WindowDriver_confinePointer0 - (JNIEnv *env, jclass clazz, jlong display, jlong window, jboolean confine) + (JNIEnv *env, jclass clazz, jlong display, jlong javaWindow, jboolean confine) { Display * dpy = (Display *) (intptr_t) display; - Window w = (Window)window; + JavaWindow *jw = (JavaWindow*)(intptr_t)javaWindow; DBG_PRINT( "X11: confinePointer0: %d\n", confine); if(JNI_TRUE == confine) { - return GrabSuccess == XGrabPointer(dpy, w, True, + return GrabSuccess == XGrabPointer(dpy, jw->window, True, X11_MOUSE_EVENT_MASK, - GrabModeAsync, GrabModeAsync, w, None, CurrentTime) + GrabModeAsync, GrabModeAsync, jw->window, None, CurrentTime) ? JNI_TRUE : JNI_FALSE ; } XUngrabPointer(dpy, CurrentTime); @@ -1062,13 +1376,13 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_WindowDriver_confinePoint * Signature: (JJII)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_warpPointer0 - (JNIEnv *env, jclass clazz, jlong display, jlong window, jint x, jint y) + (JNIEnv *env, jclass clazz, jlong display, jlong javaWindow, jint x, jint y) { Display * dpy = (Display *) (intptr_t) display; - Window w = (Window)window; + JavaWindow *jw = (JavaWindow*)(intptr_t)javaWindow; DBG_PRINT( "X11: warpPointer0: %d/%d\n", x, y); - XWarpPointer(dpy, None, w, 0, 0, 0, 0, x, y); + XWarpPointer(dpy, None, jw->window, 0, 0, 0, 0, x, y); } diff --git a/src/newt/native/XCBEvent.c b/src/newt/native/XCBEvent.c index d02d5a4ba..f27d30b28 100644 --- a/src/newt/native/XCBEvent.c +++ b/src/newt/native/XCBEvent.c @@ -24,7 +24,7 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, // Periodically take a break while( num_events > 0 ) { - jobject jwindow = NULL; + JavaWindow *w = NULL; xcb_generic_event_t *evt; // KeySym keySym = 0; jint modifiers = 0; @@ -54,11 +54,11 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, // X11WindowDisplayErrorHandlerEnable(1, env); - // jwindow = X11WindowGetJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom, VERBOSE_BOOL); + // w = X11WindowGetJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom, VERBOSE_BOOL); //X11WindowDisplayErrorHandlerEnable(0, env); - /*if(NULL==jwindow) { + /*if(NULL==w) { fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n", (void*)dpy, evt.type, (void*)evt.xany.window); continue; @@ -109,14 +109,14 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, (void*)dpy, xcb_event_type); continue; } - jwindow = getJavaWindowProperty(env, dpy, event_window, javaObjectAtom, + w = getJavaWindowProperty(env, dpy, event_window, javaObjectAtom, #ifdef VERBOSE_ON True #else False #endif ); - if(NULL==jwindow) { + if(NULL==w) { fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n", (void*)(intptr_t)dpy, xcb_event_type, (void*)(intptr_t)event_window); continue; @@ -125,13 +125,13 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, switch( xcb_event_type ) { case XCB_BUTTON_PRESS: { xcb_button_press_event_t *_evt = (xcb_button_press_event_t *)evt; - (*env)->CallVoidMethod(env, jwindow, requestFocusID, JNI_FALSE); + (*env)->CallVoidMethod(env, w->jwindow, requestFocusID, JNI_FALSE); #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, + (*env)->CallVoidMethod(env, w->jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, modifiers, (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/); #else - (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED, + (*env)->CallVoidMethod(env, w->jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED, modifiers, (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/); #endif @@ -139,11 +139,11 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, case XCB_BUTTON_RELEASE: { xcb_button_release_event_t *_evt = (xcb_button_release_event_t *)evt; #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, + (*env)->CallVoidMethod(env, w->jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, modifiers, (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/); #else - (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED, + (*env)->CallVoidMethod(env, w->jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED, modifiers, (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/); #endif @@ -151,11 +151,11 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, case XCB_MOTION_NOTIFY: { xcb_motion_notify_event_t *_evt = (xcb_motion_notify_event_t *)evt; #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, + (*env)->CallVoidMethod(env, w->jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, modifiers, (jint) _evt->event_x, (jint) _evt->event_y, (jint)0, 0.0f /*rotation*/); #else - (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED, + (*env)->CallVoidMethod(env, w->jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED, modifiers, (jint) _evt->event_x, (jint) _evt->event_y, (jint)0, 0.0f /*rotation*/); #endif @@ -163,10 +163,10 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, case XCB_KEY_PRESS: { xcb_key_press_event_t *_evt = (xcb_key_press_event_t *)evt; #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED, + (*env)->CallVoidMethod(env, w->jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED, modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar); #else - (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED, + (*env)->CallVoidMethod(env, w->jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED, modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar); #endif } break; @@ -174,10 +174,10 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, xcb_key_release_event_t *_evt = (xcb_key_release_event_t *)evt; event_window = ((xcb_key_release_event_t *)evt)->event; #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED, + (*env)->CallVoidMethod(env, w->jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED, modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar); #else - (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED, + (*env)->CallVoidMethod(env, w->jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED, modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar); #endif @@ -201,9 +201,9 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, evt.xconfigure.override_redirect, evt.xconfigure.window != evt.xconfigure.event); if ( evt.xconfigure.window == evt.xconfigure.event ) { // ignore child window change notification - (*env)->CallVoidMethod(env, jwindow, sizeChangedID, + (*env)->CallVoidMethod(env, w->jwindow, sizeChangedID, (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, JNI_FALSE); - (*env)->CallVoidMethod(env, jwindow, positionChangedID, + (*env)->CallVoidMethod(env, w->jwindow, positionChangedID, (jint) evt.xconfigure.x, (jint) evt.xconfigure.y); } break; @@ -211,7 +211,7 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, if (evt.xclient.send_event==True && evt.xclient.data.l[0]==(Atom)wmDeleteAtom) { 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); + (*env)->CallVoidMethod(env, w->jwindow, windowDestroyNotifyID); // Called by Window.java: CloseWindow(); num_events = 0; // end loop in case of destroyed display } @@ -219,12 +219,12 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, case FocusIn: DBG_PRINT( "X11: event . FocusIn call %p\n", (void*)evt.xvisibility.window); - (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_TRUE); + (*env)->CallVoidMethod(env, w->jwindow, focusChangedID, JNI_TRUE); break; case FocusOut: DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xvisibility.window); - (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE); + (*env)->CallVoidMethod(env, w->jwindow, focusChangedID, JNI_FALSE); break; */ @@ -234,7 +234,7 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, _evt->x, _evt->y, _evt->width, _evt->height, _evt->count); if (_evt->count == 0 && _evt->width > 0 && _evt->height > 0) { - (*env)->CallVoidMethod(env, jwindow, windowRepaintID, + (*env)->CallVoidMethod(env, w->jwindow, windowRepaintID, _evt->x, _evt->y, _evt->width, _evt->height); } } break; @@ -246,7 +246,7 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, _evt->event!=_evt->window); if( _evt->event == _evt->window ) { // ignore child window notification - (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_TRUE); + (*env)->CallVoidMethod(env, w->jwindow, visibleChangedID, JNI_TRUE); } } break; @@ -257,7 +257,7 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, _evt->event!=_evt->window); if( _evt->event == _evt->window ) { // ignore child window notification - (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE); + (*env)->CallVoidMethod(env, w->jwindow, visibleChangedID, JNI_FALSE); } } break; /* @@ -291,7 +291,7 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, (void*)evt.xreparent.window, (void*)winRoot, (void*)winTopParent); #endif - (*env)->CallVoidMethod(env, jwindow, windowReparentedID, parentResult); + (*env)->CallVoidMethod(env, w->jwindow, windowReparentedID, parentResult); } break; */ |