WIP code for getting layout from menu

This commit is contained in:
Ian Douglas Scott 2021-08-26 16:09:25 -07:00
parent 9fca893fe1
commit 4c799a2bed

View file

@ -11,7 +11,7 @@ use gtk4::{
subclass::prelude::*, subclass::prelude::*,
}; };
use once_cell::unsync::OnceCell; use once_cell::unsync::OnceCell;
use std::{cell::RefCell, collections::HashMap}; use std::{borrow::Cow, cell::RefCell, collections::HashMap};
use crate::deref_cell::DerefCell; use crate::deref_cell::DerefCell;
@ -98,6 +98,10 @@ impl StatusArea {
let image = gtk4::Image::from_icon_name(item.icon_name().as_deref()); let image = gtk4::Image::from_icon_name(item.icon_name().as_deref());
self.inner().box_.append(&image); self.inner().box_.append(&image);
if let Some(menu) = item.menu() {
println!("{:?}", menu.get_layout(0, -1, &[]).await);
}
self.item_unregistered(name); self.item_unregistered(name);
self.inner() self.inner()
.icons .icons
@ -115,23 +119,88 @@ impl StatusArea {
} }
} }
struct StatusNotifierItem(gio::DBusProxy); #[derive(Debug)]
struct Layout(i32, HashMap<String, glib::Variant>, Vec<Layout>);
impl StatusNotifierItem { impl glib::StaticVariantType for Layout {
async fn new(name: &str) -> Result<Self, glib::Error> { fn static_variant_type() -> Cow<'static, glib::VariantTy> {
let idx = name.find('/').unwrap(); glib::VariantTy::new("(ia{sv}av)").unwrap().into()
}
}
impl glib::FromVariant for Layout {
fn from_variant(variant: &glib::Variant) -> Option<Self> {
let (id, props, children) = variant.get::<(_, _, Vec<glib::Variant>)>()?;
let children = children.iter().filter_map(Self::from_variant).collect();
Some(Self(id, props, children))
}
}
#[derive(Clone)]
struct DBusMenu(gio::DBusProxy);
impl DBusMenu {
async fn new(dest: &str, path: &str) -> Result<Self, glib::Error> {
let proxy = gio::DBusProxy::for_bus_future( let proxy = gio::DBusProxy::for_bus_future(
gio::BusType::Session, gio::BusType::Session,
gio::DBusProxyFlags::NONE, gio::DBusProxyFlags::NONE,
None, None,
&name[..idx], dest,
&name[idx..], path,
"org.kde.StatusNotifierItem", "com.canonical.dbusmenu",
) )
.await?; .await?;
Ok(Self(proxy)) Ok(Self(proxy))
} }
async fn get_layout(
&self,
parent: i32,
depth: i32,
properties: &[&str],
) -> Result<(u32, Layout), glib::Error> {
// XXX unwrap
Ok(self
.0
.call_future(
"GetLayout",
Some(&(parent, depth, properties).to_variant()),
gio::DBusCallFlags::NONE,
1000,
)
.await?
.get()
.unwrap())
}
}
struct StatusNotifierItem(gio::DBusProxy, Option<DBusMenu>);
impl StatusNotifierItem {
async fn new(name: &str) -> Result<Self, glib::Error> {
let idx = name.find('/').unwrap();
let dest = &name[..idx];
let path = &name[idx..];
let proxy = gio::DBusProxy::for_bus_future(
gio::BusType::Session,
gio::DBusProxyFlags::NONE,
None,
dest,
path,
"org.kde.StatusNotifierItem",
)
.await?;
let menu_path = proxy
.cached_property("Menu")
.and_then(|x| x.get::<String>());
let menu = if let Some(menu_path) = menu_path {
Some(DBusMenu::new(dest, &menu_path).await?)
} else {
None
};
Ok(Self(proxy, menu))
}
fn property<T: glib::FromVariant>(&self, prop: &str) -> Option<T> { fn property<T: glib::FromVariant>(&self, prop: &str) -> Option<T> {
self.0.cached_property(prop)?.get() self.0.cached_property(prop)?.get()
} }
@ -141,9 +210,8 @@ impl StatusNotifierItem {
self.property("IconName") self.property("IconName")
} }
fn menu(&self) -> Option<String> { fn menu(&self) -> Option<DBusMenu> {
// TODO: Return menu rather than just string self.1.clone()
self.property("Menu")
} }
} }