diff --git a/src/wayland/protocols/toplevel_info.rs b/src/wayland/protocols/toplevel_info.rs index b52ae354..b9251744 100644 --- a/src/wayland/protocols/toplevel_info.rs +++ b/src/wayland/protocols/toplevel_info.rs @@ -590,7 +590,7 @@ where .iter() .filter(|w| !handle_state.workspaces.contains(w)) { - if let Some(handle) = workspace_state.raw_workspace_handle(&new_workspace, &instance.id()) { + for handle in workspace_state.raw_workspace_handles(&new_workspace, &instance.id()) { instance.workspace_enter(&handle); changed = true; } @@ -600,7 +600,7 @@ where .iter() .filter(|w| !state.workspaces.contains(w)) { - if let Some(handle) = workspace_state.raw_workspace_handle(&old_workspace, &instance.id()) { + for handle in workspace_state.raw_workspace_handles(&old_workspace, &instance.id()) { instance.workspace_leave(&handle); changed = true; } diff --git a/src/wayland/protocols/workspace/cosmic.rs b/src/wayland/protocols/workspace/cosmic.rs index b19bf211..aaebc0af 100644 --- a/src/wayland/protocols/workspace/cosmic.rs +++ b/src/wayland/protocols/workspace/cosmic.rs @@ -130,7 +130,7 @@ where .workspace_state() .groups .iter() - .find(|g| g.instances.contains(obj)) + .find(|g| g.instances.iter().any(|(_, i)| i == obj)) .map(|g| g.id) { let mut state = client @@ -147,7 +147,7 @@ where } zcosmic_workspace_group_handle_v1::Request::Destroy => { for group in &mut state.workspace_state_mut().groups { - group.instances.retain(|i| i != obj) + group.instances.retain(|(_, i)| i != obj) } } _ => {} @@ -161,7 +161,7 @@ where _data: &WorkspaceGroupData, ) { for group in &mut state.workspace_state_mut().groups { - group.instances.retain(|i| i != resource) + group.instances.retain(|(_, i)| i != resource) } } } @@ -252,7 +252,7 @@ where zcosmic_workspace_handle_v1::Request::Destroy => { for group in &mut state.workspace_state_mut().groups { for workspace in &mut group.workspaces { - workspace.instances.retain(|i| i != obj) + workspace.instances.retain(|(_, i)| i != obj) } } } @@ -268,7 +268,7 @@ where ) { for group in &mut state.workspace_state_mut().groups { for workspace in &mut group.workspaces { - workspace.instances.retain(|i| i != resource) + workspace.instances.retain(|(_, i)| i != resource) } } } @@ -288,11 +288,7 @@ where + 'static, ::Client: ClientData + WorkspaceClientHandler + 'static, { - let instance = match group - .instances - .iter_mut() - .find(|i| i.id().same_client_as(&mngr.id())) - { + let (_, instance) = match group.instances.iter_mut().find(|(m, _)| m == mngr) { Some(i) => i, None => { if let Ok(client) = dh.get_client(mngr.id()) { @@ -302,7 +298,7 @@ where WorkspaceGroupData::default(), ) { mngr.workspace_group(&handle); - group.instances.push(handle); + group.instances.push((mngr.downgrade(), handle)); group.instances.last_mut().unwrap() } else { return false; @@ -363,7 +359,7 @@ where handle_state.workspace_count = group.workspaces.len(); for workspace in &mut group.workspaces { - if send_workspace_to_client::(dh, instance, workspace) { + if send_workspace_to_client::(dh, mngr, instance, workspace) { changed = true; } } @@ -373,6 +369,7 @@ where fn send_workspace_to_client( dh: &DisplayHandle, + mngr: &ZcosmicWorkspaceManagerV1, group: &ZcosmicWorkspaceGroupHandleV1, workspace: &mut Workspace, ) -> bool @@ -385,11 +382,7 @@ where + 'static, ::Client: ClientData + WorkspaceClientHandler + 'static, { - let instance = match workspace - .instances - .iter_mut() - .find(|i| i.id().same_client_as(&group.id())) - { + let (_, instance) = match workspace.instances.iter_mut().find(|(m, _)| m == mngr) { Some(i) => i, None => { if let Ok(client) = dh.get_client(group.id()) { @@ -399,7 +392,7 @@ where WorkspaceData::default(), ) { group.workspace(&handle); - workspace.instances.push(handle); + workspace.instances.push((mngr.downgrade(), handle)); workspace.instances.last_mut().unwrap() } else { return false; diff --git a/src/wayland/protocols/workspace/ext.rs b/src/wayland/protocols/workspace/ext.rs index 78d2d23a..d7746e0f 100644 --- a/src/wayland/protocols/workspace/ext.rs +++ b/src/wayland/protocols/workspace/ext.rs @@ -125,7 +125,7 @@ where .workspace_state() .groups .iter() - .find(|g| g.ext_instances.contains(obj)) + .find(|g| g.ext_instances.iter().any(|(_, i)| i == obj)) .map(|g| g.id) { let mut state = client @@ -142,7 +142,7 @@ where } ext_workspace_group_handle_v1::Request::Destroy => { for group in &mut state.workspace_state_mut().groups { - group.ext_instances.retain(|i| i != obj) + group.ext_instances.retain(|(_, i)| i != obj) } } _ => {} @@ -156,7 +156,7 @@ where _data: &WorkspaceGroupData, ) { for group in &mut state.workspace_state_mut().groups { - group.ext_instances.retain(|i| i != resource) + group.ext_instances.retain(|(_, i)| i != resource) } } } @@ -228,7 +228,7 @@ where .workspace_state() .groups .iter() - .find(|g| g.ext_instances.contains(&workspace_group)) + .find(|g| g.ext_instances.iter().any(|(_, i)| *i == workspace_group)) .map(|g| g.id) { let mut state = client @@ -247,7 +247,7 @@ where ext_workspace_handle_v1::Request::Destroy => { for group in &mut state.workspace_state_mut().groups { for workspace in &mut group.workspaces { - workspace.ext_instances.retain(|i| i != obj) + workspace.ext_instances.retain(|(_, i)| i != obj) } } } @@ -263,7 +263,7 @@ where ) { for group in &mut state.workspace_state_mut().groups { for workspace in &mut group.workspaces { - workspace.ext_instances.retain(|i| i != resource) + workspace.ext_instances.retain(|(_, i)| i != resource) } } } @@ -283,11 +283,7 @@ where + 'static, ::Client: ClientData + WorkspaceClientHandler + 'static, { - let instance = match group - .ext_instances - .iter_mut() - .find(|i| i.id().same_client_as(&mngr.id())) - { + let (_, instance) = match group.ext_instances.iter_mut().find(|(m, _)| m == mngr) { Some(i) => i, None => { if let Ok(client) = dh.get_client(mngr.id()) { @@ -297,7 +293,7 @@ where WorkspaceGroupData::default(), ) { mngr.workspace_group(&handle); - group.ext_instances.push(handle); + group.ext_instances.push((mngr.downgrade(), handle)); group.ext_instances.last_mut().unwrap() } else { return false; @@ -372,11 +368,7 @@ where + 'static, ::Client: ClientData + WorkspaceClientHandler + 'static, { - let instance = match workspace - .ext_instances - .iter_mut() - .find(|i| Resource::id(*i).same_client_as(&mngr.id())) - { + let (_, instance) = match workspace.ext_instances.iter_mut().find(|(m, _)| m == mngr) { Some(i) => i, None => { if let Ok(client) = dh.get_client(mngr.id()) { @@ -390,7 +382,7 @@ where if let Some(id) = workspace.ext_id.clone() { handle.id(id); } - workspace.ext_instances.push(handle); + workspace.ext_instances.push((mngr.downgrade(), handle)); workspace.ext_instances.last_mut().unwrap() } else { return false; diff --git a/src/wayland/protocols/workspace/mod.rs b/src/wayland/protocols/workspace/mod.rs index 07d5c5ed..79074e42 100644 --- a/src/wayland/protocols/workspace/mod.rs +++ b/src/wayland/protocols/workspace/mod.rs @@ -13,7 +13,7 @@ use smithay::{ wayland_server::{ backend::{ClientData, GlobalId, ObjectId}, protocol::wl_output::WlOutput, - Client, Dispatch, DisplayHandle, GlobalDispatch, Resource, + Client, Dispatch, DisplayHandle, GlobalDispatch, Resource, Weak, }, }, }; @@ -84,8 +84,11 @@ crate::utils::id_gen!(next_workspace_id, WORKSPACE_ID, WORKSPACE_IDS); #[derive(Debug)] pub struct WorkspaceGroup { id: usize, - instances: Vec, - ext_instances: Vec, + instances: Vec<( + Weak, + ZcosmicWorkspaceGroupHandleV1, + )>, + ext_instances: Vec<(Weak, ExtWorkspaceGroupHandleV1)>, workspaces: Vec, outputs: Vec, @@ -134,8 +137,8 @@ pub type WorkspaceGroupData = Mutex; #[derive(Debug)] pub struct Workspace { id: usize, - instances: Vec, - ext_instances: Vec, + instances: Vec<(Weak, ZcosmicWorkspaceHandleV1)>, + ext_instances: Vec<(Weak, ExtWorkspaceHandleV1)>, name: String, capabilities: WorkspaceCapabilities, @@ -357,7 +360,7 @@ where ) -> Option { self.groups .iter() - .find(|g| g.instances.contains(group)) + .find(|g| g.instances.iter().any(|(_, i)| i == group)) .map(|g| WorkspaceGroupHandle { id: g.id }) } pub fn workspace_handle( @@ -369,32 +372,35 @@ where .find_map(|g| { g.workspaces .iter() - .find(|w| w.instances.contains(workspace)) + .find(|w| w.instances.iter().any(|(_, i)| i == workspace)) }) .map(|w| WorkspaceHandle { id: w.id }) } - pub fn raw_group_handle( - &self, - group: &WorkspaceGroupHandle, - client: &ObjectId, - ) -> Option { + pub fn raw_group_handles<'a>( + &'a self, + group: &'a WorkspaceGroupHandle, + client: &'a ObjectId, + ) -> impl Iterator + 'a { self.groups .iter() - .find(|g| g.id == group.id) - .and_then(|g| g.instances.iter().find(|i| i.id().same_client_as(client))) - .cloned() + .filter(|g| g.id == group.id) + .flat_map(|g| &g.instances) + .map(|(_, i)| i) + .filter(|i| i.id().same_client_as(client)) } - pub fn raw_workspace_handle( - &self, - workspace: &WorkspaceHandle, - client: &ObjectId, - ) -> Option { + pub fn raw_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)) - .and_then(|w| w.instances.iter().find(|i| i.id().same_client_as(client))) - .cloned() + .into_iter() + .flat_map(|w| &w.instances) + .map(|(_, i)| i) + .filter(|i| i.id().same_client_as(client)) } pub fn update(&mut self) -> WorkspaceUpdateGuard<'_, D> { @@ -433,7 +439,11 @@ where ) -> Option { self.groups .iter() - .find_map(|g| g.workspaces.iter().find(|w| w.instances.contains(handle))) + .find_map(|g| { + g.workspaces + .iter() + .find(|w| w.instances.iter().any(|(_, i)| i == handle)) + }) .map(|w| WorkspaceHandle { id: w.id }) } @@ -446,7 +456,7 @@ where .find_map(|g| { g.workspaces .iter() - .find(|w| w.ext_instances.contains(handle)) + .find(|w| w.ext_instances.iter().any(|(_, i)| i == handle)) }) .map(|w| WorkspaceHandle { id: w.id }) } @@ -524,10 +534,10 @@ where } if let Some(group) = self.0.groups.iter().find(|g| g.id == group.id) { - for instance in &group.instances { + for (_, instance) in &group.instances { instance.remove(); } - for instance in &group.ext_instances { + for (_, instance) in &group.ext_instances { instance.removed(); } } @@ -538,13 +548,14 @@ where pub fn remove_workspace(&mut self, workspace: WorkspaceHandle) { for group in &mut self.0.groups { if let Some(workspace) = group.workspaces.iter().find(|w| w.id == workspace.id) { - for instance in &workspace.instances { + for (_, instance) in &workspace.instances { instance.remove(); } - for instance in &workspace.ext_instances { - // TODO remove only if it matches the group - for group_instance in &group.ext_instances { - group_instance.workspace_leave(instance); + for (manager, instance) in &workspace.ext_instances { + for (group_manager, group_instance) in &group.ext_instances { + if manager == group_manager { + group_instance.workspace_leave(instance); + } } instance.removed(); }