diff options
Diffstat (limited to 'src/newt/native/X11Window.c')
-rw-r--r-- | src/newt/native/X11Window.c | 402 |
1 files changed, 231 insertions, 171 deletions
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index 0f93b3e76..2cc66c78d 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -98,11 +98,11 @@ static void setJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlon } jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning) { - Atom actual_type; - int actual_format; + 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; + jobject jwindow = 0; { unsigned long nitems= 0; @@ -122,7 +122,9 @@ jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong ja } if(actual_type!=(Atom)javaObjectAtom || nitems<nitems_32 || NULL==jogl_java_object_data_pp) { - XFree(jogl_java_object_data_pp); + if( NULL != jogl_java_object_data_pp ) { + XFree(jogl_java_object_data_pp); + } if(True==showWarning) { fprintf(stderr, "Warning: NEWT X11Window: Fetched invalid Atom NEWT_JAVA_OBJECT window property (res %d) nitems %ld, bytes_after %ld, actual_type %ld, NEWT_JAVA_OBJECT %ld, result 0!\n", res, nitems, bytes_after, (long)actual_type, (long)javaObjectAtom); @@ -189,8 +191,8 @@ 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) { - Atom actual_type; - int actual_format; + Atom actual_type = 0; + int actual_format = 0; int nitems_32 = 4; // l, r, t, b unsigned char * frame_extends_data_pp = NULL; @@ -210,7 +212,9 @@ static Status NewtWindows_getFrameExtends(Display *dpy, Window window, int *left } if(nitems<nitems_32 || NULL==frame_extends_data_pp) { - XFree(frame_extends_data_pp); + if( NULL != frame_extends_data_pp ) { + XFree(frame_extends_data_pp); + } // DBG_PRINT( "Warning: NEWT X11Window: Fetched invalid Atom _NET_FRAME_EXTENTS window property (res %d) nitems %ld, bytes_after %ld, actual_type %ld, actual_format %d, _NET_FRAME_EXTENTS %ld, result 0!\n", // res, nitems, bytes_after, (long)actual_type, actual_format, _NET_FRAME_EXTENTS); return 0; // Error, but ok - ie window not mapped @@ -271,18 +275,21 @@ static Bool NewtWindows_hasDecorations (Display *dpy, Window w) { #ifdef DECOR_USE_MWM Atom _MOTIF_WM_HINTS = XInternAtom( dpy, "_MOTIF_WM_HINTS", False ); - unsigned char *wm_data; - Atom wm_type; - int wm_format; - unsigned long wm_nitems, wm_bytes_after; + 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, &wm_type, &wm_format, &wm_nitems, &wm_bytes_after, &wm_data) ) { - if(wm_type != None) { + 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 unsigned long *hints = (unsigned long *) wm_data; decor = ( 0 != (hints[0] & MWM_HINTS_DECORATIONS) ) && ( 0 != hints[2] ); } + if( NULL != wm_data ) { + XFree(wm_data); + } } #endif @@ -299,9 +306,8 @@ static void NewtWindows_setNormalWindowEWMH (Display *dpy, Window w) { #define _NET_WM_STATE_REMOVE 0 #define _NET_WM_STATE_ADD 1 - -#define _NET_WM_FULLSCREEN ( 1 << 0 ) -#define _NET_WM_ABOVE ( 1 << 1 ) +#define _NET_WM_STATE_FLAG_FULLSCREEN ( 1 << 0 ) +#define _NET_WM_STATE_FLAG_ABOVE ( 1 << 1 ) /** * Set fullscreen using Extended Window Manager Hints (EWMH) @@ -314,101 +320,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_isFullscreenEWMHSupported (Display *dpy, Window w) { +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; - Atom type; - unsigned long action_len, remain; - int res = 0, form, i; + 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)) ) { - 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_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_ABOVE ; - } -#ifdef VERBOSE_ON - else { - char * astr = XGetAtomName(dpy, actions[i]); - DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: %s (unused)\n", i, astr); - XFree(astr); + 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); + } } -#endif + XFree(actions); } DBG_PRINT( "**************** X11: FS EWMH CHECK: 0x%X\n", res); } else { DBG_PRINT( "**************** X11: FS EWMH CHECK: XGetWindowProperty failed: %d\n", s); } - // above code doesn't work reliable on KDE4 ... - res = _NET_WM_FULLSCREEN | _NET_WM_ABOVE ; - return res; +#endif + return _NET_WM_STATE_FLAG_FULLSCREEN | _NET_WM_STATE_FLAG_ABOVE ; } -static Bool NewtWindows_setFullscreenEWMH (Display *dpy, Window root, Window w, int ewmhFlags, Bool isVisible, Bool enable) { +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_isFullscreenEWMHSupported(dpy, w); + 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; } - if(!isVisible && True==enable) { - Atom types[2]={0}; - int ntypes=0; - - if( 0 != ( ( _NET_WM_FULLSCREEN & ewmhMask ) & ewmhFlags ) ) { - types[ntypes++] = _NET_WM_STATE_FULLSCREEN; - } - if( 0 != ( ( _NET_WM_ABOVE & ewmhMask ) & ewmhFlags ) ) { - types[ntypes++] = _NET_WM_STATE_ABOVE; - } - if(ntypes>0) { - XChangeProperty( dpy, w, _NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, ntypes); - XSync(dpy, False); - res = True; - } - } else { - if(enable) { - NewtWindows_setCWAbove(dpy, w); - } - 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; + // _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; - xev.xclient.data.l[i++] = ( True == enable ) ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE ; - if( 0 != ( ( _NET_WM_FULLSCREEN & ewmhMask ) & ewmhFlags ) ) { - xev.xclient.data.l[i++] = _NET_WM_STATE_FULLSCREEN; - } - if( 0 != ( ( _NET_WM_ABOVE & ewmhMask ) & ewmhFlags ) ) { - xev.xclient.data.l[i++] = _NET_WM_STATE_ABOVE; - } - xev.xclient.data.l[3] = 1; //source indication for normal applications + 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 - if(i>0) { XSendEvent ( dpy, root, False, mask, &xev ); - res = True; } + // 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 ); + unsigned long value = enable ? 1 : 0; + XChangeProperty( dpy, w, _NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&value, 1); + } + XSync(dpy, False); + res = True; } - XSync(dpy, False); - DBG_PRINT( "X11: reconfigureWindow0 FULLSCREEN EWMH ON %d, ewmhMask 0x%X, ewmhFlags 0x%X, visible %d: %d\n", - enable, ewmhMask, ewmhFlags, isVisible, res); + DBG_PRINT( "X11: setStackingEWMHFlags ON %d, changeFullscreen %d, changeAbove %d, visible %d: %d\n", + enable, changeFullscreen, changeAbove, isVisible, res); return res; } @@ -438,7 +441,7 @@ Status NewtWindows_updateInsets(JNIEnv *env, jobject jwindow, Display *dpy, Wind return 0; // Error } -static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, Window w, jboolean force) { +static void NewtWindows_requestFocus (Display *dpy, Window w, Bool force) { XWindowAttributes xwa; Window focus_return; int revert_to_return; @@ -447,7 +450,7 @@ static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, 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); - if( JNI_TRUE==force || focus_return!=w) { + 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); @@ -467,11 +470,11 @@ static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, */ /* - * Class: jogamp_newt_driver_x11_X11Window + * Class: jogamp_newt_driver_x11_WindowDriver * Method: initIDs * Signature: ()Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Window_initIDs0 +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_WindowDriver_initIDs0 (JNIEnv *env, jclass clazz) { return JNI_TRUE; @@ -504,15 +507,22 @@ static void NewtWindows_setPosSize(Display *dpy, Window w, jint x, jint y, jint } } +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); +} + /* - * Class: jogamp_newt_driver_x11_X11Window + * Class: jogamp_newt_driver_x11_WindowDriver * Method: CreateWindow */ -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0 +JNIEXPORT jlong 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 x, jint y, jint width, jint height, jboolean autoPosition, int flags, + jint pixelDataSize, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct) { Display * dpy = (Display *)(intptr_t)display; Atom wm_delete_atom = (Atom)windowDeleteAtom; @@ -632,12 +642,27 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0 { XEvent event; int left=0, right=0, top=0, bottom=0; + const unsigned char * pixelPtr = NULL; + + // NOTE: MUST BE DIRECT BUFFER, since _NET_WM_ICON Atom uses buffer directly! + DBG_PRINT("X11: CreateWindow icon: size %d, pixels %p, offset %d, direct %d\n", pixelDataSize, (void*)pixels, pixels_byte_offset, pixels_is_direct); + if( 0 < pixelDataSize && NULL != pixels ) { + pixelPtr = (const unsigned char *) ( JNI_TRUE == pixels_is_direct ? + (*env)->GetDirectBufferAddress(env, pixels) : + (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) ); + DBG_PRINT("X11: CreateWindow icon: NIO %p\n", pixelPtr); + NewtWindows_setIcon(dpy, window, (int)pixelDataSize, pixelPtr+pixels_byte_offset); + } XMapWindow(dpy, window); XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) window ); // wait to get proper insets values XSync(dpy, False); + if( JNI_FALSE == pixels_is_direct && NULL != pixelPtr ) { + (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT); + } + // 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); @@ -657,7 +682,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0 NewtWindows_setPosSize(dpy, window, x, y, width, height); if( TST_FLAG_IS_ALWAYSONTOP(flags) ) { - NewtWindows_setFullscreenEWMH(dpy, root, window, _NET_WM_ABOVE, True, True); + NewtWindows_setStackingEWMHFlags(dpy, root, window, _NET_WM_STATE_FLAG_ABOVE, True, True); } } @@ -666,16 +691,17 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0 } /* - * Class: jogamp_newt_driver_x11_X11Window + * Class: jogamp_newt_driver_x11_WindowDriver * Method: CloseWindow * Signature: (JJ)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_CloseWindow0 - (JNIEnv *env, jobject obj, jlong display, jlong window, jlong javaObjectAtom, jlong windowDeleteAtom) +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 { Display * dpy = (Display *) (intptr_t) display; Window w = (Window)window; jobject jwindow; + XWindowAttributes xwa; if(dpy==NULL) { NewtCommon_FatalError(env, "invalid display connection.."); @@ -694,42 +720,47 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_CloseWindow0 } 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); - XSync(dpy, False); // Drain all events related to this window .. - Java_jogamp_newt_driver_x11_X11Display_DispatchMessages0(env, obj, display, javaObjectAtom, windowDeleteAtom); + Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, obj, display, javaObjectAtom, windowDeleteAtom /*, kbdHandle */); // XKB disabled for now XDestroyWindow(dpy, w); - XSync(dpy, False); + if( None != xwa.colormap ) { + XFreeColormap(dpy, xwa.colormap); + } + XSync(dpy, True); // discard all events now, no more handler (*env)->DeleteGlobalRef(env, jwindow); DBG_PRINT( "X11: CloseWindow END\n"); } -#if 0 +// #define REPARENT_WAIT_FOR_REPARENT_NOTIFY 1 + +#ifdef REPARENT_WAIT_FOR_REPARENT_NOTIFY static Bool WaitForReparentNotify( Display *dpy, XEvent *event, XPointer arg ) { - return (event->type == ReparentNotify) && (event->xreparent.window == (Window) arg); + Bool res = (event->type == ReparentNotify) && (event->xreparent.window == (Window) arg); + #ifdef VERBOSE_ON + if( event->type == ReparentNotify ) { + DBG_PRINT( "X11.WaitForReparentNotify: Event ReparentNotify: Result %d, exp %p, has %p\n", (int)res, arg, event->xreparent.window); + } else { + DBG_PRINT( "X11.WaitForReparentNotify: Event 0x%X: Result %d, exp %p, has %p\n", (int)event->type, (int)res, arg, event->xreparent.window); + } + #endif + return res; } #endif -/** - * KDE cause lost input focus in fullscreen mode. - * Using 'XGrabKeyboard(..)' would prevent the loss, - * but also would disable WM task switcher etc. - * - * #define FS_GRAB_KEYBOARD 1 - * - */ - /* - * Class: jogamp_newt_driver_x11_X11Window + * Class: jogamp_newt_driver_x11_WindowDriver * Method: reconfigureWindow0 * Signature: (JIJJIIIII)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0 +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, jint x, jint y, jint width, jint height, jint flags) @@ -742,51 +773,60 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0 XEvent event; Bool isVisible = !TST_FLAG_CHANGE_VISIBILITY(flags) && TST_FLAG_IS_VISIBLE(flags) ; Bool tempInvisible = ( TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_PARENTING(flags) ) && isVisible ; + // Bool tempInvisible = TST_FLAG_CHANGE_PARENTING(flags) && isVisible ; int fsEWMHFlags = 0; if( TST_FLAG_CHANGE_FULLSCREEN(flags) ) { - fsEWMHFlags |= _NET_WM_FULLSCREEN; + 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; + } if( TST_FLAG_IS_FULLSCREEN(flags) ) { if( TST_FLAG_IS_ALWAYSONTOP(flags) ) { - fsEWMHFlags |= _NET_WM_ABOVE; // fs on, above on - } // else { } // fs on, above off + fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // fs on, above on + } // else { } // fs on, above off } else if( !TST_FLAG_IS_ALWAYSONTOP(flags) ) { - fsEWMHFlags |= _NET_WM_ABOVE; // fs off, above off - } // else { } // fs off, above on - } - if( TST_FLAG_CHANGE_ALWAYSONTOP(flags) ) { - fsEWMHFlags |= _NET_WM_ABOVE; // toggle above + fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // fs off, above off + } // else { } // fs off, above 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 + if( !TST_FLAG_IS_ALWAYSONTOP(flags) ) { + fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // above off + } + } else if( TST_FLAG_CHANGE_ALWAYSONTOP(flags) ) { + fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // toggle above } - NewtDisplay_displayDispatchErrorHandlerEnable(1, env); - - 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, alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d, tempInvisible %d, fsEWMHFlags %d\n", + 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, x, y, width, height, TST_FLAG_CHANGE_PARENTING(flags), TST_FLAG_HAS_PARENT(flags), TST_FLAG_CHANGE_DECORATION(flags), TST_FLAG_IS_UNDECORATED(flags), - TST_FLAG_CHANGE_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN(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_VISIBILITY(flags), TST_FLAG_IS_VISIBLE(flags), + tempInvisible, fsEWMHFlags); - // FS Note: To toggle FS, utilizing the _NET_WM_STATE_FULLSCREEN WM state shall be enough. + // 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. - + #if 0 // Also doesn't work work properly w/ Unity WM if( fsEWMHFlags && !TST_FLAG_CHANGE_PARENTING(flags) && isVisible && + !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_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, enable) ) { - NewtDisplay_displayDispatchErrorHandlerEnable(0, env); - #ifdef FS_GRAB_KEYBOARD - if(TST_FLAG_CHANGE_FULLSCREEN(flags)) { - if(TST_FLAG_IS_FULLSCREEN(flags)) { - XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime); - } else { - XUngrabKeyboard(dpy, CurrentTime); - } - } else if(TST_FLAG_CHANGE_ALWAYSONTOP(flags) && !TST_FLAG_IS_ALWAYSONTOP(flags)) { - XUngrabKeyboard(dpy, CurrentTime); + 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); } - #endif + 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; } } @@ -798,21 +838,22 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0 // no need to notify the java side .. just temp change } - if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) || - ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && !TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // FS off - NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, False); - #ifdef FS_GRAB_KEYBOARD - XUngrabKeyboard(dpy, CurrentTime); - #endif + 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( TST_FLAG_CHANGE_PARENTING(flags) && !TST_FLAG_HAS_PARENT(flags) ) { // TOP: in -> out DBG_PRINT( "X11: reconfigureWindow0 PARENTING in->out\n"); XReparentWindow( dpy, w, parent, x, y ); // actual reparent call - // XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) w ); + #ifdef REPARENT_WAIT_FOR_REPARENT_NOTIFY + XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) w ); + #endif XSync(dpy, False); XSetWMProtocols(dpy, w, &wm_delete_atom, 1); // windowDeleteAtom + // Fix for Unity WM, i.e. _remove_ persistent previous states + NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, False); } if( TST_FLAG_CHANGE_DECORATION(flags) ) { @@ -827,7 +868,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0 // CHILD: out -> in DBG_PRINT( "X11: reconfigureWindow0 PARENTING out->in\n"); XReparentWindow( dpy, w, parent, x, y ); // actual reparent call - // XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) w ); + #ifdef REPARENT_WAIT_FOR_REPARENT_NOTIFY + XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) w ); + #endif XSync(dpy, False); } @@ -836,62 +879,58 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0 XMapRaised(dpy, w); XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) w ); // no need to notify the java side .. just temp change - } - - if( TST_FLAG_CHANGE_VISIBILITY(flags) ) { + } else if( TST_FLAG_CHANGE_VISIBILITY(flags) ) { if( TST_FLAG_IS_VISIBLE(flags) ) { DBG_PRINT( "X11: reconfigureWindow0 VISIBLE ON\n"); XMapRaised(dpy, w); + 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); } else { DBG_PRINT( "X11: reconfigureWindow0 VISIBLE OFF\n"); XUnmapWindow(dpy, w); + XSync(dpy, False); } - XSync(dpy, False); } - if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags) ) || - ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // FS on - NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, True); - #ifdef FS_GRAB_KEYBOARD - if(TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags)) { - XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime); - } - #endif + 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); } - NewtDisplay_displayDispatchErrorHandlerEnable(0, env); - - DBG_PRINT( "X11: reconfigureWindow0 X\n"); + DBG_PRINT( "X11: reconfigureWindow0 X (full)\n"); } /* - * Class: jogamp_newt_driver_x11_X11Window + * Class: jogamp_newt_driver_x11_WindowDriver * Method: requestFocus0 * Signature: (JJZ)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_requestFocus0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_requestFocus0 (JNIEnv *env, jobject obj, jlong display, jlong window, jboolean force) { - NewtWindows_requestFocus ( env, obj, (Display *) (intptr_t) display, (Window)window, force ) ; + NewtWindows_requestFocus ( (Display *) (intptr_t) display, (Window)window, JNI_TRUE==force?True:False ) ; } /* - * Class: jogamp_newt_driver_x11_X11Window + * Class: jogamp_newt_driver_x11_WindowDriver * Method: getParentWindow0 * Signature: (JJ)J */ -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_getParentWindow0 +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_getParentWindow0 (JNIEnv *env, jclass clazz, jlong display, jlong window) { return (jlong) NewtWindows_getParent ((Display *) (intptr_t) display, (Window)window); } /* - * Class: Java_jogamp_newt_driver_x11_X11Window + * Class: Java_jogamp_newt_driver_x11_WindowDriver * Method: setTitle0 * Signature: (JJLjava/lang/String;)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_setTitle0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setTitle0 (JNIEnv *env, jclass clazz, jlong display, jlong window, jstring title) { Display * dpy = (Display *) (intptr_t) display; @@ -938,11 +977,32 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_setTitle0 } /* - * Class: Java_jogamp_newt_driver_x11_X11Window + * Class: Java_jogamp_newt_driver_x11_WindowDriver + * Method: setPointerIcon0 + * 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) +{ + Display * dpy = (Display *) (intptr_t) display; + Window w = (Window)window; + + if( 0 == handle ) { + DBG_PRINT( "X11: setPointerIcon0: reset\n"); + XUndefineCursor(dpy, w); + } else { + Cursor c = (Cursor) (intptr_t) handle; + DBG_PRINT( "X11: setPointerIcon0: %p\n", (void*)c); + XDefineCursor(dpy, w, c); + } +} + +/* + * Class: Java_jogamp_newt_driver_x11_WindowDriver * Method: setPointerVisible0 * Signature: (JJZ)Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Window_setPointerVisible0 +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setPointerVisible0 (JNIEnv *env, jclass clazz, jlong display, jlong window, jboolean mouseVisible) { static char noData[] = { 0,0,0,0,0,0,0,0 }; @@ -972,11 +1032,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Window_setPointerVisib } /* - * Class: Java_jogamp_newt_driver_x11_X11Window + * Class: Java_jogamp_newt_driver_x11_WindowDriver * Method: confinePointer0 * Signature: (JJZ)Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Window_confinePointer0 +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_WindowDriver_confinePointer0 (JNIEnv *env, jclass clazz, jlong display, jlong window, jboolean confine) { Display * dpy = (Display *) (intptr_t) display; @@ -995,11 +1055,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Window_confinePointer0 } /* - * Class: Java_jogamp_newt_driver_x11_X11Window + * Class: Java_jogamp_newt_driver_x11_WindowDriver * Method: warpPointer0 * Signature: (JJII)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_warpPointer0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_warpPointer0 (JNIEnv *env, jclass clazz, jlong display, jlong window, jint x, jint y) { Display * dpy = (Display *) (intptr_t) display; |