diff options
author | Sven Gothel <[email protected]> | 2019-09-11 04:16:31 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2019-09-11 04:16:31 +0200 |
commit | fe6600234cafe16afb1d06a0254d2135ffb71b12 (patch) | |
tree | f947252a8507f533dd4c25bded3d331b17c848e9 /src | |
parent | b8db98376069a72ad40b7ef2fe2d9003aea2b091 (diff) |
Bug 1394 - NEWT X11Window didn't gather inset at window creation (properly)
X11Window.c's 'NewtWindows_getFrameExtends(..)'
retrieves the insets via XGetWindowProperty on _NET_FRAME_EXTENTS.
Right after window creation this method fails as the WM did not yet
provide the information as the window has not yet been mapped.
Implementation needs to retry for a certain amount of time (250ms)
and maximum number of attempts (96 XEvent).
This issue surfaced while validating fix for Bug 1393,
testing TestDisplayLifecycle02NEWT also on X11.
Diffstat (limited to 'src')
-rw-r--r-- | src/newt/native/X11Window.c | 62 |
1 files changed, 46 insertions, 16 deletions
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index 7ddc5d3d0..6c163ea88 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -63,6 +63,14 @@ #endif +#include <sys/time.h> + +static int64_t getCurrentMillis() { + struct timeval tv; + gettimeofday(&tv,NULL); + return (int64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000; +} + #define X11_MOUSE_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask) static int putPtrIn32Long(unsigned long * dst, uintptr_t src) { @@ -321,31 +329,41 @@ static void NewtWindows_setCWAbove(Display *dpy, Window w) { xwc.stack_mode = Above; XConfigureWindow(dpy, w, CWStackMode, &xwc); } -static Status NewtWindows_getWindowPositionRelative2Parent (Display *dpy, Window w, int *x_return, int *y_return) { +static Bool NewtWindows_getWindowPositionRelative2Parent (Display *dpy, Window win, Window winParent, int *x_return, int *y_return) { + Window child; + return XTranslateCoordinates(dpy, win, winParent, 0, 0, x_return, y_return, &child); +} +static Status NewtWindows_getWindowTopLeftPositionRelative2Parent (Display *dpy, Window win, int *x_return, int *y_return) { Window root_return; unsigned int width_return, height_return; unsigned int border_width_return; unsigned int depth_return; - if(0 != XGetGeometry(dpy, w, &root_return, x_return, y_return, &width_return, - &height_return, &border_width_return, &depth_return)) { + if(0 != XGetGeometry(dpy, win, &root_return, x_return, y_return, &width_return, + &height_return, &border_width_return, &depth_return)) { return 1; // OK } return 0; // Error } -static Status NewtWindows_getFrameExtends(Display *dpy, JavaWindow *w, int *left, int *right, int *top, int *bottom) { +static Status NewtWindows_getFrameExtends(Display *dpy, JavaWindow *javaWin, 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; + unsigned long nitems = 0; - { - unsigned long nitems = 0; + /** Safe polling ... */ + #define TIMEOUT 250 + int64_t t0 = getCurrentMillis(); + #define MAX_ATTEMPTS 96 + int evtCount = 0; + + while( nitems<nitems_32 || NULL==frame_extends_data_pp ) { unsigned long bytes_after = 0; int res; - res = XGetWindowProperty(dpy, w->window, w->allAtoms[_NET_FRAME_EXTENTS_IDX], 0, nitems_32, False, - AnyPropertyType, &actual_type, &actual_format, + res = XGetWindowProperty(dpy, javaWin->window, javaWin->allAtoms[_NET_FRAME_EXTENTS_IDX], + 0, nitems_32, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &frame_extends_data_pp); if ( Success != res ) { @@ -354,12 +372,23 @@ static Status NewtWindows_getFrameExtends(Display *dpy, JavaWindow *w, int *left } if(nitems<nitems_32 || NULL==frame_extends_data_pp) { + int64_t tD = getCurrentMillis() - t0; + // _NET_FRAME_EXTENTS data not yet delivered by WM + // E.g. window not yet mapped 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 + if( tD < TIMEOUT && evtCount < MAX_ATTEMPTS ) { + // wait for next X event to arrive, then we may try again + XEvent e; + XPeekEvent(dpy, &e); + evtCount++; + DBG_PRINT( "NEWT FrameExtends: Waiting: #%d %ldms: evt %d, window %p (this=%d)\n", + evtCount, tD, e.type, (void*)e.xany.window, (javaWin->window == e.xany.window)); + } else { + // timeout or max-attempts: exit + return 0; + } } } long * extends = (long*) frame_extends_data_pp; @@ -468,9 +497,9 @@ Bool NewtWindows_updateInsets(Display *dpy, JavaWindow * w, int *left, int *righ // 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); + if( 0 != NewtWindows_getWindowTopLeftPositionRelative2Parent (dpy, parent, left, top) ) { + *right = *left; *bottom = *left; + DBG_PRINT( "NewtWindows_updateInsets: insets relative to parent position [ l %d, r %d, t %d, b %d ]\n", *left, *right, *top, *bottom); return True; // OK } } @@ -925,8 +954,9 @@ JNIEXPORT jlongArray JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWind // 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; + if( 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, autoPos %d\n", x, y, width, height, TST_FLAG_IS_AUTOPOSITION(flags)); |