commit a95494a9f736377e9c30c62fda61efce6f4f87a2
parent 86059e16d2f518d9c8cd3c594d1d590d6850ccad
Author: Kris Maglione <jg@suckless.org>
Date: Fri, 21 Mar 2008 13:41:30 -0400
Add wistrut. Undocumented, not built by default.
Diffstat:
13 files changed, 816 insertions(+), 4 deletions(-)
diff --git a/cmd/strut/Makefile b/cmd/strut/Makefile
@@ -0,0 +1,26 @@
+ROOT= ../..
+include ${ROOT}/mk/hdr.mk
+include ${ROOT}/mk/wmii.mk
+
+main.c: ${ROOT}/mk/wmii.mk
+
+TARG = wistrut
+HFILES= dat.h fns.h
+
+LIB = ${LIBIXP}
+LDFLAGS += -lm ${LIBX11} -lXext -lXrandr -lregexp9 -lbio -lfmt -lutf
+CFLAGS += ${INCX11} -DVERSION=\"${VERSION}\" \
+ -DIXP_NEEDAPI=86
+OBJ = main \
+ event \
+ ewmh \
+ win \
+ _util \
+ ../wmii/map \
+ ../wmii/printevent \
+ printevent_kludge \
+ ../wmii/x11 \
+ ../util
+
+include ${ROOT}/mk/one.mk
+
diff --git a/cmd/strut/_util.c b/cmd/strut/_util.c
@@ -0,0 +1,77 @@
+/* Copyright ©2008 Kris Maglione <fbsdaemon@gmail.com>
+ * See LICENSE file for license details.
+ */
+#include "dat.h"
+#include <ctype.h>
+#include <string.h>
+#include "fns.h"
+
+#define strbcmp(str, const) (strncmp((str), (const), sizeof(const)-1))
+static int
+getbase(const char **s, long *sign) {
+ const char *p;
+ int ret;
+
+ ret = 10;
+ *sign = 1;
+ if(**s == '-') {
+ *sign = -1;
+ *s += 1;
+ }else if(**s == '+')
+ *s += 1;
+
+ p = *s;
+ if(!strbcmp(p, "0x")) {
+ *s += 2;
+ ret = 16;
+ }
+ else if(isdigit(p[0])) {
+ if(p[1] == 'r') {
+ *s += 2;
+ ret = p[0] - '0';
+ }
+ else if(isdigit(p[1]) && p[2] == 'r') {
+ *s += 3;
+ ret = 10*(p[0]-'0') + (p[1]-'0');
+ }
+ }
+ else if(p[0] == '0') {
+ ret = 8;
+ }
+ if(ret != 10 && (**s == '-' || **s == '+'))
+ *sign = 0;
+ return ret;
+}
+
+bool
+getlong(const char *s, long *ret) {
+ const char *end;
+ char *rend;
+ int base;
+ long sign;
+
+ end = s+strlen(s);
+ base = getbase(&s, &sign);
+ if(sign == 0)
+ return false;
+
+ *ret = sign * strtol(s, &rend, base);
+ return (end == rend);
+}
+
+bool
+getulong(const char *s, ulong *ret) {
+ const char *end;
+ char *rend;
+ int base;
+ long sign;
+
+ end = s+strlen(s);
+ base = getbase(&s, &sign);
+ if(sign < 1)
+ return false;
+
+ *ret = strtoul(s, &rend, base);
+ return (end == rend);
+}
+
diff --git a/cmd/strut/dat.h b/cmd/strut/dat.h
@@ -0,0 +1,33 @@
+#include <fmt.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <util.h>
+#include <ixp.h>
+#include <x11.h>
+
+#define BLOCK(x) do { x; }while(0)
+
+#ifndef EXTERN
+# define EXTERN extern
+#endif
+
+extern Handlers handlers;
+
+EXTERN bool running;
+
+EXTERN Window win;
+EXTERN Window frame;
+EXTERN long xtime;
+
+EXTERN char buffer[8092];
+EXTERN char* _buffer;
+
+static char* const _buf_end = buffer + sizeof buffer;
+
+#define bufclear() \
+ BLOCK( _buffer = buffer; _buffer[0] = '\0' )
+#define bufprint(...) \
+ _buffer = seprint(_buffer, _buf_end, __VA_ARGS__)
+
diff --git a/cmd/strut/event.c b/cmd/strut/event.c
@@ -0,0 +1,309 @@
+/* Copyright ©2006-2008 Kris Maglione <fbsdaemon@gmail.com>
+ * See LICENSE file for license details.
+ */
+#include "dat.h"
+#include "fns.h"
+
+static void (*handler[LASTEvent])(XEvent*);
+
+void
+dispatch_event(XEvent *e) {
+ /* printevent(e); */
+ if(e->type < nelem(handler) && handler[e->type])
+ handler[e->type](e);
+}
+
+#define handle(w, fn, ev) \
+ BLOCK(if((w)->handler->fn) (w)->handler->fn((w), ev))
+
+#ifdef notdef
+uint
+flushevents(long event_mask, bool dispatch) {
+ XEvent ev;
+ uint n = 0;
+
+ while(XCheckMaskEvent(display, event_mask, &ev)) {
+ if(dispatch)
+ dispatch_event(&ev);
+ n++;
+ }
+ return n;
+}
+
+static int
+findenter(Display *d, XEvent *e, XPointer v) {
+ long *l;
+
+ USED(d);
+ l = (long*)v;
+ if(*l)
+ return false;
+ if(e->type == EnterNotify)
+ return true;
+ if(e->type == MotionNotify)
+ (*l)++;
+ return false;
+}
+
+/* This isn't perfect. If there were motion events in the queue
+ * before this was called, then it flushes nothing. If we don't
+ * check for them, we might lose a legitamate enter event.
+ */
+uint
+flushenterevents(void) {
+ XEvent e;
+ long l;
+ int n;
+
+ l = 0;
+ n = 0;
+ while(XCheckIfEvent(display, &e, findenter, (void*)&l))
+ n++;
+ return n;
+}
+#endif
+
+static int
+findtime(Display *d, XEvent *e, XPointer v) {
+ Window *w;
+
+ w = (Window*)v;
+ if(e->type == PropertyNotify && e->xproperty.window == w->w) {
+ xtime = e->xproperty.time;
+ return true;
+ }
+ return false;
+}
+
+void
+xtime_kludge(void) {
+ Window *w;
+ WinAttr wa;
+ XEvent e;
+ long l;
+
+ w = createwindow(&scr.root, Rect(0, 0, 1, 1), 0, InputOnly, &wa, 0);
+
+ XSelectInput(display, w->w, PropertyChangeMask);
+ changeprop_long(w, "ATOM", "ATOM", &l, 0);
+ XIfEvent(display, &e, findtime, (void*)w);
+
+ destroywindow(w);
+}
+
+static void
+buttonrelease(XEvent *e) {
+ XButtonPressedEvent *ev;
+ Window *w;
+
+ ev = &e->xbutton;
+ if((w = findwin(ev->window)))
+ handle(w, bup, ev);
+}
+
+static void
+buttonpress(XEvent *e) {
+ XButtonPressedEvent *ev;
+ Window *w;
+
+ ev = &e->xbutton;
+ if((w = findwin(ev->window)))
+ handle(w, bdown, ev);
+ else
+ XAllowEvents(display, ReplayPointer, ev->time);
+}
+
+static void
+clientmessage(XEvent *e) {
+ XClientMessageEvent *ev;
+
+ ev = &e->xclient;
+ USED(ev);
+}
+
+static void
+configurenotify(XEvent *e) {
+ XConfigureEvent *ev;
+ Window *w;
+
+ ev = &e->xconfigure;
+ if((w = findwin(ev->window)))
+ handle(w, config, ev);
+}
+
+static void
+destroynotify(XEvent *e) {
+ XDestroyWindowEvent *ev;
+ Window *w;
+
+ ev = &e->xdestroywindow;
+ if((w = findwin(ev->window)))
+ handle(w, destroy, ev);
+}
+
+static void
+enternotify(XEvent *e) {
+ XCrossingEvent *ev;
+ Window *w;
+
+ ev = &e->xcrossing;
+ xtime = ev->time;
+ if(ev->mode != NotifyNormal)
+ return;
+
+ if((w = findwin(ev->window)))
+ handle(w, enter, ev);
+}
+
+static void
+leavenotify(XEvent *e) {
+ XCrossingEvent *ev;
+
+ ev = &e->xcrossing;
+ xtime = ev->time;
+}
+
+static void
+focusin(XEvent *e) {
+ XFocusChangeEvent *ev;
+ Window *w;
+
+ ev = &e->xfocus;
+ /* Yes, we're focusing in on nothing, here. */
+ if(ev->detail == NotifyDetailNone) {
+ /* FIXME: Do something. */
+ return;
+ }
+
+ if(!((ev->detail == NotifyNonlinear)
+ ||(ev->detail == NotifyNonlinearVirtual)
+ ||(ev->detail == NotifyVirtual)
+ ||(ev->detail == NotifyInferior)
+ ||(ev->detail == NotifyAncestor)))
+ return;
+ if((ev->mode == NotifyWhileGrabbed))
+ return;
+
+ if((w = findwin(ev->window)))
+ handle(w, focusin, ev);
+}
+
+static void
+focusout(XEvent *e) {
+ XFocusChangeEvent *ev;
+ Window *w;
+
+ ev = &e->xfocus;
+ if(!((ev->detail == NotifyNonlinear)
+ ||(ev->detail == NotifyNonlinearVirtual)
+ ||(ev->detail == NotifyVirtual)
+ ||(ev->detail == NotifyInferior)
+ ||(ev->detail == NotifyAncestor)))
+ return;
+
+ if((w = findwin(ev->window)))
+ handle(w, focusout, ev);
+}
+
+static void
+expose(XEvent *e) {
+ XExposeEvent *ev;
+ Window *w;
+
+ ev = &e->xexpose;
+ if(ev->count == 0) {
+ if((w = findwin(ev->window)))
+ handle(w, expose, ev);
+ }
+}
+
+static void
+keypress(XEvent *e) {
+ XKeyEvent *ev;
+
+ ev = &e->xkey;
+ xtime = ev->time;
+}
+
+static void
+mappingnotify(XEvent *e) {
+ XMappingEvent *ev;
+
+ ev = &e->xmapping;
+ /* Why do you need me to tell you this? */
+ XRefreshKeyboardMapping(ev);
+}
+
+static void
+motionnotify(XEvent *e) {
+ XMotionEvent *ev;
+ Window *w;
+
+ ev = &e->xmotion;
+ xtime = ev->time;
+ if((w = findwin(ev->window)))
+ handle(w, motion, ev);
+}
+
+static void
+propertynotify(XEvent *e) {
+ XPropertyEvent *ev;
+ Window *w;
+
+ ev = &e->xproperty;
+ xtime = ev->time;
+ if((w = findwin(ev->window)))
+ handle(w, property, ev);
+}
+
+static void
+mapnotify(XEvent *e) {
+ XMapEvent *ev;
+ Window *w;
+
+ ev = &e->xmap;
+ if((w = findwin(ev->window)))
+ handle(w, map, ev);
+}
+
+static void
+unmapnotify(XEvent *e) {
+ XUnmapEvent *ev;
+ Window *w;
+
+ ev = &e->xunmap;
+ if((w = findwin(ev->window)) && w->parent && (ev->event == w->parent->w)) {
+ if(ev->send_event || w->unmapped-- == 0)
+ handle(w, unmap, ev);
+ }
+}
+
+static void (*handler[LASTEvent])(XEvent*) = {
+ [ButtonPress] = buttonpress,
+ [ButtonRelease] = buttonrelease,
+ [ClientMessage] = clientmessage,
+ [ConfigureNotify] = configurenotify,
+ [DestroyNotify] = destroynotify,
+ [EnterNotify] = enternotify,
+ [Expose] = expose,
+ [FocusIn] = focusin,
+ [FocusOut] = focusout,
+ [KeyPress] = keypress,
+ [LeaveNotify] = leavenotify,
+ [MapNotify] = mapnotify,
+ [MappingNotify] = mappingnotify,
+ [MotionNotify] = motionnotify,
+ [PropertyNotify] = propertynotify,
+ [UnmapNotify] = unmapnotify,
+};
+
+void
+xevent_loop(void) {
+ XEvent ev;
+
+ while(running) {
+ XNextEvent(display, &ev);
+ dispatch_event(&ev);
+ }
+}
+
diff --git a/cmd/strut/ewmh.c b/cmd/strut/ewmh.c
@@ -0,0 +1,84 @@
+/* Copyright ©2007-2008 Kris Maglione <fbsdaemon@gmail.com>
+ * See LICENSE file for license details.
+ */
+#include "dat.h"
+#include <limits.h>
+#include <string.h>
+#include "fns.h"
+
+#define Net(x) ("_NET_" x)
+#define Action(x) ("_NET_WM_ACTION_" x)
+#define State(x) ("_NET_WM_STATE_" x)
+#define Type(x) ("_NET_WM_WINDOW_TYPE_" x)
+#define NET(x) xatom(Net(x))
+#define ACTION(x) xatom(Action(x))
+#define STATE(x) xatom(State(x))
+#define TYPE(x) xatom(Type(x))
+
+enum {
+ Left, Right, Top, Bottom,
+ LeftMin, LeftMax,
+ RightMin, RightMax,
+ TopMin, TopMax,
+ BottomMin, BottomMax,
+ Last
+};
+
+void
+ewmh_getstrut(Window *w, Rectangle struts[4]) {
+ long *strut;
+ ulong n;
+
+ memset(struts, 0, sizeof struts);
+
+ n = getprop_long(w, Net("WM_STRUT_PARTIAL"), "CARDINAL",
+ 0L, &strut, Last);
+ if(n != Last) {
+ free(strut);
+ n = getprop_long(w, Net("WM_STRUT"), "CARDINAL",
+ 0L, &strut, 4L);
+ if(n != 4) {
+ free(strut);
+ return;
+ }
+ strut = erealloc(strut, Last * sizeof *strut);
+ strut[LeftMin] = strut[RightMin] = 0;
+ strut[LeftMax] = strut[RightMax] = INT_MAX;
+ strut[TopMin] = strut[BottomMin] = 0;
+ strut[TopMax] = strut[BottomMax] = INT_MAX;
+ }
+ struts[Left] = Rect(0, strut[LeftMin], strut[Left], strut[LeftMax]);
+ struts[Right] = Rect(-strut[Right], strut[RightMin], 0, strut[RightMax]);
+ struts[Top] = Rect(strut[TopMin], 0, strut[TopMax], strut[Top]);
+ struts[Bottom] = Rect(strut[BottomMin], -strut[Bottom], strut[BottomMax], 0);
+ free(strut);
+}
+
+void
+ewmh_setstrut(Window *w, Rectangle struts[4]) {
+ long strut[Last];
+ int i;
+
+ strut[LeftMin] = struts[Left].min.y;
+ strut[Left] = struts[Left].max.x;
+ strut[LeftMax] = struts[Left].max.y;
+
+ strut[RightMin] = struts[Right].min.y;
+ strut[Right] = -struts[Right].min.x;
+ strut[RightMax] = struts[Right].max.y;
+
+ strut[TopMin] = struts[Top].min.x;
+ strut[Top] = struts[Top].max.y;
+ strut[TopMax] = struts[Top].max.x;
+
+ strut[BottomMin] = struts[Bottom].min.x;
+ strut[Bottom] = -struts[Bottom].min.y;
+ strut[BottomMax] = struts[Bottom].max.x;
+
+ for(i=0; i<Last; i++)
+ if(strut[i] < 0)
+ strut[i] = 0;
+
+ changeprop_long(w, Net("WM_STRUT_PARTIAL"), "CARDINAL", strut, nelem(strut));
+}
+
diff --git a/cmd/strut/fns.h b/cmd/strut/fns.h
@@ -0,0 +1,18 @@
+
+void debug(int, const char*, ...);
+void dispatch_event(XEvent*);
+uint flushevents(long, bool);
+uint flushenterevents(void);
+void xevent_loop(void);
+void xtime_kludge(void);
+
+void restrut(void);
+
+bool getlong(const char*, long*);
+bool getulong(const char*, ulong*);
+
+void ewmh_getstrut(Window*, Rectangle[4]);
+void ewmh_setstrut(Window*, Rectangle[4]);
+
+void printevent(XEvent *e);
+
diff --git a/cmd/strut/main.c b/cmd/strut/main.c
@@ -0,0 +1,144 @@
+/* Copyright ©2006-2008 Kris Maglione <fbsdaemon@gmail.com>
+ * See LICENSE file for license details.
+ */
+#define EXTERN
+#include "dat.h"
+#include <X11/Xproto.h>
+#include <locale.h>
+#include <string.h>
+#include "fns.h"
+
+static const char version[] = "witray-"VERSION", ©2007 Kris Maglione\n";
+
+static int (*xlib_errorhandler) (Display*, XErrorEvent*);
+
+static void
+usage(void) {
+ fatal("usage: %s <window>\n", argv0);
+}
+
+static int
+errfmt(Fmt *f) {
+ return fmtstrcpy(f, ixp_errbuf());
+}
+
+void
+debug(int flag, const char *fmt, ...) {
+ va_list ap;
+
+ USED(flag);
+ va_start(ap, fmt);
+ vfprint(2, fmt, ap);
+ va_end(ap);
+}
+
+/*
+ * There's no way to check accesses to destroyed windows, thus
+ * those cases are ignored (especially on UnmapNotifies).
+ * Other types of errors call Xlib's default error handler, which
+ * calls exit().
+ */
+struct {
+ uchar rcode;
+ uchar ecode;
+} itab[] = {
+ { 0, BadWindow },
+ { X_SetInputFocus, BadMatch },
+ { X_PolyText8, BadDrawable },
+ { X_PolyFillRectangle, BadDrawable },
+ { X_PolySegment, BadDrawable },
+ { X_ConfigureWindow, BadMatch },
+ { X_GrabKey, BadAccess },
+ { X_GetAtomName, BadAtom },
+};
+
+static int
+errorhandler(Display *dpy, XErrorEvent *error) {
+ int i;
+
+ USED(dpy);
+
+ if(error->request_code == X_QueryTree
+ && error->error_code == BadWindow
+ && error->resourceid == win.w)
+ fatal("%W: window does not exist", &win);
+
+ for(i = 0; i < nelem(itab); i++)
+ if((itab[i].rcode == 0 || itab[i].rcode == error->request_code)
+ && (itab[i].ecode == 0 || itab[i].ecode == error->error_code))
+ return 0;
+
+ fprint(2, "%s: fatal error: Xrequest code=%d, Xerror code=%d\n",
+ argv0, error->request_code, error->error_code);
+
+ return xlib_errorhandler(display, error); /* calls exit() */
+}
+
+static Window
+findframe(Window *w) {
+ XWindow *children;
+ XWindow xw, par, root;
+ Window ret = {0, };
+ uint n;
+
+ for(par=w->w; par != scr.root.w; ) {
+ xw = par;
+ XQueryTree(display, xw, &root, &par, &children, &n);
+ XFree(children);
+ }
+ ret.w = xw;
+ ret.parent = &scr.root;
+ return ret;
+}
+
+static void
+getwinsize(Window *win) {
+ int x, y;
+ uint w, h;
+ /* ignored */
+ XWindow root;
+ uint border, depth;
+
+ XGetGeometry(display, win->w, &root,
+ &x, &y, &w, &h,
+ &border, &depth);
+ win->r = rectaddpt(Rect(0, 0, w, h),
+ Pt(x, y));
+}
+
+int
+main(int argc, char *argv[]) {
+ char *s;
+
+ fmtinstall('r', errfmt);
+
+ ARGBEGIN{
+ default:
+ usage();
+ }ARGEND;
+
+ s = EARGF(usage());
+ if(!getulong(s, &win.w))
+ usage();
+
+ if(argc)
+ usage();
+
+ setlocale(LC_CTYPE, "");
+
+ initdisplay();
+ xlib_errorhandler = XSetErrorHandler(errorhandler);
+
+ frame = findframe(&win);
+ getwinsize(&frame);
+ restrut();
+ sethandler(&frame, &handlers);
+ selectinput(&frame, StructureNotifyMask);
+
+ running = true;
+ xevent_loop();
+
+ XCloseDisplay(display);
+ return 0;
+}
+
diff --git a/cmd/strut/printevent_kludge.c b/cmd/strut/printevent_kludge.c
@@ -0,0 +1,12 @@
+#include "dat.h"
+
+void dprint(const char *fmt, ...);
+void
+dprint(const char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprint(2, fmt, ap);
+ va_end(ap);
+}
+
diff --git a/cmd/strut/win.c b/cmd/strut/win.c
@@ -0,0 +1,103 @@
+/* Copyright ©2008 Kris Maglione <fbsdaemon@gmail.com>
+ * See LICENSE file for license details.
+ */
+#include "dat.h"
+#include <string.h>
+#include "fns.h"
+
+void
+restrut(void) {
+ enum { Left, Right, Top, Bottom };
+ Rectangle strut[4];
+ Rectangle r;
+
+ r = frame.r;
+ memset(strut, 0, sizeof strut);
+ if(Dx(r) < Dx(scr.rect)/2) {
+ if(r.min.x <= scr.rect.min.x) {
+ strut[Left] = r;
+ strut[Left].min.x = 0;
+ strut[Left].max.x -= scr.rect.min.x;
+ }
+ if(r.max.x >= scr.rect.max.x) {
+ strut[Right] = r;
+ strut[Right].min.x -= scr.rect.max.x;
+ strut[Right].max.x = 0;
+ }
+ }
+ if(Dy(r) < Dy(scr.rect)/2) {
+ if(r.min.y <= scr.rect.min.y) {
+ strut[Top] = r;
+ strut[Top].min.y = 0;
+ strut[Top].max.y -= scr.rect.min.y;
+ }
+ if(r.max.y >= scr.rect.max.y) {
+ strut[Bottom] = r;
+ strut[Bottom].min.y -= scr.rect.max.y;
+ strut[Bottom].max.y = 0;
+ }
+ }
+
+#define pstrut(name) \
+ if(!eqrect(strut[name], ZR)) \
+ fprint(2, "strut["#name"] = %R\n", strut[name])
+ /* Choose the struts which take up the least space.
+ * Not ideal.
+ */
+ if(Dy(strut[Top])) {
+ if(strut[Top].min.x <= scr.rect.min.x)
+ if(Dy(strut[Top]) < Dx(strut[Left]))
+ strut[Left] = ZR;
+ else
+ strut[Top] = ZR;
+ if(strut[Top].max.x >= scr.rect.max.x)
+ if(Dy(strut[Top]) < Dx(strut[Right]))
+ strut[Right] = ZR;
+ else
+ strut[Top] = ZR;
+ }
+ if(Dy(strut[Bottom])) {
+ if(strut[Bottom].min.x <= scr.rect.min.x)
+ if(Dy(strut[Bottom]) < Dx(strut[Left]))
+ strut[Left] = ZR;
+ else
+ strut[Bottom] = ZR;
+ if(strut[Bottom].max.x >= scr.rect.max.x)
+ if(Dy(strut[Bottom]) < Dx(strut[Right]))
+ strut[Right] = ZR;
+ else
+ strut[Bottom] = ZR;
+ }
+
+#if 0
+ pstrut(Left);
+ pstrut(Right);
+ pstrut(Top);
+ pstrut(Bottom);
+#endif
+
+ ewmh_setstrut(&win, strut);
+}
+
+static void
+config(Window *w, XConfigureEvent *ev) {
+
+ USED(w);
+
+ frame.r = rectaddpt(Rect(0, 0, ev->width, ev->height),
+ Pt(ev->x, ev->y));
+ restrut();
+
+}
+
+static void
+destroy(Window *w, XDestroyWindowEvent *ev) {
+ USED(w, ev);
+ running = false;
+}
+
+Handlers handlers = {
+ .config = config,
+ .destroy = destroy,
+};
+
diff --git a/cmd/wmii/client.c b/cmd/wmii/client.c
@@ -152,7 +152,7 @@ client_create(XWindow w, XWindowAttributes *wa) {
sethandler(c->framewin, &framehandler);
sethandler(&c->w, &handlers);
- XSelectInput(display, c->w.w, ClientMask);
+ selectinput(&c->w, ClientMask);
p.x = def.border;
p.y = labelh(def.font);
diff --git a/cmd/wmii/main.c b/cmd/wmii/main.c
@@ -328,9 +328,8 @@ main(int argc, char *argv[]) {
xlib_errorhandler = XSetErrorHandler(errorhandler);
check_other_wm = true;
- XSelectInput(display, scr.root.w,
- SubstructureRedirectMask
- | EnterWindowMask);
+ selectinput(&scr.root, SubstructureRedirectMask
+ | EnterWindowMask);
sync();
check_other_wm = false;
diff --git a/cmd/wmii/x11.c b/cmd/wmii/x11.c
@@ -279,6 +279,11 @@ setwinattr(Window *w, WinAttr *wa, int valmask) {
}
void
+selectinput(Window *w, long mask) {
+ XSelectInput(display, w->w, mask);
+}
+
+void
setborder(Window *w, int width, long pixel) {
Rectangle r;
diff --git a/include/x11.h b/include/x11.h
@@ -82,6 +82,7 @@ struct Handlers {
Rectangle (*dndmotion)(Window*, Point);
void (*bdown)(Window*, XButtonEvent*);
void (*bup)(Window*, XButtonEvent*);
+ void (*config)(Window*, XConfigureEvent*);
void (*configreq)(Window*, XConfigureRequestEvent*);
void (*destroy)(Window*, XDestroyWindowEvent*);
void (*enter)(Window*, XCrossingEvent*);
@@ -221,6 +222,7 @@ Point querypointer(Window*);
void raisewin(Window*);
void reparentwindow(Window*, Window*, Point);
void reshapewin(Window*, Rectangle);
+void selectinput(Window*, long);
void sendevent(Window*, bool propegate, long mask, XEvent*);
void setborder(Window*, int, long);
void setfocus(Window*, int mode);