rev |
line source |
paulo@0
|
1 /* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
|
paulo@0
|
2 * See LICENSE file for license details.
|
paulo@0
|
3 */
|
paulo@0
|
4 #include "dwm.h"
|
paulo@0
|
5 #include <X11/keysym.h>
|
paulo@0
|
6 #include <X11/Xatom.h>
|
paulo@0
|
7
|
paulo@0
|
8 /* static */
|
paulo@0
|
9
|
paulo@6
|
10 static unsigned int cmdmod[4];
|
paulo@6
|
11 static unsigned int keymode = COMMANDMODE;
|
paulo@6
|
12 static KeySym cmdkeysym[4];
|
paulo@6
|
13
|
paulo@0
|
14 typedef struct {
|
paulo@0
|
15 unsigned long mod;
|
paulo@0
|
16 KeySym keysym;
|
paulo@0
|
17 void (*func)(Arg *arg);
|
paulo@0
|
18 Arg arg;
|
paulo@0
|
19 } Key;
|
paulo@0
|
20
|
paulo@0
|
21 KEYS
|
paulo@0
|
22
|
paulo@0
|
23 #define CLEANMASK(mask) (mask & ~(numlockmask | LockMask))
|
paulo@0
|
24 #define MOUSEMASK (BUTTONMASK | PointerMotionMask)
|
paulo@0
|
25
|
paulo@0
|
26 static Client *
|
paulo@0
|
27 getclient(Window w) {
|
paulo@0
|
28 Client *c;
|
paulo@0
|
29
|
paulo@0
|
30 for(c = clients; c && c->win != w; c = c->next);
|
paulo@0
|
31 return c;
|
paulo@0
|
32 }
|
paulo@0
|
33
|
paulo@0
|
34 static void
|
paulo@0
|
35 movemouse(Client *c) {
|
paulo@0
|
36 int x1, y1, ocx, ocy, di, nx, ny;
|
paulo@0
|
37 unsigned int dui;
|
paulo@0
|
38 Window dummy;
|
paulo@0
|
39 XEvent ev;
|
paulo@0
|
40
|
paulo@0
|
41 ocx = nx = c->x;
|
paulo@0
|
42 ocy = ny = c->y;
|
paulo@0
|
43 if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
|
paulo@0
|
44 None, cursor[CurMove], CurrentTime) != GrabSuccess)
|
paulo@0
|
45 return;
|
paulo@0
|
46 c->ismax = False;
|
paulo@0
|
47 XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
|
paulo@0
|
48 for(;;) {
|
paulo@0
|
49 XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask, &ev);
|
paulo@0
|
50 switch (ev.type) {
|
paulo@0
|
51 case ButtonRelease:
|
paulo@0
|
52 XUngrabPointer(dpy, CurrentTime);
|
paulo@0
|
53 return;
|
paulo@0
|
54 case ConfigureRequest:
|
paulo@0
|
55 case Expose:
|
paulo@0
|
56 case MapRequest:
|
paulo@0
|
57 handler[ev.type](&ev);
|
paulo@0
|
58 break;
|
paulo@0
|
59 case MotionNotify:
|
paulo@0
|
60 XSync(dpy, False);
|
paulo@0
|
61 nx = ocx + (ev.xmotion.x - x1);
|
paulo@0
|
62 ny = ocy + (ev.xmotion.y - y1);
|
paulo@0
|
63 if(abs(wax + nx) < SNAP)
|
paulo@0
|
64 nx = wax;
|
paulo@0
|
65 else if(abs((wax + waw) - (nx + c->w + 2 * c->border)) < SNAP)
|
paulo@0
|
66 nx = wax + waw - c->w - 2 * c->border;
|
paulo@0
|
67 if(abs(way - ny) < SNAP)
|
paulo@0
|
68 ny = way;
|
paulo@0
|
69 else if(abs((way + wah) - (ny + c->h + 2 * c->border)) < SNAP)
|
paulo@0
|
70 ny = way + wah - c->h - 2 * c->border;
|
paulo@0
|
71 resize(c, nx, ny, c->w, c->h, False);
|
paulo@0
|
72 break;
|
paulo@0
|
73 }
|
paulo@0
|
74 }
|
paulo@0
|
75 }
|
paulo@0
|
76
|
paulo@0
|
77 static void
|
paulo@0
|
78 resizemouse(Client *c) {
|
paulo@0
|
79 int ocx, ocy;
|
paulo@0
|
80 int nw, nh;
|
paulo@0
|
81 XEvent ev;
|
paulo@0
|
82
|
paulo@0
|
83 ocx = c->x;
|
paulo@0
|
84 ocy = c->y;
|
paulo@0
|
85 if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
|
paulo@0
|
86 None, cursor[CurResize], CurrentTime) != GrabSuccess)
|
paulo@0
|
87 return;
|
paulo@0
|
88 c->ismax = False;
|
paulo@0
|
89 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->border - 1, c->h + c->border - 1);
|
paulo@0
|
90 for(;;) {
|
paulo@0
|
91 XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask , &ev);
|
paulo@0
|
92 switch(ev.type) {
|
paulo@0
|
93 case ButtonRelease:
|
paulo@0
|
94 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0,
|
paulo@0
|
95 c->w + c->border - 1, c->h + c->border - 1);
|
paulo@0
|
96 XUngrabPointer(dpy, CurrentTime);
|
paulo@0
|
97 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
|
paulo@0
|
98 return;
|
paulo@0
|
99 case ConfigureRequest:
|
paulo@0
|
100 case Expose:
|
paulo@0
|
101 case MapRequest:
|
paulo@0
|
102 handler[ev.type](&ev);
|
paulo@0
|
103 break;
|
paulo@0
|
104 case MotionNotify:
|
paulo@0
|
105 XSync(dpy, False);
|
paulo@0
|
106 if((nw = ev.xmotion.x - ocx - 2 * c->border + 1) <= 0)
|
paulo@0
|
107 nw = 1;
|
paulo@0
|
108 if((nh = ev.xmotion.y - ocy - 2 * c->border + 1) <= 0)
|
paulo@0
|
109 nh = 1;
|
paulo@0
|
110 resize(c, c->x, c->y, nw, nh, True);
|
paulo@0
|
111 break;
|
paulo@0
|
112 }
|
paulo@0
|
113 }
|
paulo@0
|
114 }
|
paulo@0
|
115
|
paulo@0
|
116 static void
|
paulo@0
|
117 buttonpress(XEvent *e) {
|
paulo@0
|
118 int x;
|
paulo@0
|
119 Arg a;
|
paulo@0
|
120 Client *c;
|
paulo@0
|
121 XButtonPressedEvent *ev = &e->xbutton;
|
paulo@0
|
122
|
paulo@0
|
123 if(barwin == ev->window) {
|
paulo@0
|
124 x = 0;
|
paulo@0
|
125 for(a.i = 0; a.i < ntags; a.i++) {
|
paulo@0
|
126 x += textw(tags[a.i]);
|
paulo@0
|
127 if(ev->x < x) {
|
paulo@0
|
128 if(ev->button == Button1) {
|
paulo@0
|
129 if(ev->state & MODKEY)
|
paulo@0
|
130 tag(&a);
|
paulo@0
|
131 else
|
paulo@0
|
132 view(&a);
|
paulo@0
|
133 }
|
paulo@0
|
134 else if(ev->button == Button3) {
|
paulo@0
|
135 if(ev->state & MODKEY)
|
paulo@0
|
136 toggletag(&a);
|
paulo@0
|
137 else
|
paulo@0
|
138 toggleview(&a);
|
paulo@0
|
139 }
|
paulo@0
|
140 return;
|
paulo@0
|
141 }
|
paulo@0
|
142 }
|
paulo@0
|
143 if(ev->x < x + blw)
|
paulo@0
|
144 switch(ev->button) {
|
paulo@0
|
145 case Button1:
|
paulo@0
|
146 a.i = -1;
|
paulo@0
|
147 setlayout(&a);
|
paulo@0
|
148 break;
|
pang@2
|
149 case Button3:
|
pang@2
|
150 a.i = -2;
|
pang@2
|
151 setlayout(&a);
|
pang@2
|
152 break;
|
paulo@0
|
153 case Button4:
|
paulo@0
|
154 a.i = 1;
|
paulo@0
|
155 incnmaster(&a);
|
paulo@0
|
156 break;
|
paulo@0
|
157 case Button5:
|
paulo@0
|
158 a.i = -1;
|
paulo@0
|
159 incnmaster(&a);
|
paulo@0
|
160 break;
|
paulo@0
|
161 }
|
paulo@0
|
162 if(ev->x > x + blw)
|
paulo@0
|
163 switch(ev->button) {
|
paulo@3
|
164 case Button1: zoom(NULL); break;
|
paulo@3
|
165 case Button2: toggleversatile(NULL); break;
|
paulo@3
|
166 case Button3: killclient(NULL); break;
|
paulo@3
|
167 case Button4: pushup(NULL); break;
|
paulo@3
|
168 case Button5: pushdown(NULL); break;
|
paulo@3
|
169 }
|
paulo@3
|
170 }
|
paulo@3
|
171 else if(tbarwin == ev->window) {
|
paulo@3
|
172 int i, w;
|
paulo@4
|
173 for(i=0, c = clients; c; c = c->next) {
|
paulo@4
|
174 if(isvisible(c))
|
paulo@4
|
175 i++;
|
paulo@4
|
176 }
|
paulo@4
|
177 if(!i || i >= MAX_TASKS)
|
paulo@4
|
178 return;
|
paulo@4
|
179 else
|
paulo@4
|
180 w = sw/i;
|
paulo@3
|
181 switch(ev->button) {
|
paulo@3
|
182 case Button4: focusprev(NULL); return; break;
|
paulo@3
|
183 case Button5: focusnext(NULL); return; break;
|
paulo@0
|
184 }
|
paulo@3
|
185 for(i=1, c = clients; c && i*w<=sw; c = c->next, i++) {
|
paulo@3
|
186 for(; c && !isvisible(c); c = c->next);
|
paulo@3
|
187 if(i*w > ev->x) {
|
paulo@3
|
188 switch(ev->button) {
|
paulo@3
|
189 case Button1: focus(c); restack(); break;
|
paulo@3
|
190 case Button3: focus(c); zoom(NULL); break;
|
paulo@3
|
191 }
|
paulo@3
|
192 break;
|
paulo@3
|
193 }
|
paulo@3
|
194 }
|
paulo@3
|
195 }
|
paulo@0
|
196 else if((c = getclient(ev->window))) {
|
paulo@0
|
197 focus(c);
|
paulo@0
|
198 if(CLEANMASK(ev->state) != MODKEY)
|
paulo@0
|
199 return;
|
paulo@0
|
200 if(ev->button == Button1 && (lt->arrange == versatile || c->isversatile)) {
|
paulo@0
|
201 restack();
|
paulo@0
|
202 movemouse(c);
|
paulo@0
|
203 }
|
paulo@0
|
204 else if(ev->button == Button2)
|
paulo@0
|
205 zoom(NULL);
|
paulo@0
|
206 else if(ev->button == Button3
|
paulo@0
|
207 && (lt->arrange == versatile || c->isversatile) && !c->isfixed)
|
paulo@0
|
208 {
|
paulo@0
|
209 restack();
|
paulo@0
|
210 resizemouse(c);
|
paulo@0
|
211 }
|
paulo@0
|
212 }
|
paulo@0
|
213 }
|
paulo@0
|
214
|
paulo@0
|
215 static void
|
paulo@0
|
216 configurerequest(XEvent *e) {
|
paulo@0
|
217 Client *c;
|
paulo@0
|
218 XConfigureRequestEvent *ev = &e->xconfigurerequest;
|
paulo@0
|
219 XWindowChanges wc;
|
paulo@0
|
220
|
paulo@0
|
221 if((c = getclient(ev->window))) {
|
paulo@0
|
222 c->ismax = False;
|
paulo@0
|
223 if(ev->value_mask & CWBorderWidth)
|
paulo@0
|
224 c->border = ev->border_width;
|
paulo@0
|
225 if(c->isfixed || c->isversatile || (lt->arrange == versatile)) {
|
paulo@0
|
226 if(ev->value_mask & CWX)
|
paulo@0
|
227 c->x = ev->x;
|
paulo@0
|
228 if(ev->value_mask & CWY)
|
paulo@0
|
229 c->y = ev->y;
|
paulo@0
|
230 if(ev->value_mask & CWWidth)
|
paulo@0
|
231 c->w = ev->width;
|
paulo@0
|
232 if(ev->value_mask & CWHeight)
|
paulo@0
|
233 c->h = ev->height;
|
paulo@0
|
234 if((ev->value_mask & (CWX | CWY))
|
paulo@0
|
235 && !(ev->value_mask & (CWWidth | CWHeight)))
|
paulo@0
|
236 configure(c);
|
paulo@0
|
237 if(isvisible(c))
|
paulo@0
|
238 /* XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); */
|
paulo@0
|
239 resize(c, c->x, c->y, c->w, c->h, False);
|
paulo@0
|
240 }
|
paulo@0
|
241 else
|
paulo@0
|
242 configure(c);
|
paulo@0
|
243 }
|
paulo@0
|
244 else {
|
paulo@0
|
245 wc.x = ev->x;
|
paulo@0
|
246 wc.y = ev->y;
|
paulo@0
|
247 wc.width = ev->width;
|
paulo@0
|
248 wc.height = ev->height;
|
paulo@0
|
249 wc.border_width = ev->border_width;
|
paulo@0
|
250 wc.sibling = ev->above;
|
paulo@0
|
251 wc.stack_mode = ev->detail;
|
paulo@0
|
252 XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
|
paulo@0
|
253 }
|
paulo@0
|
254 XSync(dpy, False);
|
paulo@0
|
255 }
|
paulo@0
|
256
|
paulo@0
|
257 static void
|
paulo@0
|
258 destroynotify(XEvent *e) {
|
paulo@0
|
259 Client *c;
|
paulo@0
|
260 XDestroyWindowEvent *ev = &e->xdestroywindow;
|
paulo@0
|
261
|
paulo@0
|
262 if((c = getclient(ev->window)))
|
paulo@0
|
263 unmanage(c);
|
paulo@0
|
264 }
|
paulo@0
|
265
|
paulo@0
|
266 static void
|
paulo@0
|
267 enternotify(XEvent *e) {
|
paulo@0
|
268 Client *c;
|
paulo@0
|
269 XCrossingEvent *ev = &e->xcrossing;
|
paulo@0
|
270
|
paulo@0
|
271 if(ev->mode != NotifyNormal || ev->detail == NotifyInferior)
|
paulo@0
|
272 return;
|
paulo@3
|
273 if(!CLICK_TO_FOCUS && (c = getclient(ev->window)) && isvisible(c))
|
paulo@0
|
274 focus(c);
|
paulo@0
|
275 else if(ev->window == root) {
|
paulo@0
|
276 selscreen = True;
|
paulo@0
|
277 for(c = stack; c && !isvisible(c); c = c->snext);
|
paulo@0
|
278 focus(c);
|
paulo@0
|
279 }
|
paulo@0
|
280 }
|
paulo@0
|
281
|
paulo@0
|
282 static void
|
paulo@0
|
283 expose(XEvent *e) {
|
paulo@0
|
284 XExposeEvent *ev = &e->xexpose;
|
paulo@0
|
285
|
paulo@0
|
286 if(ev->count == 0) {
|
paulo@3
|
287 if(barwin == ev->window || tbarwin == ev->window)
|
paulo@0
|
288 drawstatus();
|
paulo@0
|
289 }
|
paulo@0
|
290 }
|
paulo@0
|
291
|
paulo@0
|
292 static void
|
paulo@6
|
293 defkeypress(XEvent *e) {
|
paulo@0
|
294 static unsigned int len = sizeof key / sizeof key[0];
|
paulo@0
|
295 unsigned int i;
|
paulo@0
|
296 KeySym keysym;
|
paulo@0
|
297 XKeyEvent *ev = &e->xkey;
|
paulo@0
|
298
|
paulo@0
|
299 keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
|
paulo@0
|
300 for(i = 0; i < len; i++)
|
paulo@0
|
301 if(keysym == key[i].keysym
|
paulo@0
|
302 && CLEANMASK(key[i].mod) == CLEANMASK(ev->state))
|
paulo@0
|
303 {
|
paulo@0
|
304 if(key[i].func)
|
paulo@0
|
305 key[i].func(&key[i].arg);
|
paulo@0
|
306 }
|
paulo@0
|
307 }
|
paulo@0
|
308
|
paulo@0
|
309 static void
|
paulo@0
|
310 leavenotify(XEvent *e) {
|
paulo@0
|
311 XCrossingEvent *ev = &e->xcrossing;
|
paulo@0
|
312
|
paulo@0
|
313 if((ev->window == root) && !ev->same_screen) {
|
paulo@0
|
314 selscreen = False;
|
paulo@0
|
315 focus(NULL);
|
paulo@0
|
316 }
|
paulo@0
|
317 }
|
paulo@0
|
318
|
paulo@0
|
319 static void
|
paulo@0
|
320 mappingnotify(XEvent *e) {
|
paulo@0
|
321 XMappingEvent *ev = &e->xmapping;
|
paulo@0
|
322
|
paulo@0
|
323 XRefreshKeyboardMapping(ev);
|
paulo@0
|
324 if(ev->request == MappingKeyboard)
|
paulo@0
|
325 grabkeys();
|
paulo@0
|
326 }
|
paulo@0
|
327
|
paulo@0
|
328 static void
|
paulo@0
|
329 maprequest(XEvent *e) {
|
paulo@0
|
330 static XWindowAttributes wa;
|
paulo@0
|
331 XMapRequestEvent *ev = &e->xmaprequest;
|
paulo@0
|
332
|
paulo@0
|
333 if(!XGetWindowAttributes(dpy, ev->window, &wa))
|
paulo@0
|
334 return;
|
paulo@0
|
335 if(wa.override_redirect)
|
paulo@0
|
336 return;
|
paulo@0
|
337 if(!getclient(ev->window))
|
paulo@0
|
338 manage(ev->window, &wa);
|
paulo@0
|
339 }
|
paulo@0
|
340
|
paulo@0
|
341 static void
|
paulo@0
|
342 propertynotify(XEvent *e) {
|
paulo@0
|
343 Client *c;
|
paulo@0
|
344 Window trans;
|
paulo@0
|
345 XPropertyEvent *ev = &e->xproperty;
|
paulo@0
|
346
|
paulo@0
|
347 if(ev->state == PropertyDelete)
|
paulo@0
|
348 return; /* ignore */
|
paulo@0
|
349 if((c = getclient(ev->window))) {
|
paulo@0
|
350 switch (ev->atom) {
|
paulo@0
|
351 default: break;
|
paulo@0
|
352 case XA_WM_TRANSIENT_FOR:
|
paulo@0
|
353 XGetTransientForHint(dpy, c->win, &trans);
|
paulo@0
|
354 if(!c->isversatile && (c->isversatile = (getclient(trans) != NULL)))
|
paulo@0
|
355 lt->arrange();
|
paulo@0
|
356 break;
|
paulo@0
|
357 case XA_WM_NORMAL_HINTS:
|
paulo@0
|
358 updatesizehints(c);
|
paulo@0
|
359 break;
|
paulo@0
|
360 }
|
paulo@0
|
361 if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
|
paulo@0
|
362 updatetitle(c);
|
paulo@0
|
363 if(c == sel)
|
paulo@0
|
364 drawstatus();
|
paulo@0
|
365 }
|
paulo@0
|
366 }
|
paulo@0
|
367 }
|
paulo@0
|
368
|
paulo@0
|
369 static void
|
paulo@0
|
370 unmapnotify(XEvent *e) {
|
paulo@0
|
371 Client *c;
|
paulo@0
|
372 XUnmapEvent *ev = &e->xunmap;
|
paulo@0
|
373
|
paulo@0
|
374 if((c = getclient(ev->window)))
|
paulo@0
|
375 unmanage(c);
|
paulo@0
|
376 }
|
paulo@0
|
377
|
paulo@6
|
378 typedef struct {
|
paulo@6
|
379 unsigned int mod[4];
|
paulo@6
|
380 KeySym keysym[4];
|
paulo@6
|
381 void (*func)(Arg *arg);
|
paulo@6
|
382 Arg arg;
|
paulo@6
|
383 } Command;
|
paulo@6
|
384
|
paulo@6
|
385 CMDKEYS
|
paulo@6
|
386 COMMANDS
|
paulo@6
|
387
|
paulo@6
|
388 void
|
paulo@6
|
389 keypress(XEvent *e) {
|
paulo@6
|
390 unsigned int i, j;
|
paulo@6
|
391 Arg a = {0};
|
paulo@6
|
392 Bool ismatch = False, maybematch = False;
|
paulo@6
|
393 KeySym keysym;
|
paulo@6
|
394 XKeyEvent *ev;
|
paulo@6
|
395
|
paulo@6
|
396 if(keymode == INSERTMODE)
|
paulo@6
|
397 defkeypress(e);
|
paulo@6
|
398 else if(keymode == COMMANDMODE) {
|
paulo@6
|
399 ev = &e->xkey;
|
paulo@6
|
400 keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
|
paulo@6
|
401 if(keysym < XK_Shift_L || keysym > XK_Hyper_R) {
|
paulo@6
|
402 for(j = 0; j < LENGTH(cmdkeysym); j++)
|
paulo@6
|
403 if(cmdkeysym[j] == 0) {
|
paulo@6
|
404 cmdkeysym[j] = keysym;
|
paulo@6
|
405 cmdmod[j] = ev->state;
|
paulo@6
|
406 break;
|
paulo@6
|
407 }
|
paulo@6
|
408 for(i = 0; i < LENGTH(commands); i++) {
|
paulo@6
|
409 for(j = 0; j < LENGTH(cmdkeysym); j++) {
|
paulo@6
|
410 if(cmdkeysym[j] == commands[i].keysym[j]
|
paulo@6
|
411 && CLEANMASK(cmdmod[j]) == CLEANMASK(commands[i].mod[j]))
|
paulo@6
|
412 ismatch = True;
|
paulo@6
|
413 else if(cmdkeysym[j] == 0
|
paulo@6
|
414 && cmdmod[j] == 0) {
|
paulo@6
|
415 ismatch = False;
|
paulo@6
|
416 maybematch = True;
|
paulo@6
|
417 break;
|
paulo@6
|
418 } else {
|
paulo@6
|
419 ismatch = False;
|
paulo@6
|
420 break;
|
paulo@6
|
421 }
|
paulo@6
|
422 }
|
paulo@6
|
423 if(ismatch) {
|
paulo@6
|
424 if(commands[i].func)
|
paulo@6
|
425 commands[i].func(&(commands[i].arg));
|
paulo@6
|
426 clearcmd(&a);
|
paulo@6
|
427 break;
|
paulo@6
|
428 }
|
paulo@6
|
429
|
paulo@6
|
430 }
|
paulo@6
|
431 if(!maybematch)
|
paulo@6
|
432 clearcmd(&a);
|
paulo@6
|
433 if(!ismatch) {
|
paulo@6
|
434 for(i = 0; i < LENGTH(cmdkeys); i++)
|
paulo@6
|
435 if(keysym == cmdkeys[i].keysym
|
paulo@6
|
436 && CLEANMASK(cmdkeys[i].mod) == CLEANMASK(ev->state)
|
paulo@6
|
437 && cmdkeys[i].func) {
|
paulo@6
|
438 cmdkeys[i].func(&(cmdkeys[i].arg));
|
paulo@6
|
439 ismatch = True;
|
paulo@6
|
440 break;
|
paulo@6
|
441 }
|
paulo@6
|
442 }
|
paulo@6
|
443 }
|
paulo@6
|
444 }
|
paulo@6
|
445 }
|
paulo@6
|
446
|
paulo@0
|
447 /* extern */
|
paulo@0
|
448
|
paulo@0
|
449 void (*handler[LASTEvent]) (XEvent *) = {
|
paulo@0
|
450 [ButtonPress] = buttonpress,
|
paulo@0
|
451 [ConfigureRequest] = configurerequest,
|
paulo@0
|
452 [DestroyNotify] = destroynotify,
|
paulo@0
|
453 [EnterNotify] = enternotify,
|
paulo@0
|
454 [LeaveNotify] = leavenotify,
|
paulo@0
|
455 [Expose] = expose,
|
paulo@0
|
456 [KeyPress] = keypress,
|
paulo@0
|
457 [MappingNotify] = mappingnotify,
|
paulo@0
|
458 [MapRequest] = maprequest,
|
paulo@0
|
459 [PropertyNotify] = propertynotify,
|
paulo@0
|
460 [UnmapNotify] = unmapnotify
|
paulo@0
|
461 };
|
paulo@0
|
462
|
paulo@0
|
463 void
|
paulo@6
|
464 grabdefkeys(void) {
|
paulo@0
|
465 static unsigned int len = sizeof key / sizeof key[0];
|
paulo@0
|
466 unsigned int i;
|
paulo@0
|
467 KeyCode code;
|
paulo@0
|
468
|
paulo@0
|
469 XUngrabKey(dpy, AnyKey, AnyModifier, root);
|
paulo@0
|
470 for(i = 0; i < len; i++) {
|
paulo@0
|
471 code = XKeysymToKeycode(dpy, key[i].keysym);
|
paulo@0
|
472 XGrabKey(dpy, code, key[i].mod, root, True,
|
paulo@0
|
473 GrabModeAsync, GrabModeAsync);
|
paulo@0
|
474 XGrabKey(dpy, code, key[i].mod | LockMask, root, True,
|
paulo@0
|
475 GrabModeAsync, GrabModeAsync);
|
paulo@0
|
476 XGrabKey(dpy, code, key[i].mod | numlockmask, root, True,
|
paulo@0
|
477 GrabModeAsync, GrabModeAsync);
|
paulo@0
|
478 XGrabKey(dpy, code, key[i].mod | numlockmask | LockMask, root, True,
|
paulo@0
|
479 GrabModeAsync, GrabModeAsync);
|
paulo@0
|
480 }
|
paulo@0
|
481 }
|
paulo@6
|
482
|
paulo@6
|
483 void
|
paulo@6
|
484 clearcmd(Arg *arg) {
|
paulo@6
|
485 unsigned int i;
|
paulo@6
|
486
|
paulo@6
|
487 for(i = 0; i < LENGTH(cmdkeysym); i++) {
|
paulo@6
|
488 cmdkeysym[i] = 0;
|
paulo@6
|
489 cmdmod[i] = 0;
|
paulo@6
|
490 }
|
paulo@6
|
491 }
|
paulo@6
|
492
|
paulo@6
|
493 void
|
paulo@6
|
494 grabkeys(void) {
|
paulo@6
|
495 if(keymode == INSERTMODE) {
|
paulo@6
|
496 XUngrabKeyboard(dpy, CurrentTime);
|
paulo@6
|
497 grabdefkeys();
|
paulo@6
|
498 } else if(keymode == COMMANDMODE) {
|
paulo@6
|
499 XUngrabKey(dpy, AnyKey, AnyModifier, root);
|
paulo@6
|
500 //XGrabKey(dpy, AnyKey, AnyModifier, root,
|
paulo@6
|
501 // True, GrabModeAsync, GrabModeAsync);
|
paulo@6
|
502 XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime);
|
paulo@6
|
503 }
|
paulo@6
|
504 }
|
paulo@6
|
505
|
paulo@6
|
506 void
|
paulo@6
|
507 setkeymode(Arg *arg) {
|
paulo@6
|
508 Arg a = {0};
|
paulo@6
|
509
|
paulo@6
|
510 if(!arg)
|
paulo@6
|
511 return;
|
paulo@6
|
512 keymode = arg->i;
|
paulo@6
|
513 clearcmd(&a);
|
paulo@6
|
514 grabkeys();
|
paulo@6
|
515 drawstatus();
|
paulo@6
|
516 }
|
paulo@6
|
517
|
paulo@6
|
518 unsigned int
|
paulo@6
|
519 getkeymode(void) {
|
paulo@6
|
520 return keymode;
|
paulo@6
|
521 }
|
paulo@6
|
522
|
paulo@6
|
523 void
|
paulo@6
|
524 func_insert(void (*argfunc)(Arg *), Arg *arg) {
|
paulo@6
|
525 Arg a = { .i = INSERTMODE };
|
paulo@6
|
526 argfunc(arg);
|
paulo@6
|
527 setkeymode(&a);
|
paulo@6
|
528 }
|