twm.c revision ffd25bca
1/*****************************************************************************/
2/*
3
4Copyright 1989, 1998  The Open Group
5Copyright 2005 Hitachi, Ltd.
6
7Permission to use, copy, modify, distribute, and sell this software and its
8documentation for any purpose is hereby granted without fee, provided that
9the above copyright notice appear in all copies and that both that
10copyright notice and this permission notice appear in supporting
11documentation.
12
13The above copyright notice and this permission notice shall be included in
14all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
19OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
23Except as contained in this notice, the name of The Open Group shall not be
24used in advertising or otherwise to promote the sale, use or other dealings
25in this Software without prior written authorization from The Open Group.
26
27*/
28/**       Copyright 1988 by Evans & Sutherland Computer Corporation,        **/
29/**                          Salt Lake City, Utah                           **/
30/**                        Cambridge, Massachusetts                         **/
31/**                                                                         **/
32/**                           All Rights Reserved                           **/
33/**                                                                         **/
34/**    Permission to use, copy, modify, and distribute this software and    **/
35/**    its documentation  for  any  purpose  and  without  fee is hereby    **/
36/**    granted, provided that the above copyright notice appear  in  all    **/
37/**    copies and that both  that  copyright  notice  and  this  permis-    **/
38/**    sion  notice appear in supporting  documentation,  and  that  the    **/
39/**    name of Evans & Sutherland not be used in advertising    **/
40/**    in publicity pertaining to distribution of the  software  without    **/
41/**    specific, written prior permission.                                  **/
42/**                                                                         **/
43/**    EVANS & SUTHERLAND DISCLAIMs ALL WARRANTIES WITH REGARD    **/
44/**    TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES  OF  MERCHANT-    **/
45/**    ABILITY  AND  FITNESS,  IN  NO  EVENT SHALL EVANS & SUTHERLAND    **/
46/**    BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL  DAM-    **/
47/**    AGES OR  ANY DAMAGES WHATSOEVER  RESULTING FROM LOSS OF USE, DATA    **/
48/**    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER    **/
49/**    TORTIOUS ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE    **/
50/**    OR PERFORMANCE OF THIS SOFTWARE.                                     **/
51/*****************************************************************************/
52
53
54/***********************************************************************
55 *
56 * twm - "Tom's Window Manager"
57 *
58 * 27-Oct-1987 Thomas E. LaStrange    File created
59 * 10-Oct-1990 David M. Sternlicht    Storing saved colors on root
60 * 19-Feb-2005 Julien Lafon           Handle print screens for unified Xserver
61 ***********************************************************************/
62
63#include <stdio.h>
64#include <signal.h>
65#include <fcntl.h>
66#include "twm.h"
67#include "iconmgr.h"
68#include "add_window.h"
69#include "gc.h"
70#include "parse.h"
71#include "version.h"
72#include "menus.h"
73#include "events.h"
74#include "util.h"
75#include "gram.h"
76#include "screen.h"
77#include "parse.h"
78#include "session.h"
79#include <X11/Xproto.h>
80#include <X11/Xatom.h>
81#include <X11/SM/SMlib.h>
82#include <X11/Xmu/Error.h>
83#include <X11/extensions/sync.h>
84#include <X11/Xlocale.h>
85#ifdef XPRINT
86#include <X11/extensions/Print.h>
87#endif /* XPRINT */
88
89XtAppContext appContext;	/* Xt application context */
90XtSignalId si;
91
92Display *dpy = NULL;		/* which display are we talking to */
93Window ResizeWindow;		/* the window we are resizing */
94
95int MultiScreen = TRUE;		/* try for more than one screen? */
96int NoPrintscreens = False;     /* ignore special handling of print screens? */
97int NumScreens;			/* number of screens in ScreenList */
98int HasShape;			/* server supports shape extension? */
99int ShapeEventBase, ShapeErrorBase;
100int HasSync;			/* server supports SYNC extension? */
101int SyncEventBase, SyncErrorBase;
102ScreenInfo **ScreenList;	/* structures for each screen */
103ScreenInfo *Scr = NULL;		/* the cur and prev screens */
104int PreviousScreen;		/* last screen that we were on */
105int FirstScreen;		/* TRUE ==> first screen of display */
106Bool PrintErrorMessages = False;	/* controls error messages */
107static int RedirectError;	/* TRUE ==> another window manager running */
108static int TwmErrorHandler ( Display *dpy, XErrorEvent *event );	/* for settting RedirectError */
109static int CatchRedirectError ( Display *dpy, XErrorEvent *event );	/* for everything else */
110static SIGNAL_T sigHandler(int);
111char Info[INFO_LINES][INFO_SIZE];		/* info strings to print */
112int InfoLines;
113char *InitFile = NULL;
114
115Cursor UpperLeftCursor;		/* upper Left corner cursor */
116Cursor RightButt;
117Cursor MiddleButt;
118Cursor LeftButt;
119
120XContext TwmContext;		/* context for twm windows */
121XContext MenuContext;		/* context for all menu windows */
122XContext IconManagerContext;	/* context for all window list windows */
123XContext ScreenContext;		/* context to get screen data */
124XContext ColormapContext;	/* context for colormap operations */
125
126XClassHint NoClass;		/* for applications with no class */
127
128XGCValues Gcv;
129
130char *Home;			/* the HOME environment variable */
131int HomeLen;			/* length of Home */
132int ParseError;			/* error parsing the .twmrc file */
133
134int HandlingEvents = FALSE;	/* are we handling events yet? */
135
136Window JunkRoot;		/* junk window */
137Window JunkChild;		/* junk window */
138int JunkX;			/* junk variable */
139int JunkY;			/* junk variable */
140unsigned int JunkWidth, JunkHeight, JunkBW, JunkDepth, JunkMask;
141
142char *ProgramName;
143int Argc;
144char **Argv;
145
146Bool RestartPreviousState = False;	/* try to restart in previous state */
147
148unsigned long black, white;
149
150Atom TwmAtoms[11];
151
152Bool use_fontset;		/* use XFontSet-related functions or not */
153
154/* don't change the order of these strings */
155static char* atom_names[11] = {
156    "_MIT_PRIORITY_COLORS",
157    "WM_CHANGE_STATE",
158    "WM_STATE",
159    "WM_COLORMAP_WINDOWS",
160    "WM_PROTOCOLS",
161    "WM_TAKE_FOCUS",
162    "WM_SAVE_YOURSELF",
163    "WM_DELETE_WINDOW",
164    "SM_CLIENT_ID",
165    "WM_CLIENT_LEADER",
166    "WM_WINDOW_ROLE"
167};
168
169#ifdef XPRINT
170/* |hasExtension()| and |IsPrintScreen()| have been stolen from
171 * xc/programs/xdpyinfo/xdpyinfo.c */
172static
173Bool hasExtension(Display *dpy, char *extname)
174{
175  int    num_extensions,
176         i;
177  char **extensions;
178  extensions = XListExtensions(dpy, &num_extensions);
179  for (i = 0; i < num_extensions &&
180         (strcmp(extensions[i], extname) != 0); i++);
181  XFreeExtensionList(extensions);
182  return i != num_extensions;
183}
184
185static
186Bool IsPrintScreen(Screen *s)
187{
188    Display *dpy = XDisplayOfScreen(s);
189    int      i;
190
191    /* Check whether this is a screen of a print DDX */
192    if (hasExtension(dpy, XP_PRINTNAME)) {
193        Screen **pscreens;
194        int      pscrcount;
195
196        pscreens = XpQueryScreens(dpy, &pscrcount);
197        for( i = 0 ; (i < pscrcount) && pscreens ; i++ ) {
198            if (s == pscreens[i]) {
199                return True;
200            }
201        }
202        XFree(pscreens);
203    }
204    return False;
205}
206#endif /* XPRINT */
207
208/***********************************************************************
209 *
210 *  Procedure:
211 *	main - start of twm
212 *
213 ***********************************************************************
214 */
215
216int
217main(int argc, char *argv[])
218{
219    Window root, parent, *children;
220    unsigned int nchildren;
221    int i, j;
222    char *display_name = NULL;
223    unsigned long valuemask;	/* mask for create windows */
224    XSetWindowAttributes attributes;	/* attributes for create windows */
225    int numManaged, firstscrn, lastscrn, scrnum;
226    int zero = 0;
227    char *restore_filename = NULL;
228    char *client_id = NULL;
229    char *loc;
230
231    ProgramName = argv[0];
232    Argc = argc;
233    Argv = argv;
234
235    for (i = 1; i < argc; i++) {
236	if (argv[i][0] == '-') {
237	    switch (argv[i][1]) {
238	      case 'd':				/* -display dpy */
239		if (strcmp(&argv[i][1], "display")) goto usage;
240		if (++i >= argc) goto usage;
241		display_name = argv[i];
242		continue;
243	      case 's':				/* -single */
244		MultiScreen = FALSE;
245		continue;
246#ifdef XPRINT
247	      case 'n':				/* -noprint */
248		if (strcmp(&argv[i][1], "noprint")) goto usage;
249		NoPrintscreens = True;
250		continue;
251#endif /* XPRINT */
252	      case 'f':				/* -file twmrcfilename */
253		if (++i >= argc) goto usage;
254		InitFile = argv[i];
255		continue;
256	      case 'v':				/* -verbose */
257		PrintErrorMessages = True;
258		continue;
259	      case 'c':				/* -clientId */
260		if (strcmp(&argv[i][1], "clientId")) goto usage;
261		if (++i >= argc) goto usage;
262		client_id = argv[i];
263		continue;
264	      case 'r':				/* -restore */
265		if (strcmp(&argv[i][1], "restore")) goto usage;
266		if (++i >= argc) goto usage;
267		restore_filename = argv[i];
268		continue;
269	      case 'q':				/* -quiet */
270		PrintErrorMessages = False;
271		continue;
272	    }
273	}
274      usage:
275	fprintf (stderr,
276		 "usage:  %s [-display dpy] [-f file] [-s] [-q] [-v]"
277#ifdef XPRINT
278                 " [-noprint]"
279#endif /* XPRINT */
280                 " [-clientId id] [-restore file]\n",
281		 ProgramName);
282	exit (1);
283    }
284
285    loc = setlocale(LC_ALL, "");
286    if (!loc || !strcmp(loc, "C") || !strcmp(loc, "POSIX") ||
287	!XSupportsLocale()) {
288	 use_fontset = False;
289    } else {
290	 use_fontset = True;
291    }
292
293#define newhandler(sig) \
294    if (signal (sig, SIG_IGN) != SIG_IGN) (void) signal (sig, sigHandler)
295
296
297    newhandler (SIGINT);
298    newhandler (SIGHUP);
299    newhandler (SIGQUIT);
300    newhandler (SIGTERM);
301
302#undef newhandler
303
304    Home = getenv("HOME");
305    if (Home != NULL) {
306    	char *temp_p;
307
308	/*
309	 * Make a copy of Home because the string returned by getenv() can be
310	 * overwritten by some POSIX.1 and ANSI-C implementations of getenv()
311	 * when further calls to getenv() are made
312	 */
313
314	temp_p = strdup(Home);
315	Home = temp_p;
316    }
317
318    if (Home == NULL)
319	Home = "./";
320
321    HomeLen = strlen(Home);
322
323    NoClass.res_name = NoName;
324    NoClass.res_class = NoName;
325
326    XtToolkitInitialize ();
327    appContext = XtCreateApplicationContext ();
328
329    si = XtAppAddSignal(appContext, Done, NULL);
330
331    if (!(dpy = XtOpenDisplay (appContext, display_name, "twm", "twm",
332	NULL, 0, &zero, NULL))) {
333	fprintf (stderr, "%s:  unable to open display \"%s\"\n",
334		 ProgramName, XDisplayName(display_name));
335	exit (1);
336    }
337
338    if (fcntl(ConnectionNumber(dpy), F_SETFD, 1) == -1) {
339	fprintf (stderr,
340		 "%s:  unable to mark display connection as close-on-exec\n",
341		 ProgramName);
342	exit (1);
343    }
344
345    if (restore_filename)
346	ReadWinConfigFile (restore_filename);
347
348    HasShape = XShapeQueryExtension (dpy, &ShapeEventBase, &ShapeErrorBase);
349    HasSync = XSyncQueryExtension(dpy,  &SyncEventBase, &SyncErrorBase);
350    TwmContext = XUniqueContext();
351    MenuContext = XUniqueContext();
352    IconManagerContext = XUniqueContext();
353    ScreenContext = XUniqueContext();
354    ColormapContext = XUniqueContext();
355
356    (void) XInternAtoms(dpy, atom_names, sizeof TwmAtoms / sizeof TwmAtoms[0],
357			False, TwmAtoms);
358
359    /* Set up the per-screen global information. */
360
361    NumScreens = ScreenCount(dpy);
362
363    if (MultiScreen)
364    {
365	firstscrn = 0;
366	lastscrn = NumScreens - 1;
367    }
368    else
369    {
370	firstscrn = lastscrn = DefaultScreen(dpy);
371    }
372
373    InfoLines = 0;
374
375    /* for simplicity, always allocate NumScreens ScreenInfo struct pointers */
376    ScreenList = (ScreenInfo **) calloc (NumScreens, sizeof (ScreenInfo *));
377    if (ScreenList == NULL)
378    {
379	fprintf (stderr, "%s: Unable to allocate memory for screen list, exiting.\n",
380		 ProgramName);
381	exit (1);
382    }
383    numManaged = 0;
384    PreviousScreen = DefaultScreen(dpy);
385    FirstScreen = TRUE;
386    for (scrnum = firstscrn ; scrnum <= lastscrn; scrnum++)
387    {
388#ifdef XPRINT
389        /* Ignore print screens to avoid that users accidentally warp on a
390         * print screen (which are not visible on video displays) */
391        if ((!NoPrintscreens) && IsPrintScreen(XScreenOfDisplay(dpy, scrnum)))
392        {
393	    fprintf (stderr, "%s:  skipping print screen %d\n",
394		     ProgramName, scrnum);
395            continue;
396        }
397#endif /* XPRINT */
398
399        /* Make sure property priority colors is empty */
400        XChangeProperty (dpy, RootWindow(dpy, scrnum), _XA_MIT_PRIORITY_COLORS,
401			 XA_CARDINAL, 32, PropModeReplace, NULL, 0);
402	RedirectError = FALSE;
403	XSetErrorHandler(CatchRedirectError);
404	XSelectInput(dpy, RootWindow (dpy, scrnum),
405	    ColormapChangeMask | EnterWindowMask | PropertyChangeMask |
406	    SubstructureRedirectMask | KeyPressMask |
407	    ButtonPressMask | ButtonReleaseMask);
408	XSync(dpy, 0);
409	XSetErrorHandler(TwmErrorHandler);
410
411	if (RedirectError)
412	{
413	    fprintf (stderr, "%s:  another window manager is already running.",
414		     ProgramName);
415	    if (MultiScreen && NumScreens > 0)
416		fprintf(stderr, " on screen %d?\n", scrnum);
417	    else
418		fprintf(stderr, "?\n");
419	    continue;
420	}
421
422	numManaged ++;
423
424	/* Note:  ScreenInfo struct is calloc'ed to initialize to zero. */
425	Scr = ScreenList[scrnum] =
426	    (ScreenInfo *) calloc(1, sizeof(ScreenInfo));
427  	if (Scr == NULL)
428  	{
429  	    fprintf (stderr, "%s: unable to allocate memory for ScreenInfo structure for screen %d.\n",
430  		     ProgramName, scrnum);
431  	    continue;
432  	}
433
434	/* initialize list pointers, remember to put an initialization
435	 * in InitVariables also
436	 */
437	Scr->BorderColorL = NULL;
438	Scr->IconBorderColorL = NULL;
439	Scr->BorderTileForegroundL = NULL;
440	Scr->BorderTileBackgroundL = NULL;
441	Scr->TitleForegroundL = NULL;
442	Scr->TitleBackgroundL = NULL;
443	Scr->IconForegroundL = NULL;
444	Scr->IconBackgroundL = NULL;
445	Scr->NoTitle = NULL;
446	Scr->MakeTitle = NULL;
447	Scr->AutoRaise = NULL;
448	Scr->IconNames = NULL;
449	Scr->NoHighlight = NULL;
450	Scr->NoStackModeL = NULL;
451	Scr->NoTitleHighlight = NULL;
452	Scr->DontIconify = NULL;
453	Scr->IconMgrNoShow = NULL;
454	Scr->IconMgrShow = NULL;
455	Scr->IconifyByUn = NULL;
456	Scr->IconManagerFL = NULL;
457	Scr->IconManagerBL = NULL;
458	Scr->IconMgrs = NULL;
459	Scr->StartIconified = NULL;
460	Scr->SqueezeTitleL = NULL;
461	Scr->DontSqueezeTitleL = NULL;
462	Scr->WindowRingL = NULL;
463	Scr->WarpCursorL = NULL;
464	/* remember to put an initialization in InitVariables also
465	 */
466
467	Scr->screen = scrnum;
468	Scr->d_depth = DefaultDepth(dpy, scrnum);
469	Scr->d_visual = DefaultVisual(dpy, scrnum);
470	Scr->Root = RootWindow(dpy, scrnum);
471	XSaveContext (dpy, Scr->Root, ScreenContext, (caddr_t) Scr);
472
473	Scr->TwmRoot.cmaps.number_cwins = 1;
474	Scr->TwmRoot.cmaps.cwins =
475		(ColormapWindow **) malloc(sizeof(ColormapWindow *));
476	Scr->TwmRoot.cmaps.cwins[0] =
477		CreateColormapWindow(Scr->Root, True, False);
478	Scr->TwmRoot.cmaps.cwins[0]->visibility = VisibilityPartiallyObscured;
479
480	Scr->cmapInfo.cmaps = NULL;
481	Scr->cmapInfo.maxCmaps =
482		MaxCmapsOfScreen(ScreenOfDisplay(dpy, Scr->screen));
483	Scr->cmapInfo.root_pushes = 0;
484	InstallWindowColormaps(0, &Scr->TwmRoot);
485
486	Scr->StdCmapInfo.head = Scr->StdCmapInfo.tail =
487	  Scr->StdCmapInfo.mru = NULL;
488	Scr->StdCmapInfo.mruindex = 0;
489	LocateStandardColormaps();
490
491	Scr->TBInfo.nleft = Scr->TBInfo.nright = 0;
492	Scr->TBInfo.head = NULL;
493	Scr->TBInfo.border = 1;
494	Scr->TBInfo.width = 0;
495	Scr->TBInfo.leftx = 0;
496	Scr->TBInfo.titlex = 0;
497
498	Scr->MyDisplayWidth = DisplayWidth(dpy, scrnum);
499	Scr->MyDisplayHeight = DisplayHeight(dpy, scrnum);
500	Scr->MaxWindowWidth = 32767 - Scr->MyDisplayWidth;
501	Scr->MaxWindowHeight = 32767 - Scr->MyDisplayHeight;
502
503	Scr->XORvalue = (((unsigned long) 1) << Scr->d_depth) - 1;
504
505	if (DisplayCells(dpy, scrnum) < 3)
506	    Scr->Monochrome = MONOCHROME;
507	else if (DefaultVisual(dpy, scrnum)->class == GrayScale)
508 	    Scr->Monochrome = GRAYSCALE;
509	else
510	    Scr->Monochrome = COLOR;
511
512	/* setup default colors */
513	Scr->FirstTime = TRUE;
514	GetColor(Scr->Monochrome, &black, "black");
515	Scr->Black = black;
516	GetColor(Scr->Monochrome, &white, "white");
517	Scr->White = white;
518
519	if (FirstScreen)
520	{
521	    SetFocus ((TwmWindow *)NULL, CurrentTime);
522
523	    /* define cursors */
524
525	    NewFontCursor(&UpperLeftCursor, "top_left_corner");
526	    NewFontCursor(&RightButt, "rightbutton");
527	    NewFontCursor(&LeftButt, "leftbutton");
528	    NewFontCursor(&MiddleButt, "middlebutton");
529	}
530
531	Scr->iconmgr.x = 0;
532	Scr->iconmgr.y = 0;
533	Scr->iconmgr.width = 150;
534	Scr->iconmgr.height = 5;
535	Scr->iconmgr.next = NULL;
536	Scr->iconmgr.prev = NULL;
537	Scr->iconmgr.lasti = &(Scr->iconmgr);
538	Scr->iconmgr.first = NULL;
539	Scr->iconmgr.last = NULL;
540	Scr->iconmgr.active = NULL;
541	Scr->iconmgr.scr = Scr;
542	Scr->iconmgr.columns = 1;
543	Scr->iconmgr.count = 0;
544	Scr->iconmgr.name = "TWM";
545	Scr->iconmgr.icon_name = "Icons";
546
547	Scr->IconDirectory = NULL;
548
549	Scr->siconifyPm = None;
550	Scr->pullPm = None;
551	Scr->hilitePm = None;
552	Scr->tbpm.xlogo = None;
553	Scr->tbpm.resize = None;
554	Scr->tbpm.question = None;
555	Scr->tbpm.menu = None;
556	Scr->tbpm.delete = None;
557
558	InitVariables();
559	InitMenus();
560
561	/* Parse it once for each screen. */
562	ParseTwmrc(InitFile);
563	assign_var_savecolor(); /* storeing pixels for twmrc "entities" */
564	if (Scr->SqueezeTitle == -1) Scr->SqueezeTitle = FALSE;
565	if (!Scr->HaveFonts) CreateFonts();
566	CreateGCs();
567	MakeMenus();
568
569	Scr->TitleBarFont.y += Scr->FramePadding;
570	Scr->TitleHeight = Scr->TitleBarFont.height + Scr->FramePadding * 2;
571	/* make title height be odd so buttons look nice and centered */
572	if (!(Scr->TitleHeight & 1)) Scr->TitleHeight++;
573
574	InitTitlebarButtons ();		/* menus are now loaded! */
575
576	XGrabServer(dpy);
577	XSync(dpy, 0);
578
579	JunkX = 0;
580	JunkY = 0;
581
582	XQueryTree(dpy, Scr->Root, &root, &parent, &children, &nchildren);
583	CreateIconManagers();
584	if (!Scr->NoIconManagers)
585	    Scr->iconmgr.twm_win->icon = TRUE;
586
587	/*
588	 * weed out icon windows
589	 */
590	for (i = 0; i < nchildren; i++) {
591	    if (children[i]) {
592		XWMHints *wmhintsp = XGetWMHints (dpy, children[i]);
593
594		if (wmhintsp) {
595		    if (wmhintsp->flags & IconWindowHint) {
596			for (j = 0; j < nchildren; j++) {
597			    if (children[j] == wmhintsp->icon_window) {
598				children[j] = None;
599				break;
600			    }
601			}
602		    }
603		    XFree ((char *) wmhintsp);
604		}
605	    }
606	}
607
608	/*
609	 * map all of the non-override windows
610	 */
611	for (i = 0; i < nchildren; i++)
612	{
613	    if (children[i] && MappedNotOverride(children[i]))
614	    {
615		XUnmapWindow(dpy, children[i]);
616		SimulateMapRequest(children[i]);
617	    }
618	}
619
620	if (Scr->ShowIconManager && !Scr->NoIconManagers)
621	{
622	    Scr->iconmgr.twm_win->icon = FALSE;
623	    if (Scr->iconmgr.count)
624	    {
625		SetMapStateProp (Scr->iconmgr.twm_win, NormalState);
626		XMapWindow(dpy, Scr->iconmgr.w);
627		XMapWindow(dpy, Scr->iconmgr.twm_win->frame);
628	    }
629	}
630
631
632	attributes.border_pixel = Scr->DefaultC.fore;
633	attributes.background_pixel = Scr->DefaultC.back;
634	attributes.event_mask = (ExposureMask | ButtonPressMask |
635				 KeyPressMask | ButtonReleaseMask);
636	attributes.backing_store = NotUseful;
637	attributes.cursor = XCreateFontCursor (dpy, XC_hand2);
638	valuemask = (CWBorderPixel | CWBackPixel | CWEventMask |
639		     CWBackingStore | CWCursor);
640	Scr->InfoWindow = XCreateWindow (dpy, Scr->Root, 0, 0,
641					 (unsigned int) 5, (unsigned int) 5,
642					 (unsigned int) BW, 0,
643					 (unsigned int) CopyFromParent,
644					 (Visual *) CopyFromParent,
645					 valuemask, &attributes);
646
647	Scr->SizeStringWidth = MyFont_TextWidth (&Scr->SizeFont,
648					   " 8888 x 8888 ", 13);
649	valuemask = (CWBorderPixel | CWBackPixel | CWBitGravity);
650	attributes.bit_gravity = NorthWestGravity;
651	Scr->SizeWindow = XCreateWindow (dpy, Scr->Root, 0, 0,
652					 (unsigned int) Scr->SizeStringWidth,
653					 (unsigned int) (Scr->SizeFont.height +
654							 SIZE_VINDENT*2),
655					 (unsigned int) BW, 0,
656					 (unsigned int) CopyFromParent,
657					 (Visual *) CopyFromParent,
658					 valuemask, &attributes);
659
660	XUngrabServer(dpy);
661
662	FirstScreen = FALSE;
663    	Scr->FirstTime = FALSE;
664    } /* for */
665
666    if (numManaged == 0) {
667	if (MultiScreen && NumScreens > 0)
668	  fprintf (stderr, "%s:  unable to find any unmanaged %sscreens.\n",
669		   ProgramName, NoPrintscreens?"":"video ");
670	exit (1);
671    }
672
673    (void) ConnectToSessionManager (client_id);
674
675    RestartPreviousState = False;
676    HandlingEvents = TRUE;
677    InitEvents();
678    HandleEvents();
679    exit(0);
680}
681
682/**
683 * initialize twm variables
684 */
685void
686InitVariables()
687{
688    FreeList(&Scr->BorderColorL);
689    FreeList(&Scr->IconBorderColorL);
690    FreeList(&Scr->BorderTileForegroundL);
691    FreeList(&Scr->BorderTileBackgroundL);
692    FreeList(&Scr->TitleForegroundL);
693    FreeList(&Scr->TitleBackgroundL);
694    FreeList(&Scr->IconForegroundL);
695    FreeList(&Scr->IconBackgroundL);
696    FreeList(&Scr->IconManagerFL);
697    FreeList(&Scr->IconManagerBL);
698    FreeList(&Scr->IconMgrs);
699    FreeList(&Scr->NoTitle);
700    FreeList(&Scr->MakeTitle);
701    FreeList(&Scr->AutoRaise);
702    FreeList(&Scr->IconNames);
703    FreeList(&Scr->NoHighlight);
704    FreeList(&Scr->NoStackModeL);
705    FreeList(&Scr->NoTitleHighlight);
706    FreeList(&Scr->DontIconify);
707    FreeList(&Scr->IconMgrNoShow);
708    FreeList(&Scr->IconMgrShow);
709    FreeList(&Scr->IconifyByUn);
710    FreeList(&Scr->StartIconified);
711    FreeList(&Scr->IconManagerHighlightL);
712    FreeList(&Scr->SqueezeTitleL);
713    FreeList(&Scr->DontSqueezeTitleL);
714    FreeList(&Scr->WindowRingL);
715    FreeList(&Scr->WarpCursorL);
716
717    NewFontCursor(&Scr->FrameCursor, "top_left_arrow");
718    NewFontCursor(&Scr->TitleCursor, "top_left_arrow");
719    NewFontCursor(&Scr->IconCursor, "top_left_arrow");
720    NewFontCursor(&Scr->IconMgrCursor, "top_left_arrow");
721    NewFontCursor(&Scr->MoveCursor, "fleur");
722    NewFontCursor(&Scr->ResizeCursor, "fleur");
723    NewFontCursor(&Scr->MenuCursor, "sb_left_arrow");
724    NewFontCursor(&Scr->ButtonCursor, "hand2");
725    NewFontCursor(&Scr->WaitCursor, "watch");
726    NewFontCursor(&Scr->SelectCursor, "dot");
727    NewFontCursor(&Scr->DestroyCursor, "pirate");
728
729    Scr->Ring = NULL;
730    Scr->RingLeader = NULL;
731
732    Scr->DefaultC.fore = black;
733    Scr->DefaultC.back = white;
734    Scr->BorderColor = black;
735    Scr->BorderTileC.fore = black;
736    Scr->BorderTileC.back = white;
737    Scr->TitleC.fore = black;
738    Scr->TitleC.back = white;
739    Scr->MenuC.fore = black;
740    Scr->MenuC.back = white;
741    Scr->MenuTitleC.fore = black;
742    Scr->MenuTitleC.back = white;
743    Scr->MenuShadowColor = black;
744    Scr->MenuBorderColor = black;
745    Scr->IconC.fore = black;
746    Scr->IconC.back = white;
747    Scr->IconBorderColor = black;
748    Scr->PointerForeground.pixel = black;
749    XQueryColor(dpy, Scr->TwmRoot.cmaps.cwins[0]->colormap->c,
750		&Scr->PointerForeground);
751    Scr->PointerBackground.pixel = white;
752    XQueryColor(dpy, Scr->TwmRoot.cmaps.cwins[0]->colormap->c,
753		&Scr->PointerBackground);
754    Scr->IconManagerC.fore = black;
755    Scr->IconManagerC.back = white;
756    Scr->IconManagerHighlight = black;
757
758    Scr->FramePadding = 2;		/* values that look "nice" on */
759    Scr->TitlePadding = 8;		/* 75 and 100dpi displays */
760    Scr->ButtonIndent = 1;
761    Scr->SizeStringOffset = 0;
762    Scr->BorderWidth = BW;
763    Scr->IconBorderWidth = BW;
764    Scr->MenuBorderWidth = BW;
765    Scr->UnknownWidth = 0;
766    Scr->UnknownHeight = 0;
767    Scr->NumAutoRaises = 0;
768    Scr->NoDefaults = FALSE;
769    Scr->UsePPosition = PPOS_OFF;
770    Scr->FocusRoot = TRUE;
771    Scr->Focus = NULL;
772    Scr->WarpCursor = FALSE;
773    Scr->ForceIcon = FALSE;
774    Scr->NoGrabServer = FALSE;
775    Scr->NoRaiseMove = FALSE;
776    Scr->NoRaiseResize = FALSE;
777    Scr->NoRaiseDeicon = FALSE;
778    Scr->NoRaiseWarp = FALSE;
779    Scr->DontMoveOff = FALSE;
780    Scr->DoZoom = FALSE;
781    Scr->TitleFocus = TRUE;
782    Scr->NoTitlebar = FALSE;
783    Scr->DecorateTransients = FALSE;
784    Scr->IconifyByUnmapping = FALSE;
785    Scr->ShowIconManager = FALSE;
786    Scr->IconManagerDontShow =FALSE;
787    Scr->BackingStore = TRUE;
788    Scr->SaveUnder = TRUE;
789    Scr->RandomPlacement = FALSE;
790    Scr->OpaqueMove = FALSE;
791    Scr->Highlight = TRUE;
792    Scr->StackMode = TRUE;
793    Scr->TitleHighlight = TRUE;
794    Scr->MoveDelta = 1;		/* so that f.deltastop will work */
795    Scr->ZoomCount = 8;
796    Scr->SortIconMgr = FALSE;
797    Scr->Shadow = TRUE;
798    Scr->InterpolateMenuColors = FALSE;
799    Scr->NoIconManagers = FALSE;
800    Scr->ClientBorderWidth = FALSE;
801    Scr->SqueezeTitle = -1;
802    Scr->FirstRegion = NULL;
803    Scr->LastRegion = NULL;
804    Scr->FirstTime = TRUE;
805    Scr->HaveFonts = FALSE;		/* i.e. not loaded yet */
806    Scr->CaseSensitive = TRUE;
807    Scr->WarpUnmapped = FALSE;
808
809    /* setup default fonts; overridden by defaults from system.twmrc */
810#define DEFAULT_NICE_FONT "variable"
811#define DEFAULT_FAST_FONT "fixed"
812
813    Scr->TitleBarFont.font = NULL;
814    Scr->TitleBarFont.fontset = NULL;
815    Scr->TitleBarFont.name = DEFAULT_NICE_FONT;
816    Scr->MenuFont.font = NULL;
817    Scr->MenuFont.fontset = NULL;
818    Scr->MenuFont.name = DEFAULT_NICE_FONT;
819    Scr->IconFont.font = NULL;
820    Scr->IconFont.fontset = NULL;
821    Scr->IconFont.name = DEFAULT_NICE_FONT;
822    Scr->SizeFont.font = NULL;
823    Scr->SizeFont.fontset = NULL;
824    Scr->SizeFont.name = DEFAULT_FAST_FONT;
825    Scr->IconManagerFont.font = NULL;
826    Scr->IconManagerFont.fontset = NULL;
827    Scr->IconManagerFont.name = DEFAULT_NICE_FONT;
828    Scr->DefaultFont.font = NULL;
829    Scr->DefaultFont.fontset = NULL;
830    Scr->DefaultFont.name = DEFAULT_FAST_FONT;
831
832}
833
834void
835CreateFonts ()
836{
837    GetFont(&Scr->TitleBarFont);
838    GetFont(&Scr->MenuFont);
839    GetFont(&Scr->IconFont);
840    GetFont(&Scr->SizeFont);
841    GetFont(&Scr->IconManagerFont);
842    GetFont(&Scr->DefaultFont);
843    Scr->HaveFonts = TRUE;
844}
845
846void
847RestoreWithdrawnLocation (TwmWindow *tmp)
848{
849    int gravx, gravy;
850    unsigned int bw, mask;
851    XWindowChanges xwc;
852
853    if (XGetGeometry (dpy, tmp->w, &JunkRoot, &xwc.x, &xwc.y,
854		      &JunkWidth, &JunkHeight, &bw, &JunkDepth)) {
855
856	GetGravityOffsets (tmp, &gravx, &gravy);
857	if (gravy < 0) xwc.y -= tmp->title_height;
858
859	if (bw != tmp->old_bw) {
860	    int xoff, yoff;
861
862	    if (!Scr->ClientBorderWidth) {
863		xoff = gravx;
864		yoff = gravy;
865	    } else {
866		xoff = 0;
867		yoff = 0;
868	    }
869
870	    xwc.x -= (xoff + 1) * tmp->old_bw;
871	    xwc.y -= (yoff + 1) * tmp->old_bw;
872	}
873	if (!Scr->ClientBorderWidth) {
874	    xwc.x += gravx * tmp->frame_bw;
875	    xwc.y += gravy * tmp->frame_bw;
876	}
877
878	mask = (CWX | CWY);
879	if (bw != tmp->old_bw) {
880	    xwc.border_width = tmp->old_bw;
881	    mask |= CWBorderWidth;
882	}
883
884	XConfigureWindow (dpy, tmp->w, mask, &xwc);
885
886	if (tmp->wmhints && (tmp->wmhints->flags & IconWindowHint)) {
887	    XUnmapWindow (dpy, tmp->wmhints->icon_window);
888	}
889
890    }
891}
892
893
894void
895Reborder (Time time)
896{
897    TwmWindow *tmp;			/* temp twm window structure */
898    int scrnum;
899
900    /* put a border back around all windows */
901
902    XGrabServer (dpy);
903    for (scrnum = 0; scrnum < NumScreens; scrnum++)
904    {
905	if ((Scr = ScreenList[scrnum]) == NULL)
906	    continue;
907
908	InstallWindowColormaps (0, &Scr->TwmRoot);	/* force reinstall */
909	for (tmp = Scr->TwmRoot.next; tmp != NULL; tmp = tmp->next)
910	{
911	    RestoreWithdrawnLocation (tmp);
912	    XMapWindow (dpy, tmp->w);
913	}
914    }
915
916    XUngrabServer (dpy);
917    SetFocus ((TwmWindow*)NULL, time);
918}
919
920static SIGNAL_T
921sigHandler(int sig)
922{
923    XtNoticeSignal(si);
924    SIGNAL_RETURN;
925}
926
927/**
928 * cleanup and exit twm
929 */
930void
931Done(XtPointer client_data, XtSignalId *si)
932{
933    if (dpy)
934    {
935	Reborder(CurrentTime);
936	XCloseDisplay(dpy);
937    }
938    exit(0);
939}
940
941
942/*
943 * Error Handlers.  If a client dies, we'll get a BadWindow error (except for
944 * GetGeometry which returns BadDrawable) for most operations that we do before
945 * manipulating the client's window.
946 */
947
948Bool ErrorOccurred = False;
949XErrorEvent LastErrorEvent;
950
951static int
952TwmErrorHandler(Display *dpy, XErrorEvent *event)
953{
954    LastErrorEvent = *event;
955    ErrorOccurred = True;
956
957    if (PrintErrorMessages && 			/* don't be too obnoxious */
958	event->error_code != BadWindow &&	/* watch for dead puppies */
959	(event->request_code != X_GetGeometry &&	 /* of all styles */
960	 event->error_code != BadDrawable))
961      XmuPrintDefaultErrorMessage (dpy, event, stderr);
962    return 0;
963}
964
965
966static int
967CatchRedirectError(Display *dpy, XErrorEvent *event)
968{
969    RedirectError = TRUE;
970    LastErrorEvent = *event;
971    ErrorOccurred = True;
972    return 0;
973}
974