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 int virt;
19 Client * currents[NUMVIRTUALS] =
20 {
21 NULL, NULL, NULL, NULL,
22 };
24 char *b2items[NUMVIRTUALS+1] =
25 {
26 "One",
27 "Two",
28 "Three",
29 "Four",
30 "Five",
31 "Six",
32 "Seven",
33 "Eight",
34 "Nine",
35 "Ten",
36 "Eleven",
37 "Twelve",
38 0,
39 };
41 Menu b2menu =
42 {
43 b2items,
44 };
46 char *b3items[B3FIXED+MAXHIDDEN+1] =
47 {
48 "New",
49 "Reshape",
50 "Move",
51 "Delete",
52 "Hide",
53 0,
54 };
56 Menu b3menu =
57 {
58 b3items,
59 };
61 Menu egg =
62 {
63 version,
64 };
66 void
67 button(XButtonEvent *e)
68 {
69 int n, shift;
70 Client *c;
71 Window dw;
72 ScreenInfo *s;
74 curtime = e->time;
75 s = getscreen(e->root);
76 if (s == 0)
77 return;
78 c = getclient(e->window, 0);
79 if(c){
80 if (debug) fprintf(stderr, "but: e x=%d y=%d c x=%d y=%d dx=%d dy=%d BORDR %d\n",
81 e->x, e->y, c->x, c->y, c->dx, c->dy, BORDER);
82 if(borderorient(c, e->x, e->y) != BorderUnknown){
83 switch (e->button) {
84 case Button1:
85 case Button2:
86 reshape(c, e->button, pull, e);
87 return;
88 case Button3:
89 move(c, Button3);
90 return;
91 default:
92 return;
93 }
94 }
95 e->x += c->x - BORDER;
96 e->y += c->y - BORDER;
97 } else if (e->window != e->root) {
98 if (debug) fprintf(stderr, "but no client: e x=%d y=%d\n",
99 e->x, e->y);
100 XTranslateCoordinates(dpy, e->window, s->root, e->x, e->y,
101 &e->x, &e->y, &dw);
103 switch (e->button) {
104 case Button1:
105 if (c) {
106 XMapRaised(dpy, c->parent);
107 top(c);
108 active(c);
110 return;
111 case Button2:
112 if (c) {
113 XMapRaised(dpy, c->parent);
114 active(c);
115 XAllowEvents (dpy, ReplayPointer, curtime);
116 } else if ((e->state&(ShiftMask|ControlMask))==(ShiftMask|ControlMask)) {
117 menuhit(e, &egg);
118 } else if(numvirtuals > 1 && (n = menuhit(e, &b2menu)) > -1)
119 button2(n);
120 return;
121 case Button3:
122 break;
123 case Button4:
124 /* scroll up changes to previous virtual screen */
125 if(!c && e->type == ButtonPress)
126 if(numvirtuals > 1 && virt > 0)
127 switch_to(virt - 1);
128 return;
129 case Button5:
130 /* scroll down changes to next virtual screen */
131 if(!c && e->type == ButtonPress)
132 if(numvirtuals > 1 && virt < numvirtuals - 1)
133 switch_to(virt + 1);
134 return;
135 default:
136 return;
139 if (current && current->screen == s)
140 cmapnofocus(s);
141 switch (n = menuhit(e, &b3menu)) {
142 case 0: /* New */
143 spawn(s);
144 break;
145 case 1: /* Reshape */
146 reshape(selectwin(1, 0, s), Button3, sweep, 0);
147 break;
148 case 2: /* Move */
149 move(selectwin(0, 0, s), Button3);
150 break;
151 case 3: /* Delete */
152 shift = 0;
153 c = selectwin(1, &shift, s);
154 delete(c, shift);
155 break;
156 case 4: /* Hide */
157 hide(selectwin(1, 0, s));
158 break;
159 default: /* unhide window */
160 unhide(n - B3FIXED, 1);
161 break;
162 case -1: /* nothing */
163 break;
165 if (current && current->screen == s)
166 cmapfocus(current);
169 void
170 spawn(ScreenInfo *s)
172 /*
173 * ugly dance to cause sweeping for terminals.
174 * the very next window created will require sweeping.
175 * hope it's created by the program we're about to
176 * exec!
177 */
178 isNew = 1;
179 /*
180 * ugly dance to avoid leaving zombies. Could use SIGCHLD,
181 * but it's not very portable.
182 */
183 if (fork() == 0) {
184 if (fork() == 0) {
185 close(ConnectionNumber(dpy));
186 if (s->display[0] != '\0')
187 putenv(s->display);
188 signal(SIGINT, SIG_DFL);
189 signal(SIGTERM, SIG_DFL);
190 signal(SIGHUP, SIG_DFL);
191 if (termprog != NULL) {
192 execl(shell, shell, "-c", termprog, 0);
193 fprintf(stderr, "rio: exec %s", shell);
194 perror(" failed");
196 execlp("9term", "9term", scrolling ? "-ws" : "-w", 0);
197 execlp("xterm", "xterm", "-ut", 0);
198 perror("rio: exec 9term/xterm failed");
199 exit(1);
201 exit(0);
203 wait((int *) 0);
206 void
207 reshape(Client *c, int but, int (*fn)(Client*, int, XButtonEvent *), XButtonEvent *e)
209 int odx, ody;
211 if (c == 0)
212 return;
213 odx = c->dx;
214 ody = c->dy;
215 if (fn(c, but, e) == 0)
216 return;
217 active(c);
218 top(c);
219 XRaiseWindow(dpy, c->parent);
220 XMoveResizeWindow(dpy, c->parent, c->x-BORDER, c->y-BORDER,
221 c->dx+2*BORDER, c->dy+2*BORDER);
222 if (c->dx == odx && c->dy == ody)
223 sendconfig(c);
224 else
225 XMoveResizeWindow(dpy, c->window, BORDER, BORDER, c->dx, c->dy);
228 void
229 move(Client *c, int but)
231 if (c == 0)
232 return;
233 if (drag(c, but) == 0)
234 return;
235 active(c);
236 top(c);
237 XRaiseWindow(dpy, c->parent);
238 XMoveWindow(dpy, c->parent, c->x-BORDER, c->y-BORDER);
239 sendconfig(c);
242 void
243 delete(Client *c, int shift)
245 if (c == 0)
246 return;
247 if ((c->proto & Pdelete) && !shift)
248 sendcmessage(c->window, wm_protocols, wm_delete, 0, 0);
249 else
250 XKillClient(dpy, c->window); /* let event clean up */
253 void
254 hide(Client *c)
256 if (c == 0 || numhidden == MAXHIDDEN)
257 return;
258 if (hidden(c)) {
259 fprintf(stderr, "rio: already hidden: %s\n", c->label);
260 return;
262 XUnmapWindow(dpy, c->parent);
263 XUnmapWindow(dpy, c->window);
264 setstate(c, IconicState);
265 if (c == current)
266 nofocus();
267 hiddenc[numhidden] = c;
268 b3items[B3FIXED+numhidden] = c->label;
269 numhidden++;
270 b3items[B3FIXED+numhidden] = 0;
273 void
274 unhide(int n, int map)
276 Client *c;
277 int i;
279 if (n >= numhidden) {
280 fprintf(stderr, "rio: unhide: n %d numhidden %d\n", n, numhidden);
281 return;
283 c = hiddenc[n];
284 if (!hidden(c)) {
285 fprintf(stderr, "rio: unhide: not hidden: %s(0x%x)\n",
286 c->label, (int)c->window);
287 return;
289 c->virt = virt;
291 if (map) {
292 XMapWindow(dpy, c->window);
293 XMapRaised(dpy, c->parent);
294 setstate(c, NormalState);
295 active(c);
296 top(c);
299 numhidden--;
300 for (i = n; i < numhidden; i ++) {
301 hiddenc[i] = hiddenc[i+1];
302 b3items[B3FIXED+i] = b3items[B3FIXED+i+1];
304 b3items[B3FIXED+numhidden] = 0;
307 void
308 unhidec(Client *c, int map)
310 int i;
312 for (i = 0; i < numhidden; i++)
313 if (c == hiddenc[i]) {
314 unhide(i, map);
315 return;
317 fprintf(stderr, "rio: unhidec: not hidden: %s(0x%x)\n",
318 c->label, (int)c->window);
321 void
322 renamec(Client *c, char *name)
324 int i;
326 if (name == 0)
327 name = "???";
328 c->label = name;
329 if (!hidden(c))
330 return;
331 for (i = 0; i < numhidden; i++)
332 if (c == hiddenc[i]) {
333 b3items[B3FIXED+i] = name;
334 return;
338 void
339 button2(int n)
341 switch_to(n);
342 if (current)
343 cmapfocus(current);
346 void
347 switch_to_c(int n, Client *c)
349 if (c && c->next)
350 switch_to_c(n,c->next);
352 if (c->parent == DefaultRootWindow(dpy))
353 return;
355 if (c->virt != virt && c->state == NormalState) {
356 XUnmapWindow(dpy, c->parent);
357 XUnmapWindow(dpy, c->window);
358 setstate(c, IconicState);
359 if (c == current)
360 nofocus();
361 } else if (c->virt == virt && c->state == IconicState) {
362 int i;
364 for (i = 0; i < numhidden; i++)
365 if (c == hiddenc[i])
366 break;
368 if (i == numhidden) {
369 XMapWindow(dpy, c->window);
370 XMapWindow(dpy, c->parent);
371 setstate(c, NormalState);
372 if (currents[virt] == c)
373 active(c);
378 void
379 switch_to(int n)
381 if (n == virt)
382 return;
383 currents[virt] = current;
384 virt = n;
386 /* redundant when called from a menu switch
387 * but needed for scroll-button switches
388 */
389 b2menu.lasthit = n;
391 switch_to_c(n, clients);
392 current = currents[virt];
395 void
396 initb2menu(int n)
398 b2items[n] = 0;