898 lines
26 KiB
C
898 lines
26 KiB
C
/*****************************************************************************/
|
|
/*
|
|
|
|
Copyright 1989, 1998 The Open Group
|
|
Copyright 2005 Hitachi, Ltd.
|
|
|
|
Permission to use, copy, modify, distribute, and sell this software and its
|
|
documentation for any purpose is hereby granted without fee, provided that
|
|
the above copyright notice appear in all copies and that both that
|
|
copyright notice and this permission notice appear in supporting
|
|
documentation.
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
Except as contained in this notice, the name of The Open Group shall not be
|
|
used in advertising or otherwise to promote the sale, use or other dealings
|
|
in this Software without prior written authorization from The Open Group.
|
|
|
|
*/
|
|
/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/
|
|
/** Salt Lake City, Utah **/
|
|
/** Cambridge, Massachusetts **/
|
|
/** **/
|
|
/** All Rights Reserved **/
|
|
/** **/
|
|
/** Permission to use, copy, modify, and distribute this software and **/
|
|
/** its documentation for any purpose and without fee is hereby **/
|
|
/** granted, provided that the above copyright notice appear in all **/
|
|
/** copies and that both that copyright notice and this permis- **/
|
|
/** sion notice appear in supporting documentation, and that the **/
|
|
/** name of Evans & Sutherland not be used in advertising **/
|
|
/** in publicity pertaining to distribution of the software without **/
|
|
/** specific, written prior permission. **/
|
|
/** **/
|
|
/** EVANS & SUTHERLAND DISCLAIMs ALL WARRANTIES WITH REGARD **/
|
|
/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/
|
|
/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND **/
|
|
/** BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/
|
|
/** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/
|
|
/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/
|
|
/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/
|
|
/** OR PERFORMANCE OF THIS SOFTWARE. **/
|
|
/*****************************************************************************/
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* twm - "Tom's Window Manager"
|
|
*
|
|
* 27-Oct-1987 Thomas E. LaStrange File created
|
|
* 10-Oct-1990 David M. Sternlicht Storing saved colors on root
|
|
* 19-Feb-2005 Julien Lafon Handle print screens for unified Xserver
|
|
***********************************************************************/
|
|
|
|
#include <stdio.h>
|
|
#include <signal.h>
|
|
#include <fcntl.h>
|
|
#include "twm.h"
|
|
#include "add_window.h"
|
|
#include "gc.h"
|
|
#include "parse.h"
|
|
#include "version.h"
|
|
#include "menus.h"
|
|
#include "events.h"
|
|
#include "util.h"
|
|
#include "gram.h"
|
|
#include "screen.h"
|
|
#include "parse.h"
|
|
#include "session.h"
|
|
#include <X11/Xproto.h>
|
|
#include <X11/Xatom.h>
|
|
#include <X11/SM/SMlib.h>
|
|
#include <X11/Xmu/Error.h>
|
|
#include <X11/extensions/sync.h>
|
|
#include <X11/Xlocale.h>
|
|
#ifdef XPRINT
|
|
#include <X11/extensions/Print.h>
|
|
#endif /* XPRINT */
|
|
|
|
static void InitVariables ( void );
|
|
|
|
XtAppContext appContext; /* Xt application context */
|
|
XtSignalId si;
|
|
|
|
Display *dpy = NULL; /* which display are we talking to */
|
|
Window ResizeWindow; /* the window we are resizing */
|
|
|
|
int MultiScreen = TRUE; /* try for more than one screen? */
|
|
int NoPrintscreens = False; /* ignore special handling of print screens? */
|
|
int NumScreens; /* number of screens in ScreenList */
|
|
int HasShape; /* server supports shape extension? */
|
|
int ShapeEventBase, ShapeErrorBase;
|
|
int HasSync; /* server supports SYNC extension? */
|
|
int SyncEventBase, SyncErrorBase;
|
|
ScreenInfo **ScreenList; /* structures for each screen */
|
|
ScreenInfo *Scr = NULL; /* the cur and prev screens */
|
|
int PreviousScreen; /* last screen that we were on */
|
|
int FirstScreen; /* TRUE ==> first screen of display */
|
|
static Bool PrintErrorMessages = False; /* controls error messages */
|
|
static int RedirectError; /* TRUE ==> another window manager running */
|
|
static int TwmErrorHandler ( Display *dpy, XErrorEvent *event ); /* for settting RedirectError */
|
|
static int CatchRedirectError ( Display *dpy, XErrorEvent *event ); /* for everything else */
|
|
static void sigHandler(int);
|
|
char Info[INFO_LINES][INFO_SIZE]; /* info strings to print */
|
|
int InfoLines;
|
|
static char *InitFile = NULL;
|
|
|
|
Cursor UpperLeftCursor; /* upper Left corner cursor */
|
|
Cursor RightButt;
|
|
Cursor MiddleButt;
|
|
Cursor LeftButt;
|
|
|
|
XContext TwmContext; /* context for twm windows */
|
|
XContext MenuContext; /* context for all menu windows */
|
|
XContext ScreenContext; /* context to get screen data */
|
|
XContext ColormapContext; /* context for colormap operations */
|
|
|
|
XClassHint NoClass; /* for applications with no class */
|
|
|
|
XGCValues Gcv;
|
|
|
|
const char *Home; /* the HOME environment variable */
|
|
int HomeLen; /* length of Home */
|
|
int ParseError; /* error parsing the .twmrc file */
|
|
|
|
int HandlingEvents = FALSE; /* are we handling events yet? */
|
|
|
|
Window JunkRoot; /* junk window */
|
|
Window JunkChild; /* junk window */
|
|
int JunkX; /* junk variable */
|
|
int JunkY; /* junk variable */
|
|
unsigned int JunkWidth, JunkHeight, JunkBW, JunkDepth, JunkMask;
|
|
|
|
char *ProgramName;
|
|
int Argc;
|
|
char **Argv;
|
|
|
|
Bool RestartPreviousState = False; /* try to restart in previous state */
|
|
|
|
static unsigned long black, white;
|
|
|
|
Atom TwmAtoms[11];
|
|
|
|
Bool use_fontset; /* use XFontSet-related functions or not */
|
|
|
|
/* don't change the order of these strings */
|
|
static char* atom_names[11] = {
|
|
"_MIT_PRIORITY_COLORS",
|
|
"WM_CHANGE_STATE",
|
|
"WM_STATE",
|
|
"WM_COLORMAP_WINDOWS",
|
|
"WM_PROTOCOLS",
|
|
"WM_TAKE_FOCUS",
|
|
"WM_SAVE_YOURSELF",
|
|
"WM_DELETE_WINDOW",
|
|
"SM_CLIENT_ID",
|
|
"WM_CLIENT_LEADER",
|
|
"WM_WINDOW_ROLE"
|
|
};
|
|
|
|
#ifdef XPRINT
|
|
/* |hasExtension()| and |IsPrintScreen()| have been stolen from
|
|
* xc/programs/xdpyinfo/xdpyinfo.c */
|
|
static
|
|
Bool hasExtension(Display *dpy, char *extname)
|
|
{
|
|
int num_extensions,
|
|
i;
|
|
char **extensions;
|
|
extensions = XListExtensions(dpy, &num_extensions);
|
|
for (i = 0; i < num_extensions &&
|
|
(strcmp(extensions[i], extname) != 0); i++);
|
|
XFreeExtensionList(extensions);
|
|
return i != num_extensions;
|
|
}
|
|
|
|
static
|
|
Bool IsPrintScreen(Screen *s)
|
|
{
|
|
Display *dpy = XDisplayOfScreen(s);
|
|
int i;
|
|
|
|
/* Check whether this is a screen of a print DDX */
|
|
if (hasExtension(dpy, XP_PRINTNAME)) {
|
|
Screen **pscreens;
|
|
int pscrcount;
|
|
|
|
pscreens = XpQueryScreens(dpy, &pscrcount);
|
|
for( i = 0 ; (i < pscrcount) && pscreens ; i++ ) {
|
|
if (s == pscreens[i]) {
|
|
return True;
|
|
}
|
|
}
|
|
XFree(pscreens);
|
|
}
|
|
return False;
|
|
}
|
|
#endif /* XPRINT */
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Procedure:
|
|
* main - start of twmruined
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
Window root, parent, *children;
|
|
unsigned int nchildren;
|
|
int i, j;
|
|
char *display_name = NULL;
|
|
unsigned long valuemask; /* mask for create windows */
|
|
XSetWindowAttributes attributes; /* attributes for create windows */
|
|
int numManaged, firstscrn, lastscrn, scrnum;
|
|
int zero = 0;
|
|
char *restore_filename = NULL;
|
|
char *client_id = NULL;
|
|
char *loc;
|
|
|
|
ProgramName = argv[0];
|
|
Argc = argc;
|
|
Argv = argv;
|
|
|
|
for (i = 1; i < argc; i++) {
|
|
if (argv[i][0] == '-') {
|
|
switch (argv[i][1]) {
|
|
case 'd': /* -display dpy */
|
|
if (strcmp(&argv[i][1], "display")) goto usage;
|
|
if (++i >= argc) goto usage;
|
|
display_name = argv[i];
|
|
continue;
|
|
case 's': /* -single */
|
|
MultiScreen = FALSE;
|
|
continue;
|
|
#ifdef XPRINT
|
|
case 'n': /* -noprint */
|
|
if (strcmp(&argv[i][1], "noprint")) goto usage;
|
|
NoPrintscreens = True;
|
|
continue;
|
|
#endif /* XPRINT */
|
|
case 'f': /* -file twmrcfilename */
|
|
if (++i >= argc) goto usage;
|
|
InitFile = argv[i];
|
|
continue;
|
|
case 'v': /* -verbose */
|
|
PrintErrorMessages = True;
|
|
continue;
|
|
case 'c': /* -clientId */
|
|
if (strcmp(&argv[i][1], "clientId")) goto usage;
|
|
if (++i >= argc) goto usage;
|
|
client_id = argv[i];
|
|
continue;
|
|
case 'r': /* -restore */
|
|
if (strcmp(&argv[i][1], "restore")) goto usage;
|
|
if (++i >= argc) goto usage;
|
|
restore_filename = argv[i];
|
|
continue;
|
|
case 'q': /* -quiet */
|
|
PrintErrorMessages = False;
|
|
continue;
|
|
}
|
|
}
|
|
usage:
|
|
fprintf (stderr,
|
|
"usage: %s [-display dpy] [-f file] [-s] [-q] [-v]"
|
|
#ifdef XPRINT
|
|
" [-noprint]"
|
|
#endif /* XPRINT */
|
|
" [-clientId id] [-restore file]\n",
|
|
ProgramName);
|
|
exit (1);
|
|
}
|
|
|
|
loc = setlocale(LC_ALL, "");
|
|
if (!loc || !strcmp(loc, "C") || !strcmp(loc, "POSIX") ||
|
|
!XSupportsLocale()) {
|
|
use_fontset = False;
|
|
} else {
|
|
use_fontset = True;
|
|
}
|
|
|
|
#define newhandler(sig) \
|
|
if (signal (sig, SIG_IGN) != SIG_IGN) (void) signal (sig, sigHandler)
|
|
|
|
|
|
newhandler (SIGINT);
|
|
newhandler (SIGHUP);
|
|
newhandler (SIGQUIT);
|
|
newhandler (SIGTERM);
|
|
|
|
#undef newhandler
|
|
|
|
Home = getenv("HOME");
|
|
if (Home != NULL) {
|
|
char *temp_p;
|
|
|
|
/*
|
|
* Make a copy of Home because the string returned by getenv() can be
|
|
* overwritten by some POSIX.1 and ANSI-C implementations of getenv()
|
|
* when further calls to getenv() are made
|
|
*/
|
|
|
|
temp_p = strdup(Home);
|
|
Home = temp_p;
|
|
}
|
|
|
|
if (Home == NULL)
|
|
Home = "./";
|
|
|
|
HomeLen = strlen(Home);
|
|
|
|
NoClass.res_name = NoName;
|
|
NoClass.res_class = NoName;
|
|
|
|
XtToolkitInitialize ();
|
|
appContext = XtCreateApplicationContext ();
|
|
|
|
si = XtAppAddSignal(appContext, Done, NULL);
|
|
|
|
if (!(dpy = XtOpenDisplay (appContext, display_name, "twm", "twm",
|
|
NULL, 0, &zero, NULL))) {
|
|
fprintf (stderr, "%s: unable to open display \"%s\"\n",
|
|
ProgramName, XDisplayName(display_name));
|
|
exit (1);
|
|
}
|
|
|
|
if (fcntl(ConnectionNumber(dpy), F_SETFD, 1) == -1) {
|
|
fprintf (stderr,
|
|
"%s: unable to mark display connection as close-on-exec\n",
|
|
ProgramName);
|
|
exit (1);
|
|
}
|
|
|
|
if (restore_filename)
|
|
ReadWinConfigFile (restore_filename);
|
|
|
|
HasShape = XShapeQueryExtension(dpy, &ShapeEventBase, &ShapeErrorBase);
|
|
HasSync = XSyncQueryExtension(dpy, &SyncEventBase, &SyncErrorBase);
|
|
TwmContext = XUniqueContext();
|
|
MenuContext = XUniqueContext();
|
|
ScreenContext = XUniqueContext();
|
|
ColormapContext = XUniqueContext();
|
|
|
|
(void) XInternAtoms(dpy, atom_names, sizeof TwmAtoms / sizeof TwmAtoms[0],
|
|
False, TwmAtoms);
|
|
|
|
/* Set up the per-screen global information. */
|
|
|
|
NumScreens = ScreenCount(dpy);
|
|
|
|
if (MultiScreen)
|
|
{
|
|
firstscrn = 0;
|
|
lastscrn = NumScreens - 1;
|
|
}
|
|
else
|
|
{
|
|
firstscrn = lastscrn = DefaultScreen(dpy);
|
|
}
|
|
|
|
InfoLines = 0;
|
|
|
|
/* for simplicity, always allocate NumScreens ScreenInfo struct pointers */
|
|
ScreenList = calloc (NumScreens, sizeof (ScreenInfo *));
|
|
if (ScreenList == NULL)
|
|
{
|
|
fprintf (stderr, "%s: Unable to allocate memory for screen list, exiting.\n",
|
|
ProgramName);
|
|
exit (1);
|
|
}
|
|
numManaged = 0;
|
|
PreviousScreen = DefaultScreen(dpy);
|
|
FirstScreen = TRUE;
|
|
for (scrnum = firstscrn ; scrnum <= lastscrn; scrnum++)
|
|
{
|
|
#ifdef XPRINT
|
|
/* Ignore print screens to avoid that users accidentally warp on a
|
|
* print screen (which are not visible on video displays) */
|
|
if ((!NoPrintscreens) && IsPrintScreen(XScreenOfDisplay(dpy, scrnum)))
|
|
{
|
|
fprintf (stderr, "%s: skipping print screen %d\n",
|
|
ProgramName, scrnum);
|
|
continue;
|
|
}
|
|
#endif /* XPRINT */
|
|
|
|
/* Make sure property priority colors is empty */
|
|
XChangeProperty (dpy, RootWindow(dpy, scrnum), _XA_MIT_PRIORITY_COLORS,
|
|
XA_CARDINAL, 32, PropModeReplace, NULL, 0);
|
|
RedirectError = FALSE;
|
|
XSetErrorHandler(CatchRedirectError);
|
|
XSelectInput(dpy, RootWindow (dpy, scrnum),
|
|
ColormapChangeMask | EnterWindowMask | PropertyChangeMask |
|
|
SubstructureRedirectMask | KeyPressMask |
|
|
ButtonPressMask | ButtonReleaseMask);
|
|
XSync(dpy, 0);
|
|
XSetErrorHandler(TwmErrorHandler);
|
|
|
|
if (RedirectError)
|
|
{
|
|
fprintf (stderr, "%s: another window manager is already running.",
|
|
ProgramName);
|
|
if (MultiScreen && NumScreens > 0)
|
|
fprintf(stderr, " on screen %d?\n", scrnum);
|
|
else
|
|
fprintf(stderr, "?\n");
|
|
continue;
|
|
}
|
|
|
|
numManaged ++;
|
|
|
|
/* Note: ScreenInfo struct is calloc'ed to initialize to zero. */
|
|
Scr = ScreenList[scrnum] = calloc(1, sizeof(ScreenInfo));
|
|
if (Scr == NULL)
|
|
{
|
|
fprintf (stderr, "%s: unable to allocate memory for ScreenInfo structure for screen %d.\n",
|
|
ProgramName, scrnum);
|
|
continue;
|
|
}
|
|
|
|
/* initialize list pointers, remember to put an initialization
|
|
* in InitVariables also
|
|
*/
|
|
Scr->BorderColorL = NULL;
|
|
Scr->IconBorderColorL = NULL;
|
|
Scr->BorderTileForegroundL = NULL;
|
|
Scr->BorderTileBackgroundL = NULL;
|
|
Scr->TitleForegroundL = NULL;
|
|
Scr->TitleBackgroundL = NULL;
|
|
Scr->IconForegroundL = NULL;
|
|
Scr->IconBackgroundL = NULL;
|
|
Scr->NoTitle = NULL;
|
|
Scr->MakeTitle = NULL;
|
|
Scr->AutoRaise = NULL;
|
|
Scr->IconNames = NULL;
|
|
Scr->NoStackModeL = NULL;
|
|
Scr->StartIconified = NULL;
|
|
Scr->WindowRingL = NULL;
|
|
Scr->WarpCursorL = NULL;
|
|
/* remember to put an initialization in InitVariables also
|
|
*/
|
|
|
|
Scr->screen = scrnum;
|
|
Scr->d_depth = DefaultDepth(dpy, scrnum);
|
|
Scr->d_visual = DefaultVisual(dpy, scrnum);
|
|
Scr->Root = RootWindow(dpy, scrnum);
|
|
XSaveContext (dpy, Scr->Root, ScreenContext, (caddr_t) Scr);
|
|
|
|
Scr->TwmRoot.cmaps.number_cwins = 1;
|
|
Scr->TwmRoot.cmaps.cwins = malloc(sizeof(ColormapWindow *));
|
|
Scr->TwmRoot.cmaps.cwins[0] =
|
|
CreateColormapWindow(Scr->Root, True, False);
|
|
Scr->TwmRoot.cmaps.cwins[0]->visibility = VisibilityPartiallyObscured;
|
|
|
|
Scr->cmapInfo.cmaps = NULL;
|
|
Scr->cmapInfo.maxCmaps =
|
|
MaxCmapsOfScreen(ScreenOfDisplay(dpy, Scr->screen));
|
|
Scr->cmapInfo.root_pushes = 0;
|
|
InstallWindowColormaps(0, &Scr->TwmRoot);
|
|
|
|
Scr->StdCmapInfo.head = Scr->StdCmapInfo.tail =
|
|
Scr->StdCmapInfo.mru = NULL;
|
|
Scr->StdCmapInfo.mruindex = 0;
|
|
LocateStandardColormaps();
|
|
|
|
Scr->TBInfo.nleft = Scr->TBInfo.nright = 0;
|
|
Scr->TBInfo.head = NULL;
|
|
Scr->TBInfo.border = 1;
|
|
Scr->TBInfo.width = 0;
|
|
Scr->TBInfo.leftx = 0;
|
|
Scr->TBInfo.titlex = 0;
|
|
|
|
Scr->MyDisplayWidth = DisplayWidth(dpy, scrnum);
|
|
Scr->MyDisplayHeight = DisplayHeight(dpy, scrnum);
|
|
Scr->MaxWindowWidth = 32767 - Scr->MyDisplayWidth;
|
|
Scr->MaxWindowHeight = 32767 - Scr->MyDisplayHeight;
|
|
|
|
Scr->XORvalue = (((unsigned long) 1) << Scr->d_depth) - 1;
|
|
|
|
if (DisplayCells(dpy, scrnum) < 3)
|
|
Scr->Monochrome = MONOCHROME;
|
|
else if (DefaultVisual(dpy, scrnum)->class == GrayScale)
|
|
Scr->Monochrome = GRAYSCALE;
|
|
else
|
|
Scr->Monochrome = COLOR;
|
|
|
|
/* setup default colors */
|
|
Scr->FirstTime = TRUE;
|
|
GetColor(Scr->Monochrome, &black, "black");
|
|
Scr->Black = black;
|
|
GetColor(Scr->Monochrome, &white, "white");
|
|
Scr->White = white;
|
|
|
|
if (FirstScreen)
|
|
{
|
|
SetFocus ((TwmWindow *)NULL, CurrentTime);
|
|
|
|
/* define cursors */
|
|
|
|
NewFontCursor(&UpperLeftCursor, "top_left_corner");
|
|
NewFontCursor(&RightButt, "rightbutton");
|
|
NewFontCursor(&LeftButt, "leftbutton");
|
|
NewFontCursor(&MiddleButt, "middlebutton");
|
|
}
|
|
|
|
Scr->IconDirectory = NULL;
|
|
|
|
Scr->siconifyPm = None;
|
|
Scr->pullPm = None;
|
|
Scr->tbpm.xlogo = None;
|
|
Scr->tbpm.resize = None;
|
|
Scr->tbpm.question = None;
|
|
Scr->tbpm.menu = None;
|
|
Scr->tbpm.delete = None;
|
|
|
|
InitVariables();
|
|
InitMenus();
|
|
|
|
/* Parse it once for each screen. */
|
|
ParseTwmrc(InitFile);
|
|
assign_var_savecolor(); /* storeing pixels for twmrc "entities" */
|
|
if (!Scr->HaveFonts) CreateFonts();
|
|
CreateGCs();
|
|
MakeMenus();
|
|
|
|
Scr->TitleBarFont.y += Scr->FramePadding;
|
|
Scr->TitleHeight = Scr->TitleBarFont.height + Scr->FramePadding * 2;
|
|
/* make title height be odd so buttons look nice and centered */
|
|
if (!(Scr->TitleHeight & 1)) Scr->TitleHeight++;
|
|
|
|
InitTitlebarButtons (); /* menus are now loaded! */
|
|
|
|
XGrabServer(dpy);
|
|
XSync(dpy, 0);
|
|
|
|
JunkX = 0;
|
|
JunkY = 0;
|
|
|
|
XQueryTree(dpy, Scr->Root, &root, &parent, &children, &nchildren);
|
|
|
|
/*
|
|
* weed out icon windows
|
|
*/
|
|
for (i = 0; i < nchildren; i++) {
|
|
if (children[i]) {
|
|
XWMHints *wmhintsp = XGetWMHints (dpy, children[i]);
|
|
|
|
if (wmhintsp) {
|
|
if (wmhintsp->flags & IconWindowHint) {
|
|
for (j = 0; j < nchildren; j++) {
|
|
if (children[j] == wmhintsp->icon_window) {
|
|
children[j] = None;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
XFree (wmhintsp);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* map all of the non-override windows
|
|
*/
|
|
for (i = 0; i < nchildren; i++)
|
|
{
|
|
if (children[i] && MappedNotOverride(children[i]))
|
|
{
|
|
XUnmapWindow(dpy, children[i]);
|
|
SimulateMapRequest(children[i]);
|
|
}
|
|
}
|
|
|
|
attributes.border_pixel = Scr->DefaultC.fore;
|
|
attributes.background_pixel = Scr->DefaultC.back;
|
|
attributes.event_mask = (ExposureMask | ButtonPressMask |
|
|
KeyPressMask | ButtonReleaseMask);
|
|
attributes.backing_store = NotUseful;
|
|
attributes.cursor = XCreateFontCursor (dpy, XC_hand2);
|
|
valuemask = (CWBorderPixel | CWBackPixel | CWEventMask |
|
|
CWBackingStore | CWCursor);
|
|
Scr->InfoWindow = XCreateWindow (dpy, Scr->Root, 0, 0,
|
|
(unsigned int) 5, (unsigned int) 5,
|
|
(unsigned int) BW, 0,
|
|
(unsigned int) CopyFromParent,
|
|
(Visual *) CopyFromParent,
|
|
valuemask, &attributes);
|
|
|
|
Scr->SizeStringWidth = MyFont_TextWidth (&Scr->SizeFont,
|
|
" 8888 x 8888 ", 13);
|
|
valuemask = (CWBorderPixel | CWBackPixel | CWBitGravity);
|
|
attributes.bit_gravity = NorthWestGravity;
|
|
Scr->SizeWindow = XCreateWindow (dpy, Scr->Root, 0, 0,
|
|
(unsigned int) Scr->SizeStringWidth,
|
|
(unsigned int) (Scr->SizeFont.height +
|
|
SIZE_VINDENT*2),
|
|
(unsigned int) BW, 0,
|
|
(unsigned int) CopyFromParent,
|
|
(Visual *) CopyFromParent,
|
|
valuemask, &attributes);
|
|
|
|
XUngrabServer(dpy);
|
|
|
|
FirstScreen = FALSE;
|
|
Scr->FirstTime = FALSE;
|
|
} /* for */
|
|
|
|
if (numManaged == 0) {
|
|
if (MultiScreen && NumScreens > 0)
|
|
fprintf (stderr, "%s: unable to find any unmanaged %sscreens.\n",
|
|
ProgramName, NoPrintscreens?"":"video ");
|
|
exit (1);
|
|
}
|
|
|
|
(void) ConnectToSessionManager (client_id);
|
|
|
|
RestartPreviousState = False;
|
|
HandlingEvents = TRUE;
|
|
InitEvents();
|
|
HandleEvents();
|
|
exit(0);
|
|
}
|
|
|
|
/**
|
|
* initialize twm variables
|
|
*/
|
|
static void
|
|
InitVariables(void)
|
|
{
|
|
FreeList(&Scr->BorderColorL);
|
|
FreeList(&Scr->IconBorderColorL);
|
|
FreeList(&Scr->BorderTileForegroundL);
|
|
FreeList(&Scr->BorderTileBackgroundL);
|
|
FreeList(&Scr->TitleForegroundL);
|
|
FreeList(&Scr->TitleBackgroundL);
|
|
FreeList(&Scr->IconForegroundL);
|
|
FreeList(&Scr->IconBackgroundL);
|
|
FreeList(&Scr->NoTitle);
|
|
FreeList(&Scr->MakeTitle);
|
|
FreeList(&Scr->AutoRaise);
|
|
FreeList(&Scr->IconNames);
|
|
FreeList(&Scr->NoStackModeL);
|
|
FreeList(&Scr->StartIconified);
|
|
FreeList(&Scr->WindowRingL);
|
|
FreeList(&Scr->WarpCursorL);
|
|
|
|
NewFontCursor(&Scr->FrameCursor, "top_left_arrow");
|
|
NewFontCursor(&Scr->TitleCursor, "top_left_arrow");
|
|
NewFontCursor(&Scr->IconCursor, "top_left_arrow");
|
|
NewFontCursor(&Scr->MoveCursor, "fleur");
|
|
NewFontCursor(&Scr->ResizeCursor, "fleur");
|
|
NewFontCursor(&Scr->MenuCursor, "sb_left_arrow");
|
|
NewFontCursor(&Scr->ButtonCursor, "hand2");
|
|
NewFontCursor(&Scr->WaitCursor, "watch");
|
|
NewFontCursor(&Scr->SelectCursor, "dot");
|
|
NewFontCursor(&Scr->DestroyCursor, "pirate");
|
|
|
|
Scr->Ring = NULL;
|
|
Scr->RingLeader = NULL;
|
|
|
|
Scr->DefaultC.fore = black;
|
|
Scr->DefaultC.back = white;
|
|
Scr->BorderColor = black;
|
|
Scr->BorderTileC.fore = black;
|
|
Scr->BorderTileC.back = white;
|
|
Scr->TitleC.fore = black;
|
|
Scr->TitleC.back = white;
|
|
Scr->MenuC.fore = black;
|
|
Scr->MenuC.back = white;
|
|
Scr->MenuTitleC.fore = black;
|
|
Scr->MenuTitleC.back = white;
|
|
Scr->MenuShadowColor = black;
|
|
Scr->MenuBorderColor = black;
|
|
Scr->IconC.fore = black;
|
|
Scr->IconC.back = white;
|
|
Scr->IconBorderColor = black;
|
|
Scr->PointerForeground.pixel = black;
|
|
XQueryColor(dpy, Scr->TwmRoot.cmaps.cwins[0]->colormap->c,
|
|
&Scr->PointerForeground);
|
|
Scr->PointerBackground.pixel = white;
|
|
XQueryColor(dpy, Scr->TwmRoot.cmaps.cwins[0]->colormap->c,
|
|
&Scr->PointerBackground);
|
|
|
|
Scr->FramePadding = 2; /* values that look "nice" on */
|
|
Scr->TitlePadding = 8; /* 75 and 100dpi displays */
|
|
Scr->ButtonIndent = 1;
|
|
Scr->SizeStringOffset = 0;
|
|
Scr->BorderWidth = BW;
|
|
Scr->IconBorderWidth = BW;
|
|
Scr->MenuBorderWidth = BW;
|
|
Scr->UnknownWidth = 0;
|
|
Scr->UnknownHeight = 0;
|
|
Scr->NumAutoRaises = 0;
|
|
Scr->NoDefaults = FALSE;
|
|
Scr->UsePPosition = PPOS_OFF;
|
|
Scr->FocusRoot = TRUE;
|
|
Scr->Focus = NULL;
|
|
Scr->WarpCursor = FALSE;
|
|
Scr->ForceIcon = FALSE;
|
|
Scr->NoGrabServer = FALSE;
|
|
Scr->NoRaiseMove = FALSE;
|
|
Scr->NoRaiseResize = FALSE;
|
|
Scr->NoRaiseDeicon = FALSE;
|
|
Scr->NoRaiseWarp = FALSE;
|
|
Scr->DontMoveOff = FALSE;
|
|
Scr->DoZoom = FALSE;
|
|
Scr->TitleFocus = TRUE;
|
|
Scr->NoTitlebar = FALSE;
|
|
Scr->DecorateTransients = FALSE;
|
|
Scr->BackingStore = TRUE;
|
|
Scr->SaveUnder = TRUE;
|
|
Scr->RandomPlacement = FALSE;
|
|
Scr->OpaqueMove = FALSE;
|
|
Scr->StackMode = TRUE;
|
|
Scr->MoveDelta = 1; /* so that f.deltastop will work */
|
|
Scr->ZoomCount = 8;
|
|
Scr->Shadow = TRUE;
|
|
Scr->InterpolateMenuColors = FALSE;
|
|
Scr->ClientBorderWidth = FALSE;
|
|
Scr->FirstRegion = NULL;
|
|
Scr->LastRegion = NULL;
|
|
Scr->FirstTime = TRUE;
|
|
Scr->HaveFonts = FALSE; /* i.e. not loaded yet */
|
|
Scr->CaseSensitive = TRUE;
|
|
Scr->WarpUnmapped = FALSE;
|
|
|
|
/* setup default fonts; overridden by defaults from system.twmrc */
|
|
#define DEFAULT_NICE_FONT "variable"
|
|
#define DEFAULT_FAST_FONT "fixed"
|
|
|
|
Scr->TitleBarFont.font = NULL;
|
|
Scr->TitleBarFont.fontset = NULL;
|
|
Scr->TitleBarFont.name = DEFAULT_NICE_FONT;
|
|
Scr->MenuFont.font = NULL;
|
|
Scr->MenuFont.fontset = NULL;
|
|
Scr->MenuFont.name = DEFAULT_NICE_FONT;
|
|
Scr->IconFont.font = NULL;
|
|
Scr->IconFont.fontset = NULL;
|
|
Scr->IconFont.name = DEFAULT_NICE_FONT;
|
|
Scr->SizeFont.font = NULL;
|
|
Scr->SizeFont.fontset = NULL;
|
|
Scr->SizeFont.name = DEFAULT_FAST_FONT;
|
|
Scr->DefaultFont.font = NULL;
|
|
Scr->DefaultFont.fontset = NULL;
|
|
Scr->DefaultFont.name = DEFAULT_FAST_FONT;
|
|
|
|
}
|
|
|
|
void
|
|
CreateFonts (void)
|
|
{
|
|
GetFont(&Scr->TitleBarFont);
|
|
GetFont(&Scr->MenuFont);
|
|
GetFont(&Scr->IconFont);
|
|
GetFont(&Scr->SizeFont);
|
|
GetFont(&Scr->DefaultFont);
|
|
Scr->HaveFonts = TRUE;
|
|
}
|
|
|
|
void
|
|
RestoreWithdrawnLocation (TwmWindow *tmp)
|
|
{
|
|
int gravx, gravy;
|
|
unsigned int bw, mask;
|
|
XWindowChanges xwc;
|
|
|
|
if (XGetGeometry (dpy, tmp->w, &JunkRoot, &xwc.x, &xwc.y,
|
|
&JunkWidth, &JunkHeight, &bw, &JunkDepth)) {
|
|
|
|
GetGravityOffsets (tmp, &gravx, &gravy);
|
|
if (gravy < 0) xwc.y -= tmp->title_height;
|
|
|
|
if (bw != tmp->old_bw) {
|
|
int xoff, yoff;
|
|
|
|
if (!Scr->ClientBorderWidth) {
|
|
xoff = gravx;
|
|
yoff = gravy;
|
|
} else {
|
|
xoff = 0;
|
|
yoff = 0;
|
|
}
|
|
|
|
xwc.x -= (xoff + 1) * tmp->old_bw;
|
|
xwc.y -= (yoff + 1) * tmp->old_bw;
|
|
}
|
|
if (!Scr->ClientBorderWidth) {
|
|
xwc.x += gravx * tmp->frame_bw;
|
|
xwc.y += gravy * tmp->frame_bw;
|
|
}
|
|
|
|
mask = (CWX | CWY);
|
|
if (bw != tmp->old_bw) {
|
|
xwc.border_width = tmp->old_bw;
|
|
mask |= CWBorderWidth;
|
|
}
|
|
|
|
XConfigureWindow (dpy, tmp->w, mask, &xwc);
|
|
|
|
if (tmp->wmhints && (tmp->wmhints->flags & IconWindowHint)) {
|
|
XUnmapWindow (dpy, tmp->wmhints->icon_window);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
Reborder (Time time)
|
|
{
|
|
TwmWindow *tmp; /* temp twm window structure */
|
|
int scrnum;
|
|
|
|
/* put a border back around all windows */
|
|
|
|
XGrabServer (dpy);
|
|
for (scrnum = 0; scrnum < NumScreens; scrnum++)
|
|
{
|
|
if ((Scr = ScreenList[scrnum]) == NULL)
|
|
continue;
|
|
|
|
InstallWindowColormaps (0, &Scr->TwmRoot); /* force reinstall */
|
|
for (tmp = Scr->TwmRoot.next; tmp != NULL; tmp = tmp->next)
|
|
{
|
|
RestoreWithdrawnLocation (tmp);
|
|
XMapWindow (dpy, tmp->w);
|
|
}
|
|
}
|
|
|
|
XUngrabServer (dpy);
|
|
SetFocus ((TwmWindow*)NULL, time);
|
|
}
|
|
|
|
static void
|
|
sigHandler(int sig)
|
|
{
|
|
XtNoticeSignal(si);
|
|
}
|
|
|
|
/**
|
|
* cleanup and exit twm
|
|
*/
|
|
void
|
|
Done(XtPointer client_data, XtSignalId *si)
|
|
{
|
|
if (dpy)
|
|
{
|
|
Reborder(CurrentTime);
|
|
XCloseDisplay(dpy);
|
|
}
|
|
exit(0);
|
|
}
|
|
|
|
|
|
/*
|
|
* Error Handlers. If a client dies, we'll get a BadWindow error (except for
|
|
* GetGeometry which returns BadDrawable) for most operations that we do before
|
|
* manipulating the client's window.
|
|
*/
|
|
|
|
Bool ErrorOccurred = False;
|
|
XErrorEvent LastErrorEvent;
|
|
|
|
static int
|
|
TwmErrorHandler(Display *dpy, XErrorEvent *event)
|
|
{
|
|
LastErrorEvent = *event;
|
|
ErrorOccurred = True;
|
|
|
|
if (PrintErrorMessages && /* don't be too obnoxious */
|
|
event->error_code != BadWindow && /* watch for dead puppies */
|
|
(event->request_code != X_GetGeometry && /* of all styles */
|
|
event->error_code != BadDrawable))
|
|
XmuPrintDefaultErrorMessage (dpy, event, stderr);
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int
|
|
CatchRedirectError(Display *dpy, XErrorEvent *event)
|
|
{
|
|
RedirectError = TRUE;
|
|
LastErrorEvent = *event;
|
|
ErrorOccurred = True;
|
|
return 0;
|
|
}
|