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 libraries 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.
31 * (c) Copyright 1987, 1988, 1989, 1990, 1993, 1994 HEWLETT-PACKARD COMPANY
32 * (c) Copyright 1993, 1994 International Business Machines Corp.
33 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
34 * (c) Copyright 1993, 1994 Novell, Inc.
42 #include "WmResNames.h"
45 #define DTWM_NEED_FNTPL
46 #include "WmIBitmap.h"
49 #endif /* NO_OL_COMPAT */
51 #include <X11/cursorfont.h>
53 #include <Xm/AtomMgr.h>
54 #include <X11/Shell.h>
56 #include <X11/keysym.h>
57 #ifndef NO_HP_KEY_REMAP
58 #include <Xm/VirtKeysP.h>
64 } str_xref_rec, *str_xref ;
65 #endif /* NO_HP_KEY_REMAP */
66 #include <Dt/GetDispRes.h>
67 #include <Dt/SessionP.h>
68 #include <Dt/SessionM.h>
70 #include <Dt/Message.h>
72 #include <Dt/EnvControlP.h>
74 /* Busy is also defined in the BMS -> bms.h. This conflicts with
75 * /usr/include/X11/Xasync.h on ibm.
82 #include <X11/Xlibint.h>
85 * include extern functions
87 #include "WmBackdrop.h"
89 #include "WmColormap.h"
92 #include "WmFeedback.h"
93 #include "WmFunction.h"
97 #include "WmIconBox.h"
98 #include "WmKeyFocus.h"
99 #include "WmPanelP.h" /* for typedef in WmManage.h */
100 #include "WmManage.h"
102 #include "WmPresence.h"
103 #include "WmProperty.h"
104 #include "WmResCvt.h"
105 #include "WmResource.h"
106 #include "WmSignal.h"
107 #include "WmProtocol.h"
108 #include "WmCDecor.h"
110 #include "WmResParse.h"
115 * Function Declarations:
118 #include "WmInitWs.h"
120 static void InsureDefaultBackdropDir(char **ppchBackdropDirs);
121 void InitWmDisplayEnv (void);
122 #ifndef NO_MESSAGE_CATALOG
123 void InitNlsStrings (void);
125 #ifndef NO_HP_KEY_REMAP
126 Boolean VirtKeys4DIN(Display *dpy);
127 #endif /* NO_HP_KEY_REMAP */
129 /* limited to 3 chars max */
130 #define UNSPECIFIED_SCREEN_NAME "fbk"
131 char **dpy2Argv; /* copy for second display */
136 extern int firstTime;
137 #ifndef NO_MESSAGE_CATALOG
138 extern char * pWarningStringFile;
139 extern char * pWarningStringLine;
145 * Special case for a two button mouse; move the BMENU binding
146 * from Button3 to Button2. Fails for one-button mice.
149 InitMouseBinding(void)
151 wmGD.numMouseButtons = XGetPointerMapping(DISPLAY, (unsigned char *)0, 0);
153 if (wmGD.numMouseButtons < 3) {
154 wmGD.bMenuButton = Button2;
156 wmGD.bMenuButton = Button3;
160 /******************************<->*************************************
162 * BuildLockMaskSequence ()
164 * Set up the sequence of modifier masks to use to when grabbing
165 * key- and button-bindings. This sequence of masks is NULL
169 * wmGD.lockingModMask
172 * wmGD.pLockMaskSequence
175 *************************************<->***********************************/
177 BuildLockMaskSequence(void)
181 unsigned int thisbit;
189 * Count the bits to determine the number of elements in
190 * the mask sequence. The actual number of masks is
191 * 2^<bitcount> - 1. We're not interested in the case
192 * where there none of the mask bits are set.
194 mask = wmGD.lockingModMask;
205 num_masks = (0x1 << num_bits) - 1;
208 * Allocate the space for the mask sequence + terminator.
210 wmGD.pLockMaskSequence = (unsigned int *)
211 XtCalloc (num_masks+1, sizeof (unsigned int));
214 * Fill in the mask sequence
216 mask = wmGD.lockingModMask;
219 while (mask && thisbit)
222 while (!(thisbit & mask))
224 thisbit = thisbit << 1;
227 /* clear it from mask */
233 * Set it in the appropriate slots in the
234 * mask sequence. The start of the loop is
235 * funny because we skip the case of all the
238 run = (0x1 << bit-1); /* number of consecutive masks to set
240 bit_on = False; /* are we setting bits or not? */
242 for (j=0, k=run-1; j<num_masks; j++, k--)
254 if (bit_on) wmGD.pLockMaskSequence[j] |= thisbit;
260 /******************************<->*************************************
262 * SetupLockingModifierMask ()
264 * Set up the mask used to ignore locking modifier keys (e.g. Shift Lock)
265 * when processing key- and button-bindings.
267 * We want to try to ignore the set of locking modifers
268 * such as Shift Lock, Num Lock, Kana Lock, etc. This involves
269 * some amount of guessing since these things can be mapped
270 * onto any of the Mod1-Mod5 modifiers. The approach taken is to
271 * identify the mapping of the locking modifier keysyms to
272 * Mod1-Mod5 and build the set of masks needed to ignore them.
274 *************************************<->***********************************/
277 * This is the set of locking modifiers keysyms that might be
278 * bound to Mod1-Mod5. (Caps Lock is handled independently of
281 static KeySym pksLockingMods[] = {
288 #define NUM_LOCKING_MODS (sizeof(pksLockingMods)/sizeof(KeySym))
291 SetupLockingModifierMask(void)
293 int i, j, start_index;
294 XModifierKeymap *modifier_map = NULL;
295 static Modifiers mod_masks[] = { None, Mod1Mask, Mod2Mask,
296 Mod3Mask, Mod4Mask, Mod5Mask };
297 Display *dpy = wmGD.display;
298 int pkcLockingMods[NUM_LOCKING_MODS];
302 for (i=0; i<NUM_LOCKING_MODS; i++)
304 pkcLockingMods[i] = XKeysymToKeycode(dpy, pksLockingMods[i]);
308 * Start out with Caps lock and add others we discover.
310 wmGD.lockingModMask = LockMask;
312 modifier_map = XGetModifierMapping(dpy);
314 /* just check Mod1 through Mod5 */
315 start_index = modifier_map->max_keypermod * Mod1MapIndex;
317 for (i = start_index; i < modifier_map->max_keypermod * 8; i++) {
318 int this_mod = ((i - start_index) / modifier_map->max_keypermod) + 1;
320 kc = modifier_map->modifiermap[i];
323 for (j=0; j<NUM_LOCKING_MODS; j++)
325 if (pkcLockingMods[j] == kc)
327 wmGD.lockingModMask |= mod_masks[this_mod];
334 BuildLockMaskSequence();
336 if(modifier_map != NULL)
337 XFreeModifiermap(modifier_map);
341 /******************************<->*************************************
343 * MappingEventHandler (Widget, XtPointer, XEvent *, Boolean *)
345 * Catch and handle changes to the mapping of the modifier keys.
347 *************************************<->***********************************/
352 XtPointer client_data,
354 Boolean *cont_to_dispatch)
356 if(event->xany.type != MappingNotify ||
357 event->xmapping.request == MappingPointer)
360 if(event->xmapping.request == MappingModifier)
361 SetupLockingModifierMask();
365 /******************************<->*************************************
367 * InitWmGlobal (argc, argv, environ)
372 * This function initializes the workspace manager.
377 * argc = number of command line arguments (+1)
379 * argv = window manager command line arguments
381 * environ = window manager environment
386 * wmGD = (initialize the global data structure)
388 *************************************<->***********************************/
390 void InitWmGlobal (int argc, char *argv [], char *environ [])
392 XSetWindowAttributes sAttributes;
396 Boolean activeSet = False;
397 Boolean processedGlobalResources = False;
404 wmGD.errorFlag = False;
406 wmGD.iSlideUpsInProgress = 0;
408 SetupWmSignalHandlers (0); /* dummy paramater */
412 * Do (pre-toolkit) initialization:
415 wmGD.windowContextType = XUniqueContext ();
416 wmGD.screenContextType = XUniqueContext ();
418 wmGD.cmapWindowContextType = XUniqueContext ();
420 wmGD.mwmWindowContextType = XUniqueContext ();
422 /* copy argv (the XtInititalize changes the original) for use in restart */
424 CopyArgv (argc, argv);
426 wmGD.environ = environ;
428 wmGD.pWmPB = _DtWmParseNewBuf();
433 if ((wmGD.mwmName = (char*)strrchr (wmGD.argv[0], '/')) != NULL)
439 wmGD.mwmName = wmGD.argv[0];
443 res_class = WM_RESOURCE_CLASS;
447 res_class = DT_WM_RESOURCE_CLASS;
449 wmGD.statusColorServer = CSERVE_NOT_AVAILABLE;
451 wmGD.display = (Display *)NULL;
452 wmGD.topLevelW = (Widget)NULL;
455 * Do X Tookit initialization:
458 XtToolkitInitialize();
460 wmGD.mwmAppContext = XtCreateApplicationContext();
461 AddWmResourceConverters ();
462 wmGD.display = XtOpenDisplay (wmGD.mwmAppContext,
468 &argc, /* R5 changed from Cardinal to int*/
473 Warning(((char *)GETMESSAGE(40, 1, "Could not open display.")));
474 ExitWM (WM_ERROR_EXIT_VALUE);
477 #if defined(sun) && defined(ALLPLANES)
481 wmGD.allplanes = XAllPlanesQueryExtension(wmGD.display,
484 #endif /* defined(sun) && defined(ALLPLANES) */
487 * Setup error handling:
490 WmInitErrorHandler(wmGD.display);
493 * Initialize cursor size info and
494 * display the startup cursor.
499 ShowWaitState (TRUE);
502 * Initialize support for BMenu virtual mouse binding
506 * Set up the _MOTIF_BINDINGS property on the root window
507 * of screen 0. Must do this before we create shells.
510 ProcessMotifBindings ();
511 #ifndef NO_HP_KEY_REMAP
513 /* VirtKeys4DIN deals with a shortcoming in the OSF/Motif
514 * mechanism for selecting a virtual key binding table.
515 * When a client connects to a display, code inside of libXm
516 * gets the vendor identifier from the server and uses this
517 * identifier to select a default virtual key binding table
518 * from an internal list of possible tables (provided to
519 * OSF by vendors). A virtual key binding table maps OSF
520 * virtual keysyms to an "appropriate" set of X keysyms for
521 * a particular server vendor. The problem with this
522 * mechanism is that it only allows for a _single_ default
523 * virtual key binding table per server vendor. If a
524 * hardware vendor ships more than one distinct keyboard,
525 * then the single virtual key binding table selected for
526 * that server might not be appropriate for all keyboards.
527 * The HP migration from the "ITF" keyboard to the "PC-style"
528 * keyboard causes this problem to be exposed for Motif
529 * clients. The default HP virtual key binding table maps
530 * osfInsert and osfDelete to hpInsertChar and hpDeleteChar,
531 * respectively. But since hpInsertChar and hpDeleteChar
532 * are absent from the PC-style keyboard, HP servers with
533 * this keyboard do not generate key events that map to the
534 * important osfInsert and osfDelete virtual keys.
535 * The Motif 1.2 version of libXm installs (one or two)
536 * properties on the root window, these properties exporting
537 * the virtual key binding table to be used by all (subsequently
538 * connected) Motif clients. The VirtKeys4DIN routine attempts
539 * to ensure that the virtual key binding table exported by
540 * those properties does not include dependencies on keysyms
541 * that are not available in the server's current modmap.
542 * The routine accomplishes this by searching the keyboard
543 * mapping of the display for the absence of known problematic
544 * keysyms. For those keysyms that are missing from the
545 * keyboard map, the corresponding dependencies in the
546 * virtual key binding table are altered to use pre-determined
547 * substitutes (which are generic X keysyms that are present
548 * on the PC-style keyboard mapping).
549 * The side-effects of this routine are that if there are no
550 * key binding properties on the root window when this routine
551 * is called, there will be a property installed (this occurs
552 * with all Motif 1.2 clients anyway). Since the virtual key
553 * binding table is only altered if it contains a keysym that
554 * is missing from the server's keyboard mapping, there is
555 * little chance of deleterious effects.
557 VirtKeys4DIN(DISPLAY);
558 #endif /* NO_HP_KEY_REMAP */
561 XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
562 XtSetArg (args[argnum], XtNx, 10000); argnum++;
563 XtSetArg (args[argnum], XtNy, 0); argnum++;
564 XtSetArg (args[argnum], XtNwidth, 10); argnum++;
565 XtSetArg (args[argnum], XtNheight, 10); argnum++;
566 XtSetArg (args[argnum], XtNmappedWhenManaged, False); argnum++;
567 XtSetArg (args[argnum], XtNjoinSession, True); argnum++;
568 XtSetArg (args[argnum], XtNrestartStyle, SmRestartNever); argnum++;
569 XtSetArg (args[argnum], XtNargc, savedArgc); argnum++;
570 XtSetArg (args[argnum], XtNargv, wmGD.argv); argnum++;
572 /* create topmost shell (application shell) */
573 wmGD.topLevelW = XtAppCreateShell (NULL,
575 sessionShellWidgetClass,
580 XtAddEventHandler(wmGD.topLevelW, NoEventMask, True,
581 MappingEventHandler, NULL);
583 /* Add callbacks used for communication with Session Manager. */
586 /* allocate namespace for screens */
590 * Determine the screen management policy (all or none)
591 * Process command line arguments that we handle
592 * This could change the number of screens we manage
594 ProcessGlobalScreenResources ();
595 ProcessCommandLine (argc, argv);
598 * Make sure backdrops are in our icon search path.
599 * This call MUST occur before ANY icons are looked up either
600 * explicitly or through resource processing!!!
601 * Uses variables set by ProcessGlobalScreenResources and
602 * ProcessCommandLine.
607 Boolean useMultiColorIcons;
608 Boolean useIconFileCacheRtn;
611 sNum = (wmGD.numScreens == 1) ? DefaultScreen(DISPLAY) : 0;
613 XmeGetIconControlInfo(ScreenOfDisplay(DISPLAY, sNum), &useMaskRtn,
614 &useMultiColorIcons, &useIconFileCacheRtn);
616 sBdPath = wmGD.backdropDirs;
617 InsureDefaultBackdropDir ((char **) &sBdPath);
619 _DtWsmSetBackdropSearchPath(XScreenOfDisplay(DISPLAY, sNum),
620 sBdPath, useMultiColorIcons);
626 * Allocate data and initialize for screens we manage:
629 if (!(wmGD.Screens = (WmScreenData *)
630 XtCalloc (wmGD.numScreens, sizeof(WmScreenData))))
632 ShowWaitState (FALSE);
633 Warning (((char *)GETMESSAGE(40, 2, "Insufficient memory for Screen data")));
634 ExitWM (WM_ERROR_EXIT_VALUE);
639 sAttributes.event_mask = SubstructureRedirectMask;
641 for (scr=0; scr<wmGD.numScreens; scr++)
646 * Gain control of the root windows of each screen:
649 sNum = (wmGD.numScreens == 1) ? DefaultScreen(DISPLAY) : scr;
650 wmGD.errorFlag = False;
652 XChangeWindowAttributes (DISPLAY, RootWindow (DISPLAY, sNum),
653 CWEventMask, &sAttributes);
655 * Do XSync to force server action and catch errors
658 XSync (DISPLAY, False /* do not discard events */);
660 if ((wmGD.errorFlag) &&
661 (RootWindow (DISPLAY, sNum) == (Window) wmGD.errorResource) &&
662 (wmGD.errorRequestCode == X_ChangeWindowAttributes))
665 ((char *)GETMESSAGE(40, 3, "Another window manager is running on screen %d")), sNum);
666 Warning ((char *) &pch[0]);
667 wmGD.Screens[scr].managed = False;
671 if (!processedGlobalResources)
674 XA_DT_SESSION_HINTS, XA_DT_SM_WM_PROTOCOL,
675 XA_DT_SM_START_ACK_WINDOWS, XA_DT_SM_STOP_ACK_WINDOWS,
676 XA_DT_WM_WINDOW_ACK, XA_DT_WM_EXIT_SESSION,
677 XA_DT_WM_LOCK_DISPLAY, XA_DT_WM_READY, NUM_ATOMS };
678 static char *atom_names[] = {
679 _XA_DT_SESSION_HINTS, _XA_DT_SM_WM_PROTOCOL,
680 _XA_DT_SM_START_ACK_WINDOWS, _XA_DT_SM_STOP_ACK_WINDOWS,
681 _XA_DT_WM_WINDOW_ACK, _XA_DT_WM_EXIT_SESSION,
682 _XA_DT_WM_LOCK_DISPLAY, _XA_DT_WM_READY };
684 Atom atoms[XtNumber(atom_names)];
685 XInternAtoms(DISPLAY, atom_names, XtNumber(atom_names),
688 wmGD.xa_DT_SESSION_HINTS = atoms[XA_DT_SESSION_HINTS];
689 wmGD.xa_DT_SM_WM_PROTOCOL = atoms[XA_DT_SM_WM_PROTOCOL];
690 wmGD.xa_DT_SM_START_ACK_WINDOWS =
691 atoms[XA_DT_SM_START_ACK_WINDOWS];
692 wmGD.xa_DT_SM_STOP_ACK_WINDOWS =
693 atoms[XA_DT_SM_STOP_ACK_WINDOWS];
694 wmGD.xa_DT_WM_WINDOW_ACK = atoms[XA_DT_WM_WINDOW_ACK];
695 wmGD.xa_DT_WM_EXIT_SESSION = atoms[XA_DT_WM_EXIT_SESSION];
696 wmGD.xa_DT_WM_LOCK_DISPLAY = atoms[XA_DT_WM_LOCK_DISPLAY];
697 wmGD.xa_DT_WM_READY = atoms[XA_DT_WM_READY];
700 #endif /* NO_OL_COMPAT */
702 wmGD.hasShape = XShapeQueryExtension (DISPLAY,
703 &wmGD.shapeEventBase,
704 &wmGD.shapeErrorBase);
705 #endif /* NO_SHAPE */
707 wmGD.replayEnterEvent = False;
708 wmGD.menuActive = NULL;
709 wmGD.menuUnpostKeySpec = NULL;
710 wmGD.F_NextKeySpec = NULL;
711 wmGD.F_PrevKeySpec = NULL;
712 wmGD.passKeysActive = False;
713 wmGD.passKeysKeySpec = NULL;
714 wmGD.checkHotspot = False;
715 wmGD.configAction = NO_ACTION;
716 wmGD.configPart = FRAME_NONE;
717 wmGD.configSet = False;
718 wmGD.preMove = False;
719 wmGD.gadgetClient = NULL;
720 wmGD.wmTimers = NULL;
721 wmGD.clientDefaultTitle =
722 XmStringCreateLocalized(DEFAULT_CLIENT_TITLE);
723 wmGD.iconDefaultTitle =
724 XmStringCreateLocalized(DEFAULT_ICON_TITLE);
725 wmGD.attributesWindow = (Window)NULL;
726 wmGD.clickData.pCD = NULL;
727 wmGD.clickData.clickPending = False;
728 wmGD.clickData.doubleClickPending = False;
729 wmGD.systemModalActive = False;
730 wmGD.activeIconTextDisplayed = False;
731 wmGD.movingIcon = False;
732 wmGD.queryScreen = True;
733 wmGD.dataType = GLOBAL_DATA_TYPE;
735 wmGD.pLockMaskSequence = NULL;
736 SetupLockingModifierMask ();
737 wmGD.requestContextWin = (Window) 0L;
738 wmGD.cppCommand = NULL;
739 wmGD.evLastButton.button = 0;
740 wmGD.bReplayedButton = False;
741 wmGD.bSuspendSecondaryRestack = False;
743 * Get a second display connection for
744 * internal WM windows.
746 wmGD.display1 = XtOpenDisplay (wmGD.mwmAppContext,
756 ShowWaitState (FALSE);
757 Warning(((char *)GETMESSAGE(40, 4, "Could not open second display connection.")));
758 ExitWM (WM_ERROR_EXIT_VALUE);
761 _DtGetSmWindow(DISPLAY,
762 RootWindow(DISPLAY, 0),
766 * If this is the first screen we've managed,
767 * tell the session manager we're ready
769 if (!processedGlobalResources)
771 SendClientMsg( wmGD.dtSmWindow,
772 (long) wmGD.xa_DT_SM_WM_PROTOCOL,
773 (long) wmGD.xa_DT_WM_READY,
774 CurrentTime, NULL, 0);
776 #endif /* PANACOMM */
778 /* create topmost shell (application shell) */
780 XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
781 XtSetArg (args[argnum], XtNx, 10000); argnum++;
782 XtSetArg (args[argnum], XtNy, 0); argnum++;
783 XtSetArg (args[argnum], XtNwidth, 10); argnum++;
784 XtSetArg (args[argnum], XtNheight, 10); argnum++;
785 XtSetArg (args[argnum],
786 XtNmappedWhenManaged, False); argnum++;
789 XtAppCreateShell (NULL,
791 applicationShellWidgetClass,
799 * if this is the first screen we can manage,
803 processedGlobalResources = True;
806 * Get the _MOTIF_WM_INFO property and determine
807 * the startup / restart state.
810 ProcessMotifWmInfo (RootWindow (DISPLAY, sNum));
813 * Process global window manager resources:
815 #ifndef NO_MESSAGE_CATALOG
816 InitBuiltinSystemMenu();
819 ProcessWmResources ();
823 InitWmScreen (&(wmGD.Screens[scr]), sNum);
824 wmGD.Screens[scr].managed = True;
826 GetDtSessionHints(&(wmGD.Screens[scr]), sNum);
831 ACTIVE_PSD = &wmGD.Screens[scr];
839 * No screens for me to manage, give up.
841 ShowWaitState (FALSE);
842 Warning (((char *)GETMESSAGE(40, 5, "Unable to manage any screens on display.")));
843 ExitWM (WM_ERROR_EXIT_VALUE);
847 * Initialize the IPC mechanism
849 dtInitialize(argv[0], wmGD.mwmAppContext);
850 #ifndef NO_MESSAGE_CATALOG
852 * Set up NLS error messages.
853 * Must be done after DtInitialize.
859 * For multiple connections to the server, turn off
860 * the geometry manager's insistence on synchronous
865 XtSetArg (args[argnum], XmNuseAsyncGeometry, True); argnum++;
866 XtSetValues (wmGD.topLevelW, args, argnum);
867 XtSetValues (wmGD.topLevelW1, args, argnum);
871 * Prepare to have child processes (e.g., exec'ed commands).
872 * The X connection should not be passed on to child processes
873 * (it should be automatically closed when a fork is done).
876 if (fcntl (ConnectionNumber (DISPLAY), F_SETFD, 1) == -1)
878 ShowWaitState (FALSE);
879 Warning (((char *)GETMESSAGE(40, 6, "Cannot configure X connection")));
880 ExitWM (WM_ERROR_EXIT_VALUE);
885 enum { XA_DT_WORKSPACE_HINTS, XA_DT_WORKSPACE_PRESENCE,
886 XA_DT_WORKSPACE_INFO, XA_WmNall,
887 XA_DT_WORKSPACE_EMBEDDED_CLIENTS, XA_DT_WM_REQUEST,
888 XA_DT_WORKSPACE_LIST, XA_DT_WORKSPACE_CURRENT, NUM_ATOMS };
889 static char *atom_names[] = {
890 _XA_DT_WORKSPACE_HINTS, _XA_DT_WORKSPACE_PRESENCE,
891 _XA_DT_WORKSPACE_INFO, WmNall,
892 _XA_DT_WORKSPACE_EMBEDDED_CLIENTS, _XA_DT_WM_REQUEST,
893 _XA_DT_WORKSPACE_LIST, _XA_DT_WORKSPACE_CURRENT };
895 Atom atoms[XtNumber(atom_names)];
896 XInternAtoms(DISPLAY, atom_names, XtNumber(atom_names), False, atoms);
898 wmGD.xa_DT_WORKSPACE_HINTS = atoms[XA_DT_WORKSPACE_HINTS];
899 wmGD.xa_DT_WORKSPACE_PRESENCE = atoms[XA_DT_WORKSPACE_PRESENCE];
900 wmGD.xa_DT_WORKSPACE_INFO = atoms[XA_DT_WORKSPACE_INFO];
901 wmGD.xa_ALL_WORKSPACES = atoms[XA_WmNall];
902 wmGD.xa_DT_EMBEDDED_CLIENTS = atoms[XA_DT_WORKSPACE_EMBEDDED_CLIENTS];
903 wmGD.xa_DT_WM_REQUEST = atoms[XA_DT_WM_REQUEST];
904 wmGD.xa_DT_WORKSPACE_LIST = atoms[XA_DT_WORKSPACE_LIST];
905 wmGD.xa_DT_WORKSPACE_CURRENT = atoms[XA_DT_WORKSPACE_CURRENT];
909 /* Initialize properties used in session management. */
910 wmGD.xa_SM_CLIENT_ID =
911 XmInternAtom (DISPLAY, _XA_DT_SM_CLIENT_ID, False);
912 wmGD.xa_WMSAVE_HINT =
913 XmInternAtom (DISPLAY, _XA_DT_WMSAVE_HINT, False);
915 /* Load client resource database. */
916 wmGD.clientResourceDB = LoadClientResourceDB();
919 * Make the window manager workspace window.
920 * Setup the _MOTIF_WM_INFO property on the root window.
923 SetupWmWorkspaceWindows ();
926 /* make the cursors that the window manager uses */
927 MakeWorkspaceCursors ();
930 /* Sync the table used by Mwm's modifier parser to actual modMasks used */
931 SyncModifierStrings();
934 * Setup screen data and resources (after processing Wm resources.
936 for (scr = 0; scr < wmGD.numScreens; scr++)
938 pSD = &(wmGD.Screens[scr]);
942 if (XDefaultScreen (wmGD.display) == pSD->screen)
944 wmGD.commandWindow = wmGD.Screens[scr].wmWorkspaceWin;
948 * Initialize workspace colormap data.
951 InitWorkspaceColormap (pSD);
954 * Process the window manager resource description file (.mwmrc):
957 ProcessWmFile (pSD, False /* not nested */);
960 * Setup default resources for the system menu and key bindings:
963 SetupDefaultResources (pSD);
967 * Make global window manager facilities:
970 if(pSD->iconDecoration & ICON_ACTIVE_LABEL_PART)
972 /* create active icon window */
973 CreateActiveIconTextWindow(pSD);
978 * Make menus and other resources that are used by window manager
979 * functions that are activated by menus, buttons and keys.
982 MakeWmFunctionResources (pSD);
987 * Remove any temp config file we created if we needed to
988 * convert DT 2.0 syntax to DT 3.0
990 DeleteTempConfigFileIfAny();
992 * Point second display's resource data base
993 * to the first display's resource data base
994 * so dtwm "clients" change colors dynamically.
998 wmGD.display1->db = wmGD.display->db;
1001 * Realize the top level widget, make the window override
1002 * redirect so we don't manage it, and then move it out of the way
1005 XtRealizeWidget (wmGD.topLevelW);
1006 XtRealizeWidget (wmGD.topLevelW1);
1009 * Initialize the message handling.
1010 * (This must be done after the realize because a window
1011 * is required for ICCCM-style messaging).
1013 dtInitializeMessaging (wmGD.topLevelW);
1015 sAttributes.override_redirect = True;
1016 XChangeWindowAttributes (DISPLAY, XtWindow (wmGD.topLevelW),
1017 CWOverrideRedirect, &sAttributes);
1020 /* setup window manager inter-client communications conventions handling */
1024 * Use the WM_SAVE_YOURSELF protocol
1025 * for notification of when to save ourself
1027 SetMwmSaveSessionInfo(wmGD.commandWindow);
1029 * Initialize window manager event handling:
1032 InitEventHandling ();
1037 * Initialize frame component graphics
1040 for (scr = 0; scr < wmGD.numScreens; scr++)
1042 pSD = &(wmGD.Screens[scr]);
1046 InitClientDecoration (pSD);
1049 * Make an icon box if specificed:
1051 if (pSD->useIconBox)
1057 * Adopt client windows that exist before wm startup:
1060 AdoptInitialClients (pSD);
1063 * Setup initial keyboard focus and colormap focus:
1066 InitColormapFocus (pSD);
1071 for (scr = 0; scr < wmGD.numScreens; scr++)
1074 pSD = &(wmGD.Screens[scr]);
1078 ACTIVE_PSD = &wmGD.Screens[scr];
1079 MapIconBoxes (pSD->pActiveWS);
1081 ChangeBackdrop (pSD->pActiveWS);
1084 UpdateWorkspaceInfoProperty (pSD); /* backward compatible */
1087 SetCurrentWorkspaceProperty (pSD);
1088 SetWorkspaceListProperty (pSD);
1090 for (iws=0; iws < pSD->numWorkspaces; iws++)
1092 SetWorkspaceInfoProperty (&(pSD->pWS[iws]));
1100 /* MapWorkspaceBox (); */
1103 * Allocate front panel widgets
1105 if (wmGD.useFrontPanel && (pSD == wmGD.dtSD))
1110 WmPanelistObject pPanelist;
1112 wmGD.dtSD->wPanelist =
1113 WmPanelistAllocate(pSD->screenTopLevelW1,
1114 (XtPointer) &wmGD, (XtPointer) pSD);
1116 pPanelist = (WmPanelistObject) pSD->wPanelist;
1118 if (pPanelist != NULL && O_Shell(pPanelist))
1121 * Make a default front panel icon image.
1123 iconBitmap = XCreateBitmapFromData (DISPLAY,
1125 (char *) fntpl_i_bm_bits,
1130 XtSetArg (al[ac], XmNiconPixmap, iconBitmap); ac++;
1131 XtSetValues (O_Shell(pPanelist), al, ac);
1136 if (wmGD.useFrontPanel && pSD->wPanelist &&
1140 * Make the front panel visible
1142 WmPanelistShow (pSD->wPanelist);
1145 * Find special clients associated with the
1146 * front panel. This needs to be done after
1147 * WmPanelistShow where the data is set up.
1149 ScanForPushRecallClients (pSD);
1150 ScanForEmbeddedClients (pSD);
1153 RestoreHelpDialogs(pSD);
1159 InitKeyboardFocus ();
1161 ShowWaitState (FALSE);
1164 * Tell the rest of DT that we're up
1166 dtReadyNotification();
1168 #ifdef DEBUG_RESOURCE_DATABASE
1169 XrmPutFileDatabase(wmGD.display->db, "/tmp/dtwm.resDB");
1170 #endif /* DEBUG_RESOURCE_DATABASE */
1172 } /* END OF FUNCTION InitWmGlobal */
1176 /******************************<->*************************************
1183 * This function initializes a screen data block.
1187 * pSD = pointer to preallocated screen data block
1188 * sNum = screen number for this screen
1192 *************************************<->***********************************/
1195 InitWmScreen (WmScreenData *pSD, int sNum)
1201 WmWorkspaceData *pwsI;
1206 #define LENCBUFFER 256
1207 char buffer[LENCBUFFER]; /* screen name & display name! */
1208 char displayName[LENCBUFFER];
1209 char *token1, *token2;
1213 * Set screen data values
1216 pSD->rootWindow = RootWindow (DISPLAY, sNum);
1217 pSD->clientCounter = 0;
1218 pSD->defaultSystemMenuUseBuiltin = TRUE;
1219 pSD->displayString = NULL;
1220 pSD->acceleratorMenuCount = 0;
1221 pSD->activeIconTextWin = (Window)NULL;
1222 pSD->focusPriority = 0;
1223 pSD->inputScreenWindow = (Window)NULL;
1224 pSD->colormapFocus = NULL;
1225 pSD->keySpecs = NULL;
1227 pSD->confirmboxW[DEFAULT_BEHAVIOR_ACTION] = NULL;
1228 pSD->confirmboxW[CUSTOM_BEHAVIOR_ACTION] = NULL;
1229 pSD->confirmboxW[RESTART_ACTION] = NULL;
1230 pSD->confirmboxW[QUIT_MWM_ACTION] = NULL;
1231 pSD->feedbackWin = (Window)NULL;
1232 pSD->fbStyle = FB_OFF;
1233 pSD->fbWinWidth = 0;
1234 pSD->fbWinHeight = 0;
1235 pSD->fbLocation[0] = '\0';
1236 pSD->fbSize[0] = '\0';
1243 pSD->fbLastWidth = -1;
1244 pSD->fbLastHeight = -1;
1246 pSD->fbBottom = NULL;
1247 pSD->actionNbr = -1;
1248 pSD->clientList = NULL;
1249 pSD->lastClient = NULL;
1250 pSD->lastInstalledColormap = (Colormap)NULL;
1251 pSD->shrinkWrapGC = NULL;
1252 pSD->bitmapCache = NULL;
1253 pSD->bitmapCacheSize = 0;
1254 pSD->bitmapCacheCount = 0;
1255 pSD->dataType = SCREEN_DATA_TYPE;
1256 pSD->managed = False;
1258 pSD->initialWorkspace=NULL;
1259 pSD->presence.shellW = NULL;
1260 pSD->presence.onScreen = False;
1261 pSD->presence.userDismissed = True;
1262 pSD->workspaceList = NULL;
1263 pSD->numWorkspaces = 0;
1264 pSD->numWsDataAllocated = 0;
1265 pSD->lastBackdropWin = None;
1266 pSD->pDtSessionItems = NULL;
1267 pSD->totalSessionItems = 0;
1268 pSD->remainingSessionItems = 0;
1270 pSD->cachedHelp = NULL;
1271 pSD->dtHelp.shell = (Widget)NULL;
1272 pSD->dtHelp.dialog = (Widget)NULL;
1273 pSD->dtHelp.errorDialog = (Widget)NULL;
1274 pSD->dtHelp.xPos = 0;
1275 pSD->dtHelp.yPos = 0;
1276 pSD->dtHelp.restored = False;
1277 pSD->dtHelp.onScreen = False;
1278 pSD->dtHelp.userDismissed = False;
1279 pSD->dtHelp.pCDforClient= NULL;
1280 pSD->helpResources=NULL;
1281 pSD->bMarqueeSelectionInitialized = False;
1282 pSD->woN = (Window) 0L;
1283 pSD->woS = (Window) 0L;
1284 pSD->woE = (Window) 0L;
1285 pSD->woW = (Window) 0L;
1286 pSD->wPanelist = NULL;
1288 pSD->numPushRecallClients = 0;
1289 pSD->numEmbeddedClients = 0;
1291 pSD->iconBoxControl = False;
1292 pSD->displayResolutionType = _DtGetDisplayResolution(DISPLAY, sNum);
1295 * We've got display resolution type--now, let's get color
1299 ProcessWmColors (pSD);
1301 if (!(strcmp ((char *)wmGD.screenNames[sNum], UNSPECIFIED_SCREEN_NAME)))
1303 sprintf (buffer, "%d", sNum);
1305 buf_size = strlen(buffer) + 1;
1307 if ((wmGD.screenNames[sNum] =
1308 (unsigned char *)XtRealloc ((char *)wmGD.screenNames[sNum], buf_size)) == NULL)
1310 Warning (((char *)GETMESSAGE(40, 7, "Cannot create enough memory for the screen names")));
1311 ExitWM (WM_ERROR_EXIT_VALUE);
1315 strcpy((char *)wmGD.screenNames[sNum], buffer);
1317 } /* if wmGD.screenNames[sNum] == UNSPECIFIED_SCREEN_NAME */
1320 * Save screen context
1322 XSaveContext (DISPLAY, pSD->rootWindow, wmGD.screenContextType,
1325 * Create shell widget for screen resource hierarchy
1329 XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
1330 XtSetArg (args[argnum], XtNx, 10000); argnum++;
1331 XtSetArg (args[argnum], XtNy, 10000); argnum++;
1332 XtSetArg (args[argnum], XtNwidth, 10); argnum++;
1333 XtSetArg (args[argnum], XtNheight, 10); argnum++;
1334 XtSetArg (args[argnum], XtNoverrideRedirect, True); argnum++;
1336 XtSetArg (args[argnum], XtNdepth,
1337 DefaultDepth(DISPLAY, sNum)); argnum++;
1338 XtSetArg (args[argnum], XtNscreen,
1339 ScreenOfDisplay(DISPLAY, sNum)); argnum++;
1340 XtSetArg (args[argnum], XtNcolormap,
1341 DefaultColormap(DISPLAY, sNum)); argnum++;
1343 pSD->screenTopLevelW = XtCreatePopupShell ((String) wmGD.screenNames[sNum],
1344 vendorShellWidgetClass,
1350 XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
1351 XtSetArg (args[argnum], XtNx, 10000); argnum++;
1352 XtSetArg (args[argnum], XtNy, 10000); argnum++;
1353 XtSetArg (args[argnum], XtNwidth, 10); argnum++;
1354 XtSetArg (args[argnum], XtNheight, 10); argnum++;
1355 XtSetArg (args[argnum], XtNoverrideRedirect, True); argnum++;
1356 XtSetArg (args[argnum], XtNmappedWhenManaged, False); argnum++;
1358 XtSetArg (args[argnum], XtNdepth,
1359 DefaultDepth(DISPLAY1, sNum)); argnum++;
1360 XtSetArg (args[argnum], XtNscreen,
1361 ScreenOfDisplay(DISPLAY1, sNum)); argnum++;
1362 XtSetArg (args[argnum], XtNcolormap,
1363 DefaultColormap(DISPLAY1, sNum)); argnum++;
1365 pSD->screenTopLevelW1 = XtCreatePopupShell ((String) wmGD.screenNames[sNum],
1366 vendorShellWidgetClass,
1370 XtRealizeWidget (pSD->screenTopLevelW1);
1373 * Fetch screen based resources
1375 ProcessScreenResources (pSD, wmGD.screenNames[sNum]);
1378 * Initialize other screen resources and parameters
1384 * Complete initialization of workspace structures
1387 pwsI = pSD->pWS; wsnum < pSD->numWorkspaces;
1391 * Set up workspace for this screen
1393 InitWmWorkspace (pwsI, pSD);
1397 if (pSD->initialWorkspace)
1400 * restore to the last initialWorkspace saved from
1401 * Quit, Restart, OR save session
1405 * Compare initialWorkspace against workspace name,
1406 * NOT workspace title.
1408 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
1410 if (!strcmp(pSD->pWS[iwsx].name, pSD->initialWorkspace))
1416 if (iwsx >= pSD->numWorkspaces)
1418 /* make first workspace in list the active one to start with */
1419 pSD->pActiveWS = pSD->pWS;
1423 pSD->pActiveWS = &pSD->pWS[iwsx];
1428 /* make first workspace in list the active one to start with */
1429 pSD->pActiveWS = pSD->pWS;
1433 pDisplayName = DisplayString (DISPLAY);
1436 * Construct displayString for this string.
1438 * NOTE: The variable buffer is reused here. It was
1439 * used earlier to generate a screen name.
1442 strcpy(displayName, pDisplayName);
1444 token1 = (char*)strtok(displayName, ":"); /* parse of hostname */
1446 if((token2 = (char*)strtok(NULL, ".")) || /* parse off dpy & scr # */
1447 (token2 = (char*)strtok(NULL, "")) ||
1448 (displayName[0] == ':'))
1450 if (displayName[0] == ':') /* local dpy (special case) */
1452 if ((token2 = (char*)strtok(token1, ".")) != NULL) /* parse dpy# */
1453 sprintf(buffer, "DISPLAY=:%s.%d",
1455 } else { /* otherwise process normally */
1456 sprintf(buffer, "DISPLAY=%s:%s.%d",
1457 token1, token2, sNum);
1461 * Allocate space for the display string
1464 if ((pSD->displayString =
1465 (String)XtMalloc ((unsigned int) (strlen(buffer) + 1))) == NULL)
1467 Warning (((char *)GETMESSAGE(40, 9,
1468 "Insufficient memory for displayString")));
1472 strcpy(pSD->displayString, buffer);
1479 } /* END OF FUNCTION InitWmScreen */
1482 /*************************************<->*************************************
1489 * This function initializes a workspace data block.
1493 * pWS = pointer to preallocated workspace data block
1494 * pSD = ptr to parent screen data block
1498 *************************************<->***********************************/
1500 void InitWmWorkspace (WmWorkspaceData *pWS, WmScreenData *pSD)
1507 pWS->pIconBox = NULL;
1508 pWS->dataType = WORKSPACE_DATA_TYPE;
1509 pWS->backdrop.window = 0;
1510 pWS->backdrop.nameAtom = 0;
1511 pWS->backdrop.image = NULL;
1512 pWS->numClients = 0;
1513 pWS->sizeClientList = 0;
1515 pWS->buttonW = NULL;
1518 * Create widget for workspace resource hierarchy
1521 XtSetArg (args[argnum], XtNdepth,
1522 DefaultDepth(DISPLAY, pSD->screen)); argnum++;
1523 XtSetArg (args[argnum], XtNscreen,
1524 ScreenOfDisplay(DISPLAY, pSD->screen)); argnum++;
1525 XtSetArg (args[argnum], XtNcolormap,
1526 DefaultColormap(DISPLAY, pSD->screen)); argnum++;
1527 XtSetArg (args[argnum], XtNwidth, 5); argnum++;
1528 XtSetArg (args[argnum], XtNheight, 5); argnum++;
1530 pWS->workspaceTopLevelW = XtCreateWidget ( pWS->name,
1531 xmPrimitiveWidgetClass,
1532 pSD->screenTopLevelW,
1536 /* internalize the workspace name */
1537 pWS->id = XInternAtom (DISPLAY, pWS->name, False);
1540 * Process workspace based resources
1542 ProcessWorkspaceResources (pWS);
1544 /* setup icon placement */
1545 if (wmGD.iconAutoPlace)
1547 InitIconPlacement (pWS);
1550 } /* END OF FUNCTION InitWmWorkspace */
1553 /******************************<->*************************************
1555 * InsureDefaultBackdropDir(char **ppchBackdropDirs)
1560 * This function checks and edits a directory path to insure
1561 * that the system backdrop directroy (/usr/dt/backdrops) is in the
1562 * path. If not it adds it to the end. Further, it always adds the user's
1563 * backdrop directory ($HOME/.dt/backdrops) to the beginning of the path
1564 * and the system admin directory (/etc/dt/backdrops) before the system
1569 * ppchBackdropDirs - Pointer to a pointer to a directory path
1570 * (must be allocated memory)
1574 * *ppchBackdropDirs - Directory path may be modified, path
1575 * pointer may be realloc'ed.
1579 * Assumes that the default directory does not start with a
1580 * multi-byte character.
1582 ******************************<->***********************************/
1584 InsureDefaultBackdropDir(char **ppchBackdropDirs)
1587 Boolean bFound = False;
1588 char *pch, *pchEnd, *pch2, *tmpptr;
1589 char *pchD = DEFAULT_BACKDROP_DIR;
1594 * Set up initial stuff
1596 pch = *ppchBackdropDirs;
1597 len = strlen (pchD);
1598 pchEnd = pch + strlen(pch);
1600 while (!bFound && (pch != NULL) && (*pch != 0))
1602 if (strncmp (pch, pchD, len) == 0)
1604 /* found partial match, confirm complete match ...
1605 * complete match if char off end of partial match
1606 * is a NULL or a colon
1609 if ((pch2 <= pchEnd) &&
1611 (((mblen (pch2, MB_CUR_MAX) == 1) &&
1619 /* find next path component */
1620 pch = strchr (pch, (int) ':');
1621 if ((pch != NULL) && (*pch != 0))
1623 /* skip path separator */
1624 chlen = mblen (pch, MB_CUR_MAX);
1632 * Always add the user's home directory to the beginning of the string
1634 homeDir = (char *) XmeGetHomeDirName();
1637 * If found add the user's home directory ($HOME/.dt/backdrops) and the
1638 * admin directory /etc/dt/backdrops to the beginning of the string
1643 len = strlen (homeDir) + strlen("/.dt/backdrops") +
1644 strlen (*ppchBackdropDirs) + strlen("/etc/dt/backdrops") + 3;
1645 tmpptr = XtMalloc (len * sizeof (char *));
1646 strcpy (tmpptr, homeDir);
1647 strcat (tmpptr, "/.dt/backdrops");
1648 strcat (tmpptr, ":");
1649 strcat (tmpptr, "/etc/dt/backdrops");
1650 strcat (tmpptr, ":");
1651 strcat (tmpptr, *ppchBackdropDirs);
1652 *ppchBackdropDirs = tmpptr;
1656 * If string not found, then add home directory to the beginning of
1657 * string and the admin directory and system directory to the end.
1660 len = strlen (homeDir) + strlen("/.dt/backdrops") +
1661 strlen (*ppchBackdropDirs) + strlen(pchD) +
1662 strlen("/etc/dt/backdrops") + 4;
1663 tmpptr = XtMalloc (len * sizeof (char *));
1664 strcpy (tmpptr, homeDir);
1665 strcat (tmpptr, "/.dt/backdrops");
1666 strcat (tmpptr, ":");
1667 strcat (tmpptr, *ppchBackdropDirs);
1668 strcat (tmpptr, ":");
1669 strcat (tmpptr, "/etc/dt/backdrops");
1670 strcat (tmpptr, ":");
1671 strcat (tmpptr, pchD);
1672 *ppchBackdropDirs = tmpptr;
1675 } /* END OF FUNCTION InsureDefaultBackdropDirs */
1678 /*************************************<->*************************************
1680 * ProcessMotifWmInfo (rootWindowOfScreen)
1685 * This function is used retrieve and save the information in the
1686 * _MOTIF_WM_INFO property. If the property does not exist then
1687 * the start / restart state is set to initial startup with the
1688 * user specified (not standard) configuration.
1693 * wmGD.useStandardBehavior = True if set indicated in property
1695 * wmGD.wmRestarted = True if the window manager was restarted
1697 *************************************<->***********************************/
1699 void ProcessMotifWmInfo (Window rootWindowOfScreen)
1703 wmGD.xa_MWM_INFO = XInternAtom (DISPLAY, _XA_MWM_INFO, False);
1704 if ((pMwmInfo = (MotifWmInfo *)GetMwmInfo (rootWindowOfScreen)) != NULL)
1706 wmGD.useStandardBehavior =
1707 (pMwmInfo->flags & MWM_INFO_STARTUP_STANDARD) ? True : False;
1708 wmGD.wmRestarted = True;
1709 XFree ((char *)pMwmInfo);
1713 wmGD.useStandardBehavior = False;
1714 wmGD.wmRestarted = False;
1717 } /* END OF FUNCTION ProcessMotifWmInfo */
1721 /*************************************<->*************************************
1723 * SetupWmWorkspaceWindows ()
1728 * This function is used to setup a window that can be used in doing window
1729 * management functions. This window is not visible on the screen.
1734 * pSD->wmWorkspaceWin = window that is used to hold wm properties
1736 *************************************<->***********************************/
1738 void SetupWmWorkspaceWindows (void)
1742 XSetWindowAttributes sAttributes;
1744 for (scr = 0; scr < wmGD.numScreens; scr++)
1746 pSD = &(wmGD.Screens[scr]);
1749 sAttributes.override_redirect = True;
1750 sAttributes.event_mask = FocusChangeMask | PropertyChangeMask;
1751 pSD->wmWorkspaceWin = XCreateWindow (DISPLAY, pSD->rootWindow,
1752 -100, -100, 10, 10, 0, 0,
1753 InputOnly, CopyFromParent,
1754 (CWOverrideRedirect |CWEventMask),
1757 XMapWindow (DISPLAY, pSD->wmWorkspaceWin);
1759 SetMwmInfo (pSD->rootWindow,
1760 (long) ((wmGD.useStandardBehavior) ?
1761 MWM_INFO_STARTUP_STANDARD : MWM_INFO_STARTUP_CUSTOM),
1762 pSD->wmWorkspaceWin);
1763 XSaveContext (DISPLAY, pSD->wmWorkspaceWin,
1764 wmGD.mwmWindowContextType, (caddr_t)pSD);
1768 } /* END OF FUNCTION SetupWmWorkspaceWindow */
1772 /*************************************<->*************************************
1774 * MakeWorkspaceCursors ()
1779 * This function makes the cursors that the window manager uses.
1791 * wmGD = (stretchCursors ...)
1793 *************************************<->***********************************/
1795 void MakeWorkspaceCursors (void)
1797 wmGD.workspaceCursor = XCreateFontCursor (DISPLAY, XC_left_ptr);
1799 wmGD.stretchCursors[STRETCH_NORTH_WEST] =
1800 XCreateFontCursor (DISPLAY, XC_top_left_corner);
1801 wmGD.stretchCursors[STRETCH_NORTH] =
1802 XCreateFontCursor (DISPLAY, XC_top_side);
1803 wmGD.stretchCursors[STRETCH_NORTH_EAST] =
1804 XCreateFontCursor (DISPLAY, XC_top_right_corner);
1805 wmGD.stretchCursors[STRETCH_EAST] =
1806 XCreateFontCursor (DISPLAY, XC_right_side);
1807 wmGD.stretchCursors[STRETCH_SOUTH_EAST] =
1808 XCreateFontCursor (DISPLAY, XC_bottom_right_corner);
1809 wmGD.stretchCursors[STRETCH_SOUTH] =
1810 XCreateFontCursor (DISPLAY, XC_bottom_side);
1811 wmGD.stretchCursors[STRETCH_SOUTH_WEST] =
1812 XCreateFontCursor (DISPLAY, XC_bottom_left_corner);
1813 wmGD.stretchCursors[STRETCH_WEST] =
1814 XCreateFontCursor (DISPLAY, XC_left_side);
1816 wmGD.configCursor = XCreateFontCursor (DISPLAY, XC_fleur);
1818 wmGD.movePlacementCursor = XCreateFontCursor (DISPLAY, XC_ul_angle);
1819 wmGD.sizePlacementCursor = XCreateFontCursor (DISPLAY, XC_lr_angle);
1822 } /* END OF FUNCTION MakeWorkspaceCursors */
1826 /*************************************<->*************************************
1828 * MakeWmFunctionResources (pSD)
1833 * This function makes menus and other resources that are used by window
1834 * manager functions.
1839 * wmGD = (menuSpecs, keySpecs, buttonSpecs)
1844 * wmGD (menuSpecs) = new menu panes, protocol atoms
1846 *************************************<->***********************************/
1848 void MakeWmFunctionResources (WmScreenData *pSD)
1850 ButtonSpec *buttonSpec;
1853 Context menuContext;
1857 * Scan through the menu specifications and make wm protocol atoms.
1862 * Scan through the button binding specifications making menus if the
1863 * f.menu function is invoked.
1866 buttonSpec = pSD->buttonSpecs;
1869 if (buttonSpec->wmFunction == F_Menu)
1871 if (buttonSpec->context & F_CONTEXT_WINDOW)
1873 menuContext = F_CONTEXT_WINDOW;
1875 else if (buttonSpec->context & F_CONTEXT_ICON)
1877 menuContext = F_CONTEXT_ICON;
1881 menuContext = F_CONTEXT_ROOT;
1884 menuSpec = MAKE_MENU (pSD, NULL, buttonSpec->wmFuncArgs,
1886 buttonSpec->context,
1887 (MenuItem *) NULL, FALSE);
1891 * If successful, save in pSD->acceleratorMenuSpecs
1892 * Note: these accelerators have nonzero contexts.
1895 SaveMenuAccelerators (pSD, menuSpec);
1899 buttonSpec->wmFunction = F_Nop;
1902 buttonSpec = buttonSpec->nextButtonSpec;
1907 * Scan through the key binding specifications making menus if the
1908 * f.menu function is invoked.
1911 keySpec = pSD->keySpecs;
1914 if (keySpec->wmFunction == F_Menu)
1916 if (keySpec->context & F_CONTEXT_WINDOW)
1918 menuContext = F_CONTEXT_WINDOW;
1920 else if (keySpec->context & F_CONTEXT_ICON)
1922 menuContext = F_CONTEXT_ICON;
1926 menuContext = F_CONTEXT_ROOT;
1929 menuSpec = MAKE_MENU (pSD, NULL, keySpec->wmFuncArgs, menuContext,
1931 (MenuItem *) NULL, FALSE);
1935 * If successful, save in pSD->acceleratorMenuSpecs
1936 * Note: these accelerators have nonzero contexts.
1939 SaveMenuAccelerators (pSD, menuSpec);
1943 keySpec->wmFunction = F_Nop;
1946 keySpec = keySpec->nextKeySpec;
1950 } /* END OF FUNCTION MakeWmFunctionResources */
1954 /*************************************<->*************************************
1961 * Make an XOR graphic context for resizing and moving
1966 * pSD = pointer to screen data
1970 * Modifies global data
1976 *************************************<->***********************************/
1978 void MakeXorGC (WmScreenData *pSD)
1983 mask = GCFunction | GCLineWidth | GCSubwindowMode | GCCapStyle;
1984 gcv.function = GXinvert;
1986 gcv.cap_style = CapNotLast;
1987 gcv.subwindow_mode = IncludeInferiors;
1989 /* Fix so that the rubberbanding for resize and move will
1990 * have more contrasting colors.
1993 gcv.plane_mask = BlackPixelOfScreen( DefaultScreenOfDisplay( DISPLAY )) ^
1994 WhitePixelOfScreen( DefaultScreenOfDisplay( DISPLAY ));
1995 mask = mask | GCPlaneMask;
1997 pSD->xorGC = XCreateGC (DISPLAY, pSD->rootWindow, mask, &gcv);
2000 } /* END OF FUNCTION MakeXorGC */
2004 /*************************************<->*************************************
2006 * CopyArgv (argc, argv)
2011 * This function makes a copy of the window manager's argv for use by
2012 * the f.restart function. A copy must be kept because XtInitialize
2018 * argc = the number of strings in argv
2020 * argv = window manager parameters
2025 * Return = a copy of argv
2027 *************************************<->***********************************/
2030 void CopyArgv (int argc, char *argv [])
2035 if ((wmGD.argv = (char **)XtMalloc ((argc + 1) * sizeof (char *))) == NULL)
2037 Warning (((char *)GETMESSAGE(40, 10, "Insufficient memory for window manager data")));
2043 for (i = 0; i < argc; i++)
2045 wmGD.argv[i] = argv[i];
2047 wmGD.argv[i] = NULL;
2048 if ((dpy2Argv = (char **)XtMalloc((argc + 1) * sizeof(char *))) == NULL)
2050 Warning (((char *)GETMESSAGE(40, 11, "Insufficient memory for window manager data")));
2055 for (i = 0; i < argc; i++)
2057 dpy2Argv[i] = argv[i];
2064 } /* END OF FUNCTION CopyArgv */
2067 /*************************************<->*************************************
2069 * InitScreenNames ()
2074 * Initializes the name space for screen names
2078 * Modifies global data
2083 * Initializes screenNames to contain a numeric name for each screen
2085 *************************************<->***********************************/
2087 void InitScreenNames (void)
2089 int num, numScreens;
2091 numScreens = ScreenCount (wmGD.display);
2093 if (!(wmGD.screenNames =
2094 (unsigned char **) XtMalloc (numScreens * sizeof(char *))))
2096 ShowWaitState (FALSE);
2097 Warning (((char *)GETMESSAGE(40, 12, "Insufficient memory for screen names")));
2098 ExitWM (WM_ERROR_EXIT_VALUE);
2101 for (num=0; num<numScreens; num++)
2103 if (!(wmGD.screenNames[num] =
2104 (unsigned char *) XtMalloc (4*sizeof(char))))
2106 ShowWaitState (FALSE);
2107 Warning (((char *)GETMESSAGE(40, 13, "Insufficient memory for screen names")));
2108 ExitWM (WM_ERROR_EXIT_VALUE);
2110 /* default name is left justified, 3-chars max, zero terminated */
2111 sprintf((char *)wmGD.screenNames[num], UNSPECIFIED_SCREEN_NAME);
2114 #ifndef NO_MESSAGE_CATALOG
2117 void InitNlsStrings (void)
2122 * Initialize messages
2124 wmGD.okLabel=XmStringCreateLocalized((String)_DtOkString);
2125 wmGD.cancelLabel=XmStringCreateLocalized((String)_DtCancelString);
2126 wmGD.helpLabel=XmStringCreateLocalized((String)_DtHelpString);
2129 * catgets returns a pointer to an area that is over written
2130 * on each call to catgets.
2133 tmpString = ((char *)GETMESSAGE(40, 14, "Icons"));
2134 if ((wmNLS.default_icon_box_title =
2135 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2137 Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
2138 wmNLS.default_icon_box_title = "Icons";
2142 strcpy(wmNLS.default_icon_box_title, tmpString);
2145 tmpString = ((char *)GETMESSAGE(40, 20, "%s: %s on line %d of configuration file %s\n"));
2146 if ((pWarningStringFile =
2147 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2149 Warning (((char *)GETMESSAGE(40, 17, "Insufficient memory for local message string")));
2150 pWarningStringFile = "%s: %s on line %d of configuration file %s\n";
2154 strcpy(pWarningStringFile, tmpString);
2157 tmpString = ((char *)GETMESSAGE(40, 21, "%s: %s on line %d of specification string\n"));
2158 if ((pWarningStringLine =
2159 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2161 Warning (((char *)GETMESSAGE(40, 19, "Insufficient memory for local message string")));
2162 pWarningStringLine = "%s: %s on line %d of specification string\n";
2166 strcpy(pWarningStringLine, tmpString);
2170 tmpString = ((char *)GETMESSAGE(40, 22, "About Workspace Manager"));
2171 if ((wmNLS.defaultVersionTitle =
2172 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2174 Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
2175 wmNLS.defaultVersionTitle = "About Workspace Manager";
2179 strcpy(wmNLS.defaultVersionTitle, tmpString);
2182 tmpString = ((char *)GETMESSAGE(40, 23, "Workspace Manager - Help"));
2183 if ((wmNLS.defaultDtwmHelpTitle =
2184 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2186 Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
2187 wmNLS.defaultDtwmHelpTitle = "Workspace Manager - Help";
2191 strcpy(wmNLS.defaultDtwmHelpTitle, tmpString);
2194 tmpString = ((char *)GETMESSAGE(40, 24, "Workspace Manager - Help"));
2195 if ((wmNLS.defaultHelpTitle =
2196 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2198 Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
2199 wmNLS.defaultHelpTitle = "Workspace Manager - Help";
2203 strcpy(wmNLS.defaultHelpTitle, tmpString);
2206 } /* InitNlsStrings */
2211 /******************************<->*************************************
2218 * This function saves the display string for putenv in F_Exec.
2225 *************************************<->***********************************/
2228 InitWmDisplayEnv (void)
2232 char displayName[256];
2234 pDisplayName = DisplayString (DISPLAY);
2237 * Construct displayString for this string.
2239 strcpy(displayName, pDisplayName);
2240 sprintf(buffer, "DISPLAY=%s",displayName);
2243 * Allocate space for the display string
2245 if ((wmGD.displayString =
2246 (String)XtMalloc ((unsigned int) (strlen(buffer) + 1))) == NULL)
2248 wmGD.displayString = NULL;
2249 Warning (((char *)GETMESSAGE(40, 9,
2250 "Insufficient memory for displayString")));
2254 strcpy(wmGD.displayString, buffer);
2255 putenv(wmGD.displayString);
2258 } /* END OF FUNCTION InitWmDisplayEnv */
2260 #ifndef NO_HP_KEY_REMAP
2273 str_xref xref_rtn = NULL ;
2274 unsigned num_xref = 0 ;
2276 XDisplayKeycodes( dsp, &min_kc, &max_kc) ;
2277 kc_count = max_kc + 1 - min_kc ;
2278 key_map = XGetKeyboardMapping( dsp, min_kc, kc_count, &ks_per_kc) ;
2279 if( key_map == NULL )
2283 kc_count *= ks_per_kc ;
2288 KeySym ks = XStringToKeysym( std_xref[i].default_name) ;
2291 while( j < kc_count )
2293 if( key_map[j] == ks )
2295 /* Found keysym used in virtkey table in keymap,
2296 * so break -> j != kc_count
2304 /* Didn't find keysym of virtkey table, so add record to
2305 * returned list which will later cause replacement in
2308 xref_rtn = (str_xref) XtRealloc( (char *) xref_rtn,
2309 sizeof( str_xref_rec) * (num_xref + 2)) ;
2310 xref_rtn[num_xref++] = std_xref[i] ;
2311 xref_rtn[num_xref].default_name = NULL ;
2315 XFree( (char *) key_map) ;
2320 GetBindingsProperty(
2327 unsigned long num_items ;
2328 unsigned long bytes_after ;
2329 unsigned char *prop = NULL ;
2331 XGetWindowProperty( dsp, RootWindow( dsp, 0), property, 0, 1000000L,
2332 FALSE, XA_STRING, &actual_type, &actual_format, &num_items, &bytes_after,
2334 if( (actual_type != XA_STRING)
2335 || (actual_format != 8)
2336 || (num_items == 0) )
2344 *binding = (String) prop ;
2349 SetBindingsProperty(
2354 XChangeProperty( dsp, RootWindow( dsp, 0), property, XA_STRING, 8,
2355 PropModeReplace, (unsigned char *) binding, strlen( binding)) ;
2359 FixupBindingsString(
2360 String bindingsString,
2363 String fixed_str = XtNewString( bindingsString) ;
2364 String ptr_next = fixed_str ;
2366 while( repl_xref->default_name != NULL )
2368 String ks_ptr = strstr( ptr_next, repl_xref->default_name) ;
2369 unsigned orig_len = strlen( repl_xref->default_name) ;
2371 if( ks_ptr == NULL )
2373 /* Only increment to next replacement when no other instances
2374 * are found in fixed_str.
2377 ptr_next = fixed_str ;
2381 if( (strpbrk( (ks_ptr - 1), " \t>") == (ks_ptr - 1))
2382 && (strpbrk( ks_ptr, " \t\n") == (ks_ptr + orig_len)) )
2384 unsigned new_len = strlen( repl_xref->new_name) ;
2385 unsigned suffix_len = strlen( ks_ptr + orig_len) ;
2387 if( new_len > orig_len )
2389 unsigned new_ttl_len = strlen( fixed_str) + new_len - orig_len ;
2390 unsigned prefix_len ;
2393 prefix_len = strlen( fixed_str) ;
2394 fixed_str = XtRealloc( fixed_str, (new_ttl_len + 1)) ;
2395 ks_ptr = fixed_str + prefix_len ;
2397 memmove( (ks_ptr + new_len), (ks_ptr + orig_len), (suffix_len + 1)) ;
2398 memcpy( ks_ptr, repl_xref->new_name, new_len) ;
2400 ptr_next = ks_ptr + new_len ;
2404 ptr_next = ks_ptr + 1 ;
2415 /* This routine examines the X server's key map table to determine
2416 * if certain HP-specific keysyms are missing. If they are, then
2417 * the Motif virtual binding table properties are updated to utilize
2418 * generic X keysyms instead of the missing HP vendor keysyms.
2419 * In particular, this fixes the Motif virtual key binding table for
2420 * correct operation on HP systems using the AT2/DIN style keyboard.
2422 static char *prop_names[] = { "_MOTIF_BINDINGS",
2423 "_MOTIF_DEFAULT_BINDINGS" } ;
2424 static str_xref_rec std_xref[] = { { "hpInsertChar", "Insert" },
2425 { "hpDeleteChar", "Delete" },
2428 Boolean PropChanged4DIN = FALSE ;
2430 char *bindingsString ;
2431 unsigned prop_existed ;
2433 str_xref vkeysym_xref ;
2434 unsigned num_props = XtNumber( prop_names) ;
2436 vkeysym_xref = GetReplacementList( dsp, std_xref, XtNumber(std_xref)) ;
2437 if( vkeysym_xref == NULL )
2439 return PropChanged4DIN ;
2442 prop_atoms = (Atom *) XtMalloc( sizeof( Atom) * num_props) ;
2443 XInternAtoms(dsp, prop_names, num_props, FALSE, prop_atoms);
2445 prop_existed = FALSE ;
2447 while( i < num_props )
2449 if( GetBindingsProperty( dsp, prop_atoms[i], &bindingsString) )
2451 String new_bstring = FixupBindingsString( bindingsString,
2453 prop_existed = TRUE ;
2454 XFree( bindingsString) ;
2456 if( new_bstring != NULL )
2458 SetBindingsProperty( dsp, prop_atoms[i], new_bstring) ;
2459 XtFree( new_bstring) ;
2466 bindingsString = NULL ;
2467 /* FIXME: this is an unexported openmotif procedure */
2468 extern void _XmVirtKeysLoadFallbackBindings(Display *dsp, String *binding);
2469 _XmVirtKeysLoadFallbackBindings( dsp, &bindingsString) ;
2470 XtFree( bindingsString) ;
2473 while( i < num_props )
2475 if( GetBindingsProperty( dsp, prop_atoms[i], &bindingsString) )
2477 String new_bstring = FixupBindingsString( bindingsString,
2479 XtFree( bindingsString) ;
2480 if( new_bstring != NULL )
2482 PropChanged4DIN = TRUE ;
2483 SetBindingsProperty( dsp, prop_atoms[i], new_bstring) ;
2484 XtFree( new_bstring) ;
2486 XFree( bindingsString) ;
2492 XtFree( (char *) vkeysym_xref) ;
2493 XtFree( (char *) prop_atoms) ;
2494 return PropChanged4DIN ;
2496 #endif /* NO_HP_KEY_REMAP */
2498 /**************************** eof ***************************/