Home | History | Annotate | Line # | Download | only in dist
      1 /*
      2  *       Copyright 1988 by Evans & Sutherland Computer Corporation,
      3  *                          Salt Lake City, Utah
      4  *  Portions Copyright 1989 by the Massachusetts Institute of Technology
      5  *                        Cambridge, Massachusetts
      6  *
      7  * $XConsortium: twm.c,v 1.124 91/05/08 11:01:54 dave Exp $
      8  *
      9  * twm - "Tom's Window Manager"
     10  *
     11  * 27-Oct-87 Thomas E. LaStrange        File created
     12  * 10-Oct-90 David M. Sternlicht        Storing saved colors on root
     13  *
     14  * Copyright 1992 Claude Lecommandeur.
     15  *
     16  * Do the necessary modification to be integrated in ctwm.
     17  * Can no longer be used for the standard twm.
     18  *
     19  * 22-April-92 Claude Lecommandeur.
     20  */
     21 
     22 #include "ctwm.h"
     23 
     24 #include <stdio.h>
     25 #include <stdlib.h>
     26 #include <unistd.h>
     27 #include <locale.h>
     28 
     29 #include <fcntl.h>
     30 #include <X11/Xatom.h>
     31 #include <X11/extensions/shape.h>
     32 
     33 
     34 #include "ctwm_atoms.h"
     35 #include "ctwm_main.h"
     36 #include "ctwm_takeover.h"
     37 #include "clargs.h"
     38 #include "add_window.h"
     39 #include "gc.h"
     40 #include "parse.h"
     41 #include "version.h"
     42 #include "colormaps.h"
     43 #include "events.h"
     44 #include "util.h"
     45 #include "mask_screen.h"
     46 #include "animate.h"
     47 #include "screen.h"
     48 #include "icons.h"
     49 #include "iconmgr.h"
     50 #include "list.h"
     51 #ifdef SESSION
     52 #include "session.h"
     53 #endif
     54 #include "occupation.h"
     55 #include "otp.h"
     56 #include "cursor.h"
     57 #ifdef WINBOX
     58 #include "windowbox.h"
     59 #endif
     60 #ifdef CAPTIVE
     61 #include "captive.h"
     62 #endif
     63 #ifdef XRANDR
     64 #include "xrandr.h"
     65 #endif
     66 #include "r_area.h"
     67 #include "r_area_list.h"
     68 #include "r_layout.h"
     69 #include "signals.h"
     70 #include "vscreen.h"
     71 #include "win_decorations_init.h"
     72 #include "win_ops.h"
     73 #include "win_regions.h"
     74 #include "win_utils.h"
     75 #include "workspace_manager.h"
     76 #ifdef SOUNDS
     77 #  include "sound.h"
     78 #endif
     79 
     80 #include "gram.tab.h"
     81 
     82 
     83 XtAppContext appContext;        /* Xt application context */
     84 Display *dpy;                   /* which display are we talking to */
     85 Window ResizeWindow;            /* the window we are resizing */
     86 
     87 Atom XCTWMAtom[NUM_CTWM_XATOMS]; ///< Our various common atoms
     88 
     89 int NumScreens;                 /* number of screens in ScreenList */
     90 bool HasShape;                  /* server supports shape extension? */
     91 int ShapeEventBase, ShapeErrorBase;
     92 ScreenInfo **ScreenList;        /* structures for each screen */
     93 ScreenInfo *Scr = NULL;         /* the cur and prev screens */
     94 int PreviousScreen;             /* last screen that we were on */
     95 static bool cfgerrs = false;    ///< Whether there were config parsing errors
     96 
     97 #ifdef CAPTIVE
     98 static Window CreateCaptiveRootWindow(int x, int y,
     99                                       unsigned int width, unsigned int height);
    100 #endif
    101 ScreenInfo *InitScreenInfo(int scrnum, Window croot, int crootx, int crooty,
    102                            unsigned int crootw, unsigned int crooth);
    103 static bool MappedNotOverride(Window w);
    104 
    105 Cursor  UpperLeftCursor;
    106 Cursor  TopRightCursor,
    107         TopLeftCursor,
    108         BottomRightCursor,
    109         BottomLeftCursor,
    110         LeftCursor,
    111         RightCursor,
    112         TopCursor,
    113         BottomCursor;
    114 
    115 Cursor RightButt;
    116 Cursor MiddleButt;
    117 Cursor LeftButt;
    118 
    119 XContext TwmContext;            /* context for twm windows */
    120 XContext MenuContext;           /* context for all menu windows */
    121 XContext ScreenContext;         /* context to get screen data */
    122 XContext ColormapContext;       /* context for colormap operations */
    123 
    124 XClassHint NoClass;             /* for applications with no class */
    125 
    126 XGCValues Gcv;
    127 
    128 char *Home;                     /* the HOME environment variable */
    129 int HomeLen;                    /* length of Home */
    130 
    131 bool HandlingEvents = false;    /* are we handling events yet? */
    132 
    133 /*
    134  * Various junk vars for xlib calls.  Many calls have to get passed these
    135  * pointers to return values into, but in a lot of cases we don't care
    136  * about some/all of them, and since xlib blindly derefs and stores into
    137  * them, we can't just pass NULL for the ones we don't care about.  So we
    138  * make this set of globals to use as standin.  These should never be
    139  * used or read in our own code; use real vars for the values we DO use
    140  * from the calls.
    141  */
    142 Window JunkRoot, JunkChild;
    143 int JunkX, JunkY;
    144 unsigned int JunkWidth, JunkHeight, JunkBW, JunkDepth, JunkMask;
    145 
    146 char *ProgramName;
    147 size_t ProgramNameLen;
    148 int Argc;
    149 char **Argv;
    150 
    151 bool RestartPreviousState = true;      /* try to restart in previous state */
    152 
    153 
    154 /// Magic flag for tests.  Nothing else should touch this!
    155 bool ctwm_test = false;
    156 
    157 /// Magic callback for tests.  This will trigger right after config file
    158 /// parsing if it's set, and then exit.  Nothing else should ever touch
    159 /// this!
    160 int (*ctwm_test_postparse)(void) = NULL;
    161 
    162 
    163 
    164 
    165 /**
    166  * Start up ctwm.  This is effectively main(), just wrapped for various
    167  * unimportant reasons.
    168  */
    169 int
    170 ctwm_main(int argc, char *argv[])
    171 {
    172 	int numManaged, firstscrn, lastscrn;
    173 	bool FirstScreen;
    174 	bool takeover = true;
    175 	bool nodpyok = false;
    176 
    177 	setlocale(LC_ALL, "");
    178 
    179 	ProgramName = argv[0];
    180 	ProgramNameLen = strlen(ProgramName);
    181 	Argc = argc;
    182 	Argv = argv;
    183 
    184 
    185 	/*
    186 	 * Run consistency check.  This is mostly to keep devs from
    187 	 * accidental screwups; if a user ever sees anything from this,
    188 	 * something went very very wrong.
    189 	 */
    190 	chk_keytable_order();
    191 
    192 	/*
    193 	 * Parse-out command line args, and check the results.
    194 	 */
    195 	clargs_parse(argc, argv);
    196 	clargs_check();
    197 	/* If we get this far, it was all good */
    198 
    199 	/* Some clargs mean we're not actually trying to take over the screen */
    200 	if(CLarg.cfgchk) {
    201 		takeover = false;
    202 	}
    203 #ifdef CAPTIVE
    204 	if(CLarg.is_captive) {
    205 		takeover = false;
    206 	}
    207 #endif
    208 
    209 	/* And some mean we actually don't care if we lack an X server */
    210 	if(CLarg.cfgchk) {
    211 		nodpyok = true;
    212 	}
    213 
    214 	/* Support for tests: be ready to fake everything */
    215 	if(ctwm_test) {
    216 		takeover = false;
    217 		nodpyok  = true;
    218 	}
    219 
    220 
    221 	/*
    222 	 * Hook up signal handlers
    223 	 */
    224 	setup_signal_handlers();
    225 
    226 
    227 	// Various bits of code care about $HOME
    228 	Home = getenv("HOME");
    229 	if(Home == NULL) {
    230 		Home = "./";
    231 	}
    232 	HomeLen = strlen(Home);
    233 
    234 
    235 	// XXX This is only used in AddWindow(), and is probably bogus to
    236 	// have globally....
    237 	NoClass.res_name = NoName;
    238 	NoClass.res_class = NoName;
    239 
    240 
    241 	/*
    242 	 * Initialize our X connection and state bits.
    243 	 */
    244 	{
    245 		int zero = 0; // Fakey
    246 
    247 		XtToolkitInitialize();
    248 		appContext = XtCreateApplicationContext();
    249 
    250 		// Tests don't talk to a real X server.
    251 		// XXX This needs revisiting if we ever get one that _does_.
    252 		// We'll have to add another flag...
    253 		if(!ctwm_test) {
    254 			// Connect
    255 			dpy = XtOpenDisplay(appContext, CLarg.display_name, "twm", "twm",
    256 			                    NULL, 0, &zero, NULL);
    257 		}
    258 
    259 		// Failed?  Usually a problem, but somethings we allow faking...
    260 		if(!dpy && !nodpyok) {
    261 			fprintf(stderr, "%s:  unable to open display \"%s\"\n",
    262 			        ProgramName, XDisplayName(CLarg.display_name));
    263 			exit(1);
    264 		}
    265 
    266 		if(dpy && fcntl(ConnectionNumber(dpy), F_SETFD, FD_CLOEXEC) == -1) {
    267 			fprintf(stderr,
    268 			        "%s:  unable to mark display connection as close-on-exec\n",
    269 			        ProgramName);
    270 			exit(1);
    271 		}
    272 
    273 		if(!dpy && !ctwm_test) {
    274 			// At least warn, except for tests
    275 			fprintf(stderr, "%s: Can't connect to X server, proceeding anyway...\n",
    276 			        ProgramName);
    277 		}
    278 	}
    279 
    280 
    281 #ifdef SESSION
    282 	// Load session stuff
    283 	if(CLarg.restore_filename) {
    284 		ReadWinConfigFile(CLarg.restore_filename);
    285 	}
    286 #endif
    287 
    288 
    289 	if(dpy) {
    290 		// Load up info about X extensions
    291 		HasShape = XShapeQueryExtension(dpy, &ShapeEventBase, &ShapeErrorBase);
    292 
    293 		// Allocate contexts/atoms/etc we use
    294 		TwmContext = XUniqueContext();
    295 		MenuContext = XUniqueContext();
    296 		ScreenContext = XUniqueContext();
    297 		ColormapContext = XUniqueContext();
    298 		InitWorkSpaceManagerContext();
    299 
    300 		// Load up our standard set of atoms
    301 		XInternAtoms(dpy, XCTWMAtomNames, NUM_CTWM_XATOMS, False, XCTWMAtom);
    302 
    303 		NumScreens = ScreenCount(dpy);
    304 		PreviousScreen = DefaultScreen(dpy);
    305 	}
    306 	else {
    307 		NumScreens = 1;
    308 		PreviousScreen = 0;
    309 	}
    310 
    311 	// Allocate/define common cursors
    312 	NewFontCursor(&TopLeftCursor, "top_left_corner");
    313 	NewFontCursor(&TopRightCursor, "top_right_corner");
    314 	NewFontCursor(&BottomLeftCursor, "bottom_left_corner");
    315 	NewFontCursor(&BottomRightCursor, "bottom_right_corner");
    316 	NewFontCursor(&LeftCursor, "left_side");
    317 	NewFontCursor(&RightCursor, "right_side");
    318 	NewFontCursor(&TopCursor, "top_side");
    319 	NewFontCursor(&BottomCursor, "bottom_side");
    320 
    321 	NewFontCursor(&UpperLeftCursor, "top_left_corner");
    322 	NewFontCursor(&RightButt, "rightbutton");
    323 	NewFontCursor(&LeftButt, "leftbutton");
    324 	NewFontCursor(&MiddleButt, "middlebutton");
    325 
    326 
    327 	// Prep up the per-screen global info
    328 	if(CLarg.MultiScreen) {
    329 		firstscrn = 0;
    330 		lastscrn = NumScreens - 1;
    331 	}
    332 	else if(!dpy) {
    333 		firstscrn = lastscrn = 0;
    334 	}
    335 	else {
    336 		firstscrn = lastscrn = DefaultScreen(dpy);
    337 	}
    338 
    339 	// For simplicity, pre-allocate NumScreens ScreenInfo struct pointers
    340 	ScreenList = calloc(NumScreens, sizeof(ScreenInfo *));
    341 	if(ScreenList == NULL) {
    342 		fprintf(stderr, "%s: Unable to allocate memory for screen list, exiting.\n",
    343 		        ProgramName);
    344 		exit(1);
    345 	}
    346 
    347 
    348 	// Do a little early initialization
    349 #ifdef EWMH
    350 	if(dpy) {
    351 		EwmhInit();
    352 	}
    353 #endif /* EWMH */
    354 #ifdef SOUNDS
    355 	// Needs init'ing before we get to config parsing
    356 	sound_init();
    357 #endif
    358 	InitEvents();
    359 
    360 
    361 
    362 	// Start looping over the screens
    363 	numManaged = 0;
    364 	FirstScreen = true;
    365 	for(int scrnum = firstscrn ; scrnum <= lastscrn; scrnum++) {
    366 		Window croot;
    367 		int crootx, crooty;
    368 		unsigned int crootw, crooth;
    369 		bool screenmasked;
    370 		char *welcomefile;
    371 
    372 
    373 		/*
    374 		 * First, setup the root window for the screen.
    375 		 */
    376 		if(0) {
    377 			// Dummy
    378 		}
    379 #ifdef CAPTIVE
    380 		else if(CLarg.is_captive) {
    381 			// Captive ctwm.  We make a fake root.
    382 			XWindowAttributes wa;
    383 			if(CLarg.capwin && XGetWindowAttributes(dpy, CLarg.capwin, &wa)) {
    384 				Window junk;
    385 				croot  = CLarg.capwin;
    386 				crootw = wa.width;
    387 				crooth = wa.height;
    388 				XTranslateCoordinates(dpy, CLarg.capwin, wa.root, 0, 0, &crootx, &crooty,
    389 				                      &junk);
    390 			}
    391 			else {
    392 				// Fake up default size.  Probably ideally should be
    393 				// configurable, but even more ideally we wouldn't have
    394 				// captive...
    395 				crootx = crooty = 100;
    396 				crootw = 1280;
    397 				crooth = 768;
    398 				croot = CreateCaptiveRootWindow(crootx, crooty, crootw, crooth);
    399 			}
    400 		}
    401 #endif
    402 		else {
    403 			// Normal; get the real display's root.
    404 			crootx = 0;
    405 			crooty = 0;
    406 
    407 			if(dpy) {
    408 				croot  = RootWindow(dpy, scrnum);
    409 				crootw = DisplayWidth(dpy, scrnum);
    410 				crooth = DisplayHeight(dpy, scrnum);
    411 			}
    412 			else {
    413 				croot = None;
    414 				crootw = 1280;
    415 				crooth = 768;
    416 			}
    417 		}
    418 
    419 
    420 
    421 		/*
    422 		 * Create ScreenInfo for this Screen, and populate various
    423 		 * default/initial config.
    424 		 */
    425 		Scr = ScreenList[scrnum] = InitScreenInfo(scrnum, croot,
    426 		                           crootx, crooty, crootw, crooth);
    427 		if(Scr == NULL) {
    428 			fprintf(stderr,
    429 			        "%s: unable to allocate memory for ScreenInfo structure"
    430 			        " for screen %d.\n",
    431 			        ProgramName, scrnum);
    432 			continue;
    433 		}
    434 
    435 		// Other misc adjustments to default config.
    436 		Scr->ShowWelcomeWindow = CLarg.ShowWelcomeWindow;
    437 
    438 
    439 
    440 		/*
    441 		 * Figure out the layout of our various monitors if RANDR is
    442 		 * around and can tell us.
    443 		 */
    444 #ifdef XRANDR
    445 		if(dpy) {
    446 			Scr->Layout = XrandrNewLayout(dpy, Scr->XineramaRoot);
    447 		}
    448 #endif
    449 		if(Scr->Layout == NULL) {
    450 			// No RANDR, so as far as we know, the layout is just one
    451 			// monitor with our full size.
    452 			RArea *fs;
    453 			RAreaList *fsl;
    454 
    455 			fs = RAreaNewStatic(Scr->rootx, Scr->rooty, Scr->rootw, Scr->rooth);
    456 			fsl = RAreaListNew(1, fs, NULL);
    457 			Scr->Layout = RLayoutNew(fsl);
    458 		}
    459 #ifdef DEBUG
    460 		fprintf(stderr, "Layout: ");
    461 		RLayoutPrint(Scr->Layout);
    462 #endif
    463 		if(RLayoutNumMonitors(Scr->Layout) < 1) {
    464 			fprintf(stderr, "Error: No monitors found on screen %d!\n", scrnum);
    465 			continue;
    466 		}
    467 
    468 
    469 
    470 		// Now we can stash some info about the screen
    471 		if(dpy) {
    472 			Scr->d_depth = DefaultDepth(dpy, scrnum);
    473 			Scr->d_visual = DefaultVisual(dpy, scrnum);
    474 			Scr->RealRoot = RootWindow(dpy, scrnum);
    475 			{
    476 				// Stash these for m4
    477 				Screen *tscr = ScreenOfDisplay(dpy, scrnum);
    478 				Scr->mm_w = tscr->mwidth;
    479 				Scr->mm_h = tscr->mheight;
    480 			}
    481 		}
    482 		else {
    483 			// Standin; fake the values we need in m4 parsing
    484 			Scr->d_visual = calloc(1, sizeof(Visual));
    485 			Scr->d_visual->bits_per_rgb = 8;
    486 			Scr->d_visual->class = TrueColor;
    487 		}
    488 
    489 
    490 		// Now that we have d_depth...
    491 		Scr->XORvalue = (((unsigned long) 1) << Scr->d_depth) - 1;
    492 
    493 #ifdef CAPTIVE
    494 		// Init captive bits.  We stick this name into m4 props, so do it
    495 		// before config processing.
    496 		if(CLarg.is_captive) {
    497 			Scr->CaptiveRoot = croot;
    498 			Scr->captivename = AddToCaptiveList(CLarg.captivename);
    499 			if(Scr->captivename) {
    500 				XmbSetWMProperties(dpy, croot,
    501 				                   Scr->captivename, Scr->captivename,
    502 				                   NULL, 0, NULL, NULL, NULL);
    503 			}
    504 		}
    505 #endif
    506 
    507 
    508 		// Init some colormap bits.  We need this before we get into the
    509 		// config parsing, since various things in there poke into
    510 		// colormaps.
    511 		{
    512 			// 1 on the root
    513 			Scr->RootColormaps.number_cwins = 1;
    514 			Scr->RootColormaps.cwins = malloc(sizeof(ColormapWindow *));
    515 			Scr->RootColormaps.cwins[0] = CreateColormapWindow(Scr->Root, true,
    516 			                              false);
    517 			Scr->RootColormaps.cwins[0]->visibility = VisibilityPartiallyObscured;
    518 
    519 			// Initialize storage for all maps the Screen can hold
    520 			Scr->cmapInfo.cmaps = NULL;
    521 			if(dpy) {
    522 				Scr->cmapInfo.maxCmaps = MaxCmapsOfScreen(ScreenOfDisplay(dpy,
    523 				                         Scr->screen));
    524 			}
    525 			Scr->cmapInfo.root_pushes = 0;
    526 			InstallColormaps(0, &Scr->RootColormaps);
    527 
    528 			// Setup which we're using
    529 			Scr->StdCmapInfo.head = Scr->StdCmapInfo.tail
    530 			                        = Scr->StdCmapInfo.mru = NULL;
    531 			Scr->StdCmapInfo.mruindex = 0;
    532 			if(dpy) {
    533 				LocateStandardColormaps();
    534 			}
    535 		}
    536 
    537 
    538 		// Are we monochrome?  Or do we care this millennium?
    539 		if(CLarg.Monochrome || (dpy && DisplayCells(dpy, scrnum) < 3)) {
    540 			Scr->Monochrome = MONOCHROME;
    541 		}
    542 		else {
    543 			Scr->Monochrome = COLOR;
    544 		}
    545 
    546 
    547 		// With the colormap/monochrome bits set, we can setup our
    548 		// default color bits.
    549 		GetColor(Scr->Monochrome, &(Scr->Black), "black");
    550 		GetColor(Scr->Monochrome, &(Scr->White), "white");
    551 
    552 		Scr->MenuShadowColor = Scr->Black;
    553 		Scr->IconBorderColor = Scr->Black;
    554 		Scr->IconManagerHighlight = Scr->Black;
    555 
    556 #define SETFB(fld) Scr->fld.fore = Scr->Black; Scr->fld.back = Scr->White;
    557 		SETFB(DefaultC)
    558 		SETFB(BorderColorC)
    559 		SETFB(BorderTileC)
    560 		SETFB(TitleC)
    561 		SETFB(MenuC)
    562 		SETFB(MenuTitleC)
    563 		SETFB(IconC)
    564 		SETFB(IconManagerC)
    565 		SETFB(workSpaceMgr.windowcp)
    566 		SETFB(workSpaceMgr.curColors)
    567 		SETFB(workSpaceMgr.defColors)
    568 #undef SETFB
    569 
    570 
    571 		// The first time around, we focus onto the root [of the first
    572 		// Screen].  Maybe we should revisit this...
    573 		if(dpy && FirstScreen) {
    574 			// XXX This func also involves a lot of stuff that isn't
    575 			// setup yet, and probably only works by accident.  Maybe we
    576 			// should just manually extract out the couple bits we
    577 			// actually want to run?
    578 			SetFocus(NULL, CurrentTime);
    579 			FirstScreen = false;
    580 		}
    581 
    582 		// Create default icon manager memory bits (in the first
    583 		// workspace)
    584 		AllocateIconManager("TWM", "Icons", "", 1);
    585 
    586 
    587 		/*
    588 		 * Mask over the screen with our welcome window stuff if we were
    589 		 * asked to on the command line/environment; too early to get
    590 		 * info from config file about it.
    591 		 */
    592 		screenmasked = false;
    593 		if(dpy && takeover && Scr->ShowWelcomeWindow
    594 		                && (welcomefile = getenv("CTWM_WELCOME_FILE"))) {
    595 			screenmasked = true;
    596 			MaskScreen(welcomefile);
    597 		}
    598 
    599 
    600 
    601 		/*
    602 		 * Load up config file
    603 		 */
    604 		{
    605 			bool ok = LoadTwmrc(CLarg.InitFile);
    606 
    607 			// cfgchk just displays whether there are errors, then moves
    608 			// on.
    609 			if(CLarg.cfgchk) {
    610 				if(ok) {
    611 					fprintf(stderr, "%d: No errors found\n", scrnum);
    612 				}
    613 				else {
    614 					fprintf(stderr, "%d: Errors found\n", scrnum);
    615 					cfgerrs = true;
    616 				}
    617 				continue;
    618 			}
    619 
    620 			// In non-config-check mode, we historically proceed even if
    621 			// there were errors, so keep doing that...
    622 		}
    623 
    624 
    625 		// For testing, it's useful to do all that initial setup up
    626 		// through parsing, and then inspect Scr and the like.
    627 		// Long-term, IWBNI we had a better way to do all the necessary
    628 		// initialization and then call the parse ourselves at that
    629 		// level.  But for now, provide a callback func that can pass
    630 		// control back to the test code, then just exits.
    631 		if(ctwm_test_postparse != NULL) {
    632 			exit(ctwm_test_postparse());
    633 		}
    634 
    635 
    636 
    637 		/*
    638 		 * Since we've loaded the config, go ahead and take over the
    639 		 * screen.
    640 		 */
    641 		if(takeover) {
    642 			if(takeover_screen(Scr) != true) {
    643 				// Well, move on to the next one, maybe we'll get it...
    644 				if(screenmasked) {
    645 					UnmaskScreen();
    646 				}
    647 				continue;
    648 			}
    649 
    650 			// Well, we got this one
    651 			numManaged++;
    652 		}
    653 
    654 		// If the config wants us to show the splash screen and we
    655 		// haven't already, do it now.
    656 		if(Scr->ShowWelcomeWindow && !screenmasked) {
    657 			MaskScreen(NULL);
    658 		}
    659 
    660 
    661 
    662 		/*
    663 		 * Do various setup based on the results from the config file.
    664 		 */
    665 
    666 		// Few simple var defaults
    667 		if(Scr->ClickToFocus) {
    668 			Scr->FocusRoot  = false;
    669 			Scr->TitleFocus = false;
    670 		}
    671 
    672 		if(Scr->use3Dborders) {
    673 			Scr->ClientBorderWidth = false;
    674 		}
    675 
    676 
    677 		// Now that we know what Border's there may be, create our
    678 		// BorderedLayout.
    679 		Scr->BorderedLayout = RLayoutCopyCropped(Scr->Layout,
    680 		                      Scr->BorderLeft, Scr->BorderRight,
    681 		                      Scr->BorderTop, Scr->BorderBottom);
    682 		if(Scr->BorderedLayout == NULL) {
    683 			Scr->BorderedLayout = Scr->Layout;        // nothing to crop
    684 		}
    685 		else if(Scr->BorderedLayout->monitors->len == 0) {
    686 			fprintf(stderr,
    687 			        "Borders too large! correct BorderLeft, BorderRight, BorderTop and/or BorderBottom parameters\n");
    688 			exit(1);
    689 		}
    690 #ifdef DEBUG
    691 		fprintf(stderr, "Bordered: ");
    692 		RLayoutPrint(Scr->BorderedLayout);
    693 #endif
    694 
    695 
    696 		/*
    697 		 * Setup stuff relating to VirtualScreens.  If something to do
    698 		 * with it is set in the config, this all implements stuff needed
    699 		 * for that.  If not, InitVirtualScreens() creates a single one
    700 		 * mirroring our real root.
    701 		 */
    702 		InitVirtualScreens(Scr);
    703 #ifdef VSCREEN
    704 #ifdef EWMH
    705 		EwmhInitVirtualRoots(Scr);
    706 #endif /* EWMH */
    707 #endif // vscreen
    708 
    709 		// Setup WSM[s] (per-vscreen).  This also sets up the about the
    710 		// workspaces for each vscreen and which is currently displayed.
    711 		ConfigureWorkSpaceManager(Scr);
    712 
    713 
    714 		/*
    715 		 * Various decoration default overrides for 3d/2d.  Values that
    716 		 * [presumtively] look "nice" on 75/100dpi displays.  -100 is a
    717 		 * sentinel value we set before the config file parsing; since
    718 		 * these defaults differ for 3d vs not, we can't just set them as
    719 		 * default before the parse.
    720 		 */
    721 #define SETDEF(fld, num) if(Scr->fld == -100) { Scr->fld = num; }
    722 		if(Scr->use3Dtitles) {
    723 			SETDEF(FramePadding,  0);
    724 			SETDEF(TitlePadding,  0);
    725 			SETDEF(ButtonIndent,  0);
    726 			SETDEF(TBInfo.border, 0);
    727 		}
    728 		else {
    729 			SETDEF(FramePadding,  2);
    730 			SETDEF(TitlePadding,  8);
    731 			SETDEF(ButtonIndent,  1);
    732 			SETDEF(TBInfo.border, 1);
    733 		}
    734 #undef SETDEF
    735 
    736 		// These values are meaningless in !3d cases, so always zero them
    737 		// out.
    738 		if(! Scr->use3Dtitles) {
    739 			Scr->TitleShadowDepth       = 0;
    740 			Scr->TitleButtonShadowDepth = 0;
    741 		}
    742 		if(! Scr->use3Dborders) {
    743 			Scr->BorderShadowDepth = 0;
    744 		}
    745 		if(! Scr->use3Dmenus) {
    746 			Scr->MenuShadowDepth = 0;
    747 		}
    748 		if(! Scr->use3Diconmanagers) {
    749 			Scr->IconManagerShadowDepth = 0;
    750 		}
    751 		if(! Scr->use3Dborders) {
    752 			Scr->ThreeDBorderWidth = 0;
    753 		}
    754 
    755 		// Setup colors stuff
    756 		if(!Scr->BeNiceToColormap) {
    757 			// Default pair
    758 			GetShadeColors(&Scr->DefaultC);
    759 
    760 			// Various conditionally 3d bits
    761 			if(Scr->use3Dtitles) {
    762 				GetShadeColors(&Scr->TitleC);
    763 			}
    764 			if(Scr->use3Dmenus) {
    765 				GetShadeColors(&Scr->MenuC);
    766 			}
    767 			if(Scr->use3Dmenus) {
    768 				GetShadeColors(&Scr->MenuTitleC);
    769 			}
    770 			if(Scr->use3Dborders) {
    771 				GetShadeColors(&Scr->BorderColorC);
    772 			}
    773 		}
    774 
    775 		// Defaults for IconRegion bits that aren't set.
    776 		for(IconRegion *ir = Scr->FirstRegion; ir; ir = ir->next) {
    777 			if(ir->TitleJustification == TJ_UNDEF) {
    778 				ir->TitleJustification = Scr->IconJustification;
    779 			}
    780 			if(ir->Justification == IRJ_UNDEF) {
    781 				ir->Justification = Scr->IconRegionJustification;
    782 			}
    783 			if(ir->Alignement == IRA_UNDEF) {
    784 				ir->Alignement = Scr->IconRegionAlignement;
    785 			}
    786 		}
    787 
    788 		// Put the results of SaveColor{} into _MIT_PRIORITY_COLORS.
    789 		assign_var_savecolor();
    790 
    791 		// Setup cursor values that weren't give in the config
    792 #define DEFCURSOR(name, val) if(!Scr->name) NewFontCursor(&Scr->name, val)
    793 		DEFCURSOR(FrameCursor,   "top_left_arrow");
    794 		DEFCURSOR(TitleCursor,   "top_left_arrow");
    795 		DEFCURSOR(IconCursor,    "top_left_arrow");
    796 		DEFCURSOR(IconMgrCursor, "top_left_arrow");
    797 		DEFCURSOR(MoveCursor,    "fleur");
    798 		DEFCURSOR(ResizeCursor,  "fleur");
    799 		DEFCURSOR(MenuCursor,    "sb_left_arrow");
    800 		DEFCURSOR(ButtonCursor,  "hand2");
    801 		DEFCURSOR(WaitCursor,    "watch");
    802 		DEFCURSOR(SelectCursor,  "dot");
    803 		DEFCURSOR(DestroyCursor, "pirate");
    804 		DEFCURSOR(AlterCursor,   "question_arrow");
    805 #undef DEFCURSOR
    806 
    807 		// Load up fonts for the screen.
    808 		//
    809 		// XXX HaveFonts is kinda stupid, however it gets useful in one
    810 		// place: when loading button bindings, we make some sort of
    811 		// "menu" for things (x-ref GotButton()), and the menu gen code
    812 		// needs to load font stuff, so if that happened in the config
    813 		// process, we would have already run CreateFonts().  Of course,
    814 		// that's a order-dependent bit of the config file parsing too;
    815 		// if you define the fonts too late, they wouldn't have been set
    816 		// by then, and we won't [re]try them now...    arg.
    817 		if(!Scr->HaveFonts) {
    818 			CreateFonts(Scr);
    819 		}
    820 
    821 		// Adjust settings for titlebar.  Must follow CreateFonts() call
    822 		// so we know these bits are populated
    823 		Scr->TitleBarFont.y += Scr->FramePadding;
    824 		Scr->TitleHeight = Scr->TitleBarFont.height + Scr->FramePadding * 2;
    825 		if(Scr->use3Dtitles) {
    826 			Scr->TitleHeight += 2 * Scr->TitleShadowDepth;
    827 		}
    828 		/* make title height be odd so buttons look nice and centered */
    829 		if(!(Scr->TitleHeight & 1)) {
    830 			Scr->TitleHeight++;
    831 		}
    832 
    833 
    834 
    835 		/*
    836 		 * Now we can start making various things.
    837 		 */
    838 
    839 		// Stash up a ref to our Scr on the root, so we can find the
    840 		// right Scr for events etc.
    841 		XSaveContext(dpy, Scr->Root, ScreenContext, (XPointer) Scr);
    842 
    843 		// Setup GC's for drawing, so we can start making stuff we have
    844 		// to actually draw.  Could move earlier, has to preceed a lot of
    845 		// following.
    846 		CreateGCs();
    847 
    848 		// Create and draw the menus we config'd
    849 		MakeMenus();
    850 
    851 		// Load up the images for titlebar buttons
    852 		InitTitlebarButtons();
    853 
    854 		// Allocate controls for WindowRegion's.  Has to follow
    855 		// workspaces setup, but doesn't talk to X.
    856 		CreateWindowRegions();
    857 
    858 		// Copy the icon managers over to workspaces past the first as
    859 		// necessary.  AllocateIconManager() and the config parsing
    860 		// already made them on the first WS.
    861 		AllocateOtherIconManagers();
    862 
    863 		// Create the windows for our icon managers now that all our
    864 		// tracking for it is setup.
    865 		CreateIconManagers();
    866 
    867 		// Create the WSM window (per-vscreen) and stash info on the root
    868 		// about our WS's.
    869 		CreateWorkSpaceManager();
    870 
    871 		// Create the f.occupy window
    872 		CreateOccupyWindow();
    873 
    874 		// Setup TwmWorkspaces menu.  Needs workspaces setup, as well as
    875 		// menus made.
    876 		MakeWorkspacesMenu();
    877 
    878 #ifdef WINBOX
    879 		// setup WindowBox's
    880 		createWindowBoxes();
    881 #endif
    882 
    883 		// Initialize Xrm stuff; things with setting occupation etc use
    884 		// Xrm bits.
    885 		XrmInitialize();
    886 
    887 #ifdef EWMH
    888 		// Set EWMH-related properties on various root-ish windows, for
    889 		// other programs to read to find out how we view the world.
    890 		EwmhInitScreenLate(Scr);
    891 #endif /* EWMH */
    892 
    893 
    894 		/*
    895 		 * Look up and handle all the windows on the screen.
    896 		 */
    897 		{
    898 			Window parent, *children;
    899 			unsigned int nchildren;
    900 
    901 			XQueryTree(dpy, Scr->Root, &croot, &parent, &children, &nchildren);
    902 
    903 			/* Weed out icon windows */
    904 			for(int i = 0; i < nchildren; i++) {
    905 				if(children[i]) {
    906 					XWMHints *wmhintsp = XGetWMHints(dpy, children[i]);
    907 
    908 					if(wmhintsp) {
    909 						if(wmhintsp->flags & IconWindowHint) {
    910 							for(int j = 0; j < nchildren; j++) {
    911 								if(children[j] == wmhintsp->icon_window) {
    912 									children[j] = None;
    913 									break;
    914 								}
    915 							}
    916 						}
    917 						XFree(wmhintsp);
    918 					}
    919 				}
    920 			}
    921 
    922 			/*
    923 			 * Map all of the non-override windows.  This winds down
    924 			 * into AddWindow() and friends through SimulateMapRequest(),
    925 			 * so this is where we actually adopt the windows on the
    926 			 * screen.
    927 			 */
    928 			for(int i = 0; i < nchildren; i++) {
    929 				if(children[i] && MappedNotOverride(children[i])) {
    930 					XUnmapWindow(dpy, children[i]);
    931 					SimulateMapRequest(children[i]);
    932 				}
    933 			}
    934 
    935 			/*
    936 			 * At this point, we've adopted all the windows currently on
    937 			 * the screen (aside from those we're intentionally not).
    938 			 * Note that this happens _before_ the various other windows
    939 			 * we create below, which is why they don't wind up getting
    940 			 * TwmWindow's tied to them or show up in icon managers, etc.
    941 			 * We'd need to actually make it _explicit_ that those
    942 			 * windows aren't tracked by us if we changed that order...
    943 			 */
    944 		}
    945 
    946 
    947 		// Show the WSM window if we should
    948 		if(Scr->ShowWorkspaceManager && Scr->workSpaceManagerActive) {
    949 			VirtualScreen *vs;
    950 			if(Scr->WindowMask) {
    951 				XRaiseWindow(dpy, Scr->WindowMask);
    952 			}
    953 			for(vs = Scr->vScreenList; vs != NULL; vs = vs->next) {
    954 				SetMapStateProp(vs->wsw->twm_win, NormalState);
    955 				XMapWindow(dpy, vs->wsw->twm_win->frame);
    956 				if(vs->wsw->twm_win->StartSqueezed) {
    957 					Squeeze(vs->wsw->twm_win);
    958 				}
    959 				else {
    960 					XMapWindow(dpy, vs->wsw->w);
    961 				}
    962 				vs->wsw->twm_win->mapped = true;
    963 			}
    964 		}
    965 
    966 
    967 		/*
    968 		 * Setup the Info window, used for f.identify and f.version.
    969 		 */
    970 		{
    971 			unsigned long valuemask;
    972 			XSetWindowAttributes attributes;
    973 
    974 			attributes.border_pixel = Scr->DefaultC.fore;
    975 			attributes.background_pixel = Scr->DefaultC.back;
    976 			attributes.event_mask = (ExposureMask | ButtonPressMask |
    977 			                         KeyPressMask | ButtonReleaseMask);
    978 			NewFontCursor(&attributes.cursor, "hand2");
    979 			valuemask = (CWBorderPixel | CWBackPixel | CWEventMask | CWCursor);
    980 			Scr->InfoWindow.win =
    981 			        XCreateWindow(dpy, Scr->Root, 0, 0,
    982 			                      5, 5,
    983 			                      0, 0,
    984 			                      CopyFromParent, CopyFromParent,
    985 			                      valuemask, &attributes);
    986 		}
    987 
    988 
    989 		/*
    990 		 * Setup the Size/Position window for showing during resize/move
    991 		 * operations.
    992 		 */
    993 		{
    994 			// Stick the SizeWindow at the top left of the first monitor
    995 			// we found on this Screen.  That _may_ not be (0,0) (imagine
    996 			// a shorter left and taller right monitor, with their bottom
    997 			// edges lined up instead of top), so we have to look up what
    998 			// that coordinate is.  If we're CenterFeedbackWindow'ing,
    999 			// the window will have to move between monitors depending on
   1000 			// where the window we're moving is (starts), but
   1001 			// MoveResizeSizeWindow() will handle that.  If not, it
   1002 			// always stays in the top-left of the first display.
   1003 			RArea area = RLayoutGetAreaIndex(Scr->Layout, 0);
   1004 			XRectangle ink_rect;
   1005 			XRectangle logical_rect;
   1006 			unsigned long valuemask;
   1007 			XSetWindowAttributes attributes;
   1008 
   1009 			XmbTextExtents(Scr->SizeFont.font_set,
   1010 			               " 8888 x 8888 ", 13,
   1011 			               &ink_rect, &logical_rect);
   1012 			Scr->SizeStringWidth = logical_rect.width;
   1013 			valuemask = (CWBorderPixel | CWBackPixel | CWBitGravity);
   1014 			attributes.bit_gravity = NorthWestGravity;
   1015 
   1016 			if(Scr->SaveUnder) {
   1017 				attributes.save_under = True;
   1018 				valuemask |= CWSaveUnder;
   1019 			}
   1020 
   1021 			Scr->SizeWindow = XCreateWindow(dpy, Scr->Root,
   1022 			                                area.x, area.y,
   1023 			                                Scr->SizeStringWidth,
   1024 			                                (Scr->SizeFont.height +
   1025 			                                 SIZE_VINDENT * 2),
   1026 			                                0, 0,
   1027 			                                CopyFromParent,
   1028 			                                CopyFromParent,
   1029 			                                valuemask, &attributes);
   1030 		}
   1031 
   1032 		// Create util window used in animation
   1033 		Scr->ShapeWindow = XCreateSimpleWindow(dpy, Scr->Root, 0, 0,
   1034 		                                       Scr->rootw, Scr->rooth, 0, 0, 0);
   1035 
   1036 
   1037 		// Clear out the splash screen if we had one
   1038 		if(Scr->ShowWelcomeWindow) {
   1039 			UnmaskScreen();
   1040 		}
   1041 
   1042 		// Done setting up this Screen.  x-ref XXX's about whether this
   1043 		// element is worth anything...
   1044 		Scr->FirstTime = false;
   1045 	} // for each screen on display
   1046 
   1047 
   1048 	// If we're just checking the config, there's nothing more to do.
   1049 	if(CLarg.cfgchk) {
   1050 		exit(cfgerrs);
   1051 	}
   1052 
   1053 
   1054 	// We're not much of a window manager if we didn't get stuff to
   1055 	// manage...
   1056 	if(numManaged == 0) {
   1057 		if(CLarg.MultiScreen && NumScreens > 0)
   1058 			fprintf(stderr, "%s:  unable to find any unmanaged screens\n",
   1059 			        ProgramName);
   1060 		exit(1);
   1061 	}
   1062 
   1063 #ifdef SESSION
   1064 	// Hook up session
   1065 	ConnectToSessionManager(CLarg.client_id);
   1066 #endif
   1067 
   1068 #ifdef SOUNDS
   1069 	// Announce ourselves
   1070 	sound_load_list();
   1071 	play_startup_sound();
   1072 #endif
   1073 
   1074 	// Hard-reset this flag.
   1075 	// XXX This doesn't seem right?
   1076 	RestartPreviousState = true;
   1077 
   1078 	// Set vars to enable animation bits
   1079 	StartAnimation();
   1080 
   1081 	// Main loop.
   1082 	HandlingEvents = true;
   1083 	HandleEvents();
   1084 
   1085 	// Should never get here...
   1086 	fprintf(stderr, "Shouldn't return from HandleEvents()!\n");
   1087 	exit(1);
   1088 }
   1089 
   1090 
   1091 
   1092 /**
   1093  * Initialize ScreenInfo for a Screen.  This allocates the struct,
   1094  * assigns in the info we pass it about the screen and dimensions, and
   1095  * then puts in our various default/fallback/sentinel/etc values to
   1096  * prepare it for later use.
   1097  *
   1098  * It is intentional that this doesn't do any of the initialization that
   1099  * involves calling out to X functions; it operates as a pure function.
   1100  * This makes it easier to use it to fake up a ScreenInfo for something
   1101  * that isn't actually an X Screen, for testing etc.
   1102  *
   1103  * \param scrnum The Screen number (e.g, :0.0 -> 0)
   1104  * \param croot  The X Window for the Screen's root window
   1105  * \param crootx Root X coordinate
   1106  * \param crooty Root Y coordinate
   1107  * \param crootw Root width
   1108  * \param crooth Root height
   1109  * \return Allocated and populated ScreenInfo
   1110  */
   1111 ScreenInfo *
   1112 InitScreenInfo(int scrnum, Window croot, int crootx, int crooty,
   1113                unsigned int crootw, unsigned int crooth)
   1114 {
   1115 	ScreenInfo *scr;
   1116 	scr = calloc(1, sizeof(ScreenInfo));
   1117 	if(scr == NULL) {
   1118 		return NULL;
   1119 	}
   1120 	// Because of calloc(), it's already all 0 bytes, which are NULL and
   1121 	// false and 0 and similar.  Some following initializations are
   1122 	// nugatory because of that, but are left for clarity.
   1123 
   1124 	// Poison the global Scr to protect against typos
   1125 #define Scr StupidProgrammer
   1126 
   1127 
   1128 	// Basic pieces about the X screen we're talking about, and some
   1129 	// derived dimension-related bits.
   1130 	scr->screen = scrnum;
   1131 	scr->XineramaRoot = scr->Root = croot;
   1132 	scr->rootx = crootx;
   1133 	scr->rooty = crooty;
   1134 	scr->rootw = crootw;
   1135 	scr->rooth = crooth;
   1136 
   1137 #ifdef CAPTIVE
   1138 	scr->crootx = crootx;
   1139 	scr->crooty = crooty;
   1140 	scr->crootw = crootw;
   1141 	scr->crooth = crooth;
   1142 #endif
   1143 
   1144 	// Don't allow icon titles wider than the screen
   1145 	scr->MaxIconTitleWidth = scr->rootw;
   1146 
   1147 	// Attempt to come up with a sane default for the max sizes.  Start
   1148 	// by limiting so that a window with its left/top on the right/bottom
   1149 	// edge of the screen can't extend further than X can address (signed
   1150 	// 16-bit).  However, when your screen size starts approaching that
   1151 	// limit, reducing the max window sizes too much gets stupid too, so
   1152 	// set an arbitrary floor on how low this will take it.
   1153 	// MaxWindowSize in the config will override whatever's here anyway.
   1154 	scr->MaxWindowWidth  = 32767 - (scr->rootx + scr->rootw);
   1155 	scr->MaxWindowHeight = 32767 - (scr->rooty + scr->rooth);
   1156 	if(scr->MaxWindowWidth < 4096) {
   1157 		scr->MaxWindowWidth = 4096;
   1158 	}
   1159 	if(scr->MaxWindowHeight < 4096) {
   1160 		scr->MaxWindowHeight = 4096;
   1161 	}
   1162 
   1163 
   1164 	// Flags used in the code to keep track of where in various processes
   1165 	// (especially startup) we are.
   1166 	scr->HaveFonts = false;
   1167 
   1168 	// Flag which basically means "initial screen setup time".
   1169 	// XXX Not clear to what extent this should even exist; a lot of
   1170 	// uses are fairly bogus.
   1171 	scr->FirstTime = true;
   1172 
   1173 	// Sentinel values for defaulting config values
   1174 	scr->FramePadding = -100;
   1175 	scr->TitlePadding = -100;
   1176 	scr->ButtonIndent = -100;
   1177 	scr->TBInfo.border = -100;
   1178 
   1179 	// Default values for all sorts of config params
   1180 	scr->SizeStringOffset = 0;
   1181 	scr->ThreeDBorderWidth = 6;
   1182 	scr->BorderWidth = BW;
   1183 	scr->IconBorderWidth = BW;
   1184 	scr->NumAutoRaises = 0;
   1185 	scr->NumAutoLowers = 0;
   1186 	scr->TransientOnTop = 30;
   1187 	scr->NoDefaults = false;
   1188 	scr->UsePPosition = PPOS_OFF;
   1189 	scr->UseSunkTitlePixmap = false;
   1190 	scr->FocusRoot = true;
   1191 	scr->WarpCursor = false;
   1192 	scr->ForceIcon = false;
   1193 	scr->NoGrabServer = true;
   1194 	scr->NoRaiseMove = false;
   1195 	scr->NoRaiseResize = false;
   1196 	scr->NoRaiseDeicon = false;
   1197 	scr->RaiseOnWarp = true;
   1198 	scr->DontMoveOff = false;
   1199 	scr->DoZoom = false;
   1200 	scr->TitleFocus = true;
   1201 	scr->IconManagerFocus = true;
   1202 	scr->StayUpMenus = false;
   1203 	scr->WarpToDefaultMenuEntry = false;
   1204 	scr->ClickToFocus = false;
   1205 	scr->SloppyFocus = false;
   1206 	scr->SaveWorkspaceFocus = false;
   1207 	scr->NoIconTitlebar = false;
   1208 	scr->NoTitlebar = false;
   1209 	scr->DecorateTransients = true;
   1210 	scr->IconifyByUnmapping = false;
   1211 	scr->ShowIconManager = false;
   1212 	scr->ShowWorkspaceManager = false;
   1213 	scr->WMgrButtonShadowDepth = 2;
   1214 	scr->WMgrVertButtonIndent  = 5;
   1215 	scr->WMgrHorizButtonIndent = 5;
   1216 	scr->BorderShadowDepth = 2;
   1217 	scr->TitleShadowDepth = 2;
   1218 	scr->TitleButtonShadowDepth = 2;
   1219 	scr->MenuShadowDepth = 2;
   1220 	scr->IconManagerShadowDepth = 2;
   1221 	scr->AutoOccupy = false;
   1222 	scr->TransientHasOccupation = false;
   1223 	scr->DontPaintRootWindow = false;
   1224 	scr->IconManagerDontShow = false;
   1225 	scr->BackingStore = false;
   1226 	scr->SaveUnder = true;
   1227 	scr->RandomPlacement = RP_ALL;
   1228 	scr->RandomDisplacementX = 30;
   1229 	scr->RandomDisplacementY = 30;
   1230 	scr->DoOpaqueMove = true;
   1231 	scr->OpaqueMove = false;
   1232 	scr->OpaqueMoveThreshold = 200;
   1233 	scr->OpaqueResize = false;
   1234 	scr->DoOpaqueResize = true;
   1235 	scr->OpaqueResizeThreshold = 1000;
   1236 	scr->Highlight = true;
   1237 	scr->StackMode = true;
   1238 	scr->TitleHighlight = true;
   1239 	scr->MoveDelta = 1;
   1240 	scr->MoveOffResistance = -1;
   1241 	scr->MovePackResistance = 20;
   1242 	scr->ZoomCount = 8;
   1243 	scr->SortIconMgr = true;
   1244 	scr->Shadow = true;
   1245 	scr->InterpolateMenuColors = false;
   1246 	scr->NoIconManagers = false;
   1247 	scr->ClientBorderWidth = false;
   1248 	scr->SqueezeTitle = false;
   1249 	scr->FirstTime = true;
   1250 	scr->CaseSensitive = true;
   1251 	scr->WarpUnmapped = false;
   1252 	scr->WindowRingAll = false;
   1253 	scr->WarpRingAnyWhere = true;
   1254 	scr->ShortAllWindowsMenus = false;
   1255 	scr->use3Diconmanagers = false;
   1256 	scr->use3Dmenus = false;
   1257 	scr->use3Dtitles = false;
   1258 	scr->use3Dborders = false;
   1259 	scr->use3Dwmap = false;
   1260 	scr->SunkFocusWindowTitle = false;
   1261 	scr->ClearShadowContrast = 50;
   1262 	scr->DarkShadowContrast  = 40;
   1263 	scr->BeNiceToColormap = false;
   1264 	scr->BorderCursors = false;
   1265 	scr->IconJustification = TJ_CENTER;
   1266 	scr->IconRegionJustification = IRJ_CENTER;
   1267 	scr->IconRegionAlignement = IRA_CENTER;
   1268 	scr->TitleJustification = TJ_LEFT;
   1269 	scr->IconifyStyle = ICONIFY_NORMAL;
   1270 	scr->ReallyMoveInWorkspaceManager = false;
   1271 	scr->ShowWinWhenMovingInWmgr = false;
   1272 	scr->ReverseCurrentWorkspace = false;
   1273 	scr->DontWarpCursorInWMap = false;
   1274 	scr->XMoveGrid = 1;
   1275 	scr->YMoveGrid = 1;
   1276 	scr->CenterFeedbackWindow = false;
   1277 	scr->ShrinkIconTitles = false;
   1278 	scr->AutoRaiseIcons = false;
   1279 	scr->AutoFocusToTransients = false;
   1280 	scr->OpenWindowTimeout = 0;
   1281 	scr->RaiseWhenAutoUnSqueeze = false;
   1282 	scr->RaiseOnClick = false;
   1283 	scr->RaiseOnClickButton = 1;
   1284 	scr->IgnoreModifier = 0;
   1285 	scr->IgnoreCaseInMenuSelection = false;
   1286 	scr->PackNewWindows = false;
   1287 	scr->AlwaysSqueezeToGravity = false;
   1288 	scr->NoWarpToMenuTitle = false;
   1289 	scr->DontToggleWorkspaceManagerState = false;
   1290 	scr->NameDecorations = true;
   1291 	scr->ForceFocus = false;
   1292 	scr->BorderTop    = 0;
   1293 	scr->BorderBottom = 0;
   1294 	scr->BorderLeft   = 0;
   1295 	scr->BorderRight  = 0;
   1296 	scr->PixmapDirectory   = PIXMAP_DIRECTORY;
   1297 #ifdef EWMH
   1298 	scr->PreferredIconWidth = 48;
   1299 	scr->PreferredIconHeight = 48;
   1300 
   1301 	scr->ewmh_CLIENT_LIST_used = 0;
   1302 	scr->ewmh_CLIENT_LIST_size = 16;
   1303 	scr->ewmh_CLIENT_LIST = calloc(scr->ewmh_CLIENT_LIST_size,
   1304 	                               sizeof(scr->ewmh_CLIENT_LIST[0]));
   1305 	if(scr->ewmh_CLIENT_LIST == NULL) {
   1306 		free(scr);
   1307 		return NULL;
   1308 	}
   1309 #endif
   1310 
   1311 	// OTP structure bits
   1312 	OtpScrInitData(scr);
   1313 
   1314 
   1315 	// WorkSpaceManager stuff
   1316 	scr->workSpaceMgr.initialstate  = WMS_map;
   1317 	scr->workSpaceMgr.buttonStyle   = STYLE_NORMAL;
   1318 	scr->workSpaceMgr.vspace        = scr->WMgrVertButtonIndent;
   1319 	scr->workSpaceMgr.hspace        = scr->WMgrHorizButtonIndent;
   1320 
   1321 	scr->workSpaceMgr.occupyWindow = calloc(1, sizeof(OccupyWindow));
   1322 	scr->workSpaceMgr.occupyWindow->vspace    = scr->WMgrVertButtonIndent;
   1323 	scr->workSpaceMgr.occupyWindow->hspace    = scr->WMgrHorizButtonIndent;
   1324 	scr->workSpaceMgr.occupyWindow->name      = "Occupy Window";
   1325 	scr->workSpaceMgr.occupyWindow->icon_name = "Occupy Window Icon";
   1326 
   1327 	scr->workSpaceMgr.name      = "WorkSpaceManager";
   1328 	scr->workSpaceMgr.icon_name = "WorkSpaceManager Icon";
   1329 
   1330 
   1331 	// Setup default fonts in case the config file doesn't
   1332 #define DEFAULT_NICE_FONT "-*-helvetica-bold-r-normal-*-*-120-*"
   1333 #define DEFAULT_FAST_FONT "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-*"
   1334 #define SETFONT(fld, var) (scr->fld##Font.basename = DEFAULT_##var##_FONT)
   1335 
   1336 	SETFONT(TitleBar,    NICE);
   1337 	SETFONT(Menu,        NICE);
   1338 	SETFONT(Icon,        NICE);
   1339 	SETFONT(Size,        FAST);
   1340 	SETFONT(IconManager, NICE);
   1341 	SETFONT(Default,     FAST);
   1342 	scr->workSpaceMgr.windowFont.basename =
   1343 	        "-adobe-courier-medium-r-normal--10-100-75-75-m-60-iso8859-1";
   1344 
   1345 #undef SETFONT
   1346 #undef DEFAULT_FAST_FONT
   1347 #undef DEFAULT_NICE_FONT
   1348 
   1349 
   1350 	// Set some fallback values that we set from the X server, for
   1351 	// special cases where we may not actually be talking to one.
   1352 	scr->d_depth = 24;
   1353 	scr->RealRoot = croot;
   1354 	scr->mm_w = 406; // 16 in
   1355 	scr->mm_h = 229; // 9 in
   1356 	scr->Monochrome = COLOR;
   1357 
   1358 	// Cleanup poisoning
   1359 #undef Scr
   1360 	return scr;
   1361 }
   1362 
   1363 
   1364 
   1365 
   1366 #ifdef CAPTIVE
   1367 /**
   1368  * Create a new window to use for a captive ctwm.
   1369  */
   1370 static Window
   1371 CreateCaptiveRootWindow(int x, int y,
   1372                         unsigned int width, unsigned int height)
   1373 {
   1374 	int         scrnum;
   1375 	Window      ret;
   1376 	XWMHints    wmhints;
   1377 
   1378 	scrnum = DefaultScreen(dpy);
   1379 	ret = XCreateSimpleWindow(dpy, RootWindow(dpy, scrnum),
   1380 	                          x, y, width, height, 2, WhitePixel(dpy, scrnum),
   1381 	                          BlackPixel(dpy, scrnum));
   1382 	wmhints.initial_state = NormalState;
   1383 	wmhints.input         = True;
   1384 	wmhints.flags         = InputHint | StateHint;
   1385 
   1386 	XmbSetWMProperties(dpy, ret, "Captive ctwm", NULL, NULL, 0, NULL,
   1387 	                   &wmhints, NULL);
   1388 	XChangeProperty(dpy, ret, XA_WM_CTWM_ROOT, XA_WINDOW, 32,
   1389 	                PropModeReplace, (unsigned char *) &ret, 1);
   1390 	XSelectInput(dpy, ret, StructureNotifyMask);
   1391 	XMapWindow(dpy, ret);
   1392 	return (ret);
   1393 }
   1394 #endif
   1395 
   1396 
   1397 
   1398 /**
   1399  * Return true if a window is not set to override_redirect ("Hey!  WM!
   1400  * Leave those wins alone!"), and isn't unmapped.  Used during startup to
   1401  * fake mapping for wins that should be up.
   1402  */
   1403 static bool
   1404 MappedNotOverride(Window w)
   1405 {
   1406 	XWindowAttributes wa;
   1407 
   1408 	XGetWindowAttributes(dpy, w, &wa);
   1409 	return ((wa.map_state != IsUnmapped) && (wa.override_redirect != True));
   1410 }
   1411