diff --git a/CHANGELOG.md b/CHANGELOG.md index 8316b08..825b14c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ * river: `per-output: false|true`. * `-d,--log-level=info|warning|error|none` command line option (https://codeberg.org/dnkl/yambar/issues/84). +* river: support for the river-status protocol, version 2 (‘urgent’ + views). ### Changed diff --git a/doc/yambar-modules-river.5.scd b/doc/yambar-modules-river.5.scd index 570e8a5..341176e 100644 --- a/doc/yambar-modules-river.5.scd +++ b/doc/yambar-modules-river.5.scd @@ -27,6 +27,9 @@ once for all 32 river tags. This means you probably want to use a | id : int : River tag number +| urgent +: bool +: True if the river tag has at least one urgent view. | visible : bool : True if the river tag is focused by at least one output (i.e. visible on at least one monitor). @@ -38,7 +41,7 @@ once for all 32 river tags. This means you probably want to use a : True if the river tag has views (i.e. windows). | state : string -: 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. +: Set to *urgent* if _urgent_ is true, *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 seat (*title* particle only, see CONFIGURATION) diff --git a/external/river-status-unstable-v1.xml b/external/river-status-unstable-v1.xml index a4d6f4e..13affaa 100644 --- a/external/river-status-unstable-v1.xml +++ b/external/river-status-unstable-v1.xml @@ -1,7 +1,7 @@ - Copyright 2020 Isaac Freund + Copyright 2020 The River Developers Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -16,7 +16,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - + A global factory for objects that receive status information specific to river. It could be used to implement, for example, a status bar. @@ -47,7 +47,7 @@ - + This interface allows clients to receive information about the current windowing state of an output. @@ -75,12 +75,21 @@ + + + + Sent once on binding the interface and again whenever the set of + tags with at least one urgent view changes. + + + This interface allows clients to receive information about the current - focus of a seat. + focus of a seat. Note that (un)focused_output events will only be sent + if the client has bound the relevant wl_output globals. diff --git a/modules/river.c b/modules/river.c index 9b494f3..897dbcc 100644 --- a/modules/river.c +++ b/modules/river.c @@ -29,6 +29,7 @@ struct output { /* Tags */ uint32_t occupied; uint32_t focused; + uint32_t urgent; }; struct seat { @@ -81,9 +82,10 @@ content(struct module *mod) mtx_lock(&m->mod->lock); + uint32_t urgent = 0; + uint32_t occupied = 0; uint32_t output_focused = 0; uint32_t seat_focused = 0; - uint32_t occupied = 0; tll_foreach(m->outputs, it) { const struct output *output = &it->item; @@ -96,6 +98,7 @@ content(struct module *mod) } output_focused |= output->focused; + urgent |= output->urgent; occupied |= output->occupied; tll_foreach(m->seats, it2) { @@ -112,12 +115,18 @@ content(struct module *mod) for (unsigned i = 0; i < 32; i++) { /* It's visible if any output has it focused */ - bool visible = output_focused & (1u << i); + bool is_visible = output_focused & (1u << i); /* It's focused if any output that has seat focus has it focused */ - bool focused = seat_focused & (1u << i); + bool is_focused = seat_focused & (1u << i); - const char *state = visible ? focused ? "focused" : "unfocused" : "invisible"; + bool is_urgent = urgent & (1u << i); + bool is_occupied = occupied & (1u << i); + + const char *state = + is_urgent ? "urgent" : + is_visible ? is_focused ? "focused" : "unfocused" : + "invisible"; #if 0 LOG_DBG("tag: #%u, visible=%d, focused=%d, occupied=%d, state=%s", @@ -127,12 +136,13 @@ content(struct module *mod) struct tag_set tags = { .tags = (struct tag *[]){ tag_new_int(mod, "id", i + 1), - tag_new_bool(mod, "visible", visible), - tag_new_bool(mod, "focused", focused), - tag_new_bool(mod, "occupied", occupied & (1u << i)), + tag_new_bool(mod, "urgent", is_urgent), + tag_new_bool(mod, "visible", is_visible), + tag_new_bool(mod, "focused", is_focused), + tag_new_bool(mod, "occupied", is_occupied), tag_new_string(mod, "state", state), }, - .count = 5, + .count = 6, }; tag_parts[i] = m->template->instantiate(m->template, &tags); @@ -156,7 +166,7 @@ content(struct module *mod) tag_set_destroy(&tags); } } - + mtx_unlock(&m->mod->lock); return dynlist_exposable_new(tag_parts, 32 + seat_count, 0, 0); } @@ -230,16 +240,33 @@ view_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, wl_array_for_each(set, tags) { output->occupied |= *set; } - + LOG_DBG("output: %s: occupied tags: 0x%0x", output->name, output->occupied); } mtx_unlock(&mod->lock); mod->bar->refresh(mod->bar); } +static void +urgent_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, + uint32_t tags) +{ + struct output *output = data; + struct module *mod = output->m->mod; + + mtx_lock(&mod->lock); + { + output->urgent = tags; + } + mtx_unlock(&mod->lock); + mod->bar->refresh(mod->bar); +} + + static const struct zriver_output_status_v1_listener river_status_output_listener = { .focused_tags = &focused_tags, .view_tags = &view_tags, + .urgent_tags = &urgent_tags, }; static void @@ -519,7 +546,7 @@ handle_global(void *data, struct wl_registry *registry, } else if (strcmp(interface, zriver_status_manager_v1_interface.name) == 0) { - const uint32_t required = 1; + const uint32_t required = 2; if (!verify_iface_version(interface, version, required)) return;