X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=spectrwm.c;h=3d7e10e1fc50e571c23c2915a3eaa2222288af0e;hb=1f49d9c7d5b90d7055078f8b3364a5d3c0284499;hp=495ed5b7ec6d4275c18d298d7f87443653ad2a4f;hpb=4c05d42a781ae4b32994cbb9270f4da3ea82ebb8;p=spectrwm.git diff --git a/spectrwm.c b/spectrwm.c index 495ed5b..3d7e10e 100644 --- a/spectrwm.c +++ b/spectrwm.c @@ -88,21 +88,16 @@ #include #include #include -#include -#include -#include -#include -#include -#include #include -#include -#include +#include +#include #include #include #include #include #include #include +#include /* local includes */ #include "version.h" @@ -182,6 +177,7 @@ static const char *buildstr = SPECTRWM_VERSION; #define SWM_D_EVENTQ 0x1000 #define SWM_D_CONF 0x2000 #define SWM_D_BAR 0x4000 +#define SWM_D_INIT 0x8000 u_int32_t swm_debug = 0 | SWM_D_MISC @@ -199,15 +195,25 @@ u_int32_t swm_debug = 0 | SWM_D_EVENTQ | SWM_D_CONF | SWM_D_BAR + | SWM_D_INIT ; #else #define DPRINTF(x...) #define DNPRINTF(n,x...) #endif -#define LENGTH(x) (int)(sizeof x / sizeof x[0]) +/* convert 8-bit to 16-bit */ +#define RGB_8_TO_16(col) ((col) << 8) + (col) + +#define PIXEL_TO_XRENDERCOLOR(px, xrc) \ + xrc.red = RGB_8_TO_16((px) >> 16 & 0xff); \ + xrc.green = RGB_8_TO_16((px) >> 8 & 0xff); \ + xrc.blue = RGB_8_TO_16((px) & 0xff); \ + xrc.alpha = 0xffff; + +#define LENGTH(x) (int)(sizeof (x) / sizeof (x)[0]) #define MODKEY Mod1Mask -#define CLEANMASK(mask) (mask & ~(numlockmask | LockMask)) +#define CLEANMASK(mask) ((mask) & ~(numlockmask | LockMask)) #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) #define MOUSEMASK (BUTTONMASK|PointerMotionMask) #define SWM_PROPLEN (16) @@ -218,7 +224,7 @@ u_int32_t swm_debug = 0 #define Y(r) (r)->g.y #define WIDTH(r) (r)->g.w #define HEIGHT(r) (r)->g.h -#define BORDER(w) (w->bordered ? border_width : 0) +#define BORDER(w) ((w)->bordered ? border_width : 0) #define MAX_X(r) ((r)->g.x + (r)->g.w) #define MAX_Y(r) ((r)->g.y + (r)->g.h) #define SH_MIN(w) (w)->sh.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE @@ -255,16 +261,17 @@ xcb_atom_t a_netwmname; xcb_atom_t a_utf8_string; xcb_atom_t a_string; xcb_atom_t a_swm_iconic; +xcb_atom_t a_swm_ws; volatile sig_atomic_t running = 1; volatile sig_atomic_t restart_wm = 0; int outputs = 0; /*int last_focus_event = FocusOut;*/ -int (*xerrorxlib)(Display *, XErrorEvent *); int other_wm; int ss_enabled = 0; int xrandr_support; int xrandr_eventbase; unsigned int numlockmask = 0; + Display *display; xcb_connection_t *conn; xcb_key_symbols_t *syms; @@ -354,17 +361,11 @@ int border_width = 1; int verbose_layout = 0; time_t time_started; pid_t bar_pid; -XFontSet bar_fs; -XFontSetExtents *bar_fs_extents; +XftFont *bar_font; char *bar_fonts; +XftColor bar_font_color; struct passwd *pwd; -#define SWM_MENU_FN (2) -#define SWM_MENU_NB (4) -#define SWM_MENU_NF (6) -#define SWM_MENU_SB (8) -#define SWM_MENU_SF (10) - /* layout manager data */ struct swm_geometry { int x; @@ -515,7 +516,7 @@ struct swm_screen { /* colors */ struct { - uint32_t color; + uint32_t pixel; char *name; } c[SWM_S_COLOR_MAX]; @@ -657,7 +658,7 @@ void focus_magic(struct ws_win *); xcb_atom_t get_atom_from_string(const char *); xcb_screen_t *get_screen(int); char *get_win_name(xcb_window_t); -uint16_t getstate(xcb_window_t); +uint32_t getstate(xcb_window_t); void grabbuttons(struct ws_win *, int); void map_window_raised(xcb_window_t); void new_region(struct swm_screen *, int, int, int, int); @@ -666,8 +667,10 @@ void spawn_select(struct swm_region *, union arg *, char *, int *); void store_float_geom(struct ws_win *, struct swm_region *); void unmanage_window(struct ws_win *); void update_window(struct ws_win *); +#ifdef SWM_DEBUG +char *get_atom_name(xcb_atom_t); +#endif -/* function definitions */ int parse_rgb(const char *rgb, uint16_t *rr, uint16_t *gg, uint16_t *bb) { @@ -676,9 +679,9 @@ parse_rgb(const char *rgb, uint16_t *rr, uint16_t *gg, uint16_t *bb) if (sscanf(rgb, "rgb:%x/%x/%x", &tmpr, &tmpg, &tmpb) != 3) return (-1); - *rr = tmpr << 8; - *gg = tmpg << 8; - *bb = tmpb << 8; + *rr = RGB_8_TO_16(tmpr); + *gg = RGB_8_TO_16(tmpg); + *bb = RGB_8_TO_16(tmpb); return (0); } @@ -728,7 +731,7 @@ get_atom_from_string(const char *str) xcb_intern_atom_reply_t *r; xcb_atom_t atom; - c = xcb_intern_atom(conn, False, strlen(str), str); + c = xcb_intern_atom(conn, 0, strlen(str), str); r = xcb_intern_atom_reply(conn, c, NULL); if (r) { atom = r->atom; @@ -744,35 +747,26 @@ void update_iconic(struct ws_win *win, int newv) { int32_t v = newv; - xcb_atom_t iprop; win->iconic = newv; - iprop = get_atom_from_string("_SWM_ICONIC"); - if (iprop == XCB_ATOM_NONE) - return; - if (newv) xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->id, - iprop, XCB_ATOM_INTEGER, 32, 1, &v); + a_swm_iconic, XCB_ATOM_INTEGER, 32, 1, &v); else - xcb_delete_property(conn, win->id, iprop); + xcb_delete_property(conn, win->id, a_swm_iconic); } int32_t get_iconic(struct ws_win *win) { int32_t v = 0; - xcb_atom_t iprop; xcb_get_property_reply_t *pr = NULL; - iprop = get_atom_from_string("_SWM_ICONIC"); - if (iprop == XCB_ATOM_NONE) - goto out; pr = xcb_get_property_reply(conn, - xcb_get_property(conn, False, win->id, iprop, XCB_ATOM_INTEGER, - 0, 1), NULL); + xcb_get_property(conn, 0, win->id, a_swm_iconic, + XCB_ATOM_INTEGER, 0, 1), NULL); if (!pr) goto out; if (pr->type != XCB_ATOM_INTEGER || pr->format != 32) @@ -823,10 +817,12 @@ teardown_ewmh(void) for (i = 0; i < num_screens; i++) { /* Get the support check window and destroy it */ - pc = xcb_get_property(conn, False, screens[i].root, sup_check, + pc = xcb_get_property(conn, 0, screens[i].root, sup_check, XCB_ATOM_WINDOW, 0, 1); pr = xcb_get_property_reply(conn, pc, NULL); - if (pr) { + if (!pr) + continue; + if (pr->format == sup_check) { id = *((xcb_window_t *)xcb_get_property_value(pr)); xcb_destroy_window(conn, id); @@ -846,7 +842,7 @@ ewmh_autoquirk(struct ws_win *win) xcb_get_property_cookie_t c; xcb_get_property_reply_t *r; - c = xcb_get_property(conn, False, win->id, + c = xcb_get_property(conn, 0, win->id, ewmh[_NET_WM_WINDOW_TYPE].atom, XCB_ATOM_ATOM, 0, UINT32_MAX); r = xcb_get_property_reply(conn, c, NULL); if (!r) @@ -947,6 +943,9 @@ ewmh_update_win_state(struct ws_win *win, long state, long action) if (win == NULL) return; + DNPRINTF(SWM_D_PROP, "ewmh_update_win_state: window: 0x%x, state: %ld, " + "action: %ld\n", win->id, state, action); + if (state == ewmh[_NET_WM_STATE_FULLSCREEN].atom) mask = EWMH_F_FULLSCREEN; if (state == ewmh[_NET_WM_STATE_ABOVE].atom) @@ -1029,7 +1028,7 @@ ewmh_get_win_state(struct ws_win *win) if (win->manual) win->ewmh_flags |= SWM_F_MANUAL; - c = xcb_get_property(conn, False, win->id, ewmh[_NET_WM_STATE].atom, + c = xcb_get_property(conn, 0, win->id, ewmh[_NET_WM_STATE].atom, XCB_ATOM_ATOM, 0, UINT32_MAX); r = xcb_get_property_reply(conn, c, NULL); if (!r) @@ -1050,10 +1049,13 @@ void dumpwins(struct swm_region *r, union arg *args) { struct ws_win *win; - uint16_t state; + uint32_t state; xcb_get_window_attributes_cookie_t c; xcb_get_window_attributes_reply_t *wa; + /* suppress unused warning since var is needed */ + (void)args; + if (r->ws == NULL) { warnx("dumpwins: invalid workspace"); return; @@ -1182,7 +1184,7 @@ find_pid(pid_t pid) } uint32_t -name_to_color(const char *colorname) +name_to_pixel(const char *colorname) { uint32_t result = 0; char cname[32] = "#"; @@ -1236,13 +1238,13 @@ setscreencolor(char *val, int i, int c) 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); + screens[i - 1].c[c].pixel = name_to_pixel(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 < num_screens; i++) { - screens[i].c[c].color = name_to_color(val); + screens[i].c[c].pixel = name_to_pixel(val); free(screens[i].c[c].name); if ((screens[i].c[c].name = strdup(val)) == NULL) err(1, "strdup"); @@ -1281,12 +1283,12 @@ plain_stacker(struct workspace *ws) void custom_region(char *val) { - unsigned int sidx, x, y, w, h; - int num_screens; + unsigned int x, y, w, h; + int sidx, num_screens; xcb_screen_t *screen; 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) + if (sscanf(val, "screen[%d]:%ux%u+%u+%u", &sidx, &w, &h, &x, &y) != 5) errx(1, "invalid custom region, " "should be 'screen[]:x++"); if (sidx < 1 || sidx > num_screens) @@ -1326,24 +1328,26 @@ socket_setnonblock(int fd) void bar_print(struct swm_region *r, const char *s) { - int x = 0; - size_t len; - xcb_rectangle_t rect; - uint32_t gcv[1]; - XRectangle ibox, lbox; + size_t len; + xcb_rectangle_t rect; + uint32_t gcv[1]; + int32_t x = 0; + XGlyphInfo info; + XftDraw *draw; len = strlen(s); - XmbTextExtents(bar_fs, s, len, &ibox, &lbox); + + XftTextExtentsUtf8(display, bar_font, (FcChar8 *)s, len, &info); switch (bar_justify) { case SWM_BAR_JUSTIFY_LEFT: x = SWM_BAR_OFFSET; break; case SWM_BAR_JUSTIFY_CENTER: - x = (WIDTH(r) - lbox.width) / 2; + x = (WIDTH(r) - info.width) / 2; break; case SWM_BAR_JUSTIFY_RIGHT: - x = WIDTH(r) - lbox.width - SWM_BAR_OFFSET; + x = WIDTH(r) - info.width - SWM_BAR_OFFSET; break; } @@ -1356,19 +1360,26 @@ bar_print(struct swm_region *r, const char *s) rect.height = HEIGHT(r->bar); /* clear back buffer */ - gcv[0] = r->s->c[SWM_S_COLOR_BAR].color; + gcv[0] = r->s->c[SWM_S_COLOR_BAR].pixel; xcb_change_gc(conn, r->s->bar_gc, XCB_GC_FOREGROUND, gcv); xcb_poly_fill_rectangle(conn, r->bar->buffer, r->s->bar_gc, sizeof(rect), &rect); /* draw back buffer */ - gcv[0] = r->s->c[SWM_S_COLOR_BAR].color; + gcv[0] = r->s->c[SWM_S_COLOR_BAR].pixel; xcb_change_gc(conn, r->s->bar_gc, XCB_GC_BACKGROUND, gcv); - gcv[0] = r->s->c[SWM_S_COLOR_BAR_FONT].color; + gcv[0] = r->s->c[SWM_S_COLOR_BAR_FONT].pixel; xcb_change_gc(conn, r->s->bar_gc, XCB_GC_FOREGROUND, gcv); - xcb_image_text_8(conn, len, r->bar->buffer, r->s->bar_gc, x, - (bar_fs_extents->max_logical_extent.height - lbox.height) / 2 - - lbox.y, s); + + draw = XftDrawCreate(display, r->bar->buffer, + DefaultVisual(display, r->s->idx), + DefaultColormap(display, r->s->idx)); + + XftDrawStringUtf8(draw, &bar_font_color, bar_font, x, + (HEIGHT(r->bar) + bar_font->height) / 2 - bar_font->descent, + (FcChar8 *)s, len); + + XftDrawDestroy(draw); /* blt */ xcb_copy_area(conn, r->bar->buffer, r->bar->id, r->s->bar_gc, 0, 0, @@ -1545,7 +1556,7 @@ void bar_replace_pad(char *tmp, int *limit, size_t sz) { /* special case; no limit given, pad one space, instead */ - if (*limit == sz - 1) + if (*limit == (int)sz - 1) *limit = 1; snprintf(tmp, sz, "%*s", *limit, " "); } @@ -1568,7 +1579,7 @@ bar_replace_seq(char *fmt, char *fmtrep, struct swm_region *r, size_t *offrep, size = 0; if (sscanf(fmt, "%d%n", &limit, &size) != 1) limit = sizeof tmp - 1; - if (limit <= 0 || limit >= sizeof tmp) + if (limit <= 0 || limit >= (int)sizeof tmp) limit = sizeof tmp - 1; /* there is nothing to replace (ie EOL) */ @@ -1624,7 +1635,7 @@ bar_replace_seq(char *fmt, char *fmtrep, struct swm_region *r, size_t *offrep, len = strlen(tmp); ptr = tmp; - if (len < limit) + if ((int)len < limit) limit = len; while (limit-- > 0) { if (*offrep >= sz - 1) @@ -1745,6 +1756,9 @@ bar_update(void) void bar_signal(int sig) { + /* suppress unused warning since var is needed */ + (void)sig; + bar_alarm = 1; } @@ -1754,6 +1768,10 @@ bar_toggle(struct swm_region *r, union arg *args) struct swm_region *tmpr; int i, num_screens; + /* suppress unused warnings since vars are needed */ + (void)r; + (void)args; + DNPRINTF(SWM_D_BAR, "bar_toggle\n"); num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); @@ -1819,8 +1837,8 @@ bar_refresh(void) TAILQ_FOREACH(r, &screens[i].rl, entry) { if (r->bar == NULL) continue; - wa[0] = screens[i].c[SWM_S_COLOR_BAR].color; - wa[1] = screens[i].c[SWM_S_COLOR_BAR_BORDER].color; + wa[0] = screens[i].c[SWM_S_COLOR_BAR].pixel; + wa[1] = screens[i].c[SWM_S_COLOR_BAR_BORDER].pixel; xcb_change_window_attributes(conn, r->bar->id, XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL, wa); } @@ -1830,61 +1848,73 @@ bar_refresh(void) void bar_setup(struct swm_region *r) { - char *default_string; - char **missing_charsets; - int num_missing_charsets = 0; - int i; + char *font, *fontpos; + int count; xcb_screen_t *screen = get_screen(r->s->idx); uint32_t wa[3]; + XRenderColor color; - if (bar_fs) { - XFreeFontSet(display, bar_fs); - bar_fs = NULL; - } + if (r->bar != NULL) + return; if ((r->bar = calloc(1, sizeof(struct swm_bar))) == NULL) err(1, "bar_setup: calloc: failed to allocate memory."); - DNPRINTF(SWM_D_BAR, "bar_setup: loading bar_fonts: %s\n", bar_fonts); - - bar_fs = XCreateFontSet(display, bar_fonts, &missing_charsets, - &num_missing_charsets, &default_string); - - if (num_missing_charsets > 0) { - warnx("Unable to load charset(s):"); + if (bar_font == NULL) { + while ((font = strsep(&bar_fonts, ",")) != NULL) { + if (*font == '\0') + continue; - for (i = 0; i < num_missing_charsets; ++i) - warnx("%s", missing_charsets[i]); + DNPRINTF(SWM_D_INIT, "bar_setup: try font %s\n", font); - XFreeStringList(missing_charsets); + count = 0; + fontpos = font; + while ((fontpos = index(fontpos, '-'))) { + count++; + fontpos++; + } - if (strcmp(default_string, "")) - warnx("Glyphs from those sets will be replaced " - "by '%s'.", default_string); - else - warnx("Glyphs from those sets won't be drawn."); + if (count == 14) + bar_font = XftFontOpenXlfd(display, r->s->idx, + font); + else + bar_font = XftFontOpenName(display, r->s->idx, + font); + if (!bar_font) { + warnx("unable to load font %s", font); + continue; + } else { + DNPRINTF(SWM_D_INIT, "successfully opened " + "font %s\n", font); + break; + } + } } - if (bar_fs == NULL) - errx(1, "Error creating font set structure."); - - bar_fs_extents = XExtentsOfFontSet(bar_fs); + if (bar_font == NULL) + errx(1, "unable to open a font"); - bar_height = bar_fs_extents->max_logical_extent.height + - 2 * bar_border_width; + bar_height = bar_font->height + 2 * bar_border_width; if (bar_height < 1) bar_height = 1; + PIXEL_TO_XRENDERCOLOR(r->s->c[SWM_S_COLOR_BAR_FONT].pixel, color); + + if (!XftColorAllocValue(display, DefaultVisual(display, r->s->idx), + DefaultColormap(display, r->s->idx), &color, &bar_font_color)) + warn("unable to allocate Xft color"); + X(r->bar) = X(r); Y(r->bar) = bar_at_bottom ? (Y(r) + HEIGHT(r) - bar_height) : Y(r); WIDTH(r->bar) = WIDTH(r) - 2 * bar_border_width; HEIGHT(r->bar) = bar_height - 2 * bar_border_width; r->bar->id = xcb_generate_id(conn); - wa[0] = r->s->c[SWM_S_COLOR_BAR].color; - wa[1] = r->s->c[SWM_S_COLOR_BAR_BORDER].color; + wa[0] = r->s->c[SWM_S_COLOR_BAR].pixel; + wa[1] = r->s->c[SWM_S_COLOR_BAR_BORDER].pixel; wa[2] = XCB_EVENT_MASK_EXPOSURE; + xcb_create_window(conn, XCB_COPY_FROM_PARENT, r->bar->id, r->s->root, X(r->bar), Y(r->bar), WIDTH(r->bar), HEIGHT(r->bar), bar_border_width, XCB_WINDOW_CLASS_INPUT_OUTPUT, @@ -1935,18 +1965,19 @@ set_win_state(struct ws_win *win, uint16_t state) a_state, 32, 2, data); } -uint16_t +uint32_t getstate(xcb_window_t w) { - uint16_t result = 0; + uint32_t result = 0; xcb_get_property_cookie_t c; xcb_get_property_reply_t *r; - c = xcb_get_property(conn, False, w, a_state, a_state, 0L, 2L); + c = xcb_get_property(conn, 0, w, a_state, a_state, 0L, 2L); r = xcb_get_property_reply(conn, c, NULL); if (r) { - result = *((uint16_t *)xcb_get_property_value(r)); + if (r->type == a_state && r->format == 32 && r->length == 2) + result = *((uint32_t *)xcb_get_property_value(r)); free(r); } @@ -1958,6 +1989,10 @@ getstate(xcb_window_t w) void version(struct swm_region *r, union arg *args) { + /* suppress unused warnings since vars are needed */ + (void)r; + (void)args; + bar_version = !bar_version; if (bar_version) snprintf(bar_vertext, sizeof bar_vertext, @@ -1985,7 +2020,7 @@ client_msg(struct ws_win *win, xcb_atom_t a) ev.data.data32[0] = a; ev.data.data32[1] = XCB_CURRENT_TIME; - xcb_send_event(conn, False, win->id, + xcb_send_event(conn, 0, win->id, XCB_EVENT_MASK_NO_EVENT, (const char *)&ev); } @@ -2005,7 +2040,7 @@ config_win(struct ws_win *win, xcb_configure_request_event_t *ev) ce.y = Y(win); ce.width = WIDTH(win); ce.height = HEIGHT(win); - ce.override_redirect = False; + ce.override_redirect = 0; if (ev == NULL) { /* EWMH */ @@ -2065,8 +2100,8 @@ config_win(struct ws_win *win, xcb_configure_request_event_t *ev) "(%d,%d) %d x %d, border: %d\n", YESNO(ev == NULL), win->id, ce.x, ce.y, ce.width, ce.height, ce.border_width); - xcb_send_event(conn, False, win->id, XCB_EVENT_MASK_STRUCTURE_NOTIFY, - (char *)&ce); + xcb_send_event(conn, 0, win->id, XCB_EVENT_MASK_STRUCTURE_NOTIFY, + (char *)&ce); } int @@ -2092,6 +2127,10 @@ count_win(struct workspace *ws, int count_transient) void quit(struct swm_region *r, union arg *args) { + /* suppress unused warnings since vars are needed */ + (void)r; + (void)args; + DNPRINTF(SWM_D_MISC, "quit\n"); running = 0; } @@ -2099,6 +2138,8 @@ quit(struct swm_region *r, union arg *args) void unmap_window(struct ws_win *win) { + DNPRINTF(SWM_D_EVENT, "unmap_window: window: 0x%x\n", win->id); + if (win == NULL) return; @@ -2110,7 +2151,7 @@ unmap_window(struct ws_win *win) xcb_unmap_window(conn, win->id); xcb_change_window_attributes(conn, win->id, - XCB_CW_BORDER_PIXEL, &win->s->c[SWM_S_COLOR_UNFOCUS].color); + XCB_CW_BORDER_PIXEL, &win->s->c[SWM_S_COLOR_UNFOCUS].pixel); } void @@ -2149,22 +2190,27 @@ fake_keypress(struct ws_win *win, xcb_keysym_t keysym, uint16_t modifiers) event.event_y = Y(win); event.root_x = 1; event.root_y = 1; - event.same_screen = True; + event.same_screen = 1; event.detail = *keycode; event.state = modifiers; event.response_type = XCB_KEY_PRESS; - xcb_send_event(conn, True, win->id, + xcb_send_event(conn, 1, win->id, XCB_EVENT_MASK_KEY_PRESS, (const char *)&event); event.response_type = XCB_KEY_RELEASE; - xcb_send_event(conn, True, win->id, + xcb_send_event(conn, 1, win->id, XCB_EVENT_MASK_KEY_RELEASE, (const char *)&event); + + free(keycode); } void restart(struct swm_region *r, union arg *args) { + /* suppress unused warning since var is needed */ + (void)args; + DNPRINTF(SWM_D_MISC, "restart: %s\n", start_argv[0]); /* disable alarm because the following code may not be interrupted */ @@ -2176,6 +2222,9 @@ restart(struct swm_region *r, union arg *args) bar_extra = 1; unmap_all(); + XftFontClose(display, bar_font); + XftColorFree(display, DefaultVisual(display, r->s->idx), + DefaultColormap(display, r->s->idx), &bar_font_color); xcb_key_symbols_free(syms); xcb_flush(conn); xcb_disconnect(conn); @@ -2254,8 +2303,10 @@ find_window(xcb_window_t id) return (NULL); /* if we were looking for the parent return that window instead */ - if (r->parent == 0 || r->root == r->parent) + if (r->parent == 0 || r->root == r->parent) { + free(r); return (NULL); + } /* look for parent */ for (i = 0; i < num_screens; i++) @@ -2278,8 +2329,7 @@ spawn(int ws_idx, union arg *args, int close_fd) DNPRINTF(SWM_D_MISC, "spawn: %s\n", args->argv[0]); - if (display) - close(xcb_get_file_descriptor(conn)); + close(xcb_get_file_descriptor(conn)); setenv("LD_PRELOAD", SWM_LIB, 1); @@ -2429,7 +2479,7 @@ unfocus_win(struct ws_win *win) grabbuttons(win, 0); xcb_change_window_attributes(conn, win->id, XCB_CW_BORDER_PIXEL, - &win->ws->r->s->c[SWM_S_COLOR_UNFOCUS].color); + &win->ws->r->s->c[SWM_S_COLOR_UNFOCUS].pixel); xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->s->root, ewmh[_NET_ACTIVE_WINDOW].atom, XCB_ATOM_WINDOW, 32, 1, &none); } @@ -2484,12 +2534,14 @@ focus_win(struct ws_win *win) if ((cfw = find_window(cur_focus)) != NULL) unfocus_win(cfw); else { +#if 0 /* use larger hammer since the window was killed somehow */ - /* TAILQ_FOREACH(cfw, &win->ws->winlist, entry) + TAILQ_FOREACH(cfw, &win->ws->winlist, entry) if (cfw->ws && cfw->ws->r && cfw->ws->r->s) xcb_change_window_attributes(conn, cfw->id, XCB_CW_BORDER_PIXEL, - &cfw->ws->r->s->c[SWM_S_COLOR_UNFOCUS].color);*/ + &cfw->ws->r->s->c[SWM_S_COLOR_UNFOCUS].pixel); +#endif } win->ws->focus = win; @@ -2500,8 +2552,8 @@ focus_win(struct ws_win *win) win->id, XCB_CURRENT_TIME); grabbuttons(win, 1); xcb_change_window_attributes(conn, win->id, - XCB_CW_BORDER_PIXEL, - &win->ws->r->s->c[SWM_S_COLOR_FOCUS].color); + XCB_CW_BORDER_PIXEL, + &win->ws->r->s->c[SWM_S_COLOR_FOCUS].pixel); if (win->ws->cur_layout->flags & SWM_L_MAPONFOCUS || win->ws->always_raise) map_window_raised(win->id); @@ -2586,6 +2638,8 @@ switchws(struct swm_region *r, union arg *args) event_drain(XCB_ENTER_NOTIFY); else xcb_flush(conn); + + DNPRINTF(SWM_D_WS, "switchws: done\n"); } void @@ -2990,6 +3044,9 @@ cycle_layout(struct swm_region *r, union arg *args) struct workspace *ws = r->ws; union arg a; + /* suppress unused warning since var is needed */ + (void)args; + DNPRINTF(SWM_D_EVENT, "cycle_layout: workspace: %d\n", ws->idx); ws->cur_layout++; @@ -3564,7 +3621,6 @@ send_to_ws(struct swm_region *r, union arg *args) int wsid = args->id; struct ws_win *win = NULL, *parent; struct workspace *ws, *nws; - xcb_atom_t ws_idx_atom = XCB_ATOM_NONE; char ws_idx_str[SWM_PROPLEN]; union arg a; @@ -3604,14 +3660,11 @@ send_to_ws(struct swm_region *r, union arg *args) win->ws = nws; /* Try to update the window's workspace property */ - ws_idx_atom = get_atom_from_string("_SWM_WS"); - if (ws_idx_atom && - snprintf(ws_idx_str, SWM_PROPLEN, "%d", nws->idx) < - SWM_PROPLEN) { + if (snprintf(ws_idx_str, SWM_PROPLEN, "%d", nws->idx) < SWM_PROPLEN) { DNPRINTF(SWM_D_PROP, "send_to_ws: set property: _SWM_WS: %s\n", ws_idx_str); xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->id, - ws_idx_atom, XCB_ATOM_STRING, 8, strlen(ws_idx_str), + a_swm_ws, XCB_ATOM_STRING, 8, strlen(ws_idx_str), ws_idx_str); } @@ -3624,6 +3677,9 @@ send_to_ws(struct swm_region *r, union arg *args) void pressbutton(struct swm_region *r, union arg *args) { + /* suppress unused warning since var is needed */ + (void)r; + xcb_test_fake_input(conn, XCB_BUTTON_PRESS, args->id, XCB_CURRENT_TIME, XCB_WINDOW_NONE, 0, 0, 0); xcb_test_fake_input(conn, XCB_BUTTON_RELEASE, args->id, @@ -3633,6 +3689,9 @@ pressbutton(struct swm_region *r, union arg *args) void raise_toggle(struct swm_region *r, union arg *args) { + /* suppress unused warning since var is needed */ + (void)args; + if (r == NULL || r->ws == NULL) return; @@ -3650,6 +3709,9 @@ iconify(struct swm_region *r, union arg *args) { union arg a; + /* suppress unused warning since var is needed */ + (void)args; + if (r->ws->focus == NULL) return; unmap_window(r->ws->focus); @@ -3674,12 +3736,10 @@ get_win_name(xcb_window_t win) if (xcb_icccm_get_wm_name_reply(conn, c, &r, NULL)) { if (r.name_len > 0) { name = malloc(r.name_len + 1); - if (!name) { - xcb_icccm_get_text_property_reply_wipe(&r); - return (NULL); + if (name) { + memcpy(name, r.name, r.name_len); + name[r.name_len] = '\0'; } - memcpy(name, r.name, r.name_len); - name[r.name_len] = '\0'; } xcb_icccm_get_text_property_reply_wipe(&r); } @@ -3814,7 +3874,9 @@ search_win(struct swm_region *r, union arg *args) char s[8]; FILE *lfile; size_t len; - XRectangle ibox, lbox; + XftDraw *draw; + XGlyphInfo info; + DNPRINTF(SWM_D_MISC, "search_win\n"); search_r = r; @@ -3845,13 +3907,13 @@ search_win(struct swm_region *r, union arg *args) snprintf(s, sizeof s, "%d", i); len = strlen(s); - XmbTextExtents(bar_fs, s, len, &ibox, &lbox); + XftTextExtentsUtf8(display, bar_font, (FcChar8 *)s, len, &info); w = xcb_generate_id(conn); - wa[0] = r->s->c[SWM_S_COLOR_FOCUS].color; - wa[1] = r->s->c[SWM_S_COLOR_UNFOCUS].color; + wa[0] = r->s->c[SWM_S_COLOR_FOCUS].pixel; + wa[1] = r->s->c[SWM_S_COLOR_UNFOCUS].pixel; xcb_create_window(conn, XCB_COPY_FROM_PARENT, w, win->id, 0, 0, - lbox.width + 4, bar_fs_extents->max_logical_extent.height, + info.width + 4, bar_font->height + 4, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL, wa); @@ -3859,16 +3921,22 @@ search_win(struct swm_region *r, union arg *args) TAILQ_INSERT_TAIL(&search_wl, sw, entry); sw->gc = xcb_generate_id(conn); - gcv[0] = r->s->c[SWM_S_COLOR_BAR].color; - gcv[1] = r->s->c[SWM_S_COLOR_FOCUS].color; + gcv[0] = r->s->c[SWM_S_COLOR_BAR].pixel; + gcv[1] = r->s->c[SWM_S_COLOR_FOCUS].pixel; gcv[2] = 0; xcb_create_gc(conn, sw->gc, w, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_GRAPHICS_EXPOSURES, gcv); map_window_raised(w); - xcb_image_text_8(conn, len, w, sw->gc, 2, - (bar_fs_extents->max_logical_extent.height - - lbox.height) / 2 - lbox.y, s); + draw = XftDrawCreate(display, w, + DefaultVisual(display, r->s->idx), + DefaultColormap(display, r->s->idx)); + + XftDrawStringUtf8(draw, &bar_font_color, bar_font, 2, + (HEIGHT(r->bar) + bar_font->height) / 2 - bar_font->descent, + (FcChar8 *)s, len); + + XftDrawDestroy(draw); DNPRINTF(SWM_D_MISC, "search_win: mapped window: 0x%x\n", w); @@ -3938,7 +4006,7 @@ search_resp_name_workspace(char *resp, unsigned long len) } void -search_resp_search_workspace(char *resp, unsigned long len) +search_resp_search_workspace(char *resp) { char *p, *q; int ws_idx; @@ -3956,7 +4024,7 @@ search_resp_search_workspace(char *resp, unsigned long len) p = strchr(q, ':'); if (p != NULL) *p = '\0'; - ws_idx = strtonum(q, 1, workspace_limit, &errstr); + ws_idx = (int)strtonum(q, 1, workspace_limit, &errstr); if (errstr) { DNPRINTF(SWM_D_MISC, "workspace idx is %s: %s", errstr, q); @@ -3969,7 +4037,7 @@ search_resp_search_workspace(char *resp, unsigned long len) } void -search_resp_search_window(char *resp, unsigned long len) +search_resp_search_window(char *resp) { char *s; int idx; @@ -3985,7 +4053,7 @@ search_resp_search_window(char *resp, unsigned long len) return; } - idx = strtonum(s, 1, INT_MAX, &errstr); + idx = (int)strtonum(s, 1, INT_MAX, &errstr); if (errstr) { DNPRINTF(SWM_D_MISC, "window idx is %s: %s", errstr, s); @@ -4042,10 +4110,10 @@ search_do_resp(void) search_resp_name_workspace(resp, len); break; case SWM_SEARCH_SEARCH_WORKSPACE: - search_resp_search_workspace(resp, len); + search_resp_search_workspace(resp); break; case SWM_SEARCH_SEARCH_WINDOW: - search_resp_search_window(resp, len); + search_resp_search_window(resp); break; } @@ -4121,6 +4189,9 @@ floating_toggle(struct swm_region *r, union arg *args) struct ws_win *win = r->ws->focus; union arg a; + /* suppress unused warning since var is needed */ + (void)args; + if (win == NULL) return; @@ -4184,8 +4255,8 @@ update_window(struct ws_win *win) uint32_t wc[5]; mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | - XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT | - XCB_CONFIG_WINDOW_BORDER_WIDTH; + 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); @@ -4298,7 +4369,7 @@ resize(struct ws_win *win, union arg *args) xcb_create_glyph_cursor(conn, cursor, cursor_font, cursor_font, shape, shape + 1, 0, 0, 0, 0xffff, 0xffff, 0xffff); - gpc = xcb_grab_pointer(conn, False, win->id, MOUSEMASK, + gpc = xcb_grab_pointer(conn, 0, win->id, MOUSEMASK, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_WINDOW_NONE, cursor, XCB_CURRENT_TIME), gpr = xcb_grab_pointer_reply(conn, gpc, NULL); @@ -4312,10 +4383,6 @@ resize(struct ws_win *win, union arg *args) xcb_flush(conn); resizing = 1; while ((evt = xcb_wait_for_event(conn)) && resizing) { - /* - XMaskEvent(display, MOUSEMASK | ExposureMask | - SubstructureRedirectMask, &ev); - */ switch (XCB_EVENT_RESPONSE_TYPE(evt)) { case XCB_BUTTON_RELEASE: DNPRINTF(SWM_D_EVENT, "resize: BUTTON_RELEASE\n"); @@ -4485,7 +4552,7 @@ move(struct ws_win *win, union arg *args) xcb_create_glyph_cursor(conn, cursor, cursor_font, cursor_font, XC_fleur, XC_fleur + 1, 0, 0, 0, 0xffff, 0xffff, 0xffff); - gpc = xcb_grab_pointer(conn, False, win->id, MOUSEMASK, + gpc = xcb_grab_pointer(conn, 0, win->id, MOUSEMASK, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_WINDOW_NONE, cursor, XCB_CURRENT_TIME); gpr = xcb_grab_pointer_reply(conn, gpc, NULL); @@ -4837,6 +4904,9 @@ spawn_expand(struct swm_region *r, union arg *args, char *spawn_name, int i; char *ap, **real_args; + /* suppress unused warning since var is needed */ + (void)args; + DNPRINTF(SWM_D_SPAWN, "spawn_expand: %s\n", spawn_name); /* find program */ @@ -4974,7 +5044,7 @@ spawn_insert(char *name, char *args) DNPRINTF(SWM_D_SPAWN, "spawn_insert: %s\n", name); if ((sp = calloc(1, sizeof *sp)) == NULL) - err(1, "spawn_insert: malloc"); + err(1, "spawn_insert: calloc"); if ((sp->name = strdup(name)) == NULL) err(1, "spawn_insert: strdup"); @@ -5059,6 +5129,9 @@ setspawn(char *name, char *args) int setconfspawn(char *selector, char *value, int flags) { + /* suppress unused warning since var is needed */ + (void)flags; + DNPRINTF(SWM_D_SPAWN, "setconfspawn: [%s] [%s]\n", selector, value); setspawn(selector, value); @@ -5250,6 +5323,10 @@ setconfbinding(char *selector, char *value, int flags) unsigned int mod; KeySym ks; struct spawn_prog *sp; + + /* suppress unused warning since var is needed */ + (void)flags; + DNPRINTF(SWM_D_KEY, "setconfbinding: enter\n"); if (selector == NULL) { DNPRINTF(SWM_D_KEY, "setconfbinding: unbind %s\n", value); @@ -5409,6 +5486,11 @@ int setkeymapping(char *selector, char *value, int flags) { char keymapping_file[PATH_MAX]; + + /* suppress unused warnings since vars are needed */ + (void)selector; + (void)flags; + DNPRINTF(SWM_D_KEY, "setkeymapping: enter\n"); if (value[0] == '~') snprintf(keymapping_file, sizeof keymapping_file, "%s/%s", @@ -5430,7 +5512,7 @@ updatenumlockmask(void) { unsigned int i, j; xcb_get_modifier_mapping_reply_t *modmap_r; - xcb_keycode_t *modmap, kc; + xcb_keycode_t *modmap, kc, *keycode; DNPRINTF(SWM_D_MISC, "updatenumlockmask\n"); numlockmask = 0; @@ -5444,10 +5526,11 @@ updatenumlockmask(void) for (j = 0; j < modmap_r->keycodes_per_modifier; j++) { kc = modmap[i * modmap_r->keycodes_per_modifier + j]; - - if (kc == *((xcb_keycode_t *)xcb_key_symbols_get_keycode(syms, - XK_Num_Lock))) + keycode = xcb_key_symbols_get_keycode(syms, + XK_Num_Lock); + if (kc == *keycode) numlockmask = (1 << i); + free(keycode); } } free(modmap_r); @@ -5457,8 +5540,8 @@ updatenumlockmask(void) void grabkeys(void) { - int num_screens; - unsigned int j, k; + int num_screens, k; + unsigned int j; xcb_keycode_t *code; unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask | LockMask }; @@ -5477,11 +5560,12 @@ grabkeys(void) if ((code = xcb_key_symbols_get_keycode(syms, kp->keysym))) for (j = 0; j < LENGTH(modifiers); j++) - xcb_grab_key(conn, True, + xcb_grab_key(conn, 1, screens[k].root, kp->mod | modifiers[j], *code, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); + free(code); } } } @@ -5500,7 +5584,7 @@ grabbuttons(struct ws_win *win, int focused) for (i = 0; i < LENGTH(buttons); i++) if (buttons[i].action == client_click) for (j = 0; j < LENGTH(modifiers); j++) - xcb_grab_button(conn, False, win->id, + xcb_grab_button(conn, 0, win->id, BUTTONMASK, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_SYNC, @@ -5509,7 +5593,7 @@ grabbuttons(struct ws_win *win, int focused) buttons[i].button, buttons[i].mask); } else - xcb_grab_button(conn, False, win->id, BUTTONMASK, + xcb_grab_button(conn, 0, 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); } @@ -5642,6 +5726,10 @@ setconfquirk(char *selector, char *value, int flags) char *cp, *class, *name; int retval; unsigned long quirks; + + /* suppress unused warning since var is needed */ + (void)flags; + if (selector == NULL) return (0); if ((cp = strchr(selector, ':')) == NULL) @@ -5716,6 +5804,9 @@ setconfvalue(char *selector, char *value, int flags) int i; char *b; + /* suppress unused warning since var is needed */ + (void)selector; + switch (flags) { case SWM_S_BAR_ACTION: free(bar_argv[0]); @@ -5741,7 +5832,6 @@ setconfvalue(char *selector, char *value, int flags) if (asprintf(&bar_fonts, "%s,%s", value, bar_fonts) == -1) err(1, "setconfvalue: asprintf: failed to allocate " "memory for bar_fonts."); - free(b); break; case SWM_S_BAR_FORMAT: @@ -5887,6 +5977,10 @@ setconfvalue(char *selector, char *value, int flags) int setconfmodkey(char *selector, char *value, int flags) { + /* suppress unused warnings since vars are needed */ + (void)selector; + (void)flags; + if (!strncasecmp(value, "Mod1", strlen("Mod1"))) update_modkey(Mod1Mask); else if (!strncasecmp(value, "Mod2", strlen("Mod2"))) @@ -5910,6 +6004,10 @@ setconfcolor(char *selector, char *value, int flags) int setconfregion(char *selector, char *value, int flags) { + /* suppress unused warnings since vars are needed */ + (void)selector; + (void)flags; + custom_region(value); return (0); } @@ -5925,6 +6023,10 @@ setautorun(char *selector, char *value, int flags) pid_t pid; struct pid_e *p; + /* suppress unused warnings since vars are needed */ + (void)selector; + (void)flags; + if (getenv("SWM_STARTED")) return (0); @@ -5987,6 +6089,10 @@ setlayout(char *selector, char *value, int flags) char s[1024]; struct workspace *ws; + /* suppress unused warnings since vars are needed */ + (void)selector; + (void)flags; + if (getenv("SWM_STARTED")) return (0); @@ -6158,7 +6264,7 @@ conf_load(char *filename, int keymapping) for (i = 0; i < LENGTH(configopt); i++) { opt = &configopt[i]; if (!strncasecmp(cp, opt->optname, wordlen) && - strlen(opt->optname) == wordlen) { + (int)strlen(opt->optname) == wordlen) { optind = i; break; } @@ -6276,7 +6382,7 @@ window_get_pid(xcb_window_t win) if (apid == XCB_ATOM_NONE) goto tryharder; - pc = xcb_get_property(conn, False, win, apid, XCB_ATOM_CARDINAL, 0, 1); + pc = xcb_get_property(conn, 0, win, apid, XCB_ATOM_CARDINAL, 0, 1); pr = xcb_get_property_reply(conn, pc, NULL); if (!pr) goto tryharder; @@ -6285,46 +6391,84 @@ window_get_pid(xcb_window_t win) goto tryharder; } - ret = *((pid_t *)xcb_get_property_value(pr)); + if (pr->type == apid && pr->format == 32) + ret = *((pid_t *)xcb_get_property_value(pr)); free(pr); return (ret); tryharder: apid = get_atom_from_string("_SWM_PID"); - pc = xcb_get_property(conn, False, win, apid, XCB_ATOM_STRING, + pc = xcb_get_property(conn, 0, win, apid, XCB_ATOM_STRING, 0, SWM_PROPLEN); pr = xcb_get_property_reply(conn, pc, NULL); if (!pr) return (0); - if (pr->type != XCB_ATOM_STRING) { + if (pr->type != apid) { free(pr); return (0); } - ret = strtonum(xcb_get_property_value(pr), 0, INT_MAX, &errstr); + ret = (pid_t)strtonum(xcb_get_property_value(pr), 0, INT_MAX, &errstr); free(pr); return (ret); } +int +get_ws_idx(xcb_window_t id) +{ + int ws_idx = -1; + char *prop = NULL; + size_t proplen; + const char *errstr; + xcb_get_property_reply_t *gpr; + + gpr = xcb_get_property_reply(conn, + xcb_get_property(conn, 0, id, a_swm_ws, + XCB_ATOM_STRING, 0, SWM_PROPLEN), + NULL); + if (!gpr) + return (-1); + if (gpr->type) { + proplen = xcb_get_property_value_length(gpr); + if (proplen > 0) { + prop = malloc(proplen + 1); + if (prop) { + memcpy(prop, + xcb_get_property_value(gpr), + proplen); + prop[proplen] = '\0'; + } + } + free(gpr); + } + + if (prop) { + DNPRINTF(SWM_D_PROP, "get_ws_idx: _SWM_WS: %s\n", prop); + ws_idx = (int)strtonum(prop, 0, workspace_limit - 1, &errstr); + if (errstr) { + DNPRINTF(SWM_D_PROP, "get_ws_idx: window: #%s: %s", + errstr, prop); + } + free(prop); + } + + return ws_idx; +} + struct ws_win * manage_window(xcb_window_t id) { xcb_window_t trans = XCB_WINDOW_NONE; struct workspace *ws; struct ws_win *win, *ww; - int i, ws_idx, border_me = 0; - xcb_atom_t ws_idx_atom = XCB_ATOM_NONE; + int ws_idx, border_me = 0; char ws_idx_str[SWM_PROPLEN], *prop = NULL; - size_t proplen; struct swm_region *r; - const char *errstr; struct pid_e *p; struct quirk *qp; - uint32_t event_mask; - xcb_atom_t prot; - xcb_get_property_reply_t *gpr; + uint32_t event_mask, i; xcb_icccm_get_wm_protocols_reply_t wpr; if ((win = find_window(id)) != NULL) @@ -6372,26 +6516,8 @@ manage_window(xcb_window_t id) p = find_pid(window_get_pid(id)); /* Get all the window data in one shot */ - ws_idx_atom = get_atom_from_string("_SWM_WS"); - if (ws_idx_atom) { - gpr = xcb_get_property_reply(conn, - xcb_get_property(conn, False, id, ws_idx_atom, - XCB_ATOM_STRING, 0, SWM_PROPLEN), - NULL); - if (gpr) { - proplen = xcb_get_property_value_length(gpr); - if (proplen > 0) { - prop = malloc(proplen + 1); - if (prop) { - memcpy(prop, - xcb_get_property_value(gpr), - proplen); - prop[proplen] = '\0'; - } - } - free(gpr); - } - } + ws_idx = get_ws_idx(id); + win->wa = xcb_get_geometry_reply(conn, xcb_get_geometry(conn, id), NULL); @@ -6411,11 +6537,9 @@ manage_window(xcb_window_t id) "transient: 0x%x\n", win->id, win->transient); } - prot = get_atom_from_string("WM_PROTOCOLS"); - /* get supported protocols */ if (xcb_icccm_get_wm_protocols_reply(conn, - xcb_icccm_get_wm_protocols(conn, id, prot), + xcb_icccm_get_wm_protocols(conn, id, a_prot), &wpr, NULL)) { for (i = 0; i < wpr.atoms_len; i++) { if (wpr.atoms[i] == a_takefocus) @@ -6439,14 +6563,7 @@ manage_window(xcb_window_t id) TAILQ_REMOVE(&pidlist, p, entry); free(p); p = NULL; - } else if (prop && win->transient == 0) { - DNPRINTF(SWM_D_PROP, "manage_window: get _SWM_WS: %s\n", prop); - ws_idx = strtonum(prop, 0, workspace_limit - 1, - &errstr); - if (errstr) { - DNPRINTF(SWM_D_EVENT, "manage_window: window: #%s: %s", - errstr, prop); - } + } else if (ws_idx != -1 && win->transient == 0) { ws = &r->s->ws[ws_idx]; } else { ws = r->ws; @@ -6503,13 +6620,12 @@ manage_window(xcb_window_t id) constrain_window(win, r, 0); /* Set window properties so we can remember this after reincarnation */ - if (ws_idx_atom && prop == NULL && - snprintf(ws_idx_str, SWM_PROPLEN, "%d", ws->idx) < - SWM_PROPLEN) { + if (prop == NULL && snprintf(ws_idx_str, SWM_PROPLEN, "%d", ws->idx) < + SWM_PROPLEN) { DNPRINTF(SWM_D_PROP, "manage_window: set _SWM_WS: %s\n", ws_idx_str); xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->id, - ws_idx_atom, XCB_ATOM_STRING, 8, strlen(ws_idx_str), + a_swm_ws, XCB_ATOM_STRING, 8, strlen(ws_idx_str), ws_idx_str); } if (prop) @@ -6719,7 +6835,8 @@ void buttonpress(xcb_button_press_event_t *e) { struct ws_win *win; - int i, action; + int i; + unsigned int action; DNPRINTF(SWM_D_EVENT, "buttonpress: window 0x%x, detail: %u\n", e->event, e->detail); @@ -6739,6 +6856,29 @@ buttonpress(xcb_button_press_event_t *e) xcb_flush(conn); } +#ifdef SWM_DEBUG +void +print_win_geom(xcb_window_t w) +{ + xcb_get_geometry_reply_t *wa; + + wa = xcb_get_geometry_reply(conn, xcb_get_geometry(conn, w), NULL); + + if (!wa) { + DNPRINTF(SWM_D_MISC, "print_win_geom: window not found: 0x%x\n", + w); + return; + } + + DNPRINTF(SWM_D_MISC, "print_win_geom: window: 0x%x, root: 0x%x, " + "depth: %u, (x,y) w x h: (%d,%d) %d x %d, border: %d\n", + w, wa->root, wa->depth, wa->x, wa->y, wa->width, wa->height, + wa->border_width); + + free(wa); +} +#endif + void configurerequest(xcb_configure_request_event_t *e) { @@ -6750,42 +6890,52 @@ configurerequest(xcb_configure_request_event_t *e) if ((win = find_window(e->window)) == NULL) if ((win = find_unmanaged_window(e->window)) == NULL) new = 1; - +#ifdef SWM_DEBUG + print_win_geom(e->window); +#endif if (new) { + DNPRINTF(SWM_D_EVENT, "configurerequest: new window: 0x%x, " + "value_mask: 0x%x", e->window, e->value_mask); if (e->value_mask & XCB_CONFIG_WINDOW_X) { mask |= XCB_CONFIG_WINDOW_X; wc[i++] = e->x; + DPRINTF(", X: %d", e->x); } if (e->value_mask & XCB_CONFIG_WINDOW_Y) { mask |= XCB_CONFIG_WINDOW_Y; wc[i++] = e->y; + DPRINTF(", Y: %d", e->y); } if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) { mask |= XCB_CONFIG_WINDOW_WIDTH; wc[i++] = e->width; + DPRINTF(", W: %u", e->width); } if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) { mask |= XCB_CONFIG_WINDOW_HEIGHT; wc[i++] = e->height; + DPRINTF(", H: %u", e->height); } if (e->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH) { mask |= XCB_CONFIG_WINDOW_BORDER_WIDTH; wc[i++] = e->border_width; + DPRINTF(", Border: %u", e->border_width); } if (e->value_mask & XCB_CONFIG_WINDOW_SIBLING) { mask |= XCB_CONFIG_WINDOW_SIBLING; wc[i++] = e->sibling; + DPRINTF(", Sibling: 0x%x", e->sibling); } if (e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) { mask |= XCB_CONFIG_WINDOW_STACK_MODE; wc[i++] = e->stack_mode; + DPRINTF(", StackMode: %u", e->stack_mode); } - DNPRINTF(SWM_D_EVENT, "configurerequest: new window: 0x%x, " - "new: %s, (x,y) w x h: (%d,%d) %d x %d\n", e->window, - YESNO(new), wc[0], wc[1], wc[2], wc[3]); + if (mask != 0) + xcb_configure_window(conn, e->window, mask, wc); - xcb_configure_window(conn, e->window, mask, wc); + DPRINTF(", Sent: %s\n", YESNO((mask != 0))); } else if ((!win->manual || win->quirks & SWM_Q_ANYWHERE) && !(win->ewmh_flags & EWMH_F_FULLSCREEN)) { win->g_float.x = e->x - X(win->ws->r); @@ -6949,17 +7099,16 @@ maprequest(xcb_map_request_event_t *e) focus_magic(win); } -void -propertynotify(xcb_property_notify_event_t *e) -{ - struct ws_win *win; #ifdef SWM_DEBUG - char *name; +char * +get_atom_name(xcb_atom_t atom) +{ + char *name = NULL; size_t len; xcb_get_atom_name_reply_t *r; r = xcb_get_atom_name_reply(conn, - xcb_get_atom_name(conn, e->atom), + xcb_get_atom_name(conn, atom), NULL); if (r) { len = xcb_get_atom_name_name_length(r); @@ -6968,15 +7117,26 @@ propertynotify(xcb_property_notify_event_t *e) if (name) { memcpy(name, xcb_get_atom_name_name(r), len); name[len] = '\0'; - - DNPRINTF(SWM_D_EVENT, - "propertynotify: window: 0x%x, atom: %s\n", - e->window, name); - free(name); } } free(r); } + + return (name); +} +#endif + +void +propertynotify(xcb_property_notify_event_t *e) +{ + struct ws_win *win; +#ifdef SWM_DEBUG + char *name; + + name = get_atom_name(e->atom); + DNPRINTF(SWM_D_EVENT, "propertynotify: window: 0x%x, atom: %s(%u)\n", + e->window, name, e->atom); + free(name); #endif win = find_window(e->window); @@ -7023,26 +7183,40 @@ unmapnotify(xcb_unmap_notify_event_t *e) } } -/*void +#if 0 +void visibilitynotify(xcb_visibility_notify_event_t *e) { DNPRINTF(SWM_D_EVENT, "visibilitynotify: window: 0x%x\n", e->window); -}*/ +} +#endif void clientmessage(xcb_client_message_event_t *e) { struct ws_win *win; + xcb_map_request_event_t mre; +#ifdef SWM_DEBUG + char *name; + name = get_atom_name(e->type); + DNPRINTF(SWM_D_EVENT, "clientmessage: window: 0x%x, atom: %s(%u)\n", + e->window, name, e->type); + free(name); +#endif win = find_window(e->window); - if (win == NULL) + + if (win == NULL) { + if (e->type == ewmh[_NET_ACTIVE_WINDOW].atom) { + DNPRINTF(SWM_D_EVENT, "clientmessage: request focus on " + "unmanaged window.\n"); + mre.window = e->window; + maprequest(&mre); + } return; } - DNPRINTF(SWM_D_EVENT, "clientmessage: window: 0x%x, type: %u\n", - e->window, e->type); - if (e->type == ewmh[_NET_ACTIVE_WINDOW].atom) { DNPRINTF(SWM_D_EVENT, "clientmessage: _NET_ACTIVE_WINDOW\n"); focus_win(win); @@ -7089,35 +7263,31 @@ clientmessage(xcb_client_message_event_t *e) } int -xerror_start(Display *d, XErrorEvent *ee) -{ - other_wm = 1; - return (-1); -} - -int -xerror(Display *d, XErrorEvent *ee) +enable_wm(void) { - /* warnx("error: %p %p", display, ee); */ - return (-1); -} - -int -active_wm(void) -{ - other_wm = 0; - xerrorxlib = XSetErrorHandler(xerror_start); + int num_screens, i; + const uint32_t val = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT; + xcb_screen_t *sc; + xcb_void_cookie_t wac; + xcb_generic_error_t *error; /* this causes an error if some other window manager is running */ - XSelectInput(display, DefaultRootWindow(display), - SubstructureRedirectMask); - do_sync(); - if (other_wm) - return (1); + num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + for (i = 0; i < num_screens; i++) { + sc = get_screen(i); + DNPRINTF(SWM_D_INIT, "enable_wm: screen %d, root: 0x%x\n", + i, sc->root); + wac = xcb_change_window_attributes_checked(conn, sc->root, + XCB_CW_EVENT_MASK, &val); + if ((error = xcb_request_check(conn, wac))) { + DNPRINTF(SWM_D_INIT, "enable_wm: error_code: %u\n", + error->error_code); + free(error); + return 1; + } + } - XSetErrorHandler(xerror); - do_sync(); - return (0); + return 0; } void @@ -7276,14 +7446,6 @@ screenchange(xcb_randr_screen_change_notify_event_t *e) DNPRINTF(SWM_D_EVENT, "screenchange: root: 0x%x\n", e->root); - if (e->rotation & (XCB_RANDR_ROTATION_ROTATE_90 - | XCB_RANDR_ROTATION_ROTATE_270)) - xcb_randr_set_screen_size(conn, e->root, e->height, - e->width, e->mheight, e->mwidth); - else - xcb_randr_set_screen_size(conn, e->root, e->width, - e->height, e->mwidth, e->mheight); - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); /* silly event doesn't include the screen index */ for (i = 0; i < num_screens; i++) @@ -7295,6 +7457,9 @@ screenchange(xcb_randr_screen_change_notify_event_t *e) /* brute force for now, just re-enumerate the regions */ scan_xrandr(i); +#ifdef SWM_DEBUG + print_win_geom(e->root); +#endif /* add bars to all regions */ for (i = 0; i < num_screens; i++) TAILQ_FOREACH(r, &screens[i].rl, entry) @@ -7316,6 +7481,7 @@ grab_windows(void) xcb_get_window_attributes_reply_t *r; xcb_get_property_cookie_t pc; + DNPRINTF(SWM_D_INIT, "grab_windows: begin\n"); num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); for (i = 0; i < num_screens; i++) { qtc = xcb_query_tree(conn, screens[i].root); @@ -7370,6 +7536,7 @@ grab_windows(void) } free(qtr); } + DNPRINTF(SWM_D_INIT, "grab_windows: done\n"); } void @@ -7391,12 +7558,12 @@ setup_screens(void) "screens"); /* initial Xrandr setup */ - xrandr_support = False; - c = xcb_randr_query_version(conn, True, True); + xrandr_support = 0; + c = xcb_randr_query_version(conn, 1, 1); r = xcb_randr_query_version_reply(conn, c, NULL); if (r) { if (r->major_version >= 1) - xrandr_support = True; + xrandr_support = 1; free(r); } qep = xcb_get_extension_data(conn, &xcb_randr_id); @@ -7407,7 +7574,7 @@ setup_screens(void) cursor = xcb_generate_id(conn); xcb_create_glyph_cursor(conn, cursor, cursor_font, cursor_font, - XC_left_ptr, XC_left_ptr + 1, 0, 0, 0, 0xffff, 0xffff, 0xffff); + XC_left_ptr, XC_left_ptr + 1, 0, 0, 0, 0xffff, 0xffff, 0xffff); wa[0] = cursor; /* map physical screens */ @@ -7486,28 +7653,27 @@ setup_globals(void) a_utf8_string = get_atom_from_string("UTF8_STRING"); a_string = get_atom_from_string("STRING"); a_swm_iconic = get_atom_from_string("_SWM_ICONIC"); + a_swm_ws = get_atom_from_string("_SWM_WS"); } void workaround(void) { int i, num_screens; - xcb_atom_t netwmcheck, netwmname, utf8_string; + xcb_atom_t netwmcheck; xcb_window_t root, win; uint32_t wa[2]; /* work around sun jdk bugs, code from wmname */ netwmcheck = get_atom_from_string("_NET_SUPPORTING_WM_CHECK"); - netwmname = get_atom_from_string("_NET_WM_NAME"); - utf8_string = get_atom_from_string("UTF8_STRING"); num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); for (i = 0; i < num_screens; i++) { root = screens[i].root; win = xcb_generate_id(conn); - wa[0] = screens[i].c[SWM_S_COLOR_UNFOCUS].color; - wa[1] = screens[i].c[SWM_S_COLOR_UNFOCUS].color; + wa[0] = screens[i].c[SWM_S_COLOR_UNFOCUS].pixel; + wa[1] = screens[i].c[SWM_S_COLOR_UNFOCUS].pixel; xcb_create_window(conn, XCB_COPY_FROM_PARENT, win, 0, 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL, wa); @@ -7517,7 +7683,7 @@ workaround(void) xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win, netwmcheck, XCB_ATOM_WINDOW, 32, 1, &win); xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win, - netwmname, utf8_string, 8, strlen("LG3D"), "LG3D"); + a_netwmname, a_utf8_string, 8, strlen("LG3D"), "LG3D"); } } @@ -7596,20 +7762,16 @@ main(int argc, char *argv[]) struct timeval tv; fd_set rd; + /* suppress unused warning since var is needed */ + (void)argc; + time_started = time(NULL); start_argv = argv; warnx("Welcome to spectrwm V%s Build: %s", SPECTRWM_VERSION, buildstr); - if (!setlocale(LC_CTYPE, "") || !setlocale(LC_TIME, "") || - !XSupportsLocale()) + if (!setlocale(LC_CTYPE, "") || !setlocale(LC_TIME, "")) warnx("no locale support"); - if (!X_HAVE_UTF8_STRING) - warnx("no UTF-8 support"); - - if (!(display = XOpenDisplay(0))) - errx(1, "can not open display"); - /* handle some signals */ bzero(&sact, sizeof(sact)); sigemptyset(&sact.sa_mask); @@ -7624,10 +7786,16 @@ main(int argc, char *argv[]) sact.sa_flags = SA_NOCLDSTOP; sigaction(SIGCHLD, &sact, NULL); + if (!(display = XOpenDisplay(0))) + errx(1, "can not open display"); + conn = XGetXCBConnection(display); if (xcb_connection_has_error(conn)) errx(1, "can not get XCB connection"); + XSetEventQueueOwner(display, XCBOwnsEventQueue); + + xcb_prefetch_extension_data(conn, &xcb_randr_id); xfd = xcb_get_file_descriptor(conn); /* look for local and global conf file */ @@ -7645,8 +7813,8 @@ main(int argc, char *argv[]) free(evt); } - if (active_wm()) - errx(1, "other wm running"); + if (enable_wm() != 0) + errx(1, "another window manager is currently running"); xcb_aux_sync(conn); @@ -7775,9 +7943,12 @@ done: for (i = 0; i < num_screens; ++i) if (screens[i].bar_gc != 0) xcb_free_gc(conn, screens[i].bar_gc); - XFreeFontSet(display, bar_fs); + XftFontClose(display, bar_font); + XftColorFree(display, DefaultVisual(display, 0), + DefaultColormap(display, 0), &bar_font_color); xcb_key_symbols_free(syms); + xcb_flush(conn); xcb_disconnect(conn); return (0);