75 lines
2.6 KiB
Rust
75 lines
2.6 KiB
Rust
// Copyright 2023 System76 <info@system76.com>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
use futures::{Stream, StreamExt};
|
|
use std::pin::Pin;
|
|
|
|
use super::Event;
|
|
use crate::subscriptions::status_notifier_item::StatusNotifierItem;
|
|
|
|
// TODO: Don't use trait object
|
|
pub type EventStream = Pin<Box<dyn Stream<Item = Event> + Send>>;
|
|
|
|
#[zbus::proxy(
|
|
interface = "org.kde.StatusNotifierWatcher",
|
|
default_service = "org.kde.StatusNotifierWatcher",
|
|
default_path = "/StatusNotifierWatcher"
|
|
)]
|
|
trait StatusNotifierWatcher {
|
|
fn register_status_notifier_host(&self, name: &str) -> zbus::Result<()>;
|
|
|
|
#[zbus(property)]
|
|
fn registered_status_notifier_items(&self) -> zbus::Result<Vec<String>>;
|
|
|
|
#[zbus(signal)]
|
|
fn status_notifier_item_registered(&self, name: &str) -> zbus::Result<()>;
|
|
|
|
#[zbus(signal)]
|
|
fn status_notifier_item_unregistered(&self, name: &str) -> zbus::Result<()>;
|
|
}
|
|
|
|
pub async fn watch(connection: &zbus::Connection) -> zbus::Result<EventStream> {
|
|
let watcher = StatusNotifierWatcherProxy::new(connection).await?;
|
|
|
|
let name = connection.unique_name().unwrap().as_str();
|
|
if let Err(err) = watcher.register_status_notifier_host(name).await {
|
|
eprintln!("Failed to register status notifier host: {}", err);
|
|
}
|
|
|
|
let connection_clone = connection.clone();
|
|
let registered_stream = watcher
|
|
.receive_status_notifier_item_registered()
|
|
.await?
|
|
.then(move |evt| Box::pin(item_registered(connection_clone.clone(), evt)));
|
|
let unregistered_stream = watcher
|
|
.receive_status_notifier_item_unregistered()
|
|
.await?
|
|
.map(|evt| match evt.args() {
|
|
Ok(args) => Event::Unregistered(args.name.to_string()),
|
|
Err(err) => Event::Error(err.to_string()),
|
|
});
|
|
|
|
let items = watcher.registered_status_notifier_items().await?;
|
|
let connection = connection.clone();
|
|
let items_stream = futures::stream::iter(items.into_iter())
|
|
.then(move |name| status_notifier_item(connection.clone(), name));
|
|
|
|
Ok(Box::pin(items_stream.chain(futures::stream_select!(
|
|
registered_stream,
|
|
unregistered_stream
|
|
))))
|
|
}
|
|
|
|
async fn item_registered(connection: zbus::Connection, evt: StatusNotifierItemRegistered) -> Event {
|
|
match evt.args() {
|
|
Ok(args) => status_notifier_item(connection, args.name.to_string()).await,
|
|
Err(err) => Event::Error(err.to_string()),
|
|
}
|
|
}
|
|
|
|
async fn status_notifier_item(connection: zbus::Connection, name: String) -> Event {
|
|
match StatusNotifierItem::new(&connection, name).await {
|
|
Ok(item) => Event::Registered(item),
|
|
Err(err) => Event::Error(err.to_string()),
|
|
}
|
|
}
|