1 /*****************************************************************************/
2 /** Copyright 1988 by Evans & Sutherland Computer Corporation, **/
3 /** Salt Lake City, Utah **/
4 /** Portions Copyright 1989 by the Massachusetts Institute of Technology **/
5 /** Cambridge, Massachusetts **/
7 /** All Rights Reserved **/
9 /** Permission to use, copy, modify, and distribute this software and **/
10 /** its documentation for any purpose and without fee is hereby **/
11 /** granted, provided that the above copyright notice appear in all **/
12 /** copies and that both that copyright notice and this permis- **/
13 /** sion notice appear in supporting documentation, and that the **/
14 /** names of Evans & Sutherland and M.I.T. not be used in advertising **/
15 /** in publicity pertaining to distribution of the software without **/
16 /** specific, written prior permission. **/
18 /** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/
19 /** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/
20 /** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/
21 /** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/
22 /** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/
23 /** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/
24 /** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/
25 /** OR PERFORMANCE OF THIS SOFTWARE. **/
26 /*****************************************************************************/
29 /***********************************************************************
31 * $XConsortium: events.c,v 1.182 91/07/17 13:59:14 dave Exp $
35 * 17-Nov-87 Thomas E. LaStrange File created
37 ***********************************************************************/
42 #include <X11/Xatom.h>
43 #include "add_window.h"
55 #ifndef NO_SOUND_SUPPORT
58 /* Submitted by Takeharu Kato */
60 #include <sys/select.h> /* RAISEDELAY */
62 #include <sys/time.h> /* RAISEDELAY */
63 #include <sys/types.h> /* RAISEDELAY */
67 extern void IconDown();
69 extern void AppletDown();
71 static void do_menu ();
74 extern int iconifybox_width, iconifybox_height;
75 extern unsigned int mods_used;
76 extern int menuFromFrameOrWindowOrTitlebar;
78 #ifndef NO_SOUND_SUPPORT
79 extern int createSoundFromFunction;
80 extern int destroySoundFromFunction;
83 #define MAX_X_EVENT 256
84 event_proc EventHandler[MAX_X_EVENT]; /* event handler jump table */
86 int Context = C_NO_CONTEXT; /* current button press context */
87 TwmWindow *ButtonWindow; /* button press window structure */
88 XEvent ButtonEvent; /* button press event */
89 XEvent Event; /* the current event */
90 TwmWindow *Tmp_win; /* the current twm window */
92 /* Used in HandleEnterNotify to remove border highlight from a window
93 * that has not recieved a LeaveNotify event because of a pointer grab
95 TwmWindow *UnHighLight_win = NULL;
97 Window DragWindow; /* variables used in moving windows */
107 /* Vars to tell if the resize has moved. */
108 extern int ResizeOrigX;
109 extern int ResizeOrigY;
111 static int enter_flag;
112 static int ColortableThrashing;
113 static TwmWindow *enter_win, *raise_win;
115 ScreenInfo *FindScreenInfo();
116 int ButtonPressed = -1;
118 int GlobalFirstTime = True;
119 int GlobalMenuButton = False;
121 void HandleCreateNotify();
123 void HandleShapeNotify ();
124 extern int ShapeEventBase, ShapeErrorBase;
126 void AutoRaiseWindow (tmp)
129 XRaiseWindow (dpy, tmp->frame);
130 XRaiseWindow (dpy, tmp->VirtualDesktopDisplayWindow);
132 RaiseStickyAbove(); /* DSE */
141 void SetRaiseWindow (tmp)
152 /***********************************************************************
155 * InitEvents - initialize the event jump table
157 ***********************************************************************
169 enter_win = raise_win = NULL;
171 for (i = 0; i < MAX_X_EVENT; i++)
172 EventHandler[i] = HandleUnknown;
174 EventHandler[Expose] = HandleExpose;
175 EventHandler[CreateNotify] = HandleCreateNotify;
176 EventHandler[DestroyNotify] = HandleDestroyNotify;
177 EventHandler[MapRequest] = HandleMapRequest;
178 EventHandler[MapNotify] = HandleMapNotify;
179 EventHandler[UnmapNotify] = HandleUnmapNotify;
180 #if 0 /* functionality moved to menus.c:ExecuteFunction() - djhjr - 11/7/03 */
181 EventHandler[MotionNotify] = HandleMotionNotify;
183 EventHandler[ButtonRelease] = HandleButtonRelease;
184 EventHandler[ButtonPress] = HandleButtonPress;
185 EventHandler[EnterNotify] = HandleEnterNotify;
186 EventHandler[LeaveNotify] = HandleLeaveNotify;
187 EventHandler[ConfigureRequest] = HandleConfigureRequest;
188 EventHandler[ClientMessage] = HandleClientMessage;
189 EventHandler[PropertyNotify] = HandlePropertyNotify;
190 EventHandler[KeyPress] = HandleKeyPress;
191 EventHandler[ColormapNotify] = HandleColormapNotify;
192 EventHandler[VisibilityNotify] = HandleVisibilityNotify;
194 EventHandler[ShapeEventBase+ShapeNotify] = HandleShapeNotify;
200 Time lastTimestamp = CurrentTime; /* until Xlib does this for us */
202 Bool StashEventTime (ev)
208 lastTimestamp = ev->xkey.time;
212 lastTimestamp = ev->xbutton.time;
215 lastTimestamp = ev->xmotion.time;
219 lastTimestamp = ev->xcrossing.time;
222 lastTimestamp = ev->xproperty.time;
225 lastTimestamp = ev->xselectionclear.time;
227 case SelectionRequest:
228 lastTimestamp = ev->xselectionrequest.time;
230 case SelectionNotify:
231 lastTimestamp = ev->xselection.time;
240 * WindowOfEvent - return the window about which this event is concerned; this
241 * window may not be the same as XEvent.xany.window (the first window listed
244 Window WindowOfEvent (e)
248 * Each window subfield is marked with whether or not it is the same as
249 * XEvent.xany.window or is different (which is the case for some of the
254 case KeyRelease: return e->xkey.window; /* same */
256 case ButtonRelease: return e->xbutton.window; /* same */
257 case MotionNotify: return e->xmotion.window; /* same */
259 case LeaveNotify: return e->xcrossing.window; /* same */
261 case FocusOut: return e->xfocus.window; /* same */
262 case KeymapNotify: return e->xkeymap.window; /* same */
263 case Expose: return e->xexpose.window; /* same */
264 case GraphicsExpose: return e->xgraphicsexpose.drawable; /* same */
265 case NoExpose: return e->xnoexpose.drawable; /* same */
266 case VisibilityNotify: return e->xvisibility.window; /* same */
267 case CreateNotify: return e->xcreatewindow.window; /* DIFF */
268 case DestroyNotify: return e->xdestroywindow.window; /* DIFF */
269 case UnmapNotify: return e->xunmap.window; /* DIFF */
270 case MapNotify: return e->xmap.window; /* DIFF */
271 case MapRequest: return e->xmaprequest.window; /* DIFF */
272 case ReparentNotify: return e->xreparent.window; /* DIFF */
273 case ConfigureNotify: return e->xconfigure.window; /* DIFF */
274 case ConfigureRequest: return e->xconfigurerequest.window; /* DIFF */
275 case GravityNotify: return e->xgravity.window; /* DIFF */
276 case ResizeRequest: return e->xresizerequest.window; /* same */
277 case CirculateNotify: return e->xcirculate.window; /* DIFF */
278 case CirculateRequest: return e->xcirculaterequest.window; /* DIFF */
279 case PropertyNotify: return e->xproperty.window; /* same */
280 case SelectionClear: return e->xselectionclear.window; /* same */
281 case SelectionRequest: return e->xselectionrequest.requestor; /* DIFF */
282 case SelectionNotify: return e->xselection.requestor; /* same */
283 case ColormapNotify: return e->xcolormap.window; /* same */
284 case ClientMessage: return e->xclient.window; /* same */
285 case MappingNotify: return None;
292 /***********************************************************************
296 * handle a single X event stored in global var Event
297 * this routine for is for a call during an f.move
299 **********************************************************************/
301 * Merged into DispatchEvent()
305 Bool DispatchEvent2 ()
307 Window w = Event.xany.window;
308 StashEventTime (&Event);
310 if (XFindContext (dpy, w, TwmContext, (caddr_t *) &Tmp_win) == XCNOENT)
313 if (XFindContext (dpy, w, ScreenContext, (caddr_t *)&Scr) == XCNOENT) {
314 Scr = FindScreenInfo (WindowOfEvent (&Event));
317 if (!Scr) return False;
319 if (menuFromFrameOrWindowOrTitlebar && Event.type == Expose)
322 if (!menuFromFrameOrWindowOrTitlebar && Event.type>= 0 && Event.type < MAX_X_EVENT) {
323 (*EventHandler[Event.type])();
330 /***********************************************************************
333 * DispatchEvent - handle a single X event stored in global var Event
335 ***********************************************************************
337 Bool DispatchEvent ()
339 Window w = Event.xany.window;
340 StashEventTime (&Event);
342 if (XFindContext (dpy, w, TwmContext, (caddr_t *) &Tmp_win) == XCNOENT)
345 if (XFindContext (dpy, w, ScreenContext, (caddr_t *)&Scr) == XCNOENT)
346 Scr = FindScreenInfo (WindowOfEvent (&Event));
348 if (!Scr) return False;
350 if (MoveFunction != F_NOFUNCTION && menuFromFrameOrWindowOrTitlebar)
352 if (Event.type == Expose)
355 else if (Event.type >= 0 && Event.type < MAX_X_EVENT)
356 (*EventHandler[Event.type])();
363 /***********************************************************************
366 * HandleEvents - handle X events
368 ***********************************************************************
376 if (enter_flag && !QLength(dpy)) {
377 if (enter_win && enter_win != raise_win) {
378 AutoRaiseWindow (enter_win); /* sets enter_flag T */
383 if (ColortableThrashing && !QLength(dpy) && Scr) {
384 InstallWindowColormaps(ColormapNotify, (TwmWindow *) NULL);
387 XNextEvent(dpy, &Event);
388 (void) DispatchEvent ();
394 /***********************************************************************
397 * HandleColormapNotify - colormap notify event handler
399 * This procedure handles both a client changing its own colormap, and
400 * a client explicitly installing its colormap itself (only the window
401 * manager should do that, so we must set it correctly).
403 ***********************************************************************
407 HandleColormapNotify()
409 XColormapEvent *cevent = (XColormapEvent *) &Event;
410 ColormapWindow *cwin, **cwins;
412 int lost, won, n, number_cwins;
413 extern TwmColormap *CreateTwmColormap();
415 if (XFindContext(dpy, cevent->window, ColormapContext, (caddr_t *)&cwin) == XCNOENT)
417 cmap = cwin->colormap;
421 if (XFindContext(dpy, cevent->colormap, ColormapContext,
422 (caddr_t *)&cwin->colormap) == XCNOENT)
423 cwin->colormap = CreateTwmColormap(cevent->colormap);
425 cwin->colormap->refcnt++;
429 if (cevent->state == ColormapUninstalled)
430 cmap->state &= ~CM_INSTALLED;
432 cmap->state |= CM_INSTALLED;
434 if (cmap->state & CM_INSTALLABLE)
435 InstallWindowColormaps(ColormapNotify, (TwmWindow *) NULL);
437 if (cmap->refcnt == 0)
439 XDeleteContext(dpy, cmap->c, ColormapContext);
446 if (cevent->state == ColormapUninstalled &&
447 (cmap->state & CM_INSTALLABLE))
449 if (!(cmap->state & CM_INSTALLED))
451 cmap->state &= ~CM_INSTALLED;
453 if (!ColortableThrashing)
455 ColortableThrashing = TRUE;
459 if (cevent->serial >= Scr->cmapInfo.first_req)
461 number_cwins = Scr->cmapInfo.cmaps->number_cwins;
464 * Find out which colortables collided.
467 cwins = Scr->cmapInfo.cmaps->cwins;
468 for (lost = won = -1, n = 0;
469 (lost == -1 || won == -1) && n < number_cwins;
472 if (lost == -1 && cwins[n] == cwin)
474 lost = n; /* This is the window which lost its colormap */
479 cwins[n]->colormap->install_req == cevent->serial)
481 won = n; /* This is the window whose colormap caused */
482 continue; /* the de-install of the previous colormap */
488 ** Both the request and the window were found:
489 ** One of the installs made honoring the WM_COLORMAP
490 ** property caused another of the colormaps to be
491 ** de-installed, just mark the scoreboard.
493 ** Only the request was found:
494 ** One of the installs made honoring the WM_COLORMAP
495 ** property caused a window not in the WM_COLORMAP
496 ** list to lose its map. This happens when the map
497 ** it is losing is one which is trying to be installed,
498 ** but is getting getting de-installed by another map
499 ** in this case, we'll get a scoreable event later,
500 ** this one is meaningless.
502 ** Neither the request nor the window was found:
503 ** Somebody called installcolormap, but it doesn't
504 ** affect the WM_COLORMAP windows. This case will
505 ** probably never occur.
507 ** Only the window was found:
508 ** One of the WM_COLORMAP windows lost its colormap
509 ** but it wasn't one of the requests known. This is
510 ** probably because someone did an "InstallColormap".
511 ** The colormap policy is "enforced" by re-installing
512 ** the colormaps which are believed to be correct.
518 /* lower diagonal index calculation */
520 n = lost*(lost-1)/2 + won;
522 n = won*(won-1)/2 + lost;
523 Scr->cmapInfo.cmaps->scoreboard[n] = 1;
527 ** One of the cwin installs caused one of the cwin
528 ** colormaps to be de-installed, so I'm sure to get an
529 ** UninstallNotify for the cwin I know about later.
530 ** I haven't got it yet, or the test of CM_INSTALLED
531 ** above would have failed. Turning the CM_INSTALLED
532 ** bit back on makes sure we get back here to score
535 cmap->state |= CM_INSTALLED;
538 InstallWindowColormaps(ColormapNotify, (TwmWindow *) NULL);
542 else if (cevent->state == ColormapUninstalled)
543 cmap->state &= ~CM_INSTALLED;
545 else if (cevent->state == ColormapInstalled)
546 cmap->state |= CM_INSTALLED;
551 /***********************************************************************
554 * HandleVisibilityNotify - visibility notify event handler
556 * This routine keeps track of visibility events so that colormap
557 * installation can keep the maximum number of useful colormaps
558 * installed at one time.
560 ***********************************************************************
564 HandleVisibilityNotify()
566 XVisibilityEvent *vevent = (XVisibilityEvent *) &Event;
567 ColormapWindow *cwin;
570 if (XFindContext(dpy, vevent->window, ColormapContext, (caddr_t *)&cwin) == XCNOENT)
574 * when Saber complains about retreiving an <int> from an <unsigned int>
575 * just type "touch vevent->state" and "cont"
577 cmap = cwin->colormap;
578 if ((cmap->state & CM_INSTALLABLE) &&
579 vevent->state != cwin->visibility &&
580 (vevent->state == VisibilityFullyObscured ||
581 cwin->visibility == VisibilityFullyObscured) &&
582 cmap->w == cwin->w) {
583 cwin->visibility = vevent->state;
584 InstallWindowColormaps(VisibilityNotify, (TwmWindow *) NULL);
586 cwin->visibility = vevent->state;
591 /***********************************************************************
594 * HandleKeyPress - key press event handler
596 ***********************************************************************
599 int MovedFromKeyPress = False;
606 unsigned int modifier;
610 int have_ScrFocus = 0;
614 { XUnmapWindow(dpy, Scr->InfoWindow);
615 RFB july 28 1993 this code was wrong anyway because
616 InfoLines should have been set to 0.
620 Context = C_NO_CONTEXT;
622 if (Event.xany.window == Scr->Root)
624 if ((Event.xany.window == Scr->VirtualDesktopDisplay) ||
625 (Event.xany.window == Scr->VirtualDesktopDisplayOuter))
627 if (Event.xkey.subwindow &&
628 (XFindContext(dpy, Event.xkey.subwindow, VirtualContext, (caddr_t *) &tmp_win)
631 Context = C_VIRTUAL_WIN;
634 Tmp_win = Scr->VirtualDesktopDisplayTwin;
639 if (Event.xany.window == Tmp_win->title_w)
641 if (Event.xany.window == Tmp_win->w)
643 if (Event.xany.window == Tmp_win->icon_w)
645 if (Event.xany.window == Tmp_win->frame)
647 if (Tmp_win->list && Event.xany.window == Tmp_win->list->w)
649 if (Tmp_win->list && Event.xany.window == Tmp_win->list->icon)
654 * Now HERE'S a fine little kludge: Make an icon manager's frame or
655 * the virtual desktop's frame or a door and it's frame context-
656 * sensitive to key bindings, and make the frames of windows without
657 * titlebars forward key events.
659 * djhjr - 6/5/98 7/2/98 7/14/98
661 if (Scr->Focus && (Context == C_NO_CONTEXT || Context == C_ROOT))
663 /* ugly, but it works! see also iconmgr.c:RemoveIconManager() */
664 if (Scr->Focus->iconmgr)
666 #ifdef NEVER /* warps to icon managers uniquely handled in menus.c:WarpToWindow() */
667 if (!Scr->Focus->iconmgrp->active)
669 ActiveIconManager(Scr->Focus->iconmgrp->last);
670 Tmp_win = Scr->Focus;
673 Tmp_win = Scr->Focus->iconmgrp->active->twm;
678 else if (Scr->VirtualDesktopDisplayTwin == Scr->Focus)
680 Tmp_win = Scr->Focus;
683 /* XFindContext() doesn't seem to work here!?! */
688 for (door_win = Scr->Doors; door_win != NULL;
689 door_win = door_win->next)
690 if (door_win->twin == Scr->Focus)
692 Tmp_win = Scr->Focus;
698 else if (Scr->Focus->frame && !Scr->Focus->title_w)
700 Tmp_win = Scr->Focus;
701 Event.xany.window = Tmp_win->frame;
706 modifier = (Event.xkey.state & mods_used);
707 for (key = Scr->FuncKeyRoot.next; key != NULL; key = key->next)
709 if (key->keycode == Event.xkey.keycode &&
710 key->mods == modifier &&
711 (key->cont == Context || key->cont == C_NAME))
713 /* it doesn't make sense to resize from a key press? */
714 if (key->func == F_RESIZE)
718 * Exceptions for warps from icon managers (see the above kludge)
720 * djhjr - 6/5/98 7/2/98 7/14/98
725 if (have_ScrFocus && Context == C_ROOT)
729 case F_WARPCLASSNEXT:
730 case F_WARPCLASSPREV:
732 if (Context == C_ICONMGR)
733 Scr->Focus = Tmp_win = Tmp_win->list->iconmgr->twm_win;
737 Tmp_win = Scr->Focus;
743 /* case F_WARPTOICONMGR:*/
744 /* case F_WARPTONEWEST:*/
749 /* special case for moves */
750 if (key->func == F_MOVE || key->func == F_FORCEMOVE)
751 MovedFromKeyPress = True;
753 if (key->cont != C_NAME)
755 ExecuteFunction(key->func, key->action, Event.xany.window,
756 Tmp_win, &Event, Context, FALSE);
759 * Added this 'if ()' for deferred keyboard events (see also menus.c)
760 * Submitted by Michel Eyckmans
762 if (!(Context = C_ROOT && RootFunction != F_NOFUNCTION))
763 XUngrabPointer(dpy, CurrentTime);
770 len = strlen(key->win_name);
772 /* try and match the name first */
773 for (Tmp_win = Scr->TwmRoot.next; Tmp_win != NULL;
774 Tmp_win = Tmp_win->next)
776 if (!strncmp(key->win_name, Tmp_win->name, len))
779 ExecuteFunction(key->func, key->action, Tmp_win->frame,
780 Tmp_win, &Event, C_FRAME, FALSE);
781 XUngrabPointer(dpy, CurrentTime);
785 /* now try the res_name */
787 for (Tmp_win = Scr->TwmRoot.next; Tmp_win != NULL;
788 Tmp_win = Tmp_win->next)
790 if (!strncmp(key->win_name, Tmp_win->class.res_name, len))
793 ExecuteFunction(key->func, key->action, Tmp_win->frame,
794 Tmp_win, &Event, C_FRAME, FALSE);
795 XUngrabPointer(dpy, CurrentTime);
799 /* now try the res_class */
801 for (Tmp_win = Scr->TwmRoot.next; Tmp_win != NULL;
802 Tmp_win = Tmp_win->next)
804 if (!strncmp(key->win_name, Tmp_win->class.res_class, len))
807 ExecuteFunction(key->func, key->action, Tmp_win->frame,
808 Tmp_win, &Event, C_FRAME, FALSE);
809 XUngrabPointer(dpy, CurrentTime);
819 * If we get here, no function was bound to the key. Send it
820 * to the client if it was in a window we know about.
824 if (Event.xany.window == Tmp_win->icon_w ||
825 Event.xany.window == Tmp_win->frame ||
826 Event.xany.window == Tmp_win->title_w ||
827 (Tmp_win->list && (Event.xany.window == Tmp_win->list->w)))
829 Event.xkey.window = Tmp_win->w;
830 XSendEvent(dpy, Tmp_win->w, False, KeyPressMask, &Event);
838 static void free_window_names (tmp, nukefull, nukename, nukeicon)
840 Bool nukefull, nukename, nukeicon;
842 /* the other two "free()"s were "XFree()"s - djhjr - 9/14/03 */
845 * XXX - are we sure that nobody ever sets these to another constant (check
848 if (tmp->name == tmp->full_name) nukefull = False;
850 /* this test is never true anymore... - djhjr - 2/20/99
851 if (tmp->name == tmp->icon_name) nukename = False;
854 #define isokay(v) ((v) && (v) != NoName)
856 if (nukefull && isokay(tmp->full_name)) free (tmp->full_name);
857 if (nukename && isokay(tmp->name)) free (tmp->name);
859 /* ...because the icon name is now alloc()'d locally - djhjr - 2/20/99
860 if (nukeicon && isokay(tmp->icon_name)) XFree (tmp->icon_name);
862 if (nukeicon && tmp->icon_name) free(tmp->icon_name);
870 void free_cwins (tmp)
876 if (tmp->cmaps.number_cwins) {
877 for (i = 0; i < tmp->cmaps.number_cwins; i++) {
878 if (--tmp->cmaps.cwins[i]->refcnt == 0) {
879 cmap = tmp->cmaps.cwins[i]->colormap;
880 if (--cmap->refcnt == 0) {
881 XDeleteContext(dpy, cmap->c, ColormapContext);
884 XDeleteContext(dpy, tmp->cmaps.cwins[i]->w, ColormapContext);
885 free((char *) tmp->cmaps.cwins[i]);
888 free((char *) tmp->cmaps.cwins);
889 if (tmp->cmaps.number_cwins > 1) {
890 free(tmp->cmaps.scoreboard);
891 tmp->cmaps.scoreboard = NULL;
893 tmp->cmaps.number_cwins = 0;
899 /***********************************************************************
902 * HandlePropertyNotify - property notify event handler
904 ***********************************************************************
908 HandlePropertyNotify()
911 #ifdef NO_I18N_SUPPORT
914 unsigned long nitems, bytesafter;
916 unsigned long valuemask; /* mask for create windows */
917 XSetWindowAttributes attributes; /* attributes for create windows */
920 /* watch for standard colormap changes */
921 if (Event.xproperty.window == Scr->Root) {
922 XStandardColormap *maps = NULL;
925 switch (Event.xproperty.state) {
926 case PropertyNewValue:
927 if (XGetRGBColormaps (dpy, Scr->Root, &maps, &nmaps,
928 Event.xproperty.atom)) {
929 /* if got one, then replace any existing entry */
930 InsertRGBColormap (Event.xproperty.atom, maps, nmaps, True);
935 RemoveRGBColormap (Event.xproperty.atom);
940 if (!Tmp_win) return; /* unknown window */
942 #define MAX_NAME_LEN 200L /* truncate to this many */
943 #define MAX_ICON_NAME_LEN 200L /* ditto */
945 switch (Event.xproperty.atom) {
947 /* djhjr - 9/14/03 */
948 #ifndef NO_I18N_SUPPORT
949 if (!I18N_FetchName(dpy, Tmp_win->w, &prop))
951 if (XGetWindowProperty (dpy, Tmp_win->w, Event.xproperty.atom, 0L,
952 MAX_NAME_LEN, False, XA_STRING, &actual,
953 &actual_format, &nitems, &bytesafter,
954 (unsigned char **) &prop) != Success || actual == None)
958 free_window_names (Tmp_win, True, True, False);
959 Tmp_win->full_name = (prop) ? strdup(prop) : NoName;
960 Tmp_win->name = (prop) ? strdup(prop) : NoName;
961 /* djhjr - 9/14/03 */
962 #ifndef NO_I18N_SUPPORT
963 if (prop) free(prop);
965 if (prop) XFree(prop);
968 /* djhjr - 9/14/03 */
969 #ifndef NO_I18N_SUPPORT
970 Tmp_win->name_width = MyFont_TextWidth (&Scr->TitleBarFont,
972 Tmp_win->name_width = XTextWidth (Scr->TitleBarFont.font,
975 strlen (Tmp_win->name));
977 SetupWindow (Tmp_win, Tmp_win->frame_x, Tmp_win->frame_y,
978 Tmp_win->frame_width, Tmp_win->frame_height, -1);
980 if (Tmp_win->title_w) XClearArea(dpy, Tmp_win->title_w, 0,0,0,0, True);
983 * if the icon name is NoName, set the name of the icon to be
984 * the same as the window
986 /* see that the icon name is it's own memory - djhjr - 2/20/99
987 if (Tmp_win->icon_name == NoName) {
988 Tmp_win->icon_name = Tmp_win->name;
990 if (!strcmp(Tmp_win->icon_name, NoName)) {
991 free(Tmp_win->icon_name);
992 Tmp_win->icon_name = strdup(Tmp_win->name);
998 case XA_WM_ICON_NAME:
999 /* djhjr - 9/14/03 */
1000 #ifndef NO_I18N_SUPPORT
1001 if (!I18N_GetIconName(dpy, Tmp_win->w, &prop))
1003 if (XGetWindowProperty (dpy, Tmp_win->w, Event.xproperty.atom, 0,
1004 MAX_ICON_NAME_LEN, False, XA_STRING, &actual,
1005 &actual_format, &nitems, &bytesafter,
1006 (unsigned char **) &prop) != Success || actual == None)
1010 /* see that the icon name is it's own memory - djhjr - 2/20/99
1011 if (!prop) prop = NoName;
1012 free_window_names (Tmp_win, False, False, True);
1013 Tmp_win->icon_name = prop;
1015 free_window_names (Tmp_win, False, False, True);
1016 Tmp_win->icon_name = (prop) ? strdup(prop) : NoName;
1017 /* djhjr - 9/14/03 */
1018 #ifndef NO_I18N_SUPPORT
1019 if (prop) free(prop);
1021 if (prop) XFree(prop);
1029 if (Tmp_win->wmhints) XFree ((char *) Tmp_win->wmhints);
1030 Tmp_win->wmhints = XGetWMHints(dpy, Event.xany.window);
1032 if (Tmp_win->wmhints && (Tmp_win->wmhints->flags & WindowGroupHint))
1033 Tmp_win->group = Tmp_win->wmhints->window_group;
1035 if (!Tmp_win->forced && Tmp_win->wmhints &&
1036 Tmp_win->wmhints->flags & IconWindowHint) {
1037 if (Tmp_win->icon_w) {
1041 * There's already an icon window.
1042 * Try to find out where it is; if we succeed, move the new
1043 * window to where the old one is.
1045 if (XGetGeometry (dpy, Tmp_win->icon_w, &JunkRoot, &icon_x,
1046 &icon_y, &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth)) {
1048 * Move the new icon window to where the old one was.
1050 XMoveWindow(dpy, Tmp_win->wmhints->icon_window, icon_x,
1055 * If the window is iconic, map the new icon window.
1058 XMapWindow(dpy, Tmp_win->wmhints->icon_window);
1061 * Now, if the old window isn't ours, unmap it, otherwise
1062 * just get rid of it completely.
1064 if (Tmp_win->icon_not_ours) {
1065 if (Tmp_win->icon_w != Tmp_win->wmhints->icon_window)
1066 XUnmapWindow(dpy, Tmp_win->icon_w);
1068 XDestroyWindow(dpy, Tmp_win->icon_w);
1071 * The new icon window isn't our window, so note that fact
1072 * so that we don't treat it as ours.
1074 Tmp_win->icon_not_ours = TRUE;
1077 * Now make the new window the icon window for this window,
1078 * and set it up to work as such (select for key presses
1079 * and button presses/releases, set up the contexts for it,
1080 * and define the cursor for it).
1082 Tmp_win->icon_w = Tmp_win->wmhints->icon_window;
1083 XSelectInput (dpy, Tmp_win->icon_w,
1084 KeyPressMask | ButtonPressMask | ButtonReleaseMask);
1085 XSaveContext(dpy, Tmp_win->icon_w, TwmContext, (caddr_t)Tmp_win);
1086 XSaveContext(dpy, Tmp_win->icon_w, ScreenContext, (caddr_t)Scr);
1087 XDefineCursor(dpy, Tmp_win->icon_w, Scr->IconCursor);
1091 if (Tmp_win->icon_w && !Tmp_win->forced && Tmp_win->wmhints &&
1092 (Tmp_win->wmhints->flags & IconPixmapHint)) {
1093 if (!XGetGeometry (dpy, Tmp_win->wmhints->icon_pixmap, &JunkRoot,
1094 &JunkX, &JunkY, (unsigned int *)&Tmp_win->icon_width,
1095 (unsigned int *)&Tmp_win->icon_height, &JunkBW, &JunkDepth)) {
1099 pm = XCreatePixmap (dpy, Scr->Root, Tmp_win->icon_width,
1100 Tmp_win->icon_height, Scr->d_depth);
1103 FB(Tmp_win->iconc.fore, Tmp_win->iconc.back);
1106 * adapted from CTWM-3.5 - djhjr - 9/4/98
1108 #ifdef ORIGINAL_PIXMAPS
1109 XCopyPlane(dpy, Tmp_win->wmhints->icon_pixmap, pm,
1111 0,0, Tmp_win->icon_width, Tmp_win->icon_height, 0, 0, 1 );
1113 if (JunkDepth == Scr->d_depth)
1114 XCopyArea (dpy, Tmp_win->wmhints->icon_pixmap, pm, Scr->NormalGC,
1115 0,0, Tmp_win->icon_width, Tmp_win->icon_height, 0, 0);
1117 XCopyPlane(dpy, Tmp_win->wmhints->icon_pixmap, pm, Scr->NormalGC,
1118 0,0, Tmp_win->icon_width, Tmp_win->icon_height, 0, 0, 1 );
1121 valuemask = CWBackPixmap;
1122 attributes.background_pixmap = pm;
1124 if (Tmp_win->icon_bm_w)
1125 XDestroyWindow(dpy, Tmp_win->icon_bm_w);
1127 Tmp_win->icon_bm_w =
1128 XCreateWindow (dpy, Tmp_win->icon_w, 0, 0,
1129 (unsigned int) Tmp_win->icon_width,
1130 (unsigned int) Tmp_win->icon_height,
1131 (unsigned int) 0, Scr->d_depth,
1132 (unsigned int) CopyFromParent, Scr->d_visual,
1133 valuemask, &attributes);
1136 * adapted from CTWM-3.5 - djhjr - 9/4/98
1138 #ifndef ORIGINAL_PIXMAPS
1139 if (! (Tmp_win->wmhints->flags & IconMaskHint)) {
1142 rect.x = rect.y = 0;
1143 rect.width = Tmp_win->icon_width;
1144 rect.height = Tmp_win->icon_height;
1145 XShapeCombineRectangles (dpy, Tmp_win->icon_w, ShapeBounding,
1146 0, 0, &rect, 1, ShapeUnion, 0);
1150 XFreePixmap (dpy, pm);
1155 * adapted from CTWM-3.5 - djhjr - 9/4/98
1157 #ifndef ORIGINAL_PIXMAPS
1158 if (Tmp_win->icon_w && !Tmp_win->forced && Tmp_win->wmhints &&
1159 (Tmp_win->wmhints->flags & IconMaskHint)) {
1162 if (!XGetGeometry (dpy, Tmp_win->wmhints->icon_mask, &JunkRoot,
1163 &JunkX, &JunkY, &JunkWidth, &JunkHeight, &JunkBW,
1167 if (JunkDepth != 1) return;
1169 pm = XCreatePixmap (dpy, Scr->Root, JunkWidth, JunkHeight, 1);
1172 gc = XCreateGC (dpy, pm, 0, NULL);
1175 XCopyArea (dpy, Tmp_win->wmhints->icon_mask, pm, gc,
1176 0, 0, JunkWidth, JunkHeight, 0, 0);
1179 XFreePixmap (dpy, pm);
1186 case XA_WM_NORMAL_HINTS:
1187 GetWindowSizeHints (Tmp_win);
1191 if (Event.xproperty.atom == _XA_WM_COLORMAP_WINDOWS) {
1192 FetchWmColormapWindows (Tmp_win); /* frees old data */
1194 } else if (Event.xproperty.atom == _XA_WM_PROTOCOLS) {
1195 FetchWmProtocols (Tmp_win);
1204 /***********************************************************************
1207 * RedoIconName - procedure to re-position the icon window and name
1209 ***********************************************************************
1218 /* let the expose event cause the repaint */
1219 XClearArea(dpy, Tmp_win->list->w, 0,0,0,0, True);
1221 if (Scr->SortIconMgr)
1222 SortIconManager(Tmp_win->list->iconmgr);
1226 Scr->NamesInVirtualDesktop &&
1227 Tmp_win->VirtualDesktopDisplayWindow)
1228 XClearArea(dpy, Tmp_win->VirtualDesktopDisplayWindow,
1231 if ( ! Tmp_win->icon_w ) return;
1233 if (Tmp_win->icon_not_ours)
1236 /* djhjr - 9/14/03 */
1237 #ifndef NO_I18N_SUPPORT
1238 Tmp_win->icon_w_width = MyFont_TextWidth(&Scr->IconFont,
1240 Tmp_win->icon_w_width = XTextWidth(Scr->IconFont.font,
1242 Tmp_win->icon_name, strlen(Tmp_win->icon_name));
1245 Tmp_win->icon_w_width += 6;
1246 if (Tmp_win->icon_w_width < Tmp_win->icon_width)
1248 Tmp_win->icon_x = (Tmp_win->icon_width - Tmp_win->icon_w_width)/2;
1249 Tmp_win->icon_x += 3;
1250 Tmp_win->icon_w_width = Tmp_win->icon_width;
1254 Tmp_win->icon_x = 3;
1257 Tmp_win->icon_w_width += 8;
1258 if (Tmp_win->icon_w_width < Tmp_win->icon_width + 8)
1260 Tmp_win->icon_x = (((Tmp_win->icon_width + 8) - Tmp_win->icon_w_width)/2) + 4;
1261 Tmp_win->icon_w_width = Tmp_win->icon_width + 8;
1264 Tmp_win->icon_x = 4;
1266 if (Tmp_win->icon_w_width == Tmp_win->icon_width)
1269 x = (Tmp_win->icon_w_width - Tmp_win->icon_width)/2;
1277 Tmp_win->icon_w_height = Tmp_win->icon_height + Scr->IconFont.height + 4;
1278 Tmp_win->icon_y = Tmp_win->icon_height + Scr->IconFont.height;
1280 Tmp_win->icon_w_height = Tmp_win->icon_height + Scr->IconFont.height + 8;
1281 Tmp_win->icon_y = Tmp_win->icon_height + Scr->IconFont.height + 2;
1283 XResizeWindow(dpy, Tmp_win->icon_w, Tmp_win->icon_w_width,
1284 Tmp_win->icon_w_height);
1285 if (Tmp_win->icon_bm_w)
1287 XMoveWindow(dpy, Tmp_win->icon_bm_w, x, y);
1288 XMapWindow(dpy, Tmp_win->icon_bm_w);
1292 XClearArea(dpy, Tmp_win->icon_w, 0, 0, 0, 0, True);
1297 * RedoDoorName - Redraw the contents of a door's window
1299 * djhjr - 2/10/99 2/28/99
1302 RedoDoorName(twin, door)
1308 /* font was font.font->fid - djhjr - 9/14/03 */
1309 FBF(door->colors.fore, door->colors.back, Scr->DoorFont);
1311 /* find it's twm window to get the current width, etc. */
1313 * The TWM window is passed from Do*Resize(),
1314 * as it may be undeterminable in HandleExpose()!?
1318 if (XFindContext(dpy, Event.xany.window, TwmContext,
1319 (caddr_t *)&tmp_win) != XCNOENT)
1324 XFindContext(dpy, Event.xany.window, TwmContext, (caddr_t *)&tmp_win);
1330 /* djhjr - 9/14/03 */
1331 #ifndef NO_I18N_SUPPORT
1332 tw = MyFont_TextWidth(&Scr->DoorFont,
1334 tw = XTextWidth(Scr->DoorFont.font,
1336 door->name, strlen(door->name));
1338 /* djhjr - 4/26/96 */
1340 * was 'Scr->use3Dborders' - djhjr - 8/11/98 *
1341 bw = (Scr->BorderBevelWidth > 0) ? Scr->ThreeDBorderWidth : 0;
1343 bw = (Scr->BorderBevelWidth > 0) ? Scr->BorderWidth : 0;
1345 /* change the little internal one to fit the external */
1346 XResizeWindow(dpy, door->w,
1347 tmp_win->frame_width,
1348 tmp_win->frame_height);
1350 /* draw the text in the right place */
1351 /* And it IS the right place.
1352 ** If your font has its characters starting 20 pixels
1353 ** over to the right, it just looks wrong!
1354 ** For example grog-9 from ISC's X11R3 distribution.
1356 /* djhjr - 9/14/03 */
1357 #ifndef NO_I18N_SUPPORT
1358 MyFont_DrawString(dpy, door->w, &Scr->DoorFont,
1360 XDrawString(dpy, door->w,
1363 /* gets 'SIZE_VINDENT' out of here... djhjr - 5/14/96
1364 (tmp_win->frame_width - tw)/2,
1365 tmp_win->frame_height - SIZE_VINDENT -
1366 (tmp_win->frame_height - Scr->DoorFont.height)/2,
1367 ** ...and NOW it's in the right place! */
1368 (tmp_win->frame_width - tw - 2 * bw) / 2,
1369 (tmp_win->frame_height - tmp_win->title_height -
1370 Scr->DoorFont.height - 2 * bw) / 2 +
1372 Scr->DoorFont.font->ascent,
1374 Scr->DoorFont.ascent,
1375 door->name, strlen(door->name));
1377 /* djhjr - 2/7/99 */
1378 if (Scr->DoorBevelWidth > 0)
1379 Draw3DBorder(door->w, 0, 0, tmp_win->frame_width - (bw * 2),
1380 tmp_win->frame_height - (bw * 2),
1381 Scr->DoorBevelWidth, Scr->DoorC, off, False, False);
1383 /* djhjr - 9/14/03 */
1384 #ifndef NO_I18N_SUPPORT
1385 MyFont_DrawString(dpy, door->w, &Scr->DoorFont,
1387 XDrawString(dpy, door->w,
1390 SIZE_HINDENT/2, 0/*Scr->DoorFont.height*/,
1391 door->name, strlen(door->name));
1396 * RedoListWindow - Redraw the contents of an icon manager's entry
1401 RedoListWindow(twin)
1405 * font was font.font->fid - djhjr - 9/14/03 *
1406 FBF(twin->list->fore, twin->list->back, Scr->IconManagerFont);
1408 #ifndef NO_I18N_SUPPORT
1409 MyFont_DrawString (dpy, Event.xany.window, &Scr->IconManagerFont,
1411 XDrawString (dpy, Event.xany.window,
1414 iconmgr_textx, Scr->IconManagerFont.y+4,
1415 twin->icon_name, strlen(twin->icon_name));
1416 DrawIconManagerBorder(twin->list);
1418 /* made static - djhjr - 6/18/99 */
1419 static int en = 0, dots = 0;
1421 /* djhjr - 3/29/98 */
1422 int i, j, slen = strlen(twin->icon_name);
1425 /* djhjr - 10/2/01 */
1426 if (!twin->list) return;
1429 * clip the title a couple of characters less than the width of the
1430 * icon window plus padding, and tack on ellipses - this is a little
1431 * different than the titlebar's...
1435 if (Scr->NoPrettyTitles == FALSE) /* for rader - djhjr - 2/9/99 */
1437 /* djhjr - 9/14/03 */
1438 #ifndef NO_I18N_SUPPORT
1439 i = MyFont_TextWidth(&Scr->IconManagerFont,
1441 i = XTextWidth(Scr->IconManagerFont.font,
1443 twin->icon_name, slen);
1445 /* DUH! - djhjr - 6/18/99
1446 j = twin->list->width - iconmgr_textx - en;
1448 /* djhjr - 9/14/03 */
1449 #ifndef NO_I18N_SUPPORT
1450 if (!en) en = MyFont_TextWidth(&Scr->IconManagerFont, "n", 1);
1451 if (!dots) dots = MyFont_TextWidth(&Scr->IconManagerFont, "...", 3);
1453 if (!en) en = XTextWidth(Scr->IconManagerFont.font, "n", 1);
1454 if (!dots) dots = XTextWidth(Scr->IconManagerFont.font, "...", 3);
1456 j = twin->list->width - iconmgr_textx - dots;
1458 /* djhjr - 5/5/98 */
1459 /* was 'Scr->use3Diconmanagers' - djhjr - 8/11/98 */
1460 if (Scr->IconMgrBevelWidth > 0)
1461 j -= Scr->IconMgrBevelWidth;
1463 j -= Scr->BorderWidth;
1472 for (i = slen; i >= 0; i--)
1475 if (XTextWidth(Scr->IconManagerFont.font, twin->icon_name, i) + 2 * en < j)
1477 /* djhjr - 9/14/03 */
1478 #ifndef NO_I18N_SUPPORT
1479 if (MyFont_TextWidth(&Scr->IconManagerFont,
1481 if (XTextWidth(Scr->IconManagerFont.font,
1483 twin->icon_name, i) + en < j)
1489 a = (char *)malloc(slen + 4);
1490 memcpy(a, twin->icon_name, slen);
1491 strcpy(a + slen, "...");
1496 /* font was font.font->fid - djhjr - 9/14/03 */
1497 FBF(twin->list->cp.fore, twin->list->cp.back, Scr->IconManagerFont);
1499 /* what's the point of this? - djhjr - 5/2/98
1500 if (Scr->use3Diconmanagers && (Scr->Monochrome != COLOR))
1502 #ifndef NO_I18N_SUPPORT
1503 MyFont_DrawImageString (dpy, twin->list->w,
1504 &Scr->IconManagerFont,
1506 XDrawImageString (dpy, twin->list->w,
1508 Scr->NormalGC, iconmgr_textx,
1511 Scr->IconManagerFont.y+4,
1513 (twin->list->height - Scr->IconManagerFont.height) / 2 +
1514 Scr->IconManagerFont.y,
1516 (a) ? a : twin->icon_name, slen);
1519 /* djhjr - 9/14/03 */
1520 #ifndef NO_I18N_SUPPORT
1521 MyFont_DrawString (dpy, twin->list->w,
1522 &Scr->IconManagerFont,
1524 XDrawString (dpy, twin->list->w,
1526 Scr->NormalGC, iconmgr_textx,
1529 Scr->IconManagerFont.y+4,
1531 (twin->list->height - Scr->IconManagerFont.height) / 2 +
1532 Scr->IconManagerFont.y,
1534 (a) ? a : twin->icon_name, slen);
1536 /* free the clipped title - djhjr - 3/29/98 */
1539 DrawIconManagerBorder(twin->list, False);
1543 /***********************************************************************
1546 * HandleClientMessage - client message event handler
1548 ***********************************************************************
1552 HandleClientMessage()
1554 extern void RestartVtwm();
1556 if (Event.xclient.message_type == _XA_WM_CHANGE_STATE)
1558 if (Tmp_win != NULL)
1560 if (Event.xclient.data.l[0] == IconicState && !Tmp_win->icon)
1564 XQueryPointer( dpy, Scr->Root, &JunkRoot, &JunkChild,
1565 &(button.xmotion.x_root),
1566 &(button.xmotion.y_root),
1567 &JunkX, &JunkY, &JunkMask);
1569 ExecuteFunction(F_ICONIFY, NULLSTR, Event.xany.window,
1570 Tmp_win, &button, FRAME, FALSE);
1571 XUngrabPointer(dpy, CurrentTime);
1575 /* djhjr - 7/31/98 */
1576 else if (Event.xclient.message_type == _XA_TWM_RESTART)
1577 RestartVtwm(CurrentTime);
1582 /***********************************************************************
1585 * HandleExpose - expose event handler
1587 ***********************************************************************
1590 static void flush_expose();
1596 TwmDoor *door = NULL;
1599 if (XFindContext(dpy, Event.xany.window, MenuContext, (caddr_t *)&tmp) == 0)
1601 PaintMenu(tmp, &Event);
1605 if (XFindContext(dpy, Event.xany.window, DoorContext, (caddr_t *)&door) != XCNOENT)
1607 /* see also resize.c - djhjr - 2/28/99 */
1608 RedoDoorName(NULL, door);
1609 flush_expose(Event.xany.window);
1613 if (Event.xexpose.count != 0)
1616 if (Event.xany.window == Scr->InfoWindow && InfoLines)
1621 /* font was font.font->fid - djhjr - 9/14/03 */
1622 FBF(Scr->DefaultC.fore, Scr->DefaultC.back, Scr->InfoFont);
1624 /* djhjr - 5/10/96 */
1625 XGetGeometry (dpy, Scr->InfoWindow, &JunkRoot, &JunkX, &JunkY,
1626 &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth);
1628 height = Scr->InfoFont.height+2;
1629 for (i = 0; i < InfoLines; i++)
1631 /* djhjr - 5/10/96 */
1632 j = strlen(Info[i]);
1634 /* djhjr - 4/29/98 */
1636 /* was 'Scr->use3Dborders' - djhjr - 8/11/98 */
1637 if (!i && Scr->BorderBevelWidth > 0) k += Scr->InfoBevelWidth;
1639 /* djhjr - 9/14/03 */
1640 #ifndef NO_I18N_SUPPORT
1641 MyFont_DrawString(dpy, Scr->InfoWindow, &Scr->InfoFont,
1643 XDrawString(dpy, Scr->InfoWindow,
1646 /* centers the lines... djhjr - 5/10/96
1649 /* djhjr - 9/14/03 */
1650 #ifndef NO_I18N_SUPPORT
1651 (JunkWidth - MyFont_TextWidth(&Scr->InfoFont, Info[i], j)) / 2,
1653 (JunkWidth - XTextWidth(Scr->InfoFont.font, Info[i], j)) / 2,
1656 /* 'k' was a hard-coded '5' - djhjr - 4/29/98 */
1657 (i*height) + Scr->InfoFont.y + k, Info[i], j);
1660 /* djhjr - 5/9/96 */
1661 /* was 'Scr->use3Dborders' - djhjr - 8/11/98 */
1662 if (Scr->InfoBevelWidth > 0)
1663 Draw3DBorder(Scr->InfoWindow, 0, 0, JunkWidth, JunkHeight,
1665 BW, Scr->DefaultC, off, False, False);
1667 Scr->InfoBevelWidth, Scr->DefaultC, off, False, False);
1669 flush_expose (Event.xany.window);
1672 /* see that the desktop's bevel gets redrawn - djhjr - 2/10/99 */
1673 else if (Event.xany.window == Scr->VirtualDesktopDisplay)
1675 Draw3DBorder(Scr->VirtualDesktopDisplayOuter, 0, 0,
1676 Scr->VirtualDesktopMaxWidth + (Scr->VirtualDesktopBevelWidth * 2),
1677 Scr->VirtualDesktopMaxHeight + (Scr->VirtualDesktopBevelWidth * 2),
1678 Scr->VirtualDesktopBevelWidth, Scr->VirtualC, off, False, False);
1679 flush_expose (Event.xany.window);
1683 else if (Tmp_win != NULL)
1685 /* djhjr - 4/20/96 */
1686 /* was 'Scr->use3Dborders' - djhjr - 8/11/98 */
1687 if (Scr->BorderBevelWidth > 0 && (Event.xany.window == Tmp_win->frame)) {
1688 PaintBorders (Tmp_win, ((Tmp_win == Scr->Focus) ? True : False));
1689 flush_expose (Event.xany.window);
1694 if (Event.xany.window == Tmp_win->title_w)
1697 * font was font.font->fid - djhjr - 9/14/03 *
1698 FBF(Tmp_win->title.fore, Tmp_win->title.back, Scr->TitleBarFont);
1701 #ifndef NO_I18N_SUPPORT
1702 MyFont_DrawString (dpy, Tmp_win->title_w, &Scr->TitleBarFont,
1704 XDrawString (dpy, Tmp_win->title_w,
1707 Scr->TBInfo.titlex, Scr->TitleBarFont.y,
1708 Tmp_win->name, strlen(Tmp_win->name));
1710 PaintTitle (Tmp_win);
1712 /* djhjr - 10/25/02 */
1713 PaintTitleHighlight(Tmp_win, (Tmp_win == Scr->Focus) ? on : off);
1715 flush_expose (Event.xany.window);
1718 else if (Event.xany.window == Tmp_win->icon_w)
1722 * font was font.font->fid - djhjr - 9/14/03 *
1723 FBF(Tmp_win->iconc.fore, Tmp_win->iconc.back, Scr->IconFont);
1726 #ifndef NO_I18N_SUPPORT
1727 MyFont_DrawString (dpy, Tmp_win->icon_w, &Scr->IconManagerFont,
1729 XDrawString (dpy, Tmp_win->icon_w,
1732 Tmp_win->icon_x, Tmp_win->icon_y,
1733 Tmp_win->icon_name, strlen(Tmp_win->icon_name));
1737 flush_expose (Event.xany.window);
1739 } else if (Tmp_win->titlebuttons) {
1741 Window w = Event.xany.window;
1743 int nb = Scr->TBInfo.nleft + Scr->TBInfo.nright;
1745 for (i = 0, tbw = Tmp_win->titlebuttons; i < nb; i++, tbw++) {
1746 if (w == tbw->window) {
1748 register TitleButton *tb = tbw->info;
1750 FB(Tmp_win->title.fore, Tmp_win->title.back);
1751 XCopyPlane (dpy, tb->bitmap, w, Scr->NormalGC,
1752 tb->srcx, tb->srcy, tb->width, tb->height,
1753 tb->dstx, tb->dsty, 1);
1755 /* djhjr - 11/17/97 8/10/98 */
1756 /* added the test for window highlighting - djhjr - 3/14/98 */
1757 /* collapsed two functions - djhjr - 8/10/98 */
1758 if (Scr->ButtonColorIsFrame && Tmp_win->highlight)
1759 PaintTitleButton(Tmp_win, tbw, (Scr->Focus == Tmp_win) ? 2 : 1);
1761 PaintTitleButton(Tmp_win, tbw, 0);
1768 if (Tmp_win->list) {
1769 if (Event.xany.window == Tmp_win->list->w)
1771 /* see also resize.c - djhjr - 3/1/99 */
1772 RedoListWindow(Tmp_win);
1773 flush_expose (Event.xany.window);
1776 if (Event.xany.window == Tmp_win->list->icon)
1779 FB(Tmp_win->list->fore, Tmp_win->list->back);
1780 XCopyPlane(dpy, Scr->siconifyPm, Tmp_win->list->icon,
1782 0,0, iconifybox_width, iconifybox_height, 0, 0, 1);
1785 * was 'Scr->use3Diconmanagers' - djhjr - 8/11/98 *
1786 if (Scr->IconMgrBevelWidth > 0 && Tmp_win->list->iconifypm)
1787 XCopyArea (dpy, Tmp_win->list->iconifypm, Tmp_win->list->icon,
1788 Scr->NormalGC, 0, 0,
1789 iconifybox_width, iconifybox_height, 0, 0);
1791 FB(Tmp_win->list->cp.fore, Tmp_win->list->cp.back);
1792 XCopyPlane(dpy, Scr->siconifyPm->pixmap, Tmp_win->list->icon, Scr->NormalGC,
1793 0,0, iconifybox_width, iconifybox_height, 0, 0, 1);
1796 XCopyArea(dpy, Tmp_win->list->iconifypm->pixmap,
1797 Tmp_win->list->icon, Scr->NormalGC, 0, 0,
1798 iconifybox_width, iconifybox_height, 0, 0);
1800 flush_expose (Event.xany.window);
1806 /* update the virtual desktop display names */
1807 if (Scr->Virtual && Scr->NamesInVirtualDesktop) {
1811 if (XFindContext(dpy, Event.xany.window, VirtualContext,
1812 (caddr_t *)&tmp_win) != XCNOENT) {
1813 /* font was font.font->fid - djhjr - 9/14/03 */
1814 FBF(tmp_win->virtual.fore, tmp_win->virtual.back,
1816 if (tmp_win->icon_name)
1817 name = tmp_win->icon_name;
1818 else if (tmp_win->name)
1819 name = tmp_win->name;
1821 /* djhjr - 9/14/03 */
1822 #ifndef NO_I18N_SUPPORT
1823 MyFont_DrawImageString(dpy, Event.xany.window,
1826 XDrawImageString(dpy, Event.xany.window,
1829 0, Scr->VirtualFont.height,
1830 name, strlen(name));
1837 /***********************************************************************
1840 * HandleDestroyNotify - DestroyNotify event handler
1842 ***********************************************************************
1846 HandleDestroyNotify()
1851 * Warning, this is also called by HandleUnmapNotify; if it ever needs to
1852 * look at the event, HandleUnmapNotify will have to mash the UnmapNotify
1853 * into a DestroyNotify.
1856 if (Tmp_win == NULL)
1859 /* djhjr - 6/22/01 */
1860 #ifndef NO_SOUND_SUPPORT
1861 if (destroySoundFromFunction == FALSE)
1862 PlaySound(S_CUNMAP);
1864 destroySoundFromFunction = FALSE;
1867 if (Tmp_win == Scr->Focus)
1872 if (Tmp_win == Scr->Newest) /* PF */
1873 Scr->Newest = NULL; /* PF */
1875 /* djhjr - 5/16/98 */
1876 if (Tmp_win == UnHighLight_win) UnHighLight_win = NULL;
1878 XDeleteContext(dpy, Tmp_win->w, TwmContext);
1879 XDeleteContext(dpy, Tmp_win->w, ScreenContext);
1880 XDeleteContext(dpy, Tmp_win->frame, TwmContext);
1881 XDeleteContext(dpy, Tmp_win->frame, ScreenContext);
1882 XDeleteContext(dpy, Tmp_win->VirtualDesktopDisplayWindow, VirtualContext);
1883 if (Tmp_win->icon_w)
1885 XDeleteContext(dpy, Tmp_win->icon_w, TwmContext);
1886 XDeleteContext(dpy, Tmp_win->icon_w, ScreenContext);
1888 if (Tmp_win->title_height)
1890 int nb = Scr->TBInfo.nleft + Scr->TBInfo.nright;
1891 XDeleteContext(dpy, Tmp_win->title_w, TwmContext);
1892 XDeleteContext(dpy, Tmp_win->title_w, ScreenContext);
1893 if (Tmp_win->hilite_w)
1895 XDeleteContext(dpy, Tmp_win->hilite_w, TwmContext);
1896 XDeleteContext(dpy, Tmp_win->hilite_w, ScreenContext);
1898 if (Tmp_win->titlebuttons) {
1899 for (i = 0; i < nb; i++) {
1900 XDeleteContext (dpy, Tmp_win->titlebuttons[i].window,
1902 XDeleteContext (dpy, Tmp_win->titlebuttons[i].window,
1908 if (Scr->cmapInfo.cmaps == &Tmp_win->cmaps)
1909 InstallWindowColormaps(DestroyNotify, &Scr->TwmRoot);
1912 * TwmWindows contain the following pointers
1919 * 6. class.res_class
1925 * 12. virtual desktop display window
1927 if (Tmp_win->gray) XFreePixmap (dpy, Tmp_win->gray);
1929 /* djhjr - 4/26/99 */
1930 AppletDown(Tmp_win);
1932 XDestroyWindow(dpy, Tmp_win->frame);
1933 if (Tmp_win->icon_w && !Tmp_win->icon_not_ours) {
1934 XDestroyWindow(dpy, Tmp_win->icon_w);
1937 XDestroyWindow(dpy, Tmp_win->VirtualDesktopDisplayWindow); /* 12 */
1938 RemoveIconManager(Tmp_win); /* 7 */
1939 Tmp_win->prev->next = Tmp_win->next;
1940 if (Tmp_win->next != NULL)
1941 Tmp_win->next->prev = Tmp_win->prev;
1942 if (Tmp_win->auto_raise) Scr->NumAutoRaises--;
1944 free_window_names (Tmp_win, True, True, True); /* 1, 2, 3 */
1945 if (Tmp_win->wmhints) /* 4 */
1946 XFree ((char *)Tmp_win->wmhints);
1947 if (Tmp_win->class.res_name && Tmp_win->class.res_name != NoName) /* 5 */
1948 XFree ((char *)Tmp_win->class.res_name);
1949 if (Tmp_win->class.res_class && Tmp_win->class.res_class != NoName) /* 6 */
1950 XFree ((char *)Tmp_win->class.res_class);
1951 free_cwins (Tmp_win); /* 9 */
1952 if (Tmp_win->titlebuttons) /* 10 */
1953 free ((char *) Tmp_win->titlebuttons);
1955 * 11a through 11c was handled in a local function, but
1956 * is now broken out (11a & 11b), and uses a public function
1957 * in menus.c (11c) - djhjr - 10/27/02
1959 if (enter_win == Tmp_win) { /* 11a */
1963 if (raise_win == Tmp_win) raise_win = NULL; /* 11b */
1964 RemoveWindowFromRing(Tmp_win); /* 11c */
1966 free((char *)Tmp_win);
1972 HandleCreateNotify()
1975 fprintf(stderr, "CreateNotify w = 0x%x\n", Event.xcreatewindow.window);
1984 /***********************************************************************
1987 * HandleMapRequest - MapRequest event handler
1989 ***********************************************************************
1999 Event.xany.window = Event.xmaprequest.window;
2000 stat = XFindContext(dpy, Event.xany.window, TwmContext, (caddr_t *)&Tmp_win);
2001 if (stat == XCNOENT)
2004 /* If the window has never been mapped before ... */
2005 if (Tmp_win == NULL)
2007 /* Add decorations. */
2008 Tmp_win = AddWindow(Event.xany.window, FALSE, (IconMgr *) NULL);
2009 if (Tmp_win == NULL)
2012 /* djhjr - 6/22/01 */
2013 #ifndef NO_SOUND_SUPPORT
2014 if (createSoundFromFunction == FALSE)
2017 createSoundFromFunction = FALSE;
2024 * If the window has been unmapped by the client, it won't be listed
2025 * in the icon manager. Add it again, if requested.
2027 if (Tmp_win->list == NULL)
2028 (void) AddIconManager (Tmp_win);
2031 /* If it's not merely iconified, and we have hints, use them. */
2032 if ((! Tmp_win->icon) &&
2033 Tmp_win->wmhints && (Tmp_win->wmhints->flags & StateHint))
2038 /* use WM_STATE if enabled */
2039 if (!(RestartPreviousState && GetWMState(Tmp_win->w, &state, &icon) &&
2040 (state == NormalState || state == IconicState)))
2041 state = Tmp_win->wmhints->initial_state;
2049 XMapWindow(dpy, Tmp_win->w);
2050 XMapWindow(dpy, Tmp_win->frame);
2051 SetMapStateProp(Tmp_win, NormalState);
2052 SetRaiseWindow (Tmp_win);
2054 /* djhjr - 10/2/01 */
2055 if (Scr->StrictIconManager)
2057 RemoveIconManager(Tmp_win);
2062 zoom_save = Scr->DoZoom;
2063 Scr->DoZoom = FALSE;
2064 Iconify(Tmp_win, 0, 0);
2065 Scr->DoZoom = zoom_save;
2069 /* If no hints, or currently an icon, just "deiconify" */
2073 SetRaiseWindow (Tmp_win);
2076 RaiseStickyAbove(); /* DSE */
2077 RaiseAutoPan(); /* DSE */
2083 void SimulateMapRequest (w)
2086 Event.xmaprequest.window = w;
2087 HandleMapRequest ();
2092 /***********************************************************************
2095 * HandleMapNotify - MapNotify event handler
2097 ***********************************************************************
2103 if (Tmp_win == NULL)
2107 * Need to do the grab to avoid race condition of having server send
2108 * MapNotify to client before the frame gets mapped; this is bad because
2109 * the client would think that the window has a chance of being viewable
2110 * when it really isn't.
2113 if (Tmp_win->icon_w)
2114 XUnmapWindow(dpy, Tmp_win->icon_w);
2115 if (Tmp_win->title_w)
2116 XMapSubwindows(dpy, Tmp_win->title_w);
2117 XMapSubwindows(dpy, Tmp_win->frame);
2120 if (Scr->Focus != Tmp_win && Tmp_win->hilite_w)
2121 XUnmapWindow(dpy, Tmp_win->hilite_w);
2123 if (Scr->Focus != Tmp_win)
2124 PaintTitleHighlight(Tmp_win, off);
2126 XMapWindow(dpy, Tmp_win->frame);
2127 XUngrabServer (dpy);
2129 Tmp_win->mapped = TRUE;
2130 Tmp_win->icon = FALSE;
2131 Tmp_win->icon_on = FALSE;
2133 /* Race condition if in menus.c:DeIconify() - djhjr - 10/2/01 */
2134 if (Scr->StrictIconManager)
2136 RemoveIconManager(Tmp_win);
2141 /***********************************************************************
2144 * HandleUnmapNotify - UnmapNotify event handler
2146 ***********************************************************************
2156 * The July 27, 1988 ICCCM spec states that a client wishing to switch
2157 * to WithdrawnState should send a synthetic UnmapNotify with the
2158 * event field set to (pseudo-)root, in case the window is already
2159 * unmapped (which is the case for twm for IconicState). Unfortunately,
2160 * we looked for the TwmContext using that field, so try the window
2163 if (Tmp_win == NULL)
2165 Event.xany.window = Event.xunmap.window;
2166 if (XFindContext(dpy, Event.xany.window,
2167 TwmContext, (caddr_t *)&Tmp_win) == XCNOENT)
2171 if (Tmp_win == NULL || (!Tmp_win->mapped && !Tmp_win->icon))
2175 * The program may have unmapped the client window, from either
2176 * NormalState or IconicState. Handle the transition to WithdrawnState.
2178 * We need to reparent the window back to the root (so that twm exiting
2179 * won't cause it to get mapped) and then throw away all state (pretend
2180 * that we've received a DestroyNotify).
2184 if (XTranslateCoordinates (dpy, Event.xunmap.window, Tmp_win->attr.root,
2185 0, 0, &dstx, &dsty, &dumwin)) {
2187 Bool reparented = XCheckTypedWindowEvent (dpy, Event.xunmap.window,
2188 ReparentNotify, &ev);
2189 SetMapStateProp (Tmp_win, WithdrawnState);
2191 if (Tmp_win->old_bw) XSetWindowBorderWidth (dpy,
2192 Event.xunmap.window,
2194 if (Tmp_win->wmhints && (Tmp_win->wmhints->flags & IconWindowHint))
2195 XUnmapWindow (dpy, Tmp_win->wmhints->icon_window);
2197 XReparentWindow (dpy, Event.xunmap.window, Tmp_win->attr.root,
2199 RestoreWithdrawnLocation (Tmp_win);
2201 XRemoveFromSaveSet (dpy, Event.xunmap.window);
2202 XSelectInput (dpy, Event.xunmap.window, NoEventMask);
2203 HandleDestroyNotify (); /* do not need to mash event before */
2204 } /* else window no longer exists and we'll get a destroy notify */
2205 XUngrabServer (dpy);
2211 /***********************************************************************
2214 * HandleMotionNotify - MotionNotify event handler
2216 ***********************************************************************
2219 #if 0 /* functionality moved to menus.c:ExecuteFunction() - djhjr - 11/7/03 */
2221 HandleMotionNotify()
2223 #if 0 /* done in menus.c:ExecuteFunction() now - djhjr - 11/4/03 */
2224 if (moving_window) {
2225 DoMoveWindowOnDesktop(Event.xmotion.x, Event.xmotion.y);
2229 #if 0 /* done in menus.c:ExecuteFunction() now - djhjr - 5/27/03 */
2232 XQueryPointer( dpy, Event.xany.window,
2233 &(Event.xmotion.root), &JunkChild,
2234 &(Event.xmotion.x_root), &(Event.xmotion.y_root),
2235 &(Event.xmotion.x), &(Event.xmotion.y),
2238 /* Set WindowMoved appropriately so that f.deltastop will
2239 work with resize as well as move. */
2240 if (abs (Event.xmotion.x - ResizeOrigX) >= Scr->MoveDelta
2241 || abs (Event.xmotion.y - ResizeOrigY) >= Scr->MoveDelta)
2243 /* djhjr - 9/5/98 */
2244 resizing_window = 1;
2249 /* added this 'if ()' for applying MoveDelta - djhjr - 9/5/98 */
2250 if (resizing_window)
2252 XFindContext(dpy, ResizeWindow, TwmContext, (caddr_t *)&Tmp_win);
2253 DoResize(Event.xmotion.x_root, Event.xmotion.y_root, Tmp_win);
2262 /***********************************************************************
2265 * HandleButtonRelease - ButtonRelease event handler
2267 ***********************************************************************
2270 HandleButtonRelease()
2273 int xl, xr, yt, yb, w, h;
2277 if (Scr->StayUpMenus)
2279 if (GlobalFirstTime == True && GlobalMenuButton == True )
2282 GlobalFirstTime = False;
2286 GlobalFirstTime = True;
2290 0 For StayUpMenus, delete infobox after buttonpress!
2291 0 if (InfoLines) /* delete info box on 2nd button release */
2292 0 /* if (Context == C_IDENTIFY) */
2293 0 /* This would force you to click on the box itself */
2295 0fprintf( stderr, "Kill info B\n" );
2296 0 XUnmapWindow(dpy, Scr->InfoWindow);
2298 0 Context = C_NO_CONTEXT;
2302 #if 0 /* done in menus.c:ExecuteFunction() now - djhjr - 11/4/03 */
2304 { EndMoveWindowOnDesktop();
2308 if (DragWindow != None)
2311 * Most all of this is redundant (see menus.c:ExecuteFunction()),
2312 * and I don't see why. Everything except local functionality is
2313 * '#if 0'd out, with just a few lines moved (copied) to menus.c.
2317 MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0);
2319 XFindContext(dpy, DragWindow, TwmContext, (caddr_t *)&Tmp_win);
2320 if (DragWindow == Tmp_win->frame)
2322 xl = Event.xbutton.x_root - DragX - Tmp_win->frame_bw;
2323 yt = Event.xbutton.y_root - DragY - Tmp_win->frame_bw;
2324 w = DragWidth + 2 * Tmp_win->frame_bw;
2325 h = DragHeight + 2 * Tmp_win->frame_bw;
2330 * Deskset/Openwin apps change the icon's border width attribute.
2331 * Submitted by Caveh Frank Jalali
2333 xl = Event.xbutton.x_root - DragX - Scr->IconBorderWidth;
2334 yt = Event.xbutton.y_root - DragY - Scr->IconBorderWidth;
2335 w = DragWidth + 2 * Scr->IconBorderWidth;
2336 h = DragHeight + 2 * Scr->IconBorderWidth;
2338 XWindowAttributes wat;
2340 XGetWindowAttributes(dpy, DragWindow, &wat);
2341 xl = Event.xbutton.x_root - DragX - wat.border_width;
2342 yt = Event.xbutton.y_root - DragY - wat.border_width;
2343 w = DragWidth + 2 * wat.border_width;
2344 h = DragHeight + 2 * wat.border_width;
2349 if (ConstMoveDir == MOVE_HORIZ)
2352 if (ConstMoveDir == MOVE_VERT)
2355 if (ConstMoveDir == MOVE_NONE)
2362 if (Scr->DontMoveOff && MoveFunction != F_FORCEMOVE)
2369 if (xr > Scr->MyDisplayWidth)
2370 xl = Scr->MyDisplayWidth - w;
2374 if (yb > Scr->MyDisplayHeight)
2375 yt = Scr->MyDisplayHeight - h;
2380 if (DragWindow == Tmp_win->frame)
2381 SetupWindow (Tmp_win, xl, yt,
2382 Tmp_win->frame_width, Tmp_win->frame_height, -1);
2384 XMoveWindow (dpy, DragWindow, xl, yt);
2387 if (!Scr->NoRaiseMove && !Scr->OpaqueMove) * opaque already did *
2388 XRaiseWindow(dpy, DragWindow);
2390 if (!Scr->NoRaiseMove)
2391 /* opaque already did, so test the individual window, methinks */
2392 if (DragWindow == Tmp_win->frame)
2394 if (!Tmp_win->opaque_move)
2395 XRaiseWindow(dpy, DragWindow);
2397 else if (!Scr->OpaqueMove)
2398 XRaiseWindow(dpy, DragWindow);
2400 RaiseStickyAbove(); /* DSE */
2403 if (!Scr->OpaqueMove)
2404 UninstallRootColormap();
2408 if (Scr->NumAutoRaises) {
2411 raise_win = ((DragWindow == Tmp_win->frame && !Scr->NoRaiseMove)
2420 #ifdef NEVER /* djhjr - 5/27/03 */
2427 if ( ActiveMenu && RootFunction == F_NOFUNCTION )
2431 int func = ActiveItem->func;
2432 Action = ActiveItem->action;
2441 0 case F_CIRCLEDOWN:
2443 0 case F_WARPTOSCREEN:
2444 0 case F_AUTOPAN: /*RFB */
2445 0 case F_SNAPREALSCREEN:/*RFB*/
2452 ExecuteFunction(func, Action,
2453 ButtonWindow ? ButtonWindow->frame : None,
2454 ButtonWindow, &Event/*&ButtonEvent*/, Context, TRUE);
2455 Context = C_NO_CONTEXT;
2456 ButtonWindow = NULL;
2459 * if we are not executing a defered command, then take down the
2462 if (RootFunction == F_NOFUNCTION)
2474 mask = (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask);
2475 switch (Event.xbutton.button)
2477 case Button1: mask &= ~Button1Mask; break;
2478 case Button2: mask &= ~Button2Mask; break;
2479 case Button3: mask &= ~Button3Mask; break;
2480 case Button4: mask &= ~Button4Mask; break;
2481 case Button5: mask &= ~Button5Mask; break;
2484 if (RootFunction != F_NOFUNCTION ||
2485 ResizeWindow != None ||
2486 moving_window != None ||
2488 { ButtonPressed = -1;
2491 if (RootFunction == F_NOFUNCTION &&
2492 (Event.xbutton.state & mask) == 0 &&
2493 DragWindow == None &&
2494 moving_window == None &&
2495 ResizeWindow == None)
2497 XUngrabPointer(dpy, CurrentTime);
2500 EventHandler[EnterNotify] = HandleEnterNotify;
2501 EventHandler[LeaveNotify] = HandleLeaveNotify;
2502 menuFromFrameOrWindowOrTitlebar = FALSE;
2504 if (DownIconManager)
2506 DownIconManager->down = FALSE;
2509 if (Scr->Highlight) DrawIconManagerBorder(DownIconManager);
2511 if (Scr->Highlight) DrawIconManagerBorder(DownIconManager, False);
2513 DownIconManager = NULL;
2521 static void do_menu (menu, wnd)
2522 MenuRoot *menu; /* menu to pop up */
2523 Window wnd; /* invoking window or None */
2525 int x = Event.xbutton.x_root;
2526 int y = Event.xbutton.y_root;
2529 if (Scr->StayUpMenus)
2530 { GlobalMenuButton = True;
2533 if (!Scr->NoGrabServer)
2537 /* djhjr - 1/20/98 */
2538 int w = Scr->TBInfo.width / 2;
2540 int h = Scr->TBInfo.width - Scr->TBInfo.border;
2542 int h = Scr->TBInfo.width;
2545 (void) XTranslateCoordinates (dpy, w, Scr->Root, 0, h, &x, &y, &child);
2547 (void) XTranslateCoordinates (dpy, wnd, Scr->Root, w, h, &x, &y, &child);
2551 y -= Scr->TitleHeight;
2553 y -= Scr->TitleHeight / 2;
2559 if (PopUpMenu (menu, x, y, center)) {
2562 DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
2568 /***********************************************************************
2571 * HandleButtonPress - ButtonPress event handler
2573 ***********************************************************************
2578 unsigned int modifier;
2580 TwmDoor *door = NULL;
2582 /* Submitted by Jennifer Elaan */
2583 if (Event.xbutton.button > MAX_BUTTONS)
2586 if (Scr->StayUpMenus)
2588 /* added '&& ButtonPressed == -1' - Submitted by Steve Ratcliffe */
2589 if (GlobalFirstTime == False && GlobalMenuButton == True
2590 && ButtonPressed == -1)
2596 { /* pop down the menu, if any */
2597 if (ActiveMenu != NULL) PopDownMenu();
2600 if ( InfoLines ) /* StayUpMenus */
2602 /* djhjr - 6/22/01 */
2603 #ifndef NO_SOUND_SUPPORT
2604 PlaySound(S_IUNMAP);
2607 XUnmapWindow(dpy, Scr->InfoWindow);
2611 XSync(dpy, 0); /* XXX - remove? */
2613 if (ButtonPressed != -1
2614 && !InfoLines /* want menus if we have info box */
2616 { /* we got another butt press in addition to one still held
2617 * down, we need to cancel the operation we were doing
2620 if (DragWindow != None)
2622 CurrentDragX = origDragX;
2623 CurrentDragY = origDragY;
2624 if (!menuFromFrameOrWindowOrTitlebar)
2626 /* added this 'if ... else' - djhjr - 4/7/98 */
2627 if (Tmp_win && DragWindow == Tmp_win->frame && Tmp_win->opaque_move)
2628 XMoveWindow (dpy, DragWindow, origDragX, origDragY);
2630 if (Scr->OpaqueMove && DragWindow != None)
2631 XMoveWindow (dpy, DragWindow, origDragX, origDragY);
2633 MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0);
2635 if (!Scr->OpaqueMove) UninstallRootColormap();
2638 #if 0 /* done in menus.c:ExecuteFunction() now - djhjr - 11/4/03 */
2639 /* this 'else if ...' - djhjr - 11/3/03 */
2640 else if (moving_window)
2641 EndMoveWindowOnDesktop();
2644 XUnmapWindow(dpy, Scr->SizeWindow);
2645 ResizeWindow = None;
2648 if (Event.xbutton.button == Button2) cur = MiddleButt;
2649 else if (Event.xbutton.button >= Button3) cur = RightButt;
2651 XGrabPointer(dpy, Scr->Root, True,
2652 ButtonReleaseMask | ButtonPressMask,
2653 GrabModeAsync, GrabModeAsync,
2654 Scr->Root, cur, CurrentTime);
2658 { ButtonPressed = Event.xbutton.button;
2661 if ( ResizeWindow != None
2662 || DragWindow != None
2663 || moving_window != None
2664 /* ||ActiveMenu != NULL ** tvtwm StayUpMenus */
2670 if ( ButtonPressed == Button1 && Tmp_win && Tmp_win->title_height && Tmp_win->titlebuttons )
2671 { /* check the title bar buttons */
2673 register TBWindow *tbw;
2674 int nb = Scr->TBInfo.nleft + Scr->TBInfo.nright;
2676 for (i = 0, tbw = Tmp_win->titlebuttons; i < nb; i++, tbw++)
2678 if (Event.xany.window == tbw->window)
2680 if (tbw->info->func == F_MENU)
2683 ButtonEvent = Event;
2684 ButtonWindow = Tmp_win;
2685 do_menu (tbw->info->menuroot, tbw->window);
2689 /* djhjr - 9/15/99 */
2692 ExecuteFunction (tbw->info->func, tbw->info->action,
2693 Event.xany.window, Tmp_win, &Event, C_TITLE, FALSE);
2696 * For some reason, we don't get the button up event.
2697 * Submitted by Caveh Frank Jalali
2707 Context = C_NO_CONTEXT;
2708 if ( Event.xany.window == Scr->InfoWindow ) Context = C_IDENTIFY;
2709 if ( Event.xany.window == Scr->Root ) Context = C_ROOT;
2711 /* djhjr - 9/12/96 - moved to the bottom of this context decision chain...
2713 ( Context == C_NO_CONTEXT
2715 ( Tmp_win == Scr->VirtualDesktopDisplayTwin
2717 Event.xany.window == Scr->VirtualDesktopDisplayOuter
2719 Event.xany.window == Scr->VirtualDesktopDisplay
2722 { TwmWindow *tmp_win;
2724 if ( Event.xbutton.subwindow
2725 && XFindContext( dpy, Event.xbutton.subwindow, VirtualContext,
2726 (caddr_t *) &tmp_win )
2729 { * Click in a little window in the panner. *
2731 Context = C_VIRTUAL_WIN;
2734 { * Click in the panner. *
2735 Tmp_win = Scr->VirtualDesktopDisplayTwin;
2736 Context = C_VIRTUAL;
2741 if (XFindContext(dpy, Event.xany.window,
2742 DoorContext, (caddr_t *)&door) != XCNOENT)
2745 if ( Tmp_win && Context == C_NO_CONTEXT )
2747 /* have I really determined that this isn't needed? - djhjr - 9/15/99
2751 RootFunction != F_NOFUNCTION
2753 ( Event.xany.window == Tmp_win->list->w
2755 Event.xany.window == Tmp_win->list->icon
2759 Tmp_win = Tmp_win->list->iconmgr->twm_win;
2760 XTranslateCoordinates(dpy, Event.xany.window, Tmp_win->w,
2761 Event.xbutton.x, Event.xbutton.y,
2762 &JunkX, &JunkY, &JunkChild);
2765 Event.xbutton.x = JunkX;
2766 Event.xbutton.y = JunkY - Tmp_win->title_height;
2768 Event.xbutton.x = JunkX - Tmp_win->frame_bw3D;
2769 Event.xbutton.y = JunkY - Tmp_win->title_height - Tmp_win->frame_bw3D;
2771 Event.xany.window = Tmp_win->w;
2776 if ( Event.xany.window == Tmp_win->title_w )
2780 else if (Event.xany.window == Tmp_win->w)
2782 printf("ERROR! ERROR! ERROR! YOU SHOULD NOT BE HERE!!!\n");
2785 else if (Event.xany.window == Tmp_win->icon_w)
2789 else if (Event.xany.window == Tmp_win->frame)
2790 { /* since we now place a button grab on the frame instead
2791 * of the window, (see GrabButtons() in add_window.c), we
2792 * need to figure out where the pointer exactly is before
2793 * assigning Context. If the pointer is on the application
2794 * window we will change the event structure to look as if
2795 * it came from the application window.
2797 if (Event.xbutton.subwindow == Tmp_win->w)
2798 { Event.xbutton.window = Tmp_win->w;
2801 Event.xbutton.y -= Tmp_win->title_height;
2803 Event.xbutton.x -= Tmp_win->frame_bw3D;
2804 Event.xbutton.y -= (Tmp_win->title_height + Tmp_win->frame_bw3D);
2807 Event.xbutton.x -= Tmp_win->frame_bw;
2812 /* not needed after all - djhjr - 9/10/99
2814 else if (Scr->Doors)
2816 for (door = Scr->Doors; door != NULL; door = door->next)
2817 if (door->twin->frame == Tmp_win->frame)
2824 if (!door) Context = C_FRAME;
2828 else Context = C_FRAME;
2833 ( Event.xany.window == Tmp_win->list->w
2835 Event.xany.window == Tmp_win->list->icon
2839 Tmp_win->list->down = TRUE;
2842 if (Scr->Highlight) DrawIconManagerBorder(Tmp_win->list);
2844 if (Scr->Highlight) DrawIconManagerBorder(Tmp_win->list, False);
2846 DownIconManager = Tmp_win->list;
2847 Context = C_ICONMGR;
2851 /* djhjr - 9/12/96 - moved from the top of this context decision chain...*/
2853 ( Context == C_NO_CONTEXT
2855 ( Tmp_win == Scr->VirtualDesktopDisplayTwin
2857 Event.xany.window == Scr->VirtualDesktopDisplayOuter
2859 Event.xany.window == Scr->VirtualDesktopDisplay
2862 { TwmWindow *tmp_win;
2864 if ( Event.xbutton.subwindow
2865 && XFindContext( dpy, Event.xbutton.subwindow, VirtualContext,
2866 (caddr_t *) &tmp_win )
2869 { /* Click in a little window in the panner. */
2871 Context = C_VIRTUAL_WIN;
2874 { /* Click in the panner. */
2875 Tmp_win = Scr->VirtualDesktopDisplayTwin;
2876 Context = C_VIRTUAL;
2880 /* this section of code checks to see if we were in the middle of
2881 * a command executed from a menu
2883 if (RootFunction != F_NOFUNCTION)
2885 if (Event.xany.window == Scr->Root)
2887 /* if the window was the Root, we don't know for sure it
2888 * it was the root. We must check to see if it happened to be
2889 * inside of a client that was getting button press events.
2891 XTranslateCoordinates(dpy, Scr->Root, Scr->Root,
2894 &JunkX, &JunkY, &Event.xany.window);
2896 if (Event.xany.window == 0 ||
2897 XFindContext(dpy, Event.xany.window, TwmContext,
2898 (caddr_t *)&Tmp_win) == XCNOENT)
2900 RootFunction = F_NOFUNCTION;
2901 DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
2904 * If stay up menus is set, then the menu may still be active
2905 * and should be popped down - Submitted by Steve Ratcliffe
2907 if (ActiveMenu != NULL)
2913 XTranslateCoordinates(dpy, Scr->Root, Event.xany.window,
2916 &JunkX, &JunkY, &JunkChild);
2918 Event.xbutton.x = JunkX;
2919 Event.xbutton.y = JunkY;
2923 /* make sure we are not trying to move an identify window */
2924 if (Scr->InfoWindow && Event.xany.window != Scr->InfoWindow)
2926 ExecuteFunction(RootFunction, Action, Event.xany.window,
2927 Tmp_win, &Event, Context, FALSE);
2928 if (Scr->StayUpMenus)
2929 { /* pop down the menu, if any */
2930 if (ActiveMenu != NULL) PopDownMenu();
2934 RootFunction = F_NOFUNCTION;
2938 ButtonEvent = Event;
2939 ButtonWindow = Tmp_win;
2941 /* if we get to here, we have to execute a function or pop up a
2944 modifier = (Event.xbutton.state & mods_used);
2946 if (Context == C_NO_CONTEXT) return;
2948 RootFunction = F_NOFUNCTION;
2949 if (Scr->Mouse[Event.xbutton.button][Context][modifier].func == F_MENU)
2951 do_menu (Scr->Mouse[Event.xbutton.button][Context][modifier].menu,
2953 if (Scr->StayUpMenus)
2955 GlobalMenuButton = False;
2958 else if (Scr->Mouse[Event.xbutton.button][Context][modifier].func != F_NOFUNCTION)
2961 [Event.xbutton.button][Context][modifier].item
2963 [Event.xbutton.button][Context][modifier]
2966 ExecuteFunction( Scr->Mouse
2967 [Event.xbutton.button][Context][modifier].func,
2968 Action, Event.xany.window, Tmp_win, &Event, Context, FALSE);
2970 else if (Scr->DefaultFunction.func != F_NOFUNCTION)
2972 if (Scr->DefaultFunction.func == F_MENU)
2974 do_menu (Scr->DefaultFunction.menu, (Window) None);
2978 Action = Scr->DefaultFunction.item
2979 ? Scr->DefaultFunction.item->action
2981 ExecuteFunction(Scr->DefaultFunction.func, Action,
2982 Event.xany.window, Tmp_win, &Event, Context, FALSE);
2989 /***********************************************************************
2992 * HENQueueScanner - EnterNotify event q scanner
2994 * Looks at the queued events and determines if any matching
2995 * LeaveNotify events or EnterEvents deriving from the
2996 * termination of a grab are behind this event to allow
2997 * skipping of unnecessary processing.
2999 ***********************************************************************
3002 typedef struct HENScanArgs {
3003 Window w; /* Window we are currently entering */
3004 Bool leaves; /* Any LeaveNotifies found for this window */
3005 Bool inferior; /* Was NotifyInferior the mode for LeaveNotify */
3006 Bool enters; /* Any EnterNotify events with NotifyUngrab */
3011 HENQueueScanner(dpy, ev, args)
3016 if (ev->type == LeaveNotify) {
3017 if (ev->xcrossing.window == ((HENScanArgs *) args)->w &&
3018 ev->xcrossing.mode == NotifyNormal) {
3019 ((HENScanArgs *) args)->leaves = True;
3021 * Only the last event found matters for the Inferior field.
3023 ((HENScanArgs *) args)->inferior =
3024 (ev->xcrossing.detail == NotifyInferior);
3026 } else if (ev->type == EnterNotify) {
3027 if (ev->xcrossing.mode == NotifyUngrab)
3028 ((HENScanArgs *) args)->enters = True;
3036 /***********************************************************************
3039 * HandleEnterNotify - EnterNotify event handler
3041 ***********************************************************************
3048 XEnterWindowEvent *ewp = &Event.xcrossing;
3049 HENScanArgs scanArgs;
3052 extern int RaiseDelay;/*RAISEDELAY*/
3055 * Save the id of the window entered. This will be used to remove
3056 * border highlight on entering the next application window.
3058 if (UnHighLight_win && ewp->window != UnHighLight_win->w) {
3059 SetBorder (UnHighLight_win, False); /* application window */
3060 if (UnHighLight_win->list) /* in the icon box */
3061 NotActiveIconManager(UnHighLight_win->list);
3063 if (ewp->window == Scr->Root)
3064 UnHighLight_win = NULL;
3066 UnHighLight_win = Tmp_win;
3069 * if we aren't in the middle of menu processing
3073 * We're not interested in pseudo Enter/Leave events generated
3074 * from grab initiations.
3076 if (ewp->mode == NotifyGrab)
3080 * Scan for Leave and Enter Notify events to see if we can avoid some
3081 * unnecessary processing.
3083 scanArgs.w = ewp->window;
3084 scanArgs.leaves = scanArgs.enters = False;
3085 (void) XCheckIfEvent(dpy, &dummy, HENQueueScanner, (char *) &scanArgs);
3088 * if it is one of the autopan windows, do the pan
3090 if ( Scr->AutoPanX )/*RFB F_AUTOPAN*/
3091 for (l = 0; l <= 3; l++)
3092 if (ewp->window == Scr->VirtualDesktopAutoPan[l])
3094 int xdiff, ydiff, xwarp, ywarp;
3097 * Code from FVWM-1.23b, modified to reflect "real time"
3098 * values of the resource.
3102 if (Scr->VirtualDesktopPanResistance > 0 &&
3103 Scr->VirtualDesktopPanResistance < 10000)
3106 static struct timeval timeoutval = {0, 12500};
3107 struct timeval timeout;
3109 /* The granularity of PanResistance is about 25 ms.
3110 * The timeout variable is set to 12.5 ms since we
3111 * pass this way twice each time an autopan window
3114 for (i = 25; i < Scr->VirtualDesktopPanResistance; i += 25)
3116 timeout = timeoutval;
3117 select(0, 0, 0, 0, &timeout);
3119 scanArgs.w = ewp->window;
3120 scanArgs.leaves = scanArgs.enters = False;
3121 (void)XCheckIfEvent(dpy, &dummy, HENQueueScanner,
3124 if (scanArgs.leaves)
3128 XQueryPointer(dpy, Scr->Root, &JunkRoot, &JunkChild,
3129 &x, &y, &JunkX, &JunkY, &JunkMask);
3131 if (x < Scr->AutoPanBorderWidth)
3133 else if (x >= Scr->MyDisplayWidth - Scr->AutoPanBorderWidth)
3135 else if (y < Scr->AutoPanBorderWidth)
3137 else if (y >= Scr->MyDisplayHeight - Scr->AutoPanBorderWidth)
3143 /* figure out which one it is */
3147 xdiff = -(Scr->AutoPanX);
3149 /* xwarp = AP_SIZE + 2; */
3150 xwarp = AP_SIZE + Scr->AutoPanExtraWarp; /* DSE */
3154 xdiff = Scr->AutoPanX;
3156 /* xwarp = -(AP_SIZE + 2); */
3157 xwarp = -(AP_SIZE + Scr->AutoPanExtraWarp); /* DSE */
3162 ydiff = -(Scr->AutoPanY);
3164 /* ywarp = AP_SIZE + 2; */
3165 ywarp = AP_SIZE + Scr->AutoPanExtraWarp; /* DSE */
3169 ydiff = Scr->AutoPanY;
3171 /* ywarp = -(AP_SIZE + 2); */
3172 ywarp = -(AP_SIZE + Scr->AutoPanExtraWarp); /* DSE */
3175 /* this is to stop the compiler complaining */
3176 xdiff = ydiff = xwarp = ywarp = 0;
3177 /* not with the PanResistance resource! - djhjr - 9/8/98
3178 fprintf(stderr, "vtwm: major problems with autopan\n");
3182 /* djhjr - 6/22/01 */
3183 #ifndef NO_SOUND_SUPPORT
3188 PanRealScreen(xdiff, ydiff, &xwarp, &ywarp); /* DSE */
3191 * warp the pointer out of the window so that they can keep
3194 XWarpPointer(dpy, None, None, 0, 0, 0, 0, xwarp, ywarp);
3197 } /* end if ewp->window = autopan */
3200 * if entering root window, restore twm default colormap so that
3201 * titlebars are legible
3203 if (ewp->window == Scr->Root) {
3204 if (!scanArgs.leaves && !scanArgs.enters)
3205 InstallWindowColormaps(EnterNotify, &Scr->TwmRoot);
3209 /*RAISEDELAY*/ /* Handle RaiseDelay, if any..... */
3210 /*RAISEDELAY*/ if (RaiseDelay > 0) {
3211 /*RAISEDELAY*/ if (Tmp_win && Tmp_win->auto_raise
3212 /*RAISEDELAY*/ && (!Tmp_win->list || Tmp_win->list->w != ewp->window)) {
3213 /*RAISEDELAY*/ ColormapWindow *cwin;
3216 /*RAISEDELAY*/ static struct timeval timeout = {0,12500};
3219 * Submitted by Steve Ratcliffe
3221 /*RAISEDELAY*/ static struct timeval timeoutval = {0,12500};
3222 /*RAISEDELAY*/ struct timeval timeout;
3226 /*RAISEDELAY*/ if (XFindContext(dpy, Tmp_win->w, ColormapContext,
3227 /*RAISEDELAY*/ (caddr_t *)&cwin) == XCNOENT) {
3228 /*RAISEDELAY*/ cwin = (ColormapWindow *)NULL;
3231 /*RAISEDELAY*/ if ((ewp->detail != NotifyInferior
3232 /*RAISEDELAY*/ || Tmp_win->frame == ewp->window)
3233 /*RAISEDELAY*/ && (!cwin || cwin->visibility != VisibilityUnobscured)) {
3234 /*RAISEDELAY*/ int x, y, px, py, d, i;
3235 /*RAISEDELAY*/ Window w;
3237 /*RAISEDELAY*/ XQueryPointer(dpy, Scr->Root, &w, &w, &px, &py,
3238 /*RAISEDELAY*/ &d, &d, (unsigned int *)&d);
3240 /*RAISEDELAY*/ /* The granularity of RaiseDelay is about 25 ms.
3241 * The timeout variable is set to 12.5 ms since we
3242 * pass this way twice each time a twm window is
3245 /*RAISEDELAY*/ for (i = 25; i < RaiseDelay; i += 25) {
3248 * Submitted by Steve Ratcliffe
3250 /*RAISEDELAY*/ /* The timeout needs initialising each time on Linux */
3251 /*RAISEDELAY*/ timeout = timeoutval;
3253 /*RAISEDELAY*/ select(0, 0, 0, 0, &timeout);
3254 /*RAISEDELAY*/ /* Did we leave this window already? */
3255 /*RAISEDELAY*/ scanArgs.w = ewp->window;
3256 /*RAISEDELAY*/ scanArgs.leaves = scanArgs.enters = False;
3257 /*RAISEDELAY*/ (void) XCheckIfEvent(dpy, &dummy, HENQueueScanner,
3258 /*RAISEDELAY*/ (char *) &scanArgs);
3259 /*RAISEDELAY*/ if (scanArgs.leaves && !scanArgs.inferior) return;
3261 /*RAISEDELAY*/ XQueryPointer(dpy, Scr->Root, &w, &w, &x, &y,
3262 /*RAISEDELAY*/ &d, &d, (unsigned int *)&d);
3264 /*RAISEDELAY*/ /* Has the pointer moved? If so reset the loop cnt.
3265 * We want the pointer to be still for RaiseDelay
3266 * milliseconds before terminating the loop
3268 /*RAISEDELAY*/ if (x != px || y != py) {
3269 /*RAISEDELAY*/ i = 0; px = x; py = y;
3276 * Scan for Leave and Enter Notify events to see if we can avoid some
3277 * unnecessary processing.
3279 /*RAISEDELAY*/ scanArgs.w = ewp->window;
3280 /*RAISEDELAY*/ scanArgs.leaves = scanArgs.enters = False;
3281 /*RAISEDELAY*/ (void) XCheckIfEvent(dpy, &dummy, HENQueueScanner, (char *) &scanArgs);
3284 * if entering root window, restore twm default colormap so that
3285 * titlebars are legible
3287 /*RAISEDELAY*/ if (ewp->window == Scr->Root) {
3288 /*RAISEDELAY*/ if (!scanArgs.leaves && !scanArgs.enters)
3289 /*RAISEDELAY*/ InstallWindowColormaps(EnterNotify, &Scr->TwmRoot);
3290 /*RAISEDELAY*/ return;
3293 /*RAISEDELAY*/ /* End of RaiseDelay modification. */
3296 * if we have an event for a specific one of our windows
3300 * If currently in PointerRoot mode (indicated by FocusRoot), then
3301 * focus on this window
3303 if (Scr->FocusRoot && (!scanArgs.leaves || scanArgs.inferior)) {
3304 if (Tmp_win->list) ActiveIconManager(Tmp_win->list);
3306 if (Tmp_win->mapped) {
3308 * unhighlight old focus window
3312 if (Scr->Focus && Scr->Focus != Tmp_win && Tmp_win->hilite_w)
3313 XUnmapWindow(dpy, Scr->Focus->hilite_w);
3315 if (Scr->Focus && Scr->Focus != Tmp_win)
3316 PaintTitleHighlight(Scr->Focus, off);
3319 * If entering the frame or the icon manager, then do
3320 * "window activation things":
3322 * 1. turn on highlight window (if any)
3323 * 2. install frame colormap
3324 * 3. set frame and highlight window (if any) border
3325 * 3a. set titlebutton highlight (if button color is frame)
3326 * if IconManagerFocus is set or not in icon mgr
3327 * 4. focus on client window to forward typing
3328 * 4a. same as 4 but for icon mgr and/or NoTitlebar set
3329 * 5. send WM_TAKE_FOCUS if requested
3331 if (ewp->window == Tmp_win->frame ||
3332 (Tmp_win->list && ewp->window == Tmp_win->list->w)) {
3335 if (Tmp_win->hilite_w) * 1 *
3336 XMapWindow (dpy, Tmp_win->hilite_w);
3338 PaintTitleHighlight(Tmp_win, on); /* 1 */
3340 if (!scanArgs.leaves && !scanArgs.enters) /* 2 */
3341 InstallWindowColormaps (EnterNotify,
3343 SetBorder (Tmp_win, True); /* 3, 3a */
3345 /* added this 'if()' - djhjr - 5/27/98 */
3346 /* added hack for StrictIconManager - djhjr - 10/2/01 */
3347 /* added test for transients - djhjr - 4/9/02 */
3348 if (Scr->IconManagerFocus ||
3350 Scr->StrictIconManager &&
3352 (Tmp_win->list && Tmp_win->list->w &&
3353 Tmp_win->list->w != ewp->window) ||
3356 /* added test for transients - djhjr - 4/9/02 */
3357 if ((((Tmp_win->title_w || Scr->NoTitlebar) && /* 4, 4a */
3359 Tmp_win->transient) &&
3361 Tmp_win->wmhints->input)
3362 SetFocus (Tmp_win, ewp->time);
3365 if (Tmp_win->protocols & DoesWmTakeFocus) /* 5 */
3366 SendTakeFocusMessage (Tmp_win, ewp->time);
3367 Scr->Focus = Tmp_win;
3368 } else if (ewp->window == Tmp_win->w) {
3370 * If we are entering the application window, install
3373 if (!scanArgs.leaves || scanArgs.inferior)
3374 InstallWindowColormaps(EnterNotify, Tmp_win);
3376 } /* end if Tmp_win->mapped */
3377 if (Tmp_win->wmhints != NULL &&
3378 ewp->window == Tmp_win->wmhints->icon_window &&
3379 (!scanArgs.leaves || scanArgs.inferior))
3380 InstallWindowColormaps(EnterNotify, Tmp_win);
3381 } /* end if FocusRoot */
3383 * If this window is to be autoraised, mark it so
3385 if (Tmp_win->auto_raise) {
3386 enter_win = Tmp_win;
3387 if (enter_flag == FALSE) AutoRaiseWindow (Tmp_win);
3388 } else if (enter_flag && raise_win == Tmp_win)
3389 enter_win = Tmp_win;
3393 if (Tmp_win->ring.next && (!enter_flag || raise_win == enter_win))
3396 * If this window is an icon manager window, make
3397 * the ring leader the icon manager - djhjr - 11/8/01
3399 * Is the icon manager in the ring? - djhjr - 10/27/02
3401 if (Tmp_win->list && ewp->window == Tmp_win->list->w &&
3402 Tmp_win->list->iconmgr->twm_win->ring.next)
3404 Scr->RingLeader = Tmp_win->list->iconmgr->twm_win;
3407 Scr->RingLeader = Tmp_win;
3411 } /* end if Tmp_win */
3412 } /* end if !ActiveMenu */
3415 * Find the menu that we are dealing with now; punt if unknown
3417 if (XFindContext (dpy, ewp->window, MenuContext, (caddr_t *)&mr) != XCSUCCESS) return;
3421 if (ActiveMenu && mr == ActiveMenu->prev && RootFunction == F_NOFUNCTION) {
3422 if (Scr->Shadow) XUnmapWindow (dpy, ActiveMenu->shadow);
3423 XUnmapWindow (dpy, ActiveMenu->w);
3424 ActiveMenu->mapped = UNMAPPED;
3425 UninstallRootColormap ();
3427 ActiveItem->state = 0;
3428 PaintEntry (ActiveMenu, ActiveItem, False);
3435 if (RootFunction == F_NOFUNCTION) {
3437 for (tmp = ActiveMenu; tmp; tmp = tmp->prev) {
3438 if (tmp == mr) break;
3441 for (tmp = ActiveMenu; tmp != mr; tmp = tmp->prev) {
3442 /* all 'tmp' were 'ActiveMenu'... DUH! - djhjr - 11/16/98 */
3443 if (Scr->Shadow) XUnmapWindow (dpy, tmp->shadow);
3444 XUnmapWindow (dpy, tmp->w);
3445 tmp->mapped = UNMAPPED;
3448 UninstallRootColormap ();
3450 ActiveItem->state = 0;
3451 PaintEntry (ActiveMenu, ActiveItem, False);
3462 /***********************************************************************
3465 * HLNQueueScanner - LeaveNotify event q scanner
3467 * Looks at the queued events and determines if any
3468 * EnterNotify events are behind this event to allow
3469 * skipping of unnecessary processing.
3471 ***********************************************************************
3474 typedef struct HLNScanArgs {
3475 Window w; /* The window getting the LeaveNotify */
3476 Bool enters; /* Any EnterNotify event at all */
3477 Bool matches; /* Any matching EnterNotify events */
3482 HLNQueueScanner(dpy, ev, args)
3487 if (ev->type == EnterNotify && ev->xcrossing.mode != NotifyGrab) {
3488 ((HLNScanArgs *) args)->enters = True;
3489 if (ev->xcrossing.window == ((HLNScanArgs *) args)->w)
3490 ((HLNScanArgs *) args)->matches = True;
3498 /***********************************************************************
3501 * HandleLeaveNotify - LeaveNotify event handler
3503 ***********************************************************************
3509 HLNScanArgs scanArgs;
3512 if (Tmp_win != NULL)
3517 * We're not interested in pseudo Enter/Leave events generated
3518 * from grab initiations and terminations.
3520 if (Event.xcrossing.mode != NotifyNormal)
3523 inicon = (Tmp_win->list &&
3524 Tmp_win->list->w == Event.xcrossing.window);
3527 * rem'ing this allows the window crossed out of onto the root window
3528 * to be remembered, so an f.warpring event occuring on the root window
3529 * will return to that window (see WarpAlongRing() in menus.c).
3531 * no, I don't fully understand... djhjr - 5/11/98
3533 if (Scr->RingLeader && Scr->RingLeader == Tmp_win &&
3534 (Event.xcrossing.detail != NotifyInferior &&
3535 Event.xcrossing.window != Tmp_win->w)) {
3537 #ifdef ORIGINAL_WARPRINGCOORDINATES * djhjr - 5/11/98 *
3539 if (Tmp_win->mapped) {
3540 Tmp_win->ring.cursor_valid = False;
3542 Tmp_win->ring.cursor_valid = True;
3543 Tmp_win->ring.curs_x = (Event.xcrossing.x_root -
3545 Tmp_win->ring.curs_y = (Event.xcrossing.y_root -
3551 Scr->RingLeader = (TwmWindow *) NULL;
3555 if (Scr->FocusRoot) {
3557 if (Event.xcrossing.detail != NotifyInferior) {
3560 * Scan for EnterNotify events to see if we can avoid some
3561 * unnecessary processing.
3563 scanArgs.w = Event.xcrossing.window;
3564 scanArgs.enters = scanArgs.matches = False;
3565 (void) XCheckIfEvent(dpy, &dummy, HLNQueueScanner,
3566 (char *) &scanArgs);
3568 if ((Event.xcrossing.window == Tmp_win->frame &&
3569 !scanArgs.matches) || inicon) {
3570 if (Tmp_win->list) NotActiveIconManager(Tmp_win->list);
3573 if (Tmp_win->hilite_w)
3574 XUnmapWindow (dpy, Tmp_win->hilite_w);
3576 PaintTitleHighlight(Tmp_win, off);
3578 SetBorder (Tmp_win, False);
3579 if (Scr->TitleFocus ||
3580 Tmp_win->protocols & DoesWmTakeFocus)
3581 SetFocus ((TwmWindow *) NULL, Event.xcrossing.time);
3583 } else if (Event.xcrossing.window == Tmp_win->w &&
3585 InstallWindowColormaps (LeaveNotify, &Scr->TwmRoot);
3596 /***********************************************************************
3599 * HandleConfigureRequest - ConfigureRequest event handler
3601 ***********************************************************************
3605 HandleConfigureRequest()
3609 int x, y, width, height, bw;
3611 XConfigureRequestEvent *cre = &Event.xconfigurerequest;
3614 fprintf(stderr, "ConfigureRequest\n");
3615 if (cre->value_mask & CWX)
3616 fprintf(stderr, " x = %d\n", cre->x);
3617 if (cre->value_mask & CWY)
3618 fprintf(stderr, " y = %d\n", cre->y);
3619 if (cre->value_mask & CWWidth)
3620 fprintf(stderr, " width = %d\n", cre->width);
3621 if (cre->value_mask & CWHeight)
3622 fprintf(stderr, " height = %d\n", cre->height);
3623 if (cre->value_mask & CWSibling)
3624 fprintf(stderr, " above = 0x%x\n", cre->above);
3625 if (cre->value_mask & CWStackMode)
3626 fprintf(stderr, " stack = %d\n", cre->detail);
3630 * Event.xany.window is Event.xconfigurerequest.parent, so Tmp_win will
3633 Event.xany.window = cre->window; /* mash parent field */
3634 if (XFindContext (dpy, cre->window, TwmContext, (caddr_t *) &Tmp_win) ==
3640 * According to the July 27, 1988 ICCCM draft, we should ignore size and
3641 * position fields in the WM_NORMAL_HINTS property when we map a window.
3642 * Instead, we'll read the current geometry. Therefore, we should respond
3643 * to configuration requests for windows which have never been mapped.
3645 if (!Tmp_win || Tmp_win->icon_w == cre->window) {
3646 xwcm = cre->value_mask &
3647 (CWX | CWY | CWWidth | CWHeight | CWBorderWidth);
3650 xwc.width = cre->width;
3651 xwc.height = cre->height;
3652 xwc.border_width = cre->border_width;
3653 XConfigureWindow(dpy, Event.xany.window, xwcm, &xwc);
3657 if ((cre->value_mask & CWStackMode) && Tmp_win->stackmode) {
3658 TwmWindow *otherwin;
3660 xwc.sibling = (((cre->value_mask & CWSibling) &&
3661 (XFindContext (dpy, cre->above, TwmContext,
3662 (caddr_t *) &otherwin) == XCSUCCESS))
3663 ? otherwin->frame : cre->above);
3664 xwc.stack_mode = cre->detail;
3665 XConfigureWindow (dpy, Tmp_win->frame,
3666 cre->value_mask & (CWSibling | CWStackMode), &xwc);
3670 /* Don't modify frame_XXX fields before calling SetupWindow! */
3671 x = Tmp_win->frame_x;
3672 y = Tmp_win->frame_y;
3673 width = Tmp_win->frame_width;
3674 height = Tmp_win->frame_height;
3675 bw = Tmp_win->frame_bw;
3678 * Section 4.1.5 of the ICCCM states that the (x,y) coordinates in the
3679 * configure request are for the upper-left outer corner of the window.
3680 * This means that we need to adjust for the additional title height as
3681 * well as for any border width changes that we decide to allow. The
3682 * current window gravity is to be used in computing the adjustments, just
3683 * as when initially locating the window. Note that if we do decide to
3684 * allow border width changes, we will need to send the synthetic
3685 * ConfigureNotify event.
3687 GetGravityOffsets (Tmp_win, &gravx, &gravy);
3689 if (cre->value_mask & CWBorderWidth) {
3690 int bwdelta = cre->border_width - Tmp_win->old_bw; /* posit growth */
3691 if (bwdelta && Scr->ClientBorderWidth) { /* if change allowed */
3692 x += gravx * bwdelta; /* change default values only */
3693 y += gravy * bwdelta; /* ditto */
3694 bw = cre->border_width;
3695 if (Tmp_win->title_height) height += bwdelta;
3696 x += (gravx < 0) ? bwdelta : -bwdelta;
3697 y += (gravy < 0) ? bwdelta : -bwdelta;
3699 Tmp_win->old_bw = cre->border_width; /* for restoring */
3702 if (cre->value_mask & CWX) { /* override even if border change */
3705 /* djhjr - 4/21/96 */
3706 x -= ((gravx < 0) ? 0 : Tmp_win->frame_bw3D);
3709 if (cre->value_mask & CWY) {
3710 y = cre->y - ((gravy < 0) ? 0 : Tmp_win->title_height) - bw;
3712 /* djhjr - 4/21/96 */
3713 y -= ((gravy < 0) ? 0 : Tmp_win->frame_bw3D);
3717 if (cre->value_mask & CWWidth) {
3722 width = cre->width + 2 * Tmp_win->frame_bw3D;
3725 if (cre->value_mask & CWHeight) {
3728 height = cre->height + Tmp_win->title_height;
3730 height = cre->height + Tmp_win->title_height + 2 * Tmp_win->frame_bw3D;
3734 if (width != Tmp_win->frame_width || height != Tmp_win->frame_height)
3735 Tmp_win->zoomed = ZOOM_NONE;
3738 * SetupWindow (x,y) are the location of the upper-left outer corner and
3739 * are passed directly to XMoveResizeWindow (frame). The (width,height)
3740 * are the inner size of the frame. The inner width is the same as the
3741 * requested client window width; the inner height is the same as the
3742 * requested client window height plus any title bar slop.
3744 /* propogate ConfigureNotify events - submitted by Jonathan Paisley - 11/11/02
3745 SetupWindow (Tmp_win, x, y, width, height, bw);
3747 SetupFrame(Tmp_win, x, y, width, height, bw, True);
3749 /* Change the size of the desktop representation */
3750 MoveResizeDesktop (Tmp_win, TRUE);
3753 * Raise the autopan windows in case the current window covers them.
3754 * Submitted by Steve Ratcliffe
3761 /***********************************************************************
3764 * HandleShapeNotify - shape notification event handler
3766 ***********************************************************************
3769 HandleShapeNotify ()
3771 XShapeEvent *sev = (XShapeEvent *) &Event;
3773 if (Tmp_win == NULL)
3775 if (sev->kind != ShapeBounding)
3777 if (!Tmp_win->wShaped && sev->shaped) {
3778 XShapeCombineMask (dpy, Tmp_win->frame, ShapeClip, 0, 0, None,
3781 Tmp_win->wShaped = sev->shaped;
3782 SetFrameShape (Tmp_win);
3787 /***********************************************************************
3790 * HandleUnknown - unknown event handler
3792 ***********************************************************************
3799 fprintf(stderr, "type = %d\n", Event.type);
3805 /***********************************************************************
3808 * Transient - checks to see if the window is a transient
3811 * TRUE - window is a transient
3812 * FALSE - window is not a transient
3815 * w - the window to check
3817 ***********************************************************************
3824 return (XGetTransientForHint(dpy, w, propw));
3829 /***********************************************************************
3832 * FindScreenInfo - get ScreenInfo struct associated with a given window
3840 ***********************************************************************
3847 XWindowAttributes attr;
3851 if (XGetWindowAttributes(dpy, w, &attr)) {
3852 for (scrnum = 0; scrnum < NumScreens; scrnum++) {
3853 if (ScreenList[scrnum] != NULL &&
3854 (ScreenOfDisplay(dpy, ScreenList[scrnum]->screen) ==
3856 return ScreenList[scrnum];
3865 static void flush_expose (w)
3871 while (XCheckTypedWindowEvent (dpy, w, Expose, &dummy)) ;
3876 /***********************************************************************
3879 * InstallWindowColormaps - install the colormaps for one twm window
3882 * type - type of event that caused the installation
3883 * tmp - for a subset of event types, the address of the
3884 * window structure, whose colormaps are to be installed.
3886 ***********************************************************************
3889 void InstallWindowColormaps (type, tmp)
3893 int i, j, n, number_cwins, state;
3894 ColormapWindow **cwins, *cwin, **maxcwin = NULL;
3896 char *row, *scoreboard;
3903 /* Save the colormap to be loaded for when force loading of
3904 * root colormap(s) ends.
3906 Scr->cmapInfo.pushed_window = tmp;
3907 /* Don't load any new colormap if root colormap(s) has been
3910 if (Scr->cmapInfo.root_pushes)
3912 /* Don't reload the currend window colormap list.
3914 if (Scr->cmapInfo.cmaps == &tmp->cmaps)
3916 if (Scr->cmapInfo.cmaps)
3917 for (i = Scr->cmapInfo.cmaps->number_cwins,
3918 cwins = Scr->cmapInfo.cmaps->cwins; i-- > 0; cwins++)
3919 (*cwins)->colormap->state &= ~CM_INSTALLABLE;
3920 Scr->cmapInfo.cmaps = &tmp->cmaps;
3923 case PropertyNotify:
3924 case VisibilityNotify:
3925 case ColormapNotify:
3929 number_cwins = Scr->cmapInfo.cmaps->number_cwins;
3930 cwins = Scr->cmapInfo.cmaps->cwins;
3931 scoreboard = Scr->cmapInfo.cmaps->scoreboard;
3933 ColortableThrashing = FALSE; /* in case installation aborted */
3935 state = CM_INSTALLED;
3938 * Submitted by Caveh Frank Jalali
3940 for (i = n = 0; i < number_cwins
3941 && n < Scr->cmapInfo.maxCmaps
3943 for (i = 0; i < number_cwins
3946 ** Article <21sn92INNbiv@sirius.isi.com> Mon 18:06
3947 ** Path: ..!news.isi.com!not-for-mail (Mark Kent @
3948 ** Integrated Systems, Inc.)
3952 cmap = cwin->colormap;
3953 cmap->state |= CM_INSTALLABLE;
3954 cmap->state &= ~CM_INSTALL;
3957 for (i = n = 0; i < number_cwins; i++) {
3959 cmap = cwin->colormap;
3960 if (cwin->visibility != VisibilityFullyObscured
3961 /* && n < Scr->cmapInfo.maxCmaps
3962 ** <21sn92INNbiv@sirius.isi.com>
3965 row = scoreboard + (i*(i-1)/2);
3966 for (j = 0; j < i; j++)
3967 if (row[j] && (cwins[j]->colormap->state & CM_INSTALL))
3972 maxcwin = &cwins[i];
3973 state &= (cmap->state & CM_INSTALLED);
3974 cmap->state |= CM_INSTALL;
3978 Scr->cmapInfo.first_req = NextRequest(dpy);
3981 * Submitted by Caveh Frank Jalali
3983 for ( ; n > 0; maxcwin--) {
3985 for ( ; n > 0; n--, maxcwin--) {
3987 cmap = (*maxcwin)->colormap;
3988 if (cmap->state & CM_INSTALL) {
3989 cmap->state &= ~CM_INSTALL;
3990 if (!(state & CM_INSTALLED)) {
3991 cmap->install_req = NextRequest(dpy);
3992 XInstallColormap(dpy, cmap->c);
3994 cmap->state |= CM_INSTALLED;
3995 /* see above 'for (...)'
4004 /***********************************************************************
4007 * <Uni/I>nstallRootColormap - Force (un)loads root colormap(s)
4009 * These matching routines provide a mechanism to insure that
4010 * the root colormap(s) is installed during operations like
4011 * rubber banding or menu display that require colors from
4012 * that colormap. Calls may be nested arbitrarily deeply,
4013 * as long as there is one UninstallRootColormap call per
4014 * InstallRootColormap call.
4016 * The final UninstallRootColormap will cause the colormap list
4017 * which would otherwise have be loaded to be loaded, unless
4018 * Enter or Leave Notify events are queued, indicating some
4019 * other colormap list would potentially be loaded anyway.
4020 ***********************************************************************
4023 void InstallRootColormap()
4026 if (Scr->cmapInfo.root_pushes == 0) {
4028 * The saving and restoring of cmapInfo.pushed_window here
4029 * is a slimy way to remember the actual pushed list and
4030 * not that of the root window.
4032 tmp = Scr->cmapInfo.pushed_window;
4033 InstallWindowColormaps(0, &Scr->TwmRoot);
4034 Scr->cmapInfo.pushed_window = tmp;
4036 Scr->cmapInfo.root_pushes++;
4043 UninstallRootColormapQScanner(dpy, ev, args)
4050 if (ev->type == EnterNotify) {
4051 if (ev->xcrossing.mode != NotifyGrab)
4053 } else if (ev->type == LeaveNotify) {
4054 if (ev->xcrossing.mode == NotifyNormal)
4064 void UninstallRootColormap()
4069 if (Scr->cmapInfo.root_pushes)
4070 Scr->cmapInfo.root_pushes--;
4072 if (!Scr->cmapInfo.root_pushes) {
4074 * If we have subsequent Enter or Leave Notify events,
4075 * we can skip the reload of pushed colormaps.
4079 (void) XCheckIfEvent(dpy, &dummy, UninstallRootColormapQScanner, &args);
4082 InstallWindowColormaps(0, Scr->cmapInfo.pushed_window);
4086 void SendConfigureNotify(tmp_win, x, y)
4090 XEvent client_event;
4092 client_event.type = ConfigureNotify;
4093 client_event.xconfigure.display = dpy;
4094 client_event.xconfigure.event = tmp_win->w;
4095 client_event.xconfigure.window = tmp_win->w;
4098 client_event.xconfigure.x = (x + tmp_win->frame_bw - tmp_win->old_bw);
4099 client_event.xconfigure.y = (y + tmp_win->frame_bw +
4100 tmp_win->title_height - tmp_win->old_bw);
4101 client_event.xconfigure.width = tmp_win->frame_width;
4102 client_event.xconfigure.height = tmp_win->frame_height -
4103 tmp_win->title_height;
4105 client_event.xconfigure.x = (x + tmp_win->frame_bw - tmp_win->old_bw
4106 + tmp_win->frame_bw3D);
4107 client_event.xconfigure.y = (y + tmp_win->frame_bw +
4108 tmp_win->title_height - tmp_win->old_bw
4109 + tmp_win->frame_bw3D);
4110 client_event.xconfigure.width = tmp_win->attr.width;
4111 client_event.xconfigure.height = tmp_win->attr.height;
4113 client_event.xconfigure.border_width = tmp_win->old_bw;
4114 /* Real ConfigureNotify events say we're above title window, so ... */
4115 /* what if we don't have a title ????? */
4116 client_event.xconfigure.above = tmp_win->frame;
4117 client_event.xconfigure.override_redirect = False;
4119 XSendEvent(dpy, tmp_win->w, False, StructureNotifyMask, &client_event);
4129 case KeyPress: name = "KeyPress"; break;
4130 case KeyRelease: name = "KeyRelease"; break;
4131 case ButtonPress: name = "ButtonPress"; break;
4132 case ButtonRelease: name = "ButtonRelease"; break;
4133 case MotionNotify: name = "MotionNotify"; break;
4134 case EnterNotify: name = "EnterNotify"; break;
4135 case LeaveNotify: name = "LeaveNotify"; break;
4136 case FocusIn: name = "FocusIn"; break;
4137 case FocusOut: name = "FocusOut"; break;
4138 case KeymapNotify: name = "KeymapNotify"; break;
4139 case Expose: name = "Expose"; break;
4140 case GraphicsExpose: name = "GraphicsExpose"; break;
4141 case NoExpose: name = "NoExpose"; break;
4142 case VisibilityNotify: name = "VisibilityNotify"; break;
4143 case CreateNotify: name = "CreateNotify"; break;
4144 case DestroyNotify: name = "DestroyNotify"; break;
4145 case UnmapNotify: name = "UnmapNotify"; break;
4146 case MapNotify: name = "MapNotify"; break;
4147 case MapRequest: name = "MapRequest"; break;
4148 case ReparentNotify: name = "ReparentNotify"; break;
4149 case ConfigureNotify: name = "ConfigureNotify"; break;
4150 case ConfigureRequest: name = "ConfigureRequest"; break;
4151 case GravityNotify: name = "GravityNotify"; break;
4152 case ResizeRequest: name = "ResizeRequest"; break;
4153 case CirculateNotify: name = "CirculateNotify"; break;
4154 case CirculateRequest: name = "CirculateRequest"; break;
4155 case PropertyNotify: name = "PropertyNotify"; break;
4156 case SelectionClear: name = "SelectionClear"; break;
4157 case SelectionRequest: name = "SelectionRequest"; break;
4158 case SelectionNotify: name = "SelectionNotify"; break;
4159 case ColormapNotify: name = "ColormapNotify"; break;
4160 case ClientMessage: name = "ClientMessage"; break;
4161 case MappingNotify: name = "MappingNotify"; break;
4165 printf ("event: %s, %d remaining\n", name, QLength(dpy));
4167 printf ("unknown event %d, %d remaining\n", e->type, QLength(dpy));