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)),
|
.icon_button_from_handle(icon.clone().symbolic(true)),
|
||||||
_ => self.core.applet.icon_button(menu.icon_name()),
|
_ => 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))
|
.on_enter(Msg::Hovered(*id))
|
||||||
.into()
|
.into()
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ pub enum Msg {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
item: StatusNotifierItem,
|
pub item: StatusNotifierItem,
|
||||||
layout: Option<Layout>,
|
layout: Option<Layout>,
|
||||||
expanded: Option<i32>,
|
expanded: Option<i32>,
|
||||||
icon_name: String,
|
icon_name: String,
|
||||||
|
|
@ -101,9 +101,19 @@ impl State {
|
||||||
let Some((id, is_submenu)) = self.click_event else {
|
let Some((id, is_submenu)) = self.click_event else {
|
||||||
return iced::Task::none();
|
return iced::Task::none();
|
||||||
};
|
};
|
||||||
|
|
||||||
let menu_proxy = self.item.menu_proxy().clone();
|
|
||||||
let item_proxy = self.item.item_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 {
|
tokio::spawn(async move {
|
||||||
let _ = item_proxy.provide_xdg_activation_token(token).await;
|
let _ = item_proxy.provide_xdg_activation_token(token).await;
|
||||||
let _ = menu_proxy.event(id, "clicked", &0.into(), 0).await;
|
let _ = menu_proxy.event(id, "clicked", &0.into(), 0).await;
|
||||||
|
|
@ -150,7 +160,9 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn opened(&self) {
|
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 {
|
tokio::spawn(async move {
|
||||||
let _ = menu_proxy.event(0, "opened", &0i32.into(), 0).await;
|
let _ = menu_proxy.event(0, "opened", &0i32.into(), 0).await;
|
||||||
let _ = menu_proxy.about_to_show(0).await;
|
let _ = menu_proxy.about_to_show(0).await;
|
||||||
|
|
@ -158,7 +170,9 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn closed(&self) {
|
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 {
|
tokio::spawn(async move {
|
||||||
let _ = menu_proxy.event(0, "closed", &0i32.into(), 0).await;
|
let _ = menu_proxy.event(0, "closed", &0i32.into(), 0).await;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use zbus::zvariant::{self, OwnedValue};
|
||||||
pub struct StatusNotifierItem {
|
pub struct StatusNotifierItem {
|
||||||
name: String,
|
name: String,
|
||||||
item_proxy: StatusNotifierItemProxy<'static>,
|
item_proxy: StatusNotifierItemProxy<'static>,
|
||||||
menu_proxy: DBusMenuProxy<'static>,
|
menu_proxy: Option<DBusMenuProxy<'static>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, zvariant::Value)]
|
#[derive(Clone, Debug, zvariant::Value)]
|
||||||
|
|
@ -42,7 +42,22 @@ impl StatusNotifierItem {
|
||||||
.build()
|
.build()
|
||||||
.await?;
|
.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)
|
let menu_proxy = DBusMenuProxy::builder(connection)
|
||||||
.destination(dest.to_string())?
|
.destination(dest.to_string())?
|
||||||
.path(menu_path)?
|
.path(menu_path)?
|
||||||
|
|
@ -52,7 +67,7 @@ impl StatusNotifierItem {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
name,
|
name,
|
||||||
item_proxy,
|
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
|
// TODO: Only fetch changed part of layout, if that's any faster
|
||||||
pub fn layout_subscription(&self) -> iced::Subscription<Result<Layout, String>> {
|
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(
|
Subscription::run_with_id(
|
||||||
format!("status-notifier-item-layout-{}", &self.name),
|
format!("status-notifier-item-layout-{}", &self.name),
|
||||||
async move {
|
async move {
|
||||||
|
|
@ -107,8 +124,8 @@ impl StatusNotifierItem {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn menu_proxy(&self) -> &DBusMenuProxy<'static> {
|
pub fn menu_proxy(&self) -> Option<&DBusMenuProxy<'static>> {
|
||||||
&self.menu_proxy
|
self.menu_proxy.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn item_proxy(&self) -> &StatusNotifierItemProxy<'static> {
|
pub fn item_proxy(&self) -> &StatusNotifierItemProxy<'static> {
|
||||||
|
|
@ -135,10 +152,17 @@ pub trait StatusNotifierItem {
|
||||||
#[zbus(property)]
|
#[zbus(property)]
|
||||||
fn menu(&self) -> zbus::Result<zvariant::OwnedObjectPath>;
|
fn menu(&self) -> zbus::Result<zvariant::OwnedObjectPath>;
|
||||||
|
|
||||||
|
#[zbus(property)]
|
||||||
|
fn item_is_menu(&self) -> zbus::Result<bool>;
|
||||||
|
|
||||||
#[zbus(signal)]
|
#[zbus(signal)]
|
||||||
fn new_icon(&self) -> zbus::Result<()>;
|
fn new_icon(&self) -> zbus::Result<()>;
|
||||||
|
|
||||||
fn provide_xdg_activation_token(&self, token: String) -> 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)]
|
#[derive(Clone, Debug)]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue