JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
added protocol killing stuff
[dwm.git] / event.c
1 /*
2  * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
3  * See LICENSE file for license details.
4  */
5
6 #include <fcntl.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <X11/keysym.h>
10 #include <X11/Xatom.h>
11
12 #include "wm.h"
13
14 /* local functions */
15 static void configurerequest(XEvent *e);
16 static void destroynotify(XEvent *e);
17 static void enternotify(XEvent *e);
18 static void leavenotify(XEvent *e);
19 static void expose(XEvent *e);
20 static void keymapnotify(XEvent *e);
21 static void maprequest(XEvent *e);
22 static void propertynotify(XEvent *e);
23 static void unmapnotify(XEvent *e);
24
25 void (*handler[LASTEvent]) (XEvent *) = {
26         [ConfigureRequest] = configurerequest,
27         [DestroyNotify] = destroynotify,
28         [EnterNotify] = enternotify,
29         [LeaveNotify] = leavenotify,
30         [Expose] = expose,
31         [KeyPress] = keypress,
32         [KeymapNotify] = keymapnotify,
33         [MapRequest] = maprequest,
34         [PropertyNotify] = propertynotify,
35         [UnmapNotify] = unmapnotify
36 };
37
38 unsigned int
39 flush_events(long even_mask)
40 {
41         XEvent ev;
42         unsigned int n = 0;
43         while(XCheckMaskEvent(dpy, even_mask, &ev)) n++;
44         return n;
45 }
46
47 static void
48 configurerequest(XEvent *e)
49 {
50         XConfigureRequestEvent *ev = &e->xconfigurerequest;
51         XWindowChanges wc;
52         Client *c;
53
54         c = getclient(ev->window);
55         ev->value_mask &= ~CWSibling;
56         if(c) {
57                 if(ev->value_mask & CWX)
58                         c->r[RFloat].x = ev->x;
59                 if(ev->value_mask & CWY)
60                         c->r[RFloat].y = ev->y;
61                 if(ev->value_mask & CWWidth)
62                         c->r[RFloat].width = ev->width;
63                 if(ev->value_mask & CWHeight)
64                         c->r[RFloat].height = ev->height;
65                 if(ev->value_mask & CWBorderWidth)
66                         c->border = ev->border_width;
67         }
68
69         wc.x = ev->x;
70         wc.y = ev->y;
71         wc.width = ev->width;
72         wc.height = ev->height;
73         wc.border_width = 0;
74         wc.sibling = None;
75         wc.stack_mode = Above;
76         ev->value_mask &= ~CWStackMode;
77         ev->value_mask |= CWBorderWidth;
78         XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
79         XFlush(dpy);
80 }
81
82 static void
83 destroynotify(XEvent *e)
84 {
85         Client *c;
86         XDestroyWindowEvent *ev = &e->xdestroywindow;
87
88         if((c = getclient(ev->window)))
89                 unmanage(c);
90 }
91
92 static void
93 enternotify(XEvent *e)
94 {
95         XCrossingEvent *ev = &e->xcrossing;
96         Client *c;
97
98         if(ev->mode != NotifyNormal || ev->detail == NotifyInferior)
99                 return;
100
101         if((c = getclient(ev->window)))
102                 focus(c);
103         else if(ev->window == root) {
104                 sel_screen = True;
105                 /*draw_frames();*/
106         }
107 }
108
109 static void
110 leavenotify(XEvent *e)
111 {
112         XCrossingEvent *ev = &e->xcrossing;
113
114         if((ev->window == root) && !ev->same_screen) {
115                 sel_screen = True;
116                 /*draw_frames();*/
117         }
118 }
119
120 static void
121 expose(XEvent *e)
122 {
123         XExposeEvent *ev = &e->xexpose;
124
125         if(ev->count == 0) {
126                 if(ev->window == barwin)
127                         draw_bar();
128         }
129 }
130
131 static void
132 keymapnotify(XEvent *e)
133 {
134         update_keys();
135 }
136
137 static void
138 maprequest(XEvent *e)
139 {
140         XMapRequestEvent *ev = &e->xmaprequest;
141         static XWindowAttributes wa;
142
143         if(!XGetWindowAttributes(dpy, ev->window, &wa))
144                 return;
145
146         if(wa.override_redirect) {
147                 XSelectInput(dpy, ev->window,
148                                 (StructureNotifyMask | PropertyChangeMask));
149                 return;
150         }
151
152         if(!getclient(ev->window))
153                 manage(ev->window, &wa);
154 }
155
156 static void
157 propertynotify(XEvent *e)
158 {
159         XPropertyEvent *ev = &e->xproperty;
160         long msize;
161         Client *c;
162
163         if(ev->state == PropertyDelete)
164                 return; /* ignore */
165
166         if(ev->atom == wm_atom[WMProtocols]) {
167                 c->proto = win_proto(c->win);
168                 return;
169         }
170         if((c = getclient(ev->window))) {
171                 switch (ev->atom) {
172                         default: break;
173                         case XA_WM_TRANSIENT_FOR:
174                                 XGetTransientForHint(dpy, c->win, &c->trans);
175                                 break;
176                         case XA_WM_NORMAL_HINTS:
177                                 if(!XGetWMNormalHints(dpy, c->win, &c->size, &msize)
178                                                 || !c->size.flags)
179                                         c->size.flags = PSize;
180                                 if(c->size.flags & PMinSize && c->size.flags & PMaxSize
181                                                 && c->size.min_width == c->size.max_width
182                                                 && c->size.min_height == c->size.max_height)
183                                         c->fixedsize = True;
184                                 else
185                                         c->fixedsize = False;
186                                 break;
187                 }
188                 if(ev->atom == XA_WM_NAME || ev->atom == net_atom[NetWMName]) {
189                         update_name(c);
190                         /*draw_frame(c->sel);*/
191                 }
192         }
193 }
194
195 static void
196 unmapnotify(XEvent *e)
197 {
198         Client *c;
199         XUnmapEvent *ev = &e->xunmap;
200
201         if((c = getclient(ev->window)))
202                 unmanage(c);
203 }