1
0
Fork 0
mirror of https://github.com/Zedfrigg/ironbar.git synced 2025-08-16 22:31:03 +02:00

refactor: update hyprland-rs, remove expects from hyprland client code

Fixes #960
This commit is contained in:
Jake Stanger 2025-05-16 22:15:32 +01:00
parent f3ae57bfe5
commit 1b6aa10423
No known key found for this signature in database
GPG key ID: C51FC8F9CB0BEA61
3 changed files with 233 additions and 102 deletions

118
Cargo.lock generated
View file

@ -168,6 +168,28 @@ dependencies = [
"syn 2.0.99",
]
[[package]]
name = "async-stream"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476"
dependencies = [
"async-stream-impl",
"futures-core",
"pin-project-lite",
]
[[package]]
name = "async-stream-impl"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
dependencies = [
"proc-macro2",
"quote 1.0.39",
"syn 2.0.99",
]
[[package]]
name = "async-trait"
version = "0.1.87"
@ -655,13 +677,23 @@ dependencies = [
[[package]]
name = "derive_more"
version = "0.99.19"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f"
checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05"
dependencies = [
"derive_more-impl",
]
[[package]]
name = "derive_more-impl"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
dependencies = [
"proc-macro2",
"quote 1.0.39",
"syn 2.0.99",
"unicode-xid 0.2.6",
]
[[package]]
@ -1542,17 +1574,20 @@ dependencies = [
[[package]]
name = "hyprland"
version = "0.4.0-alpha.3"
version = "0.4.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2de3f836e02af5a12f374d3a986867c1dc487a63a6d19477d66c7de50f715895"
checksum = "dc9c1413b6f0fd10b2e4463479490e30b2497ae4449f044da16053f5f2cb03b8"
dependencies = [
"ahash",
"async-stream",
"derive_more",
"either",
"futures-lite",
"hyprland-macros",
"num-traits",
"once_cell",
"paste",
"regex",
"phf",
"serde",
"serde_json",
"serde_repr",
@ -2457,6 +2492,48 @@ dependencies = [
"sha2",
]
[[package]]
name = "phf"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
dependencies = [
"phf_macros",
"phf_shared",
]
[[package]]
name = "phf_generator"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
dependencies = [
"phf_shared",
"rand",
]
[[package]]
name = "phf_macros"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216"
dependencies = [
"phf_generator",
"phf_shared",
"proc-macro2",
"quote 1.0.39",
"syn 2.0.99",
]
[[package]]
name = "phf_shared"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
dependencies = [
"siphasher",
]
[[package]]
name = "pin-project"
version = "1.1.10"
@ -2607,6 +2684,21 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
[[package]]
name = "redox_syscall"
version = "0.5.10"
@ -3038,6 +3130,12 @@ dependencies = [
"libc",
]
[[package]]
name = "siphasher"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
[[package]]
name = "slab"
version = "0.4.9"
@ -3160,7 +3258,7 @@ checksum = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
dependencies = [
"quote 0.3.15",
"synom",
"unicode-xid",
"unicode-xid 0.0.4",
]
[[package]]
@ -3200,7 +3298,7 @@ version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
dependencies = [
"unicode-xid",
"unicode-xid 0.0.4",
]
[[package]]
@ -3656,6 +3754,12 @@ version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
[[package]]
name = "unicode-xid"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "universal-config"
version = "0.5.1"

View file

@ -10,6 +10,7 @@ keywords = ["gtk", "bar", "wayland", "wlroots", "gtk-layer-shell"]
[features]
default = [
"bindmode+all",
"cli",
"cairo",
"clipboard",
@ -19,7 +20,6 @@ default = [
"focused",
"http",
"ipc",
"bindmode+all",
"keyboard+all",
"launcher",
"label",
@ -182,7 +182,7 @@ libpulse-binding = { version = "2.30.1", optional = true }
futures-lite = { version = "2.6.0", optional = true } # network_manager, upower, workspaces, keyboard
zbus = { version = "5.6.0", default-features = false, features = ["tokio"], optional = true } # network_manager, notifications, upower
swayipc-async = { version = "2.0.4", optional = true } # workspaces, keyboard
hyprland = { version = "0.4.0-alpha.3", features = ["silent"], optional = true } # workspaces, keyboard
hyprland = { version = "0.4.0-beta.2", optional = true } # workspaces, keyboard
rustix = { version = "1.0.7", default-features = false, features = ["std", "fs", "pipe", "event"], optional = true } # clipboard, input
serde_json = { version = "1.0.140", optional = true } # ipc, niri

View file

@ -1,3 +1,7 @@
#[cfg(feature = "bindmode+hyprland")]
use super::{BindModeClient, BindModeUpdate};
#[cfg(feature = "keyboard+hyprland")]
use super::{KeyboardLayoutClient, KeyboardLayoutUpdate};
use super::{Visibility, Workspace, WorkspaceUpdate};
use crate::{arc_mut, lock, send, spawn_blocking};
use color_eyre::Result;
@ -8,12 +12,7 @@ use hyprland::event_listener::EventListener;
use hyprland::prelude::*;
use hyprland::shared::{HyprDataVec, WorkspaceType};
use tokio::sync::broadcast::{Receiver, Sender, channel};
use tracing::{debug, error, info};
#[cfg(feature = "bindmode+hyprland")]
use super::{BindModeClient, BindModeUpdate};
#[cfg(feature = "keyboard+hyprland")]
use super::{KeyboardLayoutClient, KeyboardLayoutUpdate};
use tracing::{debug, error, info, warn};
#[derive(Debug)]
struct TxRx<T> {
@ -74,46 +73,56 @@ impl Client {
// cache the active workspace since Hyprland doesn't give us the prev active
#[cfg(feature = "workspaces+hyprland")]
Self::listen_workspace_events(workspace_tx, &mut event_listener, &lock);
Self::listen_workspace_events(&workspace_tx, &mut event_listener, &lock);
#[cfg(feature = "keyboard+hyprland")]
Self::listen_keyboard_events(keyboard_layout_tx, &mut event_listener, &lock);
Self::listen_keyboard_events(&keyboard_layout_tx, &mut event_listener, &lock);
#[cfg(feature = "bindmode+hyprland")]
Self::listen_bindmode_events(bindmode_tx, &mut event_listener, &lock);
Self::listen_bindmode_events(&bindmode_tx, &mut event_listener, &lock);
event_listener
.start_listener()
.expect("Failed to start listener");
if let Err(err) = event_listener.start_listener() {
error!("Failed to start listener: {err:#}");
}
});
}
#[cfg(feature = "workspaces+hyprland")]
fn listen_workspace_events(
tx: Sender<WorkspaceUpdate>,
tx: &Sender<WorkspaceUpdate>,
event_listener: &mut EventListener,
lock: &std::sync::Arc<std::sync::Mutex<()>>,
) {
let active = Self::get_active_workspace().expect("Failed to get active workspace");
let active = arc_mut!(Some(active));
let active = Self::get_active_workspace().map_or_else(
|err| {
error!("Failed to get active workspace: {err:#?}");
None
},
Some,
);
let active = arc_mut!(active);
{
let tx = tx.clone();
let lock = lock.clone();
let active = active.clone();
event_listener.add_workspace_added_handler(move |workspace_type| {
event_listener.add_workspace_added_handler(move |event| {
let _lock = lock!(lock);
debug!("Added workspace: {workspace_type:?}");
debug!("Added workspace: {event:?}");
let workspace_name = get_workspace_name(workspace_type);
let workspace_name = get_workspace_name(event.name);
let prev_workspace = lock!(active);
let workspace = Self::get_workspace(&workspace_name, prev_workspace.as_ref());
if let Some(workspace) = workspace {
match workspace {
Ok(Some(workspace)) => {
send!(tx, WorkspaceUpdate::Add(workspace));
}
Err(e) => error!("Failed to get workspace: {e:#}"),
_ => {}
}
});
}
@ -122,30 +131,29 @@ impl Client {
let lock = lock.clone();
let active = active.clone();
event_listener.add_workspace_change_handler(move |workspace_type| {
event_listener.add_workspace_changed_handler(move |event| {
let _lock = lock!(lock);
let mut prev_workspace = lock!(active);
debug!(
"Received workspace change: {:?} -> {workspace_type:?}",
"Received workspace change: {:?} -> {event:?}",
prev_workspace.as_ref().map(|w| &w.id)
);
let workspace_name = get_workspace_name(workspace_type);
let workspace_name = get_workspace_name(event.name);
let workspace = Self::get_workspace(&workspace_name, prev_workspace.as_ref());
workspace.map_or_else(
|| {
error!("Unable to locate workspace");
},
|workspace| {
// there may be another type of update so dispatch that regardless of focus change
if !workspace.visibility.is_focused() {
match workspace {
Ok(Some(workspace)) if !workspace.visibility.is_focused() => {
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
}
},
);
Ok(None) => {
error!("Unable to locate workspace");
}
Err(e) => error!("Failed to get workspace: {e:#}"),
_ => {}
}
});
}
@ -154,9 +162,12 @@ impl Client {
let lock = lock.clone();
let active = active.clone();
event_listener.add_active_monitor_change_handler(move |event_data| {
event_listener.add_active_monitor_changed_handler(move |event_data| {
let _lock = lock!(lock);
let workspace_type = event_data.workspace;
let Some(workspace_type) = event_data.workspace_name else {
warn!("Received active monitor change with no workspace name");
return;
};
let mut prev_workspace = lock!(active);
@ -168,11 +179,15 @@ impl Client {
let workspace_name = get_workspace_name(workspace_type);
let workspace = Self::get_workspace(&workspace_name, prev_workspace.as_ref());
if let Some((false, workspace)) = workspace.map(|w| (w.visibility.is_focused(), w))
{
match workspace {
Ok(Some(workspace)) if !workspace.visibility.is_focused() => {
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
} else {
error!("unable to locate workspace: {workspace_name}");
}
Ok(None) => {
error!("Unable to locate workspace");
}
Err(e) => error!("Failed to get workspace: {e:#}"),
_ => {}
}
});
}
@ -183,7 +198,7 @@ impl Client {
event_listener.add_workspace_moved_handler(move |event_data| {
let _lock = lock!(lock);
let workspace_type = event_data.workspace;
let workspace_type = event_data.name;
debug!("Received workspace move: {workspace_type:?}");
let mut prev_workspace = lock!(active);
@ -191,12 +206,15 @@ impl Client {
let workspace_name = get_workspace_name(workspace_type);
let workspace = Self::get_workspace(&workspace_name, prev_workspace.as_ref());
if let Some(workspace) = workspace {
send!(tx, WorkspaceUpdate::Move(workspace.clone()));
if !workspace.visibility.is_focused() {
match workspace {
Ok(Some(workspace)) if !workspace.visibility.is_focused() => {
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
}
Ok(None) => {
error!("Unable to locate workspace");
}
Err(e) => error!("Failed to get workspace: {e:#}"),
_ => {}
}
});
}
@ -205,15 +223,15 @@ impl Client {
let tx = tx.clone();
let lock = lock.clone();
event_listener.add_workspace_rename_handler(move |data| {
event_listener.add_workspace_renamed_handler(move |data| {
let _lock = lock!(lock);
debug!("Received workspace rename: {data:?}");
send!(
tx,
WorkspaceUpdate::Rename {
id: data.workspace_id as i64,
name: data.workspace_name
id: data.id as i64,
name: data.name
}
);
});
@ -223,10 +241,10 @@ impl Client {
let tx = tx.clone();
let lock = lock.clone();
event_listener.add_workspace_destroy_handler(move |data| {
event_listener.add_workspace_deleted_handler(move |data| {
let _lock = lock!(lock);
debug!("Received workspace destroy: {data:?}");
send!(tx, WorkspaceUpdate::Remove(data.workspace_id as i64));
send!(tx, WorkspaceUpdate::Remove(data.id as i64));
});
}
@ -234,7 +252,7 @@ impl Client {
let tx = tx.clone();
let lock = lock.clone();
event_listener.add_urgent_state_handler(move |address| {
event_listener.add_urgent_state_changed_handler(move |address| {
let _lock = lock!(lock);
debug!("Received urgent state: {address:?}");
@ -265,14 +283,14 @@ impl Client {
#[cfg(feature = "keyboard+hyprland")]
fn listen_keyboard_events(
keyboard_layout_tx: Sender<KeyboardLayoutUpdate>,
keyboard_layout_tx: &Sender<KeyboardLayoutUpdate>,
event_listener: &mut EventListener,
lock: &std::sync::Arc<std::sync::Mutex<()>>,
) {
let tx = keyboard_layout_tx.clone();
let lock = lock.clone();
event_listener.add_keyboard_layout_change_handler(move |layout_event| {
event_listener.add_layout_changed_handler(move |layout_event| {
let _lock = lock!(lock);
let layout = if layout_event.layout_name.is_empty() {
@ -319,14 +337,14 @@ impl Client {
#[cfg(feature = "bindmode+hyprland")]
fn listen_bindmode_events(
bindmode_tx: Sender<BindModeUpdate>,
bindmode_tx: &Sender<BindModeUpdate>,
event_listener: &mut EventListener,
lock: &std::sync::Arc<std::sync::Mutex<()>>,
) {
let tx = bindmode_tx.clone();
let lock = lock.clone();
event_listener.add_sub_map_change_handler(move |bind_mode| {
event_listener.add_sub_map_changed_handler(move |bind_mode| {
let _lock = lock!(lock);
debug!("Received bind mode: {bind_mode:?}");
@ -369,11 +387,8 @@ impl Client {
/// Gets a workspace by name from the server, given the active workspace if known.
#[cfg(feature = "workspaces+hyprland")]
fn get_workspace(name: &str, active: Option<&Workspace>) -> Option<Workspace> {
Workspaces::get()
.expect("Failed to get workspaces")
.into_iter()
.find_map(|w| {
fn get_workspace(name: &str, active: Option<&Workspace>) -> Result<Option<Workspace>> {
let workspace = Workspaces::get()?.into_iter().find_map(|w| {
if w.name == name {
let vis = Visibility::from((&w, active.map(|w| w.name.as_ref()), &|w| {
create_is_visible()(w)
@ -383,7 +398,9 @@ impl Client {
} else {
None
}
})
});
Ok(workspace)
}
/// Gets the active workspace from the server.
@ -409,17 +426,22 @@ impl super::WorkspaceClient for Client {
let active_id = HWorkspace::get_active().ok().map(|active| active.name);
let is_visible = create_is_visible();
let workspaces = Workspaces::get()
.expect("Failed to get workspaces")
match Workspaces::get() {
Ok(workspaces) => {
let workspaces = workspaces
.into_iter()
.map(|w| {
let vis = Visibility::from((&w, active_id.as_deref(), &is_visible));
Workspace::from((vis, w))
})
.collect();
send!(self.workspace.tx, WorkspaceUpdate::Init(workspaces));
}
Err(e) => {
error!("Failed to get workspaces: {e:#}");
}
}
rx
}
@ -428,8 +450,12 @@ impl super::WorkspaceClient for Client {
#[cfg(feature = "keyboard+hyprland")]
impl KeyboardLayoutClient for Client {
fn set_next_active(&self) {
let device = Devices::get()
.expect("Failed to get devices")
let Ok(devices) = Devices::get() else {
error!("Failed to get devices");
return;
};
let device = devices
.keyboards
.iter()
.find(|k| k.main)
@ -449,17 +475,18 @@ impl KeyboardLayoutClient for Client {
fn subscribe(&self) -> Receiver<KeyboardLayoutUpdate> {
let rx = self.keyboard_layout.tx.subscribe();
let layout = Devices::get()
.expect("Failed to get devices")
match Devices::get().map(|devices| {
devices
.keyboards
.iter()
.find(|k| k.main)
.map(|k| k.active_keymap.clone());
if let Some(layout) = layout {
.map(|k| k.active_keymap.clone())
}) {
Ok(Some(layout)) => {
send!(self.keyboard_layout.tx, KeyboardLayoutUpdate(layout));
} else {
error!("Failed to get current keyboard layout hyprland");
}
Ok(None) => error!("Failed to get current keyboard layout hyprland"),
Err(err) => error!("Failed to get devices: {err:#?}"),
}
rx