1 /* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
2 * See LICENSE file for license details.
6 #include <X11/keysym.h>
14 void (*func)(Arg *arg);
20 #define CLEANMASK(mask) (mask & ~(numlockmask | LockMask))
23 movemouse(Client *c) {
24 int x1, y1, ocx, ocy, di;
31 if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
32 None, cursor[CurMove], CurrentTime) != GrabSuccess)
35 XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
37 XMaskEvent(dpy, MOUSEMASK | ExposureMask, &ev);
40 resize(c, True, TopLeft);
41 XUngrabPointer(dpy, CurrentTime);
48 c->x = ocx + (ev.xmotion.x - x1);
49 c->y = ocy + (ev.xmotion.y - y1);
50 resize(c, False, TopLeft);
57 resizemouse(Client *c) {
65 if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
66 None, cursor[CurResize], CurrentTime) != GrabSuccess)
69 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w, c->h);
71 XMaskEvent(dpy, MOUSEMASK | ExposureMask, &ev);
74 resize(c, True, TopLeft);
75 XUngrabPointer(dpy, CurrentTime);
82 if((nw = abs(ocx - ev.xmotion.x)))
84 if((nh = abs(ocy - ev.xmotion.y)))
86 c->x = (ocx <= ev.xmotion.x) ? ocx : ocx - c->w;
87 c->y = (ocy <= ev.xmotion.y) ? ocy : ocy - c->h;
88 if(ocx <= ev.xmotion.x)
89 sticky = (ocy <= ev.xmotion.y) ? TopLeft : BotLeft;
91 sticky = (ocy <= ev.xmotion.y) ? TopRight : BotRight;
92 resize(c, True, sticky);
99 buttonpress(XEvent *e) {
103 XButtonPressedEvent *ev = &e->xbutton;
105 if(barwin == ev->window) {
107 for(a.i = 0; a.i < ntags; a.i++) {
108 x += textw(tags[a.i]);
110 if(ev->button == Button1) {
111 if(ev->state & MODKEY)
116 else if(ev->button == Button3) {
117 if(ev->state & MODKEY)
125 if((ev->x < x + bmw) && (ev->button == Button1))
128 else if((c = getclient(ev->window))) {
130 if(CLEANMASK(ev->state) != MODKEY)
132 if(ev->button == Button1 && (arrange == dofloat || c->isfloat)) {
136 else if(ev->button == Button2)
138 else if(ev->button == Button3 && (arrange == dofloat || c->isfloat)) {
146 configurerequest(XEvent *e) {
147 unsigned long newmask;
149 XConfigureRequestEvent *ev = &e->xconfigurerequest;
152 if((c = getclient(ev->window))) {
155 if(ev->value_mask & CWX)
157 if(ev->value_mask & CWY)
159 if(ev->value_mask & CWWidth)
161 if(ev->value_mask & CWHeight)
163 if(ev->value_mask & CWBorderWidth)
164 c->border = ev->border_width;
170 newmask = ev->value_mask & (~(CWSibling | CWStackMode | CWBorderWidth));
172 XConfigureWindow(dpy, c->win, newmask, &wc);
177 resize(c, False, TopLeft);
187 wc.width = ev->width;
188 wc.height = ev->height;
189 wc.border_width = ev->border_width;
190 wc.sibling = ev->above;
191 wc.stack_mode = ev->detail;
192 XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
198 destroynotify(XEvent *e) {
200 XDestroyWindowEvent *ev = &e->xdestroywindow;
202 if((c = getclient(ev->window)))
207 enternotify(XEvent *e) {
209 XCrossingEvent *ev = &e->xcrossing;
211 if(ev->mode != NotifyNormal || ev->detail == NotifyInferior)
213 if(((c = getclient(ev->window)) || (c = getctitle(ev->window))) && isvisible(c))
215 else if(ev->window == root) {
217 XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
225 XExposeEvent *ev = &e->xexpose;
228 if(barwin == ev->window)
230 else if((c = getctitle(ev->window)))
236 keypress(XEvent *e) {
237 static unsigned int len = sizeof(key) / sizeof(key[0]);
240 XKeyEvent *ev = &e->xkey;
242 keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
243 for(i = 0; i < len; i++) {
244 if(keysym == key[i].keysym
245 && CLEANMASK(key[i].mod) == CLEANMASK(ev->state))
248 key[i].func(&key[i].arg);
255 leavenotify(XEvent *e) {
256 XCrossingEvent *ev = &e->xcrossing;
258 if((ev->window == root) && !ev->same_screen) {
265 mappingnotify(XEvent *e) {
266 XMappingEvent *ev = &e->xmapping;
268 XRefreshKeyboardMapping(ev);
269 if(ev->request == MappingKeyboard)
274 maprequest(XEvent *e) {
275 static XWindowAttributes wa;
276 XMapRequestEvent *ev = &e->xmaprequest;
278 if(!XGetWindowAttributes(dpy, ev->window, &wa))
280 if(wa.override_redirect) {
281 XSelectInput(dpy, ev->window,
282 (StructureNotifyMask | PropertyChangeMask));
285 if(!getclient(ev->window))
286 manage(ev->window, &wa);
290 propertynotify(XEvent *e) {
293 XPropertyEvent *ev = &e->xproperty;
295 if(ev->state == PropertyDelete)
297 if((c = getclient(ev->window))) {
298 if(ev->atom == wmatom[WMProtocols]) {
299 c->proto = getproto(c->win);
304 case XA_WM_TRANSIENT_FOR:
305 XGetTransientForHint(dpy, c->win, &trans);
306 if(!c->isfloat && (c->isfloat = (trans != 0)))
309 case XA_WM_NORMAL_HINTS:
313 if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
322 unmapnotify(XEvent *e) {
324 XUnmapEvent *ev = &e->xunmap;
326 if((c = getclient(ev->window)))
332 void (*handler[LASTEvent]) (XEvent *) = {
333 [ButtonPress] = buttonpress,
334 [ConfigureRequest] = configurerequest,
335 [DestroyNotify] = destroynotify,
336 [EnterNotify] = enternotify,
337 [LeaveNotify] = leavenotify,
339 [KeyPress] = keypress,
340 [MappingNotify] = mappingnotify,
341 [MapRequest] = maprequest,
342 [PropertyNotify] = propertynotify,
343 [UnmapNotify] = unmapnotify
348 static unsigned int len = sizeof(key) / sizeof(key[0]);
352 XUngrabKey(dpy, AnyKey, AnyModifier, root);
353 for(i = 0; i < len; i++) {
354 code = XKeysymToKeycode(dpy, key[i].keysym);
355 XGrabKey(dpy, code, key[i].mod, root, True,
356 GrabModeAsync, GrabModeAsync);
357 XGrabKey(dpy, code, key[i].mod | LockMask, root, True,
358 GrabModeAsync, GrabModeAsync);
359 XGrabKey(dpy, code, key[i].mod | numlockmask, root, True,
360 GrabModeAsync, GrabModeAsync);
361 XGrabKey(dpy, code, key[i].mod | numlockmask | LockMask, root, True,
362 GrabModeAsync, GrabModeAsync);
370 while(XPending(dpy)) {
371 XNextEvent(dpy, &ev);
373 (handler[ev.type])(&ev); /* call handler */