summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
Diffstat (limited to 'generic')
-rw-r--r--generic/tkBind.c118
-rw-r--r--generic/tkEntry.c10
-rw-r--r--generic/tkGrab.c25
-rw-r--r--generic/tkInt.h5
-rw-r--r--generic/tkWindow.c2
5 files changed, 82 insertions, 78 deletions
diff --git a/generic/tkBind.c b/generic/tkBind.c
index 8ffcc1d..25d919f 100644
--- a/generic/tkBind.c
+++ b/generic/tkBind.c
@@ -738,7 +738,6 @@ static int NameToWindow(Tcl_Interp *interp, Tk_Window main,
Tcl_Obj *objPtr, Tk_Window *tkwinPtr);
static unsigned ParseEventDescription(Tcl_Interp *interp, const char **eventStringPtr,
TkPattern *patPtr, EventMask *eventMaskPtr);
-static void DoWarp(ClientData clientData);
static PSList * GetLookupForEvent(LookupTables* lookupPtr, const Event *eventPtr,
Tcl_Obj *object, int onlyConsiderDetailedEvents);
static void ClearLookupTable(LookupTables *lookupTables, ClientData object);
@@ -4402,17 +4401,6 @@ HandleEventGenerate(
}
/*
- * Now we have constructed the event, inject it into the event handling
- * code.
- */
-
- if (synch) {
- Tk_HandleEvent(&event.general);
- } else {
- Tk_QueueWindowEvent(&event.general, pos);
- }
-
- /*
* We only allow warping if the window is mapped.
*/
@@ -4421,11 +4409,6 @@ HandleEventGenerate(
Tk_Window warpWindow = Tk_IdToWindow(dispPtr->display, event.general.xmotion.window);
- if (!(dispPtr->flags & TK_DISPLAY_IN_WARP)) {
- Tcl_DoWhenIdle(DoWarp, dispPtr);
- dispPtr->flags |= TK_DISPLAY_IN_WARP;
- }
-
if (warpWindow != dispPtr->warpWindow) {
if (warpWindow) {
Tcl_Preserve(warpWindow);
@@ -4438,6 +4421,31 @@ HandleEventGenerate(
dispPtr->warpMainwin = mainWin;
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 directly here.
+ */
+
+ if (!dispPtr->warpWindow) {
+ TkpWarpPointer(dispPtr);
+ XForceScreenSaver(dispPtr->display, ScreenSaverReset);
+ }
+ }
+
+ /*
+ * Now we have constructed the event, inject it into the event handling
+ * code.
+ */
+
+ if (synch) {
+ Tk_HandleEvent(&event.general);
+ } else {
+ Tk_QueueWindowEvent(&event.general, pos);
}
}
@@ -4510,46 +4518,47 @@ NameToWindow(
/*
*-------------------------------------------------------------------------
*
- * DoWarp --
+ * TkDoWarpWrtWin --
*
- * Perform Warping of X pointer. Executed as an idle handler only.
+ * Perform warping of mouse pointer with respect to a window.
*
* Results:
* None
*
* Side effects:
- * X Pointer will move to a new location.
+ * Mouse pointer moves to a new location.
*
*-------------------------------------------------------------------------
*/
-static void
-DoWarp(
- ClientData clientData)
+void
+TkDoWarpWrtWin(
+ TkDisplay *dispPtr)
{
- TkDisplay *dispPtr = (TkDisplay *)clientData;
-
- assert(clientData);
+ assert(dispPtr);
/*
- * 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 NULL warpWindow means warping with respect to the whole screen.
+ * We want to warp here only if we're warping with respect to a window.
*/
- if (!dispPtr->warpWindow ||
- (Tk_IsMapped(dispPtr->warpWindow) && Tk_WindowId(dispPtr->warpWindow) != None)) {
- TkpWarpPointer(dispPtr);
- XForceScreenSaver(dispPtr->display, ScreenSaverReset);
- }
-
if (dispPtr->warpWindow) {
- Tcl_Release(dispPtr->warpWindow);
- dispPtr->warpWindow = NULL;
+
+ /*
+ * Warping with respect to a window can only be done if the window is
+ * mapped. This was checked in HandleEvent. The window needs to be
+ * still mapped at the time the present code is executed. Also
+ * one needs to guard against window destruction in the meantime,
+ * which could have happened as a side effect of an event handler.
+ */
+
+ 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;
}
/*
@@ -5320,35 +5329,6 @@ TkpGetBindingXEvent(
/*
*----------------------------------------------------------------------
*
- * TkpCancelWarp --
- *
- * This function cancels an outstanding pointer warp and
- * is called during tear down of the display.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TkpCancelWarp(
- TkDisplay *dispPtr)
-{
- assert(dispPtr);
-
- if (dispPtr->flags & TK_DISPLAY_IN_WARP) {
- Tcl_CancelIdleCall(DoWarp, dispPtr);
- dispPtr->flags &= ~TK_DISPLAY_IN_WARP;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
* TkpDumpPS --
*
* Dump given pattern sequence to stdout.
diff --git a/generic/tkEntry.c b/generic/tkEntry.c
index 5bbad3e..2c5db3e 100644
--- a/generic/tkEntry.c
+++ b/generic/tkEntry.c
@@ -3385,17 +3385,21 @@ EntryValidateChange(
if (entryPtr->validateCmd == NULL ||
entryPtr->validate == VALIDATE_NONE) {
+ if (entryPtr->flags & VALIDATING) {
+ entryPtr->flags |= VALIDATE_ABORT;
+ }
return (varValidate ? TCL_ERROR : TCL_OK);
}
/*
- * If we're already validating, then we're hitting a loop condition Return
- * and set validate to 0 to disallow further validations and prevent
- * current validation from finishing
+ * If we're already validating, then we're hitting a loop condition. Set
+ * validate to none to disallow further validations, arrange for flags
+ * to prevent current validation from finishing, and return.
*/
if (entryPtr->flags & VALIDATING) {
entryPtr->validate = VALIDATE_NONE;
+ entryPtr->flags |= VALIDATE_ABORT;
return (varValidate ? TCL_ERROR : TCL_OK);
}
diff --git a/generic/tkGrab.c b/generic/tkGrab.c
index 012d434..3e4d9db 100644
--- a/generic/tkGrab.c
+++ b/generic/tkGrab.c
@@ -666,6 +666,9 @@ ReleaseButtonGrab(
* This function is called for each pointer-related event, before the
* event has been processed. It does various things to make grabs work
* correctly.
+ * Also, this function takes care of warping the mouse pointer with
+ * respect to a given window, both when there is a grab in effect and
+ * when there is none.
*
* Results:
* If the return value is 1 it means the event should be processed (event
@@ -677,6 +680,7 @@ ReleaseButtonGrab(
* Grab state information may be updated. New events may also be pushed
* back onto the event queue to replace or augment the one passed in
* here.
+ * The mouse pointer may be moved.
*
*----------------------------------------------------------------------
*/
@@ -773,10 +777,24 @@ TkPointerEvent(
return 1;
}
+ if ((eventPtr->type == MotionNotify) && !appGrabbed) {
+
+ /*
+ * Warp the mouse pointer with respect to window dispPtr->warpWindow
+ * if such a window was set in HandleEventGenerate.
+ */
+
+ TkDoWarpWrtWin(dispPtr);
+ }
+
if (!appGrabbed) {
return 1;
}
+ /*
+ * From this point on, there is a grab in effect.
+ */
+
if (eventPtr->type == MotionNotify) {
/*
* When grabs are active, X reports motion events relative to the
@@ -799,6 +817,13 @@ TkPointerEvent(
Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_HEAD);
return 0;
}
+
+ /*
+ * Warp the mouse pointer with respect to window dispPtr->warpWindow
+ * if such a window was set in HandleEventGenerate.
+ */
+
+ TkDoWarpWrtWin(dispPtr);
return 1;
}
diff --git a/generic/tkInt.h b/generic/tkInt.h
index f37e2d3..5465a0e 100644
--- a/generic/tkInt.h
+++ b/generic/tkInt.h
@@ -576,14 +576,11 @@ typedef struct TkDisplay {
* Whether to use input methods for this display
* TK_DISPLAY_WM_TRACING: (default off)
* Whether we should do wm tracing on this display.
- * TK_DISPLAY_IN_WARP: (default off)
- * Indicates that we are in a pointer warp
*/
#define TK_DISPLAY_COLLAPSE_MOTION_EVENTS (1 << 0)
#define TK_DISPLAY_USE_IM (1 << 1)
#define TK_DISPLAY_WM_TRACING (1 << 3)
-#define TK_DISPLAY_IN_WARP (1 << 4)
/*
* One of the following structures exists for each error handler created by a
@@ -1361,8 +1358,8 @@ MODULE_SCOPE int TkInitFontchooser(Tcl_Interp *interp,
ClientData clientData);
MODULE_SCOPE void TkInitEmbeddedConfigurationInformation(
Tcl_Interp *interp);
+MODULE_SCOPE void TkDoWarpWrtWin(TkDisplay *dispPtr);
MODULE_SCOPE void TkpWarpPointer(TkDisplay *dispPtr);
-MODULE_SCOPE void TkpCancelWarp(TkDisplay *dispPtr);
MODULE_SCOPE int TkListCreateFrame(ClientData clientData,
Tcl_Interp *interp, Tcl_Obj *listObj,
int toplevel, Tcl_Obj *nameObj);
diff --git a/generic/tkWindow.c b/generic/tkWindow.c
index 26ae472..9d6c1f4 100644
--- a/generic/tkWindow.c
+++ b/generic/tkWindow.c
@@ -239,8 +239,6 @@ TkCloseDisplay(
{
TkClipCleanup(dispPtr);
- TkpCancelWarp(dispPtr);
-
if (dispPtr->name != NULL) {
ckfree(dispPtr->name);
}