|
|
1.1 root 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.7 86/11/19 20:01:48 jg 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: fprintf(stderr, "%s: Can't open display '%s'\n",
247: argv[0], XDisplayName(display));
248: exit(1);
249: }
250:
251: /*
252: * Gather information about the root window.
253: */
254: status = XQueryWindow(RootWindow, &root_info);
255: if (status == FAILURE) {
256: Error("Can't acquire root window information from X server.");
257: }
258:
259: ScreenHeight = root_info.height; /* True height of entire screen. */
260: ScreenWidth = root_info.width; /* True width of entire screen. */
261:
262: /*
263: * Create and store the icon background pixmap.
264: */
265: gray_bitmap = XStoreBitmap(16, 16, gray_bits);
266: GrayPixmap = XMakePixmap(gray_bitmap, BlackPixel, WhitePixel);
267:
268:
269: /*
270: * Set up icon window, icon cursor and pop-up window color parameters.
271: */
272: if (reverse) {
273: IconCursorFunc = GXcopyInverted;
274: IBorder = WhitePixmap;
275: IBackground = GrayPixmap;
276: ITextForground = WhitePixel;
277: ITextBackground = BlackPixel;
278: PBorder = BlackPixmap;
279: PBackground = WhitePixmap;
280: PTextForground = BlackPixel;
281: PTextBackground = WhitePixel;
282: }
283: else {
284: IconCursorFunc = GXcopy;
285: IBorder = BlackPixmap;
286: IBackground = GrayPixmap;
287: ITextForground = BlackPixel;
288: ITextBackground = WhitePixel;
289: PBorder = WhitePixmap;
290: PBackground = BlackPixmap;
291: PTextForground = WhitePixel;
292: PTextBackground = BlackPixel;
293: }
294:
295: /*
296: * Store all the cursors.
297: */
298: StoreCursors();
299:
300: /*
301: * Grab all 3 mouse buttons w/ respect to the root window. Grab
302: * pressed status with the mouse button mask.
303: */
304: status = XGrabButton(
305: RootWindow,
306: DotCursor,
307: (LeftMask | ButtonMask),
308: (ButtonPressed | ButtonReleased)
309: );
310: if (status == FAILURE) Error("Can't grab left mouse button.");
311: status = XGrabButton(
312: RootWindow,
313: ArrowCrossCursor,
314: (MiddleMask | ButtonMask),
315: (ButtonPressed | ButtonReleased)
316: );
317: if (status == FAILURE) Error("Can't grab middle mouse button.");
318: status = XGrabButton(
319: RootWindow,
320: CircleCursor,
321: (RightMask | ButtonMask),
322: (ButtonPressed | ButtonReleased)
323: );
324: if (status == FAILURE) Error("Can't grab right mouse button.");
325:
326: /*
327: * Load the selected fonts and retrieve the information structure
328: * for each. Set global font information pointers.
329: */
330: IFont = XGetFont(i_font_name);
331: if (IFont == FAILURE) {
332: sprintf(message, "Unable to get icon font '%s'.", i_font_name);
333: Error(message);
334: }
335:
336: status = XQueryFont(IFont, &IFontInfo);
337: if (status == FAILURE) {
338: Error("Unable to query X server for icon font information.");
339: }
340:
341: PFont = XGetFont(p_font_name);
342: if (PFont == FAILURE) {
343: sprintf(message, "Unable to get pop up font '%s'.", p_font_name);
344: Error(message);
345: }
346:
347: status = XQueryFont(PFont, &PFontInfo);
348: if (status == FAILURE) {
349: Error("Unable to query X server for pop up font information.");
350: }
351:
352: /*
353: * Calculate size of the resize pop-up window.
354: */
355: str_width = XQueryWidth(PText, PFont);
356: pop_width = str_width + (PPadding << 1);
357: PWidth = pop_width + (PBorderWidth << 1);
358: pop_height = PFontInfo.height + (PPadding << 1);
359: PHeight = pop_height + (PBorderWidth << 1);
360:
361: /*
362: * Create the pop-up window. Create it at (0, 0) for now, we will
363: * move it where we want later.
364: */
365: Pop = XCreateWindow(
366: RootWindow,
367: 0, 0,
368: pop_width, pop_height,
369: PBorderWidth,
370: PBorder, PBackground
371: );
372: if (Pop == FAILURE) Error("Can't open pop-up dimension display window.");
373:
374: /*
375: * Main command loop.
376: */
377: while (TRUE) {
378: /*
379: * Get the next mouse button event. Spin our wheels until
380: * a button event is returned (ie. GetButton == TRUE).
381: * Note that mouse events within an icon window are handled
382: * in the "GetButton" function or by the icon's owner if
383: * it is not xwm.
384: */
385: if (!GetButton(&button_event)) continue;
386:
387: /*
388: * If the button event recieved is not a ButtonPressed event
389: * then continue until we find one.
390: */
391: if (button_event.type != ButtonPressed) continue;
392:
393: /*
394: * Ok, determine the event window and mouse coordinates.
395: */
396: status = XInterpretLocator(
397: RootWindow,
398: &x, &y,
399: &event_win,
400: button_event.location
401: );
402: if (status == FAILURE) continue;
403:
404: /*
405: * If the event subwindow is 0 then the event
406: * occured on the root window.
407: */
408: if (event_win == 0) {
409: event_win = RootWindow;
410: }
411:
412: /*
413: * Invoke a function based on which button was pressed.
414: */
415: switch (button_event.detail & ValueMask) {
416: case LeftButton:
417: /*
418: * LeftDown is used to lower or iconify a window if
419: * the event window is not the root window. If it is the
420: * RoowWindow then circulate all windows down.
421: */
422:
423: /*
424: * Abort any focus sequence that is in progress.
425: */
426: focus_seq = FALSE;
427:
428: if (event_win == RootWindow) {
429: XCircWindowDown(RootWindow);
430: }
431: else {
432: LowerIconify(event_win, x, y);
433: }
434: break;
435:
436: case MiddleButton:
437: /*
438: * MiddleDown is used to resize a window and establish the
439: * focus window.
440: */
441:
442: /*
443: * If this is not the root window, go ahead and allow it
444: * to be changed.
445: */
446: changed = FALSE;
447: if (event_win != RootWindow) {
448: changed = Change(event_win, x, y);
449: }
450:
451: if (focus) {
452: /*
453: * Two middle clicks will focus the keyboard...
454: */
455: if (focus_seq) {
456: /*
457: * ... and this is the second ...
458: */
459: if (focus_win == event_win) {
460: /*
461: * ... and both have the same event window then
462: * focus the keyboard provided the window did not
463: * change. This also ends the focus sequence.
464: */
465: if (!changed) XFocusKeyboard(event_win);
466: focus_seq = FALSE;
467: focus_win = RootWindow;
468: }
469: else {
470: /*
471: * ... both don't have the same window. This
472: * ends the focus sequence.
473: */
474: focus_seq = FALSE;
475: focus_win = RootWindow;
476: }
477: }
478: else {
479: /*
480: * Begin a focus sequence, salt away the
481: * perspective focus window.
482: */
483: focus_seq = TRUE;
484: focus_win = event_win;
485: }
486: }
487: break;
488:
489: case RightButton:
490: /*
491: * RightDown is used to move a window or bring it to the
492: * top of the window stack if the event window is not
493: * the root window. If it is the root window then circulate
494: * all windows up.
495: */
496:
497: /*
498: * Abort any focus sequence that is in progress.
499: */
500: focus_seq = FALSE;
501:
502: if (event_win == RootWindow) {
503: XCircWindowUp(RootWindow);
504: }
505: else {
506: Move(event_win, x, y);
507: }
508: break;
509:
510: }
511: }
512: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.