|
|
1.1 root 1: /*
2: * $Locker: $
3: */
4: static char *rcsid = "$Header: test.c,v 1.2 87/06/17 16:08:52 swick Locked ";
5: #include <stdio.h>
6: #include <X11/Xlib.h>
7: #include <X11/Xutil.h>
8: #include <X11/Xatom.h>
9: #include <X11/X10.h>
10: #include "test.h"
11: #include "externs.h"
12: #include "dblArrow.h"
13: #include "growBox.h"
14: #include "cross.h"
15:
16: XAssocTable *frameInfo;
17: XFontStruct *font;
18: Display *dpy;
19: int ErrorFunc();
20:
21: extern char *malloc();
22:
23: void MoveOutline();
24:
25: RootInfoRec *
26: findRootInfo(win)
27: Window win;
28: {
29: int i;
30:
31: for (i = 0; i < ScreenCount(dpy); i++) {
32: if (RootInfo[i].root == win)
33: return (&(RootInfo[i]));
34: }
35: return (NULL);
36: }
37:
38: #ifdef debug
39: static char *eventtype[] = {
40: "zero",
41: "one",
42: "KeyPress",
43: "KeyRelease",
44: "ButtonPress",
45: "ButtonRelease",
46: "MotionNotify",
47: "EnterNotify",
48: "LeaveNotify",
49: "FocusIn",
50: "FocusOut",
51: "KeymapNotify",
52: "Expose",
53: "GraphicsExpose",
54: "NoExpose",
55: "VisibilityNotify",
56: "CreateNotify",
57: "DestroyNotify",
58: "UnmapNotify",
59: "MapNotify",
60: "MapRequest",
61: "ReparentNotify",
62: "ConfigureNotify",
63: "ConfigureRequest",
64: "GravityNotify",
65: "ResizeRequest",
66: "CirculateNotify",
67: "CirculateRequest",
68: "PropertyNotify",
69: "SelectionClear",
70: "SelectionRequest",
71: "SelectionNotify",
72: "ColormapNotify",
73: "ClientMessage",
74: "MappingNotify",
75: };
76: #endif debug
77:
78: main(argc, argv) int argc; char *argv[];
79: {
80: Window parent;
81: Window *children;
82: int nchildren;
83: int i;
84: Window dragWindow = None;
85: Window resizeWindow = None;
86: Window iconifyWindow = None;
87: int dragx, dragy;
88: int iconPressx, iconPressy;
89: int dragHeight, dragWidth;
90: int origx, origy, origWidth, origHeight;
91: int clampTop, clampBottom, clampLeft, clampRight;
92: int buttonsPressed = 0;
93: int buttonsDown[128]; /* XXX */
94: int hdrWidth;
95:
96: XSetWindowAttributes attributes;
97: XGCValues gcv;
98:
99: for (i = 0; i < 128; i++) buttonsDown[i] = 0; /* XXX */
100: StartConnectionToServer(argc, argv);
101: XSetErrorHandler(ErrorHandler);
102: #ifdef debug
103: XSynchronize(dpy, 1);
104: #endif
105: frameInfo = XCreateAssocTable(ASSOCTABLESZ);
106: if (!frameInfo) {
107: Error(1, "XCreateAssocTable failed\n");
108: }
109:
110: font = XLoadQueryFont(dpy, "fixed");
111: if (!font)
112: Error(1, "XFont failed\n");
113: #ifdef debug
114: printf("descent=%d, ascent=%d, width=%d\n",
115: font->max_bounds.descent, font->max_bounds.ascent,
116: font->max_bounds.width);
117: #endif
118:
119: RootInfo = (RootInfoRec *) malloc(ScreenCount(dpy) * sizeof(RootInfoRec));
120: for (i = 0; i < ScreenCount(dpy); i++) {
121: RootInfo[i].root = RootWindow(dpy, i);
122: RootInfo[i].doubleArrow = MakePixmap(RootInfo[i].root,
123: dblArrow_bits,
124: dblArrow_width,
125: dblArrow_height);
126: RootInfo[i].growBox = MakePixmap(RootInfo[i].root,
127: growBox_bits,
128: growBox_width,
129: growBox_height);
130: RootInfo[i].cross = MakePixmap(RootInfo[i].root,
131: cross_bits,
132: cross_width,
133: cross_height);
134: gcv.font = font->fid;
135: gcv.foreground = WhitePixel(dpy, i);
136: gcv.background = BlackPixel(dpy, i);
137: RootInfo[i].headerGC = XCreateGC(dpy, RootInfo[i].root,
138: GCForeground | GCBackground | GCFont, &gcv);
139: gcv.function = GXinvert;
140: gcv.subwindow_mode = IncludeInferiors;
141: RootInfo[i].xorGC = XCreateGC(dpy, RootInfo[i].root,
142: GCFunction | GCSubwindowMode, &gcv);
143: {
144: Window retroot;
145: int bw, depth;
146: XGetGeometry(dpy, (Drawable) RootInfo[i].root, &retroot,
147: &RootInfo[i].rootx, &RootInfo[i].rooty,
148: &RootInfo[i].rootwidth, &RootInfo[i].rootheight, &bw, &depth);
149: }
150: /*
151: * select Substructure Redirect on the root to have MapRequest
152: * events generated instead of windows getting mapped
153: */
154: errorStatus = False;
155: attributes.event_mask = (SubstructureRedirectMask|
156: ButtonPressMask|ButtonReleaseMask|FocusChangeMask);
157: XChangeWindowAttributes(dpy, RootInfo[i].root, CWEventMask, &attributes);
158: /* XSelectInput(dpy, root, SubstructureRedirectMask); */
159: XSync(dpy, False);
160: if (errorStatus == True) {
161: fprintf(stderr, "Are you running another window manager?\n");
162: exit(1);
163: }
164: if (XQueryTree(dpy, RootInfo[i].root, &RootInfo[i].root, &parent,
165: &children, &nchildren)) {
166: int i;
167:
168: for (i = 0; i < nchildren; i++) {
169: if (MappedNotOverride(children[i]))
170: AddGizmos(children[i]);
171: }
172: if (children)
173: free((char *)children);
174: }
175: XFlush(dpy);
176: }
177: XSetErrorHandler(ErrorFunc);
178: while (1) {
179: XEvent ev;
180: XNextEvent(dpy, &ev);
181: #ifdef debug
182: printf("event %s ", eventtype[ev.type]);
183: #endif
184: switch (ev.type) {
185: case MapRequest:{
186: Window w;
187: GenericAssoc *ga;
188: w = ev.xmaprequest.window;
189: ga = (GenericAssoc *) XLookUpAssoc(dpy, frameInfo, (XID) w);
190: if (ga) {
191: XMapWindow(dpy, ga->frame);
192: }
193: else {
194: AddGizmos(w);
195: #ifdef debug
196: printf("delivered to %s of frame %d\n",
197: WindowType(w), Frame(w));
198: #endif
199: }
200: break;
201: }
202: case UnmapNotify:{
203: GenericAssoc *ga;
204: Window w;
205: w = ev.xunmap.window;
206: #ifdef debug
207: printf("delivered to %s of frame %d\n",
208: WindowType(w), Frame(w));
209: #endif
210: ga = (GenericAssoc *) XLookUpAssoc(dpy, frameInfo, (XID) w);
211: if (ga && (ga->client == w))
212: XUnmapWindow(dpy, ga->frame);
213: break;
214: }
215: case DestroyNotify:{
216: GenericAssoc *ga;
217: Window w;
218: w = ev.xdestroywindow.window;
219: #ifdef debug
220: printf("delivered to %s of frame %d\n",
221: WindowType(w), Frame(w));
222: #endif
223: ga = (GenericAssoc *) XLookUpAssoc(dpy, frameInfo, (XID) w);
224: if (ga && (ga->client == w))
225: RemoveGizmos(ga);
226: break;
227: }
228: case PropertyNotify:{
229: GenericAssoc *ga;
230: Window w;
231: Window root;
232: int x, y, wd, ht, bw, d;
233:
234: w = ev.xproperty.window;
235: XGetGeometry(dpy, (Drawable) w, &root, &x, &y, &wd, &ht, &bw, &d);
236: ga = (GenericAssoc *) XLookUpAssoc(dpy, frameInfo, (XID) w);
237: if (!ga || w != ga->client)
238: break;
239: switch (ev.xproperty.atom) {
240: case XA_WM_NAME:
241: ProcessNewName(root, ga);
242: break;
243: case XA_WM_ICON_NAME:
244: ProcessNewIconName(root, ga);
245: break;
246: default:
247: break;
248: }
249: break;
250: }
251: case ButtonPress:{
252: GenericAssoc *ga;
253: Window w;
254: w = ev.xbutton.window;
255: #ifdef debug
256: printf("delivered to %s of frame %d\n",
257: WindowType(w), Frame(w));
258: #endif
259: if (buttonsDown[ev.xbutton.button])
260: break;
261: buttonsDown[ev.xbutton.button] = 1;
262: if (buttonsPressed++) {
263: iconifyWindow = None;
264: dragWindow = None;
265: resizeWindow = None;
266: MoveOutline(ev.xbutton.root,
267: ev.xbutton.x_root - dragx - BORDERWIDTH,
268: ev.xbutton.y_root - dragy - BORDERWIDTH,
269: 0, 0);
270: XUngrabServer(dpy);
271: break;
272: }
273: ga = (GenericAssoc *) XLookUpAssoc(dpy, frameInfo, (XID) w);
274: if (ga && (ga->rbox == w) && resizeWindow == None) {
275: Window junkRoot;
276: int junkbw, junkDepth;
277: resizeWindow = ga->frame;
278: XGrabServer(dpy);
279: XGetGeometry(dpy, (Drawable) resizeWindow, &junkRoot,
280: &dragx, &dragy, &dragWidth, &dragHeight, &junkbw,
281: &junkDepth);
282: dragx += BW;
283: dragy += BW;
284: origx = dragx;
285: origy = dragy;
286: origWidth = dragWidth;
287: origHeight = dragHeight;
288: clampTop = clampBottom = clampLeft = clampRight = 0;
289: }
290: else if (ga && (ga->iconWindow == w)) {
291: iconifyWindow = w;
292: if (ev.xbutton.state & ShiftMask) {
293: Window junkRoot;
294: int junkX, junkY, junkbw, junkDepth;
295: dragWindow = w;
296: dragx = ev.xbutton.x;
297: dragy = ev.xbutton.y;
298: XGrabServer(dpy);
299: XGetGeometry(dpy, (Drawable) dragWindow,
300: &junkRoot, &junkX,
301: &junkY, &dragWidth, &dragHeight, &junkbw,
302: &junkDepth);
303: #ifdef debug
304: printf("From: x=%d, y=%d, w=%d, h=%d\n",
305: junkX, junkY, dragWidth, dragHeight);
306: #endif
307: MoveOutline(ev.xbutton.root,
308: ev.xbutton.x_root - dragx - BORDERWIDTH,
309: ev.xbutton.y_root - dragy - BORDERWIDTH,
310: dragWidth + 2 * BORDERWIDTH,
311: dragHeight + 2 * BORDERWIDTH);
312: }
313: }
314: else if (ga && (ga->upbox == w)) {
315: XWindowChanges wc;
316: wc.stack_mode = Opposite;
317: XConfigureWindow(dpy, ga->frame, CWStackMode, &wc);
318: }
319: else if (ga && (ga->iconify == w) && (iconifyWindow == None)) {
320: Window junkRoot;
321: int junkX, junkY, junkbw, junkDepth;
322: iconifyWindow = w;
323: iconPressx = ev.xbutton.x_root;
324: iconPressy = ev.xbutton.y_root;
325: dragx = 0;
326: dragy = 0;
327: dragWindow = ga->iconWindow;
328: XGrabServer(dpy);
329: XGetGeometry(dpy, (Drawable) dragWindow,
330: &junkRoot, &junkX,
331: &junkY, &dragWidth, &dragHeight, &junkbw,
332: &junkDepth);
333: #ifdef debug
334: printf("From: x=%d, y=%d, w=%d, h=%d\n",
335: junkX, junkY, dragWidth, dragHeight);
336: #endif
337: MoveOutline(ev.xbutton.root,
338: ev.xbutton.x_root - dragx - BORDERWIDTH,
339: ev.xbutton.y_root - dragy - BORDERWIDTH,
340: dragWidth + 2 * BORDERWIDTH,
341: dragHeight + 2 * BORDERWIDTH);
342: }
343: else if (ga && (ga->header == w) && dragWindow == None) {
344: Window junkRoot;
345: int junkX, junkY, junkbw, junkDepth;
346: dragWindow = ga->frame;
347: dragx = ev.xbutton.x + UPBOXWIDTH + ICONIFYWIDTH + BORDERWIDTH;
348: dragy = ev.xbutton.y;
349: hdrWidth = ga->headerWidth;
350: XGrabServer(dpy);
351: XGetGeometry(dpy, (Drawable) dragWindow, &junkRoot, &junkX,
352: &junkY, &dragWidth, &dragHeight, &junkbw,
353: &junkDepth);
354: #ifdef debug
355: printf("From: x=%d, y=%d, w=%d, h=%d\n",
356: junkX, junkY, dragWidth, dragHeight);
357: #endif
358: MoveOutline(ev.xbutton.root,
359: ev.xbutton.x_root - dragx - BORDERWIDTH,
360: ev.xbutton.y_root - dragy - BORDERWIDTH,
361: dragWidth + 2 * BORDERWIDTH,
362: dragHeight + 2 * BORDERWIDTH);
363: }
364: else {
365: int newx, newy;
366: Window newRoot;
367: RootInfoRec *ro = findRootInfo(ev.xbutton.root);
368: RootInfoRec *rn = ro;
369:
370: if (++rn >= (RootInfo + ScreenCount(dpy)))
371: rn = RootInfo;
372: #ifdef debug
373: printf("Roots 0x%x: old 0x%x, new 0x%x\n", ev.xbutton.root, ro, rn);
374: #endif
375: if (rn != ro) {
376: #ifdef debug
377: printf("Warp from %d to %d new root is 0x%x\n",
378: (ro - RootInfo), (rn - RootInfo), rn->root);
379: #endif
380: newx = (((ev.xbutton.x_root - ro->rootx)*100/(ro->rootwidth))
381: *(rn->rootwidth))/100 + rn->rootx;
382: newy = (((ev.xbutton.y_root - ro->rooty)*100/(ro->rootheight))
383: *(rn->rootheight))/100 + rn->rooty;
384: XWarpPointer(dpy, None, rn->root, 0, 0, 0, 0, newx, newy);
385: }
386: }
387: break;
388: }
389: case MotionNotify:{
390: Window junkRoot, junkChild;
391: int junkx, junky, junkrx, junkry;
392: unsigned int junkMask;
393: Window root;
394: #ifdef debug
395: printf("\n");
396: #endif
397: if (QLength(dpy)) {
398: XEvent rete;
399: XPeekEvent(dpy, &rete);
400: if (rete.type == MotionNotify &&
401: rete.xmotion.window == ev.xmotion.window) {
402: break;
403: }
404: }
405: root = ev.xmotion.root;
406: if (dragWindow != None) {
407: int x, y;
408: x = ev.xmotion.x_root - dragx;
409: y = ev.xmotion.y_root - dragy;
410: if (iconifyWindow != None)
411: MakeReachable(root, &x, &y, dragWidth,
412: dragHeight);
413: else {
414: x += UPBOXWIDTH + ICONIFYWIDTH + BW;
415: MakeReachable(root, &x, &y, hdrWidth,
416: TITLEHEIGHT);
417: x -= UPBOXWIDTH + ICONIFYWIDTH + BW;
418: }
419: MoveOutline(root,
420: x - BORDERWIDTH, y - BORDERWIDTH,
421: dragWidth + 2 * BORDERWIDTH,
422: dragHeight + 2 * BORDERWIDTH);
423: XQueryPointer(dpy, root, &junkRoot, &junkChild,
424: &junkrx, &junkry,
425: &junkx, &junky, &junkMask);
426: }
427: else if (resizeWindow != None) {
428: int action = 0;
429: if (clampTop) {
430: int delta = ev.xmotion.y_root - dragy;
431: if (dragHeight - delta < MINHEIGHT) {
432: delta = dragHeight - MINHEIGHT;
433: clampTop = 0;
434: }
435: dragy += delta;
436: dragHeight -= delta;
437: action = 1;
438: }
439: else if (ev.xmotion.y_root <= dragy ||
440: ev.xmotion.y_root == findRootInfo(root)->rooty) {
441: dragy = ev.xmotion.y_root;
442: dragHeight = origy + origHeight -
443: ev.xmotion.y_root;
444: clampBottom = 0;
445: clampTop = 1;
446: action = 1;
447: }
448: if (clampLeft) {
449: int delta = ev.xmotion.x_root - dragx;
450: if (dragWidth - delta < MINWIDTH) {
451: delta = dragWidth - MINWIDTH;
452: clampLeft = 0;
453: }
454: dragx += delta;
455: dragWidth -= delta;
456: action = 1;
457: }
458: else if (ev.xmotion.x_root <= dragx ||
459: ev.xmotion.x_root == findRootInfo(root)->rootx) {
460: dragx = ev.xmotion.x_root;
461: dragWidth = origx + origWidth -
462: ev.xmotion.x_root;
463: clampRight = 0;
464: clampLeft = 1;
465: action = 1;
466: }
467: if (clampBottom) {
468: int delta = ev.xmotion.y_root - dragy - dragHeight;
469: if (dragHeight + delta < MINHEIGHT) {
470: delta = MINHEIGHT - dragHeight;
471: clampBottom = 0;
472: }
473: dragHeight += delta;
474: action = 1;
475: }
476: else if (ev.xmotion.y_root >= dragy + dragHeight - 1 ||
477: ev.xmotion.y_root == findRootInfo(root)->rooty
478: + findRootInfo(root)->rootheight - 1) {
479: dragy = origy;
480: dragHeight = 1 + ev.xmotion.y_root - dragy;
481: clampTop = 0;
482: clampBottom = 1;
483: action = 1;
484: }
485: if (clampRight) {
486: int delta = ev.xmotion.x_root - dragx - dragWidth;
487: if (dragWidth + delta < MINWIDTH) {
488: delta = MINWIDTH - dragWidth;
489: clampRight = 0;
490: }
491: dragWidth += delta;
492: action = 1;
493: }
494: else if (ev.xmotion.x_root >= dragx + dragWidth - 1 ||
495: ev.xmotion.x_root == findRootInfo(root)->rootx +
496: findRootInfo(root)->rootwidth - 1) {
497: dragx = origx;
498: dragWidth = 1 + ev.xmotion.x_root - origx;
499: clampLeft = 0;
500: clampRight = 1;
501: action = 1;
502: }
503: if (action) {
504: MoveOutline(root,
505: dragx - BORDERWIDTH,
506: dragy - BORDERWIDTH,
507: dragWidth + 2 * BORDERWIDTH,
508: dragHeight + 2 * BORDERWIDTH);
509: XQueryPointer(dpy, root, &junkRoot, &junkChild,
510: &junkrx, &junkry,
511: &junkx, &junky, &junkMask);
512: }
513: }
514: break;
515: }
516: case ButtonRelease:{
517: Window w;
518: GenericAssoc *ga;
519: if (!buttonsDown[ev.xbutton.button])
520: break;
521: buttonsDown[ev.xbutton.button] = 0;
522: buttonsPressed--;
523: w = ev.xbutton.window;
524: ga = (GenericAssoc *) XLookUpAssoc(dpy, frameInfo,
525: (XID) w);
526:
527: if (ga && (ga->header == w)
528: && (ga->frame == dragWindow)) {
529: XWindowChanges wc;
530: wc.x = ev.xbutton.x_root - dragx;
531: wc.y = ev.xbutton.y_root - dragy;
532: wc.x += UPBOXWIDTH + ICONIFYWIDTH + BW;
533: MakeReachable(ev.xbutton.root, &wc.x, &wc.y, ga->headerWidth,
534: TITLEHEIGHT);
535: wc.x -= UPBOXWIDTH + ICONIFYWIDTH + 2 * BW;
536: /*
537: * the extra BW is because XReconfigureWindow includes
538: * the border width in x and y, but not in width and
539: * height
540: */
541: wc.y -= BW;
542: #ifdef debug
543: printf("delivered to %s of frame %d\n",
544: WindowType(w), Frame(w));
545: #endif
546: MoveOutline(ev.xbutton.root, 0, 0, 0, 0);
547: XUngrabServer(dpy);
548: #ifdef debug
549: printf("To x=%d, y=%d\n",
550: ev.xbutton.x_root - dragx,
551: ev.xbutton.y_root - dragy);
552: #endif
553: XConfigureWindow(dpy, dragWindow,
554: CWX | CWY, &wc);
555: dragWindow = None;
556: }
557: else if (ga && (ga->rbox == w)
558: && (ga->frame == resizeWindow)) {
559: #ifdef debug
560: printf("delivered to %s of frame %d\n",
561: WindowType(w), Frame(w));
562: #endif
563: MoveOutline(ev.xbutton.root, 0, 0, 0, 0);
564: XUngrabServer(dpy);
565: ReconfigureFrameAndClient(ev.xbutton.root, ga, dragx,
566: dragy + TITLEHEIGHT + BORDERWIDTH, dragWidth,
567: dragHeight - TITLEHEIGHT - BORDERWIDTH);
568: resizeWindow = None;
569: }
570: else if (ga && (ga->iconify == w) && (iconifyWindow == w)) {
571: XWindowChanges wc;
572: #ifdef debug
573: printf("delivered to %s of frame %d\n",
574: WindowType(w), Frame(w));
575: #endif
576: if (ga->iconknown && iconPressx == ev.xbutton.x_root
577: && iconPressy == ev.xbutton.y_root) {
578: wc.x = ga->iconx;
579: wc.y = ga->icony;
580: }
581: else {
582: ga->iconknown = True;
583: wc.x = ga->iconx = ev.xbutton.x_root;
584: wc.y = ga->icony = ev.xbutton.y_root;
585: }
586: MakeReachable(ev.xbutton.root, &wc.x, &wc.y,
587: dragWidth, dragHeight);
588: wc.x -= BW;
589: wc.y -= BW;
590: MoveOutline(ev.xbutton.root, 0, 0, 0, 0);
591: XUngrabServer(dpy);
592: dragWindow = None;
593: iconifyWindow = None;
594: XConfigureWindow(dpy, ga->iconWindow, CWX | CWY, &wc);
595: XUnmapWindow(dpy, ga->frame);
596: XMapWindow(dpy, ga->iconWindow);
597: }
598: else if (ga && (ga->iconWindow == w) && (iconifyWindow == w)) {
599: if (dragWindow == w) {
600: XWindowChanges wc;
601: wc.x = ev.xbutton.x_root - dragx;
602: wc.y = ev.xbutton.y_root - dragy;
603: #ifdef debug
604: printf("delivered to %s of frame %d\n",
605: WindowType(w), Frame(w));
606: #endif
607: MoveOutline(ev.xbutton.root, 0, 0, 0, 0);
608: XUngrabServer(dpy);
609: ga->iconx = wc.x;
610: ga->icony = wc.y;
611: #ifdef debug
612: printf("To x=%d, y=%d\n",
613: ev.xbutton.x_root - dragx,
614: ev.xbutton.y_root - dragy);
615: #endif
616: MakeReachable(ev.xbutton.root, &wc.x, &wc.y, dragWidth,
617: dragHeight);
618: wc.x -= BW;
619: wc.y -= BW;
620: XConfigureWindow(
621: dpy, dragWindow, CWX | CWY, &wc);
622: dragWindow = None;
623: }
624: else {
625: XUnmapWindow(dpy, ga->iconWindow);
626: XMapWindow(dpy, ga->frame);
627: }
628: iconifyWindow = None;
629: }
630: else {
631: #ifdef debug
632: printf("delivered to ???\n");
633: #endif
634: }
635: break;
636: }
637: case ConfigureRequest:{
638: Window w;
639: GenericAssoc *ga;
640: XWindowChanges wc;
641: XConfigureRequestEvent evc;
642: evc = ev.xconfigurerequest;
643: w = evc.window;
644: ga = (GenericAssoc *) XLookUpAssoc(dpy, frameInfo, (XID) w);
645: if (!ga) {
646: #ifdef debug
647: printf("delivered to unknown client\n");
648: #endif
649: wc.x = evc.x;
650: wc.y = evc.y;
651: wc.width = evc.width;
652: wc.height = evc.height;
653: wc.border_width = evc.border_width;
654: wc.sibling = evc.above;
655: wc.stack_mode = Above;
656: XConfigureWindow(dpy, w, CWX | CWY | CWWidth |
657: CWBorderWidth | CWSibling | CWStackMode,
658: &wc);
659: }
660: else if (ga->client == w) {
661: int x, y;
662: Window root, jc;
663: int ht, wd, bw, d, x1, y1;
664: #ifdef debug
665: printf("delivered to %s of frame %d\n",
666: WindowType(w), Frame(w));
667: #endif
668: XGetGeometry(dpy,
669: (Drawable) w, &root, &x1, &y1, &wd, &ht, &bw, &d);
670: XTranslateCoordinates(dpy, w, root, 0, 0, &x, &y, &jc);
671: ReconfigureFrameAndClient
672: (root, ga, x, y, evc.width, evc.height);
673: }
674: else {
675: #ifdef debug
676: printf("delivered to %s of frame %d\n",
677: WindowType(w), Frame(w));
678: #endif
679: }
680: break;
681: }
682: case Expose:{
683: Window w = ev.xexpose.window;
684: GenericAssoc *ga;
685: Window root;
686: int x, y, wd, ht, bw, d;
687:
688: #ifdef debug
689: printf("delivered to %s of frame %d\n",
690: WindowType(w), Frame(w));
691: #endif
692: ga = (GenericAssoc *) XLookUpAssoc(dpy, frameInfo, (XID) w);
693: XGetGeometry(dpy, (Drawable) w, &root, &x, &y, &wd, &ht, &bw, &d);
694: if (ga && ga->header == w) {
695: int x;
696: x = (ga->headerWidth -
697: XTextWidth(font, ga->name, ga->namelen)) / 2;
698: XDrawString(dpy, w, findRootInfo(root)->headerGC, x,
699: font->max_bounds.ascent + 5,
700: ga->name, ga->namelen);
701: }
702: else if (ga && ga->iconWindow == w) {
703: if (ga->iconnamelen == 0)
704: XDrawString(dpy, w, findRootInfo(root)->headerGC, 2,
705: font->max_bounds.ascent + 5,
706: ga->name, ga->namelen);
707: else
708: XDrawString(dpy, w, findRootInfo(root)->headerGC, 2,
709: font->max_bounds.ascent + 5,
710: ga->iconname, ga->iconnamelen);
711: } /* else if (ga && (ga->upbox == w)) {
712: * XCopyArea(dpy, doubleArrow, w,
713: * headerGC, 0, 0, UPBOXWIDTH,
714: * TITLEHEIGHT, 0, 0); } else if (ga &&
715: * (ga->rbox == w)) { XCopyArea(dpy,
716: * growBox, w, headerGC, 0, 0, UPBOXWIDTH,
717: * TITLEHEIGHT, 0, 0); } else if (ga &&
718: * (ga->iconify == w)) { XCopyArea(dpy,
719: * cross, w, headerGC, 0, 0, UPBOXWIDTH,
720: * TITLEHEIGHT, 0, 0); } */
721: break;
722: }
723: case FocusIn: break; /* just ignore */
724: case FocusOut: {
725: if (ev.xfocus.detail == NotifyPointerRoot)
726: XSetInputFocus(dpy, PointerRoot, None, CurrentTime);
727: break;
728: }
729: default:
730: #ifdef debug
731: printf("\n");
732: #endif
733: ;
734: }
735: }
736: }
737:
738: int
739: ErrorFunc(dpy, event)
740: Display *dpy;
741: XErrorEvent *event;
742: {
743: switch (event->error_code) {
744: case BadWindow:
745: case BadDrawable:
746: (void) fprintf(stderr, "wm: Window #0x%x disappeared!\n",
747: event->resourceid);
748: break;
749: default:
750: _XDefaultError(dpy, event);
751: }
752: return (0);
753: }
754:
755: Bool
756: MappedNotOverride(w) Window w;
757: {
758: XWindowAttributes wa;
759: XGetWindowAttributes(dpy, w, &wa);
760: return ((wa.map_state != IsUnmapped) && (wa.override_redirect != True));
761: }
762:
763: static void
764: MoveOutline(root, x, y, width, height)
765: Window root;
766: int x, y, width, height;
767: {
768: static int lastx = 0;
769: static int lasty = 0;
770: static int lastWidth = 0;
771: static int lastHeight = 0;
772: XRectangle outline[8];
773: XRectangle *r = outline;
774:
775: if (x == lastx && y == lasty && width == lastWidth && height == lastHeight)
776: return;
777: if (lastWidth || lastHeight) {
778: r->x = lastx;
779: r->y = lasty;
780: r->width = lastWidth;
781: r++->height = BORDERWIDTH;
782: r->x = lastx;
783: r->y = lasty + lastHeight - BORDERWIDTH;
784: r->width = lastWidth;
785: r++->height = BORDERWIDTH;
786: r->x = lastx;
787: r->y = lasty + BORDERWIDTH;
788: r->width = BORDERWIDTH;
789: r++->height = lastHeight - 2 * BORDERWIDTH;
790: r->x = lastx + lastWidth - BORDERWIDTH;
791: r->y = lasty + BORDERWIDTH;
792: r->width = BORDERWIDTH;
793: r++->height = lastHeight - 2 * BORDERWIDTH;
794: }
795: lastx = x;
796: lasty = y;
797: lastWidth = width;
798: lastHeight = height;
799: if (lastWidth || lastHeight) {
800: r->x = lastx;
801: r->y = lasty;
802: r->width = lastWidth;
803: r++->height = BORDERWIDTH;
804: r->x = lastx;
805: r->y = lasty + lastHeight - BORDERWIDTH;
806: r->width = lastWidth;
807: r++->height = BORDERWIDTH;
808: r->x = lastx;
809: r->y = lasty + BORDERWIDTH;
810: r->width = BORDERWIDTH;
811: r++->height = lastHeight - 2 * BORDERWIDTH;
812: r->x = lastx + lastWidth - BORDERWIDTH;
813: r->y = lasty + BORDERWIDTH;
814: r->width = BORDERWIDTH;
815: r++->height = lastHeight - 2 * BORDERWIDTH;
816: }
817: if (r != outline) {
818: XFillRectangles(dpy, root, findRootInfo(root)->xorGC, outline, r - outline);
819: }
820: }
821:
822: void
823: AddGizmos(w)
824: Window w;
825: {
826: XWindowAttributes wa;
827: Window root, fw, gw, lw, uw, iw, iconw, hpw;
828: int hw;
829: Bool resize = False;
830: int x, y, wd, h, bw, d;
831:
832: /*
833: * When we reparent w to fw, below, make sure w gets reparented back when
834: * fw goes away. We do this early, in case we die, otherwise the map
835: * request in the client will hang forever.
836: */
837: XChangeSaveSet(dpy, w, SetModeInsert);
838:
839: /*
840: * Don't try to fiddle with InputOnly windows.
841: */
842: XGetWindowAttributes(dpy, w, &wa);
843: if (wa.class == InputOnly) {
844: XClientMessageEvent ev;
845:
846: ev.type = ClientMessage;
847: ev.display = (Display *)NULL;
848: ev.window = w;
849: ev.message_type = XA_WM_HINTS;
850: ev.format = 8;
851: strcpy( ev.data.b, "bad window class" ); /* fix */
852: XSendEvent( dpy, w, False, -1, &ev );
853: return;
854: }
855:
856: XGetGeometry(dpy, (Drawable) w, &root, &x, &y, &wd, &h, &bw, &d);
857: /* set the border of the original window to 0 */
858: ChangeBorderWidth(w, 0);
859: /* make sure this window is big enough */
860: if (wa.width < MINWIDTH) {
861: resize = True;
862: wa.width = MINWIDTH;
863: }
864: if (wa.height + TITLEHEIGHT + 2 * BW < MINHEIGHT) {
865: resize = True;
866: wa.height = MINHEIGHT;
867: }
868: if (resize == True) {
869: XResizeWindow(dpy, w, wa.width, wa.height);
870: }
871: /* MakeFrame makes sure part of the header is on-screen */
872: fw = MakeFrame(root, wa.x, wa.y - TITLEHEIGHT - BW, wa.width,
873: wa.height + TITLEHEIGHT + BW);
874: if (!fw)
875: return;
876: hw = wa.width - GROWBOXWIDTH - UPBOXWIDTH - ICONIFYWIDTH - 2 * BW;
877: hpw = MakeHeaderParent(root, fw, hw);
878: gw = MakeHeader(root, hpw, hw);
879: lw = MakeGrowBox(root, fw, wa.width - GROWBOXWIDTH);
880: iw = MakeIconBox(root, fw, UPBOXWIDTH);
881: uw = MakeUpBox(root, fw);
882: iconw = MakeIcon(root, fw);
883: XSync(dpy, False);
884: errorStatus = False;
885: {
886: XWindowChanges wc;
887:
888: wc.sibling = w;
889: wc.stack_mode = Above;
890: XConfigureWindow(dpy, fw, CWSibling|CWStackMode, &wc);
891: }
892: XReparentWindow(dpy, w, fw, 0, TITLEHEIGHT + BW);
893: XSync(dpy, False);
894: if (errorStatus == True) {
895: XDestroyWindow(dpy, fw);
896: return;
897: }
898: /* register fw, w, gw, and lw in the association table */
899: RegisterCompleteWindow(fw, w, gw, hpw, lw, iw, uw, iconw, hw);
900: MapCompleteWindow(fw);
901: }
902:
903: void
904: ReconfigureFrameAndClient(root, ga, x, y, width, height)
905: Window root;
906: GenericAssoc *ga;
907: int x, y, width, height;
908: {
909: XWindowAttributes wa;
910: XWindowChanges wc;
911: unsigned long mask;
912:
913: if (width < MINWIDTH)
914: width = MINWIDTH;
915: if (height < TITLEHEIGHT)
916: height = TITLEHEIGHT;
917:
918: /* let's unmap all the inferiors, so we dont' see all the interim
919: * exposure events of the inferior windows in the old sizes.
920: * XXX I suspect this might actually be hiding a real bug in the
921: * server, and should be reexamined someday.
922: */
923: XUnmapSubwindows(dpy,ga->frame);
924:
925: /* Reconfigure frame */
926: wc.x = x + UPBOXWIDTH + ICONIFYWIDTH + BW;
927: wc.y = y - TITLEHEIGHT - BW;
928: MakeReachable(root, &wc.x, &wc.y, width - UPBOXWIDTH - GROWBOXWIDTH -
929: ICONIFYWIDTH - 2 * BW, TITLEHEIGHT);
930: wc.x -= UPBOXWIDTH + ICONIFYWIDTH + 2 * BW;
931: /* the extra BW is because XReconfigureWindow includes the border */
932: /* width in x and y, but not in width and height */
933: wc.y -= BW;
934: wc.width = width;
935: wc.height = height + TITLEHEIGHT + BW;
936: mask = CWX | CWY | CWWidth | CWHeight;
937: XConfigureWindow(dpy, ga->frame, mask, &wc);
938: /* Reconfigure client */
939: wc.x = 0;
940: wc.y = TITLEHEIGHT + BW;
941: wc.width = width;
942: wc.height = height;
943: wc.border_width = 0;
944: mask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth;
945: XConfigureWindow(dpy, ga->client, mask, &wc);
946: /* Reconfigure raise button */
947: wc.x = 0;
948: wc.y = 0;
949: wc.width = UPBOXWIDTH;
950: wc.height = TITLEHEIGHT;
951: mask = CWX | CWY | CWWidth | CWHeight;
952: XConfigureWindow(dpy, ga->upbox, mask, &wc);
953: /* Reconfigure header parent */
954: wc.x = UPBOXWIDTH + BW + ICONIFYWIDTH;
955: wc.y = 0;
956: wc.width = width - UPBOXWIDTH - GROWBOXWIDTH - 2 * BW - ICONIFYWIDTH;
957: ga->headerWidth = wc.width;
958: wc.height = TITLEHEIGHT;
959: mask = CWX | CWY | CWWidth | CWHeight;
960: XConfigureWindow(dpy, ga->headerParent, mask, &wc);
961: /* Reconfigure header */
962: wc.x = 0;
963: wc.y = 0;
964: wc.width = width - UPBOXWIDTH - GROWBOXWIDTH - 2 * BW - ICONIFYWIDTH;
965: wc.height = TITLEHEIGHT;
966: mask = CWX | CWY | CWWidth | CWHeight;
967: XConfigureWindow(dpy, ga->header, mask, &wc);
968: /* Reconfigure resize button */
969: wc.x = width - GROWBOXWIDTH;
970: wc.y = 0;
971: wc.width = GROWBOXWIDTH;
972: wc.height = TITLEHEIGHT;
973: mask = CWX | CWY | CWWidth | CWHeight;
974: XConfigureWindow(dpy, ga->rbox, mask, &wc);
975: /* Reconfigure iconify button */
976: wc.x = UPBOXWIDTH;
977: wc.y = 0;
978: wc.width = ICONIFYWIDTH;
979: wc.height = TITLEHEIGHT;
980: mask = CWX | CWY | CWWidth | CWHeight;
981: XConfigureWindow(dpy, ga->iconify, mask, &wc);
982: XGetWindowAttributes(dpy, ga->frame, &wa);
983:
984: XMapSubwindows(dpy,ga->frame);
985: }
986:
987: Window
988: MakeGrowBox(root, fw, lx)
989: Window root;
990: Window fw;
991: int lx;
992: {
993: unsigned long valuemask;
994: XSetWindowAttributes attributes;
995: RootInfoRec *ri = findRootInfo(root);
996: int scr = ri - RootInfo;
997:
998: valuemask = CWEventMask | CWBackPixmap;
999: attributes.background_pixmap = ri->growBox;
1000: attributes.event_mask =
1001: ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
1002: PointerMotionHintMask | ExposureMask;
1003: return XCreateWindow(dpy, fw, lx, 0, GROWBOXWIDTH, TITLEHEIGHT, 0,
1004: DefaultDepth(dpy, scr), CopyFromParent,
1005: DefaultVisual(dpy, scr), valuemask, &attributes);
1006: }
1007:
1008: Window
1009: MakeUpBox(root, fw)
1010: Window root;
1011: Window fw;
1012: {
1013: unsigned long valuemask;
1014: XSetWindowAttributes attributes;
1015: RootInfoRec *ri = findRootInfo(root);
1016: int scr = ri - RootInfo;
1017:
1018: valuemask = CWEventMask | CWBackPixmap;
1019: attributes.background_pixmap = ri->doubleArrow;
1020: attributes.event_mask =
1021: ButtonPressMask | ButtonReleaseMask | ExposureMask;
1022: return XCreateWindow(dpy, fw, 0, 0, UPBOXWIDTH, TITLEHEIGHT, 0,
1023: DefaultDepth(dpy, scr), CopyFromParent, DefaultVisual(dpy, scr),
1024: valuemask, &attributes);
1025: }
1026:
1027: Window
1028: MakeIconBox(root, fw, ix)
1029: Window root;
1030: Window fw;
1031: int ix;
1032: {
1033: unsigned long valuemask;
1034: XSetWindowAttributes attributes;
1035: RootInfoRec *ri = findRootInfo(root);
1036: int scr = ri - RootInfo;
1037:
1038: valuemask = CWEventMask | CWBackPixmap;
1039: attributes.background_pixmap = ri->cross;
1040: attributes.event_mask =
1041: ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
1042: PointerMotionHintMask | ExposureMask;
1043: return XCreateWindow(dpy, fw, ix, 0, UPBOXWIDTH, TITLEHEIGHT, 0,
1044: DefaultDepth(dpy, scr), CopyFromParent, DefaultVisual(dpy, scr),
1045: valuemask, &attributes);
1046: }
1047:
1048: void
1049: ChangeBorderWidth(w, newWidth) Window w; int newWidth;
1050: {
1051: XWindowChanges wch;
1052: wch.border_width = newWidth;
1053: XConfigureWindow(dpy, w, CWBorderWidth, &wch);
1054: }
1055:
1056: void
1057: MapCompleteWindow(frame) Window frame;
1058: {
1059: XMapSubwindows(dpy, frame);
1060: XMapWindow(dpy, frame);
1061: }
1062:
1063: void
1064: RegisterCompleteWindow(frame, client, header, hp, rbox, iconify, upbox, iconw, headerWidth)
1065: Window frame, client, header, hp, rbox, upbox, iconify, iconw;
1066: int headerWidth;
1067: {
1068: GenericAssoc *fa;
1069: XWMHints *wmhints;
1070: Window root;
1071: int x, y, wd, ht, bw, d;
1072:
1073: XGetGeometry(dpy, (Drawable) client, &root, &x, &y, &wd, &ht, &bw, &d);
1074:
1075: XSelectInput(dpy, client, PropertyChangeMask);
1076: fa = GimmeAssocStruct();
1077: fa->frame = frame;
1078: fa->header = header;
1079: fa->headerParent = hp;
1080: fa->client = client;
1081: fa->rbox = rbox;
1082: fa->iconify = iconify;
1083: fa->upbox = upbox;
1084: fa->headerWidth = headerWidth;
1085: fa->iconWindow = iconw;
1086: fa->iconnamelen = fa->namelen = 0;
1087: ProcessNewIconName(root, fa);
1088: ProcessNewName(root, fa);
1089: if ((wmhints = XGetWMHints(dpy, client)) &&
1090: (wmhints->flags & IconPositionHint)) {
1091: fa->iconx = wmhints->icon_x;
1092: fa->icony = wmhints->icon_y;
1093: fa->iconknown = True;
1094: }
1095: else
1096: fa->iconknown = False;
1097: if (wmhints)
1098: free((char *) wmhints);
1099: XMakeAssoc(dpy, frameInfo, (XID) frame, (char *) fa);
1100: XMakeAssoc(dpy, frameInfo, (XID) header, (char *) fa);
1101: XMakeAssoc(dpy, frameInfo, (XID) hp, (char *) fa);
1102: XMakeAssoc(dpy, frameInfo, (XID) client, (char *) fa);
1103: XMakeAssoc(dpy, frameInfo, (XID) rbox, (char *) fa);
1104: XMakeAssoc(dpy, frameInfo, (XID) iconify, (char *) fa);
1105: XMakeAssoc(dpy, frameInfo, (XID) upbox, (char *) fa);
1106: XMakeAssoc(dpy, frameInfo, (XID) iconw, (char *) fa);
1107: /* Xfree(pd); */
1108: }
1109:
1110: Window
1111: MakeHeaderParent(root, fw, width)
1112: Window root;
1113: Window fw;
1114: int width;
1115: {
1116: unsigned long valuemask;
1117: XSetWindowAttributes attributes;
1118: Window result;
1119: int scr = findRootInfo(root) - RootInfo;
1120:
1121: valuemask = CWBackPixel;
1122: attributes.background_pixel = BlackPixel(dpy, scr);
1123: result = XCreateWindow(dpy, fw, UPBOXWIDTH + ICONIFYWIDTH + BW, 0,
1124: width, TITLEHEIGHT, 0,
1125: DefaultDepth(dpy, scr), CopyFromParent,
1126: DefaultVisual(dpy, scr), valuemask,
1127: &attributes);
1128: return result;
1129: }
1130:
1131: Window
1132: MakeHeader(root, hw, width)
1133: Window root;
1134: Window hw;
1135: int width;
1136: {
1137: unsigned long valuemask;
1138: XSetWindowAttributes attributes;
1139: Window result;
1140: int scr = findRootInfo(root) - RootInfo;
1141:
1142: valuemask = CWEventMask | CWBackPixel;
1143: attributes.event_mask =
1144: ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
1145: ExposureMask | PointerMotionHintMask;
1146: attributes.background_pixel = BlackPixel(dpy, scr);
1147: result = XCreateWindow(dpy, hw, 0, 0, width, TITLEHEIGHT, 0,
1148: DefaultDepth(dpy, scr), CopyFromParent,
1149: DefaultVisual(dpy, scr), valuemask,
1150: &attributes);
1151: return result;
1152: }
1153:
1154: /* XXX fw unused? */
1155: MakeIcon(root, fw)
1156: Window root;
1157: Window fw;
1158: {
1159: unsigned long valuemask;
1160: XSetWindowAttributes attributes;
1161: Window result;
1162: int scr = findRootInfo(root) - RootInfo;
1163:
1164: valuemask = CWEventMask | CWBackPixel | CWBorderPixel;
1165: attributes.event_mask =
1166: ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
1167: ExposureMask | PointerMotionHintMask;
1168: attributes.background_pixel = BlackPixel(dpy, scr);
1169: attributes.border_pixel = WhitePixel(dpy, scr);
1170: result = XCreateWindow(dpy, root, 0, 0, ICONWIDTH, TITLEHEIGHT, BW,
1171: DefaultDepth(dpy, scr), CopyFromParent, DefaultVisual(dpy, scr),
1172: valuemask, &attributes);
1173: return result;
1174: }
1175:
1176:
1177: Window
1178: MakeFrame(root, x, y, width, height)
1179: Window root;
1180: int x, y, width, height;
1181: {
1182: unsigned long valuemask;
1183: XSetWindowAttributes attributes;
1184: int hx, hy;
1185: int scr;
1186: RootInfoRec *ri = findRootInfo(root);
1187:
1188: if (!ri)
1189: return (NULL);
1190: scr = ri - RootInfo;
1191: hx = x + ICONIFYWIDTH + UPBOXWIDTH + BW;
1192: hy = y;
1193: MakeReachable(root, &hx, &hy, width - UPBOXWIDTH - GROWBOXWIDTH - ICONIFYWIDTH
1194: - 2 * BW, TITLEHEIGHT);
1195: x = hx - (ICONIFYWIDTH + UPBOXWIDTH + BW) - BW;
1196: y = hy - BW;
1197: valuemask = CWEventMask | CWBorderPixel | CWBackPixel;
1198: attributes.event_mask = SubstructureRedirectMask
1199: | SubstructureNotifyMask;
1200: attributes.background_pixel = WhitePixel(dpy, scr);
1201: attributes.border_pixel = WhitePixel(dpy, scr);
1202: attributes.bit_gravity = NorthWestGravity;
1203: return XCreateWindow(dpy, root, x, y, width, height, BORDERWIDTH,
1204: DefaultDepth(dpy, scr), CopyFromParent, DefaultVisual(dpy, scr),
1205: valuemask, &attributes);
1206: }
1207:
1208: void
1209: RemoveGizmos(ga) GenericAssoc *ga;
1210: {
1211: XDeleteAssoc(dpy, frameInfo, ga->frame);
1212: XDeleteAssoc(dpy, frameInfo, ga->header);
1213: XDeleteAssoc(dpy, frameInfo, ga->rbox);
1214: XDeleteAssoc(dpy, frameInfo, ga->iconify);
1215: XDeleteAssoc(dpy, frameInfo, ga->upbox);
1216: XDeleteAssoc(dpy, frameInfo, ga->iconWindow);
1217: XDeleteAssoc(dpy, frameInfo, ga->client);
1218: XDestroyWindow(dpy, ga->frame);
1219: XDestroyWindow(dpy, ga->iconWindow);
1220: free((char *) ga);
1221: }
1222:
1223:
1224: StartConnectionToServer(argc, argv)
1225: int argc;
1226: char *argv[];
1227: {
1228: char *display;
1229: int i;
1230: extern char *index();
1231:
1232: display = NULL;
1233: for (i = 1; i < argc; i++) {
1234: if (index(argv[i], ':') != NULL)
1235: display = argv[i];
1236: }
1237: if (!(dpy = XOpenDisplay(display))) {
1238: Error(1, "Cannot open display\n");
1239: }
1240: }
1241:
1242: Error(status, message) int status; char *message;
1243: {
1244: printf("%s", message);
1245: if (!status) return;
1246: else exit(1);
1247: }
1248:
1249: GenericAssoc *
1250: GimmeAssocStruct(){
1251: return (GenericAssoc *) malloc(sizeof(GenericAssoc));
1252: }
1253:
1254:
1255: char *
1256: WindowType(w) Window w;
1257: {
1258: GenericAssoc *ga;
1259: ga = (GenericAssoc *) XLookUpAssoc(dpy, frameInfo, w);
1260: if (ga && w == ga->frame) return "frame";
1261: if (ga && w == ga->header) return "header";
1262: if (ga && w == ga->client) return "client";
1263: if (ga && w == ga->rbox) return "resize box";
1264: if (ga && w == ga->iconify) return "iconify box";
1265: if (ga && w == ga->upbox) return "raise box";
1266: if (ga && w == ga->iconWindow) return "icon";
1267: if (ga) {
1268: Error(0, "WindowType: error in association table routines\n");
1269: return "error";
1270: }
1271: Error(0, "WindowType: window %d not found in assoc table\n", w);
1272: return "error";
1273: }
1274:
1275: Window
1276: Frame(w) Window w;
1277: {
1278: GenericAssoc *ga;
1279: ga = (GenericAssoc *) XLookUpAssoc(dpy, frameInfo, w);
1280: if (ga) return ga->frame;
1281: Error(0, "Frame: window %d not found in assoc table\n");
1282: return None;
1283: }
1284:
1285: void
1286: MakeReachable(root, x, y, width, height)
1287: Window root;
1288: int *x, *y;
1289: int width, height;
1290: {
1291: RootInfoRec *ri = findRootInfo(root);
1292:
1293: if (!ri)
1294: return;
1295: if (*x <= MARGIN + ri->rootx - width)
1296: *x = MARGIN + ri->rootx - width + 1;
1297: if (*y <= MARGIN + ri->rooty - height)
1298: *y = MARGIN + ri->rooty - height + 1;
1299: if (*x >= ri->rootx + ri->rootwidth - MARGIN)
1300: *x = ri->rootx + ri->rootwidth - MARGIN - 1;
1301: if (*y >= ri->rooty + ri->rootheight - MARGIN)
1302: *y = ri->rooty + ri->rootheight - MARGIN - 1;
1303: }
1304:
1305: Bool
1306: FillName(ga) GenericAssoc *ga;
1307: {
1308: Status status;
1309: char *name;
1310: Bool noname = False;
1311: int len;
1312: Bool res;
1313: extern char *strncpy();
1314:
1315: status = XFetchName(dpy, ga->client, &name);
1316: if (!status || !name || !(*name)) {
1317: name = "No name";
1318: noname = True;
1319: }
1320:
1321: len = strlen(name);
1322: if (len >= MAXNAME)
1323: len = MAXNAME;
1324: if (len != ga->namelen || strncmp(name, ga->name, len)) {
1325: ga->namelen = len;
1326: (void) strncpy(ga->name, name, ga->namelen);
1327: res = True;
1328: }
1329: else
1330: res = False;
1331: if (!noname)
1332: free(name);
1333: return res;
1334: }
1335:
1336: void
1337: FillIconName(ga) GenericAssoc *ga;
1338: {
1339: Status status;
1340: long len2;
1341: char *pd;
1342: Atom at;
1343: int af;
1344: long ba;
1345: status = XGetWindowProperty(dpy, ga->client, XA_WM_ICON_NAME,
1346: 0, MAXNAME, False,
1347: XA_STRING, &at, &af, &len2, &ba, &pd);
1348: if (status != Success) {
1349: ga->iconnamelen = 0;
1350: } else {
1351: switch (af) {
1352: case 8:
1353: ga->iconnamelen = len2;
1354: if (ga->iconnamelen >= MAXNAME) ga->iconnamelen = MAXNAME;
1355: strncpy(ga->iconname, pd, ga->iconnamelen);
1356: free (pd);
1357: break;
1358: default:
1359: ga->iconnamelen = 0;
1360: if (pd) free(pd);
1361: }
1362: }
1363: }
1364:
1365: void
1366: ProcessNewName(root, ga)
1367: Window root;
1368: GenericAssoc *ga;
1369: {
1370: if (!FillName(ga)) return;
1371: if (ga->iconnamelen == 0) {
1372: Bool wasMapped;
1373: int width;
1374: wasMapped = MappedNotOverride(ga->iconWindow);
1375: width = XTextWidth(font, ga->name, ga->namelen) + 2*BW;
1376: MakeReachable(root, &ga->iconx, &ga->icony, width, TITLEHEIGHT);
1377: if (wasMapped) XUnmapWindow(dpy, ga->iconWindow);
1378: XMoveResizeWindow(dpy, ga->iconWindow, ga->iconx - BW,
1379: ga->icony - BW, width, TITLEHEIGHT);
1380: if (wasMapped) XMapWindow(dpy, ga->iconWindow);
1381: }
1382: XUnmapWindow(dpy, ga->header);
1383: XMapWindow(dpy, ga->header);
1384: }
1385:
1386: void
1387: ProcessNewIconName(root, ga)
1388: Window root;
1389: GenericAssoc *ga;
1390: {
1391: int oldIconLen;
1392: Bool wasMapped;
1393: int width;
1394:
1395: wasMapped = MappedNotOverride(ga->iconWindow);
1396: oldIconLen = ga->iconnamelen;
1397: FillIconName(ga);
1398: if (ga->iconnamelen == 0) {
1399: if (oldIconLen == 0)
1400: return;
1401: width = XTextWidth(font, ga->name, ga->namelen) + 2 * BW;
1402: MakeReachable(root, &ga->iconx, &ga->icony, width, TITLEHEIGHT);
1403: if (wasMapped)
1404: XUnmapWindow(dpy, ga->iconWindow);
1405: XMoveResizeWindow(dpy, ga->iconWindow, ga->iconx - BW,
1406: ga->icony - BW, width, TITLEHEIGHT);
1407: if (wasMapped)
1408: XMapWindow(dpy, ga->iconWindow);
1409: return;
1410: }
1411: width = XTextWidth(font, ga->iconname, ga->iconnamelen) + 2 * BW;
1412: MakeReachable(root, &ga->iconx, &ga->icony, width, TITLEHEIGHT);
1413: if (wasMapped)
1414: XUnmapWindow(dpy, ga->iconWindow);
1415: XMoveResizeWindow(dpy, ga->iconWindow, ga->iconx - BW,
1416: ga->icony - BW, width, TITLEHEIGHT);
1417: if (wasMapped)
1418: XMapWindow(dpy, ga->iconWindow);
1419: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.