use crate::Ironbar; use std::sync::Arc; #[cfg(feature = "clipboard")] pub mod clipboard; #[cfg(feature = "workspaces")] pub mod compositor; #[cfg(feature = "music")] pub mod music; #[cfg(feature = "notifications")] pub mod swaync; #[cfg(feature = "tray")] pub mod tray; #[cfg(feature = "upower")] pub mod upower; #[cfg(feature = "volume")] pub mod volume; pub mod wayland; /// Singleton wrapper consisting of /// all the singleton client types used by modules. #[derive(Debug, Default)] pub struct Clients { wayland: Option>, #[cfg(feature = "workspaces")] workspaces: Option>, #[cfg(feature = "clipboard")] clipboard: Option>, #[cfg(feature = "music")] music: std::collections::HashMap>, #[cfg(feature = "notifications")] notifications: Option>, #[cfg(feature = "tray")] tray: Option>, #[cfg(feature = "upower")] upower: Option>>, #[cfg(feature = "volume")] volume: Option>, } impl Clients { pub(crate) fn new() -> Self { Self::default() } pub fn wayland(&mut self) -> Arc { self.wayland .get_or_insert_with(|| Arc::new(wayland::Client::new())) .clone() } #[cfg(feature = "clipboard")] pub fn clipboard(&mut self) -> Arc { let wayland = self.wayland(); self.clipboard .get_or_insert_with(|| Arc::new(clipboard::Client::new(wayland))) .clone() } #[cfg(feature = "workspaces")] pub fn workspaces(&mut self) -> Arc { // TODO: Error handling here isn't great - should throw a user-friendly error & exit self.workspaces .get_or_insert_with(|| { compositor::Compositor::create_workspace_client().expect("to be valid compositor") }) .clone() } #[cfg(feature = "music")] pub fn music(&mut self, client_type: music::ClientType) -> Arc { self.music .entry(client_type.clone()) .or_insert_with(|| music::create_client(client_type)) .clone() } #[cfg(feature = "notifications")] pub fn notifications(&mut self) -> Arc { self.notifications .get_or_insert_with(|| { Arc::new(crate::await_sync(async { swaync::Client::new().await })) }) .clone() } #[cfg(feature = "tray")] pub fn tray(&mut self) -> Arc { // TODO: Error handling here isn't great - should throw a user-friendly error self.tray .get_or_insert_with(|| { Arc::new(crate::await_sync(async { let service_name = format!("{}-{}", env!("CARGO_CRATE_NAME"), Ironbar::unique_id()); tray::Client::new(&service_name) .await .expect("to be able to start client") })) }) .clone() } #[cfg(feature = "upower")] pub fn upower(&mut self) -> Arc> { self.upower .get_or_insert_with(|| { crate::await_sync(async { upower::create_display_proxy().await }) }) .clone() } #[cfg(feature = "volume")] pub fn volume(&mut self) -> Arc { self.volume .get_or_insert_with(volume::create_client) .clone() } } /// Types implementing this trait /// indicate that they provide a singleton client instance of type `T`. pub trait ProvidesClient { /// Returns a singleton client instance of type `T`. fn provide(&self) -> Arc; } /// Generates a `ProvidesClient` impl block on `WidgetContext` /// for the provided `$ty` (first argument) client type. /// /// The implementation calls `$method` (second argument) /// on the `Clients` struct to obtain the client instance. /// /// # Example /// `register_client!(Client, clipboard);` #[macro_export] macro_rules! register_client { ($ty:ty, $method:ident) => { impl $crate::clients::ProvidesClient<$ty> for $crate::modules::WidgetContext where TSend: Clone, { fn provide(&self) -> std::sync::Arc<$ty> { self.ironbar.clients.borrow_mut().$method() } } }; }