summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Verevkin <34583604+MaxVerevkin@users.noreply.github.com>2023-06-01 16:34:33 +0300
committerGitHub <noreply@github.com>2023-06-01 16:34:33 +0300
commitaaaa16d9b7c54ff04e8548fe990fb1a54d454fa0 (patch)
tree9fe36b384cf106a02da8ecb4fb4cd93185b3755c
parent84b8dfe8cd190de33221f465a7059be6a30769f5 (diff)
parent13c08ca31ee1ccbbeceb8962d739a077048d59ac (diff)
downloadi3bar-mango-aaaa16d9b7c54ff04e8548fe990fb1a54d454fa0.tar.gz
Merge pull request #8 from MaxVerevkin/hyprland
Hyprland
-rw-r--r--Cargo.toml3
-rw-r--r--README.md4
-rw-r--r--protocols/ext-workspace-unstable-v1.xml306
-rw-r--r--src/pointer_btn.rs2
-rw-r--r--src/protocol.rs3
-rw-r--r--src/text.rs3
-rw-r--r--src/wm_info_provider.rs41
-rw-r--r--src/wm_info_provider/ext_workspace_unstable.rs215
-rw-r--r--src/wm_info_provider/river.rs1
9 files changed, 566 insertions, 12 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 68e91ec..d2ba84b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,6 +8,9 @@ edition = "2021"
license = "GPL-3.0-only"
authors = ["MaxVerevkin <maxxverrr@gmail.com>"]
+[features]
+hyprland = []
+
[dependencies]
anyhow = "1"
toml = { version = "0.7", default-features = false, features = ["parse"] }
diff --git a/README.md b/README.md
index 9fc5f2b..f1cf446 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,10 @@ A list of things that are missing (for now):
- Support for rounded corners
- Show/hide with `pkill -SIGUSR1 i3bar-river`
+## Hyprland support
+
+Hyprland/wlr_ext_workspaces support is experimental and is behind `hyprland` feature flag. Build with `-F hyprland` to enable it.
+
## Installation
### Arch
diff --git a/protocols/ext-workspace-unstable-v1.xml b/protocols/ext-workspace-unstable-v1.xml
new file mode 100644
index 0000000..24410b6
--- /dev/null
+++ b/protocols/ext-workspace-unstable-v1.xml
@@ -0,0 +1,306 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="ext_workspace_unstable_v1">
+ <copyright>
+ Copyright © 2019 Christopher Billington
+ Copyright © 2020 Ilia Bozhinov
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that copyright notice and this permission
+ notice appear in supporting documentation, and that the name of
+ the copyright holders not be used in advertising or publicity
+ pertaining to distribution of the software without specific,
+ written prior permission. The copyright holders make no
+ representations about the suitability of this software for any
+ purpose. It is provided "as is" without express or implied
+ warranty.
+
+ THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+ THIS SOFTWARE.
+ </copyright>
+
+ <interface name="zext_workspace_manager_v1" version="1">
+ <description summary="list and control workspaces">
+ Workspaces, also called virtual desktops, are groups of surfaces. A
+ compositor with a concept of workspaces may only show some such groups of
+ surfaces (those of 'active' workspaces) at a time. 'Activating' a
+ workspace is a request for the compositor to display that workspace's
+ surfaces as normal, whereas the compositor may hide or otherwise
+ de-emphasise surfaces that are associated only with 'inactive' workspaces.
+ Workspaces are grouped by which sets of outputs they correspond to, and
+ may contain surfaces only from those outputs. In this way, it is possible
+ for each output to have its own set of workspaces, or for all outputs (or
+ any other arbitrary grouping) to share workspaces. Compositors may
+ optionally conceptually arrange each group of workspaces in an
+ N-dimensional grid.
+
+ The purpose of this protocol is to enable the creation of taskbars and
+ docks by providing them with a list of workspaces and their properties,
+ and allowing them to activate and deactivate workspaces.
+
+ After a client binds the zext_workspace_manager_v1, each workspace will be
+ sent via the workspace event.
+ </description>
+
+ <event name="workspace_group">
+ <description summary="a workspace group has been created">
+ This event is emitted whenever a new workspace group has been created.
+
+ All initial details of the workspace group (workspaces, outputs) will be
+ sent immediately after this event via the corresponding events in
+ zext_workspace_group_handle_v1.
+ </description>
+ <arg name="workspace_group" type="new_id" interface="zext_workspace_group_handle_v1"/>
+ </event>
+
+ <request name="commit">
+ <description summary="all requests about the workspaces have been sent">
+ The client must send this request after it has finished sending other
+ requests. The compositor must process a series of requests preceding a
+ commit request atomically.
+
+ This allows changes to the workspace properties to be seen as atomic,
+ even if they happen via multiple events, and even if they involve
+ multiple zext_workspace_handle_v1 objects, for example, deactivating one
+ workspace and activating another.
+ </description>
+ </request>
+
+ <event name="done">
+ <description summary="all information about the workspace groups has been sent">
+ This event is sent after all changes in all workspace groups have been
+ sent.
+
+ This allows changes to one or more zext_workspace_group_handle_v1
+ properties to be seen as atomic, even if they happen via multiple
+ events. In particular, an output moving from one workspace group to
+ another sends an output_enter event and an output_leave event to the two
+ zext_workspace_group_handle_v1 objects in question. The compositor sends
+ the done event only after updating the output information in both
+ workspace groups.
+ </description>
+ </event>
+
+ <event name="finished">
+ <description summary="the compositor has finished with the workspace_manager">
+ This event indicates that the compositor is done sending events to the
+ zext_workspace_manager_v1. The server will destroy the object
+ immediately after sending this request, so it will become invalid and
+ the client should free any resources associated with it.
+ </description>
+ </event>
+
+ <request name="stop">
+ <description summary="stop sending events">
+ Indicates the client no longer wishes to receive events for new
+ workspace groups. However the compositor may emit further workspace
+ events, until the finished event is emitted.
+
+ The client must not send any more requests after this one.
+ </description>
+ </request>
+ </interface>
+
+ <interface name="zext_workspace_group_handle_v1" version="1">
+ <description summary="a workspace group assigned to a set of outputs">
+ A zext_workspace_group_handle_v1 object represents a a workspace group
+ that is assigned a set of outputs and contains a number of workspaces.
+
+ The set of outputs assigned to the workspace group is conveyed to the client via
+ output_enter and output_leave events, and its workspaces are conveyed with
+ workspace events.
+
+ For example, a compositor which has a set of workspaces for each output may
+ advertise a workspace group (and its workspaces) per output, whereas a compositor
+ where a workspace spans all outputs may advertise a single workspace group for all
+ outputs.
+ </description>
+
+ <event name="output_enter">
+ <description summary="output assigned to workspace group">
+ This event is emitted whenever an output is assigned to the workspace
+ group.
+ </description>
+ <arg name="output" type="object" interface="wl_output"/>
+ </event>
+
+ <event name="output_leave">
+ <description summary="output removed from workspace group">
+ This event is emitted whenever an output is removed from the workspace
+ group.
+ </description>
+ <arg name="output" type="object" interface="wl_output"/>
+ </event>
+
+ <event name="workspace">
+ <description summary="workspace added to workspace group">
+ This event is emitted whenever a new workspace has been created.
+
+ All initial details of the workspace (name, coordinates, state) will
+ be sent immediately after this event via the corresponding events in
+ zext_workspace_handle_v1.
+ </description>
+ <arg name="workspace" type="new_id" interface="zext_workspace_handle_v1"/>
+ </event>
+
+ <event name="remove">
+ <description summary="this workspace group has been destroyed">
+ This event means the zext_workspace_group_handle_v1 has been destroyed.
+ It is guaranteed there won't be any more events for this
+ zext_workspace_group_handle_v1. The zext_workspace_group_handle_v1 becomes
+ inert so any requests will be ignored except the destroy request.
+
+ The compositor must remove all workspaces belonging to a workspace group
+ before removing the workspace group.
+ </description>
+ </event>
+
+ <request name="create_workspace">
+ <description summary="create a new workspace">
+ Request that the compositor create a new workspace with the given name.
+
+ There is no guarantee that the compositor will create a new workspace,
+ or that the created workspace will have the provided name.
+ </description>
+ <arg name="workspace" type="string"/>
+ </request>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the zext_workspace_handle_v1 object">
+ Destroys the zext_workspace_handle_v1 object.
+
+ This request should be called either when the client does not want to
+ use the workspace object any more or after the remove event to finalize
+ the destruction of the object.
+ </description>
+ </request>
+ </interface>
+
+ <interface name="zext_workspace_handle_v1" version="1">
+ <description summary="a workspace handing a group of surfaces">
+ A zext_workspace_handle_v1 object represents a a workspace that handles a
+ group of surfaces.
+
+ Each workspace has a name, conveyed to the client with the name event; a
+ list of states, conveyed to the client with the state event; and
+ optionally a set of coordinates, conveyed to the client with the
+ coordinates event. The client may request that the compositor activate or
+ deactivate the workspace.
+
+ Each workspace can belong to only a single workspace group.
+ Depepending on the compositor policy, there might be workspaces with
+ the same name in different workspace groups, but these workspaces are still
+ separate (e.g. one of them might be active while the other is not).
+ </description>
+
+ <event name="name">
+ <description summary="workspace name changed">
+ This event is emitted immediately after the zext_workspace_handle_v1 is
+ created and whenever the name of the workspace changes.
+ </description>
+ <arg name="name" type="string"/>
+ </event>
+
+ <event name="coordinates">
+ <description summary="workspace coordinates changed">
+ This event is used to organize workspaces into an N-dimensional grid
+ within a workspace group, and if supported, is emitted immediately after
+ the zext_workspace_handle_v1 is created and whenever the coordinates of
+ the workspace change. Compositors may not send this event if they do not
+ conceptually arrange workspaces in this way. If compositors simply
+ number workspaces, without any geometric interpretation, they may send
+ 1D coordinates, which clients should not interpret as implying any
+ geometry. Sending an empty array means that the compositor no longer
+ orders the workspace geometrically.
+
+ Coordinates have an arbitrary number of dimensions N with an uint32
+ position along each dimension. By convention if N > 1, the first
+ dimension is X, the second Y, the third Z, and so on. The compositor may
+ chose to utilize these events for a more novel workspace layout
+ convention, however. No guarantee is made about the grid being filled or
+ bounded; there may be a workspace at coordinate 1 and another at
+ coordinate 1000 and none in between. Within a workspace group, however,
+ workspaces must have unique coordinates of equal dimensionality.
+ </description>
+ <arg name="coordinates" type="array"/>
+ </event>
+
+ <event name="state">
+ <description summary="the state of the workspace changed">
+ This event is emitted immediately after the zext_workspace_handle_v1 is
+ created and each time the workspace state changes, either because of a
+ compositor action or because of a request in this protocol.
+ </description>
+ <arg name="state" type="array"/>
+ </event>
+
+ <enum name="state">
+ <description summary="types of states on the workspace">
+ The different states that a workspace can have.
+ </description>
+
+ <entry name="active" value="0" summary="the workspace is active"/>
+ <entry name="urgent" value="1" summary="the workspace requests attention"/>
+ <entry name="hidden" value="2">
+ <description summary="the workspace is not visible">
+ The workspace is not visible in its workspace group, and clients
+ attempting to visualize the compositor workspace state should not
+ display such workspaces.
+ </description>
+ </entry>
+ </enum>
+
+ <event name="remove">
+ <description summary="this workspace has been destroyed">
+ This event means the zext_workspace_handle_v1 has been destroyed. It is
+ guaranteed there won't be any more events for this
+ zext_workspace_handle_v1. The zext_workspace_handle_v1 becomes inert so
+ any requests will be ignored except the destroy request.
+ </description>
+ </event>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the zext_workspace_handle_v1 object">
+ Destroys the zext_workspace_handle_v1 object.
+
+ This request should be called either when the client does not want to
+ use the workspace object any more or after the remove event to finalize
+ the destruction of the object.
+ </description>
+ </request>
+
+ <request name="activate">
+ <description summary="activate the workspace">
+ Request that this workspace be activated.
+
+ There is no guarantee the workspace will be actually activated, and
+ behaviour may be compositor-dependent. For example, activating a
+ workspace may or may not deactivate all other workspaces in the same
+ group.
+ </description>
+ </request>
+
+ <request name="deactivate">
+ <description summary="activate the workspace">
+ Request that this workspace be deactivated.
+
+ There is no guarantee the workspace will be actually deactivated.
+ </description>
+ </request>
+
+ <request name="remove">
+ <description summary="remove the workspace">
+ Request that this workspace be removed.
+
+ There is no guarantee the workspace will be actually removed.
+ </description>
+ </request>
+ </interface>
+</protocol>
diff --git a/src/pointer_btn.rs b/src/pointer_btn.rs
index 829fc9c..e5e0722 100644
--- a/src/pointer_btn.rs
+++ b/src/pointer_btn.rs
@@ -10,7 +10,7 @@ const BTN_FORWARD: u32 = 0x115;
const BTN_BACK: u32 = 0x116;
// const BTN_TASK: u32 = 0x117;
-#[derive(Debug, Clone, Copy)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PointerBtn {
Left,
Middle,
diff --git a/src/protocol.rs b/src/protocol.rs
index 5b30463..d14d92a 100644
--- a/src/protocol.rs
+++ b/src/protocol.rs
@@ -4,3 +4,6 @@ pub use wayrs_protocols::viewporter::*;
pub use wayrs_protocols::wlr_layer_shell_unstable_v1::*;
wayrs_client::scanner::generate!("protocols/river-status-unstable-v1.xml");
wayrs_client::scanner::generate!("protocols/river-control-unstable-v1.xml");
+
+#[cfg(feature = "hyprland")]
+wayrs_client::scanner::generate!("protocols/ext-workspace-unstable-v1.xml");
diff --git a/src/text.rs b/src/text.rs
index 61bf5ca..bc1516d 100644
--- a/src/text.rs
+++ b/src/text.rs
@@ -106,7 +106,8 @@ impl ComputedText {
context,
0.0,
0.0,
- self.width + options.overlap,
+ // HACK: this `+ 0.5` fixes some artifacts of fractional scaling
+ self.width + options.overlap + 0.5,
options.bar_height,
options.r_left,
options.r_right,
diff --git a/src/wm_info_provider.rs b/src/wm_info_provider.rs
index 12e4fb8..e11e48e 100644
--- a/src/wm_info_provider.rs
+++ b/src/wm_info_provider.rs
@@ -1,5 +1,3 @@
-mod river;
-
use wayrs_client::connection::Connection;
use wayrs_client::global::*;
@@ -7,9 +5,19 @@ use crate::pointer_btn::PointerBtn;
use crate::protocol::*;
use crate::state::State;
+#[cfg(feature = "hyprland")]
+mod ext_workspace_unstable;
+#[cfg(feature = "hyprland")]
+use ext_workspace_unstable::*;
+
+mod river;
+use river::*;
+
pub enum WmInfoProvider {
None,
- River(river::RiverInfoProvider),
+ River(RiverInfoProvider),
+ #[cfg(feature = "hyprland")]
+ Ewu(ExtWorkspaceUnstable),
}
pub type WmInfoCallback = fn(&mut Connection<State>, &mut State, WlOutput, WmInfo);
@@ -20,21 +28,33 @@ impl WmInfoProvider {
globals: &Globals,
callback: WmInfoCallback,
) -> WmInfoProvider {
- let Some(river) = river::RiverInfoProvider::bind(conn, globals, callback) else { return Self::None };
- Self::River(river)
+ if let Some(river) = RiverInfoProvider::bind(conn, globals, callback) {
+ return Self::River(river);
+ }
+
+ #[cfg(feature = "hyprland")]
+ if let Some(ext_wp_u) = ExtWorkspaceUnstable::bind(conn, globals, callback) {
+ return Self::Ewu(ext_wp_u);
+ }
+
+ Self::None
}
pub fn new_ouput(&mut self, conn: &mut Connection<State>, output: WlOutput) {
match self {
Self::None => (),
- Self::River(river) => river.new_output(conn, output),
+ Self::River(x) => x.new_output(conn, output),
+ #[cfg(feature = "hyprland")]
+ Self::Ewu(x) => x.new_ouput(conn, output),
}
}
pub fn output_removed(&mut self, conn: &mut Connection<State>, output: WlOutput) {
match self {
Self::None => (),
- Self::River(river) => river.output_removed(conn, output),
+ Self::River(x) => x.output_removed(conn, output),
+ #[cfg(feature = "hyprland")]
+ Self::Ewu(x) => x.output_removed(conn, output),
}
}
@@ -48,17 +68,20 @@ impl WmInfoProvider {
) {
match self {
Self::None => (),
- Self::River(river) => river.click_on_tag(conn, output, seat, tag, btn),
+ Self::River(x) => x.click_on_tag(conn, output, seat, tag, btn),
+ #[cfg(feature = "hyprland")]
+ Self::Ewu(x) => x.click_on_tag(conn, output, seat, tag, btn),
}
}
}
-#[derive(Default)]
+#[derive(Default, Debug)]
pub struct WmInfo {
pub layout_name: Option<String>,
pub tags: Vec<Tag>,
}
+#[derive(Debug)]
pub struct Tag {
pub name: String,
pub is_focused: bool,
diff --git a/src/wm_info_provider/ext_workspace_unstable.rs b/src/wm_info_provider/ext_workspace_unstable.rs
new file mode 100644
index 0000000..0af550b
--- /dev/null
+++ b/src/wm_info_provider/ext_workspace_unstable.rs
@@ -0,0 +1,215 @@
+use wayrs_client::connection::Connection;
+use wayrs_client::global::*;
+use wayrs_client::object::ObjectId;
+use wayrs_client::proxy::Proxy;
+
+use super::*;
+use crate::state::State;
+
+pub struct ExtWorkspaceUnstable {
+ manager: ZextWorkspaceManagerV1,
+ groups: Vec<Group>,
+ known_outputs: Vec<WlOutput>,
+ callback: WmInfoCallback,
+}
+
+#[derive(Debug)]
+struct Group {
+ group_handle: ZextWorkspaceGroupHandleV1,
+ workspaces: Vec<Workspace>,
+ outputs: Vec<ObjectId>,
+}
+
+#[derive(Debug)]
+struct Workspace {
+ workspace_handle: ZextWorkspaceHandleV1,
+ name: Option<String>,
+ is_focused: bool,
+ is_urgent: bool,
+}
+
+impl ExtWorkspaceUnstable {
+ pub fn bind(
+ conn: &mut Connection<State>,
+ globals: &Globals,
+ callback: WmInfoCallback,
+ ) -> Option<Self> {
+ Some(Self {
+ manager: globals.bind_with_cb(conn, 1..=1, manager_cb).ok()?,
+ groups: Vec::new(),
+ known_outputs: Vec::new(),
+ callback,
+ })
+ }
+}
+
+impl ExtWorkspaceUnstable {
+ pub fn new_ouput(&mut self, _: &mut Connection<State>, output: WlOutput) {
+ self.known_outputs.push(output);
+ }
+
+ pub fn output_removed(&mut self, _: &mut Connection<State>, output: WlOutput) {
+ self.known_outputs.retain(|&o| o != output);
+ for group in &mut self.groups {
+ group.outputs.retain(|&id| id != output.id());
+ }
+ }
+
+ pub fn click_on_tag(
+ &mut self,
+ conn: &mut Connection<State>,
+ _: WlOutput,
+ _: WlSeat,
+ tag: &str,
+ btn: PointerBtn,
+ ) {
+ if btn != PointerBtn::Left {
+ return;
+ }
+
+ let Some(ws) = self
+ .groups
+ .iter()
+ .find_map(|g| g.workspaces.iter().find(|w| w.name.as_deref() == Some(tag)))
+ else { return };
+
+ ws.workspace_handle.activate(conn);
+ self.manager.commit(conn);
+ }
+}
+
+fn manager_cb(
+ conn: &mut Connection<State>,
+ s: &mut State,
+ _: ZextWorkspaceManagerV1,
+ event: zext_workspace_manager_v1::Event,
+) {
+ let WmInfoProvider::Ewu(state) = &mut s.shared_state.wm_info_provider else { unreachable!() };
+
+ match event {
+ zext_workspace_manager_v1::Event::WorkspaceGroup(group_handle) => {
+ conn.set_callback_for(group_handle, group_cb);
+ state.groups.push(Group {
+ group_handle,
+ workspaces: Vec::new(),
+ outputs: Vec::new(),
+ });
+ }
+ zext_workspace_manager_v1::Event::Done => {
+ let mut events = Vec::new();
+ for &output in &state.known_outputs {
+ if let Some(group) = state
+ .groups
+ .iter()
+ .find(|g| g.outputs.contains(&output.id()))
+ {
+ let mut tags: Vec<_> = group
+ .workspaces
+ .iter()
+ .flat_map(|w| {
+ let name = w.name.clone()?;
+ Some(Tag {
+ name,
+ is_focused: w.is_focused,
+ is_active: true,
+ is_urgent: w.is_urgent,
+ })
+ })
+ .collect();
+ tags.sort_unstable_by(|a, b| a.name.cmp(&b.name));
+ events.push((output, tags));
+ }
+ }
+
+ let cb = state.callback;
+ for (output, tags) in events {
+ let info = WmInfo {
+ layout_name: None,
+ tags,
+ };
+ (cb)(conn, s, output, info);
+ }
+ }
+ zext_workspace_manager_v1::Event::Finished => unreachable!(),
+ }
+}
+
+fn group_cb(
+ conn: &mut Connection<State>,
+ state: &mut State,
+ group_handle: ZextWorkspaceGroupHandleV1,
+ event: zext_workspace_group_handle_v1::Event,
+) {
+ let WmInfoProvider::Ewu(state) = &mut state.shared_state.wm_info_provider else { unreachable!() };
+ let group = state
+ .groups
+ .iter_mut()
+ .find(|g| g.group_handle == group_handle)
+ .unwrap();
+
+ match event {
+ zext_workspace_group_handle_v1::Event::OutputEnter(output) => {
+ group.outputs.push(output);
+ }
+ zext_workspace_group_handle_v1::Event::OutputLeave(_) => todo!(),
+ zext_workspace_group_handle_v1::Event::Workspace(workspace_handle) => {
+ conn.set_callback_for(workspace_handle, workspace_cb);
+ group.workspaces.push(Workspace {
+ workspace_handle,
+ name: None,
+ is_focused: false,
+ is_urgent: false,
+ });
+ }
+ zext_workspace_group_handle_v1::Event::Remove => {
+ todo!();
+ }
+ }
+}
+
+fn workspace_cb(
+ conn: &mut Connection<State>,
+ state: &mut State,
+ workspace_handle: ZextWorkspaceHandleV1,
+ event: zext_workspace_handle_v1::Event,
+) {
+ let WmInfoProvider::Ewu(state) = &mut state.shared_state.wm_info_provider else { unreachable!() };
+ let group = state
+ .groups
+ .iter_mut()
+ .find(|g| {
+ g.workspaces
+ .iter()
+ .any(|w| w.workspace_handle == workspace_handle)
+ })
+ .unwrap();
+ let workspace = group
+ .workspaces
+ .iter_mut()
+ .find(|w| w.workspace_handle == workspace_handle)
+ .unwrap();
+
+ match event {
+ zext_workspace_handle_v1::Event::Name(name) => {
+ workspace.name = Some(name.to_string_lossy().into_owned());
+ }
+ zext_workspace_handle_v1::Event::Coordinates(_) => (),
+ zext_workspace_handle_v1::Event::State(state) => {
+ workspace.is_focused = false;
+ workspace.is_urgent = false;
+ for state in state
+ .chunks_exact(4)
+ .map(|b| u32::from_ne_bytes(b.try_into().unwrap()))
+ {
+ workspace.is_focused |= state == zext_workspace_handle_v1::State::Active as u32;
+ workspace.is_urgent |= state == zext_workspace_handle_v1::State::Urgent as u32;
+ }
+ }
+ zext_workspace_handle_v1::Event::Remove => {
+ group
+ .workspaces
+ .retain(|w| w.workspace_handle != workspace_handle);
+ workspace_handle.destroy(conn);
+ }
+ }
+}
diff --git a/src/wm_info_provider/river.rs b/src/wm_info_provider/river.rs
index c7740a3..82fa5d8 100644
--- a/src/wm_info_provider/river.rs
+++ b/src/wm_info_provider/river.rs
@@ -4,7 +4,6 @@ use wayrs_client::connection::Connection;
use wayrs_client::{cstr, global::*};
use super::*;
-use crate::protocol::*;
use crate::state::State;
pub struct RiverInfoProvider {