Tk Source Code

Check-in [e1dbced6]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merged core-8-6-branch
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | tip-446-undodepth
Files: files | file ages | folders
SHA1: e1dbced686a14c412f6bec33baa3eeb2662bcbc4
User & Date: fvogel 2016-05-01 20:03:04
Context
2016-05-12
22:22
Unified branched tip-446-undodepth and tip-446-canundo to become branch tip-446 Closed-Leaf check-in: e9c606f4 user: fvogel tags: mistake
22:21
Unified branched tip-446-undodepth and tip-446-canundo to become branch tip-446 check-in: 2bfc04af user: fvogel tags: tip-446
2016-05-01
20:03
Merged core-8-6-branch Closed-Leaf check-in: e1dbced6 user: fvogel tags: tip-446-undodepth
19:51
Fixed [b362182e45] - Generation of virtual events through Tk_HandleEvent is unsafe check-in: 047d31f2 user: fvogel tags: core-8-6-branch
2016-04-07
20:18
Tests for [.t edit undodepth/redodepth] check-in: 00090592 user: fvogel tags: tip-446-undodepth
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to doc/event.n.

347
348
349
350
351
352
353






354
355
356
357
358
359
360
action.
.TP
\fB<<TraverseOut>>\fR
This is sent to a widget when the focus leaves the widget because of a
user-driven
.QW "tab to widget"
action.






.PP
Tk defines the following virtual events for the purposes of unifying
bindings across multiple platforms. Users expect them to behave in the
following way:
.TP
\fB<<Clear>>\fR
Delete the currently selected widget contents.






>
>
>
>
>
>







347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
action.
.TP
\fB<<TraverseOut>>\fR
This is sent to a widget when the focus leaves the widget because of a
user-driven
.QW "tab to widget"
action.
.TP
\fB<<WidgetViewSync>>\fR
This is sent to a text widget when its internal data become obsolete,
and again when these internal data are back in sync with the widget
view. The detail field (%d substitution) is either true (when the
widget is in sync) or false (when it is not).
.PP
Tk defines the following virtual events for the purposes of unifying
bindings across multiple platforms. Users expect them to behave in the
following way:
.TP
\fB<<Clear>>\fR
Delete the currently selected widget contents.

Changes to doc/text.n.

976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
does not really matter compared to execution speed.
.PP
In case accurate result is needed (and if the text widget is managed by a
geometry manager), one can resort to \fIpathName \fBsync\fR and \fIpathName
\fBpendingsync\fR to control the synchronization of the view of text widgets.
.PP
The \fB<<WidgetViewSync>>\fR virtual event fires when the line heights of the
text widget becomes obsolete (due to some editing command or configuration
change), and again when the internal data of the text widget are back in sync
with the widget view. The detail field (%d substitution) is either true (when
the widget is in sync) or false (when it is not).
.PP
\fIpathName \fBsync\fR, \fIpathName \fBpendingsync\fR and
\fB<<WidgetViewSync>>\fR apply to each text widget independently of its peers.
.PP






|







976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
does not really matter compared to execution speed.
.PP
In case accurate result is needed (and if the text widget is managed by a
geometry manager), one can resort to \fIpathName \fBsync\fR and \fIpathName
\fBpendingsync\fR to control the synchronization of the view of text widgets.
.PP
The \fB<<WidgetViewSync>>\fR virtual event fires when the line heights of the
text widget become obsolete (due to some editing command or configuration
change), and again when the internal data of the text widget are back in sync
with the widget view. The detail field (%d substitution) is either true (when
the widget is in sync) or false (when it is not).
.PP
\fIpathName \fBsync\fR, \fIpathName \fBpendingsync\fR and
\fB<<WidgetViewSync>>\fR apply to each text widget independently of its peers.
.PP

Changes to generic/tkInt.h.

1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
			    Window parent);
MODULE_SCOPE void	TkpCreateBusy(Tk_FakeWin *winPtr, Tk_Window tkRef,
			    Window *parentPtr, Tk_Window tkParent,
			    TkBusy busy);
MODULE_SCOPE int	TkBackgroundEvalObjv(Tcl_Interp *interp,
			    int objc, Tcl_Obj *const *objv, int flags);
MODULE_SCOPE void	TkSendVirtualEvent(Tk_Window tgtWin,
			    const char *eventName);
MODULE_SCOPE Tcl_Command TkMakeEnsemble(Tcl_Interp *interp,
			    const char *nsname, const char *name,
			    ClientData clientData, const TkEnsemble *map);
MODULE_SCOPE int	TkInitTkCmd(Tcl_Interp *interp,
			    ClientData clientData);
MODULE_SCOPE int	TkInitFontchooser(Tcl_Interp *interp,
			    ClientData clientData);






|







1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
			    Window parent);
MODULE_SCOPE void	TkpCreateBusy(Tk_FakeWin *winPtr, Tk_Window tkRef,
			    Window *parentPtr, Tk_Window tkParent,
			    TkBusy busy);
MODULE_SCOPE int	TkBackgroundEvalObjv(Tcl_Interp *interp,
			    int objc, Tcl_Obj *const *objv, int flags);
MODULE_SCOPE void	TkSendVirtualEvent(Tk_Window tgtWin,
			    const char *eventName, Tcl_Obj *detail);
MODULE_SCOPE Tcl_Command TkMakeEnsemble(Tcl_Interp *interp,
			    const char *nsname, const char *name,
			    ClientData clientData, const TkEnsemble *map);
MODULE_SCOPE int	TkInitTkCmd(Tcl_Interp *interp,
			    ClientData clientData);
MODULE_SCOPE int	TkInitFontchooser(Tcl_Interp *interp,
			    ClientData clientData);

Changes to generic/tkListbox.c.

3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
 *----------------------------------------------------------------------
 */

static void
GenerateListboxSelectEvent(
    Listbox *listPtr)		/* Information about widget. */
{
    union {XEvent general; XVirtualEvent virtual;} event;

    memset(&event, 0, sizeof(event));
    event.general.xany.type = VirtualEvent;
    event.general.xany.serial = NextRequest(Tk_Display(listPtr->tkwin));
    event.general.xany.send_event = False;
    event.general.xany.window = Tk_WindowId(listPtr->tkwin);
    event.general.xany.display = Tk_Display(listPtr->tkwin);
    event.virtual.name = Tk_GetUid("ListboxSelect");
    Tk_HandleEvent(&event.general);
}
 
/*
 *----------------------------------------------------------------------
 *
 * EventuallyRedrawRange --
 *






|
<
<
<
<
<
<
<
<
<







3219
3220
3221
3222
3223
3224
3225
3226









3227
3228
3229
3230
3231
3232
3233
 *----------------------------------------------------------------------
 */

static void
GenerateListboxSelectEvent(
    Listbox *listPtr)		/* Information about widget. */
{
    TkSendVirtualEvent(listPtr->tkwin, "ListboxSelect", NULL);









}
 
/*
 *----------------------------------------------------------------------
 *
 * EventuallyRedrawRange --
 *

Changes to generic/tkText.c.

3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
....
5213
5214
5215
5216
5217
5218
5219


5220

5221
5222
5223
5224
5225
5226
5227
....
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406

5407
5408
5409
5410
5411
5412
5413
    TkText *textPtr)
{
    /*
     * Send an event that the selection changed. This is equivalent to:
     *     event generate $textWidget <<Selection>>
     */

    union {XEvent general; XVirtualEvent virtual;} event;

    memset(&event, 0, sizeof(event));
    event.general.xany.type = VirtualEvent;
    event.general.xany.serial = NextRequest(Tk_Display(textPtr->tkwin));
    event.general.xany.send_event = False;
    event.general.xany.window = Tk_WindowId(textPtr->tkwin);
    event.general.xany.display = Tk_Display(textPtr->tkwin);
    event.virtual.name = Tk_GetUid("Selection");
    Tk_HandleEvent(&event.general);
}
 
/*
 *----------------------------------------------------------------------
 *
 * TextBlinkProc --
 *
................................................................................

	/*
	 * Only issue the <<Modified>> event if the flag actually changed.
	 * However, degree of modified-ness doesn't matter. [Bug 1799782]
	 */

	if ((!oldModified) != (!setModified)) {


	    GenerateModifiedEvent(textPtr);

	}
	break;
    case EDIT_REDO:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 3, objv, NULL);
	    return TCL_ERROR;
	}
................................................................................
 *----------------------------------------------------------------------
 */

static void
GenerateModifiedEvent(
    TkText *textPtr)	/* Information about text widget. */
{
    union {
	XEvent general;
	XVirtualEvent virtual;
    } event;

    Tk_MakeWindowExist(textPtr->tkwin);

    memset(&event, 0, sizeof(event));
    event.general.xany.type = VirtualEvent;
    event.general.xany.serial = NextRequest(Tk_Display(textPtr->tkwin));
    event.general.xany.send_event = False;
    event.general.xany.window = Tk_WindowId(textPtr->tkwin);
    event.general.xany.display = Tk_Display(textPtr->tkwin);
    event.virtual.name = Tk_GetUid("Modified");
    Tk_HandleEvent(&event.general);

}
 
/*
 *----------------------------------------------------------------------
 *
 * UpdateDirtyFlag --
 *






|
<
<
<
<
<
<
<
<
<







 







>
>
|
>







 







<
<
<
<
<

<
<
<
<
<
<
<
<
<
>







3550
3551
3552
3553
3554
3555
3556
3557









3558
3559
3560
3561
3562
3563
3564
....
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
....
5379
5380
5381
5382
5383
5384
5385





5386









5387
5388
5389
5390
5391
5392
5393
5394
    TkText *textPtr)
{
    /*
     * Send an event that the selection changed. This is equivalent to:
     *     event generate $textWidget <<Selection>>
     */

    TkSendVirtualEvent(textPtr->tkwin, "Selection", NULL);









}
 
/*
 *----------------------------------------------------------------------
 *
 * TextBlinkProc --
 *
................................................................................

	/*
	 * Only issue the <<Modified>> event if the flag actually changed.
	 * However, degree of modified-ness doesn't matter. [Bug 1799782]
	 */

	if ((!oldModified) != (!setModified)) {
            for (textPtr = textPtr->sharedTextPtr->peers; textPtr != NULL;
                    textPtr = textPtr->next) {
                GenerateModifiedEvent(textPtr);
            }
	}
	break;
    case EDIT_REDO:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 3, objv, NULL);
	    return TCL_ERROR;
	}
................................................................................
 *----------------------------------------------------------------------
 */

static void
GenerateModifiedEvent(
    TkText *textPtr)	/* Information about text widget. */
{





    Tk_MakeWindowExist(textPtr->tkwin);









    TkSendVirtualEvent(textPtr->tkwin, "Modified", NULL);
}
 
/*
 *----------------------------------------------------------------------
 *
 * UpdateDirtyFlag --
 *

Changes to generic/tkTextDisp.c.

3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
....
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
 *----------------------------------------------------------------------
 *
 * GenerateWidgetViewSyncEvent --
 *
 *      Send the <<WidgetViewSync>> event related to the text widget
 *      line metrics asynchronous update.
 *      This is equivalent to:
 *         event generate $textWidget <<WidgetViewSync>> -detail $s
 *      where $s is the sync status: true (when the widget view is in
 *      sync with its internal data) or false (when it is not).
 *
 * Results:
 *      None
 *
 * Side effects:
................................................................................
 *
 *----------------------------------------------------------------------
 */

static void
GenerateWidgetViewSyncEvent(
    TkText *textPtr,		/* Information about text widget. */
    Bool InSync)                /* True if in sync, false otherwise */
{
    union {XEvent general; XVirtualEvent virtual;} event;

    memset(&event, 0, sizeof(event));
    event.general.xany.type = VirtualEvent;
    event.general.xany.serial = NextRequest(Tk_Display(textPtr->tkwin));
    event.general.xany.send_event = False;
    event.general.xany.window = Tk_WindowId(textPtr->tkwin);
    event.general.xany.display = Tk_Display(textPtr->tkwin);
    event.virtual.name = Tk_GetUid("WidgetViewSync");
    event.virtual.user_data = Tcl_NewBooleanObj(InSync);
    Tk_HandleEvent(&event.general);
}
 
/*
 *----------------------------------------------------------------------
 *
 * TkTextUpdateLineMetrics --
 *






|







 







|

|
<
<
<
<
<
<
<
<
|
<







3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
....
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125








3126

3127
3128
3129
3130
3131
3132
3133
 *----------------------------------------------------------------------
 *
 * GenerateWidgetViewSyncEvent --
 *
 *      Send the <<WidgetViewSync>> event related to the text widget
 *      line metrics asynchronous update.
 *      This is equivalent to:
 *         event generate $textWidget <<WidgetViewSync>> -data $s
 *      where $s is the sync status: true (when the widget view is in
 *      sync with its internal data) or false (when it is not).
 *
 * Results:
 *      None
 *
 * Side effects:
................................................................................
 *
 *----------------------------------------------------------------------
 */

static void
GenerateWidgetViewSyncEvent(
    TkText *textPtr,		/* Information about text widget. */
    Bool InSync)                /* true if in sync, false otherwise */
{
    TkSendVirtualEvent(textPtr->tkwin, "WidgetViewSync",








        Tcl_NewBooleanObj(InSync));

}
 
/*
 *----------------------------------------------------------------------
 *
 * TkTextUpdateLineMetrics --
 *

Changes to generic/tkUtil.c.

1158
1159
1160
1161
1162
1163
1164

1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176

1177
1178
1179
1180
1181
1182
1183
1184
1185
1186



1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
 
/*
 *----------------------------------------------------------------------
 *
 * TkSendVirtualEvent --
 *
 * 	Send a virtual event notification to the specified target window.

 * 	Equivalent to "event generate $target <<$eventName>>"
 *
 * 	Note that we use Tk_QueueWindowEvent, not Tk_HandleEvent, so this
 * 	routine does not reenter the interpreter.
 *
 *----------------------------------------------------------------------
 */

void
TkSendVirtualEvent(
    Tk_Window target,
    const char *eventName)

{
    union {XEvent general; XVirtualEvent virtual;} event;

    memset(&event, 0, sizeof(event));
    event.general.xany.type = VirtualEvent;
    event.general.xany.serial = NextRequest(Tk_Display(target));
    event.general.xany.send_event = False;
    event.general.xany.window = Tk_WindowId(target);
    event.general.xany.display = Tk_Display(target);
    event.virtual.name = Tk_GetUid(eventName);




    Tk_QueueWindowEvent(&event.general, TCL_QUEUE_TAIL);
}
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */






>
|










|
>










>
>
>










1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
 
/*
 *----------------------------------------------------------------------
 *
 * TkSendVirtualEvent --
 *
 * 	Send a virtual event notification to the specified target window.
 * 	Equivalent to:
 * 	    "event generate $target <<$eventName>> -data $detail"
 *
 * 	Note that we use Tk_QueueWindowEvent, not Tk_HandleEvent, so this
 * 	routine does not reenter the interpreter.
 *
 *----------------------------------------------------------------------
 */

void
TkSendVirtualEvent(
    Tk_Window target,
    const char *eventName,
    Tcl_Obj *detail)
{
    union {XEvent general; XVirtualEvent virtual;} event;

    memset(&event, 0, sizeof(event));
    event.general.xany.type = VirtualEvent;
    event.general.xany.serial = NextRequest(Tk_Display(target));
    event.general.xany.send_event = False;
    event.general.xany.window = Tk_WindowId(target);
    event.general.xany.display = Tk_Display(target);
    event.virtual.name = Tk_GetUid(eventName);
    if (detail != NULL) {
        event.virtual.user_data = detail;
    }

    Tk_QueueWindowEvent(&event.general, TCL_QUEUE_TAIL);
}
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to macosx/tkMacOSXDialog.c.

1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
....
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
....
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
....
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
    if (!fontchooserInterp) {
	return;
    }
    fcdPtr = Tcl_GetAssocData(fontchooserInterp, "::tk::fontchooser", NULL);
    switch (kind) {
    case FontchooserClosed:
	if (fcdPtr->parent != None) {
	    TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserVisibility");
	    fontchooserInterp = NULL;
	}
	break;
    case FontchooserSelection:
	fontObj = TkMacOSXFontDescriptionForNSFontAndNSFontAttributes(
		fontPanelFont, fontPanelFontAttributes);
	if (fontObj) {
................................................................................
		    memcpy(tmpv, objv, sizeof(Tcl_Obj *) * objc);
		    tmpv[objc] = fontObj;
		    TkBackgroundEvalObjv(fontchooserInterp, objc + 1, tmpv,
			    TCL_EVAL_GLOBAL);
		    ckfree(tmpv);
		}
	    }
	    TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserFontChanged");
	}
	break;
    }
}
 
/*
 *----------------------------------------------------------------------
................................................................................
	    NSFontPanel *fp = [fm fontPanel:NO];

	    [fp setPanelFont:fontPanelFont isMultiple:NO];
	    [fm setSelectedFont:fontPanelFont isMultiple:NO];
	    [fm setSelectedAttributes:fontPanelFontAttributes
		    isMultiple:NO];
	    if ([fp isVisible]) {
		TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserFontChanged");
	    }
	    break;
	case FontchooserCmd:
	    if (fcdPtr->cmdObj) {
		Tcl_DecrRefCount(fcdPtr->cmdObj);
	    }
	    Tcl_GetStringFromObj(objv[i+1], &len);
................................................................................
    NSFontManager *fm = [NSFontManager sharedFontManager];
    NSFontPanel *fp = [fm fontPanel:YES];
    if ([fp delegate] != NSApp) {
	[fp setDelegate:NSApp];
    }
    if (![fp isVisible]) {
	[fm orderFrontFontPanel:NSApp];
	TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserVisibility");
    }
    fontchooserInterp = interp;

    return TCL_OK;
}
 
/*






|







 







|







 







|







 







|







1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
....
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
....
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
....
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
    if (!fontchooserInterp) {
	return;
    }
    fcdPtr = Tcl_GetAssocData(fontchooserInterp, "::tk::fontchooser", NULL);
    switch (kind) {
    case FontchooserClosed:
	if (fcdPtr->parent != None) {
	    TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserVisibility", NULL);
	    fontchooserInterp = NULL;
	}
	break;
    case FontchooserSelection:
	fontObj = TkMacOSXFontDescriptionForNSFontAndNSFontAttributes(
		fontPanelFont, fontPanelFontAttributes);
	if (fontObj) {
................................................................................
		    memcpy(tmpv, objv, sizeof(Tcl_Obj *) * objc);
		    tmpv[objc] = fontObj;
		    TkBackgroundEvalObjv(fontchooserInterp, objc + 1, tmpv,
			    TCL_EVAL_GLOBAL);
		    ckfree(tmpv);
		}
	    }
	    TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserFontChanged", NULL);
	}
	break;
    }
}
 
/*
 *----------------------------------------------------------------------
................................................................................
	    NSFontPanel *fp = [fm fontPanel:NO];

	    [fp setPanelFont:fontPanelFont isMultiple:NO];
	    [fm setSelectedFont:fontPanelFont isMultiple:NO];
	    [fm setSelectedAttributes:fontPanelFontAttributes
		    isMultiple:NO];
	    if ([fp isVisible]) {
		TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserFontChanged", NULL);
	    }
	    break;
	case FontchooserCmd:
	    if (fcdPtr->cmdObj) {
		Tcl_DecrRefCount(fcdPtr->cmdObj);
	    }
	    Tcl_GetStringFromObj(objv[i+1], &len);
................................................................................
    NSFontManager *fm = [NSFontManager sharedFontManager];
    NSFontPanel *fp = [fm fontPanel:YES];
    if ([fp delegate] != NSApp) {
	[fp setDelegate:NSApp];
    }
    if (![fp isVisible]) {
	[fm orderFrontFontPanel:NSApp];
	TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserVisibility", NULL);
    }
    fontchooserInterp = interp;

    return TCL_OK;
}
 
/*

Changes to tests/listbox.test.

3166
3167
3168
3169
3170
3171
3172

3173
3174
3175
3176
3177
3178
3179
    pack [listbox .l -exportselection true]
    update
    bind .l <<ListboxSelect>> {lappend res [list [selection own] [%W curselection]]}
    .l insert end a b c
    focus -force .l
    event generate .l <1> -x 5 -y 5  ; # <<ListboxSelect>> fires
    selection clear                  ; # <<ListboxSelect>> fires again

    set res
} -cleanup {
    destroy .l
} -result {{.l 0} {{} {}}}

resetGridInfo
deleteWindows






>







3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
    pack [listbox .l -exportselection true]
    update
    bind .l <<ListboxSelect>> {lappend res [list [selection own] [%W curselection]]}
    .l insert end a b c
    focus -force .l
    event generate .l <1> -x 5 -y 5  ; # <<ListboxSelect>> fires
    selection clear                  ; # <<ListboxSelect>> fires again
    update
    set res
} -cleanup {
    destroy .l
} -result {{.l 0} {{} {}}}

resetGridInfo
deleteWindows

Changes to tests/text.test.

3048
3049
3050
3051
3052
3053
3054



















3055
3056
3057
3058
3059
3060
3061
....
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
....
6291
6292
6293
6294
6295
6296
6297

6298
6299
6300
6301
6302
6303
6304
6305
6306
6307

6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319

6320
6321
6322
6323















6324
6325
6326
6327
6328
6329
6330

6331
6332
6333
6334
6335
6336
6337
    .top.yt sync
    vwait res  ; # event dealt with by the event loop, with %d==1 i.e. we're in sync again
    lappend res "Pending:[.top.yt pendingsync]"
    set res
} -cleanup {
    destroy .top.yt .top
} -result {Sync:0 Pending:1 Sync:1 Pending:0}




















test text-12.1 {TextWidgetCmd procedure, "index" option} -setup {
    text .t
} -body {
    .t index
} -cleanup {
    destroy .t
................................................................................
    pack .t
    set ::retval {}
} -body {
    bind .t <<Modified>> "lappend ::retval modified"
# Shouldn't require [update idle] to trigger event [Bug 1809538]
    lappend ::retval [.t edit modified]
    .t edit modified 1
    update idletasks
    lappend ::retval [.t edit modified]
    .t edit modified 1 ; # binding should only fire once [Bug 1799782]
    update idletasks
    lappend ::retval [.t edit modified]
} -cleanup {
    destroy .t
} -result {0 modified 1 1}
................................................................................
test text-27.12 {<<Modified>> virtual event} -body {
    set ::retval unmodified
    text .t -undo 1
    pack .t
    bind .t <<Modified>> "set ::retval modified"
    update idletasks
    .t insert end "nothing special\n"

    return $::retval
} -cleanup {
    destroy .t
} -result {modified}
test text-27.13 {<<Modified>> virtual event - insert before Modified} -body {
    set ::retval {}
    pack [text .t -undo 1]
    bind .t <<Modified>> { set ::retval [.t get 1.0 end-1c] }
    update idletasks
    .t insert end "nothing special"

    return $::retval
} -cleanup {
    destroy .t
} -result {nothing special}
test text-27.14 {<<Modified>> virtual event - delete before Modified} -body {
# Bug 1737288, make sure we delete chars before triggering <<Modified>>
    set ::retval {}
    pack [text .t -undo 1]
    bind .t <<Modified>> { set ::retval [.t get 1.0 end-1c] }
    .t insert end "nothing special"
    .t edit modified 0
    .t delete 1.0 1.2

    set ::retval
} -cleanup {
    destroy .t
} -result {thing special}















test text-27.15 {<<Selection>> virtual event} -body {
    set ::retval no_selection
    pack [text .t -undo 1]
    bind .t <<Selection>> "set ::retval selection_changed"
    update idletasks
    .t insert end "nothing special\n"
    .t tag add sel 1.0 1.1

    set ::retval
} -cleanup {
    destroy .t
} -result {selection_changed}
test text-27.16 {-maxundo configuration option} -body {
    text .t -undo 1  -autoseparators 1 -maxundo 2
    pack .t






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|







 







>










>












>




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







>







3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
....
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
....
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
    .top.yt sync
    vwait res  ; # event dealt with by the event loop, with %d==1 i.e. we're in sync again
    lappend res "Pending:[.top.yt pendingsync]"
    set res
} -cleanup {
    destroy .top.yt .top
} -result {Sync:0 Pending:1 Sync:1 Pending:0}

test text-11a.51 {<<WidgetViewSync>> calls TkSendVirtualEvent(),
                  NOT Tk_HandleEvent().
                  Bug [b362182e45704dd7bbd6aed91e48122035ea3d16]} -setup {
    destroy .top.t .top
} -body {
    set res {}
    toplevel .top
    pack [text .top.t]
    for {set i 1} {$i < 10000} {incr i} {
        .top.t insert end "Hello world!\n" 
    }
    bind .top.t <<WidgetViewSync>> {destroy .top.t}
    .top.t tag add mytag 1.5 8000.8    ; # shall not crash
    update
    set res "Still doing fine!"
} -cleanup {
    destroy .top.t .top
} -result {Still doing fine!}

test text-12.1 {TextWidgetCmd procedure, "index" option} -setup {
    text .t
} -body {
    .t index
} -cleanup {
    destroy .t
................................................................................
    pack .t
    set ::retval {}
} -body {
    bind .t <<Modified>> "lappend ::retval modified"
# Shouldn't require [update idle] to trigger event [Bug 1809538]
    lappend ::retval [.t edit modified]
    .t edit modified 1
    update
    lappend ::retval [.t edit modified]
    .t edit modified 1 ; # binding should only fire once [Bug 1799782]
    update idletasks
    lappend ::retval [.t edit modified]
} -cleanup {
    destroy .t
} -result {0 modified 1 1}
................................................................................
test text-27.12 {<<Modified>> virtual event} -body {
    set ::retval unmodified
    text .t -undo 1
    pack .t
    bind .t <<Modified>> "set ::retval modified"
    update idletasks
    .t insert end "nothing special\n"
    update
    return $::retval
} -cleanup {
    destroy .t
} -result {modified}
test text-27.13 {<<Modified>> virtual event - insert before Modified} -body {
    set ::retval {}
    pack [text .t -undo 1]
    bind .t <<Modified>> { set ::retval [.t get 1.0 end-1c] }
    update idletasks
    .t insert end "nothing special"
    update
    return $::retval
} -cleanup {
    destroy .t
} -result {nothing special}
test text-27.14 {<<Modified>> virtual event - delete before Modified} -body {
# Bug 1737288, make sure we delete chars before triggering <<Modified>>
    set ::retval {}
    pack [text .t -undo 1]
    bind .t <<Modified>> { set ::retval [.t get 1.0 end-1c] }
    .t insert end "nothing special"
    .t edit modified 0
    .t delete 1.0 1.2
    update
    set ::retval
} -cleanup {
    destroy .t
} -result {thing special}
test text-27.14a {<<Modified>> virtual event - propagation to peers} -body {
# Bug [fd3a4dc111], <<Modified>> event is not always sent to peers
    set ::retval 0
    text .t -undo 1
    .t peer create .tt
    pack .t .tt
    bind .t <<Modified>> {incr ::retval}
    bind .tt <<Modified>> {incr ::retval}
    .t insert end "This increments ::retval once for each peer, i.e. twice."
    .t edit modified 0  ; # shall increment twice as well, not just once
    update
    set ::retval
} -cleanup {
    destroy .t .tt
} -result {4}
test text-27.15 {<<Selection>> virtual event} -body {
    set ::retval no_selection
    pack [text .t -undo 1]
    bind .t <<Selection>> "set ::retval selection_changed"
    update idletasks
    .t insert end "nothing special\n"
    .t tag add sel 1.0 1.1
    update
    set ::retval
} -cleanup {
    destroy .t
} -result {selection_changed}
test text-27.16 {-maxundo configuration option} -body {
    text .t -undo 1  -autoseparators 1 -maxundo 2
    pack .t

Changes to win/tkWinDialog.c.

3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
....
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
....
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
	if (IsWindow(hwndCtrl)) {
	    EnableWindow(hwndCtrl, FALSE);
	}
	hwndCtrl = GetDlgItem(hwndDlg, 0x473);
	if (IsWindow(hwndCtrl)) {
	    EnableWindow(hwndCtrl, FALSE);
	}
	TkSendVirtualEvent(phd->parent, "TkFontchooserVisibility");
	return 1; /* we handled the message */
    }

    if (WM_DESTROY == msg) {
	phd->hwnd = NULL;
	TkSendVirtualEvent(phd->parent, "TkFontchooserVisibility");
	return 0;
    }

    /*
     * Handle apply button by calling the provided command script as a
     * background evaluation (ie: errors dont come back here).
     */
................................................................................
	HDC hdc = GetDC(hwndDlg);

	SendMessage(hwndDlg, WM_CHOOSEFONT_GETLOGFONT, 0, (LPARAM) &lf);
	if (phd && phd->cmdObj) {
	    ApplyLogfont(phd->interp, phd->cmdObj, hdc, &lf);
	}
	if (phd && phd->parent) {
	    TkSendVirtualEvent(phd->parent, "TkFontchooserFontChanged");
	}
	return 1;
    }
    return 0; /* pass on for default processing */
}
 
/*
................................................................................
    if (TCL_OK == r) {
	oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
	if (ChooseFont(&cf)) {
	    if (hdPtr->cmdObj) {
		ApplyLogfont(hdPtr->interp, hdPtr->cmdObj, hdc, &lf);
	    }
	    if (hdPtr->parent) {
		TkSendVirtualEvent(hdPtr->parent, "TkFontchooserFontChanged");
	    }
	}
	Tcl_SetServiceMode(oldMode);
	EnableWindow(cf.hwndOwner, 1);
    }

    ReleaseDC(cf.hwndOwner, hdc);






|





|







 







|







 







|







3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
....
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
....
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
	if (IsWindow(hwndCtrl)) {
	    EnableWindow(hwndCtrl, FALSE);
	}
	hwndCtrl = GetDlgItem(hwndDlg, 0x473);
	if (IsWindow(hwndCtrl)) {
	    EnableWindow(hwndCtrl, FALSE);
	}
	TkSendVirtualEvent(phd->parent, "TkFontchooserVisibility", NULL);
	return 1; /* we handled the message */
    }

    if (WM_DESTROY == msg) {
	phd->hwnd = NULL;
	TkSendVirtualEvent(phd->parent, "TkFontchooserVisibility", NULL);
	return 0;
    }

    /*
     * Handle apply button by calling the provided command script as a
     * background evaluation (ie: errors dont come back here).
     */
................................................................................
	HDC hdc = GetDC(hwndDlg);

	SendMessage(hwndDlg, WM_CHOOSEFONT_GETLOGFONT, 0, (LPARAM) &lf);
	if (phd && phd->cmdObj) {
	    ApplyLogfont(phd->interp, phd->cmdObj, hdc, &lf);
	}
	if (phd && phd->parent) {
	    TkSendVirtualEvent(phd->parent, "TkFontchooserFontChanged", NULL);
	}
	return 1;
    }
    return 0; /* pass on for default processing */
}
 
/*
................................................................................
    if (TCL_OK == r) {
	oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
	if (ChooseFont(&cf)) {
	    if (hdPtr->cmdObj) {
		ApplyLogfont(hdPtr->interp, hdPtr->cmdObj, hdc, &lf);
	    }
	    if (hdPtr->parent) {
		TkSendVirtualEvent(hdPtr->parent, "TkFontchooserFontChanged", NULL);
	    }
	}
	Tcl_SetServiceMode(oldMode);
	EnableWindow(cf.hwndOwner, 1);
    }

    ReleaseDC(cf.hwndOwner, hdc);