1 /****************************************************************************
2  * This module is based on Twm, but has been siginificantly modified
3  * by Rob Nation
4  *
5  * slightly modified by Bo Yang
6  *
7  ****************************************************************************/
8 /*****************************************************************************/
9 /**       Copyright 1988 by Evans & Sutherland Computer Corporation,        **/
10 /**                          Salt Lake City, Utah                           **/
11 /**  Portions Copyright 1989 by the Massachusetts Institute of Technology   **/
12 /**                        Cambridge, Massachusetts                         **/
13 /**                                                                         **/
14 /**                           All Rights Reserved                           **/
15 /**                                                                         **/
16 /**    Permission to use, copy, modify, and distribute this software and    **/
17 /**    its documentation  for  any  purpose  and  without  fee is hereby    **/
18 /**    granted, provided that the above copyright notice appear  in  all    **/
19 /**    copies and that both  that  copyright  notice  and  this  permis-    **/
20 /**    sion  notice appear in supporting  documentation,  and  that  the    **/
21 /**    names of Evans & Sutherland and M.I.T. not be used in advertising    **/
22 /**    in publicity pertaining to distribution of the  software  without    **/
23 /**    specific, written prior permission.                                  **/
24 /**                                                                         **/
25 /**    EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD    **/
26 /**    TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES  OF  MERCHANT-    **/
27 /**    ABILITY  AND  FITNESS,  IN  NO  EVENT SHALL EVANS & SUTHERLAND OR    **/
28 /**    M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL  DAM-    **/
29 /**    AGES OR  ANY DAMAGES WHATSOEVER  RESULTING FROM LOSS OF USE, DATA    **/
30 /**    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER    **/
31 /**    TORTIOUS ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE    **/
32 /**    OR PERFORMANCE OF THIS SOFTWARE.                                     **/
33 /*****************************************************************************/
34 
35 
36 /**************************************************************************
37  *
38  * Assorted odds and ends
39  *
40  **************************************************************************/
41 
42 
43 #include "../configure.h"
44 
45 #include <stdio.h>
46 #include <string.h>
47 #include <sys/types.h>
48 #include <sys/time.h>
49 #include <unistd.h>
50 #include <signal.h>
51 #include <limits.h>
52 
53 #include "afterstep.h"
54 #include <X11/Xatom.h>
55 #include "menus.h"
56 #include "misc.h"
57 #include "parse.h"
58 #include "screen.h"
59 #include "module.h"
60 
61 
62 
63 /**************************************************************************
64  *
65  * Releases dynamically allocated space used to store window/icon names
66  *
67  **************************************************************************/
free_window_names(ASWindow * tmp,Bool nukename,Bool nukeicon)68 void free_window_names (ASWindow *tmp, Bool nukename, Bool nukeicon)
69 {
70   if (!tmp)
71     return;
72 
73   if (nukename && nukeicon)
74     {
75       if (tmp->name == tmp->icon_name)
76 	{
77 	  if (tmp->name != NoName)
78 	    XFree (tmp->name);
79 	  tmp->name = NULL;
80 	  tmp->icon_name = NULL;
81 	}
82       else
83 	{
84 	  if (tmp->name != NoName)
85 	    XFree (tmp->name);
86 	  tmp->name = NULL;
87 	  if (tmp->icon_name != NoName)
88 	    XFree (tmp->icon_name);
89 	  tmp->icon_name = NULL;
90 	}
91     }
92   else if (nukename)
93     {
94       if (tmp->name != tmp->icon_name && tmp->name != NoName)
95 	XFree (tmp->name);
96       tmp->name = NULL;
97     }
98   else
99     { /* if (nukeicon) */
100       if (tmp->icon_name != tmp->name && tmp->icon_name != NoName)
101 	XFree (tmp->icon_name);
102       tmp->icon_name = NULL;
103     }
104 
105   return;
106 }
107 
108 /***************************************************************************
109  *
110  * Handles destruction of a window
111  *
112  ****************************************************************************/
Destroy(ASWindow * Tmp_win)113 void Destroy(ASWindow *Tmp_win)
114 {
115   int i;
116   extern ASWindow *ButtonWindow;
117   extern ASWindow *colormap_win;
118   /*
119    * Warning, this is also called by HandleUnmapNotify; if it ever needs to
120    * look at the event, HandleUnmapNotify will have to mash the UnmapNotify
121    * into a DestroyNotify.
122    */
123   if(!Tmp_win)
124     return;
125 
126   XUnmapWindow(dpy, Tmp_win->frame);
127   XSync(dpy,0);
128 
129   if(Tmp_win == Scr.Hilite)
130     Scr.Hilite = NULL;
131 
132   Broadcast(M_DESTROY_WINDOW,3,Tmp_win->w,Tmp_win->frame,
133 	    (unsigned long)Tmp_win,0,0,0,0);
134 
135   if(Scr.PreviousFocus == Tmp_win)
136     Scr.PreviousFocus = NULL;
137 
138   if(ButtonWindow == Tmp_win)
139     ButtonWindow = NULL;
140 
141   if((Tmp_win == Scr.Focus)&&(Scr.flags & ClickToFocus))
142     {
143       ASWindow *t, *tn = NULL;
144       long best = LONG_MIN;
145       for (t = Scr.ASRoot.next; t != NULL; t = t->next)
146         {
147 	  if ((t->focus_sequence > best) && (t != Tmp_win))
148 	    {
149 	      best = t->focus_sequence;
150 	      tn = t;
151 	    }
152 	}
153       if (tn)
154 	SetFocus(tn->w, tn, False);
155       else
156 	SetFocus(Scr.NoFocusWin, NULL, False);
157     }
158 
159   if(Scr.Focus == Tmp_win)
160     SetFocus(Scr.NoFocusWin, NULL, False);
161 
162   if(Tmp_win == Scr.pushed_window)
163     Scr.pushed_window = NULL;
164 
165   if(Tmp_win == colormap_win)
166     colormap_win = NULL;
167 
168   XDestroyWindow(dpy, Tmp_win->frame);
169   XDeleteContext(dpy, Tmp_win->frame, ASContext);
170 
171   XDestroyWindow(dpy, Tmp_win->Parent);
172 
173   XDeleteContext(dpy, Tmp_win->Parent, ASContext);
174 
175   XDeleteContext(dpy, Tmp_win->w, ASContext);
176 
177 
178 #ifndef NO_PAGER
179   if ((Scr.Pager_w)&& !(Tmp_win->flags & STICKY))
180     XDestroyWindow(dpy, Tmp_win->pager_view);
181 #endif
182 
183   if((Tmp_win->flags &ICON_OURS)&&(Tmp_win->icon_pixmap_w != None))
184     XDestroyWindow(dpy, Tmp_win->icon_pixmap_w);
185   if(Tmp_win->icon_pixmap_w != None)
186     XDeleteContext(dpy, Tmp_win->icon_pixmap_w, ASContext);
187 
188   if (Tmp_win->flags & TITLE)
189     {
190       XDeleteContext(dpy, Tmp_win->title_w, ASContext);
191       for(i=0;i<Scr.nr_left_buttons;i++)
192 	XDeleteContext(dpy, Tmp_win->left_w[i], ASContext);
193       for(i=0;i<Scr.nr_right_buttons;i++)
194 	if(Tmp_win->right_w[i] != None)
195 	  XDeleteContext(dpy, Tmp_win->right_w[i], ASContext);
196     }
197   if (Tmp_win->flags & BORDER)
198     {
199       XDeleteContext(dpy, Tmp_win->side, ASContext);
200       for(i=0;i<2;i++)
201 	XDeleteContext(dpy, Tmp_win->corners[i], ASContext);
202     }
203 
204   Tmp_win->prev->next = Tmp_win->next;
205   if (Tmp_win->next != NULL)
206     Tmp_win->next->prev = Tmp_win->prev;
207   free_window_names (Tmp_win, True, True);
208   if (Tmp_win->wmhints)
209     XFree ((char *)Tmp_win->wmhints);
210   if (Tmp_win->class.res_name && Tmp_win->class.res_name != NoName)
211     XFree ((char *)Tmp_win->class.res_name);
212   if (Tmp_win->class.res_class && Tmp_win->class.res_class != NoName)
213     XFree ((char *)Tmp_win->class.res_class);
214   if(Tmp_win->mwm_hints)
215     XFree((char *)Tmp_win->mwm_hints);
216 
217   if(Tmp_win->cmap_windows != (Window *)NULL)
218     XFree((void *)Tmp_win->cmap_windows);
219 #ifdef ENABLE_TEXTURE
220   if (Tmp_win->backPixmap != None)
221     XFreePixmap(dpy, Tmp_win->backPixmap);
222   if (Tmp_win->backPixmap2 != None)
223     XFreePixmap(dpy, Tmp_win->backPixmap2);
224 #endif
225 
226   free((char *)Tmp_win);
227 
228 #ifndef NO_PAGER
229   RedrawPager();
230 #endif
231   XSync(dpy,0);
232   return;
233 }
234 
235 
236 
237 /**************************************************************************
238  *
239  * Removes expose events for a specific window from the queue
240  *
241  *************************************************************************/
flush_expose(Window w)242 int flush_expose (Window w)
243 {
244   XEvent dummy;
245   int i=0;
246 
247   while (XCheckTypedWindowEvent (dpy, w, Expose, &dummy))i++;
248   return i;
249 }
250 
251 
252 
253 /***********************************************************************
254  *
255  *  Procedure:
256  *	RestoreWithdrawnLocation
257  *
258  *  Puts windows back where they were before afterstep took over
259  *
260  ************************************************************************/
RestoreWithdrawnLocation(ASWindow * tmp,Bool restart)261 void RestoreWithdrawnLocation (ASWindow *tmp,Bool restart)
262 {
263   int a,b,w2,h2;
264   unsigned int bw,mask;
265   XWindowChanges xwc;
266 
267   if(!tmp)
268     return;
269 
270   if (XGetGeometry (dpy, tmp->w, &JunkRoot, &xwc.x, &xwc.y,
271 		    &JunkWidth, &JunkHeight, &bw, &JunkDepth))
272     {
273       XTranslateCoordinates(dpy,tmp->frame,Scr.Root,xwc.x,xwc.y,
274 			    &a,&b,&JunkChild);
275       xwc.x = a + tmp->xdiff;
276       xwc.y = b + tmp->ydiff;
277       xwc.border_width = tmp->old_bw;
278       mask = (CWX | CWY|CWBorderWidth);
279 
280       /* We can not assume that the window is currently on the screen.
281        * Although this is normally the case, it is not always true.  The
282        * most common example is when the user does something in an
283        * application which will, after some amount of computational delay,
284        * cause the window to be unmapped, but then switches screens before
285        * this happens.  The XTranslateCoordinates call above will set the
286        * window coordinates to either be larger than the screen, or negative.
287        * This will result in the window being placed in odd, or even
288        * unviewable locations when the window is remapped.  The followin code
289        * forces the "relative" location to be within the bounds of the display.
290        *
291        * gpw -- 11/11/93
292        *
293        * Unfortunately, this does horrendous things during re-starts,
294        * hence the "if(restart) clause (RN)
295        *
296        * Also, fixed so that it only does this stuff if a window is more than
297        * half off the screen. (RN)
298        */
299 
300       if(!restart)
301 	{
302 	  /* Don't mess with it if its partially on the screen now */
303 	  if((tmp->frame_x < 0)||(tmp->frame_y<0)||
304 	     (tmp->frame_x >= Scr.MyDisplayWidth)||
305 	     (tmp->frame_y >= Scr.MyDisplayHeight))
306 	    {
307 	      w2 = (tmp->frame_width>>1);
308 	      h2 = (tmp->frame_height>>1);
309 	      if (( xwc.x < -w2) || (xwc.x > (Scr.MyDisplayWidth-w2 )))
310 		{
311 		  xwc.x = xwc.x % Scr.MyDisplayWidth;
312 		  if ( xwc.x < -w2 )
313 		    xwc.x += Scr.MyDisplayWidth;
314 		}
315 	      if ((xwc.y < -h2) || (xwc.y > (Scr.MyDisplayHeight-h2 )))
316 		{
317 		  xwc.y = xwc.y % Scr.MyDisplayHeight;
318 		  if ( xwc.y < -h2 )
319 		    xwc.y += Scr.MyDisplayHeight;
320 		}
321 	    }
322 	}
323       XReparentWindow (dpy, tmp->w,Scr.Root,xwc.x,xwc.y);
324 
325       if((tmp->flags & ICONIFIED)&&(!(tmp->flags & SUPPRESSICON)))
326 	{
327 	  if (tmp->icon_pixmap_w)
328 	    XUnmapWindow(dpy, tmp->icon_pixmap_w);
329 	}
330 
331       XConfigureWindow (dpy, tmp->w, mask, &xwc);
332       XSync(dpy,0);
333     }
334 }
335 
336 
337 /***************************************************************************
338  *
339  * Start/Stops the auto-raise timer
340  *
341  ****************************************************************************/
SetTimer(int delay)342 void SetTimer(int delay)
343 {
344 #ifdef HAVE_SETITIMER
345   struct itimerval value;
346 
347   value.it_value.tv_usec = 1000*(delay%1000);
348   value.it_value.tv_sec = delay/1000;
349   value.it_interval.tv_usec = 0;
350   value.it_interval.tv_sec = 0;
351   setitimer(ITIMER_REAL,&value,NULL);
352 #endif
353 }
354 
355 /***************************************************************************
356  *
357  * ICCCM Client Messages - Section 4.2.8 of the ICCCM dictates that all
358  * client messages will have the following form:
359  *
360  *     event type	ClientMessage
361  *     message type	_XA_WM_PROTOCOLS
362  *     window		tmp->w
363  *     format		32
364  *     data[0]		message atom
365  *     data[1]		time stamp
366  *
367  ****************************************************************************/
send_clientmessage(Window w,Atom a,Time timestamp)368 void send_clientmessage (Window w, Atom a, Time timestamp)
369 {
370   XClientMessageEvent ev;
371 
372   ev.type = ClientMessage;
373   ev.window = w;
374   ev.message_type = _XA_WM_PROTOCOLS;
375   ev.format = 32;
376   ev.data.l[0] = a;
377   ev.data.l[1] = timestamp;
378   XSendEvent (dpy, w, False, 0L, (XEvent *) &ev);
379 }
380 
381 
382 
383 
384 
385 /****************************************************************************
386  *
387  * Records the time of the last processed event. Used in XSetInputFocus
388  *
389  ****************************************************************************/
390 Time lastTimestamp = CurrentTime;	/* until Xlib does this for us */
391 
StashEventTime(XEvent * ev)392 Bool StashEventTime (XEvent *ev)
393 {
394   Time NewTimestamp = CurrentTime;
395 
396   switch (ev->type)
397     {
398     case KeyPress:
399     case KeyRelease:
400       NewTimestamp = ev->xkey.time;
401       break;
402     case ButtonPress:
403     case ButtonRelease:
404       NewTimestamp = ev->xbutton.time;
405       break;
406     case MotionNotify:
407       NewTimestamp = ev->xmotion.time;
408       break;
409     case EnterNotify:
410     case LeaveNotify:
411       NewTimestamp = ev->xcrossing.time;
412       break;
413     case PropertyNotify:
414       NewTimestamp = ev->xproperty.time;
415       break;
416     case SelectionClear:
417       NewTimestamp = ev->xselectionclear.time;
418       break;
419     case SelectionRequest:
420       NewTimestamp = ev->xselectionrequest.time;
421       break;
422     case SelectionNotify:
423       NewTimestamp = ev->xselection.time;
424       break;
425     default:
426       return False;
427     }
428   if(NewTimestamp > lastTimestamp)
429     lastTimestamp = NewTimestamp;
430   return True;
431 }
432 
433 
434 /******************************************************************************
435  *
436  * Move a window to the top (dir 1) or bottom (dir -1) of the circulate seq.
437  *
438  *****************************************************************************/
439 
SetCirculateSequence(ASWindow * tw,int dir)440 void SetCirculateSequence(ASWindow* tw, int dir)
441 {
442   ASWindow *t;
443   long best = (dir == -1) ? LONG_MAX : LONG_MIN;
444 
445   t = Scr.ASRoot.next;
446   if (t)
447     {
448       do
449         {
450 	  if ((dir == -1) ? (t->circulate_sequence < best)
451 	      : (t->circulate_sequence > best))
452 	      best = t->circulate_sequence;
453 	} while ((t = t->next));
454     }
455   else
456       best = 0;
457 
458   tw->circulate_sequence = best + dir;
459 }
460 
461 
462 
463 /******************************************************************************
464  *
465  * Versions of grab primitives that circumvent modifier problems
466  *
467  *****************************************************************************/
468 
469 unsigned mygrabs_no_mods[] = { 0 };
470 
MyXGrabButton(Display * display,unsigned button,unsigned modifiers,Window grab_window,Bool owner_events,unsigned event_mask,int pointer_mode,int keyboard_mode,Window confine_to,Cursor cursor)471 void MyXGrabButton(Display* display, unsigned button, unsigned modifiers,
472 		   Window grab_window, Bool owner_events, unsigned event_mask,
473 		   int pointer_mode, int keyboard_mode, Window confine_to,
474 		   Cursor cursor)
475 {
476     unsigned mod, *mods;
477     mods = (modifiers != AnyModifier) ? Scr.lock_mods : mygrabs_no_mods;
478     do {
479 	mod = *mods++;
480 	XGrabButton(display, button, modifiers | mod, grab_window,
481 		    owner_events, event_mask, pointer_mode, keyboard_mode,
482 		    confine_to, cursor);
483     } while (mod);
484 }
485 
MyXUngrabButton(Display * display,unsigned button,unsigned modifiers,Window grab_window)486 void MyXUngrabButton(Display* display, unsigned button, unsigned modifiers,
487 		     Window grab_window)
488 {
489     unsigned mod, *mods;
490     mods = (modifiers != AnyModifier) ? Scr.lock_mods : mygrabs_no_mods;
491     do {
492 	mod = *mods++;
493 	XUngrabButton(display, button, modifiers | mod, grab_window);
494     } while (mod);
495 }
496 
MyXGrabKey(Display * display,int keycode,unsigned modifiers,Window grab_window,Bool owner_events,int pointer_mode,int keyboard_mode)497 void MyXGrabKey(Display* display, int keycode, unsigned modifiers,
498 		Window grab_window, Bool owner_events, int pointer_mode,
499 		int keyboard_mode)
500 {
501     unsigned mod, *mods;
502     mods = (modifiers != AnyModifier) ? Scr.lock_mods : mygrabs_no_mods;
503     do {
504 	mod = *mods++;
505 	XGrabKey(display, keycode, modifiers | mod, grab_window, owner_events,
506 		 pointer_mode, keyboard_mode);
507     } while (mod);
508 }
509 
510 /******************************************************************************
511  *
512  * Grab ClickToRaise button press events for a window
513  *
514  *****************************************************************************/
GrabRaiseClick(ASWindow * t)515 void GrabRaiseClick(ASWindow* t)
516 {
517   int b;
518   for (b = 1; b <= MAX_BUTTONS; b++)
519     {
520       if (Scr.RaiseButtons & (1<<b))
521 	  MyXGrabButton(dpy, b, 0, t->w, True, ButtonPressMask, GrabModeSync,
522 		      GrabModeAsync, None, Scr.ASCursors[TITLE_CURSOR]);
523     }
524 }
525 
526 /******************************************************************************
527  *
528  * Ungrab ClickToRaise button press events to allow their use in applications
529  *
530  *****************************************************************************/
UngrabRaiseClick(ASWindow * t)531 void UngrabRaiseClick(ASWindow* t)
532 {
533   int b;
534   for (b = 1; b <= MAX_BUTTONS; b++)
535     {
536 	if (Scr.RaiseButtons & (1<<b))
537 	  MyXUngrabButton(dpy, b, 0, t->w);
538     }
539 }
540 
541 /******************************************************************************
542  *
543  * Recalculate the visibility flags
544  *
545  *****************************************************************************/
546 
UpdateVisibility(void)547 void UpdateVisibility(void)
548 {
549     ASWindow *t, *s, *tbase;
550     int tx1, ty1, tx2, ty2;
551     int ontop = 1, visible;
552 
553     tbase = Scr.ASRoot.next;
554     for (t = Scr.ASRoot.next; t != NULL; t = t->next)
555       {
556 	if (t->flags & MAPPED)
557 	  {
558 	    tx1 = t->frame_x;
559 	    ty1 = t->frame_y;
560 	    tx2 = t->frame_x + t->frame_width;
561 	    ty2 = t->frame_y + t->frame_height;
562 	  }
563 	else if (t->flags & ICONIFIED)
564 	  {
565 	    tx1 = t->icon_x_loc;
566 	    ty1 = t->icon_y_loc;
567 	    tx2 = t->icon_x_loc + t->icon_p_width;
568 	    ty2 = t->icon_y_loc + t->icon_p_height;
569 	  }
570         else if (t->flags & SHADED)
571           {
572             tx1 = t->frame_x;
573             ty1 = t->frame_y;
574             tx2 = t->frame_x + t->frame_width;
575             ty2 = t->frame_y + NS_TITLE_HEIGHT;
576           }
577 	else continue;
578 
579 	if (ontop && !(t->flags & ONTOP))
580 	  {
581 	    ontop = 0;
582 	    tbase = t;
583 	  }
584 	if ((tx2 > 0) && (tx1 < Scr.MyDisplayWidth) &&
585 	    (ty2 > 0) && (ty1 < Scr.MyDisplayHeight))
586 	  {
587 	    visible = VISIBLE;
588 	    for (s = tbase; s != t; s = s->next)
589 	      {
590 		if ((s->flags & TRANSIENT) && (s->transientfor == t->w))
591 		    continue;
592 		if (s->flags & MAPPED)
593 		  {
594 		    if ((tx2 > s->frame_x)&&(tx1 < s->frame_x+s->frame_width)&&
595 			(ty2 > s->frame_y)&&(ty1 < s->frame_y+s->frame_height))
596 		      {
597 			visible = 0;
598 			break;
599 		      }
600 		  }
601 		else if (s->flags & ICONIFIED)
602 		  {
603 		    if ((tx2 > s->icon_x_loc)&&(tx1 < s->icon_x_loc+s->icon_p_width) &&
604 			(ty2 > s->icon_y_loc)&&(ty1 < s->icon_y_loc+s->icon_p_height))
605                       {
606                         visible = 0;
607                         break;
608                       }
609                   }
610                 else if (s->flags & SHADED)
611                   {
612                     if ((tx2 > s->frame_x)&&(tx1 < s->frame_x+s->frame_width)&&
613                         (ty2 > s->frame_y)&&(ty1 < s->frame_y+NS_TITLE_HEIGHT))
614 
615 		      {
616 			visible = 0;
617 			break;
618 		      }
619 		  }
620 
621 	      }
622 	  }
623 	else
624 	  visible = 0;
625 	if ((t->flags & VISIBLE) != visible)
626 	  {
627 	    t->flags ^= VISIBLE;
628 	    if ((Scr.flags & ClickToRaise) && ! (Scr.flags & ClickToFocus)
629 		&& (t->flags & MAPPED))
630 	      {
631 		if (visible)
632 		  UngrabRaiseClick(t);
633 		else
634 		  GrabRaiseClick(t);
635 	      }
636 	  }
637       }
638 }
639 
640 /******************************************************************************
641  *
642  * Get the correct window stacking order from the X server and
643  * make sure everything that depends on the order is fine and dandy
644  *
645  *****************************************************************************/
646 
CorrectStackOrder(void)647 void CorrectStackOrder(void)
648 {
649     Window root, parent, *children, *cp;
650     unsigned nchildren;
651     ASWindow *t;
652 
653     if (XQueryTree(dpy, Scr.ASRoot.w, &root, &parent, &children,
654 		   &nchildren))
655       {
656 	for (cp = children; nchildren-- > 0; cp++)
657 	  {
658 	    if ((XFindContext(dpy, *cp, ASContext, (caddr_t*) &t) == XCSUCCESS)
659 		&& (t->frame == *cp))
660 	      {
661 		if (t != Scr.ASRoot.next)
662 		  {
663 		    t->prev->next = t->next;
664 		    if (t->next)  t->next->prev = t->prev;
665 		    t->next = Scr.ASRoot.next;
666 		    t->prev = &Scr.ASRoot;
667 		    Scr.ASRoot.next->prev = t;
668 		    Scr.ASRoot.next = t;
669 		  }
670 	      }
671 	  }
672 	XFree(children);
673       }
674     else
675       {
676 	fprintf(stderr, "CorrectStackOrder(): XQueryTree failed!\n");
677       }
678 
679     t = Scr.ASRoot.next;
680     if (t)
681       {
682         if (t->flags & ONTOP)
683           {
684 	    do { t = t->next; } while (t && (t->flags & ONTOP));
685 	    if (t)
686 	      {
687 	        do { t = t->next; } while (t && ! (t->flags & ONTOP));
688 	        if (t)  RaiseWindow(Scr.ASRoot.next);
689 	      }
690 	  }
691         else
692           {
693 	    do { t = t->next; } while (t && ! (t->flags & ONTOP));
694 	    if (t)  RaiseWindow(t);
695 	  }
696       }
697 
698     UpdateVisibility();
699 }
700