feat(status-area): provide activation token on menu item activation
This commit is contained in:
parent
1d3d869f4a
commit
a5d813dc9b
3 changed files with 72 additions and 5 deletions
|
|
@ -4,6 +4,8 @@
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
app,
|
app,
|
||||||
applet::cosmic_panel_config::PanelAnchor,
|
applet::cosmic_panel_config::PanelAnchor,
|
||||||
|
applet::token::subscription::{activation_token_subscription, TokenRequest, TokenUpdate},
|
||||||
|
cctk::sctk::reexports::calloop,
|
||||||
iced::{
|
iced::{
|
||||||
self,
|
self,
|
||||||
overlay::menu,
|
overlay::menu,
|
||||||
|
|
@ -15,6 +17,7 @@ use cosmic::{
|
||||||
Element, Task,
|
Element, Task,
|
||||||
};
|
};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
use zbus::connection::socket::channel;
|
||||||
|
|
||||||
use crate::{components::status_menu, subscriptions::status_notifier_watcher};
|
use crate::{components::status_menu, subscriptions::status_notifier_watcher};
|
||||||
|
|
||||||
|
|
@ -29,10 +32,11 @@ pub enum Msg {
|
||||||
Surface(surface::Action),
|
Surface(surface::Action),
|
||||||
ToggleOverflow,
|
ToggleOverflow,
|
||||||
HoveredOverflow,
|
HoveredOverflow,
|
||||||
|
Token(TokenUpdate),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct App {
|
pub(crate) struct App {
|
||||||
core: app::Core,
|
core: app::Core,
|
||||||
connection: Option<zbus::Connection>,
|
connection: Option<zbus::Connection>,
|
||||||
menus: BTreeMap<usize, status_menu::State>,
|
menus: BTreeMap<usize, status_menu::State>,
|
||||||
|
|
@ -40,6 +44,7 @@ struct App {
|
||||||
max_menu_id: usize,
|
max_menu_id: usize,
|
||||||
popup: Option<window::Id>,
|
popup: Option<window::Id>,
|
||||||
overflow_popup: Option<window::Id>,
|
overflow_popup: Option<window::Id>,
|
||||||
|
token_tx: Option<calloop::channel::Sender<TokenRequest>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
|
|
@ -167,7 +172,7 @@ impl cosmic::Application for App {
|
||||||
}
|
}
|
||||||
Msg::StatusMenu((id, msg)) => match self.menus.get_mut(&id) {
|
Msg::StatusMenu((id, msg)) => match self.menus.get_mut(&id) {
|
||||||
Some(state) => state
|
Some(state) => state
|
||||||
.update(msg)
|
.update(msg, id, self.token_tx.as_ref())
|
||||||
.map(move |msg| cosmic::action::app(Msg::StatusMenu((id, msg)))),
|
.map(move |msg| cosmic::action::app(Msg::StatusMenu((id, msg)))),
|
||||||
None => Task::none(),
|
None => Task::none(),
|
||||||
},
|
},
|
||||||
|
|
@ -267,6 +272,32 @@ impl cosmic::Application for App {
|
||||||
}
|
}
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
|
Msg::Token(u) => match u {
|
||||||
|
TokenUpdate::Init(tx) => {
|
||||||
|
self.token_tx = Some(tx);
|
||||||
|
return Task::none();
|
||||||
|
}
|
||||||
|
TokenUpdate::Finished => {
|
||||||
|
self.token_tx = None;
|
||||||
|
return Task::none();
|
||||||
|
}
|
||||||
|
TokenUpdate::ActivationToken { token, exec: id } => {
|
||||||
|
if let Some(((state, id), token)) = str::parse(&id)
|
||||||
|
.ok()
|
||||||
|
.and_then(|id: usize| self.menus.get_mut(&id).map(|m| (m, id)))
|
||||||
|
.zip(token)
|
||||||
|
{
|
||||||
|
return state
|
||||||
|
.update(
|
||||||
|
status_menu::Msg::ClickToken(token),
|
||||||
|
id,
|
||||||
|
self.token_tx.as_ref(),
|
||||||
|
)
|
||||||
|
.map(move |msg| cosmic::action::app(Msg::StatusMenu((id, msg))));
|
||||||
|
}
|
||||||
|
return Task::none();
|
||||||
|
}
|
||||||
|
},
|
||||||
Msg::Hovered(id) => {
|
Msg::Hovered(id) => {
|
||||||
let mut cmds = Vec::new();
|
let mut cmds = Vec::new();
|
||||||
if let Some(old_id) = self.open_menu.take() {
|
if let Some(old_id) = self.open_menu.take() {
|
||||||
|
|
@ -417,6 +448,7 @@ impl cosmic::Application for App {
|
||||||
for (id, menu) in self.menus.iter() {
|
for (id, menu) in self.menus.iter() {
|
||||||
subscriptions.push(menu.subscription().with(*id).map(Msg::StatusMenu));
|
subscriptions.push(menu.subscription().with(*id).map(Msg::StatusMenu));
|
||||||
}
|
}
|
||||||
|
subscriptions.push(activation_token_subscription(0).map(Msg::Token));
|
||||||
|
|
||||||
iced::Subscription::batch(subscriptions)
|
iced::Subscription::batch(subscriptions)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,14 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
applet::menu_button,
|
applet::{
|
||||||
iced::{self, Padding},
|
menu_button,
|
||||||
|
token::{self, subscription::TokenRequest},
|
||||||
|
},
|
||||||
|
cctk::sctk::reexports::calloop,
|
||||||
|
iced,
|
||||||
widget::icon,
|
widget::icon,
|
||||||
|
Application,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::subscriptions::status_notifier_item::{IconUpdate, Layout, StatusNotifierItem};
|
use crate::subscriptions::status_notifier_item::{IconUpdate, Layout, StatusNotifierItem};
|
||||||
|
|
@ -14,6 +19,7 @@ pub enum Msg {
|
||||||
Layout(Result<Layout, String>),
|
Layout(Result<Layout, String>),
|
||||||
Icon(IconUpdate),
|
Icon(IconUpdate),
|
||||||
Click(i32, bool),
|
Click(i32, bool),
|
||||||
|
ClickToken(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
|
|
@ -23,6 +29,7 @@ pub struct State {
|
||||||
icon_name: String,
|
icon_name: String,
|
||||||
// TODO handle icon with multiple sizes?
|
// TODO handle icon with multiple sizes?
|
||||||
icon_pixmap: Option<icon::Handle>,
|
icon_pixmap: Option<icon::Handle>,
|
||||||
|
click_event: Option<(i32, bool)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
|
|
@ -34,12 +41,18 @@ impl State {
|
||||||
expanded: None,
|
expanded: None,
|
||||||
icon_name: String::new(),
|
icon_name: String::new(),
|
||||||
icon_pixmap: None,
|
icon_pixmap: None,
|
||||||
|
click_event: None,
|
||||||
},
|
},
|
||||||
iced::Task::none(),
|
iced::Task::none(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, message: Msg) -> iced::Task<Msg> {
|
pub fn update(
|
||||||
|
&mut self,
|
||||||
|
message: Msg,
|
||||||
|
menu_id: usize,
|
||||||
|
token_tx: Option<&calloop::channel::Sender<TokenRequest>>,
|
||||||
|
) -> iced::Task<Msg> {
|
||||||
match message {
|
match message {
|
||||||
Msg::Layout(layout) => {
|
Msg::Layout(layout) => {
|
||||||
match layout {
|
match layout {
|
||||||
|
|
@ -78,8 +91,24 @@ impl State {
|
||||||
iced::Task::none()
|
iced::Task::none()
|
||||||
}
|
}
|
||||||
Msg::Click(id, is_submenu) => {
|
Msg::Click(id, is_submenu) => {
|
||||||
|
if let Some(token_tx) = token_tx {
|
||||||
|
_ = token_tx.send(TokenRequest {
|
||||||
|
app_id: super::app::App::APP_ID.to_string(),
|
||||||
|
exec: menu_id.to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
self.click_event = Some((id, is_submenu));
|
||||||
|
iced::Task::none()
|
||||||
|
}
|
||||||
|
Msg::ClickToken(token) => {
|
||||||
|
let Some((id, is_submenu)) = self.click_event else {
|
||||||
|
return iced::Task::none();
|
||||||
|
};
|
||||||
|
|
||||||
let menu_proxy = self.item.menu_proxy().clone();
|
let menu_proxy = self.item.menu_proxy().clone();
|
||||||
|
let item_proxy = self.item.item_proxy().clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
|
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;
|
||||||
});
|
});
|
||||||
if is_submenu {
|
if is_submenu {
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,10 @@ impl StatusNotifierItem {
|
||||||
pub fn menu_proxy(&self) -> &DBusMenuProxy<'static> {
|
pub fn menu_proxy(&self) -> &DBusMenuProxy<'static> {
|
||||||
&self.menu_proxy
|
&self.menu_proxy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn item_proxy(&self) -> &StatusNotifierItemProxy<'static> {
|
||||||
|
&self.item_proxy
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_layout(menu_proxy: DBusMenuProxy<'static>) -> Result<Layout, String> {
|
async fn get_layout(menu_proxy: DBusMenuProxy<'static>) -> Result<Layout, String> {
|
||||||
|
|
@ -136,6 +140,8 @@ pub trait StatusNotifierItem {
|
||||||
|
|
||||||
#[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<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue