suport long lived plugin, and sort top level manually

This commit is contained in:
wiiznokes 2024-07-03 03:42:39 +02:00 committed by Ashley Wulber
parent fca3b25552
commit 593e397b03
12 changed files with 123 additions and 21 deletions

49
Cargo.lock generated
View file

@ -1428,6 +1428,16 @@ dependencies = [
"memoffset", "memoffset",
] ]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
dependencies = [
"overload",
"winapi",
]
[[package]] [[package]]
name = "num-conv" name = "num-conv"
version = "0.1.0" version = "0.1.0"
@ -1519,6 +1529,12 @@ dependencies = [
"pin-project-lite", "pin-project-lite",
] ]
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]] [[package]]
name = "parking" name = "parking"
version = "2.2.1" version = "2.2.1"
@ -1634,6 +1650,7 @@ dependencies = [
"pop-launcher-toolkit", "pop-launcher-toolkit",
"tokio", "tokio",
"tracing", "tracing",
"tracing-journald",
"tracing-subscriber", "tracing-subscriber",
] ]
@ -2580,6 +2597,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
dependencies = [ dependencies = [
"once_cell", "once_cell",
"valuable",
]
[[package]]
name = "tracing-journald"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba316a74e8fc3c3896a850dba2375928a9fa171b085ecddfc7c054d39970f3fd"
dependencies = [
"libc",
"tracing-core",
"tracing-subscriber",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
] ]
[[package]] [[package]]
@ -2590,12 +2630,15 @@ checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
dependencies = [ dependencies = [
"chrono", "chrono",
"matchers", "matchers",
"nu-ansi-term",
"once_cell", "once_cell",
"regex", "regex",
"sharded-slab", "sharded-slab",
"smallvec",
"thread_local", "thread_local",
"tracing", "tracing",
"tracing-core", "tracing-core",
"tracing-log",
] ]
[[package]] [[package]]
@ -2686,6 +2729,12 @@ version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a"
[[package]]
name = "valuable"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.5" version = "0.9.5"

View file

@ -16,6 +16,7 @@ tracing-subscriber = { version = "0.3.18", default-features = false, features =
"env-filter", "env-filter",
"chrono", "chrono",
] } ] }
tracing-journald = "0.3.0"
dirs.workspace = true dirs.workspace = true
mimalloc = "0.1.43" mimalloc = "0.1.43"

View file

@ -5,8 +5,6 @@ use pop_launcher_toolkit::plugins;
use pop_launcher_toolkit::service; use pop_launcher_toolkit::service;
use mimalloc::MiMalloc; use mimalloc::MiMalloc;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::EnvFilter;
#[global_allocator] #[global_allocator]
static GLOBAL: MiMalloc = MiMalloc; static GLOBAL: MiMalloc = MiMalloc;
@ -41,7 +39,7 @@ async fn main() {
// todo: support journald once this issue is resolved: https://github.com/tokio-rs/tracing/issues/2348 // todo: support journald once this issue is resolved: https://github.com/tokio-rs/tracing/issues/2348
fn init_logging(cmd: &str) { fn init_logging(cmd: &str) {
use tracing_subscriber::{fmt, Registry}; use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
let logdir = match dirs::state_dir() { let logdir = match dirs::state_dir() {
Some(dir) => dir.join("pop-launcher/"), Some(dir) => dir.join("pop-launcher/"),
@ -59,7 +57,7 @@ fn init_logging(cmd: &str) {
if let Ok(file) = logfile { if let Ok(file) = logfile {
if let Ok(meta) = file.metadata() { if let Ok(meta) = file.metadata() {
if meta.len() > 1000 { if meta.len() > 10000 {
let _ = file.set_len(0); let _ = file.set_len(0);
} }
} }
@ -68,13 +66,18 @@ fn init_logging(cmd: &str) {
.or_else(|_| EnvFilter::try_new("warn")) .or_else(|_| EnvFilter::try_new("warn"))
.unwrap(); .unwrap();
let fmt_layer = fmt::layer() let fmt_layer = fmt::layer().with_target(false).with_writer(file);
.with_target(false)
.with_timer(fmt::time::ChronoLocal::new("%T".into()))
.with_writer(file);
let subscriber = Registry::default().with(filter_layer).with(fmt_layer); if let Ok(journal_layer) = tracing_journald::layer() {
tracing_subscriber::registry()
tracing::subscriber::set_global_default(subscriber).expect("Failed to set subscriber"); .with(journal_layer)
.with(filter_layer)
.init();
} else {
tracing_subscriber::registry()
.with(fmt_layer)
.with(filter_layer)
.init();
}
} }
} }

View file

@ -1,10 +1,12 @@
mod toplevel_handler; mod toplevel_handler;
use cctk::cosmic_protocols::toplevel_info::v1::client::zcosmic_toplevel_handle_v1::State;
use cctk::wayland_client::Proxy; use cctk::wayland_client::Proxy;
use cctk::{cosmic_protocols, sctk::reexports::calloop, toplevel_info::ToplevelInfo}; use cctk::{cosmic_protocols, sctk::reexports::calloop, toplevel_info::ToplevelInfo};
use cosmic_protocols::toplevel_info::v1::client::zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1; use cosmic_protocols::toplevel_info::v1::client::zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1;
use fde::DesktopEntry; use fde::DesktopEntry;
use freedesktop_desktop_entry as fde; use freedesktop_desktop_entry as fde;
use tracing::{debug, info};
use crate::desktop_entries::utils::get_description; use crate::desktop_entries::utils::get_description;
use crate::send; use crate::send;
@ -19,12 +21,13 @@ use pop_launcher::{
}; };
use std::borrow::Cow; use std::borrow::Cow;
use std::iter; use std::iter;
use std::collections::VecDeque;
use tokio::io::{AsyncWrite, AsyncWriteExt}; use tokio::io::{AsyncWrite, AsyncWriteExt};
use self::toplevel_handler::{toplevel_handler, ToplevelAction, ToplevelEvent}; use self::toplevel_handler::{toplevel_handler, ToplevelAction, ToplevelEvent};
pub async fn main() { pub async fn main() {
tracing::info!("starting cosmic-toplevel"); info!("starting cosmic-toplevel");
let mut tx = async_stdout(); let mut tx = async_stdout();
@ -68,20 +71,37 @@ pub async fn main() {
Either::Right((Some(event), second_to_next_request)) => { Either::Right((Some(event), second_to_next_request)) => {
next_event = toplevel_rx.next(); next_event = toplevel_rx.next();
next_request = second_to_next_request; next_request = second_to_next_request;
match event { match event {
ToplevelEvent::Add(handle, info) => { ToplevelEvent::Add(handle, info) => {
tracing::info!("{}", &info.app_id); tracing::info!("add {}", &info.app_id);
app.toplevels.retain(|t| t.0 != handle); app.toplevels.retain(|t| t.0 != handle);
app.toplevels.push((handle, info)); app.toplevels.push_front((handle, info));
} }
ToplevelEvent::Remove(handle) => { ToplevelEvent::Remove(handle) => {
app.toplevels.retain(|t| t.0 != handle); if let Some(pos) = app.toplevels.iter().position(|t| t.0 == handle) {
app.toplevels.remove(pos);
// ignore requests for this id until after the next search // ignore requests for this id until after the next search
app.ids_to_ignore.push(handle.id().protocol_id()); app.ids_to_ignore.push(handle.id().protocol_id());
} else {
tracing::warn!("ToplevelEvent::Remove, no toplevel found");
}
} }
ToplevelEvent::Update(handle, info) => { ToplevelEvent::Update(handle, info) => {
if let Some(t) = app.toplevels.iter_mut().find(|t| t.0 == handle) { debug!("Update {}", &info.app_id);
t.1 = info; debug!("Update {:?}", &info.state);
if let Some(pos) = app.toplevels.iter().position(|t| t.0 == handle) {
if info.state.contains(&State::Activated) {
tracing::warn!("Update {:?}: push front", &info.app_id);
app.toplevels.remove(pos);
app.toplevels.push_front((handle, info));
} else {
app.toplevels[pos].1 = info;
}
} else {
tracing::warn!("ToplevelEvent::Update, no toplevel found");
app.toplevels.push_front((handle, info));
} }
} }
} }
@ -95,7 +115,8 @@ struct App<W> {
locales: Vec<String>, locales: Vec<String>,
desktop_entries: Vec<DesktopEntry<'static>>, desktop_entries: Vec<DesktopEntry<'static>>,
ids_to_ignore: Vec<u32>, ids_to_ignore: Vec<u32>,
toplevels: Vec<(ZcosmicToplevelHandleV1, ToplevelInfo)>, // XXX: use LinkedList?
toplevels: VecDeque<(ZcosmicToplevelHandleV1, ToplevelInfo)>,
calloop_tx: calloop::channel::Sender<ToplevelAction>, calloop_tx: calloop::channel::Sender<ToplevelAction>,
tx: W, tx: W,
} }
@ -119,7 +140,7 @@ impl<W: AsyncWrite + Unpin> App<W> {
locales, locales,
desktop_entries, desktop_entries,
ids_to_ignore: Vec::new(), ids_to_ignore: Vec::new(),
toplevels: Vec::new(), toplevels: VecDeque::new(),
calloop_tx, calloop_tx,
tx, tx,
}, },

View file

@ -4,4 +4,5 @@
query: (persistent: true, priority: High), query: (persistent: true, priority: High),
bin: (path: "cosmic-toplevel"), bin: (path: "cosmic-toplevel"),
icon: Name("focus-windows-symbolic"), icon: Name("focus-windows-symbolic"),
long_lived: true,
) )

View file

@ -9,11 +9,13 @@ use futures::StreamExt;
use pop_launcher::*; use pop_launcher::*;
use std::borrow::Cow; use std::borrow::Cow;
use tokio::io::AsyncWrite; use tokio::io::AsyncWrite;
use tracing::info;
use utils::get_description; use utils::get_description;
pub(crate) mod utils; pub(crate) mod utils;
pub async fn main() { pub async fn main() {
info!("starting desktop entries");
let mut app = App::new(async_stdout()); let mut app = App::new(async_stdout());
app.reload().await; app.reload().await;

View file

@ -201,6 +201,15 @@ impl<O: futures::Sink<Response> + Unpin> Service<O> {
break; break;
} }
Request::Close => {
for (_key, plugin) in self.plugins.iter_mut() {
if !plugin.config.long_lived {
let tx = plugin.sender_exec();
_ = tx.send_async(Request::Exit).await;
plugin.sender_drop();
}
}
}
} }
} }
@ -465,6 +474,8 @@ impl<O: futures::Sink<Response> + Unpin> Service<O> {
} }
} }
} else { } else {
self.no_sort = query.is_empty();
for plugin_id in query_queue { for plugin_id in query_queue {
if let Some(plugin) = self.plugins.get_mut(plugin_id) { if let Some(plugin) = self.plugins.get_mut(plugin_id) {
if plugin if plugin

View file

@ -30,6 +30,9 @@ pub struct PluginConfig {
#[serde(default)] #[serde(default)]
pub history: bool, pub history: bool,
#[serde(default)]
pub long_lived: bool,
} }
#[derive(Debug, Default, Deserialize, Clone)] #[derive(Debug, Default, Deserialize, Clone)]

View file

@ -24,6 +24,7 @@ pub const CONFIG: PluginConfig = PluginConfig {
}, },
icon: Some(IconSource::Name(Cow::Borrowed("system-help-symbolic"))), icon: Some(IconSource::Name(Cow::Borrowed("system-help-symbolic"))),
history: false, history: false,
long_lived: false,
}; };
pub struct HelpPlugin { pub struct HelpPlugin {
pub id: usize, pub id: usize,

View file

@ -60,6 +60,9 @@ where
self.exit(); self.exit();
break; break;
} }
Request::Close => {
self.exit();
}
} }
} }

View file

@ -137,6 +137,9 @@ pub enum Request {
Context(Indice), Context(Indice),
/// Request to end the service. /// Request to end the service.
Exit, Exit,
/// The frontend was closed and the service should release resources
/// and prepare for the next query
Close,
/// Requests to cancel any active searches. /// Requests to cancel any active searches.
Interrupt, Interrupt,
/// Request to close the selected item. /// Request to close the selected item.

View file

@ -89,6 +89,10 @@ where
self.exit(); self.exit();
break; break;
} }
Request::Close => {
self.exit();
break;
}
}, },
Err(why) => tracing::error!("Malformed json request: {why}"), Err(why) => tracing::error!("Malformed json request: {why}"),
} }