JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
oops - don't xcb_disconnect() on restart.
[spectrwm.git] / spectrwm.c
index b4e86a4..8bdecf1 100644 (file)
@@ -90,7 +90,7 @@
 #include <X11/keysym.h>
 #include <X11/XKBlib.h>
 #include <X11/Xatom.h>
-#include <X11/Xlib.h>
+#include <X11/Xlib-xcb.h>
 #include <X11/Xproto.h>
 #include <X11/Xutil.h>
 #include <X11/extensions/Xrandr.h>
@@ -221,6 +221,7 @@ int                 xrandr_support;
 int                    xrandr_eventbase;
 unsigned int           numlockmask = 0;
 Display                        *display;
+xcb_connection_t       *conn;
 
 int                    cycle_empty = 0;
 int                    cycle_visible = 0;
@@ -335,8 +336,8 @@ struct swm_screen;
 struct workspace;
 
 struct swm_bar {
-       Window                  id;
-       Pixmap                  buffer;
+       xcb_window_t            id;
+       xcb_pixmap_t            buffer;
        struct swm_geometry     g;
 };
 
@@ -353,8 +354,8 @@ TAILQ_HEAD(swm_region_list, swm_region);
 
 struct ws_win {
        TAILQ_ENTRY(ws_win)     entry;
-       Window                  id;
-       Window                  transient;
+       xcb_window_t            id;
+       xcb_window_t            transient;
        struct ws_win           *child_trans;   /* transient child window */
        struct swm_geometry     g;              /* current geometry */
        struct swm_geometry     g_float;        /* region coordinates */
@@ -401,12 +402,12 @@ void      max_stack(struct workspace *, struct swm_geometry *);
 void   plain_stacker(struct workspace *);
 void   fancy_stacker(struct workspace *);
 
-struct ws_win *find_window(Window);
+struct ws_win *find_window(xcb_window_t);
 
 void   grabbuttons(struct ws_win *, int);
 void   new_region(struct swm_screen *, int, int, int, int);
 void   unmanage_window(struct ws_win *);
-long   getstate(Window);
+long   getstate(xcb_window_t);
 
 int    conf_load(char *, int);
 
@@ -478,7 +479,7 @@ struct swm_screen {
        int                     idx;    /* screen index */
        struct swm_region_list  rl;     /* list of regions on this screen */
        struct swm_region_list  orl;    /* list of old regions */
-       Window                  root;
+       xcb_window_t            root;
        struct workspace        ws[SWM_WS_MAX];
 
        /* colors */
@@ -586,34 +587,34 @@ enum {
 };
 
 struct ewmh_hint {
-       char    *name;
-       Atom     atom;
+       char            *name;
+       xcb_atom_t      atom;
 } ewmh[SWM_EWMH_HINT_MAX] =    {
     /* must be in same order as in the enum */
-    {"_NET_ACTIVE_WINDOW", None},
-    {"_NET_CLOSE_WINDOW", None},
-    {"_NET_MOVERESIZE_WINDOW", None},
-    {"_NET_WM_ACTION_CLOSE", None},
-    {"_NET_WM_ACTION_FULLSCREEN", None},
-    {"_NET_WM_ACTION_MOVE", None},
-    {"_NET_WM_ACTION_RESIZE", None},
-    {"_NET_WM_ALLOWED_ACTIONS", None},
-    {"_NET_WM_STATE", None},
-    {"_NET_WM_STATE_ABOVE", None},
-    {"_NET_WM_STATE_FULLSCREEN", None},
-    {"_NET_WM_STATE_HIDDEN", None},
-    {"_NET_WM_STATE_MAXIMIZED_HORZ", None},
-    {"_NET_WM_STATE_MAXIMIZED_VERT", None},
-    {"_NET_WM_STATE_SKIP_PAGER", None},
-    {"_NET_WM_STATE_SKIP_TASKBAR", None},
-    {"_NET_WM_WINDOW_TYPE", None},
-    {"_NET_WM_WINDOW_TYPE_DIALOG", None},
-    {"_NET_WM_WINDOW_TYPE_DOCK", None},
-    {"_NET_WM_WINDOW_TYPE_NORMAL", None},
-    {"_NET_WM_WINDOW_TYPE_SPLASH", None},
-    {"_NET_WM_WINDOW_TYPE_TOOLBAR", None},
-    {"_NET_WM_WINDOW_TYPE_UTILITY", None},
-    {"_SWM_WM_STATE_MANUAL", None},
+    {"_NET_ACTIVE_WINDOW", XCB_ATOM_NONE},
+    {"_NET_CLOSE_WINDOW", XCB_ATOM_NONE},
+    {"_NET_MOVERESIZE_WINDOW", XCB_ATOM_NONE},
+    {"_NET_WM_ACTION_CLOSE", XCB_ATOM_NONE},
+    {"_NET_WM_ACTION_FULLSCREEN", XCB_ATOM_NONE},
+    {"_NET_WM_ACTION_MOVE", XCB_ATOM_NONE},
+    {"_NET_WM_ACTION_RESIZE", XCB_ATOM_NONE},
+    {"_NET_WM_ALLOWED_ACTIONS", XCB_ATOM_NONE},
+    {"_NET_WM_STATE", XCB_ATOM_NONE},
+    {"_NET_WM_STATE_ABOVE", XCB_ATOM_NONE},
+    {"_NET_WM_STATE_FULLSCREEN", XCB_ATOM_NONE},
+    {"_NET_WM_STATE_HIDDEN", XCB_ATOM_NONE},
+    {"_NET_WM_STATE_MAXIMIZED_HORZ", XCB_ATOM_NONE},
+    {"_NET_WM_STATE_MAXIMIZED_VERT", XCB_ATOM_NONE},
+    {"_NET_WM_STATE_SKIP_PAGER", XCB_ATOM_NONE},
+    {"_NET_WM_STATE_SKIP_TASKBAR", XCB_ATOM_NONE},
+    {"_NET_WM_WINDOW_TYPE", XCB_ATOM_NONE},
+    {"_NET_WM_WINDOW_TYPE_DIALOG", XCB_ATOM_NONE},
+    {"_NET_WM_WINDOW_TYPE_DOCK", XCB_ATOM_NONE},
+    {"_NET_WM_WINDOW_TYPE_NORMAL", XCB_ATOM_NONE},
+    {"_NET_WM_WINDOW_TYPE_SPLASH", XCB_ATOM_NONE},
+    {"_NET_WM_WINDOW_TYPE_TOOLBAR", XCB_ATOM_NONE},
+    {"_NET_WM_WINDOW_TYPE_UTILITY", XCB_ATOM_NONE},
+    {"_SWM_WM_STATE_MANUAL", XCB_ATOM_NONE},
 };
 
 void            store_float_geom(struct ws_win *, struct swm_region *);
@@ -621,7 +622,7 @@ int          floating_toggle_win(struct ws_win *);
 void            constrain_window(struct ws_win *, struct swm_region *, int);
 void            update_window(struct ws_win *);
 void            spawn_select(struct swm_region *, union arg *, char *, int *);
-unsigned char  *get_win_name(Window);
+unsigned char  *get_win_name(xcb_window_t);
 
 int
 get_property(Window id, Atom atom, long count, Atom type, unsigned long *nitems,
@@ -649,76 +650,104 @@ get_property(Window id, Atom atom, long count, Atom type, unsigned long *nitems,
 void
 update_iconic(struct ws_win *win, int newv)
 {
-       int32_t v = newv;
-       Atom iprop;
+       int32_t                         v = newv;
+       xcb_atom_t                      iprop;
+       xcb_intern_atom_cookie_t        c;
+       xcb_intern_atom_reply_t         *r;
 
        win->iconic = newv;
 
-       iprop = XInternAtom(display, "_SWM_ICONIC", False);
-       if (!iprop)
+       c = xcb_intern_atom(conn, False, strlen("_SWM_ICONIC"), "_SWM_ICONIC");
+       r = xcb_intern_atom_reply(conn, c, NULL);
+       if (r) {
+               iprop = r->atom;
+               free(r);
+       } else
                return;
+               
        if (newv)
-               XChangeProperty(display, win->id, iprop, XA_INTEGER, 32,
-                   PropModeReplace, (unsigned char *)&v, 1);
+               xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->id,
+                       iprop, XCB_ATOM_INTEGER, 32, 1, &v);
        else
-               XDeleteProperty(display, win->id, iprop);
+               xcb_delete_property(conn, win->id, iprop);
 }
 
 int
 get_iconic(struct ws_win *win)
 {
-       int32_t v = 0;
-       int retfmt, status;
-       Atom iprop, rettype;
-       unsigned long nitems, extra;
-       unsigned char *prop = NULL;
-
-       iprop = XInternAtom(display, "_SWM_ICONIC", False);
-       if (!iprop)
-               goto out;
-       status = XGetWindowProperty(display, win->id, iprop, 0L, 1L,
-           False, XA_INTEGER, &rettype, &retfmt, &nitems, &extra, &prop);
-       if (status != Success)
-               goto out;
-       if (rettype != XA_INTEGER || retfmt != 32)
-               goto out;
-       if (nitems != 1)
+       int32_t v = 0, *vtmp;
+       xcb_atom_t                      iprop;
+       xcb_intern_atom_cookie_t        c;
+       xcb_intern_atom_reply_t         *r;
+       xcb_get_property_cookie_t       pc;
+       xcb_get_property_reply_t        *pr;
+
+       c = xcb_intern_atom(conn, False, strlen("_SWM_ICONIC"), "_SWM_ICONIC");
+       r = xcb_intern_atom_reply(conn, c, NULL);
+       if (r) {
+               iprop = r->atom;
+               free(r);
+       } else
                goto out;
-       v = *((int32_t *)prop);
 
+       pc = xcb_get_property(conn, False, win->id, iprop, XCB_ATOM_INTEGER,
+                       0, 1);
+       pr = xcb_get_property_reply(conn, pc, NULL);
+       if (!pr)
+               goto out;       
+       if (pr->type != XCB_ATOM_INTEGER || pr->format != 32)
+               goto out;
+       vtmp = xcb_get_property_value(pr);
+       v = *vtmp;
 out:
-       if (prop != NULL)
-               XFree(prop);
+       if (pr != NULL)
+               free(pr);
        return (v);
 }
 
 void
 setup_ewmh(void)
 {
-       int                     i,j;
-       Atom                    sup_list;
-
-       sup_list = XInternAtom(display, "_NET_SUPPORTED", False);
-
-       for (i = 0; i < LENGTH(ewmh); i++)
-               ewmh[i].atom = XInternAtom(display, ewmh[i].name, False);
+       xcb_atom_t                      sup_list;
+       xcb_intern_atom_cookie_t        c;
+       xcb_intern_atom_reply_t         *r;
+       int                             i, j, num_screens;
+
+       c = xcb_intern_atom(conn, False, strlen("_NET_SUPPORTED"),
+               "_NET_SUPPORTED");
+       r = xcb_intern_atom_reply(conn, c, NULL);
+       if (r) {
+               sup_list = r->atom;
+               free(r);
+       }
+       
+       for (i = 0; i < LENGTH(ewmh); i++) {
+               c = xcb_intern_atom(conn, False, strlen(ewmh[i].name),
+                       ewmh[i].name);
+               r = xcb_intern_atom_reply(conn, c, NULL);
+               if (r) {
+                       ewmh[i].atom = r->atom;
+                       free(r);
+               }
+       }
 
-       for (i = 0; i < ScreenCount(display); i++) {
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+       for (i = 0; i < num_screens; i++) {
                /* Support check window will be created by workaround(). */
 
                /* Report supported atoms */
-               XDeleteProperty(display, screens[i].root, sup_list);
+               xcb_delete_property(conn, screens[i].root, sup_list);
                for (j = 0; j < LENGTH(ewmh); j++)
-                       XChangeProperty(display, screens[i].root,
-                           sup_list, XA_ATOM, 32,
-                           PropModeAppend, (unsigned char *)&ewmh[j].atom, 1);
+                       xcb_change_property(conn, XCB_PROP_MODE_APPEND,
+                               screens[i].root, sup_list, XCB_ATOM_ATOM, 32, 1,
+                               &ewmh[j].atom);
        }
 }
 
 void
 teardown_ewmh(void)
 {
-       int                     i, success;
+       int                     i, success, num_screens;
        unsigned char           *data = NULL;
        unsigned long           n;
        Atom                    sup_check, sup_list;
@@ -727,7 +756,8 @@ teardown_ewmh(void)
        sup_check = XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", False);
        sup_list = XInternAtom(display, "_NET_SUPPORTED", False);
 
-       for (i = 0; i < ScreenCount(display); i++) {
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+       for (i = 0; i < num_screens; i++) {
                /* Get the support check window and destroy it */
                success = get_property(screens[i].root, sup_check, 1, XA_WINDOW,
                    &n, NULL, &data);
@@ -821,7 +851,7 @@ ewmh_set_win_fullscreen(struct ws_win *win, int fs)
 void
 ewmh_update_actions(struct ws_win *win)
 {
-       Atom                    actions[SWM_EWMH_ACTION_COUNT_MAX];
+       xcb_atom_t              actions[SWM_EWMH_ACTION_COUNT_MAX];
        int                     n = 0;
 
        if (win == NULL)
@@ -834,8 +864,9 @@ ewmh_update_actions(struct ws_win *win)
                actions[n++] = ewmh[_NET_WM_ACTION_RESIZE].atom;
        }
 
-       XChangeProperty(display, win->id, ewmh[_NET_WM_ALLOWED_ACTIONS].atom,
-           XA_ATOM, 32, PropModeReplace, (unsigned char *)actions, n);
+       xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->id,
+               ewmh[_NET_WM_ALLOWED_ACTIONS].atom, XCB_ATOM_ATOM, 32, 1,
+               actions);
 }
 
 #define _NET_WM_STATE_REMOVE   0    /* remove/unset property */
@@ -893,28 +924,28 @@ ewmh_update_win_state(struct ws_win *win, long state, long action)
                            win->ewmh_flags & EWMH_F_FULLSCREEN))
                                win->ewmh_flags = orig_flags; /* revert */
 
-       XDeleteProperty(display, win->id, ewmh[_NET_WM_STATE].atom);
+       xcb_delete_property(conn, win->id, ewmh[_NET_WM_STATE].atom);
 
        if (win->ewmh_flags & EWMH_F_FULLSCREEN)
-               XChangeProperty(display, win->id, ewmh[_NET_WM_STATE].atom,
-                   XA_ATOM, 32, PropModeAppend,
-                   (unsigned char *)&ewmh[_NET_WM_STATE_FULLSCREEN].atom, 1);
+               xcb_change_property(conn, XCB_PROP_MODE_APPEND, win->id,
+                       ewmh[_NET_WM_STATE].atom, XCB_ATOM_ATOM, 32, 1,
+                       &ewmh[_NET_WM_STATE_FULLSCREEN].atom);
        if (win->ewmh_flags & EWMH_F_SKIP_PAGER)
-               XChangeProperty(display, win->id, ewmh[_NET_WM_STATE].atom,
-                   XA_ATOM, 32, PropModeAppend,
-                   (unsigned char *)&ewmh[_NET_WM_STATE_SKIP_PAGER].atom, 1);
+               xcb_change_property(conn, XCB_PROP_MODE_APPEND, win->id,
+                       ewmh[_NET_WM_STATE].atom, XCB_ATOM_ATOM, 32, 1,
+                       &ewmh[_NET_WM_STATE_SKIP_PAGER].atom);  
        if (win->ewmh_flags & EWMH_F_SKIP_TASKBAR)
-               XChangeProperty(display, win->id, ewmh[_NET_WM_STATE].atom,
-                   XA_ATOM, 32, PropModeAppend,
-                   (unsigned char *)&ewmh[_NET_WM_STATE_SKIP_TASKBAR].atom, 1);
+               xcb_change_property(conn, XCB_PROP_MODE_APPEND, win->id,
+                       ewmh[_NET_WM_STATE].atom, XCB_ATOM_ATOM, 32, 1,
+                       &ewmh[_NET_WM_STATE_SKIP_TASKBAR].atom);
        if (win->ewmh_flags & EWMH_F_ABOVE)
-               XChangeProperty(display, win->id, ewmh[_NET_WM_STATE].atom,
-                   XA_ATOM, 32, PropModeAppend,
-                   (unsigned char *)&ewmh[_NET_WM_STATE_ABOVE].atom, 1);
+               xcb_change_property(conn, XCB_PROP_MODE_APPEND, win->id,
+                       ewmh[_NET_WM_STATE].atom, XCB_ATOM_ATOM, 32, 1,
+                       &ewmh[_NET_WM_STATE_ABOVE].atom);
        if (win->ewmh_flags & SWM_F_MANUAL)
-               XChangeProperty(display, win->id, ewmh[_NET_WM_STATE].atom,
-                   XA_ATOM, 32, PropModeAppend,
-                   (unsigned char *)&ewmh[_SWM_WM_STATE_MANUAL].atom, 1);
+               xcb_change_property(conn, XCB_PROP_MODE_APPEND, win->id,
+                       ewmh[_NET_WM_STATE].atom, XCB_ATOM_ATOM, 32, 1,
+                       &ewmh[_SWM_WM_STATE_MANUAL].atom);
 }
 
 void
@@ -1220,26 +1251,34 @@ find_pid(long pid)
        return (NULL);
 }
 
-unsigned long
-name_to_color(char *colorname)
+uint32_t
+name_to_color(const char *colorname)
 {
-       Colormap                cmap;
-       Status                  status;
-       XColor                  screen_def, exact_def;
-       unsigned long           result = 0;
-       char                    cname[32] = "#";
+       uint32_t                        result = 0;
+       char                            cname[32] = "#";
+       xcb_screen_t                    *screen;
+       xcb_colormap_t                  cmap;
+       xcb_alloc_named_color_cookie_t  c;
+       xcb_alloc_named_color_reply_t   *r;
 
-       cmap = DefaultColormap(display, screens[0].idx);
-       status = XAllocNamedColor(display, cmap, colorname,
-           &screen_def, &exact_def);
-       if (!status) {
+       /* XXX - does not support rgb:/RR/GG/BB
+        *       will need to use xcb_alloc_color
+        */
+       screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
+       cmap = screen->default_colormap;
+
+       c = xcb_alloc_named_color(conn, cmap, strlen(colorname), colorname);
+       r = xcb_alloc_named_color_reply(conn, c, NULL);
+       if (!r) {
                strlcat(cname, colorname + 2, sizeof cname - 1);
-               status = XAllocNamedColor(display, cmap, cname, &screen_def,
-                   &exact_def);
+               c = xcb_alloc_named_color(conn, cmap, strlen(cname),
+                       cname);
+               r = xcb_alloc_named_color_reply(conn, c, NULL);
        }
-       if (status)
-               result = screen_def.pixel;
-       else
+       if (r) {
+               result = r->pixel;
+               free(r);
+       } else
                warnx("color '%s' not found", colorname);
 
        return (result);
@@ -1248,13 +1287,16 @@ name_to_color(char *colorname)
 void
 setscreencolor(char *val, int i, int c)
 {
-       if (i > 0 && i <= ScreenCount(display)) {
+       int     num_screens;
+
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+       if (i > 0 && i <= num_screens) {
                screens[i - 1].c[c].color = name_to_color(val);
                free(screens[i - 1].c[c].name);
                if ((screens[i - 1].c[c].name = strdup(val)) == NULL)
                        err(1, "strdup");
        } else if (i == -1) {
-               for (i = 0; i < ScreenCount(display); i++) {
+               for (i = 0; i < num_screens; i++) {
                        screens[i].c[c].color = name_to_color(val);
                        free(screens[i].c[c].name);
                        if ((screens[i].c[c].name = strdup(val)) == NULL)
@@ -1262,7 +1304,7 @@ setscreencolor(char *val, int i, int c)
                }
        } else
                errx(1, "invalid screen index: %d out of bounds (maximum %d)",
-                   i, ScreenCount(display));
+                   i, num_screens);
 }
 
 void
@@ -1295,13 +1337,15 @@ void
 custom_region(char *val)
 {
        unsigned int                    sidx, x, y, w, h;
+       int                             num_screens;
 
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));      
        if (sscanf(val, "screen[%u]:%ux%u+%u+%u", &sidx, &w, &h, &x, &y) != 5)
                errx(1, "invalid custom region, "
                    "should be 'screen[<n>]:<n>x<n>+<n>+<n>");
-       if (sidx < 1 || sidx > ScreenCount(display))
+       if (sidx < 1 || sidx > num_screens)
                errx(1, "invalid screen index: %d out of bounds (maximum %d)",
-                   sidx, ScreenCount(display));
+                   sidx, num_screens);
        sidx--;
 
        if (w < 1 || h < 1)
@@ -1447,13 +1491,14 @@ bar_urgent(char *s, size_t sz)
 {
        XWMHints                *wmh = NULL;
        struct ws_win           *win;
-       int                     i, j;
+       int                     i, j, num_screens;
        char                    b[8];
 
        for (i = 0; i < workspace_limit; i++)
                urgent[i] = 0;
 
-       for (i = 0; i < ScreenCount(display); i++)
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+       for (i = 0; i < num_screens; i++)
                for (j = 0; j < workspace_limit; j++)
                        TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry) {
                                wmh = XGetWMHints(display, win->id);
@@ -1539,46 +1584,44 @@ bar_fmt(const char *fmtexp, char *fmtnew, struct swm_region *r, size_t sz)
        strlcat(fmtnew, "+4<+A+4<+V", sz);
 }
 
+void
+bar_replace_pad(char *tmp, int *limit, size_t sz)
+{
+       /* special case; no limit given, pad one space, instead */
+       if (*limit == sz - 1)
+               *limit = 1;
+       snprintf(tmp, sz, "%*s", *limit, " ");
+}
+
 /* replaces the bar format character sequences (like in tmux(1)) */
 char *
 bar_replace_seq(char *fmt, char *fmtrep, struct swm_region *r, size_t *offrep,
     size_t sz)
 {
        char                    *ptr;
-       char                    num[8], tmp[SWM_BAR_MAX];
-       int                     limit;
-       size_t                  len, numoff = 0;
+       char                    tmp[SWM_BAR_MAX];
+       int                     limit, size;
+       size_t                  len;
 
        /* reset strlcat(3) buffer */
        *tmp = '\0';
 
        /* get number, if any */
        fmt++;
-       while (*fmt != '\0' && isdigit((unsigned char) *fmt)) {
-               if (numoff >= sizeof num - 1)
-                       break;
-               num[numoff++] = *fmt++;
-       }
-       num[numoff] = '\0';
-
-       if ((limit = strtonum(num, 1, sizeof tmp - 1, NULL)) == 0)
+       size = 0;
+       if (sscanf(fmt, "%d%n", &limit, &size) != 1)
+               limit = sizeof tmp - 1;
+       if (limit <= 0 || limit >= sizeof tmp)
                limit = sizeof tmp - 1;
 
-       /* if number is too big, skip to the first non-digit */
-       if (numoff >= sizeof num - 1) {
-               while (*fmt != '\0' && isdigit((unsigned char) *fmt))
-                       fmt++;
-       }
        /* there is nothing to replace (ie EOL) */
+       fmt += size;
        if (*fmt == '\0')
                return (fmt);
 
        switch (*fmt) {
        case '<':
-               /* special case; no limit given, pad one space, instead */
-               if (limit == sizeof tmp - 1)
-                       limit = 1;
-               snprintf(tmp, sizeof tmp, "%*s", limit, " ");
+               bar_replace_pad(tmp, &limit, sizeof tmp);
                break;
        case 'A':
                snprintf(tmp, sizeof tmp, "%s", bar_ext);
@@ -1698,13 +1741,14 @@ bar_fmt_print(void)
 {
        char                    fmtexp[SWM_BAR_MAX], fmtnew[SWM_BAR_MAX];
        char                    fmtrep[SWM_BAR_MAX];
-       int                     i;
+       int                     i, num_screens;
        struct swm_region       *r;
 
        /* expand the format by first passing it through strftime(3) */
        bar_fmt_expand(fmtexp, sizeof fmtexp);
 
-       for (i = 0; i < ScreenCount(display); i++) {
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+       for (i = 0; i < num_screens; i++) {
                TAILQ_FOREACH(r, &screens[i].rl, entry) {
                        if (r->bar == NULL)
                                continue;
@@ -1751,17 +1795,18 @@ void
 bar_toggle(struct swm_region *r, union arg *args)
 {
        struct swm_region       *tmpr;
-       int                     i, sc = ScreenCount(display);
+       int                     i, num_screens; 
 
        DNPRINTF(SWM_D_BAR, "bar_toggle\n");
 
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
        if (bar_enabled) {
-               for (i = 0; i < sc; i++)
+               for (i = 0; i < num_screens; i++)
                        TAILQ_FOREACH(tmpr, &screens[i].rl, entry)
                                if (tmpr->bar)
                                        XUnmapWindow(display, tmpr->bar->id);
        } else {
-               for (i = 0; i < sc; i++)
+               for (i = 0; i < num_screens; i++)
                        TAILQ_FOREACH(tmpr, &screens[i].rl, entry)
                                if (tmpr->bar)
                                        XMapRaised(display, tmpr->bar->id);
@@ -1777,9 +1822,9 @@ bar_toggle(struct swm_region *r, union arg *args)
 void
 bar_refresh(void)
 {
-       XSetWindowAttributes    wa;
        struct swm_region       *r;
-       int                     i;
+       uint32_t                wa[2];
+       int                     i, num_screens;
 
        /* do this here because the conf file is in memory */
        if (bar_extra && bar_extra_running == 0 && bar_argv[0]) {
@@ -1810,17 +1855,15 @@ bar_refresh(void)
                }
        }
 
-       bzero(&wa, sizeof wa);
-       for (i = 0; i < ScreenCount(display); i++)
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+       for (i = 0; i < num_screens; i++)
                TAILQ_FOREACH(r, &screens[i].rl, entry) {
                        if (r->bar == NULL)
                                continue;
-                       wa.border_pixel =
-                           screens[i].c[SWM_S_COLOR_BAR_BORDER].color;
-                       wa.background_pixel =
-                           screens[i].c[SWM_S_COLOR_BAR].color;
-                       XChangeWindowAttributes(display, r->bar->id,
-                           CWBackPixel | CWBorderPixel, &wa);
+                       wa[0] = screens[i].c[SWM_S_COLOR_BAR].color;
+                       wa[1] = screens[i].c[SWM_S_COLOR_BAR_BORDER].color;
+                       xcb_change_window_attributes(conn, r->bar->id,
+                               XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL, wa);
                }
        bar_update();
 }
@@ -1904,8 +1947,8 @@ bar_cleanup(struct swm_region *r)
 {
        if (r->bar == NULL)
                return;
-       XDestroyWindow(display, r->bar->id);
-       XFreePixmap(display, r->bar->buffer);
+       xcb_destroy_window(conn, r->bar->id);
+       xcb_free_pixmap(conn, r->bar->buffer);
        free(r->bar);
        r->bar = NULL;
 }
@@ -1937,7 +1980,7 @@ set_win_state(struct ws_win *win, long state)
 }
 
 long
-getstate(Window w)
+getstate(xcb_window_t w)
 {
        long                    result = -1;
        unsigned char           *p = NULL;
@@ -2109,9 +2152,9 @@ void
 unmap_all(void)
 {
        struct ws_win           *win;
-       int                     i, j;
+       int                     i, j, num_screens;
 
-       for (i = 0; i < ScreenCount(display); i++)
+       for (i = 0; i < num_screens; i++)
                for (j = 0; j < workspace_limit; j++)
                        TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry)
                                unmap_window(win);
@@ -2172,12 +2215,13 @@ root_to_region(Window root)
 {
        struct swm_region       *r = NULL;
        Window                  rr, cr;
-       int                     i, x, y, wx, wy;
+       int                     i, x, y, wx, wy, num_screens;
        unsigned int            mask;
 
        DNPRINTF(SWM_D_MISC, "root_to_region: window: 0x%lx\n", root);
 
-       for (i = 0; i < ScreenCount(display); i++)
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+       for (i = 0; i < num_screens; i++)
                if (screens[i].root == root)
                        break;
 
@@ -2202,9 +2246,10 @@ struct ws_win *
 find_unmanaged_window(Window id)
 {
        struct ws_win           *win;
-       int                     i, j;
+       int                     i, j, num_screens;
 
-       for (i = 0; i < ScreenCount(display); i++)
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+       for (i = 0; i < num_screens; i++)
                for (j = 0; j < workspace_limit; j++)
                        TAILQ_FOREACH(win, &screens[i].ws[j].unmanagedlist,
                            entry)
@@ -2214,14 +2259,15 @@ find_unmanaged_window(Window id)
 }
 
 struct ws_win *
-find_window(Window id)
+find_window(xcb_window_t id)
 {
        struct ws_win           *win;
        Window                  wrr, wpr, *wcr = NULL;
-       int                     i, j;
+       int                     i, j, num_screens;
        unsigned int            nc;
 
-       for (i = 0; i < ScreenCount(display); i++)
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+       for (i = 0; i < num_screens; i++)
                for (j = 0; j < workspace_limit; j++)
                        TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry)
                                if (id == win->id)
@@ -2238,7 +2284,7 @@ find_window(Window id)
                return (NULL);
 
        /* look for parent */
-       for (i = 0; i < ScreenCount(display); i++)
+       for (i = 0; i < num_screens; i++)
                for (j = 0; j < workspace_limit; j++)
                        TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry)
                                if (wpr == win->id)
@@ -2306,14 +2352,15 @@ spawn(int ws_idx, union arg *args, int close_fd)
 void
 kill_refs(struct ws_win *win)
 {
-       int                     i, x;
+       int                     i, x, num_screens;
        struct swm_region       *r;
        struct workspace        *ws;
 
        if (win == NULL)
                return;
 
-       for (i = 0; i < ScreenCount(display); i++)
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+       for (i = 0; i < num_screens; i++)
                TAILQ_FOREACH(r, &screens[i].rl, entry)
                        for (x = 0; x < workspace_limit; x++) {
                                ws = &r->s->ws[x];
@@ -2330,12 +2377,13 @@ validate_win(struct ws_win *testwin)
        struct ws_win           *win;
        struct workspace        *ws;
        struct swm_region       *r;
-       int                     i, x;
+       int                     i, x, num_screens;
 
        if (testwin == NULL)
                return (0);
 
-       for (i = 0; i < ScreenCount(display); i++)
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+       for (i = 0; i < num_screens; i++)
                TAILQ_FOREACH(r, &screens[i].rl, entry)
                        for (x = 0; x < workspace_limit; x++) {
                                ws = &r->s->ws[x];
@@ -2351,10 +2399,11 @@ validate_ws(struct workspace *testws)
 {
        struct swm_region       *r;
        struct workspace        *ws;
-       int                     i, x;
+       int                     i, x, num_screens;
 
        /* validate all ws */
-       for (i = 0; i < ScreenCount(display); i++)
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+       for (i = 0; i < num_screens; i++)
                TAILQ_FOREACH(r, &screens[i].rl, entry)
                        for (x = 0; x < workspace_limit; x++) {
                                ws = &r->s->ws[x];
@@ -2368,7 +2417,7 @@ void
 unfocus_win(struct ws_win *win)
 {
        XEvent                  cne;
-       Window                  none = None;
+       xcb_window_t            none = XCB_WINDOW_NONE;
 
        DNPRINTF(SWM_D_FOCUS, "unfocus_win: window: 0x%lx\n", WINID(win));
 
@@ -2410,20 +2459,21 @@ unfocus_win(struct ws_win *win)
        XSetWindowBorder(display, win->id,
            win->ws->r->s->c[SWM_S_COLOR_UNFOCUS].color);
 
-       XChangeProperty(display, win->s->root,
-           ewmh[_NET_ACTIVE_WINDOW].atom, XA_WINDOW, 32,
-           PropModeReplace, (unsigned char *)&none, 1);
+       xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->s->root,
+               ewmh[_NET_ACTIVE_WINDOW].atom, XCB_ATOM_WINDOW, 32, 1,
+               &none);
 }
 
 void
 unfocus_all(void)
 {
        struct ws_win           *win;
-       int                     i, j;
+       int                     i, j, num_screens;
 
        DNPRINTF(SWM_D_FOCUS, "unfocus_all\n");
 
-       for (i = 0; i < ScreenCount(display); i++)
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+       for (i = 0; i < num_screens; i++)
                for (j = 0; j < workspace_limit; j++)
                        TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry)
                                unfocus_win(win);
@@ -2617,10 +2667,11 @@ cyclescr(struct swm_region *r, union arg *args)
 {
        struct swm_region       *rr = NULL;
        union arg               a;
-       int                     i, x, y;
+       int                     i, x, y, num_screens;
 
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
        /* do nothing if we don't have more than one screen */
-       if (!(ScreenCount(display) > 1 || outputs > 1))
+       if (!(num_screens > 1 || outputs > 1))
                return;
 
        i = r->s->idx;
@@ -2980,14 +3031,15 @@ void
 stack(void) {
        struct swm_geometry     g;
        struct swm_region       *r;
-       int                     i;
+       int                     i, num_screens;
 #ifdef SWM_DEBUG
        int j;
 #endif
 
        DNPRINTF(SWM_D_STACK, "stack: begin\n");
-
-       for (i = 0; i < ScreenCount(display); i++) {
+       
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+       for (i = 0; i < num_screens; i++) {
 #ifdef SWM_DEBUG
                j = 0;
 #endif
@@ -3449,7 +3501,7 @@ max_stack(struct workspace *ws, struct swm_geometry *g)
 {
        struct swm_geometry     gg = *g;
        struct ws_win           *win, *wintrans = NULL, *parent = NULL;
-       int                     winno;
+       int                     winno, num_screens;
 
        DNPRINTF(SWM_D_STACK, "max_stack: workspace: %d\n", ws->idx);
 
@@ -3460,6 +3512,7 @@ max_stack(struct workspace *ws, struct swm_geometry *g)
        if (winno == 0 && count_win(ws, 1) == 0)
                return;
 
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
        TAILQ_FOREACH(win, &ws->winlist, entry) {
                if (win->transient) {
                        wintrans = win;
@@ -3492,7 +3545,7 @@ max_stack(struct workspace *ws, struct swm_geometry *g)
                }
                /* unmap only if we don't have multi screen */
                if (win != ws->focus)
-                       if (!(ScreenCount(display) > 1 || outputs > 1))
+                       if (!(num_screens > 1 || outputs > 1))
                                unmap_window(win);
        }
 
@@ -3603,7 +3656,7 @@ iconify(struct swm_region *r, union arg *args)
 }
 
 unsigned char *
-get_win_name(Window win)
+get_win_name(xcb_window_t win)
 {
        unsigned char           *prop = NULL;
        unsigned long           nbytes, nitems;
@@ -3668,7 +3721,7 @@ uniconify(struct swm_region *r, union arg *args)
                name = get_win_name(win->id);
                if (name == NULL)
                        continue;
-               fprintf(lfile, "%s.%lu\n", name, win->id);
+               fprintf(lfile, "%s.%u\n", name, win->id);
                XFree(name);
        }
 
@@ -3825,7 +3878,7 @@ search_resp_uniconify(char *resp, unsigned long len)
                name = get_win_name(win->id);
                if (name == NULL)
                        continue;
-               if (asprintf(&s, "%s.%lu", name, win->id) == -1) {
+               if (asprintf(&s, "%s.%u", name, win->id) == -1) {
                        XFree(name);
                        continue;
                }
@@ -4106,23 +4159,23 @@ constrain_window(struct ws_win *win, struct swm_region *r, int resizable)
 void
 update_window(struct ws_win *win)
 {
-       unsigned int            mask;
-       XWindowChanges          wc;
+       uint16_t        mask;
+       uint32_t        wc[5];
 
-       bzero(&wc, sizeof wc);
-       mask = CWBorderWidth | CWWidth | CWHeight | CWX | CWY;
+       mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y |
+               XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT |
+               XCB_CONFIG_WINDOW_BORDER_WIDTH; 
+       wc[0] = X(win);
+       wc[1] = Y(win);
+       wc[2] = WIDTH(win);
+       wc[3] = HEIGHT(win);
+       wc[4] = BORDER(win);
 
-       wc.border_width = BORDER(win);
-       wc.x = X(win);
-       wc.y = Y(win);
-       wc.width = WIDTH(win);
-       wc.height = HEIGHT(win);
+       DNPRINTF(SWM_D_EVENT, "update_window: window: 0x%x, (x,y) w x h: "
+           "(%d,%d) %d x %d, bordered: %s\n", win->id, wc[0], wc[1], wc[2],
+           wc[3], YESNO(win->bordered));
 
-       DNPRINTF(SWM_D_EVENT, "update_window: window: 0x%lx, (x,y) w x h: "
-           "(%d,%d) %d x %d, bordered: %s\n", win->id, wc.x, wc.y, wc.width,
-           wc.height, YESNO(win->bordered));
-
-       XConfigureWindow(display, win->id, mask, &wc);
+       xcb_configure_window(conn, win->id, mask, wc);
 }
 
 #define SWM_RESIZE_STEPS       (50)
@@ -5332,6 +5385,7 @@ updatenumlockmask(void)
 void
 grabkeys(void)
 {
+       int                     num_screens;
        unsigned int            j, k;
        KeyCode                 code;
        unsigned int            modifiers[] =
@@ -5341,7 +5395,8 @@ grabkeys(void)
        DNPRINTF(SWM_D_MISC, "grabkeys\n");
        updatenumlockmask();
 
-       for (k = 0; k < ScreenCount(display); k++) {
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+       for (k = 0; k < num_screens; k++) {
                if (TAILQ_EMPTY(&screens[k].rl))
                        continue;
                XUngrabKey(display, AnyKey, AnyModifier, screens[k].root);
@@ -5364,19 +5419,25 @@ grabbuttons(struct ws_win *win, int focused)
            { 0, LockMask, numlockmask, numlockmask|LockMask };
 
        updatenumlockmask();
-       XUngrabButton(display, AnyButton, AnyModifier, win->id);
+       xcb_ungrab_button(conn, XCB_BUTTON_INDEX_ANY, win->id,
+               XCB_BUTTON_MASK_ANY);
        if (focused) {
                for (i = 0; i < LENGTH(buttons); i++)
                        if (buttons[i].action == client_click)
                                for (j = 0; j < LENGTH(modifiers); j++)
-                                       XGrabButton(display, buttons[i].button,
-                                           buttons[i].mask | modifiers[j],
-                                           win->id, False, BUTTONMASK,
-                                           GrabModeAsync, GrabModeSync, None,
-                                           None);
+                                       xcb_grab_button(conn, False, win->id,
+                                               BUTTONMASK,
+                                               XCB_GRAB_MODE_ASYNC,
+                                               XCB_GRAB_MODE_SYNC,
+                                               XCB_WINDOW_NONE,
+                                               XCB_CURSOR_NONE,
+                                               buttons[i].button,
+                                               buttons[i].mask);
        } else
-               XGrabButton(display, AnyButton, AnyModifier, win->id, False,
-                   BUTTONMASK, GrabModeAsync, GrabModeSync, None, None);
+               xcb_grab_button(conn, False, win->id, BUTTONMASK,
+                       XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_SYNC,
+                       XCB_WINDOW_NONE, XCB_CURSOR_NONE, XCB_BUTTON_INDEX_ANY,
+                       XCB_BUTTON_MASK_ANY); 
 }
 
 const char *quirkname[] = {
@@ -5848,7 +5909,7 @@ int
 setlayout(char *selector, char *value, int flags)
 {
        int                     ws_id, i, x, mg, ma, si, raise, f = 0;
-       int                     st = SWM_V_STACK;
+       int                     st = SWM_V_STACK, num_screens;
        char                    s[1024];
        struct workspace        *ws;
 
@@ -5882,7 +5943,8 @@ setlayout(char *selector, char *value, int flags)
                    "<master_grow>:<master_add>:<stack_inc>:<always_raise>:"
                    "<type>'");
 
-       for (i = 0; i < ScreenCount(display); i++) {
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+       for (i = 0; i < num_screens; i++) {
                ws = (struct workspace *)&screens[i].ws;
                ws[ws_id].cur_layout = &layouts[st];
 
@@ -6104,7 +6166,7 @@ set_child_transient(struct ws_win *win, Window *trans)
                    " for 0x%lx trans 0x%lx\n", win->id, win->transient);
 
                if (win->hints == NULL) {
-                       warnx("no hints for 0x%lx", win->id);
+                       warnx("no hints for 0x%x", win->id);
                        return;
                }
 
@@ -6116,7 +6178,7 @@ set_child_transient(struct ws_win *win, Window *trans)
                                XFree(wmh);
 
                        if ((wmh = XGetWMHints(display, w->id)) == NULL) {
-                               warnx("can't get hints for 0x%lx", w->id);
+                               warnx("can't get hints for 0x%x", w->id);
                                continue;
                        }
 
@@ -6127,7 +6189,7 @@ set_child_transient(struct ws_win *win, Window *trans)
                        win->transient = w->id;
                        *trans = w->id;
                        DNPRINTF(SWM_D_MISC, "set_child_transient: asjusting "
-                           "transient to 0x%lx\n", win->transient);
+                           "transient to 0x%x\n", win->transient);
                        break;
                }
        }
@@ -6139,45 +6201,51 @@ set_child_transient(struct ws_win *win, Window *trans)
 long
 window_get_pid(Window win)
 {
-       Atom                    actual_type_return;
-       int                     actual_format_return = 0;
-       unsigned long           nitems_return = 0;
-       unsigned long           bytes_after_return = 0;
-       long                    *pid = NULL;
-       long                    ret = 0;
-       const char              *errstr;
-       unsigned char           *prop = NULL;
-
-       if (XGetWindowProperty(display, win,
-           XInternAtom(display, "_NET_WM_PID", False), 0, 1, False,
-           XA_CARDINAL, &actual_type_return, &actual_format_return,
-           &nitems_return, &bytes_after_return,
-           (unsigned char**)(void*)&pid) != Success)
+       long                            ret = 0;
+       const char                      *errstr;
+       xcb_atom_t                      apid;
+       xcb_intern_atom_cookie_t        c;
+       xcb_intern_atom_reply_t         *r;
+       xcb_get_property_cookie_t       pc;
+       xcb_get_property_reply_t        *pr;    
+
+       c = xcb_intern_atom(conn, False, strlen("_NET_WM_PID"), "_NET_WM_PID");
+       r = xcb_intern_atom_reply(conn, c, NULL);
+       if (r) {
+               apid = r->atom;
+               free(r);
+       } else
                goto tryharder;
-       if (actual_type_return != XA_CARDINAL)
+
+       pc = xcb_get_property(conn, False, win, apid, XCB_ATOM_CARDINAL, 0, 1);
+       pr = xcb_get_property_reply(conn, pc, NULL);
+       if (!pr)
                goto tryharder;
-       if (pid == NULL)
+       if (pr->type != XCB_ATOM_CARDINAL)
                goto tryharder;
 
-       ret = *pid;
-       XFree(pid);
+       ret = *(long *)xcb_get_property_value(pr);
+       free(pr);
 
        return (ret);
 
 tryharder:
-       if (XGetWindowProperty(display, win,
-           XInternAtom(display, "_SWM_PID", False), 0, SWM_PROPLEN, False,
-           XA_STRING, &actual_type_return, &actual_format_return,
-           &nitems_return, &bytes_after_return, &prop) != Success)
+       c = xcb_intern_atom(conn, False, strlen("_SWM_PID"), "_SWM_PID");
+       r = xcb_intern_atom_reply(conn, c, NULL);
+       if (r) {
+               apid = r->atom;
+               free(r);
+       }
+       pc = xcb_get_property(conn, False, win, apid, XCB_ATOM_STRING,
+               0, SWM_PROPLEN);
+       pr = xcb_get_property_reply(conn, pc, NULL);
+       if (!pr)
                return (0);
-       if (actual_type_return != XA_STRING)
+       if (pr->type != XCB_ATOM_STRING)
+               free(pr);
                return (0);
-       if (prop == NULL)
-               return (0);
-
-       ret = strtonum((const char *)prop, 0, UINT_MAX, &errstr);
-       /* ignore error because strtonum returns 0 anyway */
-       XFree(prop);
+       ret = strtonum(xcb_get_property_value(pr), 0, UINT_MAX, &errstr);
+       free(pr);
 
        return (ret);
 }
@@ -6213,9 +6281,10 @@ manage_window(Window id)
                        TAILQ_INSERT_AFTER(&win->ws->winlist, ww, win, entry);
                else if ((ww = win->ws->focus) &&
                    spawn_position == SWM_STACK_ABOVE)
-                       TAILQ_INSERT_AFTER(&win->ws->winlist, win->ws->focus, win, entry);
+                       TAILQ_INSERT_AFTER(&win->ws->winlist, win->ws->focus,
+                           win, entry);
                else if (ww && spawn_position == SWM_STACK_BELOW)
-                       TAILQ_INSERT_AFTER(&win->ws->winlist, win->ws->focus, win, entry);
+                       TAILQ_INSERT_BEFORE(win->ws->focus, win, entry);
                else switch (spawn_position) {
                default:
                case SWM_STACK_TOP:
@@ -6314,10 +6383,21 @@ manage_window(Window id)
        win->s = r->s;  /* this never changes */
        if (trans && (ww = find_window(trans)))
                TAILQ_INSERT_AFTER(&ws->winlist, ww, win, entry);
-       else if (spawn_position == SWM_STACK_ABOVE && win->ws->focus)
-               TAILQ_INSERT_AFTER(&win->ws->winlist, win->ws->focus, win, entry);
-       else
-               TAILQ_INSERT_TAIL(&ws->winlist, win, entry);
+       else if (win->ws->focus && spawn_position == SWM_STACK_ABOVE)
+               TAILQ_INSERT_AFTER(&win->ws->winlist, win->ws->focus, win,
+                   entry);
+       else if (win->ws->focus && spawn_position == SWM_STACK_BELOW)
+               TAILQ_INSERT_BEFORE(win->ws->focus, win, entry);
+       else switch (spawn_position) {
+       default:
+       case SWM_STACK_TOP:
+       case SWM_STACK_ABOVE:
+               TAILQ_INSERT_TAIL(&win->ws->winlist, win, entry);
+               break;
+       case SWM_STACK_BOTTOM:
+       case SWM_STACK_BELOW:
+               TAILQ_INSERT_HEAD(&win->ws->winlist, win, entry);
+       }
 
        /* ignore window border if there is one. */
        WIDTH(win) = win->wa.width;
@@ -6956,29 +7036,39 @@ unmapnotify(XEvent *e)
 void
 visibilitynotify(XEvent *e)
 {
-       int                     i;
+       int                     i, num_screens;
        struct swm_region       *r;
 
        DNPRINTF(SWM_D_EVENT, "visibilitynotify: window: 0x%lx\n",
            e->xvisibility.window);
-       if (e->xvisibility.state == VisibilityUnobscured)
-               for (i = 0; i < ScreenCount(display); i++)
+
+       if (e->xvisibility.state == VisibilityUnobscured) {
+               num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+               for (i = 0; i < num_screens; i++)
                        TAILQ_FOREACH(r, &screens[i].rl, entry)
                                if (e->xvisibility.window == WINID(r->bar))
                                        bar_update();
+       }
 }
 
 void
 clientmessage(XEvent *e)
 {
-       XClientMessageEvent *ev;
-       struct ws_win *win;
+       XClientMessageEvent     *ev;
+       struct ws_win           *win;
 
        ev = &e->xclient;
 
        win = find_window(ev->window);
-       if (win == NULL)
+       if (win == NULL) {
+               if (ev->message_type == ewmh[_NET_ACTIVE_WINDOW].atom) {
+                       DNPRINTF(SWM_D_EVENT, "clientmessage: request focus on "
+                           "unmanaged window.\n");
+                       e->xmaprequest.window = ev->window;
+                       maprequest(e);
+               }
                return;
+       }
 
        DNPRINTF(SWM_D_EVENT, "clientmessage: window: 0x%lx, type: %ld\n",
            ev->window, ev->message_type);
@@ -7143,9 +7233,10 @@ scan_xrandr(int i)
        int                     ncrtc = 0;
 #endif /* SWM_XRR_HAS_CRTC */
        struct swm_region       *r;
+       int                     num_screens;
 
-
-       if (i >= ScreenCount(display))
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+       if (i >= num_screens)
                errx(1, "scan_xrandr: invalid screen");
 
        /* remove any old regions */
@@ -7160,7 +7251,7 @@ scan_xrandr(int i)
        /* map virtual screens onto physical screens */
 #ifdef SWM_XRR_HAS_CRTC
        if (xrandr_support) {
-               sr = XRRGetScreenResources(display, screens[i].root);
+               sr = XRRGetScreenResourcesCurrent(display, screens[i].root);
                if (sr == NULL)
                        new_region(&screens[i], 0, 0,
                            DisplayWidth(display, i),
@@ -7196,25 +7287,26 @@ void
 screenchange(XEvent *e) {
        XRRScreenChangeNotifyEvent      *xe = (XRRScreenChangeNotifyEvent *)e;
        struct swm_region               *r;
-       int                             i;
+       int                             i, num_screens;
 
        DNPRINTF(SWM_D_EVENT, "screenchange: root: 0x%lx\n", xe->root);
 
        if (!XRRUpdateConfiguration(e))
                return;
 
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
        /* silly event doesn't include the screen index */
-       for (i = 0; i < ScreenCount(display); i++)
+       for (i = 0; i < num_screens; i++)
                if (screens[i].root == xe->root)
                        break;
-       if (i >= ScreenCount(display))
+       if (i >= num_screens)
                errx(1, "screenchange: screen not found");
 
        /* brute force for now, just re-enumerate the regions */
        scan_xrandr(i);
 
        /* add bars to all regions */
-       for (i = 0; i < ScreenCount(display); i++)
+       for (i = 0; i < num_screens; i++)
                TAILQ_FOREACH(r, &screens[i].rl, entry)
                        bar_setup(r);
        stack();
@@ -7228,10 +7320,11 @@ grab_windows(void)
        Window                  d1, d2, *wins = NULL;
        XWindowAttributes       wa;
        unsigned int            no;
-       int                     i, j;
+       int                     i, j, num_screens;
        long                    state, manage;
 
-       for (i = 0; i < ScreenCount(display); i++) {
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+       for (i = 0; i < num_screens; i++) {
                if (!XQueryTree(display, screens[i].root, &d1, &d2, &wins, &no))
                        continue;
 
@@ -7270,12 +7363,13 @@ grab_windows(void)
 void
 setup_screens(void)
 {
-       int                     i, j, k;
+       int                     i, j, k, num_screens;
        int                     errorbase, major, minor;
        struct workspace        *ws;
        XGCValues               gcv;
 
-       if ((screens = calloc(ScreenCount(display),
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+       if ((screens = calloc(num_screens,
             sizeof(struct swm_screen))) == NULL)
                err(1, "setup_screens: calloc: failed to allocate memory for "
                    "screens");
@@ -7288,7 +7382,7 @@ setup_screens(void)
                        xrandr_support = 0;
 
        /* map physical screens */
-       for (i = 0; i < ScreenCount(display); i++) {
+       for (i = 0; i < num_screens; i++) {
                DNPRINTF(SWM_D_WS, "setup_screens: init screen: %d\n", i);
                screens[i].idx = i;
                TAILQ_INIT(&screens[i].rl);
@@ -7352,7 +7446,7 @@ setup_globals(void)
 void
 workaround(void)
 {
-       int                     i;
+       int                     i, num_screens;
        Atom                    netwmcheck, netwmname, utf8_string;
        Window                  root, win;
 
@@ -7360,7 +7454,9 @@ workaround(void)
        netwmcheck = XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", False);
        netwmname = XInternAtom(display, "_NET_WM_NAME", False);
        utf8_string = XInternAtom(display, "UTF8_STRING", False);
-       for (i = 0; i < ScreenCount(display); i++) {
+
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+       for (i = 0; i < num_screens; i++) {
                root = screens[i].root;
                win = XCreateSimpleWindow(display,root, 0, 0, 1, 1, 0,
                    screens[i].c[SWM_S_COLOR_UNFOCUS].color,
@@ -7385,7 +7481,7 @@ main(int argc, char *argv[])
        char                    conf[PATH_MAX], *cfile = NULL;
        struct stat             sb;
        XEvent                  e;
-       int                     xfd, i;
+       int                     xfd, i, num_screens;
        fd_set                  rd;
        struct sigaction        sact;
 
@@ -7401,6 +7497,9 @@ main(int argc, char *argv[])
        if (!(display = XOpenDisplay(0)))
                errx(1, "can not open display");
 
+       if (!(conn = XGetXCBConnection(display)))
+               errx(1, "can not get XCB connection");
+
        if (active_wm())
                errx(1, "other wm running");
 
@@ -7489,7 +7588,8 @@ noconfig:
                setenv("SWM_STARTED", "YES", 1);
 
        /* setup all bars */
-       for (i = 0; i < ScreenCount(display); i++)
+       num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+       for (i = 0; i < num_screens; i++)
                TAILQ_FOREACH(r, &screens[i].rl, entry) {
                        if (winfocus == NULL)
                                winfocus = TAILQ_FIRST(&r->ws->winlist);
@@ -7542,7 +7642,7 @@ noconfig:
                                continue;
                        }
                        /* move pointer to first screen if multi screen */
-                       if (ScreenCount(display) > 1 || outputs > 1)
+                       if (num_screens > 1 || outputs > 1)
                                XWarpPointer(display, None, rr->s[0].root,
                                    0, 0, 0, 0, X(rr),
                                    Y(rr) + (bar_enabled ? bar_height : 0));
@@ -7575,11 +7675,12 @@ done:
        teardown_ewmh();
        bar_extra_stop();
 
-       for (i = 0; i < ScreenCount(display); ++i)
+       for (i = 0; i < num_screens; ++i)
                if (screens[i].bar_gc != NULL)
                        XFreeGC(display, screens[i].bar_gc);
 
        XFreeFontSet(display, bar_fs);
+       xcb_disconnect(conn);   
        XCloseDisplay(display);
 
        return (0);