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/X11Window.c | |
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/X11Window.c')
-rw-r--r-- | src/newt/native/X11Window.c | 920 |
1 files changed, 617 insertions, 303 deletions
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); } |