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;
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;
-sig_atomic_t bar_alarm = 0;
-int bar_delay = 30;
int bar_enabled = 1;
int bar_border_width = 1;
int bar_at_bottom = 0;
char * bar_replace_seq(char *, char *, struct swm_region *, size_t *,
size_t);
void bar_setup(struct swm_region *);
-void bar_signal(int);
void bar_title_name(char *, size_t, struct swm_region *);
void bar_toggle(struct swm_region *, union arg *);
void bar_update(void);
void
bar_update(void)
{
- size_t len;
- char *b;
+ size_t len;
+ char b[SWM_BAR_MAX];
- if (!bar_enabled)
- return;
- if (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);
+ if (bar_enabled && bar_extra && bar_extra_running) {
+ 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));
+ } else {
+ /* Buffer output. */
+ strlcat(bar_ext_buf, b, sizeof(bar_ext_buf));
}
- if (b == NULL && errno != EAGAIN) {
+ }
+
+ if (errno != EAGAIN) {
warn("bar_update: bar_extra failed");
bar_extra_stop();
}
- } else
- strlcpy(bar_ext, "", sizeof bar_ext);
+ } else {
+ /*
+ * Attempt to drain stdin, so it doesn't cause the main loop to
+ * call us as fast as it can.
+ */
+ fgets(b, sizeof(b), stdin);
- bar_fmt_print();
- alarm(bar_delay);
-}
+ if (!bar_enabled)
+ return;
-void
-bar_signal(int sig)
-{
- /* suppress unused warning since var is needed */
- (void)sig;
+ bar_ext[0] = '\0';
+ }
- bar_alarm = 1;
+ bar_fmt_print();
}
void
/* Only change if master switch is enabled. */
if (bar_enabled)
r->ws->bar_enabled = !r->ws->bar_enabled;
+ else
+ bar_enabled = r->ws->bar_enabled = 1;
break;
case SWM_ARG_ID_BAR_TOGGLE:
bar_enabled = !bar_enabled;
err(1, "pipe error");
socket_setnonblock(bar_pipe[0]);
socket_setnonblock(bar_pipe[1]); /* XXX hmmm, really? */
+
+ /* Set stdin to read from the pipe. */
if (dup2(bar_pipe[0], 0) == -1)
err(1, "dup2");
+
+ /* Set stdout to write to the pipe. */
if (dup2(bar_pipe[1], 1) == -1)
err(1, "dup2");
+
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
err(1, "could not disable SIGPIPE");
switch (bar_pid = fork()) {
xcb_change_window_attributes(conn, r->bar->id,
XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL, wa);
}
+
bar_update();
+ xcb_flush(conn);
}
int
"%d x %d\n", WINID(r->bar), X(r->bar), Y(r->bar), WIDTH(r->bar),
HEIGHT(r->bar));
- if (signal(SIGALRM, bar_signal) == SIG_ERR)
- err(1, "could not install bar_signal");
bar_refresh();
}
SWM_S_BAR_BORDER_WIDTH,
SWM_S_BAR_DELAY,
SWM_S_BAR_ENABLED,
+ SWM_S_BAR_ENABLED_WS,
SWM_S_BAR_FONT,
SWM_S_BAR_FORMAT,
SWM_S_BAR_JUSTIFY,
int
setconfvalue(char *selector, char *value, int flags)
{
- int i;
- char *b;
+ struct workspace *ws;
+ int i, ws_id, num_screens;
+ char *b;
/* suppress unused warning since var is needed */
(void)selector;
bar_border_width = 0;
break;
case SWM_S_BAR_DELAY:
- bar_delay = atoi(value);
+ /* No longer needed; leave to not break old conf files. */
break;
case SWM_S_BAR_ENABLED:
bar_enabled = atoi(value);
break;
+ case SWM_S_BAR_ENABLED_WS:
+ ws_id = atoi(selector) - 1;
+ if (ws_id < 0 || ws_id >= workspace_limit)
+ errx(1, "setconfvalue: bar_enabled_ws: invalid "
+ "workspace %d.", ws_id + 1);
+
+ num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+ for (i = 0; i < num_screens; i++) {
+ ws = (struct workspace *)&screens[i].ws;
+ ws[ws_id].bar_enabled = atoi(value);
+ }
+ break;
case SWM_S_BAR_FONT:
b = bar_fonts;
if (asprintf(&bar_fonts, "%s,%s", value, bar_fonts) == -1)
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);
};
struct config_option configopt[] = {
{ "bar_enabled", setconfvalue, SWM_S_BAR_ENABLED },
+ { "bar_enabled_ws", setconfvalue, SWM_S_BAR_ENABLED_WS },
{ "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 },
xcb_generic_event_t *evt;
struct timeval tv;
fd_set rd;
+ int rd_max;
+ int do_bar_update = 0;
+ int num_readable;
/* suppress unused warning since var is needed */
(void)argc;
xcb_ungrab_server(conn);
xcb_flush(conn);
+ rd_max = xfd > STDIN_FILENO ? xfd : STDIN_FILENO;
+
while (running) {
while ((evt = xcb_poll_for_event(conn))) {
if (!running)
}
FD_ZERO(&rd);
+ FD_SET(STDIN_FILENO, &rd);
FD_SET(xfd, &rd);
tv.tv_sec = 1;
tv.tv_usec = 0;
- if (select(xfd + 1, &rd, NULL, NULL, &tv) == -1)
- if (errno != EINTR) {
- DNPRINTF(SWM_D_MISC, "select failed");
- }
+ num_readable = select(rd_max + 1, &rd, NULL, NULL, &tv);
+ 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;
+
if (restart_wm)
restart(NULL, NULL);
+
if (search_resp)
search_do_resp();
+
if (!running)
goto done;
- if (bar_alarm) {
- bar_alarm = 0;
+
+ if (do_bar_update) {
+ do_bar_update = 0;
bar_update();
+ xcb_flush(conn);
}
}
done: