summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authorfvogel <fvogelnew1@free.fr>2020-06-02 06:16:12 (GMT)
committerfvogel <fvogelnew1@free.fr>2020-06-02 06:16:12 (GMT)
commit6694505c3ede36fbdf40007bf50495675a8d9455 (patch)
treeb848a14add4ef1b54ca3b46d1a170ea4f68c81a6 /generic
parent94796510222de972274beb287fa2aaa581dd4a7a (diff)
downloadtk-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.c34
-rw-r--r--generic/tkGrab.c37
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;
}