2002-06-21  Mo DeJong  <mdejong@users.sourceforge.net>

	* tests/wm.test: Add tests to make sure a withdrawn
	transient does not get remapped by state changes
	in the master.
	* unix/tkUnixWm.c (Tk_WmCmd, WmWaitMapProc):
	* win/tkWinWm.c (Tk_WmCmd, WmWaitVisibilityOrMapProc):
	Add a WM_TRANSIENT_WITHDRAWN flag that gets set by the
	withdraw, deiconify, or state wm subcommands. Check
	this flag before mapping a transient when processing
	a MapNotify event.

Index: tests/wm.test
===================================================================
RCS file: /cvsroot/tktoolkit/tk/tests/wm.test,v
retrieving revision 1.10
diff -u -r1.10 wm.test
--- tests/wm.test	13 Jun 2002 21:35:09 -0000	1.10
+++ tests/wm.test	22 Jun 2002 00:37:29 -0000
@@ -509,6 +509,39 @@
     wm transient .subject
 } {}
 
+test wm-transient-6.1 { a withdrawn transient does not track
+        state changes in the master } {
+    deleteWindows
+    toplevel .master
+    toplevel .subject
+    update
+    wm transient .subject .master
+    wm withdraw .subject
+    wm withdraw .master
+    wm deiconify .master
+    wm state .subject
+} {withdrawn}
+
+test wm-transient-6.2 { a withdrawn transient does not track
+        state changes in the master } {
+    set results [list]
+    deleteWindows
+    toplevel .master
+    toplevel .subject
+    update
+    wm transient .subject .master
+    wm withdraw .subject
+    wm withdraw .master
+    wm deiconify .master
+    lappend results [wm state .subject]
+    wm deiconify .subject
+    lappend results [wm state .subject]
+    wm withdraw .master
+    lappend results [wm state .subject]
+    wm deiconify .master
+    lappend results [wm state .subject]
+} {withdrawn normal withdrawn normal}
+
 
 test wm-state-1.1 {usage} {
     list [catch {wm state} err] $err
Index: unix/tkUnixWm.c
===================================================================
RCS file: /cvsroot/tktoolkit/tk/unix/tkUnixWm.c,v
retrieving revision 1.23
diff -u -r1.23 tkUnixWm.c
--- unix/tkUnixWm.c	15 Jun 2002 01:54:47 -0000	1.23
+++ unix/tkUnixWm.c	22 Jun 2002 00:37:33 -0000
@@ -244,6 +244,9 @@
  *				allow the user to change the height of the
  *				window (controlled by "wm resizable"
  *				command).
+ * WM_TRANSIENT_WITHDRAWN -	non-zero means that this is a transient window
+ *				that has explicitly been withdrawn. It should
+ *				not mirror state changes in the master.
  */
 
 #define WM_NEVER_MAPPED			1
@@ -259,6 +262,7 @@
 #define WM_ADDED_TOPLEVEL_COLORMAP	0x800
 #define WM_WIDTH_NOT_RESIZABLE		0x1000
 #define WM_HEIGHT_NOT_RESIZABLE		0x2000
+#define WM_TRANSIENT_WITHDRAWN		0x4000
 
 /*
  * This module keeps a list of all top-level windows, primarily to
@@ -1139,6 +1143,9 @@
 		    (char *) NULL);
 	    return TCL_ERROR;
 	}
+	if (wmPtr->flags & WM_TRANSIENT_WITHDRAWN) {
+	    wmPtr->flags &= ~WM_TRANSIENT_WITHDRAWN;
+	}
 	(void) TkpWmSetState(winPtr, NormalState);
     } else if ((c == 'f') && (strncmp(argv[1], "focusmodel", length) == 0)
 	    && (length >= 2)) {
@@ -1941,6 +1948,9 @@
 	    length = strlen(argv[3]);
 
 	    if ((c == 'n') && (strncmp(argv[3], "normal", length) == 0)) {
+		if (wmPtr->flags & WM_TRANSIENT_WITHDRAWN) {
+		    wmPtr->flags &= ~WM_TRANSIENT_WITHDRAWN;
+		}
 		(void) TkpWmSetState(winPtr, NormalState);
 	    } else if ((c == 'i')
 		    && (strncmp(argv[3], "iconic", length) == 0)) {
@@ -1965,6 +1975,9 @@
 		}
 	    } else if ((c == 'w')
 		    && (strncmp(argv[3], "withdrawn", length) == 0)) {
+		if (wmPtr->masterPtr != NULL) {
+		    wmPtr->flags |= WM_TRANSIENT_WITHDRAWN;
+		}
 		if (TkpWmSetState(winPtr, WithdrawnState) == 0) {
 		    Tcl_SetResult(interp,
 			    "couldn't send withdraw message to window manager",
@@ -2145,6 +2158,9 @@
 		    (char *) NULL);
 	    return TCL_ERROR;
 	}
+	if (wmPtr->masterPtr != NULL) {
+	    wmPtr->flags |= WM_TRANSIENT_WITHDRAWN;
+	}
 	if (TkpWmSetState(winPtr, WithdrawnState) == 0) {
 	    Tcl_SetResult(interp,
 		    "couldn't send withdraw message to window manager",
@@ -2187,7 +2203,8 @@
     if (masterPtr == NULL)
         return;
 
-    if (eventPtr->type == MapNotify) {
+    if (eventPtr->type == MapNotify &&
+            !(winPtr->wmInfoPtr->flags & WM_TRANSIENT_WITHDRAWN)) {
         (void) TkpWmSetState(winPtr, NormalState);
     } else if (eventPtr->type == UnmapNotify) {
         (void) TkpWmSetState(winPtr, WithdrawnState);
Index: win/tkWinWm.c
===================================================================
RCS file: /cvsroot/tktoolkit/tk/win/tkWinWm.c,v
retrieving revision 1.41
diff -u -r1.41 tkWinWm.c
--- win/tkWinWm.c	15 Jun 2002 01:54:48 -0000	1.41
+++ win/tkWinWm.c	22 Jun 2002 00:37:36 -0000
@@ -283,6 +283,17 @@
  *				was called the top-level itself wasn't
  *				specified, so we added it implicitly at
  *				the end of the list.
+ * WM_WIDTH_NOT_RESIZABLE -	non-zero means that we're not supposed to
+ *				allow the user to change the width of the
+ *				window (controlled by "wm resizable"
+ *				command).
+ * WM_HEIGHT_NOT_RESIZABLE -	non-zero means that we're not supposed to
+ *				allow the user to change the height of the
+ *				window (controlled by "wm resizable"
+ *				command).
+ * WM_TRANSIENT_WITHDRAWN -	non-zero means that this is a transient window
+ *				that has explicitly been withdrawn. It should
+ *				not mirror state changes in the master.
  */
 
 #define WM_NEVER_MAPPED			(1<<0)
@@ -297,6 +308,7 @@
 #define WM_ADDED_TOPLEVEL_COLORMAP	(1<<9)
 #define WM_WIDTH_NOT_RESIZABLE		(1<<10)
 #define WM_HEIGHT_NOT_RESIZABLE		(1<<11)
+#define WM_TRANSIENT_WITHDRAWN		(1<<12)
 
 /*
  * Window styles for various types of toplevel windows.
@@ -2419,6 +2431,11 @@
                     ": it is an embedded window", (char *) NULL);
             return TCL_ERROR;
         }
+
+	if (wmPtr->flags & WM_TRANSIENT_WITHDRAWN) {
+	    wmPtr->flags &= ~WM_TRANSIENT_WITHDRAWN;
+	}
+
 	/*
 	 * If WM_UPDATE_PENDING is true, a pending UpdateGeometryInfo may
 	 * need to be called first to update a withdrew toplevel's geometry
@@ -3271,6 +3288,9 @@
 	    length = strlen(argv[3]);
 
 	    if ((c == 'n') && (strncmp(argv[3], "normal", length) == 0)) {
+		if (wmPtr->flags & WM_TRANSIENT_WITHDRAWN) {
+		    wmPtr->flags &= ~WM_TRANSIENT_WITHDRAWN;
+		}
 		TkpWmSetState(winPtr, NormalState);
 		/*
 		 * This varies from 'wm deiconify' because it does not
@@ -3294,6 +3314,9 @@
 		TkpWmSetState(winPtr, IconicState);
 	    } else if ((c == 'w')
 		    && (strncmp(argv[3], "withdrawn", length) == 0)) {
+		if (wmPtr->masterPtr != NULL) {
+		    wmPtr->flags |= WM_TRANSIENT_WITHDRAWN;
+		}
 		TkpWmSetState(winPtr, WithdrawnState);
 	    } else if ((c == 'z')
 		    && (strncmp(argv[3], "zoomed", length) == 0)) {
@@ -3455,6 +3478,9 @@
 		    (char *) NULL);
 	    return TCL_ERROR;
 	}
+	if (wmPtr->masterPtr != NULL) {
+	    wmPtr->flags |= WM_TRANSIENT_WITHDRAWN;
+	}
 	TkpWmSetState(winPtr, WithdrawnState);
     } else {
 	Tcl_AppendResult(interp, "unknown or ambiguous option \"", argv[1],
@@ -3488,7 +3514,8 @@
     if (masterPtr == NULL)
 	return;
 
-    if (eventPtr->type == MapNotify) {
+    if (eventPtr->type == MapNotify &&
+            !(winPtr->wmInfoPtr->flags & WM_TRANSIENT_WITHDRAWN)) {
 	TkpWmSetState(winPtr, NormalState);
     } else if (eventPtr->type == UnmapNotify) {
 	TkpWmSetState(winPtr, WithdrawnState);
