Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch bug-43573999ca Excluding Merge-Ins
This is equivalent to a diff from 87d8b0cd to df4a096e
2022-10-26
| ||
19:40 | Fix [43573999ca]: Problem with tkBind.c since Tk 8.6.10 (various assertions fail). check-in: 4ad7dd2e user: fvogel tags: core-8-6-branch | |
2022-10-25
| ||
20:33 | Fix [5e4e44a93b]: ttk::panedwindow chokes on drag. Closed-Leaf check-in: 347a8882 user: fvogel tags: bug-5e4e44a93b | |
19:51 | Rework comments a bit more. Closed-Leaf check-in: df4a096e user: fvogel tags: bug-43573999ca | |
19:43 | Rework comments a bit. check-in: 51b9372b user: fvogel tags: bug-43573999ca | |
2022-10-24
| ||
21:59 | Rebase to latest 8.6 check-in: b6d0e36b user: jan.nijtmans tags: cygwin | |
05:49 | Add test bind-37.1 demonstrating bug [43573999ca]. This test currently crashes (on all platforms). check-in: 802fde74 user: fvogel tags: bug-43573999ca | |
2022-10-18
| ||
20:15 | merge 8.6 check-in: 1bcc6791 user: fvogel tags: trunk, main | |
20:13 | merge 8.6 check-in: 21f26740 user: fvogel tags: unstable_tests | |
14:09 | merge 8.6 check-in: fbf6e9bd user: dgp tags: core-8-6-13-rc | |
2022-10-17
| ||
20:45 | Add a few more test adjustments check-in: 87d8b0cd user: culler tags: core-8-6-branch | |
19:31 | Merge unstable_tests branch. This commit stabilizes several more tests that could sporadically fail on macOS. No test expected results were changed. check-in: f001c786 user: fvogel tags: core-8-6-branch | |
2022-10-10
| ||
21:24 | Add a few other adjustments to unstable_tests Closed-Leaf check-in: 0599fb44 user: culler tags: unstable_plus | |
Changes to generic/tkBind.c.
︙ | ︙ | |||
139 140 141 142 143 144 145 | struct PatSeq; /* forward declaration */ /* We need this array for bookkeeping the last matching modifier mask per pattern. */ TK_ARRAY_DEFINE(PSModMaskArr, unsigned); typedef struct PSEntry { | | | 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | struct PatSeq; /* forward declaration */ /* We need this array for bookkeeping the last matching modifier mask per pattern. */ TK_ARRAY_DEFINE(PSModMaskArr, unsigned); typedef struct PSEntry { TK_DLIST_LINKS(PSEntry); /* Makes this struct a doubly linked list; must be first entry. */ Window window; /* Window of last match. */ struct PatSeq* psPtr; /* Pointer to pattern sequence. */ PSModMaskArr *lastModMaskArr; /* Last matching modifier mask per pattern (except last pattern). * Only needed if pattern sequence is not single (more than one * pattern), and if one of these patterns contains a non-zero * modifier mask. */ |
︙ | ︙ | |||
184 185 186 187 188 189 190 | * binding tables may exist at once, either because there are multiple * applications open, or because there are multiple domains within an * application with separate event bindings for each (for example, each canvas * widget has a separate binding table for associating events with the items * in the canvas). */ | | | 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | * binding tables may exist at once, either because there are multiple * applications open, or because there are multiple domains within an * application with separate event bindings for each (for example, each canvas * widget has a separate binding table for associating events with the items * in the canvas). */ /* Defining the whole PromArr_* stuff (array of PSList entries) */ TK_ARRAY_DEFINE(PromArr, PSList); typedef struct Tk_BindingTable_ { Event eventInfo[TK_LASTEVENT]; /* Containing the most recent event for every event type. */ PromArr *promArr; /* Contains the promoted pattern sequences. */ Event *curEvent; /* Pointing to most recent event. */ |
︙ | ︙ | |||
415 416 417 418 419 420 421 | /* * Flags for ModInfo structures: * * DOUBLE - Non-zero means duplicate this event, e.g. for double-clicks. * TRIPLE - Non-zero means triplicate this event, e.g. for triple-clicks. * QUADRUPLE - Non-zero means quadruple this event, e.g. for 4-fold-clicks. | | | 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 | /* * Flags for ModInfo structures: * * DOUBLE - Non-zero means duplicate this event, e.g. for double-clicks. * TRIPLE - Non-zero means triplicate this event, e.g. for triple-clicks. * QUADRUPLE - Non-zero means quadruple this event, e.g. for 4-fold-clicks. * MULT_CLICKS - Combination of all the above. */ #define DOUBLE (1<<0) #define TRIPLE (1<<1) #define QUADRUPLE (1<<2) #define MULT_CLICKS (DOUBLE|TRIPLE|QUADRUPLE) |
︙ | ︙ | |||
552 553 554 555 556 557 558 | #define MAPREQ (1<<20) #define CONFIGREQ (1<<21) #define RESIZEREQ (1<<22) #define CIRCREQ (1<<23) /* * These structs agree with xkey for the fields type, serial, send_event, display, | | | 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 | #define MAPREQ (1<<20) #define CONFIGREQ (1<<21) #define RESIZEREQ (1<<22) #define CIRCREQ (1<<23) /* * These structs agree with xkey for the fields type, serial, send_event, display, * window, root, subwindow, time, x, y, x_root, and y_root. So when accessing * these fields we may pretend that we are using a struct xkey. */ #define HAS_XKEY_HEAD (KEY|BUTTON|MOTION|VIRTUAL|CROSSING|WHEEL) /* * The xcrossing struct puts the state field in a different location, but the other |
︙ | ︙ | |||
750 751 752 753 754 755 756 | static int IsOdd(int n) { return n & 1; } static int TestNearbyTime(int lhs, int rhs) { return Abs(lhs - rhs) <= NEARBY_MS; } static int TestNearbyCoords(int lhs, int rhs) { return Abs(lhs - rhs) <= NEARBY_PIXELS; } static int IsSubsetOf( | | | | 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 | static int IsOdd(int n) { return n & 1; } static int TestNearbyTime(int lhs, int rhs) { return Abs(lhs - rhs) <= NEARBY_MS; } static int TestNearbyCoords(int lhs, int rhs) { return Abs(lhs - rhs) <= NEARBY_PIXELS; } static int IsSubsetOf( unsigned lhsMask, /* Is this a subset... */ unsigned rhsMask) /* ...of this bit field? */ { return (lhsMask & rhsMask) == lhsMask; } static const char* SkipSpaces( const char* s) |
︙ | ︙ | |||
854 855 856 857 858 859 860 | unsigned eventType) { return eventType == ButtonPress || eventType == ButtonRelease; } static int MatchEventNearby( | | | | | | 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 | unsigned eventType) { return eventType == ButtonPress || eventType == ButtonRelease; } static int MatchEventNearby( const XEvent *lhs, /* Previous button event */ const XEvent *rhs) /* Current button event */ { assert(lhs); assert(rhs); assert(IsButtonEventType(lhs->type)); assert(lhs->type == rhs->type); /* assert: lhs->xbutton.time <= rhs->xbutton.time */ return TestNearbyTime(rhs->xbutton.time, lhs->xbutton.time) && TestNearbyCoords(rhs->xbutton.x_root, lhs->xbutton.x_root) && TestNearbyCoords(rhs->xbutton.y_root, lhs->xbutton.y_root); } static int MatchEventRepeat( const XKeyEvent *lhs, /* Previous key event */ const XKeyEvent *rhs) /* Current key event */ { assert(lhs); assert(rhs); assert(IsKeyEventType(lhs->type)); assert(lhs->type == rhs->type); /* assert: lhs->time <= rhs->time */ |
︙ | ︙ | |||
1097 1098 1099 1100 1101 1102 1103 | { PatternTableKey key; Tcl_HashEntry *hPtr; assert(lookupTables); assert(eventPtr); | | | 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 | { PatternTableKey key; Tcl_HashEntry *hPtr; assert(lookupTables); assert(eventPtr); /* Otherwise on some systems the key contains uninitialized bytes. */ memset(&key, 0, sizeof(PatternTableKey)); if (onlyConsiderDetailedEvents) { switch (eventPtr->xev.type) { case ButtonPress: /* fallthru */ case ButtonRelease: key.detail.info = eventPtr->xev.xbutton.button; break; case MotionNotify: key.detail.info = ButtonNumberFromState(eventPtr->xev.xmotion.state); break; |
︙ | ︙ | |||
1228 1229 1230 1231 1232 1233 1234 | * Side effects: * Memory allocated. * *--------------------------------------------------------------------------- */ /* | | | | | | | | | | | 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 | * Side effects: * Memory allocated. * *--------------------------------------------------------------------------- */ /* * Windows compiler does not allow the definition of these static variables inside a function, * otherwise this should belong to function TkBindInit(). */ TCL_DECLARE_MUTEX(bindMutex); static int initialized = 0; void TkBindInit( TkMainInfo *mainPtr) /* The newly created application. */ { BindInfo *bindInfoPtr; assert(mainPtr); /* Otherwise virtual events can't be supported. */ assert(sizeof(XEvent) >= sizeof(XVirtualEvent)); /* Is type of TkPattern.info well defined? */ assert(sizeof(Info) >= sizeof(KeySym)); assert(sizeof(Info) >= sizeof(unsigned)); /* Ensure that our matching algorithm is working (when testing detail). */ assert(sizeof(Detail) == sizeof(Tk_Uid)); /* Test expected indices of Button1..Button5, otherwise our button handling is not working. */ assert(Button1 == 1 && Button2 == 2 && Button3 == 3 && Button4 == 4 && Button5 == 5); assert(Button2Mask == (Button1Mask << 1)); assert(Button3Mask == (Button1Mask << 2)); assert(Button4Mask == (Button1Mask << 3)); assert(Button5Mask == (Button1Mask << 4)); /* Test expected values of button motion masks, otherwise our button handling is not working. */ assert(Button1MotionMask == Button1Mask); assert(Button2MotionMask == Button2Mask); assert(Button3MotionMask == Button3Mask); assert(Button4MotionMask == Button4Mask); assert(Button5MotionMask == Button5Mask); /* Because we expect zero if keySym is empty. */ 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)); /* 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)); |
︙ | ︙ | |||
2238 2239 2240 2241 2242 2243 2244 | case KeyRelease: { int reset = 1; if (eventPtr->xkey.time) { bindInfoPtr->lastCurrentTime = CurrentTimeInMilliSecs(); bindInfoPtr->lastEventTime = eventPtr->xkey.time; } | | | | | 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 | case KeyRelease: { int reset = 1; if (eventPtr->xkey.time) { bindInfoPtr->lastCurrentTime = CurrentTimeInMilliSecs(); bindInfoPtr->lastEventTime = eventPtr->xkey.time; } /* Modifier keys should not influence button events. */ for (i = 0; i < (unsigned) dispPtr->numModKeyCodes; ++i) { if (dispPtr->modKeyCodes[i] == eventPtr->xkey.keycode) { reset = 0; } } if (reset) { /* Reset repetition count for button events. */ bindPtr->eventInfo[ButtonPress].countAny = 0; bindPtr->eventInfo[ButtonPress].countDetailed = 0; bindPtr->eventInfo[ButtonRelease].countAny = 0; bindPtr->eventInfo[ButtonRelease].countDetailed = 0; } break; } case ButtonPress: case ButtonRelease: /* Reset repetition count for key events. */ bindPtr->eventInfo[KeyPress].countAny = 0; bindPtr->eventInfo[KeyPress].countDetailed = 0; bindPtr->eventInfo[KeyRelease].countAny = 0; bindPtr->eventInfo[KeyRelease].countDetailed = 0; /* fallthru */ case MotionNotify: if (eventPtr->xmotion.time) { |
︙ | ︙ | |||
2359 2360 2361 2362 2363 2364 2365 | bindPtr->curEvent = curEvent; physTables = &bindPtr->lookupTables; scriptCount = 0; arraySize = 0; Tcl_DStringInit(&scripts); if ((size_t) numObjects > SIZE_OF_ARRAY(matchPtrBuf)) { | | | 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 | bindPtr->curEvent = curEvent; physTables = &bindPtr->lookupTables; scriptCount = 0; arraySize = 0; Tcl_DStringInit(&scripts); if ((size_t) numObjects > SIZE_OF_ARRAY(matchPtrBuf)) { /* It's unrealistic that the buffer size is too small, but who knows? */ matchPtrArr = (PatSeq **)ckalloc(numObjects*sizeof(matchPtrArr[0])); } memset(matchPtrArr, 0, numObjects*sizeof(matchPtrArr[0])); if (!PromArr_IsEmpty(bindPtr->promArr)) { for (k = 0; k < (unsigned) numObjects; ++k) { psl[1] = PromArr_Last(bindPtr->promArr); |
︙ | ︙ | |||
2381 2382 2383 2384 2385 2386 2387 | * usually this list only contains one or two patterns. */ for (i = PromArr_Size(bindPtr->promArr); i > 0; --i, --psl[0], --psl[1]) { psPtr[0] = MatchPatterns(dispPtr, bindPtr, psl[0], psl[1], i, curEvent, objArr[k], NULL); if (IsBetterMatch(matchPtrArr[k], psPtr[0])) { | | | | 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 | * usually this list only contains one or two patterns. */ for (i = PromArr_Size(bindPtr->promArr); i > 0; --i, --psl[0], --psl[1]) { psPtr[0] = MatchPatterns(dispPtr, bindPtr, psl[0], psl[1], i, curEvent, objArr[k], NULL); if (IsBetterMatch(matchPtrArr[k], psPtr[0])) { /* We will process it later, because we still may find a pattern with better match. */ matchPtrArr[k] = psPtr[0]; } if (!PSList_IsEmpty(psl[1])) { /* We have promoted sequences, adjust array size. */ arraySize = Max(i + 1, arraySize); } } } } /* |
︙ | ︙ | |||
2410 2411 2412 2413 2414 2415 2416 | assert(psl[0] == NULL || psl[0] != psl[1]); psPtr[0] = MatchPatterns(dispPtr, bindPtr, psl[0], psSuccList, 0, curEvent, objArr[k], NULL); psPtr[1] = MatchPatterns(dispPtr, bindPtr, psl[1], psSuccList, 0, curEvent, objArr[k], NULL); if (!PSList_IsEmpty(psSuccList)) { | | | 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 | assert(psl[0] == NULL || psl[0] != psl[1]); psPtr[0] = MatchPatterns(dispPtr, bindPtr, psl[0], psSuccList, 0, curEvent, objArr[k], NULL); psPtr[1] = MatchPatterns(dispPtr, bindPtr, psl[1], psSuccList, 0, curEvent, objArr[k], NULL); if (!PSList_IsEmpty(psSuccList)) { /* We have promoted sequences, adjust array size. */ arraySize = Max(1u, arraySize); } bestPtr = psPtr[0] ? psPtr[0] : psPtr[1]; if (matchPtrArr[k]) { if (IsBetterMatch(matchPtrArr[k], bestPtr)) { |
︙ | ︙ | |||
2463 2464 2465 2466 2467 2468 2469 | matchPtrArr[k] = matchPtr; } } } if (matchPtrArr[k]) { ExpandPercents(winPtr, matchPtrArr[k]->script, curEvent, scriptCount++, &scripts); | | | 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 | matchPtrArr[k] = matchPtr; } } } if (matchPtrArr[k]) { ExpandPercents(winPtr, matchPtrArr[k]->script, curEvent, scriptCount++, &scripts); /* Null is added to the scripts string to separate the various scripts. */ Tcl_DStringAppend(&scripts, "", 1); } } PromArr_SetSize(bindPtr->promArr, arraySize); /* |
︙ | ︙ | |||
2528 2529 2530 2531 2532 2533 2534 | } break; } } } if (!PSList_IsEmpty(psList)) { | | | | 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 | } break; } } } if (!PSList_IsEmpty(psList)) { /* We still have promoted sequences, adjust array size. */ newArraySize = Max(i + 1, newArraySize); } } PromArr_SetSize(bindPtr->promArr, newArraySize); if (matchPtrArr != matchPtrBuf) { ckfree(matchPtrArr); } if (Tcl_DStringLength(&scripts) == 0) { return; /* Nothing to do. */ } /* * Now go back through and evaluate the binding for each object, in order, * dealing with "break" and "continue" exceptions appropriately. * * There are two tricks here: |
︙ | ︙ | |||
2671 2672 2673 2674 2675 2676 2677 | if (*physPtrPtr) { const TkPattern *physPatPtr = (*physPtrPtr)->pats; const TkPattern *virtPatPtr = psPtr->pats; if (physPatPtr->info || !virtPatPtr->info) { if (IsSubsetOf(virtPatPtr->modMask, physPatPtr->modMask)) { | | | | 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 | if (*physPtrPtr) { const TkPattern *physPatPtr = (*physPtrPtr)->pats; const TkPattern *virtPatPtr = psPtr->pats; if (physPatPtr->info || !virtPatPtr->info) { if (IsSubsetOf(virtPatPtr->modMask, physPatPtr->modMask)) { return 0; /* We cannot surpass this match. */ } } } /* Otherwise on some systems the key contains uninitialized bytes. */ memset(&key, 0, sizeof(key)); key.object = object; key.type = VirtualEvent; owners = psPtr->ptr.owners; for (i = 0; i < VirtOwners_Size(owners); ++i) { |
︙ | ︙ | |||
2702 2703 2704 2705 2706 2707 2708 | return 0; } /* helper function */ static int Compare( const PatSeq *fstMatchPtr, | | | 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 | return 0; } /* helper function */ static int Compare( const PatSeq *fstMatchPtr, const PatSeq *sndMatchPtr) /* Most recent match. */ { int diff; if (!fstMatchPtr) { return +1; } assert(sndMatchPtr); diff = CountSpecialized(fstMatchPtr, sndMatchPtr); return diff ? diff : (int) sndMatchPtr->count - (int) fstMatchPtr->count; |
︙ | ︙ | |||
2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 | /* Finally compare modifier masks of last pattern. */ if (IsSubsetOf(fstModMask, sndModMask)) { ++sndCount; } if (IsSubsetOf(sndModMask, fstModMask)) { ++fstCount; } return fstCount - sndCount; } static PatSeq * MatchPatterns( TkDisplay *dispPtr, /* Display from which the event came. */ Tk_BindingTable bindPtr, /* Table in which to look for bindings. */ PSList *psList, /* List of potentially matching patterns, can be NULL. */ PSList *psSuccList, /* Add all matching higher-level pattern sequences to this list. | > > > > > > > > > > > > > > | 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 | /* Finally compare modifier masks of last pattern. */ if (IsSubsetOf(fstModMask, sndModMask)) { ++sndCount; } if (IsSubsetOf(sndModMask, fstModMask)) { ++fstCount; } return fstCount - sndCount; } /* helper function */ static int IsPSInPSList( const PatSeq *psPtr, /* Is this pattern sequence... */ const PSList *psList) /* ...an element of this list of patterns sequence? */ { PSEntry *psEntry; TK_DLIST_FOREACH(psEntry, psList) { if (psEntry->psPtr == psPtr) { return 1; } } return 0; } static PatSeq * MatchPatterns( TkDisplay *dispPtr, /* Display from which the event came. */ Tk_BindingTable bindPtr, /* Table in which to look for bindings. */ PSList *psList, /* List of potentially matching patterns, can be NULL. */ PSList *psSuccList, /* Add all matching higher-level pattern sequences to this list. |
︙ | ︙ | |||
2827 2828 2829 2830 2831 2832 2833 | assert(psPtr->numPats > patIndex); if (psPtr->object ? psPtr->object == object : VirtPatIsBound(bindPtr, psPtr, object, physPtrPtr)) { TkPattern *patPtr = psPtr->pats + patIndex; | | | | | | 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 | assert(psPtr->numPats > patIndex); if (psPtr->object ? psPtr->object == object : VirtPatIsBound(bindPtr, psPtr, object, physPtrPtr)) { TkPattern *patPtr = psPtr->pats + patIndex; /* Ignore modifier key events, and KeyRelease events if the current event * is of a different type (e.g. a Button event) */ psEntry->keepIt = isModKeyOnly || \ ((patPtr->eventType != (unsigned) curEvent->xev.type) && curEvent->xev.type == KeyRelease); if (patPtr->eventType == (unsigned) curEvent->xev.type && (curEvent->xev.type != CreateNotify || curEvent->xev.xcreatewindow.parent == window) && (!patPtr->name || patPtr->name == curEvent->detail.name) && (!patPtr->info || patPtr->info == curEvent->detail.info)) { /* * Resolve the modifier mask for Alt and Mod keys. Unfortunately this * cannot be done in ParseEventDescription, otherwise this function would * be the better place. */ unsigned modMask = ResolveModifiers(dispPtr, patPtr->modMask); unsigned curModMask = ResolveModifiers(dispPtr, bindPtr->curModMask); psEntry->expired = 1; /* Remove it from promotion list. */ psEntry->keepIt = 0; /* Don't keep matching patterns. */ if (IsSubsetOf(modMask, curModMask)) { unsigned count = patPtr->info ? curEvent->countDetailed : curEvent->countAny; if (patIndex < PSModMaskArr_Size(psEntry->lastModMaskArr)) { PSModMaskArr_Set(psEntry->lastModMaskArr, patIndex, &modMask); } /* * This pattern is finally matching. */ if (psPtr->numPats == patIndex + 1) { if (patPtr->count <= count) { /* * This is also a final pattern (i.e. the pattern sequence is complete). * We always prefer the pattern with better match. * If completely equal than prefer most recently defined pattern. */ int cmp = Compare(bestPtr, psPtr); if (cmp == 0) { |
︙ | ︙ | |||
2885 2886 2887 2888 2889 2890 2891 | bestModMaskArr = psEntry->lastModMaskArr; if (physPtrPtr) { bestPhysPtr = *physPtrPtr; } } } else { DEBUG(psEntry->expired = 0;) | | | > > | | | | | | | | | | | | | | | | | > > > > > > > > | 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 | bestModMaskArr = psEntry->lastModMaskArr; if (physPtrPtr) { bestPhysPtr = *physPtrPtr; } } } else { DEBUG(psEntry->expired = 0;) psEntry->keepIt = 1; /* Don't remove it from promotion list. */ } } else if (psSuccList) { /* * Not a final pattern, but matching (i.e. successive patterns match the pattern sequence so far), * so promote the pattern sequence to next level if not already promoted in the success list. * But do not promote if count of current pattern is not yet reached. */ if (!IsPSInPSList(psPtr, psSuccList)) { if (patPtr->count == psEntry->count) { PSEntry *psNewEntry; assert(!patPtr->name); psNewEntry = MakeListEntry( &bindPtr->lookupTables.entryPool, psPtr, psPtr->modMaskUsed); if (!PSModMaskArr_IsEmpty(psNewEntry->lastModMaskArr)) { PSModMaskArr_Set(psNewEntry->lastModMaskArr, patIndex, &modMask); } assert(psNewEntry->keepIt); assert(psNewEntry->count == 1u); PSList_Append(psSuccList, psNewEntry); psNewEntry->window = window; /* Bind to current window. */ } else { assert(psEntry->count < patPtr->count); DEBUG(psEntry->expired = 0;) psEntry->count += 1; psEntry->keepIt = 1; /* Don't remove it from promotion list. */ } } else { /* * Pattern sequence is already present in the success list. */ DEBUG(psEntry->expired = 0;) psEntry->keepIt = 1; /* Don't remove it from promotion list. */ } } } } } } } |
︙ | ︙ | |||
3545 3546 3547 3548 3549 3550 3551 | assert(eventString); if (!(virtUid = GetVirtualEventUid(interp, virtString))) { return 0; } /* | | | 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 | assert(eventString); if (!(virtUid = GetVirtualEventUid(interp, virtString))) { return 0; } /* * Find/create physical event. */ if (!(psPtr = FindSequence(interp, &vetPtr->lookupTables, NULL, eventString, 1, 0, NULL))) { return 0; } assert(TEST_PSENTRY(psPtr)); |
︙ | ︙ | |||
3653 3654 3655 3656 3657 3658 3659 | assert(TEST_PSENTRY(psPtr)); if (!eventPSPtr || psPtr == eventPSPtr) { VirtOwners *owners = psPtr->ptr.owners; int iVirt = VirtOwners_Find(owners, vhPtr); | | | 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 | assert(TEST_PSENTRY(psPtr)); if (!eventPSPtr || psPtr == eventPSPtr) { VirtOwners *owners = psPtr->ptr.owners; int iVirt = VirtOwners_Find(owners, vhPtr); assert(iVirt != -1); /* Otherwise we couldn't find owner, and this should not happen. */ /* * Remove association between this physical event and the given * virtual event that it triggers. */ if (VirtOwners_Size(owners) > 1) { |
︙ | ︙ | |||
4833 4834 4835 4836 4837 4838 4839 | unsigned count = 1; assert(eventStringPtr); assert(patPtr); assert(eventMaskPtr); p = *eventStringPtr; | | | 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 | unsigned count = 1; assert(eventStringPtr); assert(patPtr); assert(eventMaskPtr); p = *eventStringPtr; memset(patPtr, 0, sizeof(TkPattern)); /* Otherwise memcmp doesn't work. */ /* * Handle simple ASCII characters. */ if (*p != '<') { char string[2]; |
︙ | ︙ | |||
4964 4965 4966 4967 4968 4969 4970 | } if (*field) { unsigned button = GetButtonNumber(field); if ((eventFlags & BUTTON) || (button && eventFlags == 0) || (SUPPORT_ADDITIONAL_MOTION_SYNTAX && (eventFlags & MOTION) && button == 0)) { | | | 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 | } if (*field) { unsigned button = GetButtonNumber(field); if ((eventFlags & BUTTON) || (button && eventFlags == 0) || (SUPPORT_ADDITIONAL_MOTION_SYNTAX && (eventFlags & MOTION) && button == 0)) { /* This must be a button (or bad motion) event. */ if (button == 0) { return FinalizeParseEventDescription( interp, patPtr, 0, Tcl_ObjPrintf("bad button number \"%s\"", field), "BUTTON"); } patPtr->info = button; |
︙ | ︙ |
Changes to tests/bind.test.
︙ | ︙ | |||
6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 6992 6993 6994 6995 | # are at (10,10) inside the label widget as requested by the warping expr {$x1==$x2 && $y1==$y2 && $x1==[winfo rootx .top.l]+10 \ && $y1==[winfo rooty .top.l]+10} } -cleanup { destroy .top unset x1 y1 x2 y2 } -result 1 # cleanup cleanupTests return # vi:set ts=4 sw=4 et: # Local Variables: | > > > > > > > > > > > > > > > > > > > > > | 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 6992 6993 6994 6995 6996 6997 6998 6999 7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 | # are at (10,10) inside the label widget as requested by the warping expr {$x1==$x2 && $y1==$y2 && $x1==[winfo rootx .top.l]+10 \ && $y1==[winfo rooty .top.l]+10} } -cleanup { destroy .top unset x1 y1 x2 y2 } -result 1 test bind-37.1 {Promotion tables do not contain duplicate sequences, bug [43573999ca]} -body { proc A {} { bind .c <B1-Motion><Enter> {} set myv(a) 1 set b [array get myv] bind .c <B1-Motion><Enter> "puts Trigger" } pack [canvas .c] bind .c <ButtonRelease-1> "A" A update event generate .c <Button-1> event generate .c <B1-Motion> event generate .c <B1-Motion> event generate .c <B1-Motion> event generate .c <ButtonRelease-1> event generate .c <B1-Motion> } -cleanup { destroy .c } -returnCodes ok -result {} ; # shall not crash (assertion failed) # cleanup cleanupTests return # vi:set ts=4 sw=4 et: # Local Variables: |
︙ | ︙ |