summaryrefslogtreecommitdiffstats
path: root/generic/tkBind.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tkBind.c')
-rw-r--r--generic/tkBind.c224
1 files changed, 111 insertions, 113 deletions
diff --git a/generic/tkBind.c b/generic/tkBind.c
index ad59299..3776c95 100644
--- a/generic/tkBind.c
+++ b/generic/tkBind.c
@@ -62,21 +62,21 @@
* equivalent sequences. However it is logical to give <Double-1> higher precedence
* since it is more specific. Indeed <Double-1> includes time and space requirements,
* which is not the case for <1><1>.
- * This can be achieved by setting PREFER_MOST_SPECIALIZED_EVENT to 1.
+ * This is achieved by setting PREFER_MOST_SPECIALIZED_EVENT to 1.
*/
#ifndef PREFER_MOST_SPECIALIZED_EVENT
-# define PREFER_MOST_SPECIALIZED_EVENT 0
+# define PREFER_MOST_SPECIALIZED_EVENT 1
#endif
/*
* Traditionally motion events can be combined with buttons in this way: <B1-B2-Motion>.
- * However it should be allowed to express this as <Motion-1-2> in addition. This can be
- * achieved by setting SUPPORT_ADDITIONAL_MOTION_SYNTAX to 1.
+ * However it should be allowed to express this as <Motion-1-2> in addition. This is achieved
+ * by setting SUPPORT_ADDITIONAL_MOTION_SYNTAX to 1.
*/
#ifndef SUPPORT_ADDITIONAL_MOTION_SYNTAX
-# define SUPPORT_ADDITIONAL_MOTION_SYNTAX 0 /* set to 1 if wanted */
+# define SUPPORT_ADDITIONAL_MOTION_SYNTAX 1
#endif
/*
@@ -445,6 +445,14 @@ static const ModInfo modArray[] = {
{"Button4", Button4Mask, 0},
{"B5", Button5Mask, 0},
{"Button5", Button5Mask, 0},
+ {"B6", Button6Mask, 0},
+ {"Button6", Button6Mask, 0},
+ {"B7", Button7Mask, 0},
+ {"Button7", Button7Mask, 0},
+ {"B8", Button8Mask, 0},
+ {"Button8", Button8Mask, 0},
+ {"B9", Button9Mask, 0},
+ {"Button9", Button9Mask, 0},
{"Mod1", Mod1Mask, 0},
{"M1", Mod1Mask, 0},
{"Command", Mod1Mask, 0},
@@ -723,7 +731,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, unsigned *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);
@@ -785,8 +792,10 @@ static unsigned
GetButtonNumber(
const char *field)
{
+ unsigned button;
assert(field);
- return (field[0] >= '1' && field[0] <= '5' && field[1] == '\0') ? field[0] - '0' : 0;
+ button = (field[0] >= '1' && field[0] <= '9' && field[1] == '\0') ? field[0] - '0' : 0;
+ return (button > 3) ? (button + 4) : button;
}
static Time
@@ -946,6 +955,7 @@ FreePatSeqEntry(
PSEntry *entry)
{
PSEntry *next = PSList_Next(entry);
+
PSModMaskArr_Free(&entry->lastModMaskArr);
ckfree(entry);
return next;
@@ -983,7 +993,11 @@ ButtonNumberFromState(
if (state & Button2Mask) { return 2; }
if (state & Button3Mask) { return 3; }
if (state & Button4Mask) { return 4; }
- return 5;
+ if (state & Button5Mask) { return 5; }
+ if (state & Button6Mask) { return 6; }
+ if (state & Button7Mask) { return 7; }
+ if (state & Button8Mask) { return 8; }
+ return 9;
}
static void
@@ -1272,49 +1286,49 @@ TkBindInit(
assert(NoSymbol == 0L);
/* this must be a union, not a struct, otherwise comparison with NULL will not work */
- assert(Tk_Offset(Detail, name) == Tk_Offset(Detail, info));
+ assert(offsetof(Detail, name) == offsetof(Detail, info));
/* we use some constraints about X*Event */
- assert(Tk_Offset(XButtonEvent, time) == Tk_Offset(XMotionEvent, time));
- assert(Tk_Offset(XButtonEvent, x_root) == Tk_Offset(XMotionEvent, x_root));
- assert(Tk_Offset(XButtonEvent, y_root) == Tk_Offset(XMotionEvent, y_root));
- assert(Tk_Offset(XCreateWindowEvent, border_width) == Tk_Offset(XConfigureEvent, border_width));
- assert(Tk_Offset(XCreateWindowEvent, width) == Tk_Offset(XConfigureEvent, width));
- assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XCirculateRequestEvent, window));
- assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XConfigureEvent, window));
- assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XGravityEvent, window));
- assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XMapEvent, window));
- assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XReparentEvent, window));
- assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XUnmapEvent, window));
- assert(Tk_Offset(XCreateWindowEvent, x) == Tk_Offset(XConfigureEvent, x));
- assert(Tk_Offset(XCreateWindowEvent, x) == Tk_Offset(XGravityEvent, x));
- assert(Tk_Offset(XCreateWindowEvent, y) == Tk_Offset(XConfigureEvent, y));
- assert(Tk_Offset(XCreateWindowEvent, y) == Tk_Offset(XGravityEvent, y));
- assert(Tk_Offset(XCrossingEvent, time) == Tk_Offset(XEnterWindowEvent, time));
- assert(Tk_Offset(XCrossingEvent, time) == Tk_Offset(XLeaveWindowEvent, time));
- assert(Tk_Offset(XCrossingEvent, time) == Tk_Offset(XKeyEvent, time));
- assert(Tk_Offset(XKeyEvent, root) == Tk_Offset(XButtonEvent, root));
- assert(Tk_Offset(XKeyEvent, root) == Tk_Offset(XCrossingEvent, root));
- assert(Tk_Offset(XKeyEvent, root) == Tk_Offset(XMotionEvent, root));
- assert(Tk_Offset(XKeyEvent, state) == Tk_Offset(XButtonEvent, state));
- assert(Tk_Offset(XKeyEvent, state) == Tk_Offset(XMotionEvent, state));
- assert(Tk_Offset(XKeyEvent, subwindow) == Tk_Offset(XButtonEvent, subwindow));
- assert(Tk_Offset(XKeyEvent, subwindow) == Tk_Offset(XCrossingEvent, subwindow));
- assert(Tk_Offset(XKeyEvent, subwindow) == Tk_Offset(XMotionEvent, subwindow));
- assert(Tk_Offset(XKeyEvent, time) == Tk_Offset(XButtonEvent, time));
- assert(Tk_Offset(XKeyEvent, time) == Tk_Offset(XMotionEvent, time));
- assert(Tk_Offset(XKeyEvent, x) == Tk_Offset(XButtonEvent, x));
- assert(Tk_Offset(XKeyEvent, x) == Tk_Offset(XCrossingEvent, x));
- assert(Tk_Offset(XKeyEvent, x) == Tk_Offset(XMotionEvent, x));
- assert(Tk_Offset(XKeyEvent, x_root) == Tk_Offset(XButtonEvent, x_root));
- assert(Tk_Offset(XKeyEvent, x_root) == Tk_Offset(XCrossingEvent, x_root));
- assert(Tk_Offset(XKeyEvent, x_root) == Tk_Offset(XMotionEvent, x_root));
- assert(Tk_Offset(XKeyEvent, y) == Tk_Offset(XButtonEvent, y));
- assert(Tk_Offset(XKeyEvent, y) == Tk_Offset(XCrossingEvent, y));
- assert(Tk_Offset(XKeyEvent, y) == Tk_Offset(XMotionEvent, y));
- assert(Tk_Offset(XKeyEvent, y_root) == Tk_Offset(XButtonEvent, y_root));
- assert(Tk_Offset(XKeyEvent, y_root) == Tk_Offset(XCrossingEvent, y_root));
- assert(Tk_Offset(XKeyEvent, y_root) == Tk_Offset(XMotionEvent, y_root));
+ assert(offsetof(XButtonEvent, time) == offsetof(XMotionEvent, time));
+ assert(offsetof(XButtonEvent, x_root) == offsetof(XMotionEvent, x_root));
+ assert(offsetof(XButtonEvent, y_root) == offsetof(XMotionEvent, y_root));
+ assert(offsetof(XCreateWindowEvent, border_width) == offsetof(XConfigureEvent, border_width));
+ assert(offsetof(XCreateWindowEvent, width) == offsetof(XConfigureEvent, width));
+ assert(offsetof(XCreateWindowEvent, window) == offsetof(XCirculateRequestEvent, window));
+ assert(offsetof(XCreateWindowEvent, window) == offsetof(XConfigureEvent, window));
+ assert(offsetof(XCreateWindowEvent, window) == offsetof(XGravityEvent, window));
+ assert(offsetof(XCreateWindowEvent, window) == offsetof(XMapEvent, window));
+ assert(offsetof(XCreateWindowEvent, window) == offsetof(XReparentEvent, window));
+ assert(offsetof(XCreateWindowEvent, window) == offsetof(XUnmapEvent, window));
+ assert(offsetof(XCreateWindowEvent, x) == offsetof(XConfigureEvent, x));
+ assert(offsetof(XCreateWindowEvent, x) == offsetof(XGravityEvent, x));
+ assert(offsetof(XCreateWindowEvent, y) == offsetof(XConfigureEvent, y));
+ assert(offsetof(XCreateWindowEvent, y) == offsetof(XGravityEvent, y));
+ assert(offsetof(XCrossingEvent, time) == offsetof(XEnterWindowEvent, time));
+ assert(offsetof(XCrossingEvent, time) == offsetof(XLeaveWindowEvent, time));
+ assert(offsetof(XCrossingEvent, time) == offsetof(XKeyEvent, time));
+ assert(offsetof(XKeyEvent, root) == offsetof(XButtonEvent, root));
+ assert(offsetof(XKeyEvent, root) == offsetof(XCrossingEvent, root));
+ assert(offsetof(XKeyEvent, root) == offsetof(XMotionEvent, root));
+ assert(offsetof(XKeyEvent, state) == offsetof(XButtonEvent, state));
+ assert(offsetof(XKeyEvent, state) == offsetof(XMotionEvent, state));
+ assert(offsetof(XKeyEvent, subwindow) == offsetof(XButtonEvent, subwindow));
+ assert(offsetof(XKeyEvent, subwindow) == offsetof(XCrossingEvent, subwindow));
+ assert(offsetof(XKeyEvent, subwindow) == offsetof(XMotionEvent, subwindow));
+ assert(offsetof(XKeyEvent, time) == offsetof(XButtonEvent, time));
+ assert(offsetof(XKeyEvent, time) == offsetof(XMotionEvent, time));
+ assert(offsetof(XKeyEvent, x) == offsetof(XButtonEvent, x));
+ assert(offsetof(XKeyEvent, x) == offsetof(XCrossingEvent, x));
+ assert(offsetof(XKeyEvent, x) == offsetof(XMotionEvent, x));
+ assert(offsetof(XKeyEvent, x_root) == offsetof(XButtonEvent, x_root));
+ assert(offsetof(XKeyEvent, x_root) == offsetof(XCrossingEvent, x_root));
+ assert(offsetof(XKeyEvent, x_root) == offsetof(XMotionEvent, x_root));
+ assert(offsetof(XKeyEvent, y) == offsetof(XButtonEvent, y));
+ assert(offsetof(XKeyEvent, y) == offsetof(XCrossingEvent, y));
+ assert(offsetof(XKeyEvent, y) == offsetof(XMotionEvent, y));
+ assert(offsetof(XKeyEvent, y_root) == offsetof(XButtonEvent, y_root));
+ assert(offsetof(XKeyEvent, y_root) == offsetof(XCrossingEvent, y_root));
+ assert(offsetof(XKeyEvent, y_root) == offsetof(XMotionEvent, y_root));
/*
* Initialize the static data structures used by the binding package. They
@@ -1621,7 +1635,7 @@ Tk_CreateBinding(
ClientData object, /* Token for object with which binding is associated. */
const char *eventString, /* String describing event sequence that triggers binding. */
const char *script, /* Contains Tcl script to execute when binding triggers. */
- int append) /* 0 means replace any existing binding for eventString;
+ int append) /* 0 means replace any existing binding for eventString;
* 1 means append to that binding. If the existing binding is
* for a callback function and not a Tcl command string, the
* existing binding will always be replaced. */
@@ -4026,6 +4040,9 @@ HandleEventGenerate(
return TCL_ERROR;
}
if (flags & BUTTON) {
+ if (number >= Button4) {
+ number += (Button8 - Button4);
+ }
event.general.xbutton.button = number;
} else {
badOpt = 1;
@@ -4401,10 +4418,19 @@ HandleEventGenerate(
dispPtr->warpX = event.general.xmotion.x;
dispPtr->warpY = event.general.xmotion.y;
- if (!(dispPtr->flags & TK_DISPLAY_IN_WARP)) {
- Tcl_DoWhenIdle(DoWarp, dispPtr);
- dispPtr->flags |= TK_DISPLAY_IN_WARP;
- }
+ /*
+ * 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);
+ }
}
/*
@@ -4488,46 +4514,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 = 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;
}
/*
@@ -4610,7 +4637,7 @@ FindSequence(
* associated. For virtual event table, NULL. */
const char *eventString, /* String description of pattern to match on. See user
* documentation for details. */
- int create, /* 0 means don't create the entry if it doesn't already exist.
+ int create, /* 0 means don't create the entry if it doesn't already exist.
* 1 means create. */
int allowVirtual, /* 0 means that virtual events are not allowed in the sequence.
* 1 otherwise. */
@@ -4979,7 +5006,7 @@ ParseEventDescription(
"NON_BUTTON");
}
#if SUPPORT_ADDITIONAL_MOTION_SYNTAX
- patPtr->modMask |= TkGetButtonMask(button);
+ patPtr->modMask |= Tk_GetButtonMask(button);
p = SkipFieldDelims(p);
while (*p && *p != '>') {
p = SkipFieldDelims(GetField(p, field, sizeof(field)));
@@ -4989,7 +5016,7 @@ ParseEventDescription(
patPtr, 0,
Tcl_ObjPrintf("bad button number \"%s\"", field), "BUTTON");
}
- patPtr->modMask |= TkGetButtonMask(button);
+ patPtr->modMask |= Tk_GetButtonMask(button);
}
patPtr->info = ButtonNumberFromState(patPtr->modMask);
#endif
@@ -5167,16 +5194,16 @@ GetPatternObj(
}
case ButtonPress:
case ButtonRelease:
- assert(patPtr->info <= Button5);
- Tcl_AppendPrintfToObj(patternObj, "-%u", (unsigned) patPtr->info);
+ assert(patPtr->info <= 13);
+ Tcl_AppendPrintfToObj(patternObj, "-%u", (unsigned) ((patPtr->info > 7) ? (patPtr->info - 4) : patPtr->info));
break;
#if PRINT_SHORT_MOTION_SYNTAX
case MotionNotify: {
unsigned mask = patPtr->modMask;
while (mask & ALL_BUTTONS) {
unsigned button = ButtonNumberFromState(mask);
- Tcl_AppendPrintfToObj(patternObj, "-%u", button);
- mask &= ~TkGetButtonMask(button);
+ Tcl_AppendPrintfToObj(patternObj, "-%u", (button > 7) ? (button - 4) : button);
+ mask &= ~Tk_GetButtonMask(button);
}
break;
}
@@ -5298,35 +5325,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.