diff --git a/Cargo.lock b/Cargo.lock index 38e0eefd..6bce11b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -641,7 +641,7 @@ dependencies = [ [[package]] name = "cosmic-protocols" 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 = [ "bitflags 2.4.1", "wayland-backend", @@ -954,7 +954,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ - "libloading 0.8.1", + "libloading 0.7.4", ] [[package]] diff --git a/src/shell/grabs/menu/default.rs b/src/shell/grabs/menu/default.rs index abf08fd7..0d312e3e 100644 --- a/src/shell/grabs/menu/default.rs +++ b/src/shell/grabs/menu/default.rs @@ -65,7 +65,7 @@ fn move_prev_workspace(state: &mut State, mapped: &CosmicMapped) { if let Some(prev_handle) = maybe_handle { Shell::move_window( state, - &seat, + Some(&seat), mapped, ¤t_handle, &prev_handle, @@ -93,7 +93,7 @@ fn move_next_workspace(state: &mut State, mapped: &CosmicMapped) { if let Some(next_handle) = maybe_handle { Shell::move_window( state, - &seat, + Some(&seat), mapped, ¤t_handle, &next_handle, diff --git a/src/shell/mod.rs b/src/shell/mod.rs index b67ed9b7..a183a708 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -1710,7 +1710,7 @@ impl Shell { pub fn move_window( state: &mut State, - seat: &Seat, + seat: Option<&Seat>, mapped: &CosmicMapped, from: &WorkspaceHandle, to: &WorkspaceHandle, @@ -1759,7 +1759,9 @@ impl Shell { state.common.shell.update_reactive_popups(&mapped); } let new_pos = if follow { - seat.set_active_output(&to_output); + if let Some(seat) = seat { + seat.set_active_output(&to_output); + } state .common .shell @@ -1776,13 +1778,13 @@ impl Shell { .workspaces .space_for_handle_mut(to) .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 { to_workspace.floating_layer.map(mapped.clone(), None); } else { to_workspace.tiling_layer.map( mapped.clone(), - Some(focus_stack.iter()), + focus_stack.as_ref().map(|x| x.iter()), direction, true, ); @@ -1852,7 +1854,9 @@ impl Shell { } 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 @@ -1893,7 +1897,13 @@ impl Shell { let from = from_workspace.handle; Ok(Shell::move_window( - state, seat, &mapped, &from, &to, follow, direction, + state, + Some(seat), + &mapped, + &from, + &to, + follow, + direction, )) } diff --git a/src/wayland/handlers/toplevel_management.rs b/src/wayland/handlers/toplevel_management.rs index d4440908..4fbaab6b 100644 --- a/src/wayland/handlers/toplevel_management.rs +++ b/src/wayland/handlers/toplevel_management.rs @@ -1,9 +1,10 @@ // 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::{ - shell::CosmicSurface, + shell::{CosmicSurface, Shell}, utils::prelude::*, wayland::protocols::{ toplevel_info::ToplevelInfoHandler, @@ -59,6 +60,35 @@ impl ToplevelManagementHandler for State { fn close(&mut self, _dh: &DisplayHandle, window: &::Window) { window.close(); } + + fn move_to_workspace( + &mut self, + _dh: &DisplayHandle, + window: &::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 { diff --git a/src/wayland/protocols/toplevel_management.rs b/src/wayland/protocols/toplevel_management.rs index 1b46e6b2..6d881109 100644 --- a/src/wayland/protocols/toplevel_management.rs +++ b/src/wayland/protocols/toplevel_management.rs @@ -12,8 +12,11 @@ use smithay::{ }; 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::{ - self, ZcosmicToplevelManagerV1, +use cosmic_protocols::{ + 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}; @@ -58,6 +61,14 @@ where fn unmaximize(&mut self, dh: &DisplayHandle, window: &::Window) {} fn minimize(&mut self, dh: &DisplayHandle, window: &::Window) {} fn unminimize(&mut self, dh: &DisplayHandle, window: &::Window) {} + fn move_to_workspace( + &mut self, + dh: &DisplayHandle, + window: &::Window, + workspace: ZcosmicWorkspaceHandleV1, + output: Output, + ) { + } } pub struct ToplevelManagerGlobalData { @@ -79,7 +90,7 @@ impl ToplevelManagementState { F: for<'a> Fn(&'a Client) -> bool + Send + Sync + 'static, { let global = dh.create_global::( - 1, + 2, ToplevelManagerGlobalData { 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!(), } } diff --git a/src/wayland/protocols/workspace.rs b/src/wayland/protocols/workspace.rs index 91186ca5..8e38aaa8 100644 --- a/src/wayland/protocols/workspace.rs +++ b/src/wayland/protocols/workspace.rs @@ -307,58 +307,36 @@ where ) { match request { zcosmic_workspace_handle_v1::Request::Activate => { - if let Some(id) = state - .workspace_state() - .groups - .iter() - .find_map(|g| g.workspaces.iter().find(|w| w.instances.contains(obj))) - .map(|w| w.id) - { + if let Some(workspace_handle) = state.workspace_state().get_workspace_handle(obj) { let mut state = client .get_data::<::Client>() .unwrap() .workspace_state() .lock() .unwrap(); - state - .requests - .push(Request::Activate(WorkspaceHandle { id })); + state.requests.push(Request::Activate(workspace_handle)); } } zcosmic_workspace_handle_v1::Request::Deactivate => { - if let Some(id) = state - .workspace_state() - .groups - .iter() - .find_map(|g| g.workspaces.iter().find(|w| w.instances.contains(obj))) - .map(|w| w.id) - { + if let Some(workspace_handle) = state.workspace_state().get_workspace_handle(obj) { let mut state = client .get_data::<::Client>() .unwrap() .workspace_state() .lock() .unwrap(); - state - .requests - .push(Request::Deactivate(WorkspaceHandle { id })); + state.requests.push(Request::Deactivate(workspace_handle)); } } zcosmic_workspace_handle_v1::Request::Remove => { - if let Some(id) = state - .workspace_state() - .groups - .iter() - .find_map(|g| g.workspaces.iter().find(|w| w.instances.contains(obj))) - .map(|w| w.id) - { + if let Some(workspace_handle) = state.workspace_state().get_workspace_handle(obj) { let mut state = client .get_data::<::Client>() .unwrap() .workspace_state() .lock() .unwrap(); - state.requests.push(Request::Remove(WorkspaceHandle { id })); + state.requests.push(Request::Remove(workspace_handle)); } } zcosmic_workspace_handle_v1::Request::Destroy => { @@ -556,6 +534,16 @@ where } } + pub fn get_workspace_handle( + &self, + handle: &ZcosmicWorkspaceHandleV1, + ) -> Option { + 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 { self.global.clone() }