One more check on valid display which is known to be in the startup
[xcircuit.git] / Xw / Manager.c
blob00bd0c1d3c19a585dc4721fff32ef0b24f6375cf
1 /*************************************<+>*************************************
2 *****************************************************************************
3 **
4 ** File: Manager.c
5 **
6 ** Project: X Widgets
7 **
8 ** Description: This file contains source for the Manager Meta Widget.
9 **
10 *****************************************************************************
11 **
12 ** Copyright (c) 1988 by Hewlett-Packard Company
13 ** Copyright (c) 1988 by the Massachusetts Institute of Technology
14 **
15 ** Permission to use, copy, modify, and distribute this software
16 ** and its documentation for any purpose and without fee is hereby
17 ** granted, provided that the above copyright notice appear in all
18 ** copies and that both that copyright notice and this permission
19 ** notice appear in supporting documentation, and that the names of
20 ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
21 ** pertaining to distribution of the software without specific, written
22 ** prior permission.
23 **
24 *****************************************************************************
25 *************************************<+>*************************************/
27 #include <stdio.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <X11/IntrinsicP.h>
31 #include <X11/Intrinsic.h>
32 #include <X11/Shell.h>
33 #include <Xw/Xw.h>
34 #include <Xw/XwP.h>
35 #include <X11/StringDefs.h>
37 static Boolean XwFocusIsHere();
38 static void MgrDestroy();
39 static void MgrClassPartInit();
40 static void ClassInitialize();
41 static void Initialize();
42 static Boolean SetValues();
46 /*************************************<->*************************************
48 * Default translations for all subclasses of Manager
49 * -----------
50 * Note, if a manager subclass has additional translations it
51 * will have to duplicate this set as well.
52 *************************************<->***********************************/
54 static char defaultTranslations[] =
55 "<EnterWindow>: enter() \n\
56 <LeaveWindow>: leave() \n\
57 <Visible>: visible() \n\
58 <FocusIn>: focusIn()";
62 /*************************************<->*************************************
64 * Default actions for all subclasses of Manager
65 * -----------
67 *************************************<->***********************************/
69 static XtActionsRec actionsList[] =
71 {"enter", (XtActionProc) _XwManagerEnter},
72 {"leave", (XtActionProc) _XwManagerLeave},
73 {"focusIn", (XtActionProc) _XwManagerFocusIn},
74 {"visible", (XtActionProc) _XwManagerVisibility},
78 * Resource definitions for Subclasses of Manager
81 static XtResource resources[] =
84 XtNforeground, XtCForeground, XtRPixel, sizeof (Pixel),
85 XtOffset (XwManagerWidget, manager.foreground),
86 XtRString, "XtDefaultForeground"
90 XtNbackgroundTile, XtCBackgroundTile, XtRTileType, sizeof (int),
91 XtOffset (XwManagerWidget, manager.background_tile),
92 XtRString, "background"
96 XtNhighlightThickness, XtCHighlightThickness, XtRInt, sizeof (int),
97 XtOffset (XwManagerWidget, manager.highlight_thickness),
98 XtRString, "0"
102 XtNtraversalOn, XtCTraversalOn, XtRBoolean, sizeof (Boolean),
103 XtOffset (XwManagerWidget, manager.traversal_on),
104 XtRString, "False"
108 XtNlayout, XtCLayout, XtRLayout, sizeof(int),
109 XtOffset(XwManagerWidget, manager.layout),
110 XtRString, "minimize"
114 XtNnextTop, XtCCallback, XtRCallback, sizeof(caddr_t),
115 XtOffset (XwManagerWidget, manager.next_top),
116 XtRPointer, (caddr_t) NULL
122 /******************************************************************
123 * The Manager class record definition
124 ******************************************************************/
126 XwManagerClassRec XwmanagerClassRec =
129 (WidgetClass) &constraintClassRec, /* superclass */
130 "XwManager", /* class_name */
131 sizeof(XwManagerRec), /* widget_size */
132 ClassInitialize, /* class_initialize */
133 MgrClassPartInit, /* class part initialize */
134 FALSE, /* class_inited */
135 Initialize, /* initialize */
136 NULL, /* initialize hook */
137 NULL, /* realize */
138 actionsList, /* actions */
139 XtNumber(actionsList), /* num_actions */
140 resources, /* resources */
141 XtNumber(resources), /* num_resources */
142 NULLQUARK, /* xrm_class */
143 TRUE, /* compress_motion */
144 TRUE, /* compress_exposure */
145 TRUE, /* compress enterleave */
146 FALSE, /* visible_interest */
147 MgrDestroy, /* destroy */
148 NULL, /* resize */
149 NULL, /* expose */
150 SetValues, /* set_values */
151 NULL, /* set_values_hook */
152 XtInheritSetValuesAlmost, /* set_values_almost */
153 NULL, /* get_values_hook */
154 NULL, /* accept_focus */
155 XtVersion, /* version */
156 NULL, /* callback private */
157 NULL, /* tm_table */
158 NULL, /* query geometry */
159 /* display_accelerator */ XtInheritDisplayAccelerator,
160 /* extension */ NULL
162 { /* Composite class */
163 NULL, /* Geometry Manager */
164 NULL, /* Change Managed */
165 _XwManagerInsertChild, /* Insert Child */
166 XtInheritDeleteChild, /* Delete Child */
167 NULL,
170 { /* constraint class fields */
171 NULL,
174 NULL,
175 NULL,
176 NULL,
177 NULL,
181 (XwTraversalProc) mgr_traversal, /* Mgr class traversal handler */
182 NULL, /* default translations */
186 WidgetClass XwmanagerWidgetClass = (WidgetClass) &XwmanagerClassRec;
190 /************************************************************************
192 * ClassInitialize
193 * Initialize the manager class structure. This is called only the
194 * first time a manager widget is created.
197 * After class init, the "translations" variable will contain the compiled
198 * translations to be used to augment a widget's translation
199 * table if they wish to have keyboard traversal on.
201 ************************************************************************/
203 static void ClassInitialize()
205 XwRegisterConverters(); /* Register Library Conversion Rtnes */
207 XwmanagerClassRec.manager_class.translations =
208 XtParseTranslationTable(defaultTranslations);
212 /************************************************************************
214 * MgrClassPartInit
216 * Used by subclasses of manager to inherit class record procedures.
218 ************************************************************************/
220 static void MgrClassPartInit(w)
221 WidgetClass w;
224 XwManagerWidgetClass mw= (XwManagerWidgetClass) w;
226 if (mw->manager_class.traversal_handler == XtInheritTraversalProc)
227 mw->manager_class.traversal_handler = (XwTraversalProc) mgr_traversal;
235 /************************************************************************
237 * Initialize
238 * The main widget instance initialization routine.
240 ************************************************************************/
242 static void Initialize (request, new)
243 Widget request, new;
245 XwManagerWidget mw = (XwManagerWidget) new;
246 Arg args[1];
249 if ((mw->manager.layout < XwIGNORE) || (mw->manager.layout > XwSWINDOW))
251 mw->manager.layout = XwMINIMIZE;
252 XtWarning("Manager: Invalid layout setting.");
256 mw -> manager.managed_children = (WidgetList) XtMalloc
257 (XwBLOCK * sizeof(Widget));
258 mw -> manager.num_slots = XwBLOCK;
259 mw -> manager.num_managed_children = 0;
260 mw -> manager.active_child = NULL;
262 mw -> composite.children = (WidgetList) XtMalloc
263 (XwBLOCK * sizeof(Widget));
264 mw -> composite.num_slots = XwBLOCK;
265 mw -> composite.num_children = 0;
266 /* mw -> composite.num_mapped_children = 0; for R3 */
268 mw -> composite.insert_position = (XtOrderProc) _XwInsertOrder;
271 /* Verify the highlight and tiling resources */
273 if (mw -> manager.background_tile != XwBACKGROUND)
275 XtWarning("Manager: Incorrect background tile.");
276 mw -> manager.background_tile = XwBACKGROUND;
280 /* If this widget is requesting traversal then augment its
281 * translation table with some additional events.
283 if (mw->manager.traversal_on == True)
285 XtAugmentTranslations((Widget) mw,
286 XwmanagerClassRec.manager_class.translations);
287 mw->core.widget_class->core_class.visible_interest = True;
296 /*********************************************************************
298 * _XwManagerInsertChild
300 ********************************************************************/
302 /* ARGSUSED */
303 void _XwManagerInsertChild(w)
304 Widget w;
306 Cardinal position;
307 Cardinal i;
308 CompositeWidget cw;
310 cw = (CompositeWidget) w->core.parent;
311 if (cw -> composite.insert_position != NULL)
312 position = (*cw->composite.insert_position)((Widget)cw);
313 else
314 position = cw->composite.num_children;
317 /*************************************************
318 * Allocate another block of space if needed
319 *************************************************/
320 if ((cw -> composite.num_children + 1) >
321 cw -> composite.num_slots)
323 cw -> composite.num_slots += XwBLOCK;
324 cw -> composite.children = (WidgetList)
325 XtRealloc ((caddr_t) cw -> composite.children,
326 (cw -> composite.num_slots * sizeof(Widget)));
330 /********************************************************
331 * Ripple children up one space from "position"
332 *********************************************************/
334 for (i = cw->composite.num_children; i > position; i--) {
335 cw->composite.children[i] = cw->composite.children[i-1];
337 cw->composite.children[position] = w;
338 cw->composite.num_children++;
342 /***************************************************************************
344 * Cardinal
345 * _XwInsertOrder (cw)
347 ************************************************************************/
349 Cardinal _XwInsertOrder (cw)
351 CompositeWidget cw; /* Composite widget being inserted into */
353 Cardinal position = cw->composite.num_children;
355 return (position);
358 /**********************************************************************
360 * _XwReManageChildren
362 * This procedure will be called by the ChangeManged procedure of
363 * each manager. It will reassemble the currently managed children
364 * into the "manager.managed_children" list.
366 ********************************************************************/
367 void _XwReManageChildren(mw)
368 XwManagerWidget mw;
370 int i;
372 /* Put "managed children" info together again */
374 mw -> manager.num_managed_children = 0;
375 for (i=0; i < mw->composite.num_children; i++)
377 if (mw -> composite.children[i]->core.managed)
379 if ((mw -> manager.num_managed_children + 1) >
380 mw -> manager.num_slots)
382 mw -> manager.num_slots += XwBLOCK;
383 mw -> manager.managed_children = (WidgetList)
384 XtRealloc ((caddr_t) mw -> manager.managed_children,
385 (mw -> manager.num_slots * sizeof(Widget)));
387 mw -> manager.managed_children
388 [mw -> manager.num_managed_children++] =
389 mw -> composite.children[i];
395 /************************************************************************
397 * SetValues
398 * Perform and updating necessary for a set values call.
400 ************************************************************************/
402 static Boolean SetValues (current, request, new, last)
403 Widget current, request, new;
404 Boolean last;
407 Boolean returnFlag = False;
408 Boolean tempTrav, tempVisible, tempSensitive;
409 Boolean tempAnSensitive, tempMapped;
410 XwManagerWidget curmw = (XwManagerWidget) current;
411 XwManagerWidget reqmw = (XwManagerWidget) request;
412 XwManagerWidget newmw = (XwManagerWidget) new;
413 Widget tempoldActive, old_active;
414 XwManagerWidget parent;
415 Boolean traversalIsHere = False;
416 Boolean parentIsMgr = False;
419 /* Verify correct new values. */
421 if (newmw -> manager.traversal_on != True &&
422 newmw -> manager.traversal_on != False)
423 newmw -> manager.traversal_on = curmw -> manager.traversal_on;
426 /* Process the change in values */
428 if ((curmw->core.mapped_when_managed != newmw->core.mapped_when_managed) ||
429 (curmw->core.sensitive != newmw->core.sensitive) ||
430 (curmw->core.ancestor_sensitive != newmw->core.ancestor_sensitive) ||
431 (curmw->core.visible != newmw-> core.visible) ||
432 (curmw->manager.traversal_on != newmw->manager.traversal_on))
434 returnFlag = TRUE;
435 if (XwFocusIsHere(curmw))
437 tempTrav= curmw->manager.traversal_on;
438 tempVisible = curmw->core.visible;
439 tempSensitive = curmw->core.sensitive;
440 tempAnSensitive = curmw->core.ancestor_sensitive;
441 tempMapped = curmw->core.mapped_when_managed;
443 curmw->manager.traversal_on = newmw->manager.traversal_on;
444 curmw->core.ancestor_sensitive = newmw->core.ancestor_sensitive;
445 curmw->core.sensitive = newmw->core.sensitive;
446 curmw->core.visible = newmw->core.visible;
447 curmw->core.mapped_when_managed = newmw->core.mapped_when_managed;
449 XwProcessTraversal (curmw, XwTRAVERSE_HOME, FALSE);
451 curmw->manager.traversal_on = tempTrav;
452 curmw->core.visible = tempVisible;
453 curmw->core.sensitive = tempSensitive;
454 curmw->core.ancestor_sensitive = tempAnSensitive;
455 curmw->core.mapped_when_managed = tempMapped;
457 else
459 traversalIsHere = False;
460 parentIsMgr = False;
462 /* There are special cases if we are the highest Xw mgr widget */
463 if (XtIsSubclass((Widget)(parent = (XwManagerWidget)XtParent(newmw)),
464 XwmanagerWidgetClass))
466 parentIsMgr = True;
467 if (parent->manager.active_child == (Widget)curmw)
468 traversalIsHere = True;
470 else if (newmw->manager.active_child)
471 traversalIsHere = True;
473 if (traversalIsHere)
475 /* Clear the active child path, from us down */
476 old_active = newmw->manager.active_child;
477 newmw->manager.active_child = NULL;
478 if (parentIsMgr)
479 parent->manager.active_child = NULL;
480 while (old_active != NULL)
482 if (!XtIsSubclass(old_active, XwmanagerWidgetClass))
483 old_active = NULL;
484 else
486 tempoldActive = ((XwManagerWidget)old_active)->manager.
487 active_child;
488 ((XwManagerWidget)old_active)->manager.active_child = NULL;
489 old_active = tempoldActive;
493 /* Find the top most manager */
494 if (parentIsMgr)
496 while ((parent->core.parent != NULL) &&
497 (XtIsSubclass(parent->core.parent, XwmanagerWidgetClass)))
498 parent = (XwManagerWidget)parent->core.parent;
500 else
501 parent = curmw;
503 /* Clear the toolkit kbd focus */
504 XtSetKeyboardFocus((Widget)parent, NULL);
510 if (newmw->manager.layout != curmw->manager.layout)
512 if ((newmw->manager.layout < XwIGNORE) ||
513 (newmw->manager.layout > XwSWINDOW))
515 newmw->manager.layout = curmw->manager.layout;
516 XtWarning("Manager: Invalid layout setting.");
518 else returnFlag = True;
522 if (newmw -> manager.highlight_thickness < 0)
524 XtWarning ("Manager: Invalid highlight thickness.");
525 newmw -> manager.highlight_thickness =
526 curmw -> manager.highlight_thickness;
530 if (newmw -> manager.background_tile != XwBACKGROUND)
532 XtWarning("Manager: Incorrect background tile.");
533 newmw -> manager.background_tile =
534 curmw -> manager.background_tile;
537 /* Set the widget's background tile */
539 if (newmw -> manager.background_tile !=
540 curmw -> manager.background_tile ||
541 newmw -> manager.foreground !=
542 curmw -> manager.foreground ||
543 newmw -> core.background_pixel !=
544 curmw -> core.background_pixel)
546 Mask valueMask;
547 XSetWindowAttributes attributes;
549 if (newmw -> manager.background_tile == XwFOREGROUND)
551 valueMask = CWBackPixel;
552 attributes.background_pixel = newmw -> manager.foreground;
554 else
556 valueMask = CWBackPixel;
557 attributes.background_pixel = newmw -> core.background_pixel;
560 if (XtIsRealized ((Widget)newmw))
561 XChangeWindowAttributes (XtDisplay(newmw), newmw -> core.window,
562 valueMask, &attributes);
564 returnFlag = TRUE;
568 /* Check the geometry in relationship to the highlight thickness */
570 if ((request -> core.width == 0) && (current -> core.width == 0))
571 newmw -> core.width += newmw -> manager.highlight_thickness * 2;
573 if ((request -> core.height == 0) && (current -> core.height == 0))
574 newmw -> core.height += newmw -> manager.highlight_thickness * 2;
577 /* If this widget is requesting traversal then augment its
578 * translation table with some additional events.
580 if ((newmw->manager.traversal_on != curmw->manager.traversal_on) &&
581 (newmw->manager.traversal_on == True))
583 /* XXX this was a hard bug! where were the XXX's?
585 * In R2 we could not pass newmw to this toolkit call! But I
586 * have found the bug!!!! In R2 it was a temporary structure (stack)
587 * but now curmw is the temporary one and newmw is real!
588 * I can see why they were worried before. Now there is no worry.
589 * Go ahead and pass newmw!
591 XtAugmentTranslations((Widget) newmw,
592 XwmanagerClassRec.manager_class.translations);
593 newmw->core.widget_class->core_class.visible_interest = True;
598 /* Return flag to indicate if redraw is needed. */
600 return (returnFlag);
605 /************************************************************************
607 * Enter, FocusIn and Leave Window procs
609 * These two procedures handle traversal activation and deactivation
610 * for manager widgets. They are invoked directly throught the
611 * the action table of a widget.
613 ************************************************************************/
615 void _XwManagerEnter (mw, event)
616 XwManagerWidget mw;
617 XEvent * event;
620 XPoint ul,lr;
622 ul.x = ul.y = lr.x = lr.y = 0;
624 /* Only the top level manager should invoke a traversal handler*/
625 if (!XtIsSubclass (mw -> core.parent, XwmanagerWidgetClass))
628 * All external entry points into the traversal code must take
629 * care of initializing the traversal list.
631 _XwInitCheckList();
633 (*(((XwManagerWidgetClass) mw -> core.widget_class) ->
634 manager_class.traversal_handler))
635 ((Widget)mw, ul, lr, XwTRAVERSE_CURRENT);
638 return;
643 void _XwManagerFocusIn (mw, event)
644 XwManagerWidget mw;
645 XEvent * event;
648 _XwManagerEnter (mw, event);
649 return;
653 void _XwManagerLeave (mw, event)
654 XwManagerWidget mw;
655 XEvent * event;
658 XwManagerWidget tw;
660 /* if my parent is NOT a subclass of XwManager then I will assume
661 that I have left the traversal hierarchy. For the time being
662 I will set the focus back to pointer root--I should not have to
663 do this if the window manager people can come to an agreement
664 on conventions for focus change.
666 if (!XtIsSubclass (mw -> core.parent, XwmanagerWidgetClass))
667 XSetInputFocus (XtDisplay (mw->core.parent),
668 PointerRoot, RevertToNone, CurrentTime);
674 /************************************************************************
676 * Find a Traversable Primitive
677 * This functions is used by manager widget's traversal handlers
678 * to determine if there is a primitive in their hierarchy which
679 * can be traversed to.
681 ************************************************************************/
683 Boolean _XwFindTraversablePrim (cw)
684 CompositeWidget cw;
687 register int i;
688 WidgetList wList;
689 Widget w;
691 wList = cw -> composite.children;
693 for (i = 0; i < cw -> composite.num_children; i++)
695 w = *wList++;
697 if (XtIsSubclass(w, XwmanagerWidgetClass) &&
698 ((((XwManagerWidget)w)->manager.traversal_on == False) ||
699 (w->core.visible == FALSE)))
701 continue;
704 if (XtIsSubclass (w, compositeWidgetClass) && w -> core.managed == True)
706 if (_XwFindTraversablePrim ((CompositeWidget) w))
708 return (True);
712 else if (XtIsSubclass (w, XwprimitiveWidgetClass))
714 if (w -> core.sensitive == True &&
715 w -> core.ancestor_sensitive == True &&
716 w -> core.visible == True &&
717 w -> core.managed == True &&
718 w -> core.mapped_when_managed == True &&
719 w -> core.being_destroyed == False &&
720 ((XwPrimitiveWidget) w)->primitive.traversal_type ==
721 XwHIGHLIGHT_TRAVERSAL)
724 return (True);
728 else /* Check for non - primitive class primitives?? */
733 return (False);
737 /*************************************<->*************************************
739 * Boolean
740 * XwTestTraversability(widget, widgetType)
742 * Description:
743 * -----------
744 * xxxxxxxxxxxxxxxxxxxxxxx
747 * Inputs:
748 * ------
749 * xxxxxxxxxxxx = xxxxxxxxxxxxx
751 * Outputs:
752 * -------
753 * xxxxxxxxxxxx = xxxxxxxxxxxxx
755 * Procedures Called
756 * -----------------
758 *************************************<->***********************************/
760 Boolean XwTestTraversability(widget, widgetType)
761 Widget widget;
762 int * widgetType;
764 Boolean returnFlag=FALSE;
766 if (XtIsSubclass (widget, XwprimitiveWidgetClass))
768 *widgetType = XwPRIMITIVE;
769 if (((XwPrimitiveWidget) widget)->primitive.traversal_type ==
770 XwHIGHLIGHT_TRAVERSAL)
771 returnFlag = TRUE;
773 else
774 if (XtIsSubclass (widget, XwmanagerWidgetClass))
776 *widgetType = XwMANAGER;
777 if (((XwManagerWidget)widget) -> manager.traversal_on)
778 returnFlag = TRUE;
780 else
781 *widgetType = 0;
784 if (widget-> core.sensitive != True ||
785 widget-> core.ancestor_sensitive != True ||
786 widget-> core.visible != True ||
787 widget-> core.managed != True ||
788 widget-> core.mapped_when_managed != True ||
789 widget-> core.being_destroyed == True)
791 returnFlag = FALSE;
794 return(returnFlag);
798 static Boolean XwFocusIsHere(mw)
800 XwManagerWidget mw;
802 while (1)
804 if (mw->manager.active_child == NULL) return(FALSE);
805 if (XtIsSubclass(mw->manager.active_child, XwmanagerWidgetClass))
806 mw= (XwManagerWidget)mw->manager.active_child;
807 else
808 if (XtIsSubclass(mw->manager.active_child, XwprimitiveWidgetClass))
810 if (((XwPrimitiveWidget)mw->manager.active_child)
811 ->primitive.I_have_traversal) return(TRUE);
812 else return(FALSE);
818 /*************************************<->*************************************
820 * MgrDestroy (w)
822 * Description:
823 * -----------
824 * Free up space allocated to track managed children.
826 * Inputs:
827 * ------
828 * w = manager subclass to be destroyed.
831 *************************************<->***********************************/
833 static void MgrDestroy(w)
834 XwManagerWidget w;
836 XwManagerWidget parent;
839 * If we are in the traversal focus path, then we need to clean
840 * things up.
842 if (XwFocusIsHere(w))
843 XwProcessTraversal(w, XwTRAVERSE_HOME, FALSE);
844 else if ((XtIsSubclass((Widget)(parent = (XwManagerWidget)XtParent(w)),
845 XwmanagerWidgetClass)) &&
846 (parent->manager.active_child == (Widget)w))
848 parent->manager.active_child = NULL;
850 XtRemoveCallbacks ((Widget)w, XtNnextTop, w -> manager.next_top);
851 XtFree((char *) w->manager.managed_children);
855 /************************************************************************
857 * Visibility
858 * Track whether a widget is visible.
860 ***********************************************************************/
861 void _XwManagerVisibility (mw, event)
862 XwManagerWidget mw;
863 XEvent * event;
865 XVisibilityEvent * vEvent = (XVisibilityEvent *)event;
867 if (vEvent->state == VisibilityFullyObscured)
869 mw->core.visible = False;
870 if (XwFocusIsHere(mw))
871 XwProcessTraversal (mw, XwTRAVERSE_HOME, FALSE);
873 else
874 mw->core.visible = True;
880 /************************************************************************
882 * Unmap
883 * Track whether a widget is visible.
885 ***********************************************************************/
886 void _XwManagerUnmap (mw, event)
887 XwManagerWidget mw;
888 XEvent * event;
890 mw->core.visible = False;
891 if (XwFocusIsHere(mw))
892 XwProcessTraversal (mw, XwTRAVERSE_HOME, FALSE);