X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=spectrwm.c;h=61874aff305e151a6ea886d9cc83b0ad8d388760;hb=7caf33e7559fb3a53ae4c18623cacb9db48515c1;hp=6945965a4b2deb3de60434a1d97ce4bfb01c9a1a;hpb=0cef11f17d67e85505327ce278ab1f32fc8c7e87;p=spectrwm.git diff --git a/spectrwm.c b/spectrwm.c index 6945965..61874af 100644 --- a/spectrwm.c +++ b/spectrwm.c @@ -243,7 +243,7 @@ u_int32_t swm_debug = 0 #define SH_INC_W(w) (w)->sh.width_inc #define SH_INC_H(w) (w)->sh.height_inc #define SWM_MAX_FONT_STEPS (3) -#define WINID(w) ((w) ? (w)->id : 0) +#define WINID(w) ((w) ? (w)->id : XCB_WINDOW_NONE) #define YESNO(x) ((x) ? "yes" : "no") /* Constrain Window flags */ @@ -947,6 +947,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); +xcb_window_t get_sibling(struct ws_win *, int); int get_screen_count(void); #ifdef SWM_DEBUG char *get_stack_mode_name(uint8_t); @@ -1050,6 +1051,7 @@ void spawn(int, union arg *, int); void spawn_custom(struct swm_region *, union arg *, const char *); int spawn_expand(struct swm_region *, union arg *, const char *, char ***); void spawn_insert(const char *, const char *, int); +struct spawn_prog *spawn_find(const char *); void spawn_remove(struct spawn_prog *); void spawn_replace(struct spawn_prog *, const char *, const char *, int); void spawn_select(struct swm_region *, union arg *, const char *, int *); @@ -2829,8 +2831,8 @@ map_window(struct ws_win *win, xcb_window_t sibling) if (win == NULL) return; - DNPRINTF(SWM_D_EVENT, "map_window: win 0x%x, mapped: %s, sibling: %x\n", - win->id, YESNO(win->mapped), sibling); + DNPRINTF(SWM_D_EVENT, "map_window: win 0x%x, mapped: %s, " + "sibling: 0x%x\n", win->id, YESNO(win->mapped), sibling); xcb_configure_window(conn, win->id, mode, val); @@ -3180,6 +3182,42 @@ validate_ws(struct workspace *testws) return (1); } +xcb_window_t +get_sibling(struct ws_win *win, int mode) +{ + struct ws_win *w = win; + + switch (mode) { + case SWM_STACK_TOP: + TAILQ_FOREACH_REVERSE(w, &w->ws->winlist, ws_win_list, entry) + if (w != win && !w->floating && !w->iconic) + break; + break; + case SWM_STACK_ABOVE: + do { + w = TAILQ_NEXT(w, entry); + } while (w != NULL && (w == win || w->floating || w->iconic)); + break; + case SWM_STACK_BELOW: + do { + w = TAILQ_PREV(w, ws_win_list, entry); + } while (w != NULL && (w == win || w->floating || w->iconic)); + break; + case SWM_STACK_BOTTOM: + TAILQ_FOREACH(w, &w->ws->winlist, entry) + if (w != win && !w->floating && !w->iconic) + break; + break; + default: + w = NULL; + } + + if (w == NULL) + return (win->ws->r->id); + else + return (w->id); +} + void unfocus_win(struct ws_win *win) { @@ -3211,6 +3249,8 @@ unfocus_win(struct ws_win *win) } if (win->ws->focus == win) { + if (tile_gap < 0 && !win->floating) + map_window(win, get_sibling(win, SWM_STACK_BELOW)); win->ws->focus = NULL; win->ws->focus_prev = win; } @@ -3328,6 +3368,14 @@ focus_win(struct ws_win *win) TAILQ_FOREACH(w, &ws->winlist, entry) if (w->transient == win->id && !w->iconic) map_window(w, XCB_WINDOW_NONE); + } else if (tile_gap < 0 && !win->floating) { + /* + * Windows overlap in the layout. + * Raise focused win above all tiled wins. + */ + if (tile_gap < 0 && !win->floating) + map_window(win, + get_sibling(win, SWM_STACK_TOP)); } set_region(ws->r); @@ -4198,8 +4246,7 @@ void stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip) { struct swm_geometry win_g, r_g = *g; - struct ws_win *win, *fs_win = NULL, *wtmp; - xcb_window_t sibling; + struct ws_win *win, *fs_win = NULL; int i, j, s, stacks; int w_inc = 1, h_inc, w_base = 1, h_base; int hrh, extra = 0, h_slice, last_h = 0; @@ -4376,19 +4423,17 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip) update_window(win); } - wtmp = TAILQ_PREV(win, ws_win_list, entry); - if (wtmp) - sibling = wtmp->id; - else - sibling = ws->r->bar->id; - - map_window(win, sibling); + map_window(win, get_sibling(win, SWM_STACK_BELOW)); last_h = win_g.h; i++; j++; } + /* Map/raise focused tiled window to top if windows could overlap. */ + if (tile_gap < 0 && ws->focus != NULL && !ws->focus->floating) + map_window(ws->focus, get_sibling(ws->focus, SWM_STACK_TOP)); + notiles: /* now, stack all the floaters and transients */ TAILQ_FOREACH(win, &ws->winlist, entry) { @@ -5996,7 +6041,7 @@ spawn_expand(struct swm_region *r, union arg *args, const char *spawn_name, char ***ret_args) { struct spawn_prog *prog = NULL; - int i; + int i, c; char *ap, **real_args; /* suppress unused warning since var is needed */ @@ -6019,62 +6064,68 @@ spawn_expand(struct swm_region *r, union arg *args, const char *spawn_name, err(1, "spawn_custom: calloc real_args"); /* expand spawn_args into real_args */ - for (i = 0; i < prog->argc; i++) { + for (i = c = 0; i < prog->argc; i++) { ap = prog->argv[i]; DNPRINTF(SWM_D_SPAWN, "spawn_custom: raw arg: %s\n", ap); if (!strcasecmp(ap, "$bar_border")) { - if ((real_args[i] = + if ((real_args[c] = strdup(r->s->c[SWM_S_COLOR_BAR_BORDER].name)) == NULL) err(1, "spawn_custom border color"); } else if (!strcasecmp(ap, "$bar_color")) { - if ((real_args[i] = + if ((real_args[c] = strdup(r->s->c[SWM_S_COLOR_BAR].name)) == NULL) err(1, "spawn_custom bar color"); } else if (!strcasecmp(ap, "$bar_font")) { - if ((real_args[i] = strdup(bar_fonts)) + if ((real_args[c] = strdup(bar_fonts)) == NULL) err(1, "spawn_custom bar fonts"); } else if (!strcasecmp(ap, "$bar_font_color")) { - if ((real_args[i] = + if ((real_args[c] = strdup(r->s->c[SWM_S_COLOR_BAR_FONT].name)) == NULL) err(1, "spawn_custom color font"); } else if (!strcasecmp(ap, "$color_focus")) { - if ((real_args[i] = + if ((real_args[c] = strdup(r->s->c[SWM_S_COLOR_FOCUS].name)) == NULL) err(1, "spawn_custom color focus"); } else if (!strcasecmp(ap, "$color_unfocus")) { - if ((real_args[i] = + if ((real_args[c] = strdup(r->s->c[SWM_S_COLOR_UNFOCUS].name)) == NULL) err(1, "spawn_custom color unfocus"); } else if (!strcasecmp(ap, "$region_index")) { - if (asprintf(&real_args[i], "%d", + if (asprintf(&real_args[c], "%d", get_region_index(r) + 1) < 1) err(1, "spawn_custom region index"); } else if (!strcasecmp(ap, "$workspace_index")) { - if (asprintf(&real_args[i], "%d", r->ws->idx + 1) < 1) + if (asprintf(&real_args[c], "%d", r->ws->idx + 1) < 1) + err(1, "spawn_custom workspace index"); + } else if (!strcasecmp(ap, "$dmenu_bottom")) { + if (!bar_at_bottom) + continue; + if ((real_args[c] = strdup("-b")) == NULL) err(1, "spawn_custom workspace index"); } else { /* no match --> copy as is */ - if ((real_args[i] = strdup(ap)) == NULL) + if ((real_args[c] = strdup(ap)) == NULL) err(1, "spawn_custom strdup(ap)"); } DNPRINTF(SWM_D_SPAWN, "spawn_custom: cooked arg: %s\n", - real_args[i]); + real_args[c]); + ++c; } #ifdef SWM_DEBUG DNPRINTF(SWM_D_SPAWN, "spawn_custom: result: "); - for (i = 0; i < prog->argc; i++) - DNPRINTF(SWM_D_SPAWN, "\"%s\" ", real_args[i]); - DNPRINTF(SWM_D_SPAWN, "\n"); + for (i = 0; i < c; ++i) + DPRINTF("\"%s\" ", real_args[i]); + DPRINTF("\n"); #endif *ret_args = real_args; - return (prog->argc); + return (c); } void @@ -6191,6 +6242,18 @@ spawn_remove(struct spawn_prog *sp) DNPRINTF(SWM_D_SPAWN, "spawn_remove: leave\n"); } +struct spawn_prog* +spawn_find(const char *name) +{ + struct spawn_prog *sp; + + TAILQ_FOREACH(sp, &spawns, entry) + if (!strcasecmp(sp->name, name)) + return sp; + + return NULL; +} + void setspawn(const char *name, const char *args, int flags) { @@ -6202,11 +6265,8 @@ setspawn(const char *name, const char *args, int flags) return; /* Remove any old spawn under the same name. */ - TAILQ_FOREACH(sp, &spawns, entry) - if (!strcmp(sp->name, name)) { - spawn_remove(sp); - break; - } + if ((sp = spawn_find(name)) != NULL) + spawn_remove(sp); if (*args != '\0') spawn_insert(name, args, flags); @@ -6246,11 +6306,7 @@ validate_spawns(void) continue; /* find program */ - TAILQ_FOREACH(sp, &spawns, entry) { - if (!strcasecmp(kp->spawn_name, sp->name)) - break; - } - + sp = spawn_find(kp->spawn_name); if (sp == NULL || sp->flags & SWM_SPAWN_OPTIONAL) continue; @@ -6278,6 +6334,7 @@ setup_spawn(void) setconfspawn("spawn_term", "xterm", 0); setconfspawn("menu", "dmenu_run" + " $dmenu_bottom" " -fn $bar_font" " -nb $bar_color" " -nf $bar_font_color" @@ -6285,6 +6342,7 @@ setup_spawn(void) " -sf $bar_color", 0); setconfspawn("search", "dmenu" + " $dmenu_bottom" " -i" " -fn $bar_font" " -nb $bar_color" @@ -6293,6 +6351,7 @@ setup_spawn(void) " -sf $bar_color", 0); setconfspawn("name_workspace", "dmenu" + " $dmenu_bottom" " -p Workspace" " -fn $bar_font" " -nb $bar_color" @@ -6487,17 +6546,15 @@ 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 " - "spawn\n", selector); - if (parsekeys(value, mod_key, &mod, &ks) == 0) { - setkeybinding(mod, ks, KF_SPAWN_CUSTOM, - sp->name); - return (0); - } else - return (1); - } + if ((sp = spawn_find(selector)) != NULL) { + 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); + return (0); + } else + return (1); } DNPRINTF(SWM_D_KEY, "setconfbinding: no match\n"); return (1); @@ -7157,8 +7214,6 @@ setconfvalue(char *selector, char *value, int flags) break; case SWM_S_TILE_GAP: tile_gap = atoi(value); - if (tile_gap < 0) - tile_gap = 0; break; case SWM_S_TITLE_CLASS_ENABLED: title_class_enabled = atoi(value); @@ -8568,8 +8623,12 @@ maprequest(xcb_map_request_event_t *e) if (w == win || !w->mapped) continue; - if (!strcmp(w->ch.class_name, + if (w->ch.class_name && + win->ch.class_name && + !strcmp(w->ch.class_name, win->ch.class_name) && + w->ch.instance_name && + win->ch.instance_name && !strcmp(w->ch.instance_name, win->ch.instance_name)) break;