X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=event.c;h=bdf4071299b4eaa30729c466119db739cdd09332;hb=d934296476be7345842fec1a2630d1752c704078;hp=b027a3eee03ec4e1c019c912d80c43d7066f6840;hpb=a1d0f819661f2be48f7a03ddd001f2a1a8f325e4;p=dwm.git diff --git a/event.c b/event.c index b027a3e..ce23e41 100644 --- a/event.c +++ b/event.c @@ -1,109 +1,236 @@ -/* - * (C)opyright MMVI Anselm R. Garbe - * See LICENSE file for license details. - */ - -#include +/* © 2006-2007 Anselm R. Garbe + * © 2006-2007 Sander van Dijk + * © 2006-2007 Jukka Salmi + * © 2007 Premysl Hruby + * © 2007 Szabolcs Nagy + * See LICENSE file for license details. */ +#include "dwm.h" #include #include -#include #include #include -#include "dwm.h" +/* static */ -/* local functions */ -static void buttonpress(XEvent *e); -static void configurerequest(XEvent *e); -static void destroynotify(XEvent *e); -static void enternotify(XEvent *e); -static void leavenotify(XEvent *e); -static void expose(XEvent *e); -static void keymapnotify(XEvent *e); -static void maprequest(XEvent *e); -static void propertynotify(XEvent *e); -static void unmapnotify(XEvent *e); +typedef struct { + unsigned long mod; + KeySym keysym; + void (*func)(const char *arg); + const char *arg; +} Key; -void (*handler[LASTEvent]) (XEvent *) = { - [ButtonPress] = buttonpress, - [ConfigureRequest] = configurerequest, - [DestroyNotify] = destroynotify, - [EnterNotify] = enternotify, - [LeaveNotify] = leavenotify, - [Expose] = expose, - [KeyPress] = keypress, - [KeymapNotify] = keymapnotify, - [MapRequest] = maprequest, - [PropertyNotify] = propertynotify, - [UnmapNotify] = unmapnotify -}; +KEYS -static void -buttonpress(XEvent *e) -{ - XButtonPressedEvent *ev = &e->xbutton; +#define CLEANMASK(mask) (mask & ~(numlockmask | LockMask)) +#define MOUSEMASK (BUTTONMASK | PointerMotionMask) + +static Client * +getclient(Window w) { Client *c; - if(barwin == ev->window) - barclick(ev); - else if((c = getclient(ev->window))) { - craise(c); - switch(ev->button) { - default: + for(c = clients; c && c->win != w; c = c->next); + return c; +} + +static void +movemouse(Client *c) { + int x1, y1, ocx, ocy, di, nx, ny; + unsigned int dui; + Window dummy; + XEvent ev; + + ocx = nx = c->x; + ocy = ny = c->y; + if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurMove], CurrentTime) != GrabSuccess) + return; + c->ismax = False; + XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui); + for(;;) { + XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask, &ev); + switch (ev.type) { + case ButtonRelease: + XUngrabPointer(dpy, CurrentTime); + return; + case ConfigureRequest: + case Expose: + case MapRequest: + handler[ev.type](&ev); break; - case Button1: - mmove(c); + case MotionNotify: + XSync(dpy, False); + nx = ocx + (ev.xmotion.x - x1); + ny = ocy + (ev.xmotion.y - y1); + if(abs(wax + nx) < SNAP) + nx = wax; + else if(abs((wax + waw) - (nx + c->w + 2 * c->border)) < SNAP) + nx = wax + waw - c->w - 2 * c->border; + if(abs(way - ny) < SNAP) + ny = way; + else if(abs((way + wah) - (ny + c->h + 2 * c->border)) < SNAP) + ny = way + wah - c->h - 2 * c->border; + resize(c, nx, ny, c->w, c->h, False); break; - case Button2: - lower(c); + } + } +} + +static void +resizemouse(Client *c) { + int ocx, ocy; + int nw, nh; + XEvent ev; + + ocx = c->x; + ocy = c->y; + if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurResize], CurrentTime) != GrabSuccess) + return; + c->ismax = False; + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->border - 1, c->h + c->border - 1); + for(;;) { + XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask , &ev); + switch(ev.type) { + case ButtonRelease: + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, + c->w + c->border - 1, c->h + c->border - 1); + XUngrabPointer(dpy, CurrentTime); + while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); + return; + case ConfigureRequest: + case Expose: + case MapRequest: + handler[ev.type](&ev); break; - case Button3: - mresize(c); + case MotionNotify: + XSync(dpy, False); + if((nw = ev.xmotion.x - ocx - 2 * c->border + 1) <= 0) + nw = 1; + if((nh = ev.xmotion.y - ocy - 2 * c->border + 1) <= 0) + nh = 1; + resize(c, c->x, c->y, nw, nh, True); break; } } } static void -configurerequest(XEvent *e) -{ +buttonpress(XEvent *e) { + static char buf[32]; + unsigned int i, x; + Client *c; + XButtonPressedEvent *ev = &e->xbutton; + + buf[0] = 0; + if(barwin == ev->window) { + x = 0; + for(i = 0; i < ntags; i++) { + x += textw(tags[i]); + if(ev->x < x) { + snprintf(buf, sizeof buf, "%d", i); + if(ev->button == Button1) { + if(ev->state & MODKEY) + tag(buf); + else + view(buf); + } + else if(ev->button == Button3) { + if(ev->state & MODKEY) + toggletag(buf); + else + toggleview(buf); + } + return; + } + } + if(ev->x < x + blw) + switch(ev->button) { + case Button1: + setlayout(NULL); + break; + } + } + else if((c = getclient(ev->window))) { + focus(c); + if(CLEANMASK(ev->state) != MODKEY) + return; + if(ev->button == Button1 && (lt->arrange == floating || c->isfloating)) { + restack(); + movemouse(c); + } + else if(ev->button == Button2) + zoom(NULL); + else if(ev->button == Button3 + && (lt->arrange == floating || c->isfloating) && !c->isfixed) + { + restack(); + resizemouse(c); + } + } +} + +static void +configurerequest(XEvent *e) { + Client *c; XConfigureRequestEvent *ev = &e->xconfigurerequest; XWindowChanges wc; - Client *c; - ev->value_mask &= ~CWSibling; if((c = getclient(ev->window))) { - gravitate(c, True); - if(ev->value_mask & CWX) - c->x = ev->x; - if(ev->value_mask & CWY) - c->y = ev->y; - if(ev->value_mask & CWWidth) - c->w = ev->width; - if(ev->value_mask & CWHeight) - c->h = ev->height; + c->ismax = False; if(ev->value_mask & CWBorderWidth) - c->border = 1; - gravitate(c, False); - resize(c, True); + c->border = ev->border_width; + if(c->isfixed || c->isfloating || (lt->arrange == floating)) { + if(ev->value_mask & CWX) + c->x = ev->x; + if(ev->value_mask & CWY) + c->y = ev->y; + if(ev->value_mask & CWWidth) + c->w = ev->width; + if(ev->value_mask & CWHeight) + c->h = ev->height; + if((c->x + c->w) > sw && c->isfloating) + c->x = sw / 2 - c->w / 2; /* center in x direction */ + if((c->y + c->h) > sh && c->isfloating) + c->y = sh / 2 - c->h / 2; /* center in y direction */ + if((ev->value_mask & (CWX | CWY)) + && !(ev->value_mask & (CWWidth | CWHeight))) + configure(c); + if(isvisible(c)) + XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); + } + else + configure(c); + } + else { + wc.x = ev->x; + wc.y = ev->y; + wc.width = ev->width; + wc.height = ev->height; + wc.border_width = ev->border_width; + wc.sibling = ev->above; + wc.stack_mode = ev->detail; + XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); } + XSync(dpy, False); +} + +static void +configurenotify(XEvent *e) { + XConfigureEvent *ev = &e->xconfigure; - wc.x = ev->x; - wc.y = ev->y; - wc.width = ev->width; - wc.height = ev->height; - wc.border_width = 1; - wc.sibling = None; - wc.stack_mode = Above; - ev->value_mask &= ~CWStackMode; - ev->value_mask |= CWBorderWidth; - XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); - XFlush(dpy); + if (ev->window == root && (ev->width != sw || ev->height != sh)) { + sw = ev->width; + sh = ev->height; + XFreePixmap(dpy, dc.drawable); + dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); + XResizeWindow(dpy, barwin, sw, bh); + updatebarpos(); + lt->arrange(); + } } static void -destroynotify(XEvent *e) -{ +destroynotify(XEvent *e) { Client *c; XDestroyWindowEvent *ev = &e->xdestroywindow; @@ -112,105 +239,149 @@ destroynotify(XEvent *e) } static void -enternotify(XEvent *e) -{ - XCrossingEvent *ev = &e->xcrossing; +enternotify(XEvent *e) { Client *c; + XCrossingEvent *ev = &e->xcrossing; if(ev->mode != NotifyNormal || ev->detail == NotifyInferior) return; - if((c = getclient(ev->window))) focus(c); - else if(ev->window == root) - issel = True; + else if(ev->window == root) { + selscreen = True; + focus(NULL); + } } static void -leavenotify(XEvent *e) -{ - XCrossingEvent *ev = &e->xcrossing; +expose(XEvent *e) { + XExposeEvent *ev = &e->xexpose; - if((ev->window == root) && !ev->same_screen) - issel = True; + if(ev->count == 0) { + if(barwin == ev->window) + drawstatus(); + } } static void -expose(XEvent *e) -{ - XExposeEvent *ev = &e->xexpose; - Client *c; +keypress(XEvent *e) { + static unsigned int len = sizeof key / sizeof key[0]; + unsigned int i; + KeySym keysym; + XKeyEvent *ev = &e->xkey; - if(ev->count == 0) { - if((c = gettitle(ev->window))) - draw_client(c); + keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); + for(i = 0; i < len; i++) + if(keysym == key[i].keysym + && CLEANMASK(key[i].mod) == CLEANMASK(ev->state)) + { + if(key[i].func) + key[i].func(key[i].arg); + } +} + +static void +leavenotify(XEvent *e) { + XCrossingEvent *ev = &e->xcrossing; + + if((ev->window == root) && !ev->same_screen) { + selscreen = False; + focus(NULL); } } static void -keymapnotify(XEvent *e) -{ - update_keys(); +mappingnotify(XEvent *e) { + XMappingEvent *ev = &e->xmapping; + + XRefreshKeyboardMapping(ev); + if(ev->request == MappingKeyboard) + grabkeys(); } static void -maprequest(XEvent *e) -{ - XMapRequestEvent *ev = &e->xmaprequest; +maprequest(XEvent *e) { static XWindowAttributes wa; + XMapRequestEvent *ev = &e->xmaprequest; if(!XGetWindowAttributes(dpy, ev->window, &wa)) return; - - if(wa.override_redirect) { - XSelectInput(dpy, ev->window, - (StructureNotifyMask | PropertyChangeMask)); + if(wa.override_redirect) return; - } - if(!getclient(ev->window)) manage(ev->window, &wa); } static void -propertynotify(XEvent *e) -{ - XPropertyEvent *ev = &e->xproperty; - Window trans; +propertynotify(XEvent *e) { Client *c; + Window trans; + XPropertyEvent *ev = &e->xproperty; if(ev->state == PropertyDelete) return; /* ignore */ - if((c = getclient(ev->window))) { - if(ev->atom == wm_atom[WMProtocols]) { - c->proto = win_proto(c->win); - return; - } switch (ev->atom) { default: break; case XA_WM_TRANSIENT_FOR: XGetTransientForHint(dpy, c->win, &trans); - if(!c->floating && (c->floating = (trans != 0))) - arrange(NULL); + if(!c->isfloating && (c->isfloating = (getclient(trans) != NULL))) + lt->arrange(); break; case XA_WM_NORMAL_HINTS: - update_size(c); + updatesizehints(c); break; } - if(ev->atom == XA_WM_NAME || ev->atom == net_atom[NetWMName]) { - update_name(c); - draw_client(c); + if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { + updatetitle(c); + if(c == sel) + drawstatus(); } } } static void -unmapnotify(XEvent *e) -{ +unmapnotify(XEvent *e) { Client *c; XUnmapEvent *ev = &e->xunmap; if((c = getclient(ev->window))) unmanage(c); } + +/* extern */ + +void (*handler[LASTEvent]) (XEvent *) = { + [ButtonPress] = buttonpress, + [ConfigureRequest] = configurerequest, + [ConfigureNotify] = configurenotify, + [DestroyNotify] = destroynotify, + [EnterNotify] = enternotify, + [LeaveNotify] = leavenotify, + [Expose] = expose, + [KeyPress] = keypress, + [MappingNotify] = mappingnotify, + [MapRequest] = maprequest, + [PropertyNotify] = propertynotify, + [UnmapNotify] = unmapnotify +}; + +void +grabkeys(void) { + static unsigned int len = sizeof key / sizeof key[0]; + unsigned int i; + KeyCode code; + + XUngrabKey(dpy, AnyKey, AnyModifier, root); + for(i = 0; i < len; i++) { + code = XKeysymToKeycode(dpy, key[i].keysym); + XGrabKey(dpy, code, key[i].mod, root, True, + GrabModeAsync, GrabModeAsync); + XGrabKey(dpy, code, key[i].mod | LockMask, root, True, + GrabModeAsync, GrabModeAsync); + XGrabKey(dpy, code, key[i].mod | numlockmask, root, True, + GrabModeAsync, GrabModeAsync); + XGrabKey(dpy, code, key[i].mod | numlockmask | LockMask, root, True, + GrabModeAsync, GrabModeAsync); + } +}