From 5e7f576841f94bdfd89d401cb9a2ba1fabb45c1c Mon Sep 17 00:00:00 2001 From: Jake Stanger Date: Mon, 6 May 2024 16:46:26 +0100 Subject: [PATCH] fix(workspaces): add support for hyprland rename event Renaming workspaces on Hyprland will now work as expected. This also refactors the workspace code to depend on IDs rather than names which should make it more robust against the same sort of issue in future. Fixes #469 --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- src/clients/compositor/hyprland.rs | 25 ++++++++++++++++++----- src/clients/compositor/mod.rs | 6 ++++++ src/modules/workspaces.rs | 32 ++++++++++++++++++++---------- 5 files changed, 52 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6e6fb67..2816d7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1444,9 +1444,9 @@ dependencies = [ [[package]] name = "hyprland" -version = "0.4.0-alpha.1" +version = "0.4.0-alpha.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54fdc60390459bd6da28ec708ee7a672b8f6680efb8f8f33cbe970da16f40a48" +checksum = "d627cd06fb3389f2554b7a4bb21db8c0bfca8863e6e653702cc4c6dbf20d8276" dependencies = [ "ahash", "derive_more", @@ -2008,9 +2008,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] diff --git a/Cargo.toml b/Cargo.toml index 3e6b4c4..1c2b605 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -148,7 +148,7 @@ libpulse-binding = { version = "2.28.1", optional = true } # workspaces swayipc-async = { version = "2.0.1", optional = true } -hyprland = { version = "0.4.0-alpha.1", features = ["silent"], optional = true } +hyprland = { version = "0.4.0-alpha.2", features = ["silent"], optional = true } futures-util = { version = "0.3.30", optional = true } num-traits = "0.2.18" diff --git a/src/clients/compositor/hyprland.rs b/src/clients/compositor/hyprland.rs index d5c453c..3932578 100644 --- a/src/clients/compositor/hyprland.rs +++ b/src/clients/compositor/hyprland.rs @@ -149,12 +149,27 @@ impl Client { } { - event_listener.add_workspace_destroy_handler(move |workspace_type| { - let _lock = lock!(lock); - debug!("Received workspace destroy: {workspace_type:?}"); + let tx = tx.clone(); + let lock = lock.clone(); - let name = get_workspace_name(workspace_type); - send!(tx, WorkspaceUpdate::Remove(name)); + event_listener.add_workspace_rename_handler(move |data| { + let _lock = lock!(lock); + + send!( + tx, + WorkspaceUpdate::Rename { + id: data.workspace_id.to_string(), + name: data.workspace_name + } + ); + }); + } + + { + event_listener.add_workspace_destroy_handler(move |data| { + let _lock = lock!(lock); + debug!("Received workspace destroy: {data:?}"); + send!(tx, WorkspaceUpdate::Remove(data.workspace_id.to_string())); }); } diff --git a/src/clients/compositor/mod.rs b/src/clients/compositor/mod.rs index 0371913..6dc2398 100644 --- a/src/clients/compositor/mod.rs +++ b/src/clients/compositor/mod.rs @@ -126,6 +126,12 @@ pub enum WorkspaceUpdate { old: Option, new: Workspace, }, + + Rename { + id: String, + name: String, + }, + /// An update was triggered by the compositor but this was not mapped by Ironbar. /// /// This is purely used for ergonomics within the compositor clients diff --git a/src/modules/workspaces.rs b/src/modules/workspaces.rs index 4eb0755..45e816e 100644 --- a/src/modules/workspaces.rs +++ b/src/modules/workspaces.rs @@ -135,7 +135,7 @@ fn reorder_workspaces(container: >k::Box) { impl WorkspacesModule { fn show_workspace_check(&self, output: &String, work: &Workspace) -> bool { - (work.visibility.is_focused() || !self.hidden.contains(&work.name)) + (work.visibility.is_focused() || !self.hidden.contains(&work.id)) && (self.all_monitors || output == &work.monitor) } } @@ -213,7 +213,7 @@ impl Module for WorkspacesModule { let mut added = HashSet::new(); - let mut add_workspace = |name: &str, visibility: Visibility| { + let mut add_workspace = |id: &str, name: &str, visibility: Visibility| { let item = create_button( name, visibility, @@ -224,13 +224,13 @@ impl Module for WorkspacesModule { ); container.add(&item); - button_map.insert(name.to_string(), item); + button_map.insert(id.to_string(), item); }; // add workspaces from client for workspace in &workspaces { if self.show_workspace_check(&output_name, workspace) { - add_workspace(&workspace.name, workspace.visibility); + add_workspace(&workspace.id, &workspace.name, workspace.visibility); added.insert(workspace.name.to_string()); } } @@ -240,7 +240,11 @@ impl Module for WorkspacesModule { fav_names.push(name.to_string()); if !added.contains(name) { - add_workspace(name, Visibility::Hidden); + // Favourites are added with the same name and ID + // as Hyprland will initialize them this way. + // Since existing workspaces are added above, + // this means there shouldn't be any issues with renaming. + add_workspace(name, name, Visibility::Hidden); added.insert(name.to_string()); } } @@ -265,7 +269,7 @@ impl Module for WorkspacesModule { } } WorkspaceUpdate::Focus { old, new } => { - if let Some(btn) = old.as_ref().and_then(|w| button_map.get(&w.name)) { + if let Some(btn) = old.as_ref().and_then(|w| button_map.get(&w.id)) { if Some(new.monitor) == old.map(|w| w.monitor) { btn.style_context().remove_class("visible"); } @@ -273,7 +277,7 @@ impl Module for WorkspacesModule { btn.style_context().remove_class("focused"); } - let new = button_map.get(&new.name); + let new = button_map.get(&new.id); if let Some(btn) = new { let style = btn.style_context(); @@ -281,9 +285,15 @@ impl Module for WorkspacesModule { style.add_class("focused"); } } + WorkspaceUpdate::Rename { id, name } => { + if let Some(btn) = button_map.get(&id) { + let name = name_map.get(&name).unwrap_or(&name); + btn.set_label(name); + } + } WorkspaceUpdate::Add(workspace) => { if fav_names.contains(&workspace.name) { - let btn = button_map.get(&workspace.name); + let btn = button_map.get(&workspace.id); if let Some(btn) = btn { btn.style_context().remove_class("inactive"); } @@ -306,7 +316,7 @@ impl Module for WorkspacesModule { item.show(); if !name.is_empty() { - button_map.insert(name, item); + button_map.insert(workspace.id, item); } } } @@ -332,9 +342,9 @@ impl Module for WorkspacesModule { item.show(); if !name.is_empty() { - button_map.insert(name, item); + button_map.insert(workspace.id, item); } - } else if let Some(item) = button_map.get(&workspace.name) { + } else if let Some(item) = button_map.get(&workspace.id) { container.remove(item); } }