annotate event.c @ 3:faa4cb9d7bd6

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