From 97a13ea5154e0e9f63c4c5777813cd9bddf30678 Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Wed, 20 Dec 2023 20:49:37 +0000 Subject: [PATCH] shell: Lift/Refactor (interactive) resize to consider sticky windows --- src/shell/layout/floating/grabs/resize.rs | 34 +++++++--- src/shell/mod.rs | 56 ++++++++++++++--- src/shell/workspace.rs | 76 ++++++++--------------- src/wayland/handlers/compositor.rs | 8 +-- 4 files changed, 101 insertions(+), 73 deletions(-) diff --git a/src/shell/layout/floating/grabs/resize.rs b/src/shell/layout/floating/grabs/resize.rs index bda485be..f61a5490 100644 --- a/src/shell/layout/floating/grabs/resize.rs +++ b/src/shell/layout/floating/grabs/resize.rs @@ -290,17 +290,34 @@ impl ResizeSurfaceGrab { } } - pub fn apply_resize_to_location(window: CosmicMapped, space: &mut Workspace) { - if let Some(location) = space - .floating_layer + pub fn apply_resize_to_location(window: CosmicMapped, shell: &mut Shell) { + let mut resize_state = window.resize_state.lock().unwrap(); + + if resize_state.is_none() { + return; + } + + let (output, floating_layer) = if let Some((output, set)) = shell + .workspaces + .sets + .iter_mut() + .find(|(_, set)| set.sticky_layer.mapped().any(|m| m == &window)) + { + (output, &mut set.sticky_layer) + } else if let Some(workspace) = shell.space_for_mut(&window) { + (&workspace.output, &mut workspace.floating_layer) + } else { + return; + }; + + if let Some(location) = floating_layer .space .element_location(&window) .map(PointExt::as_local) - .map(|p| p.to_global(space.output())) + .map(|p| p.to_global(output)) { let mut new_location = None; - let mut resize_state = window.resize_state.lock().unwrap(); // If the window is being resized by top or left, its location must be adjusted // accordingly. match *resize_state { @@ -311,7 +328,7 @@ impl ResizeSurfaceGrab { initial_window_location, initial_window_size, } = resize_data; - let initial_window_location = initial_window_location.to_global(space.output()); + let initial_window_location = initial_window_location.to_global(output); if edges.intersects(ResizeEdge::TOP_LEFT) { let size = window.geometry().size; @@ -344,7 +361,7 @@ impl ResizeSurfaceGrab { update_reactive_popups( &window, new_location + offset.as_global(), - space.floating_layer.space.outputs(), + floating_layer.space.outputs(), ); } CosmicSurface::X11(surface) => { @@ -355,8 +372,7 @@ impl ResizeSurfaceGrab { _ => unreachable!(), } } - space - .floating_layer + floating_layer .space .map_element(window, new_location.as_logical(), false); } diff --git a/src/shell/mod.rs b/src/shell/mod.rs index bdd99911..f32520a5 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -2479,16 +2479,38 @@ impl Shell { check_grab_preconditions(&seat, surface, serial, ReleaseMode::NoMouseButtons) { if let Some(mapped) = state.common.shell.element_for_wl_surface(surface).cloned() { - if let Some(workspace) = state.common.shell.space_for_mut(&mapped) { - if let Some(grab) = workspace.resize_request(&mapped, &seat, start_data, edges) - { + if mapped.is_fullscreen(true) || mapped.is_maximized(true) { + return; + } + + let floating_layer = if let Some(set) = state + .common + .shell + .workspaces + .sets + .values_mut() + .find(|set| set.sticky_layer.mapped().any(|m| m == &mapped)) + { + &mut set.sticky_layer + } else if let Some(workspace) = state.common.shell.space_for_mut(&mapped) { + &mut workspace.floating_layer + } else { + return; + }; + + if let Some(grab) = floating_layer.resize_request( + &mapped, + seat, + start_data.clone(), + edges, + ReleaseMode::NoMouseButtons, + ) { seat.get_pointer().unwrap().set_grab( state, grab, serial.unwrap_or_else(|| SERIAL_COUNTER.next_serial()), Focus::Clear, ); - } } } } @@ -2500,8 +2522,6 @@ impl Shell { let Some(focused) = seat.get_keyboard().unwrap().current_focus() else { return; }; - - if let Some(workspace) = self.workspaces.get_mut(idx, &output) { let amount = (self .resize_state .take() @@ -2509,6 +2529,17 @@ impl Shell { .unwrap_or(10) + 2) .min(20); + + if self + .workspaces + .sets + .get_mut(&output) + .unwrap() + .sticky_layer + .resize(&focused, direction, edge, amount) + { + self.resize_state = Some((focused, direction, edge, amount, idx, output)); + } else if let Some(workspace) = self.workspaces.get_mut(idx, &output) { if workspace.resize(&focused, direction, edge, amount) { self.resize_state = Some((focused, direction, edge, amount, idx, output)); } @@ -2519,18 +2550,25 @@ impl Shell { if let Some((old_focused, old_direction, old_edge, _, idx, output)) = self.resize_state.take() { - let workspace = self.workspaces.get(idx, &output).unwrap(); if old_direction == direction && old_edge == edge { let Some(toplevel) = old_focused.toplevel() else { return; }; - let Some(mapped) = workspace + let Some(mapped) = self.workspaces.sets.values() + .find_map(|set| set.sticky_layer.mapped() + .find(|m| m.has_surface(&toplevel, WindowSurfaceType::TOPLEVEL)) + ).cloned() + .or_else(|| { + let workspace = self.workspaces.get(idx, &output).unwrap(); + workspace .mapped() .find(|m| m.has_surface(&toplevel, WindowSurfaceType::TOPLEVEL)) .cloned() + }) else { - return; + return }; + let mut resize_state = mapped.resize_state.lock().unwrap(); if let Some(ResizeState::Resizing(data)) = *resize_state { *resize_state = Some(ResizeState::WaitingForCommit(data)); diff --git a/src/shell/workspace.rs b/src/shell/workspace.rs index 77210ca2..98296514 100644 --- a/src/shell/workspace.rs +++ b/src/shell/workspace.rs @@ -69,7 +69,7 @@ use super::{ target::{KeyboardFocusTarget, PointerFocusTarget, WindowGroup}, FocusDirection, FocusStack, FocusStackMut, }, - grabs::{ReleaseMode, ResizeEdge, ResizeGrab}, + grabs::ResizeEdge, layout::tiling::{Data, NodeDesc}, CosmicMappedRenderElement, CosmicSurface, ResizeDirection, ResizeMode, }; @@ -449,34 +449,34 @@ impl Workspace { } pub fn unmaximize_request(&mut self, elem: &CosmicMapped) -> Option> { - let mut state = elem.maximized_state.lock().unwrap(); - if let Some(state) = state.take() { - match state.original_layer { - ManagedLayer::Tiling => { - // should still be mapped in tiling - self.floating_layer.unmap(&elem); - elem.output_enter(&self.output, elem.bbox()); - elem.set_maximized(false); - elem.set_geometry(state.original_geometry.to_global(&self.output)); - elem.configure(); - self.tiling_layer.recalculate(); + let mut state = elem.maximized_state.lock().unwrap(); + if let Some(state) = state.take() { + match state.original_layer { + ManagedLayer::Tiling => { + // should still be mapped in tiling + self.floating_layer.unmap(&elem); + elem.output_enter(&self.output, elem.bbox()); + elem.set_maximized(false); + elem.set_geometry(state.original_geometry.to_global(&self.output)); + elem.configure(); + self.tiling_layer.recalculate(); self.tiling_layer - .element_geometry(&elem) + .element_geometry(&elem) .map(|geo| geo.size.as_logical()) - } - ManagedLayer::Floating => { - elem.set_maximized(false); - self.floating_layer.map_internal( - elem.clone(), - Some(state.original_geometry.loc), - Some(state.original_geometry.size.as_logical()), - ); - Some(state.original_geometry.size.as_logical()) - } - ManagedLayer::Sticky => unreachable!(), } + ManagedLayer::Floating => { + elem.set_maximized(false); + self.floating_layer.map_internal( + elem.clone(), + Some(state.original_geometry.loc), + Some(state.original_geometry.size.as_logical()), + ); + Some(state.original_geometry.size.as_logical()) + } + ManagedLayer::Sticky => unreachable!(), + } } else { - None + None } } @@ -595,32 +595,6 @@ impl Workspace { .map(|f| &f.surface) } - pub fn resize_request( - &mut self, - mapped: &CosmicMapped, - seat: &Seat, - start_data: PointerGrabStartData, - edges: ResizeEdge, - ) -> Option { - if mapped.is_fullscreen(true) || mapped.is_maximized(true) { - return None; - } - - if self.floating_layer.mapped().any(|m| m == mapped) { - self.floating_layer - .resize_request( - mapped, - seat, - start_data.clone(), - edges, - ReleaseMode::NoMouseButtons, - ) - .map(Into::into) - } else { - None - } - } - pub fn resize( &mut self, focused: &KeyboardFocusTarget, diff --git a/src/wayland/handlers/compositor.rs b/src/wayland/handlers/compositor.rs index f3724dd6..372241f0 100644 --- a/src/wayland/handlers/compositor.rs +++ b/src/wayland/handlers/compositor.rs @@ -219,11 +219,11 @@ impl CompositorHandler for State { // We only want to resize once the client has acknoledged & commited the new size, // so we need to carefully track the state through different handlers. if let Some(element) = self.common.shell.element_for_wl_surface(surface).cloned() { + crate::shell::layout::floating::ResizeSurfaceGrab::apply_resize_to_location( + element.clone(), + &mut self.common.shell, + ); if let Some(workspace) = self.common.shell.space_for_mut(&element) { - crate::shell::layout::floating::ResizeSurfaceGrab::apply_resize_to_location( - element.clone(), - workspace, - ); workspace.commit(surface); } }