2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * (c) Copyright 1989, 1990, 1991, 1992, 1993, 1994 OPEN SOFTWARE FOUNDATION, INC.
32 static char rcsid[] = "$TOG: WmInitWs.c /main/18 1999/09/20 15:18:22 mgreess $"
36 * (c) Copyright 1987, 1988, 1989, 1990, 1993, 1994 HEWLETT-PACKARD COMPANY
37 * (c) Copyright 1993, 1994 International Business Machines Corp.
38 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
39 * (c) Copyright 1993, 1994 Novell, Inc.
47 #include "WmResNames.h"
53 #define DTWM_NEED_FNTPL
54 #include "WmIBitmap.h"
58 #endif /* NO_OL_COMPAT */
60 #include <X11/cursorfont.h>
62 #include <X11/Shell.h>
64 #include <X11/keysym.h>
65 #ifndef NO_HP_KEY_REMAP
66 #include <Xm/VirtKeysP.h>
68 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
69 # include <Xm/DrawingA.h>
70 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
76 } str_xref_rec, *str_xref ;
77 #endif /* NO_HP_KEY_REMAP */
79 #include <Dt/GetDispRes.h>
80 #include <Dt/SessionP.h>
82 #include <Dt/Message.h>
86 /* Busy is also defined in the BMS -> bms.h. This conflicts with
87 * /usr/include/X11/Xasync.h on ibm.
94 #include <X11/Xlibint.h>
97 * include extern functions
100 #include "WmBackdrop.h"
102 #include "WmCDInfo.h"
103 #include "WmColormap.h"
106 #include "WmFeedback.h"
107 #include "WmFunction.h"
108 #include "WmIDecor.h"
112 #include "WmIPlace.h"
113 #include "WmIconBox.h"
114 #include "WmKeyFocus.h"
116 #include "WmPanelP.h" /* for typedef in WmManage.h */
117 #endif /* PANELIST */
118 #include "WmManage.h"
121 #include "WmPresence.h"
123 #include "WmProperty.h"
124 #include "WmResCvt.h"
125 #include "WmResource.h"
126 #include "WmSignal.h"
127 #include "WmProtocol.h"
128 #include "WmCDecor.h"
130 #include "WmResParse.h"
137 * Function Declarations:
140 #include "WmInitWs.h"
142 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
143 # include "WmWsmLib/wsm_proto.h"
144 # include "WmWsmLib/utm_send.h"
145 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
148 static void InsureDefaultBackdropDir(char **ppchBackdropDirs);
150 void InitWmDisplayEnv (void);
151 #ifndef NO_MESSAGE_CATALOG
152 void InitNlsStrings (void);
154 #ifndef NO_HP_KEY_REMAP
155 Boolean VirtKeys4DIN(Display *dpy);
156 #endif /* NO_HP_KEY_REMAP */
159 /* limited to 3 chars max */
160 #define UNSPECIFIED_SCREEN_NAME "fbk"
161 char **dpy2Argv; /* copy for second display */
164 WmScreenData *dtSD; /* for the "DT screen" of the display */
165 #endif /* PANELIST */
170 extern int firstTime;
171 #ifndef NO_MESSAGE_CATALOG
172 extern char * pWarningStringFile;
173 extern char * pWarningStringLine;
179 * Special case for a two button mouse; move the BMENU binding
180 * from Button3 to Button2. Fails for one-button mice.
183 InitMouseBinding(void)
185 wmGD.numMouseButtons = XGetPointerMapping(DISPLAY, (unsigned char *)0, 0);
187 if (wmGD.numMouseButtons < 3) {
188 wmGD.bMenuButton = Button2;
190 wmGD.bMenuButton = Button3;
194 /******************************<->*************************************
196 * BuildLockMaskSequence ()
198 * Set up the sequence of modifier masks to use to when grabbing
199 * key- and button-bindings. This sequence of masks is NULL
203 * wmGD.lockingModMask
206 * wmGD.pLockMaskSequence
209 *************************************<->***********************************/
211 BuildLockMaskSequence(void)
215 unsigned int thisbit;
223 * Count the bits to determine the number of elements in
224 * the mask sequence. The actual number of masks is
225 * 2^<bitcount> - 1. We're not interested in the case
226 * where there none of the mask bits are set.
228 mask = wmGD.lockingModMask;
239 num_masks = (0x1 << num_bits) - 1;
242 * Allocate the space for the mask sequence + terminator.
244 wmGD.pLockMaskSequence = (unsigned int *)
245 XtCalloc (num_masks+1, sizeof (unsigned int));
248 * Fill in the mask sequence
250 mask = wmGD.lockingModMask;
253 while (mask && thisbit)
256 while (!(thisbit & mask))
258 thisbit = thisbit << 1;
261 /* clear it from mask */
267 * Set it in the appropriate slots in the
268 * mask sequence. The start of the loop is
269 * funny because we skip the case of all the
272 run = (0x1 << bit-1); /* number of consecutive masks to set
274 bit_on = False; /* are we setting bits or not? */
276 for (j=0, k=run-1; j<num_masks; j++, k--)
288 if (bit_on) wmGD.pLockMaskSequence[j] |= thisbit;
294 /******************************<->*************************************
296 * SetupLockingModifierMask ()
298 * Set up the mask used to ignore locking modifier keys (e.g. Shift Lock)
299 * when processing key- and button-bindings.
301 * We want to try to ignore the set of locking modifers
302 * such as Shift Lock, Num Lock, Kana Lock, etc. This involves
303 * some amount of guessing since these things can be mapped
304 * onto any of the Mod1-Mod5 modifiers. The approach taken is to
305 * identify the mapping of the locking modifier keysyms to
306 * Mod1-Mod5 and build the set of masks needed to ignore them.
308 *************************************<->***********************************/
311 * This is the set of locking modifiers keysyms that might be
312 * bound to Mod1-Mod5. (Caps Lock is handled independently of
315 static KeySym pksLockingMods[] = {
322 #define NUM_LOCKING_MODS (sizeof(pksLockingMods)/sizeof(KeySym))
325 SetupLockingModifierMask(void)
327 int i, j, start_index;
328 XModifierKeymap *modifier_map = NULL;
329 static Modifiers mod_masks[] = { None, Mod1Mask, Mod2Mask,
330 Mod3Mask, Mod4Mask, Mod5Mask };
331 Display *dpy = wmGD.display;
332 int pkcLockingMods[NUM_LOCKING_MODS];
336 for (i=0; i<NUM_LOCKING_MODS; i++)
338 pkcLockingMods[i] = XKeysymToKeycode(dpy, pksLockingMods[i]);
342 * Start out with Caps lock and add others we discover.
344 wmGD.lockingModMask = LockMask;
346 modifier_map = XGetModifierMapping(dpy);
348 /* just check Mod1 through Mod5 */
349 start_index = modifier_map->max_keypermod * Mod1MapIndex;
351 for (i = start_index; i < modifier_map->max_keypermod * 8; i++) {
352 int this_mod = ((i - start_index) / modifier_map->max_keypermod) + 1;
354 kc = modifier_map->modifiermap[i];
357 for (j=0; j<NUM_LOCKING_MODS; j++)
359 if (pkcLockingMods[j] == kc)
361 wmGD.lockingModMask |= mod_masks[this_mod];
368 BuildLockMaskSequence();
370 if(modifier_map != NULL)
371 XFreeModifiermap(modifier_map);
375 /******************************<->*************************************
377 * MappingEventHandler (Widget, XtPointer, XEvent *, Boolean *)
379 * Catch and handle changes to the mapping of the modifier keys.
381 *************************************<->***********************************/
386 XtPointer client_data,
388 Boolean *cont_to_dispatch)
390 if(event->xany.type != MappingNotify ||
391 event->xmapping.request == MappingPointer)
394 if(event->xmapping.request == MappingModifier)
395 SetupLockingModifierMask();
399 /******************************<->*************************************
401 * InitWmGlobal (argc, argv, environ)
406 * This function initializes the workspace manager.
411 * argc = number of command line arguments (+1)
413 * argv = window manager command line arguments
415 * environ = window manager environment
420 * wmGD = (initialize the global data structure)
422 *************************************<->***********************************/
424 void InitWmGlobal (int argc, char *argv [], char *environ [])
426 XSetWindowAttributes sAttributes;
430 Boolean activeSet = False;
431 Boolean processedGlobalResources = False;
438 wmGD.errorFlag = False;
444 wmGD.iSlideUpsInProgress = 0;
448 SetupWmSignalHandlers (0); /* dummy paramater */
452 * Do (pre-toolkit) initialization:
455 wmGD.windowContextType = XUniqueContext ();
456 wmGD.screenContextType = XUniqueContext ();
458 wmGD.cmapWindowContextType = XUniqueContext ();
461 wmGD.mwmWindowContextType = XUniqueContext ();
464 /* copy argv (the XtInititalize changes the original) for use in restart */
466 CopyArgv (argc, argv);
468 wmGD.environ = environ;
471 wmGD.pWmPB = _DtWmParseNewBuf();
477 if ((wmGD.mwmName = (char*)strrchr (wmGD.argv[0], '/')) != NULL)
483 wmGD.mwmName = wmGD.argv[0];
488 res_class = WM_RESOURCE_CLASS;
492 res_class = DT_WM_RESOURCE_CLASS;
494 wmGD.statusColorServer = CSERVE_NOT_AVAILABLE;
497 res_class = WM_RESOURCE_CLASS;
500 wmGD.display = (Display *)NULL;
501 wmGD.topLevelW = (Widget)NULL;
504 * Do X Tookit initialization:
507 XtToolkitInitialize();
509 wmGD.mwmAppContext = XtCreateApplicationContext();
510 AddWmResourceConverters ();
511 wmGD.display = XtOpenDisplay (wmGD.mwmAppContext,
517 &argc, /* R5 changed from Cardinal to int*/
522 Warning(((char *)GETMESSAGE(40, 1, "Could not open display.")));
523 ExitWM (WM_ERROR_EXIT_VALUE);
526 #if defined(sun) && defined(ALLPLANES)
530 wmGD.allplanes = XAllPlanesQueryExtension(wmGD.display,
533 #endif /* defined(sun) && defined(ALLPLANES) */
536 * Setup error handling:
539 WmInitErrorHandler(wmGD.display);
542 * Initialize cursor size info and
543 * display the startup cursor.
550 ShowWaitState (TRUE);
553 * Initialize support for BMenu virtual mouse binding
557 * Set up the _MOTIF_BINDINGS property on the root window
558 * of screen 0. Must do this before we create shells.
561 ProcessMotifBindings ();
562 #ifndef NO_HP_KEY_REMAP
564 /* VirtKeys4DIN deals with a shortcoming in the OSF/Motif
565 * mechanism for selecting a virtual key binding table.
566 * When a client connects to a display, code inside of libXm
567 * gets the vendor identifier from the server and uses this
568 * identifier to select a default virtual key binding table
569 * from an internal list of possible tables (provided to
570 * OSF by vendors). A virtual key binding table maps OSF
571 * virtual keysyms to an "appropriate" set of X keysyms for
572 * a particular server vendor. The problem with this
573 * mechanism is that it only allows for a _single_ default
574 * virtual key binding table per server vendor. If a
575 * hardware vendor ships more than one distinct keyboard,
576 * then the single virtual key binding table selected for
577 * that server might not be appropriate for all keyboards.
578 * The HP migration from the "ITF" keyboard to the "PC-style"
579 * keyboard causes this problem to be exposed for Motif
580 * clients. The default HP virtual key binding table maps
581 * osfInsert and osfDelete to hpInsertChar and hpDeleteChar,
582 * respectively. But since hpInsertChar and hpDeleteChar
583 * are absent from the PC-style keyboard, HP servers with
584 * this keyboard do not generate key events that map to the
585 * important osfInsert and osfDelete virtual keys.
586 * The Motif 1.2 version of libXm installs (one or two)
587 * properties on the root window, these properties exporting
588 * the virtual key binding table to be used by all (subsequently
589 * connected) Motif clients. The VirtKeys4DIN routine attempts
590 * to ensure that the virtual key binding table exported by
591 * those properties does not include dependencies on keysyms
592 * that are not available in the server's current modmap.
593 * The routine accomplishes this by searching the keyboard
594 * mapping of the display for the absence of known problematic
595 * keysyms. For those keysyms that are missing from the
596 * keyboard map, the corresponding dependencies in the
597 * virtual key binding table are altered to use pre-determined
598 * substitutes (which are generic X keysyms that are present
599 * on the PC-style keyboard mapping).
600 * The side-effects of this routine are that if there are no
601 * key binding properties on the root window when this routine
602 * is called, there will be a property installed (this occurs
603 * with all Motif 1.2 clients anyway). Since the virtual key
604 * binding table is only altered if it contains a keysym that
605 * is missing from the server's keyboard mapping, there is
606 * little chance of deleterious effects.
608 VirtKeys4DIN(DISPLAY);
609 #endif /* NO_HP_KEY_REMAP */
612 XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
613 XtSetArg (args[argnum], XtNx, 10000); argnum++;
614 XtSetArg (args[argnum], XtNy, 0); argnum++;
615 XtSetArg (args[argnum], XtNwidth, 10); argnum++;
616 XtSetArg (args[argnum], XtNheight, 10); argnum++;
617 XtSetArg (args[argnum], XtNmappedWhenManaged, False); argnum++;
618 XtSetArg (args[argnum], XtNjoinSession, True); argnum++;
620 XtSetArg (args[argnum], XtNrestartStyle, SmRestartNever); argnum++;
622 XtSetArg (args[argnum], XtNrestartStyle, SmRestartIfRunning); argnum++;
624 XtSetArg (args[argnum], XtNargc, savedArgc); argnum++;
625 XtSetArg (args[argnum], XtNargv, wmGD.argv); argnum++;
627 /* create topmost shell (application shell) */
628 wmGD.topLevelW = XtAppCreateShell (NULL,
630 sessionShellWidgetClass,
636 _XmColorObjCreate ( wmGD.topLevelW, NULL, NULL);
637 _XmColorObjCreate ( wmGD.topLevelW, NULL, NULL);
640 XtAddEventHandler(wmGD.topLevelW, NoEventMask, True,
641 MappingEventHandler, NULL);
643 /* Add callbacks used for communication with Session Manager. */
646 /* allocate namespace for screens */
650 * Determine the screen management policy (all or none)
651 * Process command line arguments that we handle
652 * This could change the number of screens we manage
654 ProcessGlobalScreenResources ();
655 ProcessCommandLine (argc, argv);
659 * Make sure backdrops are in our icon search path.
660 * This call MUST occur before ANY icons are looked up either
661 * explicitly or through resource processing!!!
662 * Uses variables set by ProcessGlobalScreenResources and
663 * ProcessCommandLine.
668 Boolean useMultiColorIcons;
669 Boolean useIconFileCacheRtn;
672 sNum = (wmGD.numScreens == 1) ? DefaultScreen(DISPLAY) : 0;
674 XmeGetIconControlInfo(ScreenOfDisplay(DISPLAY, sNum), &useMaskRtn,
675 &useMultiColorIcons, &useIconFileCacheRtn);
677 sBdPath = wmGD.backdropDirs;
678 InsureDefaultBackdropDir ((char **) &sBdPath);
680 _DtWsmSetBackdropSearchPath(XScreenOfDisplay(DISPLAY, sNum),
681 sBdPath, useMultiColorIcons);
688 * Allocate data and initialize for screens we manage:
691 if (!(wmGD.Screens = (WmScreenData *)
692 XtCalloc (wmGD.numScreens, sizeof(WmScreenData))))
694 ShowWaitState (FALSE);
695 Warning (((char *)GETMESSAGE(40, 2, "Insufficient memory for Screen data")));
696 ExitWM (WM_ERROR_EXIT_VALUE);
701 sAttributes.event_mask = SubstructureRedirectMask;
703 for (scr=0; scr<wmGD.numScreens; scr++)
708 * Gain control of the root windows of each screen:
711 sNum = (wmGD.numScreens == 1) ? DefaultScreen(DISPLAY) : scr;
712 wmGD.errorFlag = False;
714 XChangeWindowAttributes (DISPLAY, RootWindow (DISPLAY, sNum),
715 CWEventMask, &sAttributes);
717 * Do XSync to force server action and catch errors
720 XSync (DISPLAY, False /* do not discard events */);
722 if ((wmGD.errorFlag) &&
723 (RootWindow (DISPLAY, sNum) == (Window) wmGD.errorResource) &&
724 (wmGD.errorRequestCode == X_ChangeWindowAttributes))
727 ((char *)GETMESSAGE(40, 3, "Another window manager is running on screen %d")), sNum);
728 Warning ((char *) &pch[0]);
729 wmGD.Screens[scr].managed = False;
733 if (!processedGlobalResources)
737 XA_DT_SESSION_HINTS, XA_DT_SM_WM_PROTOCOL,
738 XA_DT_SM_START_ACK_WINDOWS, XA_DT_SM_STOP_ACK_WINDOWS,
739 XA_DT_WM_WINDOW_ACK, XA_DT_WM_EXIT_SESSION,
740 XA_DT_WM_LOCK_DISPLAY, XA_DT_WM_READY, NUM_ATOMS };
741 static char *atom_names[] = {
742 _XA_DT_SESSION_HINTS, _XA_DT_SM_WM_PROTOCOL,
743 _XA_DT_SM_START_ACK_WINDOWS, _XA_DT_SM_STOP_ACK_WINDOWS,
744 _XA_DT_WM_WINDOW_ACK, _XA_DT_WM_EXIT_SESSION,
745 _XA_DT_WM_LOCK_DISPLAY, _XA_DT_WM_READY };
747 Atom atoms[XtNumber(atom_names)];
748 XInternAtoms(DISPLAY, atom_names, XtNumber(atom_names),
751 wmGD.xa_DT_SESSION_HINTS = atoms[XA_DT_SESSION_HINTS];
752 wmGD.xa_DT_SM_WM_PROTOCOL = atoms[XA_DT_SM_WM_PROTOCOL];
753 wmGD.xa_DT_SM_START_ACK_WINDOWS =
754 atoms[XA_DT_SM_START_ACK_WINDOWS];
755 wmGD.xa_DT_SM_STOP_ACK_WINDOWS =
756 atoms[XA_DT_SM_STOP_ACK_WINDOWS];
757 wmGD.xa_DT_WM_WINDOW_ACK = atoms[XA_DT_WM_WINDOW_ACK];
758 wmGD.xa_DT_WM_EXIT_SESSION = atoms[XA_DT_WM_EXIT_SESSION];
759 wmGD.xa_DT_WM_LOCK_DISPLAY = atoms[XA_DT_WM_LOCK_DISPLAY];
760 wmGD.xa_DT_WM_READY = atoms[XA_DT_WM_READY];
764 #endif /* NO_OL_COMPAT */
766 wmGD.hasShape = XShapeQueryExtension (DISPLAY,
767 &wmGD.shapeEventBase,
768 &wmGD.shapeErrorBase);
769 #endif /* NO_SHAPE */
771 wmGD.replayEnterEvent = False;
772 wmGD.menuActive = NULL;
773 wmGD.menuUnpostKeySpec = NULL;
774 wmGD.F_NextKeySpec = NULL;
775 wmGD.F_PrevKeySpec = NULL;
776 wmGD.passKeysActive = False;
777 wmGD.passKeysKeySpec = NULL;
778 wmGD.checkHotspot = False;
779 wmGD.configAction = NO_ACTION;
780 wmGD.configPart = FRAME_NONE;
781 wmGD.configSet = False;
782 wmGD.preMove = False;
783 wmGD.gadgetClient = NULL;
784 wmGD.wmTimers = NULL;
785 wmGD.clientDefaultTitle =
786 XmStringCreateLocalized(DEFAULT_CLIENT_TITLE);
787 wmGD.iconDefaultTitle =
788 XmStringCreateLocalized(DEFAULT_ICON_TITLE);
789 wmGD.attributesWindow = (Window)NULL;
790 wmGD.clickData.pCD = NULL;
791 wmGD.clickData.clickPending = False;
792 wmGD.clickData.doubleClickPending = False;
793 wmGD.systemModalActive = False;
794 wmGD.activeIconTextDisplayed = False;
795 wmGD.movingIcon = False;
796 wmGD.queryScreen = True;
797 wmGD.dataType = GLOBAL_DATA_TYPE;
799 wmGD.pLockMaskSequence = NULL;
800 SetupLockingModifierMask ();
802 wmGD.requestContextWin = (Window) 0L;
803 wmGD.cppCommand = NULL;
804 wmGD.evLastButton.button = 0;
805 wmGD.bReplayedButton = False;
806 wmGD.bSuspendSecondaryRestack = False;
808 * Get a second display connection for
809 * internal WM windows.
811 wmGD.display1 = XtOpenDisplay (wmGD.mwmAppContext,
821 ShowWaitState (FALSE);
822 Warning(((char *)GETMESSAGE(40, 4, "Could not open second display connection.")));
823 ExitWM (WM_ERROR_EXIT_VALUE);
826 _DtGetSmWindow(DISPLAY,
827 RootWindow(DISPLAY, 0),
831 * If this is the first screen we've managed,
832 * tell the session manager we're ready
834 if (!processedGlobalResources)
836 SendClientMsg( wmGD.dtSmWindow,
837 (long) wmGD.xa_DT_SM_WM_PROTOCOL,
838 (long) wmGD.xa_DT_WM_READY,
839 CurrentTime, NULL, 0);
841 #endif /* PANACOMM */
843 /* create topmost shell (application shell) */
845 XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
846 XtSetArg (args[argnum], XtNx, 10000); argnum++;
847 XtSetArg (args[argnum], XtNy, 0); argnum++;
848 XtSetArg (args[argnum], XtNwidth, 10); argnum++;
849 XtSetArg (args[argnum], XtNheight, 10); argnum++;
850 XtSetArg (args[argnum],
851 XtNmappedWhenManaged, False); argnum++;
854 XtAppCreateShell (NULL,
856 applicationShellWidgetClass,
865 * if this is the first screen we can manage,
869 processedGlobalResources = True;
872 * Get the _MOTIF_WM_INFO property and determine
873 * the startup / restart state.
876 ProcessMotifWmInfo (RootWindow (DISPLAY, sNum));
879 * Process global window manager resources:
881 #ifndef NO_MESSAGE_CATALOG
882 InitBuiltinSystemMenu();
885 ProcessWmResources ();
889 InitWmScreen (&(wmGD.Screens[scr]), sNum);
890 wmGD.Screens[scr].managed = True;
893 GetDtSessionHints(&(wmGD.Screens[scr]), sNum);
899 ACTIVE_PSD = &wmGD.Screens[scr];
907 * No screens for me to manage, give up.
909 ShowWaitState (FALSE);
910 Warning (((char *)GETMESSAGE(40, 5, "Unable to manage any screens on display.")));
911 ExitWM (WM_ERROR_EXIT_VALUE);
916 * Initialize the IPC mechanism
918 dtInitialize(argv[0], wmGD.mwmAppContext);
919 #ifndef NO_MESSAGE_CATALOG
921 * Set up NLS error messages.
922 * Must be done after DtInitialize.
928 * For multiple connections to the server, turn off
929 * the geometry manager's insistence on synchronous
934 XtSetArg (args[argnum], XmNuseAsyncGeometry, True); argnum++;
935 XtSetValues (wmGD.topLevelW, args, argnum);
936 XtSetValues (wmGD.topLevelW1, args, argnum);
942 * Prepare to have child processes (e.g., exec'ed commands).
943 * The X connection should not be passed on to child processes
944 * (it should be automatically closed when a fork is done).
947 if (fcntl (ConnectionNumber (DISPLAY), F_SETFD, 1) == -1)
949 ShowWaitState (FALSE);
950 Warning (((char *)GETMESSAGE(40, 6, "Cannot configure X connection")));
951 ExitWM (WM_ERROR_EXIT_VALUE);
957 enum { XA_DT_WORKSPACE_HINTS, XA_DT_WORKSPACE_PRESENCE,
958 XA_DT_WORKSPACE_INFO, XA_WmNall,
959 XA_DT_WORKSPACE_EMBEDDED_CLIENTS, XA_DT_WM_REQUEST,
960 XA_DT_WORKSPACE_LIST, XA_DT_WORKSPACE_CURRENT, NUM_ATOMS };
961 static char *atom_names[] = {
962 _XA_DT_WORKSPACE_HINTS, _XA_DT_WORKSPACE_PRESENCE,
963 _XA_DT_WORKSPACE_INFO, WmNall,
964 _XA_DT_WORKSPACE_EMBEDDED_CLIENTS, _XA_DT_WM_REQUEST,
965 _XA_DT_WORKSPACE_LIST, _XA_DT_WORKSPACE_CURRENT };
967 Atom atoms[XtNumber(atom_names)];
968 XInternAtoms(DISPLAY, atom_names, XtNumber(atom_names), False, atoms);
970 wmGD.xa_DT_WORKSPACE_HINTS = atoms[XA_DT_WORKSPACE_HINTS];
971 wmGD.xa_DT_WORKSPACE_PRESENCE = atoms[XA_DT_WORKSPACE_PRESENCE];
972 wmGD.xa_DT_WORKSPACE_INFO = atoms[XA_DT_WORKSPACE_INFO];
973 wmGD.xa_ALL_WORKSPACES = atoms[XA_WmNall];
974 wmGD.xa_DT_EMBEDDED_CLIENTS = atoms[XA_DT_WORKSPACE_EMBEDDED_CLIENTS];
975 wmGD.xa_DT_WM_REQUEST = atoms[XA_DT_WM_REQUEST];
976 wmGD.xa_DT_WORKSPACE_LIST = atoms[XA_DT_WORKSPACE_LIST];
977 wmGD.xa_DT_WORKSPACE_CURRENT = atoms[XA_DT_WORKSPACE_CURRENT];
982 /* Initialize properties used in session management. */
983 wmGD.xa_SM_CLIENT_ID =
984 XmInternAtom (DISPLAY, _XA_DT_SM_CLIENT_ID, False);
985 wmGD.xa_WMSAVE_HINT =
986 XmInternAtom (DISPLAY, _XA_DT_WMSAVE_HINT, False);
988 /* Load client resource database. */
989 wmGD.clientResourceDB = LoadClientResourceDB();
992 * Make the window manager workspace window.
993 * Setup the _MOTIF_WM_INFO property on the root window.
996 SetupWmWorkspaceWindows ();
999 /* make the cursors that the window manager uses */
1000 MakeWorkspaceCursors ();
1003 /* Sync the table used by Mwm's modifier parser to actual modMasks used */
1004 SyncModifierStrings();
1007 * Setup screen data and resources (after processing Wm resources.
1009 for (scr = 0; scr < wmGD.numScreens; scr++)
1011 pSD = &(wmGD.Screens[scr]);
1016 if (XDefaultScreen (wmGD.display) == pSD->screen)
1018 wmGD.commandWindow = wmGD.Screens[scr].wmWorkspaceWin;
1023 * Initialize workspace colormap data.
1026 InitWorkspaceColormap (pSD);
1029 * Process the window manager resource description file (.mwmrc):
1033 ProcessWmFile (pSD, False /* not nested */);
1035 #else /* PANELIST */
1036 ProcessWmFile (pSD);
1037 #endif /* PANELIST */
1041 * Setup default resources for the system menu and key bindings:
1044 SetupDefaultResources (pSD);
1048 * Make global window manager facilities:
1051 if(pSD->iconDecoration & ICON_ACTIVE_LABEL_PART)
1053 /* create active icon window */
1054 CreateActiveIconTextWindow(pSD);
1059 * Make menus and other resources that are used by window manager
1060 * functions that are activated by menus, buttons and keys.
1063 MakeWmFunctionResources (pSD);
1069 * Set root cursor to be a pointer for dtwm
1074 /* Fixes problem on multiscreen where cursor is only
1075 * set on primary screen.
1079 XDefineCursor (DISPLAY,
1080 RootWindow (DISPLAY, scr),
1081 wmGD.workspaceCursor);
1089 * Remove any temp config file we created if we needed to
1090 * convert DT 2.0 syntax to DT 3.0
1092 DeleteTempConfigFileIfAny();
1093 #endif /* PANELIST */
1096 * Point second display's resource data base
1097 * to the first display's resource data base
1098 * so dtwm "clients" change colors dynamically.
1102 wmGD.display1->db = wmGD.display->db;
1106 * Realize the top level widget, make the window override
1107 * redirect so we don't manage it, and then move it out of the way
1110 XtRealizeWidget (wmGD.topLevelW);
1112 XtRealizeWidget (wmGD.topLevelW1);
1115 * Initialize the message handling.
1116 * (This must be done after the realize because a window
1117 * is required for ICCCM-style messaging).
1119 dtInitializeMessaging (wmGD.topLevelW);
1122 sAttributes.override_redirect = True;
1123 XChangeWindowAttributes (DISPLAY, XtWindow (wmGD.topLevelW),
1124 CWOverrideRedirect, &sAttributes);
1127 /* setup window manager inter-client communications conventions handling */
1131 * Use the WM_SAVE_YOURSELF protocol
1132 * for notification of when to save ourself
1135 SetMwmSaveSessionInfo(wmGD.commandWindow);
1138 * Initialize window manager event handling:
1141 InitEventHandling ();
1146 * Initialize frame component graphics
1149 for (scr = 0; scr < wmGD.numScreens; scr++)
1151 pSD = &(wmGD.Screens[scr]);
1155 InitClientDecoration (pSD);
1158 * Make an icon box if specificed:
1160 if (pSD->useIconBox)
1166 * Adopt client windows that exist before wm startup:
1169 AdoptInitialClients (pSD);
1172 * Setup initial keyboard focus and colormap focus:
1175 InitColormapFocus (pSD);
1180 for (scr = 0; scr < wmGD.numScreens; scr++)
1185 pSD = &(wmGD.Screens[scr]);
1189 ACTIVE_PSD = &wmGD.Screens[scr];
1191 MapIconBoxes (pSD->pActiveWS);
1193 ChangeBackdrop (pSD->pActiveWS);
1196 UpdateWorkspaceInfoProperty (pSD); /* backward compatible */
1199 SetCurrentWorkspaceProperty (pSD);
1200 SetWorkspaceListProperty (pSD);
1202 for (iws=0; iws < pSD->numWorkspaces; iws++)
1204 SetWorkspaceInfoProperty (&(pSD->pWS[iws]));
1212 /* MapWorkspaceBox (); */
1216 * Allocate front panel widgets
1218 if (wmGD.useFrontPanel && (pSD == wmGD.dtSD))
1224 WmPanelistObject pPanelist;
1226 wmGD.dtSD->wPanelist =
1227 WmPanelistAllocate(pSD->screenTopLevelW1,
1228 (XtPointer) &wmGD, (XtPointer) pSD);
1230 pPanelist = (WmPanelistObject) pSD->wPanelist;
1232 if (pPanelist != NULL && O_Shell(pPanelist))
1235 * Make a default front panel icon image.
1237 iconBitmap = XCreateBitmapFromData (DISPLAY,
1239 (char *) fntpl_i_bm_bits,
1244 XtSetArg (al[ac], XmNiconPixmap, iconBitmap); ac++;
1245 XtSetValues (O_Shell(pPanelist), al, ac);
1250 if (wmGD.useFrontPanel && pSD->wPanelist &&
1254 * Make the front panel visible
1256 WmPanelistShow (pSD->wPanelist);
1259 * Find special clients associated with the
1260 * front panel. This needs to be done after
1261 * WmPanelistShow where the data is set up.
1263 ScanForPushRecallClients (pSD);
1264 ScanForEmbeddedClients (pSD);
1266 #endif /* PANELIST */
1268 RestoreHelpDialogs(pSD);
1270 MapIconBoxes (pSD->pActiveWS);
1277 InitKeyboardFocus ();
1280 InitWmDisplayEnv ();
1282 ShowWaitState (FALSE);
1286 * Tell the rest of DT that we're up
1288 dtReadyNotification();
1291 #ifdef DEBUG_RESOURCE_DATABASE
1292 XrmPutFileDatabase(wmGD.display->db, "/tmp/dtwm.resDB");
1293 #endif /* DEBUG_RESOURCE_DATABASE */
1295 } /* END OF FUNCTION InitWmGlobal */
1299 /******************************<->*************************************
1306 * This function initializes a screen data block.
1310 * pSD = pointer to preallocated screen data block
1311 * sNum = screen number for this screen
1315 *************************************<->***********************************/
1318 InitWmScreen (WmScreenData *pSD, int sNum)
1325 WmWorkspaceData *pwsI;
1328 static int dupnum = 0;
1333 #define LENCBUFFER 256
1334 char buffer[LENCBUFFER]; /* screen name & display name! */
1335 char displayName[LENCBUFFER];
1336 char *token1, *token2;
1340 * Set screen data values
1343 pSD->rootWindow = RootWindow (DISPLAY, sNum);
1344 pSD->clientCounter = 0;
1345 pSD->defaultSystemMenuUseBuiltin = TRUE;
1346 pSD->displayString = NULL;
1347 pSD->acceleratorMenuCount = 0;
1348 pSD->activeIconTextWin = (Window)NULL;
1349 pSD->focusPriority = 0;
1350 pSD->inputScreenWindow = (Window)NULL;
1351 pSD->colormapFocus = NULL;
1352 pSD->keySpecs = NULL;
1354 pSD->confirmboxW[DEFAULT_BEHAVIOR_ACTION] = NULL;
1355 pSD->confirmboxW[CUSTOM_BEHAVIOR_ACTION] = NULL;
1356 pSD->confirmboxW[RESTART_ACTION] = NULL;
1357 pSD->confirmboxW[QUIT_MWM_ACTION] = NULL;
1358 pSD->feedbackWin = (Window)NULL;
1359 pSD->fbStyle = FB_OFF;
1360 pSD->fbWinWidth = 0;
1361 pSD->fbWinHeight = 0;
1362 pSD->fbLocation[0] = '\0';
1363 pSD->fbSize[0] = '\0';
1370 pSD->fbLastWidth = -1;
1371 pSD->fbLastHeight = -1;
1373 pSD->fbBottom = NULL;
1374 pSD->actionNbr = -1;
1375 pSD->clientList = NULL;
1376 pSD->lastClient = NULL;
1377 pSD->lastInstalledColormap = (Colormap)NULL;
1378 pSD->shrinkWrapGC = NULL;
1379 pSD->bitmapCache = NULL;
1380 pSD->bitmapCacheSize = 0;
1381 pSD->bitmapCacheCount = 0;
1382 pSD->dataType = SCREEN_DATA_TYPE;
1383 pSD->managed = False;
1384 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
1385 pSD->cciTree = NULL;
1386 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
1389 pSD->initialWorkspace=NULL;
1390 pSD->presence.shellW = NULL;
1391 pSD->presence.onScreen = False;
1392 pSD->presence.userDismissed = True;
1393 pSD->workspaceList = NULL;
1394 pSD->numWorkspaces = 0;
1395 pSD->numWsDataAllocated = 0;
1396 pSD->lastBackdropWin = NULL;
1397 pSD->pDtSessionItems = NULL;
1398 pSD->totalSessionItems = 0;
1399 pSD->remainingSessionItems = 0;
1401 pSD->cachedHelp = NULL;
1402 pSD->dtHelp.shell = (Widget)NULL;
1403 pSD->dtHelp.dialog = (Widget)NULL;
1404 pSD->dtHelp.errorDialog = (Widget)NULL;
1405 pSD->dtHelp.xPos = 0;
1406 pSD->dtHelp.yPos = 0;
1407 pSD->dtHelp.restored = False;
1408 pSD->dtHelp.onScreen = False;
1409 pSD->dtHelp.userDismissed = False;
1410 pSD->dtHelp.pCDforClient= NULL;
1411 pSD->helpResources=NULL;
1412 pSD->bMarqueeSelectionInitialized = False;
1413 pSD->woN = (Window) 0L;
1414 pSD->woS = (Window) 0L;
1415 pSD->woE = (Window) 0L;
1416 pSD->woW = (Window) 0L;
1419 pSD->wPanelist = NULL;
1421 pSD->numPushRecallClients = 0;
1422 pSD->numEmbeddedClients = 0;
1424 pSD->iconBoxControl = False;
1425 #endif /* PANELIST */
1427 pSD->displayResolutionType = _DtGetDisplayResolution(DISPLAY, sNum);
1430 * We've got display resolution type--now, let's get color
1434 ProcessWmColors (pSD);
1436 if (!(strcmp ((char *)wmGD.screenNames[sNum], UNSPECIFIED_SCREEN_NAME)))
1438 sprintf (buffer, "%d", sNum);
1440 buf_size = strlen(buffer) + 1;
1442 if ((wmGD.screenNames[sNum] =
1443 (unsigned char *)XtRealloc (wmGD.screenNames[sNum], buf_size)) == NULL)
1445 Warning (((char *)GETMESSAGE(40, 7, "Cannot create enough memory for the screen names")));
1446 ExitWM (WM_ERROR_EXIT_VALUE);
1450 strcpy((char *)wmGD.screenNames[sNum], buffer);
1452 } /* if wmGD.screenNames[sNum] == UNSPECIFIED_SCREEN_NAME */
1456 * Save screen context
1458 XSaveContext (DISPLAY, pSD->rootWindow, wmGD.screenContextType,
1461 * Create shell widget for screen resource hierarchy
1465 XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
1466 XtSetArg (args[argnum], XtNx, 10000); argnum++;
1467 XtSetArg (args[argnum], XtNy, 10000); argnum++;
1468 XtSetArg (args[argnum], XtNwidth, 10); argnum++;
1469 XtSetArg (args[argnum], XtNheight, 10); argnum++;
1470 XtSetArg (args[argnum], XtNoverrideRedirect, True); argnum++;
1472 XtSetArg (args[argnum], XtNdepth,
1473 DefaultDepth(DISPLAY, sNum)); argnum++;
1474 XtSetArg (args[argnum], XtNscreen,
1475 ScreenOfDisplay(DISPLAY, sNum)); argnum++;
1476 XtSetArg (args[argnum], XtNcolormap,
1477 DefaultColormap(DISPLAY, sNum)); argnum++;
1479 pSD->screenTopLevelW = XtCreatePopupShell ((String) wmGD.screenNames[sNum],
1480 vendorShellWidgetClass,
1485 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
1486 /* Create a DrawingArea as a child of the popupShell. This will be used
1487 * to handle UTM traffic relating to cci. We need this
1488 * particular widget to get the callbacks from conversion requests made
1489 * against Mwm and the requests Mwm makes against other clients.
1491 pSD->utmShell = XmCreateDrawingArea(pSD->screenTopLevelW, "UTM_Shell",
1493 XtManageChild(pSD->utmShell);
1496 * Setup the destinationCallback handler to handle conversion
1497 * requests made by Mwm against other clients.
1499 XtAddCallback(pSD->utmShell, XmNdestinationCallback, UTMDestinationProc,
1502 /* Must realize to own WM_i if unmapped, causes mwm to
1503 freeze when menu is displayed. */
1504 XtPopup(pSD->screenTopLevelW, XtGrabNone);
1505 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
1509 XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
1510 XtSetArg (args[argnum], XtNx, 10000); argnum++;
1511 XtSetArg (args[argnum], XtNy, 10000); argnum++;
1512 XtSetArg (args[argnum], XtNwidth, 10); argnum++;
1513 XtSetArg (args[argnum], XtNheight, 10); argnum++;
1514 XtSetArg (args[argnum], XtNoverrideRedirect, True); argnum++;
1515 XtSetArg (args[argnum], XtNmappedWhenManaged, False); argnum++;
1517 XtSetArg (args[argnum], XtNdepth,
1518 DefaultDepth(DISPLAY1, sNum)); argnum++;
1519 XtSetArg (args[argnum], XtNscreen,
1520 ScreenOfDisplay(DISPLAY1, sNum)); argnum++;
1521 XtSetArg (args[argnum], XtNcolormap,
1522 DefaultColormap(DISPLAY1, sNum)); argnum++;
1524 pSD->screenTopLevelW1 = XtCreatePopupShell ((String) wmGD.screenNames[sNum],
1525 vendorShellWidgetClass,
1529 XtRealizeWidget (pSD->screenTopLevelW1);
1532 * Fetch screen based resources
1534 ProcessScreenResources (pSD, wmGD.screenNames[sNum]);
1537 * Initialize other screen resources and parameters
1544 * Complete initialization of workspace structures
1547 pwsI = pSD->pWS; wsnum < pSD->numWorkspaces;
1551 * Set up workspace for this screen
1553 InitWmWorkspace (pwsI, pSD);
1557 if (pSD->initialWorkspace)
1560 * restore to the last initialWorkspace saved from
1561 * Quit, Restart, OR save session
1565 * Compare initialWorkspace against workspace name,
1566 * NOT workspace title.
1568 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
1570 if (!strcmp(pSD->pWS[iwsx].name, pSD->initialWorkspace))
1576 if (iwsx >= pSD->numWorkspaces)
1578 /* make first workspace in list the active one to start with */
1579 pSD->pActiveWS = pSD->pWS;
1583 pSD->pActiveWS = &pSD->pWS[iwsx];
1588 /* make first workspace in list the active one to start with */
1589 pSD->pActiveWS = pSD->pWS;
1593 * Allocate and initialize a workspace structure
1596 if (!(pSD->pWS = (WmWorkspaceData *) XtMalloc (sizeof(WmWorkspaceData))))
1598 ShowWaitState (FALSE);
1599 Warning (((char *)GETMESSAGE(40, 8, "Insufficient memory for Workspace data")));
1600 ExitWM (WM_ERROR_EXIT_VALUE);
1604 * Set up workspace for this screen
1606 InitWmWorkspace (pSD->pWS, pSD);
1607 pSD->pActiveWS = pSD->pWS;
1611 pDisplayName = DisplayString (DISPLAY);
1614 * Construct displayString for this string.
1616 * NOTE: The variable buffer is reused here. It was
1617 * used earlier to generate a screen name.
1620 strcpy(displayName, pDisplayName);
1622 token1 = (char*)strtok(displayName, ":"); /* parse of hostname */
1624 if((token2 = (char*)strtok(NULL, ".")) || /* parse off dpy & scr # */
1625 (token2 = (char*)strtok(NULL, "")) ||
1626 (displayName[0] == ':'))
1628 if (displayName[0] == ':') /* local dpy (special case) */
1630 if ((token2 = (char*)strtok(token1, ".")) != NULL) /* parse dpy# */
1631 sprintf(buffer, "DISPLAY=:%s.%d",
1633 } else { /* otherwise process normally */
1634 sprintf(buffer, "DISPLAY=%s:%s.%d",
1635 token1, token2, sNum);
1639 * Allocate space for the display string
1642 if ((pSD->displayString =
1643 (String)XtMalloc ((unsigned int) (strlen(buffer) + 1))) == NULL)
1645 Warning (((char *)GETMESSAGE(40, 9,
1646 "Insufficient memory for displayString")));
1650 strcpy(pSD->displayString, buffer);
1657 } /* END OF FUNCTION InitWmScreen */
1660 /*************************************<->*************************************
1667 * This function initializes a workspace data block.
1671 * pWS = pointer to preallocated workspace data block
1672 * pSD = ptr to parent screen data block
1676 *************************************<->***********************************/
1678 void InitWmWorkspace (WmWorkspaceData *pWS, WmScreenData *pSD)
1684 #define DEFAULT_WS_NAME "workspace"
1685 #endif /* not WSM */
1688 pWS->pIconBox = NULL;
1689 pWS->dataType = WORKSPACE_DATA_TYPE;
1691 pWS->backdrop.window = 0;
1692 pWS->backdrop.nameAtom = 0;
1693 pWS->backdrop.image = NULL;
1694 pWS->numClients = 0;
1695 pWS->sizeClientList = 0;
1697 pWS->buttonW = NULL;
1700 if ((pWS->name = (char *)
1701 XtMalloc ((1+strlen(DEFAULT_WS_NAME)) * sizeof (char))) == NULL)
1703 ShowWaitState (FALSE);
1704 ExitWM (WM_ERROR_EXIT_VALUE);
1706 strcpy (pWS->name, DEFAULT_WS_NAME);
1710 * Create widget for workspace resource hierarchy
1713 XtSetArg (args[argnum], XtNdepth,
1714 DefaultDepth(DISPLAY, pSD->screen)); argnum++;
1715 XtSetArg (args[argnum], XtNscreen,
1716 ScreenOfDisplay(DISPLAY, pSD->screen)); argnum++;
1717 XtSetArg (args[argnum], XtNcolormap,
1718 DefaultColormap(DISPLAY, pSD->screen)); argnum++;
1719 XtSetArg (args[argnum], XtNwidth, 5); argnum++;
1720 XtSetArg (args[argnum], XtNheight, 5); argnum++;
1722 pWS->workspaceTopLevelW = XtCreateWidget ( pWS->name,
1723 xmPrimitiveWidgetClass,
1724 pSD->screenTopLevelW,
1729 /* internalize the workspace name */
1730 pWS->id = XInternAtom (DISPLAY, pWS->name, False);
1734 * Process workspace based resources
1736 ProcessWorkspaceResources (pWS);
1738 /* setup icon placement */
1739 if (wmGD.iconAutoPlace)
1741 InitIconPlacement (pWS);
1744 } /* END OF FUNCTION InitWmWorkspace */
1748 /******************************<->*************************************
1750 * InsureDefaultBackdropDir(char **ppchBackdropDirs)
1755 * This function checks and edits a directory path to insure
1756 * that the system backdrop directroy (/usr/dt/backdrops) is in the
1757 * path. If not it adds it to the end. Further, it always adds the user's
1758 * backdrop directory ($HOME/.dt/backdrops) to the beginning of the path
1759 * and the system admin directory (/etc/dt/backdrops) before the system
1764 * ppchBackdropDirs - Pointer to a pointer to a directory path
1765 * (must be allocated memory)
1769 * *ppchBackdropDirs - Directory path may be modified, path
1770 * pointer may be realloc'ed.
1774 * Assumes that the default directory does not start with a
1775 * multi-byte character.
1777 ******************************<->***********************************/
1779 InsureDefaultBackdropDir(char **ppchBackdropDirs)
1782 Boolean bFound = False;
1783 char *pch, *pchEnd, *pch2, *tmpptr;
1784 char *pchD = DEFAULT_BACKDROP_DIR;
1789 * Set up initial stuff
1791 pch = *ppchBackdropDirs;
1792 len = strlen (pchD);
1793 pchEnd = pch + strlen(pch);
1795 while (!bFound && (pch != NULL) && (*pch != NULL))
1797 if (strncmp (pch, pchD, len) == 0)
1799 /* found partial match, confirm complete match ...
1800 * complete match if char off end of partial match
1801 * is a NULL or a colon
1804 if ((pch2 <= pchEnd) &&
1806 (((mblen (pch2, MB_CUR_MAX) == 1) &&
1814 /* find next path component */
1815 pch = strchr (pch, (int) ':');
1816 if ((pch != NULL) && (*pch != NULL))
1818 /* skip path separator */
1819 chlen = mblen (pch, MB_CUR_MAX);
1827 * Always add the user's home directory to the beginning of the string
1829 homeDir = (char *) XmeGetHomeDirName();
1832 * If found add the user's home directory ($HOME/.dt/backdrops) and the
1833 * admin directory /etc/dt/backdrops to the beginning of the string
1838 len = strlen (homeDir) + strlen("/.dt/backdrops") +
1839 strlen (*ppchBackdropDirs) + strlen("/etc/dt/backdrops") + 3;
1840 tmpptr = XtMalloc (len * sizeof (char *));
1841 strcpy (tmpptr, homeDir);
1842 strcat (tmpptr, "/.dt/backdrops");
1843 strcat (tmpptr, ":");
1844 strcat (tmpptr, "/etc/dt/backdrops");
1845 strcat (tmpptr, ":");
1846 strcat (tmpptr, *ppchBackdropDirs);
1847 *ppchBackdropDirs = tmpptr;
1851 * If string not found, then add home directory to the beginning of
1852 * string and the admin directory and system directory to the end.
1855 len = strlen (homeDir) + strlen("/.dt/backdrops") +
1856 strlen (*ppchBackdropDirs) + strlen(pchD) +
1857 strlen("/etc/dt/backdrops") + 4;
1858 tmpptr = XtMalloc (len * sizeof (char *));
1859 strcpy (tmpptr, homeDir);
1860 strcat (tmpptr, "/.dt/backdrops");
1861 strcat (tmpptr, ":");
1862 strcat (tmpptr, *ppchBackdropDirs);
1863 strcat (tmpptr, ":");
1864 strcat (tmpptr, "/etc/dt/backdrops");
1865 strcat (tmpptr, ":");
1866 strcat (tmpptr, pchD);
1867 *ppchBackdropDirs = tmpptr;
1870 } /* END OF FUNCTION InsureDefaultBackdropDirs */
1874 /*************************************<->*************************************
1876 * ProcessMotifWmInfo (rootWindowOfScreen)
1881 * This function is used retrieve and save the information in the
1882 * _MOTIF_WM_INFO property. If the property does not exist then
1883 * the start / restart state is set to initial startup with the
1884 * user specified (not standard) configuration.
1889 * wmGD.useStandardBehavior = True if set indicated in property
1891 * wmGD.wmRestarted = True if the window manager was restarted
1893 *************************************<->***********************************/
1895 void ProcessMotifWmInfo (Window rootWindowOfScreen)
1899 wmGD.xa_MWM_INFO = XInternAtom (DISPLAY, _XA_MWM_INFO, False);
1900 if ((pMwmInfo = (MotifWmInfo *)GetMwmInfo (rootWindowOfScreen)) != NULL)
1902 wmGD.useStandardBehavior =
1903 (pMwmInfo->flags & MWM_INFO_STARTUP_STANDARD) ? True : False;
1904 wmGD.wmRestarted = True;
1905 XFree ((char *)pMwmInfo);
1909 wmGD.useStandardBehavior = False;
1910 wmGD.wmRestarted = False;
1913 } /* END OF FUNCTION ProcessMotifWmInfo */
1917 /*************************************<->*************************************
1919 * SetupWmWorkspaceWindows ()
1924 * This function is used to setup a window that can be used in doing window
1925 * management functions. This window is not visible on the screen.
1930 * pSD->wmWorkspaceWin = window that is used to hold wm properties
1932 *************************************<->***********************************/
1934 void SetupWmWorkspaceWindows (void)
1938 XSetWindowAttributes sAttributes;
1940 for (scr = 0; scr < wmGD.numScreens; scr++)
1942 pSD = &(wmGD.Screens[scr]);
1945 sAttributes.override_redirect = True;
1946 sAttributes.event_mask = FocusChangeMask | PropertyChangeMask;
1947 pSD->wmWorkspaceWin = XCreateWindow (DISPLAY, pSD->rootWindow,
1948 -100, -100, 10, 10, 0, 0,
1949 InputOnly, CopyFromParent,
1950 (CWOverrideRedirect |CWEventMask),
1953 XMapWindow (DISPLAY, pSD->wmWorkspaceWin);
1955 SetMwmInfo (pSD->rootWindow,
1956 (long) ((wmGD.useStandardBehavior) ?
1957 MWM_INFO_STARTUP_STANDARD : MWM_INFO_STARTUP_CUSTOM),
1958 pSD->wmWorkspaceWin);
1960 XSaveContext (DISPLAY, pSD->wmWorkspaceWin,
1961 wmGD.mwmWindowContextType, (caddr_t)pSD);
1966 } /* END OF FUNCTION SetupWmWorkspaceWindow */
1970 /*************************************<->*************************************
1972 * MakeWorkspaceCursors ()
1977 * This function makes the cursors that the window manager uses.
1989 * wmGD = (stretchCursors ...)
1991 *************************************<->***********************************/
1993 void MakeWorkspaceCursors (void)
1995 wmGD.workspaceCursor = XCreateFontCursor (DISPLAY, XC_left_ptr);
1997 wmGD.stretchCursors[STRETCH_NORTH_WEST] =
1998 XCreateFontCursor (DISPLAY, XC_top_left_corner);
1999 wmGD.stretchCursors[STRETCH_NORTH] =
2000 XCreateFontCursor (DISPLAY, XC_top_side);
2001 wmGD.stretchCursors[STRETCH_NORTH_EAST] =
2002 XCreateFontCursor (DISPLAY, XC_top_right_corner);
2003 wmGD.stretchCursors[STRETCH_EAST] =
2004 XCreateFontCursor (DISPLAY, XC_right_side);
2005 wmGD.stretchCursors[STRETCH_SOUTH_EAST] =
2006 XCreateFontCursor (DISPLAY, XC_bottom_right_corner);
2007 wmGD.stretchCursors[STRETCH_SOUTH] =
2008 XCreateFontCursor (DISPLAY, XC_bottom_side);
2009 wmGD.stretchCursors[STRETCH_SOUTH_WEST] =
2010 XCreateFontCursor (DISPLAY, XC_bottom_left_corner);
2011 wmGD.stretchCursors[STRETCH_WEST] =
2012 XCreateFontCursor (DISPLAY, XC_left_side);
2014 wmGD.configCursor = XCreateFontCursor (DISPLAY, XC_fleur);
2016 wmGD.movePlacementCursor = XCreateFontCursor (DISPLAY, XC_ul_angle);
2017 wmGD.sizePlacementCursor = XCreateFontCursor (DISPLAY, XC_lr_angle);
2020 } /* END OF FUNCTION MakeWorkspaceCursors */
2024 /*************************************<->*************************************
2026 * MakeWmFunctionResources (pSD)
2031 * This function makes menus and other resources that are used by window
2032 * manager functions.
2037 * wmGD = (menuSpecs, keySpecs, buttonSpecs)
2042 * wmGD (menuSpecs) = new menu panes, protocol atoms
2044 *************************************<->***********************************/
2046 void MakeWmFunctionResources (WmScreenData *pSD)
2048 ButtonSpec *buttonSpec;
2051 Context menuContext;
2055 * Scan through the menu specifications and make wm protocol atoms.
2060 * Scan through the button binding specifications making menus if the
2061 * f.menu function is invoked.
2064 buttonSpec = pSD->buttonSpecs;
2067 if (buttonSpec->wmFunction == F_Menu)
2069 if (buttonSpec->context & F_CONTEXT_WINDOW)
2071 menuContext = F_CONTEXT_WINDOW;
2073 else if (buttonSpec->context & F_CONTEXT_ICON)
2075 menuContext = F_CONTEXT_ICON;
2079 menuContext = F_CONTEXT_ROOT;
2082 menuSpec = MAKE_MENU (pSD, NULL, buttonSpec->wmFuncArgs,
2084 buttonSpec->context,
2085 (MenuItem *) NULL, FALSE);
2089 * If successful, save in pSD->acceleratorMenuSpecs
2090 * Note: these accelerators have nonzero contexts.
2093 SaveMenuAccelerators (pSD, menuSpec);
2097 buttonSpec->wmFunction = F_Nop;
2100 buttonSpec = buttonSpec->nextButtonSpec;
2105 * Scan through the key binding specifications making menus if the
2106 * f.menu function is invoked.
2109 keySpec = pSD->keySpecs;
2112 if (keySpec->wmFunction == F_Menu)
2114 if (keySpec->context & F_CONTEXT_WINDOW)
2116 menuContext = F_CONTEXT_WINDOW;
2118 else if (keySpec->context & F_CONTEXT_ICON)
2120 menuContext = F_CONTEXT_ICON;
2124 menuContext = F_CONTEXT_ROOT;
2127 menuSpec = MAKE_MENU (pSD, NULL, keySpec->wmFuncArgs, menuContext,
2129 (MenuItem *) NULL, FALSE);
2133 * If successful, save in pSD->acceleratorMenuSpecs
2134 * Note: these accelerators have nonzero contexts.
2137 SaveMenuAccelerators (pSD, menuSpec);
2141 keySpec->wmFunction = F_Nop;
2144 keySpec = keySpec->nextKeySpec;
2148 } /* END OF FUNCTION MakeWmFunctionResources */
2152 /*************************************<->*************************************
2159 * Make an XOR graphic context for resizing and moving
2164 * pSD = pointer to screen data
2168 * Modifies global data
2174 *************************************<->***********************************/
2176 void MakeXorGC (WmScreenData *pSD)
2181 mask = GCFunction | GCLineWidth | GCSubwindowMode | GCCapStyle;
2182 gcv.function = GXinvert;
2184 gcv.cap_style = CapNotLast;
2185 gcv.subwindow_mode = IncludeInferiors;
2187 /* Fix so that the rubberbanding for resize and move will
2188 * have more contrasting colors.
2191 gcv.plane_mask = BlackPixelOfScreen( DefaultScreenOfDisplay( DISPLAY )) ^
2192 WhitePixelOfScreen( DefaultScreenOfDisplay( DISPLAY ));
2193 mask = mask | GCPlaneMask;
2195 pSD->xorGC = XCreateGC (DISPLAY, pSD->rootWindow, mask, &gcv);
2198 } /* END OF FUNCTION MakeXorGC */
2202 /*************************************<->*************************************
2204 * CopyArgv (argc, argv)
2209 * This function makes a copy of the window manager's argv for use by
2210 * the f.restart function. A copy must be kept because XtInitialize
2216 * argc = the number of strings in argv
2218 * argv = window manager parameters
2223 * Return = a copy of argv
2225 *************************************<->***********************************/
2228 void CopyArgv (int argc, char *argv [])
2233 if ((wmGD.argv = (char **)XtMalloc ((argc + 1) * sizeof (char *))) == NULL)
2235 Warning (((char *)GETMESSAGE(40, 10, "Insufficient memory for window manager data")));
2243 for (i = 0; i < argc; i++)
2245 wmGD.argv[i] = argv[i];
2247 wmGD.argv[i] = NULL;
2249 if ((dpy2Argv = (char **)XtMalloc((argc + 1) * sizeof(char *))) == NULL)
2251 Warning (((char *)GETMESSAGE(40, 11, "Insufficient memory for window manager data")));
2256 for (i = 0; i < argc; i++)
2258 dpy2Argv[i] = argv[i];
2266 } /* END OF FUNCTION CopyArgv */
2269 /*************************************<->*************************************
2271 * InitScreenNames ()
2276 * Initializes the name space for screen names
2280 * Modifies global data
2285 * Initializes screenNames to contain a numeric name for each screen
2287 *************************************<->***********************************/
2289 void InitScreenNames (void)
2291 int num, numScreens;
2293 numScreens = ScreenCount (wmGD.display);
2295 if (!(wmGD.screenNames =
2296 (unsigned char **) XtMalloc (numScreens * sizeof(char *))))
2298 ShowWaitState (FALSE);
2299 Warning (((char *)GETMESSAGE(40, 12, "Insufficient memory for screen names")));
2300 ExitWM (WM_ERROR_EXIT_VALUE);
2303 for (num=0; num<numScreens; num++)
2305 if (!(wmGD.screenNames[num] =
2306 (unsigned char *) XtMalloc (4*sizeof(char))))
2308 ShowWaitState (FALSE);
2309 Warning (((char *)GETMESSAGE(40, 13, "Insufficient memory for screen names")));
2310 ExitWM (WM_ERROR_EXIT_VALUE);
2312 /* default name is left justified, 3-chars max, zero terminated */
2314 sprintf((char *)wmGD.screenNames[num], UNSPECIFIED_SCREEN_NAME);
2316 sprintf((char *)wmGD.screenNames[num],"%d",num%1000);
2320 #ifndef NO_MESSAGE_CATALOG
2323 void InitNlsStrings (void)
2329 * Initialize messages
2331 wmGD.okLabel=XmStringCreateLocalized(_DtOkString);
2332 wmGD.cancelLabel=XmStringCreateLocalized(_DtCancelString);
2333 wmGD.helpLabel=XmStringCreateLocalized(_DtHelpString);
2337 * catgets returns a pointer to an area that is over written
2338 * on each call to catgets.
2341 tmpString = ((char *)GETMESSAGE(40, 14, "Icons"));
2342 if ((wmNLS.default_icon_box_title =
2343 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2345 Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
2346 wmNLS.default_icon_box_title = "Icons";
2350 strcpy(wmNLS.default_icon_box_title, tmpString);
2354 tmpString = ((char *)GETMESSAGE(40, 20, "%s: %s on line %d of configuration file %s\n"));
2355 if ((pWarningStringFile =
2356 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2358 Warning (((char *)GETMESSAGE(40, 17, "Insufficient memory for local message string")));
2359 pWarningStringFile = "%s: %s on line %d of configuration file %s\n";
2363 strcpy(pWarningStringFile, tmpString);
2366 tmpString = ((char *)GETMESSAGE(40, 21, "%s: %s on line %d of specification string\n"));
2367 if ((pWarningStringLine =
2368 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2370 Warning (((char *)GETMESSAGE(40, 19, "Insufficient memory for local message string")));
2371 pWarningStringLine = "%s: %s on line %d of specification string\n";
2375 strcpy(pWarningStringLine, tmpString);
2379 tmpString = ((char *)GETMESSAGE(40, 22, "About Workspace Manager"));
2380 if ((wmNLS.defaultVersionTitle =
2381 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2383 Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
2384 wmNLS.defaultVersionTitle = "About Workspace Manager";
2388 strcpy(wmNLS.defaultVersionTitle, tmpString);
2391 tmpString = ((char *)GETMESSAGE(40, 23, "Workspace Manager - Help"));
2392 if ((wmNLS.defaultDtwmHelpTitle =
2393 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2395 Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
2396 wmNLS.defaultDtwmHelpTitle = "Workspace Manager - Help";
2400 strcpy(wmNLS.defaultDtwmHelpTitle, tmpString);
2403 tmpString = ((char *)GETMESSAGE(40, 24, "Workspace Manager - Help"));
2404 if ((wmNLS.defaultHelpTitle =
2405 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2407 Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
2408 wmNLS.defaultHelpTitle = "Workspace Manager - Help";
2412 strcpy(wmNLS.defaultHelpTitle, tmpString);
2416 } /* InitNlsStrings */
2421 /******************************<->*************************************
2428 * This function saves the display string for putenv in F_Exec.
2435 *************************************<->***********************************/
2438 InitWmDisplayEnv (void)
2442 char displayName[256];
2444 pDisplayName = DisplayString (DISPLAY);
2447 * Construct displayString for this string.
2449 strcpy(displayName, pDisplayName);
2450 sprintf(buffer, "DISPLAY=%s",displayName);
2453 * Allocate space for the display string
2455 if ((wmGD.displayString =
2456 (String)XtMalloc ((unsigned int) (strlen(buffer) + 1))) == NULL)
2458 wmGD.displayString = NULL;
2459 Warning (((char *)GETMESSAGE(40, 9,
2460 "Insufficient memory for displayString")));
2464 strcpy(wmGD.displayString, buffer);
2466 putenv(wmGD.displayString);
2470 } /* END OF FUNCTION InitWmDisplayEnv */
2472 #ifndef NO_HP_KEY_REMAP
2485 str_xref xref_rtn = NULL ;
2486 unsigned num_xref = 0 ;
2488 XDisplayKeycodes( dsp, &min_kc, &max_kc) ;
2489 kc_count = max_kc + 1 - min_kc ;
2490 key_map = XGetKeyboardMapping( dsp, min_kc, kc_count, &ks_per_kc) ;
2491 if( key_map == NULL )
2495 kc_count *= ks_per_kc ;
2500 KeySym ks = XStringToKeysym( std_xref[i].default_name) ;
2503 while( j < kc_count )
2505 if( key_map[j] == ks )
2507 /* Found keysym used in virtkey table in keymap,
2508 * so break -> j != kc_count
2516 /* Didn't find keysym of virtkey table, so add record to
2517 * returned list which will later cause replacement in
2520 xref_rtn = (str_xref) XtRealloc( (char *) xref_rtn,
2521 sizeof( str_xref_rec) * (num_xref + 2)) ;
2522 xref_rtn[num_xref++] = std_xref[i] ;
2523 xref_rtn[num_xref].default_name = NULL ;
2527 XFree( (char *) key_map) ;
2532 GetBindingsProperty(
2539 unsigned long num_items ;
2540 unsigned long bytes_after ;
2541 unsigned char *prop = NULL ;
2543 XGetWindowProperty( dsp, RootWindow( dsp, 0), property, 0, 1000000L,
2544 FALSE, XA_STRING, &actual_type, &actual_format, &num_items, &bytes_after,
2546 if( (actual_type != XA_STRING)
2547 || (actual_format != 8)
2548 || (num_items == 0) )
2556 *binding = (String) prop ;
2561 SetBindingsProperty(
2566 XChangeProperty( dsp, RootWindow( dsp, 0), property, XA_STRING, 8,
2567 PropModeReplace, (unsigned char *) binding, strlen( binding)) ;
2571 FixupBindingsString(
2572 String bindingsString,
2575 String fixed_str = XtNewString( bindingsString) ;
2576 String ptr_next = fixed_str ;
2578 while( repl_xref->default_name != NULL )
2580 String ks_ptr = strstr( ptr_next, repl_xref->default_name) ;
2581 unsigned orig_len = strlen( repl_xref->default_name) ;
2583 if( ks_ptr == NULL )
2585 /* Only increment to next replacement when no other instances
2586 * are found in fixed_str.
2589 ptr_next = fixed_str ;
2593 if( (strpbrk( (ks_ptr - 1), " \t>") == (ks_ptr - 1))
2594 && (strpbrk( ks_ptr, " \t\n") == (ks_ptr + orig_len)) )
2596 unsigned new_len = strlen( repl_xref->new_name) ;
2597 unsigned suffix_len = strlen( ks_ptr + orig_len) ;
2599 if( new_len > orig_len )
2601 unsigned new_ttl_len = strlen( fixed_str) + new_len - orig_len ;
2602 unsigned prefix_len ;
2605 prefix_len = strlen( fixed_str) ;
2606 fixed_str = XtRealloc( fixed_str, (new_ttl_len + 1)) ;
2607 ks_ptr = fixed_str + prefix_len ;
2609 memmove( (ks_ptr + new_len), (ks_ptr + orig_len), (suffix_len + 1)) ;
2610 memcpy( ks_ptr, repl_xref->new_name, new_len) ;
2612 ptr_next = ks_ptr + new_len ;
2616 ptr_next = ks_ptr + 1 ;
2627 /* This routine examines the X server's key map table to determine
2628 * if certain HP-specific keysyms are missing. If they are, then
2629 * the Motif virtual binding table properties are updated to utilize
2630 * generic X keysyms instead of the missing HP vendor keysyms.
2631 * In particular, this fixes the Motif virtual key binding table for
2632 * correct operation on HP systems using the AT2/DIN style keyboard.
2634 static char *prop_names[] = { "_MOTIF_BINDINGS",
2635 "_MOTIF_DEFAULT_BINDINGS" } ;
2636 static str_xref_rec std_xref[] = { { "hpInsertChar", "Insert" },
2637 { "hpDeleteChar", "Delete" },
2640 Boolean PropChanged4DIN = FALSE ;
2642 char *bindingsString ;
2643 unsigned prop_existed ;
2645 str_xref vkeysym_xref ;
2646 unsigned num_props = XtNumber( prop_names) ;
2648 vkeysym_xref = GetReplacementList( dsp, std_xref, XtNumber(std_xref)) ;
2649 if( vkeysym_xref == NULL )
2651 return PropChanged4DIN ;
2654 prop_atoms = (Atom *) XtMalloc( sizeof( Atom) * num_props) ;
2655 XInternAtoms(dsp, prop_names, num_props, FALSE, prop_atoms);
2657 prop_existed = FALSE ;
2659 while( i < num_props )
2661 if( GetBindingsProperty( dsp, prop_atoms[i], &bindingsString) )
2663 String new_bstring = FixupBindingsString( bindingsString,
2665 prop_existed = TRUE ;
2666 XFree( bindingsString) ;
2668 if( new_bstring != NULL )
2670 SetBindingsProperty( dsp, prop_atoms[i], new_bstring) ;
2671 XtFree( new_bstring) ;
2678 bindingsString = NULL ;
2679 _XmVirtKeysLoadFallbackBindings( dsp, &bindingsString) ;
2680 XtFree( bindingsString) ;
2683 while( i < num_props )
2685 if( GetBindingsProperty( dsp, prop_atoms[i], &bindingsString) )
2687 String new_bstring = FixupBindingsString( bindingsString,
2689 XtFree( bindingsString) ;
2690 if( new_bstring != NULL )
2692 PropChanged4DIN = TRUE ;
2693 SetBindingsProperty( dsp, prop_atoms[i], new_bstring) ;
2694 XtFree( new_bstring) ;
2696 XFree( bindingsString) ;
2702 XtFree( (char *) vkeysym_xref) ;
2703 XtFree( (char *) prop_atoms) ;
2704 return PropChanged4DIN ;
2706 #endif /* NO_HP_KEY_REMAP */
2709 /**************************** eof ***************************/