Blob


1 /* Copyright (c) 1994-1996 David Hogan, see README for licence details */
2 #include <stdio.h>
3 #include <signal.h>
4 #include <unistd.h>
5 #include <stdlib.h>
6 #include <sys/wait.h>
7 #include <X11/X.h>
8 #include <X11/Xlib.h>
9 #include <X11/Xutil.h>
10 #include "dat.h"
11 #include "fns.h"
13 Client *hiddenc[MAXHIDDEN];
15 int numhidden;
17 char *b3items[B3FIXED+MAXHIDDEN+1] =
18 {
19 "New",
20 "Reshape",
21 "Move",
22 "Delete",
23 "Hide",
24 0,
25 };
27 Menu b3menu =
28 {
29 b3items,
30 };
32 Menu egg =
33 {
34 version,
35 };
37 void
38 button(XButtonEvent *e)
39 {
40 int n, shift;
41 Client *c;
42 Window dw;
43 ScreenInfo *s;
45 curtime = e->time;
46 s = getscreen(e->root);
47 if (s == 0)
48 return;
49 c = getclient(e->window, 0);
50 if (c) {
51 if (debug) fprintf(stderr, "but: e x=%d y=%d c x=%d y=%d dx=%d dy=%d BORDR %d\n",
52 e->x, e->y, c->x, c->y, c->dx, c->dy, BORDER);
53 if (e->x <= BORDER || e->x > (c->dx + BORDER) ||
54 e->y <= BORDER || e->y > (c->dy + BORDER)) {
55 switch (e->button) {
56 case Button1:
57 case Button2:
58 reshape(c, e->button, pull, e);
59 return;
60 case Button3:
61 move(c, Button3);
62 return;
63 default:
64 return;
65 }
66 }
67 e->x += c->x - BORDER;
68 e->y += c->y - BORDER;
69 }
70 else if (e->window != e->root) {
71 if (debug) fprintf(stderr, "but no client: e x=%d y=%d\n",
72 e->x, e->y);
73 XTranslateCoordinates(dpy, e->window, s->root, e->x, e->y,
74 &e->x, &e->y, &dw);
75 }
76 switch (e->button) {
77 case Button1:
78 if (c) {
79 XMapRaised(dpy, c->parent);
80 top(c);
81 active(c);
82 }
83 return;
84 case Button2:
85 if ((e->state&(ShiftMask|ControlMask))==(ShiftMask|ControlMask))
86 menuhit(e, &egg);
87 return;
88 default:
89 return;
90 case Button3:
91 break;
92 }
94 if (current && current->screen == s)
95 cmapnofocus(s);
96 switch (n = menuhit(e, &b3menu)) {
97 case 0: /* New */
98 spawn(s);
99 break;
100 case 1: /* Reshape */
101 reshape(selectwin(1, 0, s), Button3, sweep, 0);
102 break;
103 case 2: /* Move */
104 move(selectwin(0, 0, s), Button3);
105 break;
106 case 3: /* Delete */
107 shift = 0;
108 c = selectwin(1, &shift, s);
109 delete(c, shift);
110 break;
111 case 4: /* Hide */
112 hide(selectwin(1, 0, s));
113 break;
114 default: /* unhide window */
115 unhide(n - B3FIXED, 1);
116 break;
117 case -1: /* nothing */
118 break;
120 if (current && current->screen == s)
121 cmapfocus(current);
124 void
125 spawn(ScreenInfo *s)
127 /*
128 * ugly dance to cause sweeping for terminals.
129 * the very next window created will require sweeping.
130 * hope it's created by the program we're about to
131 * exec!
132 */
133 isNew = 1;
134 /*
135 * ugly dance to avoid leaving zombies. Could use SIGCHLD,
136 * but it's not very portable.
137 */
138 if (fork() == 0) {
139 if (fork() == 0) {
140 close(ConnectionNumber(dpy));
141 if (s->display[0] != '\0')
142 putenv(s->display);
143 if (termprog != NULL) {
144 execl(shell, shell, "-c", termprog, 0);
145 fprintf(stderr, "9wm: exec %s", shell);
146 perror(" failed");
148 execlp("9term", "9term", "-w", 0);
149 execlp("xterm", "xterm", "-ut", 0);
150 perror("9wm: exec 9term/xterm failed");
151 exit(1);
153 exit(0);
155 wait((int *) 0);
158 void
159 reshape(Client *c, int but, int (*fn)(Client*, int, XButtonEvent *), XButtonEvent *e)
161 int odx, ody;
163 if (c == 0)
164 return;
165 odx = c->dx;
166 ody = c->dy;
167 if (fn(c, but, e) == 0)
168 return;
169 active(c);
170 top(c);
171 XRaiseWindow(dpy, c->parent);
172 XMoveResizeWindow(dpy, c->parent, c->x-BORDER, c->y-BORDER,
173 c->dx+2*BORDER, c->dy+2*BORDER);
174 if (c->dx == odx && c->dy == ody)
175 sendconfig(c);
176 else
177 XMoveResizeWindow(dpy, c->window, BORDER, BORDER, c->dx, c->dy);
180 void
181 move(Client *c, int but)
183 if (c == 0)
184 return;
185 if (drag(c, but) == 0)
186 return;
187 active(c);
188 top(c);
189 XRaiseWindow(dpy, c->parent);
190 XMoveWindow(dpy, c->parent, c->x-BORDER, c->y-BORDER);
191 sendconfig(c);
194 void
195 delete(Client *c, int shift)
197 if (c == 0)
198 return;
199 if ((c->proto & Pdelete) && !shift)
200 sendcmessage(c->window, wm_protocols, wm_delete, 0);
201 else
202 XKillClient(dpy, c->window); /* let event clean up */
205 void
206 hide(Client *c)
208 if (c == 0 || numhidden == MAXHIDDEN)
209 return;
210 if (hidden(c)) {
211 fprintf(stderr, "9wm: already hidden: %s\n", c->label);
212 return;
214 XUnmapWindow(dpy, c->parent);
215 XUnmapWindow(dpy, c->window);
216 setstate(c, IconicState);
217 if (c == current)
218 nofocus();
219 hiddenc[numhidden] = c;
220 b3items[B3FIXED+numhidden] = c->label;
221 numhidden++;
222 b3items[B3FIXED+numhidden] = 0;
225 void
226 unhide(int n, int map)
228 Client *c;
229 int i;
231 if (n >= numhidden) {
232 fprintf(stderr, "9wm: unhide: n %d numhidden %d\n", n, numhidden);
233 return;
235 c = hiddenc[n];
236 if (!hidden(c)) {
237 fprintf(stderr, "9wm: unhide: not hidden: %s(0x%x)\n",
238 c->label, (int)c->window);
239 return;
242 if (map) {
243 XMapWindow(dpy, c->window);
244 XMapRaised(dpy, c->parent);
245 setstate(c, NormalState);
246 active(c);
247 top(c);
250 numhidden--;
251 for (i = n; i < numhidden; i ++) {
252 hiddenc[i] = hiddenc[i+1];
253 b3items[B3FIXED+i] = b3items[B3FIXED+i+1];
255 b3items[B3FIXED+numhidden] = 0;
258 void
259 unhidec(Client *c, int map)
261 int i;
263 for (i = 0; i < numhidden; i++)
264 if (c == hiddenc[i]) {
265 unhide(i, map);
266 return;
268 fprintf(stderr, "9wm: unhidec: not hidden: %s(0x%x)\n",
269 c->label, (int)c->window);
272 void
273 renamec(Client *c, char *name)
275 int i;
277 if (name == 0)
278 name = "???";
279 c->label = name;
280 if (!hidden(c))
281 return;
282 for (i = 0; i < numhidden; i++)
283 if (c == hiddenc[i]) {
284 b3items[B3FIXED+i] = name;
285 return;