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