status-area: Send unregistered signal in watcher
Still not working as expected...
This commit is contained in:
parent
0ecba6a6d0
commit
e52446c770
5 changed files with 155 additions and 93 deletions
77
Cargo.lock
generated
77
Cargo.lock
generated
|
|
@ -368,7 +368,7 @@ dependencies = [
|
||||||
"relm4-macros",
|
"relm4-macros",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracker",
|
"tracker",
|
||||||
"zbus",
|
"zbus 2.3.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -381,7 +381,7 @@ dependencies = [
|
||||||
"libcosmic",
|
"libcosmic",
|
||||||
"libcosmic-applet",
|
"libcosmic-applet",
|
||||||
"relm4",
|
"relm4",
|
||||||
"zbus",
|
"zbus 2.3.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -395,7 +395,7 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"relm4-macros",
|
"relm4-macros",
|
||||||
"tokio",
|
"tokio",
|
||||||
"zbus",
|
"zbus 2.3.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -413,7 +413,7 @@ dependencies = [
|
||||||
"relm4-macros",
|
"relm4-macros",
|
||||||
"slotmap",
|
"slotmap",
|
||||||
"tokio",
|
"tokio",
|
||||||
"zbus",
|
"zbus 2.3.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -430,7 +430,7 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"relm4-macros",
|
"relm4-macros",
|
||||||
"serde",
|
"serde",
|
||||||
"zbus",
|
"zbus 2.3.2",
|
||||||
"zbus_names",
|
"zbus_names",
|
||||||
"zvariant",
|
"zvariant",
|
||||||
]
|
]
|
||||||
|
|
@ -449,7 +449,7 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"relm4-macros",
|
"relm4-macros",
|
||||||
"tokio",
|
"tokio",
|
||||||
"zbus",
|
"zbus 2.3.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -464,8 +464,7 @@ dependencies = [
|
||||||
"libcosmic-applet",
|
"libcosmic-applet",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"serde",
|
"serde",
|
||||||
"zbus",
|
"zbus 3.1.0",
|
||||||
"zbus_names",
|
|
||||||
"zvariant",
|
"zvariant",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -482,7 +481,7 @@ dependencies = [
|
||||||
"libcosmic-applet",
|
"libcosmic-applet",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"serde",
|
"serde",
|
||||||
"zbus",
|
"zbus 2.3.2",
|
||||||
"zbus_names",
|
"zbus_names",
|
||||||
"zvariant",
|
"zvariant",
|
||||||
]
|
]
|
||||||
|
|
@ -521,7 +520,7 @@ dependencies = [
|
||||||
"derive_builder",
|
"derive_builder",
|
||||||
"procfs",
|
"procfs",
|
||||||
"time 0.3.13",
|
"time 0.3.13",
|
||||||
"zbus",
|
"zbus 2.3.2",
|
||||||
"zvariant",
|
"zvariant",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1713,7 +1712,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c03958f20018a20963daf0c16ada4f271ae2da3e0017fb40caa8b0e3dc5b0226"
|
checksum = "c03958f20018a20963daf0c16ada4f271ae2da3e0017fb40caa8b0e3dc5b0226"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"zbus",
|
"zbus 2.3.2",
|
||||||
"zvariant",
|
"zvariant",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1761,7 +1760,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"time 0.3.13",
|
"time 0.3.13",
|
||||||
"zbus",
|
"zbus 2.3.2",
|
||||||
"zvariant",
|
"zvariant",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -3171,7 +3170,46 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
"uds_windows",
|
"uds_windows",
|
||||||
"winapi",
|
"winapi",
|
||||||
"zbus_macros",
|
"zbus_macros 2.3.2",
|
||||||
|
"zbus_names",
|
||||||
|
"zvariant",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zbus"
|
||||||
|
version = "3.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d37e0d34b881934b987b72a91fdc1daba9ebc90c1f91b7944c680991c4443fc6"
|
||||||
|
dependencies = [
|
||||||
|
"async-broadcast",
|
||||||
|
"async-channel",
|
||||||
|
"async-executor",
|
||||||
|
"async-io",
|
||||||
|
"async-lock",
|
||||||
|
"async-recursion",
|
||||||
|
"async-task",
|
||||||
|
"async-trait",
|
||||||
|
"byteorder",
|
||||||
|
"derivative",
|
||||||
|
"dirs 4.0.0",
|
||||||
|
"enumflags2",
|
||||||
|
"event-listener",
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-util",
|
||||||
|
"hex",
|
||||||
|
"nix 0.24.2",
|
||||||
|
"once_cell",
|
||||||
|
"ordered-stream",
|
||||||
|
"rand",
|
||||||
|
"serde",
|
||||||
|
"serde_repr",
|
||||||
|
"sha1",
|
||||||
|
"static_assertions",
|
||||||
|
"tracing",
|
||||||
|
"uds_windows",
|
||||||
|
"winapi",
|
||||||
|
"zbus_macros 3.1.0",
|
||||||
"zbus_names",
|
"zbus_names",
|
||||||
"zvariant",
|
"zvariant",
|
||||||
]
|
]
|
||||||
|
|
@ -3189,6 +3227,19 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zbus_macros"
|
||||||
|
version = "3.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba7905f7c665ea41828bd69112902daa131191a85131fef0f60f7cc3bc2fbec4"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-crate",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"regex",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zbus_names"
|
name = "zbus_names"
|
||||||
version = "2.2.0"
|
version = "2.2.0"
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,5 @@ libcosmic = { git = "https://github.com/pop-os/libcosmic", default-features = fa
|
||||||
libcosmic-applet = { path = "../../libcosmic-applet" }
|
libcosmic-applet = { path = "../../libcosmic-applet" }
|
||||||
once_cell = "1.12"
|
once_cell = "1.12"
|
||||||
serde = "1"
|
serde = "1"
|
||||||
zbus = "2.0.1"
|
zbus = "3"
|
||||||
zbus_names = "2"
|
|
||||||
zvariant = "3"
|
zvariant = "3"
|
||||||
|
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
use futures::prelude::*;
|
|
||||||
use gtk4::glib::{self, clone};
|
|
||||||
use std::cell::Cell;
|
|
||||||
use zbus::fdo::{DBusProxy, RequestNameFlags, RequestNameReply};
|
|
||||||
use zbus_names::WellKnownName;
|
|
||||||
|
|
||||||
pub async fn create<
|
|
||||||
F: Fn(zbus::ConnectionBuilder<'static>) -> zbus::Result<zbus::ConnectionBuilder<'static>>,
|
|
||||||
>(
|
|
||||||
well_known_name: &'static str,
|
|
||||||
serve_cb: F,
|
|
||||||
) -> zbus::Result<zbus::Connection> {
|
|
||||||
let well_known_name = WellKnownName::try_from(well_known_name)?;
|
|
||||||
|
|
||||||
let connection = serve_cb(zbus::ConnectionBuilder::session()?)?
|
|
||||||
.build()
|
|
||||||
.await?;
|
|
||||||
let dbus_proxy = DBusProxy::new(&connection).await?;
|
|
||||||
let mut name_owner_changed_stream = dbus_proxy.receive_name_owner_changed().await?;
|
|
||||||
|
|
||||||
let flags = RequestNameFlags::AllowReplacement.into();
|
|
||||||
match dbus_proxy
|
|
||||||
.request_name(well_known_name.as_ref(), flags)
|
|
||||||
.await?
|
|
||||||
{
|
|
||||||
RequestNameReply::InQueue => {
|
|
||||||
eprintln!("Bus name '{}' already owned", well_known_name);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
glib::MainContext::default().spawn_local(clone!(@strong connection => async move {
|
|
||||||
let have_bus_name = Cell::new(false);
|
|
||||||
let unique_name = connection.unique_name().map(|x| x.as_ref());
|
|
||||||
while let Some(evt) = name_owner_changed_stream.next().await {
|
|
||||||
let args = match evt.args() {
|
|
||||||
Ok(args) => args,
|
|
||||||
Err(_) => { continue; },
|
|
||||||
};
|
|
||||||
if args.name.as_ref() == well_known_name {
|
|
||||||
if args.new_owner.as_ref() == unique_name.as_ref() {
|
|
||||||
eprintln!("Acquired bus name: {}", well_known_name);
|
|
||||||
have_bus_name.set(true);
|
|
||||||
} else if have_bus_name.get() {
|
|
||||||
eprintln!("Lost bus name: {}", well_known_name);
|
|
||||||
have_bus_name.set(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
Ok(connection)
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
use cascade::cascade;
|
use cascade::cascade;
|
||||||
use gtk4::{glib, prelude::*};
|
use gtk4::{glib, prelude::*};
|
||||||
|
|
||||||
mod dbus_service;
|
|
||||||
mod deref_cell;
|
mod deref_cell;
|
||||||
mod status_area;
|
mod status_area;
|
||||||
mod status_menu;
|
mod status_menu;
|
||||||
|
|
|
||||||
|
|
@ -1,74 +1,140 @@
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use std::sync::{Arc, Mutex};
|
use futures::prelude::*;
|
||||||
use zbus::{dbus_interface, MessageHeader, Result, SignalContext};
|
use gtk4::glib::{self, clone};
|
||||||
|
use std::cell::Cell;
|
||||||
|
use zbus::{
|
||||||
|
dbus_interface,
|
||||||
|
fdo::{DBusProxy, RequestNameFlags, RequestNameReply},
|
||||||
|
names::{BusName, UniqueName, WellKnownName},
|
||||||
|
MessageHeader, Result, SignalContext,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::dbus_service;
|
const OBJECT_PATH: &str = "/StatusNotifierWatcher";
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct StatusNotifierWatcher {
|
struct StatusNotifierWatcher {
|
||||||
items: Arc<Mutex<Vec<String>>>,
|
items: Vec<(UniqueName<'static>, String)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[dbus_interface(name = "org.kde.StatusNotifierWatcher")]
|
#[dbus_interface(name = "org.kde.StatusNotifierWatcher")]
|
||||||
impl StatusNotifierWatcher {
|
impl StatusNotifierWatcher {
|
||||||
async fn RegisterStatusNotifierItem(
|
async fn register_status_notifier_item(
|
||||||
&self,
|
&mut self,
|
||||||
service: &str,
|
service: &str,
|
||||||
#[zbus(header)] hdr: MessageHeader<'_>,
|
#[zbus(header)] hdr: MessageHeader<'_>,
|
||||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||||
) {
|
) {
|
||||||
|
let sender = hdr.sender().unwrap().unwrap();
|
||||||
let service = if service.starts_with('/') {
|
let service = if service.starts_with('/') {
|
||||||
format!("{}{}", hdr.sender().unwrap().unwrap(), service)
|
format!("{}{}", sender, service)
|
||||||
} else {
|
} else {
|
||||||
service.to_string()
|
service.to_string()
|
||||||
};
|
};
|
||||||
Self::StatusNotifierItemRegistered(&ctxt, &service)
|
Self::status_notifier_item_registered(&ctxt, &service)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// XXX emit unreigstered
|
self.items.push((sender.to_owned(), service));
|
||||||
self.items.lock().unwrap().push(service);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn RegisterStatusNotifierHost(&self, _service: &str) {
|
fn register_status_notifier_host(&self, _service: &str) {
|
||||||
// XXX emit registed/unregistered
|
// XXX emit registed/unregistered
|
||||||
}
|
}
|
||||||
|
|
||||||
#[dbus_interface(property)]
|
#[dbus_interface(property)]
|
||||||
fn RegisteredStatusNotifierItems(&self) -> Vec<String> {
|
fn registered_status_notifier_items(&self) -> Vec<String> {
|
||||||
self.items.lock().unwrap().clone()
|
self.items.iter().map(|(_, x)| x.clone()).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[dbus_interface(property)]
|
#[dbus_interface(property)]
|
||||||
fn IsStatusNotifierHostRegistered(&self) -> bool {
|
fn is_status_notifier_host_registered(&self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
#[dbus_interface(property)]
|
#[dbus_interface(property)]
|
||||||
fn ProtocolVersion(&self) -> i32 {
|
fn protocol_version(&self) -> i32 {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
#[dbus_interface(signal)]
|
#[dbus_interface(signal)]
|
||||||
async fn StatusNotifierItemRegistered(ctxt: &SignalContext<'_>, service: &str) -> Result<()>;
|
async fn status_notifier_item_registered(ctxt: &SignalContext<'_>, service: &str)
|
||||||
|
-> Result<()>;
|
||||||
|
|
||||||
#[dbus_interface(signal)]
|
#[dbus_interface(signal)]
|
||||||
async fn StatusNotifierItemUnregistered(ctxt: &SignalContext<'_>, service: &str) -> Result<()>;
|
async fn status_notifier_item_unregistered(
|
||||||
|
ctxt: &SignalContext<'_>,
|
||||||
|
service: &str,
|
||||||
|
) -> Result<()>;
|
||||||
|
|
||||||
#[dbus_interface(signal)]
|
#[dbus_interface(signal)]
|
||||||
async fn StatusNotifierHostRegistered(ctxt: &SignalContext<'_>) -> Result<()>;
|
async fn status_notifier_host_registered(ctxt: &SignalContext<'_>) -> Result<()>;
|
||||||
|
|
||||||
#[dbus_interface(signal)]
|
#[dbus_interface(signal)]
|
||||||
async fn StatusNotifierHostUnregistered(ctxt: &SignalContext<'_>) -> Result<()>;
|
async fn status_notifier_host_unregistered(ctxt: &SignalContext<'_>) -> Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_service() -> zbus::Result<zbus::Connection> {
|
||||||
|
let well_known_name = WellKnownName::try_from("org.kde.StatusNotifierWatcher")?;
|
||||||
|
|
||||||
|
let connection = zbus::ConnectionBuilder::session()?.build().await?;
|
||||||
|
connection
|
||||||
|
.object_server()
|
||||||
|
.at(OBJECT_PATH, StatusNotifierWatcher::default())
|
||||||
|
.await?;
|
||||||
|
let interface = connection
|
||||||
|
.object_server()
|
||||||
|
.interface::<_, StatusNotifierWatcher>(OBJECT_PATH)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let dbus_proxy = DBusProxy::new(&connection).await?;
|
||||||
|
let mut name_owner_changed_stream = dbus_proxy.receive_name_owner_changed().await?;
|
||||||
|
|
||||||
|
let flags = RequestNameFlags::AllowReplacement.into();
|
||||||
|
match dbus_proxy
|
||||||
|
.request_name(well_known_name.as_ref(), flags)
|
||||||
|
.await?
|
||||||
|
{
|
||||||
|
RequestNameReply::InQueue => {
|
||||||
|
eprintln!("Bus name '{}' already owned", well_known_name);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
glib::MainContext::default().spawn_local(clone!(@strong connection => async move {
|
||||||
|
let have_bus_name = Cell::new(false);
|
||||||
|
let unique_name = connection.unique_name().map(|x| x.as_ref());
|
||||||
|
while let Some(evt) = name_owner_changed_stream.next().await {
|
||||||
|
let args = match evt.args() {
|
||||||
|
Ok(args) => args,
|
||||||
|
Err(_) => { continue; },
|
||||||
|
};
|
||||||
|
if args.name.as_ref() == well_known_name {
|
||||||
|
if args.new_owner.as_ref() == unique_name.as_ref() {
|
||||||
|
eprintln!("Acquired bus name: {}", well_known_name);
|
||||||
|
have_bus_name.set(true);
|
||||||
|
} else if have_bus_name.get() {
|
||||||
|
eprintln!("Lost bus name: {}", well_known_name);
|
||||||
|
have_bus_name.set(false);
|
||||||
|
}
|
||||||
|
} else if let BusName::Unique(name) = &args.name {
|
||||||
|
let mut interface = interface.get_mut().await;
|
||||||
|
if let Some(idx) = interface.items.iter().position(|(unique_name, _)| unique_name == name) {
|
||||||
|
let ctxt = zbus::SignalContext::new(&connection, OBJECT_PATH).unwrap();
|
||||||
|
let service = interface.items.remove(idx).1;
|
||||||
|
StatusNotifierWatcher::status_notifier_item_unregistered(&ctxt, &service)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
Ok(connection)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn start() {
|
pub async fn start() {
|
||||||
if let Err(err) = dbus_service::create("org.kde.StatusNotifierWatcher", |builder| {
|
if let Err(err) = create_service().await {
|
||||||
builder.serve_at("/StatusNotifierWatcher", StatusNotifierWatcher::default())
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
eprintln!("Failed to start `StatusNotifierWatcher` service: {}", err);
|
eprintln!("Failed to start `StatusNotifierWatcher` service: {}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue