mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
2482 lines
64 KiB
C
2482 lines
64 KiB
C
/*
|
||
* CDE - Common Desktop Environment
|
||
*
|
||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
||
*
|
||
* These libraries and programs are free software; you can
|
||
* redistribute them and/or modify them under the terms of the GNU
|
||
* Lesser General Public License as published by the Free Software
|
||
* Foundation; either version 2 of the License, or (at your option)
|
||
* any later version.
|
||
*
|
||
* These libraries and programs are distributed in the hope that
|
||
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
||
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||
* PURPOSE. See the GNU Lesser General Public License for more
|
||
* details.
|
||
*
|
||
* You should have received a copy of the GNU Lesser General Public
|
||
* License along with these libraries and programs; if not, write
|
||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
||
* Floor, Boston, MA 02110-1301 USA
|
||
*/
|
||
/*
|
||
* (c) Copyright 1989, 1990, 1991, 1992, 1993, 1994 OPEN SOFTWARE FOUNDATION, INC.
|
||
* ALL RIGHTS RESERVED
|
||
*/
|
||
/*
|
||
* Motif Release 1.2.4
|
||
*/
|
||
/*
|
||
* (c) Copyright 1987, 1988, 1989, 1990, 1993, 1994 HEWLETT-PACKARD COMPANY
|
||
* (c) Copyright 1993, 1994 International Business Machines Corp.
|
||
* (c) Copyright 1993, 1994 Sun Microsystems, Inc.
|
||
* (c) Copyright 1993, 1994 Novell, Inc.
|
||
*/
|
||
|
||
/*
|
||
* Included Files:
|
||
*/
|
||
|
||
#include "WmGlobal.h"
|
||
#include "WmResNames.h"
|
||
#include "WmHelp.h"
|
||
#include "WmICCC.h"
|
||
#define DTWM_NEED_FNTPL
|
||
#include "WmIBitmap.h"
|
||
#include "WmOL.h"
|
||
#include <X11/Xos.h>
|
||
#include <X11/cursorfont.h>
|
||
#include <Xm/Xm.h>
|
||
#include <Xm/AtomMgr.h>
|
||
#include <X11/Shell.h>
|
||
#include <X11/Core.h>
|
||
#include <X11/keysym.h>
|
||
#ifndef NO_HP_KEY_REMAP
|
||
#include <Xm/VirtKeysP.h>
|
||
|
||
typedef struct
|
||
{
|
||
String default_name ;
|
||
String new_name ;
|
||
} str_xref_rec, *str_xref ;
|
||
#endif /* NO_HP_KEY_REMAP */
|
||
#include <Dt/GetDispRes.h>
|
||
#include <Dt/SessionP.h>
|
||
#include <Dt/SessionM.h>
|
||
#include <Dt/DtP.h>
|
||
#include <Dt/Message.h>
|
||
#include <Dt/WsmM.h>
|
||
#include <Dt/EnvControlP.h>
|
||
|
||
/* Busy is also defined in the BMS -> bms.h. This conflicts with
|
||
* /usr/include/X11/Xasync.h on ibm.
|
||
*/
|
||
#ifdef _AIX
|
||
#ifdef Busy
|
||
#undef Busy
|
||
#endif
|
||
#endif
|
||
#include <X11/Xlibint.h>
|
||
|
||
/*
|
||
* include extern functions
|
||
*/
|
||
#include "WmBackdrop.h"
|
||
#include "WmCDInfo.h"
|
||
#include "WmColormap.h"
|
||
#include "WmError.h"
|
||
#include "WmEvent.h"
|
||
#include "WmEwmh.h"
|
||
#include "WmFeedback.h"
|
||
#include "WmFunction.h"
|
||
#include "WmIDecor.h"
|
||
#include "WmIPC.h"
|
||
#include "WmIPlace.h"
|
||
#include "WmIconBox.h"
|
||
#include "WmKeyFocus.h"
|
||
#include "WmPanelP.h" /* for typedef in WmManage.h */
|
||
#include "WmManage.h"
|
||
#include "WmMenu.h"
|
||
#include "WmPresence.h"
|
||
#include "WmProperty.h"
|
||
#include "WmResCvt.h"
|
||
#include "WmResource.h"
|
||
#include "WmSignal.h"
|
||
#include "WmProtocol.h"
|
||
#include "WmCDecor.h"
|
||
#include "stdio.h"
|
||
#include "WmResParse.h"
|
||
#include <stdlib.h>
|
||
#include "WmXSMP.h"
|
||
|
||
/*
|
||
* Function Declarations:
|
||
*/
|
||
|
||
#include "WmInitWs.h"
|
||
|
||
static void InsureDefaultBackdropDir(char **ppchBackdropDirs);
|
||
void InitWmDisplayEnv (void);
|
||
#ifndef NO_MESSAGE_CATALOG
|
||
void InitNlsStrings (void);
|
||
#endif
|
||
#ifndef NO_HP_KEY_REMAP
|
||
Boolean VirtKeys4DIN(Display *dpy);
|
||
#endif /* NO_HP_KEY_REMAP */
|
||
|
||
/* limited to 3 chars max */
|
||
#define UNSPECIFIED_SCREEN_NAME "fbk"
|
||
char **dpy2Argv; /* copy for second display */
|
||
int dpy2Argc;
|
||
/*
|
||
* Global Variables:
|
||
*/
|
||
extern int firstTime;
|
||
#ifndef NO_MESSAGE_CATALOG
|
||
extern char * pWarningStringFile;
|
||
extern char * pWarningStringLine;
|
||
#endif
|
||
|
||
/*
|
||
* InitMouseBinding
|
||
*
|
||
* Special case for a two button mouse; move the BMENU binding
|
||
* from Button3 to Button2. Fails for one-button mice.
|
||
*/
|
||
static void
|
||
InitMouseBinding(void)
|
||
{
|
||
wmGD.numMouseButtons = XGetPointerMapping(DISPLAY, (unsigned char *)0, 0);
|
||
|
||
if (wmGD.numMouseButtons < 3) {
|
||
wmGD.bMenuButton = Button2;
|
||
} else {
|
||
wmGD.bMenuButton = Button3;
|
||
}
|
||
}
|
||
|
||
/******************************<->*************************************
|
||
*
|
||
* BuildLockMaskSequence ()
|
||
*
|
||
* Set up the sequence of modifier masks to use to when grabbing
|
||
* key- and button-bindings. This sequence of masks is NULL
|
||
* terminated.
|
||
*
|
||
* Input:
|
||
* wmGD.lockingModMask
|
||
*
|
||
* Output:
|
||
* wmGD.pLockMaskSequence
|
||
*
|
||
*
|
||
*************************************<->***********************************/
|
||
static void
|
||
BuildLockMaskSequence(void)
|
||
{
|
||
int j, k;
|
||
unsigned int mask;
|
||
unsigned int thisbit;
|
||
Boolean bit_on;
|
||
int num_masks;
|
||
int num_bits;
|
||
int bit;
|
||
int run;
|
||
|
||
/*
|
||
* Count the bits to determine the number of elements in
|
||
* the mask sequence. The actual number of masks is
|
||
* 2^<bitcount> - 1. We're not interested in the case
|
||
* where there none of the mask bits are set.
|
||
*/
|
||
mask = wmGD.lockingModMask;
|
||
|
||
num_bits=0;
|
||
while (mask)
|
||
{
|
||
if (mask & 0x1)
|
||
{
|
||
num_bits++;
|
||
}
|
||
mask = mask >> 1;
|
||
}
|
||
num_masks = (0x1 << num_bits) - 1;
|
||
|
||
/*
|
||
* Allocate the space for the mask sequence + terminator.
|
||
*/
|
||
wmGD.pLockMaskSequence = (unsigned int *)
|
||
XtCalloc (num_masks+1, sizeof (unsigned int));
|
||
|
||
/*
|
||
* Fill in the mask sequence
|
||
*/
|
||
mask = wmGD.lockingModMask;
|
||
thisbit = 0x1;
|
||
bit = 0;
|
||
while (mask && thisbit)
|
||
{
|
||
/* find next bit */
|
||
while (!(thisbit & mask))
|
||
{
|
||
thisbit = thisbit << 1;
|
||
}
|
||
|
||
/* clear it from mask */
|
||
mask &= ~thisbit;
|
||
|
||
bit++;
|
||
|
||
/*
|
||
* Set it in the appropriate slots in the
|
||
* mask sequence. The start of the loop is
|
||
* funny because we skip the case of all the
|
||
* bits cleared.
|
||
*/
|
||
run = (0x1 << (bit-1)); /* number of consecutive masks to set
|
||
bits in */
|
||
bit_on = False; /* are we setting bits or not? */
|
||
|
||
for (j=0, k=run-1; j<num_masks; j++, k--)
|
||
{
|
||
if (k < 1)
|
||
{
|
||
if (bit_on)
|
||
bit_on = False;
|
||
else
|
||
bit_on = True;
|
||
|
||
k = run;
|
||
}
|
||
|
||
if (bit_on) wmGD.pLockMaskSequence[j] |= thisbit;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/******************************<->*************************************
|
||
*
|
||
* SetupLockingModifierMask ()
|
||
*
|
||
* Set up the mask used to ignore locking modifier keys (e.g. Shift Lock)
|
||
* when processing key- and button-bindings.
|
||
*
|
||
* We want to try to ignore the set of locking modifers
|
||
* such as Shift Lock, Num Lock, Kana Lock, etc. This involves
|
||
* some amount of guessing since these things can be mapped
|
||
* onto any of the Mod1-Mod5 modifiers. The approach taken is to
|
||
* identify the mapping of the locking modifier keysyms to
|
||
* Mod1-Mod5 and build the set of masks needed to ignore them.
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
/*
|
||
* This is the set of locking modifiers keysyms that might be
|
||
* bound to Mod1-Mod5. (Caps Lock is handled independently of
|
||
* this set.)
|
||
*/
|
||
static KeySym pksLockingMods[] = {
|
||
XK_Scroll_Lock,
|
||
XK_Kana_Lock,
|
||
XK_Num_Lock,
|
||
XK_Mode_switch
|
||
};
|
||
|
||
#define NUM_LOCKING_MODS (sizeof(pksLockingMods)/sizeof(KeySym))
|
||
|
||
static void
|
||
SetupLockingModifierMask(void)
|
||
{
|
||
int i, j, start_index;
|
||
XModifierKeymap *modifier_map = NULL;
|
||
static Modifiers mod_masks[] = { None, Mod1Mask, Mod2Mask,
|
||
Mod3Mask, Mod4Mask, Mod5Mask };
|
||
Display *dpy = wmGD.display;
|
||
int pkcLockingMods[NUM_LOCKING_MODS];
|
||
|
||
int kc;
|
||
|
||
for (i=0; i<NUM_LOCKING_MODS; i++)
|
||
{
|
||
pkcLockingMods[i] = XKeysymToKeycode(dpy, pksLockingMods[i]);
|
||
}
|
||
|
||
/*
|
||
* Start out with Caps lock and add others we discover.
|
||
*/
|
||
wmGD.lockingModMask = LockMask;
|
||
|
||
modifier_map = XGetModifierMapping(dpy);
|
||
|
||
/* just check Mod1 through Mod5 */
|
||
start_index = modifier_map->max_keypermod * Mod1MapIndex;
|
||
|
||
for (i = start_index; i < modifier_map->max_keypermod * 8; i++) {
|
||
int this_mod = ((i - start_index) / modifier_map->max_keypermod) + 1;
|
||
|
||
kc = modifier_map->modifiermap[i];
|
||
if (kc)
|
||
{
|
||
for (j=0; j<NUM_LOCKING_MODS; j++)
|
||
{
|
||
if (pkcLockingMods[j] == kc)
|
||
{
|
||
wmGD.lockingModMask |= mod_masks[this_mod];
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
BuildLockMaskSequence();
|
||
|
||
if(modifier_map != NULL)
|
||
XFreeModifiermap(modifier_map);
|
||
|
||
}
|
||
|
||
/******************************<->*************************************
|
||
*
|
||
* MappingEventHandler (Widget, XtPointer, XEvent *, Boolean *)
|
||
*
|
||
* Catch and handle changes to the mapping of the modifier keys.
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
static void
|
||
MappingEventHandler(
|
||
Widget w,
|
||
XtPointer client_data,
|
||
XEvent *event,
|
||
Boolean *cont_to_dispatch)
|
||
{
|
||
if(event->xany.type != MappingNotify ||
|
||
event->xmapping.request == MappingPointer)
|
||
return;
|
||
|
||
if(event->xmapping.request == MappingModifier)
|
||
SetupLockingModifierMask();
|
||
}
|
||
|
||
|
||
/******************************<->*************************************
|
||
*
|
||
* InitWmGlobal (argc, argv, environ)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* This function initializes the workspace manager.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* argc = number of command line arguments (+1)
|
||
*
|
||
* argv = window manager command line arguments
|
||
*
|
||
* environ = window manager environment
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* wmGD = (initialize the global data structure)
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
void InitWmGlobal (int argc, char *argv [], char *environ [])
|
||
{
|
||
XSetWindowAttributes sAttributes;
|
||
int scr;
|
||
int managed = 0;
|
||
char pch[80];
|
||
Boolean activeSet = False;
|
||
Boolean processedGlobalResources = False;
|
||
WmScreenData *pSD;
|
||
Arg args[20];
|
||
int argnum;
|
||
char *res_class;
|
||
int savedArgc;
|
||
|
||
wmGD.errorFlag = False;
|
||
wmGD.dtSD = NULL;
|
||
wmGD.iSlideUpsInProgress = 0;
|
||
|
||
SetupWmSignalHandlers (0); /* dummy paramater */
|
||
|
||
|
||
/*
|
||
* Do (pre-toolkit) initialization:
|
||
*/
|
||
|
||
wmGD.windowContextType = XUniqueContext ();
|
||
wmGD.screenContextType = XUniqueContext ();
|
||
#ifndef IBM_169380
|
||
wmGD.cmapWindowContextType = XUniqueContext ();
|
||
#endif
|
||
wmGD.mwmWindowContextType = XUniqueContext ();
|
||
|
||
/* copy argv (the XtInititalize changes the original) for use in restart */
|
||
savedArgc = argc;
|
||
CopyArgv (argc, argv);
|
||
|
||
wmGD.environ = environ;
|
||
|
||
wmGD.pWmPB = _DtWmParseNewBuf();
|
||
|
||
|
||
|
||
/* set our name */
|
||
if ((wmGD.mwmName = (char*)strrchr (wmGD.argv[0], '/')) != NULL)
|
||
{
|
||
wmGD.mwmName++;
|
||
}
|
||
else
|
||
{
|
||
wmGD.mwmName = wmGD.argv[0];
|
||
}
|
||
if (MwmBehavior)
|
||
{
|
||
res_class = WM_RESOURCE_CLASS;
|
||
}
|
||
else
|
||
{
|
||
res_class = DT_WM_RESOURCE_CLASS;
|
||
}
|
||
wmGD.statusColorServer = CSERVE_NOT_AVAILABLE;
|
||
|
||
wmGD.display = (Display *)NULL;
|
||
wmGD.topLevelW = (Widget)NULL;
|
||
|
||
/*
|
||
* Do X Tookit initialization:
|
||
*/
|
||
|
||
XtToolkitInitialize();
|
||
|
||
wmGD.mwmAppContext = XtCreateApplicationContext();
|
||
AddWmResourceConverters ();
|
||
wmGD.display = XtOpenDisplay (wmGD.mwmAppContext,
|
||
NULL,
|
||
wmGD.mwmName,
|
||
res_class,
|
||
NULL,
|
||
0,
|
||
&argc, /* R5 changed from Cardinal to int*/
|
||
argv);
|
||
|
||
if (!wmGD.display)
|
||
{
|
||
Warning(((char *)GETMESSAGE(40, 1, "Could not open display.")));
|
||
ExitWM (WM_ERROR_EXIT_VALUE);
|
||
}
|
||
|
||
#if defined(sun) && defined(ALLPLANES)
|
||
{
|
||
int dummy;
|
||
|
||
wmGD.allplanes = XAllPlanesQueryExtension(wmGD.display,
|
||
&dummy, &dummy);
|
||
}
|
||
#endif /* defined(sun) && defined(ALLPLANES) */
|
||
|
||
/*
|
||
* Setup error handling:
|
||
*/
|
||
|
||
WmInitErrorHandler(wmGD.display);
|
||
|
||
/*
|
||
* Initialize cursor size info and
|
||
* display the startup cursor.
|
||
*/
|
||
|
||
InitCursorInfo ();
|
||
InitWmDisplayEnv ();
|
||
ShowWaitState (TRUE);
|
||
|
||
/*
|
||
* Initialize support for BMenu virtual mouse binding
|
||
*/
|
||
InitMouseBinding();
|
||
/*
|
||
* Set up the _MOTIF_BINDINGS property on the root window
|
||
* of screen 0. Must do this before we create shells.
|
||
*/
|
||
|
||
ProcessMotifBindings ();
|
||
#ifndef NO_HP_KEY_REMAP
|
||
|
||
/* VirtKeys4DIN deals with a shortcoming in the OSF/Motif
|
||
* mechanism for selecting a virtual key binding table.
|
||
* When a client connects to a display, code inside of libXm
|
||
* gets the vendor identifier from the server and uses this
|
||
* identifier to select a default virtual key binding table
|
||
* from an internal list of possible tables (provided to
|
||
* OSF by vendors). A virtual key binding table maps OSF
|
||
* virtual keysyms to an "appropriate" set of X keysyms for
|
||
* a particular server vendor. The problem with this
|
||
* mechanism is that it only allows for a _single_ default
|
||
* virtual key binding table per server vendor. If a
|
||
* hardware vendor ships more than one distinct keyboard,
|
||
* then the single virtual key binding table selected for
|
||
* that server might not be appropriate for all keyboards.
|
||
* The HP migration from the "ITF" keyboard to the "PC-style"
|
||
* keyboard causes this problem to be exposed for Motif
|
||
* clients. The default HP virtual key binding table maps
|
||
* osfInsert and osfDelete to hpInsertChar and hpDeleteChar,
|
||
* respectively. But since hpInsertChar and hpDeleteChar
|
||
* are absent from the PC-style keyboard, HP servers with
|
||
* this keyboard do not generate key events that map to the
|
||
* important osfInsert and osfDelete virtual keys.
|
||
* The Motif 1.2 version of libXm installs (one or two)
|
||
* properties on the root window, these properties exporting
|
||
* the virtual key binding table to be used by all (subsequently
|
||
* connected) Motif clients. The VirtKeys4DIN routine attempts
|
||
* to ensure that the virtual key binding table exported by
|
||
* those properties does not include dependencies on keysyms
|
||
* that are not available in the server's current modmap.
|
||
* The routine accomplishes this by searching the keyboard
|
||
* mapping of the display for the absence of known problematic
|
||
* keysyms. For those keysyms that are missing from the
|
||
* keyboard map, the corresponding dependencies in the
|
||
* virtual key binding table are altered to use pre-determined
|
||
* substitutes (which are generic X keysyms that are present
|
||
* on the PC-style keyboard mapping).
|
||
* The side-effects of this routine are that if there are no
|
||
* key binding properties on the root window when this routine
|
||
* is called, there will be a property installed (this occurs
|
||
* with all Motif 1.2 clients anyway). Since the virtual key
|
||
* binding table is only altered if it contains a keysym that
|
||
* is missing from the server's keyboard mapping, there is
|
||
* little chance of deleterious effects.
|
||
*/
|
||
VirtKeys4DIN(DISPLAY);
|
||
#endif /* NO_HP_KEY_REMAP */
|
||
|
||
argnum = 0;
|
||
XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
|
||
XtSetArg (args[argnum], XtNx, 10000); argnum++;
|
||
XtSetArg (args[argnum], XtNy, 0); argnum++;
|
||
XtSetArg (args[argnum], XtNwidth, 10); argnum++;
|
||
XtSetArg (args[argnum], XtNheight, 10); argnum++;
|
||
XtSetArg (args[argnum], XtNmappedWhenManaged, False); argnum++;
|
||
XtSetArg (args[argnum], XtNjoinSession, True); argnum++;
|
||
XtSetArg (args[argnum], XtNrestartStyle, SmRestartNever); argnum++;
|
||
XtSetArg (args[argnum], XtNargc, savedArgc); argnum++;
|
||
XtSetArg (args[argnum], XtNargv, wmGD.argv); argnum++;
|
||
|
||
/* create topmost shell (application shell) */
|
||
wmGD.topLevelW = XtAppCreateShell (NULL,
|
||
res_class,
|
||
sessionShellWidgetClass,
|
||
DISPLAY,
|
||
args,
|
||
argnum);
|
||
|
||
XtAddEventHandler(wmGD.topLevelW, NoEventMask, True,
|
||
MappingEventHandler, NULL);
|
||
|
||
/* Add callbacks used for communication with Session Manager. */
|
||
AddSMCallbacks ();
|
||
|
||
/* allocate namespace for screens */
|
||
InitScreenNames();
|
||
|
||
/*
|
||
* Determine the screen management policy (all or none)
|
||
* Process command line arguments that we handle
|
||
* This could change the number of screens we manage
|
||
*/
|
||
ProcessGlobalScreenResources ();
|
||
ProcessCommandLine (argc, argv);
|
||
|
||
/*
|
||
* Make sure backdrops are in our icon search path.
|
||
* This call MUST occur before ANY icons are looked up either
|
||
* explicitly or through resource processing!!!
|
||
* Uses variables set by ProcessGlobalScreenResources and
|
||
* ProcessCommandLine.
|
||
*/
|
||
{
|
||
int sNum;
|
||
Boolean useMaskRtn;
|
||
Boolean useMultiColorIcons;
|
||
Boolean useIconFileCacheRtn;
|
||
String sBdPath;
|
||
|
||
sNum = (wmGD.numScreens == 1) ? DefaultScreen(DISPLAY) : 0;
|
||
|
||
XmeGetIconControlInfo(ScreenOfDisplay(DISPLAY, sNum), &useMaskRtn,
|
||
&useMultiColorIcons, &useIconFileCacheRtn);
|
||
|
||
sBdPath = wmGD.backdropDirs;
|
||
InsureDefaultBackdropDir ((char **) &sBdPath);
|
||
|
||
_DtWsmSetBackdropSearchPath(XScreenOfDisplay(DISPLAY, sNum),
|
||
sBdPath, useMultiColorIcons);
|
||
|
||
XtFree(sBdPath);
|
||
}
|
||
|
||
/*
|
||
* Allocate data and initialize for screens we manage:
|
||
*/
|
||
|
||
if (!(wmGD.Screens = (WmScreenData *)
|
||
XtCalloc (wmGD.numScreens, sizeof(WmScreenData))))
|
||
{
|
||
ShowWaitState (FALSE);
|
||
Warning (((char *)GETMESSAGE(40, 2, "Insufficient memory for Screen data")));
|
||
ExitWM (WM_ERROR_EXIT_VALUE);
|
||
}
|
||
else
|
||
{
|
||
|
||
sAttributes.event_mask = SubstructureRedirectMask;
|
||
|
||
for (scr=0; scr<wmGD.numScreens; scr++)
|
||
{
|
||
int sNum;
|
||
|
||
/*
|
||
* Gain control of the root windows of each screen:
|
||
*/
|
||
|
||
sNum = (wmGD.numScreens == 1) ? DefaultScreen(DISPLAY) : scr;
|
||
wmGD.errorFlag = False;
|
||
|
||
XChangeWindowAttributes (DISPLAY, RootWindow (DISPLAY, sNum),
|
||
CWEventMask, &sAttributes);
|
||
/*
|
||
* Do XSync to force server action and catch errors
|
||
* immediately.
|
||
*/
|
||
XSync (DISPLAY, False /* do not discard events */);
|
||
|
||
if ((wmGD.errorFlag) &&
|
||
(RootWindow (DISPLAY, sNum) == (Window) wmGD.errorResource) &&
|
||
(wmGD.errorRequestCode == X_ChangeWindowAttributes))
|
||
{
|
||
sprintf(pch,
|
||
((char *)GETMESSAGE(40, 3, "Another window manager is running on screen %d")), sNum);
|
||
Warning ((char *) &pch[0]);
|
||
wmGD.Screens[scr].managed = False;
|
||
}
|
||
else
|
||
{
|
||
if (!processedGlobalResources)
|
||
{
|
||
enum {
|
||
XA_DT_SESSION_HINTS, XA_DT_SM_WM_PROTOCOL,
|
||
XA_DT_SM_START_ACK_WINDOWS, XA_DT_SM_STOP_ACK_WINDOWS,
|
||
XA_DT_WM_WINDOW_ACK, XA_DT_WM_EXIT_SESSION,
|
||
XA_DT_WM_LOCK_DISPLAY, XA_DT_WM_READY, NUM_ATOMS };
|
||
static char *atom_names[] = {
|
||
_XA_DT_SESSION_HINTS, _XA_DT_SM_WM_PROTOCOL,
|
||
_XA_DT_SM_START_ACK_WINDOWS, _XA_DT_SM_STOP_ACK_WINDOWS,
|
||
_XA_DT_WM_WINDOW_ACK, _XA_DT_WM_EXIT_SESSION,
|
||
_XA_DT_WM_LOCK_DISPLAY, _XA_DT_WM_READY };
|
||
|
||
Atom atoms[XtNumber(atom_names)];
|
||
XInternAtoms(DISPLAY, atom_names, XtNumber(atom_names),
|
||
False, atoms);
|
||
|
||
wmGD.xa_DT_SESSION_HINTS = atoms[XA_DT_SESSION_HINTS];
|
||
wmGD.xa_DT_SM_WM_PROTOCOL = atoms[XA_DT_SM_WM_PROTOCOL];
|
||
wmGD.xa_DT_SM_START_ACK_WINDOWS =
|
||
atoms[XA_DT_SM_START_ACK_WINDOWS];
|
||
wmGD.xa_DT_SM_STOP_ACK_WINDOWS =
|
||
atoms[XA_DT_SM_STOP_ACK_WINDOWS];
|
||
wmGD.xa_DT_WM_WINDOW_ACK = atoms[XA_DT_WM_WINDOW_ACK];
|
||
wmGD.xa_DT_WM_EXIT_SESSION = atoms[XA_DT_WM_EXIT_SESSION];
|
||
wmGD.xa_DT_WM_LOCK_DISPLAY = atoms[XA_DT_WM_LOCK_DISPLAY];
|
||
wmGD.xa_DT_WM_READY = atoms[XA_DT_WM_READY];
|
||
InitOLCompat();
|
||
wmGD.hasShape = XShapeQueryExtension (DISPLAY,
|
||
&wmGD.shapeEventBase,
|
||
&wmGD.shapeErrorBase);
|
||
|
||
wmGD.replayEnterEvent = False;
|
||
wmGD.menuActive = NULL;
|
||
wmGD.menuUnpostKeySpec = NULL;
|
||
wmGD.F_NextKeySpec = NULL;
|
||
wmGD.F_PrevKeySpec = NULL;
|
||
wmGD.passKeysActive = False;
|
||
wmGD.passKeysKeySpec = NULL;
|
||
wmGD.checkHotspot = False;
|
||
wmGD.configAction = NO_ACTION;
|
||
wmGD.configPart = FRAME_NONE;
|
||
wmGD.configSet = False;
|
||
wmGD.preMove = False;
|
||
wmGD.gadgetClient = NULL;
|
||
wmGD.wmTimers = NULL;
|
||
wmGD.clientDefaultTitle =
|
||
XmStringCreateLocalized(DEFAULT_CLIENT_TITLE);
|
||
wmGD.iconDefaultTitle =
|
||
XmStringCreateLocalized(DEFAULT_ICON_TITLE);
|
||
wmGD.attributesWindow = (Window)NULL;
|
||
wmGD.clickData.pCD = NULL;
|
||
wmGD.clickData.clickPending = False;
|
||
wmGD.clickData.doubleClickPending = False;
|
||
wmGD.systemModalActive = False;
|
||
wmGD.activeIconTextDisplayed = False;
|
||
wmGD.movingIcon = False;
|
||
wmGD.queryScreen = True;
|
||
wmGD.dataType = GLOBAL_DATA_TYPE;
|
||
|
||
wmGD.pLockMaskSequence = NULL;
|
||
SetupLockingModifierMask ();
|
||
wmGD.requestContextWin = (Window) 0L;
|
||
wmGD.cppCommand = NULL;
|
||
wmGD.evLastButton.button = 0;
|
||
wmGD.bReplayedButton = False;
|
||
wmGD.bSuspendSecondaryRestack = False;
|
||
/*
|
||
* Get a second display connection for
|
||
* internal WM windows.
|
||
*/
|
||
wmGD.display1 = XtOpenDisplay (wmGD.mwmAppContext,
|
||
NULL,
|
||
wmGD.mwmName,
|
||
res_class,
|
||
NULL,
|
||
0,
|
||
&dpy2Argc,
|
||
dpy2Argv);
|
||
if (!wmGD.display1)
|
||
{
|
||
ShowWaitState (FALSE);
|
||
Warning(((char *)GETMESSAGE(40, 4, "Could not open second display connection.")));
|
||
ExitWM (WM_ERROR_EXIT_VALUE);
|
||
}
|
||
|
||
_DtGetSmWindow(DISPLAY,
|
||
RootWindow(DISPLAY, 0),
|
||
&wmGD.dtSmWindow) ;
|
||
|
||
/* create topmost shell (application shell) */
|
||
argnum = 0;
|
||
XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
|
||
XtSetArg (args[argnum], XtNx, 10000); argnum++;
|
||
XtSetArg (args[argnum], XtNy, 0); argnum++;
|
||
XtSetArg (args[argnum], XtNwidth, 10); argnum++;
|
||
XtSetArg (args[argnum], XtNheight, 10); argnum++;
|
||
XtSetArg (args[argnum],
|
||
XtNmappedWhenManaged, False); argnum++;
|
||
|
||
wmGD.topLevelW1 =
|
||
XtAppCreateShell (NULL,
|
||
res_class,
|
||
applicationShellWidgetClass,
|
||
DISPLAY1,
|
||
args,
|
||
argnum);
|
||
|
||
|
||
|
||
/*
|
||
* if this is the first screen we can manage,
|
||
* process global.
|
||
*/
|
||
|
||
processedGlobalResources = True;
|
||
|
||
/*
|
||
* Get the _MOTIF_WM_INFO property and determine
|
||
* the startup / restart state.
|
||
*/
|
||
|
||
ProcessMotifWmInfo (RootWindow (DISPLAY, sNum));
|
||
|
||
/*
|
||
* Process global window manager resources:
|
||
*/
|
||
#ifndef NO_MESSAGE_CATALOG
|
||
InitBuiltinSystemMenu();
|
||
#endif
|
||
|
||
ProcessWmResources ();
|
||
|
||
}
|
||
|
||
InitWmScreen (&(wmGD.Screens[scr]), sNum);
|
||
wmGD.Screens[scr].managed = True;
|
||
managed++;
|
||
GetDtSessionHints(&(wmGD.Screens[scr]), sNum);
|
||
|
||
if (!activeSet)
|
||
{
|
||
activeSet = True;
|
||
ACTIVE_PSD = &wmGD.Screens[scr];
|
||
}
|
||
}
|
||
}
|
||
|
||
if (managed == 0)
|
||
{
|
||
/*
|
||
* No screens for me to manage, give up.
|
||
*/
|
||
ShowWaitState (FALSE);
|
||
Warning (((char *)GETMESSAGE(40, 5, "Unable to manage any screens on display.")));
|
||
ExitWM (WM_ERROR_EXIT_VALUE);
|
||
}
|
||
}
|
||
/*
|
||
* Initialize the IPC mechanism
|
||
*/
|
||
dtInitialize(argv[0], wmGD.mwmAppContext);
|
||
#ifndef NO_MESSAGE_CATALOG
|
||
/*
|
||
* Set up NLS error messages.
|
||
* Must be done after DtInitialize.
|
||
*/
|
||
InitNlsStrings ();
|
||
#endif
|
||
|
||
/*
|
||
* For multiple connections to the server, turn off
|
||
* the geometry manager's insistence on synchronous
|
||
* management.
|
||
*/
|
||
|
||
argnum = 0;
|
||
XtSetArg (args[argnum], XmNuseAsyncGeometry, True); argnum++;
|
||
XtSetValues (wmGD.topLevelW, args, argnum);
|
||
XtSetValues (wmGD.topLevelW1, args, argnum);
|
||
|
||
|
||
/*
|
||
* Prepare to have child processes (e.g., exec'ed commands).
|
||
* The X connection should not be passed on to child processes
|
||
* (it should be automatically closed when a fork is done).
|
||
*/
|
||
|
||
if (fcntl (ConnectionNumber (DISPLAY), F_SETFD, 1) == -1)
|
||
{
|
||
ShowWaitState (FALSE);
|
||
Warning (((char *)GETMESSAGE(40, 6, "Cannot configure X connection")));
|
||
ExitWM (WM_ERROR_EXIT_VALUE);
|
||
}
|
||
|
||
|
||
{
|
||
enum { XA_DT_WORKSPACE_HINTS, XA_DT_WORKSPACE_PRESENCE,
|
||
XA_DT_WORKSPACE_INFO, XA_WmNall,
|
||
XA_DT_WORKSPACE_EMBEDDED_CLIENTS, XA_DT_WM_REQUEST,
|
||
XA_DT_WORKSPACE_LIST, XA_DT_WORKSPACE_CURRENT, NUM_ATOMS };
|
||
static char *atom_names[] = {
|
||
_XA_DT_WORKSPACE_HINTS, _XA_DT_WORKSPACE_PRESENCE,
|
||
_XA_DT_WORKSPACE_INFO, WmNall,
|
||
_XA_DT_WORKSPACE_EMBEDDED_CLIENTS, _XA_DT_WM_REQUEST,
|
||
_XA_DT_WORKSPACE_LIST, _XA_DT_WORKSPACE_CURRENT };
|
||
|
||
Atom atoms[XtNumber(atom_names)];
|
||
XInternAtoms(DISPLAY, atom_names, XtNumber(atom_names), False, atoms);
|
||
|
||
wmGD.xa_DT_WORKSPACE_HINTS = atoms[XA_DT_WORKSPACE_HINTS];
|
||
wmGD.xa_DT_WORKSPACE_PRESENCE = atoms[XA_DT_WORKSPACE_PRESENCE];
|
||
wmGD.xa_DT_WORKSPACE_INFO = atoms[XA_DT_WORKSPACE_INFO];
|
||
wmGD.xa_ALL_WORKSPACES = atoms[XA_WmNall];
|
||
wmGD.xa_DT_EMBEDDED_CLIENTS = atoms[XA_DT_WORKSPACE_EMBEDDED_CLIENTS];
|
||
wmGD.xa_DT_WM_REQUEST = atoms[XA_DT_WM_REQUEST];
|
||
wmGD.xa_DT_WORKSPACE_LIST = atoms[XA_DT_WORKSPACE_LIST];
|
||
wmGD.xa_DT_WORKSPACE_CURRENT = atoms[XA_DT_WORKSPACE_CURRENT];
|
||
}
|
||
|
||
|
||
/* Initialize properties used in session management. */
|
||
wmGD.xa_SM_CLIENT_ID =
|
||
XmInternAtom (DISPLAY, _XA_DT_SM_CLIENT_ID, False);
|
||
wmGD.xa_WMSAVE_HINT =
|
||
XmInternAtom (DISPLAY, _XA_DT_WMSAVE_HINT, False);
|
||
|
||
/* Load client resource database. */
|
||
wmGD.clientResourceDB = LoadClientResourceDB();
|
||
|
||
/*
|
||
* Make the window manager workspace window.
|
||
* Setup the _MOTIF_WM_INFO property on the root window.
|
||
*/
|
||
|
||
SetupWmWorkspaceWindows ();
|
||
|
||
|
||
/* make the cursors that the window manager uses */
|
||
MakeWorkspaceCursors ();
|
||
|
||
|
||
/* Sync the table used by Mwm's modifier parser to actual modMasks used */
|
||
SyncModifierStrings();
|
||
|
||
/*
|
||
* Setup screen data and resources (after processing Wm resources.
|
||
*/
|
||
for (scr = 0; scr < wmGD.numScreens; scr++)
|
||
{
|
||
pSD = &(wmGD.Screens[scr]);
|
||
|
||
if (pSD->managed)
|
||
{
|
||
if (XDefaultScreen (wmGD.display) == pSD->screen)
|
||
{
|
||
wmGD.commandWindow = wmGD.Screens[scr].wmWorkspaceWin;
|
||
}
|
||
|
||
/*
|
||
* Initialize workspace colormap data.
|
||
*/
|
||
|
||
InitWorkspaceColormap (pSD);
|
||
|
||
/*
|
||
* Process the window manager resource description file (.mwmrc):
|
||
*/
|
||
|
||
ProcessWmFile (pSD, False /* not nested */);
|
||
|
||
/*
|
||
* Setup default resources for the system menu and key bindings:
|
||
*/
|
||
|
||
SetupDefaultResources (pSD);
|
||
|
||
|
||
/*
|
||
* Make global window manager facilities:
|
||
*/
|
||
|
||
if(pSD->iconDecoration & ICON_ACTIVE_LABEL_PART)
|
||
{
|
||
/* create active icon window */
|
||
CreateActiveIconTextWindow(pSD);
|
||
}
|
||
|
||
|
||
/*
|
||
* Make menus and other resources that are used by window manager
|
||
* functions that are activated by menus, buttons and keys.
|
||
*/
|
||
|
||
MakeWmFunctionResources (pSD);
|
||
}
|
||
|
||
}
|
||
/*
|
||
* Remove any temp config file we created if we needed to
|
||
* convert DT 2.0 syntax to DT 3.0
|
||
*/
|
||
DeleteTempConfigFileIfAny();
|
||
/*
|
||
* Point second display's resource data base
|
||
* to the first display's resource data base
|
||
* so dtwm "clients" change colors dynamically.
|
||
*
|
||
* NEW LOCATION
|
||
*/
|
||
wmGD.display1->db = wmGD.display->db;
|
||
|
||
/*
|
||
* Realize the top level widget, make the window override
|
||
* redirect so we don't manage it, and then move it out of the way
|
||
*/
|
||
|
||
XtRealizeWidget (wmGD.topLevelW);
|
||
XtRealizeWidget (wmGD.topLevelW1);
|
||
|
||
/*
|
||
* Initialize the message handling.
|
||
* (This must be done after the realize because a window
|
||
* is required for ICCCM-style messaging).
|
||
*/
|
||
dtInitializeMessaging (wmGD.topLevelW);
|
||
|
||
sAttributes.override_redirect = True;
|
||
XChangeWindowAttributes (DISPLAY, XtWindow (wmGD.topLevelW),
|
||
CWOverrideRedirect, &sAttributes);
|
||
|
||
|
||
/* setup window manager inter-client communications conventions handling */
|
||
SetupWmICCC ();
|
||
|
||
/* setup EWMH handling */
|
||
SetupWmEwmh ();
|
||
|
||
/*
|
||
* Use the WM_SAVE_YOURSELF protocol
|
||
* for notification of when to save ourself
|
||
*/
|
||
SetMwmSaveSessionInfo(wmGD.commandWindow);
|
||
/*
|
||
* Initialize window manager event handling:
|
||
*/
|
||
|
||
InitEventHandling ();
|
||
|
||
|
||
|
||
/*
|
||
* Initialize frame component graphics
|
||
*/
|
||
{
|
||
for (scr = 0; scr < wmGD.numScreens; scr++)
|
||
{
|
||
pSD = &(wmGD.Screens[scr]);
|
||
|
||
if (pSD->managed)
|
||
{
|
||
InitClientDecoration (pSD);
|
||
|
||
/*
|
||
* Make an icon box if specificed:
|
||
*/
|
||
if (pSD->useIconBox)
|
||
{
|
||
InitIconBox (pSD);
|
||
}
|
||
|
||
/*
|
||
* Adopt client windows that exist before wm startup:
|
||
*/
|
||
|
||
AdoptInitialClients (pSD);
|
||
|
||
/*
|
||
* Setup initial keyboard focus and colormap focus:
|
||
*/
|
||
|
||
InitColormapFocus (pSD);
|
||
|
||
}
|
||
}
|
||
|
||
for (scr = 0; scr < wmGD.numScreens; scr++)
|
||
{
|
||
int iws;
|
||
pSD = &(wmGD.Screens[scr]);
|
||
|
||
if (pSD->managed)
|
||
{
|
||
ACTIVE_PSD = &wmGD.Screens[scr];
|
||
MapIconBoxes (pSD->pActiveWS);
|
||
|
||
ChangeBackdrop (pSD->pActiveWS);
|
||
SetCurrentWorkspaceProperty (pSD);
|
||
SetWorkspaceListProperty (pSD);
|
||
|
||
for (iws=0; iws < pSD->numWorkspaces; iws++)
|
||
{
|
||
SetWorkspaceInfoProperty (&(pSD->pWS[iws]));
|
||
}
|
||
|
||
|
||
XFlush (DISPLAY);
|
||
|
||
|
||
|
||
/* MapWorkspaceBox (); */
|
||
|
||
/*
|
||
* Allocate front panel widgets
|
||
*/
|
||
if (wmGD.useFrontPanel && (pSD == wmGD.dtSD))
|
||
{
|
||
Pixmap iconBitmap;
|
||
Arg al[5];
|
||
int ac;
|
||
WmPanelistObject pPanelist;
|
||
|
||
wmGD.dtSD->wPanelist =
|
||
WmPanelistAllocate(pSD->screenTopLevelW1,
|
||
(XtPointer) &wmGD, (XtPointer) pSD);
|
||
|
||
pPanelist = (WmPanelistObject) pSD->wPanelist;
|
||
|
||
if (pPanelist != NULL && O_Shell(pPanelist))
|
||
{
|
||
/*
|
||
* Make a default front panel icon image.
|
||
*/
|
||
iconBitmap = XCreateBitmapFromData (DISPLAY,
|
||
pSD->rootWindow,
|
||
(char *) fntpl_i_bm_bits,
|
||
fntpl_i_bm_width,
|
||
fntpl_i_bm_height);
|
||
|
||
ac = 0;
|
||
XtSetArg (al[ac], XmNiconPixmap, iconBitmap); ac++;
|
||
XtSetValues (O_Shell(pPanelist), al, ac);
|
||
|
||
}
|
||
}
|
||
|
||
if (wmGD.useFrontPanel && pSD->wPanelist &&
|
||
(pSD == wmGD.dtSD))
|
||
{
|
||
/*
|
||
* Make the front panel visible
|
||
*/
|
||
WmPanelistShow (pSD->wPanelist);
|
||
|
||
/*
|
||
* Find special clients associated with the
|
||
* front panel. This needs to be done after
|
||
* WmPanelistShow where the data is set up.
|
||
*/
|
||
ScanForPushRecallClients (pSD);
|
||
ScanForEmbeddedClients (pSD);
|
||
}
|
||
|
||
RestoreHelpDialogs(pSD);
|
||
}
|
||
}
|
||
firstTime = 0;
|
||
}
|
||
|
||
InitKeyboardFocus ();
|
||
|
||
ShowWaitState (FALSE);
|
||
|
||
/*
|
||
* Tell the rest of DT that we're up
|
||
*/
|
||
dtReadyNotification();
|
||
|
||
#ifdef DEBUG_RESOURCE_DATABASE
|
||
XrmPutFileDatabase(wmGD.display->db, "/tmp/dtwm.resDB");
|
||
#endif /* DEBUG_RESOURCE_DATABASE */
|
||
|
||
} /* END OF FUNCTION InitWmGlobal */
|
||
|
||
|
||
|
||
/******************************<->*************************************
|
||
*
|
||
* InitWmScreen
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* This function initializes a screen data block.
|
||
*
|
||
* Inputs:
|
||
* -------
|
||
* pSD = pointer to preallocated screen data block
|
||
* sNum = screen number for this screen
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
*************************************<->***********************************/
|
||
|
||
void
|
||
InitWmScreen (WmScreenData *pSD, int sNum)
|
||
{
|
||
Arg args[12];
|
||
int argnum;
|
||
|
||
int wsnum;
|
||
WmWorkspaceData *pwsI;
|
||
int buf_size;
|
||
int iwsx;
|
||
|
||
char *pDisplayName;
|
||
#define LENCBUFFER 256
|
||
char buffer[LENCBUFFER]; /* screen name & display name! */
|
||
char displayName[LENCBUFFER];
|
||
char *token1, *token2;
|
||
|
||
|
||
/*
|
||
* Set screen data values
|
||
*/
|
||
|
||
pSD->rootWindow = RootWindow (DISPLAY, sNum);
|
||
pSD->clientCounter = 0;
|
||
pSD->defaultSystemMenuUseBuiltin = TRUE;
|
||
pSD->displayString = NULL;
|
||
pSD->acceleratorMenuCount = 0;
|
||
pSD->activeIconTextWin = (Window)NULL;
|
||
pSD->focusPriority = 0;
|
||
pSD->inputScreenWindow = (Window)NULL;
|
||
pSD->colormapFocus = NULL;
|
||
pSD->keySpecs = NULL;
|
||
pSD->screen = sNum;
|
||
pSD->confirmboxW[DEFAULT_BEHAVIOR_ACTION] = NULL;
|
||
pSD->confirmboxW[CUSTOM_BEHAVIOR_ACTION] = NULL;
|
||
pSD->confirmboxW[RESTART_ACTION] = NULL;
|
||
pSD->confirmboxW[QUIT_MWM_ACTION] = NULL;
|
||
pSD->feedbackWin = (Window)NULL;
|
||
pSD->fbStyle = FB_OFF;
|
||
pSD->fbWinWidth = 0;
|
||
pSD->fbWinHeight = 0;
|
||
pSD->fbLocation[0] = '\0';
|
||
pSD->fbSize[0] = '\0';
|
||
pSD->fbLocX = 0;
|
||
pSD->fbLocY = 0;
|
||
pSD->fbSizeX = 0;
|
||
pSD->fbSizeY = 0;
|
||
pSD->fbLastX = -1;
|
||
pSD->fbLastY = -1;
|
||
pSD->fbLastWidth = -1;
|
||
pSD->fbLastHeight = -1;
|
||
pSD->fbTop = NULL;
|
||
pSD->fbBottom = NULL;
|
||
pSD->actionNbr = -1;
|
||
pSD->clientList = NULL;
|
||
pSD->lastClient = NULL;
|
||
pSD->lastInstalledColormap = (Colormap)NULL;
|
||
pSD->shrinkWrapGC = NULL;
|
||
pSD->bitmapCache = NULL;
|
||
pSD->bitmapCacheSize = 0;
|
||
pSD->bitmapCacheCount = 0;
|
||
pSD->dataType = SCREEN_DATA_TYPE;
|
||
pSD->managed = False;
|
||
|
||
pSD->initialWorkspace=NULL;
|
||
pSD->presence.shellW = NULL;
|
||
pSD->presence.onScreen = False;
|
||
pSD->presence.userDismissed = True;
|
||
pSD->instantTitleData.widgetsInitialized = False;
|
||
pSD->workspaceList = NULL;
|
||
pSD->numWorkspaces = 0;
|
||
pSD->numWsDataAllocated = 0;
|
||
pSD->lastBackdropWin = None;
|
||
pSD->pDtSessionItems = NULL;
|
||
pSD->totalSessionItems = 0;
|
||
pSD->remainingSessionItems = 0;
|
||
|
||
pSD->cachedHelp = NULL;
|
||
pSD->dtHelp.shell = (Widget)NULL;
|
||
pSD->dtHelp.dialog = (Widget)NULL;
|
||
pSD->dtHelp.errorDialog = (Widget)NULL;
|
||
pSD->dtHelp.xPos = 0;
|
||
pSD->dtHelp.yPos = 0;
|
||
pSD->dtHelp.restored = False;
|
||
pSD->dtHelp.onScreen = False;
|
||
pSD->dtHelp.userDismissed = False;
|
||
pSD->dtHelp.pCDforClient= NULL;
|
||
pSD->helpResources=NULL;
|
||
pSD->bMarqueeSelectionInitialized = False;
|
||
pSD->woN = (Window) 0L;
|
||
pSD->woS = (Window) 0L;
|
||
pSD->woE = (Window) 0L;
|
||
pSD->woW = (Window) 0L;
|
||
pSD->wPanelist = NULL;
|
||
pSD->pECD = NULL;
|
||
pSD->numPushRecallClients = 0;
|
||
pSD->numEmbeddedClients = 0;
|
||
pSD->pPRCD = NULL;
|
||
pSD->iconBoxControl = False;
|
||
pSD->displayResolutionType = _DtGetDisplayResolution(DISPLAY, sNum);
|
||
|
||
pSD->topClient = NULL;
|
||
pSD->bottomClient = NULL;
|
||
|
||
/*
|
||
* We've got display resolution type--now, let's get color
|
||
* characteristics.
|
||
*/
|
||
|
||
ProcessWmColors (pSD);
|
||
|
||
if (!(strcmp ((char *)wmGD.screenNames[sNum], UNSPECIFIED_SCREEN_NAME)))
|
||
{
|
||
sprintf (buffer, "%d", sNum);
|
||
|
||
buf_size = strlen(buffer) + 1;
|
||
|
||
if ((wmGD.screenNames[sNum] =
|
||
(unsigned char *)XtRealloc ((char *)wmGD.screenNames[sNum], buf_size)) == NULL)
|
||
{
|
||
Warning (((char *)GETMESSAGE(40, 7, "Cannot create enough memory for the screen names")));
|
||
ExitWM (WM_ERROR_EXIT_VALUE);
|
||
}
|
||
else
|
||
{
|
||
strcpy((char *)wmGD.screenNames[sNum], buffer);
|
||
}
|
||
} /* if wmGD.screenNames[sNum] == UNSPECIFIED_SCREEN_NAME */
|
||
|
||
/*
|
||
* Save screen context
|
||
*/
|
||
XSaveContext (DISPLAY, pSD->rootWindow, wmGD.screenContextType,
|
||
(caddr_t)pSD);
|
||
/*
|
||
* Create shell widget for screen resource hierarchy
|
||
*/
|
||
|
||
argnum = 0;
|
||
XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
|
||
XtSetArg (args[argnum], XtNx, 10000); argnum++;
|
||
XtSetArg (args[argnum], XtNy, 10000); argnum++;
|
||
XtSetArg (args[argnum], XtNwidth, 10); argnum++;
|
||
XtSetArg (args[argnum], XtNheight, 10); argnum++;
|
||
XtSetArg (args[argnum], XtNoverrideRedirect, True); argnum++;
|
||
|
||
XtSetArg (args[argnum], XtNdepth,
|
||
DefaultDepth(DISPLAY, sNum)); argnum++;
|
||
XtSetArg (args[argnum], XtNscreen,
|
||
ScreenOfDisplay(DISPLAY, sNum)); argnum++;
|
||
XtSetArg (args[argnum], XtNcolormap,
|
||
DefaultColormap(DISPLAY, sNum)); argnum++;
|
||
|
||
pSD->screenTopLevelW = XtCreatePopupShell ((String) wmGD.screenNames[sNum],
|
||
vendorShellWidgetClass,
|
||
wmGD.topLevelW,
|
||
args,
|
||
argnum);
|
||
|
||
argnum = 0;
|
||
XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
|
||
XtSetArg (args[argnum], XtNx, 10000); argnum++;
|
||
XtSetArg (args[argnum], XtNy, 10000); argnum++;
|
||
XtSetArg (args[argnum], XtNwidth, 10); argnum++;
|
||
XtSetArg (args[argnum], XtNheight, 10); argnum++;
|
||
XtSetArg (args[argnum], XtNoverrideRedirect, True); argnum++;
|
||
XtSetArg (args[argnum], XtNmappedWhenManaged, False); argnum++;
|
||
|
||
XtSetArg (args[argnum], XtNdepth,
|
||
DefaultDepth(DISPLAY1, sNum)); argnum++;
|
||
XtSetArg (args[argnum], XtNscreen,
|
||
ScreenOfDisplay(DISPLAY1, sNum)); argnum++;
|
||
XtSetArg (args[argnum], XtNcolormap,
|
||
DefaultColormap(DISPLAY1, sNum)); argnum++;
|
||
|
||
pSD->screenTopLevelW1 = XtCreatePopupShell ((String) wmGD.screenNames[sNum],
|
||
vendorShellWidgetClass,
|
||
wmGD.topLevelW1,
|
||
args,
|
||
argnum);
|
||
XtRealizeWidget (pSD->screenTopLevelW1);
|
||
|
||
/*
|
||
* Fetch screen based resources
|
||
*/
|
||
ProcessScreenResources (pSD, wmGD.screenNames[sNum]);
|
||
|
||
/*
|
||
* Initialize other screen resources and parameters
|
||
*/
|
||
MakeXorGC (pSD);
|
||
InitIconSize(pSD);
|
||
|
||
/*
|
||
* Complete initialization of workspace structures
|
||
*/
|
||
for (wsnum = 0,
|
||
pwsI = pSD->pWS; wsnum < pSD->numWorkspaces;
|
||
wsnum++, pwsI++)
|
||
{
|
||
/*
|
||
* Set up workspace for this screen
|
||
*/
|
||
InitWmWorkspace (pwsI, pSD);
|
||
|
||
}
|
||
|
||
if (pSD->initialWorkspace)
|
||
{
|
||
/*
|
||
* restore to the last initialWorkspace saved from
|
||
* Quit, Restart, OR save session
|
||
*/
|
||
|
||
/*
|
||
* Compare initialWorkspace against workspace name,
|
||
* NOT workspace title.
|
||
*/
|
||
for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
|
||
{
|
||
if (!strcmp(pSD->pWS[iwsx].name, pSD->initialWorkspace))
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
/* check bounds */
|
||
if (iwsx >= pSD->numWorkspaces)
|
||
{
|
||
/* make first workspace in list the active one to start with */
|
||
pSD->pActiveWS = pSD->pWS;
|
||
}
|
||
else
|
||
{
|
||
pSD->pActiveWS = &pSD->pWS[iwsx];
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/* make first workspace in list the active one to start with */
|
||
pSD->pActiveWS = pSD->pWS;
|
||
}
|
||
|
||
|
||
pDisplayName = DisplayString (DISPLAY);
|
||
|
||
/*
|
||
* Construct displayString for this string.
|
||
*
|
||
* NOTE: The variable buffer is reused here. It was
|
||
* used earlier to generate a screen name.
|
||
*/
|
||
|
||
strcpy(displayName, pDisplayName);
|
||
|
||
token1 = (char*)strtok(displayName, ":"); /* parse of hostname */
|
||
|
||
if((token2 = (char*)strtok(NULL, ".")) || /* parse off dpy & scr # */
|
||
(token2 = (char*)strtok(NULL, "")) ||
|
||
(displayName[0] == ':'))
|
||
{
|
||
if (displayName[0] == ':') /* local dpy (special case) */
|
||
{
|
||
if ((token2 = (char*)strtok(token1, ".")) != NULL) /* parse dpy# */
|
||
sprintf(buffer, "DISPLAY=:%s.%d",
|
||
token2, sNum);
|
||
} else { /* otherwise process normally */
|
||
sprintf(buffer, "DISPLAY=%s:%s.%d",
|
||
token1, token2, sNum);
|
||
}
|
||
|
||
/*
|
||
* Allocate space for the display string
|
||
*/
|
||
|
||
if ((pSD->displayString =
|
||
(String)XtMalloc ((unsigned int) (strlen(buffer) + 1))) == NULL)
|
||
{
|
||
Warning (((char *)GETMESSAGE(40, 9,
|
||
"Insufficient memory for displayString")));
|
||
}
|
||
else
|
||
{
|
||
strcpy(pSD->displayString, buffer);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
} /* END OF FUNCTION InitWmScreen */
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* InitWmWorkspace
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* This function initializes a workspace data block.
|
||
*
|
||
* Inputs:
|
||
* -------
|
||
* pWS = pointer to preallocated workspace data block
|
||
* pSD = ptr to parent screen data block
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
*************************************<->***********************************/
|
||
|
||
void InitWmWorkspace (WmWorkspaceData *pWS, WmScreenData *pSD)
|
||
{
|
||
Arg args[10];
|
||
int argnum;
|
||
|
||
|
||
pWS->pSD = pSD;
|
||
pWS->pIconBox = NULL;
|
||
pWS->dataType = WORKSPACE_DATA_TYPE;
|
||
pWS->backdrop.window = 0;
|
||
pWS->backdrop.nameAtom = 0;
|
||
pWS->backdrop.image = NULL;
|
||
pWS->numClients = 0;
|
||
pWS->sizeClientList = 0;
|
||
pWS->ppClients = 0;
|
||
pWS->buttonW = NULL;
|
||
|
||
/*
|
||
* Create widget for workspace resource hierarchy
|
||
*/
|
||
argnum = 0;
|
||
XtSetArg (args[argnum], XtNdepth,
|
||
DefaultDepth(DISPLAY, pSD->screen)); argnum++;
|
||
XtSetArg (args[argnum], XtNscreen,
|
||
ScreenOfDisplay(DISPLAY, pSD->screen)); argnum++;
|
||
XtSetArg (args[argnum], XtNcolormap,
|
||
DefaultColormap(DISPLAY, pSD->screen)); argnum++;
|
||
XtSetArg (args[argnum], XtNwidth, 5); argnum++;
|
||
XtSetArg (args[argnum], XtNheight, 5); argnum++;
|
||
|
||
pWS->workspaceTopLevelW = XtCreateWidget ( pWS->name,
|
||
xmPrimitiveWidgetClass,
|
||
pSD->screenTopLevelW,
|
||
args,
|
||
argnum);
|
||
|
||
/* internalize the workspace name */
|
||
pWS->id = XInternAtom (DISPLAY, pWS->name, False);
|
||
|
||
/*
|
||
* Process workspace based resources
|
||
*/
|
||
ProcessWorkspaceResources (pWS);
|
||
|
||
/* setup icon placement */
|
||
if (wmGD.iconAutoPlace)
|
||
{
|
||
InitIconPlacement (pWS);
|
||
}
|
||
|
||
} /* END OF FUNCTION InitWmWorkspace */
|
||
|
||
|
||
/******************************<->*************************************
|
||
*
|
||
* InsureDefaultBackdropDir(char **ppchBackdropDirs)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* This function checks and edits a directory path to insure
|
||
* that the system backdrop directroy (/usr/dt/backdrops) is in the
|
||
* path. If not it adds it to the end. Further, it always adds the user's
|
||
* backdrop directory ($HOME/.dt/backdrops) to the beginning of the path
|
||
* and the system admin directory (/etc/dt/backdrops) before the system
|
||
* directory.
|
||
*
|
||
* Inputs:
|
||
* -------
|
||
* ppchBackdropDirs - Pointer to a pointer to a directory path
|
||
* (must be allocated memory)
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* *ppchBackdropDirs - Directory path may be modified, path
|
||
* pointer may be realloc'ed.
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* Assumes that the default directory does not start with a
|
||
* multi-byte character.
|
||
*
|
||
******************************<->***********************************/
|
||
static void
|
||
InsureDefaultBackdropDir(char **ppchBackdropDirs)
|
||
{
|
||
int len;
|
||
Boolean bFound = False;
|
||
char *pch, *pchEnd, *pch2, *tmpptr;
|
||
char *pchD = DEFAULT_BACKDROP_DIR;
|
||
unsigned int chlen;
|
||
char * homeDir;
|
||
|
||
/*
|
||
* Set up initial stuff
|
||
*/
|
||
pch = *ppchBackdropDirs;
|
||
len = strlen (pchD);
|
||
pchEnd = pch + strlen(pch);
|
||
|
||
while (!bFound && (pch != NULL) && (*pch != 0))
|
||
{
|
||
if (strncmp (pch, pchD, len) == 0)
|
||
{
|
||
/* found partial match, confirm complete match ...
|
||
* complete match if char off end of partial match
|
||
* is a NULL or a colon
|
||
*/
|
||
pch2 = pch + len;
|
||
if ((pch2 <= pchEnd) &&
|
||
((*pch2 == 0) ||
|
||
(((mblen (pch2, MB_CUR_MAX) == 1) &&
|
||
(*pch2 == ':')))))
|
||
{
|
||
bFound = True;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/* find next path component */
|
||
pch = strchr (pch, (int) ':');
|
||
if ((pch != NULL) && (*pch != 0))
|
||
{
|
||
/* skip path separator */
|
||
chlen = mblen (pch, MB_CUR_MAX);
|
||
pch += chlen;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
* Always add the user's home directory to the beginning of the string
|
||
*/
|
||
homeDir = (char *) XmeGetHomeDirName();
|
||
|
||
/*
|
||
* If found add the user's home directory ($HOME/.dt/backdrops) and the
|
||
* admin directory /etc/dt/backdrops to the beginning of the string
|
||
*/
|
||
|
||
if (bFound)
|
||
{
|
||
len = strlen (homeDir) + strlen("/.dt/backdrops") +
|
||
strlen (*ppchBackdropDirs) + strlen("/etc/dt/backdrops") + 3;
|
||
tmpptr = XtMalloc (len * sizeof (char *));
|
||
strcpy (tmpptr, homeDir);
|
||
strcat (tmpptr, "/.dt/backdrops");
|
||
strcat (tmpptr, ":");
|
||
strcat (tmpptr, "/etc/dt/backdrops");
|
||
strcat (tmpptr, ":");
|
||
strcat (tmpptr, *ppchBackdropDirs);
|
||
*ppchBackdropDirs = tmpptr;
|
||
}
|
||
else
|
||
/*
|
||
* If string not found, then add home directory to the beginning of
|
||
* string and the admin directory and system directory to the end.
|
||
*/
|
||
{
|
||
len = strlen (homeDir) + strlen("/.dt/backdrops") +
|
||
strlen (*ppchBackdropDirs) + strlen(pchD) +
|
||
strlen("/etc/dt/backdrops") + 4;
|
||
tmpptr = XtMalloc (len * sizeof (char *));
|
||
strcpy (tmpptr, homeDir);
|
||
strcat (tmpptr, "/.dt/backdrops");
|
||
strcat (tmpptr, ":");
|
||
strcat (tmpptr, *ppchBackdropDirs);
|
||
strcat (tmpptr, ":");
|
||
strcat (tmpptr, "/etc/dt/backdrops");
|
||
strcat (tmpptr, ":");
|
||
strcat (tmpptr, pchD);
|
||
*ppchBackdropDirs = tmpptr;
|
||
}
|
||
|
||
} /* END OF FUNCTION InsureDefaultBackdropDirs */
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* ProcessMotifWmInfo (rootWindowOfScreen)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* This function is used retrieve and save the information in the
|
||
* _MOTIF_WM_INFO property. If the property does not exist then
|
||
* the start / restart state is set to initial startup with the
|
||
* user specified (not standard) configuration.
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* wmGD.useStandardBehavior = True if set indicated in property
|
||
*
|
||
* wmGD.wmRestarted = True if the window manager was restarted
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
void ProcessMotifWmInfo (Window rootWindowOfScreen)
|
||
{
|
||
MwmInfo *pMwmInfo;
|
||
|
||
wmGD.xa_MWM_INFO = XInternAtom (DISPLAY, _XA_MWM_INFO, False);
|
||
if ((pMwmInfo = (MotifWmInfo *)GetMwmInfo (rootWindowOfScreen)) != NULL)
|
||
{
|
||
wmGD.useStandardBehavior =
|
||
(pMwmInfo->flags & MWM_INFO_STARTUP_STANDARD) ? True : False;
|
||
wmGD.wmRestarted = True;
|
||
XFree ((char *)pMwmInfo);
|
||
}
|
||
else
|
||
{
|
||
wmGD.useStandardBehavior = False;
|
||
wmGD.wmRestarted = False;
|
||
}
|
||
|
||
} /* END OF FUNCTION ProcessMotifWmInfo */
|
||
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* SetupWmWorkspaceWindows ()
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* This function is used to setup a window that can be used in doing window
|
||
* management functions. This window is not visible on the screen.
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* pSD->wmWorkspaceWin = window that is used to hold wm properties
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
void SetupWmWorkspaceWindows (void)
|
||
{
|
||
int scr;
|
||
WmScreenData *pSD;
|
||
XSetWindowAttributes sAttributes;
|
||
|
||
for (scr = 0; scr < wmGD.numScreens; scr++)
|
||
{
|
||
pSD = &(wmGD.Screens[scr]);
|
||
if (pSD->managed)
|
||
{
|
||
sAttributes.override_redirect = True;
|
||
sAttributes.event_mask = FocusChangeMask | PropertyChangeMask;
|
||
pSD->wmWorkspaceWin = XCreateWindow (DISPLAY, pSD->rootWindow,
|
||
-100, -100, 10, 10, 0, 0,
|
||
InputOnly, CopyFromParent,
|
||
(CWOverrideRedirect |CWEventMask),
|
||
&sAttributes);
|
||
|
||
XMapWindow (DISPLAY, pSD->wmWorkspaceWin);
|
||
|
||
SetMwmInfo (pSD->rootWindow,
|
||
(long) ((wmGD.useStandardBehavior) ?
|
||
MWM_INFO_STARTUP_STANDARD : MWM_INFO_STARTUP_CUSTOM),
|
||
pSD->wmWorkspaceWin);
|
||
XSaveContext (DISPLAY, pSD->wmWorkspaceWin,
|
||
wmGD.mwmWindowContextType, (caddr_t)pSD);
|
||
}
|
||
}
|
||
|
||
} /* END OF FUNCTION SetupWmWorkspaceWindow */
|
||
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* MakeWorkspaceCursors ()
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* This function makes the cursors that the window manager uses.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* XXinput = ...
|
||
*
|
||
* XXinput = ...
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* wmGD = (stretchCursors ...)
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
void MakeWorkspaceCursors (void)
|
||
{
|
||
wmGD.workspaceCursor = XCreateFontCursor (DISPLAY, XC_left_ptr);
|
||
|
||
wmGD.stretchCursors[STRETCH_NORTH_WEST] =
|
||
XCreateFontCursor (DISPLAY, XC_top_left_corner);
|
||
wmGD.stretchCursors[STRETCH_NORTH] =
|
||
XCreateFontCursor (DISPLAY, XC_top_side);
|
||
wmGD.stretchCursors[STRETCH_NORTH_EAST] =
|
||
XCreateFontCursor (DISPLAY, XC_top_right_corner);
|
||
wmGD.stretchCursors[STRETCH_EAST] =
|
||
XCreateFontCursor (DISPLAY, XC_right_side);
|
||
wmGD.stretchCursors[STRETCH_SOUTH_EAST] =
|
||
XCreateFontCursor (DISPLAY, XC_bottom_right_corner);
|
||
wmGD.stretchCursors[STRETCH_SOUTH] =
|
||
XCreateFontCursor (DISPLAY, XC_bottom_side);
|
||
wmGD.stretchCursors[STRETCH_SOUTH_WEST] =
|
||
XCreateFontCursor (DISPLAY, XC_bottom_left_corner);
|
||
wmGD.stretchCursors[STRETCH_WEST] =
|
||
XCreateFontCursor (DISPLAY, XC_left_side);
|
||
|
||
wmGD.configCursor = XCreateFontCursor (DISPLAY, XC_fleur);
|
||
|
||
wmGD.movePlacementCursor = XCreateFontCursor (DISPLAY, XC_ul_angle);
|
||
wmGD.sizePlacementCursor = XCreateFontCursor (DISPLAY, XC_lr_angle);
|
||
|
||
|
||
} /* END OF FUNCTION MakeWorkspaceCursors */
|
||
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* MakeWmFunctionResources (pSD)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* This function makes menus and other resources that are used by window
|
||
* manager functions.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* wmGD = (menuSpecs, keySpecs, buttonSpecs)
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* wmGD (menuSpecs) = new menu panes, protocol atoms
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
void MakeWmFunctionResources (WmScreenData *pSD)
|
||
{
|
||
ButtonSpec *buttonSpec;
|
||
KeySpec *keySpec;
|
||
MenuSpec *menuSpec;
|
||
Context menuContext;
|
||
|
||
|
||
/*
|
||
* Scan through the menu specifications and make wm protocol atoms.
|
||
*/
|
||
|
||
|
||
/*
|
||
* Scan through the button binding specifications making menus if the
|
||
* f.menu function is invoked.
|
||
*/
|
||
|
||
buttonSpec = pSD->buttonSpecs;
|
||
while (buttonSpec)
|
||
{
|
||
if (buttonSpec->wmFunction == F_Menu)
|
||
{
|
||
if (buttonSpec->context & F_CONTEXT_WINDOW)
|
||
{
|
||
menuContext = F_CONTEXT_WINDOW;
|
||
}
|
||
else if (buttonSpec->context & F_CONTEXT_ICON)
|
||
{
|
||
menuContext = F_CONTEXT_ICON;
|
||
}
|
||
else
|
||
{
|
||
menuContext = F_CONTEXT_ROOT;
|
||
}
|
||
|
||
menuSpec = MAKE_MENU (pSD, NULL, buttonSpec->wmFuncArgs,
|
||
menuContext,
|
||
buttonSpec->context,
|
||
(MenuItem *) NULL, FALSE);
|
||
|
||
if (menuSpec)
|
||
/*
|
||
* If successful, save in pSD->acceleratorMenuSpecs
|
||
* Note: these accelerators have nonzero contexts.
|
||
*/
|
||
{
|
||
SaveMenuAccelerators (pSD, menuSpec);
|
||
}
|
||
else
|
||
{
|
||
buttonSpec->wmFunction = F_Nop;
|
||
}
|
||
}
|
||
buttonSpec = buttonSpec->nextButtonSpec;
|
||
}
|
||
|
||
|
||
/*
|
||
* Scan through the key binding specifications making menus if the
|
||
* f.menu function is invoked.
|
||
*/
|
||
|
||
keySpec = pSD->keySpecs;
|
||
while (keySpec)
|
||
{
|
||
if (keySpec->wmFunction == F_Menu)
|
||
{
|
||
if (keySpec->context & F_CONTEXT_WINDOW)
|
||
{
|
||
menuContext = F_CONTEXT_WINDOW;
|
||
}
|
||
else if (keySpec->context & F_CONTEXT_ICON)
|
||
{
|
||
menuContext = F_CONTEXT_ICON;
|
||
}
|
||
else
|
||
{
|
||
menuContext = F_CONTEXT_ROOT;
|
||
}
|
||
|
||
menuSpec = MAKE_MENU (pSD, NULL, keySpec->wmFuncArgs, menuContext,
|
||
keySpec->context,
|
||
(MenuItem *) NULL, FALSE);
|
||
|
||
if (menuSpec)
|
||
/*
|
||
* If successful, save in pSD->acceleratorMenuSpecs
|
||
* Note: these accelerators have nonzero contexts.
|
||
*/
|
||
{
|
||
SaveMenuAccelerators (pSD, menuSpec);
|
||
}
|
||
else
|
||
{
|
||
keySpec->wmFunction = F_Nop;
|
||
}
|
||
}
|
||
keySpec = keySpec->nextKeySpec;
|
||
}
|
||
|
||
|
||
} /* END OF FUNCTION MakeWmFunctionResources */
|
||
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* MakeXorGC (pSD)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Make an XOR graphic context for resizing and moving
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pSD = pointer to screen data
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Modifies global data
|
||
*
|
||
* Comments:
|
||
* --------
|
||
*
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
void MakeXorGC (WmScreenData *pSD)
|
||
{
|
||
XGCValues gcv;
|
||
XtGCMask mask;
|
||
|
||
mask = GCFunction | GCLineWidth | GCSubwindowMode | GCCapStyle;
|
||
gcv.function = GXinvert;
|
||
gcv.line_width = 0;
|
||
gcv.cap_style = CapNotLast;
|
||
gcv.subwindow_mode = IncludeInferiors;
|
||
|
||
/* Fix so that the rubberbanding for resize and move will
|
||
* have more contrasting colors.
|
||
*/
|
||
|
||
gcv.plane_mask = BlackPixelOfScreen( DefaultScreenOfDisplay( DISPLAY )) ^
|
||
WhitePixelOfScreen( DefaultScreenOfDisplay( DISPLAY ));
|
||
mask = mask | GCPlaneMask;
|
||
|
||
pSD->xorGC = XCreateGC (DISPLAY, pSD->rootWindow, mask, &gcv);
|
||
|
||
|
||
} /* END OF FUNCTION MakeXorGC */
|
||
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* CopyArgv (argc, argv)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* This function makes a copy of the window manager's argv for use by
|
||
* the f.restart function. A copy must be kept because XtInitialize
|
||
* changes argv.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* argc = the number of strings in argv
|
||
*
|
||
* argv = window manager parameters
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Return = a copy of argv
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
|
||
void CopyArgv (int argc, char *argv [])
|
||
{
|
||
int i;
|
||
|
||
|
||
if ((wmGD.argv = (char **)XtMalloc ((argc + 1) * sizeof (char *))) == NULL)
|
||
{
|
||
Warning (((char *)GETMESSAGE(40, 10, "Insufficient memory for window manager data")));
|
||
wmGD.argv = argv;
|
||
dpy2Argv = argv;
|
||
}
|
||
else
|
||
{
|
||
for (i = 0; i < argc; i++)
|
||
{
|
||
wmGD.argv[i] = argv[i];
|
||
}
|
||
wmGD.argv[i] = NULL;
|
||
if ((dpy2Argv = (char **)XtMalloc((argc + 1) * sizeof(char *))) == NULL)
|
||
{
|
||
Warning (((char *)GETMESSAGE(40, 11, "Insufficient memory for window manager data")));
|
||
dpy2Argv = argv;
|
||
}
|
||
else
|
||
{
|
||
for (i = 0; i < argc; i++)
|
||
{
|
||
dpy2Argv[i] = argv[i];
|
||
}
|
||
dpy2Argc = argc;
|
||
dpy2Argv[i] = NULL;
|
||
}
|
||
}
|
||
|
||
} /* END OF FUNCTION CopyArgv */
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* InitScreenNames ()
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Initializes the name space for screen names
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Modifies global data
|
||
* + screenNames
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* Initializes screenNames to contain a numeric name for each screen
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
void InitScreenNames (void)
|
||
{
|
||
int num, numScreens;
|
||
|
||
numScreens = ScreenCount (wmGD.display);
|
||
|
||
if (!(wmGD.screenNames =
|
||
(unsigned char **) XtMalloc (numScreens * sizeof(char *))))
|
||
{
|
||
ShowWaitState (FALSE);
|
||
Warning (((char *)GETMESSAGE(40, 12, "Insufficient memory for screen names")));
|
||
ExitWM (WM_ERROR_EXIT_VALUE);
|
||
}
|
||
|
||
for (num=0; num<numScreens; num++)
|
||
{
|
||
if (!(wmGD.screenNames[num] =
|
||
(unsigned char *) XtMalloc (4*sizeof(char))))
|
||
{
|
||
ShowWaitState (FALSE);
|
||
Warning (((char *)GETMESSAGE(40, 13, "Insufficient memory for screen names")));
|
||
ExitWM (WM_ERROR_EXIT_VALUE);
|
||
}
|
||
/* default name is left justified, 3-chars max, zero terminated */
|
||
sprintf((char *)wmGD.screenNames[num], UNSPECIFIED_SCREEN_NAME);
|
||
}
|
||
}
|
||
#ifndef NO_MESSAGE_CATALOG
|
||
|
||
|
||
void InitNlsStrings (void)
|
||
{
|
||
char * tmpString;
|
||
|
||
/*
|
||
* Initialize messages
|
||
*/
|
||
wmGD.okLabel=XmStringCreateLocalized((String)_DtOkString);
|
||
wmGD.cancelLabel=XmStringCreateLocalized((String)_DtCancelString);
|
||
wmGD.helpLabel=XmStringCreateLocalized((String)_DtHelpString);
|
||
|
||
/*
|
||
* catgets returns a pointer to an area that is over written
|
||
* on each call to catgets.
|
||
*/
|
||
|
||
tmpString = ((char *)GETMESSAGE(40, 14, "Icons"));
|
||
if ((wmNLS.default_icon_box_title =
|
||
(char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
|
||
{
|
||
Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
|
||
wmNLS.default_icon_box_title = "Icons";
|
||
}
|
||
else
|
||
{
|
||
strcpy(wmNLS.default_icon_box_title, tmpString);
|
||
}
|
||
|
||
tmpString = ((char *)GETMESSAGE(40, 20, "%s: %s on line %d of configuration file %s\n"));
|
||
if ((pWarningStringFile =
|
||
(char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
|
||
{
|
||
Warning (((char *)GETMESSAGE(40, 17, "Insufficient memory for local message string")));
|
||
pWarningStringFile = "%s: %s on line %d of configuration file %s\n";
|
||
}
|
||
else
|
||
{
|
||
strcpy(pWarningStringFile, tmpString);
|
||
}
|
||
|
||
tmpString = ((char *)GETMESSAGE(40, 21, "%s: %s on line %d of specification string\n"));
|
||
if ((pWarningStringLine =
|
||
(char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
|
||
{
|
||
Warning (((char *)GETMESSAGE(40, 19, "Insufficient memory for local message string")));
|
||
pWarningStringLine = "%s: %s on line %d of specification string\n";
|
||
}
|
||
else
|
||
{
|
||
strcpy(pWarningStringLine, tmpString);
|
||
}
|
||
|
||
|
||
tmpString = ((char *)GETMESSAGE(40, 22, "About Workspace Manager"));
|
||
if ((wmNLS.defaultVersionTitle =
|
||
(char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
|
||
{
|
||
Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
|
||
wmNLS.defaultVersionTitle = "About Workspace Manager";
|
||
}
|
||
else
|
||
{
|
||
strcpy(wmNLS.defaultVersionTitle, tmpString);
|
||
}
|
||
|
||
tmpString = ((char *)GETMESSAGE(40, 23, "Workspace Manager - Help"));
|
||
if ((wmNLS.defaultDtwmHelpTitle =
|
||
(char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
|
||
{
|
||
Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
|
||
wmNLS.defaultDtwmHelpTitle = "Workspace Manager - Help";
|
||
}
|
||
else
|
||
{
|
||
strcpy(wmNLS.defaultDtwmHelpTitle, tmpString);
|
||
}
|
||
|
||
tmpString = ((char *)GETMESSAGE(40, 24, "Workspace Manager - Help"));
|
||
if ((wmNLS.defaultHelpTitle =
|
||
(char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
|
||
{
|
||
Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
|
||
wmNLS.defaultHelpTitle = "Workspace Manager - Help";
|
||
}
|
||
else
|
||
{
|
||
strcpy(wmNLS.defaultHelpTitle, tmpString);
|
||
}
|
||
|
||
} /* InitNlsStrings */
|
||
#endif
|
||
|
||
|
||
|
||
/******************************<->*************************************
|
||
*
|
||
* InitWmDisplayEnv
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* This function saves the display string for putenv in F_Exec.
|
||
*
|
||
* Inputs:
|
||
* -------
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
*************************************<->***********************************/
|
||
|
||
void
|
||
InitWmDisplayEnv (void)
|
||
{
|
||
char *pDisplayName;
|
||
char displayName[256];
|
||
char buffer[10 + sizeof(displayName)];
|
||
|
||
pDisplayName = DisplayString (DISPLAY);
|
||
|
||
/*
|
||
* Construct displayString for this string.
|
||
*/
|
||
strcpy(displayName, pDisplayName);
|
||
sprintf(buffer, "DISPLAY=%s",displayName);
|
||
|
||
/*
|
||
* Allocate space for the display string
|
||
*/
|
||
if ((wmGD.displayString =
|
||
(String)XtMalloc ((unsigned int) (strlen(buffer) + 1))) == NULL)
|
||
{
|
||
wmGD.displayString = NULL;
|
||
Warning (((char *)GETMESSAGE(40, 9,
|
||
"Insufficient memory for displayString")));
|
||
}
|
||
else
|
||
{
|
||
strcpy(wmGD.displayString, buffer);
|
||
putenv(wmGD.displayString);
|
||
}
|
||
|
||
} /* END OF FUNCTION InitWmDisplayEnv */
|
||
|
||
#ifndef NO_HP_KEY_REMAP
|
||
static str_xref
|
||
GetReplacementList(
|
||
Display *dsp,
|
||
str_xref std_xref,
|
||
int count)
|
||
{
|
||
int min_kc ;
|
||
int max_kc ;
|
||
int ks_per_kc ;
|
||
int kc_count ;
|
||
KeySym *key_map ;
|
||
unsigned i ;
|
||
str_xref xref_rtn = NULL ;
|
||
unsigned num_xref = 0 ;
|
||
|
||
XDisplayKeycodes( dsp, &min_kc, &max_kc) ;
|
||
kc_count = max_kc + 1 - min_kc ;
|
||
key_map = XGetKeyboardMapping( dsp, min_kc, kc_count, &ks_per_kc) ;
|
||
if( key_map == NULL )
|
||
{
|
||
return NULL ;
|
||
}
|
||
kc_count *= ks_per_kc ;
|
||
|
||
i = 0 ;
|
||
while( i < count )
|
||
{
|
||
KeySym ks = XStringToKeysym( std_xref[i].default_name) ;
|
||
unsigned j = 0 ;
|
||
|
||
while( j < kc_count )
|
||
{
|
||
if( key_map[j] == ks )
|
||
{
|
||
/* Found keysym used in virtkey table in keymap,
|
||
* so break -> j != kc_count
|
||
*/
|
||
break ;
|
||
}
|
||
++j ;
|
||
}
|
||
if( j == kc_count )
|
||
{
|
||
/* Didn't find keysym of virtkey table, so add record to
|
||
* returned list which will later cause replacement in
|
||
* virtkeys table.
|
||
*/
|
||
xref_rtn = (str_xref) XtRealloc( (char *) xref_rtn,
|
||
sizeof( str_xref_rec) * (num_xref + 2)) ;
|
||
xref_rtn[num_xref++] = std_xref[i] ;
|
||
xref_rtn[num_xref].default_name = NULL ;
|
||
}
|
||
++i ;
|
||
}
|
||
XFree( (char *) key_map) ;
|
||
return xref_rtn ;
|
||
}
|
||
|
||
static Boolean
|
||
GetBindingsProperty(
|
||
Display *dsp,
|
||
Atom property,
|
||
String *binding)
|
||
{
|
||
Atom actual_type ;
|
||
int actual_format ;
|
||
unsigned long num_items ;
|
||
unsigned long bytes_after ;
|
||
unsigned char *prop = NULL ;
|
||
|
||
XGetWindowProperty( dsp, RootWindow( dsp, 0), property, 0, 1000000L,
|
||
FALSE, XA_STRING, &actual_type, &actual_format, &num_items, &bytes_after,
|
||
&prop) ;
|
||
if( (actual_type != XA_STRING)
|
||
|| (actual_format != 8)
|
||
|| (num_items == 0) )
|
||
{
|
||
if( prop != NULL )
|
||
{
|
||
XFree( prop) ;
|
||
}
|
||
return FALSE ;
|
||
}
|
||
*binding = (String) prop ;
|
||
return TRUE ;
|
||
}
|
||
|
||
static void
|
||
SetBindingsProperty(
|
||
Display *dsp,
|
||
Atom property,
|
||
String binding)
|
||
{
|
||
XChangeProperty( dsp, RootWindow( dsp, 0), property, XA_STRING, 8,
|
||
PropModeReplace, (unsigned char *) binding, strlen( binding)) ;
|
||
}
|
||
|
||
static String
|
||
FixupBindingsString(
|
||
String bindingsString,
|
||
str_xref repl_xref)
|
||
{
|
||
String fixed_str = XtNewString( bindingsString) ;
|
||
String ptr_next = fixed_str ;
|
||
|
||
while( repl_xref->default_name != NULL )
|
||
{
|
||
String ks_ptr = strstr( ptr_next, repl_xref->default_name) ;
|
||
unsigned orig_len = strlen( repl_xref->default_name) ;
|
||
|
||
if( ks_ptr == NULL )
|
||
{
|
||
/* Only increment to next replacement when no other instances
|
||
* are found in fixed_str.
|
||
*/
|
||
++repl_xref ;
|
||
ptr_next = fixed_str ;
|
||
continue ;
|
||
}
|
||
|
||
if( (strpbrk( (ks_ptr - 1), " \t>") == (ks_ptr - 1))
|
||
&& (strpbrk( ks_ptr, " \t\n") == (ks_ptr + orig_len)) )
|
||
{
|
||
unsigned new_len = strlen( repl_xref->new_name) ;
|
||
unsigned suffix_len = strlen( ks_ptr + orig_len) ;
|
||
|
||
if( new_len > orig_len )
|
||
{
|
||
unsigned new_ttl_len = strlen( fixed_str) + new_len - orig_len ;
|
||
unsigned prefix_len ;
|
||
|
||
*ks_ptr = '\0' ;
|
||
prefix_len = strlen( fixed_str) ;
|
||
fixed_str = XtRealloc( fixed_str, (new_ttl_len + 1)) ;
|
||
ks_ptr = fixed_str + prefix_len ;
|
||
}
|
||
memmove( (ks_ptr + new_len), (ks_ptr + orig_len), (suffix_len + 1)) ;
|
||
memcpy( ks_ptr, repl_xref->new_name, new_len) ;
|
||
|
||
ptr_next = ks_ptr + new_len ;
|
||
}
|
||
else
|
||
{
|
||
ptr_next = ks_ptr + 1 ;
|
||
}
|
||
}
|
||
return fixed_str ;
|
||
}
|
||
|
||
|
||
Boolean
|
||
VirtKeys4DIN(
|
||
Display *dsp)
|
||
{
|
||
/* This routine examines the X server's key map table to determine
|
||
* if certain HP-specific keysyms are missing. If they are, then
|
||
* the Motif virtual binding table properties are updated to utilize
|
||
* generic X keysyms instead of the missing HP vendor keysyms.
|
||
* In particular, this fixes the Motif virtual key binding table for
|
||
* correct operation on HP systems using the AT2/DIN style keyboard.
|
||
*/
|
||
static char *prop_names[] = { "_MOTIF_BINDINGS",
|
||
"_MOTIF_DEFAULT_BINDINGS" } ;
|
||
static str_xref_rec std_xref[] = { { "hpInsertChar", "Insert" },
|
||
{ "hpDeleteChar", "Delete" },
|
||
{ "End", "F7" },
|
||
} ;
|
||
Boolean PropChanged4DIN = FALSE ;
|
||
unsigned i ;
|
||
char *bindingsString ;
|
||
unsigned prop_existed ;
|
||
Atom *prop_atoms ;
|
||
str_xref vkeysym_xref ;
|
||
unsigned num_props = XtNumber( prop_names) ;
|
||
|
||
vkeysym_xref = GetReplacementList( dsp, std_xref, XtNumber(std_xref)) ;
|
||
if( vkeysym_xref == NULL )
|
||
{
|
||
return PropChanged4DIN ;
|
||
}
|
||
|
||
prop_atoms = (Atom *) XtMalloc( sizeof( Atom) * num_props) ;
|
||
XInternAtoms(dsp, prop_names, num_props, FALSE, prop_atoms);
|
||
|
||
prop_existed = FALSE ;
|
||
i = 0 ;
|
||
while( i < num_props )
|
||
{
|
||
if( GetBindingsProperty( dsp, prop_atoms[i], &bindingsString) )
|
||
{
|
||
String new_bstring = FixupBindingsString( bindingsString,
|
||
vkeysym_xref) ;
|
||
prop_existed = TRUE ;
|
||
XFree( bindingsString) ;
|
||
|
||
if( new_bstring != NULL )
|
||
{
|
||
SetBindingsProperty( dsp, prop_atoms[i], new_bstring) ;
|
||
XtFree( new_bstring) ;
|
||
}
|
||
}
|
||
++i ;
|
||
}
|
||
if( !prop_existed )
|
||
{
|
||
bindingsString = NULL ;
|
||
/* FIXME: this is an unexported openmotif procedure */
|
||
extern void _XmVirtKeysLoadFallbackBindings(Display *dsp, String *binding);
|
||
_XmVirtKeysLoadFallbackBindings( dsp, &bindingsString) ;
|
||
XtFree( bindingsString) ;
|
||
|
||
i = 0 ;
|
||
while( i < num_props )
|
||
{
|
||
if( GetBindingsProperty( dsp, prop_atoms[i], &bindingsString) )
|
||
{
|
||
String new_bstring = FixupBindingsString( bindingsString,
|
||
vkeysym_xref) ;
|
||
XtFree( bindingsString) ;
|
||
if( new_bstring != NULL )
|
||
{
|
||
PropChanged4DIN = TRUE ;
|
||
SetBindingsProperty( dsp, prop_atoms[i], new_bstring) ;
|
||
XtFree( new_bstring) ;
|
||
}
|
||
XFree( bindingsString) ;
|
||
}
|
||
++i ;
|
||
}
|
||
}
|
||
|
||
XtFree( (char *) vkeysym_xref) ;
|
||
XtFree( (char *) prop_atoms) ;
|
||
return PropChanged4DIN ;
|
||
}
|
||
#endif /* NO_HP_KEY_REMAP */
|
||
|
||
/**************************** eof ***************************/
|