X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=spectrwm.c;h=c912e3f57e690df03c731680ccac694dc670ffb5;hb=ff9fc42a008c56f255e9eabe5f79151c0232cf73;hp=b4e86a400fdf8d9ad6fa02c9caf6c52b932dc7c4;hpb=545774e9638ac958c62bb2125276e5f93e2f907d;p=spectrwm.git diff --git a/spectrwm.c b/spectrwm.c index b4e86a4..c912e3f 100644 --- a/spectrwm.c +++ b/spectrwm.c @@ -90,7 +90,7 @@ #include #include #include -#include +#include #include #include #include @@ -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; }; @@ -649,69 +650,97 @@ 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); } } @@ -1248,13 +1277,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 +1294,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 +1327,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[]:x++"); - 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) @@ -1539,46 +1573,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); @@ -1904,8 +1936,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; } @@ -2161,6 +2193,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"); @@ -6139,45 +6172,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 +6252,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 +6354,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; @@ -6971,14 +7022,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); @@ -7160,7 +7218,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), @@ -7270,12 +7328,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 +7347,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); @@ -7401,6 +7460,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"); @@ -7580,6 +7642,7 @@ done: XFreeGC(display, screens[i].bar_gc); XFreeFontSet(display, bar_fs); + xcb_disconnect(conn); XCloseDisplay(display); return (0);