From aac816696209fa0120a225fd3df1d20131eae7da Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Wed, 19 Feb 2025 14:07:51 -0800 Subject: [PATCH] Add `cosmic-workspace-v2`, image source, toplevel info changes This new protocol extends `ext-workspace-v1` with the same additional functionality `cosmic-workspace-v1` provided. Toplevel info and toplevel management are also updated to use ext handles, and there's an image source for ext workspaces. For now, the old protocol is still supported. --- src/shell/mod.rs | 2 +- src/shell/workspace.rs | 2 +- src/wayland/handlers/workspace.rs | 2 +- src/wayland/protocols/image_source.rs | 92 ++++++++ src/wayland/protocols/toplevel_info.rs | 10 +- src/wayland/protocols/toplevel_management.rs | 16 +- src/wayland/protocols/workspace/cosmic.rs | 42 +++- src/wayland/protocols/workspace/cosmic_v2.rs | 221 +++++++++++++++++++ src/wayland/protocols/workspace/ext.rs | 9 + src/wayland/protocols/workspace/mod.rs | 87 +++++++- 10 files changed, 459 insertions(+), 24 deletions(-) create mode 100644 src/wayland/protocols/workspace/cosmic_v2.rs diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 01d6e664..443d360d 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -15,7 +15,7 @@ use cosmic_comp_config::{ workspace::{WorkspaceLayout, WorkspaceMode}, TileBehavior, ZoomConfig, ZoomMovement, }; -use cosmic_protocols::workspace::v1::server::zcosmic_workspace_handle_v1::TilingState; +use cosmic_protocols::workspace::v2::server::zcosmic_workspace_handle_v2::TilingState; use cosmic_settings_config::shortcuts::action::{Direction, FocusDirection, ResizeDirection}; use cosmic_settings_config::{shortcuts, window_rules::ApplicationException}; use keyframe::{ease, functions::EaseInOutCubic}; diff --git a/src/shell/workspace.rs b/src/shell/workspace.rs index f386caa5..ffae76d1 100644 --- a/src/shell/workspace.rs +++ b/src/shell/workspace.rs @@ -19,7 +19,7 @@ use crate::{ }; use cosmic::theme::CosmicTheme; -use cosmic_protocols::workspace::v1::server::zcosmic_workspace_handle_v1::TilingState; +use cosmic_protocols::workspace::v2::server::zcosmic_workspace_handle_v2::TilingState; use id_tree::Tree; use indexmap::IndexSet; use keyframe::{ease, functions::EaseInOutCubic}; diff --git a/src/wayland/handlers/workspace.rs b/src/wayland/handlers/workspace.rs index ee231b7e..4231571d 100644 --- a/src/wayland/handlers/workspace.rs +++ b/src/wayland/handlers/workspace.rs @@ -9,7 +9,7 @@ use crate::{ WorkspaceHandler, WorkspaceState, }, }; -use cosmic_protocols::workspace::v1::server::zcosmic_workspace_handle_v1::TilingState; +use cosmic_protocols::workspace::v2::server::zcosmic_workspace_handle_v2::TilingState; use smithay::reexports::wayland_server::DisplayHandle; impl WorkspaceClientHandler for ClientState { diff --git a/src/wayland/protocols/image_source.rs b/src/wayland/protocols/image_source.rs index 1032de82..4835e0e3 100644 --- a/src/wayland/protocols/image_source.rs +++ b/src/wayland/protocols/image_source.rs @@ -4,6 +4,9 @@ use super::{ }; use crate::shell::CosmicSurface; use cosmic_protocols::image_source::v1::server::{ + zcosmic_ext_workspace_image_source_manager_v1::{ + Request as ExtWorkspaceSourceRequest, ZcosmicExtWorkspaceImageSourceManagerV1, + }, zcosmic_image_source_v1::ZcosmicImageSourceV1, zcosmic_output_image_source_manager_v1::{ Request as OutputSourceRequest, ZcosmicOutputImageSourceManagerV1, @@ -27,6 +30,7 @@ use wayland_backend::server::GlobalId; pub struct ImageSourceState { output_source_global: GlobalId, workspace_source_global: GlobalId, + ext_workspace_source_global: GlobalId, toplevel_source_global: GlobalId, } @@ -57,6 +61,10 @@ impl ImageSourceState { ZcosmicWorkspaceImageSourceManagerV1, WorkspaceImageSourceManagerGlobalData, > + Dispatch + + GlobalDispatch< + ZcosmicExtWorkspaceImageSourceManagerV1, + WorkspaceImageSourceManagerGlobalData, + > + Dispatch + GlobalDispatch< ZcosmicToplevelImageSourceManagerV1, ToplevelImageSourceManagerGlobalData, @@ -80,6 +88,13 @@ impl ImageSourceState { filter: Box::new(client_filter.clone()), }, ), + ext_workspace_source_global: display + .create_global::( + 1, + WorkspaceImageSourceManagerGlobalData { + filter: Box::new(client_filter.clone()), + }, + ), toplevel_source_global: display .create_global::( 1, @@ -98,6 +113,10 @@ impl ImageSourceState { &self.workspace_source_global } + pub fn ext_workspace_source_id(&self) -> &GlobalId { + &self.ext_workspace_source_global + } + pub fn toplevel_source_id(&self) -> &GlobalId { &self.toplevel_source_global } @@ -152,6 +171,36 @@ where } } +impl + GlobalDispatch< + ZcosmicExtWorkspaceImageSourceManagerV1, + WorkspaceImageSourceManagerGlobalData, + D, + > for ImageSourceState +where + D: GlobalDispatch< + ZcosmicExtWorkspaceImageSourceManagerV1, + WorkspaceImageSourceManagerGlobalData, + > + Dispatch + + Dispatch + + 'static, +{ + fn bind( + _state: &mut D, + _handle: &DisplayHandle, + _client: &Client, + resource: New, + _global_data: &WorkspaceImageSourceManagerGlobalData, + data_init: &mut DataInit<'_, D>, + ) { + data_init.init(resource, ()); + } + + fn can_view(client: Client, global_data: &WorkspaceImageSourceManagerGlobalData) -> bool { + (global_data.filter)(&client) + } +} + impl GlobalDispatch for ImageSourceState where @@ -249,6 +298,43 @@ where } } +impl Dispatch for ImageSourceState +where + D: Dispatch + + Dispatch + + WorkspaceHandler + + 'static, +{ + fn request( + state: &mut D, + _client: &Client, + _resource: &ZcosmicExtWorkspaceImageSourceManagerV1, + request: ::Request, + _data: &(), + _dhandle: &DisplayHandle, + data_init: &mut DataInit<'_, D>, + ) { + match request { + ExtWorkspaceSourceRequest::CreateSource { source, output } => { + let data = match state.workspace_state().get_ext_workspace_handle(&output) { + Some(workspace) => ImageSourceData::Workspace(workspace), + None => ImageSourceData::Destroyed, + }; + data_init.init(source, data); + } + _ => {} + } + } + + fn destroyed( + _state: &mut D, + _client: wayland_backend::server::ClientId, + _resource: &ZcosmicExtWorkspaceImageSourceManagerV1, + _data: &(), + ) { + } +} + impl Dispatch for ImageSourceState where D: Dispatch @@ -329,6 +415,12 @@ macro_rules! delegate_image_source { smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ cosmic_protocols::image_source::v1::server::zcosmic_workspace_image_source_manager_v1::ZcosmicWorkspaceImageSourceManagerV1: () ] => $crate::wayland::protocols::image_source::ImageSourceState); + smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ + cosmic_protocols::image_source::v1::server::zcosmic_ext_workspace_image_source_manager_v1::ZcosmicExtWorkspaceImageSourceManagerV1: $crate::wayland::protocols::image_source::WorkspaceImageSourceManagerGlobalData + ] => $crate::wayland::protocols::image_source::ImageSourceState); + smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ + cosmic_protocols::image_source::v1::server::zcosmic_ext_workspace_image_source_manager_v1::ZcosmicExtWorkspaceImageSourceManagerV1: () + ] => $crate::wayland::protocols::image_source::ImageSourceState); smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ cosmic_protocols::image_source::v1::server::zcosmic_toplevel_image_source_manager_v1::ZcosmicToplevelImageSourceManagerV1: $crate::wayland::protocols::image_source::ToplevelImageSourceManagerGlobalData ] => $crate::wayland::protocols::image_source::ImageSourceState); diff --git a/src/wayland/protocols/toplevel_info.rs b/src/wayland/protocols/toplevel_info.rs index b9251744..e1013ae0 100644 --- a/src/wayland/protocols/toplevel_info.rs +++ b/src/wayland/protocols/toplevel_info.rs @@ -309,7 +309,7 @@ where F: for<'a> Fn(&'a Client) -> bool + Send + Sync + Clone + 'static, { let global = dh.create_global::( - 2, + 3, ToplevelInfoGlobalData { filter: Box::new(client_filter.clone()), }, @@ -594,6 +594,10 @@ where instance.workspace_enter(&handle); changed = true; } + for handle in workspace_state.raw_ext_workspace_handles(&new_workspace, &instance.id()) { + instance.ext_workspace_enter(&handle); + changed = true; + } } for old_workspace in handle_state .workspaces @@ -604,6 +608,10 @@ where instance.workspace_leave(&handle); changed = true; } + for handle in workspace_state.raw_ext_workspace_handles(&old_workspace, &instance.id()) { + instance.ext_workspace_leave(&handle); + changed = true; + } } handle_state.workspaces = state.workspaces.clone(); diff --git a/src/wayland/protocols/toplevel_management.rs b/src/wayland/protocols/toplevel_management.rs index 0304d12b..80c2cdd4 100644 --- a/src/wayland/protocols/toplevel_management.rs +++ b/src/wayland/protocols/toplevel_management.rs @@ -116,7 +116,7 @@ impl ToplevelManagementState { F: for<'a> Fn(&'a Client) -> bool + Send + Sync + 'static, { let global = dh.create_global::( - 3, + 4, ToplevelManagerGlobalData { filter: Box::new(client_filter), }, @@ -263,6 +263,20 @@ where } } } + zcosmic_toplevel_manager_v1::Request::MoveToExtWorkspace { + toplevel, + workspace, + output, + } => { + let window = window_from_handle(toplevel).unwrap(); + if let Some(workspace_handle) = + state.workspace_state().get_ext_workspace_handle(&workspace) + { + if let Some(output) = Output::from_resource(&output) { + state.move_to_workspace(dh, &window, workspace_handle, output); + } + } + } _ => unreachable!(), } } diff --git a/src/wayland/protocols/workspace/cosmic.rs b/src/wayland/protocols/workspace/cosmic.rs index 58638654..9e5576a5 100644 --- a/src/wayland/protocols/workspace/cosmic.rs +++ b/src/wayland/protocols/workspace/cosmic.rs @@ -1,10 +1,10 @@ // SPDX-License-Identifier: GPL-3.0-only use smithay::{ - reexports::wayland_protocols::ext::workspace::v1::server::ext_workspace_handle_v1::{self}, + reexports::wayland_protocols::ext::workspace::v1::server::ext_workspace_handle_v1, reexports::wayland_server::{ backend::{ClientData, ClientId}, - Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource, + Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource, WEnum, }, }; @@ -14,10 +14,13 @@ use super::{ WorkspaceHandler, WorkspaceState, }; -use cosmic_protocols::workspace::v1::server::{ - zcosmic_workspace_group_handle_v1::{self, ZcosmicWorkspaceGroupHandleV1}, - zcosmic_workspace_handle_v1::{self, ZcosmicWorkspaceHandleV1}, - zcosmic_workspace_manager_v1::{self, ZcosmicWorkspaceManagerV1}, +use cosmic_protocols::workspace::{ + v1::server::{ + zcosmic_workspace_group_handle_v1::{self, ZcosmicWorkspaceGroupHandleV1}, + zcosmic_workspace_handle_v1::{self, ZcosmicWorkspaceHandleV1}, + zcosmic_workspace_manager_v1::{self, ZcosmicWorkspaceManagerV1}, + }, + v2::server::zcosmic_workspace_handle_v2, }; impl GlobalDispatch for WorkspaceState @@ -243,6 +246,17 @@ where .workspace_state() .lock() .unwrap(); + let tiling_state = match tiling_state { + WEnum::Value(zcosmic_workspace_handle_v1::TilingState::FloatingOnly) => { + WEnum::Value(zcosmic_workspace_handle_v2::TilingState::FloatingOnly) + } + WEnum::Value(zcosmic_workspace_handle_v1::TilingState::TilingEnabled) => { + WEnum::Value(zcosmic_workspace_handle_v2::TilingState::TilingEnabled) + } + // Won't be adding more variants to v1, at least + WEnum::Value(_) => unreachable!(), + WEnum::Unknown(value) => WEnum::Unknown(value), + }; state.requests.push(Request::SetTilingState { workspace: workspace_handle, state: tiling_state, @@ -477,7 +491,21 @@ where .map(|state| state != workspace.tiling) .unwrap_or(true) { - instance.tiling_state(workspace.tiling); + let tiling_state = match workspace.tiling { + zcosmic_workspace_handle_v2::TilingState::FloatingOnly => { + zcosmic_workspace_handle_v1::TilingState::FloatingOnly + } + zcosmic_workspace_handle_v2::TilingState::TilingEnabled => { + zcosmic_workspace_handle_v1::TilingState::TilingEnabled + } + _ => { + // Not clear what to do if state doesn't match. Which + // shouldn't happen (or protocol will be irrelevant by + // then). + zcosmic_workspace_handle_v1::TilingState::TilingEnabled + } + }; + instance.tiling_state(tiling_state); handle_state.tiling = Some(workspace.tiling); changed = true; } diff --git a/src/wayland/protocols/workspace/cosmic_v2.rs b/src/wayland/protocols/workspace/cosmic_v2.rs new file mode 100644 index 00000000..03d72358 --- /dev/null +++ b/src/wayland/protocols/workspace/cosmic_v2.rs @@ -0,0 +1,221 @@ +// SPDX-License-Identifier: GPL-3.0-only + +use cosmic_protocols::workspace::v2::server::{ + zcosmic_workspace_handle_v2::{self, ZcosmicWorkspaceHandleV2}, + zcosmic_workspace_manager_v2::{self, ZcosmicWorkspaceManagerV2}, +}; +use smithay::reexports::{ + wayland_protocols::ext::workspace::v1::server::ext_workspace_handle_v1::ExtWorkspaceHandleV1, + wayland_server::{ + backend::ClientData, Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, + Resource, Weak, + }, +}; +use std::sync::Mutex; + +use super::{ + Request, Workspace, WorkspaceCapabilities, WorkspaceClientHandler, WorkspaceData, + WorkspaceGlobalData, WorkspaceHandler, WorkspaceState, +}; + +#[derive(Default)] +pub struct CosmicWorkspaceDataInner { + capabilities: Option, + tiling: Option, +} + +pub struct CosmicWorkspaceData { + workspace: Weak, + inner: Mutex, +} + +impl GlobalDispatch for WorkspaceState +where + D: GlobalDispatch + + Dispatch + + Dispatch + + WorkspaceHandler + + 'static, + ::Client: ClientData + WorkspaceClientHandler + 'static, +{ + fn bind( + _state: &mut D, + _dh: &DisplayHandle, + _client: &Client, + resource: New, + _global_data: &WorkspaceGlobalData, + data_init: &mut DataInit<'_, D>, + ) { + data_init.init(resource, ()); + } + + fn can_view(client: Client, global_data: &WorkspaceGlobalData) -> bool { + (global_data.filter)(&client) + } +} + +impl Dispatch for WorkspaceState +where + D: GlobalDispatch + + Dispatch + + Dispatch + + WorkspaceHandler + + 'static, + ::Client: ClientData + WorkspaceClientHandler + 'static, +{ + fn request( + state: &mut D, + _client: &Client, + obj: &ZcosmicWorkspaceManagerV2, + request: zcosmic_workspace_manager_v2::Request, + _data: &(), + _dh: &DisplayHandle, + data_init: &mut DataInit<'_, D>, + ) { + match request { + zcosmic_workspace_manager_v2::Request::GetCosmicWorkspace { + cosmic_workspace, + workspace, + } => { + let cosmic_workspace = data_init.init( + cosmic_workspace, + CosmicWorkspaceData { + workspace: workspace.downgrade(), + inner: Mutex::new(CosmicWorkspaceDataInner::default()), + }, + ); + if let Some(data) = workspace.data::() { + let mut data = data.lock().unwrap(); + if data.cosmic_v2_handle.as_ref().is_some_and(|x| x.is_alive()) { + obj.post_error( + zcosmic_workspace_manager_v2::Error::WorkspaceExists, + "zcosmic_workspace_handle_v2 already exists for ext_workspace_handle_v1", + ); + return; + } + data.cosmic_v2_handle = Some(cosmic_workspace.downgrade()); + if let Some((workspace, ext_mngr, _)) = state + .workspace_state() + .groups + .iter() + .flat_map(|g| &g.workspaces) + .flat_map(|w| w.ext_instances.iter().map(move |(mngr, i)| (w, mngr, i))) + .find(|(_, _, i)| **i == workspace) + { + if let Ok(ext_mngr) = ext_mngr.upgrade() { + send_workspace_to_client(&cosmic_workspace, workspace); + ext_mngr.done(); + } + } + } + } + _ => unreachable!(), + } + } +} + +impl Dispatch for WorkspaceState +where + D: GlobalDispatch + + Dispatch + + Dispatch + + WorkspaceHandler + + 'static, + ::Client: ClientData + WorkspaceClientHandler + 'static, +{ + fn request( + state: &mut D, + client: &Client, + _obj: &ZcosmicWorkspaceHandleV2, + request: zcosmic_workspace_handle_v2::Request, + data: &CosmicWorkspaceData, + _dh: &DisplayHandle, + _data_init: &mut DataInit<'_, D>, + ) { + let Ok(workspace) = data.workspace.upgrade() else { + return; + }; + match request { + zcosmic_workspace_handle_v2::Request::Rename { name } => { + if let Some(workspace_handle) = + state.workspace_state().get_ext_workspace_handle(&workspace) + { + let mut state = client + .get_data::<::Client>() + .unwrap() + .workspace_state() + .lock() + .unwrap(); + state.requests.push(Request::Rename { + workspace: workspace_handle, + name, + }); + } + } + zcosmic_workspace_handle_v2::Request::SetTilingState { + state: tiling_state, + } => { + if let Some(workspace_handle) = + state.workspace_state().get_ext_workspace_handle(&workspace) + { + let mut state = client + .get_data::<::Client>() + .unwrap() + .workspace_state() + .lock() + .unwrap(); + state.requests.push(Request::SetTilingState { + workspace: workspace_handle, + state: tiling_state, + }); + } + } + _ => unreachable!(), + } + } +} + +pub fn send_workspace_to_client( + instance: &ZcosmicWorkspaceHandleV2, + workspace: &Workspace, +) -> bool { + let mut changed = false; + + let mut handle_state = instance + .data::() + .unwrap() + .inner + .lock() + .unwrap(); + + if handle_state.capabilities != Some(workspace.capabilities) { + let caps = workspace + .capabilities + .iter() + .filter_map(|cap| match cap { + WorkspaceCapabilities::Rename => { + Some(zcosmic_workspace_handle_v2::WorkspaceCapabilities::Rename) + } + WorkspaceCapabilities::SetTilingState => { + Some(zcosmic_workspace_handle_v2::WorkspaceCapabilities::SetTilingState) + } + _ => None, + }) + .collect::(); + instance.capabilities(caps); + handle_state.capabilities = Some(workspace.capabilities); + changed = true; + } + + if handle_state + .tiling + .map(|state| state != workspace.tiling) + .unwrap_or(true) + { + instance.tiling_state(workspace.tiling); + handle_state.tiling = Some(workspace.tiling); + changed = true; + } + + changed +} diff --git a/src/wayland/protocols/workspace/ext.rs b/src/wayland/protocols/workspace/ext.rs index 610f9ef7..af99ac8d 100644 --- a/src/wayland/protocols/workspace/ext.rs +++ b/src/wayland/protocols/workspace/ext.rs @@ -392,6 +392,7 @@ where } } }; + let instance = instance.clone(); let mut handle_state = instance.data::().unwrap().lock().unwrap(); let mut changed = false; @@ -442,5 +443,13 @@ where } // TODO ext_workspace_handle_v1::id + if let Some(cosmic_v2_handle) = handle_state + .cosmic_v2_handle + .as_ref() + .and_then(|x| x.upgrade().ok()) + { + changed |= super::cosmic_v2::send_workspace_to_client(&cosmic_v2_handle, workspace); + } + changed } diff --git a/src/wayland/protocols/workspace/mod.rs b/src/wayland/protocols/workspace/mod.rs index 1137f89e..481335c9 100644 --- a/src/wayland/protocols/workspace/mod.rs +++ b/src/wayland/protocols/workspace/mod.rs @@ -19,13 +19,21 @@ use smithay::{ }; use wayland_backend::protocol::WEnum; -use cosmic_protocols::workspace::v1::server::{ - zcosmic_workspace_group_handle_v1::ZcosmicWorkspaceGroupHandleV1, - zcosmic_workspace_handle_v1::{self, ZcosmicWorkspaceHandleV1}, - zcosmic_workspace_manager_v1::ZcosmicWorkspaceManagerV1, +use cosmic_protocols::workspace::{ + v1::server::{ + zcosmic_workspace_group_handle_v1::ZcosmicWorkspaceGroupHandleV1, + zcosmic_workspace_handle_v1::ZcosmicWorkspaceHandleV1, + zcosmic_workspace_manager_v1::ZcosmicWorkspaceManagerV1, + }, + v2::server::{ + zcosmic_workspace_handle_v2::{self, ZcosmicWorkspaceHandleV2}, + zcosmic_workspace_manager_v2::ZcosmicWorkspaceManagerV2, + }, }; mod cosmic; +mod cosmic_v2; +pub use cosmic_v2::CosmicWorkspaceData; mod ext; pub use smithay::reexports::wayland_protocols::ext::workspace::v1::server::ext_workspace_group_handle_v1::GroupCapabilities; @@ -56,6 +64,9 @@ where + Dispatch + Dispatch + Dispatch + + GlobalDispatch + + Dispatch + + Dispatch + WorkspaceHandler + 'static, ::Client: ClientData + WorkspaceClientHandler + 'static, @@ -63,6 +74,7 @@ where dh: DisplayHandle, cosmic_global: GlobalId, ext_global: GlobalId, + cosmic_v2_global: GlobalId, instances: Vec, ext_instances: Vec, groups: Vec, @@ -134,7 +146,7 @@ pub struct Workspace { capabilities: WorkspaceCapabilities, coordinates: Vec, states: ext_workspace_handle_v1::State, - tiling: zcosmic_workspace_handle_v1::TilingState, + tiling: zcosmic_workspace_handle_v2::TilingState, ext_id: Option, } @@ -149,7 +161,8 @@ pub struct WorkspaceDataInner { capabilities: Option, coordinates: Vec, states: Option, - tiling: Option, + tiling: Option, + cosmic_v2_handle: Option>, } pub type WorkspaceData = Mutex; @@ -164,6 +177,9 @@ where + Dispatch + Dispatch + Dispatch + + GlobalDispatch + + Dispatch + + Dispatch + Sized + 'static, { @@ -189,7 +205,7 @@ pub enum Request { }, SetTilingState { workspace: WorkspaceHandle, - state: WEnum, + state: WEnum, }, Create { in_group: WorkspaceGroupHandle, @@ -221,6 +237,9 @@ where + Dispatch + Dispatch + Dispatch + + GlobalDispatch + + Dispatch + + Dispatch + WorkspaceHandler + 'static, ::Client: ClientData + WorkspaceClientHandler + 'static, @@ -239,7 +258,14 @@ where let ext_global = dh.create_global::( 1, WorkspaceGlobalData { - filter: Box::new(client_filter), + filter: Box::new(client_filter.clone()), + }, + ); + + let cosmic_v2_global = dh.create_global::( + 1, + WorkspaceGlobalData { + filter: Box::new(client_filter.clone()), }, ); @@ -247,6 +273,7 @@ where dh: dh.clone(), cosmic_global, ext_global, + cosmic_v2_global, instances: Vec::new(), ext_instances: Vec::new(), groups: Vec::new(), @@ -324,7 +351,7 @@ where pub fn workspace_tiling_state( &self, workspace: &WorkspaceHandle, - ) -> Option { + ) -> Option { self.groups.iter().find_map(|g| { g.workspaces .iter() @@ -342,6 +369,7 @@ where .find(|g| g.instances.iter().any(|(_, i)| i == group)) .map(|g| WorkspaceGroupHandle { id: g.id }) } + pub fn workspace_handle( &self, workspace: &ZcosmicWorkspaceHandleV1, @@ -368,6 +396,7 @@ where .map(|(_, i)| i) .filter(|i| i.id().same_client_as(client)) } + pub fn raw_workspace_handles<'a>( &'a self, workspace: &'a WorkspaceHandle, @@ -382,6 +411,20 @@ where .filter(|i| i.id().same_client_as(client)) } + pub fn raw_ext_workspace_handles<'a>( + &'a self, + workspace: &'a WorkspaceHandle, + client: &'a ObjectId, + ) -> impl Iterator + 'a { + self.groups + .iter() + .find_map(|g| g.workspaces.iter().find(|w| w.id == workspace.id)) + .into_iter() + .flat_map(|w| &w.ext_instances) + .map(|(_, i)| i) + .filter(|i| Resource::id(*i).same_client_as(client)) + } + pub fn update(&mut self) -> WorkspaceUpdateGuard<'_, D> { WorkspaceUpdateGuard(self) } @@ -447,6 +490,10 @@ where pub fn ext_global_id(&self) -> GlobalId { self.ext_global.clone() } + + pub fn cosmic_v2_global_id(&self) -> GlobalId { + self.cosmic_v2_global.clone() + } } impl<'a, D> WorkspaceUpdateGuard<'a, D> @@ -458,6 +505,9 @@ where + Dispatch + Dispatch + Dispatch + + GlobalDispatch + + Dispatch + + Dispatch + WorkspaceHandler + 'static, ::Client: ClientData + WorkspaceClientHandler + 'static, @@ -475,7 +525,7 @@ where pub fn create_workspace( &mut self, group: &WorkspaceGroupHandle, - tiling: zcosmic_workspace_handle_v1::TilingState, + tiling: zcosmic_workspace_handle_v2::TilingState, ext_id: Option, ) -> Option { if let Some(group) = self.0.groups.iter_mut().find(|g| g.id == group.id) { @@ -688,14 +738,14 @@ where pub fn workspace_tiling_state( &self, workspace: &WorkspaceHandle, - ) -> Option { + ) -> Option { self.0.workspace_tiling_state(workspace) } pub fn set_workspace_tiling_state( &mut self, workspace: &WorkspaceHandle, - state: zcosmic_workspace_handle_v1::TilingState, + state: zcosmic_workspace_handle_v2::TilingState, ) { if let Some(workspace) = self .0 @@ -718,6 +768,9 @@ where + Dispatch + Dispatch + Dispatch + + GlobalDispatch + + Dispatch + + Dispatch + WorkspaceHandler + 'static, ::Client: ClientData + WorkspaceClientHandler + 'static, @@ -754,6 +807,16 @@ macro_rules! delegate_workspace { smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ smithay::reexports::wayland_protocols::ext::workspace::v1::server::ext_workspace_handle_v1::ExtWorkspaceHandleV1: $crate::wayland::protocols::workspace::WorkspaceData ] => $crate::wayland::protocols::workspace::WorkspaceState); + + smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ + cosmic_protocols::workspace::v2::server::zcosmic_workspace_manager_v2::ZcosmicWorkspaceManagerV2: $crate::wayland::protocols::workspace::WorkspaceGlobalData + ] => $crate::wayland::protocols::workspace::WorkspaceState); + smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ + cosmic_protocols::workspace::v2::server::zcosmic_workspace_manager_v2::ZcosmicWorkspaceManagerV2: () + ] => $crate::wayland::protocols::workspace::WorkspaceState); + smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ + cosmic_protocols::workspace::v2::server::zcosmic_workspace_handle_v2::ZcosmicWorkspaceHandleV2: $crate::wayland::protocols::workspace::CosmicWorkspaceData + ] => $crate::wayland::protocols::workspace::WorkspaceState); }; } pub(crate) use delegate_workspace;