Skip to content

protocols/workspace: Set ext workspace id for pinned workspace #1478

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cosmic-comp-config/src/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,6 @@ pub struct OutputMatch {
pub struct PinnedWorkspace {
pub output: OutputMatch,
pub tiling_enabled: bool,
// TODO: name, id
pub id: Option<String>,
// TODO: name
}
3 changes: 1 addition & 2 deletions src/shell/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -400,8 +400,7 @@ fn create_workspace_from_pinned(
} else {
TilingState::FloatingOnly
},
// TODO Set id for persistent workspaces
None,
pinned.id.clone(),
)
.unwrap();
state.add_workspace_state(&workspace_handle, WState::Pinned);
Expand Down
8 changes: 6 additions & 2 deletions src/shell/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@ const FULLSCREEN_ANIMATION_DURATION: Duration = Duration::from_millis(200);

// For stable workspace id, generate random 24-bit integer, as a hex string
// Must be compared with existing workspaces work uniqueness.
// TODO: Assign an id to any workspace that is pinned
pub fn random_id() -> String {
pub fn random_workspace_id() -> String {
let id = rand::random_range(0..(2 << 24));
format!("{:x}", id)
}
Expand Down Expand Up @@ -106,6 +105,7 @@ pub struct Workspace {
pub tiling_enabled: bool,
pub fullscreen: Option<FullscreenSurface>,
pub pinned: bool,
pub id: Option<String>,

pub handle: WorkspaceHandle,
pub focus_stack: FocusStacks,
Expand Down Expand Up @@ -362,6 +362,7 @@ impl Workspace {
minimized_windows: Vec::new(),
fullscreen: None,
pinned: false,
id: None,
handle,
focus_stack: FocusStacks::default(),
screencopy: ScreencopySessions::default(),
Expand Down Expand Up @@ -393,6 +394,7 @@ impl Workspace {
minimized_windows: Vec::new(),
fullscreen: None,
pinned: true,
id: pinned.id.clone(),
handle,
focus_stack: FocusStacks::default(),
screencopy: ScreencopySessions::default(),
Expand All @@ -410,6 +412,7 @@ impl Workspace {
}

pub fn to_pinned(&self) -> Option<PinnedWorkspace> {
debug_assert!(self.id.is_some());
let output = self.explicit_output().clone();
if self.pinned {
Some(PinnedWorkspace {
Expand All @@ -418,6 +421,7 @@ impl Workspace {
edid: output.edid,
},
tiling_enabled: self.tiling_enabled,
id: self.id.clone(),
})
} else {
None
Expand Down
7 changes: 7 additions & 0 deletions src/wayland/handlers/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ impl WorkspaceHandler for State {
workspace.pinned = pinned;
let mut update = self.common.workspace_state.update();
if pinned {
if workspace.id.is_none() {
let id = crate::shell::random_workspace_id();
update
.set_id(&workspace.handle, &id)
.expect("workspace already has id");
workspace.id = Some(id);
}
update.add_workspace_state(&workspace.handle, WState::Pinned);
// TODO: Also need to update on changing other properties that are saved
shell.workspaces.persist(&self.common.config);
Expand Down
12 changes: 7 additions & 5 deletions src/wayland/protocols/workspace/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pub struct WorkspaceDataInner {
capabilities: Option<ext_workspace_handle_v1::WorkspaceCapabilities>,
coordinates: Vec<u32>,
states: Option<ext_workspace_handle_v1::State>,
ext_id: Option<String>,
pub(super) cosmic_v2_handle: Option<Weak<ZcosmicWorkspaceHandleV2>>,
}

Expand Down Expand Up @@ -404,9 +405,6 @@ where
},
) {
mngr.workspace(&handle);
if let Some(id) = workspace.ext_id.clone() {
handle.id(id);
}
workspace.ext_instances.push(handle);
workspace.ext_instances.last_mut().unwrap()
} else {
Expand Down Expand Up @@ -492,8 +490,12 @@ where
handle_state.states = Some(states);
changed = true;
}
// TODO ext_workspace_handle_v1::id
// TODO send id if pinned

if handle_state.ext_id.is_none() {
if let Some(id) = workspace.ext_id.clone() {
instance.id(id);
}
}

if let Some(cosmic_v2_handle) = handle_state
.cosmic_v2_handle
Expand Down
23 changes: 22 additions & 1 deletion src/wayland/protocols/workspace/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,6 @@ where
&mut self,
group: &WorkspaceGroupHandle,
tiling: zcosmic_workspace_handle_v2::TilingState,
// TODO way to add id to workspace that doesn't have it
ext_id: Option<String>,
) -> Option<WorkspaceHandle> {
if let Some(group) = self.0.groups.iter_mut().find(|g| g.id == group.id) {
Expand Down Expand Up @@ -597,6 +596,25 @@ where
workspace.tiling = state;
}
}

pub fn set_id(
&mut self,
workspace: &WorkspaceHandle,
id: &str,
) -> Result<(), WorkspaceIdAlreadySetError> {
if let Some(workspace) = self
.0
.groups
.iter_mut()
.find_map(|g| g.workspaces.iter_mut().find(|w| w.id == workspace.id))
{
if workspace.ext_id.is_some() {
return Err(WorkspaceIdAlreadySetError);
}
workspace.ext_id = Some(id.to_owned());
}
Ok(())
}
}

impl<'a, D> Drop for WorkspaceUpdateGuard<'a, D>
Expand All @@ -608,6 +626,9 @@ where
}
}

#[derive(Clone, Copy, Debug)]
pub struct WorkspaceIdAlreadySetError;

macro_rules! delegate_workspace {
($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
Expand Down
Loading