2024-04-01 16:34:25 +01:00
|
|
|
use crate::{await_sync, Ironbar};
|
|
|
|
use color_eyre::Result;
|
2024-03-10 12:51:23 +00:00
|
|
|
use std::path::Path;
|
|
|
|
use std::rc::Rc;
|
2024-01-07 23:50:10 +00:00
|
|
|
use std::sync::Arc;
|
|
|
|
|
2023-02-25 14:30:45 +00:00
|
|
|
#[cfg(feature = "clipboard")]
|
|
|
|
pub mod clipboard;
|
2023-02-01 20:42:05 +00:00
|
|
|
#[cfg(feature = "workspaces")]
|
2023-01-27 20:08:14 +00:00
|
|
|
pub mod compositor;
|
2024-03-10 12:51:23 +00:00
|
|
|
#[cfg(feature = "cairo")]
|
|
|
|
pub mod lua;
|
2023-02-01 20:42:05 +00:00
|
|
|
#[cfg(feature = "music")]
|
2023-01-25 22:46:42 +00:00
|
|
|
pub mod music;
|
2024-03-03 22:42:57 +00:00
|
|
|
#[cfg(feature = "notifications")]
|
|
|
|
pub mod swaync;
|
2023-02-01 20:42:05 +00:00
|
|
|
#[cfg(feature = "tray")]
|
2024-03-29 00:23:44 +00:00
|
|
|
pub mod tray;
|
2023-03-19 02:16:49 +05:30
|
|
|
#[cfg(feature = "upower")]
|
|
|
|
pub mod upower;
|
2023-04-01 13:07:47 +01:00
|
|
|
#[cfg(feature = "volume")]
|
|
|
|
pub mod volume;
|
2022-11-06 23:38:51 +00:00
|
|
|
pub mod wayland;
|
2024-01-07 23:50:10 +00:00
|
|
|
|
|
|
|
/// Singleton wrapper consisting of
|
|
|
|
/// all the singleton client types used by modules.
|
|
|
|
#[derive(Debug, Default)]
|
|
|
|
pub struct Clients {
|
|
|
|
wayland: Option<Arc<wayland::Client>>,
|
|
|
|
#[cfg(feature = "workspaces")]
|
|
|
|
workspaces: Option<Arc<dyn compositor::WorkspaceClient>>,
|
|
|
|
#[cfg(feature = "clipboard")]
|
|
|
|
clipboard: Option<Arc<clipboard::Client>>,
|
2024-03-10 12:51:23 +00:00
|
|
|
#[cfg(feature = "cairo")]
|
|
|
|
lua: Option<Rc<lua::LuaEngine>>,
|
2024-01-07 23:50:10 +00:00
|
|
|
#[cfg(feature = "music")]
|
|
|
|
music: std::collections::HashMap<music::ClientType, Arc<dyn music::MusicClient>>,
|
2024-03-03 22:42:57 +00:00
|
|
|
#[cfg(feature = "notifications")]
|
|
|
|
notifications: Option<Arc<swaync::Client>>,
|
2024-01-07 23:50:10 +00:00
|
|
|
#[cfg(feature = "tray")]
|
2024-03-29 00:23:44 +00:00
|
|
|
tray: Option<Arc<tray::Client>>,
|
2024-01-07 23:50:10 +00:00
|
|
|
#[cfg(feature = "upower")]
|
|
|
|
upower: Option<Arc<zbus::fdo::PropertiesProxy<'static>>>,
|
2023-04-01 13:07:47 +01:00
|
|
|
#[cfg(feature = "volume")]
|
|
|
|
volume: Option<Arc<volume::Client>>,
|
2024-01-07 23:50:10 +00:00
|
|
|
}
|
|
|
|
|
2024-04-01 16:34:25 +01:00
|
|
|
pub type ClientResult<T> = Result<Arc<T>>;
|
|
|
|
|
2024-01-07 23:50:10 +00:00
|
|
|
impl Clients {
|
|
|
|
pub(crate) fn new() -> Self {
|
|
|
|
Self::default()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn wayland(&mut self) -> Arc<wayland::Client> {
|
|
|
|
self.wayland
|
|
|
|
.get_or_insert_with(|| Arc::new(wayland::Client::new()))
|
|
|
|
.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "clipboard")]
|
|
|
|
pub fn clipboard(&mut self) -> Arc<clipboard::Client> {
|
|
|
|
let wayland = self.wayland();
|
|
|
|
|
|
|
|
self.clipboard
|
|
|
|
.get_or_insert_with(|| Arc::new(clipboard::Client::new(wayland)))
|
|
|
|
.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "workspaces")]
|
2024-04-01 16:34:25 +01:00
|
|
|
pub fn workspaces(&mut self) -> ClientResult<dyn compositor::WorkspaceClient> {
|
|
|
|
let client = match &self.workspaces {
|
|
|
|
Some(workspaces) => workspaces.clone(),
|
|
|
|
None => {
|
|
|
|
let client = compositor::Compositor::create_workspace_client()?;
|
|
|
|
self.workspaces.replace(client.clone());
|
|
|
|
client
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(client)
|
2024-01-07 23:50:10 +00:00
|
|
|
}
|
|
|
|
|
2024-03-10 12:51:23 +00:00
|
|
|
#[cfg(feature = "cairo")]
|
|
|
|
pub fn lua(&mut self, config_dir: &Path) -> Rc<lua::LuaEngine> {
|
|
|
|
self.lua
|
|
|
|
.get_or_insert_with(|| Rc::new(lua::LuaEngine::new(config_dir)))
|
|
|
|
.clone()
|
|
|
|
}
|
|
|
|
|
2024-01-07 23:50:10 +00:00
|
|
|
#[cfg(feature = "music")]
|
|
|
|
pub fn music(&mut self, client_type: music::ClientType) -> Arc<dyn music::MusicClient> {
|
|
|
|
self.music
|
|
|
|
.entry(client_type.clone())
|
|
|
|
.or_insert_with(|| music::create_client(client_type))
|
|
|
|
.clone()
|
|
|
|
}
|
|
|
|
|
2024-03-03 22:42:57 +00:00
|
|
|
#[cfg(feature = "notifications")]
|
2024-04-01 16:34:25 +01:00
|
|
|
pub fn notifications(&mut self) -> ClientResult<swaync::Client> {
|
|
|
|
let client = match &self.notifications {
|
|
|
|
Some(client) => client.clone(),
|
|
|
|
None => {
|
|
|
|
let client = await_sync(async { swaync::Client::new().await })?;
|
|
|
|
let client = Arc::new(client);
|
|
|
|
self.notifications.replace(client.clone());
|
|
|
|
client
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(client)
|
2024-03-03 22:42:57 +00:00
|
|
|
}
|
|
|
|
|
2024-01-07 23:50:10 +00:00
|
|
|
#[cfg(feature = "tray")]
|
2024-04-01 16:34:25 +01:00
|
|
|
pub fn tray(&mut self) -> ClientResult<tray::Client> {
|
|
|
|
let client = match &self.tray {
|
|
|
|
Some(client) => client.clone(),
|
|
|
|
None => {
|
|
|
|
let service_name = format!("{}-{}", env!("CARGO_CRATE_NAME"), Ironbar::unique_id());
|
|
|
|
|
|
|
|
let client = await_sync(async { tray::Client::new(&service_name).await })?;
|
|
|
|
let client = Arc::new(client);
|
|
|
|
self.tray.replace(client.clone());
|
|
|
|
client
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(client)
|
2024-01-07 23:50:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "upower")]
|
|
|
|
pub fn upower(&mut self) -> Arc<zbus::fdo::PropertiesProxy<'static>> {
|
|
|
|
self.upower
|
|
|
|
.get_or_insert_with(|| {
|
|
|
|
crate::await_sync(async { upower::create_display_proxy().await })
|
|
|
|
})
|
|
|
|
.clone()
|
|
|
|
}
|
2023-04-01 13:07:47 +01:00
|
|
|
|
|
|
|
#[cfg(feature = "volume")]
|
|
|
|
pub fn volume(&mut self) -> Arc<volume::Client> {
|
|
|
|
self.volume
|
|
|
|
.get_or_insert_with(volume::create_client)
|
|
|
|
.clone()
|
|
|
|
}
|
2024-01-07 23:50:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Types implementing this trait
|
|
|
|
/// indicate that they provide a singleton client instance of type `T`.
|
|
|
|
pub trait ProvidesClient<T: ?Sized> {
|
|
|
|
/// Returns a singleton client instance of type `T`.
|
|
|
|
fn provide(&self) -> Arc<T>;
|
|
|
|
}
|
|
|
|
|
2024-04-01 16:34:25 +01:00
|
|
|
/// Types implementing this trait
|
|
|
|
/// indicate that they provide a singleton client instance of type `T`,
|
|
|
|
/// which may fail to be created.
|
|
|
|
pub trait ProvidesFallibleClient<T: ?Sized> {
|
|
|
|
/// Returns a singleton client instance of type `T`.
|
|
|
|
fn try_provide(&self) -> ClientResult<T>;
|
|
|
|
}
|
|
|
|
|
2024-01-07 23:50:10 +00:00
|
|
|
/// 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<TSend, TReceive> $crate::clients::ProvidesClient<$ty>
|
|
|
|
for $crate::modules::WidgetContext<TSend, TReceive>
|
|
|
|
where
|
|
|
|
TSend: Clone,
|
|
|
|
{
|
2024-03-03 22:42:57 +00:00
|
|
|
fn provide(&self) -> std::sync::Arc<$ty> {
|
2024-01-07 23:50:10 +00:00
|
|
|
self.ironbar.clients.borrow_mut().$method()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2024-04-01 16:34:25 +01:00
|
|
|
|
|
|
|
/// 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_fallible_client {
|
|
|
|
($ty:ty, $method:ident) => {
|
|
|
|
impl<TSend, TReceive> $crate::clients::ProvidesFallibleClient<$ty>
|
|
|
|
for $crate::modules::WidgetContext<TSend, TReceive>
|
|
|
|
where
|
|
|
|
TSend: Clone,
|
|
|
|
{
|
|
|
|
fn try_provide(&self) -> color_eyre::Result<std::sync::Arc<$ty>> {
|
|
|
|
self.ironbar.clients.borrow_mut().$method()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|