Tk Source Code

Changes On Branch bug-22349fc78a-v2
Login

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

Changes In Branch bug-22349fc78a-v2 Excluding Merge-Ins

This is equivalent to a diff from 087440d5 to 83d82f00

2024-06-10
15:37
New branch: merges the crossing events fix (sans processevents) with cgimage drawing check-in: 44bca138 user: culler tags: cgimage_with_crossing
2024-06-09
20:29
Add parenthesis that was missing from previous commit. Closed-Leaf check-in: 83d82f00 user: fvogel tags: bug-22349fc78a-v2
20:25
TCL_UNUSED() parameter in SendEnterLeaveForDestroy() on Linux. check-in: 5e31837f user: fvogel tags: bug-22349fc78a-v2
2024-06-02
07:15
Fix [0fb337ea84]: ttk::combobox selection overruns downarrow element. Thanks to Emiliano Gavilan. check-in: ceab69ad user: fvogel tags: core-8-6-branch
2024-06-01
13:45
Merge core-8-6-branch Leaf check-in: 2f300f95 user: culler tags: chavez_cgimage_drawing
2024-05-31
17:11
merge core-8-6-branch Closed-Leaf check-in: 71089d07 user: fvogel tags: bug-22349fc78a
17:11
merge core-8-6-branch check-in: 1a015bb6 user: fvogel tags: bug-22349fc78a-v2
2024-05-29
20:11
Merge 8.6 check-in: c97bea36 user: jan.nijtmans tags: core-8-branch
19:56
Fix [0fb337ea84]: ttk::combobox selection overruns downarrow element. Thanks to Emiliano Gavilan. Closed-Leaf check-in: 0a36b34b user: fvogel tags: bug-0fb337ea84
18:49
merge core-8-6-branch check-in: 03fd50a4 user: fvogel tags: less_tests_constraints
18:46
Merge core-8-6-branch. check-in: 7dc8ff8b user: fvogel tags: trunk, main
18:45
Fix [8162e9b7a9]: Fonts are always scaled with UI when creating new instances. Many thanks to Csaba Nemethi! check-in: 087440d5 user: fvogel tags: core-8-6-branch
2024-05-28
21:22
Request font with pixel size 13 instead of 11, so that font-44.1 passes without Xft under xvfb too. Closed-Leaf check-in: a5ac9aad user: fvogel tags: bug-8162e9b7a9
2024-05-24
16:53
Make compilable with strict C99 compiler (missing declaration for XUnionRegion()) check-in: f2f2900e user: jan.nijtmans tags: core-8-6-branch

Changes to .github/workflows/linux-build.yml.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
name: Linux
on:
  push:
    branches:
    - "main"
    - "core-8-branch"
    - "core-8-6-branch"

    tags:
    - "core-**"
permissions:
  contents: read
defaults:
  run:
    shell: bash







>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
name: Linux
on:
  push:
    branches:
    - "main"
    - "core-8-branch"
    - "core-8-6-branch"
    - "bug-22349fc78a-v2"
    tags:
    - "core-**"
permissions:
  contents: read
defaults:
  run:
    shell: bash
Changes to .github/workflows/mac-build.yml.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
name: macOS
on:
  push:
    branches:
    - "main"
    - "core-8-branch"
    - "core-8-6-branch"

    tags:
    - "core-**"
permissions:
  contents: read
env:
  ERROR_ON_FAILURES: 1
jobs:







>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
name: macOS
on:
  push:
    branches:
    - "main"
    - "core-8-branch"
    - "core-8-6-branch"
    - "bug-22349fc78a-v2"
    tags:
    - "core-**"
permissions:
  contents: read
env:
  ERROR_ON_FAILURES: 1
jobs:
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
          if [ $nmatches -lt 4 ]
          then
            echo "::error::Failure during Test"
            exit 1
          fi
        timeout-minutes: 30
  clang:
    runs-on: macos-11
    strategy:
      matrix:
        symbols:
          - 'no'
          - 'mem'
        options:
          - '--enable-aqua'







|







54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
          if [ $nmatches -lt 4 ]
          then
            echo "::error::Failure during Test"
            exit 1
          fi
        timeout-minutes: 30
  clang:
    runs-on: macos-12
    strategy:
      matrix:
        symbols:
          - 'no'
          - 'mem'
        options:
          - '--enable-aqua'
Changes to .github/workflows/win-build.yml.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
name: Windows
on:
  push:
    branches:
    - "main"
    - "core-8-branch"
    - "core-8-6-branch"

    tags:
    - "core-**"
permissions:
  contents: read
env:
  ERROR_ON_FAILURES: 1
jobs:







>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
name: Windows
on:
  push:
    branches:
    - "main"
    - "core-8-branch"
    - "core-8-6-branch"
    - "bug-22349fc78a-v2"
    tags:
    - "core-**"
permissions:
  contents: read
env:
  ERROR_ON_FAILURES: 1
jobs:
Changes to generic/tkTest.c.
142
143
144
145
146
147
148



149
150
151
152
153
154
155

/*
 * Forward declarations for functions defined later in this file:
 */

static int		ImageObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,



			    Tcl_Obj * const objv[]);
static int		TestbitmapObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj * const objv[]);
static int		TestborderObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj * const objv[]);







>
>
>







142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

/*
 * Forward declarations for functions defined later in this file:
 */

static int		ImageObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj * const objv[]);
static int		TestProcessEventsObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj * const objv[]);
static int		TestbitmapObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj * const objv[]);
static int		TestborderObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj * const objv[]);
243
244
245
246
247
248
249

250
251
252
253
254
255
256
     * Create additional commands for testing Tk.
     */

    if (Tcl_PkgProvideEx(interp, "Tktest", TK_PATCH_LEVEL, NULL) == TCL_ERROR) {
	return TCL_ERROR;
    }


    Tcl_CreateObjCommand(interp, "square", SquareObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testbitmap", TestbitmapObjCmd,
	    (ClientData) Tk_MainWindow(interp), NULL);
    Tcl_CreateObjCommand(interp, "testborder", TestborderObjCmd,
	    (ClientData) Tk_MainWindow(interp), NULL);
    Tcl_CreateObjCommand(interp, "testcolor", TestcolorObjCmd,
	    (ClientData) Tk_MainWindow(interp), NULL);







>







246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
     * Create additional commands for testing Tk.
     */

    if (Tcl_PkgProvideEx(interp, "Tktest", TK_PATCH_LEVEL, NULL) == TCL_ERROR) {
	return TCL_ERROR;
    }

    Tcl_CreateObjCommand(interp, "testprocessevents", TestProcessEventsObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "square", SquareObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testbitmap", TestbitmapObjCmd,
	    (ClientData) Tk_MainWindow(interp), NULL);
    Tcl_CreateObjCommand(interp, "testborder", TestborderObjCmd,
	    (ClientData) Tk_MainWindow(interp), NULL);
    Tcl_CreateObjCommand(interp, "testcolor", TestcolorObjCmd,
	    (ClientData) Tk_MainWindow(interp), NULL);
1674
1675
1676
1677
1678
1679
1680








































































1681
1682
1683
1684
1685
1686
1687
	    TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);

    Tcl_DeleteCommand(timPtr->interp, timPtr->imageName);
    ckfree(timPtr->imageName);
    ckfree(timPtr->varName);
    ckfree(timPtr);
}









































































/*
 *----------------------------------------------------------------------
 *
 * TestmakeexistObjCmd --
 *
 *	This function implements the "testmakeexist" command. It calls







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







1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
	    TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);

    Tcl_DeleteCommand(timPtr->interp, timPtr->imageName);
    ckfree(timPtr->imageName);
    ckfree(timPtr->varName);
    ckfree(timPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TestProcessEventsObjCmd --
 *
 *      This function implements the "testprocessevents" command which processes
 *      all queued events of a type specified by one of the arguments to the
 *      command.  Currently the supported arguments are leave, enter, motion,
 *      and expose.  Others could be added if needed.
 *
 * Results:
 *      A standard Tcl result.
 *
 * Side effects:
 *      Events are processed
 *
 *----------------------------------------------------------------------
 */

static Tk_RestrictAction
CrossingRestrictProc(
    ClientData arg,
    XEvent *eventPtr)
{
    int *eventTypes = (int *) arg;
    for (int *t = eventTypes; *t != 0; t++) {
	if (eventPtr->type == *t) {
	    return TK_PROCESS_EVENT;
	}
    }
    return TK_DEFER_EVENT;	
}

static int TestProcessEventsObjCmd(
    TCL_UNUSED(ClientData),	/* Main window for application. */
    Tcl_Interp* interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj* const objv[])	/* Argument objects. */
{
    ClientData oldArg;
    Tk_RestrictProc *oldProc;
    int index;
    static const char *const eventTypeNames[] = {
	"leave", "enter", "motion", "expose", NULL};
    static const int eventTypes[] = {
	LeaveNotify, EnterNotify, MotionNotify, Expose};
#define NUM_TYPES (sizeof(eventTypes)/sizeof(int))
    int whichEvents[1 + NUM_TYPES];
    if (objc < 2) {
        Tcl_WrongNumArgs(interp, 1, objv, "eventtype ?eventtype ...?");
        return TCL_ERROR;
    }
    if (objc > NUM_TYPES + 1) {
        Tcl_WrongNumArgs(interp, 1, objv, "too many event types");
        return TCL_ERROR;
    }
#undef NUM_TYPES
    for (int n = 1; n < objc; n++) {
	if (Tcl_GetIndexFromObj(interp, objv[n], eventTypeNames, "eventtype", 0,
				&index) != TCL_OK) {
	    return TCL_ERROR;
	}
	whichEvents[n - 1] = eventTypes[index];
    }
    whichEvents[objc - 1] = 0;
    oldProc = Tk_RestrictEvents(CrossingRestrictProc, (void *) whichEvents,
				&oldArg);
    while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT)) {};
    Tk_RestrictEvents(oldProc, oldArg, &oldArg);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestmakeexistObjCmd --
 *
 *	This function implements the "testmakeexist" command. It calls
Changes to generic/tkWindow.c.
211
212
213
214
215
216
217











218
219
220
221
222
223
224
static void		DeleteWindowsExitProc(ClientData clientData);
static TkDisplay *	GetScreen(Tcl_Interp *interp, const char *screenName,
			    int *screenPtr);
static int		Initialize(Tcl_Interp *interp);
static int		NameWindow(Tcl_Interp *interp, TkWindow *winPtr,
			    TkWindow *parentPtr, const char *name);
static void		UnlinkWindow(TkWindow *winPtr);












/*
 *----------------------------------------------------------------------
 *
 * TkCloseDisplay --
 *
 *	Closing the display can lead to order of deletion problems. We defer







>
>
>
>
>
>
>
>
>
>
>







211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
static void		DeleteWindowsExitProc(ClientData clientData);
static TkDisplay *	GetScreen(Tcl_Interp *interp, const char *screenName,
			    int *screenPtr);
static int		Initialize(Tcl_Interp *interp);
static int		NameWindow(Tcl_Interp *interp, TkWindow *winPtr,
			    TkWindow *parentPtr, const char *name);
static void		UnlinkWindow(TkWindow *winPtr);

/*
 * This static variable only makes sense for macOS and Windows, which never
 * have more than one display.  It is set by TkCloseDisplay, and when set
 * prevents sending Enter and Leave events when all of the windows in the
 * display are being destroyed.  Tk does not send those events on X11; that
 * job is handled by the X server.
 */

static int displayBeingClosed = 0;


/*
 *----------------------------------------------------------------------
 *
 * TkCloseDisplay --
 *
 *	Closing the display can lead to order of deletion problems. We defer
235
236
237
238
239
240
241

242
243
244
245
246
247
248
 *----------------------------------------------------------------------
 */

static void
TkCloseDisplay(
    TkDisplay *dispPtr)
{

    TkClipCleanup(dispPtr);

    TkpCancelWarp(dispPtr);

    if (dispPtr->name != NULL) {
	ckfree(dispPtr->name);
    }







>







246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
 *----------------------------------------------------------------------
 */

static void
TkCloseDisplay(
    TkDisplay *dispPtr)
{
    displayBeingClosed = 1;
    TkClipCleanup(dispPtr);

    TkpCancelWarp(dispPtr);

    if (dispPtr->name != NULL) {
	ckfree(dispPtr->name);
    }
1318
1319
1320
1321
1322
1323
1324

































1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343




1344
1345
1346
1347
1348
1349
1350
 * Side effects:
 *	The window is deleted, along with all of its children. Relevant
 *	callback functions are invoked.
 *
 *--------------------------------------------------------------
 */


































void
Tk_DestroyWindow(
    Tk_Window tkwin)		/* Window to destroy. */
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    TkDisplay *dispPtr = winPtr->dispPtr;
    XEvent event;
    TkHalfdeadWindow *halfdeadPtr, *prev_halfdeadPtr;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (winPtr->flags & TK_ALREADY_DEAD) {
	/*
	 * A destroy event binding caused the window to be destroyed again.
	 * Ignore the request.
	 */

	return;
    }




    winPtr->flags |= TK_ALREADY_DEAD;

    /*
     * Unless we are cleaning up a half dead window from
     * DeleteWindowsExitProc, add this window to the half dead list.
     */








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



















>
>
>
>







1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
 * Side effects:
 *	The window is deleted, along with all of its children. Relevant
 *	callback functions are invoked.
 *
 *--------------------------------------------------------------
 */

#if defined(MAC_OSX_TK) || defined(_WIN32)
static void SendEnterLeaveForDestroy(
    Tk_Window tkwin)
{
    int x, y;
    unsigned int state;
    Tk_Window pointerWin;
    TkWindow *containerPtr;

    if (displayBeingClosed) {
	return;
    }
    XQueryPointer(Tk_Display(tkwin), None, NULL, NULL, &x, &y,
		  NULL, NULL, &state);
    pointerWin = Tk_CoordsToWindow(x, y, tkwin);
    if (pointerWin == tkwin) {
	if (!Tk_IsTopLevel(tkwin)) {
	    containerPtr = TkGetContainer((TkWindow *)pointerWin);
	    Tk_UpdatePointer((Tk_Window) containerPtr, x, y, state);
	}
    }
    
    if (pointerWin && (tkwin == Tk_Parent(pointerWin))) {
	Tk_UpdatePointer(Tk_Parent(tkwin), x, y, state);
    }
}
#else
static void SendEnterLeaveForDestroy(
    TCL_UNUSED(Tk_Window))
{
}
#endif

void
Tk_DestroyWindow(
    Tk_Window tkwin)		/* Window to destroy. */
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    TkDisplay *dispPtr = winPtr->dispPtr;
    XEvent event;
    TkHalfdeadWindow *halfdeadPtr, *prev_halfdeadPtr;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (winPtr->flags & TK_ALREADY_DEAD) {
	/*
	 * A destroy event binding caused the window to be destroyed again.
	 * Ignore the request.
	 */

	return;
    }
    if ((winPtr->flags & TK_DONT_DESTROY_WINDOW) == 0) {
	SendEnterLeaveForDestroy(tkwin);
    }
    
    winPtr->flags |= TK_ALREADY_DEAD;

    /*
     * Unless we are cleaning up a half dead window from
     * DeleteWindowsExitProc, add this window to the half dead list.
     */

1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
	Tcl_Panic("window not found on half dead list");
    }

    /*
     * Cleanup the data structures associated with this window.
     */

    if (winPtr->flags & TK_WIN_MANAGED) {
	TkWmDeadWindow(winPtr);
    } else if (winPtr->flags & TK_WM_COLORMAP_WINDOW) {
	TkWmRemoveFromColormapWindows(winPtr);
    }
    if (winPtr->window != None) {
#if defined(MAC_OSX_TK) || defined(_WIN32)
	XDestroyWindow(winPtr->display, winPtr->window);







|







1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
	Tcl_Panic("window not found on half dead list");
    }

    /*
     * Cleanup the data structures associated with this window.
     */

    if (winPtr->wmInfoPtr && (winPtr->flags & TK_WIN_MANAGED)) {
	TkWmDeadWindow(winPtr);
    } else if (winPtr->flags & TK_WM_COLORMAP_WINDOW) {
	TkWmRemoveFromColormapWindows(winPtr);
    }
    if (winPtr->window != None) {
#if defined(MAC_OSX_TK) || defined(_WIN32)
	XDestroyWindow(winPtr->display, winPtr->window);
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
				 * then tkwin goes above or below all windows
				 * in the same parent. */
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *otherPtr = (TkWindow *) other;

    /*
     * Special case: if winPtr is a top-level window then just find the
     * top-level ancestor of otherPtr and restack winPtr above otherPtr
     * without changing any of Tk's childLists.
     */

    if (winPtr->flags & TK_WIN_MANAGED) {
	while ((otherPtr != NULL) && !(otherPtr->flags & TK_TOP_HIERARCHY)) {
	    otherPtr = otherPtr->parentPtr;







|







2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
				 * then tkwin goes above or below all windows
				 * in the same parent. */
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *otherPtr = (TkWindow *) other;

    /*
     * Special case: if winPtr is a toplevel window then just find the
     * top-level ancestor of otherPtr and restack winPtr above otherPtr
     * without changing any of Tk's childLists.
     */

    if (winPtr->flags & TK_WIN_MANAGED) {
	while ((otherPtr != NULL) && !(otherPtr->flags & TK_TOP_HIERARCHY)) {
	    otherPtr = otherPtr->parentPtr;
Changes to macosx/tkMacOSXInit.c.
419
420
421
422
423
424
425












426
427
428
429
430
431
432
    void *clientdata)
{
    Bool doCleanup = doCleanupFromExit;
    if (doCleanupFromExit) {
	doCleanupFromExit = NO; /* prevent possible recursive call. */
	closePanels();
    }













    /*
     * Tcl_Exit does not call Tcl_Finalize if there is an exit proc installed.
     */

    Tcl_Finalize();
    if (doCleanup == YES) {







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







419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
    void *clientdata)
{
    Bool doCleanup = doCleanupFromExit;
    if (doCleanupFromExit) {
	doCleanupFromExit = NO; /* prevent possible recursive call. */
	closePanels();
    }

    /*
     * At this point it is too late to be looking up the Tk window associated
     * to any NSWindows, but it can happen.  This makes sure the answer is None
     * if such a query is attempted. 
     */
    
    for (TKWindow *w in [NSApp orderedWindows]) {
	if ([w respondsToSelector: @selector (tkWindow)]) {
	    [w setTkWindow: None];
	}
    }

    /*
     * Tcl_Exit does not call Tcl_Finalize if there is an exit proc installed.
     */

    Tcl_Finalize();
    if (doCleanup == YES) {
Changes to macosx/tkMacOSXMouseEvent.c.
496
497
498
499
500
501
502

503
504
505
506
507
508
509
510
511
	     * we make sure that the button state appears the way that Tk
	     * expects.
	     */

	    state |= TkGetButtonMask(Button1);
	}
	if (eventType == NSMouseEntered) {

	    Tk_UpdatePointer((Tk_Window) [NSApp tkPointerWindow],
				 global.x, global.y, state);
	} else if (eventType == NSMouseExited) {
	    if ([NSApp tkDragTarget]) {
	    	Tk_UpdatePointer((Tk_Window) [NSApp tkDragTarget],
	    			 global.x, global.y, state);
	    } else {
	    Tk_UpdatePointer(NULL, global.x, global.y, state);
	    }







>
|
|







496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
	     * we make sure that the button state appears the way that Tk
	     * expects.
	     */

	    state |= TkGetButtonMask(Button1);
	}
	if (eventType == NSMouseEntered) {
	    Tk_Window new_win = Tk_CoordsToWindow(global.x, global.y,
		 (Tk_Window) [NSApp tkPointerWindow]);
	    Tk_UpdatePointer(new_win, global.x, global.y, state);
	} else if (eventType == NSMouseExited) {
	    if ([NSApp tkDragTarget]) {
	    	Tk_UpdatePointer((Tk_Window) [NSApp tkDragTarget],
	    			 global.x, global.y, state);
	    } else {
	    Tk_UpdatePointer(NULL, global.x, global.y, state);
	    }
Changes to macosx/tkMacOSXSubwindows.c.
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
    MacDrawable *macWin = (MacDrawable *)window;

    /*
     * Remove any dangling pointers that may exist if the window we are
     * deleting is being tracked by the grab code.
     */

    TkPointerDeadWindow(macWin->winPtr);
    TkMacOSXSelDeadWindow(macWin->winPtr);
    macWin->toplevel->referenceCount--;

    if (!Tk_IsTopLevel(macWin->winPtr)) {
	TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
	if (macWin->winPtr->parentPtr != NULL) {
	    TkMacOSXInvalClipRgns((Tk_Window)macWin->winPtr->parentPtr);
	}







|
|







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
    MacDrawable *macWin = (MacDrawable *)window;

    /*
     * Remove any dangling pointers that may exist if the window we are
     * deleting is being tracked by the grab code.
     */

    TkMacOSXSelDeadWindow(macWin->winPtr);
    TkPointerDeadWindow(macWin->winPtr);
    macWin->toplevel->referenceCount--;

    if (!Tk_IsTopLevel(macWin->winPtr)) {
	TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
	if (macWin->winPtr->parentPtr != NULL) {
	    TkMacOSXInvalClipRgns((Tk_Window)macWin->winPtr->parentPtr);
	}
Changes to macosx/tkMacOSXWindowEvent.c.
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266

- (void) windowMapped: (NSNotification *) notification
{
    NSWindow *w = [notification object];
    TkWindow *winPtr = TkMacOSXGetTkWindow(w);

    if (winPtr) {
	while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}
    }
}

- (void) windowLiveResize: (NSNotification *) notification
{
    NSString *name = [notification name];
    if ([name isEqualToString:NSWindowWillStartLiveResizeNotification]) {







|







252
253
254
255
256
257
258
259
260
261
262
263
264
265
266

- (void) windowMapped: (NSNotification *) notification
{
    NSWindow *w = [notification object];
    TkWindow *winPtr = TkMacOSXGetTkWindow(w);

    if (winPtr) {
   	while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}
    }
}

- (void) windowLiveResize: (NSNotification *) notification
{
    NSString *name = [notification name];
    if ([name isEqualToString:NSWindowWillStartLiveResizeNotification]) {
280
281
282
283
284
285
286

287
288
289

290
291
292
293
294
295
296

- (void) windowUnmapped: (NSNotification *) notification
{
    TKLog(@"-[%@(%p) %s] %@", [self class], self, sel_getName(_cmd), notification);
    NSWindow *w = [notification object];
    TkWindow *winPtr = TkMacOSXGetTkWindow(w);


    if (winPtr) {
	//Tk_UnmapWindow((Tk_Window)winPtr);
    }

}

#endif /* TK_MAC_DEBUG_NOTIFICATIONS */

- (void) _setupWindowNotifications
{
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];







>

|

>







280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298

- (void) windowUnmapped: (NSNotification *) notification
{
    TKLog(@"-[%@(%p) %s] %@", [self class], self, sel_getName(_cmd), notification);
    NSWindow *w = [notification object];
    TkWindow *winPtr = TkMacOSXGetTkWindow(w);

#if 0
    if (winPtr) {
        Tk_UnmapWindow((Tk_Window)winPtr);
    }
#endif
}

#endif /* TK_MAC_DEBUG_NOTIFICATIONS */

- (void) _setupWindowNotifications
{
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
Changes to macosx/tkMacOSXWm.c.
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641





642
643
644
645
646
647
648
649
650
    NSPoint p = NSMakePoint(x, TkMacOSXZeroScreenHeight() - y);
    NSArray *windows = [NSApp orderedWindows];
    TkWindow *winPtr = NULL;

    for (NSWindow *w in windows) {
	winPtr = TkMacOSXGetTkWindow(w);
	if (winPtr) {
	    WmInfo *wmPtr = winPtr->wmInfoPtr;
	    NSRect windowFrame = [w frame];
	    NSRect contentFrame = [w frame];

	    contentFrame.size.height = [[w contentView] frame].size.height;
	    /*
	     * For consistency with other platforms, points in the
	     * title bar are not considered to be contained in the
	     * window.
	     */

	    if ((wmPtr->hints.initial_state == NormalState ||
		    wmPtr->hints.initial_state == ZoomState)) {
		if (NSMouseInRect(p, contentFrame, NO)) {
		    return winPtr;
		} else if (NSMouseInRect(p, windowFrame, NO)) {





		    return NULL;
		}
	    }
	}
    }
    return NULL;
}

/*







<










<
<
|
|
|
>
>
>
>
>
|
<







619
620
621
622
623
624
625

626
627
628
629
630
631
632
633
634
635


636
637
638
639
640
641
642
643
644

645
646
647
648
649
650
651
    NSPoint p = NSMakePoint(x, TkMacOSXZeroScreenHeight() - y);
    NSArray *windows = [NSApp orderedWindows];
    TkWindow *winPtr = NULL;

    for (NSWindow *w in windows) {
	winPtr = TkMacOSXGetTkWindow(w);
	if (winPtr) {

	    NSRect windowFrame = [w frame];
	    NSRect contentFrame = [w frame];

	    contentFrame.size.height = [[w contentView] frame].size.height;
	    /*
	     * For consistency with other platforms, points in the
	     * title bar are not considered to be contained in the
	     * window.
	     */



	    if (NSMouseInRect(p, contentFrame, NO)) {
		return winPtr;
	    } else if (NSMouseInRect(p, windowFrame, NO)) {
		/*
		 * The pointer is in the title bar of the highest NSWindow
		 * containing it, and therefore is should not be considered
		 * to be contained in any Tk window.
		 */
		return NULL;

	    }
	}
    }
    return NULL;
}

/*
893
894
895
896
897
898
899


900
901
902
903
904
905

906
907
908
909
910
911
912
913

914
915
916
917
918
919
920
921
922
923
924
925
926
927
/*
 *----------------------------------------------------------------------
 *
 * TkWmDeadWindow --
 *
 *	This procedure is invoked when a top-level window is about to be
 *	deleted. It cleans up the wm-related data structures for the window.


 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The WmInfo structure for winPtr gets freed up.

 *
 *----------------------------------------------------------------------
 */

void
TkWmDeadWindow(
    TkWindow *winPtr)		/* Top-level window that's being deleted. */
{

    WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2;
    TKWindow *deadNSWindow;

    if (wmPtr == NULL) {
	return;
    }

    /*
     *If the dead window is a transient, remove it from the container's list.
     */

    RemoveTransient(winPtr);
    Tk_ManageGeometry((Tk_Window)winPtr, NULL, NULL);
    Tk_DeleteEventHandler((Tk_Window)winPtr, StructureNotifyMask,







>
>





|
>








>

|
|
|


<







894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924

925
926
927
928
929
930
931
/*
 *----------------------------------------------------------------------
 *
 * TkWmDeadWindow --
 *
 *	This procedure is invoked when a top-level window is about to be
 *	deleted. It cleans up the wm-related data structures for the window.
 *      If the dead window contains the pointer, TkUpdatePointer is called
 *      to tell Tk which window will be the new pointer window. 
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The WmInfo structure for winPtr gets freed.  Tk's cached pointer
 *      window may change.
 *
 *----------------------------------------------------------------------
 */

void
TkWmDeadWindow(
    TkWindow *winPtr)		/* Top-level window that's being deleted. */
{
    TkWindow *winPtr2;
    WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2;
    TKWindow *deadNSWindow = (TKWindow *)TkMacOSXGetNSWindowForDrawable(
	Tk_WindowId(winPtr));
    if (deadNSWindow == NULL) {
	return;
    }

    /*
     *If the dead window is a transient, remove it from the container's list.
     */

    RemoveTransient(winPtr);
    Tk_ManageGeometry((Tk_Window)winPtr, NULL, NULL);
    Tk_DeleteEventHandler((Tk_Window)winPtr, StructureNotifyMask,
981
982
983
984
985
986
987
988
989
990
991
992

993
994
995
996
997
998


999
1000
1001
1002




1003
1004
1005
1006
1007
1008
1009
1010




















1011
1012
1013
1014
1015
1016
1017
    while (wmPtr->transientPtr != NULL) {
	Transient *transientPtr = wmPtr->transientPtr;

	wmPtr->transientPtr = transientPtr->nextPtr;
	ckfree(transientPtr);
    }

    deadNSWindow = (TKWindow *)wmPtr->window;

    /*
     * Remove references to the Tk window from the mouse event processing
     * state which is recorded in the NSApplication object.

     */

    if (winPtr == [NSApp tkPointerWindow]) {
	NSWindow *w;
	NSPoint mouse = [NSEvent mouseLocation];
	[NSApp setTkPointerWindow:nil];


	for (w in [NSApp orderedWindows]) {
	    if (w == deadNSWindow) {
		continue;
	    }




	    if (NSPointInRect(mouse, [w frame])) {
		TkWindow *winPtr2 = TkMacOSXGetTkWindow(w);
		int x = mouse.x, y = TkMacOSXZeroScreenHeight() - mouse.y;
		[NSApp setTkPointerWindow:winPtr2];
		Tk_UpdatePointer((Tk_Window) winPtr2, x, y,
				 [NSApp tkButtonState]);
		break;
	    }




















	}
    }

    /*
     * Unregister the NSWindow and remove all references to it from the Tk
     * data structures.  If the NSWindow is a child, disassociate it from
     * the parent.  Then close and release the NSWindow.







<
<


|
>


|
|
<
|
>
>
|
|
|
|
>
>
>
>
|
<
<
|
<
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







985
986
987
988
989
990
991


992
993
994
995
996
997
998
999

1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011


1012


1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
    while (wmPtr->transientPtr != NULL) {
	Transient *transientPtr = wmPtr->transientPtr;

	wmPtr->transientPtr = transientPtr->nextPtr;
	ckfree(transientPtr);
    }



    /*
     * Remove references to the Tk window from the mouse event processing
     * state which is recorded in the NSApplication object and notify Tk
     * of the new pointer window.
     */

    NSPoint mouse = [NSEvent mouseLocation];
    NSWindow *w;

    [NSApp setTkPointerWindow:nil];
    winPtr2 = NULL;
    
    for (w in [NSApp orderedWindows]) {
	if (w == deadNSWindow || w == NULL) {
	    continue;
	}
	winPtr2 = TkMacOSXGetTkWindow(w);
	if (winPtr2 == NULL) {
	    continue;
	}
	if (NSPointInRect(mouse, [w frame])) {


	    [NSApp setTkPointerWindow: winPtr2];


	    break;
	}
    }
    if (winPtr2) {
	/*
	 * We now know which toplevel will contain the pointer when the window
	 * is destroyed.  We need to know which Tk window within the
	 * toplevel will contain the pointer.
	 */
	NSPoint local = [w tkConvertPointFromScreen: mouse];
	int top_x = floor(local.x),
	    top_y = floor(w.frame.size.height - local.y);
	int root_x = floor(mouse.x),
	    root_y = floor(TkMacOSXZeroScreenHeight() - mouse.y);
	int win_x, win_y;
	Tk_Window target = Tk_TopCoordsToWindow((Tk_Window) winPtr2, top_x, top_y, &win_x, &win_y);
	/*
	 * A non-toplevel window can have a NULL parent while it is in the process of
	 * being destroyed.  We should not call Tk_UpdatePointer in that case.
	 */
	if (Tk_Parent(target) != NULL || Tk_IsTopLevel(target)) {
	    Tk_UpdatePointer(target, root_x, root_y, [NSApp tkButtonState]);
	}
    }

    /*
     * Unregister the NSWindow and remove all references to it from the Tk
     * data structures.  If the NSWindow is a child, disassociate it from
     * the parent.  Then close and release the NSWindow.
1055
1056
1057
1058
1059
1060
1061

1062
1063
1064
1065
1066
1067
1068
1069
1070
1071


	/*
	 * Fix bug 5692042764:
	 * set tkEventTarget to NULL when there is no window to send Tk events to.
	 */
	TkWindow *newTkEventTarget = NULL;


	for (NSWindow *w in [NSApp orderedWindows]) {
	    TkWindow *winPtr2 = TkMacOSXGetTkWindow(w);
	    BOOL isOnScreen;

	    if (!winPtr2 || !winPtr2->wmInfoPtr) {
		continue;
	    }
	    wmPtr2 = winPtr2->wmInfoPtr;
	    isOnScreen = (wmPtr2->hints.initial_state != IconicState &&







>


|







1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096


	/*
	 * Fix bug 5692042764:
	 * set tkEventTarget to NULL when there is no window to send Tk events to.
	 */
	TkWindow *newTkEventTarget = NULL;
	winPtr2 = NULL;

	for (NSWindow *w in [NSApp orderedWindows]) {
	    winPtr2 = TkMacOSXGetTkWindow(w);
	    BOOL isOnScreen;

	    if (!winPtr2 || !winPtr2->wmInfoPtr) {
		continue;
	    }
	    wmPtr2 = winPtr2->wmInfoPtr;
	    isOnScreen = (wmPtr2->hints.initial_state != IconicState &&
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
    	Tk_UnmapWindow(frameWin);

	macWin->toplevel->referenceCount--;
	macWin->toplevel = winPtr->parentPtr->privatePtr->toplevel;
	macWin->toplevel->referenceCount++;
	macWin->flags &= ~TK_HOST_EXISTS;

	TkWmDeadWindow(winPtr);
	RemapWindows(winPtr, (MacDrawable *)winPtr->parentPtr->window);

        /*
         * Make sure wm no longer manages this window
         */
        Tk_ManageGeometry(frameWin, NULL, NULL);








<







2040
2041
2042
2043
2044
2045
2046

2047
2048
2049
2050
2051
2052
2053
    	Tk_UnmapWindow(frameWin);

	macWin->toplevel->referenceCount--;
	macWin->toplevel = winPtr->parentPtr->privatePtr->toplevel;
	macWin->toplevel->referenceCount++;
	macWin->flags &= ~TK_HOST_EXISTS;


	RemapWindows(winPtr, (MacDrawable *)winPtr->parentPtr->window);

        /*
         * Make sure wm no longer manages this window
         */
        Tk_ManageGeometry(frameWin, NULL, NULL);

2894
2895
2896
2897
2898
2899
2900

2901
2902
2903
2904
2905
2906
2907
	winPtr->flags |=
		(TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED);
	TkMapTopFrame(frameWin);
	TkWmMapWindow(winPtr);
    } else if (Tk_IsTopLevel(frameWin)) {
	/* Already managed by wm - ignore it */
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * WmMaxsizeCmd --







>







2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
	winPtr->flags |=
		(TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED);
	TkMapTopFrame(frameWin);
	TkWmMapWindow(winPtr);
    } else if (Tk_IsTopLevel(frameWin)) {
	/* Already managed by wm - ignore it */
    }
    Tk_ManageGeometry((Tk_Window)winPtr, &wmMgrType, NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * WmMaxsizeCmd --
Changes to tests/event.test.
307
308
309
310
311
312
313

314
315
316
317
318
319
320
    $e get 1.0 1.end
} -cleanup {
    deleteWindows
} -result {MEL}
test event-2.6(keypress) {type into text widget, triple click,
    hit Delete key, and then type some more} -setup {
	deleteWindows

} -body {
    set t [toplevel .t]
    set e [text $t.e]
    pack $e
    tkwait visibility $e
    _keypress_string $e JUMP








>







307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
    $e get 1.0 1.end
} -cleanup {
    deleteWindows
} -result {MEL}
test event-2.6(keypress) {type into text widget, triple click,
    hit Delete key, and then type some more} -setup {
	deleteWindows
	update idletasks
} -body {
    set t [toplevel .t]
    set e [text $t.e]
    pack $e
    tkwait visibility $e
    _keypress_string $e JUMP

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


887
888

889
890
891
892

893


894


895






896


897
898
899
900



901

902


903
904
905


906

907














908
909

910
911





912







913




914








915









916




















917
918
919
920
921
922
923
924
925
926
927


928
929
930
931
932
                on which this test is run does NOT have a diaeresis \
                physical key - in this case, test is actually void."
    }
} -cleanup {
    deleteWindows
} -result {OK}











test event-9.1 {enter . window by destroying a toplevel - bug b1d115fa60} -setup {

    set EnterBind [bind . <Enter>]



































































} -body {





    wm geometry . 200x200+300+300






    wm deiconify .


    _pause 200




















    toplevel .top2 -width 200 -height 200
    wm geometry .top2 +[expr {[winfo rootx .]+50}]+[expr {[winfo rooty .]+50}]

    wm deiconify .top2






    raise .top2
    _pause 400

    event generate .top2 <Motion> -warp 1 -x 50 -y 50
    _pause 100
    bind . <Enter> {lappend res %W}


    set res [list ]



    destroy .top2


    _pause 200

















    set res
} -cleanup {





    deleteWindows


















    bind . <Enter> $EnterBind














} -result {.}
test event-9.2 {enter toplevel window by destroying a toplevel - bug b1d115fa60} -setup {


    set iconified false
    if {[winfo ismapped .]} {

        wm iconify .
        update
        set iconified true
    }

} -body {


    toplevel .top1


    wm geometry .top1 200x200+300+300






    wm deiconify .top1


    _pause 200
    toplevel .top2 -width 200 -height 200
    wm geometry .top2 +[expr {[winfo rootx .top1]+50}]+[expr {[winfo rooty .top1]+50}]
    _pause 200



    wm deiconify .top2

    raise .top2


    _pause 400
    event generate .top2 <Motion> -warp 1 -x 50 -y 50
    _pause 100


    bind .top1 <Enter> {lappend res %W}

    set res [list ]














    destroy .top2
    _pause 200

    set res
} -cleanup {





    deleteWindows ; # destroy all children of ".", this already includes .top1







    if {$iconified} {




        wm deiconify .








        update









    }




















} -result {.top1}

# cleanup
update
unset -nocomplain keypress_lookup
rename _init_keypress_lookup {}
rename _keypress_lookup {}
rename _keypress {}
rename _pause {}
rename _text_ind_to_x_y {}
rename _get_selection {}



cleanupTests
return









>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
|
>
>
>
>
>
>
|
|
>
|
|
<
>
>
|
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
|
|
>
|
|
<

>
|
>
>
|
>
>
|
>
>
>
>
>
>
|
>
>
|
<
<
|
>
>
>
|
>
|
>
>
|
<
<
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
|

>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|










>
>





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
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996

997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073

1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092


1093
1094
1095
1096
1097
1098
1099
1100
1101
1102


1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
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
1202
                on which this test is run does NOT have a diaeresis \
                physical key - in this case, test is actually void."
    }
} -cleanup {
    deleteWindows
} -result {OK}

proc waitForWindowEvent {w event {timeout 1000}} {
# This proc is intended to overcome latency of windowing system
# notifications when toplevel windows are involved. These latencies vary
# considerably with the window manager in use, with the system load,
# with configured scheduling priorities for processes, etc ...
# Waiting for the corresponding window events evades the trouble that is
# associated with the alternative: waiting or halting the Tk process for a
# fixed amount of time (using "after ms"). With the latter strategy it's
# always a gamble how much waiting time is enough on an end user's system.
# It also leads to long fixed waiting times in order to be on the safe side.

    variable _windowEvent

    # Use counter as a unique ID to prevent subsequent waits
    # from interfering with each other.
    set counter [incr _windowEvent(counter)]
    set _windowEvent($counter) 1
    set savedBinding [bind $w $event]
    bind $w $event [list +waitForWindowEvent.signal $counter]
    set afterID [after $timeout [list set _windowEvent($counter) -1]]
    vwait _windowEvent($counter)
    set late [expr {$_windowEvent($counter) == -1}]
    bind $w $event $savedBinding
    unset _windowEvent($counter)
    if {$late} {
	puts stderr "wait for $event event on $w timed out (> $timeout ms)"
    } else {
        after cancel $afterID
    }
}
proc waitForWindowEvent.signal {counter} {
# Helper proc that records the triggering of a window event.
    incr ::_windowEvent($counter)
}

proc create_and_pack_frames {{w {}}} {
    frame $w.f1 -bg blue -width 200 -height 200
    pack propagate $w.f1 0
    frame $w.f1.f2 -bg yellow -width 100 -height 100
    pack $w.f1.f2 $w.f1 -side bottom -anchor se
    update idletasks
}

proc setup_win_mousepointer {w} {
# Position the window and the mouse pointer as an initial state for some tests.
# The so-called "pointer window" is the $w window that will now contain the mouse pointer.
    wm geometry . +700+400; # root window out of our way - must not cover windows from event-9.1*
    toplevel $w
    pack propagate $w 0
    wm geometry $w 300x300+100+100
    tkwait visibility $w
    update; # service remaining screen drawing events (e.g. <Expose>)
    set pointerWin [winfo containing [winfo pointerx $w] [winfo pointery $w]]
    event generate $w <Motion> -warp 1 -x 250 -y 250
    if {($pointerWin ne $w) && ([tk windowingsystem] ne "aqua")} {
        waitForWindowEvent $w <Enter>
    } else {
        controlPointerWarpTiming
    }
}

test event-9.11 {pointer window container = parent} -setup {
    setup_win_mousepointer .one
    wm withdraw .one
    create_and_pack_frames .one
    wm deiconify .one
    tkwait visibility .one.f1.f2
    _pause 200; # needed for Windows
    update idletasks; # finish display of window
    set result "|"
} -body {
    bind all <Leave> {append result "<Leave> %d %W|"}
    bind all <Enter> {append result "<Enter> %d %W|"}
    destroy .one.f1.f2
    if {[tk windowingsystem] ne "x11"} {
        testprocessevents enter leave
    } else {
	update
    }
    set result
} -cleanup {
    bind all <Leave> {}
    bind all <Enter> {}
    destroy .one
    unset result
} -result {|<Enter> NotifyInferior .one.f1|}

test event-9.12 {pointer window container != parent} -setup {
    setup_win_mousepointer .one
    wm withdraw .one
    create_and_pack_frames .one
    pack propagate .one.f1.f2 0
    pack [frame .one.g -bg orange -width 80 -height 80] -anchor se -side bottom -in .one.f1.f2
    wm deiconify .one
    tkwait visibility .one.g
    event generate .one <Motion> -warp 1 -x 250 -y 250
    _pause 200; # needed for Windows
    set result "|"
} -body {
    bind all <Leave> {append result "<Leave> %d %W|"}
    bind all <Enter> {append result "<Enter> %d %W|"}
    destroy .one.g
    if {[tk windowingsystem] ne "x11"} {
        testprocessevents enter leave
    } else {
	update
    }
    set result
} -cleanup {
    bind all <Leave> {}
    bind all <Enter> {}
    destroy .one
    unset result
} -result {|<Enter> NotifyNonlinearVirtual .one.f1|<Enter> NotifyNonlinear .one.f1.f2|}

test event-9.13 {pointer window is a toplevel, toplevel destination} -setup {
    setup_win_mousepointer .one
    toplevel .two
    wm geometry .two 300x300+150+150
    wm withdraw .two
    wm deiconify .two
    waitForWindowEvent .two <Enter>
    update idletasks; # finish displaying windows
    set result |
} -body {
    bind all <Leave> {append result "<Leave> %d %W|"}
    bind all <Enter> {append result "<Enter> %d %W|"}
    destroy .two
    waitForWindowEvent .one <Enter>
    if {[tk windowingsystem] ne "x11"} {
        testprocessevents enter leave
    } else {

	update
    }
    set result
} -cleanup {
    bind all <Leave> {}
    bind all <Enter> {}
    destroy .one
    unset result
} -result {|<Enter> NotifyNonlinear .one|}

test event-9.14 {pointer window is a toplevel, tk internal destination} -setup {
    setup_win_mousepointer .one
    wm withdraw .one
    create_and_pack_frames .one
    toplevel .two
    wm geometry .two 300x300+150+150
    wm withdraw .two
    wm deiconify .one
    wm deiconify .two
    waitForWindowEvent .two <Enter>
    set result "|"
} -body {
    bind all <Leave> {append result "<Leave> %d %W|"}
    bind all <Enter> {append result "<Enter> %d %W|"}
    destroy .two
    waitForWindowEvent .one.f1.f2 <Enter>
    testprocessevents enter leave
    set result
} -cleanup {
    bind all <Leave> {}
    bind all <Enter> {}
    destroy .one
    unset result
} -result {|<Enter> NotifyNonlinearVirtual .one|<Enter> NotifyNonlinearVirtual .one.f1|<Enter> NotifyNonlinear .one.f1.f2|}

test event-9.15 {pointer window is a toplevel, destination is screen root} -setup {
    setup_win_mousepointer .one; # ensure the mouse pointer is where we want it to be (the .one toplevel is not itself used in this test)
#    destroy .one
    toplevel .two
    wm geometry .two 300x300+150+150
    wm deiconify .two
    waitForWindowEvent .two <Enter>
    update idletasks; # finish displaying .two
    event generate .two <Motion> -warp 1 -x 275 -y 275
    controlPointerWarpTiming
    set result "|"
} -body {
    bind all <Leave> {append result "<Leave> %d %W|"}
    bind all <Enter> {append result "<Enter> %d %W|"}
    destroy .two
    set result
} -cleanup {
    bind all <Leave> {}
    bind all <Enter> {}
    destroy .one
    unset result
} -result {|}

test event-9.16 {Successive destructions (pointer window + parent), single generation of crossing events} -setup {
    # Tests correctness of overwriting the dead window struct in
    # TkPointerDeadWindow() and subsequent reading in GenerateEnterLeave().
    setup_win_mousepointer .one
    wm withdraw .one
    create_and_pack_frames .one
    wm deiconify .one
    tkwait visibility .one.f1.f2
    update idletasks; # finish displaying window
    _pause 200; # needed for Windows
    set result "|"
} -body {
    bind all <Leave> {append result "<Leave> %d %W|"}
    bind all <Enter> {append result "<Enter> %d %W|"}
    destroy .one.f1
    if {[tk windowingsystem] ne "x11"} {
        testprocessevents enter leave
    } else {
	update

    }
    set result
} -cleanup {
    bind all <Leave> {}
    bind all <Enter> {}
    destroy .one
    unset result
} -result {|<Enter> NotifyInferior .one|}

test event-9.17 {Successive destructions (pointer window + parent), separate crossing events} -setup {
    # Tests correctness of overwriting the dead window struct in
    # TkPointerDeadWindow() and subsequent reading in GenerateEnterLeave().
    setup_win_mousepointer .one
    wm withdraw .one
    create_and_pack_frames .one
    wm deiconify .one
    tkwait visibility .one.f1.f2
    update idletasks; # finish displaying window
    _pause 200; # needed for Windows


    set result "|"
} -body {
    bind all <Leave> {append result "<Leave> %d %W|"}
    bind all <Enter> {append result "<Enter> %d %W|"}
    destroy .one.f1.f2
    update; # make sure window is gone
    destroy .one.f1
    update; # make sure window is gone
    if {[tk windowingsystem] ne "x11"} {testprocessevents enter leave}
    set result


} -cleanup {
    bind all <Leave> {}
    bind all <Enter> {}
    destroy .one
    unset result
} -result {|<Enter> NotifyInferior .one.f1|<Enter> NotifyInferior .one|}

test event-9.18 {Successive destructions (pointer window + ancestors including its toplevel), destination is non-root toplevel} -setup {
    setup_win_mousepointer .one
    toplevel .two
    pack propagate .two 0
    wm geometry .two 300x300+100+100
    create_and_pack_frames .two
    wm deiconify .two
    waitForWindowEvent .two.f1.f2 <Enter>
    set result "|"
} -body {
    bind all <Leave> {append result "<Leave> %d %W|"}
    bind all <Enter> {append result "<Enter> %d %W|"}
    destroy .two
    waitForWindowEvent .one <Enter>
    if {[tk windowingsystem] ne "x11"} {testprocessevents enter leave}
    set result
} -cleanup {
    bind all <Leave> {}
    bind all <Enter> {}
    destroy .one
    unset result
} -result {|<Enter> NotifyNonlinear .one|}

test event-9.19 {Successive destructions (pointer window + ancestors including its toplevel), destination is internal window, bypass root win} -setup {
    setup_win_mousepointer .one; # ensure the mouse pointer is where we want it to be (the .one toplevel is not itself used in this test)
#    destroy .one
    toplevel .two
    pack propagate .two 0
    wm geometry .two 300x300+100+100
    create_and_pack_frames .two
    wm deiconify .two
    toplevel .three
    pack propagate .three 0
    wm geometry .three 300x300+110+110
    create_and_pack_frames .three
    wm deiconify .three
    waitForWindowEvent .three.f1.f2 <Enter>
    update idletasks; # finish displaying windows
    set result "|"
} -body {
    bind all <Leave> {append result "<Leave> %d %W|"}
    bind all <Enter> {append result "<Enter> %d %W|"}
    destroy .three
    waitForWindowEvent .two.f1.f2 <Enter>
    update idletasks; #finish destroying .two
    if {[tk windowingsystem] ne "x11"} {testprocessevents enter leave}
    set result
} -cleanup {
    bind all <Leave> {}
    bind all <Enter> {}
    destroy .one
    destroy .two
    unset result
} -result {|<Enter> NotifyNonlinearVirtual .two|<Enter> NotifyNonlinearVirtual .two.f1|<Enter> NotifyNonlinear .two.f1.f2|}

test event-9.20 {Successive destructions (pointer window + ancestors including its toplevel), destination is screen root} -setup {
    setup_win_mousepointer .one; # ensure the mouse pointer is where we want it to be (the .one toplevel is not itself used in this test)
    destroy .one
    toplevel .two
    pack propagate .two 0
    wm geometry .two 300x300+100+100
    create_and_pack_frames .two
    wm deiconify .two
    waitForWindowEvent .two.f1.f2 <Enter>
    set result "|"
} -body {
    bind all <Leave> {append result "<Leave> %d %W|"}
    bind all <Enter> {append result "<Enter> %d %W|"}
    destroy .two
    update idletasks; #finish destroying .two
    set result
} -cleanup {
    bind all <Leave> {}
    bind all <Enter> {}
    unset result
} -result {|}

# cleanup
update
unset -nocomplain keypress_lookup
rename _init_keypress_lookup {}
rename _keypress_lookup {}
rename _keypress {}
rename _pause {}
rename _text_ind_to_x_y {}
rename _get_selection {}
rename create_and_pack_frames {}
rename setup_win_mousepointer {}

cleanupTests
return


Changes to tests/font.test.
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
    set text Hello!
    destroy .t.c
    set c [canvas .t.c]
    set textid [$c create text 20 20 -font MyFont -text $text -anchor nw]
    set twidth [font measure MyFont $text]
    set theight [font metrics MyFont -linespace]
    set circid [$c create polygon \
		    15                    15 \
		    [expr {15 + $twidth}] 15 \
		    [expr {15 + $twidth}] [expr {15 + $theight}] \
		    15                    [expr {15 + $theight}] \
		    -width 1 -joinstyle round -smooth true -fill {} -outline blue]
    pack $c -fill both -expand 1 -side top
    update

    # Lamda test functions
    set circle_text {{w user_data text circ} {
	if {[winfo class $w] ne "Canvas"} {
	    puts "Wrong widget type: $w"
	    return
	}
	if {$user_data ne "FontChanged"} {
	    return







|
|
|
|
|



|







2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
    set text Hello!
    destroy .t.c
    set c [canvas .t.c]
    set textid [$c create text 20 20 -font MyFont -text $text -anchor nw]
    set twidth [font measure MyFont $text]
    set theight [font metrics MyFont -linespace]
    set circid [$c create polygon \
        15                    15 \
        [expr {15 + $twidth}] 15 \
        [expr {15 + $twidth}] [expr {15 + $theight}] \
        15                    [expr {15 + $theight}] \
            -width 1 -joinstyle round -smooth true -fill {} -outline blue]
    pack $c -fill both -expand 1 -side top
    update

    # Lambda test functions
    set circle_text {{w user_data text circ} {
	if {[winfo class $w] ne "Canvas"} {
	    puts "Wrong widget type: $w"
	    return
	}
	if {$user_data ne "FontChanged"} {
	    return
2464
2465
2466
2467
2468
2469
2470

2471
2472
2473
2474
2475
2476
2477
    }}
    set enclosed {{can id} {$can find enclosed {*}[$can bbox $id]}}

    set results {}
    apply $circle_text $c FontChanged $textid $circid
    update
    bind $c <<TkWorldChanged>> [list apply $circle_text %W %d $textid $circid]


    # Begin test:
    set results {}
    lappend results [apply $enclosed $c $circid]
    font configure MyFont -size 26
    update  ; # services the "TheWorldHasChanged" event, queues "TkWorldChanged" events
    update  ; # services the queued "TkWorldChanged" events







>







2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
    }}
    set enclosed {{can id} {$can find enclosed {*}[$can bbox $id]}}

    set results {}
    apply $circle_text $c FontChanged $textid $circid
    update
    bind $c <<TkWorldChanged>> [list apply $circle_text %W %d $textid $circid]
    update idletasks

    # Begin test:
    set results {}
    lappend results [apply $enclosed $c $circid]
    font configure MyFont -size 26
    update  ; # services the "TheWorldHasChanged" event, queues "TkWorldChanged" events
    update  ; # services the queued "TkWorldChanged" events
Changes to tests/unixWm.test.
101
102
103
104
105
106
107

108
109
110
111
112
113
114
    } $geom
    incr i
}

set i 1
foreach geom "+20+80 +80+$Y0 +0+$Y0 -0-0 +0-0 -0+$Y0 -10-5 -10+$Y5 +10-5" {
    test unixWm-3.$i {moving window while iconified} unix {

	wm iconify .t
	update idletasks
	wm geom .t $geom
	update idletasks
	wm deiconify .t
	update idletasks
	scan [wm geom .t] %dx%d%1s%d%1s%d width height xsign x ysign y







>







101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
    } $geom
    incr i
}

set i 1
foreach geom "+20+80 +80+$Y0 +0+$Y0 -0-0 +0-0 -0+$Y0 -10-5 -10+$Y5 +10-5" {
    test unixWm-3.$i {moving window while iconified} unix {
        update
	wm iconify .t
	update idletasks
	wm geom .t $geom
	update idletasks
	wm deiconify .t
	update idletasks
	scan [wm geom .t] %dx%d%1s%d%1s%d width height xsign x ysign y
637
638
639
640
641
642
643


644
645
646
647
648
649
650

test unixWm-16.1 {Tk_WmCmd procedure, "deiconify" option} unix {
    list [catch {wm deiconify .t 12} msg] $msg
} {1 {wrong # args: should be "wm deiconify window"}}
test unixWm-16.2 {Tk_WmCmd procedure, "deiconify" option} unix {
    destroy .icon
    toplevel .icon -width 50 -height 50 -bg red


    wm iconwindow .t .icon
    set result [list [catch {wm deiconify .icon} msg] $msg]
    destroy .icon
    set result
} {1 {can't deiconify .icon: it is an icon for .t}}
test unixWm-16.3 {Tk_WmCmd procedure, "deiconify" option} {unix failsOnUbuntu failsOnXQuarz} {
    wm iconify .t







>
>







638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653

test unixWm-16.1 {Tk_WmCmd procedure, "deiconify" option} unix {
    list [catch {wm deiconify .t 12} msg] $msg
} {1 {wrong # args: should be "wm deiconify window"}}
test unixWm-16.2 {Tk_WmCmd procedure, "deiconify" option} unix {
    destroy .icon
    toplevel .icon -width 50 -height 50 -bg red
    # calling update here prevents a crash in 16.3 on macOS
    update
    wm iconwindow .t .icon
    set result [list [catch {wm deiconify .icon} msg] $msg]
    destroy .icon
    set result
} {1 {can't deiconify .icon: it is an icon for .t}}
test unixWm-16.3 {Tk_WmCmd procedure, "deiconify" option} {unix failsOnUbuntu failsOnXQuarz} {
    wm iconify .t
1348
1349
1350
1351
1352
1353
1354


1355
1356


1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375

1376

1377
1378
1379
1380
1381
1382
1383
    set result [list [catch {wm withdraw .t2} msg]  $msg]
    destroy .t2
    set result
} {1 {can't withdraw .t2: it is an icon for .t}}
test unixWm-38.3 {Tk_WmCmd procedure, "withdraw" option} unix {
    set result {}
    wm withdraw .t


    lappend result [wm state .t] [winfo ismapped .t]
    wm deiconify .t


    lappend result [wm state .t] [winfo ismapped .t]
} {withdrawn 0 normal 1}

test unixWm-39.1 {Tk_WmCmd procedure, miscellaneous} unix {
    list [catch {wm unknown .t} msg] $msg
} {1 {bad option "unknown": must be aspect, attributes, client, colormapwindows, command, deiconify, focusmodel, forget, frame, geometry, grid, group, iconbitmap, iconify, iconmask, iconname, iconphoto, iconposition, iconwindow, manage, maxsize, minsize, overrideredirect, positionfrom, protocol, resizable, sizefrom, stackorder, state, title, transient, or withdraw}}

destroy .t .icon

test unixWm-40.1 {Tk_SetGrid procedure, set grid dimensions before turning on grid} {unix nonPortable} {
    destroy .t
    toplevel .t
    wm geometry .t 30x10+0+0
    listbox .t.l -height 20 -width 20 -setgrid 1
    pack .t.l -fill both -expand 1
    update
    wm geometry .t
} {30x10+0+0}
test unixWm-40.2 {Tk_SetGrid procedure, turning on grid when dimensions already set} unix {

    destroy .t

    toplevel .t
    wm geometry .t 200x100+100+$Y0
    listbox .t.l -height 20 -width 20
    pack .t.l -fill both -expand 1
    update
    .t.l configure -setgrid 1
    update







>
>


>
>



















>

>







1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
    set result [list [catch {wm withdraw .t2} msg]  $msg]
    destroy .t2
    set result
} {1 {can't withdraw .t2: it is an icon for .t}}
test unixWm-38.3 {Tk_WmCmd procedure, "withdraw" option} unix {
    set result {}
    wm withdraw .t
    #added to avoid a crash on macOS
    update idletasks
    lappend result [wm state .t] [winfo ismapped .t]
    wm deiconify .t
    #added to avoid a crash on macOS
    update idletasks
    lappend result [wm state .t] [winfo ismapped .t]
} {withdrawn 0 normal 1}

test unixWm-39.1 {Tk_WmCmd procedure, miscellaneous} unix {
    list [catch {wm unknown .t} msg] $msg
} {1 {bad option "unknown": must be aspect, attributes, client, colormapwindows, command, deiconify, focusmodel, forget, frame, geometry, grid, group, iconbitmap, iconify, iconmask, iconname, iconphoto, iconposition, iconwindow, manage, maxsize, minsize, overrideredirect, positionfrom, protocol, resizable, sizefrom, stackorder, state, title, transient, or withdraw}}

destroy .t .icon

test unixWm-40.1 {Tk_SetGrid procedure, set grid dimensions before turning on grid} {unix nonPortable} {
    destroy .t
    toplevel .t
    wm geometry .t 30x10+0+0
    listbox .t.l -height 20 -width 20 -setgrid 1
    pack .t.l -fill both -expand 1
    update
    wm geometry .t
} {30x10+0+0}
test unixWm-40.2 {Tk_SetGrid procedure, turning on grid when dimensions already set} unix {
    update
    destroy .t
    update
    toplevel .t
    wm geometry .t 200x100+100+$Y0
    listbox .t.l -height 20 -width 20
    pack .t.l -fill both -expand 1
    update
    .t.l configure -setgrid 1
    update
1794
1795
1796
1797
1798
1799
1800


1801
1802
1803
1804
1805
1806
1807
    testmenubar window .t .t.m
    update
    list [expr [winfo rootx .t.m.f] - $x] [expr [winfo rooty .t.m.f] - $y] \
	    [expr [winfo rootx .t.f] - $x] [expr [winfo rooty .t.f] - $y]
} {52 7 12 62}

deleteWindows


wm withdraw .
if {[tk windowingsystem] eq "aqua"} {
    # Modern mac windows have no border.
    set result_50_1 {{} {} .t .t .t2 {} .t2 .t .t}
} else {
    # Windows are assumed to have a border (invisible in Gnome 3).
    set result_50_1 {{} {} .t {} .t2 {} .t2 {} .t}







>
>







1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
    testmenubar window .t .t.m
    update
    list [expr [winfo rootx .t.m.f] - $x] [expr [winfo rooty .t.m.f] - $y] \
	    [expr [winfo rootx .t.f] - $x] [expr [winfo rooty .t.f] - $y]
} {52 7 12 62}

deleteWindows
# Make sure that the root window is out of the way!
wm geom . +700+700
wm withdraw .
if {[tk windowingsystem] eq "aqua"} {
    # Modern mac windows have no border.
    set result_50_1 {{} {} .t .t .t2 {} .t2 .t .t}
} else {
    # Windows are assumed to have a border (invisible in Gnome 3).
    set result_50_1 {{} {} .t {} .t2 {} .t2 {} .t}
Changes to tests/winfo.test.
437
438
439
440
441
442
443

444
445

446
447
448
449
450
451
452
} -cleanup {
    deleteWindows
} -result {child 0 parent 0}

test winfo-13.4 {[winfo containing] with embedded windows} -setup {
    deleteWindows
} -body {

    frame .con -container 1
    pack .con -expand yes -fill both

    toplevel .emb -use [winfo id .con] -bd 0 -highlightthickness 0
    button .emb.b
    pack .emb.b -expand yes -fill both
    update

    button .b
    pack .b -expand yes -fill both







>


>







437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
} -cleanup {
    deleteWindows
} -result {child 0 parent 0}

test winfo-13.4 {[winfo containing] with embedded windows} -setup {
    deleteWindows
} -body {
    wm geometry . +100+100
    frame .con -container 1
    pack .con -expand yes -fill both
    update
    toplevel .emb -use [winfo id .con] -bd 0 -highlightthickness 0
    button .emb.b
    pack .emb.b -expand yes -fill both
    update

    button .b
    pack .b -expand yes -fill both
Changes to tests/wm.test.
940
941
942
943
944
945
946


947
948
949
950
951
952
953
    wm iconwindow .t2 .icon
    wm iconwindow .t .icon
} -returnCodes error -cleanup {
    destroy .t2 .icon
} -result {.icon is already an icon for .t2}

test wm-iconwindow-2.1 {setting and reading values} -setup {


    destroy .icon
    set result {}
} -body {
    lappend result [wm iconwindow .t]
    toplevel .icon -width 50 -height 50 -bg green
    wm iconwindow .t .icon
    lappend result [wm iconwindow .t]







>
>







940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
    wm iconwindow .t2 .icon
    wm iconwindow .t .icon
} -returnCodes error -cleanup {
    destroy .t2 .icon
} -result {.icon is already an icon for .t2}

test wm-iconwindow-2.1 {setting and reading values} -setup {
    # without this macOS crashes for unknown reasons
    wm iconwindow .t {}
    destroy .icon
    set result {}
} -body {
    lappend result [wm iconwindow .t]
    toplevel .icon -width 50 -height 50 -bg green
    wm iconwindow .t .icon
    lappend result [wm iconwindow .t]
Changes to tests/xmfbox.test.
50
51
52
53
54
55
56

57
58
59
60
61
62
63
    } msg4]

    if {$err0 || $err1 || $err2 || $err3 || $err4} {
	    error [list $msg0 $msg1 $msg2 $msg3 $msg4]
    }
    catch {unset foo}
    destroy .foo

}

# ----------------------------------------------------------------------

test xmfbox-1.1 {tk::MotifFDialog_Create, -parent switch} -constraints {
    unix
} -setup {







>







50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
    } msg4]

    if {$err0 || $err1 || $err2 || $err3 || $err4} {
	    error [list $msg0 $msg1 $msg2 $msg3 $msg4]
    }
    catch {unset foo}
    destroy .foo
    update
}

# ----------------------------------------------------------------------

test xmfbox-1.1 {tk::MotifFDialog_Create, -parent switch} -constraints {
    unix
} -setup {
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86
87
88
89
90
91

92
93
94
95
96
97
98
99
100
101
102

103
104
105
106
107
108
109
110
111
112
113

114
115
116
117
118
119
120
121
122
123
124
125
126

127
128
129
130
131
132
133
134
135
136

137
138
139
140
141
142
143
    unix
} -setup {
    catch {unset foo}
    deleteWindows
} -body {
    toplevel .bar
    wm geometry .bar +0+0

    set x [tk::MotifFDialog_Create foo open {-parent .bar}]
} -cleanup {
    destroy $x
    destroy .bar
}  -result {.bar.foo}


test xmfbox-2.1 {tk::MotifFDialog_InterpFilter, ~ in dir names} -constraints {
    unix
} -body {
    cleanup
    file mkdir ./~nosuchuser1
    set x [tk::MotifFDialog_Create foo open {}]

    $::tk::dialog::file::foo(fEnt) delete 0 end
    $::tk::dialog::file::foo(fEnt) insert 0 [pwd]/~nosuchuser1
    set kk [tk::MotifFDialog_InterpFilter $x]
} -result "$testPWD/~nosuchuser1 *"

test xmfbox-2.2 {tk::MotifFDialog_InterpFilter, ~ in file names} -constraints {
    unix
} -body {
    cleanup
    close [open ./~nosuchuser1 {CREAT TRUNC WRONLY}]
    set x [tk::MotifFDialog_Create foo open {}]

    $::tk::dialog::file::foo(fEnt) delete 0 end
    $::tk::dialog::file::foo(fEnt) insert 0 [pwd]/~nosuchuser1
    set kk [tk::MotifFDialog_InterpFilter $x]
} -result "$testPWD ./~nosuchuser1"

test xmfbox-2.3 {tk::MotifFDialog_Update, ~ in file names} -constraints {
    unix
} -body {
    cleanup
    close [open ./~nosuchuser1 {CREAT TRUNC WRONLY}]
    set x [tk::MotifFDialog_Create foo open {}]

    $::tk::dialog::file::foo(fEnt) delete 0 end
    $::tk::dialog::file::foo(fEnt) insert 0 [pwd]/~nosuchuser1
    tk::MotifFDialog_InterpFilter $x
    tk::MotifFDialog_Update $x
    $::tk::dialog::file::foo(fList) get end
} -result {~nosuchuser1}

test xmfbox-2.4 {tk::MotifFDialog_LoadFile, ~ in file names} -constraints {
    unix
} -body {
    cleanup
    close [open ./~nosuchuser1 {CREAT TRUNC WRONLY}]
    set x [tk::MotifFDialog_Create foo open {}]

    set i [lsearch [$::tk::dialog::file::foo(fList) get 0 end] ~nosuchuser1]
    expr {$i >= 0}
} -result 1

test xmfbox-2.5 {tk::MotifFDialog_BrowseFList, ~ in file names} -constraints {
    unix
} -body {
    cleanup
    close [open ./~nosuchuser1 {CREAT TRUNC WRONLY}]
    set x [tk::MotifFDialog_Create foo open {}]

    set i [lsearch [$::tk::dialog::file::foo(fList) get 0 end] ~nosuchuser1]
    $::tk::dialog::file::foo(fList) selection clear 0 end
    $::tk::dialog::file::foo(fList) selection set $i
    tk::MotifFDialog_BrowseFList $x
    $::tk::dialog::file::foo(sEnt) get
} -result "$testPWD/~nosuchuser1"








>













>











>











>













>










>







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
    unix
} -setup {
    catch {unset foo}
    deleteWindows
} -body {
    toplevel .bar
    wm geometry .bar +0+0
    update
    set x [tk::MotifFDialog_Create foo open {-parent .bar}]
} -cleanup {
    destroy $x
    destroy .bar
}  -result {.bar.foo}


test xmfbox-2.1 {tk::MotifFDialog_InterpFilter, ~ in dir names} -constraints {
    unix
} -body {
    cleanup
    file mkdir ./~nosuchuser1
    set x [tk::MotifFDialog_Create foo open {}]
    update
    $::tk::dialog::file::foo(fEnt) delete 0 end
    $::tk::dialog::file::foo(fEnt) insert 0 [pwd]/~nosuchuser1
    set kk [tk::MotifFDialog_InterpFilter $x]
} -result "$testPWD/~nosuchuser1 *"

test xmfbox-2.2 {tk::MotifFDialog_InterpFilter, ~ in file names} -constraints {
    unix
} -body {
    cleanup
    close [open ./~nosuchuser1 {CREAT TRUNC WRONLY}]
    set x [tk::MotifFDialog_Create foo open {}]
    update
    $::tk::dialog::file::foo(fEnt) delete 0 end
    $::tk::dialog::file::foo(fEnt) insert 0 [pwd]/~nosuchuser1
    set kk [tk::MotifFDialog_InterpFilter $x]
} -result "$testPWD ./~nosuchuser1"

test xmfbox-2.3 {tk::MotifFDialog_Update, ~ in file names} -constraints {
    unix
} -body {
    cleanup
    close [open ./~nosuchuser1 {CREAT TRUNC WRONLY}]
    set x [tk::MotifFDialog_Create foo open {}]
    update
    $::tk::dialog::file::foo(fEnt) delete 0 end
    $::tk::dialog::file::foo(fEnt) insert 0 [pwd]/~nosuchuser1
    tk::MotifFDialog_InterpFilter $x
    tk::MotifFDialog_Update $x
    $::tk::dialog::file::foo(fList) get end
} -result {~nosuchuser1}

test xmfbox-2.4 {tk::MotifFDialog_LoadFile, ~ in file names} -constraints {
    unix
} -body {
    cleanup
    close [open ./~nosuchuser1 {CREAT TRUNC WRONLY}]
    set x [tk::MotifFDialog_Create foo open {}]
    update
    set i [lsearch [$::tk::dialog::file::foo(fList) get 0 end] ~nosuchuser1]
    expr {$i >= 0}
} -result 1

test xmfbox-2.5 {tk::MotifFDialog_BrowseFList, ~ in file names} -constraints {
    unix
} -body {
    cleanup
    close [open ./~nosuchuser1 {CREAT TRUNC WRONLY}]
    set x [tk::MotifFDialog_Create foo open {}]
    update
    set i [lsearch [$::tk::dialog::file::foo(fList) get 0 end] ~nosuchuser1]
    $::tk::dialog::file::foo(fList) selection clear 0 end
    $::tk::dialog::file::foo(fList) selection set $i
    tk::MotifFDialog_BrowseFList $x
    $::tk::dialog::file::foo(sEnt) get
} -result "$testPWD/~nosuchuser1"

Changes to win/tkWinWm.c.
2572
2573
2574
2575
2576
2577
2578



























2579
2580
2581
2582
2583
2584
2585
 *	None.
 *
 * Side effects:
 *	The WmInfo structure for winPtr gets freed up.
 *
 *--------------------------------------------------------------
 */




























void
TkWmDeadWindow(
    TkWindow *winPtr)		/* Top-level window that's being deleted. */
{
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr2;







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







2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
 *	None.
 *
 * Side effects:
 *	The WmInfo structure for winPtr gets freed up.
 *
 *--------------------------------------------------------------
 */

static void CheckForPointer(TkWindow *winPtr)
{
    POINT mouse;
    int x, y;
    unsigned int state = TkWinGetModifierState();
    TkWindow **windows = TkWmStackorderToplevel(winPtr->mainPtr->winPtr);
    TkWindow **w;
    TkGetPointerCoords(NULL, &x, &y);
    mouse.x = x;
    mouse.y = y;
    if (windows != NULL) {
	for (w = windows; *w ; w++) {
	    RECT windowRect;
	    HWND hwnd = Tk_GetHWND(Tk_WindowId((Tk_Window) *w));
	    if (GetWindowRect(hwnd, &windowRect) == 0) {
		continue;
	    }
	    if (winPtr != *w && PtInRect(&windowRect, mouse)) {
		Tk_Window target = Tk_CoordsToWindow(x, y, (Tk_Window) *w);
		Tk_UpdatePointer((Tk_Window) target, x, y, state);
		break;
	    }
	}
	ckfree(windows);
    }
}

void
TkWmDeadWindow(
    TkWindow *winPtr)		/* Top-level window that's being deleted. */
{
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr2;
2711
2712
2713
2714
2715
2716
2717







2718
2719
2720
2721
2722
2723
2724
	 * after destroying the decorative frame, because the decorative frame
	 * is using this icon.
	 */

	DecrIconRefCount(wmPtr->iconPtr);
    }








    ckfree(wmPtr);
    winPtr->wmInfoPtr = NULL;
}

/*
 *--------------------------------------------------------------
 *







>
>
>
>
>
>
>







2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
	 * after destroying the decorative frame, because the decorative frame
	 * is using this icon.
	 */

	DecrIconRefCount(wmPtr->iconPtr);
    }

    /*
     * Check if the dead window is a toplevel containing the pointer.  If so,
     * find the window which will inherit the pointer and call
     * TkUpdatePointer.
     */

    CheckForPointer(winPtr);
    ckfree(wmPtr);
    winPtr->wmInfoPtr = NULL;
}

/*
 *--------------------------------------------------------------
 *
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
{
    Tcl_HashEntry *hPtr;
    TkWindow *childWinPtr;

    TkWmStackorderToplevelPair *pair =
	    (TkWmStackorderToplevelPair *) lParam;

    /*fprintf(stderr, "Looking up HWND %d\n", hwnd);*/

    hPtr = Tcl_FindHashEntry(pair->table, (char *) hwnd);
    if (hPtr != NULL) {
	childWinPtr = (TkWindow *)Tcl_GetHashValue(hPtr);

	/*
	 * Double check that same HWND does not get passed twice.
	 */







<
<







6701
6702
6703
6704
6705
6706
6707


6708
6709
6710
6711
6712
6713
6714
{
    Tcl_HashEntry *hPtr;
    TkWindow *childWinPtr;

    TkWmStackorderToplevelPair *pair =
	    (TkWmStackorderToplevelPair *) lParam;



    hPtr = Tcl_FindHashEntry(pair->table, (char *) hwnd);
    if (hPtr != NULL) {
	childWinPtr = (TkWindow *)Tcl_GetHashValue(hPtr);

	/*
	 * Double check that same HWND does not get passed twice.
	 */