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

build: fix compilation for many feature combinations (#932)

* Fix compilation for many feature combinations

* fix: keep Mpris as the default music player type

* fix: update futures-lite comment

* fix: remove redundant "clap" feature dependency from "cli"

* fix: don't make IPC a dependency of sysinfo module

* refactor: move serde_json feature to "shared" section

* refactor: avoid cfgs inside listen_workspace_events

by splitting list_keyboards_events out of it, which manages its own
connection to the Hyprland IPC socket.

* refactor: sort multiline cfg any's

* Revert "refactor: avoid cfgs inside listen_workspace_events"

This reverts commit 1b4202ed80c9483c609ada8c4436e0fec26a9eef.

* refactor: split listen_workspace_events in more functions

* style: fix broken identation

Not sure why rustfmt didn't catch this.
This commit is contained in:
Rodrigo Batista de Moraes 2025-04-16 18:43:14 -03:00 committed by GitHub
parent 5744929931
commit cff6b1fc83
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 363 additions and 265 deletions

View file

@ -30,11 +30,11 @@ default = [
"tray",
"upower",
"volume",
"workspaces+all"
"workspaces+all",
]
cli = ["dep:clap", "ipc"]
ipc = ["dep:serde_json"]
cli = ["ipc"]
ipc = ["dep:serde_json", "dep:clap"]
http = ["dep:reqwest"]
@ -61,7 +61,7 @@ custom = []
focused = []
keyboard = ["dep:colpetto", "dep:evdev-rs", "dep:rustix"]
keyboard = ["dep:colpetto", "dep:evdev-rs", "dep:rustix", "futures-lite"]
"keyboard+all" = ["keyboard", "keyboard+sway", "keyboard+hyprland"]
"keyboard+sway" = ["keyboard", "sway"]
"keyboard+hyprland" = ["keyboard", "hyprland"]
@ -93,10 +93,12 @@ workspaces = ["futures-lite"]
"workspaces+all" = ["workspaces", "workspaces+sway", "workspaces+hyprland", "workspaces+niri"]
"workspaces+sway" = ["workspaces", "sway"]
"workspaces+hyprland" = ["workspaces", "hyprland"]
"workspaces+niri" = ["workspaces"]
"workspaces+niri" = ["workspaces", "niri"]
sway = ["swayipc-async", "futures-lite"]
niri = ["dep:serde_json"]
schema = ["dep:schemars"]
[dependencies]
@ -136,9 +138,6 @@ cfg-if = "1.0.0"
# cli
clap = { version = "4.5.36", optional = true, features = ["derive"] }
# ipc
serde_json = { version = "1.0.140", optional = true }
# http
reqwest = { version = "0.12.15", default-features = false, features = ["default-tls", "http2"], optional = true }
@ -174,11 +173,12 @@ system-tray = { version = "0.7.0", features = ["dbusmenu-gtk3"], optional = true
libpulse-binding = { version = "2.29.0", optional = true }
# shared
futures-lite = { version = "2.6.0", optional = true } # network_manager, upower, workspaces
futures-lite = { version = "2.6.0", optional = true } # network_manager, upower, workspaces, keyboard
zbus = { version = "5.5.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
rustix = { version = "1.0.5", default-features = false, features = ["std", "fs", "pipe", "event"], optional = true } # clipboard, input
serde_json = { version = "1.0.140", optional = true } # ipc, niri
# schema
schemars = { version = "0.8.22", optional = true }

View file

@ -1,4 +1,4 @@
use super::{KeyboardLayoutClient, KeyboardLayoutUpdate, Visibility, Workspace, WorkspaceUpdate};
use super::{Visibility, Workspace, WorkspaceUpdate};
use crate::{arc_mut, lock, send, spawn_blocking};
use color_eyre::Result;
use hyprland::ctl::switch_xkb_layout;
@ -11,35 +11,53 @@ use tokio::sync::broadcast::{Receiver, Sender, channel};
use tracing::{debug, error, info};
#[derive(Debug)]
pub struct Client {
workspace_tx: Sender<WorkspaceUpdate>,
_workspace_rx: Receiver<WorkspaceUpdate>,
struct TxRx<T> {
tx: Sender<T>,
_rx: Receiver<T>,
}
keyboard_layout_tx: Sender<KeyboardLayoutUpdate>,
_keyboard_layout_rx: Receiver<KeyboardLayoutUpdate>,
#[derive(Debug)]
pub struct Client {
#[cfg(feature = "workspaces+hyprland")]
workspace: TxRx<WorkspaceUpdate>,
#[cfg(feature = "keyboard+hyprland")]
keyboard_layout: TxRx<KeyboardLayoutUpdate>,
}
impl Client {
pub(crate) fn new() -> Self {
#[cfg(feature = "workspaces+hyprland")]
let (workspace_tx, workspace_rx) = channel(16);
#[cfg(feature = "keyboard+hyprland")]
let (keyboard_layout_tx, keyboard_layout_rx) = channel(16);
let instance = Self {
workspace_tx,
_workspace_rx: workspace_rx,
keyboard_layout_tx,
_keyboard_layout_rx: keyboard_layout_rx,
#[cfg(feature = "workspaces+hyprland")]
workspace: TxRx {
tx: workspace_tx,
_rx: workspace_rx,
},
#[cfg(feature = "keyboard+hyprland")]
keyboard_layout: TxRx {
tx: keyboard_layout_tx,
_rx: keyboard_layout_rx,
},
};
instance.listen_workspace_events();
instance.listen_events();
instance
}
fn listen_workspace_events(&self) {
fn listen_events(&self) {
info!("Starting Hyprland event listener");
let tx = self.workspace_tx.clone();
let keyboard_layout_tx = self.keyboard_layout_tx.clone();
#[cfg(feature = "workspaces+hyprland")]
let tx = self.workspace.tx.clone();
#[cfg(feature = "keyboard+hyprland")]
let keyboard_layout_tx = self.keyboard_layout.tx.clone();
spawn_blocking(move || {
let mut event_listener = EventListener::new();
@ -48,223 +66,11 @@ impl Client {
let lock = arc_mut!(());
// cache the active workspace since Hyprland doesn't give us the prev active
let active = Self::get_active_workspace().expect("Failed to get active workspace");
let active = arc_mut!(Some(active));
#[cfg(feature = "workspaces+hyprland")]
Self::listen_workspace_events(tx, &mut event_listener, &lock);
{
let tx = tx.clone();
let lock = lock.clone();
let active = active.clone();
event_listener.add_workspace_added_handler(move |workspace_type| {
let _lock = lock!(lock);
debug!("Added workspace: {workspace_type:?}");
let workspace_name = get_workspace_name(workspace_type);
let prev_workspace = lock!(active);
let workspace = Self::get_workspace(&workspace_name, prev_workspace.as_ref());
if let Some(workspace) = workspace {
send!(tx, WorkspaceUpdate::Add(workspace));
}
});
}
{
let tx = tx.clone();
let lock = lock.clone();
let active = active.clone();
event_listener.add_workspace_change_handler(move |workspace_type| {
let _lock = lock!(lock);
let mut prev_workspace = lock!(active);
debug!(
"Received workspace change: {:?} -> {workspace_type:?}",
prev_workspace.as_ref().map(|w| &w.id)
);
let workspace_name = get_workspace_name(workspace_type);
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() {
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
}
},
);
});
}
{
let tx = tx.clone();
let lock = lock.clone();
let active = active.clone();
event_listener.add_active_monitor_change_handler(move |event_data| {
let _lock = lock!(lock);
let workspace_type = event_data.workspace;
let mut prev_workspace = lock!(active);
debug!(
"Received active monitor change: {:?} -> {workspace_type:?}",
prev_workspace.as_ref().map(|w| &w.name)
);
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))
{
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
} else {
error!("unable to locate workspace: {workspace_name}");
}
});
}
{
let tx = tx.clone();
let lock = lock.clone();
event_listener.add_workspace_moved_handler(move |event_data| {
let _lock = lock!(lock);
let workspace_type = event_data.workspace;
debug!("Received workspace move: {workspace_type:?}");
let mut prev_workspace = lock!(active);
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() {
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
}
}
});
}
{
let tx = tx.clone();
let lock = lock.clone();
event_listener.add_workspace_rename_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
}
);
});
}
{
let tx = tx.clone();
let lock = lock.clone();
event_listener.add_workspace_destroy_handler(move |data| {
let _lock = lock!(lock);
debug!("Received workspace destroy: {data:?}");
send!(tx, WorkspaceUpdate::Remove(data.workspace_id as i64));
});
}
{
let tx = tx.clone();
let lock = lock.clone();
event_listener.add_urgent_state_handler(move |address| {
let _lock = lock!(lock);
debug!("Received urgent state: {address:?}");
let clients = match hyprland::data::Clients::get() {
Ok(clients) => clients,
Err(err) => {
error!("Failed to get clients: {err}");
return;
}
};
clients.iter().find(|c| c.address == address).map_or_else(
|| {
error!("Unable to locate client");
},
|c| {
send!(
tx,
WorkspaceUpdate::Urgent {
id: c.workspace.id as i64,
urgent: true,
}
);
},
);
});
}
{
let tx = keyboard_layout_tx.clone();
let lock = lock.clone();
event_listener.add_keyboard_layout_change_handler(move |layout_event| {
let _lock = lock!(lock);
let layout = if layout_event.layout_name.is_empty() {
// FIXME: This field is empty due to bug in `hyprland-rs_0.4.0-alpha.3`. Which is already fixed in last betas
// The layout may be empty due to a bug in `hyprland-rs`, because of which the `layout_event` is incorrect.
//
// Instead of:
// ```
// LayoutEvent {
// keyboard_name: "keychron-keychron-c2",
// layout_name: "English (US)",
// }
// ```
//
// We get:
// ```
// LayoutEvent {
// keyboard_name: "keychron-keychron-c2,English (US)",
// layout_name: "",
// }
// ```
//
// Here we are trying to recover `layout_name` from `keyboard_name`
let layout = layout_event.keyboard_name.as_str().split(',').nth(1);
let Some(layout) = layout else {
error!(
"Failed to get layout from string: {}. The failed logic is a workaround for a bug in `hyprland 0.4.0-alpha.3`", layout_event.keyboard_name);
return;
};
layout.into()
}
else {
layout_event.layout_name
};
debug!("Received layout: {layout:?}");
send!(tx, KeyboardLayoutUpdate(layout));
});
}
#[cfg(feature = "keyboard+hyprland")]
Self::listen_keyboard_events(keyboard_layout_tx, &mut event_listener, lock);
event_listener
.start_listener()
@ -272,8 +78,238 @@ impl Client {
});
}
#[cfg(feature = "workspaces+hyprland")]
fn listen_workspace_events(
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 tx = tx.clone();
let lock = lock.clone();
let active = active.clone();
event_listener.add_workspace_added_handler(move |workspace_type| {
let _lock = lock!(lock);
debug!("Added workspace: {workspace_type:?}");
let workspace_name = get_workspace_name(workspace_type);
let prev_workspace = lock!(active);
let workspace = Self::get_workspace(&workspace_name, prev_workspace.as_ref());
if let Some(workspace) = workspace {
send!(tx, WorkspaceUpdate::Add(workspace));
}
});
}
{
let tx = tx.clone();
let lock = lock.clone();
let active = active.clone();
event_listener.add_workspace_change_handler(move |workspace_type| {
let _lock = lock!(lock);
let mut prev_workspace = lock!(active);
debug!(
"Received workspace change: {:?} -> {workspace_type:?}",
prev_workspace.as_ref().map(|w| &w.id)
);
let workspace_name = get_workspace_name(workspace_type);
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() {
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
}
},
);
});
}
{
let tx = tx.clone();
let lock = lock.clone();
let active = active.clone();
event_listener.add_active_monitor_change_handler(move |event_data| {
let _lock = lock!(lock);
let workspace_type = event_data.workspace;
let mut prev_workspace = lock!(active);
debug!(
"Received active monitor change: {:?} -> {workspace_type:?}",
prev_workspace.as_ref().map(|w| &w.name)
);
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))
{
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
} else {
error!("unable to locate workspace: {workspace_name}");
}
});
}
{
let tx = tx.clone();
let lock = lock.clone();
event_listener.add_workspace_moved_handler(move |event_data| {
let _lock = lock!(lock);
let workspace_type = event_data.workspace;
debug!("Received workspace move: {workspace_type:?}");
let mut prev_workspace = lock!(active);
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() {
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
}
}
});
}
{
let tx = tx.clone();
let lock = lock.clone();
event_listener.add_workspace_rename_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
}
);
});
}
{
let tx = tx.clone();
let lock = lock.clone();
event_listener.add_workspace_destroy_handler(move |data| {
let _lock = lock!(lock);
debug!("Received workspace destroy: {data:?}");
send!(tx, WorkspaceUpdate::Remove(data.workspace_id as i64));
});
}
{
let tx = tx.clone();
let lock = lock.clone();
event_listener.add_urgent_state_handler(move |address| {
let _lock = lock!(lock);
debug!("Received urgent state: {address:?}");
let clients = match hyprland::data::Clients::get() {
Ok(clients) => clients,
Err(err) => {
error!("Failed to get clients: {err}");
return;
}
};
clients.iter().find(|c| c.address == address).map_or_else(
|| {
error!("Unable to locate client");
},
|c| {
send!(
tx,
WorkspaceUpdate::Urgent {
id: c.workspace.id as i64,
urgent: true,
}
);
},
);
});
}
}
#[cfg(feature = "keyboard+hyprland")]
fn listen_keyboard_events(
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| {
let _lock = lock!(lock);
let layout = if layout_event.layout_name.is_empty() {
// FIXME: This field is empty due to bug in `hyprland-rs_0.4.0-alpha.3`. Which is already fixed in last betas
// The layout may be empty due to a bug in `hyprland-rs`, because of which the `layout_event` is incorrect.
//
// Instead of:
// ```
// LayoutEvent {
// keyboard_name: "keychron-keychron-c2",
// layout_name: "English (US)",
// }
// ```
//
// We get:
// ```
// LayoutEvent {
// keyboard_name: "keychron-keychron-c2,English (US)",
// layout_name: "",
// }
// ```
//
// Here we are trying to recover `layout_name` from `keyboard_name`
let layout = layout_event.keyboard_name.as_str().split(',').nth(1);
let Some(layout) = layout else {
error!(
"Failed to get layout from string: {}. The failed logic is a workaround for a bug in `hyprland 0.4.0-alpha.3`", layout_event.keyboard_name);
return;
};
layout.into()
}
else {
layout_event.layout_name
};
debug!("Received layout: {layout:?}");
send!(tx, KeyboardLayoutUpdate(layout));
});
}
/// Sends a `WorkspaceUpdate::Focus` event
/// and updates the active workspace cache.
#[cfg(feature = "workspaces+hyprland")]
fn send_focus_change(
prev_workspace: &mut Option<Workspace>,
workspace: Workspace,
@ -299,6 +335,7 @@ 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")
@ -323,7 +360,7 @@ impl Client {
}
}
#[cfg(feature = "workspaces")]
#[cfg(feature = "workspaces+hyprland")]
impl super::WorkspaceClient for Client {
fn focus(&self, id: i64) {
let identifier = WorkspaceIdentifierWithSpecial::Id(id as i32);
@ -334,7 +371,7 @@ impl super::WorkspaceClient for Client {
}
fn subscribe(&self) -> Receiver<WorkspaceUpdate> {
let rx = self.workspace_tx.subscribe();
let rx = self.workspace.tx.subscribe();
let active_id = HWorkspace::get_active().ok().map(|active| active.name);
let is_visible = create_is_visible();
@ -349,12 +386,16 @@ impl super::WorkspaceClient for Client {
})
.collect();
send!(self.workspace_tx, WorkspaceUpdate::Init(workspaces));
send!(self.workspace.tx, WorkspaceUpdate::Init(workspaces));
rx
}
}
#[cfg(feature = "keyboard+hyprland")]
use super::{KeyboardLayoutClient, KeyboardLayoutUpdate};
#[cfg(feature = "keyboard+hyprland")]
impl KeyboardLayoutClient for Client {
fn set_next_active(&self) {
let device = Devices::get()
@ -376,7 +417,7 @@ impl KeyboardLayoutClient for Client {
}
fn subscribe(&self) -> Receiver<KeyboardLayoutUpdate> {
let rx = self.keyboard_layout_tx.subscribe();
let rx = self.keyboard_layout.tx.subscribe();
let layout = Devices::get()
.expect("Failed to get devices")
@ -386,7 +427,7 @@ impl KeyboardLayoutClient for Client {
.map(|k| k.active_keymap.clone());
if let Some(layout) = layout {
send!(self.keyboard_layout_tx, KeyboardLayoutUpdate(layout));
send!(self.keyboard_layout.tx, KeyboardLayoutUpdate(layout));
} else {
error!("Failed to get current keyboard layout hyprland");
}

View file

@ -7,19 +7,19 @@ use std::sync::Arc;
use tokio::sync::broadcast;
use tracing::debug;
#[cfg(any(feature = "keyboard+hyprland", feature = "workspaces+hyprland"))]
#[cfg(feature = "hyprland")]
pub mod hyprland;
#[cfg(feature = "workspaces+niri")]
#[cfg(feature = "niri")]
pub mod niri;
#[cfg(any(feature = "keyboard+sway", feature = "workspaces+sway"))]
#[cfg(feature = "sway")]
pub mod sway;
pub enum Compositor {
#[cfg(any(feature = "keyboard+sway", feature = "workspaces+sway"))]
#[cfg(feature = "sway")]
Sway,
#[cfg(any(feature = "keyboard+hyprland", feature = "workspaces+hyprland"))]
#[cfg(feature = "hyprland")]
Hyprland,
#[cfg(feature = "workspaces+niri")]
#[cfg(feature = "niri")]
Niri,
Unsupported,
}
@ -30,9 +30,9 @@ impl Display for Compositor {
f,
"{}",
match self {
#[cfg(any(feature = "keyboard+sway", feature = "workspaces+sway"))]
#[cfg(any(feature = "sway"))]
Self::Sway => "Sway",
#[cfg(any(feature = "keyboard+hyprland", feature = "workspaces+hyprland"))]
#[cfg(any(feature = "hyprland"))]
Self::Hyprland => "Hyprland",
#[cfg(feature = "workspaces+niri")]
Self::Niri => "Niri",
@ -48,17 +48,17 @@ impl Compositor {
fn get_current() -> Self {
if std::env::var("SWAYSOCK").is_ok() {
cfg_if! {
if #[cfg(any(feature = "keyboard+sway", feature = "workspaces+sway"))] { Self::Sway }
if #[cfg(feature = "sway")] { Self::Sway }
else { tracing::error!("Not compiled with Sway support"); Self::Unsupported }
}
} else if std::env::var("HYPRLAND_INSTANCE_SIGNATURE").is_ok() {
cfg_if! {
if #[cfg(any(feature = "keyboard+hyprland", feature = "workspaces+hyprland"))] { Self::Hyprland }
if #[cfg(feature = "hyprland")] { Self::Hyprland }
else { tracing::error!("Not compiled with Hyprland support"); Self::Unsupported }
}
} else if std::env::var("NIRI_SOCKET").is_ok() {
cfg_if! {
if #[cfg(feature = "workspaces+niri")] { Self::Niri }
if #[cfg(feature = "niri")] { Self::Niri }
else {tracing::error!("Not compiled with Niri support"); Self::Unsupported }
}
} else {
@ -79,13 +79,16 @@ impl Compositor {
.map(|client| client as Arc<dyn KeyboardLayoutClient + Send + Sync>),
#[cfg(feature = "keyboard+hyprland")]
Self::Hyprland => Ok(clients.hyprland()),
#[cfg(feature = "workspaces")]
#[cfg(feature = "niri")]
Self::Niri => Err(Report::msg("Unsupported compositor").note(
"Currently keyboard layout functionality are only supported by Sway and Hyprland",
)),
Self::Unsupported => Err(Report::msg("Unsupported compositor").note(
"Currently keyboard layout functionality are only supported by Sway and Hyprland",
)),
#[allow(unreachable_patterns)]
_ => Err(Report::msg("Unsupported compositor")
.note("Keyboard layout feature is disabled for this compositor")),
}
}
@ -108,6 +111,9 @@ impl Compositor {
Self::Niri => Ok(Arc::new(niri::Client::new())),
Self::Unsupported => Err(Report::msg("Unsupported compositor")
.note("Currently workspaces are only supported by Sway, Niri and Hyprland")),
#[allow(unreachable_patterns)]
_ => Err(Report::msg("Unsupported compositor")
.note("Workspaces feature is disabled for this compositor")),
}
}
}

View file

@ -1,11 +1,11 @@
use super::{KeyboardLayoutClient, KeyboardLayoutUpdate, Visibility, Workspace, WorkspaceUpdate};
use super::{Visibility, Workspace, WorkspaceUpdate};
use crate::clients::sway::Client;
use crate::{await_sync, error, send, spawn};
use color_eyre::Report;
use swayipc_async::{InputChange, InputEvent, Node, WorkspaceChange, WorkspaceEvent};
use tokio::sync::broadcast::{Receiver, channel};
#[cfg(feature = "workspaces")]
#[cfg(feature = "workspaces+sway")]
impl super::WorkspaceClient for Client {
fn focus(&self, id: i64) {
let client = self.connection().clone();
@ -153,6 +153,10 @@ impl From<WorkspaceEvent> for WorkspaceUpdate {
}
}
#[cfg(feature = "keyboard+sway")]
use super::{KeyboardLayoutClient, KeyboardLayoutUpdate};
#[cfg(feature = "keyboard+sway")]
impl KeyboardLayoutClient for Client {
fn set_next_active(&self) {
let client = self.connection().clone();
@ -210,6 +214,7 @@ impl KeyboardLayoutClient for Client {
}
}
#[cfg(feature = "keyboard+sway")]
impl TryFrom<InputEvent> for KeyboardLayoutUpdate {
type Error = ();

View file

@ -7,7 +7,7 @@ use std::sync::Arc;
#[cfg(feature = "clipboard")]
pub mod clipboard;
#[cfg(any(feature = "keyboard", feature = "workspaces"))]
#[cfg(any(feature = "keyboard", feature = "workspaces", feature = "hyprland"))]
pub mod compositor;
#[cfg(feature = "keyboard")]
pub mod libinput;
@ -195,7 +195,10 @@ impl Clients {
self.sys_info
.get_or_insert_with(|| {
let client = Arc::new(sysinfo::Client::new());
#[cfg(feature = "ipc")]
Ironbar::variable_manager().register_namespace("sysinfo", client.clone());
client
})
.clone()

View file

@ -70,13 +70,17 @@ pub trait MusicClient: Debug + Send + Sync {
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum ClientType {
#[cfg(feature = "music+mpd")]
Mpd { host: String, music_dir: PathBuf },
#[cfg(feature = "music+mpris")]
Mpris,
}
pub fn create_client(client_type: ClientType) -> Arc<dyn MusicClient> {
match client_type {
#[cfg(feature = "music+mpd")]
ClientType::Mpd { host, music_dir } => Arc::new(mpd::Client::new(host, music_dir)),
#[cfg(feature = "music+mpris")]
ClientType::Mpris => Arc::new(mpris::Client::new()),
}
}

View file

@ -1,4 +1,3 @@
use crate::ironvar::Namespace;
use crate::modules::sysinfo::Interval;
use crate::{lock, register_client};
use color_eyre::{Report, Result};
@ -483,6 +482,10 @@ impl FromStr for TokenType {
}
}
#[cfg(feature = "ipc")]
use crate::ironvar::Namespace;
#[cfg(feature = "ipc")]
impl Namespace for Client {
fn get(&self, key: &str) -> Option<String> {
let get = |value: Value| Some(value.get(Prefix::None).to_string());
@ -591,6 +594,7 @@ impl Namespace for Client {
}
}
#[cfg(feature = "ipc")]
impl Namespace for ValueSet {
fn get(&self, key: &str) -> Option<String> {
let function = Function::from_str(key).ok()?;

View file

@ -6,10 +6,13 @@ use std::ops::Deref;
#[derive(Debug, Clone)]
#[cfg(any(
feature = "cairo",
feature = "clipboard",
feature = "clipboard",
feature = "keyboard",
feature = "launcher",
feature = "music",
feature = "workspaces"
feature = "workspaces",
))]
pub struct IconButton {
button: Button,
@ -17,10 +20,13 @@ pub struct IconButton {
}
#[cfg(any(
feature = "cairo",
feature = "clipboard",
feature = "clipboard",
feature = "keyboard",
feature = "launcher",
feature = "music",
feature = "workspaces"
feature = "workspaces",
))]
impl IconButton {
pub fn new(input: &str, icon_theme: &IconTheme, size: i32) -> Self {
@ -57,6 +63,15 @@ impl IconButton {
}
}
#[cfg(any(
feature = "clipboard",
feature = "keyboard",
feature = "music",
feature = "workspaces",
feature = "cairo",
feature = "clipboard",
feature = "launcher",
))]
impl Deref for IconButton {
type Target = Button;
@ -138,6 +153,7 @@ impl IconLabel {
}
}
#[cfg(any(feature = "keyboard", feature = "music", feature = "workspaces"))]
impl Deref for IconLabel {
type Target = gtk::Box;

View file

@ -1,12 +1,19 @@
#[cfg(any(
feature = "clipboard",
feature = "keyboard",
feature = "launcher",
feature = "music",
feature = "workspaces"
feature = "workspaces",
))]
mod gtk;
mod provider;
#[cfg(any(feature = "keyboard", feature = "music", feature = "workspaces"))]
#[cfg(any(
feature = "clipboard",
feature = "keyboard",
feature = "launcher",
feature = "music",
feature = "workspaces",
))]
pub use self::gtk::*;
pub use provider::ImageProvider;

View file

@ -74,13 +74,23 @@ impl Default for Icons {
#[serde(rename_all = "snake_case")]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum PlayerType {
#[cfg(feature = "music+mpd")]
Mpd,
#[cfg(feature = "music+mpris")]
Mpris,
}
impl Default for PlayerType {
fn default() -> Self {
Self::Mpris
cfg_if::cfg_if! {
if #[cfg(feature = "music+mpris")] {
Self::Mpris
} else if #[cfg(feature = "music+mpd")] {
Self::Mpd
} else {
compile_error!("No player type feature enabled")
}
}
}
}

View file

@ -76,7 +76,9 @@ fn get_client(
music_dir: PathBuf,
) -> Arc<dyn MusicClient> {
let client_type = match player_type {
#[cfg(feature = "music+mpd")]
PlayerType::Mpd => music::ClientType::Mpd { host, music_dir },
#[cfg(feature = "music+mpris")]
PlayerType::Mpris => music::ClientType::Mpris,
};