From fe0e4bf409234fc1b632efc22403b46282f892c0 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Wed, 28 Jan 2026 18:44:05 -0800 Subject: [PATCH] status-area: Use `ItemIsMenu` correctly The comment that was previously here assumed that `ItemIsMenu` should be defined for any status item that has a menu, but the FreeDesktop spec rather defines it as an item that "only supports the context menu", so we should open the menu instead of trying to call `Activate`. This change won't affect behavior if `ItemIsMenu` is true, but `Activate` errors, except by opening the menu without having to wait for that errror first. It will fix the left click to open menu behavior if any client defines that method to not error, but does set `ItemIsMenu`. --- .../src/components/app.rs | 3 ++ .../src/subscriptions/status_notifier_item.rs | 41 +++++++++---------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/cosmic-applet-status-area/src/components/app.rs b/cosmic-applet-status-area/src/components/app.rs index eeeba7ec..03e56e9d 100644 --- a/cosmic-applet-status-area/src/components/app.rs +++ b/cosmic-applet-status-area/src/components/app.rs @@ -543,6 +543,9 @@ fn activate( item: &StatusNotifierItem, activation_token: Option, ) -> Task> { + if item.is_menu() { + return Task::done(cosmic::action::app(Msg::TogglePopup(id))); + } let item_proxy = item.item_proxy().clone(); Task::future(async move { if let Some(t) = activation_token { diff --git a/cosmic-applet-status-area/src/subscriptions/status_notifier_item.rs b/cosmic-applet-status-area/src/subscriptions/status_notifier_item.rs index ee12cbe0..5a67f07b 100644 --- a/cosmic-applet-status-area/src/subscriptions/status_notifier_item.rs +++ b/cosmic-applet-status-area/src/subscriptions/status_notifier_item.rs @@ -10,6 +10,7 @@ use zbus::zvariant::{self, OwnedValue}; #[derive(Clone, Debug)] pub struct StatusNotifierItem { name: String, + is_menu: bool, item_proxy: StatusNotifierItemProxy<'static>, menu_proxy: Option>, } @@ -44,32 +45,25 @@ impl StatusNotifierItem { .build() .await?; - // XX: some items will not implement this but have a menu anyway - let is_menu = item_proxy.item_is_menu().await; + let is_menu = item_proxy.item_is_menu().await.unwrap_or(false); - 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 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)? - .build() - .await?; + let menu_proxy = if let Ok(menu_path) = item_proxy.menu().await { + Some( + DBusMenuProxy::builder(connection) + .destination(dest.to_string())? + .path(menu_path)? + .build() + .await?, + ) + } else { + None + }; Ok(Self { name, + is_menu, item_proxy, - menu_proxy: Some(menu_proxy), + menu_proxy, }) } @@ -126,6 +120,11 @@ impl StatusNotifierItem { ) } + /// Item is only a menu, with no `Activate` action + pub fn is_menu(&self) -> bool { + self.is_menu + } + pub fn menu_proxy(&self) -> Option<&DBusMenuProxy<'static>> { self.menu_proxy.as_ref() }