diff --git a/cosmic-applet-minimize/src/lib.rs b/cosmic-applet-minimize/src/lib.rs index f2c9e715..0098b330 100644 --- a/cosmic-applet-minimize/src/lib.rs +++ b/cosmic-applet-minimize/src/lib.rs @@ -147,7 +147,10 @@ impl cosmic::Application for Minimize { self.apps.push((handle, info, data, None)); } } - ToplevelUpdate::Remove(handle) => self.apps.retain(|a| a.0 != handle), + ToplevelUpdate::Remove(handle) => { + self.apps.retain(|a| a.0 != handle); + self.apps.shrink_to_fit(); + } }, WaylandUpdate::Image(handle, img) => { if let Some(pos) = self.apps.iter().position(|a| a.0 == handle) { diff --git a/cosmic-applet-minimize/src/wayland_handler.rs b/cosmic-applet-minimize/src/wayland_handler.rs index 52b5a438..d1b39f0d 100644 --- a/cosmic-applet-minimize/src/wayland_handler.rs +++ b/cosmic-applet-minimize/src/wayland_handler.rs @@ -54,7 +54,7 @@ use cosmic_protocols::{ toplevel_info::v1::client::zcosmic_toplevel_handle_v1, toplevel_management::v1::client::zcosmic_toplevel_manager_v1, }; -use futures::channel::mpsc::UnboundedSender; +use futures::{channel::mpsc, SinkExt}; use sctk::registry::{ProvidesRegistryState, RegistryState}; use wayland_client::{globals::registry_queue_init, Connection, QueueHandle}; @@ -115,7 +115,7 @@ impl ScreencopyFrameDataExt for FrameData { struct AppData { exit: bool, - tx: UnboundedSender, + tx: mpsc::Sender, queue_handle: QueueHandle, conn: Connection, screencopy_state: ScreencopyState, @@ -301,7 +301,7 @@ impl ToplevelManagerHandler for AppData { } impl AppData { fn send_image(&self, handle: ZcosmicToplevelHandleV1) { - let tx = self.tx.clone(); + let mut tx = self.tx.clone(); let capure_data = CaptureData { qh: self.queue_handle.clone(), conn: self.conn.clone(), @@ -325,7 +325,7 @@ impl AppData { // XXX is this going to use to much memory? let img = capure_data.capture_source_shm_fd(false, handle.clone(), fd, None); if let Some(img) = img { - let Ok(img) = img.image() else { + let Ok(mut img) = img.image() else { tracing::error!("Failed to get RgbaImage"); return; }; @@ -334,23 +334,21 @@ impl AppData { let max = img.width().max(img.height()); let ratio = max as f32 / 128.0; - let img = if ratio > 1.0 { + if ratio > 1.0 { let new_width = (img.width() as f32 / ratio).round(); let new_height = (img.height() as f32 / ratio).round(); - image::imageops::resize( + img = image::imageops::resize( &img, new_width as u32, new_height as u32, - image::imageops::FilterType::Lanczos3, - ) - } else { - img - }; + image::imageops::FilterType::Nearest, + ); + } - if let Err(err) = - tx.unbounded_send(WaylandUpdate::Image(handle, WaylandImage::new(img))) - { + if let Err(err) = futures::executor::block_on( + tx.send(WaylandUpdate::Image(handle, WaylandImage::new(img))), + ) { tracing::error!("Failed to send image event to subscription {err:?}"); }; } else { @@ -378,18 +376,13 @@ impl ToplevelInfoHandler for AppData { { // spawn thread for sending the image self.send_image(toplevel.clone()); - let _ = self - .tx - .unbounded_send(WaylandUpdate::Toplevel(ToplevelUpdate::Add( - toplevel.clone(), - info.clone(), - ))); + let _ = futures::executor::block_on(self.tx.send(WaylandUpdate::Toplevel( + ToplevelUpdate::Add(toplevel.clone(), info.clone()), + ))); } else { - let _ = self - .tx - .unbounded_send(WaylandUpdate::Toplevel(ToplevelUpdate::Remove( - toplevel.clone(), - ))); + let _ = futures::executor::block_on(self.tx.send(WaylandUpdate::Toplevel( + ToplevelUpdate::Remove(toplevel.clone()), + ))); } } } @@ -406,18 +399,13 @@ impl ToplevelInfoHandler for AppData { .contains(&zcosmic_toplevel_handle_v1::State::Minimized) { self.send_image(toplevel.clone()); - let _ = self - .tx - .unbounded_send(WaylandUpdate::Toplevel(ToplevelUpdate::Update( - toplevel.clone(), - info.clone(), - ))); + let _ = futures::executor::block_on(self.tx.send(WaylandUpdate::Toplevel( + ToplevelUpdate::Update(toplevel.clone(), info.clone()), + ))); } else { - let _ = self - .tx - .unbounded_send(WaylandUpdate::Toplevel(ToplevelUpdate::Remove( - toplevel.clone(), - ))); + let _ = futures::executor::block_on(self.tx.send(WaylandUpdate::Toplevel( + ToplevelUpdate::Remove(toplevel.clone()), + ))); } } } @@ -428,16 +416,14 @@ impl ToplevelInfoHandler for AppData { _qh: &QueueHandle, toplevel: &zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1, ) { - let _ = self - .tx - .unbounded_send(WaylandUpdate::Toplevel(ToplevelUpdate::Remove( - toplevel.clone(), - ))); + let _ = futures::executor::block_on(self.tx.send(WaylandUpdate::Toplevel( + ToplevelUpdate::Remove(toplevel.clone()), + ))); } } pub(crate) fn wayland_handler( - tx: UnboundedSender, + tx: mpsc::Sender, rx: calloop::channel::Channel, ) { let socket = std::env::var("X_PRIVILEGED_WAYLAND_SOCKET") diff --git a/cosmic-applet-minimize/src/wayland_subscription.rs b/cosmic-applet-minimize/src/wayland_subscription.rs index 08445914..b832f9d1 100644 --- a/cosmic-applet-minimize/src/wayland_subscription.rs +++ b/cosmic-applet-minimize/src/wayland_subscription.rs @@ -13,73 +13,33 @@ use cosmic::{ iced_futures::{futures, stream}, }; use cosmic_protocols::toplevel_info::v1::client::zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1; -use futures::{ - channel::mpsc::{unbounded, UnboundedReceiver}, - SinkExt, StreamExt, -}; +use futures::SinkExt; use image::EncodableLayout; -use once_cell::sync::Lazy; use std::fmt::Debug; -use tokio::sync::Mutex; use crate::wayland_handler::wayland_handler; -pub static WAYLAND_RX: Lazy>>> = - Lazy::new(|| Mutex::new(None)); - pub fn wayland_subscription() -> iced::Subscription { Subscription::run_with_id( std::any::TypeId::of::(), - stream::channel(50, move |mut output| async move { - let mut state = State::Waiting; + stream::channel(1, move |mut output| async move { + let (calloop_tx, calloop_rx) = calloop::channel::channel(); + let runtime = tokio::runtime::Handle::current(); - loop { - state = start_listening(state, &mut output).await; - } + let _ = std::thread::spawn(move || { + runtime.block_on(async move { + _ = output.send(WaylandUpdate::Init(calloop_tx)).await; + wayland_handler(output.clone(), calloop_rx); + tracing::error!("Wayland handler thread died"); + _ = output.send(WaylandUpdate::Finished).await; + }); + }); + + futures::future::pending().await }), ) } -pub enum State { - Waiting, - Finished, -} - -async fn start_listening( - state: State, - output: &mut futures::channel::mpsc::Sender, -) -> State { - match state { - State::Waiting => { - let mut guard = WAYLAND_RX.lock().await; - let rx = { - if guard.is_none() { - let (calloop_tx, calloop_rx) = calloop::channel::channel(); - let (toplevel_tx, toplevel_rx) = unbounded(); - let _ = std::thread::spawn(move || { - wayland_handler(toplevel_tx, calloop_rx); - }); - *guard = Some(toplevel_rx); - _ = output.send(WaylandUpdate::Init(calloop_tx)).await; - } - guard.as_mut().unwrap() - }; - match rx.next().await { - Some(u) => { - _ = output.send(u).await; - State::Waiting - } - None => { - _ = output.send(WaylandUpdate::Finished).await; - tracing::error!("Wayland handler thread died"); - State::Finished - } - } - } - State::Finished => iced::futures::future::pending().await, - } -} - #[derive(Clone, Debug)] pub enum WaylandUpdate { Init(calloop::channel::Sender),