X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=spectrwm.c;h=423db9287bd5f2012e765595e43bd1337991a68f;hb=1ddfc76bfe73ba2d356c7f794f8390b868a0d61c;hp=0020f39633e6e494e6b6adfcc5d9a63e5341ba5e;hpb=d3818f73f1a4d3c7c50bee72fa2897d22c07f8c1;p=spectrwm.git diff --git a/spectrwm.c b/spectrwm.c index 0020f39..423db92 100644 --- a/spectrwm.c +++ b/spectrwm.c @@ -279,7 +279,6 @@ volatile sig_atomic_t restart_wm = 0; xcb_timestamp_t last_event_time = 0; int outputs = 0; int other_wm; -int ss_enabled = 0; int xrandr_support; int xrandr_eventbase; unsigned int numlockmask = 0; @@ -349,6 +348,7 @@ double dialog_ratio = 0.6; char *bar_argv[] = { NULL, NULL }; int bar_pipe[2]; char bar_ext[SWM_BAR_MAX]; +char bar_ext_buf[SWM_BAR_MAX]; char bar_vertext[SWM_BAR_MAX]; int bar_version = 0; int bar_enabled = 1; @@ -820,13 +820,14 @@ void adjust_font(struct ws_win *); void bar_class_name(char *, size_t, struct swm_region *); void bar_class_title_name(char *, size_t, struct swm_region *); void bar_cleanup(struct swm_region *); +void bar_extra_setup(void); void bar_extra_stop(void); +void bar_extra_update(void); void bar_fmt(const char *, char *, struct swm_region *, size_t); void bar_fmt_expand(char *, size_t); -void bar_fmt_print(void); +void bar_draw(void); void bar_print(struct swm_region *, const char *); void bar_print_legacy(struct swm_region *, const char *); -void bar_refresh(void); void bar_replace(char *, char *, struct swm_region *, size_t); void bar_replace_pad(char *, int *, size_t); char * bar_replace_seq(char *, char *, struct swm_region *, size_t *, @@ -834,7 +835,6 @@ char * bar_replace_seq(char *, char *, struct swm_region *, size_t *, void bar_setup(struct swm_region *); void bar_title_name(char *, size_t, struct swm_region *); void bar_toggle(struct swm_region *, union arg *); -void bar_update(void); void bar_urgent(char *, size_t); void bar_window_float(char *, size_t, struct swm_region *); void bar_window_name(char *, size_t, struct swm_region *); @@ -2160,8 +2160,9 @@ bar_fmt_expand(char *fmtexp, size_t sz) #endif } +/* Redraws the bar; need to follow with xcb_flush() or focus_flush(). */ void -bar_fmt_print(void) +bar_draw(void) { char fmtexp[SWM_BAR_MAX], fmtnew[SWM_BAR_MAX]; char fmtrep[SWM_BAR_MAX]; @@ -2177,7 +2178,7 @@ bar_fmt_print(void) if (r->bar == NULL) continue; - if (r->ws->bar_enabled) + if (bar_enabled && r->ws->bar_enabled) xcb_map_window(conn, r->bar->id); else { xcb_unmap_window(conn, r->bar->id); @@ -2194,21 +2195,40 @@ bar_fmt_print(void) } } +/* Reads external script output; call when stdin is readable. */ void -bar_update(void) +bar_extra_update(void) { - size_t len; - char *b; + size_t len; + char b[SWM_BAR_MAX]; + int redraw = 0; if (bar_enabled && bar_extra && bar_extra_running) { - /* Ignore short reads; it'll correct itself. */ - while ((b = fgetln(stdin, &len)) != NULL) - if (b && b[len - 1] == '\n') { - b[len - 1] = '\0'; - strlcpy(bar_ext, b, sizeof bar_ext); + while (fgets(b, sizeof(b), stdin) != NULL) { + len = strlen(b); + if (b[len - 1] == '\n') { + /* Remove newline. */ + b[--len] = '\0'; + + /* "Clear" bar_ext. */ + bar_ext[0] = '\0'; + + /* Flush buffered output. */ + strlcpy(bar_ext, bar_ext_buf, sizeof(bar_ext)); + bar_ext_buf[0] = '\0'; + + /* Append new output to bar. */ + strlcat(bar_ext, b, sizeof(bar_ext)); + + redraw = 1; + } else { + /* Buffer output. */ + strlcat(bar_ext_buf, b, sizeof(bar_ext_buf)); } - if (b == NULL && errno != EAGAIN) { - warn("bar_update: bar_extra failed"); + } + + if (errno != EAGAIN) { + warn("bar_action failed"); bar_extra_stop(); } } else { @@ -2216,15 +2236,22 @@ bar_update(void) * Attempt to drain stdin, so it doesn't cause the main loop to * call us as fast as it can. */ - fgetln(stdin, &len); + while (fgets(b, sizeof(b), stdin) != NULL); if (!bar_enabled) return; - bar_ext[0] = '\0'; + /* Clear bar script output if bar script is not running. */ + if (bar_ext[0] != '\0') { + bar_ext[0] = '\0'; + redraw = 1; + } } - bar_fmt_print(); + if (redraw) { + bar_draw(); + xcb_flush(conn); + } } void @@ -2266,13 +2293,13 @@ bar_toggle(struct swm_region *r, union arg *args) stack(); /* must be after stack */ - bar_update(); + bar_draw(); focus_flush(); } void -bar_refresh(void) +bar_extra_setup(void) { struct swm_region *r; uint32_t wa[2]; @@ -2323,7 +2350,7 @@ bar_refresh(void) XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL, wa); } - bar_update(); + bar_draw(); xcb_flush(conn); } @@ -2490,7 +2517,7 @@ bar_setup(struct swm_region *r) "%d x %d\n", WINID(r->bar), X(r->bar), Y(r->bar), WIDTH(r->bar), HEIGHT(r->bar)); - bar_refresh(); + bar_extra_setup(); } void @@ -2553,8 +2580,8 @@ version(struct swm_region *r, union arg *args) "Version: %s Build: %s", SPECTRWM_VERSION, buildstr); else strlcpy(bar_vertext, "", sizeof bar_vertext); - bar_update(); + bar_draw(); xcb_flush(conn); } @@ -3124,6 +3151,9 @@ focus_win(struct ws_win *win) if (win->ws == NULL) goto out; + if (!win->mapped) + goto out; + ws = win->ws; if (validate_ws(ws)) @@ -3209,7 +3239,7 @@ focus_win(struct ws_win *win) } out: - bar_update(); + bar_draw(); DNPRINTF(SWM_D_FOCUS, "focus_win: done.\n"); } @@ -3331,7 +3361,7 @@ switchws(struct swm_region *r, union arg *args) /* Clear bar if new ws is empty. */ if (new_ws->focus_pending == NULL) - bar_update(); + bar_draw(); focus_flush(); @@ -3440,7 +3470,7 @@ cyclescr(struct swm_region *r, union arg *args) rr->s[i].root, XCB_CURRENT_TIME); /* Clear bar since empty. */ - bar_update(); + bar_draw(); } focus_flush(); @@ -3592,37 +3622,70 @@ get_focus_prev(struct ws_win *win) if (winfocus == NULL || winfocus == win) { switch (focus_close) { case SWM_STACK_BOTTOM: - winfocus = TAILQ_FIRST(wl); + TAILQ_FOREACH(winfocus, wl, entry) + if (!winfocus->iconic && winfocus != cur_focus) + break; break; case SWM_STACK_TOP: - winfocus = TAILQ_LAST(wl, ws_win_list); + TAILQ_FOREACH_REVERSE(winfocus, wl, ws_win_list, entry) + if (!winfocus->iconic && winfocus != cur_focus) + break; break; case SWM_STACK_ABOVE: - if ((winfocus = TAILQ_NEXT(cur_focus, entry)) == NULL) { - if (focus_close_wrap) - winfocus = TAILQ_FIRST(wl); - else - winfocus = TAILQ_PREV(cur_focus, - ws_win_list, entry); + winfocus = TAILQ_NEXT(cur_focus, entry); + while (winfocus && winfocus->iconic) + winfocus = TAILQ_NEXT(winfocus, entry); + + if (winfocus == NULL) { + if (focus_close_wrap) { + TAILQ_FOREACH(winfocus, wl, entry) + if (!winfocus->iconic && + winfocus != cur_focus) + break; + } else { + TAILQ_FOREACH_REVERSE(winfocus, wl, + ws_win_list, entry) + if (!winfocus->iconic && + winfocus != cur_focus) + break; + } } break; case SWM_STACK_BELOW: - if ((winfocus = TAILQ_PREV(cur_focus, ws_win_list, - entry)) == NULL) { - if (focus_close_wrap) - winfocus = TAILQ_LAST(wl, ws_win_list); - else - winfocus = TAILQ_NEXT(cur_focus, entry); + winfocus = TAILQ_PREV(cur_focus, ws_win_list, entry); + while (winfocus && winfocus->iconic) + winfocus = TAILQ_PREV(winfocus, ws_win_list, + entry); + + if (winfocus == NULL) { + if (focus_close_wrap) { + TAILQ_FOREACH_REVERSE(winfocus, wl, + ws_win_list, entry) + if (!winfocus->iconic && + winfocus != cur_focus) + break; + } else { + TAILQ_FOREACH(winfocus, wl, entry) + if (!winfocus->iconic && + winfocus != cur_focus) + break; + } } break; } } done: - if (winfocus == NULL) { - if (focus_default == SWM_STACK_TOP) - winfocus = TAILQ_LAST(wl, ws_win_list); - else - winfocus = TAILQ_FIRST(wl); + if (winfocus == NULL || + (winfocus && (winfocus->iconic || winfocus == cur_focus))) { + if (focus_default == SWM_STACK_TOP) { + TAILQ_FOREACH_REVERSE(winfocus, wl, ws_win_list, entry) + if (!winfocus->iconic && winfocus != cur_focus) + break; + } else { + TAILQ_FOREACH(winfocus, wl, entry) + if (!winfocus->iconic && winfocus != cur_focus) + break; + } } kill_refs(win); @@ -3753,7 +3816,7 @@ cycle_layout(struct swm_region *r, union arg *args) ws->cur_layout = &layouts[0]; stack(); - bar_update(); + bar_draw(); focus_win(get_region_focus(r)); @@ -3773,7 +3836,7 @@ stack_config(struct swm_region *r, union arg *args) if (args->id != SWM_ARG_ID_STACKINIT) stack(); - bar_update(); + bar_draw(); focus_flush(); } @@ -4325,8 +4388,8 @@ max_stack(struct workspace *ws, struct swm_geometry *g) } /* Unmap unwanted windows if not multi-screen. */ - if (!(num_screens > 1 || outputs > 1) && (w != win || - w != parent || w->transient != win->id)) + if (num_screens <= 1 && outputs <= 1 && w != win && + w != parent && w->transient != win->id) unmap_window(w); } @@ -6232,7 +6295,7 @@ grabkeys(void) screens[k].root, kp->mod | modifiers[j], *code, XCB_GRAB_MODE_SYNC, - XCB_GRAB_MODE_ASYNC); + XCB_GRAB_MODE_SYNC); free(code); } } @@ -6622,9 +6685,10 @@ setconfvalue(char *selector, char *value, int flags) setconfspawn("spawn_term", value, 0); break; case SWM_S_SS_APP: + /* No longer needed; leave to not break old conf files. */ break; case SWM_S_SS_ENABLED: - ss_enabled = atoi(value); + /* No longer needed; leave to not break old conf files. */ break; case SWM_S_STACK_ENABLED: stack_enabled = atoi(value); @@ -6870,51 +6934,51 @@ struct config_option { int funcflags; }; struct config_option configopt[] = { - { "bar_enabled", setconfvalue, SWM_S_BAR_ENABLED }, - { "bar_enabled_ws", setconfvalue, SWM_S_BAR_ENABLED_WS }, + { "autorun", setautorun, 0 }, + { "bar_action", setconfvalue, SWM_S_BAR_ACTION }, { "bar_at_bottom", setconfvalue, SWM_S_BAR_AT_BOTTOM }, { "bar_border", setconfcolor, SWM_S_COLOR_BAR_BORDER }, { "bar_border_width", setconfvalue, SWM_S_BAR_BORDER_WIDTH }, { "bar_color", setconfcolor, SWM_S_COLOR_BAR }, - { "bar_font_color", setconfcolor, SWM_S_COLOR_BAR_FONT }, - { "bar_font", setconfvalue, SWM_S_BAR_FONT }, - { "bar_action", setconfvalue, SWM_S_BAR_ACTION }, { "bar_delay", setconfvalue, SWM_S_BAR_DELAY }, - { "bar_justify", setconfvalue, SWM_S_BAR_JUSTIFY }, + { "bar_enabled", setconfvalue, SWM_S_BAR_ENABLED }, + { "bar_enabled_ws", setconfvalue, SWM_S_BAR_ENABLED_WS }, + { "bar_font", setconfvalue, SWM_S_BAR_FONT }, + { "bar_font_color", setconfcolor, SWM_S_COLOR_BAR_FONT }, { "bar_format", setconfvalue, SWM_S_BAR_FORMAT }, - { "keyboard_mapping", setkeymapping, 0 }, + { "bar_justify", setconfvalue, SWM_S_BAR_JUSTIFY }, { "bind", setconfbinding, 0 }, - { "stack_enabled", setconfvalue, SWM_S_STACK_ENABLED }, + { "border_width", setconfvalue, SWM_S_BORDER_WIDTH }, { "clock_enabled", setconfvalue, SWM_S_CLOCK_ENABLED }, { "clock_format", setconfvalue, SWM_S_CLOCK_FORMAT }, { "color_focus", setconfcolor, SWM_S_COLOR_FOCUS }, { "color_unfocus", setconfcolor, SWM_S_COLOR_UNFOCUS }, { "cycle_empty", setconfvalue, SWM_S_CYCLE_EMPTY }, { "cycle_visible", setconfvalue, SWM_S_CYCLE_VISIBLE }, - { "workspace_limit", setconfvalue, SWM_S_WORKSPACE_LIMIT }, { "dialog_ratio", setconfvalue, SWM_S_DIALOG_RATIO }, - { "verbose_layout", setconfvalue, SWM_S_VERBOSE_LAYOUT }, + { "disable_border", setconfvalue, SWM_S_DISABLE_BORDER }, + { "focus_close", setconfvalue, SWM_S_FOCUS_CLOSE }, + { "focus_close_wrap", setconfvalue, SWM_S_FOCUS_CLOSE_WRAP }, + { "focus_default", setconfvalue, SWM_S_FOCUS_DEFAULT }, + { "focus_mode", setconfvalue, SWM_S_FOCUS_MODE }, + { "keyboard_mapping", setkeymapping, 0 }, + { "layout", setlayout, 0 }, { "modkey", setconfmodkey, 0 }, { "program", setconfspawn, 0 }, { "quirk", setconfquirk, 0 }, { "region", setconfregion, 0 }, - { "spawn_term", setconfvalue, SWM_S_SPAWN_TERM }, - { "screenshot_enabled", setconfvalue, SWM_S_SS_ENABLED }, { "screenshot_app", setconfvalue, SWM_S_SS_APP }, - { "window_name_enabled", setconfvalue, SWM_S_WINDOW_NAME_ENABLED }, - { "urgent_enabled", setconfvalue, SWM_S_URGENT_ENABLED }, + { "screenshot_enabled", setconfvalue, SWM_S_SS_ENABLED }, + { "spawn_position", setconfvalue, SWM_S_SPAWN_ORDER }, + { "spawn_term", setconfvalue, SWM_S_SPAWN_TERM }, + { "stack_enabled", setconfvalue, SWM_S_STACK_ENABLED }, { "term_width", setconfvalue, SWM_S_TERM_WIDTH }, { "title_class_enabled", setconfvalue, SWM_S_TITLE_CLASS_ENABLED }, { "title_name_enabled", setconfvalue, SWM_S_TITLE_NAME_ENABLED }, - { "focus_mode", setconfvalue, SWM_S_FOCUS_MODE }, - { "focus_close", setconfvalue, SWM_S_FOCUS_CLOSE }, - { "focus_close_wrap", setconfvalue, SWM_S_FOCUS_CLOSE_WRAP }, - { "focus_default", setconfvalue, SWM_S_FOCUS_DEFAULT }, - { "spawn_position", setconfvalue, SWM_S_SPAWN_ORDER }, - { "disable_border", setconfvalue, SWM_S_DISABLE_BORDER }, - { "border_width", setconfvalue, SWM_S_BORDER_WIDTH }, - { "autorun", setautorun, 0 }, - { "layout", setlayout, 0 }, + { "urgent_enabled", setconfvalue, SWM_S_URGENT_ENABLED }, + { "verbose_layout", setconfvalue, SWM_S_VERBOSE_LAYOUT }, + { "window_name_enabled", setconfvalue, SWM_S_WINDOW_NAME_ENABLED }, + { "workspace_limit", setconfvalue, SWM_S_WORKSPACE_LIMIT }, }; int @@ -7427,7 +7491,7 @@ expose(xcb_expose_event_t *e) for (i = 0; i < num_screens; i++) TAILQ_FOREACH(r, &screens[i].rl, entry) if (e->window == WINID(r->bar)) - bar_update(); + bar_draw(); xcb_flush(conn); } @@ -7458,10 +7522,14 @@ keypress(xcb_key_press_event_t *e) keysym = xcb_key_press_lookup_keysym(syms, e, 0); - DNPRINTF(SWM_D_EVENT, "keypress: %u %u\n", e->detail, keysym); + DNPRINTF(SWM_D_EVENT, "keypress: keysym: %u, win (x,y): 0x%x (%d,%d), " + "detail: %u, time: %u, root (x,y): 0x%x (%d,%d), child: 0x%x, " + "state: %u, same_screen: %s\n", keysym, e->event, e->event_x, + e->event_y, e->detail, e->time, e->root, e->root_x, e->root_y, + e->child, e->state, YESNO(e->same_screen)); if ((kp = key_lookup(CLEANMASK(e->state), keysym)) == NULL) - return; + goto out; last_event_time = e->time; @@ -7471,6 +7539,13 @@ keypress(xcb_key_press_event_t *e) else if (keyfuncs[kp->funcid].func) keyfuncs[kp->funcid].func(root_to_region(e->root, SWM_CK_ALL), &(keyfuncs[kp->funcid].args)); + +out: + /* Unfreeze grab events. */ + xcb_allow_events(conn, XCB_ALLOW_ASYNC_KEYBOARD, e->time); + xcb_flush(conn); + + DNPRINTF(SWM_D_EVENT, "keypress: done.\n"); } void @@ -7512,7 +7587,7 @@ buttonpress(xcb_button_press_event_t *e) XCB_INPUT_FOCUS_PARENT, e->root, e->time); /* Clear bar since empty. */ - bar_update(); + bar_draw(); handled = 1; goto out; @@ -7893,7 +7968,7 @@ enternotify(xcb_enter_notify_event_t *e) XCB_INPUT_FOCUS_PARENT, e->root, e->time); /* Clear bar since empty. */ - bar_update(); + bar_draw(); focus_flush(); } @@ -8091,7 +8166,7 @@ propertynotify(xcb_property_notify_event_t *e) } } else if (e->atom == XCB_ATOM_WM_CLASS || e->atom == XCB_ATOM_WM_NAME) { - bar_update(); + bar_draw(); } xcb_flush(conn); @@ -8839,7 +8914,7 @@ main(int argc, char *argv[]) struct timeval tv; fd_set rd; int rd_max; - int do_bar_update = 0; + int stdin_ready = 0; int num_readable; /* suppress unused warning since var is needed */ @@ -9002,10 +9077,11 @@ noconfig: tv.tv_sec = 1; tv.tv_usec = 0; num_readable = select(rd_max + 1, &rd, NULL, NULL, &tv); - if (num_readable == -1 && errno != EINTR) + if (num_readable == -1 && errno != EINTR) { DNPRINTF(SWM_D_MISC, "select failed"); - else if (num_readable > 0 && FD_ISSET(STDIN_FILENO, &rd)) - do_bar_update = 1; + } else if (num_readable > 0 && FD_ISSET(STDIN_FILENO, &rd)) { + stdin_ready = 1; + } if (restart_wm) restart(NULL, NULL); @@ -9016,9 +9092,9 @@ noconfig: if (!running) goto done; - if (do_bar_update) { - do_bar_update = 0; - bar_update(); + if (stdin_ready) { + stdin_ready = 0; + bar_extra_update(); } } done: