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