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 <Xm/AtomMgr.h>
63 #include <X11/Shell.h>
65 #include <X11/keysym.h>
66 #ifndef NO_HP_KEY_REMAP
67 #include <Xm/VirtKeysP.h>
69 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
70 # include <Xm/DrawingA.h>
71 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
77 } str_xref_rec, *str_xref ;
78 #endif /* NO_HP_KEY_REMAP */
80 #include <Dt/GetDispRes.h>
81 #include <Dt/SessionP.h>
82 #include <Dt/SessionM.h>
84 #include <Dt/Message.h>
86 #include <Dt/EnvControlP.h>
89 /* Busy is also defined in the BMS -> bms.h. This conflicts with
90 * /usr/include/X11/Xasync.h on ibm.
97 #include <X11/Xlibint.h>
100 * include extern functions
103 #include "WmBackdrop.h"
105 #include "WmCDInfo.h"
106 #include "WmColormap.h"
109 #include "WmFeedback.h"
110 #include "WmFunction.h"
111 #include "WmIDecor.h"
115 #include "WmIPlace.h"
116 #include "WmIconBox.h"
117 #include "WmKeyFocus.h"
119 #include "WmPanelP.h" /* for typedef in WmManage.h */
120 #endif /* PANELIST */
121 #include "WmManage.h"
124 #include "WmPresence.h"
126 #include "WmProperty.h"
127 #include "WmResCvt.h"
128 #include "WmResource.h"
129 #include "WmSignal.h"
130 #include "WmProtocol.h"
131 #include "WmCDecor.h"
133 #include "WmResParse.h"
140 * Function Declarations:
143 #include "WmInitWs.h"
145 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
146 # include "WmWsmLib/wsm_proto.h"
147 # include "WmWsmLib/utm_send.h"
148 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
151 static void InsureDefaultBackdropDir(char **ppchBackdropDirs);
153 void InitWmDisplayEnv (void);
154 #ifndef NO_MESSAGE_CATALOG
155 void InitNlsStrings (void);
157 #ifndef NO_HP_KEY_REMAP
158 Boolean VirtKeys4DIN(Display *dpy);
159 #endif /* NO_HP_KEY_REMAP */
162 /* limited to 3 chars max */
163 #define UNSPECIFIED_SCREEN_NAME "fbk"
164 char **dpy2Argv; /* copy for second display */
167 WmScreenData *dtSD; /* for the "DT screen" of the display */
168 #endif /* PANELIST */
173 extern int firstTime;
174 #ifndef NO_MESSAGE_CATALOG
175 extern char * pWarningStringFile;
176 extern char * pWarningStringLine;
182 * Special case for a two button mouse; move the BMENU binding
183 * from Button3 to Button2. Fails for one-button mice.
186 InitMouseBinding(void)
188 wmGD.numMouseButtons = XGetPointerMapping(DISPLAY, (unsigned char *)0, 0);
190 if (wmGD.numMouseButtons < 3) {
191 wmGD.bMenuButton = Button2;
193 wmGD.bMenuButton = Button3;
197 /******************************<->*************************************
199 * BuildLockMaskSequence ()
201 * Set up the sequence of modifier masks to use to when grabbing
202 * key- and button-bindings. This sequence of masks is NULL
206 * wmGD.lockingModMask
209 * wmGD.pLockMaskSequence
212 *************************************<->***********************************/
214 BuildLockMaskSequence(void)
218 unsigned int thisbit;
226 * Count the bits to determine the number of elements in
227 * the mask sequence. The actual number of masks is
228 * 2^<bitcount> - 1. We're not interested in the case
229 * where there none of the mask bits are set.
231 mask = wmGD.lockingModMask;
242 num_masks = (0x1 << num_bits) - 1;
245 * Allocate the space for the mask sequence + terminator.
247 wmGD.pLockMaskSequence = (unsigned int *)
248 XtCalloc (num_masks+1, sizeof (unsigned int));
251 * Fill in the mask sequence
253 mask = wmGD.lockingModMask;
256 while (mask && thisbit)
259 while (!(thisbit & mask))
261 thisbit = thisbit << 1;
264 /* clear it from mask */
270 * Set it in the appropriate slots in the
271 * mask sequence. The start of the loop is
272 * funny because we skip the case of all the
275 run = (0x1 << bit-1); /* number of consecutive masks to set
277 bit_on = False; /* are we setting bits or not? */
279 for (j=0, k=run-1; j<num_masks; j++, k--)
291 if (bit_on) wmGD.pLockMaskSequence[j] |= thisbit;
297 /******************************<->*************************************
299 * SetupLockingModifierMask ()
301 * Set up the mask used to ignore locking modifier keys (e.g. Shift Lock)
302 * when processing key- and button-bindings.
304 * We want to try to ignore the set of locking modifers
305 * such as Shift Lock, Num Lock, Kana Lock, etc. This involves
306 * some amount of guessing since these things can be mapped
307 * onto any of the Mod1-Mod5 modifiers. The approach taken is to
308 * identify the mapping of the locking modifier keysyms to
309 * Mod1-Mod5 and build the set of masks needed to ignore them.
311 *************************************<->***********************************/
314 * This is the set of locking modifiers keysyms that might be
315 * bound to Mod1-Mod5. (Caps Lock is handled independently of
318 static KeySym pksLockingMods[] = {
325 #define NUM_LOCKING_MODS (sizeof(pksLockingMods)/sizeof(KeySym))
328 SetupLockingModifierMask(void)
330 int i, j, start_index;
331 XModifierKeymap *modifier_map = NULL;
332 static Modifiers mod_masks[] = { None, Mod1Mask, Mod2Mask,
333 Mod3Mask, Mod4Mask, Mod5Mask };
334 Display *dpy = wmGD.display;
335 int pkcLockingMods[NUM_LOCKING_MODS];
339 for (i=0; i<NUM_LOCKING_MODS; i++)
341 pkcLockingMods[i] = XKeysymToKeycode(dpy, pksLockingMods[i]);
345 * Start out with Caps lock and add others we discover.
347 wmGD.lockingModMask = LockMask;
349 modifier_map = XGetModifierMapping(dpy);
351 /* just check Mod1 through Mod5 */
352 start_index = modifier_map->max_keypermod * Mod1MapIndex;
354 for (i = start_index; i < modifier_map->max_keypermod * 8; i++) {
355 int this_mod = ((i - start_index) / modifier_map->max_keypermod) + 1;
357 kc = modifier_map->modifiermap[i];
360 for (j=0; j<NUM_LOCKING_MODS; j++)
362 if (pkcLockingMods[j] == kc)
364 wmGD.lockingModMask |= mod_masks[this_mod];
371 BuildLockMaskSequence();
373 if(modifier_map != NULL)
374 XFreeModifiermap(modifier_map);
378 /******************************<->*************************************
380 * MappingEventHandler (Widget, XtPointer, XEvent *, Boolean *)
382 * Catch and handle changes to the mapping of the modifier keys.
384 *************************************<->***********************************/
389 XtPointer client_data,
391 Boolean *cont_to_dispatch)
393 if(event->xany.type != MappingNotify ||
394 event->xmapping.request == MappingPointer)
397 if(event->xmapping.request == MappingModifier)
398 SetupLockingModifierMask();
402 /******************************<->*************************************
404 * InitWmGlobal (argc, argv, environ)
409 * This function initializes the workspace manager.
414 * argc = number of command line arguments (+1)
416 * argv = window manager command line arguments
418 * environ = window manager environment
423 * wmGD = (initialize the global data structure)
425 *************************************<->***********************************/
427 void InitWmGlobal (int argc, char *argv [], char *environ [])
429 XSetWindowAttributes sAttributes;
433 Boolean activeSet = False;
434 Boolean processedGlobalResources = False;
441 wmGD.errorFlag = False;
447 wmGD.iSlideUpsInProgress = 0;
451 SetupWmSignalHandlers (0); /* dummy paramater */
455 * Do (pre-toolkit) initialization:
458 wmGD.windowContextType = XUniqueContext ();
459 wmGD.screenContextType = XUniqueContext ();
461 wmGD.cmapWindowContextType = XUniqueContext ();
464 wmGD.mwmWindowContextType = XUniqueContext ();
467 /* copy argv (the XtInititalize changes the original) for use in restart */
469 CopyArgv (argc, argv);
471 wmGD.environ = environ;
474 wmGD.pWmPB = _DtWmParseNewBuf();
480 if ((wmGD.mwmName = (char*)strrchr (wmGD.argv[0], '/')) != NULL)
486 wmGD.mwmName = wmGD.argv[0];
491 res_class = WM_RESOURCE_CLASS;
495 res_class = DT_WM_RESOURCE_CLASS;
497 wmGD.statusColorServer = CSERVE_NOT_AVAILABLE;
500 res_class = WM_RESOURCE_CLASS;
503 wmGD.display = (Display *)NULL;
504 wmGD.topLevelW = (Widget)NULL;
507 * Do X Tookit initialization:
510 XtToolkitInitialize();
512 wmGD.mwmAppContext = XtCreateApplicationContext();
513 AddWmResourceConverters ();
514 wmGD.display = XtOpenDisplay (wmGD.mwmAppContext,
520 &argc, /* R5 changed from Cardinal to int*/
525 Warning(((char *)GETMESSAGE(40, 1, "Could not open display.")));
526 ExitWM (WM_ERROR_EXIT_VALUE);
529 #if defined(sun) && defined(ALLPLANES)
533 wmGD.allplanes = XAllPlanesQueryExtension(wmGD.display,
536 #endif /* defined(sun) && defined(ALLPLANES) */
539 * Setup error handling:
542 WmInitErrorHandler(wmGD.display);
545 * Initialize cursor size info and
546 * display the startup cursor.
553 ShowWaitState (TRUE);
556 * Initialize support for BMenu virtual mouse binding
560 * Set up the _MOTIF_BINDINGS property on the root window
561 * of screen 0. Must do this before we create shells.
564 ProcessMotifBindings ();
565 #ifndef NO_HP_KEY_REMAP
567 /* VirtKeys4DIN deals with a shortcoming in the OSF/Motif
568 * mechanism for selecting a virtual key binding table.
569 * When a client connects to a display, code inside of libXm
570 * gets the vendor identifier from the server and uses this
571 * identifier to select a default virtual key binding table
572 * from an internal list of possible tables (provided to
573 * OSF by vendors). A virtual key binding table maps OSF
574 * virtual keysyms to an "appropriate" set of X keysyms for
575 * a particular server vendor. The problem with this
576 * mechanism is that it only allows for a _single_ default
577 * virtual key binding table per server vendor. If a
578 * hardware vendor ships more than one distinct keyboard,
579 * then the single virtual key binding table selected for
580 * that server might not be appropriate for all keyboards.
581 * The HP migration from the "ITF" keyboard to the "PC-style"
582 * keyboard causes this problem to be exposed for Motif
583 * clients. The default HP virtual key binding table maps
584 * osfInsert and osfDelete to hpInsertChar and hpDeleteChar,
585 * respectively. But since hpInsertChar and hpDeleteChar
586 * are absent from the PC-style keyboard, HP servers with
587 * this keyboard do not generate key events that map to the
588 * important osfInsert and osfDelete virtual keys.
589 * The Motif 1.2 version of libXm installs (one or two)
590 * properties on the root window, these properties exporting
591 * the virtual key binding table to be used by all (subsequently
592 * connected) Motif clients. The VirtKeys4DIN routine attempts
593 * to ensure that the virtual key binding table exported by
594 * those properties does not include dependencies on keysyms
595 * that are not available in the server's current modmap.
596 * The routine accomplishes this by searching the keyboard
597 * mapping of the display for the absence of known problematic
598 * keysyms. For those keysyms that are missing from the
599 * keyboard map, the corresponding dependencies in the
600 * virtual key binding table are altered to use pre-determined
601 * substitutes (which are generic X keysyms that are present
602 * on the PC-style keyboard mapping).
603 * The side-effects of this routine are that if there are no
604 * key binding properties on the root window when this routine
605 * is called, there will be a property installed (this occurs
606 * with all Motif 1.2 clients anyway). Since the virtual key
607 * binding table is only altered if it contains a keysym that
608 * is missing from the server's keyboard mapping, there is
609 * little chance of deleterious effects.
611 VirtKeys4DIN(DISPLAY);
612 #endif /* NO_HP_KEY_REMAP */
615 XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
616 XtSetArg (args[argnum], XtNx, 10000); argnum++;
617 XtSetArg (args[argnum], XtNy, 0); argnum++;
618 XtSetArg (args[argnum], XtNwidth, 10); argnum++;
619 XtSetArg (args[argnum], XtNheight, 10); argnum++;
620 XtSetArg (args[argnum], XtNmappedWhenManaged, False); argnum++;
621 XtSetArg (args[argnum], XtNjoinSession, True); argnum++;
623 XtSetArg (args[argnum], XtNrestartStyle, SmRestartNever); argnum++;
625 XtSetArg (args[argnum], XtNrestartStyle, SmRestartIfRunning); argnum++;
627 XtSetArg (args[argnum], XtNargc, savedArgc); argnum++;
628 XtSetArg (args[argnum], XtNargv, wmGD.argv); argnum++;
630 /* create topmost shell (application shell) */
631 wmGD.topLevelW = XtAppCreateShell (NULL,
633 sessionShellWidgetClass,
639 _XmColorObjCreate ( wmGD.topLevelW, NULL, NULL);
640 _XmColorObjCreate ( wmGD.topLevelW, NULL, NULL);
643 XtAddEventHandler(wmGD.topLevelW, NoEventMask, True,
644 MappingEventHandler, NULL);
646 /* Add callbacks used for communication with Session Manager. */
649 /* allocate namespace for screens */
653 * Determine the screen management policy (all or none)
654 * Process command line arguments that we handle
655 * This could change the number of screens we manage
657 ProcessGlobalScreenResources ();
658 ProcessCommandLine (argc, argv);
662 * Make sure backdrops are in our icon search path.
663 * This call MUST occur before ANY icons are looked up either
664 * explicitly or through resource processing!!!
665 * Uses variables set by ProcessGlobalScreenResources and
666 * ProcessCommandLine.
671 Boolean useMultiColorIcons;
672 Boolean useIconFileCacheRtn;
675 sNum = (wmGD.numScreens == 1) ? DefaultScreen(DISPLAY) : 0;
677 XmeGetIconControlInfo(ScreenOfDisplay(DISPLAY, sNum), &useMaskRtn,
678 &useMultiColorIcons, &useIconFileCacheRtn);
680 sBdPath = wmGD.backdropDirs;
681 InsureDefaultBackdropDir ((char **) &sBdPath);
683 _DtWsmSetBackdropSearchPath(XScreenOfDisplay(DISPLAY, sNum),
684 sBdPath, useMultiColorIcons);
691 * Allocate data and initialize for screens we manage:
694 if (!(wmGD.Screens = (WmScreenData *)
695 XtCalloc (wmGD.numScreens, sizeof(WmScreenData))))
697 ShowWaitState (FALSE);
698 Warning (((char *)GETMESSAGE(40, 2, "Insufficient memory for Screen data")));
699 ExitWM (WM_ERROR_EXIT_VALUE);
704 sAttributes.event_mask = SubstructureRedirectMask;
706 for (scr=0; scr<wmGD.numScreens; scr++)
711 * Gain control of the root windows of each screen:
714 sNum = (wmGD.numScreens == 1) ? DefaultScreen(DISPLAY) : scr;
715 wmGD.errorFlag = False;
717 XChangeWindowAttributes (DISPLAY, RootWindow (DISPLAY, sNum),
718 CWEventMask, &sAttributes);
720 * Do XSync to force server action and catch errors
723 XSync (DISPLAY, False /* do not discard events */);
725 if ((wmGD.errorFlag) &&
726 (RootWindow (DISPLAY, sNum) == (Window) wmGD.errorResource) &&
727 (wmGD.errorRequestCode == X_ChangeWindowAttributes))
730 ((char *)GETMESSAGE(40, 3, "Another window manager is running on screen %d")), sNum);
731 Warning ((char *) &pch[0]);
732 wmGD.Screens[scr].managed = False;
736 if (!processedGlobalResources)
740 XA_DT_SESSION_HINTS, XA_DT_SM_WM_PROTOCOL,
741 XA_DT_SM_START_ACK_WINDOWS, XA_DT_SM_STOP_ACK_WINDOWS,
742 XA_DT_WM_WINDOW_ACK, XA_DT_WM_EXIT_SESSION,
743 XA_DT_WM_LOCK_DISPLAY, XA_DT_WM_READY, NUM_ATOMS };
744 static char *atom_names[] = {
745 _XA_DT_SESSION_HINTS, _XA_DT_SM_WM_PROTOCOL,
746 _XA_DT_SM_START_ACK_WINDOWS, _XA_DT_SM_STOP_ACK_WINDOWS,
747 _XA_DT_WM_WINDOW_ACK, _XA_DT_WM_EXIT_SESSION,
748 _XA_DT_WM_LOCK_DISPLAY, _XA_DT_WM_READY };
750 Atom atoms[XtNumber(atom_names)];
751 XInternAtoms(DISPLAY, atom_names, XtNumber(atom_names),
754 wmGD.xa_DT_SESSION_HINTS = atoms[XA_DT_SESSION_HINTS];
755 wmGD.xa_DT_SM_WM_PROTOCOL = atoms[XA_DT_SM_WM_PROTOCOL];
756 wmGD.xa_DT_SM_START_ACK_WINDOWS =
757 atoms[XA_DT_SM_START_ACK_WINDOWS];
758 wmGD.xa_DT_SM_STOP_ACK_WINDOWS =
759 atoms[XA_DT_SM_STOP_ACK_WINDOWS];
760 wmGD.xa_DT_WM_WINDOW_ACK = atoms[XA_DT_WM_WINDOW_ACK];
761 wmGD.xa_DT_WM_EXIT_SESSION = atoms[XA_DT_WM_EXIT_SESSION];
762 wmGD.xa_DT_WM_LOCK_DISPLAY = atoms[XA_DT_WM_LOCK_DISPLAY];
763 wmGD.xa_DT_WM_READY = atoms[XA_DT_WM_READY];
767 #endif /* NO_OL_COMPAT */
769 wmGD.hasShape = XShapeQueryExtension (DISPLAY,
770 &wmGD.shapeEventBase,
771 &wmGD.shapeErrorBase);
772 #endif /* NO_SHAPE */
774 wmGD.replayEnterEvent = False;
775 wmGD.menuActive = NULL;
776 wmGD.menuUnpostKeySpec = NULL;
777 wmGD.F_NextKeySpec = NULL;
778 wmGD.F_PrevKeySpec = NULL;
779 wmGD.passKeysActive = False;
780 wmGD.passKeysKeySpec = NULL;
781 wmGD.checkHotspot = False;
782 wmGD.configAction = NO_ACTION;
783 wmGD.configPart = FRAME_NONE;
784 wmGD.configSet = False;
785 wmGD.preMove = False;
786 wmGD.gadgetClient = NULL;
787 wmGD.wmTimers = NULL;
788 wmGD.clientDefaultTitle =
789 XmStringCreateLocalized(DEFAULT_CLIENT_TITLE);
790 wmGD.iconDefaultTitle =
791 XmStringCreateLocalized(DEFAULT_ICON_TITLE);
792 wmGD.attributesWindow = (Window)NULL;
793 wmGD.clickData.pCD = NULL;
794 wmGD.clickData.clickPending = False;
795 wmGD.clickData.doubleClickPending = False;
796 wmGD.systemModalActive = False;
797 wmGD.activeIconTextDisplayed = False;
798 wmGD.movingIcon = False;
799 wmGD.queryScreen = True;
800 wmGD.dataType = GLOBAL_DATA_TYPE;
802 wmGD.pLockMaskSequence = NULL;
803 SetupLockingModifierMask ();
805 wmGD.requestContextWin = (Window) 0L;
806 wmGD.cppCommand = NULL;
807 wmGD.evLastButton.button = 0;
808 wmGD.bReplayedButton = False;
809 wmGD.bSuspendSecondaryRestack = False;
811 * Get a second display connection for
812 * internal WM windows.
814 wmGD.display1 = XtOpenDisplay (wmGD.mwmAppContext,
824 ShowWaitState (FALSE);
825 Warning(((char *)GETMESSAGE(40, 4, "Could not open second display connection.")));
826 ExitWM (WM_ERROR_EXIT_VALUE);
829 _DtGetSmWindow(DISPLAY,
830 RootWindow(DISPLAY, 0),
834 * If this is the first screen we've managed,
835 * tell the session manager we're ready
837 if (!processedGlobalResources)
839 SendClientMsg( wmGD.dtSmWindow,
840 (long) wmGD.xa_DT_SM_WM_PROTOCOL,
841 (long) wmGD.xa_DT_WM_READY,
842 CurrentTime, NULL, 0);
844 #endif /* PANACOMM */
846 /* create topmost shell (application shell) */
848 XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
849 XtSetArg (args[argnum], XtNx, 10000); argnum++;
850 XtSetArg (args[argnum], XtNy, 0); argnum++;
851 XtSetArg (args[argnum], XtNwidth, 10); argnum++;
852 XtSetArg (args[argnum], XtNheight, 10); argnum++;
853 XtSetArg (args[argnum],
854 XtNmappedWhenManaged, False); argnum++;
857 XtAppCreateShell (NULL,
859 applicationShellWidgetClass,
868 * if this is the first screen we can manage,
872 processedGlobalResources = True;
875 * Get the _MOTIF_WM_INFO property and determine
876 * the startup / restart state.
879 ProcessMotifWmInfo (RootWindow (DISPLAY, sNum));
882 * Process global window manager resources:
884 #ifndef NO_MESSAGE_CATALOG
885 InitBuiltinSystemMenu();
888 ProcessWmResources ();
892 InitWmScreen (&(wmGD.Screens[scr]), sNum);
893 wmGD.Screens[scr].managed = True;
896 GetDtSessionHints(&(wmGD.Screens[scr]), sNum);
902 ACTIVE_PSD = &wmGD.Screens[scr];
910 * No screens for me to manage, give up.
912 ShowWaitState (FALSE);
913 Warning (((char *)GETMESSAGE(40, 5, "Unable to manage any screens on display.")));
914 ExitWM (WM_ERROR_EXIT_VALUE);
919 * Initialize the IPC mechanism
921 dtInitialize(argv[0], wmGD.mwmAppContext);
922 #ifndef NO_MESSAGE_CATALOG
924 * Set up NLS error messages.
925 * Must be done after DtInitialize.
931 * For multiple connections to the server, turn off
932 * the geometry manager's insistence on synchronous
937 XtSetArg (args[argnum], XmNuseAsyncGeometry, True); argnum++;
938 XtSetValues (wmGD.topLevelW, args, argnum);
939 XtSetValues (wmGD.topLevelW1, args, argnum);
945 * Prepare to have child processes (e.g., exec'ed commands).
946 * The X connection should not be passed on to child processes
947 * (it should be automatically closed when a fork is done).
950 if (fcntl (ConnectionNumber (DISPLAY), F_SETFD, 1) == -1)
952 ShowWaitState (FALSE);
953 Warning (((char *)GETMESSAGE(40, 6, "Cannot configure X connection")));
954 ExitWM (WM_ERROR_EXIT_VALUE);
960 enum { XA_DT_WORKSPACE_HINTS, XA_DT_WORKSPACE_PRESENCE,
961 XA_DT_WORKSPACE_INFO, XA_WmNall,
962 XA_DT_WORKSPACE_EMBEDDED_CLIENTS, XA_DT_WM_REQUEST,
963 XA_DT_WORKSPACE_LIST, XA_DT_WORKSPACE_CURRENT, NUM_ATOMS };
964 static char *atom_names[] = {
965 _XA_DT_WORKSPACE_HINTS, _XA_DT_WORKSPACE_PRESENCE,
966 _XA_DT_WORKSPACE_INFO, WmNall,
967 _XA_DT_WORKSPACE_EMBEDDED_CLIENTS, _XA_DT_WM_REQUEST,
968 _XA_DT_WORKSPACE_LIST, _XA_DT_WORKSPACE_CURRENT };
970 Atom atoms[XtNumber(atom_names)];
971 XInternAtoms(DISPLAY, atom_names, XtNumber(atom_names), False, atoms);
973 wmGD.xa_DT_WORKSPACE_HINTS = atoms[XA_DT_WORKSPACE_HINTS];
974 wmGD.xa_DT_WORKSPACE_PRESENCE = atoms[XA_DT_WORKSPACE_PRESENCE];
975 wmGD.xa_DT_WORKSPACE_INFO = atoms[XA_DT_WORKSPACE_INFO];
976 wmGD.xa_ALL_WORKSPACES = atoms[XA_WmNall];
977 wmGD.xa_DT_EMBEDDED_CLIENTS = atoms[XA_DT_WORKSPACE_EMBEDDED_CLIENTS];
978 wmGD.xa_DT_WM_REQUEST = atoms[XA_DT_WM_REQUEST];
979 wmGD.xa_DT_WORKSPACE_LIST = atoms[XA_DT_WORKSPACE_LIST];
980 wmGD.xa_DT_WORKSPACE_CURRENT = atoms[XA_DT_WORKSPACE_CURRENT];
985 /* Initialize properties used in session management. */
986 wmGD.xa_SM_CLIENT_ID =
987 XmInternAtom (DISPLAY, _XA_DT_SM_CLIENT_ID, False);
988 wmGD.xa_WMSAVE_HINT =
989 XmInternAtom (DISPLAY, _XA_DT_WMSAVE_HINT, False);
991 /* Load client resource database. */
992 wmGD.clientResourceDB = LoadClientResourceDB();
995 * Make the window manager workspace window.
996 * Setup the _MOTIF_WM_INFO property on the root window.
999 SetupWmWorkspaceWindows ();
1002 /* make the cursors that the window manager uses */
1003 MakeWorkspaceCursors ();
1006 /* Sync the table used by Mwm's modifier parser to actual modMasks used */
1007 SyncModifierStrings();
1010 * Setup screen data and resources (after processing Wm resources.
1012 for (scr = 0; scr < wmGD.numScreens; scr++)
1014 pSD = &(wmGD.Screens[scr]);
1019 if (XDefaultScreen (wmGD.display) == pSD->screen)
1021 wmGD.commandWindow = wmGD.Screens[scr].wmWorkspaceWin;
1026 * Initialize workspace colormap data.
1029 InitWorkspaceColormap (pSD);
1032 * Process the window manager resource description file (.mwmrc):
1036 ProcessWmFile (pSD, False /* not nested */);
1038 #else /* PANELIST */
1039 ProcessWmFile (pSD);
1040 #endif /* PANELIST */
1044 * Setup default resources for the system menu and key bindings:
1047 SetupDefaultResources (pSD);
1051 * Make global window manager facilities:
1054 if(pSD->iconDecoration & ICON_ACTIVE_LABEL_PART)
1056 /* create active icon window */
1057 CreateActiveIconTextWindow(pSD);
1062 * Make menus and other resources that are used by window manager
1063 * functions that are activated by menus, buttons and keys.
1066 MakeWmFunctionResources (pSD);
1072 * Set root cursor to be a pointer for dtwm
1077 /* Fixes problem on multiscreen where cursor is only
1078 * set on primary screen.
1082 XDefineCursor (DISPLAY,
1083 RootWindow (DISPLAY, scr),
1084 wmGD.workspaceCursor);
1092 * Remove any temp config file we created if we needed to
1093 * convert DT 2.0 syntax to DT 3.0
1095 DeleteTempConfigFileIfAny();
1096 #endif /* PANELIST */
1099 * Point second display's resource data base
1100 * to the first display's resource data base
1101 * so dtwm "clients" change colors dynamically.
1105 wmGD.display1->db = wmGD.display->db;
1109 * Realize the top level widget, make the window override
1110 * redirect so we don't manage it, and then move it out of the way
1113 XtRealizeWidget (wmGD.topLevelW);
1115 XtRealizeWidget (wmGD.topLevelW1);
1118 * Initialize the message handling.
1119 * (This must be done after the realize because a window
1120 * is required for ICCCM-style messaging).
1122 dtInitializeMessaging (wmGD.topLevelW);
1125 sAttributes.override_redirect = True;
1126 XChangeWindowAttributes (DISPLAY, XtWindow (wmGD.topLevelW),
1127 CWOverrideRedirect, &sAttributes);
1130 /* setup window manager inter-client communications conventions handling */
1134 * Use the WM_SAVE_YOURSELF protocol
1135 * for notification of when to save ourself
1138 SetMwmSaveSessionInfo(wmGD.commandWindow);
1141 * Initialize window manager event handling:
1144 InitEventHandling ();
1149 * Initialize frame component graphics
1152 for (scr = 0; scr < wmGD.numScreens; scr++)
1154 pSD = &(wmGD.Screens[scr]);
1158 InitClientDecoration (pSD);
1161 * Make an icon box if specificed:
1163 if (pSD->useIconBox)
1169 * Adopt client windows that exist before wm startup:
1172 AdoptInitialClients (pSD);
1175 * Setup initial keyboard focus and colormap focus:
1178 InitColormapFocus (pSD);
1183 for (scr = 0; scr < wmGD.numScreens; scr++)
1188 pSD = &(wmGD.Screens[scr]);
1192 ACTIVE_PSD = &wmGD.Screens[scr];
1194 MapIconBoxes (pSD->pActiveWS);
1196 ChangeBackdrop (pSD->pActiveWS);
1199 UpdateWorkspaceInfoProperty (pSD); /* backward compatible */
1202 SetCurrentWorkspaceProperty (pSD);
1203 SetWorkspaceListProperty (pSD);
1205 for (iws=0; iws < pSD->numWorkspaces; iws++)
1207 SetWorkspaceInfoProperty (&(pSD->pWS[iws]));
1215 /* MapWorkspaceBox (); */
1219 * Allocate front panel widgets
1221 if (wmGD.useFrontPanel && (pSD == wmGD.dtSD))
1227 WmPanelistObject pPanelist;
1229 wmGD.dtSD->wPanelist =
1230 WmPanelistAllocate(pSD->screenTopLevelW1,
1231 (XtPointer) &wmGD, (XtPointer) pSD);
1233 pPanelist = (WmPanelistObject) pSD->wPanelist;
1235 if (pPanelist != NULL && O_Shell(pPanelist))
1238 * Make a default front panel icon image.
1240 iconBitmap = XCreateBitmapFromData (DISPLAY,
1242 (char *) fntpl_i_bm_bits,
1247 XtSetArg (al[ac], XmNiconPixmap, iconBitmap); ac++;
1248 XtSetValues (O_Shell(pPanelist), al, ac);
1253 if (wmGD.useFrontPanel && pSD->wPanelist &&
1257 * Make the front panel visible
1259 WmPanelistShow (pSD->wPanelist);
1262 * Find special clients associated with the
1263 * front panel. This needs to be done after
1264 * WmPanelistShow where the data is set up.
1266 ScanForPushRecallClients (pSD);
1267 ScanForEmbeddedClients (pSD);
1269 #endif /* PANELIST */
1271 RestoreHelpDialogs(pSD);
1273 MapIconBoxes (pSD->pActiveWS);
1280 InitKeyboardFocus ();
1283 InitWmDisplayEnv ();
1285 ShowWaitState (FALSE);
1289 * Tell the rest of DT that we're up
1291 dtReadyNotification();
1294 #ifdef DEBUG_RESOURCE_DATABASE
1295 XrmPutFileDatabase(wmGD.display->db, "/tmp/dtwm.resDB");
1296 #endif /* DEBUG_RESOURCE_DATABASE */
1298 } /* END OF FUNCTION InitWmGlobal */
1302 /******************************<->*************************************
1309 * This function initializes a screen data block.
1313 * pSD = pointer to preallocated screen data block
1314 * sNum = screen number for this screen
1318 *************************************<->***********************************/
1321 InitWmScreen (WmScreenData *pSD, int sNum)
1328 WmWorkspaceData *pwsI;
1331 static int dupnum = 0;
1336 #define LENCBUFFER 256
1337 char buffer[LENCBUFFER]; /* screen name & display name! */
1338 char displayName[LENCBUFFER];
1339 char *token1, *token2;
1343 * Set screen data values
1346 pSD->rootWindow = RootWindow (DISPLAY, sNum);
1347 pSD->clientCounter = 0;
1348 pSD->defaultSystemMenuUseBuiltin = TRUE;
1349 pSD->displayString = NULL;
1350 pSD->acceleratorMenuCount = 0;
1351 pSD->activeIconTextWin = (Window)NULL;
1352 pSD->focusPriority = 0;
1353 pSD->inputScreenWindow = (Window)NULL;
1354 pSD->colormapFocus = NULL;
1355 pSD->keySpecs = NULL;
1357 pSD->confirmboxW[DEFAULT_BEHAVIOR_ACTION] = NULL;
1358 pSD->confirmboxW[CUSTOM_BEHAVIOR_ACTION] = NULL;
1359 pSD->confirmboxW[RESTART_ACTION] = NULL;
1360 pSD->confirmboxW[QUIT_MWM_ACTION] = NULL;
1361 pSD->feedbackWin = (Window)NULL;
1362 pSD->fbStyle = FB_OFF;
1363 pSD->fbWinWidth = 0;
1364 pSD->fbWinHeight = 0;
1365 pSD->fbLocation[0] = '\0';
1366 pSD->fbSize[0] = '\0';
1373 pSD->fbLastWidth = -1;
1374 pSD->fbLastHeight = -1;
1376 pSD->fbBottom = NULL;
1377 pSD->actionNbr = -1;
1378 pSD->clientList = NULL;
1379 pSD->lastClient = NULL;
1380 pSD->lastInstalledColormap = (Colormap)NULL;
1381 pSD->shrinkWrapGC = NULL;
1382 pSD->bitmapCache = NULL;
1383 pSD->bitmapCacheSize = 0;
1384 pSD->bitmapCacheCount = 0;
1385 pSD->dataType = SCREEN_DATA_TYPE;
1386 pSD->managed = False;
1387 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
1388 pSD->cciTree = NULL;
1389 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
1392 pSD->initialWorkspace=NULL;
1393 pSD->presence.shellW = NULL;
1394 pSD->presence.onScreen = False;
1395 pSD->presence.userDismissed = True;
1396 pSD->workspaceList = NULL;
1397 pSD->numWorkspaces = 0;
1398 pSD->numWsDataAllocated = 0;
1399 pSD->lastBackdropWin = NULL;
1400 pSD->pDtSessionItems = NULL;
1401 pSD->totalSessionItems = 0;
1402 pSD->remainingSessionItems = 0;
1404 pSD->cachedHelp = NULL;
1405 pSD->dtHelp.shell = (Widget)NULL;
1406 pSD->dtHelp.dialog = (Widget)NULL;
1407 pSD->dtHelp.errorDialog = (Widget)NULL;
1408 pSD->dtHelp.xPos = 0;
1409 pSD->dtHelp.yPos = 0;
1410 pSD->dtHelp.restored = False;
1411 pSD->dtHelp.onScreen = False;
1412 pSD->dtHelp.userDismissed = False;
1413 pSD->dtHelp.pCDforClient= NULL;
1414 pSD->helpResources=NULL;
1415 pSD->bMarqueeSelectionInitialized = False;
1416 pSD->woN = (Window) 0L;
1417 pSD->woS = (Window) 0L;
1418 pSD->woE = (Window) 0L;
1419 pSD->woW = (Window) 0L;
1422 pSD->wPanelist = NULL;
1424 pSD->numPushRecallClients = 0;
1425 pSD->numEmbeddedClients = 0;
1427 pSD->iconBoxControl = False;
1428 #endif /* PANELIST */
1430 pSD->displayResolutionType = _DtGetDisplayResolution(DISPLAY, sNum);
1433 * We've got display resolution type--now, let's get color
1437 ProcessWmColors (pSD);
1439 if (!(strcmp ((char *)wmGD.screenNames[sNum], UNSPECIFIED_SCREEN_NAME)))
1441 sprintf (buffer, "%d", sNum);
1443 buf_size = strlen(buffer) + 1;
1445 if ((wmGD.screenNames[sNum] =
1446 (unsigned char *)XtRealloc (wmGD.screenNames[sNum], buf_size)) == NULL)
1448 Warning (((char *)GETMESSAGE(40, 7, "Cannot create enough memory for the screen names")));
1449 ExitWM (WM_ERROR_EXIT_VALUE);
1453 strcpy((char *)wmGD.screenNames[sNum], buffer);
1455 } /* if wmGD.screenNames[sNum] == UNSPECIFIED_SCREEN_NAME */
1459 * Save screen context
1461 XSaveContext (DISPLAY, pSD->rootWindow, wmGD.screenContextType,
1464 * Create shell widget for screen resource hierarchy
1468 XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
1469 XtSetArg (args[argnum], XtNx, 10000); argnum++;
1470 XtSetArg (args[argnum], XtNy, 10000); argnum++;
1471 XtSetArg (args[argnum], XtNwidth, 10); argnum++;
1472 XtSetArg (args[argnum], XtNheight, 10); argnum++;
1473 XtSetArg (args[argnum], XtNoverrideRedirect, True); argnum++;
1475 XtSetArg (args[argnum], XtNdepth,
1476 DefaultDepth(DISPLAY, sNum)); argnum++;
1477 XtSetArg (args[argnum], XtNscreen,
1478 ScreenOfDisplay(DISPLAY, sNum)); argnum++;
1479 XtSetArg (args[argnum], XtNcolormap,
1480 DefaultColormap(DISPLAY, sNum)); argnum++;
1482 pSD->screenTopLevelW = XtCreatePopupShell ((String) wmGD.screenNames[sNum],
1483 vendorShellWidgetClass,
1488 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
1489 /* Create a DrawingArea as a child of the popupShell. This will be used
1490 * to handle UTM traffic relating to cci. We need this
1491 * particular widget to get the callbacks from conversion requests made
1492 * against Mwm and the requests Mwm makes against other clients.
1494 pSD->utmShell = XmCreateDrawingArea(pSD->screenTopLevelW, "UTM_Shell",
1496 XtManageChild(pSD->utmShell);
1499 * Setup the destinationCallback handler to handle conversion
1500 * requests made by Mwm against other clients.
1502 XtAddCallback(pSD->utmShell, XmNdestinationCallback, UTMDestinationProc,
1505 /* Must realize to own WM_i if unmapped, causes mwm to
1506 freeze when menu is displayed. */
1507 XtPopup(pSD->screenTopLevelW, XtGrabNone);
1508 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
1512 XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
1513 XtSetArg (args[argnum], XtNx, 10000); argnum++;
1514 XtSetArg (args[argnum], XtNy, 10000); argnum++;
1515 XtSetArg (args[argnum], XtNwidth, 10); argnum++;
1516 XtSetArg (args[argnum], XtNheight, 10); argnum++;
1517 XtSetArg (args[argnum], XtNoverrideRedirect, True); argnum++;
1518 XtSetArg (args[argnum], XtNmappedWhenManaged, False); argnum++;
1520 XtSetArg (args[argnum], XtNdepth,
1521 DefaultDepth(DISPLAY1, sNum)); argnum++;
1522 XtSetArg (args[argnum], XtNscreen,
1523 ScreenOfDisplay(DISPLAY1, sNum)); argnum++;
1524 XtSetArg (args[argnum], XtNcolormap,
1525 DefaultColormap(DISPLAY1, sNum)); argnum++;
1527 pSD->screenTopLevelW1 = XtCreatePopupShell ((String) wmGD.screenNames[sNum],
1528 vendorShellWidgetClass,
1532 XtRealizeWidget (pSD->screenTopLevelW1);
1535 * Fetch screen based resources
1537 ProcessScreenResources (pSD, wmGD.screenNames[sNum]);
1540 * Initialize other screen resources and parameters
1547 * Complete initialization of workspace structures
1550 pwsI = pSD->pWS; wsnum < pSD->numWorkspaces;
1554 * Set up workspace for this screen
1556 InitWmWorkspace (pwsI, pSD);
1560 if (pSD->initialWorkspace)
1563 * restore to the last initialWorkspace saved from
1564 * Quit, Restart, OR save session
1568 * Compare initialWorkspace against workspace name,
1569 * NOT workspace title.
1571 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
1573 if (!strcmp(pSD->pWS[iwsx].name, pSD->initialWorkspace))
1579 if (iwsx >= pSD->numWorkspaces)
1581 /* make first workspace in list the active one to start with */
1582 pSD->pActiveWS = pSD->pWS;
1586 pSD->pActiveWS = &pSD->pWS[iwsx];
1591 /* make first workspace in list the active one to start with */
1592 pSD->pActiveWS = pSD->pWS;
1596 * Allocate and initialize a workspace structure
1599 if (!(pSD->pWS = (WmWorkspaceData *) XtMalloc (sizeof(WmWorkspaceData))))
1601 ShowWaitState (FALSE);
1602 Warning (((char *)GETMESSAGE(40, 8, "Insufficient memory for Workspace data")));
1603 ExitWM (WM_ERROR_EXIT_VALUE);
1607 * Set up workspace for this screen
1609 InitWmWorkspace (pSD->pWS, pSD);
1610 pSD->pActiveWS = pSD->pWS;
1614 pDisplayName = DisplayString (DISPLAY);
1617 * Construct displayString for this string.
1619 * NOTE: The variable buffer is reused here. It was
1620 * used earlier to generate a screen name.
1623 strcpy(displayName, pDisplayName);
1625 token1 = (char*)strtok(displayName, ":"); /* parse of hostname */
1627 if((token2 = (char*)strtok(NULL, ".")) || /* parse off dpy & scr # */
1628 (token2 = (char*)strtok(NULL, "")) ||
1629 (displayName[0] == ':'))
1631 if (displayName[0] == ':') /* local dpy (special case) */
1633 if ((token2 = (char*)strtok(token1, ".")) != NULL) /* parse dpy# */
1634 sprintf(buffer, "DISPLAY=:%s.%d",
1636 } else { /* otherwise process normally */
1637 sprintf(buffer, "DISPLAY=%s:%s.%d",
1638 token1, token2, sNum);
1642 * Allocate space for the display string
1645 if ((pSD->displayString =
1646 (String)XtMalloc ((unsigned int) (strlen(buffer) + 1))) == NULL)
1648 Warning (((char *)GETMESSAGE(40, 9,
1649 "Insufficient memory for displayString")));
1653 strcpy(pSD->displayString, buffer);
1660 } /* END OF FUNCTION InitWmScreen */
1663 /*************************************<->*************************************
1670 * This function initializes a workspace data block.
1674 * pWS = pointer to preallocated workspace data block
1675 * pSD = ptr to parent screen data block
1679 *************************************<->***********************************/
1681 void InitWmWorkspace (WmWorkspaceData *pWS, WmScreenData *pSD)
1687 #define DEFAULT_WS_NAME "workspace"
1688 #endif /* not WSM */
1691 pWS->pIconBox = NULL;
1692 pWS->dataType = WORKSPACE_DATA_TYPE;
1694 pWS->backdrop.window = 0;
1695 pWS->backdrop.nameAtom = 0;
1696 pWS->backdrop.image = NULL;
1697 pWS->numClients = 0;
1698 pWS->sizeClientList = 0;
1700 pWS->buttonW = NULL;
1703 if ((pWS->name = (char *)
1704 XtMalloc ((1+strlen(DEFAULT_WS_NAME)) * sizeof (char))) == NULL)
1706 ShowWaitState (FALSE);
1707 ExitWM (WM_ERROR_EXIT_VALUE);
1709 strcpy (pWS->name, DEFAULT_WS_NAME);
1713 * Create widget for workspace resource hierarchy
1716 XtSetArg (args[argnum], XtNdepth,
1717 DefaultDepth(DISPLAY, pSD->screen)); argnum++;
1718 XtSetArg (args[argnum], XtNscreen,
1719 ScreenOfDisplay(DISPLAY, pSD->screen)); argnum++;
1720 XtSetArg (args[argnum], XtNcolormap,
1721 DefaultColormap(DISPLAY, pSD->screen)); argnum++;
1722 XtSetArg (args[argnum], XtNwidth, 5); argnum++;
1723 XtSetArg (args[argnum], XtNheight, 5); argnum++;
1725 pWS->workspaceTopLevelW = XtCreateWidget ( pWS->name,
1726 xmPrimitiveWidgetClass,
1727 pSD->screenTopLevelW,
1732 /* internalize the workspace name */
1733 pWS->id = XInternAtom (DISPLAY, pWS->name, False);
1737 * Process workspace based resources
1739 ProcessWorkspaceResources (pWS);
1741 /* setup icon placement */
1742 if (wmGD.iconAutoPlace)
1744 InitIconPlacement (pWS);
1747 } /* END OF FUNCTION InitWmWorkspace */
1751 /******************************<->*************************************
1753 * InsureDefaultBackdropDir(char **ppchBackdropDirs)
1758 * This function checks and edits a directory path to insure
1759 * that the system backdrop directroy (/usr/dt/backdrops) is in the
1760 * path. If not it adds it to the end. Further, it always adds the user's
1761 * backdrop directory ($HOME/.dt/backdrops) to the beginning of the path
1762 * and the system admin directory (/etc/dt/backdrops) before the system
1767 * ppchBackdropDirs - Pointer to a pointer to a directory path
1768 * (must be allocated memory)
1772 * *ppchBackdropDirs - Directory path may be modified, path
1773 * pointer may be realloc'ed.
1777 * Assumes that the default directory does not start with a
1778 * multi-byte character.
1780 ******************************<->***********************************/
1782 InsureDefaultBackdropDir(char **ppchBackdropDirs)
1785 Boolean bFound = False;
1786 char *pch, *pchEnd, *pch2, *tmpptr;
1787 char *pchD = DEFAULT_BACKDROP_DIR;
1792 * Set up initial stuff
1794 pch = *ppchBackdropDirs;
1795 len = strlen (pchD);
1796 pchEnd = pch + strlen(pch);
1798 while (!bFound && (pch != NULL) && (*pch != NULL))
1800 if (strncmp (pch, pchD, len) == 0)
1802 /* found partial match, confirm complete match ...
1803 * complete match if char off end of partial match
1804 * is a NULL or a colon
1807 if ((pch2 <= pchEnd) &&
1809 (((mblen (pch2, MB_CUR_MAX) == 1) &&
1817 /* find next path component */
1818 pch = strchr (pch, (int) ':');
1819 if ((pch != NULL) && (*pch != NULL))
1821 /* skip path separator */
1822 chlen = mblen (pch, MB_CUR_MAX);
1830 * Always add the user's home directory to the beginning of the string
1832 homeDir = (char *) XmeGetHomeDirName();
1835 * If found add the user's home directory ($HOME/.dt/backdrops) and the
1836 * admin directory /etc/dt/backdrops to the beginning of the string
1841 len = strlen (homeDir) + strlen("/.dt/backdrops") +
1842 strlen (*ppchBackdropDirs) + strlen("/etc/dt/backdrops") + 3;
1843 tmpptr = XtMalloc (len * sizeof (char *));
1844 strcpy (tmpptr, homeDir);
1845 strcat (tmpptr, "/.dt/backdrops");
1846 strcat (tmpptr, ":");
1847 strcat (tmpptr, "/etc/dt/backdrops");
1848 strcat (tmpptr, ":");
1849 strcat (tmpptr, *ppchBackdropDirs);
1850 *ppchBackdropDirs = tmpptr;
1854 * If string not found, then add home directory to the beginning of
1855 * string and the admin directory and system directory to the end.
1858 len = strlen (homeDir) + strlen("/.dt/backdrops") +
1859 strlen (*ppchBackdropDirs) + strlen(pchD) +
1860 strlen("/etc/dt/backdrops") + 4;
1861 tmpptr = XtMalloc (len * sizeof (char *));
1862 strcpy (tmpptr, homeDir);
1863 strcat (tmpptr, "/.dt/backdrops");
1864 strcat (tmpptr, ":");
1865 strcat (tmpptr, *ppchBackdropDirs);
1866 strcat (tmpptr, ":");
1867 strcat (tmpptr, "/etc/dt/backdrops");
1868 strcat (tmpptr, ":");
1869 strcat (tmpptr, pchD);
1870 *ppchBackdropDirs = tmpptr;
1873 } /* END OF FUNCTION InsureDefaultBackdropDirs */
1877 /*************************************<->*************************************
1879 * ProcessMotifWmInfo (rootWindowOfScreen)
1884 * This function is used retrieve and save the information in the
1885 * _MOTIF_WM_INFO property. If the property does not exist then
1886 * the start / restart state is set to initial startup with the
1887 * user specified (not standard) configuration.
1892 * wmGD.useStandardBehavior = True if set indicated in property
1894 * wmGD.wmRestarted = True if the window manager was restarted
1896 *************************************<->***********************************/
1898 void ProcessMotifWmInfo (Window rootWindowOfScreen)
1902 wmGD.xa_MWM_INFO = XInternAtom (DISPLAY, _XA_MWM_INFO, False);
1903 if ((pMwmInfo = (MotifWmInfo *)GetMwmInfo (rootWindowOfScreen)) != NULL)
1905 wmGD.useStandardBehavior =
1906 (pMwmInfo->flags & MWM_INFO_STARTUP_STANDARD) ? True : False;
1907 wmGD.wmRestarted = True;
1908 XFree ((char *)pMwmInfo);
1912 wmGD.useStandardBehavior = False;
1913 wmGD.wmRestarted = False;
1916 } /* END OF FUNCTION ProcessMotifWmInfo */
1920 /*************************************<->*************************************
1922 * SetupWmWorkspaceWindows ()
1927 * This function is used to setup a window that can be used in doing window
1928 * management functions. This window is not visible on the screen.
1933 * pSD->wmWorkspaceWin = window that is used to hold wm properties
1935 *************************************<->***********************************/
1937 void SetupWmWorkspaceWindows (void)
1941 XSetWindowAttributes sAttributes;
1943 for (scr = 0; scr < wmGD.numScreens; scr++)
1945 pSD = &(wmGD.Screens[scr]);
1948 sAttributes.override_redirect = True;
1949 sAttributes.event_mask = FocusChangeMask | PropertyChangeMask;
1950 pSD->wmWorkspaceWin = XCreateWindow (DISPLAY, pSD->rootWindow,
1951 -100, -100, 10, 10, 0, 0,
1952 InputOnly, CopyFromParent,
1953 (CWOverrideRedirect |CWEventMask),
1956 XMapWindow (DISPLAY, pSD->wmWorkspaceWin);
1958 SetMwmInfo (pSD->rootWindow,
1959 (long) ((wmGD.useStandardBehavior) ?
1960 MWM_INFO_STARTUP_STANDARD : MWM_INFO_STARTUP_CUSTOM),
1961 pSD->wmWorkspaceWin);
1963 XSaveContext (DISPLAY, pSD->wmWorkspaceWin,
1964 wmGD.mwmWindowContextType, (caddr_t)pSD);
1969 } /* END OF FUNCTION SetupWmWorkspaceWindow */
1973 /*************************************<->*************************************
1975 * MakeWorkspaceCursors ()
1980 * This function makes the cursors that the window manager uses.
1992 * wmGD = (stretchCursors ...)
1994 *************************************<->***********************************/
1996 void MakeWorkspaceCursors (void)
1998 wmGD.workspaceCursor = XCreateFontCursor (DISPLAY, XC_left_ptr);
2000 wmGD.stretchCursors[STRETCH_NORTH_WEST] =
2001 XCreateFontCursor (DISPLAY, XC_top_left_corner);
2002 wmGD.stretchCursors[STRETCH_NORTH] =
2003 XCreateFontCursor (DISPLAY, XC_top_side);
2004 wmGD.stretchCursors[STRETCH_NORTH_EAST] =
2005 XCreateFontCursor (DISPLAY, XC_top_right_corner);
2006 wmGD.stretchCursors[STRETCH_EAST] =
2007 XCreateFontCursor (DISPLAY, XC_right_side);
2008 wmGD.stretchCursors[STRETCH_SOUTH_EAST] =
2009 XCreateFontCursor (DISPLAY, XC_bottom_right_corner);
2010 wmGD.stretchCursors[STRETCH_SOUTH] =
2011 XCreateFontCursor (DISPLAY, XC_bottom_side);
2012 wmGD.stretchCursors[STRETCH_SOUTH_WEST] =
2013 XCreateFontCursor (DISPLAY, XC_bottom_left_corner);
2014 wmGD.stretchCursors[STRETCH_WEST] =
2015 XCreateFontCursor (DISPLAY, XC_left_side);
2017 wmGD.configCursor = XCreateFontCursor (DISPLAY, XC_fleur);
2019 wmGD.movePlacementCursor = XCreateFontCursor (DISPLAY, XC_ul_angle);
2020 wmGD.sizePlacementCursor = XCreateFontCursor (DISPLAY, XC_lr_angle);
2023 } /* END OF FUNCTION MakeWorkspaceCursors */
2027 /*************************************<->*************************************
2029 * MakeWmFunctionResources (pSD)
2034 * This function makes menus and other resources that are used by window
2035 * manager functions.
2040 * wmGD = (menuSpecs, keySpecs, buttonSpecs)
2045 * wmGD (menuSpecs) = new menu panes, protocol atoms
2047 *************************************<->***********************************/
2049 void MakeWmFunctionResources (WmScreenData *pSD)
2051 ButtonSpec *buttonSpec;
2054 Context menuContext;
2058 * Scan through the menu specifications and make wm protocol atoms.
2063 * Scan through the button binding specifications making menus if the
2064 * f.menu function is invoked.
2067 buttonSpec = pSD->buttonSpecs;
2070 if (buttonSpec->wmFunction == F_Menu)
2072 if (buttonSpec->context & F_CONTEXT_WINDOW)
2074 menuContext = F_CONTEXT_WINDOW;
2076 else if (buttonSpec->context & F_CONTEXT_ICON)
2078 menuContext = F_CONTEXT_ICON;
2082 menuContext = F_CONTEXT_ROOT;
2085 menuSpec = MAKE_MENU (pSD, NULL, buttonSpec->wmFuncArgs,
2087 buttonSpec->context,
2088 (MenuItem *) NULL, FALSE);
2092 * If successful, save in pSD->acceleratorMenuSpecs
2093 * Note: these accelerators have nonzero contexts.
2096 SaveMenuAccelerators (pSD, menuSpec);
2100 buttonSpec->wmFunction = F_Nop;
2103 buttonSpec = buttonSpec->nextButtonSpec;
2108 * Scan through the key binding specifications making menus if the
2109 * f.menu function is invoked.
2112 keySpec = pSD->keySpecs;
2115 if (keySpec->wmFunction == F_Menu)
2117 if (keySpec->context & F_CONTEXT_WINDOW)
2119 menuContext = F_CONTEXT_WINDOW;
2121 else if (keySpec->context & F_CONTEXT_ICON)
2123 menuContext = F_CONTEXT_ICON;
2127 menuContext = F_CONTEXT_ROOT;
2130 menuSpec = MAKE_MENU (pSD, NULL, keySpec->wmFuncArgs, menuContext,
2132 (MenuItem *) NULL, FALSE);
2136 * If successful, save in pSD->acceleratorMenuSpecs
2137 * Note: these accelerators have nonzero contexts.
2140 SaveMenuAccelerators (pSD, menuSpec);
2144 keySpec->wmFunction = F_Nop;
2147 keySpec = keySpec->nextKeySpec;
2151 } /* END OF FUNCTION MakeWmFunctionResources */
2155 /*************************************<->*************************************
2162 * Make an XOR graphic context for resizing and moving
2167 * pSD = pointer to screen data
2171 * Modifies global data
2177 *************************************<->***********************************/
2179 void MakeXorGC (WmScreenData *pSD)
2184 mask = GCFunction | GCLineWidth | GCSubwindowMode | GCCapStyle;
2185 gcv.function = GXinvert;
2187 gcv.cap_style = CapNotLast;
2188 gcv.subwindow_mode = IncludeInferiors;
2190 /* Fix so that the rubberbanding for resize and move will
2191 * have more contrasting colors.
2194 gcv.plane_mask = BlackPixelOfScreen( DefaultScreenOfDisplay( DISPLAY )) ^
2195 WhitePixelOfScreen( DefaultScreenOfDisplay( DISPLAY ));
2196 mask = mask | GCPlaneMask;
2198 pSD->xorGC = XCreateGC (DISPLAY, pSD->rootWindow, mask, &gcv);
2201 } /* END OF FUNCTION MakeXorGC */
2205 /*************************************<->*************************************
2207 * CopyArgv (argc, argv)
2212 * This function makes a copy of the window manager's argv for use by
2213 * the f.restart function. A copy must be kept because XtInitialize
2219 * argc = the number of strings in argv
2221 * argv = window manager parameters
2226 * Return = a copy of argv
2228 *************************************<->***********************************/
2231 void CopyArgv (int argc, char *argv [])
2236 if ((wmGD.argv = (char **)XtMalloc ((argc + 1) * sizeof (char *))) == NULL)
2238 Warning (((char *)GETMESSAGE(40, 10, "Insufficient memory for window manager data")));
2246 for (i = 0; i < argc; i++)
2248 wmGD.argv[i] = argv[i];
2250 wmGD.argv[i] = NULL;
2252 if ((dpy2Argv = (char **)XtMalloc((argc + 1) * sizeof(char *))) == NULL)
2254 Warning (((char *)GETMESSAGE(40, 11, "Insufficient memory for window manager data")));
2259 for (i = 0; i < argc; i++)
2261 dpy2Argv[i] = argv[i];
2269 } /* END OF FUNCTION CopyArgv */
2272 /*************************************<->*************************************
2274 * InitScreenNames ()
2279 * Initializes the name space for screen names
2283 * Modifies global data
2288 * Initializes screenNames to contain a numeric name for each screen
2290 *************************************<->***********************************/
2292 void InitScreenNames (void)
2294 int num, numScreens;
2296 numScreens = ScreenCount (wmGD.display);
2298 if (!(wmGD.screenNames =
2299 (unsigned char **) XtMalloc (numScreens * sizeof(char *))))
2301 ShowWaitState (FALSE);
2302 Warning (((char *)GETMESSAGE(40, 12, "Insufficient memory for screen names")));
2303 ExitWM (WM_ERROR_EXIT_VALUE);
2306 for (num=0; num<numScreens; num++)
2308 if (!(wmGD.screenNames[num] =
2309 (unsigned char *) XtMalloc (4*sizeof(char))))
2311 ShowWaitState (FALSE);
2312 Warning (((char *)GETMESSAGE(40, 13, "Insufficient memory for screen names")));
2313 ExitWM (WM_ERROR_EXIT_VALUE);
2315 /* default name is left justified, 3-chars max, zero terminated */
2317 sprintf((char *)wmGD.screenNames[num], UNSPECIFIED_SCREEN_NAME);
2319 sprintf((char *)wmGD.screenNames[num],"%d",num%1000);
2323 #ifndef NO_MESSAGE_CATALOG
2326 void InitNlsStrings (void)
2332 * Initialize messages
2334 wmGD.okLabel=XmStringCreateLocalized(_DtOkString);
2335 wmGD.cancelLabel=XmStringCreateLocalized(_DtCancelString);
2336 wmGD.helpLabel=XmStringCreateLocalized(_DtHelpString);
2340 * catgets returns a pointer to an area that is over written
2341 * on each call to catgets.
2344 tmpString = ((char *)GETMESSAGE(40, 14, "Icons"));
2345 if ((wmNLS.default_icon_box_title =
2346 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2348 Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
2349 wmNLS.default_icon_box_title = "Icons";
2353 strcpy(wmNLS.default_icon_box_title, tmpString);
2357 tmpString = ((char *)GETMESSAGE(40, 20, "%s: %s on line %d of configuration file %s\n"));
2358 if ((pWarningStringFile =
2359 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2361 Warning (((char *)GETMESSAGE(40, 17, "Insufficient memory for local message string")));
2362 pWarningStringFile = "%s: %s on line %d of configuration file %s\n";
2366 strcpy(pWarningStringFile, tmpString);
2369 tmpString = ((char *)GETMESSAGE(40, 21, "%s: %s on line %d of specification string\n"));
2370 if ((pWarningStringLine =
2371 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2373 Warning (((char *)GETMESSAGE(40, 19, "Insufficient memory for local message string")));
2374 pWarningStringLine = "%s: %s on line %d of specification string\n";
2378 strcpy(pWarningStringLine, tmpString);
2382 tmpString = ((char *)GETMESSAGE(40, 22, "About Workspace Manager"));
2383 if ((wmNLS.defaultVersionTitle =
2384 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2386 Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
2387 wmNLS.defaultVersionTitle = "About Workspace Manager";
2391 strcpy(wmNLS.defaultVersionTitle, tmpString);
2394 tmpString = ((char *)GETMESSAGE(40, 23, "Workspace Manager - Help"));
2395 if ((wmNLS.defaultDtwmHelpTitle =
2396 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2398 Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
2399 wmNLS.defaultDtwmHelpTitle = "Workspace Manager - Help";
2403 strcpy(wmNLS.defaultDtwmHelpTitle, tmpString);
2406 tmpString = ((char *)GETMESSAGE(40, 24, "Workspace Manager - Help"));
2407 if ((wmNLS.defaultHelpTitle =
2408 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2410 Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
2411 wmNLS.defaultHelpTitle = "Workspace Manager - Help";
2415 strcpy(wmNLS.defaultHelpTitle, tmpString);
2419 } /* InitNlsStrings */
2424 /******************************<->*************************************
2431 * This function saves the display string for putenv in F_Exec.
2438 *************************************<->***********************************/
2441 InitWmDisplayEnv (void)
2445 char displayName[256];
2447 pDisplayName = DisplayString (DISPLAY);
2450 * Construct displayString for this string.
2452 strcpy(displayName, pDisplayName);
2453 sprintf(buffer, "DISPLAY=%s",displayName);
2456 * Allocate space for the display string
2458 if ((wmGD.displayString =
2459 (String)XtMalloc ((unsigned int) (strlen(buffer) + 1))) == NULL)
2461 wmGD.displayString = NULL;
2462 Warning (((char *)GETMESSAGE(40, 9,
2463 "Insufficient memory for displayString")));
2467 strcpy(wmGD.displayString, buffer);
2469 putenv(wmGD.displayString);
2473 } /* END OF FUNCTION InitWmDisplayEnv */
2475 #ifndef NO_HP_KEY_REMAP
2488 str_xref xref_rtn = NULL ;
2489 unsigned num_xref = 0 ;
2491 XDisplayKeycodes( dsp, &min_kc, &max_kc) ;
2492 kc_count = max_kc + 1 - min_kc ;
2493 key_map = XGetKeyboardMapping( dsp, min_kc, kc_count, &ks_per_kc) ;
2494 if( key_map == NULL )
2498 kc_count *= ks_per_kc ;
2503 KeySym ks = XStringToKeysym( std_xref[i].default_name) ;
2506 while( j < kc_count )
2508 if( key_map[j] == ks )
2510 /* Found keysym used in virtkey table in keymap,
2511 * so break -> j != kc_count
2519 /* Didn't find keysym of virtkey table, so add record to
2520 * returned list which will later cause replacement in
2523 xref_rtn = (str_xref) XtRealloc( (char *) xref_rtn,
2524 sizeof( str_xref_rec) * (num_xref + 2)) ;
2525 xref_rtn[num_xref++] = std_xref[i] ;
2526 xref_rtn[num_xref].default_name = NULL ;
2530 XFree( (char *) key_map) ;
2535 GetBindingsProperty(
2542 unsigned long num_items ;
2543 unsigned long bytes_after ;
2544 unsigned char *prop = NULL ;
2546 XGetWindowProperty( dsp, RootWindow( dsp, 0), property, 0, 1000000L,
2547 FALSE, XA_STRING, &actual_type, &actual_format, &num_items, &bytes_after,
2549 if( (actual_type != XA_STRING)
2550 || (actual_format != 8)
2551 || (num_items == 0) )
2559 *binding = (String) prop ;
2564 SetBindingsProperty(
2569 XChangeProperty( dsp, RootWindow( dsp, 0), property, XA_STRING, 8,
2570 PropModeReplace, (unsigned char *) binding, strlen( binding)) ;
2574 FixupBindingsString(
2575 String bindingsString,
2578 String fixed_str = XtNewString( bindingsString) ;
2579 String ptr_next = fixed_str ;
2581 while( repl_xref->default_name != NULL )
2583 String ks_ptr = strstr( ptr_next, repl_xref->default_name) ;
2584 unsigned orig_len = strlen( repl_xref->default_name) ;
2586 if( ks_ptr == NULL )
2588 /* Only increment to next replacement when no other instances
2589 * are found in fixed_str.
2592 ptr_next = fixed_str ;
2596 if( (strpbrk( (ks_ptr - 1), " \t>") == (ks_ptr - 1))
2597 && (strpbrk( ks_ptr, " \t\n") == (ks_ptr + orig_len)) )
2599 unsigned new_len = strlen( repl_xref->new_name) ;
2600 unsigned suffix_len = strlen( ks_ptr + orig_len) ;
2602 if( new_len > orig_len )
2604 unsigned new_ttl_len = strlen( fixed_str) + new_len - orig_len ;
2605 unsigned prefix_len ;
2608 prefix_len = strlen( fixed_str) ;
2609 fixed_str = XtRealloc( fixed_str, (new_ttl_len + 1)) ;
2610 ks_ptr = fixed_str + prefix_len ;
2612 memmove( (ks_ptr + new_len), (ks_ptr + orig_len), (suffix_len + 1)) ;
2613 memcpy( ks_ptr, repl_xref->new_name, new_len) ;
2615 ptr_next = ks_ptr + new_len ;
2619 ptr_next = ks_ptr + 1 ;
2630 /* This routine examines the X server's key map table to determine
2631 * if certain HP-specific keysyms are missing. If they are, then
2632 * the Motif virtual binding table properties are updated to utilize
2633 * generic X keysyms instead of the missing HP vendor keysyms.
2634 * In particular, this fixes the Motif virtual key binding table for
2635 * correct operation on HP systems using the AT2/DIN style keyboard.
2637 static char *prop_names[] = { "_MOTIF_BINDINGS",
2638 "_MOTIF_DEFAULT_BINDINGS" } ;
2639 static str_xref_rec std_xref[] = { { "hpInsertChar", "Insert" },
2640 { "hpDeleteChar", "Delete" },
2643 Boolean PropChanged4DIN = FALSE ;
2645 char *bindingsString ;
2646 unsigned prop_existed ;
2648 str_xref vkeysym_xref ;
2649 unsigned num_props = XtNumber( prop_names) ;
2651 vkeysym_xref = GetReplacementList( dsp, std_xref, XtNumber(std_xref)) ;
2652 if( vkeysym_xref == NULL )
2654 return PropChanged4DIN ;
2657 prop_atoms = (Atom *) XtMalloc( sizeof( Atom) * num_props) ;
2658 XInternAtoms(dsp, prop_names, num_props, FALSE, prop_atoms);
2660 prop_existed = FALSE ;
2662 while( i < num_props )
2664 if( GetBindingsProperty( dsp, prop_atoms[i], &bindingsString) )
2666 String new_bstring = FixupBindingsString( bindingsString,
2668 prop_existed = TRUE ;
2669 XFree( bindingsString) ;
2671 if( new_bstring != NULL )
2673 SetBindingsProperty( dsp, prop_atoms[i], new_bstring) ;
2674 XtFree( new_bstring) ;
2681 bindingsString = NULL ;
2682 /* FIXME: this is an unexported openmotif procedure */
2683 extern void _XmVirtKeysLoadFallbackBindings(Display *dsp, String *binding);
2684 _XmVirtKeysLoadFallbackBindings( dsp, &bindingsString) ;
2685 XtFree( bindingsString) ;
2688 while( i < num_props )
2690 if( GetBindingsProperty( dsp, prop_atoms[i], &bindingsString) )
2692 String new_bstring = FixupBindingsString( bindingsString,
2694 XtFree( bindingsString) ;
2695 if( new_bstring != NULL )
2697 PropChanged4DIN = TRUE ;
2698 SetBindingsProperty( dsp, prop_atoms[i], new_bstring) ;
2699 XtFree( new_bstring) ;
2701 XFree( bindingsString) ;
2707 XtFree( (char *) vkeysym_xref) ;
2708 XtFree( (char *) prop_atoms) ;
2709 return PropChanged4DIN ;
2711 #endif /* NO_HP_KEY_REMAP */
2714 /**************************** eof ***************************/