Add support for workspace pinning and dragging

Workspaces can be pinned, and dragged to reorder or move to a different
output.

These features are enabled only if cosmic-workspace-v2 advertises the
necessary protocol version and capabilities.

The layout of the labels and pin buttons could be tweaked a bit still.
Some hacks and workarounds are needed to get drag and drop working as
desired. Something iced and libcosmic could potentially improve in the
future. But this now seems fairly robust.
This commit is contained in:
Ian Douglas Scott 2025-01-31 14:17:56 -08:00 committed by Ian Douglas Scott
parent 94ec10686e
commit 3c9a923f41
8 changed files with 585 additions and 95 deletions

View file

@ -80,5 +80,8 @@ pub enum Cmd {
ExtWorkspaceHandleV1,
wl_output::WlOutput,
),
MoveWorkspaceBefore(ExtWorkspaceHandleV1, ExtWorkspaceHandleV1),
MoveWorkspaceAfter(ExtWorkspaceHandleV1, ExtWorkspaceHandleV1),
ActivateWorkspace(ExtWorkspaceHandleV1),
SetWorkspacePinned(ExtWorkspaceHandleV1, bool),
}

View file

@ -3,6 +3,7 @@
use calloop_wayland_source::WaylandSource;
use cctk::{
cosmic_protocols::workspace::v2::client::zcosmic_workspace_handle_v2,
screencopy::{CaptureSource, ScreencopyState},
sctk::{
self,
@ -106,12 +107,68 @@ impl AppData {
}
}
}
// TODO version check
Cmd::MoveWorkspaceBefore(workspace_handle, other_workspace_handle) => {
if let Ok(workspace_manager) = self.workspace_state.workspace_manager().get() {
if let Some(cosmic_workspace) = self
.workspace_state
.workspaces()
.find(|w| w.handle == workspace_handle)
.and_then(|w| w.cosmic_handle.as_ref())
{
if cosmic_workspace.version()
>= zcosmic_workspace_handle_v2::REQ_MOVE_BEFORE_SINCE
{
cosmic_workspace.move_before(&other_workspace_handle, 0);
workspace_manager.commit();
}
}
}
}
Cmd::MoveWorkspaceAfter(workspace_handle, other_workspace_handle) => {
if let Ok(workspace_manager) = self.workspace_state.workspace_manager().get() {
if let Some(cosmic_workspace) = self
.workspace_state
.workspaces()
.find(|w| w.handle == workspace_handle)
.and_then(|w| w.cosmic_handle.as_ref())
{
if cosmic_workspace.version()
>= zcosmic_workspace_handle_v2::REQ_MOVE_AFTER_SINCE
{
cosmic_workspace.move_after(&other_workspace_handle, 0);
workspace_manager.commit();
}
}
}
}
Cmd::ActivateWorkspace(workspace_handle) => {
if let Ok(workspace_manager) = self.workspace_state.workspace_manager().get() {
workspace_handle.activate();
workspace_manager.commit();
}
}
Cmd::SetWorkspacePinned(workspace_handle, pinned) => {
if let Ok(workspace_manager) = self.workspace_state.workspace_manager().get() {
if let Some(cosmic_workspace) = self
.workspace_state
.workspaces()
.find(|w| w.handle == workspace_handle)
.and_then(|w| w.cosmic_handle.as_ref())
{
if cosmic_workspace.version() >= zcosmic_workspace_handle_v2::REQ_PIN_SINCE
{
// TODO check capability
if pinned {
cosmic_workspace.pin();
} else {
cosmic_workspace.unpin();
}
workspace_manager.commit();
}
}
}
}
}
}