From 170e102275bd36814202bbb2fac53d53bcc66074 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Tue, 23 Apr 2024 11:54:05 -0700 Subject: [PATCH] Use `Cmd` instead of sending more wayland objects to frontend This isn't needed now that the workspaces view is persistent (before, it was necessary to make sure activation requests are flushed before closing). This is easier to spoof, for testing. --- src/main.rs | 81 ++++++++++++++++------------------------------ src/wayland/mod.rs | 53 +++++++++++++++++++++--------- 2 files changed, 65 insertions(+), 69 deletions(-) diff --git a/src/main.rs b/src/main.rs index 58642db..6391ce5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,14 +6,13 @@ use cctk::{ cosmic_protocols::{ toplevel_info::v1::client::zcosmic_toplevel_handle_v1, - toplevel_management::v1::client::zcosmic_toplevel_manager_v1, - workspace::v1::client::{zcosmic_workspace_handle_v1, zcosmic_workspace_manager_v1}, + workspace::v1::client::zcosmic_workspace_handle_v1, }, sctk::shell::wlr_layer::{Anchor, KeyboardInteractivity, Layer}, toplevel_info::ToplevelInfo, wayland_client::{ backend::ObjectId, - protocol::{wl_data_device_manager::DndAction, wl_output, wl_seat}, + protocol::{wl_data_device_manager::DndAction, wl_output}, Connection, Proxy, WEnum, }, }; @@ -202,9 +201,6 @@ struct App { workspaces: Vec, toplevels: Vec, conn: Option, - workspace_manager: Option, - toplevel_manager: Option, - seats: Vec, visible: bool, wayland_cmd_sender: Option>, drag_surface: Option<(SurfaceId, DragSurface, Size)>, @@ -315,22 +311,26 @@ impl App { ) } - fn update_capture_filter(&self) { + fn send_wayland_cmd(&self, cmd: wayland::Cmd) { if let Some(sender) = self.wayland_cmd_sender.as_ref() { - let mut capture_filter = wayland::CaptureFilter::default(); - if self.visible { - capture_filter.workspaces_on_outputs = - self.outputs.iter().map(|x| x.handle.clone()).collect(); - capture_filter.toplevels_on_workspaces = self - .workspaces - .iter() - .filter(|x| x.is_active) - .map(|x| x.handle.clone()) - .collect(); - } - let _ = sender.send(wayland::Cmd::CaptureFilter(capture_filter)); + sender.send(cmd).unwrap(); } } + + fn update_capture_filter(&self) { + let mut capture_filter = wayland::CaptureFilter::default(); + if self.visible { + capture_filter.workspaces_on_outputs = + self.outputs.iter().map(|x| x.handle.clone()).collect(); + capture_filter.toplevels_on_workspaces = self + .workspaces + .iter() + .filter(|x| x.is_active) + .map(|x| x.handle.clone()) + .collect(); + } + self.send_wayland_cmd(wayland::Cmd::CaptureFilter(capture_filter)); + } } impl Application for App { @@ -416,12 +416,6 @@ impl Application for App { wayland::Event::CmdSender(sender) => { self.wayland_cmd_sender = Some(sender); } - wayland::Event::ToplevelManager(manager) => { - self.toplevel_manager = Some(manager); - } - wayland::Event::WorkspaceManager(manager) => { - self.workspace_manager = Some(manager); - } wayland::Event::Workspaces(workspaces) => { let old_workspaces = mem::take(&mut self.workspaces); self.workspaces = Vec::new(); @@ -480,30 +474,17 @@ impl Application for App { toplevel.img = Some(image); } } - wayland::Event::Seats(seats) => { - self.seats = seats; - } } } Msg::Close => { return self.hide(); } Msg::ActivateWorkspace(workspace_handle) => { - let workspace_manager = self.workspace_manager.as_ref().unwrap(); - workspace_handle.activate(); - workspace_manager.commit(); - let _ = self.conn.as_ref().unwrap().flush(); + self.send_wayland_cmd(wayland::Cmd::ActivateWorkspace(workspace_handle)); } Msg::ActivateToplevel(toplevel_handle) => { - if let Some(toplevel_manager) = self.toplevel_manager.as_ref() { - if !self.seats.is_empty() { - for seat in &self.seats { - toplevel_manager.activate(&toplevel_handle, seat); - } - let _ = self.conn.as_ref().unwrap().flush(); - return self.hide(); - } - } + self.send_wayland_cmd(wayland::Cmd::ActivateToplevel(toplevel_handle)); + return self.hide(); } Msg::CloseWorkspace(_workspace_handle) => { // XXX close specific workspace @@ -521,9 +502,7 @@ impl Application for App { } Msg::CloseToplevel(toplevel_handle) => { // TODO confirmation? - if let Some(toplevel_manager) = self.toplevel_manager.as_ref() { - toplevel_manager.close(&toplevel_handle); - } + self.send_wayland_cmd(wayland::Cmd::CloseToplevel(toplevel_handle)); } Msg::StartDrag(size, drag_surface) => { let (wl_id, output, mime_type) = match &drag_surface { @@ -580,15 +559,11 @@ impl Application for App { .and_then(|s| u32::from_str(s).ok()); if let Some((_, DragSurface::Toplevel { handle, .. }, _)) = &self.drag_surface { if let Some(drop_target) = &self.drop_target { - if let Some(toplevel_manager) = self.toplevel_manager.as_ref() { - if toplevel_manager.version() >= 2 { - toplevel_manager.move_to_workspace( - handle, - &drop_target.0, - &drop_target.1, - ); - } - } + self.send_wayland_cmd(wayland::Cmd::MoveToplevelToWorkspace( + handle.clone(), + drop_target.0.clone(), + drop_target.1.clone(), + )); } } } diff --git a/src/wayland/mod.rs b/src/wayland/mod.rs index a7a8b0a..e996d8c 100644 --- a/src/wayland/mod.rs +++ b/src/wayland/mod.rs @@ -5,8 +5,7 @@ use calloop_wayland_source::WaylandSource; use cctk::{ cosmic_protocols::{ toplevel_info::v1::client::zcosmic_toplevel_handle_v1, - toplevel_management::v1::client::zcosmic_toplevel_manager_v1, - workspace::v1::client::{zcosmic_workspace_handle_v1, zcosmic_workspace_manager_v1}, + workspace::v1::client::zcosmic_workspace_handle_v1, }, screencopy::ScreencopyState, sctk::{ @@ -21,7 +20,7 @@ use cctk::{ wayland_client::{ globals::registry_queue_init, protocol::{wl_output, wl_seat}, - Connection, QueueHandle, + Connection, Proxy, QueueHandle, }, workspace::WorkspaceState, }; @@ -58,8 +57,6 @@ pub use capture::CaptureFilter; #[derive(Clone, Debug)] pub enum Event { CmdSender(calloop::channel::Sender), - ToplevelManager(zcosmic_toplevel_manager_v1::ZcosmicToplevelManagerV1), - WorkspaceManager(zcosmic_workspace_manager_v1::ZcosmicWorkspaceManagerV1), Workspaces(Vec<(HashSet, cctk::workspace::Workspace)>), WorkspaceCapture( zcosmic_workspace_handle_v1::ZcosmicWorkspaceHandleV1, @@ -79,7 +76,6 @@ pub enum Event { zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1, CaptureImage, ), - Seats(Vec), } #[derive(Clone, Debug)] @@ -98,6 +94,14 @@ pub fn subscription(conn: Connection) -> iced::Subscription { #[derive(Debug)] pub enum Cmd { CaptureFilter(CaptureFilter), + ActivateToplevel(zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1), + CloseToplevel(zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1), + MoveToplevelToWorkspace( + zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1, + zcosmic_workspace_handle_v1::ZcosmicWorkspaceHandleV1, + wl_output::WlOutput, + ), + ActivateWorkspace(zcosmic_workspace_handle_v1::ZcosmicWorkspaceHandleV1), } pub struct AppData { @@ -131,6 +135,33 @@ impl AppData { self.capture_filter = filter; self.invalidate_capture_filter(); } + Cmd::ActivateToplevel(toplevel_handle) => { + if !self.seats.is_empty() { + for seat in &self.seats { + self.toplevel_manager_state + .manager + .activate(&toplevel_handle, seat); + } + } + } + Cmd::CloseToplevel(toplevel_handle) => { + self.toplevel_manager_state.manager.close(&toplevel_handle); + } + Cmd::MoveToplevelToWorkspace(toplevel_handle, workspace_handle, output) => { + if self.toplevel_manager_state.manager.version() >= 2 { + self.toplevel_manager_state.manager.move_to_workspace( + &toplevel_handle, + &workspace_handle, + &output, + ); + } + } + Cmd::ActivateWorkspace(workspace_handle) => { + if let Ok(workspace_manager) = self.workspace_state.workspace_manager().get() { + workspace_handle.activate(); + workspace_manager.commit(); + } + } } } @@ -197,14 +228,12 @@ impl SeatHandler for AppData { fn new_seat(&mut self, _: &Connection, _: &QueueHandle, seat: wl_seat::WlSeat) { self.seats.push(seat); - self.send_event(Event::Seats(self.seats.clone())); } fn remove_seat(&mut self, _: &Connection, _: &QueueHandle, seat: wl_seat::WlSeat) { if let Some(idx) = self.seats.iter().position(|i| i == &seat) { self.seats.remove(idx); } - self.send_event(Event::Seats(self.seats.clone())); } fn new_capability( @@ -263,14 +292,6 @@ fn start(conn: Connection) -> mpsc::Receiver { scheduler, }; - app_data.send_event(Event::Seats(app_data.seat_state.seats().collect())); - app_data.send_event(Event::ToplevelManager( - app_data.toplevel_manager_state.manager.clone(), - )); - if let Ok(manager) = app_data.workspace_state.workspace_manager().get() { - app_data.send_event(Event::WorkspaceManager(manager.clone())); - } - let (cmd_sender, cmd_channel) = calloop::channel::channel(); app_data.send_event(Event::CmdSender(cmd_sender));