Tk Source Code

Check-in [fe352f24]
Login

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

Overview
Comment:Disallow transient/master cycles. Fix bgerror for Aqua to avoid hangs when an error occurs in an idle task run by [NSView drawRect].
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | core-8-6-branch
Files: files | file ages | folders
SHA3-256: fe352f24bd2f3ff248f3d663615c08ca66aee43e1632b4ba0a2f18913e8aeca0
User & Date: culler 2019-03-04 14:46:12.471
Context
2019-03-04
23:30
Fix bug [609e0045f5]: Aqua scrollwheel events have incorrect mouse coordinates. check-in: cb6302a6 user: culler tags: bug-609e0045f5
18:36
gif read not complete on overflow image - information missinterpreted if following subimage is querried [4da2191b] check-in: 5b17bc40 user: oehhar tags: core-8-6-branch
14:47
Disallow transient/master cycles. Fix bgerror for Aqua to avoid hangs when an error occurs in an idle task run by [NSView drawRect]. check-in: cf69d206 user: culler tags: trunk
14:46
Disallow transient/master cycles. Fix bgerror for Aqua to avoid hangs when an error occurs in an idle task run by [NSView drawRect]. check-in: fe352f24 user: culler tags: core-8-6-branch
2019-03-03
17:04
Increase the size of the ring buffer for Aqua, and modify bgerror so it doesn't try (and fail) to post a dialog inside [NSView drawRect]. Closed-Leaf check-in: 98cb3c6f user: culler tags: bug-1951abf33d
2019-03-01
04:01
Fix bug 1951abf33d: Aqua sometimes segfaults when destroying a transient. check-in: 8bfb7932 user: culler tags: core-8-6-branch
Changes
Unified Diff Ignore Whitespace Patch
Changes to doc/wm.n.
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722

723
724

725
726
727
728
729
730
731
732
733
should display this string in \fIwindow\fR's title bar).  In this
case the command returns an empty string.  If \fIstring\fR is not
specified then the command returns the current title for the
\fIwindow\fR.  The title for a window defaults to its name.
.TP
\fBwm transient \fIwindow\fR ?\fImaster\fR?
.
If \fImaster\fR is specified, then the window manager is informed
that \fIwindow\fR is a transient window (e.g. pull-down menu) working
on behalf of \fImaster\fR (where \fImaster\fR is the
path name for a top-level window).  If \fImaster\fR
is specified as an empty string then \fIwindow\fR is marked as not
being a transient window any more.  Otherwise the command
returns the path name of \fIwindow\fR's current master, or an
empty string if \fIwindow\fR is not currently a transient window.
A transient window will mirror state changes in the master and
inherit the state of the master when initially mapped. It is an

error to attempt to make a window a transient of itself.
The window manager may also decorate a transient window differently, removing

some features normally present (e.g., minimize and maximize buttons) though
this is entirely at the discretion of the window manager.
.TP
\fBwm withdraw \fIwindow\fR
.
Arranges for \fIwindow\fR to be withdrawn from the screen.  This
causes the window to be unmapped and forgotten about by the window
manager.  If the window
has never been mapped, then this command







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







706
707
708
709
710
711
712
713
714
715
716

717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
should display this string in \fIwindow\fR's title bar).  In this
case the command returns an empty string.  If \fIstring\fR is not
specified then the command returns the current title for the
\fIwindow\fR.  The title for a window defaults to its name.
.TP
\fBwm transient \fIwindow\fR ?\fImaster\fR?
.
If \fImaster\fR is specified, then the window manager is informed that
\fIwindow\fR is a transient window (e.g. pull-down menu) working on
behalf of \fImaster\fR (where \fImaster\fR is the path name for a
top-level window).  If \fImaster\fR is specified as an empty string

then \fIwindow\fR is marked as not being a transient window any more.
Otherwise the command returns the path name of \fIwindow\fR's current
master, or an empty string if \fIwindow\fR is not currently a
transient window.  A transient window will mirror state changes in the
master and inherit the state of the master when initially mapped. The
directed graph with an edge from each transient to its master must be
acyclic.  In particular, it is an error to attempt to make a window a
transient of itself.  The window manager may also decorate a transient
window differently, removing some features normally present (e.g.,
minimize and maximize buttons) though this is entirely at the
discretion of the window manager.
.TP
\fBwm withdraw \fIwindow\fR
.
Arranges for \fIwindow\fR to be withdrawn from the screen.  This
causes the window to be unmapped and forgotten about by the window
manager.  If the window
has never been mapped, then this command
Changes to generic/tkBind.c.
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
 * also demand that the event ring be a bit bigger.  It might be wise to
 * augment the current double-click pattern matching by adding a new
 * DoubleClick modifier bit which could be set based on the clickCount of the
 * Apple NSEvent object.
 */

#ifndef TK_MAC_OSX
  #define EVENT_BUFFER_SIZE 45
#else
  #define EVENT_BUFFER_SIZE 30
#endif

typedef struct Tk_BindingTable_ {
    XEvent eventRing[EVENT_BUFFER_SIZE];
				/* Circular queue of recent events (higher







|







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
 * also demand that the event ring be a bit bigger.  It might be wise to
 * augment the current double-click pattern matching by adding a new
 * DoubleClick modifier bit which could be set based on the clickCount of the
 * Apple NSEvent object.
 */

#ifndef TK_MAC_OSX
  #define EVENT_BUFFER_SIZE 90
#else
  #define EVENT_BUFFER_SIZE 30
#endif

typedef struct Tk_BindingTable_ {
    XEvent eventRing[EVENT_BUFFER_SIZE];
				/* Circular queue of recent events (higher
Changes to library/bgerror.tcl.
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
#	It tries to execute tkerror, if that fails it posts a dialog box
#	containing the error message and gives the user a chance to ask
#	to see a stack trace.
#
# Arguments:
#	err - The error message.
#
proc ::tk::dialog::error::bgerror err {
    global errorInfo
    variable button

    set info $errorInfo

    set ret [catch {::tkerror $err} msg];
    if {$ret != 1} {return -code $ret $msg}

    # Ok the application's tkerror either failed or was not found
    # we use the default dialog then :



    set windowingsystem [tk windowingsystem]
    if {$windowingsystem eq "aqua"} {
	set ok [mc Ok]
    } else {

	set ok [mc OK]
    }



    # Truncate the message if it is too wide (>maxLine characters) or
    # too tall (>4 lines).  Truncation occurs at the first point at
    # which one of those conditions is met.
    set displayedErr ""
    set lines 0
    set maxLine 45
    foreach line [split $err \n] {







|








|
|
>
>
>


<
|
>
|
|
|
>
>







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
#	It tries to execute tkerror, if that fails it posts a dialog box
#	containing the error message and gives the user a chance to ask
#	to see a stack trace.
#
# Arguments:
#	err - The error message.
#
proc ::tk::dialog::error::bgerror {err {flag 1}} {
    global errorInfo
    variable button

    set info $errorInfo

    set ret [catch {::tkerror $err} msg];
    if {$ret != 1} {return -code $ret $msg}

    # The application's tkerror either failed or was not found
    # so we use the default dialog.  But on Aqua we cannot display
    # the dialog if the background error occurs in an idle task
    # being processed inside of [NSView drawRect].  In that case
    # we post the dialog as an after task instead.
    set windowingsystem [tk windowingsystem]
    if {$windowingsystem eq "aqua"} {

	if $flag {
	    after 500 [list bgerror "$err" 0]
	    return
	}
    }

    set ok [mc OK]
    # Truncate the message if it is too wide (>maxLine characters) or
    # too tall (>4 lines).  Truncation occurs at the first point at
    # which one of those conditions is met.
    set displayedErr ""
    set lines 0
    set maxLine 45
    foreach line [split $err \n] {
Changes to macosx/tkMacOSXKeyEvent.c.
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_KEYBOARD
#endif
*/
#define NS_KEYLOG 0


static Tk_Window grabWinPtr = NULL;
				/* Current grab window, NULL if no grab. */
static Tk_Window keyboardGrabWinPtr = NULL;
				/* Current keyboard grab window. */
static NSWindow *keyboardGrabNSWindow = nil;
                               /* NSWindow for the current keyboard grab window. */
static NSModalSession modalSession = nil;

static BOOL processingCompose = NO;







<
<
<







20
21
22
23
24
25
26



27
28
29
30
31
32
33
/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_KEYBOARD
#endif
*/
#define NS_KEYLOG 0




static Tk_Window keyboardGrabWinPtr = NULL;
				/* Current keyboard grab window. */
static NSWindow *keyboardGrabNSWindow = nil;
                               /* NSWindow for the current keyboard grab window. */
static NSModalSession modalSession = nil;

static BOOL processingCompose = NO;
496
497
498
499
500
501
502

503
504
505
506
507
508
509
510
511
512
513
514
    Window grab_window,
    Bool owner_events,
    int pointer_mode,
    int keyboard_mode,
    Time time)
{
    keyboardGrabWinPtr = Tk_IdToWindow(display, grab_window);

    if (keyboardGrabWinPtr && grabWinPtr) {
	NSWindow *w = TkMacOSXDrawableWindow(grab_window);
	MacDrawable *macWin = (MacDrawable *) grab_window;

	if (w && macWin->toplevel->winPtr == (TkWindow*) grabWinPtr) {
	    if (modalSession) {
		Tcl_Panic("XGrabKeyboard: already grabbed");
	    }
	    keyboardGrabNSWindow = w;
	    [w retain];
	    modalSession = [NSApp beginModalSessionForWindow:w];
	}







>
|



|







493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
    Window grab_window,
    Bool owner_events,
    int pointer_mode,
    int keyboard_mode,
    Time time)
{
    keyboardGrabWinPtr = Tk_IdToWindow(display, grab_window);
    TkWindow *captureWinPtr = (TkWindow *)TkMacOSXGetCapture(); 
    if (keyboardGrabWinPtr && captureWinPtr) {
	NSWindow *w = TkMacOSXDrawableWindow(grab_window);
	MacDrawable *macWin = (MacDrawable *) grab_window;

	if (w && macWin->toplevel->winPtr == (TkWindow*) captureWinPtr) {
	    if (modalSession) {
		Tcl_Panic("XGrabKeyboard: already grabbed");
	    }
	    keyboardGrabNSWindow = w;
	    [w retain];
	    modalSession = [NSApp beginModalSessionForWindow:w];
	}
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
    }
    keyboardGrabWinPtr = NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXGetCapture --
 *
 * Results:
 *	Returns the current grab window
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tk_Window
TkMacOSXGetCapture(void)
{
    return grabWinPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXGetModalSession --
 *
 * Results:
 *	Returns the current modal session
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

MODULE_SCOPE NSModalSession
TkMacOSXGetModalSession(void)
{
    return modalSession;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpSetCapture --
 *
 *	This function captures the mouse so that all future events will be
 *	reported to this window, even if the mouse is outside the window. If
 *	the specified window is NULL, then the mouse is released.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Sets the capture flag and captures the mouse.
 *
 *----------------------------------------------------------------------
 */

void
TkpSetCapture(
    TkWindow *winPtr)		/* Capture window, or NULL. */
{
    while (winPtr && !Tk_IsTopLevel(winPtr)) {
	winPtr = winPtr->parentPtr;
    }
    grabWinPtr = (Tk_Window) winPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_SetCaretPos --
 *
 *	This enables correct placement of the XIM caret. This is called by







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







545
546
547
548
549
550
551




















552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567




























568
569
570
571
572
573
574
    }
    keyboardGrabWinPtr = NULL;
}

/*
 *----------------------------------------------------------------------
 *




















 * TkMacOSXGetModalSession --
 *
 * Results:
 *	Returns the current modal session
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

MODULE_SCOPE NSModalSession
TkMacOSXGetModalSession(void)
{
    return modalSession;
}





























/*
 *----------------------------------------------------------------------
 *
 * Tk_SetCaretPos --
 *
 *	This enables correct placement of the XIM caret. This is called by
Changes to macosx/tkMacOSXMouseEvent.c.
20
21
22
23
24
25
26

27
28
29
30
31
32
33
typedef struct {
    unsigned int state;
    long delta;
    Window window;
    Point global;
    Point local;
} MouseEventData;


static int		GenerateButtonEvent(MouseEventData *medPtr);
static unsigned int	ButtonModifiers2State(UInt32 buttonState,
					      UInt32 keyModifiers);

#pragma mark TKApplication(TKMouseEvent)








>







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
typedef struct {
    unsigned int state;
    long delta;
    Window window;
    Point global;
    Point local;
} MouseEventData;
static Tk_Window captureWinPtr = NULL; /* Current capture window; may be NULL. */

static int		GenerateButtonEvent(MouseEventData *medPtr);
static unsigned int	ButtonModifiers2State(UInt32 buttonState,
					      UInt32 keyModifiers);

#pragma mark TKApplication(TKMouseEvent)

576
577
578
579
580
581
582


















































583
584
585
586
587
588
589
590
						  pt,
						  buttonState);
    CGWarpMouseCursorPosition(pt);
    CGEventPost(kCGHIDEventTap, theEvent);
    CFRelease(theEvent);
}



















































/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */







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








577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
						  pt,
						  buttonState);
    CGWarpMouseCursorPosition(pt);
    CGEventPost(kCGHIDEventTap, theEvent);
    CFRelease(theEvent);
}

/*
 *----------------------------------------------------------------------
 *
 * TkpSetCapture --
 *
 *	This function captures the mouse so that all future events will be
 *	reported to this window, even if the mouse is outside the window. If
 *	the specified window is NULL, then the mouse is released.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Sets the capture flag and captures the mouse.
 *
 *----------------------------------------------------------------------
 */

void
TkpSetCapture(
    TkWindow *winPtr)		/* Capture window, or NULL. */
{
    while (winPtr && !Tk_IsTopLevel(winPtr)) {
	winPtr = winPtr->parentPtr;
    }
    captureWinPtr = (Tk_Window) winPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXGetCapture --
 *
 * Results:
 *	Returns the current grab window
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tk_Window
TkMacOSXGetCapture(void)
{
    return captureWinPtr;
}



/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Changes to macosx/tkMacOSXWm.c.
3564
3565
3566
3567
3568
3569
3570

3571
3572
3573
3574
3575
3576
3577
    TkWindow *winPtr,		/* Toplevel to work with */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    Tk_Window master;

    WmInfo *wmPtr2;
    Transient *transient;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?master?");
	return TCL_ERROR;
    }







>







3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
    TkWindow *winPtr,		/* Toplevel to work with */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    Tk_Window master;
    TkWindow *masterPtr, *w;
    WmInfo *wmPtr2;
    Transient *transient;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?master?");
	return TCL_ERROR;
    }
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
    if (Tcl_GetString(objv[3])[0] == '\0') {
	RemoveTransient(winPtr);

    } else {
	if (TkGetWindowFromObj(interp, tkwin, objv[3], &master) != TCL_OK) {
	    return TCL_ERROR;
	}
	TkWindow *masterPtr = (TkWindow*) master;
	while (!Tk_TopWinHierarchy(masterPtr)) {

            /*
             * Ensure that the master window is actually a Tk toplevel.
             */

            masterPtr = masterPtr->parentPtr;







|







3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
    if (Tcl_GetString(objv[3])[0] == '\0') {
	RemoveTransient(winPtr);

    } else {
	if (TkGetWindowFromObj(interp, tkwin, objv[3], &master) != TCL_OK) {
	    return TCL_ERROR;
	}
	masterPtr = (TkWindow*) master;
	while (!Tk_TopWinHierarchy(masterPtr)) {

            /*
             * Ensure that the master window is actually a Tk toplevel.
             */

            masterPtr = masterPtr->parentPtr;
3614
3615
3616
3617
3618
3619
3620


3621
3622

3623
3624
3625

3626
3627
3628
3629
3630
3631
3632
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't make \"%s\" a master: it is an icon for %s",
		    Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor)));
	    Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL);
	    return TCL_ERROR;
	}



	if (masterPtr == winPtr) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(

		    "can't make \"%s\" its own master", Tk_PathName(winPtr)));
	    Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
	    return TCL_ERROR;

	}

	/*
	 * Add the transient to the master's list, if it not already there.
	 */
	
	for (transient = wmPtr2->transientPtr;







>
>
|
|
>
|
|
|
>







3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't make \"%s\" a master: it is an icon for %s",
		    Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor)));
	    Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL);
	    return TCL_ERROR;
	}

	for (w = masterPtr; w != NULL && w->wmInfoPtr != NULL;
	     w = (TkWindow *)w->wmInfoPtr->master) {
	    if (w == winPtr) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "setting \"%s\" as master creates a transient/master cycle",
		    Tk_PathName(masterPtr)));
		Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
		return TCL_ERROR;
	    }
	}

	/*
	 * Add the transient to the master's list, if it not already there.
	 */
	
	for (transient = wmPtr2->transientPtr;
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
		     */

		    parentWindow = [macWindow parentWindow];
		    if (parentWindow && parentWindow != masterMacWin) {
			[parentWindow removeChildWindow:macWindow];
		    }

		    /*
		     * To avoid cycles, if the master is a child of some
		       other window, remove it.
		     */
		    parentWindow = [masterMacWin parentWindow];
		    if (parentWindow) {
			[parentWindow removeChildWindow:masterMacWin];
		    }
		    [masterMacWin addChildWindow:macWindow
					     ordered:NSWindowAbove];
		    }
	    }
	} else {
	    parentWindow = [macWindow parentWindow];
	    if (parentWindow) {







<
<
<
<
<
<
<
<







6882
6883
6884
6885
6886
6887
6888








6889
6890
6891
6892
6893
6894
6895
		     */

		    parentWindow = [macWindow parentWindow];
		    if (parentWindow && parentWindow != masterMacWin) {
			[parentWindow removeChildWindow:macWindow];
		    }









		    [masterMacWin addChildWindow:macWindow
					     ordered:NSWindowAbove];
		    }
	    }
	} else {
	    parentWindow = [macWindow parentWindow];
	    if (parentWindow) {
Changes to tests/wm.test.
1636
1637
1638
1639
1640
1641
1642
1643
1644










1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
    deleteWindows
} -result {can't make ".icon" a master: it is an icon for .top}
test wm-transient-1.7 {usage} -returnCodes error -body {
    toplevel .master
    wm transient .master .master
} -cleanup {
    deleteWindows
} -result {can't make ".master" its own master}
test wm-transient-1.8 {usage} -returnCodes error -body {










    toplevel .master
    frame .master.f
    wm transient .master .master.f
} -cleanup {
    deleteWindows
} -result {can't make ".master" its own master}

test wm-transient-2.1 {basic get/set of master} -setup {
    set results [list]
} -body {
    toplevel .master
    toplevel .subject
    lappend results [wm transient .subject]







|

>
>
>
>
>
>
>
>
>
>





|







1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
    deleteWindows
} -result {can't make ".icon" a master: it is an icon for .top}
test wm-transient-1.7 {usage} -returnCodes error -body {
    toplevel .master
    wm transient .master .master
} -cleanup {
    deleteWindows
} -result {setting ".master" as master creates a transient/master cycle}
test wm-transient-1.8 {usage} -returnCodes error -body {
    toplevel .t1
    toplevel .t2
    toplevel .t3
    wm transient .t2 .t1
    wm transient .t3 .t2
    wm transient .t1 .t3
} -cleanup {
    deleteWindows
} -result {setting ".t3" as master creates a transient/master cycle}
test wm-transient-1.9 {usage} -returnCodes error -body {
    toplevel .master
    frame .master.f
    wm transient .master .master.f
} -cleanup {
    deleteWindows
} -result {setting ".master" as master creates a transient/master cycle}

test wm-transient-2.1 {basic get/set of master} -setup {
    set results [list]
} -body {
    toplevel .master
    toplevel .subject
    lappend results [wm transient .subject]
Changes to unix/tkUnixWm.c.
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
    Tk_Window tkwin,		/* Main window of the application. */
    TkWindow *winPtr,		/* Toplevel to work with */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    TkWindow *masterPtr = wmPtr->masterPtr;
    WmInfo *wmPtr2;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?master?");
	return TCL_ERROR;
    }
    if (objc == 3) {







|







3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
    Tk_Window tkwin,		/* Main window of the application. */
    TkWindow *winPtr,		/* Toplevel to work with */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    TkWindow *masterPtr = wmPtr->masterPtr, *w;
    WmInfo *wmPtr2;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?master?");
	return TCL_ERROR;
    }
    if (objc == 3) {
3589
3590
3591
3592
3593
3594
3595


3596
3597

3598
3599
3600



3601
3602
3603
3604
3605
3606
3607
3608
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't make \"%s\" a master: it is an icon for %s",
		    Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor)));
	    Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL);
	    return TCL_ERROR;
	}



	if (masterPtr == winPtr) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(

		    "can't make \"%s\" its own master", Tk_PathName(winPtr)));
	    Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
	    return TCL_ERROR;



	} else if (masterPtr != wmPtr->masterPtr) {
	    /*
	     * Remove old master map/unmap binding before setting the new
	     * master. The event handler will ensure that transient states
	     * reflect the state of the master.
	     */

	    if (wmPtr->masterPtr != NULL) {







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







3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't make \"%s\" a master: it is an icon for %s",
		    Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor)));
	    Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL);
	    return TCL_ERROR;
	}

	for (w = masterPtr; w != NULL && w->wmInfoPtr != NULL;
	     w = (TkWindow *)w->wmInfoPtr->masterPtr) {
	    if (w == winPtr) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "setting \"%s\" as master creates a transient/master cycle",
		    Tk_PathName(masterPtr)));
		Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
		return TCL_ERROR;
	    }
	}

	if (masterPtr != wmPtr->masterPtr) {
	    /*
	     * Remove old master map/unmap binding before setting the new
	     * master. The event handler will ensure that transient states
	     * reflect the state of the master.
	     */

	    if (wmPtr->masterPtr != NULL) {
Changes to win/tkWinWm.c.
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
    Tk_Window tkwin,		/* Main window of the application. */
    TkWindow *winPtr,		/* Toplevel to work with */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    TkWindow *masterPtr = wmPtr->masterPtr, **masterPtrPtr = &masterPtr;
    WmInfo *wmPtr2;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?master?");
	return TCL_ERROR;
    }
    if (objc == 3) {







|







5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
    Tk_Window tkwin,		/* Main window of the application. */
    TkWindow *winPtr,		/* Toplevel to work with */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    TkWindow *masterPtr = wmPtr->masterPtr, **masterPtrPtr = &masterPtr, *w;
    WmInfo *wmPtr2;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?master?");
	return TCL_ERROR;
    }
    if (objc == 3) {
5580
5581
5582
5583
5584
5585
5586
5587

5588
5589

5590
5591
5592


5593
5594
5595
5596
5597
5598
5599
5600
	if (wmPtr2->iconFor != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't make \"%s\" a master: it is an icon for %s",
		    Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor)));
	    Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL);
	    return TCL_ERROR;
	}


	if (masterPtr == winPtr) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(

		    "can't make \"%s\" its own master", Tk_PathName(winPtr)));
	    Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
	    return TCL_ERROR;


	} else if (masterPtr != wmPtr->masterPtr) {
	    /*
	     * Remove old master map/unmap binding before setting the new
	     * master. The event handler will ensure that transient states
	     * reflect the state of the master.
	     */

	    if (wmPtr->masterPtr != NULL) {







|
>
|
|
>
|
|
|
>
>
|







5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
	if (wmPtr2->iconFor != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't make \"%s\" a master: it is an icon for %s",
		    Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor)));
	    Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL);
	    return TCL_ERROR;
	}
	for (w = masterPtr; w != NULL && w->wmInfoPtr != NULL;
	     w = (TkWindow *)w->wmInfoPtr->masterPtr) {
	    if (w == winPtr) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "setting \"%s\" as master creates a transient/master cycle",
		    Tk_PathName(masterPtr)));
		Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
		return TCL_ERROR;
	    }
	}
	if (masterPtr != wmPtr->masterPtr) {
	    /*
	     * Remove old master map/unmap binding before setting the new
	     * master. The event handler will ensure that transient states
	     * reflect the state of the master.
	     */

	    if (wmPtr->masterPtr != NULL) {