workspace-management: Implement move_to_workspace request

Needed for `cosmic-workspaces`.
This commit is contained in:
Ian Douglas Scott 2023-12-06 15:13:48 -08:00 committed by Victoria Brekenfeld
parent 75990ff056
commit 656996503c
6 changed files with 92 additions and 43 deletions

4
Cargo.lock generated
View file

@ -641,7 +641,7 @@ dependencies = [
[[package]] [[package]]
name = "cosmic-protocols" name = "cosmic-protocols"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/pop-os/cosmic-protocols?branch=main#5faec87be0a1fd1d72e99431ac8e6647ff1dfd41" source = "git+https://github.com/pop-os/cosmic-protocols?branch=main#c1b651630c2b71cd8dfd2eb4ab47ede9dbd63840"
dependencies = [ dependencies = [
"bitflags 2.4.1", "bitflags 2.4.1",
"wayland-backend", "wayland-backend",
@ -954,7 +954,7 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412"
dependencies = [ dependencies = [
"libloading 0.8.1", "libloading 0.7.4",
] ]
[[package]] [[package]]

View file

@ -65,7 +65,7 @@ fn move_prev_workspace(state: &mut State, mapped: &CosmicMapped) {
if let Some(prev_handle) = maybe_handle { if let Some(prev_handle) = maybe_handle {
Shell::move_window( Shell::move_window(
state, state,
&seat, Some(&seat),
mapped, mapped,
&current_handle, &current_handle,
&prev_handle, &prev_handle,
@ -93,7 +93,7 @@ fn move_next_workspace(state: &mut State, mapped: &CosmicMapped) {
if let Some(next_handle) = maybe_handle { if let Some(next_handle) = maybe_handle {
Shell::move_window( Shell::move_window(
state, state,
&seat, Some(&seat),
mapped, mapped,
&current_handle, &current_handle,
&next_handle, &next_handle,

View file

@ -1710,7 +1710,7 @@ impl Shell {
pub fn move_window( pub fn move_window(
state: &mut State, state: &mut State,
seat: &Seat<State>, seat: Option<&Seat<State>>,
mapped: &CosmicMapped, mapped: &CosmicMapped,
from: &WorkspaceHandle, from: &WorkspaceHandle,
to: &WorkspaceHandle, to: &WorkspaceHandle,
@ -1759,7 +1759,9 @@ impl Shell {
state.common.shell.update_reactive_popups(&mapped); state.common.shell.update_reactive_popups(&mapped);
} }
let new_pos = if follow { let new_pos = if follow {
seat.set_active_output(&to_output); if let Some(seat) = seat {
seat.set_active_output(&to_output);
}
state state
.common .common
.shell .shell
@ -1776,13 +1778,13 @@ impl Shell {
.workspaces .workspaces
.space_for_handle_mut(to) .space_for_handle_mut(to)
.unwrap(); // checked above .unwrap(); // checked above
let focus_stack = to_workspace.focus_stack.get(&seat); let focus_stack = seat.map(|seat| to_workspace.focus_stack.get(&seat));
if window_state.layer == ManagedLayer::Floating { if window_state.layer == ManagedLayer::Floating {
to_workspace.floating_layer.map(mapped.clone(), None); to_workspace.floating_layer.map(mapped.clone(), None);
} else { } else {
to_workspace.tiling_layer.map( to_workspace.tiling_layer.map(
mapped.clone(), mapped.clone(),
Some(focus_stack.iter()), focus_stack.as_ref().map(|x| x.iter()),
direction, direction,
true, true,
); );
@ -1852,7 +1854,9 @@ impl Shell {
} }
if follow { if follow {
Common::set_focus(state, Some(&focus_target), &seat, None); if let Some(seat) = seat {
Common::set_focus(state, Some(&focus_target), &seat, None);
}
} }
new_pos new_pos
@ -1893,7 +1897,13 @@ impl Shell {
let from = from_workspace.handle; let from = from_workspace.handle;
Ok(Shell::move_window( Ok(Shell::move_window(
state, seat, &mapped, &from, &to, follow, direction, state,
Some(seat),
&mapped,
&from,
&to,
follow,
direction,
)) ))
} }

View file

@ -1,9 +1,10 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use smithay::{input::Seat, reexports::wayland_server::DisplayHandle}; use cosmic_protocols::workspace::v1::server::zcosmic_workspace_handle_v1::ZcosmicWorkspaceHandleV1;
use smithay::{input::Seat, output::Output, reexports::wayland_server::DisplayHandle};
use crate::{ use crate::{
shell::CosmicSurface, shell::{CosmicSurface, Shell},
utils::prelude::*, utils::prelude::*,
wayland::protocols::{ wayland::protocols::{
toplevel_info::ToplevelInfoHandler, toplevel_info::ToplevelInfoHandler,
@ -59,6 +60,35 @@ impl ToplevelManagementHandler for State {
fn close(&mut self, _dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) { fn close(&mut self, _dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {
window.close(); window.close();
} }
fn move_to_workspace(
&mut self,
_dh: &DisplayHandle,
window: &<Self as ToplevelInfoHandler>::Window,
workspace: ZcosmicWorkspaceHandleV1,
_output: Output,
) {
let Some(to_handle) = self.common.shell.workspace_state.get_workspace_handle(&workspace) else {
return;
};
let from_workspace = self
.common
.shell
.workspaces
.spaces()
.find(|w| w.windows().any(|w| &w == window));
if let Some(from_workspace) = from_workspace {
let mapped = from_workspace
.mapped()
.find(|m| m.windows().any(|(w, _)| &w == window))
.unwrap()
.clone();
let from_handle = from_workspace.handle;
let _ = Shell::move_window(self, None, &mapped, &from_handle, &to_handle, false, None);
return;
}
}
} }
impl ManagementWindow for CosmicSurface { impl ManagementWindow for CosmicSurface {

View file

@ -12,8 +12,11 @@ use smithay::{
}; };
pub use cosmic_protocols::toplevel_management::v1::server::zcosmic_toplevel_manager_v1::ZcosmicToplelevelManagementCapabilitiesV1 as ManagementCapabilities; pub use cosmic_protocols::toplevel_management::v1::server::zcosmic_toplevel_manager_v1::ZcosmicToplelevelManagementCapabilitiesV1 as ManagementCapabilities;
use cosmic_protocols::toplevel_management::v1::server::zcosmic_toplevel_manager_v1::{ use cosmic_protocols::{
self, ZcosmicToplevelManagerV1, toplevel_management::v1::server::zcosmic_toplevel_manager_v1::{
self, ZcosmicToplevelManagerV1,
},
workspace::v1::server::zcosmic_workspace_handle_v1::ZcosmicWorkspaceHandleV1,
}; };
use super::toplevel_info::{window_from_handle, ToplevelInfoHandler, ToplevelState, Window}; use super::toplevel_info::{window_from_handle, ToplevelInfoHandler, ToplevelState, Window};
@ -58,6 +61,14 @@ where
fn unmaximize(&mut self, dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {} fn unmaximize(&mut self, dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {}
fn minimize(&mut self, dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {} fn minimize(&mut self, dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {}
fn unminimize(&mut self, dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {} fn unminimize(&mut self, dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {}
fn move_to_workspace(
&mut self,
dh: &DisplayHandle,
window: &<Self as ToplevelInfoHandler>::Window,
workspace: ZcosmicWorkspaceHandleV1,
output: Output,
) {
}
} }
pub struct ToplevelManagerGlobalData { pub struct ToplevelManagerGlobalData {
@ -79,7 +90,7 @@ impl ToplevelManagementState {
F: for<'a> Fn(&'a Client) -> bool + Send + Sync + 'static, F: for<'a> Fn(&'a Client) -> bool + Send + Sync + 'static,
{ {
let global = dh.create_global::<D, ZcosmicToplevelManagerV1, _>( let global = dh.create_global::<D, ZcosmicToplevelManagerV1, _>(
1, 2,
ToplevelManagerGlobalData { ToplevelManagerGlobalData {
filter: Box::new(client_filter), filter: Box::new(client_filter),
}, },
@ -221,6 +232,16 @@ where
} }
} }
} }
zcosmic_toplevel_manager_v1::Request::MoveToWorkspace {
toplevel,
workspace,
output,
} => {
let window = window_from_handle(toplevel).unwrap();
if let Some(output) = Output::from_resource(&output) {
state.move_to_workspace(dh, &window, workspace, output);
}
}
_ => unreachable!(), _ => unreachable!(),
} }
} }

View file

@ -307,58 +307,36 @@ where
) { ) {
match request { match request {
zcosmic_workspace_handle_v1::Request::Activate => { zcosmic_workspace_handle_v1::Request::Activate => {
if let Some(id) = state if let Some(workspace_handle) = state.workspace_state().get_workspace_handle(obj) {
.workspace_state()
.groups
.iter()
.find_map(|g| g.workspaces.iter().find(|w| w.instances.contains(obj)))
.map(|w| w.id)
{
let mut state = client let mut state = client
.get_data::<<D as WorkspaceHandler>::Client>() .get_data::<<D as WorkspaceHandler>::Client>()
.unwrap() .unwrap()
.workspace_state() .workspace_state()
.lock() .lock()
.unwrap(); .unwrap();
state state.requests.push(Request::Activate(workspace_handle));
.requests
.push(Request::Activate(WorkspaceHandle { id }));
} }
} }
zcosmic_workspace_handle_v1::Request::Deactivate => { zcosmic_workspace_handle_v1::Request::Deactivate => {
if let Some(id) = state if let Some(workspace_handle) = state.workspace_state().get_workspace_handle(obj) {
.workspace_state()
.groups
.iter()
.find_map(|g| g.workspaces.iter().find(|w| w.instances.contains(obj)))
.map(|w| w.id)
{
let mut state = client let mut state = client
.get_data::<<D as WorkspaceHandler>::Client>() .get_data::<<D as WorkspaceHandler>::Client>()
.unwrap() .unwrap()
.workspace_state() .workspace_state()
.lock() .lock()
.unwrap(); .unwrap();
state state.requests.push(Request::Deactivate(workspace_handle));
.requests
.push(Request::Deactivate(WorkspaceHandle { id }));
} }
} }
zcosmic_workspace_handle_v1::Request::Remove => { zcosmic_workspace_handle_v1::Request::Remove => {
if let Some(id) = state if let Some(workspace_handle) = state.workspace_state().get_workspace_handle(obj) {
.workspace_state()
.groups
.iter()
.find_map(|g| g.workspaces.iter().find(|w| w.instances.contains(obj)))
.map(|w| w.id)
{
let mut state = client let mut state = client
.get_data::<<D as WorkspaceHandler>::Client>() .get_data::<<D as WorkspaceHandler>::Client>()
.unwrap() .unwrap()
.workspace_state() .workspace_state()
.lock() .lock()
.unwrap(); .unwrap();
state.requests.push(Request::Remove(WorkspaceHandle { id })); state.requests.push(Request::Remove(workspace_handle));
} }
} }
zcosmic_workspace_handle_v1::Request::Destroy => { zcosmic_workspace_handle_v1::Request::Destroy => {
@ -556,6 +534,16 @@ where
} }
} }
pub fn get_workspace_handle(
&self,
handle: &ZcosmicWorkspaceHandleV1,
) -> Option<WorkspaceHandle> {
self.groups
.iter()
.find_map(|g| g.workspaces.iter().find(|w| w.instances.contains(handle)))
.map(|w| WorkspaceHandle { id: w.id })
}
pub fn global_id(&self) -> GlobalId { pub fn global_id(&self) -> GlobalId {
self.global.clone() self.global.clone()
} }