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`.
* `-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

View file

@ -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)

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="river_status_unstable_v1">
<copyright>
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.
</copyright>
<interface name="zriver_status_manager_v1" version="1">
<interface name="zriver_status_manager_v1" version="2">
<description summary="manage river status objects">
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 @@
</request>
</interface>
<interface name="zriver_output_status_v1" version="1">
<interface name="zriver_output_status_v1" version="2">
<description summary="track output tags and focus">
This interface allows clients to receive information about the current
windowing state of an output.
@ -75,12 +75,21 @@
</description>
<arg name="tags" type="array" summary="array of 32-bit bitfields"/>
</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 name="zriver_seat_status_v1" version="1">
<description summary="track seat focus">
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>
<request name="destroy" type="destructor">

View file

@ -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;