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