diff options
author | fvogel <fvogelnew1@free.fr> | 2020-06-02 06:16:12 (GMT) |
---|---|---|
committer | fvogel <fvogelnew1@free.fr> | 2020-06-02 06:16:12 (GMT) |
commit | 6694505c3ede36fbdf40007bf50495675a8d9455 (patch) | |
tree | b848a14add4ef1b54ca3b46d1a170ea4f68c81a6 /generic | |
parent | 94796510222de972274beb287fa2aaa581dd4a7a (diff) | |
download | tk-6694505c3ede36fbdf40007bf50495675a8d9455.zip tk-6694505c3ede36fbdf40007bf50495675a8d9455.tar.gz tk-6694505c3ede36fbdf40007bf50495675a8d9455.tar.bz2 |
A more robust approach to warping with respect to a window: make the call to TkpWarpPointer happen in TkPointerEvent instead of as an idle event. This allows to remove some update/after commands in tests since warping with respect to a window is now synchronous (it happens before event generate $win <Motion> -warp 1 ... returns).
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tkBind.c | 34 | ||||
-rw-r--r-- | generic/tkGrab.c | 37 |
2 files changed, 56 insertions, 15 deletions
diff --git a/generic/tkBind.c b/generic/tkBind.c index af6ab15..ea1f721 100644 --- a/generic/tkBind.c +++ b/generic/tkBind.c @@ -4364,8 +4364,21 @@ HandleEventGenerate( dispPtr->warpX = event.general.xmotion.x; dispPtr->warpY = event.general.xmotion.y; + /* + * Warping with respect to a window will be done when Tk_handleEvent + * below will run the event handlers and in particular TkPointerEvent. + * This allows to make grabs and warping work together robustly, that + * is without depending on a precise sequence of events. + * Warping with respect to the whole screen (i.e. dispPtr->warpWindow + * is NULL) is run as an idle task because the event handlers are not + * designed to work without a window (and there is anyway no point in + * making this case sleep with grabs). + */ + if (!(dispPtr->flags & TK_DISPLAY_IN_WARP)) { - Tcl_DoWhenIdle(DoWarp, dispPtr); + if (!dispPtr->warpWindow) { + Tcl_DoWhenIdle(DoWarp, dispPtr); + } dispPtr->flags |= TK_DISPLAY_IN_WARP; } } @@ -4473,23 +4486,14 @@ DoWarp( assert(clientData); /* - * DoWarp was scheduled only if the window was mapped. It needs to be - * still mapped at the time the present idle callback is executed. Also - * one needs to guard against window destruction in the meantime. - * Finally, the case warpWindow == NULL is special in that it means - * the whole screen. + * A non-NULL warpWindow means warping with respect to this window. + * We can only be here if we're warping with respect to the whole screen. */ - if (!dispPtr->warpWindow || - (Tk_IsMapped(dispPtr->warpWindow) && Tk_WindowId(dispPtr->warpWindow) != None)) { - TkpWarpPointer(dispPtr); - XForceScreenSaver(dispPtr->display, ScreenSaverReset); - } + assert(!dispPtr->warpWindow); - if (dispPtr->warpWindow) { - Tcl_Release(dispPtr->warpWindow); - dispPtr->warpWindow = NULL; - } + TkpWarpPointer(dispPtr); + XForceScreenSaver(dispPtr->display, ScreenSaverReset); dispPtr->flags &= ~TK_DISPLAY_IN_WARP; } diff --git a/generic/tkGrab.c b/generic/tkGrab.c index 2855637..0750bd5 100644 --- a/generic/tkGrab.c +++ b/generic/tkGrab.c @@ -774,6 +774,33 @@ TkPointerEvent( return 1; } + if ((eventPtr->type == MotionNotify) && !appGrabbed) { + if ((dispPtr->flags & TK_DISPLAY_IN_WARP)) { + + /* + * A NULL warpWindow means warping with respect to the whole screen. + * We can only be here if we're warping with respect to a window. + */ + + assert(dispPtr->warpWindow); + + /* + * Warping with respect to a window can only be done if the window is + * mapped. This was checked in HandleEvent. The windows needs to be + * still mapped at the time the present code is executed. Also + * one needs to guard against window destruction in the meantime. + */ + + if (Tk_IsMapped(dispPtr->warpWindow) && Tk_WindowId(dispPtr->warpWindow) != None) { + TkpWarpPointer(dispPtr); + XForceScreenSaver(dispPtr->display, ScreenSaverReset); + } + Tcl_Release(dispPtr->warpWindow); + dispPtr->warpWindow = NULL; + dispPtr->flags &= ~TK_DISPLAY_IN_WARP; + } + } + if (!appGrabbed) { return 1; } @@ -800,6 +827,16 @@ TkPointerEvent( Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_HEAD); return 0; } + if ((dispPtr->flags & TK_DISPLAY_IN_WARP)) { + assert(dispPtr->warpWindow); + if (Tk_IsMapped(dispPtr->warpWindow) && Tk_WindowId(dispPtr->warpWindow) != None) { + TkpWarpPointer(dispPtr); + XForceScreenSaver(dispPtr->display, ScreenSaverReset); + } + Tcl_Release(dispPtr->warpWindow); + dispPtr->warpWindow = NULL; + dispPtr->flags &= ~TK_DISPLAY_IN_WARP; + } return 1; } |