10bbfda8aSnia/*
20bbfda8aSnia *       Copyright 1988 by Evans & Sutherland Computer Corporation,
30bbfda8aSnia *                          Salt Lake City, Utah
40bbfda8aSnia *  Portions Copyright 1989 by the Massachusetts Institute of Technology
50bbfda8aSnia *                        Cambridge, Massachusetts
60bbfda8aSnia *
70bbfda8aSnia * $XConsortium: twm.c,v 1.124 91/05/08 11:01:54 dave Exp $
80bbfda8aSnia *
90bbfda8aSnia * twm - "Tom's Window Manager"
100bbfda8aSnia *
110bbfda8aSnia * 27-Oct-87 Thomas E. LaStrange        File created
120bbfda8aSnia * 10-Oct-90 David M. Sternlicht        Storing saved colors on root
130bbfda8aSnia *
140bbfda8aSnia * Copyright 1992 Claude Lecommandeur.
150bbfda8aSnia *
160bbfda8aSnia * Do the necessary modification to be integrated in ctwm.
170bbfda8aSnia * Can no longer be used for the standard twm.
180bbfda8aSnia *
190bbfda8aSnia * 22-April-92 Claude Lecommandeur.
200bbfda8aSnia */
210bbfda8aSnia
220bbfda8aSnia#include "ctwm.h"
230bbfda8aSnia
240bbfda8aSnia#include <stdio.h>
250bbfda8aSnia#include <stdlib.h>
260bbfda8aSnia#include <unistd.h>
270bbfda8aSnia#include <locale.h>
280bbfda8aSnia
290bbfda8aSnia#include <fcntl.h>
300bbfda8aSnia#include <X11/Xatom.h>
310bbfda8aSnia#include <X11/extensions/shape.h>
320bbfda8aSnia
330bbfda8aSnia
340bbfda8aSnia#include "ctwm_atoms.h"
350bbfda8aSnia#include "ctwm_main.h"
36b18c2d1eSnia#include "ctwm_takeover.h"
370bbfda8aSnia#include "clargs.h"
380bbfda8aSnia#include "add_window.h"
390bbfda8aSnia#include "gc.h"
400bbfda8aSnia#include "parse.h"
410bbfda8aSnia#include "version.h"
420bbfda8aSnia#include "colormaps.h"
430bbfda8aSnia#include "events.h"
440bbfda8aSnia#include "util.h"
450bbfda8aSnia#include "mask_screen.h"
460bbfda8aSnia#include "animate.h"
470bbfda8aSnia#include "screen.h"
480bbfda8aSnia#include "icons.h"
490bbfda8aSnia#include "iconmgr.h"
500bbfda8aSnia#include "list.h"
51b18c2d1eSnia#ifdef SESSION
520bbfda8aSnia#include "session.h"
53b18c2d1eSnia#endif
540bbfda8aSnia#include "occupation.h"
550bbfda8aSnia#include "otp.h"
560bbfda8aSnia#include "cursor.h"
57b18c2d1eSnia#ifdef WINBOX
580bbfda8aSnia#include "windowbox.h"
59b18c2d1eSnia#endif
60b18c2d1eSnia#ifdef CAPTIVE
610bbfda8aSnia#include "captive.h"
62b18c2d1eSnia#endif
63b18c2d1eSnia#ifdef XRANDR
64b18c2d1eSnia#include "xrandr.h"
65b18c2d1eSnia#endif
66b18c2d1eSnia#include "r_area.h"
67b18c2d1eSnia#include "r_area_list.h"
68b18c2d1eSnia#include "r_layout.h"
69b18c2d1eSnia#include "signals.h"
700bbfda8aSnia#include "vscreen.h"
710bbfda8aSnia#include "win_decorations_init.h"
720bbfda8aSnia#include "win_ops.h"
730bbfda8aSnia#include "win_regions.h"
740bbfda8aSnia#include "win_utils.h"
750bbfda8aSnia#include "workspace_manager.h"
760bbfda8aSnia#ifdef SOUNDS
770bbfda8aSnia#  include "sound.h"
780bbfda8aSnia#endif
790bbfda8aSnia
800bbfda8aSnia#include "gram.tab.h"
810bbfda8aSnia
820bbfda8aSnia
830bbfda8aSniaXtAppContext appContext;        /* Xt application context */
840bbfda8aSniaDisplay *dpy;                   /* which display are we talking to */
850bbfda8aSniaWindow ResizeWindow;            /* the window we are resizing */
860bbfda8aSnia
87b18c2d1eSniaAtom XCTWMAtom[NUM_CTWM_XATOMS]; ///< Our various common atoms
88b18c2d1eSnia
890bbfda8aSniaint NumScreens;                 /* number of screens in ScreenList */
900bbfda8aSniabool HasShape;                  /* server supports shape extension? */
910bbfda8aSniaint ShapeEventBase, ShapeErrorBase;
920bbfda8aSniaScreenInfo **ScreenList;        /* structures for each screen */
930bbfda8aSniaScreenInfo *Scr = NULL;         /* the cur and prev screens */
940bbfda8aSniaint PreviousScreen;             /* last screen that we were on */
95b18c2d1eSniastatic bool cfgerrs = false;    ///< Whether there were config parsing errors
96b18c2d1eSnia
97b18c2d1eSnia#ifdef CAPTIVE
980bbfda8aSniastatic Window CreateCaptiveRootWindow(int x, int y,
990bbfda8aSnia                                      unsigned int width, unsigned int height);
100b18c2d1eSnia#endif
1010bbfda8aSniaScreenInfo *InitScreenInfo(int scrnum, Window croot, int crootx, int crooty,
1020bbfda8aSnia                           unsigned int crootw, unsigned int crooth);
1030bbfda8aSniastatic bool MappedNotOverride(Window w);
1040bbfda8aSnia
1050bbfda8aSniaCursor  UpperLeftCursor;
1060bbfda8aSniaCursor  TopRightCursor,
1070bbfda8aSnia        TopLeftCursor,
1080bbfda8aSnia        BottomRightCursor,
1090bbfda8aSnia        BottomLeftCursor,
1100bbfda8aSnia        LeftCursor,
1110bbfda8aSnia        RightCursor,
1120bbfda8aSnia        TopCursor,
1130bbfda8aSnia        BottomCursor;
1140bbfda8aSnia
1150bbfda8aSniaCursor RightButt;
1160bbfda8aSniaCursor MiddleButt;
1170bbfda8aSniaCursor LeftButt;
1180bbfda8aSnia
1190bbfda8aSniaXContext TwmContext;            /* context for twm windows */
1200bbfda8aSniaXContext MenuContext;           /* context for all menu windows */
1210bbfda8aSniaXContext ScreenContext;         /* context to get screen data */
1220bbfda8aSniaXContext ColormapContext;       /* context for colormap operations */
1230bbfda8aSnia
1240bbfda8aSniaXClassHint NoClass;             /* for applications with no class */
1250bbfda8aSnia
1260bbfda8aSniaXGCValues Gcv;
1270bbfda8aSnia
1280bbfda8aSniachar *Home;                     /* the HOME environment variable */
1290bbfda8aSniaint HomeLen;                    /* length of Home */
1300bbfda8aSnia
1310bbfda8aSniabool HandlingEvents = false;    /* are we handling events yet? */
1320bbfda8aSnia
1330bbfda8aSnia/*
1340bbfda8aSnia * Various junk vars for xlib calls.  Many calls have to get passed these
1350bbfda8aSnia * pointers to return values into, but in a lot of cases we don't care
1360bbfda8aSnia * about some/all of them, and since xlib blindly derefs and stores into
1370bbfda8aSnia * them, we can't just pass NULL for the ones we don't care about.  So we
1380bbfda8aSnia * make this set of globals to use as standin.  These should never be
1390bbfda8aSnia * used or read in our own code; use real vars for the values we DO use
1400bbfda8aSnia * from the calls.
1410bbfda8aSnia */
1420bbfda8aSniaWindow JunkRoot, JunkChild;
1430bbfda8aSniaint JunkX, JunkY;
1440bbfda8aSniaunsigned int JunkWidth, JunkHeight, JunkBW, JunkDepth, JunkMask;
1450bbfda8aSnia
1460bbfda8aSniachar *ProgramName;
147b18c2d1eSniasize_t ProgramNameLen;
1480bbfda8aSniaint Argc;
1490bbfda8aSniachar **Argv;
1500bbfda8aSnia
1510bbfda8aSniabool RestartPreviousState = true;      /* try to restart in previous state */
1520bbfda8aSnia
1530bbfda8aSnia
154b18c2d1eSnia/// Magic flag for tests.  Nothing else should touch this!
155b18c2d1eSniabool ctwm_test = false;
156b18c2d1eSnia
157b18c2d1eSnia/// Magic callback for tests.  This will trigger right after config file
158b18c2d1eSnia/// parsing if it's set, and then exit.  Nothing else should ever touch
159b18c2d1eSnia/// this!
160b18c2d1eSniaint (*ctwm_test_postparse)(void) = NULL;
161b18c2d1eSnia
162b18c2d1eSnia
163b18c2d1eSnia
1640bbfda8aSnia
165b18c2d1eSnia/**
166b18c2d1eSnia * Start up ctwm.  This is effectively main(), just wrapped for various
167b18c2d1eSnia * unimportant reasons.
168b18c2d1eSnia */
1690bbfda8aSniaint
1700bbfda8aSniactwm_main(int argc, char *argv[])
1710bbfda8aSnia{
1720bbfda8aSnia	int numManaged, firstscrn, lastscrn;
1730bbfda8aSnia	bool FirstScreen;
174b18c2d1eSnia	bool takeover = true;
175b18c2d1eSnia	bool nodpyok = false;
1760bbfda8aSnia
1770bbfda8aSnia	setlocale(LC_ALL, "");
1780bbfda8aSnia
1790bbfda8aSnia	ProgramName = argv[0];
180b18c2d1eSnia	ProgramNameLen = strlen(ProgramName);
1810bbfda8aSnia	Argc = argc;
1820bbfda8aSnia	Argv = argv;
1830bbfda8aSnia
1840bbfda8aSnia
1850bbfda8aSnia	/*
1860bbfda8aSnia	 * Run consistency check.  This is mostly to keep devs from
1870bbfda8aSnia	 * accidental screwups; if a user ever sees anything from this,
1880bbfda8aSnia	 * something went very very wrong.
1890bbfda8aSnia	 */
1900bbfda8aSnia	chk_keytable_order();
1910bbfda8aSnia
1920bbfda8aSnia	/*
1930bbfda8aSnia	 * Parse-out command line args, and check the results.
1940bbfda8aSnia	 */
1950bbfda8aSnia	clargs_parse(argc, argv);
1960bbfda8aSnia	clargs_check();
1970bbfda8aSnia	/* If we get this far, it was all good */
1980bbfda8aSnia
199b18c2d1eSnia	/* Some clargs mean we're not actually trying to take over the screen */
200b18c2d1eSnia	if(CLarg.cfgchk) {
201b18c2d1eSnia		takeover = false;
202b18c2d1eSnia	}
203b18c2d1eSnia#ifdef CAPTIVE
204b18c2d1eSnia	if(CLarg.is_captive) {
205b18c2d1eSnia		takeover = false;
206b18c2d1eSnia	}
207b18c2d1eSnia#endif
2080bbfda8aSnia
209b18c2d1eSnia	/* And some mean we actually don't care if we lack an X server */
210b18c2d1eSnia	if(CLarg.cfgchk) {
211b18c2d1eSnia		nodpyok = true;
212b18c2d1eSnia	}
2130bbfda8aSnia
214b18c2d1eSnia	/* Support for tests: be ready to fake everything */
215b18c2d1eSnia	if(ctwm_test) {
216b18c2d1eSnia		takeover = false;
217b18c2d1eSnia		nodpyok  = true;
218b18c2d1eSnia	}
219b18c2d1eSnia
220b18c2d1eSnia
221b18c2d1eSnia	/*
222b18c2d1eSnia	 * Hook up signal handlers
223b18c2d1eSnia	 */
224b18c2d1eSnia	setup_signal_handlers();
2250bbfda8aSnia
2260bbfda8aSnia
2270bbfda8aSnia	// Various bits of code care about $HOME
2280bbfda8aSnia	Home = getenv("HOME");
2290bbfda8aSnia	if(Home == NULL) {
2300bbfda8aSnia		Home = "./";
2310bbfda8aSnia	}
2320bbfda8aSnia	HomeLen = strlen(Home);
2330bbfda8aSnia
2340bbfda8aSnia
2350bbfda8aSnia	// XXX This is only used in AddWindow(), and is probably bogus to
2360bbfda8aSnia	// have globally....
2370bbfda8aSnia	NoClass.res_name = NoName;
2380bbfda8aSnia	NoClass.res_class = NoName;
2390bbfda8aSnia
2400bbfda8aSnia
2410bbfda8aSnia	/*
2420bbfda8aSnia	 * Initialize our X connection and state bits.
2430bbfda8aSnia	 */
2440bbfda8aSnia	{
2450bbfda8aSnia		int zero = 0; // Fakey
2460bbfda8aSnia
2470bbfda8aSnia		XtToolkitInitialize();
2480bbfda8aSnia		appContext = XtCreateApplicationContext();
2490bbfda8aSnia
250b18c2d1eSnia		// Tests don't talk to a real X server.
251b18c2d1eSnia		// XXX This needs revisiting if we ever get one that _does_.
252b18c2d1eSnia		// We'll have to add another flag...
253b18c2d1eSnia		if(!ctwm_test) {
254b18c2d1eSnia			// Connect
255b18c2d1eSnia			dpy = XtOpenDisplay(appContext, CLarg.display_name, "twm", "twm",
256b18c2d1eSnia			                    NULL, 0, &zero, NULL);
257b18c2d1eSnia		}
258b18c2d1eSnia
259b18c2d1eSnia		// Failed?  Usually a problem, but somethings we allow faking...
260b18c2d1eSnia		if(!dpy && !nodpyok) {
2610bbfda8aSnia			fprintf(stderr, "%s:  unable to open display \"%s\"\n",
2620bbfda8aSnia			        ProgramName, XDisplayName(CLarg.display_name));
2630bbfda8aSnia			exit(1);
2640bbfda8aSnia		}
2650bbfda8aSnia
266b18c2d1eSnia		if(dpy && fcntl(ConnectionNumber(dpy), F_SETFD, FD_CLOEXEC) == -1) {
2670bbfda8aSnia			fprintf(stderr,
2680bbfda8aSnia			        "%s:  unable to mark display connection as close-on-exec\n",
2690bbfda8aSnia			        ProgramName);
2700bbfda8aSnia			exit(1);
2710bbfda8aSnia		}
272b18c2d1eSnia
273b18c2d1eSnia		if(!dpy && !ctwm_test) {
274b18c2d1eSnia			// At least warn, except for tests
275b18c2d1eSnia			fprintf(stderr, "%s: Can't connect to X server, proceeding anyway...\n",
276b18c2d1eSnia			        ProgramName);
277b18c2d1eSnia		}
2780bbfda8aSnia	}
2790bbfda8aSnia
2800bbfda8aSnia
281b18c2d1eSnia#ifdef SESSION
2820bbfda8aSnia	// Load session stuff
2830bbfda8aSnia	if(CLarg.restore_filename) {
2840bbfda8aSnia		ReadWinConfigFile(CLarg.restore_filename);
2850bbfda8aSnia	}
286b18c2d1eSnia#endif
2870bbfda8aSnia
2880bbfda8aSnia
289b18c2d1eSnia	if(dpy) {
290b18c2d1eSnia		// Load up info about X extensions
291b18c2d1eSnia		HasShape = XShapeQueryExtension(dpy, &ShapeEventBase, &ShapeErrorBase);
2920bbfda8aSnia
293b18c2d1eSnia		// Allocate contexts/atoms/etc we use
294b18c2d1eSnia		TwmContext = XUniqueContext();
295b18c2d1eSnia		MenuContext = XUniqueContext();
296b18c2d1eSnia		ScreenContext = XUniqueContext();
297b18c2d1eSnia		ColormapContext = XUniqueContext();
298b18c2d1eSnia		InitWorkSpaceManagerContext();
299b18c2d1eSnia
300b18c2d1eSnia		// Load up our standard set of atoms
301b18c2d1eSnia		XInternAtoms(dpy, XCTWMAtomNames, NUM_CTWM_XATOMS, False, XCTWMAtom);
302b18c2d1eSnia
303b18c2d1eSnia		NumScreens = ScreenCount(dpy);
304b18c2d1eSnia		PreviousScreen = DefaultScreen(dpy);
305b18c2d1eSnia	}
306b18c2d1eSnia	else {
307b18c2d1eSnia		NumScreens = 1;
308b18c2d1eSnia		PreviousScreen = 0;
309b18c2d1eSnia	}
3100bbfda8aSnia
3110bbfda8aSnia	// Allocate/define common cursors
3120bbfda8aSnia	NewFontCursor(&TopLeftCursor, "top_left_corner");
3130bbfda8aSnia	NewFontCursor(&TopRightCursor, "top_right_corner");
3140bbfda8aSnia	NewFontCursor(&BottomLeftCursor, "bottom_left_corner");
3150bbfda8aSnia	NewFontCursor(&BottomRightCursor, "bottom_right_corner");
3160bbfda8aSnia	NewFontCursor(&LeftCursor, "left_side");
3170bbfda8aSnia	NewFontCursor(&RightCursor, "right_side");
3180bbfda8aSnia	NewFontCursor(&TopCursor, "top_side");
3190bbfda8aSnia	NewFontCursor(&BottomCursor, "bottom_side");
3200bbfda8aSnia
3210bbfda8aSnia	NewFontCursor(&UpperLeftCursor, "top_left_corner");
3220bbfda8aSnia	NewFontCursor(&RightButt, "rightbutton");
3230bbfda8aSnia	NewFontCursor(&LeftButt, "leftbutton");
3240bbfda8aSnia	NewFontCursor(&MiddleButt, "middlebutton");
3250bbfda8aSnia
3260bbfda8aSnia
3270bbfda8aSnia	// Prep up the per-screen global info
3280bbfda8aSnia	if(CLarg.MultiScreen) {
3290bbfda8aSnia		firstscrn = 0;
3300bbfda8aSnia		lastscrn = NumScreens - 1;
3310bbfda8aSnia	}
332b18c2d1eSnia	else if(!dpy) {
333b18c2d1eSnia		firstscrn = lastscrn = 0;
334b18c2d1eSnia	}
3350bbfda8aSnia	else {
3360bbfda8aSnia		firstscrn = lastscrn = DefaultScreen(dpy);
3370bbfda8aSnia	}
3380bbfda8aSnia
3390bbfda8aSnia	// For simplicity, pre-allocate NumScreens ScreenInfo struct pointers
3400bbfda8aSnia	ScreenList = calloc(NumScreens, sizeof(ScreenInfo *));
3410bbfda8aSnia	if(ScreenList == NULL) {
3420bbfda8aSnia		fprintf(stderr, "%s: Unable to allocate memory for screen list, exiting.\n",
3430bbfda8aSnia		        ProgramName);
3440bbfda8aSnia		exit(1);
3450bbfda8aSnia	}
3460bbfda8aSnia
3470bbfda8aSnia
3480bbfda8aSnia	// Do a little early initialization
3490bbfda8aSnia#ifdef EWMH
350b18c2d1eSnia	if(dpy) {
351b18c2d1eSnia		EwmhInit();
352b18c2d1eSnia	}
3530bbfda8aSnia#endif /* EWMH */
3540bbfda8aSnia#ifdef SOUNDS
3550bbfda8aSnia	// Needs init'ing before we get to config parsing
3560bbfda8aSnia	sound_init();
3570bbfda8aSnia#endif
3580bbfda8aSnia	InitEvents();
3590bbfda8aSnia
360b18c2d1eSnia
361b18c2d1eSnia
3620bbfda8aSnia	// Start looping over the screens
3630bbfda8aSnia	numManaged = 0;
3640bbfda8aSnia	FirstScreen = true;
3650bbfda8aSnia	for(int scrnum = firstscrn ; scrnum <= lastscrn; scrnum++) {
3660bbfda8aSnia		Window croot;
3670bbfda8aSnia		int crootx, crooty;
3680bbfda8aSnia		unsigned int crootw, crooth;
3690bbfda8aSnia		bool screenmasked;
3700bbfda8aSnia		char *welcomefile;
3710bbfda8aSnia
372b18c2d1eSnia
3730bbfda8aSnia		/*
3740bbfda8aSnia		 * First, setup the root window for the screen.
3750bbfda8aSnia		 */
376b18c2d1eSnia		if(0) {
377b18c2d1eSnia			// Dummy
378b18c2d1eSnia		}
379b18c2d1eSnia#ifdef CAPTIVE
380b18c2d1eSnia		else if(CLarg.is_captive) {
3810bbfda8aSnia			// Captive ctwm.  We make a fake root.
3820bbfda8aSnia			XWindowAttributes wa;
3830bbfda8aSnia			if(CLarg.capwin && XGetWindowAttributes(dpy, CLarg.capwin, &wa)) {
3840bbfda8aSnia				Window junk;
3850bbfda8aSnia				croot  = CLarg.capwin;
3860bbfda8aSnia				crootw = wa.width;
3870bbfda8aSnia				crooth = wa.height;
3880bbfda8aSnia				XTranslateCoordinates(dpy, CLarg.capwin, wa.root, 0, 0, &crootx, &crooty,
3890bbfda8aSnia				                      &junk);
3900bbfda8aSnia			}
3910bbfda8aSnia			else {
3920bbfda8aSnia				// Fake up default size.  Probably ideally should be
3930bbfda8aSnia				// configurable, but even more ideally we wouldn't have
3940bbfda8aSnia				// captive...
3950bbfda8aSnia				crootx = crooty = 100;
3960bbfda8aSnia				crootw = 1280;
3970bbfda8aSnia				crooth = 768;
3980bbfda8aSnia				croot = CreateCaptiveRootWindow(crootx, crooty, crootw, crooth);
3990bbfda8aSnia			}
4000bbfda8aSnia		}
401b18c2d1eSnia#endif
4020bbfda8aSnia		else {
4030bbfda8aSnia			// Normal; get the real display's root.
4040bbfda8aSnia			crootx = 0;
4050bbfda8aSnia			crooty = 0;
406b18c2d1eSnia
407b18c2d1eSnia			if(dpy) {
408b18c2d1eSnia				croot  = RootWindow(dpy, scrnum);
409b18c2d1eSnia				crootw = DisplayWidth(dpy, scrnum);
410b18c2d1eSnia				crooth = DisplayHeight(dpy, scrnum);
411b18c2d1eSnia			}
412b18c2d1eSnia			else {
413b18c2d1eSnia				croot = None;
414b18c2d1eSnia				crootw = 1280;
415b18c2d1eSnia				crooth = 768;
416b18c2d1eSnia			}
4170bbfda8aSnia		}
4180bbfda8aSnia
4190bbfda8aSnia
4200bbfda8aSnia
4210bbfda8aSnia		/*
4220bbfda8aSnia		 * Create ScreenInfo for this Screen, and populate various
4230bbfda8aSnia		 * default/initial config.
4240bbfda8aSnia		 */
4250bbfda8aSnia		Scr = ScreenList[scrnum] = InitScreenInfo(scrnum, croot,
4260bbfda8aSnia		                           crootx, crooty, crootw, crooth);
4270bbfda8aSnia		if(Scr == NULL) {
4280bbfda8aSnia			fprintf(stderr,
4290bbfda8aSnia			        "%s: unable to allocate memory for ScreenInfo structure"
4300bbfda8aSnia			        " for screen %d.\n",
4310bbfda8aSnia			        ProgramName, scrnum);
4320bbfda8aSnia			continue;
4330bbfda8aSnia		}
4340bbfda8aSnia
4350bbfda8aSnia		// Other misc adjustments to default config.
4360bbfda8aSnia		Scr->ShowWelcomeWindow = CLarg.ShowWelcomeWindow;
4370bbfda8aSnia
4380bbfda8aSnia
4390bbfda8aSnia
4400bbfda8aSnia		/*
441b18c2d1eSnia		 * Figure out the layout of our various monitors if RANDR is
442b18c2d1eSnia		 * around and can tell us.
4430bbfda8aSnia		 */
444b18c2d1eSnia#ifdef XRANDR
445b18c2d1eSnia		if(dpy) {
446b18c2d1eSnia			Scr->Layout = XrandrNewLayout(dpy, Scr->XineramaRoot);
4470bbfda8aSnia		}
448b18c2d1eSnia#endif
449b18c2d1eSnia		if(Scr->Layout == NULL) {
450b18c2d1eSnia			// No RANDR, so as far as we know, the layout is just one
451b18c2d1eSnia			// monitor with our full size.
452b18c2d1eSnia			RArea *fs;
453b18c2d1eSnia			RAreaList *fsl;
454b18c2d1eSnia
455b18c2d1eSnia			fs = RAreaNewStatic(Scr->rootx, Scr->rooty, Scr->rootw, Scr->rooth);
456b18c2d1eSnia			fsl = RAreaListNew(1, fs, NULL);
457b18c2d1eSnia			Scr->Layout = RLayoutNew(fsl);
458b18c2d1eSnia		}
459b18c2d1eSnia#ifdef DEBUG
460b18c2d1eSnia		fprintf(stderr, "Layout: ");
461b18c2d1eSnia		RLayoutPrint(Scr->Layout);
462b18c2d1eSnia#endif
463b18c2d1eSnia		if(RLayoutNumMonitors(Scr->Layout) < 1) {
464b18c2d1eSnia			fprintf(stderr, "Error: No monitors found on screen %d!\n", scrnum);
4650bbfda8aSnia			continue;
4660bbfda8aSnia		}
4670bbfda8aSnia
4680bbfda8aSnia
4690bbfda8aSnia
4700bbfda8aSnia		// Now we can stash some info about the screen
471b18c2d1eSnia		if(dpy) {
472b18c2d1eSnia			Scr->d_depth = DefaultDepth(dpy, scrnum);
473b18c2d1eSnia			Scr->d_visual = DefaultVisual(dpy, scrnum);
474b18c2d1eSnia			Scr->RealRoot = RootWindow(dpy, scrnum);
475b18c2d1eSnia			{
476b18c2d1eSnia				// Stash these for m4
477b18c2d1eSnia				Screen *tscr = ScreenOfDisplay(dpy, scrnum);
478b18c2d1eSnia				Scr->mm_w = tscr->mwidth;
479b18c2d1eSnia				Scr->mm_h = tscr->mheight;
480b18c2d1eSnia			}
481b18c2d1eSnia		}
482b18c2d1eSnia		else {
483b18c2d1eSnia			// Standin; fake the values we need in m4 parsing
484b18c2d1eSnia			Scr->d_visual = calloc(1, sizeof(Visual));
485b18c2d1eSnia			Scr->d_visual->bits_per_rgb = 8;
486b18c2d1eSnia			Scr->d_visual->class = TrueColor;
487b18c2d1eSnia		}
488b18c2d1eSnia
4890bbfda8aSnia
4900bbfda8aSnia		// Now that we have d_depth...
4910bbfda8aSnia		Scr->XORvalue = (((unsigned long) 1) << Scr->d_depth) - 1;
4920bbfda8aSnia
493b18c2d1eSnia#ifdef CAPTIVE
494b18c2d1eSnia		// Init captive bits.  We stick this name into m4 props, so do it
495b18c2d1eSnia		// before config processing.
4960bbfda8aSnia		if(CLarg.is_captive) {
4970bbfda8aSnia			Scr->CaptiveRoot = croot;
4980bbfda8aSnia			Scr->captivename = AddToCaptiveList(CLarg.captivename);
4990bbfda8aSnia			if(Scr->captivename) {
5000bbfda8aSnia				XmbSetWMProperties(dpy, croot,
5010bbfda8aSnia				                   Scr->captivename, Scr->captivename,
5020bbfda8aSnia				                   NULL, 0, NULL, NULL, NULL);
5030bbfda8aSnia			}
5040bbfda8aSnia		}
505b18c2d1eSnia#endif
5060bbfda8aSnia
5070bbfda8aSnia
508b18c2d1eSnia		// Init some colormap bits.  We need this before we get into the
509b18c2d1eSnia		// config parsing, since various things in there poke into
510b18c2d1eSnia		// colormaps.
5110bbfda8aSnia		{
5120bbfda8aSnia			// 1 on the root
5130bbfda8aSnia			Scr->RootColormaps.number_cwins = 1;
5140bbfda8aSnia			Scr->RootColormaps.cwins = malloc(sizeof(ColormapWindow *));
5150bbfda8aSnia			Scr->RootColormaps.cwins[0] = CreateColormapWindow(Scr->Root, true,
5160bbfda8aSnia			                              false);
5170bbfda8aSnia			Scr->RootColormaps.cwins[0]->visibility = VisibilityPartiallyObscured;
5180bbfda8aSnia
5190bbfda8aSnia			// Initialize storage for all maps the Screen can hold
5200bbfda8aSnia			Scr->cmapInfo.cmaps = NULL;
521b18c2d1eSnia			if(dpy) {
522b18c2d1eSnia				Scr->cmapInfo.maxCmaps = MaxCmapsOfScreen(ScreenOfDisplay(dpy,
523b18c2d1eSnia				                         Scr->screen));
524b18c2d1eSnia			}
5250bbfda8aSnia			Scr->cmapInfo.root_pushes = 0;
5260bbfda8aSnia			InstallColormaps(0, &Scr->RootColormaps);
5270bbfda8aSnia
5280bbfda8aSnia			// Setup which we're using
5290bbfda8aSnia			Scr->StdCmapInfo.head = Scr->StdCmapInfo.tail
5300bbfda8aSnia			                        = Scr->StdCmapInfo.mru = NULL;
5310bbfda8aSnia			Scr->StdCmapInfo.mruindex = 0;
532b18c2d1eSnia			if(dpy) {
533b18c2d1eSnia				LocateStandardColormaps();
534b18c2d1eSnia			}
5350bbfda8aSnia		}
5360bbfda8aSnia
5370bbfda8aSnia
5380bbfda8aSnia		// Are we monochrome?  Or do we care this millennium?
539b18c2d1eSnia		if(CLarg.Monochrome || (dpy && DisplayCells(dpy, scrnum) < 3)) {
5400bbfda8aSnia			Scr->Monochrome = MONOCHROME;
5410bbfda8aSnia		}
5420bbfda8aSnia		else {
5430bbfda8aSnia			Scr->Monochrome = COLOR;
5440bbfda8aSnia		}
5450bbfda8aSnia
5460bbfda8aSnia
5470bbfda8aSnia		// With the colormap/monochrome bits set, we can setup our
5480bbfda8aSnia		// default color bits.
5490bbfda8aSnia		GetColor(Scr->Monochrome, &(Scr->Black), "black");
5500bbfda8aSnia		GetColor(Scr->Monochrome, &(Scr->White), "white");
5510bbfda8aSnia
5520bbfda8aSnia		Scr->MenuShadowColor = Scr->Black;
5530bbfda8aSnia		Scr->IconBorderColor = Scr->Black;
5540bbfda8aSnia		Scr->IconManagerHighlight = Scr->Black;
5550bbfda8aSnia
5560bbfda8aSnia#define SETFB(fld) Scr->fld.fore = Scr->Black; Scr->fld.back = Scr->White;
5570bbfda8aSnia		SETFB(DefaultC)
5580bbfda8aSnia		SETFB(BorderColorC)
5590bbfda8aSnia		SETFB(BorderTileC)
5600bbfda8aSnia		SETFB(TitleC)
5610bbfda8aSnia		SETFB(MenuC)
5620bbfda8aSnia		SETFB(MenuTitleC)
5630bbfda8aSnia		SETFB(IconC)
5640bbfda8aSnia		SETFB(IconManagerC)
5650bbfda8aSnia		SETFB(workSpaceMgr.windowcp)
5660bbfda8aSnia		SETFB(workSpaceMgr.curColors)
5670bbfda8aSnia		SETFB(workSpaceMgr.defColors)
5680bbfda8aSnia#undef SETFB
5690bbfda8aSnia
5700bbfda8aSnia
5710bbfda8aSnia		// The first time around, we focus onto the root [of the first
5720bbfda8aSnia		// Screen].  Maybe we should revisit this...
573b18c2d1eSnia		if(dpy && FirstScreen) {
5740bbfda8aSnia			// XXX This func also involves a lot of stuff that isn't
5750bbfda8aSnia			// setup yet, and probably only works by accident.  Maybe we
5760bbfda8aSnia			// should just manually extract out the couple bits we
5770bbfda8aSnia			// actually want to run?
5780bbfda8aSnia			SetFocus(NULL, CurrentTime);
5790bbfda8aSnia			FirstScreen = false;
5800bbfda8aSnia		}
5810bbfda8aSnia
5820bbfda8aSnia		// Create default icon manager memory bits (in the first
5830bbfda8aSnia		// workspace)
5840bbfda8aSnia		AllocateIconManager("TWM", "Icons", "", 1);
5850bbfda8aSnia
5860bbfda8aSnia
5870bbfda8aSnia		/*
5880bbfda8aSnia		 * Mask over the screen with our welcome window stuff if we were
5890bbfda8aSnia		 * asked to on the command line/environment; too early to get
5900bbfda8aSnia		 * info from config file about it.
5910bbfda8aSnia		 */
5920bbfda8aSnia		screenmasked = false;
593b18c2d1eSnia		if(dpy && takeover && Scr->ShowWelcomeWindow
594b18c2d1eSnia		                && (welcomefile = getenv("CTWM_WELCOME_FILE"))) {
5950bbfda8aSnia			screenmasked = true;
5960bbfda8aSnia			MaskScreen(welcomefile);
5970bbfda8aSnia		}
5980bbfda8aSnia
5990bbfda8aSnia
600b18c2d1eSnia
6010bbfda8aSnia		/*
6020bbfda8aSnia		 * Load up config file
6030bbfda8aSnia		 */
604b18c2d1eSnia		{
605b18c2d1eSnia			bool ok = LoadTwmrc(CLarg.InitFile);
606b18c2d1eSnia
607b18c2d1eSnia			// cfgchk just displays whether there are errors, then moves
608b18c2d1eSnia			// on.
609b18c2d1eSnia			if(CLarg.cfgchk) {
610b18c2d1eSnia				if(ok) {
611b18c2d1eSnia					fprintf(stderr, "%d: No errors found\n", scrnum);
612b18c2d1eSnia				}
613b18c2d1eSnia				else {
614b18c2d1eSnia					fprintf(stderr, "%d: Errors found\n", scrnum);
615b18c2d1eSnia					cfgerrs = true;
616b18c2d1eSnia				}
617b18c2d1eSnia				continue;
6180bbfda8aSnia			}
619b18c2d1eSnia
620b18c2d1eSnia			// In non-config-check mode, we historically proceed even if
621b18c2d1eSnia			// there were errors, so keep doing that...
6220bbfda8aSnia		}
623b18c2d1eSnia
624b18c2d1eSnia
625b18c2d1eSnia		// For testing, it's useful to do all that initial setup up
626b18c2d1eSnia		// through parsing, and then inspect Scr and the like.
627b18c2d1eSnia		// Long-term, IWBNI we had a better way to do all the necessary
628b18c2d1eSnia		// initialization and then call the parse ourselves at that
629b18c2d1eSnia		// level.  But for now, provide a callback func that can pass
630b18c2d1eSnia		// control back to the test code, then just exits.
631b18c2d1eSnia		if(ctwm_test_postparse != NULL) {
632b18c2d1eSnia			exit(ctwm_test_postparse());
6330bbfda8aSnia		}
6340bbfda8aSnia
6350bbfda8aSnia
636b18c2d1eSnia
6370bbfda8aSnia		/*
638b18c2d1eSnia		 * Since we've loaded the config, go ahead and take over the
639b18c2d1eSnia		 * screen.
6400bbfda8aSnia		 */
641b18c2d1eSnia		if(takeover) {
642b18c2d1eSnia			if(takeover_screen(Scr) != true) {
643b18c2d1eSnia				// Well, move on to the next one, maybe we'll get it...
644b18c2d1eSnia				if(screenmasked) {
645b18c2d1eSnia					UnmaskScreen();
646b18c2d1eSnia				}
647b18c2d1eSnia				continue;
648b18c2d1eSnia			}
6490bbfda8aSnia
650b18c2d1eSnia			// Well, we got this one
651b18c2d1eSnia			numManaged++;
652b18c2d1eSnia		}
6530bbfda8aSnia
6540bbfda8aSnia		// If the config wants us to show the splash screen and we
6550bbfda8aSnia		// haven't already, do it now.
6560bbfda8aSnia		if(Scr->ShowWelcomeWindow && !screenmasked) {
6570bbfda8aSnia			MaskScreen(NULL);
6580bbfda8aSnia		}
6590bbfda8aSnia
6600bbfda8aSnia
6610bbfda8aSnia
6620bbfda8aSnia		/*
6630bbfda8aSnia		 * Do various setup based on the results from the config file.
6640bbfda8aSnia		 */
665b18c2d1eSnia
666b18c2d1eSnia		// Few simple var defaults
6670bbfda8aSnia		if(Scr->ClickToFocus) {
6680bbfda8aSnia			Scr->FocusRoot  = false;
6690bbfda8aSnia			Scr->TitleFocus = false;
6700bbfda8aSnia		}
6710bbfda8aSnia
6720bbfda8aSnia		if(Scr->use3Dborders) {
6730bbfda8aSnia			Scr->ClientBorderWidth = false;
6740bbfda8aSnia		}
6750bbfda8aSnia
6760bbfda8aSnia
677b18c2d1eSnia		// Now that we know what Border's there may be, create our
678b18c2d1eSnia		// BorderedLayout.
679b18c2d1eSnia		Scr->BorderedLayout = RLayoutCopyCropped(Scr->Layout,
680b18c2d1eSnia		                      Scr->BorderLeft, Scr->BorderRight,
681b18c2d1eSnia		                      Scr->BorderTop, Scr->BorderBottom);
682b18c2d1eSnia		if(Scr->BorderedLayout == NULL) {
683b18c2d1eSnia			Scr->BorderedLayout = Scr->Layout;        // nothing to crop
684b18c2d1eSnia		}
685b18c2d1eSnia		else if(Scr->BorderedLayout->monitors->len == 0) {
686b18c2d1eSnia			fprintf(stderr,
687b18c2d1eSnia			        "Borders too large! correct BorderLeft, BorderRight, BorderTop and/or BorderBottom parameters\n");
688b18c2d1eSnia			exit(1);
689b18c2d1eSnia		}
690b18c2d1eSnia#ifdef DEBUG
691b18c2d1eSnia		fprintf(stderr, "Bordered: ");
692b18c2d1eSnia		RLayoutPrint(Scr->BorderedLayout);
693b18c2d1eSnia#endif
694b18c2d1eSnia
695b18c2d1eSnia
696b18c2d1eSnia		/*
697b18c2d1eSnia		 * Setup stuff relating to VirtualScreens.  If something to do
698b18c2d1eSnia		 * with it is set in the config, this all implements stuff needed
699b18c2d1eSnia		 * for that.  If not, InitVirtualScreens() creates a single one
700b18c2d1eSnia		 * mirroring our real root.
701b18c2d1eSnia		 */
702b18c2d1eSnia		InitVirtualScreens(Scr);
703b18c2d1eSnia#ifdef VSCREEN
704b18c2d1eSnia#ifdef EWMH
705b18c2d1eSnia		EwmhInitVirtualRoots(Scr);
706b18c2d1eSnia#endif /* EWMH */
707b18c2d1eSnia#endif // vscreen
708b18c2d1eSnia
709b18c2d1eSnia		// Setup WSM[s] (per-vscreen).  This also sets up the about the
710b18c2d1eSnia		// workspaces for each vscreen and which is currently displayed.
711b18c2d1eSnia		ConfigureWorkSpaceManager(Scr);
712b18c2d1eSnia
713b18c2d1eSnia
7140bbfda8aSnia		/*
7150bbfda8aSnia		 * Various decoration default overrides for 3d/2d.  Values that
7160bbfda8aSnia		 * [presumtively] look "nice" on 75/100dpi displays.  -100 is a
7170bbfda8aSnia		 * sentinel value we set before the config file parsing; since
7180bbfda8aSnia		 * these defaults differ for 3d vs not, we can't just set them as
7190bbfda8aSnia		 * default before the parse.
7200bbfda8aSnia		 */
7210bbfda8aSnia#define SETDEF(fld, num) if(Scr->fld == -100) { Scr->fld = num; }
7220bbfda8aSnia		if(Scr->use3Dtitles) {
7230bbfda8aSnia			SETDEF(FramePadding,  0);
7240bbfda8aSnia			SETDEF(TitlePadding,  0);
7250bbfda8aSnia			SETDEF(ButtonIndent,  0);
7260bbfda8aSnia			SETDEF(TBInfo.border, 0);
7270bbfda8aSnia		}
7280bbfda8aSnia		else {
7290bbfda8aSnia			SETDEF(FramePadding,  2);
7300bbfda8aSnia			SETDEF(TitlePadding,  8);
7310bbfda8aSnia			SETDEF(ButtonIndent,  1);
7320bbfda8aSnia			SETDEF(TBInfo.border, 1);
7330bbfda8aSnia		}
7340bbfda8aSnia#undef SETDEF
7350bbfda8aSnia
7360bbfda8aSnia		// These values are meaningless in !3d cases, so always zero them
7370bbfda8aSnia		// out.
7380bbfda8aSnia		if(! Scr->use3Dtitles) {
7390bbfda8aSnia			Scr->TitleShadowDepth       = 0;
7400bbfda8aSnia			Scr->TitleButtonShadowDepth = 0;
7410bbfda8aSnia		}
7420bbfda8aSnia		if(! Scr->use3Dborders) {
7430bbfda8aSnia			Scr->BorderShadowDepth = 0;
7440bbfda8aSnia		}
7450bbfda8aSnia		if(! Scr->use3Dmenus) {
7460bbfda8aSnia			Scr->MenuShadowDepth = 0;
7470bbfda8aSnia		}
7480bbfda8aSnia		if(! Scr->use3Diconmanagers) {
7490bbfda8aSnia			Scr->IconManagerShadowDepth = 0;
7500bbfda8aSnia		}
7510bbfda8aSnia		if(! Scr->use3Dborders) {
7520bbfda8aSnia			Scr->ThreeDBorderWidth = 0;
7530bbfda8aSnia		}
7540bbfda8aSnia
7550bbfda8aSnia		// Setup colors stuff
7560bbfda8aSnia		if(!Scr->BeNiceToColormap) {
7570bbfda8aSnia			// Default pair
7580bbfda8aSnia			GetShadeColors(&Scr->DefaultC);
7590bbfda8aSnia
7600bbfda8aSnia			// Various conditionally 3d bits
7610bbfda8aSnia			if(Scr->use3Dtitles) {
7620bbfda8aSnia				GetShadeColors(&Scr->TitleC);
7630bbfda8aSnia			}
7640bbfda8aSnia			if(Scr->use3Dmenus) {
7650bbfda8aSnia				GetShadeColors(&Scr->MenuC);
7660bbfda8aSnia			}
7670bbfda8aSnia			if(Scr->use3Dmenus) {
7680bbfda8aSnia				GetShadeColors(&Scr->MenuTitleC);
7690bbfda8aSnia			}
7700bbfda8aSnia			if(Scr->use3Dborders) {
7710bbfda8aSnia				GetShadeColors(&Scr->BorderColorC);
7720bbfda8aSnia			}
7730bbfda8aSnia		}
7740bbfda8aSnia
7750bbfda8aSnia		// Defaults for IconRegion bits that aren't set.
7760bbfda8aSnia		for(IconRegion *ir = Scr->FirstRegion; ir; ir = ir->next) {
7770bbfda8aSnia			if(ir->TitleJustification == TJ_UNDEF) {
7780bbfda8aSnia				ir->TitleJustification = Scr->IconJustification;
7790bbfda8aSnia			}
7800bbfda8aSnia			if(ir->Justification == IRJ_UNDEF) {
7810bbfda8aSnia				ir->Justification = Scr->IconRegionJustification;
7820bbfda8aSnia			}
7830bbfda8aSnia			if(ir->Alignement == IRA_UNDEF) {
7840bbfda8aSnia				ir->Alignement = Scr->IconRegionAlignement;
7850bbfda8aSnia			}
7860bbfda8aSnia		}
7870bbfda8aSnia
7880bbfda8aSnia		// Put the results of SaveColor{} into _MIT_PRIORITY_COLORS.
7890bbfda8aSnia		assign_var_savecolor();
7900bbfda8aSnia
7910bbfda8aSnia		// Setup cursor values that weren't give in the config
7920bbfda8aSnia#define DEFCURSOR(name, val) if(!Scr->name) NewFontCursor(&Scr->name, val)
7930bbfda8aSnia		DEFCURSOR(FrameCursor,   "top_left_arrow");
7940bbfda8aSnia		DEFCURSOR(TitleCursor,   "top_left_arrow");
7950bbfda8aSnia		DEFCURSOR(IconCursor,    "top_left_arrow");
7960bbfda8aSnia		DEFCURSOR(IconMgrCursor, "top_left_arrow");
7970bbfda8aSnia		DEFCURSOR(MoveCursor,    "fleur");
7980bbfda8aSnia		DEFCURSOR(ResizeCursor,  "fleur");
7990bbfda8aSnia		DEFCURSOR(MenuCursor,    "sb_left_arrow");
8000bbfda8aSnia		DEFCURSOR(ButtonCursor,  "hand2");
8010bbfda8aSnia		DEFCURSOR(WaitCursor,    "watch");
8020bbfda8aSnia		DEFCURSOR(SelectCursor,  "dot");
8030bbfda8aSnia		DEFCURSOR(DestroyCursor, "pirate");
8040bbfda8aSnia		DEFCURSOR(AlterCursor,   "question_arrow");
8050bbfda8aSnia#undef DEFCURSOR
8060bbfda8aSnia
8070bbfda8aSnia		// Load up fonts for the screen.
8080bbfda8aSnia		//
8090bbfda8aSnia		// XXX HaveFonts is kinda stupid, however it gets useful in one
8100bbfda8aSnia		// place: when loading button bindings, we make some sort of
8110bbfda8aSnia		// "menu" for things (x-ref GotButton()), and the menu gen code
8120bbfda8aSnia		// needs to load font stuff, so if that happened in the config
8130bbfda8aSnia		// process, we would have already run CreateFonts().  Of course,
8140bbfda8aSnia		// that's a order-dependent bit of the config file parsing too;
8150bbfda8aSnia		// if you define the fonts too late, they wouldn't have been set
8160bbfda8aSnia		// by then, and we won't [re]try them now...    arg.
8170bbfda8aSnia		if(!Scr->HaveFonts) {
8180bbfda8aSnia			CreateFonts(Scr);
8190bbfda8aSnia		}
8200bbfda8aSnia
8210bbfda8aSnia		// Adjust settings for titlebar.  Must follow CreateFonts() call
8220bbfda8aSnia		// so we know these bits are populated
8230bbfda8aSnia		Scr->TitleBarFont.y += Scr->FramePadding;
8240bbfda8aSnia		Scr->TitleHeight = Scr->TitleBarFont.height + Scr->FramePadding * 2;
8250bbfda8aSnia		if(Scr->use3Dtitles) {
8260bbfda8aSnia			Scr->TitleHeight += 2 * Scr->TitleShadowDepth;
8270bbfda8aSnia		}
8280bbfda8aSnia		/* make title height be odd so buttons look nice and centered */
8290bbfda8aSnia		if(!(Scr->TitleHeight & 1)) {
8300bbfda8aSnia			Scr->TitleHeight++;
8310bbfda8aSnia		}
8320bbfda8aSnia
833b18c2d1eSnia
834b18c2d1eSnia
835b18c2d1eSnia		/*
836b18c2d1eSnia		 * Now we can start making various things.
837b18c2d1eSnia		 */
838b18c2d1eSnia
839b18c2d1eSnia		// Stash up a ref to our Scr on the root, so we can find the
840b18c2d1eSnia		// right Scr for events etc.
841b18c2d1eSnia		XSaveContext(dpy, Scr->Root, ScreenContext, (XPointer) Scr);
842b18c2d1eSnia
8430bbfda8aSnia		// Setup GC's for drawing, so we can start making stuff we have
8440bbfda8aSnia		// to actually draw.  Could move earlier, has to preceed a lot of
8450bbfda8aSnia		// following.
8460bbfda8aSnia		CreateGCs();
8470bbfda8aSnia
8480bbfda8aSnia		// Create and draw the menus we config'd
8490bbfda8aSnia		MakeMenus();
8500bbfda8aSnia
8510bbfda8aSnia		// Load up the images for titlebar buttons
8520bbfda8aSnia		InitTitlebarButtons();
8530bbfda8aSnia
8540bbfda8aSnia		// Allocate controls for WindowRegion's.  Has to follow
8550bbfda8aSnia		// workspaces setup, but doesn't talk to X.
8560bbfda8aSnia		CreateWindowRegions();
8570bbfda8aSnia
8580bbfda8aSnia		// Copy the icon managers over to workspaces past the first as
8590bbfda8aSnia		// necessary.  AllocateIconManager() and the config parsing
8600bbfda8aSnia		// already made them on the first WS.
8610bbfda8aSnia		AllocateOtherIconManagers();
8620bbfda8aSnia
8630bbfda8aSnia		// Create the windows for our icon managers now that all our
8640bbfda8aSnia		// tracking for it is setup.
8650bbfda8aSnia		CreateIconManagers();
8660bbfda8aSnia
8670bbfda8aSnia		// Create the WSM window (per-vscreen) and stash info on the root
8680bbfda8aSnia		// about our WS's.
8690bbfda8aSnia		CreateWorkSpaceManager();
8700bbfda8aSnia
8710bbfda8aSnia		// Create the f.occupy window
8720bbfda8aSnia		CreateOccupyWindow();
8730bbfda8aSnia
8740bbfda8aSnia		// Setup TwmWorkspaces menu.  Needs workspaces setup, as well as
8750bbfda8aSnia		// menus made.
8760bbfda8aSnia		MakeWorkspacesMenu();
8770bbfda8aSnia
878b18c2d1eSnia#ifdef WINBOX
8790bbfda8aSnia		// setup WindowBox's
8800bbfda8aSnia		createWindowBoxes();
881b18c2d1eSnia#endif
8820bbfda8aSnia
8830bbfda8aSnia		// Initialize Xrm stuff; things with setting occupation etc use
8840bbfda8aSnia		// Xrm bits.
8850bbfda8aSnia		XrmInitialize();
8860bbfda8aSnia
8870bbfda8aSnia#ifdef EWMH
8880bbfda8aSnia		// Set EWMH-related properties on various root-ish windows, for
8890bbfda8aSnia		// other programs to read to find out how we view the world.
8900bbfda8aSnia		EwmhInitScreenLate(Scr);
8910bbfda8aSnia#endif /* EWMH */
8920bbfda8aSnia
8930bbfda8aSnia
8940bbfda8aSnia		/*
8950bbfda8aSnia		 * Look up and handle all the windows on the screen.
8960bbfda8aSnia		 */
8970bbfda8aSnia		{
8980bbfda8aSnia			Window parent, *children;
8990bbfda8aSnia			unsigned int nchildren;
9000bbfda8aSnia
9010bbfda8aSnia			XQueryTree(dpy, Scr->Root, &croot, &parent, &children, &nchildren);
9020bbfda8aSnia
9030bbfda8aSnia			/* Weed out icon windows */
9040bbfda8aSnia			for(int i = 0; i < nchildren; i++) {
9050bbfda8aSnia				if(children[i]) {
9060bbfda8aSnia					XWMHints *wmhintsp = XGetWMHints(dpy, children[i]);
9070bbfda8aSnia
9080bbfda8aSnia					if(wmhintsp) {
9090bbfda8aSnia						if(wmhintsp->flags & IconWindowHint) {
9100bbfda8aSnia							for(int j = 0; j < nchildren; j++) {
9110bbfda8aSnia								if(children[j] == wmhintsp->icon_window) {
9120bbfda8aSnia									children[j] = None;
9130bbfda8aSnia									break;
9140bbfda8aSnia								}
9150bbfda8aSnia							}
9160bbfda8aSnia						}
9170bbfda8aSnia						XFree(wmhintsp);
9180bbfda8aSnia					}
9190bbfda8aSnia				}
9200bbfda8aSnia			}
9210bbfda8aSnia
9220bbfda8aSnia			/*
9230bbfda8aSnia			 * Map all of the non-override windows.  This winds down
9240bbfda8aSnia			 * into AddWindow() and friends through SimulateMapRequest(),
9250bbfda8aSnia			 * so this is where we actually adopt the windows on the
9260bbfda8aSnia			 * screen.
9270bbfda8aSnia			 */
9280bbfda8aSnia			for(int i = 0; i < nchildren; i++) {
9290bbfda8aSnia				if(children[i] && MappedNotOverride(children[i])) {
9300bbfda8aSnia					XUnmapWindow(dpy, children[i]);
9310bbfda8aSnia					SimulateMapRequest(children[i]);
9320bbfda8aSnia				}
9330bbfda8aSnia			}
9340bbfda8aSnia
9350bbfda8aSnia			/*
9360bbfda8aSnia			 * At this point, we've adopted all the windows currently on
9370bbfda8aSnia			 * the screen (aside from those we're intentionally not).
9380bbfda8aSnia			 * Note that this happens _before_ the various other windows
9390bbfda8aSnia			 * we create below, which is why they don't wind up getting
9400bbfda8aSnia			 * TwmWindow's tied to them or show up in icon managers, etc.
9410bbfda8aSnia			 * We'd need to actually make it _explicit_ that those
9420bbfda8aSnia			 * windows aren't tracked by us if we changed that order...
9430bbfda8aSnia			 */
9440bbfda8aSnia		}
9450bbfda8aSnia
9460bbfda8aSnia
9470bbfda8aSnia		// Show the WSM window if we should
9480bbfda8aSnia		if(Scr->ShowWorkspaceManager && Scr->workSpaceManagerActive) {
9490bbfda8aSnia			VirtualScreen *vs;
9500bbfda8aSnia			if(Scr->WindowMask) {
9510bbfda8aSnia				XRaiseWindow(dpy, Scr->WindowMask);
9520bbfda8aSnia			}
9530bbfda8aSnia			for(vs = Scr->vScreenList; vs != NULL; vs = vs->next) {
9540bbfda8aSnia				SetMapStateProp(vs->wsw->twm_win, NormalState);
9550bbfda8aSnia				XMapWindow(dpy, vs->wsw->twm_win->frame);
9560bbfda8aSnia				if(vs->wsw->twm_win->StartSqueezed) {
9570bbfda8aSnia					Squeeze(vs->wsw->twm_win);
9580bbfda8aSnia				}
9590bbfda8aSnia				else {
9600bbfda8aSnia					XMapWindow(dpy, vs->wsw->w);
9610bbfda8aSnia				}
9620bbfda8aSnia				vs->wsw->twm_win->mapped = true;
9630bbfda8aSnia			}
9640bbfda8aSnia		}
9650bbfda8aSnia
9660bbfda8aSnia
9670bbfda8aSnia		/*
9680bbfda8aSnia		 * Setup the Info window, used for f.identify and f.version.
9690bbfda8aSnia		 */
9700bbfda8aSnia		{
9710bbfda8aSnia			unsigned long valuemask;
9720bbfda8aSnia			XSetWindowAttributes attributes;
9730bbfda8aSnia
9740bbfda8aSnia			attributes.border_pixel = Scr->DefaultC.fore;
9750bbfda8aSnia			attributes.background_pixel = Scr->DefaultC.back;
9760bbfda8aSnia			attributes.event_mask = (ExposureMask | ButtonPressMask |
9770bbfda8aSnia			                         KeyPressMask | ButtonReleaseMask);
9780bbfda8aSnia			NewFontCursor(&attributes.cursor, "hand2");
9790bbfda8aSnia			valuemask = (CWBorderPixel | CWBackPixel | CWEventMask | CWCursor);
9800bbfda8aSnia			Scr->InfoWindow.win =
9810bbfda8aSnia			        XCreateWindow(dpy, Scr->Root, 0, 0,
9820bbfda8aSnia			                      5, 5,
9830bbfda8aSnia			                      0, 0,
9840bbfda8aSnia			                      CopyFromParent, CopyFromParent,
9850bbfda8aSnia			                      valuemask, &attributes);
9860bbfda8aSnia		}
9870bbfda8aSnia
9880bbfda8aSnia
9890bbfda8aSnia		/*
9900bbfda8aSnia		 * Setup the Size/Position window for showing during resize/move
9910bbfda8aSnia		 * operations.
9920bbfda8aSnia		 */
9930bbfda8aSnia		{
994b18c2d1eSnia			// Stick the SizeWindow at the top left of the first monitor
995b18c2d1eSnia			// we found on this Screen.  That _may_ not be (0,0) (imagine
996b18c2d1eSnia			// a shorter left and taller right monitor, with their bottom
997b18c2d1eSnia			// edges lined up instead of top), so we have to look up what
998b18c2d1eSnia			// that coordinate is.  If we're CenterFeedbackWindow'ing,
999b18c2d1eSnia			// the window will have to move between monitors depending on
1000b18c2d1eSnia			// where the window we're moving is (starts), but
1001b18c2d1eSnia			// MoveResizeSizeWindow() will handle that.  If not, it
1002b18c2d1eSnia			// always stays in the top-left of the first display.
1003b18c2d1eSnia			RArea area = RLayoutGetAreaIndex(Scr->Layout, 0);
10040bbfda8aSnia			XRectangle ink_rect;
10050bbfda8aSnia			XRectangle logical_rect;
10060bbfda8aSnia			unsigned long valuemask;
10070bbfda8aSnia			XSetWindowAttributes attributes;
10080bbfda8aSnia
10090bbfda8aSnia			XmbTextExtents(Scr->SizeFont.font_set,
10100bbfda8aSnia			               " 8888 x 8888 ", 13,
10110bbfda8aSnia			               &ink_rect, &logical_rect);
10120bbfda8aSnia			Scr->SizeStringWidth = logical_rect.width;
10130bbfda8aSnia			valuemask = (CWBorderPixel | CWBackPixel | CWBitGravity);
10140bbfda8aSnia			attributes.bit_gravity = NorthWestGravity;
10150bbfda8aSnia
1016b18c2d1eSnia			if(Scr->SaveUnder) {
1017b18c2d1eSnia				attributes.save_under = True;
1018b18c2d1eSnia				valuemask |= CWSaveUnder;
10190bbfda8aSnia			}
1020b18c2d1eSnia
1021b18c2d1eSnia			Scr->SizeWindow = XCreateWindow(dpy, Scr->Root,
1022b18c2d1eSnia			                                area.x, area.y,
10230bbfda8aSnia			                                Scr->SizeStringWidth,
10240bbfda8aSnia			                                (Scr->SizeFont.height +
10250bbfda8aSnia			                                 SIZE_VINDENT * 2),
10260bbfda8aSnia			                                0, 0,
10270bbfda8aSnia			                                CopyFromParent,
10280bbfda8aSnia			                                CopyFromParent,
10290bbfda8aSnia			                                valuemask, &attributes);
10300bbfda8aSnia		}
10310bbfda8aSnia
10320bbfda8aSnia		// Create util window used in animation
10330bbfda8aSnia		Scr->ShapeWindow = XCreateSimpleWindow(dpy, Scr->Root, 0, 0,
10340bbfda8aSnia		                                       Scr->rootw, Scr->rooth, 0, 0, 0);
10350bbfda8aSnia
10360bbfda8aSnia
10370bbfda8aSnia		// Clear out the splash screen if we had one
10380bbfda8aSnia		if(Scr->ShowWelcomeWindow) {
10390bbfda8aSnia			UnmaskScreen();
10400bbfda8aSnia		}
10410bbfda8aSnia
10420bbfda8aSnia		// Done setting up this Screen.  x-ref XXX's about whether this
10430bbfda8aSnia		// element is worth anything...
10440bbfda8aSnia		Scr->FirstTime = false;
10450bbfda8aSnia	} // for each screen on display
10460bbfda8aSnia
10470bbfda8aSnia
1048b18c2d1eSnia	// If we're just checking the config, there's nothing more to do.
1049b18c2d1eSnia	if(CLarg.cfgchk) {
1050b18c2d1eSnia		exit(cfgerrs);
1051b18c2d1eSnia	}
1052b18c2d1eSnia
1053b18c2d1eSnia
10540bbfda8aSnia	// We're not much of a window manager if we didn't get stuff to
10550bbfda8aSnia	// manage...
10560bbfda8aSnia	if(numManaged == 0) {
10570bbfda8aSnia		if(CLarg.MultiScreen && NumScreens > 0)
10580bbfda8aSnia			fprintf(stderr, "%s:  unable to find any unmanaged screens\n",
10590bbfda8aSnia			        ProgramName);
10600bbfda8aSnia		exit(1);
10610bbfda8aSnia	}
10620bbfda8aSnia
1063b18c2d1eSnia#ifdef SESSION
10640bbfda8aSnia	// Hook up session
10650bbfda8aSnia	ConnectToSessionManager(CLarg.client_id);
1066b18c2d1eSnia#endif
10670bbfda8aSnia
10680bbfda8aSnia#ifdef SOUNDS
10690bbfda8aSnia	// Announce ourselves
10700bbfda8aSnia	sound_load_list();
10710bbfda8aSnia	play_startup_sound();
10720bbfda8aSnia#endif
10730bbfda8aSnia
10740bbfda8aSnia	// Hard-reset this flag.
10750bbfda8aSnia	// XXX This doesn't seem right?
10760bbfda8aSnia	RestartPreviousState = true;
10770bbfda8aSnia
1078b18c2d1eSnia	// Set vars to enable animation bits
10790bbfda8aSnia	StartAnimation();
10800bbfda8aSnia
10810bbfda8aSnia	// Main loop.
1082b18c2d1eSnia	HandlingEvents = true;
10830bbfda8aSnia	HandleEvents();
10840bbfda8aSnia
10850bbfda8aSnia	// Should never get here...
10860bbfda8aSnia	fprintf(stderr, "Shouldn't return from HandleEvents()!\n");
10870bbfda8aSnia	exit(1);
10880bbfda8aSnia}
10890bbfda8aSnia
10900bbfda8aSnia
1091b18c2d1eSnia
10920bbfda8aSnia/**
10930bbfda8aSnia * Initialize ScreenInfo for a Screen.  This allocates the struct,
10940bbfda8aSnia * assigns in the info we pass it about the screen and dimensions, and
10950bbfda8aSnia * then puts in our various default/fallback/sentinel/etc values to
10960bbfda8aSnia * prepare it for later use.
10970bbfda8aSnia *
10980bbfda8aSnia * It is intentional that this doesn't do any of the initialization that
10990bbfda8aSnia * involves calling out to X functions; it operates as a pure function.
11000bbfda8aSnia * This makes it easier to use it to fake up a ScreenInfo for something
11010bbfda8aSnia * that isn't actually an X Screen, for testing etc.
11020bbfda8aSnia *
11030bbfda8aSnia * \param scrnum The Screen number (e.g, :0.0 -> 0)
11040bbfda8aSnia * \param croot  The X Window for the Screen's root window
11050bbfda8aSnia * \param crootx Root X coordinate
11060bbfda8aSnia * \param crooty Root Y coordinate
11070bbfda8aSnia * \param crootw Root width
11080bbfda8aSnia * \param crooth Root height
11090bbfda8aSnia * \return Allocated and populated ScreenInfo
11100bbfda8aSnia */
11110bbfda8aSniaScreenInfo *
11120bbfda8aSniaInitScreenInfo(int scrnum, Window croot, int crootx, int crooty,
11130bbfda8aSnia               unsigned int crootw, unsigned int crooth)
11140bbfda8aSnia{
11150bbfda8aSnia	ScreenInfo *scr;
11160bbfda8aSnia	scr = calloc(1, sizeof(ScreenInfo));
11170bbfda8aSnia	if(scr == NULL) {
11180bbfda8aSnia		return NULL;
11190bbfda8aSnia	}
11200bbfda8aSnia	// Because of calloc(), it's already all 0 bytes, which are NULL and
11210bbfda8aSnia	// false and 0 and similar.  Some following initializations are
11220bbfda8aSnia	// nugatory because of that, but are left for clarity.
11230bbfda8aSnia
11240bbfda8aSnia	// Poison the global Scr to protect against typos
11250bbfda8aSnia#define Scr StupidProgrammer
11260bbfda8aSnia
11270bbfda8aSnia
11280bbfda8aSnia	// Basic pieces about the X screen we're talking about, and some
11290bbfda8aSnia	// derived dimension-related bits.
11300bbfda8aSnia	scr->screen = scrnum;
11310bbfda8aSnia	scr->XineramaRoot = scr->Root = croot;
1132b18c2d1eSnia	scr->rootx = crootx;
1133b18c2d1eSnia	scr->rooty = crooty;
1134b18c2d1eSnia	scr->rootw = crootw;
1135b18c2d1eSnia	scr->rooth = crooth;
1136b18c2d1eSnia
1137b18c2d1eSnia#ifdef CAPTIVE
1138b18c2d1eSnia	scr->crootx = crootx;
1139b18c2d1eSnia	scr->crooty = crooty;
1140b18c2d1eSnia	scr->crootw = crootw;
1141b18c2d1eSnia	scr->crooth = crooth;
1142b18c2d1eSnia#endif
11430bbfda8aSnia
11440bbfda8aSnia	// Don't allow icon titles wider than the screen
11450bbfda8aSnia	scr->MaxIconTitleWidth = scr->rootw;
11460bbfda8aSnia
11470bbfda8aSnia	// Attempt to come up with a sane default for the max sizes.  Start
11480bbfda8aSnia	// by limiting so that a window with its left/top on the right/bottom
11490bbfda8aSnia	// edge of the screen can't extend further than X can address (signed
11500bbfda8aSnia	// 16-bit).  However, when your screen size starts approaching that
11510bbfda8aSnia	// limit, reducing the max window sizes too much gets stupid too, so
11520bbfda8aSnia	// set an arbitrary floor on how low this will take it.
11530bbfda8aSnia	// MaxWindowSize in the config will override whatever's here anyway.
11540bbfda8aSnia	scr->MaxWindowWidth  = 32767 - (scr->rootx + scr->rootw);
11550bbfda8aSnia	scr->MaxWindowHeight = 32767 - (scr->rooty + scr->rooth);
11560bbfda8aSnia	if(scr->MaxWindowWidth < 4096) {
11570bbfda8aSnia		scr->MaxWindowWidth = 4096;
11580bbfda8aSnia	}
11590bbfda8aSnia	if(scr->MaxWindowHeight < 4096) {
11600bbfda8aSnia		scr->MaxWindowHeight = 4096;
11610bbfda8aSnia	}
11620bbfda8aSnia
11630bbfda8aSnia
11640bbfda8aSnia	// Flags used in the code to keep track of where in various processes
11650bbfda8aSnia	// (especially startup) we are.
11660bbfda8aSnia	scr->HaveFonts = false;
11670bbfda8aSnia
11680bbfda8aSnia	// Flag which basically means "initial screen setup time".
11690bbfda8aSnia	// XXX Not clear to what extent this should even exist; a lot of
11700bbfda8aSnia	// uses are fairly bogus.
11710bbfda8aSnia	scr->FirstTime = true;
11720bbfda8aSnia
11730bbfda8aSnia	// Sentinel values for defaulting config values
11740bbfda8aSnia	scr->FramePadding = -100;
11750bbfda8aSnia	scr->TitlePadding = -100;
11760bbfda8aSnia	scr->ButtonIndent = -100;
11770bbfda8aSnia	scr->TBInfo.border = -100;
11780bbfda8aSnia
11790bbfda8aSnia	// Default values for all sorts of config params
11800bbfda8aSnia	scr->SizeStringOffset = 0;
11810bbfda8aSnia	scr->ThreeDBorderWidth = 6;
11820bbfda8aSnia	scr->BorderWidth = BW;
11830bbfda8aSnia	scr->IconBorderWidth = BW;
11840bbfda8aSnia	scr->NumAutoRaises = 0;
11850bbfda8aSnia	scr->NumAutoLowers = 0;
11860bbfda8aSnia	scr->TransientOnTop = 30;
11870bbfda8aSnia	scr->NoDefaults = false;
11880bbfda8aSnia	scr->UsePPosition = PPOS_OFF;
11890bbfda8aSnia	scr->UseSunkTitlePixmap = false;
11900bbfda8aSnia	scr->FocusRoot = true;
11910bbfda8aSnia	scr->WarpCursor = false;
11920bbfda8aSnia	scr->ForceIcon = false;
11930bbfda8aSnia	scr->NoGrabServer = true;
11940bbfda8aSnia	scr->NoRaiseMove = false;
11950bbfda8aSnia	scr->NoRaiseResize = false;
11960bbfda8aSnia	scr->NoRaiseDeicon = false;
11970bbfda8aSnia	scr->RaiseOnWarp = true;
11980bbfda8aSnia	scr->DontMoveOff = false;
11990bbfda8aSnia	scr->DoZoom = false;
12000bbfda8aSnia	scr->TitleFocus = true;
12010bbfda8aSnia	scr->IconManagerFocus = true;
12020bbfda8aSnia	scr->StayUpMenus = false;
12030bbfda8aSnia	scr->WarpToDefaultMenuEntry = false;
12040bbfda8aSnia	scr->ClickToFocus = false;
12050bbfda8aSnia	scr->SloppyFocus = false;
12060bbfda8aSnia	scr->SaveWorkspaceFocus = false;
12070bbfda8aSnia	scr->NoIconTitlebar = false;
12080bbfda8aSnia	scr->NoTitlebar = false;
12090bbfda8aSnia	scr->DecorateTransients = true;
12100bbfda8aSnia	scr->IconifyByUnmapping = false;
12110bbfda8aSnia	scr->ShowIconManager = false;
12120bbfda8aSnia	scr->ShowWorkspaceManager = false;
12130bbfda8aSnia	scr->WMgrButtonShadowDepth = 2;
12140bbfda8aSnia	scr->WMgrVertButtonIndent  = 5;
12150bbfda8aSnia	scr->WMgrHorizButtonIndent = 5;
12160bbfda8aSnia	scr->BorderShadowDepth = 2;
12170bbfda8aSnia	scr->TitleShadowDepth = 2;
12180bbfda8aSnia	scr->TitleButtonShadowDepth = 2;
12190bbfda8aSnia	scr->MenuShadowDepth = 2;
12200bbfda8aSnia	scr->IconManagerShadowDepth = 2;
12210bbfda8aSnia	scr->AutoOccupy = false;
12220bbfda8aSnia	scr->TransientHasOccupation = false;
12230bbfda8aSnia	scr->DontPaintRootWindow = false;
12240bbfda8aSnia	scr->IconManagerDontShow = false;
12250bbfda8aSnia	scr->BackingStore = false;
12260bbfda8aSnia	scr->SaveUnder = true;
12270bbfda8aSnia	scr->RandomPlacement = RP_ALL;
12280bbfda8aSnia	scr->RandomDisplacementX = 30;
12290bbfda8aSnia	scr->RandomDisplacementY = 30;
12300bbfda8aSnia	scr->DoOpaqueMove = true;
12310bbfda8aSnia	scr->OpaqueMove = false;
12320bbfda8aSnia	scr->OpaqueMoveThreshold = 200;
12330bbfda8aSnia	scr->OpaqueResize = false;
12340bbfda8aSnia	scr->DoOpaqueResize = true;
12350bbfda8aSnia	scr->OpaqueResizeThreshold = 1000;
12360bbfda8aSnia	scr->Highlight = true;
12370bbfda8aSnia	scr->StackMode = true;
12380bbfda8aSnia	scr->TitleHighlight = true;
12390bbfda8aSnia	scr->MoveDelta = 1;
12400bbfda8aSnia	scr->MoveOffResistance = -1;
12410bbfda8aSnia	scr->MovePackResistance = 20;
12420bbfda8aSnia	scr->ZoomCount = 8;
12430bbfda8aSnia	scr->SortIconMgr = true;
12440bbfda8aSnia	scr->Shadow = true;
12450bbfda8aSnia	scr->InterpolateMenuColors = false;
12460bbfda8aSnia	scr->NoIconManagers = false;
12470bbfda8aSnia	scr->ClientBorderWidth = false;
12480bbfda8aSnia	scr->SqueezeTitle = false;
12490bbfda8aSnia	scr->FirstTime = true;
12500bbfda8aSnia	scr->CaseSensitive = true;
12510bbfda8aSnia	scr->WarpUnmapped = false;
12520bbfda8aSnia	scr->WindowRingAll = false;
12530bbfda8aSnia	scr->WarpRingAnyWhere = true;
12540bbfda8aSnia	scr->ShortAllWindowsMenus = false;
12550bbfda8aSnia	scr->use3Diconmanagers = false;
12560bbfda8aSnia	scr->use3Dmenus = false;
12570bbfda8aSnia	scr->use3Dtitles = false;
12580bbfda8aSnia	scr->use3Dborders = false;
12590bbfda8aSnia	scr->use3Dwmap = false;
12600bbfda8aSnia	scr->SunkFocusWindowTitle = false;
12610bbfda8aSnia	scr->ClearShadowContrast = 50;
12620bbfda8aSnia	scr->DarkShadowContrast  = 40;
12630bbfda8aSnia	scr->BeNiceToColormap = false;
12640bbfda8aSnia	scr->BorderCursors = false;
12650bbfda8aSnia	scr->IconJustification = TJ_CENTER;
12660bbfda8aSnia	scr->IconRegionJustification = IRJ_CENTER;
12670bbfda8aSnia	scr->IconRegionAlignement = IRA_CENTER;
12680bbfda8aSnia	scr->TitleJustification = TJ_LEFT;
12690bbfda8aSnia	scr->IconifyStyle = ICONIFY_NORMAL;
12700bbfda8aSnia	scr->ReallyMoveInWorkspaceManager = false;
12710bbfda8aSnia	scr->ShowWinWhenMovingInWmgr = false;
12720bbfda8aSnia	scr->ReverseCurrentWorkspace = false;
12730bbfda8aSnia	scr->DontWarpCursorInWMap = false;
12740bbfda8aSnia	scr->XMoveGrid = 1;
12750bbfda8aSnia	scr->YMoveGrid = 1;
12760bbfda8aSnia	scr->CenterFeedbackWindow = false;
12770bbfda8aSnia	scr->ShrinkIconTitles = false;
12780bbfda8aSnia	scr->AutoRaiseIcons = false;
12790bbfda8aSnia	scr->AutoFocusToTransients = false;
12800bbfda8aSnia	scr->OpenWindowTimeout = 0;
12810bbfda8aSnia	scr->RaiseWhenAutoUnSqueeze = false;
12820bbfda8aSnia	scr->RaiseOnClick = false;
12830bbfda8aSnia	scr->RaiseOnClickButton = 1;
12840bbfda8aSnia	scr->IgnoreModifier = 0;
12850bbfda8aSnia	scr->IgnoreCaseInMenuSelection = false;
12860bbfda8aSnia	scr->PackNewWindows = false;
12870bbfda8aSnia	scr->AlwaysSqueezeToGravity = false;
12880bbfda8aSnia	scr->NoWarpToMenuTitle = false;
12890bbfda8aSnia	scr->DontToggleWorkspaceManagerState = false;
12900bbfda8aSnia	scr->NameDecorations = true;
12910bbfda8aSnia	scr->ForceFocus = false;
12920bbfda8aSnia	scr->BorderTop    = 0;
12930bbfda8aSnia	scr->BorderBottom = 0;
12940bbfda8aSnia	scr->BorderLeft   = 0;
12950bbfda8aSnia	scr->BorderRight  = 0;
12960bbfda8aSnia	scr->PixmapDirectory   = PIXMAP_DIRECTORY;
12970bbfda8aSnia#ifdef EWMH
12980bbfda8aSnia	scr->PreferredIconWidth = 48;
12990bbfda8aSnia	scr->PreferredIconHeight = 48;
1300b18c2d1eSnia
1301b18c2d1eSnia	scr->ewmh_CLIENT_LIST_used = 0;
1302b18c2d1eSnia	scr->ewmh_CLIENT_LIST_size = 16;
1303b18c2d1eSnia	scr->ewmh_CLIENT_LIST = calloc(scr->ewmh_CLIENT_LIST_size,
1304b18c2d1eSnia	                               sizeof(scr->ewmh_CLIENT_LIST[0]));
1305b18c2d1eSnia	if(scr->ewmh_CLIENT_LIST == NULL) {
1306b18c2d1eSnia		free(scr);
1307b18c2d1eSnia		return NULL;
1308b18c2d1eSnia	}
13090bbfda8aSnia#endif
13100bbfda8aSnia
1311b18c2d1eSnia	// OTP structure bits
1312b18c2d1eSnia	OtpScrInitData(scr);
1313b18c2d1eSnia
13140bbfda8aSnia
13150bbfda8aSnia	// WorkSpaceManager stuff
13160bbfda8aSnia	scr->workSpaceMgr.initialstate  = WMS_map;
13170bbfda8aSnia	scr->workSpaceMgr.buttonStyle   = STYLE_NORMAL;
13180bbfda8aSnia	scr->workSpaceMgr.vspace        = scr->WMgrVertButtonIndent;
13190bbfda8aSnia	scr->workSpaceMgr.hspace        = scr->WMgrHorizButtonIndent;
13200bbfda8aSnia
13210bbfda8aSnia	scr->workSpaceMgr.occupyWindow = calloc(1, sizeof(OccupyWindow));
13220bbfda8aSnia	scr->workSpaceMgr.occupyWindow->vspace    = scr->WMgrVertButtonIndent;
13230bbfda8aSnia	scr->workSpaceMgr.occupyWindow->hspace    = scr->WMgrHorizButtonIndent;
13240bbfda8aSnia	scr->workSpaceMgr.occupyWindow->name      = "Occupy Window";
13250bbfda8aSnia	scr->workSpaceMgr.occupyWindow->icon_name = "Occupy Window Icon";
13260bbfda8aSnia
13270bbfda8aSnia	scr->workSpaceMgr.name      = "WorkSpaceManager";
13280bbfda8aSnia	scr->workSpaceMgr.icon_name = "WorkSpaceManager Icon";
13290bbfda8aSnia
13300bbfda8aSnia
13310bbfda8aSnia	// Setup default fonts in case the config file doesn't
13320bbfda8aSnia#define DEFAULT_NICE_FONT "-*-helvetica-bold-r-normal-*-*-120-*"
13330bbfda8aSnia#define DEFAULT_FAST_FONT "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-*"
13340bbfda8aSnia#define SETFONT(fld, var) (scr->fld##Font.basename = DEFAULT_##var##_FONT)
13350bbfda8aSnia
13360bbfda8aSnia	SETFONT(TitleBar,    NICE);
13370bbfda8aSnia	SETFONT(Menu,        NICE);
13380bbfda8aSnia	SETFONT(Icon,        NICE);
13390bbfda8aSnia	SETFONT(Size,        FAST);
13400bbfda8aSnia	SETFONT(IconManager, NICE);
13410bbfda8aSnia	SETFONT(Default,     FAST);
13420bbfda8aSnia	scr->workSpaceMgr.windowFont.basename =
13430bbfda8aSnia	        "-adobe-courier-medium-r-normal--10-100-75-75-m-60-iso8859-1";
13440bbfda8aSnia
13450bbfda8aSnia#undef SETFONT
13460bbfda8aSnia#undef DEFAULT_FAST_FONT
13470bbfda8aSnia#undef DEFAULT_NICE_FONT
13480bbfda8aSnia
1349b18c2d1eSnia
1350b18c2d1eSnia	// Set some fallback values that we set from the X server, for
1351b18c2d1eSnia	// special cases where we may not actually be talking to one.
1352b18c2d1eSnia	scr->d_depth = 24;
1353b18c2d1eSnia	scr->RealRoot = croot;
1354b18c2d1eSnia	scr->mm_w = 406; // 16 in
1355b18c2d1eSnia	scr->mm_h = 229; // 9 in
1356b18c2d1eSnia	scr->Monochrome = COLOR;
1357b18c2d1eSnia
13580bbfda8aSnia	// Cleanup poisoning
13590bbfda8aSnia#undef Scr
13600bbfda8aSnia	return scr;
13610bbfda8aSnia}
13620bbfda8aSnia
13630bbfda8aSnia
13640bbfda8aSnia
13650bbfda8aSnia
1366b18c2d1eSnia#ifdef CAPTIVE
1367b18c2d1eSnia/**
1368b18c2d1eSnia * Create a new window to use for a captive ctwm.
13690bbfda8aSnia */
13700bbfda8aSniastatic Window
13710bbfda8aSniaCreateCaptiveRootWindow(int x, int y,
13720bbfda8aSnia                        unsigned int width, unsigned int height)
13730bbfda8aSnia{
13740bbfda8aSnia	int         scrnum;
13750bbfda8aSnia	Window      ret;
13760bbfda8aSnia	XWMHints    wmhints;
13770bbfda8aSnia
13780bbfda8aSnia	scrnum = DefaultScreen(dpy);
13790bbfda8aSnia	ret = XCreateSimpleWindow(dpy, RootWindow(dpy, scrnum),
13800bbfda8aSnia	                          x, y, width, height, 2, WhitePixel(dpy, scrnum),
13810bbfda8aSnia	                          BlackPixel(dpy, scrnum));
13820bbfda8aSnia	wmhints.initial_state = NormalState;
13830bbfda8aSnia	wmhints.input         = True;
13840bbfda8aSnia	wmhints.flags         = InputHint | StateHint;
13850bbfda8aSnia
13860bbfda8aSnia	XmbSetWMProperties(dpy, ret, "Captive ctwm", NULL, NULL, 0, NULL,
13870bbfda8aSnia	                   &wmhints, NULL);
13880bbfda8aSnia	XChangeProperty(dpy, ret, XA_WM_CTWM_ROOT, XA_WINDOW, 32,
13890bbfda8aSnia	                PropModeReplace, (unsigned char *) &ret, 1);
13900bbfda8aSnia	XSelectInput(dpy, ret, StructureNotifyMask);
13910bbfda8aSnia	XMapWindow(dpy, ret);
13920bbfda8aSnia	return (ret);
13930bbfda8aSnia}
1394b18c2d1eSnia#endif
13950bbfda8aSnia
13960bbfda8aSnia
1397b18c2d1eSnia
1398b18c2d1eSnia/**
13990bbfda8aSnia * Return true if a window is not set to override_redirect ("Hey!  WM!
14000bbfda8aSnia * Leave those wins alone!"), and isn't unmapped.  Used during startup to
14010bbfda8aSnia * fake mapping for wins that should be up.
14020bbfda8aSnia */
14030bbfda8aSniastatic bool
14040bbfda8aSniaMappedNotOverride(Window w)
14050bbfda8aSnia{
14060bbfda8aSnia	XWindowAttributes wa;
14070bbfda8aSnia
14080bbfda8aSnia	XGetWindowAttributes(dpy, w, &wa);
14090bbfda8aSnia	return ((wa.map_state != IsUnmapped) && (wa.override_redirect != True));
14100bbfda8aSnia}
1411