fix(status-area): implement activate on left-click with menu fallback

This commit is contained in:
夜未央,天将亮 2025-12-30 15:27:24 +08:00 committed by GitHub
parent 2f1b47f2b8
commit 9db4ebdc2d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 57 additions and 14 deletions

View file

@ -20,6 +20,8 @@ use crate::{components::status_menu, subscriptions::status_notifier_watcher};
#[derive(Clone, Debug)]
pub enum Msg {
None,
Activate(usize),
Closed(window::Id),
// XXX don't use index (unique window id? or I guess that's created and destroyed)
StatusMenu((usize, status_menu::Msg)),
@ -100,10 +102,6 @@ impl App {
.on_enter(Msg::Hovered(*id))
.into()
});
let theme = self.core.system_theme();
let cosmic = theme.cosmic();
let corners = cosmic.corner_radii;
let pad = corners.radius_m[0];
self.core
.applet
@ -151,6 +149,26 @@ impl cosmic::Application for App {
fn update(&mut self, message: Msg) -> app::Task<Msg> {
match message {
Msg::None => Task::none(),
Msg::Activate(id) => {
if let Some(token_tx) = self.token_tx.as_ref() {
let _ = token_tx.send(TokenRequest {
app_id: Self::APP_ID.to_string(),
exec: format!("activate:{}", id),
});
} else {
if let Some(menu) = self.menus.get(&id) {
let item_proxy = menu.item.item_proxy().clone();
return Task::future(async move {
match item_proxy.activate(0, 0).await {
Ok(_) => cosmic::action::app(Msg::None),
Err(_) => cosmic::action::app(Msg::TogglePopup(id)),
}
});
}
}
Task::none()
}
Msg::Closed(surface) => {
if self.popup == Some(surface) {
self.popup = None;
@ -269,6 +287,36 @@ impl cosmic::Application for App {
return Task::none();
}
TokenUpdate::ActivationToken { token, exec: id } => {
if let Some(id_str) = id.strip_prefix("activate:") {
if let Ok(real_id) = id_str.parse::<usize>() {
if let Some(menu) = self.menus.get(&real_id) {
let item_proxy = menu.item.item_proxy().clone();
let token = token.clone();
let id = real_id;
return Task::future(async move {
if let Some(t) = token {
match item_proxy.provide_xdg_activation_token(t).await {
Ok(_) => {
println!("Token provided successfully to {}", id)
}
Err(e) => eprintln!(
"Failed to provide token to {}: {}",
id, e
),
}
}
match item_proxy.activate(0, 0).await {
Ok(_) => cosmic::action::app(Msg::None),
Err(err) => {
eprintln!("Activate failed: {}", err);
cosmic::action::app(Msg::TogglePopup(id))
}
}
});
}
}
return Task::none();
}
if let Some(((state, id), token)) = str::parse(&id)
.ok()
.and_then(|id: usize| self.menus.get_mut(&id).map(|m| (m, id)))
@ -445,15 +493,10 @@ impl cosmic::Application for App {
.iter()
.take(overflow_index.unwrap_or(self.menus.len()))
.map(|(id, menu)| {
mouse_area(menu_icon_button(&self.core.applet, &menu).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()
mouse_area(menu_icon_button(&self.core.applet, &menu).on_press(Msg::Activate(*id)))
.on_right_press(Msg::TogglePopup(*id))
.on_enter(Msg::Hovered(*id))
.into()
});
self.core

View file

@ -50,7 +50,7 @@ impl StatusNotifierItem {
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);
let is_menu = menu_path.is_ok() || is_menu.unwrap_or(false);
if !is_menu {
return Ok(Self {