Mercurial > hg > index.fcgi > dwm > dwm-3.6.1-12pba
comparison event.c @ 0:7024076fa948
initial add
author | paulo@localhost |
---|---|
date | Sun, 22 Mar 2009 23:26:35 -0700 |
parents | |
children | de6bb7885c97 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c52074937cd6 |
---|---|
1 /* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com> | |
2 * See LICENSE file for license details. | |
3 */ | |
4 #include "dwm.h" | |
5 #include <stdlib.h> | |
6 #include <X11/keysym.h> | |
7 #include <X11/Xatom.h> | |
8 | |
9 /* static */ | |
10 | |
11 typedef struct { | |
12 unsigned long mod; | |
13 KeySym keysym; | |
14 void (*func)(Arg *arg); | |
15 Arg arg; | |
16 } Key; | |
17 | |
18 KEYS | |
19 | |
20 #define CLEANMASK(mask) (mask & ~(numlockmask | LockMask)) | |
21 #define MOUSEMASK (BUTTONMASK | PointerMotionMask) | |
22 | |
23 static Client * | |
24 getclient(Window w) { | |
25 Client *c; | |
26 | |
27 for(c = clients; c && c->win != w; c = c->next); | |
28 return c; | |
29 } | |
30 | |
31 static void | |
32 movemouse(Client *c) { | |
33 int x1, y1, ocx, ocy, di, nx, ny; | |
34 unsigned int dui; | |
35 Window dummy; | |
36 XEvent ev; | |
37 | |
38 ocx = nx = c->x; | |
39 ocy = ny = c->y; | |
40 if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, | |
41 None, cursor[CurMove], CurrentTime) != GrabSuccess) | |
42 return; | |
43 c->ismax = False; | |
44 XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui); | |
45 for(;;) { | |
46 XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask, &ev); | |
47 switch (ev.type) { | |
48 case ButtonRelease: | |
49 XUngrabPointer(dpy, CurrentTime); | |
50 return; | |
51 case ConfigureRequest: | |
52 case Expose: | |
53 case MapRequest: | |
54 handler[ev.type](&ev); | |
55 break; | |
56 case MotionNotify: | |
57 XSync(dpy, False); | |
58 nx = ocx + (ev.xmotion.x - x1); | |
59 ny = ocy + (ev.xmotion.y - y1); | |
60 if(abs(wax + nx) < SNAP) | |
61 nx = wax; | |
62 else if(abs((wax + waw) - (nx + c->w + 2 * c->border)) < SNAP) | |
63 nx = wax + waw - c->w - 2 * c->border; | |
64 if(abs(way - ny) < SNAP) | |
65 ny = way; | |
66 else if(abs((way + wah) - (ny + c->h + 2 * c->border)) < SNAP) | |
67 ny = way + wah - c->h - 2 * c->border; | |
68 resize(c, nx, ny, c->w, c->h, False); | |
69 break; | |
70 } | |
71 } | |
72 } | |
73 | |
74 static void | |
75 resizemouse(Client *c) { | |
76 int ocx, ocy; | |
77 int nw, nh; | |
78 XEvent ev; | |
79 | |
80 ocx = c->x; | |
81 ocy = c->y; | |
82 if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, | |
83 None, cursor[CurResize], CurrentTime) != GrabSuccess) | |
84 return; | |
85 c->ismax = False; | |
86 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->border - 1, c->h + c->border - 1); | |
87 for(;;) { | |
88 XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask , &ev); | |
89 switch(ev.type) { | |
90 case ButtonRelease: | |
91 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, | |
92 c->w + c->border - 1, c->h + c->border - 1); | |
93 XUngrabPointer(dpy, CurrentTime); | |
94 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); | |
95 return; | |
96 case ConfigureRequest: | |
97 case Expose: | |
98 case MapRequest: | |
99 handler[ev.type](&ev); | |
100 break; | |
101 case MotionNotify: | |
102 XSync(dpy, False); | |
103 if((nw = ev.xmotion.x - ocx - 2 * c->border + 1) <= 0) | |
104 nw = 1; | |
105 if((nh = ev.xmotion.y - ocy - 2 * c->border + 1) <= 0) | |
106 nh = 1; | |
107 resize(c, c->x, c->y, nw, nh, True); | |
108 break; | |
109 } | |
110 } | |
111 } | |
112 | |
113 static void | |
114 buttonpress(XEvent *e) { | |
115 int x; | |
116 Arg a; | |
117 Client *c; | |
118 XButtonPressedEvent *ev = &e->xbutton; | |
119 | |
120 if(barwin == ev->window) { | |
121 x = 0; | |
122 for(a.i = 0; a.i < ntags; a.i++) { | |
123 x += textw(tags[a.i]); | |
124 if(ev->x < x) { | |
125 if(ev->button == Button1) { | |
126 if(ev->state & MODKEY) | |
127 tag(&a); | |
128 else | |
129 view(&a); | |
130 } | |
131 else if(ev->button == Button3) { | |
132 if(ev->state & MODKEY) | |
133 toggletag(&a); | |
134 else | |
135 toggleview(&a); | |
136 } | |
137 return; | |
138 } | |
139 } | |
140 if(ev->x < x + blw) | |
141 switch(ev->button) { | |
142 case Button1: | |
143 a.i = -1; | |
144 setlayout(&a); | |
145 break; | |
146 case Button4: | |
147 a.i = 1; | |
148 incnmaster(&a); | |
149 break; | |
150 case Button5: | |
151 a.i = -1; | |
152 incnmaster(&a); | |
153 break; | |
154 } | |
155 if(ev->x > x + blw) | |
156 switch(ev->button) { | |
157 case Button1: zoom(NULL); break; | |
158 case Button2: toggleversatile(NULL); break; | |
159 case Button3: killclient(NULL); break; | |
160 case Button4: focusprev(NULL); break; | |
161 case Button5: focusnext(NULL); break; | |
162 } | |
163 } | |
164 else if((c = getclient(ev->window))) { | |
165 focus(c); | |
166 if(CLEANMASK(ev->state) != MODKEY) | |
167 return; | |
168 if(ev->button == Button1 && (lt->arrange == versatile || c->isversatile)) { | |
169 restack(); | |
170 movemouse(c); | |
171 } | |
172 else if(ev->button == Button2) | |
173 zoom(NULL); | |
174 else if(ev->button == Button3 | |
175 && (lt->arrange == versatile || c->isversatile) && !c->isfixed) | |
176 { | |
177 restack(); | |
178 resizemouse(c); | |
179 } | |
180 } | |
181 } | |
182 | |
183 static void | |
184 configurerequest(XEvent *e) { | |
185 Client *c; | |
186 XConfigureRequestEvent *ev = &e->xconfigurerequest; | |
187 XWindowChanges wc; | |
188 | |
189 if((c = getclient(ev->window))) { | |
190 c->ismax = False; | |
191 if(ev->value_mask & CWBorderWidth) | |
192 c->border = ev->border_width; | |
193 if(c->isfixed || c->isversatile || (lt->arrange == versatile)) { | |
194 if(ev->value_mask & CWX) | |
195 c->x = ev->x; | |
196 if(ev->value_mask & CWY) | |
197 c->y = ev->y; | |
198 if(ev->value_mask & CWWidth) | |
199 c->w = ev->width; | |
200 if(ev->value_mask & CWHeight) | |
201 c->h = ev->height; | |
202 if((ev->value_mask & (CWX | CWY)) | |
203 && !(ev->value_mask & (CWWidth | CWHeight))) | |
204 configure(c); | |
205 if(isvisible(c)) | |
206 /* XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); */ | |
207 resize(c, c->x, c->y, c->w, c->h, False); | |
208 } | |
209 else | |
210 configure(c); | |
211 } | |
212 else { | |
213 wc.x = ev->x; | |
214 wc.y = ev->y; | |
215 wc.width = ev->width; | |
216 wc.height = ev->height; | |
217 wc.border_width = ev->border_width; | |
218 wc.sibling = ev->above; | |
219 wc.stack_mode = ev->detail; | |
220 XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); | |
221 } | |
222 XSync(dpy, False); | |
223 } | |
224 | |
225 static void | |
226 destroynotify(XEvent *e) { | |
227 Client *c; | |
228 XDestroyWindowEvent *ev = &e->xdestroywindow; | |
229 | |
230 if((c = getclient(ev->window))) | |
231 unmanage(c); | |
232 } | |
233 | |
234 static void | |
235 enternotify(XEvent *e) { | |
236 Client *c; | |
237 XCrossingEvent *ev = &e->xcrossing; | |
238 | |
239 if(ev->mode != NotifyNormal || ev->detail == NotifyInferior) | |
240 return; | |
241 if((c = getclient(ev->window)) && isvisible(c)) | |
242 focus(c); | |
243 else if(ev->window == root) { | |
244 selscreen = True; | |
245 for(c = stack; c && !isvisible(c); c = c->snext); | |
246 focus(c); | |
247 } | |
248 } | |
249 | |
250 static void | |
251 expose(XEvent *e) { | |
252 XExposeEvent *ev = &e->xexpose; | |
253 | |
254 if(ev->count == 0) { | |
255 if(barwin == ev->window) | |
256 drawstatus(); | |
257 } | |
258 } | |
259 | |
260 static void | |
261 keypress(XEvent *e) { | |
262 static unsigned int len = sizeof key / sizeof key[0]; | |
263 unsigned int i; | |
264 KeySym keysym; | |
265 XKeyEvent *ev = &e->xkey; | |
266 | |
267 keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); | |
268 for(i = 0; i < len; i++) | |
269 if(keysym == key[i].keysym | |
270 && CLEANMASK(key[i].mod) == CLEANMASK(ev->state)) | |
271 { | |
272 if(key[i].func) | |
273 key[i].func(&key[i].arg); | |
274 } | |
275 } | |
276 | |
277 static void | |
278 leavenotify(XEvent *e) { | |
279 XCrossingEvent *ev = &e->xcrossing; | |
280 | |
281 if((ev->window == root) && !ev->same_screen) { | |
282 selscreen = False; | |
283 focus(NULL); | |
284 } | |
285 } | |
286 | |
287 static void | |
288 mappingnotify(XEvent *e) { | |
289 XMappingEvent *ev = &e->xmapping; | |
290 | |
291 XRefreshKeyboardMapping(ev); | |
292 if(ev->request == MappingKeyboard) | |
293 grabkeys(); | |
294 } | |
295 | |
296 static void | |
297 maprequest(XEvent *e) { | |
298 static XWindowAttributes wa; | |
299 XMapRequestEvent *ev = &e->xmaprequest; | |
300 | |
301 if(!XGetWindowAttributes(dpy, ev->window, &wa)) | |
302 return; | |
303 if(wa.override_redirect) | |
304 return; | |
305 if(!getclient(ev->window)) | |
306 manage(ev->window, &wa); | |
307 } | |
308 | |
309 static void | |
310 propertynotify(XEvent *e) { | |
311 Client *c; | |
312 Window trans; | |
313 XPropertyEvent *ev = &e->xproperty; | |
314 | |
315 if(ev->state == PropertyDelete) | |
316 return; /* ignore */ | |
317 if((c = getclient(ev->window))) { | |
318 switch (ev->atom) { | |
319 default: break; | |
320 case XA_WM_TRANSIENT_FOR: | |
321 XGetTransientForHint(dpy, c->win, &trans); | |
322 if(!c->isversatile && (c->isversatile = (getclient(trans) != NULL))) | |
323 lt->arrange(); | |
324 break; | |
325 case XA_WM_NORMAL_HINTS: | |
326 updatesizehints(c); | |
327 break; | |
328 } | |
329 if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { | |
330 updatetitle(c); | |
331 if(c == sel) | |
332 drawstatus(); | |
333 } | |
334 } | |
335 } | |
336 | |
337 static void | |
338 unmapnotify(XEvent *e) { | |
339 Client *c; | |
340 XUnmapEvent *ev = &e->xunmap; | |
341 | |
342 if((c = getclient(ev->window))) | |
343 unmanage(c); | |
344 } | |
345 | |
346 /* extern */ | |
347 | |
348 void (*handler[LASTEvent]) (XEvent *) = { | |
349 [ButtonPress] = buttonpress, | |
350 [ConfigureRequest] = configurerequest, | |
351 [DestroyNotify] = destroynotify, | |
352 [EnterNotify] = enternotify, | |
353 [LeaveNotify] = leavenotify, | |
354 [Expose] = expose, | |
355 [KeyPress] = keypress, | |
356 [MappingNotify] = mappingnotify, | |
357 [MapRequest] = maprequest, | |
358 [PropertyNotify] = propertynotify, | |
359 [UnmapNotify] = unmapnotify | |
360 }; | |
361 | |
362 void | |
363 grabkeys(void) { | |
364 static unsigned int len = sizeof key / sizeof key[0]; | |
365 unsigned int i; | |
366 KeyCode code; | |
367 | |
368 XUngrabKey(dpy, AnyKey, AnyModifier, root); | |
369 for(i = 0; i < len; i++) { | |
370 code = XKeysymToKeycode(dpy, key[i].keysym); | |
371 XGrabKey(dpy, code, key[i].mod, root, True, | |
372 GrabModeAsync, GrabModeAsync); | |
373 XGrabKey(dpy, code, key[i].mod | LockMask, root, True, | |
374 GrabModeAsync, GrabModeAsync); | |
375 XGrabKey(dpy, code, key[i].mod | numlockmask, root, True, | |
376 GrabModeAsync, GrabModeAsync); | |
377 XGrabKey(dpy, code, key[i].mod | numlockmask | LockMask, root, True, | |
378 GrabModeAsync, GrabModeAsync); | |
379 } | |
380 } |