dwm-meillo

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