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