shell: Lift/refactor (un)maximize, consider sticky windows

This commit is contained in:
Victoria Brekenfeld 2023-12-20 20:45:47 +00:00 committed by Victoria Brekenfeld
parent d0136194f4
commit 807f63bb72
7 changed files with 86 additions and 86 deletions

View file

@ -2039,9 +2039,9 @@ impl State {
let current_output = seat.active_output(); let current_output = seat.active_output();
let workspace = self.common.shell.active_space_mut(&current_output); let workspace = self.common.shell.active_space_mut(&current_output);
let focus_stack = workspace.focus_stack.get(seat); let focus_stack = workspace.focus_stack.get(seat);
let focused_window = focus_stack.last(); let focused_window = focus_stack.last().cloned();
if let Some(window) = focused_window.map(|f| f.active_window()) { if let Some(window) = focused_window {
workspace.maximize_toggle(&window); self.common.shell.maximize_toggle(&window);
} }
} }
Action::Resizing(direction) => self.common.shell.set_resize_mode( Action::Resizing(direction) => self.common.shell.set_resize_mode(

View file

@ -274,13 +274,7 @@ impl Program for CosmicWindowInternal {
if let Some(mapped) = if let Some(mapped) =
state.common.shell.element_for_wl_surface(&surface).cloned() state.common.shell.element_for_wl_surface(&surface).cloned()
{ {
if let Some(workspace) = state.common.shell.space_for_mut(&mapped) { state.common.shell.maximize_toggle(&mapped)
let (window, _) = mapped
.windows()
.find(|(w, _)| w.wl_surface().as_ref() == Some(&surface))
.unwrap();
workspace.maximize_toggle(&window)
}
} }
}); });
} }

View file

@ -30,16 +30,6 @@ fn stack(state: &mut State, mapped: &CosmicMapped) {
} }
} }
fn maximize_toggle(state: &mut State, mapped: &CosmicMapped) {
if let Some(space) = state.common.shell.space_for_mut(mapped) {
if mapped.is_maximized(false) {
space.unmaximize_request(&mapped.active_window());
} else {
space.maximize_request(&mapped.active_window());
}
}
}
fn move_prev_workspace(state: &mut State, mapped: &CosmicMapped) { fn move_prev_workspace(state: &mut State, mapped: &CosmicMapped) {
let seat = state.common.last_active_seat().clone(); let seat = state.common.last_active_seat().clone();
let (current_handle, output) = { let (current_handle, output) = {
@ -138,7 +128,7 @@ pub fn tab_items(
.collect::<Vec<_>>() .collect::<Vec<_>>()
.into_iter() .into_iter()
{ {
workspace.unmaximize_request(&mapped.active_window()); workspace.unmaximize_request(&mapped);
} }
let focus_stack = workspace.focus_stack.get(&seat); let focus_stack = workspace.focus_stack.get(&seat);
workspace workspace
@ -202,7 +192,8 @@ pub fn window_items(
Some( Some(
Item::new(fl!("window-menu-maximize"), move |handle| { Item::new(fl!("window-menu-maximize"), move |handle| {
let mapped = maximize_clone.clone(); let mapped = maximize_clone.clone();
let _ = handle.insert_idle(move |state| maximize_toggle(state, &mapped)); let _ =
handle.insert_idle(move |state| state.common.shell.maximize_toggle(&mapped));
}) })
.shortcut(config.get_shortcut_for_action(&Action::Maximize)) .shortcut(config.get_shortcut_for_action(&Action::Maximize))
.toggled(window.is_maximized(false)), .toggled(window.is_maximized(false)),

View file

@ -71,7 +71,7 @@ use self::{
element::{ element::{
resize_indicator::{resize_indicator, ResizeIndicator}, resize_indicator::{resize_indicator, ResizeIndicator},
swap_indicator::{swap_indicator, SwapIndicator}, swap_indicator::{swap_indicator, SwapIndicator},
CosmicWindow, CosmicWindow, MaximizedState,
}, },
focus::target::{KeyboardFocusTarget, PointerFocusTarget}, focus::target::{KeyboardFocusTarget, PointerFocusTarget},
grabs::{ grabs::{
@ -2402,6 +2402,71 @@ impl Shell {
} }
} }
pub fn maximize_toggle(&mut self, window: &CosmicMapped) {
if window.is_maximized(true) {
self.unmaximize_request(window);
} else {
self.maximize_request(window);
}
}
pub fn maximize_request(&mut self, mapped: &CosmicMapped) {
let (managed_layer, floating_layer) = if let Some(set) = self
.workspaces
.sets
.values_mut()
.find(|set| set.sticky_layer.mapped().any(|m| m == mapped))
{
(ManagedLayer::Sticky, &mut set.sticky_layer)
} else if let Some(workspace) = self.space_for_mut(&mapped) {
let layer = if workspace.is_floating(&mapped) {
ManagedLayer::Floating
} else {
ManagedLayer::Tiling
};
(layer, &mut workspace.floating_layer)
} else {
return;
};
let mut state = mapped.maximized_state.lock().unwrap();
if state.is_none() {
*state = Some(MaximizedState {
original_geometry: floating_layer.element_geometry(&mapped).unwrap(),
original_layer: managed_layer,
});
std::mem::drop(state);
floating_layer.map_maximized(mapped.clone());
}
}
pub fn unmaximize_request(&mut self, mapped: &CosmicMapped) -> Option<Size<i32, Logical>> {
if let Some(set) = self
.workspaces
.sets
.values_mut()
.find(|set| set.sticky_layer.mapped().any(|m| m == mapped))
{
let mut state = mapped.maximized_state.lock().unwrap();
if let Some(state) = state.take() {
assert_eq!(state.original_layer, ManagedLayer::Sticky);
mapped.set_maximized(false);
set.sticky_layer.map_internal(
mapped.clone(),
Some(state.original_geometry.loc),
Some(state.original_geometry.size.as_logical()),
);
Some(state.original_geometry.size.as_logical())
} else {
None
}
} else if let Some(workspace) = self.space_for_mut(mapped) {
workspace.unmaximize_request(mapped)
} else {
None
}
}
pub fn resize_request( pub fn resize_request(
state: &mut State, state: &mut State,
surface: &WlSurface, surface: &WlSurface,

View file

@ -64,7 +64,6 @@ use super::{
element::{ element::{
resize_indicator::ResizeIndicator, stack::CosmicStackRenderElement, resize_indicator::ResizeIndicator, stack::CosmicStackRenderElement,
swap_indicator::SwapIndicator, window::CosmicWindowRenderElement, CosmicMapped, swap_indicator::SwapIndicator, window::CosmicWindowRenderElement, CosmicMapped,
MaximizedState,
}, },
focus::{ focus::{
target::{KeyboardFocusTarget, PointerFocusTarget, WindowGroup}, target::{KeyboardFocusTarget, PointerFocusTarget, WindowGroup},
@ -379,7 +378,7 @@ impl Workspace {
if mapped.maximized_state.lock().unwrap().is_some() { if mapped.maximized_state.lock().unwrap().is_some() {
// If surface is maximized then unmaximize it, so it is assigned to only one layer // If surface is maximized then unmaximize it, so it is assigned to only one layer
let _ = self.unmaximize_request(&mapped.active_window()); let _ = self.unmaximize_request(mapped);
} }
let was_floating = self.floating_layer.unmap(&mapped); let was_floating = self.floating_layer.unmap(&mapped);
@ -449,30 +448,7 @@ impl Workspace {
self.floating_layer.refresh(); self.floating_layer.refresh();
} }
pub fn maximize_request(&mut self, window: &CosmicSurface) { pub fn unmaximize_request(&mut self, elem: &CosmicMapped) -> Option<Size<i32, Logical>> {
if self.fullscreen.is_some() {
return;
}
if let Some(elem) = self.element_for_surface(window).cloned() {
let mut state = elem.maximized_state.lock().unwrap();
if state.is_none() {
*state = Some(MaximizedState {
original_geometry: self.element_geometry(&elem).unwrap(),
original_layer: if self.is_floating(&elem) {
ManagedLayer::Floating
} else {
ManagedLayer::Tiling
},
});
std::mem::drop(state);
self.floating_layer.map_maximized(elem);
}
}
}
pub fn unmaximize_request(&mut self, window: &CosmicSurface) -> Option<Size<i32, Logical>> {
if let Some(elem) = self.element_for_surface(window).cloned() {
let mut state = elem.maximized_state.lock().unwrap(); let mut state = elem.maximized_state.lock().unwrap();
if let Some(state) = state.take() { if let Some(state) = state.take() {
match state.original_layer { match state.original_layer {
@ -484,10 +460,9 @@ impl Workspace {
elem.set_geometry(state.original_geometry.to_global(&self.output)); elem.set_geometry(state.original_geometry.to_global(&self.output));
elem.configure(); elem.configure();
self.tiling_layer.recalculate(); self.tiling_layer.recalculate();
return self self.tiling_layer
.tiling_layer
.element_geometry(&elem) .element_geometry(&elem)
.map(|geo| geo.size.as_logical()); .map(|geo| geo.size.as_logical())
} }
ManagedLayer::Floating => { ManagedLayer::Floating => {
elem.set_maximized(false); elem.set_maximized(false);
@ -496,12 +471,13 @@ impl Workspace {
Some(state.original_geometry.loc), Some(state.original_geometry.loc),
Some(state.original_geometry.size.as_logical()), Some(state.original_geometry.size.as_logical()),
); );
return Some(state.original_geometry.size.as_logical()); Some(state.original_geometry.size.as_logical())
} }
ManagedLayer::Sticky => unreachable!(),
} }
} } else {
}
None None
}
} }
pub fn fullscreen_request( pub fn fullscreen_request(
@ -611,14 +587,6 @@ impl Workspace {
} }
} }
pub fn maximize_toggle(&mut self, window: &CosmicSurface) {
if window.is_maximized(true) {
self.unmaximize_request(window);
} else {
self.maximize_request(window);
}
}
pub fn get_fullscreen(&self) -> Option<&CosmicSurface> { pub fn get_fullscreen(&self) -> Option<&CosmicSurface> {
self.fullscreen self.fullscreen
.as_ref() .as_ref()
@ -710,7 +678,7 @@ impl Workspace {
pub fn toggle_floating_window(&mut self, seat: &Seat<State>, window: &CosmicMapped) { pub fn toggle_floating_window(&mut self, seat: &Seat<State>, window: &CosmicMapped) {
if self.tiling_enabled { if self.tiling_enabled {
if window.is_maximized(false) { if window.is_maximized(false) {
self.unmaximize_request(&window.active_window()); self.unmaximize_request(window);
} }
if self.tiling_layer.mapped().any(|(_, m, _)| m == window) { if self.tiling_layer.mapped().any(|(_, m, _)| m == window) {
self.tiling_layer.unmap(window); self.tiling_layer.unmap(window);

View file

@ -169,13 +169,7 @@ impl XdgShellHandler for State {
.element_for_wl_surface(surface.wl_surface()) .element_for_wl_surface(surface.wl_surface())
.cloned() .cloned()
{ {
if let Some(workspace) = self.common.shell.space_for_mut(&mapped) { self.common.shell.maximize_request(&mapped)
let (window, _) = mapped
.windows()
.find(|(w, _)| w.wl_surface().as_ref() == Some(surface.wl_surface()))
.unwrap();
workspace.maximize_request(&window)
}
} }
} }
@ -186,13 +180,7 @@ impl XdgShellHandler for State {
.element_for_wl_surface(surface.wl_surface()) .element_for_wl_surface(surface.wl_surface())
.cloned() .cloned()
{ {
if let Some(workspace) = self.common.shell.space_for_mut(&mapped) { self.common.shell.unmaximize_request(&mapped);
let (window, _) = mapped
.windows()
.find(|(w, _)| w.wl_surface().as_ref() == Some(surface.wl_surface()))
.unwrap();
workspace.unmaximize_request(&window);
}
} }
} }

View file

@ -426,20 +426,14 @@ impl XwmHandler for State {
fn maximize_request(&mut self, _xwm: XwmId, window: X11Surface) { fn maximize_request(&mut self, _xwm: XwmId, window: X11Surface) {
let surface = CosmicSurface::X11(window); let surface = CosmicSurface::X11(window);
if let Some(mapped) = self.common.shell.element_for_surface(&surface).cloned() { if let Some(mapped) = self.common.shell.element_for_surface(&surface).cloned() {
if let Some(workspace) = self.common.shell.space_for_mut(&mapped) { self.common.shell.maximize_request(&mapped);
let (window, _) = mapped.windows().find(|(w, _)| w == &surface).unwrap();
workspace.maximize_request(&window);
}
} }
} }
fn unmaximize_request(&mut self, _xwm: XwmId, window: X11Surface) { fn unmaximize_request(&mut self, _xwm: XwmId, window: X11Surface) {
let surface = CosmicSurface::X11(window); let surface = CosmicSurface::X11(window);
if let Some(mapped) = self.common.shell.element_for_surface(&surface).cloned() { if let Some(mapped) = self.common.shell.element_for_surface(&surface).cloned() {
if let Some(workspace) = self.common.shell.space_for_mut(&mapped) { self.common.shell.unmaximize_request(&mapped);
let (window, _) = mapped.windows().find(|(w, _)| w == &surface).unwrap();
workspace.unmaximize_request(&window);
}
} }
} }