X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=spectrwm.c;h=a47f3b0e496e4c2cb29ae72cc674dd048bfbc709;hb=66f742ca4870a1458a21732913518c87ac7c9f27;hp=606dcbe4ed9cfd11c72bfd872e837aa0350f3f74;hpb=6bc606589a755f2a73b5bbc473f622250ea701b5;p=spectrwm.git diff --git a/spectrwm.c b/spectrwm.c index 606dcbe..a47f3b0 100644 --- a/spectrwm.c +++ b/spectrwm.c @@ -610,6 +610,8 @@ struct quirk { #define SWM_Q_XTERM_FONTADJ (1<<3) /* adjust xterm fonts when resizing */ #define SWM_Q_FULLSCREEN (1<<4) /* remove border */ #define SWM_Q_FOCUSPREV (1<<5) /* focus on caller */ +#define SWM_Q_NOFOCUSONMAP (1<<6) /* Don't focus on window when mapped. */ +#define SWM_Q_FOCUSONMAP_SINGLE (1<<7) /* Only focus if single win of type. */ }; TAILQ_HEAD(quirk_list, quirk); struct quirk_list quirks = TAILQ_HEAD_INITIALIZER(quirks); @@ -930,6 +932,7 @@ struct ws_win *get_pointer_win(xcb_window_t); struct ws_win *get_region_focus(struct swm_region *); int get_region_index(struct swm_region *); xcb_screen_t *get_screen(int); +int get_screen_count(void); #ifdef SWM_DEBUG char *get_stack_mode_name(uint8_t); #endif @@ -963,7 +966,7 @@ void maprequest(xcb_map_request_event_t *); void motionnotify(xcb_motion_notify_event_t *); void move(struct ws_win *, union arg *); void move_step(struct swm_region *, union arg *); -uint32_t name_to_pixel(const char *); +uint32_t name_to_pixel(int, const char *); void name_workspace(struct swm_region *, union arg *); void new_region(struct swm_screen *, int, int, int, int); int parsekeys(char *, unsigned int, unsigned int *, KeySym *); @@ -1185,6 +1188,19 @@ get_screen(int screen) } int +get_screen_count(void) +{ + const xcb_setup_t *r; + + if ((r = xcb_get_setup(conn)) == NULL) { + DNPRINTF(SWM_D_MISC, "get_screen_count: xcb_get_setup\n"); + check_conn(); + } + + return xcb_setup_roots_length(r); +} + +int get_region_index(struct swm_region *r) { struct swm_region *rr; @@ -1278,7 +1294,7 @@ setup_ewmh(void) for (i = 0; i < LENGTH(ewmh); i++) ewmh[i].atom = get_atom_from_string(ewmh[i].name); - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) { /* Support check window will be created by workaround(). */ @@ -1302,7 +1318,7 @@ teardown_ewmh(void) sup_check = get_atom_from_string("_NET_SUPPORTING_WM_CHECK"); sup_list = get_atom_from_string("_NET_SUPPORTED"); - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) { /* Get the support check window and destroy it */ @@ -1651,7 +1667,7 @@ find_pid(pid_t pid) } uint32_t -name_to_pixel(const char *colorname) +name_to_pixel(int sidx, const char *colorname) { uint32_t result = 0; char cname[32] = "#"; @@ -1661,7 +1677,7 @@ name_to_pixel(const char *colorname) xcb_alloc_named_color_reply_t *nr; uint16_t rr, gg, bb; - screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data; + screen = get_screen(sidx); cmap = screen->default_colormap; /* color is in format rgb://rr/gg/bb */ @@ -1703,15 +1719,15 @@ setscreencolor(char *val, int i, int c) { int num_screens; - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); if (i > 0 && i <= num_screens) { - screens[i - 1].c[c].pixel = name_to_pixel(val); + screens[i - 1].c[c].pixel = name_to_pixel(i - 1, 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].pixel = name_to_pixel(val); + screens[i].c[c].pixel = name_to_pixel(0, val); free(screens[i].c[c].name); if ((screens[i].c[c].name = strdup(val)) == NULL) err(1, "strdup"); @@ -1754,7 +1770,7 @@ custom_region(char *val) int sidx, num_screens; xcb_screen_t *screen; - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); if (sscanf(val, "screen[%d]:%ux%u+%u+%u", &sidx, &w, &h, &x, &y) != 5) errx(1, "invalid custom region, " "should be 'screen[]:x++"); @@ -1982,7 +1998,7 @@ bar_urgent(char *s, size_t sz) for (i = 0; i < workspace_limit; i++) urgent[i] = 0; - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) for (j = 0; j < workspace_limit; j++) TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry) { @@ -2232,7 +2248,7 @@ bar_draw(void) /* expand the format by first passing it through strftime(3) */ bar_fmt_expand(fmtexp, sizeof fmtexp); - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) { TAILQ_FOREACH(r, &screens[i].rl, entry) { if (r->bar == NULL) @@ -2336,7 +2352,7 @@ bar_toggle(struct swm_region *r, union arg *args) } /* update bars as necessary */ - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) TAILQ_FOREACH(tmpr, &screens[i].rl, entry) if (tmpr->bar) { @@ -2821,7 +2837,7 @@ unmap_all(void) struct ws_win *win; int i, j, num_screens; - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) for (j = 0; j < workspace_limit; j++) TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry) @@ -2916,7 +2932,7 @@ root_to_region(xcb_window_t root, int check) DNPRINTF(SWM_D_MISC, "root_to_region: window: 0x%x\n", root); - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) if (screens[i].root == root) break; @@ -2968,7 +2984,7 @@ find_unmanaged_window(xcb_window_t id) struct ws_win *win; int i, j, num_screens; - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) for (j = 0; j < workspace_limit; j++) TAILQ_FOREACH(win, &screens[i].ws[j].unmanagedlist, @@ -2985,7 +3001,7 @@ find_window(xcb_window_t id) int i, j, num_screens; xcb_query_tree_reply_t *r; - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) for (j = 0; j < workspace_limit; j++) TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry) @@ -3080,7 +3096,7 @@ kill_refs(struct ws_win *win) if (win == NULL) return; - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) TAILQ_FOREACH(r, &screens[i].rl, entry) for (x = 0; x < workspace_limit; x++) { @@ -3103,7 +3119,7 @@ validate_win(struct ws_win *testwin) if (testwin == NULL) return (0); - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) TAILQ_FOREACH(r, &screens[i].rl, entry) for (x = 0; x < workspace_limit; x++) { @@ -3123,7 +3139,7 @@ validate_ws(struct workspace *testws) int i, x, num_screens; /* validate all ws */ - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) TAILQ_FOREACH(r, &screens[i].rl, entry) for (x = 0; x < workspace_limit; x++) { @@ -3543,7 +3559,7 @@ focusrg(struct swm_region *r, union arg *args) int ridx = args->id, i, num_screens; struct swm_region *rr = NULL; - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); /* do nothing if we don't have more than one screen */ if (!(num_screens > 1 || outputs > 1)) return; @@ -3567,7 +3583,7 @@ cyclerg(struct swm_region *r, union arg *args) struct swm_region *rr = NULL; int i, num_screens; - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); /* do nothing if we don't have more than one screen */ if (!(num_screens > 1 || outputs > 1)) return; @@ -3970,7 +3986,7 @@ stack(void) { DNPRINTF(SWM_D_STACK, "stack: begin\n"); - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) { #ifdef SWM_DEBUG j = 0; @@ -4545,7 +4561,7 @@ send_to_rg(struct swm_region *r, union arg *args) struct swm_region *rr = NULL; union arg a; - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); /* do nothing if we don't have more than one screen */ if (!(num_screens > 1 || outputs > 1)) return; @@ -6292,8 +6308,8 @@ setconfbinding(char *selector, char *value, int flags) for (kfid = 0; kfid < KF_INVALID; (kfid)++) { if (strncasecmp(selector, keyfuncs[kfid].name, SWM_FUNCNAME_LEN) == 0) { - DNPRINTF(SWM_D_KEY, "setconfbinding: %s: match\n", - selector); + DNPRINTF(SWM_D_KEY, "setconfbinding: %s: match " + "keyfunc\n", selector); if (parsekeys(value, mod_key, &mod, &ks) == 0) { setkeybinding(mod, ks, kfid, NULL); return (0); @@ -6304,13 +6320,11 @@ setconfbinding(char *selector, char *value, int flags) /* search by custom spawn name */ TAILQ_FOREACH(sp, &spawns, entry) { if (strcasecmp(selector, sp->name) == 0) { - DNPRINTF(SWM_D_KEY, "setconfbinding: %s: match\n", - selector); + DNPRINTF(SWM_D_KEY, "setconfbinding: %s: match " + "spawn\n", selector); if (parsekeys(value, mod_key, &mod, &ks) == 0) { setkeybinding(mod, ks, KF_SPAWN_CUSTOM, sp->name); - /* Custom binding; validate spawn. */ - sp->flags ^= SWM_SPAWN_OPTIONAL; return (0); } else return (1); @@ -6459,24 +6473,25 @@ clear_keys(void) int setkeymapping(char *selector, char *value, int flags) { - char keymapping_file[PATH_MAX]; + char *keymapping_file; /* 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", - pwd->pw_dir, &value[1]); - else - strlcpy(keymapping_file, value, sizeof keymapping_file); + + keymapping_file = expand_tilde(value); + clear_keys(); /* load new key bindings; if it fails, revert to default bindings */ if (conf_load(keymapping_file, SWM_CONF_KEYMAPPING)) { clear_keys(); setup_keys(); } + + free(keymapping_file); + DNPRINTF(SWM_D_KEY, "setkeymapping: leave\n"); return (0); } @@ -6527,7 +6542,7 @@ grabkeys(void) modifiers[2] = XCB_MOD_MASK_LOCK; modifiers[3] = numlockmask | XCB_MOD_MASK_LOCK; - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (k = 0; k < num_screens; k++) { if (TAILQ_EMPTY(&screens[k].rl)) continue; @@ -6580,6 +6595,8 @@ const char *quirkname[] = { "XTERM_FONTADJ", "FULLSCREEN", "FOCUSPREV", + "NOFOCUSONMAP", + "FOCUSONMAP_SINGLE", }; /* SWM_Q_WS: retain '|' for back compat for now (2009-08-11) */ @@ -6811,7 +6828,7 @@ setconfvalue(char *selector, char *value, int flags) errx(1, "setconfvalue: bar_enabled_ws: invalid " "workspace %d.", ws_id + 1); - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) { ws = (struct workspace *)&screens[i].ws; ws[ws_id].bar_enabled = atoi(value); @@ -7142,7 +7159,7 @@ setlayout(char *selector, char *value, int flags) "::::" "'"); - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) { ws = (struct workspace *)&screens[i].ws; ws[ws_id].cur_layout = &layouts[st]; @@ -7282,6 +7299,9 @@ conf_load(const char *filename, int keymapping) warnx("conf_load: no filename"); return (1); } + + DNPRINTF(SWM_D_CONF, "conf_load: open %s\n", filename); + if ((config = fopen(filename, "r")) == NULL) { warn("conf_load: fopen: %s", filename); return (1); @@ -7787,7 +7807,7 @@ expose(xcb_expose_event_t *e) DNPRINTF(SWM_D_EVENT, "expose: window: 0x%x\n", e->window); - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) TAILQ_FOREACH(r, &screens[i].rl, entry) if (e->window == WINID(r->bar)) @@ -8323,7 +8343,7 @@ mappingnotify(xcb_mapping_notify_event_t *e) void maprequest(xcb_map_request_event_t *e) { - struct ws_win *win; + struct ws_win *win, *w = NULL; xcb_get_window_attributes_reply_t *war; DNPRINTF(SWM_D_EVENT, "maprequest: win 0x%x\n", @@ -8347,8 +8367,25 @@ maprequest(xcb_map_request_event_t *e) (war->map_state == XCB_MAP_STATE_VIEWABLE)); /* The new window should get focus; prepare. */ - if (focus_mode != SWM_FOCUS_FOLLOW) - win->ws->focus_pending = get_focus_magic(win); + if (focus_mode != SWM_FOCUS_FOLLOW && + !(win->quirks & SWM_Q_NOFOCUSONMAP)) { + if (win->quirks & SWM_Q_FOCUSONMAP_SINGLE) { + /* See if other wins of same type are already mapped. */ + TAILQ_FOREACH(w, &win->ws->winlist, entry) { + if (w == win || !w->mapped) + continue; + + if (!strcmp(w->ch.class_name, + win->ch.class_name) && + !strcmp(w->ch.instance_name, + win->ch.instance_name)) + break; + } + } + + if (w == NULL) + win->ws->focus_pending = get_focus_magic(win); + } /* All windows need to be mapped if they are in the current workspace.*/ if (win->ws->r) @@ -8378,7 +8415,7 @@ motionnotify(xcb_motion_notify_event_t *e) last_event_time = e->time; - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) if (screens[i].root == e->root) break; @@ -8670,7 +8707,7 @@ enable_wm(void) xcb_generic_error_t *error; /* this causes an error if some other window manager is running */ - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) { if ((sc = get_screen(i)) == NULL) errx(1, "ERROR: can't get screen %d.", i); @@ -8802,7 +8839,7 @@ scan_xrandr(int i) if ((screen = get_screen(i)) == NULL) errx(1, "ERROR: can't get screen %d.", i); - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); if (i >= num_screens) errx(1, "scan_xrandr: invalid screen"); @@ -8883,7 +8920,7 @@ screenchange(xcb_randr_screen_change_notify_event_t *e) DNPRINTF(SWM_D_EVENT, "screenchange: root: 0x%x\n", e->root); - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); /* silly event doesn't include the screen index */ for (i = 0; i < num_screens; i++) if (screens[i].root == e->root) @@ -8934,7 +8971,7 @@ grab_windows(void) xcb_get_property_cookie_t pc; DNPRINTF(SWM_D_INIT, "grab_windows: begin\n"); - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) { qtc = xcb_query_tree(conn, screens[i].root); qtr = xcb_query_tree_reply(conn, qtc, NULL); @@ -9032,7 +9069,7 @@ setup_screens(void) xcb_randr_query_version_cookie_t c; xcb_randr_query_version_reply_t *r; - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); if ((screens = calloc(num_screens, sizeof(struct swm_screen))) == NULL) err(1, "setup_screens: calloc: failed to allocate memory for " @@ -9151,7 +9188,7 @@ workaround(void) /* work around sun jdk bugs, code from wmname */ netwmcheck = get_atom_from_string("_NET_SUPPORTING_WM_CHECK"); - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) { root = screens[i].root; @@ -9186,7 +9223,7 @@ shutdown_cleanup(void) teardown_ewmh(); - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (i = 0; i < num_screens; ++i) { if (screens[i].bar_gc != 0) xcb_free_gc(conn, screens[i].bar_gc); @@ -9405,7 +9442,7 @@ noconfig: setenv("SWM_STARTED", "YES", 1); /* setup all bars */ - num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); + num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) TAILQ_FOREACH(r, &screens[i].rl, entry) bar_setup(r);