From 7822030e0b12dc4966fed5f2ba664430a3757ee3 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 27 Jan 2025 14:15:59 -0800 Subject: [PATCH] workspace: Fix race between binding `wl_output` and `output_enter` https://github.com/pop-os/cosmic-comp/pull/668 previously did this for toplevel events, but missed the fact that the workspaces protocol has the same issue. Fixes https://github.com/pop-os/cosmic-workspaces-epoch/issues/61. --- src/wayland/protocols/workspace.rs | 33 +++++++++++++++--------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/wayland/protocols/workspace.rs b/src/wayland/protocols/workspace.rs index 6d661ad7..463d17e0 100644 --- a/src/wayland/protocols/workspace.rs +++ b/src/wayland/protocols/workspace.rs @@ -6,6 +6,7 @@ use smithay::{ output::Output, reexports::wayland_server::{ backend::{ClientData, ClientId, GlobalId, ObjectId}, + protocol::wl_output::WlOutput, Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource, }, }; @@ -70,6 +71,7 @@ pub struct WorkspaceGroupHandle { #[derive(Default)] pub struct WorkspaceGroupDataInner { outputs: Vec, + wl_outputs: HashSet, capabilities: Vec, workspace_count: usize, } @@ -905,26 +907,25 @@ where .unwrap(); let mut changed = false; if let Ok(client) = dh.get_client(instance.id()) { - for new_output in group - .outputs - .iter() - .filter(|o| !handle_state.outputs.contains(o)) - { - for wl_output in new_output.client_outputs(&client) { - instance.output_enter(&wl_output); + for output in &group.outputs { + for wl_output in output.client_outputs(&client) { + if handle_state.wl_outputs.insert(wl_output.clone()) { + instance.output_enter(&wl_output); + changed = true; + } } - changed = true; } - for old_output in handle_state - .outputs - .iter() - .filter(|o| !group.outputs.contains(o)) - { - for wl_output in old_output.client_outputs(&client) { + + handle_state.wl_outputs.retain(|wl_output| { + let retain = + wl_output.is_alive() && group.outputs.iter().any(|output| output.owns(wl_output)); + if !retain { instance.output_leave(&wl_output); + changed = true; } - changed = true; - } + retain + }); + handle_state.outputs = group.outputs.clone(); }