1: #include <X/mit-copyright.h> 2: 3: /* Copyright Massachusetts Institute of Technology 1985 */ 4: 5: /* 6: * xwm - X Window System window manager main routine. 7: * 8: */ 9: 10: #include "xwm.h" 11: 12: #ifdef PROFIL 13: #include <signal.h> 14: 15: #ifndef lint 16: static char *rcsid_main_c = "$Header: main.c,v 10.6 86/02/01 16:10:36 tony Rel $"; 17: #endif 18: /* 19: * Dummy handler for profiling. 20: */ 21: ptrap() 22: { 23: exit(0); 24: } 25: #endif 26: 27: static short gray_bits[16] = { 28: 0xaaaa, 0x5555, 0xaaaa, 0x5555, 29: 0xaaaa, 0x5555, 0xaaaa, 0x5555, 30: 0xaaaa, 0x5555, 0xaaaa, 0x5555, 31: 0xaaaa, 0x5555, 0xaaaa, 0x5555 32: }; 33: 34: main(argc, argv) 35: int argc; /* Argument count. */ 36: char **argv; /* Argument vector. */ 37: { 38: register int i; /* Loop index. */ 39: register int status; /* Routine call return status. */ 40: register char *arg; /* Current argument pointer. */ 41: int x, y; /* Mouse X and Y coordinates. */ 42: int str_width; /* Width in pixels of output string. */ 43: int pop_width, pop_height; /* Pop up window width and height. */ 44: int temp_button_mask = 0; /* Temporary button event mask. */ 45: char *def_val; /* X Default value. */ 46: char *i_font_name; /* Icon font name. */ 47: char *p_font_name; /* Pop up font name. */ 48: char display[256]; /* Display identifier string. */ 49: char message[128]; /* Error message buffer. */ 50: Bitmap gray_bitmap; /* Gray bitmap used for gray pixmap. */ 51: Window event_win; /* Event window. */ 52: Window focus_win; /* Keyboard focus window. */ 53: WindowInfo root_info; /* Root window info. */ 54: XButtonEvent button_event; /* Button input event. */ 55: Bool focus_seq = FALSE; /* Has a focus sequence begun? */ 56: Bool changed = FALSE; /* Has the window changed? */ 57: Bool none = FALSE; /* Allow the mouse with no keys. */ 58: Bool focus = FALSE; /* Allow input focusing? */ 59: Bool reverse = FALSE; /* Reverse video? */ 60: 61: #ifdef PROFIL 62: signal(SIGTERM, ptrap); 63: #endif 64: 65: /* 66: * Set up internal defaults. 67: */ 68: i_font_name = DEF_I_FONT; 69: p_font_name = DEF_P_FONT; 70: CursorFunc = DEF_FUNC; 71: ButtonMask = DEF_BUTTON_MASK; 72: Delta = DEF_DELTA; 73: IBorderWidth = DEF_ICON_BORDER_WIDTH; 74: IPadding = DEF_ICON_PADDING; 75: PBorderWidth = DEF_POP_BORDER_WIDTH; 76: PPadding = DEF_POP_PADDING; 77: 78: /* 79: * Initialize fixed globals. 80: */ 81: Grid = FALSE; 82: Zap = FALSE; 83: 84: /* 85: * Set XErrorFunction to be non-terminating. 86: */ 87: XErrorHandler(XError); 88: 89: /* 90: * Check for X defaults. 91: */ 92: def_val = XGetDefault(argv[0], "IconFont"); 93: if (def_val != NULL) i_font_name = def_val; 94: 95: def_val = XGetDefault(argv[0], "BodyFont"); 96: if (def_val != NULL) p_font_name = def_val; 97: 98: def_val = XGetDefault(argv[0], "InternalBorder"); 99: if (def_val != NULL) { 100: IPadding = atoi(def_val); 101: PPadding = atoi(def_val); 102: } 103: 104: def_val = XGetDefault(argv[0], "BorderWidth"); 105: if (def_val != NULL) { 106: IBorderWidth = atoi(def_val); 107: PBorderWidth = atoi(def_val); 108: } 109: 110: def_val = XGetDefault(argv[0], "ReverseVideo"); 111: if (def_val != NULL) { 112: if (strcmp (def_val, "on") == 0) reverse = TRUE; 113: } 114: 115: /* 116: * Parse the command line arguments. 117: */ 118: for (i = 1; i < argc; i++) { 119: arg = argv[i]; 120: switch (*arg) { 121: case '\0': 122: continue; 123: case '-': 124: arg++; 125: if (*arg == '\0') break; 126: for (; *arg; arg++) { 127: switch (*arg) { 128: case 'c': 129: /* 130: * Add the control key to the mouse button mask. 131: */ 132: temp_button_mask |= ControlMask; 133: break; 134: case 'd': 135: /* 136: * Check for a debug flag. 137: */ 138: Debug = TRUE; 139: break; 140: case 's': 141: /* 142: * Add the shift key to the mouse button mask. 143: */ 144: temp_button_mask |= ShiftMask; 145: break; 146: case 'm': 147: /* 148: * Add the meta key to the mouse button mask. 149: */ 150: temp_button_mask |= MetaMask; 151: break; 152: case 'n': 153: /* 154: * No keys are needed with the mouse. 155: */ 156: none = TRUE; 157: break; 158: case 'f': 159: /* 160: * Require double clicking to focus input. 161: */ 162: focus = TRUE; 163: break; 164: case 'g': 165: /* 166: * Display the tic tac toe grid on window change. 167: */ 168: Grid = TRUE; 169: break; 170: case 'r': 171: /* 172: * Make icons and pop-ups reverse video. 173: */ 174: reverse = TRUE; 175: break; 176: case 'z': 177: /* 178: * Use zap effect? 179: */ 180: Zap = TRUE; 181: break; 182: } 183: } 184: break; 185: case '+': 186: CursorFunc = atoi(arg + 1); 187: if (CursorFunc <= 0 || CursorFunc > 15) { 188: /* 189: * Oops, cursor function code out of range! 190: */ 191: errno = EDOM; 192: sprintf( 193: message, 194: "Cursor function code '%d' out of range (0 - 14).", 195: CursorFunc 196: ); 197: Error(message); 198: } 199: break; 200: case '@': 201: Delta = atoi(arg + 1); 202: if (Delta <= 0 || Delta > 100) { 203: /* 204: * Oops, delta value out of range! 205: */ 206: errno = EDOM; 207: sprintf( 208: message, 209: "Delta value '%d' out of range (1 - 99).", 210: Delta 211: ); 212: Error(message); 213: } 214: break; 215: case 'f': 216: if ((arg[1] == 'n') && (arg[2] == '=')) { 217: p_font_name = arg + 3; 218: } 219: else if ((arg[1] == 'i') && (arg[2] == '=')) { 220: i_font_name = arg + 3; 221: } 222: break; 223: default: 224: /* 225: * All that is left is a possible display string. 226: */ 227: strcpy(display, arg); 228: } 229: } 230: 231: /* 232: * Set the global mouse button event mask. 233: */ 234: 235: if (temp_button_mask) ButtonMask = temp_button_mask; 236: 237: if (none) ButtonMask = 0; 238: 239: /* 240: * Open the Display. 241: */ 242: if (XOpenDisplay(display) == NULL) { 243: /* 244: * Oops, can't open the display! 245: */ 246: sprintf(message, "Unable to open display '%s'.", display); 247: Error(message); 248: } 249: 250: /* 251: * Gather information about the root window. 252: */ 253: status = XQueryWindow(RootWindow, &root_info); 254: if (status == FAILURE) { 255: Error("Can't acquire root window information from X server."); 256: } 257: 258: ScreenHeight = root_info.height; /* True height of entire screen. */ 259: ScreenWidth = root_info.width; /* True width of entire screen. */ 260: 261: /* 262: * Create and store the icon background pixmap. 263: */ 264: gray_bitmap = XStoreBitmap(16, 16, gray_bits); 265: GrayPixmap = XMakePixmap(gray_bitmap, BlackPixel, WhitePixel); 266: 267: 268: /* 269: * Set up icon window, icon cursor and pop-up window color parameters. 270: */ 271: if (reverse) { 272: IconCursorFunc = GXcopyInverted; 273: IBorder = WhitePixmap; 274: IBackground = GrayPixmap; 275: ITextForground = WhitePixel; 276: ITextBackground = BlackPixel; 277: PBorder = BlackPixmap; 278: PBackground = WhitePixmap; 279: PTextForground = BlackPixel; 280: PTextBackground = WhitePixel; 281: } 282: else { 283: IconCursorFunc = GXcopy; 284: IBorder = BlackPixmap; 285: IBackground = GrayPixmap; 286: ITextForground = BlackPixel; 287: ITextBackground = WhitePixel; 288: PBorder = WhitePixmap; 289: PBackground = BlackPixmap; 290: PTextForground = WhitePixel; 291: PTextBackground = BlackPixel; 292: } 293: 294: /* 295: * Store all the cursors. 296: */ 297: StoreCursors(); 298: 299: /* 300: * Grab all 3 mouse buttons w/ respect to the root window. Grab 301: * pressed status with the mouse button mask. 302: */ 303: status = XGrabButton( 304: RootWindow, 305: DotCursor, 306: (LeftMask | ButtonMask), 307: (ButtonPressed | ButtonReleased) 308: ); 309: if (status == FAILURE) Error("Can't grab left mouse button."); 310: status = XGrabButton( 311: RootWindow, 312: ArrowCrossCursor, 313: (MiddleMask | ButtonMask), 314: (ButtonPressed | ButtonReleased) 315: ); 316: if (status == FAILURE) Error("Can't grab middle mouse button."); 317: status = XGrabButton( 318: RootWindow, 319: CircleCursor, 320: (RightMask | ButtonMask), 321: (ButtonPressed | ButtonReleased) 322: ); 323: if (status == FAILURE) Error("Can't grab right mouse button."); 324: 325: /* 326: * Load the selected fonts and retrieve the information structure 327: * for each. Set global font information pointers. 328: */ 329: IFont = XGetFont(i_font_name); 330: if (IFont == FAILURE) { 331: sprintf(message, "Unable to get icon font '%s'.", i_font_name); 332: Error(message); 333: } 334: 335: status = XQueryFont(IFont, &IFontInfo); 336: if (status == FAILURE) { 337: Error("Unable to query X server for icon font information."); 338: } 339: 340: PFont = XGetFont(p_font_name); 341: if (PFont == FAILURE) { 342: sprintf(message, "Unable to get pop up font '%s'.", p_font_name); 343: Error(message); 344: } 345: 346: status = XQueryFont(PFont, &PFontInfo); 347: if (status == FAILURE) { 348: Error("Unable to query X server for pop up font information."); 349: } 350: 351: /* 352: * Calculate size of the resize pop-up window. 353: */ 354: str_width = XQueryWidth(PText, PFont); 355: pop_width = str_width + (PPadding << 1); 356: PWidth = pop_width + (PBorderWidth << 1); 357: pop_height = PFontInfo.height + (PPadding << 1); 358: PHeight = pop_height + (PBorderWidth << 1); 359: 360: /* 361: * Create the pop-up window. Create it at (0, 0) for now, we will 362: * move it where we want later. 363: */ 364: Pop = XCreateWindow( 365: RootWindow, 366: 0, 0, 367: pop_width, pop_height, 368: PBorderWidth, 369: PBorder, PBackground 370: ); 371: if (Pop == FAILURE) Error("Can't open pop-up dimension display window."); 372: 373: /* 374: * Main command loop. 375: */ 376: while (TRUE) { 377: /* 378: * Get the next mouse button event. Spin our wheels until 379: * a button event is returned (ie. GetButton == TRUE). 380: * Note that mouse events within an icon window are handled 381: * in the "GetButton" function or by the icon's owner if 382: * it is not xwm. 383: */ 384: if (!GetButton(&button_event)) continue; 385: 386: /* 387: * If the button event recieved is not a ButtonPressed event 388: * then continue until we find one. 389: */ 390: if (button_event.type != ButtonPressed) continue; 391: 392: /* 393: * Ok, determine the event window and mouse coordinates. 394: */ 395: status = XInterpretLocator( 396: RootWindow, 397: &x, &y, 398: &event_win, 399: button_event.location 400: ); 401: if (status == FAILURE) continue; 402: 403: /* 404: * If the event subwindow is 0 then the event 405: * occured on the root window. 406: */ 407: if (event_win == 0) { 408: event_win = RootWindow; 409: } 410: 411: /* 412: * Invoke a function based on which button was pressed. 413: */ 414: switch (button_event.detail & ValueMask) { 415: case LeftButton: 416: /* 417: * LeftDown is used to lower or iconify a window if 418: * the event window is not the root window. If it is the 419: * RoowWindow then circulate all windows down. 420: */ 421: 422: /* 423: * Abort any focus sequence that is in progress. 424: */ 425: focus_seq = FALSE; 426: 427: if (event_win == RootWindow) { 428: XCircWindowDown(RootWindow); 429: } 430: else { 431: LowerIconify(event_win, x, y); 432: } 433: break; 434: 435: case MiddleButton: 436: /* 437: * MiddleDown is used to resize a window and establish the 438: * focus window. 439: */ 440: 441: /* 442: * If this is not the root window, go ahead and allow it 443: * to be changed. 444: */ 445: changed = FALSE; 446: if (event_win != RootWindow) { 447: changed = Change(event_win, x, y); 448: } 449: 450: if (focus) { 451: /* 452: * Two middle clicks will focus the keyboard... 453: */ 454: if (focus_seq) { 455: /* 456: * ... and this is the second ... 457: */ 458: if (focus_win == event_win) { 459: /* 460: * ... and both have the same event window then 461: * focus the keyboard provided the window did not 462: * change. This also ends the focus sequence. 463: */ 464: if (!changed) XFocusKeyboard(event_win); 465: focus_seq = FALSE; 466: focus_win = RootWindow; 467: } 468: else { 469: /* 470: * ... both don't have the same window. This 471: * ends the focus sequence. 472: */ 473: focus_seq = FALSE; 474: focus_win = RootWindow; 475: } 476: } 477: else { 478: /* 479: * Begin a focus sequence, salt away the 480: * perspective focus window. 481: */ 482: focus_seq = TRUE; 483: focus_win = event_win; 484: } 485: } 486: break; 487: 488: case RightButton: 489: /* 490: * RightDown is used to move a window or bring it to the 491: * top of the window stack if the event window is not 492: * the root window. If it is the root window then circulate 493: * all windows up. 494: */ 495: 496: /* 497: * Abort any focus sequence that is in progress. 498: */ 499: focus_seq = FALSE; 500: 501: if (event_win == RootWindow) { 502: XCircWindowUp(RootWindow); 503: } 504: else { 505: Move(event_win, x, y); 506: } 507: break; 508: 509: } 510: } 511: }