module/river: add support for river-status v2 (‘urgent’ views)

This commit is contained in:
Daniel Eklöf 2021-08-19 19:25:18 +02:00
parent b00954045b
commit 8b6b82f1e5
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
4 changed files with 57 additions and 16 deletions

View file

@ -20,6 +20,8 @@
* river: `per-output: false|true`. * river: `per-output: false|true`.
* `-d,--log-level=info|warning|error|none` command line option * `-d,--log-level=info|warning|error|none` command line option
(https://codeberg.org/dnkl/yambar/issues/84). (https://codeberg.org/dnkl/yambar/issues/84).
* river: support for the river-status protocol, version 2 (urgent
views).
### Changed ### Changed

View file

@ -27,6 +27,9 @@ once for all 32 river tags. This means you probably want to use a
| id | id
: int : int
: River tag number : River tag number
| urgent
: bool
: True if the river tag has at least one urgent view.
| visible | visible
: bool : bool
: True if the river tag is focused by at least one output (i.e. visible on at least one monitor). : 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). : True if the river tag has views (i.e. windows).
| state | state
: string : 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 | seat
: string : string
: The name of the seat (*title* particle only, see CONFIGURATION) : The name of the seat (*title* particle only, see CONFIGURATION)

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<protocol name="river_status_unstable_v1"> <protocol name="river_status_unstable_v1">
<copyright> <copyright>
Copyright 2020 Isaac Freund Copyright 2020 The River Developers
Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above 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. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
</copyright> </copyright>
<interface name="zriver_status_manager_v1" version="1"> <interface name="zriver_status_manager_v1" version="2">
<description summary="manage river status objects"> <description summary="manage river status objects">
A global factory for objects that receive status information specific A global factory for objects that receive status information specific
to river. It could be used to implement, for example, a status bar. to river. It could be used to implement, for example, a status bar.
@ -47,7 +47,7 @@
</request> </request>
</interface> </interface>
<interface name="zriver_output_status_v1" version="1"> <interface name="zriver_output_status_v1" version="2">
<description summary="track output tags and focus"> <description summary="track output tags and focus">
This interface allows clients to receive information about the current This interface allows clients to receive information about the current
windowing state of an output. windowing state of an output.
@ -75,12 +75,21 @@
</description> </description>
<arg name="tags" type="array" summary="array of 32-bit bitfields"/> <arg name="tags" type="array" summary="array of 32-bit bitfields"/>
</event> </event>
<event name="urgent_tags" since="2">
<description summary="tags of the output with an urgent view">
Sent once on binding the interface and again whenever the set of
tags with at least one urgent view changes.
</description>
<arg name="tags" type="uint" summary="32-bit bitfield"/>
</event>
</interface> </interface>
<interface name="zriver_seat_status_v1" version="1"> <interface name="zriver_seat_status_v1" version="1">
<description summary="track seat focus"> <description summary="track seat focus">
This interface allows clients to receive information about the current 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.
</description> </description>
<request name="destroy" type="destructor"> <request name="destroy" type="destructor">

View file

@ -29,6 +29,7 @@ struct output {
/* Tags */ /* Tags */
uint32_t occupied; uint32_t occupied;
uint32_t focused; uint32_t focused;
uint32_t urgent;
}; };
struct seat { struct seat {
@ -81,9 +82,10 @@ content(struct module *mod)
mtx_lock(&m->mod->lock); mtx_lock(&m->mod->lock);
uint32_t urgent = 0;
uint32_t occupied = 0;
uint32_t output_focused = 0; uint32_t output_focused = 0;
uint32_t seat_focused = 0; uint32_t seat_focused = 0;
uint32_t occupied = 0;
tll_foreach(m->outputs, it) { tll_foreach(m->outputs, it) {
const struct output *output = &it->item; const struct output *output = &it->item;
@ -96,6 +98,7 @@ content(struct module *mod)
} }
output_focused |= output->focused; output_focused |= output->focused;
urgent |= output->urgent;
occupied |= output->occupied; occupied |= output->occupied;
tll_foreach(m->seats, it2) { tll_foreach(m->seats, it2) {
@ -112,12 +115,18 @@ content(struct module *mod)
for (unsigned i = 0; i < 32; i++) { for (unsigned i = 0; i < 32; i++) {
/* It's visible if any output has it focused */ /* 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 */ /* 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 #if 0
LOG_DBG("tag: #%u, visible=%d, focused=%d, occupied=%d, state=%s", LOG_DBG("tag: #%u, visible=%d, focused=%d, occupied=%d, state=%s",
@ -127,12 +136,13 @@ content(struct module *mod)
struct tag_set tags = { struct tag_set tags = {
.tags = (struct tag *[]){ .tags = (struct tag *[]){
tag_new_int(mod, "id", i + 1), tag_new_int(mod, "id", i + 1),
tag_new_bool(mod, "visible", visible), tag_new_bool(mod, "urgent", is_urgent),
tag_new_bool(mod, "focused", focused), tag_new_bool(mod, "visible", is_visible),
tag_new_bool(mod, "occupied", occupied & (1u << i)), tag_new_bool(mod, "focused", is_focused),
tag_new_bool(mod, "occupied", is_occupied),
tag_new_string(mod, "state", state), tag_new_string(mod, "state", state),
}, },
.count = 5, .count = 6,
}; };
tag_parts[i] = m->template->instantiate(m->template, &tags); tag_parts[i] = m->template->instantiate(m->template, &tags);
@ -237,9 +247,26 @@ view_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1,
mod->bar->refresh(mod->bar); 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 = { static const struct zriver_output_status_v1_listener river_status_output_listener = {
.focused_tags = &focused_tags, .focused_tags = &focused_tags,
.view_tags = &view_tags, .view_tags = &view_tags,
.urgent_tags = &urgent_tags,
}; };
static void 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) { 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)) if (!verify_iface_version(interface, version, required))
return; return;