This patch extends the patch provided with bug 1 to address some 
issues handling toplevels in Tk when a grab is set under Windows.
At the moment if a grab is set then the non-grabbed toplevels reject
activation attempts from the user via mouseclick. However if you click
the toplevel's entry in the taskbar you can bypass this. The original
patch addresses this but we also run into a race when the user clicks
on the toplevel title and starts a move. The posted activate event
causes an early termination of the move which aborts the grab temporarily.
We fix this by delaying the handling of the activate event while a move
is in progress.

The patch also adds some handling of WM_SYSCOMMAND. As originally provided
this prevents minimizing an grabbed toplevel. The original also rejects any
system commands when a grab is present for the non-grabbed windows but I have
permitted move and resize which seems to correspond to some applications
in testing when a dialog is shown.

Possibly we will stick with the original scheme of preventing any interaction
with non-grabbed toplevels when a grab is present.

Index: win/tkWinWm.c
===================================================================
RCS file: /cvsroot/tktoolkit/tk/win/tkWinWm.c,v
retrieving revision 1.134
diff -u -r1.134 tkWinWm.c
--- win/tkWinWm.c	9 Dec 2008 21:22:56 -0000	1.134
+++ win/tkWinWm.c	6 Jan 2009 16:33:01 -0000
@@ -34,12 +34,16 @@
 
 /*
  * Event structure for synthetic activation events. These events are placed on
- * the event queue whenever a toplevel gets a WM_MOUSEACTIVATE message.
+ * the event queue whenever a toplevel gets a WM_MOUSEACTIVATE message or
+ * a WM_ACTIVATE. If the window is being moved (*flagPtr will be true)
+ * then the handling of this event must be delayed until the operation 
+ * has completed to avoid a premature WM_EXITSIZEMOVE event.
  */
 
 typedef struct ActivateEvent {
     Tcl_Event ev;
     TkWindow *winPtr;
+    int *flagPtr;
 } ActivateEvent;
 
 /*
@@ -418,6 +422,7 @@
 static int		ActivateWindow(Tcl_Event *evPtr, int flags);
 static void		ConfigureTopLevel(WINDOWPOS *pos);
 static void		GenerateConfigureNotify(TkWindow *winPtr);
+static void		GenerateActivateEvent(TkWindow *winPtr, int *flagPtr);
 static void		GetMaxSize(WmInfo *wmPtr,
 			    int *maxWidthPtr, int *maxHeightPtr);
 static void		GetMinSize(WmInfo *wmPtr,
@@ -7755,7 +7760,7 @@
 				 * after leaving move/size mode. Note that
 				 * this mechanism assumes move/size is only
 				 * one level deep. */
-    LRESULT result;
+    LRESULT result = 0;
     TkWindow *winPtr = NULL;
 
     switch (message) {
@@ -7779,6 +7784,20 @@
 	break;
 
     case WM_ACTIVATE:
+	if ( WA_ACTIVE == LOWORD(wParam) ) {
+	    winPtr = GetTopLevel(hwnd);
+	    if (winPtr && (TkGrabState(winPtr) == TK_GRAB_EXCLUDED)) {
+		/*
+		 * There is a grab in progress so queue an Activate event
+		 */
+
+		GenerateActivateEvent(winPtr, &inMoveSize);
+		result = 0;
+		goto done;
+	    }
+	}
+	/* fall through */
+	
     case WM_EXITSIZEMOVE:
 	if (inMoveSize) {
 	    inMoveSize = 0;
@@ -7881,8 +7900,6 @@
     }
 
     case WM_MOUSEACTIVATE: {
-	ActivateEvent *eventPtr;
-
 	winPtr = GetTopLevel((HWND) wParam);
 	if (winPtr && (TkGrabState(winPtr) != TK_GRAB_EXCLUDED)) {
 	    /*
@@ -7902,10 +7919,7 @@
 	 */
 
 	if (winPtr) {
-	    eventPtr = (ActivateEvent *) ckalloc(sizeof(ActivateEvent));
-	    eventPtr->ev.proc = ActivateWindow;
-	    eventPtr->winPtr = winPtr;
-	    Tcl_QueueEvent((Tcl_Event *) eventPtr, TCL_QUEUE_TAIL);
+	    GenerateActivateEvent(winPtr, &inMoveSize);
 	}
 	result = MA_NOACTIVATE;
 	goto done;
@@ -7934,6 +7948,24 @@
     winPtr = GetTopLevel(hwnd);
     switch(message) {
     case WM_SYSCOMMAND:
+	/*
+	 * If there is a grab in effect then ignore the minimize command
+	 * If there is a grab in effect and this window is outside the
+	 * grab tree then ignore all system commands. [Bug 1847002]
+	 */
+
+	if (winPtr) {
+	    int cmd = wParam & 0xfff0;
+	    int grab = TkGrabState(winPtr);
+	    if (grab != TK_GRAB_NONE && SC_MINIMIZE == cmd)
+		goto done;
+	    if (grab == TK_GRAB_EXCLUDED 
+		&& !(SC_MOVE == cmd || SC_SIZE == cmd)) {
+		goto done;
+	    }
+	}
+	/* fall through */
+	
     case WM_INITMENU:
     case WM_COMMAND:
     case WM_MENUCHAR:
@@ -7941,20 +7973,21 @@
     case WM_DRAWITEM:
     case WM_MENUSELECT:
     case WM_ENTERIDLE:
-    case WM_INITMENUPOPUP: {
-	HWND hMenuHWnd = Tk_GetEmbeddedMenuHWND((Tk_Window) winPtr);
+    case WM_INITMENUPOPUP:
+	if (winPtr) {
+	    HWND hMenuHWnd = Tk_GetEmbeddedMenuHWND((Tk_Window) winPtr);
 
-	if (hMenuHWnd) {
-	    if (SendMessage(hMenuHWnd, message, wParam, lParam)) {
+	    if (hMenuHWnd) {
+		if (SendMessage(hMenuHWnd, message, wParam, lParam)) {
+		    goto done;
+		}
+	    } else if (TkWinHandleMenuEvent(&hwnd, &message, &wParam, &lParam,
+		    &result)) {
 		goto done;
 	    }
-	} else if (TkWinHandleMenuEvent(&hwnd, &message, &wParam, &lParam,
-		&result)) {
-	    goto done;
 	}
 	break;
     }
-    }
 
     if (winPtr && winPtr->window) {
 	HWND child = Tk_GetHWND(winPtr->window);
@@ -8109,6 +8142,25 @@
 /*
  *----------------------------------------------------------------------
  *
+ * GenerateActivateEvent --
+ *
+ *	This function is called to activate a Tk window.
+ */
+
+static void
+GenerateActivateEvent(TkWindow * winPtr, int *flagPtr)
+{
+    ActivateEvent *eventPtr;
+    eventPtr = (ActivateEvent *)ckalloc(sizeof(ActivateEvent));
+    eventPtr->ev.proc = ActivateWindow;
+    eventPtr->winPtr = winPtr;
+    eventPtr->flagPtr = flagPtr;
+    Tcl_QueueEvent((Tcl_Event *)eventPtr, TCL_QUEUE_TAIL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
  * ActivateWindow --
  *
  *	This function is called when an ActivateEvent is processed.
@@ -8127,13 +8179,22 @@
     Tcl_Event *evPtr,		/* Pointer to ActivateEvent. */
     int flags)			/* Notifier event mask. */
 {
-    TkWindow *winPtr;
+    ActivateEvent *eventPtr = (ActivateEvent *)evPtr;
+    TkWindow *winPtr = eventPtr->winPtr;
 
     if (! (flags & TCL_WINDOW_EVENTS)) {
 	return 0;
     }
 
-    winPtr = ((ActivateEvent *) evPtr)->winPtr;
+    /*
+     * If the toplevel is in the middle of a move or size operation then
+     * we must delay handling of this event to avoid stealing the focus
+     * while the window manage is in control.
+     */
+
+    if (eventPtr->flagPtr && *eventPtr->flagPtr) {
+	return 0;
+    }
 
     /*
      * If the window is excluded by a grab, call SetFocus on the grabbed
