diff --git a/Cargo.lock b/Cargo.lock index 53c7718..d49a73b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1291,6 +1291,8 @@ dependencies = [ "switcheroo-control", "tokio", "tracing", + "tracing-journald", + "tracing-subscriber", "unicode-truncate", "unicode-width", "xdg", @@ -3853,6 +3855,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[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]] name = "num-conv" version = "0.1.0" @@ -4207,6 +4219,12 @@ dependencies = [ "syn 2.0.90", ] +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "owned_ttf_parser" version = "0.25.0" @@ -4477,7 +4495,7 @@ checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" [[package]] name = "pop-launcher" version = "1.2.4" -source = "git+https://github.com/pop-os/launcher/?rev=fca3b25#fca3b25552deca3bd64de8bfd1ebb38c45e4fb39" +source = "git+https://github.com/pop-os/launcher/#c37c2a3c6a0b0167267140f2792c49ccc0c15767" dependencies = [ "const_format", "dirs 5.0.1", @@ -4492,7 +4510,7 @@ dependencies = [ [[package]] name = "pop-launcher-service" version = "1.2.4" -source = "git+https://github.com/pop-os/launcher/?rev=fca3b25#fca3b25552deca3bd64de8bfd1ebb38c45e4fb39" +source = "git+https://github.com/pop-os/launcher/#c37c2a3c6a0b0167267140f2792c49ccc0c15767" dependencies = [ "anyhow", "async-oneshot", @@ -5892,6 +5910,28 @@ dependencies = [ "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]] name = "tracing-subscriber" version = "0.3.19" @@ -5899,12 +5939,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "matchers", + "nu-ansi-term", "once_cell", "regex", "sharded-slab", + "smallvec", "thread_local", "tracing", "tracing-core", + "tracing-log", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index db3fab4..9c24ece 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,10 +31,16 @@ libcosmic = { git = "https://github.com/pop-os/libcosmic/", features = [ "xdg-portal", ] } tracing = "0.1" +tracing-subscriber = { version = "0.3.18", default-features = false, features = [ + "std", + "fmt", + "env-filter", +] } +tracing-journald = "0.3.0" nix = { version = "0.27.1", features = ["process"] } once_cell = "1.17" -pop-launcher = { git = "https://github.com/pop-os/launcher/", rev = "fca3b25" } -pop-launcher-service = { git = "https://github.com/pop-os/launcher/", rev = "fca3b25" } +pop-launcher = { git = "https://github.com/pop-os/launcher/" } +pop-launcher-service = { git = "https://github.com/pop-os/launcher/" } pretty_env_logger = "0.5" rust-embed = "6.3.0" serde = { version = "1.0.152", features = ["derive"] } @@ -47,3 +53,7 @@ switcheroo-control = { git = "https://github.com/pop-os/dbus-settings-bindings" zbus = { version = "4.2.1", default-features = false, features = ["tokio"] } unicode-truncate = "1.0.0" unicode-width = "0.1.11" + +# [patch."https://github.com/pop-os/launcher/"] +# pop-launcher = { git = "https://github.com/wiiznokes/launcher/", rev = "86a54d54a68b832d404ef83a03af84cf9ef3e694" } +# pop-launcher-service = { git = "https://github.com/wiiznokes/launcher/", rev = "86a54d54a68b832d404ef83a03af84cf9ef3e694" } diff --git a/justfile b/justfile index 14d69a3..de0b0e2 100644 --- a/justfile +++ b/justfile @@ -1,16 +1,17 @@ -name := 'cosmic-launcher' +export NAME := 'cosmic-launcher' export APPID := 'com.system76.CosmicLauncher' rootdir := '' prefix := '/usr' +debug := '0' base-dir := absolute_path(clean(rootdir / prefix)) export INSTALL_DIR := base-dir / 'share' cargo-target-dir := env('CARGO_TARGET_DIR', 'target') -bin-src := cargo-target-dir / 'release' / name -bin-dst := base-dir / 'bin' / name +bin-src := if debug == '1' { 'debug' / NAME } else { cargo-target-dir / 'release' / NAME } +bin-dst := base-dir / 'bin' / NAME # Use mold linker if clang and mold exists. clang-path := `which clang || true` diff --git a/src/app.rs b/src/app.rs index adbb600..b45a941 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,6 +1,6 @@ use crate::{app::iced::event::listen_raw, components, fl, subscriptions::launcher}; use clap::Parser; -use cosmic::app::{command, Core, CosmicFlags, DbusActivationDetails, Settings, Task}; +use cosmic::app::{Core, CosmicFlags, DbusActivationDetails, Settings, Task}; use cosmic::cctk::sctk; use cosmic::iced::alignment::{Horizontal, Vertical}; use cosmic::iced::event::Status; @@ -17,11 +17,12 @@ use cosmic::iced::platform_specific::shell::commands::{ use cosmic::iced::widget::{column, container, Column}; use cosmic::iced::{self, Length, Subscription}; use cosmic::iced_core::keyboard::key::Named; -use cosmic::iced_core::{Border, Padding, Point, Rectangle, Shadow}; +use cosmic::iced_core::{window, Border, Padding, Point, Rectangle, Shadow}; use cosmic::iced_runtime::core::event::wayland::LayerEvent; use cosmic::iced_runtime::core::event::{wayland, PlatformSpecific}; use cosmic::iced_runtime::core::layout::Limits; use cosmic::iced_runtime::core::window::Id as SurfaceId; +use cosmic::iced_runtime::platform_specific::wayland::layer_surface::IcedMargin; use cosmic::iced_widget::row; use cosmic::theme::{self, Button, Container}; use cosmic::widget::icon::{from_name, IconFallback}; @@ -38,8 +39,14 @@ use once_cell::sync::Lazy; use pop_launcher::{ContextOption, GpuPreference, IconSource, SearchResult}; use serde::{Deserialize, Serialize}; use std::fmt::Display; -use std::{collections::HashMap, rc::Rc, str::FromStr, time::Instant}; +use std::{ + collections::{HashMap, VecDeque}, + rc::Rc, + str::FromStr, + time::Instant, +}; use tokio::sync::mpsc; +use tracing::{debug, error, info}; use unicode_truncate::UnicodeTruncateStr; use unicode_width::UnicodeWidthStr; @@ -60,22 +67,24 @@ pub(crate) static MENU_ID: Lazy = Lazy::new(SurfaceId::unique); #[command(propagate_version = true)] pub struct Args { #[clap(subcommand)] - pub subcommand: Option, + pub subcommand: Option, } #[derive(Debug, Serialize, Deserialize, Clone, clap::Subcommand)] -pub enum LauncherCommands { +pub enum LauncherTasks { #[clap(about = "Toggle the launcher and switch to the alt-tab view")] AltTab, + #[clap(about = "Toggle the launcher and switch to the alt-tab view")] + ShiftAltTab, } -impl Display for LauncherCommands { +impl Display for LauncherTasks { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", serde_json::ser::to_string(self).unwrap()) } } -impl FromStr for LauncherCommands { +impl FromStr for LauncherTasks { type Err = serde_json::Error; fn from_str(s: &str) -> Result { @@ -84,10 +93,10 @@ impl FromStr for LauncherCommands { } impl CosmicFlags for Args { - type SubCommand = LauncherCommands; + type SubCommand = LauncherTasks; type Args = Vec; - fn action(&self) -> Option<&LauncherCommands> { + fn action(&self) -> Option<&LauncherTasks> { self.subcommand.as_ref() } } @@ -122,20 +131,27 @@ pub fn menu_control_padding() -> Padding { [cosmic.space_xxs(), cosmic.space_m()].into() } +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum SurfaceState { + Visible, + Hidden, + WaitingToBeShown, +} + #[derive(Clone)] pub struct CosmicLauncher { core: Core, input_value: String, - active_surface: bool, + surface_state: SurfaceState, launcher_items: Vec, tx: Option>, - wait_for_result: bool, menu: Option<(u32, Vec)>, cursor_position: Option>, focused: usize, last_hide: Instant, alt_tab: bool, - window_id: SurfaceId, + window_id: window::Id, + queue: VecDeque, } #[derive(Debug, Clone)] @@ -155,38 +171,60 @@ pub enum Message { KeyboardNav(keyboard_nav::Message), ActivationToken(Option, String, String, GpuPreference), AltTab, + ShiftAltTab, AltRelease, } impl CosmicLauncher { + fn request(&self, r: launcher::Request) { + debug!("request: {:?}", r); + if let Some(tx) = &self.tx { + if let Err(e) = tx.blocking_send(r) { + error!("tx: {e}"); + } + } else { + info!("tx not found"); + } + } + + fn show(&mut self) -> Task { + self.surface_state = SurfaceState::Visible; + + get_layer_surface(SctkLayerSurfaceSettings { + id: self.window_id, + keyboard_interactivity: KeyboardInteractivity::Exclusive, + anchor: Anchor::TOP, + namespace: "launcher".into(), + size: None, + margin: IcedMargin { + top: 16, + ..Default::default() + }, + size_limits: Limits::NONE.min_width(1.0).min_height(1.0).max_width(600.0), + ..Default::default() + }) + } + fn hide(&mut self) -> Task { self.input_value.clear(); self.focused = 0; self.alt_tab = false; - self.wait_for_result = false; + self.queue.clear(); - // XXX The close will reset the launcher, but the search will restart it so it's ready - // for the next time it's opened. - if let Some(ref sender) = &self.tx { - let _res = sender.blocking_send(launcher::Request::Close); - } + self.request(launcher::Request::Close); - if let Some(tx) = &self.tx { - let _res = tx.blocking_send(launcher::Request::Search(String::new())); - } else { - tracing::info!("NOT FOUND"); - } + let mut tasks = Vec::new(); - if self.active_surface { - self.active_surface = false; - let mut commands = vec![destroy_layer_surface(self.window_id)]; + if self.surface_state == SurfaceState::Visible { + tasks.push(destroy_layer_surface(self.window_id)); if self.menu.take().is_some() { - commands.push(commands::popup::destroy_popup(*MENU_ID)); + tasks.push(commands::popup::destroy_popup(*MENU_ID)); } - return Task::batch(commands); } - Task::none() + self.surface_state = SurfaceState::Hidden; + + Task::batch(tasks) } fn focus_next(&mut self) { @@ -244,16 +282,16 @@ impl cosmic::Application for CosmicLauncher { CosmicLauncher { core, input_value: String::new(), - active_surface: false, + surface_state: SurfaceState::Hidden, launcher_items: Vec::new(), tx: None, - wait_for_result: false, menu: None, cursor_position: None, focused: 0, last_hide: Instant::now(), alt_tab: false, window_id: SurfaceId::unique(), + queue: VecDeque::new(), }, Task::none(), ) @@ -272,24 +310,16 @@ impl cosmic::Application for CosmicLauncher { match message { Message::InputChanged(value) => { self.input_value.clone_from(&value); - if let Some(tx) = &self.tx { - let _res = tx.blocking_send(launcher::Request::Search(value)); - } + self.request(launcher::Request::Search(value)); } Message::Backspace => { - let len = self.input_value.len(); - if len > 0 { - self.input_value.remove(len - 1); - } - if let Some(tx) = &self.tx { - let _res = - tx.blocking_send(launcher::Request::Search(self.input_value.clone())); - } + self.input_value.pop(); + self.request(launcher::Request::Search(self.input_value.clone())); } Message::TabPress if !self.alt_tab => { let focused = self.focused; self.focused = 0; - return command::message(cosmic::app::Message::App( + return cosmic::task::message(cosmic::app::Message::App( Self::Message::CompleteFocusedId(RESULT_IDS[focused].clone()), )); } @@ -301,37 +331,30 @@ impl cosmic::Application for CosmicLauncher { .unwrap_or_default(); if let Some(id) = self.launcher_items.get(i).map(|res| res.id) { - if let Some(tx) = &self.tx { - let _res = tx.blocking_send(launcher::Request::Complete(id)); - } + self.request(launcher::Request::Complete(id)); } } Message::Activate(i) => { - if let (Some(tx), Some(item)) = - (&self.tx, self.launcher_items.get(i.unwrap_or(self.focused))) - { - let _res = tx.blocking_send(launcher::Request::Activate(item.id)); + if let Some(item) = self.launcher_items.get(i.unwrap_or(self.focused)) { + self.request(launcher::Request::Activate(item.id)); } else { return self.hide(); } } - #[allow(clippy::cast_possible_wrap)] Message::Context(i) => { if self.menu.take().is_some() { return commands::popup::destroy_popup(*MENU_ID); } - if let (Some(tx), Some(item)) = (&self.tx, self.launcher_items.get(i)) { - let _res = tx.blocking_send(launcher::Request::Context(item.id)); + if let Some(item) = self.launcher_items.get(i) { + self.request(launcher::Request::Context(item.id)); } } Message::CursorMoved(pos) => { self.cursor_position = Some(pos); } Message::MenuButton(i, context) => { - if let Some(tx) = &self.tx { - let _res = tx.blocking_send(launcher::Request::ActivateContext(i, context)); - } + self.request(launcher::Request::ActivateContext(i, context)); if self.menu.take().is_some() { return commands::popup::destroy_popup(*MENU_ID); @@ -339,11 +362,16 @@ impl cosmic::Application for CosmicLauncher { } Message::LauncherEvent(e) => match e { launcher::Event::Started(tx) => { - _ = tx.blocking_send(launcher::Request::Search(String::new())); self.tx.replace(tx); + self.request(launcher::Request::Search(self.input_value.clone())); + } + launcher::Event::ServiceIsClosed => { + self.request(launcher::Request::ServiceIsClosed); } launcher::Event::Response(response) => match response { - pop_launcher::Response::Close => return self.hide(), + pop_launcher::Response::Close => { + return self.hide(); + } #[allow(clippy::cast_possible_truncation)] pop_launcher::Response::Context { id, options } => { if options.is_empty() { @@ -411,7 +439,7 @@ impl cosmic::Application for CosmicLauncher { } } pop_launcher::Response::Update(mut list) => { - if self.alt_tab && self.wait_for_result && list.is_empty() { + if self.alt_tab && list.is_empty() { return self.hide(); } list.sort_by(|a, b| { @@ -422,35 +450,21 @@ impl cosmic::Application for CosmicLauncher { list.truncate(10); self.launcher_items.splice(.., list); - if self.wait_for_result { - self.wait_for_result = false; - self.window_id = SurfaceId::unique(); - return Task::batch(vec![get_layer_surface( - SctkLayerSurfaceSettings { - id: self.window_id, - keyboard_interactivity: KeyboardInteractivity::Exclusive, - anchor: Anchor::TOP, - namespace: "launcher".into(), - size: Some((Some(600), Some(1))), - margin: iced::platform_specific::runtime::wayland::layer_surface::IcedMargin { - top: 16, - ..Default::default() - }, - size_limits: Limits::NONE - .min_width(1.0) - .min_height(1.0) - .max_width(600.0), - ..Default::default() - }, - )]); + let mut cmds = Vec::new(); + + while let Some(element) = self.queue.pop_front() { + let updated = self.update(element); + cmds.push(updated); + } + + if self.surface_state == SurfaceState::WaitingToBeShown { + cmds.push(self.show()); } + return Task::batch(cmds); } pop_launcher::Response::Fill(s) => { self.input_value = s; - if let Some(tx) = &self.tx { - let _res = tx - .blocking_send(launcher::Request::Search(self.input_value.clone())); - } + self.request(launcher::Request::Search(self.input_value.clone())); } }, }, @@ -482,9 +496,7 @@ impl cosmic::Application for CosmicLauncher { } keyboard_nav::Message::Escape => { self.input_value.clear(); - if let Some(tx) = &self.tx { - let _res = tx.blocking_send(launcher::Request::Search(String::new())); - } + self.request(launcher::Request::Search(String::new())); } _ => {} }; @@ -495,11 +507,10 @@ impl cosmic::Application for CosmicLauncher { }); } Message::AltTab => { - if self.alt_tab { - self.focus_next(); - } else { - self.alt_tab = true; - } + self.focus_next(); + } + Message::ShiftAltTab => { + self.focus_previous(); } Message::AltRelease => { if self.alt_tab { @@ -516,42 +527,48 @@ impl cosmic::Application for CosmicLauncher { ) -> iced::Task> { match msg.msg { DbusActivationDetails::Activate => { - if self.active_surface || self.wait_for_result { + if self.surface_state != SurfaceState::Hidden { return self.hide(); - } else if self.last_hide.elapsed().as_millis() > 100 { - if let Some(tx) = &self.tx { - let _res = tx.blocking_send(launcher::Request::Search(String::new())); - } else { - tracing::info!("NOT FOUND"); - } + } + // hack: allow to close the launcher from the panel button + if self.last_hide.elapsed().as_millis() > 100 { + self.request(launcher::Request::Search(String::new())); - self.input_value = String::new(); - self.active_surface = true; - self.wait_for_result = true; + self.surface_state = SurfaceState::WaitingToBeShown; return Task::none(); } } DbusActivationDetails::ActivateAction { action, .. } => { - if LauncherCommands::from_str(&action).is_err() { + debug!("ActivateAction {}", action); + + let Ok(cmd) = LauncherTasks::from_str(&action) else { return Task::none(); - } + }; - if let Some(tx) = &self.tx { - let _res = tx.blocking_send(launcher::Request::Search(String::new())); - } else { - tracing::info!("NOT FOUND"); + if self.surface_state == SurfaceState::Hidden { + self.surface_state = SurfaceState::WaitingToBeShown; } - if self.active_surface { - if self.launcher_items.is_empty() { - return cosmic::task::message(cosmic::app::message::app(Message::Hide)); + + match cmd { + LauncherTasks::AltTab => { + if self.alt_tab { + return self.update(Message::AltTab); + } + + self.alt_tab = true; + self.request(launcher::Request::Search(String::new())); + self.queue.push_back(Message::AltTab); } - return cosmic::task::message(cosmic::app::message::app(Message::AltTab)); - } + LauncherTasks::ShiftAltTab => { + if self.alt_tab { + return self.update(Message::ShiftAltTab); + } - self.input_value = action; - self.active_surface = true; - self.wait_for_result = true; - return cosmic::task::message(cosmic::app::message::app(Message::AltTab)); + self.alt_tab = true; + self.request(launcher::Request::Search(String::new())); + self.queue.push_back(Message::ShiftAltTab); + } + } } DbusActivationDetails::Open { .. } => {} } @@ -857,6 +874,7 @@ impl cosmic::Application for CosmicLauncher { }) => Some(Message::AltRelease), cosmic::iced::Event::Keyboard(iced::keyboard::Event::KeyPressed { key, + text: _, modifiers, .. }) => match key { diff --git a/src/main.rs b/src/main.rs index a68380e..2d961ba 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,13 +11,7 @@ use localize::localize; use crate::config::VERSION; fn main() -> cosmic::iced::Result { - // Initialize logger - #[cfg(feature = "console")] - if std::env::var("TOKIO_CONSOLE").as_deref() == Ok("1") { - std::env::set_var("RUST_LOG", "trace"); - console_subscriber::init(); - } - pretty_env_logger::init(); + init_logging(); info!( "cosmic-launcher ({})", @@ -30,3 +24,34 @@ fn main() -> cosmic::iced::Result { app::run() } + +fn init_logging() { + use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; + + // Initialize logger + #[cfg(feature = "console")] + if std::env::var("TOKIO_CONSOLE").as_deref() == Ok("1") { + std::env::set_var("RUST_LOG", "trace"); + console_subscriber::init(); + } + + let filter_layer = EnvFilter::try_from_default_env().unwrap_or(if cfg!(debug_assertions) { + EnvFilter::new(format!("warn,{}=debug", env!("CARGO_CRATE_NAME"))) + } else { + EnvFilter::new("warn") + }); + + let fmt_layer = fmt::layer().with_target(false); + + if let Ok(journal_layer) = tracing_journald::layer() { + tracing_subscriber::registry() + .with(journal_layer) + .with(filter_layer) + .init(); + } else { + tracing_subscriber::registry() + .with(fmt_layer) + .with(filter_layer) + .init(); + } +} diff --git a/src/subscriptions/launcher.rs b/src/subscriptions/launcher.rs index dc03747..99c19a7 100644 --- a/src/subscriptions/launcher.rs +++ b/src/subscriptions/launcher.rs @@ -15,12 +15,14 @@ pub enum Request { Complete(u32), ActivateContext(u32, u32), Close, + ServiceIsClosed, } #[derive(Debug, Clone)] pub enum Event { Started(mpsc::Sender), Response(pop_launcher::Response), + ServiceIsClosed, } pub fn subscription( @@ -41,13 +43,13 @@ pub fn subscription( } /// Initializes pop-launcher if it is not running, and returns a handle to its client. -async fn client_request<'a>( +fn client_request<'a>( tx: &mpsc::Sender, client: &'a mut Option<(IpcClient, oneshot::Sender<()>)>, ) -> &'a mut Option<(IpcClient, oneshot::Sender<()>)> { if client.is_none() { *client = match pop_launcher_service::IpcClient::new() { - Ok((mut new_client, responses)) => { + Ok((new_client, responses)) => { let tx = tx.clone(); let (kill_tx, kill_rx) = tokio::sync::oneshot::channel(); @@ -56,8 +58,9 @@ async fn client_request<'a>( let listener = Box::pin(async move { let mut responses = std::pin::pin!(responses); while let Some(response) = responses.next().await { - let _res = tx.send(Event::Response(response)).await; + _ = tx.send(Event::Response(response)).await; } + _ = tx.send(Event::ServiceIsClosed).await; }); let killswitch = Box::pin(async move { @@ -75,10 +78,6 @@ async fn client_request<'a>( #[cfg(not(feature = "console"))] let _res = tokio::task::spawn(listener); - let _res = new_client - .send(pop_launcher::Request::Search(String::new())) - .await; - Some((new_client, kill_tx)) } Err(why) => { @@ -103,40 +102,40 @@ pub fn service() -> impl Stream + MaybeSend { while let Some(request) = requests_rx.recv().await { match request { Request::Search(s) => { - if let Some((client, _)) = client_request(&responses_tx, client).await { + if let Some((client, _)) = client_request(&responses_tx, client) { let _res = client.send(pop_launcher::Request::Search(s)).await; } } Request::Activate(i) => { - if let Some((client, _)) = client_request(&responses_tx, client).await { + if let Some((client, _)) = client_request(&responses_tx, client) { let _res = client.send(pop_launcher::Request::Activate(i)).await; } } Request::Context(i) => { - if let Some((client, _)) = client_request(&responses_tx, client).await { + if let Some((client, _)) = client_request(&responses_tx, client) { let _res = client.send(pop_launcher::Request::Context(i)).await; } } Request::ActivateContext(id, context) => { - if let Some((client, _)) = client_request(&responses_tx, client).await { + if let Some((client, _)) = client_request(&responses_tx, client) { let _res = client .send(pop_launcher::Request::ActivateContext { id, context }) .await; } } Request::Close => { - if let Some((mut client, kill)) = client.take() { - tracing::info!("closing pop-launcher instance"); - let _res = kill.send(()); - let _res = client.child.kill().await; - let _res = client.child.wait().await; + if let Some((client, _)) = client_request(&responses_tx, client) { + let _res = client.send(pop_launcher::Request::Close).await; } } Request::Complete(id) => { - if let Some((client, _)) = client_request(&responses_tx, client).await { + if let Some((client, _)) = client_request(&responses_tx, client) { let _res = client.send(pop_launcher::Request::Complete(id)).await; } } + Request::ServiceIsClosed => { + *client = None; + } } } };