+ return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui);
+}
+
+long
+getstate(Window w) {
+ int format, status;
+ long result = -1;
+ unsigned char *p = NULL;
+ unsigned long n, extra;
+ Atom real;
+
+ status = XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState],
+ &real, &format, &n, &extra, (unsigned char **)&p);
+ if(status != Success)
+ return -1;
+ if(n != 0)
+ result = *p;
+ XFree(p);
+ return result;
+}
+
+Bool
+gettextprop(Window w, Atom atom, char *text, unsigned int size) {
+ char **list = NULL;
+ int n;
+ XTextProperty name;
+
+ if(!text || size == 0)
+ return False;
+ text[0] = '\0';
+ XGetTextProperty(dpy, w, &name, atom);
+ if(!name.nitems)
+ return False;
+ if(name.encoding == XA_STRING)
+ strncpy(text, (char *)name.value, size - 1);
+ else {
+ if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
+ && n > 0 && *list) {
+ strncpy(text, *list, size - 1);
+ XFreeStringList(list);
+ }
+ }
+ text[size - 1] = '\0';
+ XFree(name.value);
+ return True;
+}
+
+void
+grabbuttons(Client *c, Bool focused) {
+ updatenumlockmask();
+ {
+ unsigned int i, j;
+ unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
+ XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
+ if(focused) {
+ for(i = 0; i < LENGTH(buttons); i++)
+ if(buttons[i].click == ClkClientWin)
+ for(j = 0; j < LENGTH(modifiers); j++)
+ XGrabButton(dpy, buttons[i].button,
+ buttons[i].mask | modifiers[j],
+ c->win, False, BUTTONMASK,
+ GrabModeAsync, GrabModeSync, None, None);
+ } else
+ XGrabButton(dpy, AnyButton, AnyModifier, c->win, False,
+ BUTTONMASK, GrabModeAsync, GrabModeSync, None, None);
+ }
+}
+
+void
+grabkeys(void) {
+ updatenumlockmask();
+ { /* grab keys */
+ unsigned int i, j;
+ unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
+ KeyCode code;
+
+ XUngrabKey(dpy, AnyKey, AnyModifier, root);
+ for(i = 0; i < LENGTH(keys); i++) {
+ if((code = XKeysymToKeycode(dpy, keys[i].keysym)))
+ for(j = 0; j < LENGTH(modifiers); j++)
+ XGrabKey(dpy, code, keys[i].mod | modifiers[j], root,
+ True, GrabModeAsync, GrabModeAsync);
+ }
+ }
+}
+
+void
+initfont(const char *fontstr) {
+ char *def, **missing;
+ int i, n;
+
+ missing = NULL;
+ dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
+ if(missing) {
+ while(n--)
+ fprintf(stderr, "dwm: missing fontset: %s\n", missing[n]);
+ XFreeStringList(missing);
+ }
+ if(dc.font.set) {
+ XFontSetExtents *font_extents;
+ XFontStruct **xfonts;
+ char **font_names;
+ dc.font.ascent = dc.font.descent = 0;
+ font_extents = XExtentsOfFontSet(dc.font.set);
+ n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
+ for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) {
+ dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent);
+ dc.font.descent = MAX(dc.font.descent,(*xfonts)->descent);
+ xfonts++;
+ }
+ }
+ else {
+ if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr))
+ && !(dc.font.xfont = XLoadQueryFont(dpy, "fixed")))
+ die("error, cannot load font: '%s'\n", fontstr);
+ dc.font.ascent = dc.font.xfont->ascent;
+ dc.font.descent = dc.font.xfont->descent;
+ }
+ dc.font.height = dc.font.ascent + dc.font.descent;
+}
+
+Bool
+isprotodel(Client *c) {
+ int i, n;
+ Atom *protocols;
+ Bool ret = False;
+
+ if(XGetWMProtocols(dpy, c->win, &protocols, &n)) {
+ for(i = 0; !ret && i < n; i++)
+ if(protocols[i] == wmatom[WMDelete])
+ ret = True;
+ XFree(protocols);
+ }
+ return ret;
+}
+
+void
+keypress(XEvent *e) {
+ unsigned int i;
+ KeySym keysym;
+ XKeyEvent *ev;
+
+ ev = &e->xkey;
+ keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
+ for(i = 0; i < LENGTH(keys); i++)
+ if(keysym == keys[i].keysym
+ && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)
+ && keys[i].func)
+ keys[i].func(&(keys[i].arg));
+}
+
+void
+killclient(const Arg *arg) {
+ XEvent ev;
+
+ if(!selmon->sel)
+ return;
+ if(isprotodel(selmon->sel)) {
+ ev.type = ClientMessage;
+ ev.xclient.window = selmon->sel->win;
+ ev.xclient.message_type = wmatom[WMProtocols];
+ ev.xclient.format = 32;
+ ev.xclient.data.l[0] = wmatom[WMDelete];
+ ev.xclient.data.l[1] = CurrentTime;
+ XSendEvent(dpy, selmon->sel->win, False, NoEventMask, &ev);
+ }
+ else
+ XKillClient(dpy, selmon->sel->win);
+}
+
+void
+manage(Window w, XWindowAttributes *wa) {
+ static Client cz;
+ Client *c, *t = NULL;
+ Window trans = None;
+ XWindowChanges wc;
+
+ if(!(c = malloc(sizeof(Client))))
+ die("fatal: could not malloc() %u bytes\n", sizeof(Client));
+ *c = cz;
+ c->win = w;
+ c->mon = selmon;
+
+ /* geometry */
+ c->x = wa->x + selmon->wx;
+ c->y = wa->y + selmon->wy;
+ c->w = wa->width;
+ c->h = wa->height;
+ c->oldbw = wa->border_width;
+ if(c->w == selmon->mw && c->h == selmon->mh) {
+ c->x = selmon->mx;
+ c->y = selmon->my;
+ c->bw = 0;
+ }
+ else {
+ if(c->x + WIDTH(c) > selmon->mx + selmon->mw)
+ c->x = selmon->mx + selmon->mw - WIDTH(c);
+ if(c->y + HEIGHT(c) > selmon->my + selmon->mh)
+ c->y = selmon->my + selmon->mh - HEIGHT(c);
+ c->x = MAX(c->x, selmon->mx);
+ /* only fix client y-offset, if the client center might cover the bar */
+ c->y = MAX(c->y, ((c->mon->by == 0) && (c->x + (c->w / 2) >= c->mon->wx)
+ && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : selmon->my);
+ c->bw = borderpx;
+ }
+
+ wc.border_width = c->bw;
+ XConfigureWindow(dpy, w, CWBorderWidth, &wc);
+ XSetWindowBorder(dpy, w, dc.norm[ColBorder]);
+ configure(c); /* propagates border_width, if size doesn't change */
+ updatesizehints(c);
+ XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
+ grabbuttons(c, False);
+ updatetitle(c);
+ if(XGetTransientForHint(dpy, w, &trans))
+ t = getclient(trans);
+ if(t)
+ c->tags = t->tags;
+ else
+ applyrules(c);
+ if(!c->isfloating)
+ c->isfloating = trans != None || c->isfixed;
+ if(c->isfloating)
+ XRaiseWindow(dpy, c->win);
+ attach(c);
+ attachstack(c);
+ XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */
+ XMapWindow(dpy, c->win);
+ setclientstate(c, NormalState);
+ arrange();
+}
+
+void
+mappingnotify(XEvent *e) {
+ XMappingEvent *ev = &e->xmapping;
+
+ XRefreshKeyboardMapping(ev);
+ if(ev->request == MappingKeyboard)
+ grabkeys();
+}
+
+void
+maprequest(XEvent *e) {
+ static XWindowAttributes wa;
+ XMapRequestEvent *ev = &e->xmaprequest;
+
+ if(!XGetWindowAttributes(dpy, ev->window, &wa))
+ return;
+ if(wa.override_redirect)
+ return;
+ if(!getclient(ev->window))
+ manage(ev->window, &wa);
+}
+
+void
+monocle(Monitor *m) {
+ Client *c;
+
+ for(c = nexttiled(m->clients); c; c = nexttiled(c->next))
+ resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw);
+}
+
+void
+movemouse(const Arg *arg) {
+ int x, y, ocx, ocy, nx, ny;
+ Client *c;
+ Monitor *m;