fix(status-area): better handle apps with no menus
This commit is contained in:
parent
bd98de8228
commit
b026db6f7c
3 changed files with 54 additions and 12 deletions
|
|
@ -460,7 +460,11 @@ impl cosmic::Application for App {
|
|||
.icon_button_from_handle(icon.clone().symbolic(true)),
|
||||
_ => self.core.applet.icon_button(menu.icon_name()),
|
||||
}
|
||||
.on_press_down(Msg::TogglePopup(*id)),
|
||||
.on_press_down(if menu.item.menu_proxy().is_some() {
|
||||
Msg::TogglePopup(*id)
|
||||
} else {
|
||||
Msg::StatusMenu((*id, status_menu::Msg::Click(0, true)))
|
||||
}),
|
||||
)
|
||||
.on_enter(Msg::Hovered(*id))
|
||||
.into()
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ pub enum Msg {
|
|||
}
|
||||
|
||||
pub struct State {
|
||||
item: StatusNotifierItem,
|
||||
pub item: StatusNotifierItem,
|
||||
layout: Option<Layout>,
|
||||
expanded: Option<i32>,
|
||||
icon_name: String,
|
||||
|
|
@ -101,9 +101,19 @@ impl State {
|
|||
let Some((id, is_submenu)) = self.click_event else {
|
||||
return iced::Task::none();
|
||||
};
|
||||
|
||||
let menu_proxy = self.item.menu_proxy().clone();
|
||||
let item_proxy = self.item.item_proxy().clone();
|
||||
|
||||
let Some(menu_proxy) = self.item.menu_proxy().cloned() else {
|
||||
tokio::spawn(async move {
|
||||
let _ = item_proxy.provide_xdg_activation_token(token).await;
|
||||
if let Err(err) = item_proxy.activate(0, 0).await {
|
||||
tracing::error!(
|
||||
"Error activating status notifier item without menu proxy: {err:?}"
|
||||
);
|
||||
}
|
||||
});
|
||||
return iced::Task::none();
|
||||
};
|
||||
tokio::spawn(async move {
|
||||
let _ = item_proxy.provide_xdg_activation_token(token).await;
|
||||
let _ = menu_proxy.event(id, "clicked", &0.into(), 0).await;
|
||||
|
|
@ -150,7 +160,9 @@ impl State {
|
|||
}
|
||||
|
||||
pub fn opened(&self) {
|
||||
let menu_proxy = self.item.menu_proxy().clone();
|
||||
let Some(menu_proxy) = self.item.menu_proxy().cloned() else {
|
||||
return;
|
||||
};
|
||||
tokio::spawn(async move {
|
||||
let _ = menu_proxy.event(0, "opened", &0i32.into(), 0).await;
|
||||
let _ = menu_proxy.about_to_show(0).await;
|
||||
|
|
@ -158,7 +170,9 @@ impl State {
|
|||
}
|
||||
|
||||
pub fn closed(&self) {
|
||||
let menu_proxy = self.item.menu_proxy().clone();
|
||||
let Some(menu_proxy) = self.item.menu_proxy().cloned() else {
|
||||
return;
|
||||
};
|
||||
tokio::spawn(async move {
|
||||
let _ = menu_proxy.event(0, "closed", &0i32.into(), 0).await;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use zbus::zvariant::{self, OwnedValue};
|
|||
pub struct StatusNotifierItem {
|
||||
name: String,
|
||||
item_proxy: StatusNotifierItemProxy<'static>,
|
||||
menu_proxy: DBusMenuProxy<'static>,
|
||||
menu_proxy: Option<DBusMenuProxy<'static>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, zvariant::Value)]
|
||||
|
|
@ -42,7 +42,22 @@ impl StatusNotifierItem {
|
|||
.build()
|
||||
.await?;
|
||||
|
||||
let menu_path = item_proxy.menu().await?;
|
||||
// XX: some items will not implement this but have a menu anyway
|
||||
let is_menu = item_proxy.item_is_menu().await;
|
||||
|
||||
let menu_path = item_proxy.menu().await;
|
||||
|
||||
// Why would an item say it has no menu but provide a menu path? Slack does this.
|
||||
let mut is_menu = menu_path.is_ok() || is_menu.unwrap_or(false);
|
||||
|
||||
if !is_menu {
|
||||
return Ok(Self {
|
||||
name,
|
||||
item_proxy,
|
||||
menu_proxy: None,
|
||||
});
|
||||
}
|
||||
let menu_path = menu_path?;
|
||||
let menu_proxy = DBusMenuProxy::builder(connection)
|
||||
.destination(dest.to_string())?
|
||||
.path(menu_path)?
|
||||
|
|
@ -52,7 +67,7 @@ impl StatusNotifierItem {
|
|||
Ok(Self {
|
||||
name,
|
||||
item_proxy,
|
||||
menu_proxy,
|
||||
menu_proxy: Some(menu_proxy),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -62,7 +77,9 @@ impl StatusNotifierItem {
|
|||
|
||||
// TODO: Only fetch changed part of layout, if that's any faster
|
||||
pub fn layout_subscription(&self) -> iced::Subscription<Result<Layout, String>> {
|
||||
let menu_proxy = self.menu_proxy.clone();
|
||||
let Some(menu_proxy) = self.menu_proxy.clone() else {
|
||||
return Subscription::none();
|
||||
};
|
||||
Subscription::run_with_id(
|
||||
format!("status-notifier-item-layout-{}", &self.name),
|
||||
async move {
|
||||
|
|
@ -107,8 +124,8 @@ impl StatusNotifierItem {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn menu_proxy(&self) -> &DBusMenuProxy<'static> {
|
||||
&self.menu_proxy
|
||||
pub fn menu_proxy(&self) -> Option<&DBusMenuProxy<'static>> {
|
||||
self.menu_proxy.as_ref()
|
||||
}
|
||||
|
||||
pub fn item_proxy(&self) -> &StatusNotifierItemProxy<'static> {
|
||||
|
|
@ -135,10 +152,17 @@ pub trait StatusNotifierItem {
|
|||
#[zbus(property)]
|
||||
fn menu(&self) -> zbus::Result<zvariant::OwnedObjectPath>;
|
||||
|
||||
#[zbus(property)]
|
||||
fn item_is_menu(&self) -> zbus::Result<bool>;
|
||||
|
||||
#[zbus(signal)]
|
||||
fn new_icon(&self) -> zbus::Result<()>;
|
||||
|
||||
fn provide_xdg_activation_token(&self, token: String) -> zbus::Result<()>;
|
||||
|
||||
fn activate(&self, x: i32, y: i32) -> zbus::Result<()>;
|
||||
|
||||
fn secondary_activate(&self, x: i32, y: i32) -> zbus::Result<()>;
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue