|
|
1.1 root 1: #include "wm.h"
2:
3: #ifndef lint
4: static char *rcsid_wmsubs_c = "$Header: xnwm.c,v 10.6 86/11/19 19:31:32 jg Rel $";
5: #endif
6:
7: #define default_frame_width 5
8: #define default_mask MetaMask
9: #define default_menu_font "8x13"
10: #define default_size_font "8x13"
11: #define default_icon_font "8x13"
12: #define default_iconify_delta 5
13: #define default_menu_x 0
14: #define default_menu_y 0
15:
16: /* Default button assignments; the numbers are indices into the
17: menuOp array */
18:
19: #define default_left 0
20: #define default_middle 1
21: #define default_right 2
22: #define unassigned_button -1
23: #define popup_button -2
24:
25: /* Convert 0,1,2 into XRight(Middle,Left)Mask */
26: #define Button(i) (1 << (8 + (i)))
27:
28: #include "wm.cursor"
29:
30: #include "buttons.raster"
31: Pixmap buttonPixmap[3];
32:
33: Window menu;
34: typedef int (*ptrToFunc) ();
35: int Raise(), Lower(), Move(), Resize(), IconifyOrDeIconify(),
36: Select(), Circulate(), Assign(), Unassigned();
37: char *label[] = {"Select", "Raise", "Move", "(De)Iconify",
38: "Lower", "Resize", "Circulate", "Assign", ""};
39: ptrToFunc menuOp[] = {Select, Raise, Move, IconifyOrDeIconify,
40: Lower, Resize, Circulate, Assign};
41: int needsWindow[] = {TRUE, TRUE, TRUE, TRUE,
42: TRUE, TRUE, FALSE, TRUE};
43: int canDoToMenu[] = {FALSE, TRUE, TRUE, FALSE,
44: TRUE, FALSE, TRUE, TRUE};
45: /* "item" needs an extra entry at the end */
46: Window item[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
47: int buttonFunc[3] = {default_right, default_middle, default_left};
48: int itemcount, itemWidth, itemHeight;
49: int menuWidth, menuHeight, menuX, menuY;
50: char code[] = "srmilzc"; /* button assignment codes for command line */
51: int skinny = FALSE, twoRows = FALSE, vertical = FALSE;
52: int lastMenuOp = -1;
53: int doingOp = FALSE;
54:
55: int savex, savey; /* Where and what the popup menu obscures */
56: Pixmap saveScreen;
57: Pixmap menuImage = 0; /* What the popup menu looks like */
58: int popupSaved = FALSE; /* True if a popup image is saved */
59:
60: int reverse; /* whether to reverse the normal colors */
61: int buttonGXfunc; /* function to put up the button picture */
62:
63: char *index();
64:
65: main(argc, argv)
66: int argc;
67: char **argv;
68: {
69: Window w;
70: BEvent button;
71: int raisedMenu = FALSE;
72:
73: SetUpEverything(argc, argv);
74:
75: while (TRUE) {
76: GetButton(&button);
77:
78: /* If it's a ButtonReleased ignore; it's just left
79: over from some old click */
80:
81: if (button.type == ButtonReleased) continue;
82:
83: InterpretLocatorW(RootWindow, &w, button.location);
84:
85: /* If in background, raise menu or move back if just raised.
86: If using popup windows, map the popup window. Only do this
87: as long as the button is not bound to Select */
88:
89: if (w == 0 && NonSelect(&button)) {
90: if (popup) MapPopup(button.location);
91: else {
92: if (raisedMenu) XMoveWindow(menu, menuX, menuY);
93: else XRaiseWindow(menu);
94: raisedMenu = TRUE;
95: }
96: continue;
97: } else raisedMenu = FALSE;
98:
99: /* If in menu, do appropriate function */
100:
101: if (w == menu) {
102: ProcessMenuFunction(&button);
103: if (popup) UnmapPopup();
104: continue;
105: }
106:
107: /* Otherwise do preassigned button function */
108:
109: DoButtonFunc(&button, w);
110: }
111: }
112:
113: SetUpEverything(argc, argv)
114: int argc;
115: char **argv;
116: {
117: char *mfname = default_menu_font; /* font to use */
118: char *sfname = default_size_font; /* font to use */
119: char *ifname = default_icon_font; /* font to use */
120: char *location = "";
121: char display[256]; /* display to use */
122:
123: frameWidth = default_frame_width;
124: mask = default_mask;
125: iconifyDelta = default_iconify_delta;
126: menuX = menuY = 0;
127: freeze = TRUE;
128: popup = FALSE;
129: reverse = FALSE;
130:
131: GetDefaults(argv[0], &mfname, &sfname, &ifname, &location);
132: ProcessArgs(argc, argv, display, &mfname, &sfname, &ifname, &location);
133: OpenDisplay (display);
134: StoreCursors();
135: StorePixmaps();
136: SetUpFonts(mfname, sfname, ifname);
137: SetUpMenu(location);
138: GrabButtons();
139: InitializeWm();
140: }
141:
142: GetDefaults(progname, mfname, sfname, ifname, location)
143: char *progname;
144: char **mfname, **sfname, **ifname, **location;
145: {
146: register char *option;
147: int newmask = 0;
148:
149: if ((option = XGetDefault(progname,"MenuFont")) != NULL) {
150: *mfname = option;
151: }
152: if ((option = XGetDefault(progname,"SizeFont")) != NULL) {
153: *sfname = option;
154: }
155: if ((option = XGetDefault(progname,"IconFont")) != NULL) {
156: *ifname = option;
157: }
158: if ((option = XGetDefault(progname,"ReverseVideo")) != NULL) {
159: if (strcmp(option, "on") == 0) reverse = TRUE;
160: }
161: if ((option = XGetDefault(progname,"FrameWidth")) != NULL) {
162: frameWidth = atoi(option);
163: }
164: if ((option = XGetDefault(progname,"IconifyDelta")) != NULL) {
165: iconifyDelta = atoi(option);
166: }
167: if ((option = XGetDefault(progname,"MenuFormat")) != NULL) {
168: if (index(option, 't') != NULL) skinny = TRUE;
169: if (index(option, '2') != NULL) twoRows = skinny = TRUE;
170: if (index(option, 'v') != NULL) vertical = skinny = TRUE;
171: }
172: if ((option = XGetDefault(progname,"Freeze")) != NULL) {
173: if (strcmp(option, "off") == 0) freeze = FALSE;
174: }
175: if ((option = XGetDefault(progname,"KeyCombination")) != NULL) {
176: if (index(option, 'c') != NULL) newmask |= ControlMask;
177: if (index(option, 's') != NULL) newmask |= ShiftMask;
178: if (index(option, 'm') != NULL) newmask |= MetaMask;
179: if (index(option, 'l') != NULL) newmask |= ShiftLockMask;
180: if (index(option, 'n') != NULL) mask = 0;
181: else if (newmask) mask = newmask;
182: }
183: if ((option = XGetDefault(progname,"LeftButton")) != NULL) {
184: AssignButton(LeftButton, option[0]);
185: }
186: if ((option = XGetDefault(progname,"MiddleButton")) != NULL) {
187: AssignButton(MiddleButton, option[0]);
188: }
189: if ((option = XGetDefault(progname,"RightButton")) != NULL) {
190: AssignButton(RightButton, option[0]);
191: }
192: if ((option = XGetDefault(progname,"Geometry")) != NULL) {
193: *location = option;
194: }
195:
196: }
197:
198: ProcessArgs(argc, argv, display, mfname, sfname, ifname, location)
199: int argc;
200: char **argv;
201: char *display;
202: char **mfname, **sfname, **ifname, **location;
203: {
204: int i, newmask = 0, none = FALSE;
205: register char *arg;
206:
207: for (i = 1; i < argc; i++) {
208: arg = argv[i];
209: switch (*arg) {
210: case '\0':
211: continue;
212:
213: case '-':
214: arg++;
215: if (*arg == '\0') mask = 0;
216: else {
217: newmask = 0;
218: for (; *arg; arg++) {
219: switch (*arg) {
220: case 'h':
221: Syntax();
222: break;
223:
224: case 'c':
225: newmask |= ControlMask;
226: break;
227:
228: case 's':
229: newmask |= ShiftMask;
230: break;
231:
232: case 'm':
233: newmask |= MetaMask;
234: break;
235:
236: case 'l':
237: newmask |= ShiftLockMask;
238: break;
239:
240: case 'n':
241: none = TRUE;
242: break;
243:
244: case 'f':
245: freeze = FALSE;
246: break;
247:
248: case 'r':
249: reverse = TRUE;
250: break;
251:
252: case '2':
253: twoRows = skinny = TRUE;
254: vertical = FALSE;
255: break;
256:
257: case 'v':
258: vertical = skinny = TRUE;
259: twoRows = FALSE;
260: break;
261:
262: case 't':
263: skinny = TRUE;
264: vertical = twoRows = FALSE;
265: break;
266:
267: default:
268: Syntax();
269: break;
270: }
271: }
272: if (newmask) mask = newmask;
273: if (none) mask = 0;
274: }
275: break;
276:
277: case '@':
278: frameWidth = atoi(arg+1);
279: if (frameWidth < 0 || frameWidth > 100) {
280: errno = EDOM;
281: perror("xnwm:");
282: }
283: break;
284:
285: case '%':
286: iconifyDelta = atoi(arg+1);
287: break;
288:
289: case '=':
290: *location = arg+1;
291: break;
292:
293: default:
294: if (arg[1] == '=') {
295: switch (*arg) {
296: case 'l':
297: AssignButton(LeftButton, arg[2]);
298: break;
299:
300: case 'm':
301: AssignButton(MiddleButton, arg[2]);
302: break;
303:
304: case 'r':
305: AssignButton(RightButton, arg[2]);
306: break;
307:
308: default:
309: Syntax();
310: break;
311: }
312: } else if (arg[0] == 'f' && arg[2] == '=') {
313: switch (arg[1]) {
314: case 'm':
315: *mfname = arg+3;
316: break;
317:
318: case 's':
319: *sfname = arg+3;
320: break;
321:
322: case 'i':
323: *ifname = arg+3;
324: break;
325:
326: default:
327: Syntax();
328: break;
329: }
330: } else strcpy(display, arg);
331: }
332: }
333:
334: if (buttonFunc[RightButton] == popup_button ||
335: buttonFunc[MiddleButton] == popup_button ||
336: buttonFunc[LeftButton] == popup_button) {
337: popup = vertical = skinny = TRUE;
338: }
339: }
340:
341: AssignButton(which, arg)
342: int which;
343: char arg;
344: {
345: char *ch;
346:
347: if (arg == '\0') {
348: buttonFunc[which] = unassigned_button;
349: return;
350: } else if (arg == 'p') {
351: buttonFunc[which] = popup_button;
352: return;
353: }
354: ch = index(code, arg);
355: if (ch == NULL) {
356: errno = EDOM;
357: perror ("xnwm:");
358: } else buttonFunc[which] = ch - code;
359: }
360:
361: Syntax()
362: {
363: puts("Usage: xnwm {-csmln} {-f} {-r} {-2vt} {@[framewidth]}");
364: puts(" {%[iconifyDelta]} {=[{+-}xoff[{+-}yoff]]}");
365: puts(" {l={srmilzcp}} {m={srmilzcp}} {r={srmilzcp}}");
366: puts(" {fm=menu_font} {fs=size_font} {fi=icon_font}");
367: puts(" {[host]:vs}"); /* whew */
368:
369: exit(0);
370: }
371:
372: OpenDisplay(display)
373: char *display;
374: {
375: WindowInfo winfo;
376:
377: if (XOpenDisplay(display) == NULL) {
378: fprintf(stderr, "%s: Can't open display '%s'\n",
379: "xnwm" , XDisplayName(display));
380: exit(1);
381: }
382:
383: QueryWindow(RootWindow, &winfo);
384: screen_height = winfo.height;
385: screen_width = winfo.width;
386:
387: XSelectInput(RootWindow,
388: ButtonPressed | ButtonReleased | UnmapWindow | FocusChange);
389:
390: if (reverse) {
391: bgColor = BlackPixel;
392: bgPixmap = BlackPixmap;
393: fgColor = WhitePixel;
394: fgPixmap = WhitePixmap;
395: buttonGXfunc = GXor;
396: } else {
397: bgColor = WhitePixel;
398: bgPixmap = WhitePixmap;
399: fgColor = BlackPixel;
400: fgPixmap = BlackPixmap;
401: buttonGXfunc = GXand;
402: }
403: }
404:
405: StoreCursors()
406: {
407: wmCursor = XCreateCursor(nwm_width, nwm_height,
408: (caddr_t) nwm_bits, (caddr_t) NULL,
409: 1, 1,
410: fgColor, bgColor,
411: GXcopyInverted);
412: if (wmCursor == NULL) {
413: Error("Couldn't store wmCursor in StoreCursors");
414: }
415: }
416:
417: StorePixmaps()
418: {
419: static short gray_bits[] = {
420: 0xaaaa, 0x5555, 0xaaaa, 0x5555,
421: 0xaaaa, 0x5555, 0xaaaa, 0x5555,
422: 0xaaaa, 0x5555, 0xaaaa, 0x5555,
423: 0xaaaa, 0x5555, 0xaaaa, 0x5555
424: };
425:
426: buttonPixmap[RightButton] =
427: MakePixmap(button_width, button_height,
428: (caddr_t) rbutton_bits, bgColor, fgColor);
429:
430: buttonPixmap[MiddleButton] =
431: MakePixmap(button_width, button_height,
432: (caddr_t) mbutton_bits, bgColor, fgColor);
433:
434: buttonPixmap[LeftButton] =
435: MakePixmap(button_width, button_height,
436: (caddr_t) lbutton_bits, bgColor, fgColor);
437:
438: gray = MakePixmap(16, 16,
439: (caddr_t) gray_bits, bgColor, fgColor);
440: }
441:
442: Pixmap MakePixmap(width, height, bits, fg, bg)
443: int width, height;
444: caddr_t bits;
445: int fg, bg;
446: {
447: Bitmap b;
448: Pixmap p;
449:
450: b = XStoreBitmap(width, height, bits);
451: if (b == NULL) Error("Couldn't store bitmap in MakePixmap");
452: p = XMakePixmap (b, fg, bg);
453: if (p == NULL) Error("Couldn't make pixmap in MakePixmap");
454: XFreeBitmap(b);
455: return p;
456: }
457:
458: SetUpFonts(mfname, sfname, ifname)
459: char *mfname, *sfname, *ifname;
460: {
461: menufont = XGetFont(mfname);
462: if (menufont == NULL) Error("Couldn't store menu font in SetUpFont");
463: sizefont = XGetFont(sfname);
464: if (sizefont == NULL) Error("Couldn't store size font in SetUpFont");
465: iconfont = XGetFont(ifname);
466: if (iconfont == NULL) Error("Couldn't store icon font in SetUpFont");
467: }
468:
469: SetUpMenu(location)
470: char *location;
471: {
472: register int i = 0;
473: int width = 0, textwidth;
474: int x, y;
475: char xSign, ySign;
476:
477: while (label[i][0] != '\0') {
478: textwidth = XQueryWidth(label[i], menufont);
479: if (textwidth == 0) {
480: Error("Couldn't query string width in SetUpMenu");
481: }
482: if (textwidth > width) width = textwidth;
483: i++;
484: }
485:
486: itemcount = i;
487: if (skinny) {
488: itemWidth = 1 + 3 + width + 3 + button_width + 3 + 1;
489: } else itemWidth = screen_width / itemcount;
490: itemHeight = 20;
491:
492: if (vertical) {
493: menuWidth = itemWidth;
494: menuHeight = itemcount * itemHeight;
495: } else if (twoRows) {
496: menuWidth = itemWidth * ((itemcount+1) >> 1);
497: menuHeight = itemHeight * 2;
498: } else {
499: menuWidth = itemWidth * itemcount;
500: menuHeight = itemHeight;
501: }
502: if (!popup && *location != '\0') {
503: /* Interpret the location string */
504:
505: InterpLocation(location, &x, &y, &xSign, &ySign);
506:
507: if (xSign == '+') menuX = x;
508: else menuX = screen_width - x - menuWidth;
509:
510: if (ySign == '+') menuY = y;
511: else menuY = screen_height - y - menuHeight;
512: }
513:
514: menu = XCreateWindow(RootWindow, menuX, menuY, menuWidth, menuHeight,
515: 1, fgPixmap, bgPixmap);
516: if (menu == NULL) Error ("Couldn't open menu in SetUpMenu");
517: XStoreName(menu, "xnwm menu");
518: XDefineCursor(menu, wmCursor);
519:
520: if (popup) XSelectInput(menu, LeaveWindow);
521: else XSelectInput(menu, ExposeWindow);
522:
523: if (!popup) {
524: x = y = -1;
525:
526: for (i = 0; i < itemcount; i++) {
527: if (twoRows && i == (itemcount+1) >> 1) {
528: y = itemHeight;
529: x = -1;
530: }
531: item[i] = XCreateWindow (menu, x, y, itemWidth, itemHeight, 1,
532: fgPixmap, bgPixmap);
533: if (item[i] == NULL) Error ("Couldn't open item in SetUpMenu");
534: if (vertical) y += itemHeight;
535: else x += itemWidth;
536: }
537: XMapSubwindows(menu);
538: XMapWindow(menu);
539: }
540:
541: menuWidth += 2; /* Consider the border in from now on */
542: menuHeight += 2;
543:
544: /* Don't draw anything; the expose event will cause that */
545: }
546:
547: InterpLocation(location, x, y, xSign, ySign)
548: register char *location;
549: register int *x, *y;
550: char *xSign, *ySign;
551: {
552: *xSign = *location;
553:
554: switch (*location) {
555: case '+':
556: case '-':
557: location++;
558: *x = 0;
559: while(*location >= '0' && *location <= '9') {
560: *x = 10 * *x + (*location++ - '0');
561: }
562: break;
563:
564: default:
565: Syntax();
566: break;
567: }
568:
569: *ySign = *location;
570:
571: switch (*location) {
572: case '+':
573: case '-':
574: location++;
575: *y = 0;
576: while(*location >= '0' && *location <= '9') {
577: *y = 10 * *y + (*location++ - '0');
578: }
579: break;
580:
581: default:
582: Syntax();
583: break;
584: }
585:
586: if (*location != '\0') Syntax();
587: }
588:
589: GrabButtons()
590: {
591: register int i;
592:
593: for (i = 0; i < 3; i++) {
594: if (buttonFunc[i] != unassigned_button) {
595: status = XGrabButton(RootWindow, wmCursor,
596: mask | Button(i),
597: ButtonPressed|ButtonReleased);
598: if (status == NULL) {
599: Error("Couldn't grab button in GrabButtons");
600: }
601: }
602: }
603: }
604:
605: ProcessMenuFunction(button)
606: BEvent *button;
607: {
608: Window w;
609: register int i = 0;
610:
611: InterpretLocatorW(menu, &w, button->location);
612: while (item[i] != NULL && item[i] != w) i++;
613:
614: if (item[i]) {
615: InvertButton(i);
616: DoOperation(i, button->detail);
617: DisplayButton(i);
618: lastMenuOp = i;
619: }
620: }
621:
622: DoOperation(i, which)
623: int i, which;
624: {
625: BEvent newbutton;
626: Window w;
627: WindowInfo winfo;
628:
629: /* First wait for the upbutton; if it doesn't occur or
630: occurs in a different window abort */
631:
632: GetButton(&newbutton);
633: InterpretLocatorW(menu, &w, newbutton.location);
634: if (!MatchUp(newbutton, which) || w != item[i]) return;
635:
636: doingOp = TRUE;
637:
638: /* If the function needs a window, get one */
639:
640: if (needsWindow[i]) {
641: status = XGrabMouse(RootWindow, wmCursor,
642: ButtonPressed | ButtonReleased);
643: if (status == NULL) Error ("Couldn't grab mouse in DoOperation");
644: GetButton(&newbutton);
645:
646: /* This should be the same button as was pushed to select
647: the function */
648:
649: if (!MatchDown(newbutton, which)) {
650: XUngrabMouse();
651: doingOp = FALSE;
652: return;
653: }
654:
655: InterpretLocatorW(RootWindow, &w, newbutton.location);
656: if (w == 0) w = RootWindow;
657: QueryWindow(w, &winfo);
658: }
659:
660: /* Now call the appropriate function */
661:
662: if (canDoToMenu[i] || w != menu) {
663: (*menuOp[i])(which, newbutton.location, w, &winfo);
664: }
665: doingOp = FALSE;
666:
667: if (needsWindow[i]) XUngrabMouse();
668: }
669:
670: /* Returns whether or not the button is bound to Select */
671:
672: int NonSelect(button)
673: BEvent *button;
674: {
675: int which = button->detail & 0xff; /* 0, 1, or 2 */
676: int func = buttonFunc[which];
677:
678: return (func < 0 || menuOp[func] != Select);
679: }
680:
681: DoButtonFunc(button, w)
682: BEvent *button;
683: Window w;
684: {
685: int which = button->detail & 0xff; /* 0, 1, or 2 */
686: register int func = buttonFunc[which];
687: WindowInfo winfo;
688:
689: if (func == unassigned_button) {
690: Unassigned();
691: return;
692: }
693:
694: /* popup_button signifies the button to map the popup window */
695:
696: if (func == popup_button) {
697: MapPopup(button->location);
698: return;
699: }
700:
701: if (w == 0) w = RootWindow;
702:
703: if (needsWindow[func]) {
704: status = XGrabMouse(RootWindow, wmCursor,
705: ButtonPressed|ButtonReleased);
706: if (status == 0) Error ("Couldn't grab mouse in DoButtonFunc");
707: QueryWindow(w, &winfo);
708: }
709:
710: InvertButton(func);
711: (*menuOp[func])(which, button->location, w, &winfo);
712: DisplayButton(func);
713:
714: if (needsWindow[func]) XUngrabMouse();
715: }
716:
717: Unassigned()
718: {
719: XFeep (3);
720: }
721:
722: MapPopup(loc)
723: Locator loc;
724: {
725: int x, y;
726: Window w;
727: register int i;
728:
729: /* If there's not a saved popup image, create the buttons */
730:
731: if (!popupSaved) { /* Create the items */
732: XDestroySubwindows(menu); /* Get rid of old items */
733: x = y = -1;
734: for (i = 0; i < itemcount; i++) {
735: item[i] = XCreateWindow (menu, x, y, itemWidth, itemHeight, 1,
736: fgPixmap, bgPixmap);
737: if (item[i] == NULL) Error ("Couldn't open item in MapPopup");
738: y += itemHeight;
739: }
740: XMapSubwindows(menu);
741: }
742:
743: InterpretLocatorXY(RootWindow, &x, &y, loc);
744:
745: x -= menuWidth >> 1;
746: if (lastMenuOp == -1) y -= menuHeight >> 1;
747: else y -= lastMenuOp * (itemHeight+1) + (itemHeight >> 1);
748:
749: if (x < 0) x = 0;
750: else if (x + menuWidth > screen_width) {
751: x = screen_width - menuWidth;
752: }
753:
754: if (y < 0) y = 0;
755: else if (y + menuHeight > screen_height) {
756: y = screen_height - menuHeight;
757: }
758:
759: if (freeze) {
760: savex = x;
761: savey = y;
762: XGrabServer();
763: saveScreen = XPixmapSave(RootWindow, x, y, menuWidth, menuHeight);
764: if (saveScreen == 0) Error("Couldn't save screen in MapPopup");
765: }
766:
767: XMoveWindow(menu, x, y);
768: XMapWindow(menu);
769:
770: if (popupSaved) {
771: XPixmapPut(menu, 0, 0, 0, 0, menuWidth-2, menuHeight-2,
772: menuImage, GXcopy, AllPlanes);
773: } else {
774: for (i = 0; i < itemcount; i++) DisplayButton(i);;
775: menuImage = XPixmapSave(menu, 0, 0, menuWidth-2, menuHeight-2);
776: if (menuImage == 0) Error("Couldn't save menu in MapPopup");
777: }
778: QueryMouse(RootWindow, &x, &y, &w);
779: if (w != menu) UnmapPopup();
780: }
781:
782: UnmapPopup()
783: {
784: register int x, y, i;
785:
786: if (freeze && saveScreen != 0) {
787: XUnmapTransparent(menu);
788: XPixmapPut(RootWindow, 0, 0, savex, savey, menuWidth, menuHeight,
789: saveScreen, GXcopy, AllPlanes);
790: XFreePixmap(saveScreen);
791: XUngrabServer();
792: saveScreen = 0;
793: } else XUnmapWindow(menu);
794:
795: /* Now set things up so we don't have to map everything next time */
796:
797: if (!popupSaved) {
798: if (menuImage != 0) {
799: XDestroySubwindows(menu); /* Get rid of old items */
800: x = y = 0;
801: for (i = 0; i < itemcount; i++) {
802: item[i] = XCreateTransparency(menu, x, y,
803: itemWidth, itemHeight);
804: if (item[i] == NULL) {
805: Error("Couldn't open item in UnmapPopup");
806: }
807: y += itemHeight;
808: }
809: XMapSubwindows(menu);
810: popupSaved = TRUE;
811: }
812: }
813: }
814:
815: /* Undo the popup menu caching. We can't just test popupSaved, since
816: it gets set in UnmapPopup and we might be called in between */
817:
818: UnsavePopup()
819: {
820: if (menuImage != 0) {
821: XFreePixmap(menuImage);
822: menuImage = 0;
823: }
824:
825: if (popupSaved) popupSaved = FALSE;
826: }
827:
828: InvertButton(i)
829: int i;
830: {
831: if (item[i] == 0) return;
832:
833: XPixFill(item[i], -1, -1, 200, 200, 0, (Bitmap) 0,
834: GXinvert, 1);
835: }
836:
837: DisplayButton(i)
838: int i;
839: {
840: register int j;
841:
842: if (item[i] == 0) return;
843:
844: XPixSet(item[i], -1, -1, 200, 200, bgColor);
845: XText(item[i], 3, 3, label[i], strlen(label[i]), menufont,
846: fgColor, bgColor);
847: for (j = 0; j < 3; j++) {
848: if (buttonFunc[j] == i) {
849: XPixmapPut (item[buttonFunc[j]], 0, 0,
850: itemWidth - button_width - 3, 4,
851: button_width, button_height, buttonPixmap[j],
852: buttonGXfunc, AllPlanes);
853: }
854: }
855: }
856:
857: IconifyOrDeIconify(which, loc, w, winfo)
858: int which;
859: Locator loc;
860: Window w;
861: WindowInfo *winfo;
862: {
863: if (w == RootWindow) return;
864:
865: /* If we're trying to iconify an icon deiconify instead */
866:
867: if (winfo->type == IsIcon) Deiconify(which, loc, w, winfo);
868: else Iconify(which, loc, w, winfo);
869: }
870:
871: /* ARGSUSED */
872:
873: Assign(which, loc, w, winfo)
874: int which;
875: Locator loc;
876: Window w;
877: WindowInfo *winfo;
878: {
879: register int i;
880: int choice, cleared = FALSE;
881: BEvent newbutton;
882: Window neww;
883:
884: /* First make sure the new click was in the menu; if not
885: clear that button */
886:
887: if (w != menu) return;
888:
889: /* Now get rid of the old function assigned this button. But, don't
890: deassign the popup window button! */
891:
892: choice = buttonFunc[which];
893: if (choice == popup_button) return;
894:
895: if (popup) UnsavePopup(); /* The saved popup menu is invalid */
896:
897: if (choice >= 0) {
898: XClear(item[choice]);
899: buttonFunc[which] = unassigned_button;
900: DisplayButton(choice);
901: cleared = TRUE;
902: }
903:
904: /* Now find out which subwindow we were in */
905:
906: InterpretLocatorW(menu, &w, loc);
907: for (i = 0; item[i] != NULL && item[i] != w; i++) {}
908:
909: /* Can't assign Assign */
910:
911: if (menuOp[i] == NULL || menuOp[i] == Assign) {
912: if (cleared) XUngrabButton(mask | Button(which));
913: return;
914: }
915:
916: /* Now wait for the release; if it doesn't occur abort */
917:
918: GetButton(&newbutton);
919: if (!MatchUp(newbutton, which)) {
920: if (cleared) XUngrabButton(mask | Button(which));
921: return;
922: }
923:
924: InterpretLocatorW(menu, &neww, loc);
925:
926: if (neww != w) {
927: if (cleared) XUngrabButton(mask | Button(which));
928: return;
929: }
930:
931: /* Now assign that function to the button */
932:
933: buttonFunc[which] = i;
934:
935: XPixmapPut(item[i], 0, 0,
936: itemWidth - button_width - 3, 4,
937: button_width, button_height, buttonPixmap[which],
938: buttonGXfunc, AllPlanes);
939:
940: if (!cleared) { /* New assignment */
941: status = XGrabButton(RootWindow, wmCursor,
942: mask | Button(which),
943: ButtonPressed|ButtonReleased);
944: if (status == 0) Error ("Couldn't grab button in Assign");
945: }
946: }
947:
948: /* Returns whether or not this is a real event */
949:
950: int GetEvent(event)
951: XEvent *event;
952: {
953: XButtonEvent *be = (XButtonEvent *) event;
954: XLeaveWindowEvent *lwe = (XLeaveWindowEvent *) event;
955: XExposeEvent *ee = (XExposeEvent *) event;
956: XUnmapEvent *ue = (XUnmapEvent *) event;
957: XFocusChangeEvent *fce = (XFocusChangeEvent *) event;
958: WindowInfo winfo;
959: char *iconName;
960:
961: XNextEvent(event);
962:
963: /* If it's in the base window, no trouble */
964:
965: if (event->window == RootWindow) {
966: if (event->type == FocusChange) {
967: if (fce->detail == EnterWindow && fce->subwindow == 0) {
968: FocusOn(RootWindow);
969: FrameFocus();
970: }
971: return FALSE;
972:
973: } else if (event->type == UnmapWindow) {
974: FrameFocus(); /* The background has changed */
975: return FALSE;
976: }
977:
978: be->detail &= 0xff; /* mask out state of shift keys */
979: return TRUE;
980: }
981:
982: /* Is it the menu window? */
983:
984: if (event->window == menu) {
985: if (event->type == ExposeWindow) {
986: if (ee->subwindow != 0) RefreshMenu(ee->subwindow);
987: return FALSE;
988: }
989: if (event->type == LeaveWindow) {
990: if (lwe->subwindow == 0 && !doingOp) UnmapPopup();
991: return FALSE;
992: }
993: }
994:
995: /* Let's see if it's in an icon */
996:
997: QueryWindow(event->window, &winfo);
998:
999: if (winfo.type != IsIcon) return FALSE; /* Nope -- nothing */
1000:
1001: if (event->type == UnmapWindow) return FALSE;
1002:
1003: status = XFetchName(winfo.assoc_wind, &iconName);
1004: if (status == 0) Error ("Couldn't fetch name in GetButton");
1005:
1006: if (event->type == ExposeWindow) { /* Just refresh the icon */
1007: XClear(ee->window);
1008: if (iconName != NULL && iconName[0] != '\0') {
1009: XText(ee->window, 4, 4, iconName, strlen(iconName), iconfont,
1010: fgColor, bgColor);
1011: }
1012: } else EditIconName((XKeyPressedEvent *)be, iconName);
1013: if (iconName) free(iconName);
1014: return FALSE;
1015: }
1016:
1017: GetButton(event)
1018: BEvent *event;
1019: {
1020: while (!GetEvent(event)) ;
1021: }
1022:
1023: RefreshMenu(w)
1024: Window w;
1025: {
1026: register int i;
1027:
1028: for (i = 0; i < itemcount && item[i] != w; i++) {}
1029: if (i >= itemcount) return;
1030: DisplayButton(i);
1031: }
1032:
1033: Error(string)
1034: char *string;
1035: {
1036: fprintf(stderr, "\nxmwm: %s", string);
1037: fprintf(stderr, "\n\n");
1038:
1039: if (errno != 0) {
1040: perror("xwm");
1041: fprintf(stderr, "\n");
1042: }
1043:
1044: exit(1);
1045: }
1046:
1047: Flush()
1048: {
1049: XFlush();
1050: }
1051:
1052: Sync()
1053: {
1054: XSync(FALSE);
1055: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.