Mercurial > hg > index.fcgi > dwm > dwm-3.6.1-12pba
diff event.c @ 0:7024076fa948
initial add
author | paulo@localhost |
---|---|
date | Sun, 22 Mar 2009 23:26:35 -0700 |
parents | |
children | de6bb7885c97 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/event.c Sun Mar 22 23:26:35 2009 -0700 1.3 @@ -0,0 +1,380 @@ 1.4 +/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com> 1.5 + * See LICENSE file for license details. 1.6 + */ 1.7 +#include "dwm.h" 1.8 +#include <stdlib.h> 1.9 +#include <X11/keysym.h> 1.10 +#include <X11/Xatom.h> 1.11 + 1.12 +/* static */ 1.13 + 1.14 +typedef struct { 1.15 + unsigned long mod; 1.16 + KeySym keysym; 1.17 + void (*func)(Arg *arg); 1.18 + Arg arg; 1.19 +} Key; 1.20 + 1.21 +KEYS 1.22 + 1.23 +#define CLEANMASK(mask) (mask & ~(numlockmask | LockMask)) 1.24 +#define MOUSEMASK (BUTTONMASK | PointerMotionMask) 1.25 + 1.26 +static Client * 1.27 +getclient(Window w) { 1.28 + Client *c; 1.29 + 1.30 + for(c = clients; c && c->win != w; c = c->next); 1.31 + return c; 1.32 +} 1.33 + 1.34 +static void 1.35 +movemouse(Client *c) { 1.36 + int x1, y1, ocx, ocy, di, nx, ny; 1.37 + unsigned int dui; 1.38 + Window dummy; 1.39 + XEvent ev; 1.40 + 1.41 + ocx = nx = c->x; 1.42 + ocy = ny = c->y; 1.43 + if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, 1.44 + None, cursor[CurMove], CurrentTime) != GrabSuccess) 1.45 + return; 1.46 + c->ismax = False; 1.47 + XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui); 1.48 + for(;;) { 1.49 + XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask, &ev); 1.50 + switch (ev.type) { 1.51 + case ButtonRelease: 1.52 + XUngrabPointer(dpy, CurrentTime); 1.53 + return; 1.54 + case ConfigureRequest: 1.55 + case Expose: 1.56 + case MapRequest: 1.57 + handler[ev.type](&ev); 1.58 + break; 1.59 + case MotionNotify: 1.60 + XSync(dpy, False); 1.61 + nx = ocx + (ev.xmotion.x - x1); 1.62 + ny = ocy + (ev.xmotion.y - y1); 1.63 + if(abs(wax + nx) < SNAP) 1.64 + nx = wax; 1.65 + else if(abs((wax + waw) - (nx + c->w + 2 * c->border)) < SNAP) 1.66 + nx = wax + waw - c->w - 2 * c->border; 1.67 + if(abs(way - ny) < SNAP) 1.68 + ny = way; 1.69 + else if(abs((way + wah) - (ny + c->h + 2 * c->border)) < SNAP) 1.70 + ny = way + wah - c->h - 2 * c->border; 1.71 + resize(c, nx, ny, c->w, c->h, False); 1.72 + break; 1.73 + } 1.74 + } 1.75 +} 1.76 + 1.77 +static void 1.78 +resizemouse(Client *c) { 1.79 + int ocx, ocy; 1.80 + int nw, nh; 1.81 + XEvent ev; 1.82 + 1.83 + ocx = c->x; 1.84 + ocy = c->y; 1.85 + if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, 1.86 + None, cursor[CurResize], CurrentTime) != GrabSuccess) 1.87 + return; 1.88 + c->ismax = False; 1.89 + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->border - 1, c->h + c->border - 1); 1.90 + for(;;) { 1.91 + XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask , &ev); 1.92 + switch(ev.type) { 1.93 + case ButtonRelease: 1.94 + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, 1.95 + c->w + c->border - 1, c->h + c->border - 1); 1.96 + XUngrabPointer(dpy, CurrentTime); 1.97 + while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); 1.98 + return; 1.99 + case ConfigureRequest: 1.100 + case Expose: 1.101 + case MapRequest: 1.102 + handler[ev.type](&ev); 1.103 + break; 1.104 + case MotionNotify: 1.105 + XSync(dpy, False); 1.106 + if((nw = ev.xmotion.x - ocx - 2 * c->border + 1) <= 0) 1.107 + nw = 1; 1.108 + if((nh = ev.xmotion.y - ocy - 2 * c->border + 1) <= 0) 1.109 + nh = 1; 1.110 + resize(c, c->x, c->y, nw, nh, True); 1.111 + break; 1.112 + } 1.113 + } 1.114 +} 1.115 + 1.116 +static void 1.117 +buttonpress(XEvent *e) { 1.118 + int x; 1.119 + Arg a; 1.120 + Client *c; 1.121 + XButtonPressedEvent *ev = &e->xbutton; 1.122 + 1.123 + if(barwin == ev->window) { 1.124 + x = 0; 1.125 + for(a.i = 0; a.i < ntags; a.i++) { 1.126 + x += textw(tags[a.i]); 1.127 + if(ev->x < x) { 1.128 + if(ev->button == Button1) { 1.129 + if(ev->state & MODKEY) 1.130 + tag(&a); 1.131 + else 1.132 + view(&a); 1.133 + } 1.134 + else if(ev->button == Button3) { 1.135 + if(ev->state & MODKEY) 1.136 + toggletag(&a); 1.137 + else 1.138 + toggleview(&a); 1.139 + } 1.140 + return; 1.141 + } 1.142 + } 1.143 + if(ev->x < x + blw) 1.144 + switch(ev->button) { 1.145 + case Button1: 1.146 + a.i = -1; 1.147 + setlayout(&a); 1.148 + break; 1.149 + case Button4: 1.150 + a.i = 1; 1.151 + incnmaster(&a); 1.152 + break; 1.153 + case Button5: 1.154 + a.i = -1; 1.155 + incnmaster(&a); 1.156 + break; 1.157 + } 1.158 + if(ev->x > x + blw) 1.159 + switch(ev->button) { 1.160 + case Button1: zoom(NULL); break; 1.161 + case Button2: toggleversatile(NULL); break; 1.162 + case Button3: killclient(NULL); break; 1.163 + case Button4: focusprev(NULL); break; 1.164 + case Button5: focusnext(NULL); break; 1.165 + } 1.166 + } 1.167 + else if((c = getclient(ev->window))) { 1.168 + focus(c); 1.169 + if(CLEANMASK(ev->state) != MODKEY) 1.170 + return; 1.171 + if(ev->button == Button1 && (lt->arrange == versatile || c->isversatile)) { 1.172 + restack(); 1.173 + movemouse(c); 1.174 + } 1.175 + else if(ev->button == Button2) 1.176 + zoom(NULL); 1.177 + else if(ev->button == Button3 1.178 + && (lt->arrange == versatile || c->isversatile) && !c->isfixed) 1.179 + { 1.180 + restack(); 1.181 + resizemouse(c); 1.182 + } 1.183 + } 1.184 +} 1.185 + 1.186 +static void 1.187 +configurerequest(XEvent *e) { 1.188 + Client *c; 1.189 + XConfigureRequestEvent *ev = &e->xconfigurerequest; 1.190 + XWindowChanges wc; 1.191 + 1.192 + if((c = getclient(ev->window))) { 1.193 + c->ismax = False; 1.194 + if(ev->value_mask & CWBorderWidth) 1.195 + c->border = ev->border_width; 1.196 + if(c->isfixed || c->isversatile || (lt->arrange == versatile)) { 1.197 + if(ev->value_mask & CWX) 1.198 + c->x = ev->x; 1.199 + if(ev->value_mask & CWY) 1.200 + c->y = ev->y; 1.201 + if(ev->value_mask & CWWidth) 1.202 + c->w = ev->width; 1.203 + if(ev->value_mask & CWHeight) 1.204 + c->h = ev->height; 1.205 + if((ev->value_mask & (CWX | CWY)) 1.206 + && !(ev->value_mask & (CWWidth | CWHeight))) 1.207 + configure(c); 1.208 + if(isvisible(c)) 1.209 + /* XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); */ 1.210 + resize(c, c->x, c->y, c->w, c->h, False); 1.211 + } 1.212 + else 1.213 + configure(c); 1.214 + } 1.215 + else { 1.216 + wc.x = ev->x; 1.217 + wc.y = ev->y; 1.218 + wc.width = ev->width; 1.219 + wc.height = ev->height; 1.220 + wc.border_width = ev->border_width; 1.221 + wc.sibling = ev->above; 1.222 + wc.stack_mode = ev->detail; 1.223 + XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); 1.224 + } 1.225 + XSync(dpy, False); 1.226 +} 1.227 + 1.228 +static void 1.229 +destroynotify(XEvent *e) { 1.230 + Client *c; 1.231 + XDestroyWindowEvent *ev = &e->xdestroywindow; 1.232 + 1.233 + if((c = getclient(ev->window))) 1.234 + unmanage(c); 1.235 +} 1.236 + 1.237 +static void 1.238 +enternotify(XEvent *e) { 1.239 + Client *c; 1.240 + XCrossingEvent *ev = &e->xcrossing; 1.241 + 1.242 + if(ev->mode != NotifyNormal || ev->detail == NotifyInferior) 1.243 + return; 1.244 + if((c = getclient(ev->window)) && isvisible(c)) 1.245 + focus(c); 1.246 + else if(ev->window == root) { 1.247 + selscreen = True; 1.248 + for(c = stack; c && !isvisible(c); c = c->snext); 1.249 + focus(c); 1.250 + } 1.251 +} 1.252 + 1.253 +static void 1.254 +expose(XEvent *e) { 1.255 + XExposeEvent *ev = &e->xexpose; 1.256 + 1.257 + if(ev->count == 0) { 1.258 + if(barwin == ev->window) 1.259 + drawstatus(); 1.260 + } 1.261 +} 1.262 + 1.263 +static void 1.264 +keypress(XEvent *e) { 1.265 + static unsigned int len = sizeof key / sizeof key[0]; 1.266 + unsigned int i; 1.267 + KeySym keysym; 1.268 + XKeyEvent *ev = &e->xkey; 1.269 + 1.270 + keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); 1.271 + for(i = 0; i < len; i++) 1.272 + if(keysym == key[i].keysym 1.273 + && CLEANMASK(key[i].mod) == CLEANMASK(ev->state)) 1.274 + { 1.275 + if(key[i].func) 1.276 + key[i].func(&key[i].arg); 1.277 + } 1.278 +} 1.279 + 1.280 +static void 1.281 +leavenotify(XEvent *e) { 1.282 + XCrossingEvent *ev = &e->xcrossing; 1.283 + 1.284 + if((ev->window == root) && !ev->same_screen) { 1.285 + selscreen = False; 1.286 + focus(NULL); 1.287 + } 1.288 +} 1.289 + 1.290 +static void 1.291 +mappingnotify(XEvent *e) { 1.292 + XMappingEvent *ev = &e->xmapping; 1.293 + 1.294 + XRefreshKeyboardMapping(ev); 1.295 + if(ev->request == MappingKeyboard) 1.296 + grabkeys(); 1.297 +} 1.298 + 1.299 +static void 1.300 +maprequest(XEvent *e) { 1.301 + static XWindowAttributes wa; 1.302 + XMapRequestEvent *ev = &e->xmaprequest; 1.303 + 1.304 + if(!XGetWindowAttributes(dpy, ev->window, &wa)) 1.305 + return; 1.306 + if(wa.override_redirect) 1.307 + return; 1.308 + if(!getclient(ev->window)) 1.309 + manage(ev->window, &wa); 1.310 +} 1.311 + 1.312 +static void 1.313 +propertynotify(XEvent *e) { 1.314 + Client *c; 1.315 + Window trans; 1.316 + XPropertyEvent *ev = &e->xproperty; 1.317 + 1.318 + if(ev->state == PropertyDelete) 1.319 + return; /* ignore */ 1.320 + if((c = getclient(ev->window))) { 1.321 + switch (ev->atom) { 1.322 + default: break; 1.323 + case XA_WM_TRANSIENT_FOR: 1.324 + XGetTransientForHint(dpy, c->win, &trans); 1.325 + if(!c->isversatile && (c->isversatile = (getclient(trans) != NULL))) 1.326 + lt->arrange(); 1.327 + break; 1.328 + case XA_WM_NORMAL_HINTS: 1.329 + updatesizehints(c); 1.330 + break; 1.331 + } 1.332 + if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { 1.333 + updatetitle(c); 1.334 + if(c == sel) 1.335 + drawstatus(); 1.336 + } 1.337 + } 1.338 +} 1.339 + 1.340 +static void 1.341 +unmapnotify(XEvent *e) { 1.342 + Client *c; 1.343 + XUnmapEvent *ev = &e->xunmap; 1.344 + 1.345 + if((c = getclient(ev->window))) 1.346 + unmanage(c); 1.347 +} 1.348 + 1.349 +/* extern */ 1.350 + 1.351 +void (*handler[LASTEvent]) (XEvent *) = { 1.352 + [ButtonPress] = buttonpress, 1.353 + [ConfigureRequest] = configurerequest, 1.354 + [DestroyNotify] = destroynotify, 1.355 + [EnterNotify] = enternotify, 1.356 + [LeaveNotify] = leavenotify, 1.357 + [Expose] = expose, 1.358 + [KeyPress] = keypress, 1.359 + [MappingNotify] = mappingnotify, 1.360 + [MapRequest] = maprequest, 1.361 + [PropertyNotify] = propertynotify, 1.362 + [UnmapNotify] = unmapnotify 1.363 +}; 1.364 + 1.365 +void 1.366 +grabkeys(void) { 1.367 + static unsigned int len = sizeof key / sizeof key[0]; 1.368 + unsigned int i; 1.369 + KeyCode code; 1.370 + 1.371 + XUngrabKey(dpy, AnyKey, AnyModifier, root); 1.372 + for(i = 0; i < len; i++) { 1.373 + code = XKeysymToKeycode(dpy, key[i].keysym); 1.374 + XGrabKey(dpy, code, key[i].mod, root, True, 1.375 + GrabModeAsync, GrabModeAsync); 1.376 + XGrabKey(dpy, code, key[i].mod | LockMask, root, True, 1.377 + GrabModeAsync, GrabModeAsync); 1.378 + XGrabKey(dpy, code, key[i].mod | numlockmask, root, True, 1.379 + GrabModeAsync, GrabModeAsync); 1.380 + XGrabKey(dpy, code, key[i].mod | numlockmask | LockMask, root, True, 1.381 + GrabModeAsync, GrabModeAsync); 1.382 + } 1.383 +}