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 +}