workspace: Animation and geometry fixes around maximized windows

This commit is contained in:
Victoria Brekenfeld 2025-07-04 19:28:46 +02:00 committed by Victoria Brekenfeld
parent a7b369fab3
commit 7a52eff61e

View file

@ -948,21 +948,24 @@ impl Workspace {
match state.original_layer { match state.original_layer {
ManagedLayer::Tiling if self.tiling_enabled => { ManagedLayer::Tiling if self.tiling_enabled => {
// should still be mapped in tiling // should still be mapped in tiling
self.floating_layer.unmap(&elem, None); let geo = self.tiling_layer.element_geometry(&elem);
self.floating_layer.unmap(&elem, geo);
elem.output_enter(&self.output, elem.bbox()); elem.output_enter(&self.output, elem.bbox());
elem.set_maximized(false); elem.set_maximized(false);
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();
self.tiling_layer.element_geometry(&elem) geo
} }
ManagedLayer::Sticky => unreachable!(), ManagedLayer::Sticky => unreachable!(),
_ => {
x => {
let use_geometry = !matches!(x, ManagedLayer::Tiling);
elem.set_maximized(false); elem.set_maximized(false);
self.floating_layer.map_internal( self.floating_layer.map_internal(
elem.clone(), elem.clone(),
Some(state.original_geometry.loc), use_geometry.then_some(state.original_geometry.loc),
Some(state.original_geometry.size.as_logical()), use_geometry.then_some(state.original_geometry.size.as_logical()),
None, None,
); );
Some(state.original_geometry) Some(state.original_geometry)
@ -1016,38 +1019,54 @@ impl Workspace {
.mapped() .mapped()
.find(|m| m.windows().any(|(ref s, _)| s == surface)) .find(|m| m.windows().any(|(ref s, _)| s == surface))
.cloned()?; .cloned()?;
let was_maximized = if mapped.maximized_state.lock().unwrap().is_some() { let was_maximized = if let Some(MaximizedState {
// If surface is maximized then unmaximize it, so it is assigned to only one layer original_geometry,
let _ = self.unmaximize_request(&mapped); original_layer,
true }) = mapped.maximized_state.lock().unwrap().take()
{
// we need to do this manually instead of calling `self.unmaximize_request`
// to get the correct animation in the tiling case.
match original_layer {
ManagedLayer::Tiling if self.tiling_enabled => {
self.floating_layer.unmap(&mapped, Some(to));
}
_ => {}
}
mapped.set_geometry(original_geometry.to_global(&self.output));
mapped.set_maximized(false);
Some(original_geometry)
} else { } else {
false None
}; };
mapped.set_minimized(true);
mapped.configure();
if let Some(geometry) = self.floating_layer.unmap(&mapped, Some(to)) { if let Some(geometry) = self.floating_layer.unmap(&mapped, Some(to)) {
mapped.set_minimized(true);
return Some(MinimizedWindow::Floating { return Some(MinimizedWindow::Floating {
window: mapped, window: mapped,
previous: FloatingRestoreData { previous: FloatingRestoreData {
geometry, geometry: was_maximized.unwrap_or(geometry),
output_size: self.output.geometry().size.as_logical(), output_size: self.output.geometry().size.as_logical(),
was_maximized, was_maximized: was_maximized.is_some(),
}, },
}); });
} }
if let Ok(state) = self.tiling_layer.unmap(&mapped, Some(to)) { if let Ok(state) = self
mapped.set_minimized(true); .tiling_layer
.unmap(&mapped, was_maximized.is_none().then_some(to))
{
return Some(MinimizedWindow::Tiling { return Some(MinimizedWindow::Tiling {
window: mapped, window: mapped,
previous: TilingRestoreData { previous: TilingRestoreData {
state, state,
was_maximized, was_maximized: was_maximized.is_some(),
}, },
}); });
} }
None unreachable!()
} }
pub fn unminimize( pub fn unminimize(
@ -1089,7 +1108,7 @@ impl Workspace {
original_layer: ManagedLayer::Floating, original_layer: ManagedLayer::Floating,
}); });
std::mem::drop(state); std::mem::drop(state);
self.floating_layer.map_maximized(window, geometry, false); self.floating_layer.map_maximized(window, geometry, true);
} }
None None
@ -1105,8 +1124,12 @@ impl Workspace {
window.set_minimized(false); window.set_minimized(false);
if self.tiling_enabled { if self.tiling_enabled {
let focus_stack = self.focus_stack.get(seat); let focus_stack = self.focus_stack.get(seat);
self.tiling_layer self.tiling_layer.remap(
.remap(window.clone(), None, state, Some(focus_stack.iter())); window.clone(),
(!was_maximized).then_some(from),
state,
Some(focus_stack.iter()),
);
if was_maximized { if was_maximized {
let previous_geometry = let previous_geometry =
self.tiling_layer.element_geometry(&window).unwrap(); self.tiling_layer.element_geometry(&window).unwrap();
@ -1116,18 +1139,20 @@ impl Workspace {
original_layer: ManagedLayer::Tiling, original_layer: ManagedLayer::Tiling,
}); });
std::mem::drop(state); std::mem::drop(state);
self.floating_layer self.floating_layer.map_maximized(window, from, true);
.map_maximized(window, previous_geometry, true);
} }
} else { } else {
self.floating_layer.map(window.clone(), None); self.floating_layer.map(window.clone(), None);
let geometry = self.floating_layer.element_geometry(&window).unwrap(); let mut geometry = self.floating_layer.element_geometry(&window).unwrap();
if let Some(pending_size) = window.pending_size() {
geometry.size = pending_size.as_local();
}
if was_maximized { if was_maximized {
let mut state = window.maximized_state.lock().unwrap(); let mut state = window.maximized_state.lock().unwrap();
*state = Some(MaximizedState { *state = Some(MaximizedState {
original_geometry: geometry, original_geometry: geometry,
original_layer: ManagedLayer::Floating, original_layer: ManagedLayer::Tiling,
}); });
std::mem::drop(state); std::mem::drop(state);
self.floating_layer.map_maximized(window, from, true); self.floating_layer.map_maximized(window, from, true);
@ -1275,12 +1300,7 @@ impl Workspace {
let floating_windows = self.floating_layer.mapped().cloned().collect::<Vec<_>>(); let floating_windows = self.floating_layer.mapped().cloned().collect::<Vec<_>>();
for window in floating_windows.iter().filter(|w| w.is_maximized(false)) { for window in floating_windows.iter().filter(|w| w.is_maximized(false)) {
let original_geometry = { maximized_windows.push((window.clone(), ManagedLayer::Tiling));
let state = window.maximized_state.lock().unwrap();
state.as_ref().unwrap().original_geometry.clone()
};
self.unmaximize_request(&window);
maximized_windows.push((window.clone(), ManagedLayer::Tiling, original_geometry));
} }
let focus_stack = self.focus_stack.get(seat); let focus_stack = self.focus_stack.get(seat);
@ -1300,16 +1320,8 @@ impl Workspace {
.into_iter() .into_iter()
{ {
if window.is_maximized(false) { if window.is_maximized(false) {
let original_geometry = {
let state = window.maximized_state.lock().unwrap();
state.as_ref().unwrap().original_geometry.clone()
};
self.unmaximize_request(&window); self.unmaximize_request(&window);
maximized_windows.push(( maximized_windows.push((window.clone(), ManagedLayer::Floating));
window.clone(),
ManagedLayer::Floating,
original_geometry,
));
} }
let _ = self.tiling_layer.unmap(&window, None); let _ = self.tiling_layer.unmap(&window, None);
self.floating_layer.map(window, None); self.floating_layer.map(window, None);
@ -1317,7 +1329,11 @@ impl Workspace {
workspace_state.set_workspace_tiling_state(&self.handle, TilingState::FloatingOnly); workspace_state.set_workspace_tiling_state(&self.handle, TilingState::FloatingOnly);
self.tiling_enabled = false; self.tiling_enabled = false;
} }
for (window, original_layer, original_geometry) in maximized_windows { for (window, original_layer) in maximized_windows {
let mut original_geometry = self.element_geometry(&window).unwrap();
if let Some(pending_size) = window.pending_size() {
original_geometry.size = pending_size.as_local();
}
let mut state = window.maximized_state.lock().unwrap(); let mut state = window.maximized_state.lock().unwrap();
*state = Some(MaximizedState { *state = Some(MaximizedState {
original_geometry, original_geometry,