2499 lines
65 KiB
C
2499 lines
65 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"
|
|
#ifndef NO_OL_COMPAT
|
|
#include "WmOL.h"
|
|
#endif /* NO_OL_COMPAT */
|
|
#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 "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];
|
|
#ifndef NO_OL_COMPAT
|
|
InitOLCompat();
|
|
#endif /* NO_OL_COMPAT */
|
|
#ifndef NO_SHAPE
|
|
wmGD.hasShape = XShapeQueryExtension (DISPLAY,
|
|
&wmGD.shapeEventBase,
|
|
&wmGD.shapeErrorBase);
|
|
#endif /* NO_SHAPE */
|
|
|
|
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) ;
|
|
#ifdef PANACOMM
|
|
/*
|
|
* If this is the first screen we've managed,
|
|
* tell the session manager we're ready
|
|
*/
|
|
if (!processedGlobalResources)
|
|
{
|
|
SendClientMsg( wmGD.dtSmWindow,
|
|
(long) wmGD.xa_DT_SM_WM_PROTOCOL,
|
|
(long) wmGD.xa_DT_WM_READY,
|
|
CurrentTime, NULL, 0);
|
|
}
|
|
#endif /* PANACOMM */
|
|
|
|
/* 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 ();
|
|
|
|
/*
|
|
* 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);
|
|
|
|
#ifdef HP_VUE
|
|
UpdateWorkspaceInfoProperty (pSD); /* backward compatible */
|
|
#endif /* HP_VUE */
|
|
|
|
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->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);
|
|
|
|
/*
|
|
* 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 buffer[256];
|
|
char displayName[256];
|
|
|
|
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 ***************************/
|