1 /****************************************************************************
2 * This module is based on Twm, but has been siginificantly modified
3 * by Rob Nation
4 *
5 * later modified for BowMan
6 * by Bo Yang
7 *
8 * again modified for AfterStep
9 * by Frank Fejes
10 ****************************************************************************/
11 /*****************************************************************************/
12 /** Copyright 1988 by Evans & Sutherland Computer Corporation, **/
13 /** Salt Lake City, Utah **/
14 /** Portions Copyright 1989 by the Massachusetts Institute of Technology **/
15 /** Cambridge, Massachusetts **/
16 /** **/
17 /** All Rights Reserved **/
18 /** **/
19 /** Permission to use, copy, modify, and distribute this software and **/
20 /** its documentation for any purpose and without fee is hereby **/
21 /** granted, provided that the above copyright notice appear in all **/
22 /** copies and that both that copyright notice and this permis- **/
23 /** sion notice appear in supporting documentation, and that the **/
24 /** names of Evans & Sutherland and M.I.T. not be used in advertising **/
25 /** in publicity pertaining to distribution of the software without **/
26 /** specific, written prior permission. **/
27 /** **/
28 /** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/
29 /** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/
30 /** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/
31 /** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/
32 /** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/
33 /** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/
34 /** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/
35 /** OR PERFORMANCE OF THIS SOFTWARE. **/
36 /*****************************************************************************/
37
38
39 /***********************************************************************
40 *
41 * afterstep event handling
42 *
43 ***********************************************************************/
44
45 #include "../configure.h"
46
47 #ifdef ISC
48 #include <sys/bsdtypes.h>
49 #endif
50
51 #include <stdio.h>
52 #include <string.h>
53 #include <sys/types.h>
54 #include <sys/time.h>
55 #include <unistd.h>
56 #include <signal.h>
57 #include <limits.h>
58 /* Some people say that AIX and AIXV3 need 3 preceding underscores, other say
59 * no. I'll do both */
60 #if defined ___AIX || defined _AIX || defined __QNX__ || defined ___AIXV3 || defined AIXV3 || defined _SEQUENT_
61 #include <sys/select.h>
62 #endif
63
64 #include "afterstep.h"
65 #include <X11/Xatom.h>
66 #include "menus.h"
67 #include "misc.h"
68 #include "parse.h"
69 #include "screen.h"
70 #ifdef SHAPE
71 #include <X11/extensions/shape.h>
72 #endif /* SHAPE */
73 #include "module.h"
74
75 #ifndef NO_PAGER
76 extern ASWindow *FindCounterpart(Window target);
77 #endif /* NO_PAGER */
78
79 extern int menuFromFrameOrWindowOrTitlebar;
80
81 static void ChangeIcon();
82
83 int Context = C_NO_CONTEXT; /* current button press context */
84 int Button = 0;
85 ASWindow *ButtonWindow; /* button press window structure */
86 XEvent Event; /* the current event */
87 ASWindow *Tmp_win; /* the current afterstep window */
88
89 int last_event_type=0;
90 Window last_event_window=0;
91
92 #ifdef SHAPE
93 extern int ShapeEventBase;
94 void HandleShapeNotify(void);
95 #endif /* SHAPE */
96
97 Window PressedW;
98
99 /***********************************************************************
100 *
101 * Procedure:
102 * DispatchEvent - handle a single X event stored in global var Event
103 *
104 ************************************************************************/
DispatchEvent()105 void DispatchEvent()
106 {
107 Window w = Event.xany.window;
108
109 StashEventTime(&Event);
110
111 if (XFindContext (dpy, w, ASContext, (caddr_t *) &Tmp_win) == XCNOENT)
112 Tmp_win = NULL;
113 last_event_type = Event.type;
114 last_event_window = w;
115
116 switch(Event.type)
117 {
118 case Expose:
119 HandleExpose();
120 break;
121 case DestroyNotify:
122 HandleDestroyNotify();
123 break;
124 case MapRequest:
125 HandleMapRequest();
126 break;
127 case MapNotify:
128 HandleMapNotify();
129 break;
130 case UnmapNotify:
131 HandleUnmapNotify();
132 break;
133 case MotionNotify:
134 HandleMotionNotify();
135 break;
136 case ButtonPress:
137 HandleButtonPress();
138 break;
139 case ButtonRelease:
140 HandleButtonRelease();
141 break;
142 case EnterNotify:
143 HandleEnterNotify();
144 break;
145 case LeaveNotify:
146 HandleLeaveNotify();
147 break;
148 case FocusIn:
149 HandleFocusIn();
150 break;
151 case ConfigureRequest:
152 HandleConfigureRequest();
153 break;
154 case ClientMessage:
155 HandleClientMessage();
156 break;
157 case PropertyNotify:
158 HandlePropertyNotify();
159 break;
160 case KeyPress:
161 HandleKeyPress();
162 break;
163 case ColormapNotify:
164 HandleColormapNotify();
165 break;
166 default:
167 #ifdef SHAPE
168 if(Event.type == (ShapeEventBase + ShapeNotify))
169 HandleShapeNotify();
170 #endif /* SHAPE */
171
172 break;
173 }
174 return;
175 }
176
177
178 /***********************************************************************
179 *
180 * Procedure:
181 * HandleEvents - handle X events
182 *
183 ************************************************************************/
HandleEvents()184 void HandleEvents()
185 {
186 while (TRUE)
187 {
188 last_event_type = 0;
189 if(My_XNextEvent(dpy, &Event))
190 {
191 DispatchEvent ();
192 }
193 }
194 }
195
196 /***********************************************************************
197 *
198 * Procedure:
199 * Find the AS context for the Event.
200 *
201 ************************************************************************/
GetContext(ASWindow * t,XEvent * e,Window * w)202 int GetContext(ASWindow *t, XEvent *e, Window *w)
203 {
204 int i;
205
206 if (t == NULL)
207 return C_ROOT;
208
209 *w= e->xany.window;
210
211 if ((*w == Scr.NoFocusWin) || (*w == Scr.Root))
212 return C_ROOT;
213
214 /* Since key presses and button presses are grabbed in the frame
215 * when we have re-parented windows, we need to find out the real
216 * window where the event occured */
217 if (! (t->flags & ICONIFIED))
218 {
219 if (e->type == KeyPress)
220 {
221 if (e->xkey.subwindow != None)
222 *w = e->xany.window = e->xkey.subwindow;
223 }
224 else if (e->type == ButtonPress)
225 {
226 if (e->xbutton.subwindow != None)
227 *w = e->xany.window = e->xbutton.subwindow;
228 else if ((*w == t->frame) && (e->xbutton.y < NS_TITLE_HEIGHT+2))
229 return C_TITLE;
230 }
231 }
232
233 if (*w == t->title_w) return C_TITLE;
234 if ((*w == t->icon_pixmap_w) || (t->flags & ICONIFIED)) return C_ICON;
235 if ((*w == t->frame) || (*w == t->side)) return C_SIDEBAR;
236
237 for(i = 0; i < 2; i++)
238 {
239 if(*w == t->corners[i])
240 {
241 Button = i;
242 return C_FRAME;
243 }
244 }
245 for(i = 0; i < Scr.nr_left_buttons; i++)
246 {
247 if(*w == t->left_w[i])
248 {
249 Button = i;
250 return (1<<i)*C_L1;
251 }
252 }
253 for(i = 0; i < Scr.nr_right_buttons; i++)
254 {
255 if(*w == t->right_w[i])
256 {
257 Button = i;
258 return (1<<i)*C_R1;
259 }
260 }
261
262 *w = t->w;
263 return C_WINDOW;
264 }
265
266 /***********************************************************************
267 *
268 * Procedure:
269 * HandleFocusIn - handles focus in events
270 *
271 ************************************************************************/
HandleFocusIn()272 void HandleFocusIn()
273 {
274 XEvent d;
275 Window w;
276
277 w= Event.xany.window;
278 while(XCheckTypedEvent(dpy,FocusIn,&d))
279 {
280 w = d.xany.window;
281 }
282 if (XFindContext (dpy, w, ASContext, (caddr_t *) &Tmp_win) == XCNOENT)
283 {
284 Tmp_win = NULL;
285 }
286
287 if(!Tmp_win)
288 {
289 SetBorder(Scr.Hilite,False,True,True,None);
290 Broadcast(M_FOCUS_CHANGE,3,0,0,0,0,0,0,0);
291 }
292 else if(Tmp_win != Scr.Hilite)
293 {
294 SetBorder(Tmp_win,True,True,True,None);
295 Broadcast(M_FOCUS_CHANGE,3,Tmp_win->w,
296 Tmp_win->frame,(unsigned long)Tmp_win,0,0,0,0);
297 }
298 }
299
300 /***********************************************************************
301 *
302 * Procedure:
303 * HandleKeyPress - key press event handler
304 *
305 ************************************************************************/
HandleKeyPress()306 void HandleKeyPress()
307 {
308 FuncKey *key;
309 unsigned int modifier;
310 Window dummy;
311
312 Context = GetContext(Tmp_win,&Event,&dummy);
313
314 modifier = (Event.xkey.state & Scr.nonlock_mods);
315 for (key = Scr.FuncKeyRoot.next; key != NULL; key = key->next)
316 {
317 ButtonWindow = Tmp_win;
318 /* Here's a real hack - some systems have two keys with the
319 * same keysym and different keycodes. This converts all
320 * the cases to one keycode. */
321 Event.xkey.keycode =
322 XKeysymToKeycode(dpy,XkbKeycodeToKeysym(dpy,Event.xkey.keycode,0,0));
323 if ((key->keycode == Event.xkey.keycode) &&
324 ((key->mods == (modifier&(~LockMask)))||
325 (key->mods == AnyModifier)) &&
326 (key->cont & Context))
327 {
328 ExecuteFunction(key->func, key->action, Event.xany.window,Tmp_win,
329 &Event,Context,key->val1,key->val2,
330 key->val1_unit,key->val2_unit,
331 key->menu,-1);
332 return;
333 }
334 }
335
336 /* if we get here, no function key was bound to the key. Send it
337 * to the client if it was in a window we know about.
338 */
339 if (Tmp_win)
340 {
341 if(Event.xkey.window != Tmp_win->w)
342 {
343 Event.xkey.window = Tmp_win->w;
344 XSendEvent(dpy, Tmp_win->w, False, KeyPressMask, &Event);
345 }
346 }
347 ButtonWindow = NULL;
348 }
349
350
351 /***********************************************************************
352 *
353 * Procedure:
354 * HandlePropertyNotify - property notify event handler
355 *
356 ***********************************************************************/
357 #define MAX_NAME_LEN 200L /* truncate to this many */
358 #define MAX_ICON_NAME_LEN 200L /* ditto */
359
HandlePropertyNotify()360 void HandlePropertyNotify()
361 {
362 char *prop = NULL;
363 Atom actual = None;
364 int actual_format;
365 unsigned long nitems, bytesafter;
366
367 if ((!Tmp_win)||(XGetGeometry(dpy, Tmp_win->w, &JunkRoot, &JunkX, &JunkY,
368 &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth) == 0))
369 return;
370
371 switch (Event.xproperty.atom)
372 {
373 case XA_WM_NAME:
374 if (XGetWindowProperty (dpy, Tmp_win->w, Event.xproperty.atom, 0L,
375 MAX_NAME_LEN, False, XA_STRING, &actual,
376 &actual_format, &nitems, &bytesafter,
377 (unsigned char **) &prop) != Success ||
378 actual == None)
379 return;
380 if (!prop) prop = NoName;
381 free_window_names (Tmp_win, True, False);
382
383 Tmp_win->name = prop;
384 BroadcastName(M_WINDOW_NAME,Tmp_win->w,Tmp_win->frame,
385 (unsigned long)Tmp_win,Tmp_win->name);
386
387 /* fix the name in the title bar */
388 if(!(Tmp_win->flags & ICONIFIED))
389 SetTitleBar(Tmp_win,(Scr.Hilite==Tmp_win),True);
390 else
391 ChangeIcon();
392
393 /*
394 * if the icon name is NoName, set the name of the icon to be
395 * the same as the window
396 */
397 if (Tmp_win->icon_name == NoName)
398 {
399 Tmp_win->icon_name = Tmp_win->name;
400 BroadcastName(M_ICON_NAME,Tmp_win->w,Tmp_win->frame,
401 (unsigned long)Tmp_win,Tmp_win->icon_name);
402 }
403 break;
404
405 case XA_WM_ICON_NAME:
406 if (XGetWindowProperty (dpy, Tmp_win->w, Event.xproperty.atom, 0,
407 MAX_ICON_NAME_LEN, False, XA_STRING, &actual,
408 &actual_format, &nitems, &bytesafter,
409 (unsigned char **) &prop) != Success ||
410 actual == None)
411 return;
412 if (!prop) prop = NoName;
413 free_window_names (Tmp_win, False, True);
414 Tmp_win->icon_name = prop;
415 BroadcastName(M_ICON_NAME,Tmp_win->w,Tmp_win->frame,
416 (unsigned long)Tmp_win,Tmp_win->icon_name);
417 if((Tmp_win->flags & ICONIFIED))
418 ChangeIcon();
419 break;
420
421 case XA_WM_HINTS:
422 if (Tmp_win->wmhints)
423 XFree ((char *) Tmp_win->wmhints);
424 Tmp_win->wmhints = XGetWMHints(dpy, Event.xany.window);
425
426 if(Tmp_win->wmhints == NULL)
427 return;
428
429 if((Tmp_win->wmhints->flags & IconPixmapHint)||
430 (Tmp_win->wmhints->flags & IconWindowHint))
431 if(Tmp_win->icon_bitmap_file == Scr.DefaultIcon)
432 Tmp_win->icon_bitmap_file = (char *)0;
433
434 if((Tmp_win->wmhints->flags & IconPixmapHint)||
435 (Tmp_win->wmhints->flags & IconWindowHint))
436 {
437 if (!(Tmp_win->flags & SUPPRESSICON))
438 {
439 if(Tmp_win->flags & ICON_OURS)
440 {
441 if(Tmp_win->icon_pixmap_w != None)
442 {
443 XDestroyWindow(dpy,Tmp_win->icon_pixmap_w);
444 XDeleteContext(dpy, Tmp_win->icon_pixmap_w, ASContext);
445 }
446 }
447 else
448 XUnmapWindow(dpy,Tmp_win->icon_pixmap_w);
449 }
450 Tmp_win->icon_pixmap_w = None;
451 Tmp_win->iconPixmap = (Window)NULL;
452 if(Tmp_win->flags & ICONIFIED)
453 {
454 Tmp_win->flags &= ~ICONIFIED;
455 Tmp_win->flags &= ~ICON_UNMAPPED;
456 CreateIconWindow(Tmp_win,Tmp_win->icon_x_loc,Tmp_win->icon_y_loc);
457 Broadcast(M_ICONIFY,7,Tmp_win->w,Tmp_win->frame,
458 (unsigned long)Tmp_win,
459 Tmp_win->icon_x_loc,
460 Tmp_win->icon_y_loc,
461 Tmp_win->icon_p_width,
462 Tmp_win->icon_p_height);
463 BroadcastConfig(M_CONFIGURE_WINDOW,Tmp_win);
464
465 if (!(Tmp_win->flags & SUPPRESSICON))
466 {
467 LowerWindow(Tmp_win);
468 AutoPlace(Tmp_win);
469 if(Tmp_win->Desk == Scr.CurrentDesk)
470 {
471 if(Tmp_win->icon_pixmap_w != None)
472 XMapWindow(dpy, Tmp_win->icon_pixmap_w);
473 }
474 }
475 Tmp_win->flags |= ICONIFIED;
476 DrawIconWindow(Tmp_win);
477 }
478 }
479 break;
480
481 case XA_WM_NORMAL_HINTS:
482 GetWindowSizeHints (Tmp_win);
483 BroadcastConfig(M_CONFIGURE_WINDOW,Tmp_win);
484 break;
485
486 default:
487 if(Event.xproperty.atom == _XA_WM_PROTOCOLS)
488 FetchWmProtocols (Tmp_win);
489 else if (Event.xproperty.atom == _XA_WM_COLORMAP_WINDOWS)
490 {
491 FetchWmColormapWindows (Tmp_win); /* frees old data */
492 ReInstallActiveColormap();
493 }
494 else if(Event.xproperty.atom == _XA_WM_STATE)
495 {
496 if((Scr.flags & ClickToFocus)&&(Tmp_win == Scr.Focus)&&
497 (Tmp_win != NULL))
498 {
499 Scr.Focus = NULL;
500 SetFocus(Tmp_win->w,Tmp_win,False);
501 }
502 }
503 break;
504 }
505 }
506
507
508 /***********************************************************************
509 *
510 * Procedure:
511 * HandleClientMessage - client message event handler
512 *
513 ************************************************************************/
HandleClientMessage()514 void HandleClientMessage()
515 {
516 XEvent button;
517
518 if ((Event.xclient.message_type == _XA_WM_CHANGE_STATE)&&
519 (Tmp_win)&&(Event.xclient.data.l[0]==IconicState)&&
520 !(Tmp_win->flags & ICONIFIED))
521 {
522 XQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild,
523 &(button.xmotion.x_root),
524 &(button.xmotion.y_root),
525 &JunkX, &JunkY, &JunkMask);
526 button.type = 0;
527 ExecuteFunction(F_ICONIFY, NULLSTR, Event.xany.window,
528 Tmp_win, &button, C_FRAME,0,0, 0,0,
529 (MenuRoot *)0,-1);
530 #ifdef ENABLE_DND
531 /* Pass the event to the client window */
532 if (Event.xclient.window != Tmp_win->w)
533 {
534 Event.xclient.window = Tmp_win->w;
535 XSendEvent(dpy,Tmp_win->w,True,NoEventMask,&Event);
536 }
537 #endif
538 }
539 }
540
541 /***********************************************************************
542 *
543 * Procedure:
544 * HandleExpose - expose event handler
545 *
546 ***********************************************************************/
HandleExpose()547 void HandleExpose()
548 {
549 if (Event.xexpose.count != 0)
550 return;
551
552 if (Tmp_win)
553 {
554 #ifndef NO_PAGER
555 if((Tmp_win->w == Scr.Pager_w)||
556 (Tmp_win->w == Scr.CPagerWin))
557 {
558 ReallyRedrawPager();
559 }
560 #endif
561 if (Event.xany.window == Tmp_win->title_w)
562 {
563 SetTitleBar(Tmp_win,(Scr.Hilite == Tmp_win),False);
564 }
565 else
566 {
567 SetBorder(Tmp_win,(Scr.Hilite == Tmp_win),True,True,Event.xany.window);
568 }
569 }
570 #ifndef NO_PAGER
571 else
572 {
573 if(FindCounterpart(Event.xany.window))
574 ReallyRedrawPager();
575 }
576 #endif
577 return;
578 }
579
580
581
582 /***********************************************************************
583 *
584 * Procedure:
585 * HandleDestroyNotify - DestroyNotify event handler
586 *
587 ***********************************************************************/
HandleDestroyNotify()588 void HandleDestroyNotify()
589 {
590 if (Tmp_win) {
591 Destroy(Tmp_win);
592 UpdateVisibility();
593 }
594 }
595
596
597
598
599 /***********************************************************************
600 *
601 * Procedure:
602 * HandleMapRequest - MapRequest event handler
603 *
604 ************************************************************************/
HandleMapRequest()605 void HandleMapRequest()
606 {
607 extern long isIconicState;
608
609 Event.xany.window = Event.xmaprequest.window;
610
611 if(XFindContext(dpy, Event.xany.window, ASContext,
612 (caddr_t *)&Tmp_win)==XCNOENT)
613 Tmp_win = NULL;
614
615 XFlush(dpy);
616
617 /* If the window has never been mapped before ... */
618 if(!Tmp_win)
619 {
620 /* Add decorations. */
621 Tmp_win = AddWindow(Event.xany.window);
622 if (Tmp_win == NULL)
623 return;
624 }
625
626 /* If it's not merely iconified, and we have hints, use them. */
627 if (!(Tmp_win->flags & ICONIFIED))
628 {
629 int state;
630
631 if(Tmp_win->wmhints && (Tmp_win->wmhints->flags & StateHint))
632 state = Tmp_win->wmhints->initial_state;
633 else
634 state = NormalState;
635
636 if(Tmp_win->flags & STARTICONIC)
637 state = IconicState;
638
639 if(isIconicState != DontCareState)
640 state = isIconicState;
641
642 XGrabServer (dpy);
643 switch (state)
644 {
645 case DontCareState:
646 case NormalState:
647 case InactiveState:
648 default:
649 if (Tmp_win->Desk == Scr.CurrentDesk)
650 {
651 XMapWindow(dpy, Tmp_win->w);
652 XMapWindow(dpy, Tmp_win->frame);
653 Tmp_win->flags |= MAP_PENDING;
654 SetMapStateProp(Tmp_win, NormalState);
655 if(Scr.flags & ClickToFocus)
656 {
657 SetFocus(Tmp_win->w,Tmp_win,False);
658 }
659 }
660 else
661 {
662 XMapWindow(dpy, Tmp_win->w);
663 SetMapStateProp(Tmp_win, NormalState);
664 }
665 break;
666
667 case IconicState:
668 Iconify(Tmp_win, 0, 0);
669 break;
670
671 case ZoomState:
672 Shade(Tmp_win);
673 break;
674 }
675 XSync(dpy,0);
676 XUngrabServer(dpy);
677 }
678 /* If no hints, or currently an icon, just "deiconify" */
679 else
680 {
681 DeIconify(Tmp_win);
682 }
683 }
684
685
686 /***********************************************************************
687 *
688 * Procedure:
689 * HandleMapNotify - MapNotify event handler
690 *
691 ***********************************************************************/
HandleMapNotify()692 void HandleMapNotify()
693 {
694 if (!Tmp_win || (Event.xmap.event == Scr.ASRoot.w))
695 {
696 return;
697 }
698
699 /*
700 * Need to do the grab to avoid race condition of having server send
701 * MapNotify to client before the frame gets mapped; this is bad because
702 * the client would think that the window has a chance of being viewable
703 * when it really isn't.
704 */
705 XGrabServer (dpy);
706 if(Tmp_win->icon_pixmap_w != None)
707 XUnmapWindow(dpy, Tmp_win->icon_pixmap_w);
708 XMapSubwindows(dpy, Tmp_win->frame);
709
710 if(Tmp_win->Desk == Scr.CurrentDesk)
711 {
712 XMapWindow(dpy, Tmp_win->frame);
713 }
714
715 if(Tmp_win->flags & ICONIFIED)
716 Broadcast(M_DEICONIFY,3,Tmp_win->w,Tmp_win->frame,
717 (unsigned long)Tmp_win,0,0,0,0);
718 else
719 {
720 Broadcast(M_MAP,3,Tmp_win->w,Tmp_win->frame,
721 (unsigned long)Tmp_win,0,0,0,0);
722 }
723
724 if(Scr.flags & ClickToFocus)
725 SetFocus(Tmp_win->w,Tmp_win,False);
726
727 if((!(Tmp_win->flags &(BORDER|TITLE)))&&(Tmp_win->boundary_width <2))
728 {
729 SetBorder(Tmp_win,False,True,True,Tmp_win->frame);
730 }
731 XSync(dpy,0);
732 XUngrabServer (dpy);
733 XFlush (dpy);
734 Tmp_win->flags |= MAPPED;
735 Tmp_win->flags &= ~MAP_PENDING;
736 Tmp_win->flags &= ~ICONIFIED;
737 Tmp_win->flags &= ~ICON_UNMAPPED;
738 UpdateVisibility();
739 }
740
741
742 /***********************************************************************
743 *
744 * Procedure:
745 * HandleUnmapNotify - UnmapNotify event handler
746 *
747 ************************************************************************/
HandleUnmapNotify()748 void HandleUnmapNotify()
749 {
750 int dstx, dsty;
751 Window dumwin;
752 XEvent dummy;
753 extern ASWindow *colormap_win;
754
755 /*
756 * The July 27, 1988 ICCCM spec states that a client wishing to switch
757 * to WithdrawnState should send a synthetic UnmapNotify with the
758 * event field set to (pseudo-)root, in case the window is already
759 * unmapped (which is the case for afterstep for IconicState). Unfortunately,
760 * we looked for the ASContext using that field, so try the window
761 * field also.
762 */
763 if (!Tmp_win)
764 {
765 Event.xany.window = Event.xunmap.window;
766 if (XFindContext(dpy, Event.xany.window,
767 ASContext, (caddr_t *)&Tmp_win) == XCNOENT)
768 Tmp_win = NULL;
769 }
770
771 if (Event.xunmap.event == Scr.ASRoot.w) return;
772
773 if(!Tmp_win)
774 return;
775
776 if(Tmp_win == Scr.Hilite)
777 Scr.Hilite = NULL;
778
779 if(Scr.PreviousFocus == Tmp_win)
780 Scr.PreviousFocus = NULL;
781
782 if((Tmp_win == Scr.Focus)&&(Scr.flags & ClickToFocus))
783 {
784 ASWindow *t, *tn = NULL;
785 long best = LONG_MIN;
786 for (t = Scr.ASRoot.next; t != NULL; t = t->next)
787 {
788 if ((t->focus_sequence > best) && (t != Tmp_win))
789 {
790 best = t->focus_sequence;
791 tn = t;
792 }
793 }
794 if (tn)
795 SetFocus(tn->w, tn, False);
796 else
797 SetFocus(Scr.NoFocusWin, NULL, False);
798 }
799
800 if(Scr.Focus == Tmp_win)
801 SetFocus(Scr.NoFocusWin, NULL, False);
802
803 if(Tmp_win == Scr.pushed_window)
804 Scr.pushed_window = NULL;
805
806 if(Tmp_win == colormap_win)
807 colormap_win = NULL;
808
809 if ((!(Tmp_win->flags & MAPPED)&&!(Tmp_win->flags&ICONIFIED)))
810 {
811 return;
812 }
813
814 XGrabServer(dpy);
815
816 if(XCheckTypedWindowEvent (dpy, Event.xunmap.window, DestroyNotify,&dummy))
817 {
818 Destroy(Tmp_win);
819 XUngrabServer (dpy);
820 UpdateVisibility();
821 return;
822 }
823
824 /*
825 * The program may have unmapped the client window, from either
826 * NormalState or IconicState. Handle the transition to WithdrawnState.
827 *
828 * We need to reparent the window back to the root (so that afterstep exiting
829 * won't cause it to get mapped) and then throw away all state (pretend
830 * that we've received a DestroyNotify).
831 */
832 if (XTranslateCoordinates (dpy, Event.xunmap.window, Scr.Root,
833 0, 0, &dstx, &dsty, &dumwin))
834 {
835 XEvent ev;
836 Bool reparented;
837
838 reparented = XCheckTypedWindowEvent (dpy, Event.xunmap.window,
839 ReparentNotify, &ev);
840 SetMapStateProp (Tmp_win, WithdrawnState);
841 if (reparented)
842 {
843 if (Tmp_win->old_bw)
844 XSetWindowBorderWidth (dpy, Event.xunmap.window, Tmp_win->old_bw);
845 if((!(Tmp_win->flags & SUPPRESSICON))&&
846 (Tmp_win->wmhints && (Tmp_win->wmhints->flags & IconWindowHint)))
847 XUnmapWindow (dpy, Tmp_win->wmhints->icon_window);
848 }
849 else
850 {
851 RestoreWithdrawnLocation (Tmp_win,False);
852 }
853 XRemoveFromSaveSet (dpy, Event.xunmap.window);
854 XSelectInput (dpy, Event.xunmap.window, NoEventMask);
855 Destroy(Tmp_win); /* do not need to mash event before */
856 /*
857 * Flush any pending events for the window.
858 */
859 /* Bzzt! it could be about to re-map */
860 /* while(XCheckWindowEvent(dpy, Event.xunmap.window,
861 StructureNotifyMask | PropertyChangeMask |
862 ColormapChangeMask |
863 EnterWindowMask | LeaveWindowMask, &dummy));
864 */
865 } /* else window no longer exists and we'll get a destroy notify */
866 XUngrabServer (dpy);
867 UpdateVisibility();
868 XFlush (dpy);
869 }
870
871
872 /***********************************************************************
873 *
874 * Procedure:
875 * HandleMotionNotify - MotionNotify event handler
876 *
877 **********************************************************************/
HandleMotionNotify()878 void HandleMotionNotify()
879 {
880 #ifndef NO_PAGER
881 extern Bool EnablePagerRedraw;
882
883 /* here is the code for dragging the viewport around within the pager.*/
884 if((Tmp_win)&&(Tmp_win->w == Scr.Pager_w)&&
885 (!(Tmp_win->flags & ICONIFIED)))
886 {
887 if(Event.xmotion.state == Button3MotionMask)
888 {
889 EnablePagerRedraw = False;
890 SwitchPages(FALSE,FALSE);
891 }
892 }
893 #endif
894 }
895
896 /***********************************************************************
897 *
898 * Procedure:
899 * HandleButtonPress - ButtonPress event handler
900 *
901 ***********************************************************************/
HandleButtonPress()902 void HandleButtonPress()
903 {
904 #ifndef NO_PAGER
905 extern Bool EnablePagerRedraw;
906 #endif
907 unsigned int modifier;
908 MouseButton *MouseEntry;
909 char *Action;
910 Window xPressedW;
911 int LocalContext;
912
913 Context = GetContext(Tmp_win,&Event, &PressedW);
914 LocalContext = Context;
915 xPressedW= PressedW;
916
917 /* click to focus stuff goes here */
918 if (Scr.flags & ClickToFocus)
919 {
920 if (Tmp_win && (Tmp_win != Scr.Ungrabbed)
921 && ((Event.xbutton.state & Scr.nonlock_mods) == 0))
922 {
923 Bool focusAccepted = SetFocus(Tmp_win->w,Tmp_win,False);
924
925 if (! (Tmp_win->flags & VISIBLE))
926 {
927 if ((Scr.flags & ClickToRaise) && (Context == C_WINDOW)
928 && (Scr.RaiseButtons & (1<<Event.xbutton.button)))
929 RaiseWindow(Tmp_win);
930 else
931 {
932 if(Scr.AutoRaiseDelay > 0)
933 {
934 SetTimer(Scr.AutoRaiseDelay);
935 }
936 else
937 {
938 #ifdef CLICKY_MODE_1
939 if((Event.xany.window != Tmp_win->w)&&
940 (Event.xbutton.subwindow != Tmp_win->w)&&
941 (Event.xany.window != Tmp_win->Parent)&&
942 (Event.xbutton.subwindow != Tmp_win->Parent))
943 #endif
944 {
945 if(Scr.AutoRaiseDelay == 0)
946 RaiseWindow(Tmp_win);
947 }
948 }
949 }
950 }
951 if(!(Tmp_win->flags & ICONIFIED) && focusAccepted)
952 {
953 XSync(dpy,0);
954 if ((Scr.flags & EatFocusClick) && (Context == C_WINDOW))
955 XAllowEvents(dpy, AsyncPointer, CurrentTime);
956 else
957 XAllowEvents(dpy,ReplayPointer,CurrentTime);
958
959 XSync(dpy,0);
960 return;
961 }
962 }
963 }
964 else if((Scr.flags & ClickToRaise) && Tmp_win && (Context == C_WINDOW)
965 && (Scr.RaiseButtons & (1<<Event.xbutton.button))
966 && ((Event.xbutton.state & Scr.nonlock_mods) == 0)
967 && ((Tmp_win->flags & VISIBLE) == 0))
968 {
969 RaiseWindow(Tmp_win);
970 if(!(Tmp_win->flags & ICONIFIED))
971 {
972 XSync(dpy,0);
973 XAllowEvents(dpy,AsyncPointer,CurrentTime);
974 XSync(dpy,0);
975 return;
976 }
977 }
978 XSync(dpy,0);
979 XAllowEvents(dpy, (Context == C_WINDOW) ? ReplayPointer : AsyncPointer,
980 CurrentTime);
981 XSync(dpy,0);
982
983 /* here is the code for moving windows in the pager.*/
984 #ifndef NO_PAGER
985 if((Tmp_win)&&(Tmp_win->w == Event.xbutton.window)&&
986 (Tmp_win->w == Scr.Pager_w)&&(Event.xbutton.button == Button2))
987 {
988 PagerMoveWindow();
989 return;
990 }
991 if((Tmp_win)&&(Tmp_win->w == Scr.Pager_w)&&
992 (!(Tmp_win->flags & ICONIFIED))&&
993 (Event.xbutton.button == Button3)&&
994 (Event.xany.window == Scr.Pager_w))
995 {
996 #ifndef NO_PAGER
997 EnablePagerRedraw = False;
998 #endif
999 SwitchPages(FALSE,FALSE);
1000 }
1001 #endif
1002
1003 if(Context == C_TITLE)
1004 SetTitleBar(Tmp_win,(Scr.Hilite == Tmp_win),False);
1005 else
1006 SetBorder(Tmp_win,(Scr.Hilite == Tmp_win),True,True,PressedW);
1007
1008 ButtonWindow = Tmp_win;
1009
1010 /* we have to execute a function or pop up a menu
1011 */
1012
1013 modifier = (Event.xbutton.state & Scr.nonlock_mods);
1014 /* need to search for an appropriate mouse binding */
1015 MouseEntry = Scr.MouseButtonRoot;
1016 while(MouseEntry != (MouseButton *)0)
1017 {
1018 if(((MouseEntry->Button == Event.xbutton.button)||(MouseEntry->Button == 0))&&
1019 (MouseEntry->Context & Context)&&
1020 ((MouseEntry->Modifier == AnyModifier)||
1021 (MouseEntry->Modifier == modifier)))
1022 {
1023 /* got a match, now process it */
1024 if (MouseEntry->func != (int)NULL)
1025 {
1026 Action = MouseEntry->item ? MouseEntry->item->action : NULL;
1027 ExecuteFunction(MouseEntry->func, Action, Event.xany.window,
1028 Tmp_win, &Event, Context,MouseEntry->val1,
1029 MouseEntry->val2,
1030 MouseEntry->val1_unit,MouseEntry->val2_unit,
1031 MouseEntry->menu,-1);
1032 break;
1033 }
1034 }
1035 MouseEntry = MouseEntry->NextButton;
1036 }
1037 PressedW = None;
1038
1039 if(LocalContext!=C_TITLE)
1040 SetBorder(ButtonWindow,(Scr.Hilite == ButtonWindow),True,True,xPressedW);
1041 else
1042 SetTitleBar(ButtonWindow,(Scr.Hilite==ButtonWindow),False);
1043
1044 ButtonWindow = NULL;
1045 }
1046
1047 /***********************************************************************
1048 *
1049 * Procedure:
1050 * HandleButtonRelease - ButtonRelease event handler
1051 *
1052 ***********************************************************************/
HandleButtonRelease()1053 void HandleButtonRelease()
1054 {
1055 #ifndef NO_PAGER
1056 extern Bool EnablePagerRedraw;
1057 if((Tmp_win)&&(Event.xany.window == Scr.Pager_w)&&
1058 (!(Tmp_win->flags & ICONIFIED)))
1059 {
1060 switch(Event.xbutton.button)
1061 {
1062 default:
1063 case Button1:
1064 SwitchPages(TRUE,TRUE);
1065 break;
1066 case Button3:
1067 EnablePagerRedraw = True;
1068 SwitchPages(FALSE,FALSE);
1069 RedrawPager();
1070 break;
1071 }
1072 }
1073 #endif
1074 }
1075
1076
1077 /***********************************************************************
1078 *
1079 * Procedure:
1080 * HandleEnterNotify - EnterNotify event handler
1081 *
1082 ************************************************************************/
HandleEnterNotify()1083 void HandleEnterNotify()
1084 {
1085 XEnterWindowEvent *ewp = &Event.xcrossing;
1086 XEvent d;
1087
1088 /* look for a matching leaveNotify which would nullify this enterNotify */
1089 if(XCheckTypedWindowEvent (dpy, ewp->window, LeaveNotify, &d))
1090 {
1091 StashEventTime(&d);
1092 if((d.xcrossing.mode==NotifyNormal)&&
1093 (d.xcrossing.detail!=NotifyInferior))
1094 return;
1095 }
1096
1097 /* an EnterEvent in one of the PanFrameWindows activates the Paging */
1098 #ifndef NON_VIRTUAL
1099 if (ewp->window==Scr.PanFrameTop.win
1100 || ewp->window==Scr.PanFrameLeft.win
1101 || ewp->window==Scr.PanFrameRight.win
1102 || ewp->window==Scr.PanFrameBottom.win )
1103 {
1104 int delta_x=0, delta_y=0;
1105 /* this was in the HandleMotionNotify before, HEDU */
1106 HandlePaging(Scr.EdgeScrollX,Scr.EdgeScrollY,
1107 &Event.xcrossing.x_root,&Event.xcrossing.y_root,
1108 &delta_x,&delta_y,True);
1109 return;
1110 }
1111 #endif /* NON_VIRTUAL */
1112
1113 if(Event.xany.window == Scr.Root)
1114 {
1115 if((!(Scr.flags & ClickToFocus))&&(!(Scr.flags & SloppyFocus)))
1116 {
1117 SetFocus(Scr.NoFocusWin,NULL,False);
1118 }
1119 InstallWindowColormaps(NULL);
1120 return;
1121 }
1122
1123 /* make sure its for one of our windows */
1124 if (!Tmp_win)
1125 return;
1126
1127 if (Tmp_win->focus_var == 0)
1128 {
1129 if(!(Scr.flags & ClickToFocus))
1130 {
1131 if(Scr.Focus != Tmp_win)
1132 {
1133 if((Scr.AutoRaiseDelay > 0)&&(!(Tmp_win->flags & VISIBLE)))
1134 SetTimer(Scr.AutoRaiseDelay);
1135 SetFocus(Tmp_win->w,Tmp_win,False);
1136 }
1137 else
1138 SetFocus(Tmp_win->w,Tmp_win, True); /* don't affect the circ.seq. */
1139 }
1140 if((!(Tmp_win->flags & ICONIFIED))&&(Event.xany.window == Tmp_win->w))
1141 InstallWindowColormaps(Tmp_win);
1142 else
1143 InstallWindowColormaps(NULL);
1144 }
1145 return;
1146 }
1147
1148
1149 /***********************************************************************
1150 *
1151 * Procedure:
1152 * HandleLeaveNotify - LeaveNotify event handler
1153 *
1154 ************************************************************************/
HandleLeaveNotify()1155 void HandleLeaveNotify()
1156 {
1157 /* If we leave the root window, then we're really moving
1158 * another screen on a multiple screen display, and we
1159 * need to de-focus and unhighlight to make sure that we
1160 * don't end up with more than one highlighted window at a time */
1161 if(Event.xcrossing.window == Scr.Root)
1162 {
1163 if(Event.xcrossing.mode == NotifyNormal)
1164 {
1165 if (Event.xcrossing.detail != NotifyInferior)
1166 {
1167 if(Scr.Focus != NULL)
1168 {
1169 SetFocus(Scr.NoFocusWin,NULL,False);
1170 }
1171 if(Scr.Hilite != NULL)
1172 SetBorder(Scr.Hilite,False,True,True,None);
1173 }
1174 }
1175 }
1176 }
1177
1178
1179 /***********************************************************************
1180 *
1181 * Procedure:
1182 * HandleConfigureRequest - ConfigureRequest event handler
1183 *
1184 ************************************************************************/
HandleConfigureRequest()1185 void HandleConfigureRequest()
1186 {
1187 XWindowChanges xwc;
1188 unsigned long xwcm;
1189 int x, y, width, height;
1190 XConfigureRequestEvent *cre = &Event.xconfigurerequest;
1191
1192 /*
1193 * Event.xany.window is Event.xconfigurerequest.parent, so Tmp_win will
1194 * be wrong
1195 */
1196 Event.xany.window = cre->window; /* mash parent field */
1197 if (XFindContext (dpy, cre->window, ASContext, (caddr_t *) &Tmp_win) ==
1198 XCNOENT)
1199 Tmp_win = NULL;
1200
1201 /*
1202 * According to the July 27, 1988 ICCCM draft, we should ignore size and
1203 * position fields in the WM_NORMAL_HINTS property when we map a window.
1204 * Instead, we'll read the current geometry. Therefore, we should respond
1205 * to configuration requests for windows which have never been mapped.
1206 */
1207 if (!Tmp_win )
1208 {
1209 xwcm = cre->value_mask &
1210 (CWX | CWY | CWWidth | CWHeight | CWBorderWidth);
1211 xwc.x = cre->x;
1212 xwc.y = cre->y;
1213 xwc.width = cre->width;
1214 xwc.height = cre->height;
1215 xwc.border_width = cre->border_width;
1216 XConfigureWindow(dpy, Event.xany.window, xwcm, &xwc);
1217
1218 if(Tmp_win)
1219 {
1220 xwc.x = Tmp_win->icon_x_loc;
1221 xwc.y = Tmp_win->icon_y_loc - Tmp_win->icon_p_height;
1222 xwcm = cre->value_mask & (CWX | CWY);
1223 if(Tmp_win->icon_pixmap_w != None)
1224 XConfigureWindow(dpy, Tmp_win->icon_pixmap_w, xwcm, &xwc);
1225 xwc.x = Tmp_win->icon_x_loc;
1226 xwc.y = Tmp_win->icon_y_loc;
1227 xwcm = cre->value_mask & (CWX | CWY);
1228 }
1229 return;
1230 }
1231
1232 if (cre->value_mask & CWStackMode)
1233 {
1234 ASWindow *otherwin;
1235
1236 xwc.sibling = (((cre->value_mask & CWSibling) &&
1237 (XFindContext (dpy, cre->above, ASContext,
1238 (caddr_t *) &otherwin) == XCSUCCESS))
1239 ? otherwin->frame : cre->above);
1240 xwc.stack_mode = cre->detail;
1241 XConfigureWindow (dpy, Tmp_win->frame,
1242 cre->value_mask & (CWSibling | CWStackMode), &xwc);
1243 XSync(dpy, False);
1244 CorrectStackOrder();
1245 }
1246
1247 #ifdef SHAPE
1248 {
1249 int xws, yws, xbs, ybs;
1250 unsigned wws, hws, wbs, hbs;
1251 int boundingShaped, clipShaped;
1252
1253 XShapeQueryExtents (dpy, Tmp_win->w,&boundingShaped, &xws, &yws, &wws,
1254 &hws,&clipShaped, &xbs, &ybs, &wbs, &hbs);
1255 Tmp_win->wShaped = boundingShaped;
1256 }
1257 #endif /* SHAPE */
1258
1259 /* Don't modify frame_XXX fields before calling SetupWindow! */
1260 x = Tmp_win->frame_x;
1261 y = Tmp_win->frame_y;
1262 width = Tmp_win->frame_width;
1263 height = Tmp_win->frame_height;
1264
1265 /* for restoring */
1266 if (cre->value_mask & CWBorderWidth)
1267 {
1268 Tmp_win->old_bw = cre->border_width;
1269 }
1270 /* override even if border change */
1271
1272 if (cre->value_mask & CWX)
1273 x = cre->x - Tmp_win->boundary_width - Tmp_win->bw;
1274 if (cre->value_mask & CWY)
1275 y = cre->y - Tmp_win->title_height - Tmp_win->bw;
1276 if (cre->value_mask & CWWidth)
1277 width = cre->width + 2*Tmp_win->boundary_width;
1278 if (cre->value_mask & CWHeight)
1279 height = cre->height+Tmp_win->title_height+Tmp_win->boundary_height;
1280
1281 /*
1282 * SetupWindow (x,y) are the location of the upper-left outer corner and
1283 * are passed directly to XMoveResizeWindow (frame). The (width,height)
1284 * are the inner size of the frame. The inner width is the same as the
1285 * requested client window width; the inner height is the same as the
1286 * requested client window height plus any title bar slop.
1287 */
1288 SetupFrame (Tmp_win, x, y, width, height,FALSE);
1289 UpdateVisibility();
1290
1291 #ifndef NO_PAGER
1292 RedrawPager();
1293 #endif
1294 }
1295
1296 /***********************************************************************
1297 *
1298 * Procedure:
1299 * HandleShapeNotify - shape notification event handler
1300 *
1301 ***********************************************************************/
1302 #ifdef SHAPE
HandleShapeNotify(void)1303 void HandleShapeNotify (void)
1304 {
1305 XShapeEvent *sev = (XShapeEvent *) &Event;
1306
1307 if (!Tmp_win)
1308 return;
1309 if (sev->kind != ShapeBounding)
1310 return;
1311 Tmp_win->wShaped = sev->shaped;
1312 SetShape(Tmp_win,Tmp_win->frame_width);
1313 }
1314 #endif /* SHAPE*/
1315
1316 /**************************************************************************
1317 *
1318 * For auto-raising windows, this routine is called
1319 *
1320 *************************************************************************/
1321 volatile int alarmed;
enterAlarm(int nonsense)1322 void enterAlarm(int nonsense)
1323 {
1324 alarmed = True;
1325 signal(SIGALRM, enterAlarm);
1326 }
1327
1328
1329 /***************************************************************************
1330 *
1331 * Waits for next X event, or for an auto-raise timeout.
1332 *
1333 ****************************************************************************/
My_XNextEvent(Display * dpy,XEvent * event)1334 int My_XNextEvent(Display *dpy, XEvent *event)
1335 {
1336 extern int fd_width, x_fd;
1337 struct itimerval value;
1338 fd_set in_fdset,out_fdset;
1339 Window child;
1340 Window targetWindow;
1341 int i,count;
1342 int retval;
1343
1344 /* Do this prior to the select() call, in case the timer already expired,
1345 * in which case the select would never return. */
1346 if(alarmed)
1347 {
1348 alarmed = False;
1349 XQueryPointer(dpy,Scr.Root,&JunkRoot,&child,&JunkX,&JunkY,&JunkX,
1350 &JunkY,&JunkMask );
1351 if((Scr.Focus != NULL)&&(child == Scr.Focus->frame))
1352 {
1353 if(!(Scr.Focus->flags & VISIBLE))
1354 {
1355 RaiseWindow(Scr.Focus);
1356 #ifndef NO_PAGER
1357 RedrawPager();
1358 #endif
1359 }
1360 }
1361 return 0;
1362 }
1363
1364 #ifndef HAVE_GETITIMER
1365 value.it_value.tv_usec = 0;
1366 value.it_value.tv_sec = 0;
1367 #else
1368 getitimer(ITIMER_REAL,&value);
1369 #endif
1370
1371 FD_ZERO(&in_fdset);
1372 FD_SET(x_fd,&in_fdset);
1373 FD_ZERO(&out_fdset);
1374 for(i=0; i<npipes; i++)
1375 {
1376 if(readPipes[i]>=0)
1377 {
1378 FD_SET(readPipes[i], &in_fdset);
1379 }
1380 }
1381
1382 for(i=0; i<npipes; i++)
1383 {
1384 if(pipeQueue[i]!= NULL)
1385 {
1386 FD_SET(writePipes[i], &out_fdset);
1387 }
1388 }
1389
1390
1391 /* Do this IMMEDIATELY prior to select, to prevent any nasty
1392 * queued up X events from just hanging around waiting to be
1393 * flushed */
1394 XFlush(dpy);
1395 if(XPending(dpy))
1396 {
1397 XNextEvent(dpy,event);
1398 StashEventTime(event);
1399 return 1;
1400 }
1401
1402 /* Zap all those zombies! */
1403 /* If we get to here, then there are no X events waiting to be processed.
1404 * Just take a moment to check for dead children. */
1405 ReapChildren();
1406
1407 XFlush(dpy);
1408 if((value.it_value.tv_usec != 0)||
1409 (value.it_value.tv_sec != 0))
1410 #ifdef __hpux
1411 retval=select(fd_width,(int *)&in_fdset, 0, 0, &value.it_value);
1412 #else
1413 retval=select(fd_width,&in_fdset, 0, 0, &value.it_value);
1414 #endif
1415 else
1416 #ifdef __hpux
1417 retval=select(fd_width,(int *)&in_fdset, (int *)&out_fdset,
1418 0, NULL);
1419 #else
1420 retval=select(fd_width,&in_fdset, &out_fdset, 0, NULL);
1421 #endif
1422
1423 /* Check for module input. */
1424 for(i=0;i<npipes;i++)
1425 {
1426 if(readPipes[i] >= 0)
1427 {
1428 if((retval>0)&&(FD_ISSET(readPipes[i], &in_fdset)))
1429 {
1430 if((count =
1431 read(readPipes[i],&targetWindow, sizeof(Window))) >0)
1432 {
1433 HandleModuleInput(targetWindow,i);
1434 }
1435 if(count <= 0)
1436 {
1437 KillModule(i,10);
1438 }
1439 }
1440 }
1441 if(writePipes[i] >= 0)
1442 {
1443 if((retval>0)&&(FD_ISSET(writePipes[i], &out_fdset)))
1444 {
1445 FlushQueue(i);
1446 }
1447 }
1448 }
1449 return 0;
1450 }
1451
1452 /* Change the icon, bugs for that to wiz@iol.it */
ChangeIcon()1453 void ChangeIcon()
1454 {
1455 char *cp;
1456 if (!(Tmp_win->flags & SUPPRESSICON) && (Tmp_win->flags & ICON_OURS)) {
1457 SearchIcon(Tmp_win,&cp);
1458 if(cp && !( Tmp_win->icon_bitmap_file && cp == Tmp_win->icon_bitmap_file ))
1459 Tmp_win->icon_bitmap_file=cp;
1460 else
1461 return;
1462 }
1463 GetIcon(Tmp_win);
1464 DrawIconWindow(Tmp_win);
1465 }
1466
SearchIcon(ASWindow * tmp_win,char ** value)1467 void SearchIcon(ASWindow *tmp_win, char**value)
1468 {
1469 name_list *nptr=Scr.TheList;
1470 *value = NULL;
1471 /* Start from the last element, because we are looking for
1472 an icon name and it is the last match that should win,
1473 I think better to start from the end of the list...;)
1474 */
1475
1476 if(!nptr)
1477 return;
1478 nptr=nptr->prev;
1479 do{
1480 if(nptr->value){
1481 if (matchWildcards(nptr->name,tmp_win->icon_name) == TRUE){
1482 *value = nptr->value;
1483 return;
1484 }
1485 if (matchWildcards(nptr->name,tmp_win->name) == TRUE){
1486 *value = nptr->value;
1487 return;
1488 }
1489 if (matchWildcards(nptr->name,tmp_win->class.res_name) == TRUE ){
1490 *value = nptr->value;
1491 return;
1492 }
1493 if (matchWildcards(nptr->name,tmp_win->class.res_class) == TRUE){
1494 *value = nptr->value;
1495 return;
1496 }
1497
1498 }
1499 nptr=nptr->prev;
1500 } while(nptr != Scr.TheList);
1501
1502 }
1503