Tk Source Code

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

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

Overview
Comment:merge trunk
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | revised_text | tip-466
Files: files | file ages | folders
SHA3-256: 76d45a3e20142f8f79b70b0863a9fd9f498de9432668e2202ebdce393302c968
User & Date: fvogel 2019-03-14 21:05:12
Context
2019-03-19
16:35
Merge trunk check-in: 3f6280a6 user: jan.nijtmans tags: revised_text, tip-466
2019-03-14
21:05
merge trunk check-in: 76d45a3e user: fvogel tags: revised_text, tip-466
21:01
Fix [609e0045f5]: MouseWheel binding for canvas on MacOS provides wrong values for %x %y check-in: 45d655d3 user: fvogel tags: trunk
2019-02-22
19:00
merge trunk check-in: d0256ba4 user: fvogel tags: revised_text, tip-466
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to doc/wm.n.

   706    706   should display this string in \fIwindow\fR's title bar).  In this
   707    707   case the command returns an empty string.  If \fIstring\fR is not
   708    708   specified then the command returns the current title for the
   709    709   \fIwindow\fR.  The title for a window defaults to its name.
   710    710   .TP
   711    711   \fBwm transient \fIwindow\fR ?\fImaster\fR?
   712    712   .
   713         -If \fImaster\fR is specified, then the window manager is informed
   714         -that \fIwindow\fR is a transient window (e.g. pull-down menu) working
   715         -on behalf of \fImaster\fR (where \fImaster\fR is the
   716         -path name for a top-level window).  If \fImaster\fR
   717         -is specified as an empty string then \fIwindow\fR is marked as not
   718         -being a transient window any more.  Otherwise the command
   719         -returns the path name of \fIwindow\fR's current master, or an
   720         -empty string if \fIwindow\fR is not currently a transient window.
   721         -A transient window will mirror state changes in the master and
   722         -inherit the state of the master when initially mapped. It is an
   723         -error to attempt to make a window a transient of itself.
   724         -The window manager may also decorate a transient window differently, removing
   725         -some features normally present (e.g., minimize and maximize buttons) though
   726         -this is entirely at the discretion of the window manager.
          713  +If \fImaster\fR is specified, then the window manager is informed that
          714  +\fIwindow\fR is a transient window (e.g. pull-down menu) working on
          715  +behalf of \fImaster\fR (where \fImaster\fR is the path name for a
          716  +top-level window).  If \fImaster\fR is specified as an empty string
          717  +then \fIwindow\fR is marked as not being a transient window any more.
          718  +Otherwise the command returns the path name of \fIwindow\fR's current
          719  +master, or an empty string if \fIwindow\fR is not currently a
          720  +transient window.  A transient window will mirror state changes in the
          721  +master and inherit the state of the master when initially mapped. The
          722  +directed graph with an edge from each transient to its master must be
          723  +acyclic.  In particular, it is an error to attempt to make a window a
          724  +transient of itself.  The window manager may also decorate a transient
          725  +window differently, removing some features normally present (e.g.,
          726  +minimize and maximize buttons) though this is entirely at the
          727  +discretion of the window manager.
   727    728   .TP
   728    729   \fBwm withdraw \fIwindow\fR
   729    730   .
   730    731   Arranges for \fIwindow\fR to be withdrawn from the screen.  This
   731    732   causes the window to be unmapped and forgotten about by the window
   732    733   manager.  If the window
   733    734   has never been mapped, then this command

Changes to generic/tkBind.c.

    80     80    * also demand that the event ring be a bit bigger.  It might be wise to
    81     81    * augment the current double-click pattern matching by adding a new
    82     82    * DoubleClick modifier bit which could be set based on the clickCount of the
    83     83    * Apple NSEvent object.
    84     84    */
    85     85   
    86     86   #ifndef TK_MAC_OSX
    87         -  #define EVENT_BUFFER_SIZE 45
           87  +  #define EVENT_BUFFER_SIZE 90
    88     88   #else
    89     89     #define EVENT_BUFFER_SIZE 30
    90     90   #endif
    91     91   
    92     92   typedef struct Tk_BindingTable_ {
    93     93       XEvent eventRing[EVENT_BUFFER_SIZE];
    94     94   				/* Circular queue of recent events (higher

Changes to generic/tkImgGIF.c.

  1030   1030       int len, int rows,
  1031   1031       unsigned char cmap[MAXCOLORMAPSIZE][4],
  1032   1032       int srcX, int srcY,
  1033   1033       int interlace,
  1034   1034       int transparent)
  1035   1035   {
  1036   1036       unsigned char initialCodeSize;
  1037         -    int xpos = 0, ypos = 0, pass = 0, i;
         1037  +    int xpos = 0, ypos = 0, pass = 0, i, count;
  1038   1038       register unsigned char *pixelPtr;
  1039   1039       static const int interlaceStep[] = { 8, 8, 4, 2 };
  1040   1040       static const int interlaceStart[] = { 0, 4, 2, 1 };
  1041   1041       unsigned short prefix[(1 << MAX_LWZ_BITS)];
  1042   1042       unsigned char append[(1 << MAX_LWZ_BITS)];
  1043   1043       unsigned char stack[(1 << MAX_LWZ_BITS)*2];
  1044   1044       register unsigned char *top;
................................................................................
  1248   1248   		ypos = interlaceStart[pass];
  1249   1249   	    }
  1250   1250   	} else {
  1251   1251   	    ypos++;
  1252   1252   	}
  1253   1253   	pixelPtr = imagePtr + (ypos) * len * ((transparent>=0)?4:3);
  1254   1254       }
         1255  +
         1256  +    /*
         1257  +     * Now read until the final zero byte.
         1258  +     * It was observed that there might be 1 length blocks
         1259  +     * (test imgPhoto-14.1) which are not read.
         1260  +     *
         1261  +     * The field "stack" is abused for temporary buffer. it has 4096 bytes
         1262  +     * and we need 256.
         1263  +     * 
         1264  +     * Loop until we hit a 0 length block which is the end sign.
         1265  +     */
         1266  +    while ( 0 < (count = GetDataBlock(gifConfPtr, chan, stack)))
         1267  +    {
         1268  +	if (-1 == count ) {
         1269  +	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
         1270  +		    "error reading GIF image: %s", Tcl_PosixError(interp)));
         1271  +	    return TCL_ERROR;
         1272  +	}
         1273  +    }
  1255   1274       return TCL_OK;
  1256   1275   }
  1257   1276   
  1258   1277   /*
  1259   1278    *----------------------------------------------------------------------
  1260   1279    *
  1261   1280    * GetCode --

Changes to generic/tkInt.decls.

  1012   1012   declare 46 aqua {
  1013   1013       int TkpIsWindowFloating(void *window)
  1014   1014   }
  1015   1015   declare 47 aqua {
  1016   1016       Tk_Window TkMacOSXGetCapture(void)
  1017   1017   }
  1018   1018   declare 49 aqua {
  1019         -    Window TkGetTransientMaster(TkWindow *winPtr)
         1019  +    Tk_Window TkGetTransientMaster(TkWindow *winPtr)
  1020   1020   }
  1021   1021   declare 50 aqua {
  1022   1022       int TkGenerateButtonEvent(int x, int y, Window window, unsigned int state)
  1023   1023   }
  1024   1024   declare 51 aqua {
  1025   1025       void TkGenWMDestroyEvent(Tk_Window tkwin)
  1026   1026   }

Changes to generic/tkIntPlatDecls.h.

   239    239   EXTERN void		TkMacOSXPreprocessMenu(void);
   240    240   /* 46 */
   241    241   EXTERN int		TkpIsWindowFloating(void *window);
   242    242   /* 47 */
   243    243   EXTERN Tk_Window	TkMacOSXGetCapture(void);
   244    244   /* Slot 48 is reserved */
   245    245   /* 49 */
   246         -EXTERN Window		TkGetTransientMaster(TkWindow *winPtr);
          246  +EXTERN Tk_Window	TkGetTransientMaster(TkWindow *winPtr);
   247    247   /* 50 */
   248    248   EXTERN int		TkGenerateButtonEvent(int x, int y, Window window,
   249    249   				unsigned int state);
   250    250   /* 51 */
   251    251   EXTERN void		TkGenWMDestroyEvent(Tk_Window tkwin);
   252    252   /* 52 */
   253    253   EXTERN void		TkMacOSXSetDrawingEnabled(TkWindow *winPtr, int flag);
................................................................................
   388    388       Tk_Window (*tk_TopCoordsToWindow) (Tk_Window tkwin, int rootX, int rootY, int *newX, int *newY); /* 42 */
   389    389       MacDrawable * (*tkMacOSXContainerId) (TkWindow *winPtr); /* 43 */
   390    390       MacDrawable * (*tkMacOSXGetHostToplevel) (TkWindow *winPtr); /* 44 */
   391    391       void (*tkMacOSXPreprocessMenu) (void); /* 45 */
   392    392       int (*tkpIsWindowFloating) (void *window); /* 46 */
   393    393       Tk_Window (*tkMacOSXGetCapture) (void); /* 47 */
   394    394       void (*reserved48)(void);
   395         -    Window (*tkGetTransientMaster) (TkWindow *winPtr); /* 49 */
          395  +    Tk_Window (*tkGetTransientMaster) (TkWindow *winPtr); /* 49 */
   396    396       int (*tkGenerateButtonEvent) (int x, int y, Window window, unsigned int state); /* 50 */
   397    397       void (*tkGenWMDestroyEvent) (Tk_Window tkwin); /* 51 */
   398    398       void (*tkMacOSXSetDrawingEnabled) (TkWindow *winPtr, int flag); /* 52 */
   399    399       unsigned long (*tkpGetMS) (void); /* 53 */
   400    400       void * (*tkMacOSXDrawable) (Drawable drawable); /* 54 */
   401    401       int (*tkpScanWindowId) (Tcl_Interp *interp, const char *string, Window *idPtr); /* 55 */
   402    402   #endif /* AQUA */

Changes to library/bgerror.tcl.

    93     93   #	It tries to execute tkerror, if that fails it posts a dialog box
    94     94   #	containing the error message and gives the user a chance to ask
    95     95   #	to see a stack trace.
    96     96   #
    97     97   # Arguments:
    98     98   #	err - The error message.
    99     99   #
   100         -proc ::tk::dialog::error::bgerror err {
          100  +proc ::tk::dialog::error::bgerror {err {flag 1}} {
   101    101       global errorInfo
   102    102       variable button
   103    103   
   104    104       set info $errorInfo
   105    105   
   106    106       set ret [catch {::tkerror $err} msg];
   107    107       if {$ret != 1} {return -code $ret $msg}
   108    108   
   109         -    # Ok the application's tkerror either failed or was not found
   110         -    # we use the default dialog then :
          109  +    # The application's tkerror either failed or was not found
          110  +    # so we use the default dialog.  But on Aqua we cannot display
          111  +    # the dialog if the background error occurs in an idle task
          112  +    # being processed inside of [NSView drawRect].  In that case
          113  +    # we post the dialog as an after task instead.
   111    114       set windowingsystem [tk windowingsystem]
   112    115       if {$windowingsystem eq "aqua"} {
   113         -	set ok [mc Ok]
   114         -    } else {
   115         -	set ok [mc OK]
          116  +	if $flag {
          117  +	    after 500 [list bgerror "$err" 0]
          118  +	    return
          119  +	}
   116    120       }
   117    121   
          122  +    set ok [mc OK]
   118    123       # Truncate the message if it is too wide (>maxLine characters) or
   119    124       # too tall (>4 lines).  Truncation occurs at the first point at
   120    125       # which one of those conditions is met.
   121    126       set displayedErr ""
   122    127       set lines 0
   123    128       set maxLine 45
   124    129       foreach line [split $err \n] {

Changes to macosx/tkMacOSXDialog.c.

  1946   1946       XEvent *eventPtr)
  1947   1947   {
  1948   1948       FontchooserData *fcdPtr = clientData;
  1949   1949   
  1950   1950       if (eventPtr->type == DestroyNotify) {
  1951   1951   	Tk_DeleteEventHandler(fcdPtr->parent, StructureNotifyMask,
  1952   1952   		FontchooserParentEventHandler, fcdPtr);
  1953         -	fcdPtr->parent = None;
         1953  +	fcdPtr->parent = NULL;
  1954   1954   	FontchooserHideCmd(NULL, NULL, 0, NULL);
  1955   1955       }
  1956   1956   }
  1957   1957   
  1958   1958   /*
  1959   1959    * ----------------------------------------------------------------------
  1960   1960    *

Changes to macosx/tkMacOSXInit.c.

   117    117   -(void)applicationDidFinishLaunching:(NSNotification *)notification
   118    118   {
   119    119       /*
   120    120        * It is not safe to force activation of the NSApp until this
   121    121        * method is called.  Activating too early can cause the menu
   122    122        * bar to be unresponsive.
   123    123        */
          124  +
   124    125       [NSApp activateIgnoringOtherApps: YES];
          126  +
          127  +    /*
          128  +     * Process events to ensure that the root window is fully
          129  +     * initialized. See ticket 56a1823c73.
          130  +     */
          131  +    
          132  +    [NSApp _lockAutoreleasePool];
          133  +    while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS| TCL_DONT_WAIT)) {}
          134  +    [NSApp _unlockAutoreleasePool];
   125    135   }
   126    136   
   127    137   - (void) _setup: (Tcl_Interp *) interp
   128    138   {
   129    139       /*
   130    140        * Remember our interpreter.
   131    141        */

Changes to macosx/tkMacOSXKeyEvent.c.

    20     20   /*
    21     21   #ifdef TK_MAC_DEBUG
    22     22   #define TK_MAC_DEBUG_KEYBOARD
    23     23   #endif
    24     24   */
    25     25   #define NS_KEYLOG 0
    26     26   
    27         -
    28         -static Tk_Window grabWinPtr = NULL;
    29         -				/* Current grab window, NULL if no grab. */
    30     27   static Tk_Window keyboardGrabWinPtr = NULL;
    31     28   				/* Current keyboard grab window. */
    32     29   static NSWindow *keyboardGrabNSWindow = nil;
    33     30                                  /* NSWindow for the current keyboard grab window. */
    34     31   static NSModalSession modalSession = nil;
    35     32   
    36     33   static BOOL processingCompose = NO;
................................................................................
   496    493       Window grab_window,
   497    494       Bool owner_events,
   498    495       int pointer_mode,
   499    496       int keyboard_mode,
   500    497       Time time)
   501    498   {
   502    499       keyboardGrabWinPtr = Tk_IdToWindow(display, grab_window);
   503         -    if (keyboardGrabWinPtr && grabWinPtr) {
          500  +    TkWindow *captureWinPtr = (TkWindow *)TkMacOSXGetCapture(); 
          501  +    if (keyboardGrabWinPtr && captureWinPtr) {
   504    502   	NSWindow *w = TkMacOSXDrawableWindow(grab_window);
   505    503   	MacDrawable *macWin = (MacDrawable *) grab_window;
   506    504   
   507         -	if (w && macWin->toplevel->winPtr == (TkWindow*) grabWinPtr) {
          505  +	if (w && macWin->toplevel->winPtr == (TkWindow*) captureWinPtr) {
   508    506   	    if (modalSession) {
   509    507   		Tcl_Panic("XGrabKeyboard: already grabbed");
   510    508   	    }
   511    509   	    keyboardGrabNSWindow = w;
   512    510   	    [w retain];
   513    511   	    modalSession = [NSApp beginModalSessionForWindow:w];
   514    512   	}
................................................................................
   547    545       }
   548    546       keyboardGrabWinPtr = NULL;
   549    547   }
   550    548   
   551    549   /*
   552    550    *----------------------------------------------------------------------
   553    551    *
   554         - * TkMacOSXGetCapture --
   555         - *
   556         - * Results:
   557         - *	Returns the current grab window
   558         - *
   559         - * Side effects:
   560         - *	None.
   561         - *
   562         - *----------------------------------------------------------------------
   563         - */
   564         -
   565         -Tk_Window
   566         -TkMacOSXGetCapture(void)
   567         -{
   568         -    return grabWinPtr;
   569         -}
   570         -
   571         -/*
   572         - *----------------------------------------------------------------------
   573         - *
   574    552    * TkMacOSXGetModalSession --
   575    553    *
   576    554    * Results:
   577    555    *	Returns the current modal session
   578    556    *
   579    557    * Side effects:
   580    558    *	None.
................................................................................
   583    561    */
   584    562   
   585    563   MODULE_SCOPE NSModalSession
   586    564   TkMacOSXGetModalSession(void)
   587    565   {
   588    566       return modalSession;
   589    567   }
   590         -
   591         -/*
   592         - *----------------------------------------------------------------------
   593         - *
   594         - * TkpSetCapture --
   595         - *
   596         - *	This function captures the mouse so that all future events will be
   597         - *	reported to this window, even if the mouse is outside the window. If
   598         - *	the specified window is NULL, then the mouse is released.
   599         - *
   600         - * Results:
   601         - *	None.
   602         - *
   603         - * Side effects:
   604         - *	Sets the capture flag and captures the mouse.
   605         - *
   606         - *----------------------------------------------------------------------
   607         - */
   608         -
   609         -void
   610         -TkpSetCapture(
   611         -    TkWindow *winPtr)		/* Capture window, or NULL. */
   612         -{
   613         -    while (winPtr && !Tk_IsTopLevel(winPtr)) {
   614         -	winPtr = winPtr->parentPtr;
   615         -    }
   616         -    grabWinPtr = (Tk_Window) winPtr;
   617         -}
   618    568   
   619    569   /*
   620    570    *----------------------------------------------------------------------
   621    571    *
   622    572    * Tk_SetCaretPos --
   623    573    *
   624    574    *	This enables correct placement of the XIM caret. This is called by

Changes to macosx/tkMacOSXMouseEvent.c.

    20     20   typedef struct {
    21     21       unsigned int state;
    22     22       long delta;
    23     23       Window window;
    24     24       Point global;
    25     25       Point local;
    26     26   } MouseEventData;
           27  +static Tk_Window captureWinPtr = NULL; /* Current capture window; may be NULL. */
    27     28   
    28     29   static int		GenerateButtonEvent(MouseEventData *medPtr);
    29     30   static unsigned int	ButtonModifiers2State(UInt32 buttonState,
    30     31   					      UInt32 keyModifiers);
    31     32   
    32     33   #pragma mark TKApplication(TKMouseEvent)
    33     34   
................................................................................
    43     44    * window that it received in a mouse event. If it receives an NSEvent with a
    44     45    * Nil window attribute then the saved window is used.
    45     46    */
    46     47   
    47     48   @implementation TKApplication(TKMouseEvent)
    48     49   - (NSEvent *) tkProcessMouseEvent: (NSEvent *) theEvent
    49     50   {
    50         -#ifdef TK_MAC_DEBUG_EVENTS
    51         -    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
    52         -#endif
    53     51       NSWindow*    eventWindow = [theEvent window];
    54     52       NSEventType	 eventType = [theEvent type];
           53  +    TkWindow *winPtr, *grabWinPtr;
           54  +    Tk_Window tkwin;
    55     55   #if 0
    56     56       NSTrackingArea  *trackingArea = nil;
    57     57       NSInteger eventNumber, clickCount, buttonNumber;
    58     58   #endif
           59  +#ifdef TK_MAC_DEBUG_EVENTS
           60  +    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
           61  +#endif
    59     62       switch (eventType) {
    60     63       case NSMouseEntered:
    61     64       case NSMouseExited:
    62     65       case NSCursorUpdate:
    63     66       case NSLeftMouseDown:
    64     67       case NSLeftMouseUp:
    65     68       case NSRightMouseDown:
................................................................................
    83     86   	if (_windowWithMouse) {
    84     87   	    [_windowWithMouse release];
    85     88   	}
    86     89   	_windowWithMouse = eventWindow;
    87     90   	[_windowWithMouse retain];
    88     91       }
    89     92   
    90         -    /* Create an Xevent to add to the Tk queue. */
           93  +    /*
           94  +     * Compute the mouse position in Tk screen coordinates (global) and in
           95  +     * the Tk coordinates of its containing Tk Window.
           96  +     */
           97  +
    91     98       NSPoint global, local = [theEvent locationInWindow];
    92         -    if (eventWindow) { /* local will be in window coordinates. */
           99  +
          100  +    /*
          101  +     * If the event has no NSWindow, try using the cached NSWindow from the
          102  +     * last mouse event.
          103  +     */
          104  +
          105  +    if (eventWindow == NULL) {
          106  +	eventWindow == _windowWithMouse;
          107  +    }
          108  +    if (eventWindow) {
          109  +
          110  +	/*
          111  +	 * Set the local mouse position to its NSWindow flipped coordinates,
          112  +	 * with the origin at top left, and the global mouse position to the
          113  +	 * flipped screen coordinates.
          114  +	 */
          115  +
    93    116   	global = [eventWindow tkConvertPointToScreen: local];
    94    117   	local.y = [eventWindow frame].size.height - local.y;
    95    118   	global.y = tkMacOSXZeroScreenHeight - global.y;
    96         -    } else { /* local will be in screen coordinates. */
    97         -	if (_windowWithMouse ) {
    98         -	    eventWindow = _windowWithMouse;
    99         -	    global = local;
   100         -	    local = [eventWindow tkConvertPointFromScreen: local];
   101         -	    local.y = [eventWindow frame].size.height - local.y;
   102         -	    global.y = tkMacOSXZeroScreenHeight - global.y;
   103         -	} else { /* We have no window. Use the screen???*/
   104         -	    local.y = tkMacOSXZeroScreenHeight - local.y;
   105         -	    global = local;
   106         -	}
   107         -    }
   108         -
   109         -    TkWindow *winPtr = TkMacOSXGetTkWindow(eventWindow);
   110         -    Tk_Window tkwin = (Tk_Window) winPtr;
   111         -
   112         -    if (tkwin) {
   113         -	TkWindow *grabWinPtr = winPtr->dispPtr->grabWinPtr;
   114         -	if (grabWinPtr &&
   115         -	    grabWinPtr != winPtr &&
   116         -	    !winPtr->dispPtr->grabFlags && /* this means the grab is local. */
   117         -	    grabWinPtr->mainPtr == winPtr->mainPtr) {
   118         -	    return theEvent;
   119         -	}
          119  +
          120  +    } else {
          121  +
          122  +	/*
          123  +	 * As a last resort, with no NSWindow to work with, set both local and
          124  +	 * global to the screen coordinates.
          125  +	 */
          126  +
          127  +	local.y = tkMacOSXZeroScreenHeight - local.y;
          128  +	global = local;
          129  +    }
          130  +
          131  +    /*
          132  +     * Find the toplevel which corresponds to the event NSWindow.
          133  +     */
          134  +
          135  +    winPtr = TkMacOSXGetTkWindow(eventWindow);
          136  +    if (winPtr == NULL) {
          137  +	tkwin = TkMacOSXGetCapture();
          138  +	winPtr = (TkWindow *)tkwin;
   120    139       } else {
   121         -	tkwin = TkMacOSXGetCapture();
          140  +	tkwin = (Tk_Window) winPtr;
   122    141       }
   123    142       if (!tkwin) {
   124    143   	TkMacOSXDbgMsg("tkwin == NULL");
   125    144   	return theEvent; /* Give up.  No window for this event. */
   126         -    } else {
   127         -	winPtr = (TkWindow *)tkwin;
   128    145       }
   129    146   
          147  +    /*
          148  +     * If another toplevel has a grab, we ignore the event.
          149  +     */
          150  +
          151  +    grabWinPtr = winPtr->dispPtr->grabWinPtr;
          152  +    if (grabWinPtr &&
          153  +	grabWinPtr != winPtr &&
          154  +	!winPtr->dispPtr->grabFlags && /* this means the grab is local. */
          155  +	grabWinPtr->mainPtr == winPtr->mainPtr) {
          156  +	return theEvent;
          157  +    }
          158  +
          159  +    /*
          160  +     * Convert local from NSWindow flipped coordinates to the toplevel's
          161  +     * coordinates.
          162  +     */
          163  +
   130    164       local.x -= winPtr->wmInfoPtr->xInParent;
   131    165       local.y -= winPtr->wmInfoPtr->yInParent;
   132    166   
          167  +    /*
          168  +     * Find the containing Tk window, and convert local into the coordinates
          169  +     * of the Tk window.  (The converted local coordinates are only needed
          170  +     * for scrollwheel events.)
          171  +     */
          172  +
   133    173       int win_x, win_y;
   134    174       tkwin = Tk_TopCoordsToWindow(tkwin, local.x, local.y, &win_x, &win_y);
          175  +    local.x = win_x;
          176  +    local.y = win_y;
          177  +
          178  +    /*
          179  +     *  Generate an XEvent for this mouse event.
          180  +     */
   135    181   
   136    182       unsigned int state = 0;
   137    183       NSInteger button = [theEvent buttonNumber];
   138    184       EventRef eventRef = (EventRef)[theEvent eventRef];
   139    185       UInt32 buttons;
   140    186       OSStatus err = GetEventParameter(eventRef, kEventParamMouseChord,
   141    187   				     typeUInt32, NULL, sizeof(UInt32), NULL, &buttons);
................................................................................
   177    223   	state |= Mod3Mask;
   178    224       }
   179    225       if (modifiers & NSFunctionKeyMask) {
   180    226   	state |= Mod4Mask;
   181    227       }
   182    228   
   183    229       if (eventType != NSScrollWheel) {
          230  +
          231  +	/*
          232  +	 * For normal mouse events, Tk_UpdatePointer will send the XEvent.
          233  +	 */
          234  +
   184    235   #ifdef TK_MAC_DEBUG_EVENTS
   185    236   	TKLog(@"UpdatePointer %p x %f.0 y %f.0 %d", tkwin, global.x, global.y, state);
   186    237   #endif
   187    238   	Tk_UpdatePointer(tkwin, global.x, global.y, state);
   188         -    } else { /* handle scroll wheel event */
          239  +    } else {
          240  +
          241  +	/*
          242  +	 * For scroll wheel events we need to send the XEvent here.
          243  +	 */
          244  +	
   189    245   	CGFloat delta;
   190    246   	int coarseDelta;
   191    247   	XEvent xEvent;
   192    248   
   193    249   	xEvent.type = MouseWheelEvent;
   194    250   	xEvent.xbutton.x = local.x;
   195    251   	xEvent.xbutton.y = local.y;
................................................................................
   576    632   						  pt,
   577    633   						  buttonState);
   578    634       CGWarpMouseCursorPosition(pt);
   579    635       CGEventPost(kCGHIDEventTap, theEvent);
   580    636       CFRelease(theEvent);
   581    637   }
   582    638   
          639  +/*
          640  + *----------------------------------------------------------------------
          641  + *
          642  + * TkpSetCapture --
          643  + *
          644  + *	This function captures the mouse so that all future events will be
          645  + *	reported to this window, even if the mouse is outside the window. If
          646  + *	the specified window is NULL, then the mouse is released.
          647  + *
          648  + * Results:
          649  + *	None.
          650  + *
          651  + * Side effects:
          652  + *	Sets the capture flag and captures the mouse.
          653  + *
          654  + *----------------------------------------------------------------------
          655  + */
          656  +
          657  +void
          658  +TkpSetCapture(
          659  +    TkWindow *winPtr)		/* Capture window, or NULL. */
          660  +{
          661  +    while (winPtr && !Tk_IsTopLevel(winPtr)) {
          662  +	winPtr = winPtr->parentPtr;
          663  +    }
          664  +    captureWinPtr = (Tk_Window) winPtr;
          665  +}
          666  +
          667  +/*
          668  + *----------------------------------------------------------------------
          669  + *
          670  + * TkMacOSXGetCapture --
          671  + *
          672  + * Results:
          673  + *	Returns the current grab window
          674  + *
          675  + * Side effects:
          676  + *	None.
          677  + *
          678  + *----------------------------------------------------------------------
          679  + */
          680  +
          681  +Tk_Window
          682  +TkMacOSXGetCapture(void)
          683  +{
          684  +    return captureWinPtr;
          685  +}
          686  +
          687  +
          688  +
   583    689   /*
   584    690    * Local Variables:
   585    691    * mode: objc
   586    692    * c-basic-offset: 4
   587    693    * fill-column: 79
   588    694    * coding: utf-8
   589    695    * End:
   590    696    */

Changes to macosx/tkMacOSXSubwindows.c.

   145    145       }
   146    146   
   147    147       display->request++;
   148    148       macWin->winPtr->flags |= TK_MAPPED;
   149    149       if (Tk_IsTopLevel(macWin->winPtr)) {
   150    150   	if (!Tk_IsEmbedded(macWin->winPtr)) {
   151    151   	    NSWindow *win = TkMacOSXDrawableWindow(window);
          152  +
   152    153   	    /*
   153    154   	     * We want to activate Tk when a toplevel is mapped
   154    155   	     * but we must not supply YES here.  This is because
   155    156   	     * during Tk initialization the root window is mapped
   156    157   	     * before applicationDidFinishLaunching returns. Forcing
   157    158   	     * the app to activate too early can make the menu bar
   158    159   	     * unresponsive.
   159    160   	     */
          161  +
   160    162   	    TkMacOSXApplyWindowAttributes(macWin->winPtr, win);
   161    163   	    [win setExcludedFromWindowsMenu:NO];
   162    164   	    [NSApp activateIgnoringOtherApps:NO];
   163    165   	    [[win contentView] setNeedsDisplay:YES];
   164    166   	    if ( [win canBecomeKeyWindow] ) {
   165    167   		[win makeKeyAndOrderFront:NSApp];
   166    168   	    } else {
   167    169   		[win orderFrontRegardless];
   168    170   	    }
          171  +	    
          172  +	    /*
          173  +	     * In some cases the toplevel will not be drawn unless we process
          174  +	     * all pending events now.  See ticket 56a1823c73.
          175  +	     */
          176  +
          177  +	    [NSApp _lockAutoreleasePool];
          178  +	    while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS| TCL_DONT_WAIT)) {}
          179  +	    [NSApp _unlockAutoreleasePool];
   169    180   	} else {
          181  +
   170    182   	    /*
   171    183   	     * Rebuild the container's clipping region and display
   172    184   	     * the window.
   173    185   	     */
          186  +
   174    187   	    TkWindow *contWinPtr = TkpGetOtherWindow(macWin->winPtr);
   175    188   	    TkMacOSXInvalClipRgns((Tk_Window)contWinPtr);
   176    189   	    TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
   177    190   	}
   178    191   	TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr);
   179    192   
   180    193   	/*
................................................................................
   186    199   	event.xany.display = display;
   187    200   
   188    201   	event.xmap.window = window;
   189    202   	event.xmap.type = MapNotify;
   190    203   	event.xmap.event = window;
   191    204   	event.xmap.override_redirect = macWin->winPtr->atts.override_redirect;
   192    205   	Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
          206  +
   193    207       } else {
          208  +
   194    209   	/*
   195    210   	 * Rebuild the parent's clipping region and display the window.
   196    211   	 *
   197    212   	 */
   198    213   
   199    214   	TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr->parentPtr);
   200    215   	TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
................................................................................
   207    222       event.xany.send_event = False;
   208    223       event.xany.display = display;
   209    224       event.xvisibility.type = VisibilityNotify;
   210    225       event.xvisibility.state = VisibilityUnobscured;
   211    226       NotifyVisibility(macWin->winPtr, &event);
   212    227   
   213    228       /*
   214         -     * Make sure that subwindows get displayed.
          229  +     * This seems to be needed to ensure that all subwindows get displayed.
   215    230        */
   216    231   
   217    232       GenerateConfigureNotify(macWin->winPtr, 1);
   218         -
   219    233   }
   220    234   
   221    235   /*
   222    236    *----------------------------------------------------------------------
   223    237    *
   224    238    * NotifyVisibility --
   225    239    *
................................................................................
   280    294       XEvent event;
   281    295   
   282    296       display->request++;
   283    297       if (Tk_IsTopLevel(winPtr)) {
   284    298   	if (!Tk_IsEmbedded(winPtr) &&
   285    299   		winPtr->wmInfoPtr->hints.initial_state!=IconicState) {
   286    300   	    NSWindow *win = TkMacOSXDrawableWindow(window);
   287         -
   288         -	    if ([win isVisible]) {
   289         -		[[win parentWindow] removeChildWindow:win];
   290         -		[win orderOut:NSApp];
   291         -	    }
          301  +	    [win orderOut:nil];
   292    302   	}
   293    303   	TkMacOSXInvalClipRgns((Tk_Window) winPtr);
   294    304   
   295    305   	/*
   296    306   	 * We only need to send the UnmapNotify event for toplevel windows.
   297    307   	 */
   298    308   

Changes to macosx/tkMacOSXWm.c.

   665    665   {
   666    666       WmInfo *wmPtr = ckalloc(sizeof(WmInfo));
   667    667   
   668    668       wmPtr->winPtr = winPtr;
   669    669       wmPtr->reparent = None;
   670    670       wmPtr->titleUid = NULL;
   671    671       wmPtr->iconName = NULL;
   672         -    wmPtr->master = None;
          672  +    wmPtr->master = NULL;
   673    673       wmPtr->hints.flags = InputHint | StateHint;
   674    674       wmPtr->hints.input = True;
   675    675       wmPtr->hints.initial_state = NormalState;
   676    676       wmPtr->hints.icon_pixmap = None;
   677    677       wmPtr->hints.icon_window = None;
   678    678       wmPtr->hints.icon_x = wmPtr->hints.icon_y = 0;
   679    679       wmPtr->hints.icon_mask = None;
   680    680       wmPtr->hints.window_group = None;
   681    681       wmPtr->leaderName = NULL;
   682         -    wmPtr->masterWindowName = NULL;
   683    682       wmPtr->icon = NULL;
   684    683       wmPtr->iconFor = NULL;
   685    684       wmPtr->transientPtr = NULL;
   686    685       wmPtr->sizeHintsFlags = 0;
   687    686       wmPtr->minWidth = wmPtr->minHeight = 1;
   688    687       wmPtr->maxWidth = 0;
   689    688       wmPtr->maxHeight = 0;
................................................................................
   880    879    */
   881    880   
   882    881   void
   883    882   TkWmDeadWindow(
   884    883       TkWindow *winPtr)		/* Top-level window that's being deleted. */
   885    884   {
   886    885       WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2;
   887         -    TkDisplay *dispPtr = TkGetDisplayList();
   888    886   
   889    887       if (wmPtr == NULL) {
   890    888   	return;
   891    889       }
   892         -    
   893         -    /* 
          890  +
          891  +    /*
   894    892        *If the dead window is a transient, remove it from the master's list.
   895    893        */
   896    894   
   897    895       RemoveTransient(winPtr);
   898         -
   899    896       Tk_ManageGeometry((Tk_Window) winPtr, NULL, NULL);
   900    897       Tk_DeleteEventHandler((Tk_Window) winPtr, StructureNotifyMask,
   901    898   	    TopLevelEventProc, winPtr);
   902    899       if (wmPtr->hints.flags & IconPixmapHint) {
   903    900   	Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);
   904    901       }
   905    902       if (wmPtr->hints.flags & IconMaskHint) {
................................................................................
   907    904       }
   908    905       if (wmPtr->iconName != NULL) {
   909    906   	ckfree(wmPtr->iconName);
   910    907       }
   911    908       if (wmPtr->leaderName != NULL) {
   912    909   	ckfree(wmPtr->leaderName);
   913    910       }
   914         -    if (wmPtr->masterWindowName != NULL) {
   915         -	ckfree(wmPtr->masterWindowName);
   916         -    }
   917    911       if (wmPtr->icon != NULL) {
   918    912   	wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
   919    913   	wmPtr2->iconFor = NULL;
   920    914       }
   921    915       if (wmPtr->iconFor != NULL) {
   922    916   	wmPtr2 = ((TkWindow *) wmPtr->iconFor)->wmInfoPtr;
   923    917   	wmPtr2->icon = NULL;
................................................................................
   938    932   	Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr);
   939    933       }
   940    934   
   941    935       /*
   942    936        * If the dead window has a transient, remove references to it from
   943    937        * the transient.
   944    938        */
   945         -    
          939  +
   946    940       for (Transient *transientPtr = wmPtr->transientPtr;
   947    941       	 transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
   948    942       	TkWindow *winPtr2 = transientPtr->winPtr;
   949         -    	Window master = TkGetTransientMaster(winPtr2);
   950         -    	TkWindow *masterPtr = (TkWindow *)Tk_IdToWindow(dispPtr->display, master); 
          943  +    	TkWindow *masterPtr = (TkWindow *)TkGetTransientMaster(winPtr2);
   951    944       	if (masterPtr == winPtr) {
   952    945       	    wmPtr2 = winPtr2->wmInfoPtr;
   953         -    	    wmPtr2->master = None;
   954         -    	    ckfree(wmPtr2->masterWindowName);
   955         -    	    wmPtr2->masterWindowName = NULL;
          946  +    	    wmPtr2->master = NULL;
   956    947       	}
   957    948       }
   958    949   
   959    950       while (wmPtr->transientPtr != NULL) {
   960    951   	Transient *transientPtr = wmPtr->transientPtr;
   961    952   	wmPtr->transientPtr = transientPtr->nextPtr;
   962    953   	ckfree(transientPtr);
................................................................................
  1787   1778       TkWindow *winPtr,		/* Toplevel to work with */
  1788   1779       Tcl_Interp *interp,		/* Current interpreter. */
  1789   1780       int objc,			/* Number of arguments. */
  1790   1781       Tcl_Obj *const objv[])	/* Argument objects. */
  1791   1782   {
  1792   1783       register WmInfo *wmPtr = winPtr->wmInfoPtr;
  1793   1784       NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
  1794         -    TkDisplay *dispPtr = TkGetDisplayList();
  1795   1785   
  1796   1786       if (objc != 3) {
  1797   1787   	Tcl_WrongNumArgs(interp, 2, objv, "window");
  1798   1788   	return TCL_ERROR;
  1799   1789       }
  1800   1790   
  1801   1791       if (wmPtr->iconFor != NULL) {
................................................................................
  1826   1816        * it was withdrawn by the master.
  1827   1817        */
  1828   1818   
  1829   1819       for (Transient *transientPtr = wmPtr->transientPtr;
  1830   1820   	 transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
  1831   1821   	TkWindow *winPtr2 = transientPtr->winPtr;
  1832   1822   	WmInfo *wmPtr2 = winPtr2->wmInfoPtr;
  1833         -	Window master = TkGetTransientMaster(winPtr2);
  1834         -	TkWindow *masterPtr = (TkWindow *)Tk_IdToWindow(dispPtr->display, master); 
         1823  +	TkWindow *masterPtr = (TkWindow *)TkGetTransientMaster(winPtr2);
  1835   1824       	if (masterPtr == winPtr) {
  1836         -	    if (!(wmPtr2->hints.initial_state == WithdrawnState &&
  1837         -		  (transientPtr->flags & WITHDRAWN_BY_MASTER) == 0)) {
         1825  +	    if ((wmPtr2->hints.initial_state == WithdrawnState &&
         1826  +		 (transientPtr->flags & WITHDRAWN_BY_MASTER) != 0)) {
  1838   1827   		TkpWmSetState(winPtr2, NormalState);
  1839   1828   		transientPtr->flags &= ~WITHDRAWN_BY_MASTER;
  1840   1829   	    }
  1841   1830   	}
  1842   1831       }
  1843         -    
         1832  +
  1844   1833       return TCL_OK;
  1845   1834   }
  1846   1835   
  1847   1836   /*
  1848   1837    *----------------------------------------------------------------------
  1849   1838    *
  1850   1839    * WmFocusmodelCmd --
................................................................................
  2323   2312   WmIconifyCmd(
  2324   2313       Tk_Window tkwin,		/* Main window of the application. */
  2325   2314       TkWindow *winPtr,		/* Toplevel to work with */
  2326   2315       Tcl_Interp *interp,		/* Current interpreter. */
  2327   2316       int objc,			/* Number of arguments. */
  2328   2317       Tcl_Obj *const objv[])	/* Argument objects. */
  2329   2318   {
  2330         -    TkDisplay *dispPtr = TkGetDisplayList();
  2331   2319       register WmInfo *wmPtr = winPtr->wmInfoPtr;
  2332   2320       if (objc != 3) {
  2333   2321   	Tcl_WrongNumArgs(interp, 2, objv, "window");
  2334   2322   	return TCL_ERROR;
  2335   2323       }
  2336   2324   
  2337   2325       if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
  2338   2326   	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
  2339   2327   		"can't iconify \"%s\": override-redirect flag is set",
  2340   2328   		winPtr->pathName));
  2341   2329   	Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "OVERRIDE_REDIRECT",
  2342   2330   		NULL);
  2343   2331   	return TCL_ERROR;
  2344         -    } else if (wmPtr->master != None) {
         2332  +    } else if (wmPtr->master != NULL) {
  2345   2333   	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
  2346   2334   		"can't iconify \"%s\": it is a transient", winPtr->pathName));
  2347   2335   	Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "TRANSIENT", NULL);
  2348   2336   	return TCL_ERROR;
  2349   2337       } else if (wmPtr->iconFor != NULL) {
  2350   2338   	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
  2351   2339   		"can't iconify %s: it is an icon for %s",
................................................................................
  2369   2357        * If this window has a transient the transient must be withdrawn when
  2370   2358        * the master is iconified.
  2371   2359        */
  2372   2360   
  2373   2361       for (Transient *transientPtr = wmPtr->transientPtr;
  2374   2362   	 transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
  2375   2363   	TkWindow *winPtr2 = transientPtr->winPtr;
  2376         -	Window master = TkGetTransientMaster(winPtr2);
  2377         -	TkWindow *masterPtr = (TkWindow *)Tk_IdToWindow(dispPtr->display, master); 
         2364  +	TkWindow *masterPtr = (TkWindow *)TkGetTransientMaster(winPtr2);
  2378   2365       	if (masterPtr == winPtr &&
  2379   2366   	    winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) {
  2380   2367   	    TkpWmSetState(winPtr2, WithdrawnState);
  2381   2368   	    transientPtr->flags |= WITHDRAWN_BY_MASTER;
  2382   2369   	}
  2383   2370       }
  2384   2371   
................................................................................
  3462   3449   		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
  3463   3450   			"can't iconify \"%s\": override-redirect flag is set",
  3464   3451   			winPtr->pathName));
  3465   3452   		Tcl_SetErrorCode(interp, "TK", "WM", "STATE",
  3466   3453   			"OVERRIDE_REDIRECT", NULL);
  3467   3454   		return TCL_ERROR;
  3468   3455   	    }
  3469         -	    if (wmPtr->master != None) {
         3456  +	    if (wmPtr->master != NULL) {
  3470   3457   		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
  3471   3458   			"can't iconify \"%s\": it is a transient",
  3472   3459   			winPtr->pathName));
  3473   3460   		Tcl_SetErrorCode(interp, "TK", "WM", "STATE", "TRANSIENT",
  3474   3461   			NULL);
  3475   3462   		return TCL_ERROR;
  3476   3463   	    }
................................................................................
  3577   3564       TkWindow *winPtr,		/* Toplevel to work with */
  3578   3565       Tcl_Interp *interp,		/* Current interpreter. */
  3579   3566       int objc,			/* Number of arguments. */
  3580   3567       Tcl_Obj *const objv[])	/* Argument objects. */
  3581   3568   {
  3582   3569       register WmInfo *wmPtr = winPtr->wmInfoPtr;
  3583   3570       Tk_Window master;
         3571  +    TkWindow *masterPtr, *w;
  3584   3572       WmInfo *wmPtr2;
  3585         -    char *masterWindowName;
  3586         -    int length;
         3573  +    Transient *transient;
  3587   3574   
  3588   3575       if ((objc != 3) && (objc != 4)) {
  3589   3576   	Tcl_WrongNumArgs(interp, 2, objv, "window ?master?");
  3590   3577   	return TCL_ERROR;
  3591   3578       }
  3592   3579       if (objc == 3) {
  3593         -	if (wmPtr->master != None) {
         3580  +	if (wmPtr->master != NULL) {
  3594   3581   	    Tcl_SetObjResult(interp,
  3595         -		    Tcl_NewStringObj(wmPtr->masterWindowName, -1));
         3582  +		Tcl_NewStringObj(Tk_PathName(wmPtr->master), -1));
  3596   3583   	}
  3597   3584   	return TCL_OK;
  3598   3585       }
  3599   3586       if (Tcl_GetString(objv[3])[0] == '\0') {
  3600   3587   	RemoveTransient(winPtr);
  3601   3588   
  3602   3589       } else {
  3603   3590   	if (TkGetWindowFromObj(interp, tkwin, objv[3], &master) != TCL_OK) {
  3604   3591   	    return TCL_ERROR;
  3605   3592   	}
  3606         -	TkWindow *masterPtr = (TkWindow*) master;
         3593  +	masterPtr = (TkWindow*) master;
  3607   3594   	while (!Tk_TopWinHierarchy(masterPtr)) {
  3608   3595   
  3609   3596               /*
  3610   3597                * Ensure that the master window is actually a Tk toplevel.
  3611   3598                */
  3612   3599   
  3613   3600               masterPtr = masterPtr->parentPtr;
................................................................................
  3628   3615   	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
  3629   3616   		    "can't make \"%s\" a master: it is an icon for %s",
  3630   3617   		    Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor)));
  3631   3618   	    Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL);
  3632   3619   	    return TCL_ERROR;
  3633   3620   	}
  3634   3621   
  3635         -	if (masterPtr == winPtr) {
  3636         -	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
  3637         -		    "can't make \"%s\" its own master", Tk_PathName(winPtr)));
  3638         -	    Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
  3639         -	    return TCL_ERROR;
         3622  +	for (w = masterPtr; w != NULL && w->wmInfoPtr != NULL;
         3623  +	     w = (TkWindow *)w->wmInfoPtr->master) {
         3624  +	    if (w == winPtr) {
         3625  +		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
         3626  +		    "setting \"%s\" as master creates a transient/master cycle",
         3627  +		    Tk_PathName(masterPtr)));
         3628  +		Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
         3629  +		return TCL_ERROR;
         3630  +	    }
  3640   3631   	}
  3641   3632   
  3642   3633   	/*
  3643         -	 * Add the transient to the master's list.
         3634  +	 * Add the transient to the master's list, if it not already there.
  3644   3635   	 */
  3645         -
  3646         -	Transient *transient = ckalloc(sizeof(Transient));
  3647         -	transient->winPtr = winPtr;
  3648         -	transient->flags = 0;
  3649         -	transient->nextPtr = wmPtr->transientPtr;
  3650         -	wmPtr2->transientPtr = transient;
  3651   3636   	
         3637  +	for (transient = wmPtr2->transientPtr;
         3638  +	     transient != NULL && transient->winPtr != winPtr;
         3639  +	     transient = transient->nextPtr) {}
         3640  +	if (transient == NULL) {
         3641  +	    transient = ckalloc(sizeof(Transient));
         3642  +	    transient->winPtr = winPtr;
         3643  +	    transient->flags = 0;
         3644  +	    transient->nextPtr = wmPtr2->transientPtr;
         3645  +	    wmPtr2->transientPtr = transient;
         3646  +	}
         3647  +
  3652   3648   	/*
  3653   3649   	 * If the master is withdrawn or iconic then withdraw the transient.
  3654   3650   	 */
  3655   3651   
  3656   3652   	if ((wmPtr2->hints.initial_state == WithdrawnState ||
  3657   3653   	     wmPtr2->hints.initial_state == IconicState) &&
  3658   3654   	    wmPtr->hints.initial_state != WithdrawnState){
  3659   3655   	    TkpWmSetState(winPtr, WithdrawnState);
  3660   3656   	    transient->flags |= WITHDRAWN_BY_MASTER;
  3661   3657   	}
  3662   3658   
  3663         -	wmPtr->master = Tk_WindowId(masterPtr);
  3664         -	masterWindowName = masterPtr->pathName;
  3665         -	length = strlen(masterWindowName);
  3666         -	if (wmPtr->masterWindowName != NULL) {
  3667         -	    ckfree(wmPtr->masterWindowName);
  3668         -	}
  3669         -	wmPtr->masterWindowName = ckalloc(length+1);
  3670         -	strcpy(wmPtr->masterWindowName, masterWindowName);
         3659  +	wmPtr->master = (Tk_Window)masterPtr;
  3671   3660       }
  3672   3661       ApplyMasterOverrideChanges(winPtr, NULL);
  3673   3662       return TCL_OK;
  3674   3663   }
  3675   3664   
  3676   3665   /*
  3677   3666    *----------------------------------------------------------------------
................................................................................
  3693   3682    */
  3694   3683   
  3695   3684   static void
  3696   3685   RemoveTransient(
  3697   3686       TkWindow *winPtr)
  3698   3687   {
  3699   3688       WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2;
  3700         -    TkDisplay *dispPtr = TkGetDisplayList();
  3701   3689       TkWindow *masterPtr;
  3702         -    if (wmPtr == NULL || wmPtr->master == None) {
         3690  +    Transient *T, *temp;
         3691  +    
         3692  +    if (wmPtr == NULL || wmPtr->master == NULL) {
  3703   3693   	return;
  3704   3694       }
  3705         -    masterPtr = (TkWindow*)Tk_IdToWindow(dispPtr->display, wmPtr->master);
         3695  +    masterPtr = (TkWindow*)wmPtr->master;
  3706   3696       wmPtr2 = masterPtr->wmInfoPtr;
  3707   3697       if (wmPtr2 == NULL) {
  3708   3698   	return;
  3709   3699       }
  3710         -    wmPtr->master = None;
  3711         -    if (wmPtr->masterWindowName != NULL) {
  3712         -	ckfree(wmPtr->masterWindowName);
         3700  +    wmPtr->master = NULL;
         3701  +    T = wmPtr2->transientPtr;
         3702  +    while (T != NULL) {
         3703  +	if (T->winPtr != winPtr) {
         3704  +	    break;
         3705  +	}
         3706  +	temp = T->nextPtr;
         3707  +	ckfree(T);
         3708  +	T = temp;
  3713   3709       }
  3714         -    wmPtr->masterWindowName = NULL;
  3715         -    Transient *temp, *cursor = wmPtr2->transientPtr;
  3716         -    if (cursor->winPtr == winPtr) {
  3717         -	temp = cursor->nextPtr;
  3718         -	ckfree(cursor);
  3719         -	cursor = temp;
  3720         -	masterPtr->wmInfoPtr->transientPtr = cursor;
  3721         -    }
  3722         -    while (cursor != NULL) {
  3723         -	if (cursor->winPtr == winPtr) {
  3724         -	    temp = cursor->nextPtr;
  3725         -	    ckfree(cursor);
  3726         -	    cursor = temp;
         3710  +    wmPtr2->transientPtr = T;
         3711  +    while (T != NULL) {
         3712  +	if (T->nextPtr && T->nextPtr->winPtr == winPtr) {
         3713  +	    temp = T->nextPtr;
         3714  +	    T->nextPtr = temp->nextPtr;
         3715  +	    ckfree(temp);
         3716  +	} else {
         3717  +	    T = T->nextPtr;
  3727   3718   	}
  3728   3719       }
  3729   3720   }
  3730   3721   
  3731   3722   /*
  3732   3723    *----------------------------------------------------------------------
  3733   3724    *
................................................................................
  3765   3756   		"can't withdraw %s: it is an icon for %s",
  3766   3757   		Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));
  3767   3758   	Tcl_SetErrorCode(interp, "TK", "WM", "WITHDRAW", "ICON", NULL);
  3768   3759   	return TCL_ERROR;
  3769   3760       }
  3770   3761   
  3771   3762       TkpWmSetState(winPtr, WithdrawnState);
  3772         -    
         3763  +
  3773   3764       NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
  3774         -    TkDisplay *dispPtr = TkGetDisplayList();
  3775   3765       [win orderOut:nil];
  3776   3766       [win setExcludedFromWindowsMenu:YES];
  3777   3767   
  3778   3768       /*
  3779   3769        * If this window has a transient, the transient must also be withdrawn.
  3780   3770        */
  3781   3771       for (Transient *transientPtr = wmPtr->transientPtr;
  3782   3772   	 transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
  3783   3773   	TkWindow *winPtr2 = transientPtr->winPtr;
  3784         -	Window master = TkGetTransientMaster(winPtr2);
  3785         -	TkWindow *masterPtr = (TkWindow *)Tk_IdToWindow(dispPtr->display, master); 
         3774  +	TkWindow *masterPtr = (TkWindow *)TkGetTransientMaster(winPtr2);
  3786   3775       	if (masterPtr == winPtr &&
  3787   3776   	    winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) {
  3788   3777   	    TkpWmSetState(winPtr2, WithdrawnState);
  3789   3778   	    transientPtr->flags |= WITHDRAWN_BY_MASTER;
  3790   3779   	}
  3791   3780       }
  3792   3781   
................................................................................
  5331   5320    *
  5332   5321    * Side effects:
  5333   5322    *	None.
  5334   5323    *
  5335   5324    *----------------------------------------------------------------------
  5336   5325    */
  5337   5326   
  5338         -Window
         5327  +Tk_Window
  5339   5328   TkGetTransientMaster(
  5340   5329       TkWindow *winPtr)
  5341   5330   {
  5342   5331       if (winPtr->wmInfoPtr != NULL) {
  5343         -	return winPtr->wmInfoPtr->master;
         5332  +	return (Tk_Window)winPtr->wmInfoPtr->master;
  5344   5333       }
  5345         -    return None;
         5334  +    return NULL;
  5346   5335   }
  5347   5336   
  5348   5337   /*
  5349   5338    *----------------------------------------------------------------------
  5350   5339    *
  5351   5340    * TkMacOSXGetXWindow --
  5352   5341    *
................................................................................
  6575   6564   void
  6576   6565   TkMacOSXApplyWindowAttributes(
  6577   6566       TkWindow *winPtr,
  6578   6567       NSWindow *macWindow)
  6579   6568   {
  6580   6569       WmInfo *wmPtr = winPtr->wmInfoPtr;
  6581   6570       ApplyWindowAttributeFlagChanges(winPtr, macWindow, 0, 0, 0, 1);
  6582         -    if (wmPtr->master != None || winPtr->atts.override_redirect) {
         6571  +    if (wmPtr->master != NULL || winPtr->atts.override_redirect) {
  6583   6572   	ApplyMasterOverrideChanges(winPtr, macWindow);
  6584   6573       }
  6585   6574   }
  6586   6575   
  6587   6576   /*
  6588   6577    *----------------------------------------------------------------------
  6589   6578    *
................................................................................
  6712   6701   		/*
  6713   6702   		 * Exclude overrideredirect, transient, and "help"-styled
  6714   6703   		 * windows from moving into their own fullscreen space.
  6715   6704   		 *
  6716   6705   		 */
  6717   6706   
  6718   6707   		if ((winPtr->atts.override_redirect) ||
  6719         -		    (wmPtr->master != None) ||
         6708  +		    (wmPtr->master != NULL) ||
  6720   6709   		    (winPtr->wmInfoPtr->macClass == kHelpWindowClass)) {
  6721   6710   		    b |= (NSWindowCollectionBehaviorCanJoinAllSpaces |
  6722   6711   			  NSWindowCollectionBehaviorFullScreenAuxiliary);
  6723   6712   		} else {
  6724   6713   		    NSSize screenSize = [[macWindow screen]frame].size;
  6725   6714   		    b |= NSWindowCollectionBehaviorFullScreenPrimary;
  6726   6715   
................................................................................
  6789   6778       NSWindow *macWindow)
  6790   6779   {
  6791   6780       WmInfo *wmPtr = winPtr->wmInfoPtr;
  6792   6781       UInt64 oldAttributes = wmPtr->attributes;
  6793   6782       int oldFlags = wmPtr->flags;
  6794   6783       unsigned long styleMask;
  6795   6784       NSRect structureRect;
         6785  +    NSWindow *parentWindow;
  6796   6786   
  6797   6787       if (!macWindow && winPtr->window != None &&
  6798   6788   	    TkMacOSXHostToplevelExists(winPtr)) {
  6799   6789   	macWindow = TkMacOSXDrawableWindow(winPtr->window);
  6800   6790       }
  6801   6791       styleMask = [macWindow styleMask];
  6802   6792   
................................................................................
  6829   6819   		        NSMiniaturizableWindowMask |
  6830   6820   		        NSResizableWindowMask;
  6831   6821   	} else {
  6832   6822   	    styleMask |= NSTitledWindowMask;
  6833   6823   	}
  6834   6824       }
  6835   6825       if (macWindow) {
  6836         -	NSWindow *parentWindow = [macWindow parentWindow];
  6837   6826   	structureRect = [NSWindow frameRectForContentRect:NSZeroRect
  6838   6827   				  styleMask:styleMask];
  6839   6828   
  6840   6829   	/*
  6841   6830   	 * Synchronize the wmInfoPtr to match the new window configuration
  6842   6831   	 * so windowBoundsChanged won't corrupt the window manager info.
  6843   6832   	 */
................................................................................
  6848   6837   	wmPtr->parentHeight = winPtr->changes.height + structureRect.size.height;
  6849   6838   	if (winPtr->atts.override_redirect) {
  6850   6839   	    [macWindow setExcludedFromWindowsMenu:YES];
  6851   6840   	    [macWindow setStyleMask:styleMask];
  6852   6841   	    if (wmPtr->hints.initial_state == NormalState) {
  6853   6842   		[macWindow orderFront:nil];
  6854   6843   	    }
  6855         -	    if (wmPtr->master != None) {
         6844  +	    if (wmPtr->master != NULL) {
  6856   6845   		wmPtr->flags |= WM_TOPMOST;
  6857   6846   	    } else {
  6858   6847   		wmPtr->flags &= ~WM_TOPMOST;
  6859   6848   	    }
  6860   6849   	} else {
  6861   6850   	    const char *title = winPtr->wmInfoPtr->titleUid;
  6862   6851   	    if (!title) {
................................................................................
  6864   6853   	    }
  6865   6854   	    [macWindow setStyleMask:styleMask];
  6866   6855   	    [macWindow setTitle:[NSString stringWithUTF8String:title]];
  6867   6856   	    [macWindow setExcludedFromWindowsMenu:NO];
  6868   6857   	    wmPtr->flags &= ~WM_TOPMOST;
  6869   6858   	}
  6870   6859   	if (wmPtr->master != None) {
  6871         -	    TkDisplay *dispPtr = TkGetDisplayList();
  6872         -	    TkWindow *masterWinPtr = (TkWindow *)
  6873         -		    Tk_IdToWindow(dispPtr->display, wmPtr->master);
  6874         -
         6860  +	    TkWindow *masterWinPtr = (TkWindow *)wmPtr->master;
  6875   6861   	    if (masterWinPtr && masterWinPtr->window != None &&
  6876   6862   		    TkMacOSXHostToplevelExists(masterWinPtr)) {
  6877         -		NSWindow *masterMacWin =
  6878         -			TkMacOSXDrawableWindow(masterWinPtr->window);
         6863  +		NSWindow *masterMacWin = TkMacOSXDrawableWindow(
         6864  +					     masterWinPtr->window);
  6879   6865   
  6880         -		if (masterMacWin && masterMacWin != parentWindow &&
  6881         -			(winPtr->flags & TK_MAPPED)) {
  6882         -		    if (parentWindow) {
         6866  +		/*
         6867  +		 * Try to add the transient window as a child window of the
         6868  +		 * master. A child NSWindow retains its relative position with
         6869  +		 * respect to the parent when the parent is moved.  This is
         6870  +		 * pointless if the parent is offscreen, and adding a child to
         6871  +		 * an offscreen window causes the parent to be displayed as a
         6872  +		 * zombie.  So we only do this if the parent is visible.
         6873  +		 */
         6874  +
         6875  +		if (masterMacWin &&
         6876  +		    [masterMacWin isVisible] &&
         6877  +		    (winPtr->flags & TK_MAPPED)) {
         6878  +
         6879  +		    /*
         6880  +		     * If the transient is already a child of some other window,
         6881  +		     * remove it.
         6882  +		     */
         6883  +
         6884  +		    parentWindow = [macWindow parentWindow];
         6885  +		    if (parentWindow && parentWindow != masterMacWin) {
  6883   6886   			[parentWindow removeChildWindow:macWindow];
  6884   6887   		    }
         6888  +
  6885   6889   		    [masterMacWin addChildWindow:macWindow
  6886         -			    ordered:NSWindowAbove];
  6887         -		    if (wmPtr->flags & WM_TOPMOST) {
  6888         -			[macWindow setLevel:kCGUtilityWindowLevel];
         6890  +					     ordered:NSWindowAbove];
  6889   6891   		    }
  6890         -		}
         6892  +	    }
         6893  +	} else {
         6894  +	    parentWindow = [macWindow parentWindow];
         6895  +	    if (parentWindow) {
         6896  +		[parentWindow removeChildWindow:macWindow];
  6891   6897   	    }
  6892         -	} else if (parentWindow) {
  6893         -	    [parentWindow removeChildWindow:macWindow];
         6898  +	}
         6899  +	if (wmPtr->flags & WM_TOPMOST) {
         6900  +	    [macWindow setLevel:kCGUtilityWindowLevel];
  6894   6901   	}
  6895   6902   	ApplyWindowAttributeFlagChanges(winPtr, macWindow, oldAttributes,
  6896   6903   		oldFlags, 0, 0);
  6897   6904       }
  6898   6905   }
  6899   6906   
  6900   6907   /*

Changes to macosx/tkMacOSXWm.h.

    61     61   				 * that is a child of the root window (may not
    62     62   				 * be window's immediate parent). If the window
    63     63   				 * isn't reparented, this has the value
    64     64   				 * None. */
    65     65       Tk_Uid titleUid;		/* Title to display in window caption. If NULL,
    66     66   				 * use name of widget. */
    67     67       char *iconName;		/* Name to display in icon. */
    68         -    Window master;		/* Master window for TRANSIENT_FOR property, or
           68  +    Tk_Window master;		/* Master window for TRANSIENT_FOR property, or
    69     69   				 * None. */
    70     70       XWMHints hints;		/* Various pieces of information for window
    71     71   				 * manager. */
    72     72       char *leaderName;		/* Path name of leader of window group
    73     73   				 * (corresponds to hints.window_group).
    74     74   				 * Malloc-ed. Note: this field doesn't get
    75     75   				 * updated if leader is destroyed. */
    76         -    char *masterWindowName;	/* Path name of window specified as master in
    77         -				 * "wm transient" command, or NULL. Malloc-ed.
    78         -				 * Note: this field doesn't get updated if
    79         -				 * masterWindowName is destroyed. */
    80     76       Tk_Window icon;		/* Window to use as icon for this window, or
    81     77   				 * NULL. */
    82     78       Tk_Window iconFor;		/* Window for which this window is icon, or
    83     79   				 * NULL if this isn't an icon for anyone. */
    84     80       Transient *transientPtr;    /* First item in a list of all transient windows
    85     81   				 * belonging to this window, or NULL if there
    86     82   				 * are no transients. */

Changes to tests/imgPhoto.test.

  1749   1749       # This erroneously produced "malformed image" error.
  1750   1750       # The animated GIF "deferredClearCode.gif" has two frames, and calling for -index 2
  1751   1751       # simply is an easy way to trigger the problem of improper management of a deferred
  1752   1752       # clear code. The effect was that the GIF decoder bailed out before the end of the
  1753   1753       # image reading, and produced the inappropriate "malformed image error".
  1754   1754       image create photo -file $fileName -format "gif -index 2"
  1755   1755   } -returnCodes error -result {no image data for this index}
         1756  +
         1757  +test imgPhoto-14.6 {Access Subimage after Subimage with buffer overflow. Ticket 4da2191b} -setup {
         1758  +    set data {
         1759  +	R0lGODlhYwA5APcAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgAysnGy8hKzM
         1760  +	hASs3MTcjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
         1761  +	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
         1762  +	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
         1763  +	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
         1764  +	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
         1765  +	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
         1766  +	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
         1767  +	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
         1768  +	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
         1769  +	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
         1770  +	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
         1771  +	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
         1772  +	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
         1773  +	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
         1774  +	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
         1775  +	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwP8AAAD/
         1776  +	AP//AAAA//8A/wD//////ywAAAAAYwA5AAAI/wAZCBxIsKDBgwgTKlzIsKHD
         1777  +	hxAjSpxIsaLFixgzatzIsaPHjyBDihxJsqTJkyhTqlzJsqXLlzBjypxJs6bN
         1778  +	mzhz6tzJs6fPn0CDCh1KtKhRiwoSKEXAtGlTpUqPGkyagOmCq1edNsWalWkC
         1779  +	BUSXIuDqFepBqFWtZv3KU+zYrkrBSqT6dgECtjOTbu16NwFHvV3lshRLti/J
         1780  +	qlgRCE6ZuO9ik4Dt+k0ZVyZiyVIvXr77ODPEy5g9T4zMWfTEzXdNz1VbWvXn
         1781  +	uqldP1TAOrbshqBb314Y2W7n3Qdpv7UNPCHpycUVbv6dnODy5sqzQldIe8H0
         1782  +	hciva9/Ovbv37+BzBgE7ACH5BAFkAAMALAAAAAAEAAQAAAMEKLrckgA7
         1783  +    }
         1784  +} -body {
         1785  +    image create photo photo1 -data $data -format "GIF -index 1"
         1786  +} -cleanup {
         1787  +    catch {image delete photo1}
         1788  +} -result photo1
  1756   1789   
  1757   1790   test imgPhoto-15.1 {photo images can fail to allocate memory gracefully} -constraints {
  1758   1791       nonPortable
  1759   1792   } -body {
  1760   1793       # This is not portable to very large machines with more than around 3GB of
  1761   1794       # free memory available...
  1762   1795       image create photo -width 32000 -height 32000

Changes to tests/wm.test.

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

Changes to unix/tkUnixWm.c.

  3516   3516       Tk_Window tkwin,		/* Main window of the application. */
  3517   3517       TkWindow *winPtr,		/* Toplevel to work with */
  3518   3518       Tcl_Interp *interp,		/* Current interpreter. */
  3519   3519       int objc,			/* Number of arguments. */
  3520   3520       Tcl_Obj *const objv[])	/* Argument objects. */
  3521   3521   {
  3522   3522       register WmInfo *wmPtr = winPtr->wmInfoPtr;
  3523         -    TkWindow *masterPtr = wmPtr->masterPtr;
         3523  +    TkWindow *masterPtr = wmPtr->masterPtr, *w;
  3524   3524       WmInfo *wmPtr2;
  3525   3525   
  3526   3526       if ((objc != 3) && (objc != 4)) {
  3527   3527   	Tcl_WrongNumArgs(interp, 2, objv, "window ?master?");
  3528   3528   	return TCL_ERROR;
  3529   3529       }
  3530   3530       if (objc == 3) {
................................................................................
  3585   3585   	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
  3586   3586   		    "can't make \"%s\" a master: it is an icon for %s",
  3587   3587   		    Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor)));
  3588   3588   	    Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL);
  3589   3589   	    return TCL_ERROR;
  3590   3590   	}
  3591   3591   
  3592         -	if (masterPtr == winPtr) {
  3593         -	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
  3594         -		    "can't make \"%s\" its own master", Tk_PathName(winPtr)));
  3595         -	    Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
  3596         -	    return TCL_ERROR;
  3597         -	} else if (masterPtr != wmPtr->masterPtr) {
         3592  +	for (w = masterPtr; w != NULL && w->wmInfoPtr != NULL;
         3593  +	     w = (TkWindow *)w->wmInfoPtr->masterPtr) {
         3594  +	    if (w == winPtr) {
         3595  +		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
         3596  +		    "setting \"%s\" as master creates a transient/master cycle",
         3597  +		    Tk_PathName(masterPtr)));
         3598  +		Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
         3599  +		return TCL_ERROR;
         3600  +	    }
         3601  +	}
         3602  +
         3603  +	if (masterPtr != wmPtr->masterPtr) {
  3598   3604   	    /*
  3599   3605   	     * Remove old master map/unmap binding before setting the new
  3600   3606   	     * master. The event handler will ensure that transient states
  3601   3607   	     * reflect the state of the master.
  3602   3608   	     */
  3603   3609   
  3604   3610   	    if (wmPtr->masterPtr != NULL) {

Changes to win/makefile.vc.

   357    357   #---------------------------------------------------------------------
   358    358   
   359    359   release:  setup $(TKSTUBLIB) $(WISH)
   360    360   all:	  release $(CAT32)
   361    361   core:	  setup $(TKSTUBLIB) $(TKLIB)
   362    362   cwish:	  $(WISHC)
   363    363   install:  install-binaries install-libraries install-docs
          364  +!if $(SYMBOLS)
          365  +install:    install-pdbs
          366  +!endif
   364    367   tktest:	  setup $(TKTEST) $(CAT32)
   365    368   
   366    369   setup: default-setup
   367    370   
   368    371   test: test-classic test-ttk
   369    372   
   370    373   test-classic: setup $(TKTEST) $(TKLIB) $(CAT32)
................................................................................
   537    540   install-docs:
   538    541   !if exist("$(CHMFILE)")
   539    542   	@echo Installing compiled HTML help
   540    543   	@$(CPY) "$(CHMFILE)" "$(DOC_INSTALL_DIR)\"
   541    544   !endif
   542    545   # "emacs font-lock highlighting fix
   543    546   
          547  +install-pdbs:
          548  +	@echo Installing debug symbols
          549  +	@$(CPY) "$(OUT_DIR)\*.pdb" "$(BIN_INSTALL_DIR)\"
          550  +# "emacs font-lock highlighting fix
          551  +
   544    552   #---------------------------------------------------------------------
   545    553   # Special case object file targets
   546    554   #---------------------------------------------------------------------
   547    555   
   548    556   $(TMP_DIR)\testMain.obj: $(WINDIR)\winMain.c
   549    557   	$(cc32) $(appcflags_nostubs) -DTK_TEST \
   550    558   	    -DTCL_USE_STATIC_PACKAGES=$(TCL_USE_STATIC_PACKAGES) \

Changes to win/tkWinWm.c.

  5522   5522       Tk_Window tkwin,		/* Main window of the application. */
  5523   5523       TkWindow *winPtr,		/* Toplevel to work with */
  5524   5524       Tcl_Interp *interp,		/* Current interpreter. */
  5525   5525       int objc,			/* Number of arguments. */
  5526   5526       Tcl_Obj *const objv[])	/* Argument objects. */
  5527   5527   {
  5528   5528       register WmInfo *wmPtr = winPtr->wmInfoPtr;
  5529         -    TkWindow *masterPtr = wmPtr->masterPtr, **masterPtrPtr = &masterPtr;
         5529  +    TkWindow *masterPtr = wmPtr->masterPtr, **masterPtrPtr = &masterPtr, *w;
  5530   5530       WmInfo *wmPtr2;
  5531   5531   
  5532   5532       if ((objc != 3) && (objc != 4)) {
  5533   5533   	Tcl_WrongNumArgs(interp, 2, objv, "window ?master?");
  5534   5534   	return TCL_ERROR;
  5535   5535       }
  5536   5536       if (objc == 3) {
................................................................................
  5580   5580   	if (wmPtr2->iconFor != NULL) {
  5581   5581   	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
  5582   5582   		    "can't make \"%s\" a master: it is an icon for %s",
  5583   5583   		    Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor)));
  5584   5584   	    Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL);
  5585   5585   	    return TCL_ERROR;
  5586   5586   	}
  5587         -
  5588         -	if (masterPtr == winPtr) {
  5589         -	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
  5590         -		    "can't make \"%s\" its own master", Tk_PathName(winPtr)));
  5591         -	    Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
  5592         -	    return TCL_ERROR;
  5593         -	} else if (masterPtr != wmPtr->masterPtr) {
         5587  +	for (w = masterPtr; w != NULL && w->wmInfoPtr != NULL;
         5588  +	     w = (TkWindow *)w->wmInfoPtr->masterPtr) {
         5589  +	    if (w == winPtr) {
         5590  +		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
         5591  +		    "setting \"%s\" as master creates a transient/master cycle",
         5592  +		    Tk_PathName(masterPtr)));
         5593  +		Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
         5594  +		return TCL_ERROR;
         5595  +	    }
         5596  +	}
         5597  +	if (masterPtr != wmPtr->masterPtr) {
  5594   5598   	    /*
  5595   5599   	     * Remove old master map/unmap binding before setting the new
  5596   5600   	     * master. The event handler will ensure that transient states
  5597   5601   	     * reflect the state of the master.
  5598   5602   	     */
  5599   5603   
  5600   5604   	    if (wmPtr->masterPtr != NULL) {