diff --git a/Cargo.lock b/Cargo.lock index 2daad40..8f8e807 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1134,8 +1134,9 @@ dependencies = [ [[package]] name = "cosmic-client-toolkit" version = "0.1.0" -source = "git+https://github.com/pop-os/cosmic-protocols?rev=178eb0b#178eb0b14a0e5c192f64f6dee6c40341a8e5ee51" +source = "git+https://github.com/pop-os/cosmic-protocols//?branch=main#6b05c2a157118979cb472a38455ba78ca9729196" dependencies = [ + "bitflags 2.8.0", "cosmic-protocols", "libc", "smithay-client-toolkit", @@ -1197,7 +1198,7 @@ dependencies = [ [[package]] name = "cosmic-protocols" version = "0.1.0" -source = "git+https://github.com/pop-os/cosmic-protocols?rev=178eb0b#178eb0b14a0e5c192f64f6dee6c40341a8e5ee51" +source = "git+https://github.com/pop-os/cosmic-protocols//?branch=main#6b05c2a157118979cb472a38455ba78ca9729196" dependencies = [ "bitflags 2.8.0", "wayland-backend", @@ -5863,7 +5864,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.48.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 3894a69..1ef45fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,3 +44,7 @@ mock-backend = [] [profile.dev] # Not usable at opt-level 0, at least with software renderer opt-level = 1 + +[patch."https://github.com/pop-os/cosmic-protocols"] +cosmic-protocols = { git = "https://github.com/pop-os/cosmic-protocols//", branch = "main" } +cosmic-client-toolkit = { git = "https://github.com/pop-os/cosmic-protocols//", branch = "main" } diff --git a/src/backend/mock.rs b/src/backend/mock.rs index 5ee2c7c..38a6ba1 100644 --- a/src/backend/mock.rs +++ b/src/backend/mock.rs @@ -3,14 +3,12 @@ use cosmic::{ cctk::{ - cosmic_protocols::{ - toplevel_info::v1::client::zcosmic_toplevel_handle_v1, - workspace::v1::client::zcosmic_workspace_handle_v1, - }, + cosmic_protocols::toplevel_info::v1::client::zcosmic_toplevel_handle_v1, wayland_client::{ protocol::{wl_output, wl_shm}, Connection, WEnum, }, + wayland_protocols::ext::workspace::v1::client::ext_workspace_handle_v1, }, iced::{ self, @@ -80,9 +78,9 @@ impl MockObjectId { } #[derive(Eq, PartialEq, Clone, Debug, Hash)] -pub struct ZcosmicWorkspaceHandleV1(MockObjectId); +pub struct ExtWorkspaceHandleV1(MockObjectId); -impl ZcosmicWorkspaceHandleV1 { +impl ExtWorkspaceHandleV1 { pub fn id(&self) -> MockObjectId { self.0.clone() } @@ -91,27 +89,21 @@ impl ZcosmicWorkspaceHandleV1 { #[derive(Eq, PartialEq, Clone, Debug, Hash)] pub struct ExtForeignToplevelHandleV1(MockObjectId); -#[derive(Clone, Debug, Default)] -pub struct CaptureFilter { - pub workspaces_on_outputs: Vec, - pub toplevels_on_workspaces: Vec, -} - #[derive(Clone, Debug, Default)] pub struct ToplevelInfo { pub title: String, pub app_id: String, pub state: HashSet, pub output: HashSet, - pub workspace: HashSet, + pub workspace: HashSet, } #[derive(Clone, Debug)] pub struct Workspace { - pub handle: ZcosmicWorkspaceHandleV1, + pub handle: ExtWorkspaceHandleV1, pub name: String, // pub coordinates: Vec, - pub state: Vec>, + pub state: ext_workspace_handle_v1::State, // pub capabilities: Vec>, // pub tiling: Option>, } @@ -135,14 +127,14 @@ impl AppData { // Add four workspaces for each output let mut new_workspaces = Vec::new(); for i in 0..=4 { - let workspace_handle = ZcosmicWorkspaceHandleV1(MockObjectId::new()); + let workspace_handle = ExtWorkspaceHandleV1(MockObjectId::new()); let workspace = Workspace { handle: workspace_handle.clone(), name: format!("Workspace {i}"), state: if i == 0 { - vec![WEnum::Value(zcosmic_workspace_handle_v1::State::Active)] + ext_workspace_handle_v1::State::Active } else { - Vec::new() + ext_workspace_handle_v1::State::empty() }, }; // Add three toplevels for each workspace diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 15e86c9..8dfd012 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -17,12 +17,12 @@ use std::collections::HashSet; #[cfg(not(feature = "mock-backend"))] mod wayland; #[cfg(not(feature = "mock-backend"))] -pub use cosmic::cctk::{ - cosmic_protocols::workspace::v1::client::zcosmic_workspace_handle_v1::ZcosmicWorkspaceHandleV1, - toplevel_info::ToplevelInfo, workspace::Workspace, -}; +pub use cosmic::cctk::{toplevel_info::ToplevelInfo, workspace::Workspace}; #[cfg(not(feature = "mock-backend"))] -pub use wayland_protocols::ext::foreign_toplevel_list::v1::client::ext_foreign_toplevel_handle_v1::ExtForeignToplevelHandleV1; +pub use wayland_protocols::ext::{ + foreign_toplevel_list::v1::client::ext_foreign_toplevel_handle_v1::ExtForeignToplevelHandleV1, + workspace::v1::client::ext_workspace_handle_v1::ExtWorkspaceHandleV1, +}; #[cfg(not(feature = "mock-backend"))] pub use wayland::subscription; @@ -32,13 +32,13 @@ pub use wayland::subscription; mod mock; #[cfg(feature = "mock-backend")] pub use mock::{ - subscription, ExtForeignToplevelHandleV1, ToplevelInfo, Workspace, ZcosmicWorkspaceHandleV1, + subscription, ExtForeignToplevelHandleV1, ExtWorkspaceHandleV1, ToplevelInfo, Workspace, }; #[derive(Clone, Debug, Default)] pub struct CaptureFilter { pub workspaces_on_outputs: Vec, - pub toplevels_on_workspaces: Vec, + pub toplevels_on_workspaces: Vec, } #[derive(Clone, Debug)] @@ -57,7 +57,7 @@ pub struct CaptureImage { pub enum Event { CmdSender(calloop::channel::Sender), Workspaces(Vec<(HashSet, Workspace)>), - WorkspaceCapture(ZcosmicWorkspaceHandleV1, CaptureImage), + WorkspaceCapture(ExtWorkspaceHandleV1, CaptureImage), NewToplevel(ExtForeignToplevelHandleV1, ToplevelInfo), UpdateToplevel(ExtForeignToplevelHandleV1, ToplevelInfo), CloseToplevel(ExtForeignToplevelHandleV1), @@ -71,8 +71,8 @@ pub enum Cmd { CloseToplevel(ExtForeignToplevelHandleV1), MoveToplevelToWorkspace( ExtForeignToplevelHandleV1, - ZcosmicWorkspaceHandleV1, + ExtWorkspaceHandleV1, wl_output::WlOutput, ), - ActivateWorkspace(ZcosmicWorkspaceHandleV1), + ActivateWorkspace(ExtWorkspaceHandleV1), } diff --git a/src/backend/wayland/mod.rs b/src/backend/wayland/mod.rs index 365c4c1..1b2957d 100644 --- a/src/backend/wayland/mod.rs +++ b/src/backend/wayland/mod.rs @@ -94,7 +94,7 @@ impl AppData { let info = self.toplevel_info_state.info(&toplevel_handle); if let Some(cosmic_toplevel) = info.and_then(|x| x.cosmic_toplevel.as_ref()) { if self.toplevel_manager_state.manager.version() >= 2 { - self.toplevel_manager_state.manager.move_to_workspace( + self.toplevel_manager_state.manager.move_to_ext_workspace( &cosmic_toplevel, &workspace_handle, &output, @@ -113,11 +113,11 @@ impl AppData { fn matches_capture_filter(&self, source: &CaptureSource) -> bool { match source { - CaptureSource::CosmicToplevel(toplevel) => { + CaptureSource::Toplevel(toplevel) => { let info = self .toplevel_info_state .toplevels() - .find(|info| info.cosmic_toplevel.as_ref() == Some(&toplevel)); + .find(|info| info.foreign_toplevel == *toplevel); if let Some(info) = info { info.workspace.iter().any(|workspace| { self.capture_filter @@ -128,18 +128,16 @@ impl AppData { false } } - CaptureSource::CosmicWorkspace(workspace) => self + CaptureSource::Workspace(workspace) => self .workspace_state .workspace_groups() - .iter() - .find(|g| g.workspaces.iter().any(|w| w.handle == *workspace)) + .find(|g| g.workspaces.iter().any(|w| w == workspace)) .map_or(false, |group| { self.capture_filter .workspaces_on_outputs .iter() .any(|o| group.outputs.contains(o)) }), - CaptureSource::Toplevel(_) => false, CaptureSource::Output(_) => false, } } diff --git a/src/backend/wayland/screencopy.rs b/src/backend/wayland/screencopy.rs index 805c129..6c39523 100644 --- a/src/backend/wayland/screencopy.rs +++ b/src/backend/wayland/screencopy.rs @@ -192,19 +192,19 @@ impl ScreencopyHandler for AppData { ), }; match &capture.source { - CaptureSource::CosmicToplevel(toplevel) => { + CaptureSource::Toplevel(toplevel) => { let info = self .toplevel_info_state .toplevels() - .find(|info| info.cosmic_toplevel.as_ref() == Some(&toplevel)); + .find(|info| info.foreign_toplevel == *toplevel); if let Some(info) = info { self.send_event(Event::ToplevelCapture(info.foreign_toplevel.clone(), image)) } } - CaptureSource::CosmicWorkspace(workspace) => { + CaptureSource::Workspace(workspace) => { self.send_event(Event::WorkspaceCapture(workspace.clone(), image)); } - CaptureSource::Output(_) | CaptureSource::Toplevel(_) => { + CaptureSource::Output(_) => { unreachable!() } }; diff --git a/src/backend/wayland/toplevel.rs b/src/backend/wayland/toplevel.rs index 046bee0..800a76c 100644 --- a/src/backend/wayland/toplevel.rs +++ b/src/backend/wayland/toplevel.rs @@ -22,10 +22,9 @@ impl ToplevelInfoHandler for AppData { toplevel: &ExtForeignToplevelHandleV1, ) { let info = self.toplevel_info_state.info(toplevel).unwrap(); - let cosmic_toplevel = info.cosmic_toplevel.clone().unwrap(); self.send_event(Event::NewToplevel(toplevel.clone(), info.clone())); - self.add_capture_source(CaptureSource::CosmicToplevel(cosmic_toplevel)); + self.add_capture_source(CaptureSource::Toplevel(toplevel.clone())); } fn update_toplevel( @@ -44,11 +43,9 @@ impl ToplevelInfoHandler for AppData { _qh: &QueueHandle, toplevel: &ExtForeignToplevelHandleV1, ) { - let info = self.toplevel_info_state.info(toplevel).unwrap(); - let cosmic_toplevel = info.cosmic_toplevel.clone().unwrap(); self.send_event(Event::CloseToplevel(toplevel.clone())); - self.remove_capture_source(CaptureSource::CosmicToplevel(cosmic_toplevel)); + self.remove_capture_source(CaptureSource::Toplevel(toplevel.clone())); } } diff --git a/src/backend/wayland/workspace.rs b/src/backend/wayland/workspace.rs index cb334e3..8a0a7fc 100644 --- a/src/backend/wayland/workspace.rs +++ b/src/backend/wayland/workspace.rs @@ -15,11 +15,13 @@ impl WorkspaceHandler for AppData { // Handle move to another output for group in self.workspace_state.workspace_groups() { - for workspace in &group.workspaces { - workspaces.push((group.outputs.iter().cloned().collect(), workspace.clone())); + for workspace_handle in &group.workspaces { + if let Some(workspace) = self.workspace_state.workspace_info(workspace_handle) { + workspaces.push((group.outputs.iter().cloned().collect(), workspace.clone())); - // TODO one capture per output on workspace? - self.add_capture_source(CaptureSource::CosmicWorkspace(workspace.handle.clone())); + // TODO one capture per output on workspace? + self.add_capture_source(CaptureSource::Workspace(workspace_handle.clone())); + } } } diff --git a/src/dnd.rs b/src/dnd.rs index 2e55788..d1ff402 100644 --- a/src/dnd.rs +++ b/src/dnd.rs @@ -6,7 +6,7 @@ use cosmic::{ }; use std::{borrow::Cow, sync::LazyLock}; -use crate::backend::{ExtForeignToplevelHandleV1, ZcosmicWorkspaceHandleV1}; +use crate::backend::{ExtForeignToplevelHandleV1, ExtWorkspaceHandleV1}; // Include `pid` in mime. Want to drag between our surfaces, but not another // process, if we use Wayland object ids. @@ -19,7 +19,7 @@ static TOPLEVEL_MIME: LazyLock = #[derive(Clone, Debug)] pub enum DragSurface { #[allow(dead_code)] - Workspace(ZcosmicWorkspaceHandleV1), + Workspace(ExtWorkspaceHandleV1), Toplevel(ExtForeignToplevelHandleV1), } @@ -95,8 +95,8 @@ impl TryFrom<(Vec, std::string::String)> for DragWorkspace { #[derive(Clone, Debug, PartialEq)] #[repr(u8)] pub enum DropTarget { - WorkspaceSidebarEntry(ZcosmicWorkspaceHandleV1, wl_output::WlOutput), - OutputToplevels(ZcosmicWorkspaceHandleV1, wl_output::WlOutput), + WorkspaceSidebarEntry(ExtWorkspaceHandleV1, wl_output::WlOutput), + OutputToplevels(ExtWorkspaceHandleV1, wl_output::WlOutput), #[allow(dead_code)] WorkspacesBar(wl_output::WlOutput), } diff --git a/src/main.rs b/src/main.rs index bad9de5..497448a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,9 +4,9 @@ #![allow(clippy::single_match)] use cctk::{ - cosmic_protocols::workspace::v1::client::zcosmic_workspace_handle_v1, sctk::shell::wlr_layer::{Anchor, KeyboardInteractivity, Layer}, - wayland_client::{protocol::wl_output, Connection, Proxy, WEnum}, + wayland_client::{protocol::wl_output, Connection, Proxy}, + wayland_protocols::ext::workspace::v1::client::ext_workspace_handle_v1, }; use clap::Parser; use cosmic::{ @@ -43,7 +43,7 @@ mod desktop_info; mod localize; mod backend; mod view; -use backend::{ExtForeignToplevelHandleV1, ToplevelInfo, ZcosmicWorkspaceHandleV1}; +use backend::{ExtForeignToplevelHandleV1, ExtWorkspaceHandleV1, ToplevelInfo}; mod dnd; mod utils; mod widgets; @@ -89,9 +89,9 @@ enum Msg { WaylandEvent(WaylandEvent), Wayland(backend::Event), Close, - ActivateWorkspace(ZcosmicWorkspaceHandleV1), + ActivateWorkspace(ExtWorkspaceHandleV1), #[allow(dead_code)] - CloseWorkspace(ZcosmicWorkspaceHandleV1), + CloseWorkspace(ExtWorkspaceHandleV1), ActivateToplevel(ExtForeignToplevelHandleV1), CloseToplevel(ExtForeignToplevelHandleV1), StartDrag(DragSurface), @@ -118,7 +118,7 @@ struct Workspace { name: String, // img_for_output: HashMap, img: Option, - handle: ZcosmicWorkspaceHandleV1, + handle: ExtWorkspaceHandleV1, outputs: HashSet, is_active: bool, } @@ -170,13 +170,13 @@ struct App { } impl App { - fn workspace_for_handle(&self, handle: &ZcosmicWorkspaceHandleV1) -> Option<&Workspace> { + fn workspace_for_handle(&self, handle: &ExtWorkspaceHandleV1) -> Option<&Workspace> { self.workspaces.iter().find(|i| &i.handle == handle) } fn workspace_for_handle_mut( &mut self, - handle: &ZcosmicWorkspaceHandleV1, + handle: &ExtWorkspaceHandleV1, ) -> Option<&mut Workspace> { self.workspaces.iter_mut().find(|i| &i.handle == handle) } @@ -377,13 +377,14 @@ impl Application for App { backend::Event::CmdSender(sender) => { self.wayland_cmd_sender = Some(sender); } - backend::Event::Workspaces(workspaces) => { + backend::Event::Workspaces(mut workspaces) => { + workspaces.sort_by(|(_, w1), (_, w2)| w1.coordinates.cmp(&w2.coordinates)); let old_workspaces = mem::take(&mut self.workspaces); self.workspaces = Vec::new(); for (outputs, workspace) in workspaces { - let is_active = workspace.state.contains(&WEnum::Value( - zcosmic_workspace_handle_v1::State::Active, - )); + let is_active = workspace + .state + .contains(ext_workspace_handle_v1::State::Active); // XXX efficiency #[allow(clippy::mutable_key_type)] diff --git a/src/view/mod.rs b/src/view/mod.rs index df800e6..6aefc4f 100644 --- a/src/view/mod.rs +++ b/src/view/mod.rs @@ -236,7 +236,7 @@ fn workspaces_sidebar<'a>( workspaces: impl Iterator, output: &'a wl_output::WlOutput, layout: WorkspaceLayout, - drop_target: Option<&backend::ZcosmicWorkspaceHandleV1>, + drop_target: Option<&backend::ExtWorkspaceHandleV1>, ) -> cosmic::Element<'a, Msg> { let sidebar_entries = workspaces .map(|w| workspace_sidebar_entry(w, output, drop_target == Some(&w.handle)))