From e9848a2d4f4e012a953e9d5d37b7f8ed1d201fed Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Wed, 12 Feb 2025 10:42:32 -0800 Subject: [PATCH] Update for toplevel-info cctk changes Requires pop-os/cosmic-protocols#49. The duplication between applets, and cosmic-workspace/xdg-desktop-portal-cosmic, should be moved to shared abstractions. But that can be done after moving to `ext-image-copy-capture`. `ToplevelInfo` now contains both ext and cosmic handles, so the tuples of handles and info are needed. Use just the info. --- Cargo.lock | 34 ++--- Cargo.toml | 4 +- cosmic-app-list/src/app.rs | 86 ++++++----- cosmic-app-list/src/wayland_handler.rs | 52 ++++--- cosmic-app-list/src/wayland_subscription.rs | 22 ++- cosmic-applet-minimize/src/lib.rs | 133 +++++++++--------- cosmic-applet-minimize/src/wayland_handler.rs | 37 +++-- .../src/wayland_subscription.rs | 16 ++- cosmic-applet-tiling/src/wayland.rs | 12 +- 9 files changed, 218 insertions(+), 178 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 911b7f1e..e12daed0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1382,7 +1382,7 @@ dependencies = [ [[package]] name = "cosmic-client-toolkit" version = "0.1.0" -source = "git+https://github.com/pop-os/cosmic-protocols?rev=29ab323#29ab32305c6457fccf0728caaaf79fcac4cca665" +source = "git+https://github.com/pop-os/cosmic-protocols?rev=178eb0b#178eb0b14a0e5c192f64f6dee6c40341a8e5ee51" dependencies = [ "cosmic-protocols", "libc", @@ -1404,7 +1404,7 @@ dependencies = [ [[package]] name = "cosmic-config" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#f59eb77252d1730319d532fc0a0c50ce860edd9d" +source = "git+https://github.com/pop-os/libcosmic#0b7e23444afb3f351cd947c52babb6b87f30381d" dependencies = [ "atomicwrites", "cosmic-config-derive", @@ -1426,7 +1426,7 @@ dependencies = [ [[package]] name = "cosmic-config-derive" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#f59eb77252d1730319d532fc0a0c50ce860edd9d" +source = "git+https://github.com/pop-os/libcosmic#0b7e23444afb3f351cd947c52babb6b87f30381d" dependencies = [ "quote", "syn 1.0.109", @@ -1521,7 +1521,7 @@ dependencies = [ [[package]] name = "cosmic-protocols" version = "0.1.0" -source = "git+https://github.com/pop-os/cosmic-protocols?rev=29ab323#29ab32305c6457fccf0728caaaf79fcac4cca665" +source = "git+https://github.com/pop-os/cosmic-protocols?rev=178eb0b#178eb0b14a0e5c192f64f6dee6c40341a8e5ee51" dependencies = [ "bitflags 2.8.0", "wayland-backend", @@ -1586,7 +1586,7 @@ dependencies = [ [[package]] name = "cosmic-theme" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#f59eb77252d1730319d532fc0a0c50ce860edd9d" +source = "git+https://github.com/pop-os/libcosmic#0b7e23444afb3f351cd947c52babb6b87f30381d" dependencies = [ "almost", "cosmic-config", @@ -2961,7 +2961,7 @@ dependencies = [ [[package]] name = "iced" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#f59eb77252d1730319d532fc0a0c50ce860edd9d" +source = "git+https://github.com/pop-os/libcosmic#0b7e23444afb3f351cd947c52babb6b87f30381d" dependencies = [ "dnd", "iced_accessibility", @@ -2979,7 +2979,7 @@ dependencies = [ [[package]] name = "iced_accessibility" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#f59eb77252d1730319d532fc0a0c50ce860edd9d" +source = "git+https://github.com/pop-os/libcosmic#0b7e23444afb3f351cd947c52babb6b87f30381d" dependencies = [ "accesskit", "accesskit_winit", @@ -2988,7 +2988,7 @@ dependencies = [ [[package]] name = "iced_core" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#f59eb77252d1730319d532fc0a0c50ce860edd9d" +source = "git+https://github.com/pop-os/libcosmic#0b7e23444afb3f351cd947c52babb6b87f30381d" dependencies = [ "bitflags 2.8.0", "bytes", @@ -3012,7 +3012,7 @@ dependencies = [ [[package]] name = "iced_futures" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#f59eb77252d1730319d532fc0a0c50ce860edd9d" +source = "git+https://github.com/pop-os/libcosmic#0b7e23444afb3f351cd947c52babb6b87f30381d" dependencies = [ "futures", "iced_core", @@ -3038,7 +3038,7 @@ dependencies = [ [[package]] name = "iced_graphics" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#f59eb77252d1730319d532fc0a0c50ce860edd9d" +source = "git+https://github.com/pop-os/libcosmic#0b7e23444afb3f351cd947c52babb6b87f30381d" dependencies = [ "bitflags 2.8.0", "bytemuck", @@ -3060,7 +3060,7 @@ dependencies = [ [[package]] name = "iced_renderer" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#f59eb77252d1730319d532fc0a0c50ce860edd9d" +source = "git+https://github.com/pop-os/libcosmic#0b7e23444afb3f351cd947c52babb6b87f30381d" dependencies = [ "iced_graphics", "iced_tiny_skia", @@ -3072,7 +3072,7 @@ dependencies = [ [[package]] name = "iced_runtime" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#f59eb77252d1730319d532fc0a0c50ce860edd9d" +source = "git+https://github.com/pop-os/libcosmic#0b7e23444afb3f351cd947c52babb6b87f30381d" dependencies = [ "bytes", "cosmic-client-toolkit", @@ -3087,7 +3087,7 @@ dependencies = [ [[package]] name = "iced_tiny_skia" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#f59eb77252d1730319d532fc0a0c50ce860edd9d" +source = "git+https://github.com/pop-os/libcosmic#0b7e23444afb3f351cd947c52babb6b87f30381d" dependencies = [ "bytemuck", "cosmic-text", @@ -3103,7 +3103,7 @@ dependencies = [ [[package]] name = "iced_wgpu" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#f59eb77252d1730319d532fc0a0c50ce860edd9d" +source = "git+https://github.com/pop-os/libcosmic#0b7e23444afb3f351cd947c52babb6b87f30381d" dependencies = [ "as-raw-xcb-connection", "bitflags 2.8.0", @@ -3134,7 +3134,7 @@ dependencies = [ [[package]] name = "iced_widget" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#f59eb77252d1730319d532fc0a0c50ce860edd9d" +source = "git+https://github.com/pop-os/libcosmic#0b7e23444afb3f351cd947c52babb6b87f30381d" dependencies = [ "cosmic-client-toolkit", "dnd", @@ -3152,7 +3152,7 @@ dependencies = [ [[package]] name = "iced_winit" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#f59eb77252d1730319d532fc0a0c50ce860edd9d" +source = "git+https://github.com/pop-os/libcosmic#0b7e23444afb3f351cd947c52babb6b87f30381d" dependencies = [ "cosmic-client-toolkit", "dnd", @@ -3877,7 +3877,7 @@ checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libcosmic" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#f59eb77252d1730319d532fc0a0c50ce860edd9d" +source = "git+https://github.com/pop-os/libcosmic#0b7e23444afb3f351cd947c52babb6b87f30381d" dependencies = [ "apply", "ashpd 0.9.2", diff --git a/Cargo.toml b/Cargo.toml index 0aee85d3..eed56ac3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,10 +24,10 @@ resolver = "2" [workspace.dependencies] anyhow = "1.0.81" -cctk = { git = "https://github.com/pop-os/cosmic-protocols", package = "cosmic-client-toolkit", rev = "29ab323" } +cctk = { git = "https://github.com/pop-os/cosmic-protocols", package = "cosmic-client-toolkit", rev = "178eb0b" } cosmic-protocols = { git = "https://github.com/pop-os/cosmic-protocols", default-features = false, features = [ "client", -], rev = "29ab323" } +], rev = "178eb0b" } cosmic-settings-subscriptions = { git = "https://github.com/pop-os/cosmic-settings-subscriptions" } # cosmic-settings-subscriptions = { path = "../cosmic-settings-subscriptions" } diff --git a/cosmic-app-list/src/app.rs b/cosmic-app-list/src/app.rs index 3c14da6c..06b7c01b 100755 --- a/cosmic-app-list/src/app.rs +++ b/cosmic-app-list/src/app.rs @@ -14,6 +14,7 @@ use cctk::{ wayland_client::protocol::{ wl_data_device_manager::DndAction, wl_output::WlOutput, wl_seat::WlSeat, }, + wayland_protocols::ext::foreign_toplevel_list::v1::client::ext_foreign_toplevel_handle_v1::ExtForeignToplevelHandleV1, }; use cosmic::{ applet::{ @@ -44,7 +45,7 @@ use cosmic::{ }; use cosmic_app_list_config::{AppListConfig, APP_ID}; use cosmic_protocols::{ - toplevel_info::v1::client::zcosmic_toplevel_handle_v1::{State, ZcosmicToplevelHandleV1}, + toplevel_info::v1::client::zcosmic_toplevel_handle_v1::State, workspace::v1::client::zcosmic_workspace_handle_v1::ZcosmicWorkspaceHandleV1, }; use freedesktop_desktop_entry as fde; @@ -127,7 +128,7 @@ struct DockItem { // ID used internally in the applet. Each dock item // have an unique id id: u32, - toplevels: Vec<(ZcosmicToplevelHandleV1, ToplevelInfo, Option)>, + toplevels: Vec<(ToplevelInfo, Option)>, // Information found in the .desktop file desktop_info: DesktopEntry, // We must use this because the id in `DesktopEntry` is an estimation. @@ -248,7 +249,9 @@ impl DockItem { .on_press_maybe(if toplevels.is_empty() { launch_on_preferred_gpu(desktop_info, gpus) } else if toplevels.len() == 1 { - toplevels.first().map(|t| Message::Toggle(t.0.clone())) + toplevels + .first() + .map(|t| Message::Toggle(t.0.foreign_toplevel.clone())) } else { Some(Message::TopLevelListPopup((*id).into(), window_id)) }) @@ -348,8 +351,8 @@ enum Message { GpuRequest(Option>), CloseRequested(window::Id), ClosePopup, - Activate(ZcosmicToplevelHandleV1), - Toggle(ZcosmicToplevelHandleV1), + Activate(ExtForeignToplevelHandleV1), + Toggle(ExtForeignToplevelHandleV1), Exec(String, Option), Quit(String), NewSeat(WlSeat), @@ -721,9 +724,10 @@ impl cosmic::Application for CosmicAppList { .chain(self.pinned_list.iter()) .find(|t| t.id == id) { - for (ref handle, _, _) in &toplevel_group.toplevels { + for (info, _) in &toplevel_group.toplevels { if let Some(tx) = self.wayland_sender.as_ref() { - let _ = tx.send(WaylandRequest::Screencopy(handle.clone())); + let _ = + tx.send(WaylandRequest::Screencopy(info.foreign_toplevel.clone())); } } @@ -844,10 +848,10 @@ impl cosmic::Application for CosmicAppList { .chain(self.pinned_list.iter()) .find(|t| t.desktop_info.id() == id) { - for (handle, _, _) in &toplevel_group.toplevels { + for (info, _) in &toplevel_group.toplevels { if let Some(tx) = self.wayland_sender.as_ref() { let _ = tx.send(WaylandRequest::Toplevel(ToplevelRequest::Quit( - handle.clone(), + info.foreign_toplevel.clone(), ))); } } @@ -1016,10 +1020,10 @@ impl cosmic::Application for CosmicAppList { .iter_mut() .chain(self.pinned_list.iter_mut()) { - if let Some((_, _, ref mut handle_img)) = x + if let Some((_, ref mut handle_img)) = x .toplevels .iter_mut() - .find(|(toplevel_handle, _, _)| toplevel_handle.clone() == handle) + .find(|(info, _)| info.foreign_toplevel == handle) { *handle_img = Some(img); break 'img_update; @@ -1050,7 +1054,7 @@ impl cosmic::Application for CosmicAppList { .map(cosmic::app::message::app); } WaylandUpdate::Toplevel(event) => match event { - ToplevelUpdate::Add(handle, mut info) => { + ToplevelUpdate::Add(mut info) => { let new_desktop_info = load_desktop_entries_from_app_ids(&[&info.app_id], &self.locales) .remove(0); @@ -1063,7 +1067,7 @@ impl cosmic::Application for CosmicAppList { desktop_info.id() == new_desktop_info.id() }) { - t.toplevels.push((handle, info, None)); + t.toplevels.push((info, None)); } else { if info.app_id.is_empty() { info.app_id = format!("Unknown Application {}", self.item_ctr); @@ -1073,7 +1077,7 @@ impl cosmic::Application for CosmicAppList { self.active_list.push(DockItem { id: self.item_ctr, original_app_id: info.app_id.clone(), - toplevels: vec![(handle, info, None)], + toplevels: vec![(info, None)], desktop_info: new_desktop_info, }); } @@ -1084,11 +1088,12 @@ impl cosmic::Application for CosmicAppList { .iter_mut() .chain(self.pinned_list.iter_mut()) { - t.toplevels.retain(|(t_handle, _, _)| t_handle != &handle); + t.toplevels + .retain(|(info, _)| info.foreign_toplevel != handle); } self.active_list.retain(|t| !t.toplevels.is_empty()); } - ToplevelUpdate::Update(handle, info) => { + ToplevelUpdate::Update(info) => { // TODO probably want to make sure it is removed if info.app_id.is_empty() { return Task::none(); @@ -1098,8 +1103,8 @@ impl cosmic::Application for CosmicAppList { .iter_mut() .chain(self.pinned_list.iter_mut()) { - for (t_handle, t_info, _) in &mut toplevel_list.toplevels { - if &handle == t_handle { + for (t_info, _) in &mut toplevel_list.toplevels { + if info.foreign_toplevel == t_info.foreign_toplevel { *t_info = info; break 'toplevel_loop; } @@ -1404,7 +1409,7 @@ impl cosmic::Application for CosmicAppList { dock_item .toplevels .iter() - .any(|y| focused_item.contains(&y.0)), + .any(|y| focused_item.contains(&y.0.foreign_toplevel)), theme.cosmic().radius_xs(), self.core.main_window_id().unwrap(), ) @@ -1447,7 +1452,9 @@ impl cosmic::Application for CosmicAppList { false, self.config.enable_drag_source, self.gpus.as_deref(), - item.toplevels.iter().any(|y| focused_item.contains(&y.0)), + item.toplevels + .iter() + .any(|y| focused_item.contains(&y.0.foreign_toplevel)), dot_radius, self.core.main_window_id().unwrap(), ), @@ -1484,7 +1491,7 @@ impl cosmic::Application for CosmicAppList { dock_item .toplevels .iter() - .any(|y| focused_item.contains(&y.0)), + .any(|y| focused_item.contains(&y.0.foreign_toplevel)), dot_radius, self.core.main_window_id().unwrap(), ) @@ -1724,16 +1731,17 @@ impl cosmic::Application for CosmicAppList { if !toplevels.is_empty() { let mut list_col = column![]; - for (handle, info, _) in toplevels { + for (info, _) in toplevels { let title = if info.title.len() > 34 { format!("{:.32}...", &info.title) } else { info.title.clone() }; - list_col = list_col.push( - menu_button(text::body(title)) - .on_press(Message::Activate(handle.clone())), - ); + list_col = + list_col + .push(menu_button(text::body(title)).on_press( + Message::Activate(info.foreign_toplevel.clone()), + )); } content = content.push(list_col); content = content.push(divider::horizontal::light()); @@ -1814,7 +1822,7 @@ impl cosmic::Application for CosmicAppList { PanelAnchor::Left | PanelAnchor::Right => { let mut content = column![].padding(8).align_x(Alignment::Center).spacing(8); - for (handle, info, img) in toplevels { + for (info, img) in toplevels { let title = if info.title.len() > 18 { format!("{:.16}...", &info.title) } else { @@ -1822,9 +1830,10 @@ impl cosmic::Application for CosmicAppList { }; content = content.push(toplevel_button( img.clone(), - Message::Toggle(handle.clone()), + Message::Toggle(info.foreign_toplevel.clone()), title, - self.currently_active_toplevel().contains(handle), + self.currently_active_toplevel() + .contains(&info.foreign_toplevel), )); } self.core @@ -1835,7 +1844,7 @@ impl cosmic::Application for CosmicAppList { } PanelAnchor::Bottom | PanelAnchor::Top => { let mut content = row![].padding(8).align_y(Alignment::Center).spacing(8); - for (handle, info, img) in toplevels { + for (info, img) in toplevels { let title = if info.title.len() > 18 { format!("{:.16}...", &info.title) } else { @@ -1843,9 +1852,10 @@ impl cosmic::Application for CosmicAppList { }; content = content.push(toplevel_button( img.clone(), - Message::Toggle(handle.clone()), + Message::Toggle(info.foreign_toplevel.clone()), title, - self.currently_active_toplevel().contains(handle), + self.currently_active_toplevel() + .contains(&info.foreign_toplevel), )); } self.core @@ -1886,7 +1896,7 @@ impl cosmic::Application for CosmicAppList { dock_item .toplevels .iter() - .any(|y| focused_item.contains(&y.0)), + .any(|y| focused_item.contains(&y.0.foreign_toplevel)), dot_radius, id, ) @@ -1973,7 +1983,7 @@ impl cosmic::Application for CosmicAppList { dock_item .toplevels .iter() - .any(|y| focused_item.contains(&y.0)), + .any(|y| focused_item.contains(&y.0.foreign_toplevel)), dot_radius, id, ) @@ -2129,15 +2139,15 @@ impl CosmicAppList { return (Some(favorite_index), active_index); } - fn currently_active_toplevel(&self) -> Vec { + fn currently_active_toplevel(&self) -> Vec { if self.active_workspaces.is_empty() { return Vec::new(); } let current_output = self.core.applet.output_name.clone(); - let mut focused_toplevels: Vec = Vec::new(); + let mut focused_toplevels: Vec = Vec::new(); let active_workspaces = self.active_workspaces.clone(); for toplevel_list in self.active_list.iter().chain(self.pinned_list.iter()) { - for (t_handle, t_info, _) in &toplevel_list.toplevels { + for (t_info, _) in &toplevel_list.toplevels { if t_info.state.contains(&State::Activated) && active_workspaces .iter() @@ -2148,7 +2158,7 @@ impl CosmicAppList { }) }) { - focused_toplevels.push(t_handle.clone()); + focused_toplevels.push(t_info.foreign_toplevel.clone()); } } } diff --git a/cosmic-app-list/src/wayland_handler.rs b/cosmic-app-list/src/wayland_handler.rs index 9c5069bf..54b55f18 100644 --- a/cosmic-app-list/src/wayland_handler.rs +++ b/cosmic-app-list/src/wayland_handler.rs @@ -39,10 +39,11 @@ use cctk::{ }, Connection, Dispatch, QueueHandle, WEnum, }, + wayland_protocols::ext::foreign_toplevel_list::v1::client::ext_foreign_toplevel_handle_v1::ExtForeignToplevelHandleV1, workspace::{WorkspaceHandler, WorkspaceState}, }; use cosmic_protocols::{ - toplevel_info::v1::client::zcosmic_toplevel_handle_v1::{self, ZcosmicToplevelHandleV1}, + toplevel_info::v1::client::zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1, toplevel_management::v1::client::zcosmic_toplevel_manager_v1, workspace::v1::client::zcosmic_workspace_handle_v1::State as WorkspaceUpdateState, }; @@ -235,15 +236,12 @@ impl ToplevelInfoHandler for AppData { &mut self, _conn: &Connection, _qh: &QueueHandle, - toplevel: &zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1, + toplevel: &ExtForeignToplevelHandleV1, ) { if let Some(info) = self.toplevel_info_state.info(toplevel) { let _ = self .tx - .unbounded_send(WaylandUpdate::Toplevel(ToplevelUpdate::Add( - toplevel.clone(), - info.clone(), - ))); + .unbounded_send(WaylandUpdate::Toplevel(ToplevelUpdate::Add(info.clone()))); } } @@ -251,13 +249,12 @@ impl ToplevelInfoHandler for AppData { &mut self, _conn: &Connection, _qh: &QueueHandle, - toplevel: &zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1, + toplevel: &ExtForeignToplevelHandleV1, ) { if let Some(info) = self.toplevel_info_state.info(toplevel) { let _ = self .tx .unbounded_send(WaylandUpdate::Toplevel(ToplevelUpdate::Update( - toplevel.clone(), info.clone(), ))); } @@ -267,7 +264,7 @@ impl ToplevelInfoHandler for AppData { &mut self, _conn: &Connection, _qh: &QueueHandle, - toplevel: &zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1, + toplevel: &ExtForeignToplevelHandleV1, ) { let _ = self .tx @@ -479,7 +476,17 @@ impl ShmImage { } impl AppData { - fn send_image(&self, handle: ZcosmicToplevelHandleV1) { + fn cosmic_toplevel( + &self, + handle: &ExtForeignToplevelHandleV1, + ) -> Option { + self.toplevel_info_state + .info(&handle)? + .cosmic_toplevel + .clone() + } + + fn send_image(&self, handle: ExtForeignToplevelHandleV1) { let tx = self.tx.clone(); let capture_data = CaptureData { qh: self.queue_handle.clone(), @@ -487,6 +494,9 @@ impl AppData { wl_shm: self.shm_state.wl_shm().clone(), capturer: self.screencopy_state.capturer().clone(), }; + let Some(cosmic_toplevel) = self.cosmic_toplevel(&handle) else { + return; + }; std::thread::spawn(move || { use std::ffi::CStr; let name = unsafe { CStr::from_bytes_with_nul_unchecked(b"app-list-screencopy\0") }; @@ -496,7 +506,7 @@ impl AppData { }; // XXX is this going to use to much memory? - let img = capture_data.capture_source_shm_fd(false, handle.clone(), fd, None); + let img = capture_data.capture_source_shm_fd(false, cosmic_toplevel, fd, None); if let Some(img) = img { let Ok(img) = img.image() else { tracing::error!("Failed to get RgbaImage"); @@ -621,18 +631,24 @@ pub(crate) fn wayland_handler( } WaylandRequest::Toplevel(req) => match req { ToplevelRequest::Activate(handle) => { - if let Some(seat) = state.seat_state.seats().next() { - let manager = &state.toplevel_manager_state.manager; - manager.activate(&handle, &seat); + if let Some(cosmic_toplevel) = state.cosmic_toplevel(&handle) { + if let Some(seat) = state.seat_state.seats().next() { + let manager = &state.toplevel_manager_state.manager; + manager.activate(&cosmic_toplevel, &seat); + } } } ToplevelRequest::Minimize(handle) => { - let manager = &state.toplevel_manager_state.manager; - manager.set_minimized(&handle); + if let Some(cosmic_toplevel) = state.cosmic_toplevel(&handle) { + let manager = &state.toplevel_manager_state.manager; + manager.set_minimized(&cosmic_toplevel); + } } ToplevelRequest::Quit(handle) => { - let manager = &state.toplevel_manager_state.manager; - manager.close(&handle); + if let Some(cosmic_toplevel) = state.cosmic_toplevel(&handle) { + let manager = &state.toplevel_manager_state.manager; + manager.close(&cosmic_toplevel); + } } }, WaylandRequest::TokenRequest { diff --git a/cosmic-app-list/src/wayland_subscription.rs b/cosmic-app-list/src/wayland_subscription.rs index 10ff5f52..967c91e2 100644 --- a/cosmic-app-list/src/wayland_subscription.rs +++ b/cosmic-app-list/src/wayland_subscription.rs @@ -6,15 +6,13 @@ use cctk::{ sctk::{output::OutputInfo, reexports::calloop}, toplevel_info::ToplevelInfo, wayland_client::protocol::wl_output::WlOutput, + wayland_protocols::ext::foreign_toplevel_list::v1::client::ext_foreign_toplevel_handle_v1::ExtForeignToplevelHandleV1, }; use cosmic::{ iced::{self, stream, Subscription}, iced_core::image::Bytes, }; -use cosmic_protocols::{ - toplevel_info::v1::client::zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1, - workspace::v1::client::zcosmic_workspace_handle_v1::ZcosmicWorkspaceHandleV1, -}; +use cosmic_protocols::workspace::v1::client::zcosmic_workspace_handle_v1::ZcosmicWorkspaceHandleV1; use image::EncodableLayout; use futures::{ @@ -120,14 +118,14 @@ pub enum WaylandUpdate { exec: String, gpu_idx: Option, }, - Image(ZcosmicToplevelHandleV1, WaylandImage), + Image(ExtForeignToplevelHandleV1, WaylandImage), } #[derive(Clone, Debug)] pub enum ToplevelUpdate { - Add(ZcosmicToplevelHandleV1, ToplevelInfo), - Update(ZcosmicToplevelHandleV1, ToplevelInfo), - Remove(ZcosmicToplevelHandleV1), + Add(ToplevelInfo), + Update(ToplevelInfo), + Remove(ExtForeignToplevelHandleV1), } #[derive(Clone, Debug)] @@ -145,12 +143,12 @@ pub enum WaylandRequest { exec: String, gpu_idx: Option, }, - Screencopy(ZcosmicToplevelHandleV1), + Screencopy(ExtForeignToplevelHandleV1), } #[derive(Debug, Clone)] pub enum ToplevelRequest { - Activate(ZcosmicToplevelHandleV1), - Minimize(ZcosmicToplevelHandleV1), - Quit(ZcosmicToplevelHandleV1), + Activate(ExtForeignToplevelHandleV1), + Minimize(ExtForeignToplevelHandleV1), + Quit(ExtForeignToplevelHandleV1), } diff --git a/cosmic-applet-minimize/src/lib.rs b/cosmic-applet-minimize/src/lib.rs index 0098b330..75a695de 100644 --- a/cosmic-applet-minimize/src/lib.rs +++ b/cosmic-applet-minimize/src/lib.rs @@ -11,8 +11,8 @@ use cosmic::{ app, applet::cosmic_panel_config::PanelAnchor, cctk::{ - cosmic_protocols::toplevel_info::v1::client::zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1, sctk::reexports::calloop, toplevel_info::ToplevelInfo, + wayland_protocols::ext::foreign_toplevel_list::v1::client::ext_foreign_toplevel_handle_v1::ExtForeignToplevelHandleV1, }, desktop::DesktopEntryData, iced::{ @@ -45,12 +45,7 @@ pub fn run() -> cosmic::iced::Result { #[derive(Default)] struct Minimize { core: cosmic::app::Core, - apps: Vec<( - ZcosmicToplevelHandleV1, - ToplevelInfo, - DesktopEntryData, - Option, - )>, + apps: Vec<(ToplevelInfo, DesktopEntryData, Option)>, tx: Option>, overflow_popup: Option, } @@ -83,7 +78,7 @@ impl Minimize { #[derive(Debug, Clone)] enum Message { Wayland(WaylandUpdate), - Activate(ZcosmicToplevelHandleV1), + Activate(ExtForeignToplevelHandleV1), Closed(window::Id), OpenOverflowPopup, CloseOverflowPopup, @@ -127,7 +122,7 @@ impl cosmic::Application for Minimize { panic!("Wayland Subscription ended...") } WaylandUpdate::Toplevel(t) => match t { - ToplevelUpdate::Add(handle, info) | ToplevelUpdate::Update(handle, info) => { + ToplevelUpdate::Add(info) | ToplevelUpdate::Update(info) => { let data = |id| { cosmic::desktop::load_applications_for_app_ids( None, @@ -137,24 +132,32 @@ impl cosmic::Application for Minimize { ) .remove(0) }; - if let Some(pos) = self.apps.iter_mut().position(|a| a.0 == handle) { - if self.apps[pos].1.app_id != info.app_id { - self.apps[pos].2 = data(&info.app_id) + if let Some(pos) = self + .apps + .iter_mut() + .position(|a| a.0.foreign_toplevel == info.foreign_toplevel) + { + if self.apps[pos].0.app_id != info.app_id { + self.apps[pos].1 = data(&info.app_id) } - self.apps[pos].1 = info; + self.apps[pos].0 = info; } else { let data = data(&info.app_id); - self.apps.push((handle, info, data, None)); + self.apps.push((info, data, None)); } } ToplevelUpdate::Remove(handle) => { - self.apps.retain(|a| a.0 != handle); + self.apps.retain(|a| a.0.foreign_toplevel != handle); self.apps.shrink_to_fit(); } }, WaylandUpdate::Image(handle, img) => { - if let Some(pos) = self.apps.iter().position(|a| a.0 == handle) { - self.apps[pos].3 = Some(img); + if let Some(pos) = self + .apps + .iter() + .position(|a| a.0.foreign_toplevel == handle) + { + self.apps[pos].2 = Some(img); } } }, @@ -230,31 +233,29 @@ impl cosmic::Application for Minimize { let padding = self.core.applet.suggested_padding(false); let theme = self.core.system_theme().cosmic(); let space_xxs = theme.space_xxs(); - let icon_buttons = self.apps[..max_icon_count] - .iter() - .map(|(handle, _, data, img)| { - tooltip( - Element::from(crate::window_image::WindowImage::new( - img.clone(), - &data.icon, - width as f32, - Message::Activate(handle.clone()), - padding, - )), - text(data.name.clone()).shaping(text::Shaping::Advanced), - // tooltip::Position::FollowCursor, - // FIXME tooltip fails to appear when created as indicated in design - // maybe it should be a subsurface - match self.core.applet.anchor { - PanelAnchor::Left => tooltip::Position::Right, - PanelAnchor::Right => tooltip::Position::Left, - PanelAnchor::Top => tooltip::Position::Bottom, - PanelAnchor::Bottom => tooltip::Position::Top, - }, - ) - .snap_within_viewport(false) - .into() - }); + let icon_buttons = self.apps[..max_icon_count].iter().map(|(info, data, img)| { + tooltip( + Element::from(crate::window_image::WindowImage::new( + img.clone(), + &data.icon, + width as f32, + Message::Activate(info.foreign_toplevel.clone()), + padding, + )), + text(data.name.clone()).shaping(text::Shaping::Advanced), + // tooltip::Position::FollowCursor, + // FIXME tooltip fails to appear when created as indicated in design + // maybe it should be a subsurface + match self.core.applet.anchor { + PanelAnchor::Left => tooltip::Position::Right, + PanelAnchor::Right => tooltip::Position::Left, + PanelAnchor::Top => tooltip::Position::Bottom, + PanelAnchor::Bottom => tooltip::Position::Top, + }, + ) + .snap_within_viewport(false) + .into() + }); let overflow_btn = if max_icon_count < self.apps.len() { let icon = match self.core.applet.anchor { PanelAnchor::Bottom => "go-up-symbolic", @@ -335,31 +336,29 @@ impl cosmic::Application for Minimize { let padding = self.core.applet.suggested_padding(false); let theme = self.core.system_theme().cosmic(); let space_xxs = theme.space_xxs(); - let icon_buttons = self.apps[max_icon_count..] - .iter() - .map(|(handle, _, data, img)| { - tooltip( - Element::from(crate::window_image::WindowImage::new( - img.clone(), - &data.icon, - width as f32, - Message::Activate(handle.clone()), - padding, - )), - text(data.name.clone()).shaping(text::Shaping::Advanced), - // tooltip::Position::FollowCursor, - // FIXME tooltip fails to appear when created as indicated in design - // maybe it should be a subsurface - match self.core.applet.anchor { - PanelAnchor::Left => tooltip::Position::Right, - PanelAnchor::Right => tooltip::Position::Left, - PanelAnchor::Top => tooltip::Position::Bottom, - PanelAnchor::Bottom => tooltip::Position::Top, - }, - ) - .snap_within_viewport(false) - .into() - }); + let icon_buttons = self.apps[max_icon_count..].iter().map(|(info, data, img)| { + tooltip( + Element::from(crate::window_image::WindowImage::new( + img.clone(), + &data.icon, + width as f32, + Message::Activate(info.foreign_toplevel.clone()), + padding, + )), + text(data.name.clone()).shaping(text::Shaping::Advanced), + // tooltip::Position::FollowCursor, + // FIXME tooltip fails to appear when created as indicated in design + // maybe it should be a subsurface + match self.core.applet.anchor { + PanelAnchor::Left => tooltip::Position::Right, + PanelAnchor::Right => tooltip::Position::Left, + PanelAnchor::Top => tooltip::Position::Bottom, + PanelAnchor::Bottom => tooltip::Position::Top, + }, + ) + .snap_within_viewport(false) + .into() + }); // TODO optional dividers on ends if detects app list neighbor // not sure the best way to tell if there is an adjacent app-list diff --git a/cosmic-applet-minimize/src/wayland_handler.rs b/cosmic-applet-minimize/src/wayland_handler.rs index 6960018c..7084b9e4 100644 --- a/cosmic-applet-minimize/src/wayland_handler.rs +++ b/cosmic-applet-minimize/src/wayland_handler.rs @@ -42,6 +42,7 @@ use cosmic::{ }, Dispatch, }, + wayland_protocols::ext::foreign_toplevel_list::v1::client::ext_foreign_toplevel_handle_v1::ExtForeignToplevelHandleV1, }, iced_futures::futures, }; @@ -291,7 +292,17 @@ impl ToplevelManagerHandler for AppData { } } impl AppData { - fn send_image(&self, handle: ZcosmicToplevelHandleV1) { + fn cosmic_toplevel( + &self, + handle: &ExtForeignToplevelHandleV1, + ) -> Option { + self.toplevel_info_state + .info(&handle)? + .cosmic_toplevel + .clone() + } + + fn send_image(&self, handle: ExtForeignToplevelHandleV1) { let mut tx = self.tx.clone(); let capure_data = CaptureData { qh: self.queue_handle.clone(), @@ -299,6 +310,9 @@ impl AppData { wl_shm: self.shm_state.wl_shm().clone(), capturer: self.screencopy_state.capturer().clone(), }; + let Some(cosmic_toplevel) = self.cosmic_toplevel(&handle) else { + return; + }; std::thread::spawn(move || { use std::ffi::CStr; let name = @@ -309,7 +323,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); + let img = capure_data.capture_source_shm_fd(false, cosmic_toplevel, fd, None); if let Some(img) = img { let Ok(mut img) = img.image() else { tracing::error!("Failed to get RgbaImage"); @@ -353,7 +367,7 @@ impl ToplevelInfoHandler for AppData { &mut self, _conn: &Connection, _qh: &QueueHandle, - toplevel: &zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1, + toplevel: &ExtForeignToplevelHandleV1, ) { if let Some(info) = self.toplevel_info_state.info(toplevel) { if info @@ -362,9 +376,10 @@ impl ToplevelInfoHandler for AppData { { // spawn thread for sending the image self.send_image(toplevel.clone()); - let _ = futures::executor::block_on(self.tx.send(WaylandUpdate::Toplevel( - ToplevelUpdate::Add(toplevel.clone(), info.clone()), - ))); + let _ = futures::executor::block_on( + self.tx + .send(WaylandUpdate::Toplevel(ToplevelUpdate::Add(info.clone()))), + ); } else { let _ = futures::executor::block_on(self.tx.send(WaylandUpdate::Toplevel( ToplevelUpdate::Remove(toplevel.clone()), @@ -377,7 +392,7 @@ impl ToplevelInfoHandler for AppData { &mut self, _conn: &Connection, _qh: &QueueHandle, - toplevel: &zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1, + toplevel: &ExtForeignToplevelHandleV1, ) { if let Some(info) = self.toplevel_info_state.info(toplevel) { if info @@ -386,7 +401,7 @@ impl ToplevelInfoHandler for AppData { { self.send_image(toplevel.clone()); let _ = futures::executor::block_on(self.tx.send(WaylandUpdate::Toplevel( - ToplevelUpdate::Update(toplevel.clone(), info.clone()), + ToplevelUpdate::Update(info.clone()), ))); } else { let _ = futures::executor::block_on(self.tx.send(WaylandUpdate::Toplevel( @@ -400,7 +415,7 @@ impl ToplevelInfoHandler for AppData { &mut self, _conn: &Connection, _qh: &QueueHandle, - toplevel: &zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1, + toplevel: &ExtForeignToplevelHandleV1, ) { let _ = futures::executor::block_on(self.tx.send(WaylandUpdate::Toplevel( ToplevelUpdate::Remove(toplevel.clone()), @@ -442,7 +457,9 @@ pub(crate) fn wayland_handler( ToplevelRequest::Activate(handle) => { if let Some(seat) = state.seat_state.seats().next() { let manager = &state.toplevel_manager_state.manager; - manager.activate(&handle, &seat); + if let Some(cosmic_toplevel) = state.cosmic_toplevel(&handle) { + manager.activate(&cosmic_toplevel, &seat); + } } } }, diff --git a/cosmic-applet-minimize/src/wayland_subscription.rs b/cosmic-applet-minimize/src/wayland_subscription.rs index b832f9d1..becabebf 100644 --- a/cosmic-applet-minimize/src/wayland_subscription.rs +++ b/cosmic-applet-minimize/src/wayland_subscription.rs @@ -7,12 +7,14 @@ //! Source: `Interface '/org/freedesktop/UPower/KbdBacklight' from service 'org.freedesktop.UPower' on system bus`. use cctk::{sctk::reexports::calloop, toplevel_info::ToplevelInfo}; use cosmic::{ - cctk::{self, cosmic_protocols}, + cctk::{ + self, + wayland_protocols::ext::foreign_toplevel_list::v1::client::ext_foreign_toplevel_handle_v1::ExtForeignToplevelHandleV1, + }, iced::{self, Subscription}, iced_core::image::Bytes, iced_futures::{futures, stream}, }; -use cosmic_protocols::toplevel_info::v1::client::zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1; use futures::SinkExt; use image::EncodableLayout; use std::fmt::Debug; @@ -45,7 +47,7 @@ pub enum WaylandUpdate { Init(calloop::channel::Sender), Finished, Toplevel(ToplevelUpdate), - Image(ZcosmicToplevelHandleV1, WaylandImage), + Image(ExtForeignToplevelHandleV1, WaylandImage), } #[derive(Debug, Clone)] @@ -73,9 +75,9 @@ impl AsRef<[u8]> for WaylandImage { #[derive(Clone, Debug)] pub enum ToplevelUpdate { - Add(ZcosmicToplevelHandleV1, ToplevelInfo), - Update(ZcosmicToplevelHandleV1, ToplevelInfo), - Remove(ZcosmicToplevelHandleV1), + Add(ToplevelInfo), + Update(ToplevelInfo), + Remove(ExtForeignToplevelHandleV1), } #[derive(Clone, Debug)] @@ -85,5 +87,5 @@ pub enum WaylandRequest { #[derive(Debug, Clone)] pub enum ToplevelRequest { - Activate(ZcosmicToplevelHandleV1), + Activate(ExtForeignToplevelHandleV1), } diff --git a/cosmic-applet-tiling/src/wayland.rs b/cosmic-applet-tiling/src/wayland.rs index ede80326..316b586f 100644 --- a/cosmic-applet-tiling/src/wayland.rs +++ b/cosmic-applet-tiling/src/wayland.rs @@ -11,13 +11,11 @@ use cctk::{ }, toplevel_info::{ToplevelInfoHandler, ToplevelInfoState}, wayland_client::WEnum, + wayland_protocols::ext::foreign_toplevel_list::v1::client::ext_foreign_toplevel_handle_v1::ExtForeignToplevelHandleV1, workspace::{WorkspaceHandler, WorkspaceState}, }; use cosmic::iced::futures; -use cosmic_protocols::{ - toplevel_info::v1::client::zcosmic_toplevel_handle_v1, - workspace::v1::client::zcosmic_workspace_handle_v1::{self, TilingState}, -}; +use cosmic_protocols::workspace::v1::client::zcosmic_workspace_handle_v1::{self, TilingState}; use futures::{channel::mpsc, executor::block_on, SinkExt}; use std::{ collections::HashSet, @@ -274,7 +272,7 @@ impl ToplevelInfoHandler for State { &mut self, _conn: &Connection, _qh: &QueueHandle, - toplevel: &zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1, + toplevel: &ExtForeignToplevelHandleV1, ) { let Some(w) = self .toplevel_info_state @@ -290,7 +288,7 @@ impl ToplevelInfoHandler for State { &mut self, _conn: &Connection, _qh: &QueueHandle, - toplevel: &zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1, + toplevel: &ExtForeignToplevelHandleV1, ) { let Some(w) = self .toplevel_info_state @@ -306,7 +304,7 @@ impl ToplevelInfoHandler for State { &mut self, _conn: &Connection, _qh: &QueueHandle, - _toplevel: &zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1, + _toplevel: &ExtForeignToplevelHandleV1, ) { } }