aewl

view event.c @ 541:08d3d329270a

using MASTER 600 again, it is definately better, and using urxvtc for the moment (it doesn't flickers on refreshes, but this is not because of Marc Lehmann, it is because of the original rxvt code)
author arg@mig29
date Thu, 26 Oct 2006 12:13:41 +0200
parents a5567a0d3011
children fd1061442711
line source
1 /* (C)opyright MMVI 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>
9 /* static */
11 typedef struct {
12 unsigned long mod;
13 KeySym keysym;
14 void (*func)(Arg *arg);
15 Arg arg;
16 } Key;
18 KEYS
20 #define CLEANMASK(mask) (mask & ~(numlockmask | LockMask))
21 #define MOUSEMASK (BUTTONMASK | PointerMotionMask)
23 static void
24 movemouse(Client *c) {
25 int x1, y1, ocx, ocy, di;
26 unsigned int dui;
27 Window dummy;
28 XEvent ev;
30 ocx = c->x;
31 ocy = c->y;
32 if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
33 None, cursor[CurMove], CurrentTime) != GrabSuccess)
34 return;
35 c->ismax = False;
36 XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
37 for(;;) {
38 XMaskEvent(dpy, MOUSEMASK | ExposureMask, &ev);
39 switch (ev.type) {
40 case ButtonRelease:
41 resize(c, True, TopLeft);
42 XUngrabPointer(dpy, CurrentTime);
43 return;
44 case Expose:
45 handler[Expose](&ev);
46 break;
47 case MotionNotify:
48 XSync(dpy, False);
49 c->x = ocx + (ev.xmotion.x - x1);
50 c->y = ocy + (ev.xmotion.y - y1);
51 resize(c, False, TopLeft);
52 break;
53 }
54 }
55 }
57 static void
58 resizemouse(Client *c) {
59 int ocx, ocy;
60 int nw, nh;
61 Corner sticky;
62 XEvent ev;
64 ocx = c->x;
65 ocy = c->y;
66 if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
67 None, cursor[CurResize], CurrentTime) != GrabSuccess)
68 return;
69 c->ismax = False;
70 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w, c->h);
71 for(;;) {
72 XMaskEvent(dpy, MOUSEMASK | ExposureMask, &ev);
73 switch(ev.type) {
74 case ButtonRelease:
75 resize(c, True, TopLeft);
76 XUngrabPointer(dpy, CurrentTime);
77 return;
78 case Expose:
79 handler[Expose](&ev);
80 break;
81 case MotionNotify:
82 XSync(dpy, False);
83 if((nw = abs(ocx - ev.xmotion.x)))
84 c->w = nw;
85 if((nh = abs(ocy - ev.xmotion.y)))
86 c->h = nh;
87 c->x = (ocx <= ev.xmotion.x) ? ocx : ocx - c->w;
88 c->y = (ocy <= ev.xmotion.y) ? ocy : ocy - c->h;
89 if(ocx <= ev.xmotion.x)
90 sticky = (ocy <= ev.xmotion.y) ? TopLeft : BotLeft;
91 else
92 sticky = (ocy <= ev.xmotion.y) ? TopRight : BotRight;
93 resize(c, True, sticky);
94 break;
95 }
96 }
97 }
99 static void
100 buttonpress(XEvent *e) {
101 int x;
102 Arg a;
103 Client *c;
104 XButtonPressedEvent *ev = &e->xbutton;
106 if(barwin == ev->window) {
107 x = 0;
108 for(a.i = 0; a.i < ntags; a.i++) {
109 x += textw(tags[a.i]);
110 if(ev->x < x) {
111 if(ev->button == Button1) {
112 if(ev->state & MODKEY)
113 tag(&a);
114 else
115 view(&a);
116 }
117 else if(ev->button == Button3) {
118 if(ev->state & MODKEY)
119 toggletag(&a);
120 else
121 toggleview(&a);
122 }
123 return;
124 }
125 }
126 if((ev->x < x + bmw) && (ev->button == Button1))
127 togglemode(NULL);
128 }
129 else if((c = getclient(ev->window))) {
130 focus(c);
131 if(CLEANMASK(ev->state) != MODKEY)
132 return;
133 if(ev->button == Button1 && (arrange == dofloat || c->isfloat)) {
134 restack();
135 movemouse(c);
136 }
137 else if(ev->button == Button2)
138 zoom(NULL);
139 else if(ev->button == Button3 && (arrange == dofloat || c->isfloat)) {
140 restack();
141 resizemouse(c);
142 }
143 }
144 }
146 static void
147 configurerequest(XEvent *e) {
148 unsigned long newmask;
149 Client *c;
150 XConfigureRequestEvent *ev = &e->xconfigurerequest;
151 XWindowChanges wc;
153 if((c = getclient(ev->window))) {
154 c->ismax = False;
155 gravitate(c, True);
156 if(ev->value_mask & CWX)
157 c->x = ev->x;
158 if(ev->value_mask & CWY)
159 c->y = ev->y;
160 if(ev->value_mask & CWWidth)
161 c->w = ev->width;
162 if(ev->value_mask & CWHeight)
163 c->h = ev->height;
164 if(ev->value_mask & CWBorderWidth)
165 c->border = ev->border_width;
166 gravitate(c, False);
167 wc.x = c->x;
168 wc.y = c->y;
169 wc.width = c->w;
170 wc.height = c->h;
171 newmask = ev->value_mask & (~(CWSibling | CWStackMode | CWBorderWidth));
172 if(newmask)
173 XConfigureWindow(dpy, c->win, newmask, &wc);
174 else
175 configure(c);
176 XSync(dpy, False);
177 if(c->isfloat) {
178 resize(c, False, TopLeft);
179 if(!isvisible(c))
180 ban(c);
181 }
182 else
183 arrange();
184 }
185 else {
186 wc.x = ev->x;
187 wc.y = ev->y;
188 wc.width = ev->width;
189 wc.height = ev->height;
190 wc.border_width = ev->border_width;
191 wc.sibling = ev->above;
192 wc.stack_mode = ev->detail;
193 XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
194 XSync(dpy, False);
195 }
196 }
198 static void
199 destroynotify(XEvent *e) {
200 Client *c;
201 XDestroyWindowEvent *ev = &e->xdestroywindow;
203 if((c = getclient(ev->window)))
204 unmanage(c);
205 }
207 static void
208 enternotify(XEvent *e) {
209 Client *c;
210 XCrossingEvent *ev = &e->xcrossing;
212 if(ev->mode != NotifyNormal || ev->detail == NotifyInferior)
213 return;
214 if(((c = getclient(ev->window)) || (c = getctitle(ev->window))) && isvisible(c))
215 focus(c);
216 else if(ev->window == root) {
217 issel = True;
218 XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
219 drawall();
220 }
221 }
223 static void
224 expose(XEvent *e) {
225 Client *c;
226 XExposeEvent *ev = &e->xexpose;
228 if(ev->count == 0) {
229 if(barwin == ev->window)
230 drawstatus();
231 else if((c = getctitle(ev->window)))
232 drawtitle(c);
233 }
234 }
236 static void
237 keypress(XEvent *e) {
238 static unsigned int len = sizeof(key) / sizeof(key[0]);
239 unsigned int i;
240 KeySym keysym;
241 XKeyEvent *ev = &e->xkey;
243 keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
244 for(i = 0; i < len; i++) {
245 if(keysym == key[i].keysym
246 && CLEANMASK(key[i].mod) == CLEANMASK(ev->state))
247 {
248 if(key[i].func)
249 key[i].func(&key[i].arg);
250 return;
251 }
252 }
253 }
255 static void
256 leavenotify(XEvent *e) {
257 XCrossingEvent *ev = &e->xcrossing;
259 if((ev->window == root) && !ev->same_screen) {
260 issel = False;
261 drawall();
262 }
263 }
265 static void
266 mappingnotify(XEvent *e) {
267 XMappingEvent *ev = &e->xmapping;
269 XRefreshKeyboardMapping(ev);
270 if(ev->request == MappingKeyboard)
271 grabkeys();
272 }
274 static void
275 maprequest(XEvent *e) {
276 static XWindowAttributes wa;
277 XMapRequestEvent *ev = &e->xmaprequest;
279 if(!XGetWindowAttributes(dpy, ev->window, &wa))
280 return;
281 if(wa.override_redirect) {
282 XSelectInput(dpy, ev->window,
283 (StructureNotifyMask | PropertyChangeMask));
284 return;
285 }
286 if(!getclient(ev->window))
287 manage(ev->window, &wa);
288 }
290 static void
291 propertynotify(XEvent *e) {
292 Client *c;
293 Window trans;
294 XPropertyEvent *ev = &e->xproperty;
296 if(ev->state == PropertyDelete)
297 return; /* ignore */
298 if((c = getclient(ev->window))) {
299 if(ev->atom == wmatom[WMProtocols]) {
300 c->proto = getproto(c->win);
301 return;
302 }
303 switch (ev->atom) {
304 default: break;
305 case XA_WM_TRANSIENT_FOR:
306 XGetTransientForHint(dpy, c->win, &trans);
307 if(!c->isfloat && (c->isfloat = (trans != 0)))
308 arrange();
309 break;
310 case XA_WM_NORMAL_HINTS:
311 updatesize(c);
312 break;
313 }
314 if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
315 updatetitle(c);
316 resizetitle(c);
317 drawtitle(c);
318 }
319 }
320 }
322 static void
323 unmapnotify(XEvent *e) {
324 Client *c;
325 XUnmapEvent *ev = &e->xunmap;
327 if((c = getclient(ev->window)))
328 unmanage(c);
329 }
331 /* extern */
333 void (*handler[LASTEvent]) (XEvent *) = {
334 [ButtonPress] = buttonpress,
335 [ConfigureRequest] = configurerequest,
336 [DestroyNotify] = destroynotify,
337 [EnterNotify] = enternotify,
338 [LeaveNotify] = leavenotify,
339 [Expose] = expose,
340 [KeyPress] = keypress,
341 [MappingNotify] = mappingnotify,
342 [MapRequest] = maprequest,
343 [PropertyNotify] = propertynotify,
344 [UnmapNotify] = unmapnotify
345 };
347 void
348 grabkeys(void) {
349 static unsigned int len = sizeof(key) / sizeof(key[0]);
350 unsigned int i;
351 KeyCode code;
353 XUngrabKey(dpy, AnyKey, AnyModifier, root);
354 for(i = 0; i < len; i++) {
355 code = XKeysymToKeycode(dpy, key[i].keysym);
356 XGrabKey(dpy, code, key[i].mod, root, True,
357 GrabModeAsync, GrabModeAsync);
358 XGrabKey(dpy, code, key[i].mod | LockMask, root, True,
359 GrabModeAsync, GrabModeAsync);
360 XGrabKey(dpy, code, key[i].mod | numlockmask, root, True,
361 GrabModeAsync, GrabModeAsync);
362 XGrabKey(dpy, code, key[i].mod | numlockmask | LockMask, root, True,
363 GrabModeAsync, GrabModeAsync);
364 }
365 }
367 void
368 procevent(void) {
369 XEvent ev;
371 while(XPending(dpy)) {
372 XNextEvent(dpy, &ev);
373 if(handler[ev.type])
374 (handler[ev.type])(&ev); /* call handler */
375 }
376 }