diff options
author | Sven Gothel <[email protected]> | 2012-01-18 23:12:36 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2012-01-18 23:12:36 +0100 |
commit | ab3c5678527ba2e4f092b7426527b8053d12e790 (patch) | |
tree | 8ed88607f29c642137aa4b4eb43204d480aec6c0 /src | |
parent | 319fdccb670743daa6c27e247591baf1f254e5ac (diff) |
NEWT/X11: Fix Insets determination for undecorated / child window.
Due to latest changes, a bug is disposed where the native 'updateInsets'
attempts to determine the window insets by it's parent window (fall-back).
The latter works only in case of a top-level window.
Adding query to the WM whether the window is decorated (top-level) or not.
Attempt to use the fall-back parent window method in case of a decorated window.
This whole inset code based on the parent window is probably completly redundant,
nevertheless we keep it alive until further notice.
Diffstat (limited to 'src')
-rw-r--r-- | src/newt/native/X11Window.c | 139 |
1 files changed, 86 insertions, 53 deletions
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index 10ce8945b..6953140c0 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -169,16 +169,21 @@ static Window NewtWindows_getParent (Display *dpy, Window w) { } return 0; // Error } -static Status NewtWindows_getParentPosition (Display *dpy, Window w, int *x_return, int *y_return) { +static void NewtWindows_setCWAbove(Display *dpy, Window w) { + XWindowChanges xwc; + memset(&xwc, 0, sizeof(XWindowChanges)); + xwc.stack_mode = Above; + XConfigureWindow(dpy, w, CWStackMode, &xwc); + XSync(dpy, False); +} +static Status NewtWindows_getWindowPositionRelative2Parent (Display *dpy, Window w, int *x_return, int *y_return) { Window root_return; unsigned int width_return, height_return; unsigned int border_width_return; unsigned int depth_return; - Window parent = NewtWindows_getParent(dpy, w); - if(0 != parent) { - XGetGeometry(dpy, parent, &root_return, x_return, y_return, &width_return, - &height_return, &border_width_return, &depth_return); + if(0 != XGetGeometry(dpy, w, &root_return, x_return, y_return, &width_return, + &height_return, &border_width_return, &depth_return)) { return 1; // OK } return 0; // Error @@ -224,53 +229,6 @@ static Status NewtWindows_getFrameExtends(Display *dpy, Window window, int *left return 1; // Ok } -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 - } else if(0 != NewtWindows_getParentPosition (dpy, window, left, top)) { - *right = *left; *bottom = *left; - 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 - } - return 0; // Error -} - -static void NewtWindows_setCWAbove(Display *dpy, Window w) { - XWindowChanges xwc; - memset(&xwc, 0, sizeof(XWindowChanges)); - xwc.stack_mode = Above; - XConfigureWindow(dpy, w, CWStackMode, &xwc); - XSync(dpy, False); -} - -static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, Window w, jboolean 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); - - if( JNI_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); - } - } - DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d - FIN\n", dpy, (void*)w, force); - XSync(dpy, False); -} #define DECOR_USE_MWM 1 // works for known WMs // #define DECOR_USE_EWMH 1 // haven't seen this to work (NORMAL->POPUP, never gets undecorated) @@ -308,6 +266,29 @@ static void NewtWindows_setDecorations (Display *dpy, Window w, Bool decorated) XSync(dpy, False); } +static Bool NewtWindows_hasDecorations (Display *dpy, Window w) { + Bool decor = False; + +#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; + + 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) { + // 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] ); + } + } +#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}; @@ -431,6 +412,56 @@ static Bool NewtWindows_setFullscreenEWMH (Display *dpy, Window root, Window w, return res; } + +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 void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, Window w, jboolean 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); + + if( JNI_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); + } + } + DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d - FIN\n", dpy, (void*)w, force); + XSync(dpy, False); +} + /** * Window */ @@ -602,11 +633,13 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0 // we can pre-map the window here to be able to gather the insets and position. { XEvent event; - int left, right, top, bottom; + int left=0, right=0, top=0, bottom=0; XMapWindow(dpy, window); XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) window ); // wait to get proper insets values + XSync(dpy, False); + // 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); |