JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
make setup_ewmh() use xcb
[spectrwm.git] / spectrwm.c
index 666fa0f..e70be92 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;
@@ -695,23 +696,39 @@ out:
 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);
        }
 }
 
@@ -1539,46 +1556,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);
@@ -2161,6 +2176,7 @@ restart(struct swm_region *r, union arg *args)
        bar_extra_stop();
        bar_extra = 1;
        unmap_all();
+       xcb_disconnect(conn);
        XCloseDisplay(display);
        execvp(start_argv[0], start_argv);
        warn("execvp failed");
@@ -4957,6 +4973,7 @@ void
 setup_spawn(void)
 {
        setconfspawn("term",            "xterm",                0);
+       setconfspawn("spawn_term",      "xterm",                0);
        setconfspawn("screenshot_all",  "screenshot.sh full",   0);
        setconfspawn("screenshot_wind", "screenshot.sh window", 0);
        setconfspawn("lock",            "xlock",                0);
@@ -5699,6 +5716,7 @@ setconfvalue(char *selector, char *value, int flags)
                break;
        case SWM_S_SPAWN_TERM:
                setconfspawn("term", value, 0);
+               setconfspawn("spawn_term", value, 0);
                break;
        case SWM_S_SS_APP:
                break;
@@ -6211,9 +6229,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:
@@ -6312,10 +6331,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;
@@ -6969,14 +6999,21 @@ visibilitynotify(XEvent *e)
 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);
@@ -7158,7 +7195,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),
@@ -7399,6 +7436,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");
 
@@ -7578,6 +7618,7 @@ done:
                        XFreeGC(display, screens[i].bar_gc);
 
        XFreeFontSet(display, bar_fs);
+       xcb_disconnect(conn);   
        XCloseDisplay(display);
 
        return (0);