diff --git a/CHANGELOG.md b/CHANGELOG.md index 9475062..6d27aea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ individually. `border.width` is now a short-hand for setting all four borders to the same value (https://codeberg.org/dnkl/yambar/issues/77). +* river: `per-output: false|true`. ### Changed diff --git a/bar/backend.h b/bar/backend.h index d365da6..47fae95 100644 --- a/bar/backend.h +++ b/bar/backend.h @@ -14,4 +14,5 @@ struct backend { void (*commit)(const struct bar *bar); void (*refresh)(const struct bar *bar); void (*set_cursor)(struct bar *bar, const char *cursor); + const char *(*output_name)(const struct bar *bar); }; diff --git a/bar/bar.c b/bar/bar.c index c7b1ea5..9d1b0cc 100644 --- a/bar/bar.c +++ b/bar/bar.c @@ -162,6 +162,13 @@ set_cursor(struct bar *bar, const char *cursor) b->backend.iface->set_cursor(bar, cursor); } +static const char * +output_name(const struct bar *bar) +{ + const struct private *b = bar->private; + return b->backend.iface->output_name(bar); +} + static void on_mouse(struct bar *_bar, enum mouse_event event, enum mouse_button btn, int x, int y) @@ -456,6 +463,7 @@ bar_new(const struct bar_config *config) bar->destroy = &destroy; bar->refresh = &refresh; bar->set_cursor = &set_cursor; + bar->output_name = &output_name; for (size_t i = 0; i < priv->left.count; i++) priv->left.mods[i]->bar = bar; diff --git a/bar/bar.h b/bar/bar.h index 5d154dd..45fb328 100644 --- a/bar/bar.h +++ b/bar/bar.h @@ -12,6 +12,8 @@ struct bar { void (*refresh)(const struct bar *bar); void (*set_cursor)(struct bar *bar, const char *cursor); + + const char *(*output_name)(const struct bar *bar); }; enum bar_location { BAR_TOP, BAR_BOTTOM }; diff --git a/bar/wayland.c b/bar/wayland.c index ef62025..cb10eae 100644 --- a/bar/wayland.c +++ b/bar/wayland.c @@ -1308,6 +1308,15 @@ set_cursor(struct bar *_bar, const char *cursor) update_cursor_surface(backend, seat); } +static const char * +output_name(const struct bar *_bar) +{ + const struct private *bar = _bar->private; + const struct wayland_backend *backend = bar->backend.data; + + return backend->monitor != NULL ? backend->monitor->name : NULL; +} + const struct backend wayland_backend_iface = { .setup = &setup, .cleanup = &cleanup, @@ -1315,4 +1324,5 @@ const struct backend wayland_backend_iface = { .commit = &commit, .refresh = &refresh, .set_cursor = &set_cursor, + .output_name = &output_name, }; diff --git a/bar/xcb.c b/bar/xcb.c index 9c452da..4b0e7c1 100644 --- a/bar/xcb.c +++ b/bar/xcb.c @@ -462,6 +462,13 @@ set_cursor(struct bar *_bar, const char *cursor) backend->conn, backend->win, XCB_CW_CURSOR, &backend->cursor); } +static const char * +output_name(const struct bar *_bar) +{ + /* Not implemented */ + return NULL; +} + const struct backend xcb_backend_iface = { .setup = &setup, .cleanup = &cleanup, @@ -469,4 +476,5 @@ const struct backend xcb_backend_iface = { .commit = &commit, .refresh = &refresh, .set_cursor = &set_cursor, + .output_name = &output_name, }; diff --git a/config-verify.c b/config-verify.c index 7c4f365..5d4089a 100644 --- a/config-verify.c +++ b/config-verify.c @@ -50,6 +50,17 @@ conf_verify_int(keychain_t *chain, const struct yml_node *node) return false; } +bool +conf_verify_bool(keychain_t *chain, const struct yml_node *node) +{ + if (yml_value_is_bool(node)) + return true; + + LOG_ERR("%s: value is not a boolean: '%s'", + conf_err_prefix(chain, node), yml_value_as_string(node)); + return false; +} + bool conf_verify_list(keychain_t *chain, const struct yml_node *node, bool (*verify)(keychain_t *chain, const struct yml_node *node)) diff --git a/config-verify.h b/config-verify.h index dccaf5f..5afe3f6 100644 --- a/config-verify.h +++ b/config-verify.h @@ -32,6 +32,7 @@ const char *conf_err_prefix( bool conf_verify_string(keychain_t *chain, const struct yml_node *node); bool conf_verify_int(keychain_t *chain, const struct yml_node *node); +bool conf_verify_bool(keychain_t *chain, const struct yml_node *node); bool conf_verify_enum(keychain_t *chain, const struct yml_node *node, const char *values[], size_t count); diff --git a/doc/yambar-modules-river.5.scd b/doc/yambar-modules-river.5.scd index 46607a2..570e8a5 100644 --- a/doc/yambar-modules-river.5.scd +++ b/doc/yambar-modules-river.5.scd @@ -12,8 +12,8 @@ about the river tags. It has an interface similar to the i3/sway module. The configuration for the river module specifies one _title_ particle, -which will be instantiated with tags representing the currently active -seat and the currently focused view's title. +which will be instantiated once for each seat, with tags representing +the seats' name and the title of the seats' currently focused view. It also specifies a _content_ template particle, which is instantiated once for all 32 river tags. This means you probably want to use a @@ -41,10 +41,10 @@ once for all 32 river tags. This means you probably want to use a : Set to *focused* if _focused_ is true, *unfocused* if _visible_ is true, but _focused_ is false, or *invisible* if the river tag is not visible on any monitors. | seat : string -: The name of the currently active seat (*title* particle only, see CONFIGURATION) +: The name of the seat (*title* particle only, see CONFIGURATION) | title : string -: The focused view's title (*title* particle only, see CONFIGURATION) +: The seat's focused view's title (*title* particle only, see CONFIGURATION) # CONFIGURATION @@ -60,6 +60,12 @@ once for all 32 river tags. This means you probably want to use a : particle : yes : Template particle that will be instantiated once for all of the 32 river tags. +| per-output +: bool +: no +: When set to false (the default), tags reflect the union of all + outputs. When set to true, tags reflect river tags and seats for + the output yambar is on only. # EXAMPLES diff --git a/modules/river.c b/modules/river.c index 0cdab38..9b494f3 100644 --- a/modules/river.c +++ b/modules/river.c @@ -48,6 +48,7 @@ struct private { struct zriver_status_manager_v1 *status_manager; struct particle *template; struct particle *title; + bool per_output; bool is_starting_up; tll(struct output) outputs; @@ -76,6 +77,8 @@ content(struct module *mod) { const struct private *m = mod->private; + const char *output_bar_is_on = mod->bar->output_name(mod->bar); + mtx_lock(&m->mod->lock); uint32_t output_focused = 0; @@ -85,6 +88,13 @@ content(struct module *mod) tll_foreach(m->outputs, it) { const struct output *output = &it->item; + if (m->per_output && + output_bar_is_on != NULL && output->name != NULL && + strcmp(output->name, output_bar_is_on) != 0) + { + continue; + } + output_focused |= output->focused; occupied |= output->occupied; @@ -348,7 +358,6 @@ unfocused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1 mtx_lock(&mod->lock); { - struct output *output = NULL; tll_foreach(m->outputs, it) { if (it->item.wl_output == wl_output) { @@ -382,13 +391,21 @@ focused_view(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, LOG_DBG("seat: %s: focused view: %s", seat->name, title); - mtx_lock(&mod->lock); + const char *output_bar_is_on = mod->bar->output_name(mod->bar); + + if (!seat->m->per_output || + (output_bar_is_on != NULL && + seat->output != NULL && seat->output->name != NULL && + strcmp(output_bar_is_on, seat->output->name) == 0)) { - free(seat->title); - seat->title = title != NULL ? strdup(title) : NULL; + mtx_lock(&mod->lock); + { + free(seat->title); + seat->title = title != NULL ? strdup(title) : NULL; + } + mtx_unlock(&mod->lock); + mod->bar->refresh(mod->bar); } - mtx_unlock(&mod->lock); - mod->bar->refresh(mod->bar); } static const struct zriver_seat_status_v1_listener river_seat_status_listener = { @@ -646,11 +663,12 @@ out: } static struct module * -river_new(struct particle *template, struct particle *title) +river_new(struct particle *template, struct particle *title, bool per_output) { struct private *m = calloc(1, sizeof(*m)); m->template = template; m->title = title; + m->per_output = per_output; m->is_starting_up = true; struct module *mod = module_common_new(); @@ -668,9 +686,12 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited) { const struct yml_node *c = yml_get_value(node, "content"); const struct yml_node *title = yml_get_value(node, "title"); + const struct yml_node *per_output = yml_get_value(node, "per-output"); + return river_new( conf_to_particle(c, inherited), - title != NULL ? conf_to_particle(title, inherited) : NULL); + title != NULL ? conf_to_particle(title, inherited) : NULL, + per_output != NULL ? yml_value_as_bool(per_output) : false); } static bool @@ -678,6 +699,7 @@ verify_conf(keychain_t *chain, const struct yml_node *node) { static const struct attr_info attrs[] = { {"title", false, &conf_verify_particle}, + {"per-output", false, &conf_verify_bool}, MODULE_COMMON_ATTRS, };