Tk Source Code

Artifact [709e4149]
Login

Artifact 709e414910fbce127220a965fd8e9422ead787b7:

Attachment "raise-delay.patch" to ticket [601518ff] added by jenglish 2002-08-29 03:16:24.
Index: tests/wm.test
===================================================================
RCS file: /cvsroot/tktoolkit/tk/tests/wm.test,v
retrieving revision 1.18
diff -c -r1.18 wm.test
*** tests/wm.test	8 Aug 2002 23:45:01 -0000	1.18
--- tests/wm.test	28 Aug 2002 20:05:33 -0000
***************
*** 32,37 ****
--- 32,47 ----
      update
  }
  
+ # [raise] and [lower] may return before the window manager
+ # has completed the operation.  The raiseDelay procedure
+ # idles for a while to give the operation a chance to complete.
+ #
+ 
+ proc raiseDelay {} {
+     after 100; update
+ }
+ 
+ 
  deleteWindows
  stdWindow
  
***************
*** 906,911 ****
--- 916,922 ----
      catch {destroy .t}
      toplevel .t ; update
      raise .
+     raiseDelay
      wm stackorder .
  } {.t .}
  
***************
*** 916,921 ****
--- 927,933 ----
      toplevel .t2 ; update
      raise .
      raise .t2
+     raiseDelay
      wm stackorder .
  } {.t . .t2}
  
***************
*** 926,931 ****
--- 938,944 ----
      toplevel .t2 ; update
      raise .
      lower .t2
+     raiseDelay
      wm stackorder .
  } {.t2 .t .}
  
***************
*** 940,945 ****
--- 953,959 ----
      toplevel .extra ; update
      raise .parent
      lower .parent.child2
+     raiseDelay
      wm stackorder .parent
  } {.parent.child2 .parent.child1 .parent}
  
***************
*** 1051,1056 ****
--- 1065,1071 ----
      catch {destroy .t}
      toplevel .t ; update
      raise .
+     raiseDelay
      wm stackorder .t isa .
  } {0}
  
***************
*** 1058,1063 ****
--- 1073,1079 ----
      catch {destroy .t}
      toplevel .t ; update
      raise .
+     raiseDelay
      wm stackorder .t isb .
  } {1}
  
***************
*** 1071,1076 ****
--- 1087,1093 ----
      .t configure -menu .t.m
      update
      raise .
+     raiseDelay
      wm stackorder .
  } {.t .}
  
***************
*** 1081,1086 ****
--- 1098,1104 ----
      wm overrideredirect .t 1
      raise .
      update
+     raiseDelay
      wm stackorder . isabove .t
  } 0
  
***************
*** 1091,1096 ****
--- 1109,1115 ----
      wm overrideredirect .t 1
      lower .t
      update
+     raiseDelay
      wm stackorder .t isbelow .
  } 1
  
Index: unix/tkUnixWm.c
===================================================================
RCS file: /cvsroot/tktoolkit/tk/unix/tkUnixWm.c,v
retrieving revision 1.33
diff -c -r1.33 tkUnixWm.c
*** unix/tkUnixWm.c	8 Aug 2002 23:49:50 -0000	1.33
--- unix/tkUnixWm.c	28 Aug 2002 20:05:34 -0000
***************
*** 5454,5461 ****
   *
   * Side effects:
   *	WinPtr gets restacked  as specified by aboveBelow and otherPtr.
-  *	This procedure doesn't return until the restack has taken
-  *	effect and the ConfigureNotify event for it has been received.
   *
   *----------------------------------------------------------------------
   */
--- 5454,5459 ----
***************
*** 5470,5649 ****
  				 * above or below *all* siblings. */
  {
      XWindowChanges changes;
-     XWindowAttributes atts;
      unsigned int mask;
-     Window window, dummy1, dummy2, vRoot;
-     Window *children;
-     unsigned int numChildren;
-     int i;
-     int desiredIndex = 0;	/* Initialized to stop gcc warnings. */
-     int ourIndex = 0;		/* Initialized to stop gcc warnings. */
-     unsigned long serial;
-     Tk_ErrorHandler handler;
      TkWindow *wrapperPtr;
  
      memset(&changes, 0, sizeof(XWindowChanges));
      changes.stack_mode = aboveBelow;
-     changes.sibling = None;
      mask = CWStackMode;
-     if (winPtr->window == None) {
- 	Tk_MakeWindowExist((Tk_Window) winPtr);
-     }
-     if (winPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) {
- 	/*
- 	 * Can't set stacking order properly until the window is on the
- 	 * screen (mapping it may give it a reparent window), so make sure
- 	 * it's on the screen.
- 	 */
- 
- 	TkWmMapWindow(winPtr);
-     }
-     wrapperPtr = winPtr->wmInfoPtr->wrapperPtr;
-     window = (winPtr->wmInfoPtr->reparent != None)
- 	    ? winPtr->wmInfoPtr->reparent : wrapperPtr->window;
-     if (otherPtr != NULL) {
- 	if (otherPtr->window == None) {
- 	    Tk_MakeWindowExist((Tk_Window) otherPtr);
- 	}
- 	if (otherPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) {
- 	    TkWmMapWindow(otherPtr);
- 	}
- 	changes.sibling = (otherPtr->wmInfoPtr->reparent != None)
- 		? otherPtr->wmInfoPtr->reparent
- 		: otherPtr->wmInfoPtr->wrapperPtr->window;
- 	mask = CWStackMode|CWSibling;
-     }
  
      /*
!      * Before actually reconfiguring the window, see if it's already
!      * in the right place.  If so then don't reconfigure it.  The
!      * reason for this extra work is that some window managers will
!      * ignore the reconfigure request if the window is already in
!      * the right place, causing a long delay in WaitForConfigureNotify
!      * while it times out.  Special note: if the window is almost in
!      * the right place, and the only windows between it and the right
!      * place aren't mapped, then we don't reconfigure it either, for
!      * the same reason.
       */
! 
!     vRoot = winPtr->wmInfoPtr->vRoot;
!     if (vRoot == None) {
! 	vRoot = RootWindowOfScreen(Tk_Screen((Tk_Window) winPtr));
      }
!     if (XQueryTree(winPtr->display, vRoot, &dummy1, &dummy2,
! 	    &children, &numChildren) != 0) {
! 	/*
! 	 * Find where our window is in the stacking order, and
! 	 * compute the desired location in the stacking order.
! 	 */
! 
! 	for (i = 0; i < numChildren; i++) {
! 	    if (children[i] == window) {
! 		ourIndex = i;
! 	    }
! 	    if (children[i] == changes.sibling) {
! 		desiredIndex = i;
! 	    }
! 	}
! 	if (mask & CWSibling) {
! 	    if (aboveBelow == Above) {
! 		if (desiredIndex < ourIndex) {
! 		    desiredIndex += 1;
! 		}
! 	    } else {
! 		if (desiredIndex > ourIndex) {
! 		    desiredIndex -= 1;
! 		}
! 	    }
! 	} else {
! 	    if (aboveBelow == Above) {
! 		desiredIndex = numChildren-1;
! 	    } else {
! 		desiredIndex = 0;
! 	    }
! 	}
  
  	/*
! 	 * See if there are any mapped windows between where we are
! 	 * and where we want to be.
  	 */
! 
! 	handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1,
! 		(Tk_ErrorProc *) NULL, (ClientData) NULL);
! 	while (desiredIndex != ourIndex) {
! 	    if ((XGetWindowAttributes(winPtr->display, children[desiredIndex],
! 		    &atts) != 0) && (atts.map_state != IsUnmapped)) {
! 		break;
! 	    }
! 	    if (desiredIndex < ourIndex) {
! 		desiredIndex++;
! 	    } else {
! 		desiredIndex--;
! 	    }
! 	}
! 	Tk_DeleteErrorHandler(handler);
! 	XFree((char *) children);
! 	if (ourIndex == desiredIndex) {
! 	    return;
  	}
      }
  
      /*
!      * Reconfigure the window.  This tricky because of two things:
!      * (a) Some window managers, like olvwm, insist that we raise
!      *     or lower the toplevel window itself, as opposed to its
!      *     decorative frame.  Attempts to raise or lower the frame
!      *     are ignored.
!      * (b) If the raise or lower is relative to a sibling, X will
!      *     generate an error unless we work with the frames (the
!      *     toplevels themselves aren't siblings).
!      * Fortunately, the procedure XReconfigureWMWindow is supposed
!      * to handle all of this stuff, so be careful to use it instead
!      * of XConfigureWindow.
       */
  
-     serial = NextRequest(winPtr->display);
-     if (window != wrapperPtr->window) {
- 	/*
- 	 * We're going to have to wait for events on a window that
- 	 * Tk doesn't own, so we have to tell X specially that we
- 	 * want to get events on that window.  To make matters worse,
- 	 * it's possible that the window doesn't exist anymore (e.g.
- 	 * the toplevel could have been withdrawn) so ignore events
- 	 * occurring during the request.
- 	 */
- 
- 	handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1,
- 		(Tk_ErrorProc *) NULL, (ClientData) NULL);
- 	XSelectInput(winPtr->display, window, StructureNotifyMask);
- 	Tk_DeleteErrorHandler(handler);
-     }
      XReconfigureWMWindow(winPtr->display, wrapperPtr->window,
  	    Tk_ScreenNumber((Tk_Window) winPtr), mask,  &changes);
- 
-     /*
-      * Wait for the reconfiguration to complete.  If we don't wait, then
-      * the window may not restack for a while and the application might
-      * observe it before it has restacked.  Waiting for the reconfiguration
-      * is tricky if winPtr has been reparented, since the window getting
-      * the event isn't one that Tk owns.
-      */
- 
-     WaitForConfigureNotify(winPtr, serial);
- 
-     if (window != wrapperPtr->window) {
- 	/*
- 	 * Ignore errors that occur when we are de-selecting events on
- 	 * window, since it's possible that the window doesn't exist
- 	 * anymore (see comment above previous call to XSelectInput).
- 	 */
- 
- 	handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1,
- 		(Tk_ErrorProc *) NULL, (ClientData) NULL);
- 	XSelectInput(winPtr->display, window, (long) 0);
- 	Tk_DeleteErrorHandler(handler);
-     }
  }
  
  /*
   *----------------------------------------------------------------------
--- 5468,5512 ----
  				 * above or below *all* siblings. */
  {
      XWindowChanges changes;
      unsigned int mask;
      TkWindow *wrapperPtr;
  
      memset(&changes, 0, sizeof(XWindowChanges));
      changes.stack_mode = aboveBelow;
      mask = CWStackMode;
  
      /*
!      * Make sure that winPtr and its wrapper window have been created.
       */
!     if (winPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) {
! 	TkWmMapWindow(winPtr);
      }
!     wrapperPtr = winPtr->wmInfoPtr->wrapperPtr;
  
+     if (otherPtr != NULL) {
  	/*
! 	 * The window is to be restacked with respect to another toplevel.
! 	 * Make sure it has been created as well.
  	 */
! 	if (otherPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) {
! 	    TkWmMapWindow(otherPtr);
  	}
+ 	changes.sibling = otherPtr->wmInfoPtr->wrapperPtr->window;
+ 	mask |= CWSibling;
      }
  
      /*
!      * Reconfigure the window.  Note that we use XReconfigureWMWindow
!      * instead of XConfigureWindow, in order to handle the case
!      * where the window is to be restacked with respect to another toplevel.  
!      * See [ICCCM] 4.1.5 "Configuring the Window" and XReconfigureWMWindow(3)
!      * for details.
       */
  
      XReconfigureWMWindow(winPtr->display, wrapperPtr->window,
  	    Tk_ScreenNumber((Tk_Window) winPtr), mask,  &changes);
  }
+ 
  
  /*
   *----------------------------------------------------------------------