twm.c revision f66df612
13e747e6dSmrg/*****************************************************************************/
23e747e6dSmrg/*
33e747e6dSmrg
43e747e6dSmrgCopyright 1989, 1998  The Open Group
53e747e6dSmrgCopyright 2005 Hitachi, Ltd.
63e747e6dSmrg
73e747e6dSmrgPermission to use, copy, modify, distribute, and sell this software and its
83e747e6dSmrgdocumentation for any purpose is hereby granted without fee, provided that
93e747e6dSmrgthe above copyright notice appear in all copies and that both that
103e747e6dSmrgcopyright notice and this permission notice appear in supporting
113e747e6dSmrgdocumentation.
123e747e6dSmrg
133e747e6dSmrgThe above copyright notice and this permission notice shall be included in
143e747e6dSmrgall copies or substantial portions of the Software.
153e747e6dSmrg
163e747e6dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
173e747e6dSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
183e747e6dSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
193e747e6dSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
203e747e6dSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
213e747e6dSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
223e747e6dSmrg
233e747e6dSmrgExcept as contained in this notice, the name of The Open Group shall not be
243e747e6dSmrgused in advertising or otherwise to promote the sale, use or other dealings
253e747e6dSmrgin this Software without prior written authorization from The Open Group.
263e747e6dSmrg
273e747e6dSmrg*/
283e747e6dSmrg/**       Copyright 1988 by Evans & Sutherland Computer Corporation,        **/
293e747e6dSmrg/**                          Salt Lake City, Utah                           **/
303e747e6dSmrg/**                        Cambridge, Massachusetts                         **/
313e747e6dSmrg/**                                                                         **/
323e747e6dSmrg/**                           All Rights Reserved                           **/
333e747e6dSmrg/**                                                                         **/
343e747e6dSmrg/**    Permission to use, copy, modify, and distribute this software and    **/
353e747e6dSmrg/**    its documentation  for  any  purpose  and  without  fee is hereby    **/
363e747e6dSmrg/**    granted, provided that the above copyright notice appear  in  all    **/
373e747e6dSmrg/**    copies and that both  that  copyright  notice  and  this  permis-    **/
383e747e6dSmrg/**    sion  notice appear in supporting  documentation,  and  that  the    **/
393e747e6dSmrg/**    name of Evans & Sutherland not be used in advertising    **/
403e747e6dSmrg/**    in publicity pertaining to distribution of the  software  without    **/
413e747e6dSmrg/**    specific, written prior permission.                                  **/
423e747e6dSmrg/**                                                                         **/
433e747e6dSmrg/**    EVANS & SUTHERLAND DISCLAIMs ALL WARRANTIES WITH REGARD    **/
443e747e6dSmrg/**    TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES  OF  MERCHANT-    **/
453e747e6dSmrg/**    ABILITY  AND  FITNESS,  IN  NO  EVENT SHALL EVANS & SUTHERLAND    **/
463e747e6dSmrg/**    BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL  DAM-    **/
473e747e6dSmrg/**    AGES OR  ANY DAMAGES WHATSOEVER  RESULTING FROM LOSS OF USE, DATA    **/
483e747e6dSmrg/**    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER    **/
493e747e6dSmrg/**    TORTIOUS ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE    **/
503e747e6dSmrg/**    OR PERFORMANCE OF THIS SOFTWARE.                                     **/
513e747e6dSmrg/*****************************************************************************/
523e747e6dSmrg
533e747e6dSmrg/***********************************************************************
543e747e6dSmrg *
553e747e6dSmrg * twm - "Tom's Window Manager"
563e747e6dSmrg *
573e747e6dSmrg * 27-Oct-1987 Thomas E. LaStrange    File created
583e747e6dSmrg * 10-Oct-1990 David M. Sternlicht    Storing saved colors on root
593e747e6dSmrg * 19-Feb-2005 Julien Lafon           Handle print screens for unified Xserver
603e747e6dSmrg ***********************************************************************/
613e747e6dSmrg
623e747e6dSmrg#include <stdio.h>
633e747e6dSmrg#include <signal.h>
643e747e6dSmrg#include <fcntl.h>
65f66df612Smrg#include <stdarg.h>
66f66df612Smrg
673e747e6dSmrg#include "twm.h"
683e747e6dSmrg#include "iconmgr.h"
693e747e6dSmrg#include "add_window.h"
703e747e6dSmrg#include "gc.h"
713e747e6dSmrg#include "parse.h"
723e747e6dSmrg#include "menus.h"
733e747e6dSmrg#include "events.h"
743e747e6dSmrg#include "util.h"
753e747e6dSmrg#include "gram.h"
763e747e6dSmrg#include "screen.h"
773e747e6dSmrg#include "parse.h"
783e747e6dSmrg#include "session.h"
79f66df612Smrg
803e747e6dSmrg#include <X11/Xproto.h>
813e747e6dSmrg#include <X11/Xatom.h>
823e747e6dSmrg#include <X11/SM/SMlib.h>
833e747e6dSmrg#include <X11/Xmu/Error.h>
843e747e6dSmrg#include <X11/extensions/sync.h>
853e747e6dSmrg#include <X11/Xlocale.h>
86f66df612Smrg
873e747e6dSmrg#ifdef XPRINT
883e747e6dSmrg#include <X11/extensions/Print.h>
89f66df612Smrg#endif                          /* XPRINT */
90f66df612Smrg
91f66df612Smrg#ifdef HAVE_XRANDR
92f66df612Smrg#include <X11/extensions/Xrandr.h>
93f66df612Smrg#endif
943e747e6dSmrg
95f66df612Smrgstatic void InitVariables(void);
96c2535118Smrg
97f66df612SmrgXtAppContext appContext;        /* Xt application context */
983e747e6dSmrgXtSignalId si;
993e747e6dSmrg
100f66df612SmrgDisplay *dpy = NULL;            /* which display are we talking to */
101f66df612SmrgWindow ResizeWindow;            /* the window we are resizing */
1023e747e6dSmrg
103f66df612Smrgint MultiScreen = TRUE;         /* try for more than one screen? */
1043e747e6dSmrgint NoPrintscreens = False;     /* ignore special handling of print screens? */
105f66df612Smrgint NumScreens;                 /* number of screens in ScreenList */
106f66df612Smrgint HasShape;                   /* server supports shape extension? */
107f66df612Smrg
108f66df612Smrg#ifdef HAVE_XRANDR
109f66df612Smrgint HasXrandr;                  /* server supports Xrandr extension? */
110f66df612Smrgint XrandrEventBase, XrandrErrorBase;
111f66df612Smrg#endif
112f66df612Smrg
1133e747e6dSmrgint ShapeEventBase, ShapeErrorBase;
114f66df612Smrgint HasSync;                    /* server supports SYNC extension? */
1153e747e6dSmrgint SyncEventBase, SyncErrorBase;
116f66df612SmrgScreenInfo **ScreenList;        /* structures for each screen */
117f66df612SmrgScreenInfo *Scr = NULL;         /* the cur and prev screens */
118f66df612Smrgint PreviousScreen;             /* last screen that we were on */
119f66df612Smrgint FirstScreen;                /* TRUE ==> first screen of display */
120f66df612Smrgint message_level = 1;          /* controls error messages */
121f66df612Smrgstatic int RedirectError;       /* TRUE ==> another window manager running */
122f66df612Smrgstatic int TwmErrorHandler(Display *dpy, XErrorEvent *event);   /* for setting RedirectError */
123f66df612Smrgstatic int CatchRedirectError(Display *dpy, XErrorEvent *event);        /* for everything else */
124c2535118Smrgstatic void sigHandler(int);
125f66df612Smrgchar Info[INFO_LINES][INFO_SIZE];       /* info strings to print */
1263e747e6dSmrgint InfoLines;
127c2535118Smrgstatic char *InitFile = NULL;
1283e747e6dSmrg
129f66df612SmrgCursor UpperLeftCursor;         /* upper Left corner cursor */
1303e747e6dSmrgCursor RightButt;
1313e747e6dSmrgCursor MiddleButt;
1323e747e6dSmrgCursor LeftButt;
1333e747e6dSmrg
134f66df612SmrgXContext TwmContext;            /* context for twm windows */
135f66df612SmrgXContext MenuContext;           /* context for all menu windows */
136f66df612SmrgXContext IconManagerContext;    /* context for all window list windows */
137f66df612SmrgXContext ScreenContext;         /* context to get screen data */
138f66df612SmrgXContext ColormapContext;       /* context for colormap operations */
1393e747e6dSmrg
140f66df612SmrgXClassHint NoClass;             /* for applications with no class */
1413e747e6dSmrg
1423e747e6dSmrgXGCValues Gcv;
1433e747e6dSmrg
144f66df612Smrgconst char *Home;               /* the HOME environment variable */
145f66df612Smrgint HomeLen;                    /* length of Home */
146f66df612Smrgint ParseError;                 /* error parsing the .twmrc file */
1473e747e6dSmrg
148f66df612Smrgint HandlingEvents = FALSE;     /* are we handling events yet? */
1493e747e6dSmrg
150f66df612SmrgWindow JunkRoot;                /* junk window */
151f66df612SmrgWindow JunkChild;               /* junk window */
152f66df612Smrgint JunkX;                      /* junk variable */
153f66df612Smrgint JunkY;                      /* junk variable */
1543e747e6dSmrgunsigned int JunkWidth, JunkHeight, JunkBW, JunkDepth, JunkMask;
1553e747e6dSmrg
1563e747e6dSmrgchar *ProgramName;
1573e747e6dSmrgint Argc;
1583e747e6dSmrgchar **Argv;
1593e747e6dSmrg
160f66df612SmrgBool RestartPreviousState = False;      /* try to restart in previous state */
1613e747e6dSmrg
162c2535118Smrgstatic unsigned long black, white;
1633e747e6dSmrg
1643e747e6dSmrgAtom TwmAtoms[11];
1653e747e6dSmrg
166f66df612SmrgBool use_fontset;               /* use XFontSet-related functions or not */
1673e747e6dSmrg
1683e747e6dSmrg/* don't change the order of these strings */
169f66df612Smrgstatic char *atom_names[11] = {
1703e747e6dSmrg    "_MIT_PRIORITY_COLORS",
1713e747e6dSmrg    "WM_CHANGE_STATE",
1723e747e6dSmrg    "WM_STATE",
1733e747e6dSmrg    "WM_COLORMAP_WINDOWS",
1743e747e6dSmrg    "WM_PROTOCOLS",
1753e747e6dSmrg    "WM_TAKE_FOCUS",
1763e747e6dSmrg    "WM_SAVE_YOURSELF",
1773e747e6dSmrg    "WM_DELETE_WINDOW",
1783e747e6dSmrg    "SM_CLIENT_ID",
1793e747e6dSmrg    "WM_CLIENT_LEADER",
1803e747e6dSmrg    "WM_WINDOW_ROLE"
1813e747e6dSmrg};
1823e747e6dSmrg
1833e747e6dSmrg#ifdef XPRINT
1843e747e6dSmrg/* |hasExtension()| and |IsPrintScreen()| have been stolen from
1853e747e6dSmrg * xc/programs/xdpyinfo/xdpyinfo.c */
186f66df612Smrgstatic Bool
187f66df612SmrghasExtension(Display *dpy2, char *extname)
1883e747e6dSmrg{
189f66df612Smrg    int num_extensions, i;
190f66df612Smrg    char **extensions;
191f66df612Smrg
192f66df612Smrg    extensions = XListExtensions(dpy2, &num_extensions);
193f66df612Smrg    for (i = 0; i < num_extensions &&
1943e747e6dSmrg         (strcmp(extensions[i], extname) != 0); i++);
195f66df612Smrg    XFreeExtensionList(extensions);
196f66df612Smrg    return i != num_extensions;
1973e747e6dSmrg}
1983e747e6dSmrg
199f66df612Smrgstatic Bool
200f66df612SmrgIsPrintScreen(Screen *s)
2013e747e6dSmrg{
202f66df612Smrg    Display *dpy2 = XDisplayOfScreen(s);
2033e747e6dSmrg
2043e747e6dSmrg    /* Check whether this is a screen of a print DDX */
205f66df612Smrg    if (hasExtension(dpy2, XP_PRINTNAME)) {
2063e747e6dSmrg        Screen **pscreens;
207f66df612Smrg        int pscrcount;
208f66df612Smrg        int i;
2093e747e6dSmrg
210f66df612Smrg        pscreens = XpQueryScreens(dpy2, &pscrcount);
211f66df612Smrg        for (i = 0; (i < pscrcount) && pscreens; i++) {
2123e747e6dSmrg            if (s == pscreens[i]) {
2133e747e6dSmrg                return True;
2143e747e6dSmrg            }
2153e747e6dSmrg        }
216ffd25bcaSmrg        XFree(pscreens);
2173e747e6dSmrg    }
2183e747e6dSmrg    return False;
2193e747e6dSmrg}
220f66df612Smrg#endif                          /* XPRINT */
221f66df612Smrg
222f66df612Smrgstatic void
223f66df612Smrgusage(void)
224f66df612Smrg{
225f66df612Smrg    fprintf(stderr, "usage:  %s [-display dpy] [-f file] [-s] [-q] [-v] [-V]"
226f66df612Smrg#ifdef XPRINT
227f66df612Smrg            " [-noprint]"
228f66df612Smrg#endif                          /* XPRINT */
229f66df612Smrg            " [-clientId id] [-restore file]\n", ProgramName);
230f66df612Smrg    exit(EXIT_FAILURE);
231f66df612Smrg}
232f66df612Smrg
233f66df612Smrgstatic Bool
234f66df612Smrgbrief_opt(const char *param, const char *option)
235f66df612Smrg{
236f66df612Smrg    size_t have = strlen(++param);
237f66df612Smrg    size_t want = strlen(option);
238f66df612Smrg    Bool result = False;
239f66df612Smrg
240f66df612Smrg    if (have <= want) {
241f66df612Smrg        if (!strncmp(param, option, have))
242f66df612Smrg            result = True;
243f66df612Smrg    }
244f66df612Smrg    return result;
245f66df612Smrg}
2463e747e6dSmrg
2473e747e6dSmrg/***********************************************************************
2483e747e6dSmrg *
2493e747e6dSmrg *  Procedure:
250f66df612Smrg *      main - start of twm
2513e747e6dSmrg *
2523e747e6dSmrg ***********************************************************************
2533e747e6dSmrg */
2543e747e6dSmrg
2553e747e6dSmrgint
2563e747e6dSmrgmain(int argc, char *argv[])
2573e747e6dSmrg{
2583e747e6dSmrg    Window root, parent, *children;
2593e747e6dSmrg    unsigned int nchildren;
2603e747e6dSmrg    int i, j;
2613e747e6dSmrg    char *display_name = NULL;
262f66df612Smrg    unsigned long valuemask;    /* mask for create windows */
263f66df612Smrg    XSetWindowAttributes attributes;    /* attributes for create windows */
2643e747e6dSmrg    int numManaged, firstscrn, lastscrn, scrnum;
2653e747e6dSmrg    int zero = 0;
2663e747e6dSmrg    char *restore_filename = NULL;
2673e747e6dSmrg    char *client_id = NULL;
2683e747e6dSmrg    char *loc;
2693e747e6dSmrg
2703e747e6dSmrg    ProgramName = argv[0];
2713e747e6dSmrg    Argc = argc;
2723e747e6dSmrg    Argv = argv;
2733e747e6dSmrg
2743e747e6dSmrg    for (i = 1; i < argc; i++) {
275f66df612Smrg        if (argv[i][0] == '-') {
276f66df612Smrg            switch (argv[i][1]) {
277f66df612Smrg            case 'V':
278f66df612Smrg                printf("%s %s\n", APP_NAME, APP_VERSION);
279f66df612Smrg                exit(EXIT_SUCCESS);
280f66df612Smrg            case 'd':          /* -display dpy */
281f66df612Smrg                if (!brief_opt(argv[i], "display"))
282f66df612Smrg                    usage();
283f66df612Smrg                if (++i >= argc)
284f66df612Smrg                    usage();
285f66df612Smrg                display_name = argv[i];
286f66df612Smrg                continue;
287f66df612Smrg            case 's':          /* -single */
288f66df612Smrg                if (!brief_opt(argv[i], "single"))
289f66df612Smrg                    usage();
290f66df612Smrg                MultiScreen = FALSE;
291f66df612Smrg                continue;
2923e747e6dSmrg#ifdef XPRINT
293f66df612Smrg            case 'n':          /* -noprint */
294f66df612Smrg                if (!brief_opt(argv[i], "noprint"))
295f66df612Smrg                    usage();
296f66df612Smrg                NoPrintscreens = True;
297f66df612Smrg                continue;
298f66df612Smrg#endif                          /* XPRINT */
299f66df612Smrg            case 'f':          /* -file twmrcfilename */
300f66df612Smrg                if (!brief_opt(argv[i], "file"))
301f66df612Smrg                    usage();
302f66df612Smrg                if (++i >= argc)
303f66df612Smrg                    usage();
304f66df612Smrg                InitFile = argv[i];
305f66df612Smrg                continue;
306f66df612Smrg            case 'v':          /* -verbose */
307f66df612Smrg                if (!brief_opt(argv[i], "verbose"))
308f66df612Smrg                    usage();
309f66df612Smrg                message_level++;
310f66df612Smrg                continue;
311f66df612Smrg            case 'c':          /* -clientId */
312f66df612Smrg                if (!brief_opt(argv[i], "clientId"))
313f66df612Smrg                    usage();
314f66df612Smrg                if (++i >= argc)
315f66df612Smrg                    usage();
316f66df612Smrg                client_id = argv[i];
317f66df612Smrg                continue;
318f66df612Smrg            case 'r':          /* -restore */
319f66df612Smrg                if (!brief_opt(argv[i], "restore"))
320f66df612Smrg                    usage();
321f66df612Smrg                if (++i >= argc)
322f66df612Smrg                    usage();
323f66df612Smrg                restore_filename = argv[i];
324f66df612Smrg                continue;
325f66df612Smrg            case 'q':          /* -quiet */
326f66df612Smrg                if (!brief_opt(argv[i], "quiet"))
327f66df612Smrg                    usage();
328f66df612Smrg                --message_level;
329f66df612Smrg                continue;
330f66df612Smrg            }
331f66df612Smrg        }
332f66df612Smrg        usage();
3333e747e6dSmrg    }
3343e747e6dSmrg
3353e747e6dSmrg    loc = setlocale(LC_ALL, "");
3363e747e6dSmrg    if (!loc || !strcmp(loc, "C") || !strcmp(loc, "POSIX") ||
337f66df612Smrg        !XSupportsLocale()) {
338f66df612Smrg        use_fontset = False;
339f66df612Smrg    }
340f66df612Smrg    else {
341f66df612Smrg        use_fontset = True;
3423e747e6dSmrg    }
3433e747e6dSmrg
3443e747e6dSmrg#define newhandler(sig) \
3453e747e6dSmrg    if (signal (sig, SIG_IGN) != SIG_IGN) (void) signal (sig, sigHandler)
3463e747e6dSmrg
347f66df612Smrg    newhandler(SIGINT);
348f66df612Smrg    newhandler(SIGHUP);
349f66df612Smrg    newhandler(SIGQUIT);
350f66df612Smrg    newhandler(SIGTERM);
3513e747e6dSmrg
3523e747e6dSmrg#undef newhandler
3533e747e6dSmrg
3543e747e6dSmrg    Home = getenv("HOME");
3553e747e6dSmrg    if (Home != NULL) {
356f66df612Smrg        char *temp_p;
3573e747e6dSmrg
358f66df612Smrg        /*
359f66df612Smrg         * Make a copy of Home because the string returned by getenv() can be
360f66df612Smrg         * overwritten by some POSIX.1 and ANSI-C implementations of getenv()
361f66df612Smrg         * when further calls to getenv() are made
362f66df612Smrg         */
3633e747e6dSmrg
364f66df612Smrg        temp_p = strdup(Home);
365f66df612Smrg        Home = temp_p;
3663e747e6dSmrg    }
3673e747e6dSmrg
3683e747e6dSmrg    if (Home == NULL)
369f66df612Smrg        Home = "./";
3703e747e6dSmrg
371f66df612Smrg    HomeLen = (int) strlen(Home);
3723e747e6dSmrg
3733e747e6dSmrg    NoClass.res_name = NoName;
3743e747e6dSmrg    NoClass.res_class = NoName;
3753e747e6dSmrg
376f66df612Smrg    XtToolkitInitialize();
377f66df612Smrg    appContext = XtCreateApplicationContext();
3783e747e6dSmrg
3793e747e6dSmrg    si = XtAppAddSignal(appContext, Done, NULL);
380ffd25bcaSmrg
381f66df612Smrg    if (!(dpy = XtOpenDisplay(appContext, display_name, "twm", "twm",
382f66df612Smrg                              NULL, 0, &zero, NULL))) {
383f66df612Smrg        twmError("unable to open display \"%s\"", XDisplayName(display_name));
3843e747e6dSmrg    }
3853e747e6dSmrg
3863e747e6dSmrg    if (fcntl(ConnectionNumber(dpy), F_SETFD, 1) == -1) {
387f66df612Smrg        twmError("unable to mark display connection as close-on-exec");
3883e747e6dSmrg    }
3893e747e6dSmrg
3903e747e6dSmrg    if (restore_filename)
391f66df612Smrg        ReadWinConfigFile(restore_filename);
3923e747e6dSmrg
393f66df612Smrg    HasShape = XShapeQueryExtension(dpy, &ShapeEventBase, &ShapeErrorBase);
394f66df612Smrg    HasSync = XSyncQueryExtension(dpy, &SyncEventBase, &SyncErrorBase);
395f66df612Smrg#ifdef HAVE_XRANDR
396f66df612Smrg    HasXrandr = XRRQueryExtension(dpy, &XrandrEventBase, &XrandrErrorBase);
397f66df612Smrg#endif
3983e747e6dSmrg    TwmContext = XUniqueContext();
3993e747e6dSmrg    MenuContext = XUniqueContext();
4003e747e6dSmrg    IconManagerContext = XUniqueContext();
4013e747e6dSmrg    ScreenContext = XUniqueContext();
4023e747e6dSmrg    ColormapContext = XUniqueContext();
4033e747e6dSmrg
4043e747e6dSmrg    (void) XInternAtoms(dpy, atom_names, sizeof TwmAtoms / sizeof TwmAtoms[0],
405f66df612Smrg                        False, TwmAtoms);
4063e747e6dSmrg
4073e747e6dSmrg    /* Set up the per-screen global information. */
4083e747e6dSmrg
4093e747e6dSmrg    NumScreens = ScreenCount(dpy);
4103e747e6dSmrg
411f66df612Smrg    if (MultiScreen) {
412f66df612Smrg        firstscrn = 0;
413f66df612Smrg        lastscrn = NumScreens - 1;
4143e747e6dSmrg    }
415f66df612Smrg    else {
416f66df612Smrg        firstscrn = lastscrn = DefaultScreen(dpy);
4173e747e6dSmrg    }
4183e747e6dSmrg
4193e747e6dSmrg    InfoLines = 0;
4203e747e6dSmrg
4213e747e6dSmrg    /* for simplicity, always allocate NumScreens ScreenInfo struct pointers */
422f66df612Smrg    ScreenList = calloc((size_t) NumScreens, sizeof(ScreenInfo *));
423f66df612Smrg    if (ScreenList == NULL) {
424f66df612Smrg        twmError("Unable to allocate memory for screen list, exiting");
4253e747e6dSmrg    }
4263e747e6dSmrg    numManaged = 0;
4273e747e6dSmrg    PreviousScreen = DefaultScreen(dpy);
4283e747e6dSmrg    FirstScreen = TRUE;
429f66df612Smrg    for (scrnum = firstscrn; scrnum <= lastscrn; scrnum++) {
4303e747e6dSmrg#ifdef XPRINT
4313e747e6dSmrg        /* Ignore print screens to avoid that users accidentally warp on a
4323e747e6dSmrg         * print screen (which are not visible on video displays) */
433f66df612Smrg        if ((!NoPrintscreens) && IsPrintScreen(XScreenOfDisplay(dpy, scrnum))) {
434f66df612Smrg            twmWarning("skipping print screen %d", scrnum);
4353e747e6dSmrg            continue;
4363e747e6dSmrg        }
437f66df612Smrg#endif                          /* XPRINT */
4383e747e6dSmrg
4393e747e6dSmrg        /* Make sure property priority colors is empty */
440f66df612Smrg        XChangeProperty(dpy, RootWindow(dpy, scrnum), _XA_MIT_PRIORITY_COLORS,
441f66df612Smrg                        XA_CARDINAL, 32, PropModeReplace, NULL, 0);
442f66df612Smrg        RedirectError = FALSE;
443f66df612Smrg        XSetErrorHandler(CatchRedirectError);
444f66df612Smrg        XSelectInput(dpy, RootWindow(dpy, scrnum),
445f66df612Smrg                     ColormapChangeMask | EnterWindowMask | PropertyChangeMask |
446f66df612Smrg                     SubstructureRedirectMask | KeyPressMask |
447f66df612Smrg                     ButtonPressMask | ButtonReleaseMask);
448f66df612Smrg        XSync(dpy, 0);
449f66df612Smrg        XSetErrorHandler(TwmErrorHandler);
450f66df612Smrg
451f66df612Smrg        if (RedirectError) {
452f66df612Smrg            if (MultiScreen && NumScreens > 0) {
453f66df612Smrg                twmWarning("another window manager is already running."
454f66df612Smrg                           " on screen %d?\n", scrnum);
455f66df612Smrg            }
456f66df612Smrg            else {
457f66df612Smrg                twmWarning("another window manager is already running.");
458f66df612Smrg            }
459f66df612Smrg            continue;
460f66df612Smrg        }
461f66df612Smrg
462f66df612Smrg        numManaged++;
463f66df612Smrg
464f66df612Smrg        /* Note:  ScreenInfo struct is calloc'ed to initialize to zero. */
465f66df612Smrg        Scr = ScreenList[scrnum] = calloc(1, sizeof(ScreenInfo));
466f66df612Smrg        if (Scr == NULL) {
467f66df612Smrg            twmWarning
468f66df612Smrg                ("unable to allocate memory for ScreenInfo structure for screen %d.",
469f66df612Smrg                 scrnum);
470f66df612Smrg            continue;
471f66df612Smrg        }
472f66df612Smrg
473f66df612Smrg        /* initialize list pointers, remember to put an initialization
474f66df612Smrg         * in InitVariables also
475f66df612Smrg         */
476f66df612Smrg        Scr->BorderColorL = NULL;
477f66df612Smrg        Scr->IconBorderColorL = NULL;
478f66df612Smrg        Scr->BorderTileForegroundL = NULL;
479f66df612Smrg        Scr->BorderTileBackgroundL = NULL;
480f66df612Smrg        Scr->TitleForegroundL = NULL;
481f66df612Smrg        Scr->TitleBackgroundL = NULL;
482f66df612Smrg        Scr->IconForegroundL = NULL;
483f66df612Smrg        Scr->IconBackgroundL = NULL;
484f66df612Smrg        Scr->NoTitle = NULL;
485f66df612Smrg        Scr->MakeTitle = NULL;
486f66df612Smrg        Scr->AutoRaise = NULL;
487f66df612Smrg        Scr->IconNames = NULL;
488f66df612Smrg        Scr->NoHighlight = NULL;
489f66df612Smrg        Scr->NoStackModeL = NULL;
490f66df612Smrg        Scr->NoTitleHighlight = NULL;
491f66df612Smrg        Scr->DontIconify = NULL;
492f66df612Smrg        Scr->IconMgrNoShow = NULL;
493f66df612Smrg        Scr->IconMgrShow = NULL;
494f66df612Smrg        Scr->IconifyByUn = NULL;
495f66df612Smrg        Scr->IconManagerFL = NULL;
496f66df612Smrg        Scr->IconManagerBL = NULL;
497f66df612Smrg        Scr->IconMgrs = NULL;
498f66df612Smrg        Scr->StartIconified = NULL;
499f66df612Smrg        Scr->SqueezeTitleL = NULL;
500f66df612Smrg        Scr->DontSqueezeTitleL = NULL;
501f66df612Smrg        Scr->WindowRingL = NULL;
502f66df612Smrg        Scr->WarpCursorL = NULL;
503f66df612Smrg        /* remember to put an initialization in InitVariables also
504f66df612Smrg         */
505f66df612Smrg
506f66df612Smrg        Scr->screen = scrnum;
507f66df612Smrg        Scr->d_depth = DefaultDepth(dpy, scrnum);
508f66df612Smrg        Scr->d_visual = DefaultVisual(dpy, scrnum);
509f66df612Smrg        Scr->Root = RootWindow(dpy, scrnum);
510f66df612Smrg        XSaveContext(dpy, Scr->Root, ScreenContext, (XPointer) Scr);
511f66df612Smrg
512f66df612Smrg        Scr->TwmRoot.cmaps.number_cwins = 1;
513f66df612Smrg        Scr->TwmRoot.cmaps.cwins = malloc(sizeof(ColormapWindow *));
514f66df612Smrg        Scr->TwmRoot.cmaps.cwins[0] =
515f66df612Smrg            CreateColormapWindow(Scr->Root, True, False);
516f66df612Smrg        Scr->TwmRoot.cmaps.cwins[0]->visibility = VisibilityPartiallyObscured;
517f66df612Smrg
518f66df612Smrg        Scr->cmapInfo.cmaps = NULL;
519f66df612Smrg        Scr->cmapInfo.maxCmaps =
520f66df612Smrg            MaxCmapsOfScreen(ScreenOfDisplay(dpy, Scr->screen));
521f66df612Smrg        Scr->cmapInfo.root_pushes = 0;
522f66df612Smrg        InstallWindowColormaps(0, &Scr->TwmRoot);
523f66df612Smrg
524f66df612Smrg        Scr->StdCmapInfo.head = Scr->StdCmapInfo.tail =
525f66df612Smrg            Scr->StdCmapInfo.mru = NULL;
526f66df612Smrg        Scr->StdCmapInfo.mruindex = 0;
527f66df612Smrg        LocateStandardColormaps();
528f66df612Smrg
529f66df612Smrg        Scr->TBInfo.nleft = Scr->TBInfo.nright = 0;
530f66df612Smrg        Scr->TBInfo.head = NULL;
531f66df612Smrg        Scr->TBInfo.border = 1;
532f66df612Smrg        Scr->TBInfo.width = 0;
533f66df612Smrg        Scr->TBInfo.leftx = 0;
534f66df612Smrg        Scr->TBInfo.titlex = 0;
535f66df612Smrg
536f66df612Smrg        Scr->MyDisplayWidth = DisplayWidth(dpy, scrnum);
537f66df612Smrg        Scr->MyDisplayHeight = DisplayHeight(dpy, scrnum);
538f66df612Smrg        Scr->MaxWindowWidth = 32767 - Scr->MyDisplayWidth;
539f66df612Smrg        Scr->MaxWindowHeight = 32767 - Scr->MyDisplayHeight;
540f66df612Smrg
541f66df612Smrg        Scr->XORvalue = (((unsigned long) 1) << Scr->d_depth) - 1;
542f66df612Smrg
543f66df612Smrg        if (DisplayCells(dpy, scrnum) < 3)
544f66df612Smrg            Scr->Monochrome = MONOCHROME;
545f66df612Smrg        else if (DefaultVisual(dpy, scrnum)->class == GrayScale)
546f66df612Smrg            Scr->Monochrome = GRAYSCALE;
547f66df612Smrg        else
548f66df612Smrg            Scr->Monochrome = COLOR;
549f66df612Smrg
550f66df612Smrg        /* setup default colors */
551f66df612Smrg        Scr->FirstTime = TRUE;
552f66df612Smrg        GetColor(Scr->Monochrome, &black, "black");
553f66df612Smrg        Scr->Black = black;
554f66df612Smrg        GetColor(Scr->Monochrome, &white, "white");
555f66df612Smrg        Scr->White = white;
556f66df612Smrg
557f66df612Smrg        if (FirstScreen) {
558f66df612Smrg            SetFocus((TwmWindow *) NULL, CurrentTime);
559f66df612Smrg
560f66df612Smrg            /* define cursors */
561f66df612Smrg
562f66df612Smrg            NewFontCursor(&UpperLeftCursor, "top_left_corner");
563f66df612Smrg            NewFontCursor(&RightButt, "rightbutton");
564f66df612Smrg            NewFontCursor(&LeftButt, "leftbutton");
565f66df612Smrg            NewFontCursor(&MiddleButt, "middlebutton");
566f66df612Smrg        }
567f66df612Smrg
568f66df612Smrg        Scr->iconmgr.x = 0;
569f66df612Smrg        Scr->iconmgr.y = 0;
570f66df612Smrg        Scr->iconmgr.width = 150;
571f66df612Smrg        Scr->iconmgr.height = 5;
572f66df612Smrg        Scr->iconmgr.next = NULL;
573f66df612Smrg        Scr->iconmgr.prev = NULL;
574f66df612Smrg        Scr->iconmgr.lasti = &(Scr->iconmgr);
575f66df612Smrg        Scr->iconmgr.first = NULL;
576f66df612Smrg        Scr->iconmgr.last = NULL;
577f66df612Smrg        Scr->iconmgr.active = NULL;
578f66df612Smrg        Scr->iconmgr.scr = Scr;
579f66df612Smrg        Scr->iconmgr.columns = 1;
580f66df612Smrg        Scr->iconmgr.count = 0;
581f66df612Smrg        Scr->iconmgr.name = "TWM";
582f66df612Smrg        Scr->iconmgr.icon_name = "Icons";
583f66df612Smrg
584f66df612Smrg        Scr->IconDirectory = NULL;
585f66df612Smrg
586f66df612Smrg        Scr->siconifyPm = None;
587f66df612Smrg        Scr->pullPm = None;
588f66df612Smrg        Scr->hilitePm = None;
589f66df612Smrg        Scr->tbpm.xlogo = None;
590f66df612Smrg        Scr->tbpm.resize = None;
591f66df612Smrg        Scr->tbpm.question = None;
592f66df612Smrg        Scr->tbpm.menu = None;
593f66df612Smrg        Scr->tbpm.delete = None;
594f66df612Smrg
595f66df612Smrg        InitVariables();
596f66df612Smrg        InitMenus();
597f66df612Smrg
598f66df612Smrg        /* Parse it once for each screen. */
599f66df612Smrg        ParseTwmrc(InitFile);
600f66df612Smrg        assign_var_savecolor(); /* storing pixels for twmrc "entities" */
601f66df612Smrg        if (Scr->SqueezeTitle == -1)
602f66df612Smrg            Scr->SqueezeTitle = FALSE;
603f66df612Smrg        if (!Scr->HaveFonts)
604f66df612Smrg            CreateFonts();
605f66df612Smrg        CreateGCs();
606f66df612Smrg        MakeMenus();
607f66df612Smrg
608f66df612Smrg        Scr->TitleBarFont.y += Scr->FramePadding;
609f66df612Smrg        Scr->TitleHeight = Scr->TitleBarFont.height + Scr->FramePadding * 2;
610f66df612Smrg        /* make title height be odd so buttons look nice and centered */
611f66df612Smrg        if (!(Scr->TitleHeight & 1))
612f66df612Smrg            Scr->TitleHeight++;
613f66df612Smrg
614f66df612Smrg        InitTitlebarButtons();  /* menus are now loaded! */
615f66df612Smrg
616f66df612Smrg        XGrabServer(dpy);
617f66df612Smrg        XSync(dpy, 0);
618f66df612Smrg
619f66df612Smrg        JunkX = 0;
620f66df612Smrg        JunkY = 0;
621f66df612Smrg
622f66df612Smrg        XQueryTree(dpy, Scr->Root, &root, &parent, &children, &nchildren);
623f66df612Smrg        CreateIconManagers();
624f66df612Smrg        if (!Scr->NoIconManagers)
625f66df612Smrg            Scr->iconmgr.twm_win->icon = TRUE;
626f66df612Smrg
627f66df612Smrg        /*
628f66df612Smrg         * weed out icon windows
629f66df612Smrg         */
630f66df612Smrg        for (i = 0; (unsigned) i < nchildren; i++) {
631f66df612Smrg            if (children[i]) {
632f66df612Smrg                XWMHints *wmhintsp = XGetWMHints(dpy, children[i]);
633f66df612Smrg
634f66df612Smrg                if (wmhintsp) {
635f66df612Smrg                    if (wmhintsp->flags & IconWindowHint) {
636f66df612Smrg                        for (j = 0; (unsigned) j < nchildren; j++) {
637f66df612Smrg                            if (children[j] == wmhintsp->icon_window) {
638f66df612Smrg                                children[j] = None;
639f66df612Smrg                                break;
640f66df612Smrg                            }
641f66df612Smrg                        }
642f66df612Smrg                    }
643f66df612Smrg                    XFree(wmhintsp);
644f66df612Smrg                }
645f66df612Smrg            }
646f66df612Smrg        }
647f66df612Smrg
648f66df612Smrg        /*
649f66df612Smrg         * map all of the non-override windows
650f66df612Smrg         */
651f66df612Smrg        for (i = 0; (unsigned) i < nchildren; i++) {
652f66df612Smrg            if (children[i] && MappedNotOverride(children[i])) {
653f66df612Smrg                XUnmapWindow(dpy, children[i]);
654f66df612Smrg                SimulateMapRequest(children[i]);
655f66df612Smrg            }
656f66df612Smrg        }
657f66df612Smrg
658f66df612Smrg        if (Scr->ShowIconManager && !Scr->NoIconManagers) {
659f66df612Smrg            Scr->iconmgr.twm_win->icon = FALSE;
660f66df612Smrg            if (Scr->iconmgr.count) {
661f66df612Smrg                SetMapStateProp(Scr->iconmgr.twm_win, NormalState);
662f66df612Smrg                XMapWindow(dpy, Scr->iconmgr.w);
663f66df612Smrg                XMapWindow(dpy, Scr->iconmgr.twm_win->frame);
664f66df612Smrg            }
665f66df612Smrg        }
666f66df612Smrg
667f66df612Smrg        attributes.border_pixel = Scr->DefaultC.fore;
668f66df612Smrg        attributes.background_pixel = Scr->DefaultC.back;
669f66df612Smrg        attributes.event_mask = (ExposureMask | ButtonPressMask |
670f66df612Smrg                                 KeyPressMask | ButtonReleaseMask);
671f66df612Smrg        attributes.backing_store = NotUseful;
672f66df612Smrg        attributes.cursor = XCreateFontCursor(dpy, XC_hand2);
673f66df612Smrg        valuemask = (CWBorderPixel | CWBackPixel | CWEventMask |
674f66df612Smrg                     CWBackingStore | CWCursor);
675f66df612Smrg        Scr->InfoWindow = XCreateWindow(dpy, Scr->Root, 0, 0,
676f66df612Smrg                                        (unsigned int) 5, (unsigned int) 5,
677f66df612Smrg                                        (unsigned int) BW, 0,
678f66df612Smrg                                        (unsigned int) CopyFromParent,
679f66df612Smrg                                        (Visual *) CopyFromParent,
680f66df612Smrg                                        valuemask, &attributes);
681f66df612Smrg
682f66df612Smrg        Scr->SizeStringWidth = MyFont_TextWidth(&Scr->SizeFont,
683f66df612Smrg                                                " 8888 x 8888 ", 13);
684f66df612Smrg        valuemask = (CWBorderPixel | CWBackPixel | CWBitGravity);
685f66df612Smrg        attributes.bit_gravity = NorthWestGravity;
686f66df612Smrg        Scr->SizeWindow = XCreateWindow(dpy, Scr->Root, 0, 0,
687f66df612Smrg                                        (unsigned int) Scr->SizeStringWidth,
688f66df612Smrg                                        (unsigned int) (Scr->SizeFont.height +
689f66df612Smrg                                                        SIZE_VINDENT * 2),
690f66df612Smrg                                        (unsigned int) BW, 0,
691f66df612Smrg                                        (unsigned int) CopyFromParent,
692f66df612Smrg                                        (Visual *) CopyFromParent,
693f66df612Smrg                                        valuemask, &attributes);
694f66df612Smrg
695f66df612Smrg        XUngrabServer(dpy);
696f66df612Smrg
697f66df612Smrg        FirstScreen = FALSE;
698f66df612Smrg        Scr->FirstTime = FALSE;
699f66df612Smrg    }                           /* for */
7003e747e6dSmrg
7013e747e6dSmrg    if (numManaged == 0) {
702f66df612Smrg        if (MultiScreen && NumScreens > 0) {
703f66df612Smrg            twmError("unable to find any unmanaged %sscreens.\n",
704f66df612Smrg                     NoPrintscreens ? "" : "video ");
705f66df612Smrg        }
706f66df612Smrg        exit(EXIT_FAILURE);
7073e747e6dSmrg    }
7083e747e6dSmrg
709f66df612Smrg    (void) ConnectToSessionManager(client_id);
7103e747e6dSmrg
7113e747e6dSmrg    RestartPreviousState = False;
7123e747e6dSmrg    HandlingEvents = TRUE;
7133e747e6dSmrg    InitEvents();
7143e747e6dSmrg    HandleEvents();
715f66df612Smrg    exit(EXIT_SUCCESS);
7163e747e6dSmrg}
7173e747e6dSmrg
7183e747e6dSmrg/**
7193e747e6dSmrg * initialize twm variables
7203e747e6dSmrg */
721c2535118Smrgstatic void
722c2535118SmrgInitVariables(void)
7233e747e6dSmrg{
7243e747e6dSmrg    FreeList(&Scr->BorderColorL);
7253e747e6dSmrg    FreeList(&Scr->IconBorderColorL);
7263e747e6dSmrg    FreeList(&Scr->BorderTileForegroundL);
7273e747e6dSmrg    FreeList(&Scr->BorderTileBackgroundL);
7283e747e6dSmrg    FreeList(&Scr->TitleForegroundL);
7293e747e6dSmrg    FreeList(&Scr->TitleBackgroundL);
7303e747e6dSmrg    FreeList(&Scr->IconForegroundL);
7313e747e6dSmrg    FreeList(&Scr->IconBackgroundL);
7323e747e6dSmrg    FreeList(&Scr->IconManagerFL);
7333e747e6dSmrg    FreeList(&Scr->IconManagerBL);
7343e747e6dSmrg    FreeList(&Scr->IconMgrs);
7353e747e6dSmrg    FreeList(&Scr->NoTitle);
7363e747e6dSmrg    FreeList(&Scr->MakeTitle);
7373e747e6dSmrg    FreeList(&Scr->AutoRaise);
7383e747e6dSmrg    FreeList(&Scr->IconNames);
7393e747e6dSmrg    FreeList(&Scr->NoHighlight);
7403e747e6dSmrg    FreeList(&Scr->NoStackModeL);
7413e747e6dSmrg    FreeList(&Scr->NoTitleHighlight);
7423e747e6dSmrg    FreeList(&Scr->DontIconify);
7433e747e6dSmrg    FreeList(&Scr->IconMgrNoShow);
7443e747e6dSmrg    FreeList(&Scr->IconMgrShow);
7453e747e6dSmrg    FreeList(&Scr->IconifyByUn);
7463e747e6dSmrg    FreeList(&Scr->StartIconified);
7473e747e6dSmrg    FreeList(&Scr->IconManagerHighlightL);
7483e747e6dSmrg    FreeList(&Scr->SqueezeTitleL);
7493e747e6dSmrg    FreeList(&Scr->DontSqueezeTitleL);
7503e747e6dSmrg    FreeList(&Scr->WindowRingL);
7513e747e6dSmrg    FreeList(&Scr->WarpCursorL);
7523e747e6dSmrg
7533e747e6dSmrg    NewFontCursor(&Scr->FrameCursor, "top_left_arrow");
7543e747e6dSmrg    NewFontCursor(&Scr->TitleCursor, "top_left_arrow");
7553e747e6dSmrg    NewFontCursor(&Scr->IconCursor, "top_left_arrow");
7563e747e6dSmrg    NewFontCursor(&Scr->IconMgrCursor, "top_left_arrow");
7573e747e6dSmrg    NewFontCursor(&Scr->MoveCursor, "fleur");
7583e747e6dSmrg    NewFontCursor(&Scr->ResizeCursor, "fleur");
7593e747e6dSmrg    NewFontCursor(&Scr->MenuCursor, "sb_left_arrow");
7603e747e6dSmrg    NewFontCursor(&Scr->ButtonCursor, "hand2");
7613e747e6dSmrg    NewFontCursor(&Scr->WaitCursor, "watch");
7623e747e6dSmrg    NewFontCursor(&Scr->SelectCursor, "dot");
7633e747e6dSmrg    NewFontCursor(&Scr->DestroyCursor, "pirate");
7643e747e6dSmrg
7653e747e6dSmrg    Scr->Ring = NULL;
7663e747e6dSmrg    Scr->RingLeader = NULL;
7673e747e6dSmrg
7683e747e6dSmrg    Scr->DefaultC.fore = black;
7693e747e6dSmrg    Scr->DefaultC.back = white;
7703e747e6dSmrg    Scr->BorderColor = black;
7713e747e6dSmrg    Scr->BorderTileC.fore = black;
7723e747e6dSmrg    Scr->BorderTileC.back = white;
7733e747e6dSmrg    Scr->TitleC.fore = black;
7743e747e6dSmrg    Scr->TitleC.back = white;
7753e747e6dSmrg    Scr->MenuC.fore = black;
7763e747e6dSmrg    Scr->MenuC.back = white;
7773e747e6dSmrg    Scr->MenuTitleC.fore = black;
7783e747e6dSmrg    Scr->MenuTitleC.back = white;
7793e747e6dSmrg    Scr->MenuShadowColor = black;
7803e747e6dSmrg    Scr->MenuBorderColor = black;
7813e747e6dSmrg    Scr->IconC.fore = black;
7823e747e6dSmrg    Scr->IconC.back = white;
7833e747e6dSmrg    Scr->IconBorderColor = black;
7843e747e6dSmrg    Scr->PointerForeground.pixel = black;
7853e747e6dSmrg    XQueryColor(dpy, Scr->TwmRoot.cmaps.cwins[0]->colormap->c,
786f66df612Smrg                &Scr->PointerForeground);
7873e747e6dSmrg    Scr->PointerBackground.pixel = white;
7883e747e6dSmrg    XQueryColor(dpy, Scr->TwmRoot.cmaps.cwins[0]->colormap->c,
789f66df612Smrg                &Scr->PointerBackground);
7903e747e6dSmrg    Scr->IconManagerC.fore = black;
7913e747e6dSmrg    Scr->IconManagerC.back = white;
7923e747e6dSmrg    Scr->IconManagerHighlight = black;
7933e747e6dSmrg
794f66df612Smrg    Scr->FramePadding = 2;      /* values that look "nice" on */
795f66df612Smrg    Scr->TitlePadding = 8;      /* 75 and 100dpi displays */
7963e747e6dSmrg    Scr->ButtonIndent = 1;
7973e747e6dSmrg    Scr->SizeStringOffset = 0;
7983e747e6dSmrg    Scr->BorderWidth = BW;
7993e747e6dSmrg    Scr->IconBorderWidth = BW;
8003e747e6dSmrg    Scr->MenuBorderWidth = BW;
8013e747e6dSmrg    Scr->UnknownWidth = 0;
8023e747e6dSmrg    Scr->UnknownHeight = 0;
8033e747e6dSmrg    Scr->NumAutoRaises = 0;
8043e747e6dSmrg    Scr->NoDefaults = FALSE;
8053e747e6dSmrg    Scr->UsePPosition = PPOS_OFF;
8063e747e6dSmrg    Scr->FocusRoot = TRUE;
8073e747e6dSmrg    Scr->Focus = NULL;
8083e747e6dSmrg    Scr->WarpCursor = FALSE;
8093e747e6dSmrg    Scr->ForceIcon = FALSE;
8103e747e6dSmrg    Scr->NoGrabServer = FALSE;
8113e747e6dSmrg    Scr->NoRaiseMove = FALSE;
8123e747e6dSmrg    Scr->NoRaiseResize = FALSE;
8133e747e6dSmrg    Scr->NoRaiseDeicon = FALSE;
8143e747e6dSmrg    Scr->NoRaiseWarp = FALSE;
8153e747e6dSmrg    Scr->DontMoveOff = FALSE;
8163e747e6dSmrg    Scr->DoZoom = FALSE;
8173e747e6dSmrg    Scr->TitleFocus = TRUE;
8183e747e6dSmrg    Scr->NoTitlebar = FALSE;
8193e747e6dSmrg    Scr->DecorateTransients = FALSE;
8203e747e6dSmrg    Scr->IconifyByUnmapping = FALSE;
8213e747e6dSmrg    Scr->ShowIconManager = FALSE;
822f66df612Smrg    Scr->IconManagerDontShow = FALSE;
8233e747e6dSmrg    Scr->BackingStore = TRUE;
8243e747e6dSmrg    Scr->SaveUnder = TRUE;
8253e747e6dSmrg    Scr->RandomPlacement = FALSE;
8263e747e6dSmrg    Scr->OpaqueMove = FALSE;
8273e747e6dSmrg    Scr->Highlight = TRUE;
8283e747e6dSmrg    Scr->StackMode = TRUE;
8293e747e6dSmrg    Scr->TitleHighlight = TRUE;
830f66df612Smrg    Scr->MoveDelta = 1;         /* so that f.deltastop will work */
8313e747e6dSmrg    Scr->ZoomCount = 8;
8323e747e6dSmrg    Scr->SortIconMgr = FALSE;
8333e747e6dSmrg    Scr->Shadow = TRUE;
8343e747e6dSmrg    Scr->InterpolateMenuColors = FALSE;
8353e747e6dSmrg    Scr->NoIconManagers = FALSE;
8363e747e6dSmrg    Scr->ClientBorderWidth = FALSE;
8373e747e6dSmrg    Scr->SqueezeTitle = -1;
8383e747e6dSmrg    Scr->FirstRegion = NULL;
8393e747e6dSmrg    Scr->LastRegion = NULL;
8403e747e6dSmrg    Scr->FirstTime = TRUE;
841f66df612Smrg    Scr->HaveFonts = FALSE;     /* i.e. not loaded yet */
8423e747e6dSmrg    Scr->CaseSensitive = TRUE;
8433e747e6dSmrg    Scr->WarpUnmapped = FALSE;
8443e747e6dSmrg
8453e747e6dSmrg    /* setup default fonts; overridden by defaults from system.twmrc */
8463e747e6dSmrg#define DEFAULT_NICE_FONT "variable"
8473e747e6dSmrg#define DEFAULT_FAST_FONT "fixed"
8483e747e6dSmrg
8493e747e6dSmrg    Scr->TitleBarFont.font = NULL;
8503e747e6dSmrg    Scr->TitleBarFont.fontset = NULL;
8513e747e6dSmrg    Scr->TitleBarFont.name = DEFAULT_NICE_FONT;
8523e747e6dSmrg    Scr->MenuFont.font = NULL;
8533e747e6dSmrg    Scr->MenuFont.fontset = NULL;
8543e747e6dSmrg    Scr->MenuFont.name = DEFAULT_NICE_FONT;
8553e747e6dSmrg    Scr->IconFont.font = NULL;
8563e747e6dSmrg    Scr->IconFont.fontset = NULL;
8573e747e6dSmrg    Scr->IconFont.name = DEFAULT_NICE_FONT;
8583e747e6dSmrg    Scr->SizeFont.font = NULL;
8593e747e6dSmrg    Scr->SizeFont.fontset = NULL;
8603e747e6dSmrg    Scr->SizeFont.name = DEFAULT_FAST_FONT;
8613e747e6dSmrg    Scr->IconManagerFont.font = NULL;
8623e747e6dSmrg    Scr->IconManagerFont.fontset = NULL;
8633e747e6dSmrg    Scr->IconManagerFont.name = DEFAULT_NICE_FONT;
8643e747e6dSmrg    Scr->DefaultFont.font = NULL;
8653e747e6dSmrg    Scr->DefaultFont.fontset = NULL;
8663e747e6dSmrg    Scr->DefaultFont.name = DEFAULT_FAST_FONT;
8673e747e6dSmrg
8683e747e6dSmrg}
8693e747e6dSmrg
8703e747e6dSmrgvoid
871f66df612SmrgCreateFonts(void)
8723e747e6dSmrg{
8733e747e6dSmrg    GetFont(&Scr->TitleBarFont);
8743e747e6dSmrg    GetFont(&Scr->MenuFont);
8753e747e6dSmrg    GetFont(&Scr->IconFont);
8763e747e6dSmrg    GetFont(&Scr->SizeFont);
8773e747e6dSmrg    GetFont(&Scr->IconManagerFont);
8783e747e6dSmrg    GetFont(&Scr->DefaultFont);
8793e747e6dSmrg    Scr->HaveFonts = TRUE;
8803e747e6dSmrg}
8813e747e6dSmrg
8823e747e6dSmrgvoid
883f66df612SmrgRestoreWithdrawnLocation(TwmWindow *tmp)
8843e747e6dSmrg{
8853e747e6dSmrg    int gravx, gravy;
886f66df612Smrg    unsigned int bw;
8873e747e6dSmrg    XWindowChanges xwc;
8883e747e6dSmrg
889f66df612Smrg    if (XGetGeometry(dpy, tmp->w, &JunkRoot, &xwc.x, &xwc.y,
890f66df612Smrg                     &JunkWidth, &JunkHeight, &bw, &JunkDepth)) {
891f66df612Smrg        unsigned mask;
8923e747e6dSmrg
893f66df612Smrg        GetGravityOffsets(tmp, &gravx, &gravy);
894f66df612Smrg        if (gravy < 0)
895f66df612Smrg            xwc.y -= tmp->title_height;
8963e747e6dSmrg
897f66df612Smrg        if (bw != (unsigned) tmp->old_bw) {
898f66df612Smrg            int xoff, yoff;
8993e747e6dSmrg
900f66df612Smrg            if (!Scr->ClientBorderWidth) {
901f66df612Smrg                xoff = gravx;
902f66df612Smrg                yoff = gravy;
903f66df612Smrg            }
904f66df612Smrg            else {
905f66df612Smrg                xoff = 0;
906f66df612Smrg                yoff = 0;
907f66df612Smrg            }
9083e747e6dSmrg
909f66df612Smrg            xwc.x -= (xoff + 1) * tmp->old_bw;
910f66df612Smrg            xwc.y -= (yoff + 1) * tmp->old_bw;
911f66df612Smrg        }
912f66df612Smrg        if (!Scr->ClientBorderWidth) {
913f66df612Smrg            xwc.x += gravx * tmp->frame_bw;
914f66df612Smrg            xwc.y += gravy * tmp->frame_bw;
915f66df612Smrg        }
9163e747e6dSmrg
917f66df612Smrg        mask = (CWX | CWY);
918f66df612Smrg        if (bw != (unsigned) tmp->old_bw) {
919f66df612Smrg            xwc.border_width = tmp->old_bw;
920f66df612Smrg            mask |= CWBorderWidth;
921f66df612Smrg        }
9223e747e6dSmrg
923f66df612Smrg        XConfigureWindow(dpy, tmp->w, mask, &xwc);
9243e747e6dSmrg
925f66df612Smrg        if (tmp->wmhints && (tmp->wmhints->flags & IconWindowHint)) {
926f66df612Smrg            XUnmapWindow(dpy, tmp->wmhints->icon_window);
927f66df612Smrg        }
9283e747e6dSmrg
9293e747e6dSmrg    }
9303e747e6dSmrg}
9313e747e6dSmrg
932ffd25bcaSmrgvoid
933f66df612SmrgReborder(Time time)
9343e747e6dSmrg{
935f66df612Smrg    TwmWindow *tmp;             /* temp twm window structure */
9363e747e6dSmrg    int scrnum;
9373e747e6dSmrg
9383e747e6dSmrg    /* put a border back around all windows */
9393e747e6dSmrg
940f66df612Smrg    XGrabServer(dpy);
941f66df612Smrg    for (scrnum = 0; scrnum < NumScreens; scrnum++) {
942f66df612Smrg        if ((Scr = ScreenList[scrnum]) == NULL)
943f66df612Smrg            continue;
944f66df612Smrg
945f66df612Smrg        InstallWindowColormaps(0, &Scr->TwmRoot);       /* force reinstall */
946f66df612Smrg        for (tmp = Scr->TwmRoot.next; tmp != NULL; tmp = tmp->next) {
947f66df612Smrg            RestoreWithdrawnLocation(tmp);
948f66df612Smrg            XMapWindow(dpy, tmp->w);
949f66df612Smrg        }
9503e747e6dSmrg    }
9513e747e6dSmrg
952f66df612Smrg    XUngrabServer(dpy);
953f66df612Smrg    SetFocus((TwmWindow *) NULL, time);
9543e747e6dSmrg}
9553e747e6dSmrg
956c2535118Smrgstatic void
957f66df612SmrgsigHandler(int sig _X_UNUSED)
9583e747e6dSmrg{
9593e747e6dSmrg    XtNoticeSignal(si);
9603e747e6dSmrg}
9613e747e6dSmrg
9623e747e6dSmrg/**
9633e747e6dSmrg * cleanup and exit twm
9643e747e6dSmrg */
9653e747e6dSmrgvoid
966f66df612SmrgDone(XtPointer client_data _X_UNUSED, XtSignalId *si2 _X_UNUSED)
9673e747e6dSmrg{
968f66df612Smrg    if (dpy) {
969f66df612Smrg        Reborder(CurrentTime);
970f66df612Smrg        XCloseDisplay(dpy);
9713e747e6dSmrg    }
972f66df612Smrg    exit(EXIT_SUCCESS);
9733e747e6dSmrg}
9743e747e6dSmrg
9753e747e6dSmrg/*
9763e747e6dSmrg * Error Handlers.  If a client dies, we'll get a BadWindow error (except for
9773e747e6dSmrg * GetGeometry which returns BadDrawable) for most operations that we do before
9783e747e6dSmrg * manipulating the client's window.
9793e747e6dSmrg */
9803e747e6dSmrg
9813e747e6dSmrgBool ErrorOccurred = False;
9823e747e6dSmrgXErrorEvent LastErrorEvent;
9833e747e6dSmrg
984ffd25bcaSmrgstatic int
985f66df612SmrgTwmErrorHandler(Display *dpy2, XErrorEvent *event)
9863e747e6dSmrg{
9873e747e6dSmrg    LastErrorEvent = *event;
9883e747e6dSmrg    ErrorOccurred = True;
9893e747e6dSmrg
990f66df612Smrg    if ((message_level > 1) &&  /* don't be too obnoxious */
991f66df612Smrg        event->error_code != BadWindow &&       /* watch for dead puppies */
992f66df612Smrg        (event->request_code != X_GetGeometry &&        /* of all styles */
993f66df612Smrg         event->error_code != BadDrawable))
994f66df612Smrg        XmuPrintDefaultErrorMessage(dpy2, event, stderr);
9953e747e6dSmrg    return 0;
9963e747e6dSmrg}
9973e747e6dSmrg
998ffd25bcaSmrgstatic int
999f66df612SmrgCatchRedirectError(Display *dpy2 _X_UNUSED, XErrorEvent *event)
10003e747e6dSmrg{
10013e747e6dSmrg    RedirectError = TRUE;
10023e747e6dSmrg    LastErrorEvent = *event;
10033e747e6dSmrg    ErrorOccurred = True;
10043e747e6dSmrg    return 0;
10053e747e6dSmrg}
1006f66df612Smrg
1007f66df612Smrgvoid
1008f66df612SmrgtwmError(const char *format, ...)
1009f66df612Smrg{
1010f66df612Smrg    va_list ap;
1011f66df612Smrg
1012f66df612Smrg    va_start(ap, format);
1013f66df612Smrg    fprintf(stderr, "%s: error: ", ProgramName);
1014f66df612Smrg    vfprintf(stderr, format, ap);
1015f66df612Smrg    fputc('\n', stderr);
1016f66df612Smrg    va_end(ap);
1017f66df612Smrg    exit(EXIT_FAILURE);
1018f66df612Smrg}
1019f66df612Smrg
1020f66df612Smrgvoid
1021f66df612SmrgtwmWarning(const char *format, ...)
1022f66df612Smrg{
1023f66df612Smrg    if (message_level > 0) {
1024f66df612Smrg        va_list ap;
1025f66df612Smrg
1026f66df612Smrg        va_start(ap, format);
1027f66df612Smrg        fprintf(stderr, "%s: warning: ", ProgramName);
1028f66df612Smrg        vfprintf(stderr, format, ap);
1029f66df612Smrg        fputc('\n', stderr);
1030f66df612Smrg        va_end(ap);
1031f66df612Smrg    }
1032f66df612Smrg}
1033f66df612Smrg
1034f66df612Smrgvoid
1035f66df612SmrgtwmVerbose(const char *format, ...)
1036f66df612Smrg{
1037f66df612Smrg    if (message_level > 1) {
1038f66df612Smrg        va_list ap;
1039f66df612Smrg
1040f66df612Smrg        va_start(ap, format);
1041f66df612Smrg        fprintf(stderr, "%s: warning: ", ProgramName);
1042f66df612Smrg        vfprintf(stderr, format, ap);
1043f66df612Smrg        fputc('\n', stderr);
1044f66df612Smrg        va_end(ap);
1045f66df612Smrg    }
1046f66df612Smrg}
1047f66df612Smrg
1048f66df612Smrgvoid
1049f66df612SmrgtwmMessage(const char *format, ...)
1050f66df612Smrg{
1051f66df612Smrg    va_list ap;
1052f66df612Smrg
1053f66df612Smrg    va_start(ap, format);
1054f66df612Smrg    printf("%s: ", ProgramName);
1055f66df612Smrg    vprintf(format, ap);
1056f66df612Smrg    putc('\n', stdout);
1057f66df612Smrg    va_end(ap);
1058f66df612Smrg
1059f66df612Smrg    fflush(stdout);
1060f66df612Smrg}
1061