Blob


1 /* Copyright (c) 1994-1996 David Hogan, see README for licence details */
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <X11/X.h>
5 #include <X11/Xos.h>
6 #include <X11/Xlib.h>
7 #include <X11/Xutil.h>
8 #include <X11/Xatom.h>
9 #include <X11/extensions/shape.h>
10 #include "dat.h"
11 #include "fns.h"
12 #include "patchlevel.h"
14 void
15 mainloop(int shape_event)
16 {
17 XEvent ev;
19 for(;;){
20 getevent(&ev);
22 #ifdef DEBUG_EV
23 if(debug){
24 ShowEvent(&ev);
25 printf("\n");
26 }
27 #endif
28 switch (ev.type){
29 default:
30 #ifdef SHAPE
31 if(shape && ev.type == shape_event)
32 shapenotify((XShapeEvent *)&ev);
33 else
34 #endif
35 fprintf(stderr, "rio: unknown ev.type %d\n", ev.type);
36 break;
37 case KeyPress:
38 keypress(&ev.xkey);
39 break;
40 case KeyRelease:
41 keyrelease(&ev.xkey);
42 break;
43 case ButtonPress:
44 button(&ev.xbutton);
45 break;
46 case ButtonRelease:
47 break;
48 case MapRequest:
49 mapreq(&ev.xmaprequest);
50 break;
51 case ConfigureRequest:
52 configurereq(&ev.xconfigurerequest);
53 break;
54 case CirculateRequest:
55 circulatereq(&ev.xcirculaterequest);
56 break;
57 case UnmapNotify:
58 unmap(&ev.xunmap);
59 break;
60 case CreateNotify:
61 newwindow(&ev.xcreatewindow);
62 break;
63 case DestroyNotify:
64 destroy(ev.xdestroywindow.window);
65 break;
66 case ClientMessage:
67 clientmesg(&ev.xclient);
68 break;
69 case ColormapNotify:
70 cmap(&ev.xcolormap);
71 break;
72 case PropertyNotify:
73 property(&ev.xproperty);
74 break;
75 case SelectionClear:
76 fprintf(stderr, "rio: SelectionClear (this should not happen)\n");
77 break;
78 case SelectionNotify:
79 fprintf(stderr, "rio: SelectionNotify (this should not happen)\n");
80 break;
81 case SelectionRequest:
82 fprintf(stderr, "rio: SelectionRequest (this should not happen)\n");
83 break;
84 case EnterNotify:
85 enter(&ev.xcrossing);
86 break;
87 case LeaveNotify:
88 leave(&ev.xcrossing);
89 break;
90 case ReparentNotify:
91 reparent(&ev.xreparent);
92 break;
93 case FocusIn:
94 focusin(&ev.xfocus);
95 break;
96 case MotionNotify:
97 motionnotify(&ev.xmotion);
98 break;
99 case Expose:
100 case NoExpose:
101 case FocusOut:
102 case ConfigureNotify:
103 case MapNotify:
104 case MappingNotify:
105 case GraphicsExpose:
106 /* not interested */
107 trace("ignore", 0, &ev);
108 break;
114 void
115 configurereq(XConfigureRequestEvent *e)
117 XWindowChanges wc;
118 Client *c;
120 /* we don't set curtime as nothing here uses it */
121 c = getclient(e->window, 0);
122 trace("configurereq", c, e);
124 e->value_mask &= ~CWSibling;
126 if(c){
127 if(e->value_mask & CWX)
128 c->x = e->x;
129 if(e->value_mask & CWY)
130 c->y = e->y;
131 if(e->value_mask & CWWidth)
132 c->dx = e->width;
133 if(e->value_mask & CWHeight)
134 c->dy = e->height;
135 if(e->value_mask & CWBorderWidth)
136 c->border = e->border_width;
138 if(c->dx >= c->screen->width && c->dy >= c->screen->height)
139 c->border = 0;
140 else
141 c->border = BORDER;
143 if(e->value_mask & CWStackMode){
144 if(e->detail == Above)
145 top(c);
146 else
147 e->value_mask &= ~CWStackMode;
149 e->value_mask |= CWX|CWY|CWHeight|CWWidth;
151 if(c->parent != c->screen->root && c->window == e->window){
152 wc.x = c->x - c->border;
153 wc.y = c->y - c->border;
154 wc.width = c->dx+c->border+c->border;
155 wc.height = c->dy+c->border+c->border;
156 wc.border_width = 1;
157 wc.sibling = None;
158 wc.stack_mode = e->detail;
159 XConfigureWindow(dpy, c->parent, e->value_mask, &wc);
161 if(e->value_mask & CWStackMode){
162 top(c);
163 active(c);
168 if(c && c->parent != c->screen->root){
169 wc.x = c->border;
170 wc.y = c->border;
171 }else {
172 wc.x = c->x;
173 wc.y = c->y;
175 wc.width = c->dx;
176 wc.height = c->dy;
177 wc.border_width = 0;
178 wc.sibling = None;
179 wc.stack_mode = Above;
180 e->value_mask &= ~CWStackMode;
181 e->value_mask |= CWBorderWidth;
182 XConfigureWindow(dpy, c->window, e->value_mask, &wc);
185 void
186 mapreq(XMapRequestEvent *e)
188 Client *c;
189 int i;
191 curtime = CurrentTime;
192 c = getclient(e->window, 0);
193 trace("mapreq", c, e);
195 if(c == 0 || c->window != e->window){
196 /* workaround for stupid NCDware */
197 fprintf(stderr, "rio: bad mapreq c %p w %x, rescanning\n",
198 (void*)c, (int)e->window);
199 for(i = 0; i < num_screens; i++)
200 scanwins(&screens[i]);
201 c = getclient(e->window, 0);
202 if(c == 0 || c->window != e->window){
203 fprintf(stderr, "rio: window not found after rescan\n");
204 return;
208 switch (c->state){
209 case WithdrawnState:
210 if(c->parent == c->screen->root){
211 if(!manage(c, 0))
212 return;
213 break;
215 XReparentWindow(dpy, c->window, c->parent, BORDER-1, BORDER-1);
216 XAddToSaveSet(dpy, c->window);
217 /* fall through... */
218 case NormalState:
219 XMapWindow(dpy, c->window);
220 XMapRaised(dpy, c->parent);
221 top(c);
222 setstate(c, NormalState);
223 if(c->trans != None && current && c->trans == current->window)
224 active(c);
225 break;
226 case IconicState:
227 unhidec(c, 1);
228 break;
232 void
233 unmap(XUnmapEvent *e)
235 Client *c;
237 curtime = CurrentTime;
238 c = getclient(e->window, 0);
239 if(c){
240 switch (c->state){
241 case IconicState:
242 if(e->send_event){
243 unhidec(c, 0);
244 withdraw(c);
246 break;
247 case NormalState:
248 if(c == current)
249 nofocus();
250 if(!c->reparenting)
251 withdraw(c);
252 break;
254 c->reparenting = 0;
258 void
259 circulatereq(XCirculateRequestEvent *e)
261 fprintf(stderr, "It must be the warlock Krill!\n"); /* ☺ */
264 void
265 newwindow(XCreateWindowEvent *e)
267 Client *c;
268 ScreenInfo *s;
270 /* we don't set curtime as nothing here uses it */
271 if(e->override_redirect)
272 return;
273 c = getclient(e->window, 1);
274 if(c && c->window == e->window && (s = getscreen(e->parent))){
275 c->x = e->x;
276 c->y = e->y;
277 c->dx = e->width;
278 c->dy = e->height;
279 c->border = e->border_width;
280 c->screen = s;
281 if(c->parent == None)
282 c->parent = c->screen->root;
286 void
287 destroy(Window w)
289 int i;
290 Client *c;
292 curtime = CurrentTime;
293 c = getclient(w, 0);
294 if(c == 0)
295 return;
297 if(numvirtuals > 1)
298 for(i=0; i<numvirtuals; i++)
299 if(currents[i] == c)
300 currents[i] = 0;
302 rmclient(c);
304 /* flush any errors generated by the window's sudden demise */
305 ignore_badwindow = 1;
306 XSync(dpy, False);
307 ignore_badwindow = 0;
310 void
311 clientmesg(XClientMessageEvent *e)
313 Client *c;
315 curtime = CurrentTime;
316 if(e->message_type == exit_rio){
317 cleanup();
318 exit(0);
320 if(e->message_type == restart_rio){
321 fprintf(stderr, "*** rio restarting ***\n");
322 cleanup();
323 execvp(myargv[0], myargv);
324 perror("rio: exec failed");
325 exit(1);
327 if(e->message_type == wm_protocols)
328 return;
329 if(e->message_type == wm_change_state){
330 c = getclient(e->window, 0);
331 if(e->format == 32 && e->data.l[0] == IconicState && c != 0){
332 if(normal(c))
333 hide(c);
335 else
336 fprintf(stderr, "rio: WM_CHANGE_STATE: format %d data %d w 0x%x\n",
337 (int)e->format, (int)e->data.l[0], (int)e->window);
338 return;
340 if(e->message_type == wm_state){
341 // c = getclient(e->window, 0);
342 // if(e->format == 32 && e->data.l[1] == wm_state_fullscreen){
343 // }else
344 fprintf(stderr, "rio: WM_STATE: format %d data %d %d w 0x%x\n",
345 (int)e->format, (int)e->data.l[0], (int)e->data.l[1],
346 (int)e->window);
347 return;
349 fprintf(stderr, "rio: strange ClientMessage, type 0x%x window 0x%x\n",
350 (int)e->message_type, (int)e->window);
353 void
354 cmap(XColormapEvent *e)
356 Client *c;
357 int i;
359 /* we don't set curtime as nothing here uses it */
360 if(e->new){
361 c = getclient(e->window, 0);
362 if(c){
363 c->cmap = e->colormap;
364 if(c == current)
365 cmapfocus(c);
367 else
368 for(c = clients; c; c = c->next){
369 for(i = 0; i < c->ncmapwins; i++)
370 if(c->cmapwins[i] == e->window){
371 c->wmcmaps[i] = e->colormap;
372 if(c == current)
373 cmapfocus(c);
374 return;
380 void
381 property(XPropertyEvent *e)
383 Atom a;
384 int delete;
385 Client *c;
386 long msize;
388 /* we don't set curtime as nothing here uses it */
389 a = e->atom;
390 delete = (e->state == PropertyDelete);
391 c = getclient(e->window, 0);
392 if(c == 0)
393 return;
395 switch (a){
396 case XA_WM_ICON_NAME:
397 if(c->iconname != 0)
398 XFree((char*) c->iconname);
399 c->iconname = delete ? 0 : getprop(c->window, a);
400 setlabel(c);
401 renamec(c, c->label);
402 return;
403 case XA_WM_NAME:
404 if(c->name != 0)
405 XFree((char*) c->name);
406 c->name = delete ? 0 : getprop(c->window, a);
407 setlabel(c);
408 renamec(c, c->label);
409 return;
410 case XA_WM_TRANSIENT_FOR:
411 gettrans(c);
412 return;
413 case XA_WM_HINTS:
414 case XA_WM_SIZE_HINTS:
415 case XA_WM_ZOOM_HINTS:
416 /* placeholders to not forget. ignore for now. -Axel */
417 return;
418 case XA_WM_NORMAL_HINTS:
419 if(XGetWMNormalHints(dpy, c->window, &c->size, &msize) == 0 || c->size.flags == 0)
420 c->size.flags = PSize; /* not specified - punt */
421 return;
423 if(a == _rio_hold_mode){
424 c->hold = getiprop(c->window, _rio_hold_mode);
425 if(c == current)
426 draw_border(c, 1);
428 else if(a == wm_colormaps){
429 getcmaps(c);
430 if(c == current)
431 cmapfocus(c);
435 void
436 reparent(XReparentEvent *e)
438 Client *c;
439 XWindowAttributes attr;
440 ScreenInfo *s;
442 /* we don't set curtime as nothing here uses it */
443 if(!getscreen(e->event) || e->override_redirect)
444 return;
445 if((s = getscreen(e->parent)) != 0){
446 c = getclient(e->window, 1);
447 if(c != 0 && (c->dx == 0 || c->dy == 0)){
448 /* flush any errors */
449 ignore_badwindow = 1;
450 XGetWindowAttributes(dpy, c->window, &attr);
451 XSync(dpy, False);
452 ignore_badwindow = 0;
454 c->x = attr.x;
455 c->y = attr.y;
456 c->dx = attr.width;
457 c->dy = attr.height;
458 c->border = attr.border_width;
459 c->screen = s;
460 if(c->parent == None)
461 c->parent = c->screen->root;
464 else {
465 c = getclient(e->window, 0);
466 if(c != 0 && (c->parent == c->screen->root || withdrawn(c)))
467 rmclient(c);
471 #ifdef SHAPE
472 void
473 shapenotify(XShapeEvent *e)
475 Client *c;
477 /* we don't set curtime as nothing here uses it */
478 c = getclient(e->window, 0);
479 if(c == 0)
480 return;
482 setshape(c);
484 #endif
486 void
487 enter(XCrossingEvent *e)
489 Client *c;
491 curtime = e->time;
492 if(!ffm)
493 if(e->mode != NotifyGrab || e->detail != NotifyNonlinearVirtual)
494 return;
495 c = getclient(e->window, 0);
496 if(c != 0 && c != current){
497 /* someone grabbed the pointer; make them current */
498 if(!ffm)
499 XMapRaised(dpy, c->parent);
500 top(c);
501 active(c);
505 void
506 leave(XCrossingEvent *e)
508 Client *c;
510 c = getclient(e->window, 0);
511 if(c)
512 XUndefineCursor(dpy, c->parent);
513 /* XDefineCursor(dpy, c->parent, c->screen->arrow); */
516 void
517 focusin(XFocusChangeEvent *e)
519 Client *c;
521 curtime = CurrentTime;
522 if(e->detail != NotifyNonlinearVirtual)
523 return;
524 c = getclient(e->window, 0);
525 if(c != 0 && c->window == e->window && c != current){
526 /* someone grabbed keyboard or seized focus; make them current */
527 XMapRaised(dpy, c->parent);
528 top(c);
529 active(c);
533 BorderOrient
534 borderorient(Client *c, int x, int y)
536 if(x <= BORDER){
537 if(y <= CORNER){
538 if(debug) fprintf(stderr, "topleft\n");
539 return BorderWNW;
541 if(y >= (c->dy + 2*BORDER) - CORNER){
542 if(debug) fprintf(stderr, "botleft\n");
543 return BorderWSW;
545 if(y > CORNER &&
546 y < (c->dy + 2*BORDER) - CORNER){
547 if(debug) fprintf(stderr, "left\n");
548 return BorderW;
550 } else if(x <= CORNER){
551 if(y <= BORDER){
552 if(debug) fprintf(stderr, "topleft\n");
553 return BorderNNW;
555 if (y >= (c->dy + BORDER)){
556 if(debug) fprintf(stderr, "botleft\n");
557 return BorderSSW;
559 } else if(x >= (c->dx + BORDER)){
560 if(y <= CORNER){
561 if(debug) fprintf(stderr, "topright\n");
562 return BorderENE;
564 if(y >= (c->dy + 2*BORDER) - CORNER){
565 if(debug) fprintf(stderr, "botright\n");
566 return BorderESE;
568 if(y > CORNER &&
569 y < (c->dy + 2*BORDER) - CORNER){
570 if(debug) fprintf(stderr, "right\n");
571 return BorderE;
573 } else if(x >= (c->dx + 2*BORDER) - CORNER){
574 if(y <= BORDER){
575 if(debug) fprintf(stderr, "topright\n");
576 return BorderNNE;
578 if (y >= (c->dy + BORDER)){
579 if(debug) fprintf(stderr, "botright\n");
580 return BorderSSE;
582 } else if(x > CORNER &&
583 x < (c->dx + 2*BORDER) - CORNER){
584 if(y <= BORDER){
585 if(debug) fprintf(stderr, "top\n");
586 return BorderN;
588 if(y >= (c->dy + BORDER)){
589 if(debug) fprintf(stderr, "bot\n");
590 return BorderS;
593 return BorderUnknown;
596 void
597 motionnotify(XMotionEvent *e)
599 Client *c;
600 BorderOrient bl;
602 c = getclient(e->window, 0);
603 if(c){
604 bl = borderorient(c, e->x, e->y);
605 if(bl == BorderUnknown)
606 XUndefineCursor(dpy, c->parent);
607 else
608 XDefineCursor(dpy, c->parent, c->screen->bordcurs[bl]);