shell: Properly restore maximized state from minimize/fullscreen

This commit is contained in:
Victoria Brekenfeld 2025-07-02 15:09:06 +02:00 committed by Victoria Brekenfeld
parent b11456614f
commit 165f83fa38
3 changed files with 142 additions and 60 deletions

View file

@ -2443,7 +2443,7 @@ impl Shell {
window, window,
original_geometry.map(|rect| rect.loc), original_geometry.map(|rect| rect.loc),
original_geometry.map(|rect| rect.size.as_logical()), original_geometry.map(|rect| rect.size.as_logical()),
None, Some(set.output.geometry().to_local(&set.output)),
); );
return; return;
} }
@ -2465,6 +2465,7 @@ impl Shell {
None => self.workspaces.active_mut(&seat.active_output()).unwrap(), None => self.workspaces.active_mut(&seat.active_output()).unwrap(),
Some(FullscreenRestoreState::Sticky { .. }) => unreachable!(), Some(FullscreenRestoreState::Sticky { .. }) => unreachable!(),
}; };
let fullscreen_geometry = workspace.output.geometry().to_local(&workspace.output);
match state { match state {
None => { None => {
@ -2472,22 +2473,43 @@ impl Shell {
toplevel_enter_workspace(&window.active_window(), &workspace.handle); toplevel_enter_workspace(&window.active_window(), &workspace.handle);
if workspace.tiling_enabled { if workspace.tiling_enabled {
workspace.tiling_layer.map( workspace.tiling_layer.remap(
window, window,
Some(workspace.focus_stack.get(seat).iter()), Some(fullscreen_geometry),
None, None,
Some(workspace.focus_stack.get(seat).iter()),
); );
} else { } else {
workspace.floating_layer.map(window, None); workspace.floating_layer.map_internal(
window,
None,
None,
Some(fullscreen_geometry),
);
} }
} }
Some(FullscreenRestoreState::Floating { .. }) => { Some(FullscreenRestoreState::Floating {
state: FloatingRestoreData { was_maximized, .. },
..
}) => {
workspace.floating_layer.map_internal( workspace.floating_layer.map_internal(
window, window.clone(),
original_geometry.map(|geo| geo.loc), original_geometry.map(|geo| geo.loc),
original_geometry.map(|geo| geo.size.as_logical()), original_geometry.map(|geo| geo.size.as_logical()),
None, Some(fullscreen_geometry),
); );
if was_maximized {
let geometry = workspace.floating_layer.element_geometry(&window).unwrap();
let mut state = window.maximized_state.lock().unwrap();
*state = Some(MaximizedState {
original_geometry: geometry,
original_layer: ManagedLayer::Floating,
});
std::mem::drop(state);
workspace
.floating_layer
.map_maximized(window, fullscreen_geometry, true);
}
} }
Some(FullscreenRestoreState::Tiling { Some(FullscreenRestoreState::Tiling {
state: state:
@ -2497,16 +2519,47 @@ impl Shell {
}, },
.. ..
}) => { }) => {
let focus_stack = workspace.focus_stack.get(seat); if workspace.tiling_enabled {
workspace let focus_stack = workspace.focus_stack.get(seat);
.tiling_layer workspace.tiling_layer.remap(
.remap(window.clone(), None, state, Some(focus_stack.iter())); window.clone(),
if was_maximized { Some(fullscreen_geometry),
let previous_geometry = state,
workspace.tiling_layer.element_geometry(&window).unwrap(); Some(focus_stack.iter()),
workspace );
.floating_layer if was_maximized {
.map_maximized(window, previous_geometry, true); let previous_geometry =
workspace.tiling_layer.element_geometry(&window).unwrap();
let mut state = window.maximized_state.lock().unwrap();
*state = Some(MaximizedState {
original_geometry: previous_geometry,
original_layer: ManagedLayer::Tiling,
});
std::mem::drop(state);
workspace
.floating_layer
.map_maximized(window, fullscreen_geometry, true);
}
} else {
workspace.floating_layer.map_internal(
window.clone(),
None,
None,
Some(fullscreen_geometry),
);
if was_maximized {
let geometry = workspace.floating_layer.element_geometry(&window).unwrap();
let mut state = window.maximized_state.lock().unwrap();
*state = Some(MaximizedState {
original_geometry: geometry,
original_layer: ManagedLayer::Floating,
});
std::mem::drop(state);
workspace
.floating_layer
.map_maximized(window, fullscreen_geometry, true);
}
} }
} }
Some(FullscreenRestoreState::Sticky { .. }) => unreachable!(), Some(FullscreenRestoreState::Sticky { .. }) => unreachable!(),
@ -3940,6 +3993,7 @@ impl Shell {
previous: FloatingRestoreData { previous: FloatingRestoreData {
geometry: geo, geometry: geo,
output_size: set.output.geometry().size.as_logical(), output_size: set.output.geometry().size.as_logical(),
was_maximized: false,
}, },
}); });
} else { } else {
@ -4474,6 +4528,7 @@ impl Shell {
state: FloatingRestoreData { state: FloatingRestoreData {
geometry: from, geometry: from,
output_size: workspace.output.geometry().size.as_logical(), output_size: workspace.output.geometry().size.as_logical(),
was_maximized: false,
}, },
}), }),
Some(from), Some(from),

View file

@ -274,6 +274,7 @@ impl From<ManagedLayer> for WorkspaceRestoreData {
pub struct FloatingRestoreData { pub struct FloatingRestoreData {
pub geometry: Rectangle<i32, Local>, pub geometry: Rectangle<i32, Local>,
pub output_size: Size<i32, Logical>, pub output_size: Size<i32, Logical>,
pub was_maximized: bool,
} }
impl FloatingRestoreData { impl FloatingRestoreData {
@ -571,10 +572,13 @@ impl Workspace {
} }
pub fn unmap_element(&mut self, mapped: &CosmicMapped) -> Option<WorkspaceRestoreData> { pub fn unmap_element(&mut self, mapped: &CosmicMapped) -> Option<WorkspaceRestoreData> {
if mapped.maximized_state.lock().unwrap().is_some() { let was_maximized = 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); let _ = self.unmaximize_request(&mapped);
} true
} else {
false
};
self.focus_stack self.focus_stack
.0 .0
@ -594,18 +598,13 @@ impl Workspace {
}); });
} }
let was_maximized = if let Some(floating_geometry) = self.floating_layer.unmap(&mapped, None) {
if let Some(floating_geometry) = self.floating_layer.unmap(&mapped, None) { return Some(WorkspaceRestoreData::Floating(Some(FloatingRestoreData {
if mapped.maximized_state.lock().unwrap().is_none() { geometry: floating_geometry,
return Some(WorkspaceRestoreData::Floating(Some(FloatingRestoreData { output_size: self.output.geometry().size.as_logical(),
geometry: floating_geometry, was_maximized,
output_size: self.output.geometry().size.as_logical(), })));
}))); };
}
true
} else {
false
};
if let Ok(state) = self.tiling_layer.unmap(&mapped, None) { if let Ok(state) = self.tiling_layer.unmap(&mapped, None) {
return Some(WorkspaceRestoreData::Tiling(Some(TilingRestoreData { return Some(WorkspaceRestoreData::Tiling(Some(TilingRestoreData {
state, state,
@ -1012,37 +1011,37 @@ impl Workspace {
}); });
} }
let maybe_elem = self let mapped = self
.tiling_layer
.mapped() .mapped()
.find(|(m, _)| m.windows().any(|(ref s, _)| s == surface)) .find(|m| m.windows().any(|(ref s, _)| s == surface))
.map(|(s, _)| s.clone()); .cloned()?;
if let Some(elem) = maybe_elem { let was_maximized = if mapped.maximized_state.lock().unwrap().is_some() {
let was_maximized = self.floating_layer.unmap(&elem, None).is_some(); // If surface is maximized then unmaximize it, so it is assigned to only one layer
let previous_state = self.tiling_layer.unmap(&elem, Some(to)).unwrap(); let _ = self.unmaximize_request(&mapped);
elem.set_minimized(true); true
return Some(MinimizedWindow::Tiling { } else {
window: elem, false
previous: TilingRestoreData { };
state: previous_state,
if let Some(geometry) = self.floating_layer.unmap(&mapped, Some(to)) {
mapped.set_minimized(true);
return Some(MinimizedWindow::Floating {
window: mapped,
previous: FloatingRestoreData {
geometry,
output_size: self.output.geometry().size.as_logical(),
was_maximized, was_maximized,
}, },
}); });
} }
let maybe_elem = self if let Ok(state) = self.tiling_layer.unmap(&mapped, Some(to)) {
.floating_layer mapped.set_minimized(true);
.mapped() return Some(MinimizedWindow::Tiling {
.find(|m| m.windows().any(|(ref s, _)| s == surface)) window: mapped,
.cloned(); previous: TilingRestoreData {
if let Some(elem) = maybe_elem { state,
let geometry = self.floating_layer.unmap(&elem, Some(to)).unwrap(); was_maximized,
elem.set_minimized(true);
return Some(MinimizedWindow::Floating {
window: elem,
previous: FloatingRestoreData {
geometry,
output_size: self.output.geometry().size.as_logical(),
}, },
}); });
} }
@ -1079,7 +1078,19 @@ impl Workspace {
window.set_minimized(false); window.set_minimized(false);
self.floating_layer self.floating_layer
.remap_minimized(window, from, previous_position); .remap_minimized(window.clone(), from, previous_position);
if previous.was_maximized {
let geometry = self.floating_layer.element_geometry(&window).unwrap();
let mut state = window.maximized_state.lock().unwrap();
*state = Some(MaximizedState {
original_geometry: geometry,
original_layer: ManagedLayer::Floating,
});
std::mem::drop(state);
self.floating_layer.map_maximized(window, geometry, false);
}
None None
} }
MinimizedWindow::Tiling { MinimizedWindow::Tiling {
@ -1098,16 +1109,29 @@ impl Workspace {
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();
let mut state = window.maximized_state.lock().unwrap();
*state = Some(MaximizedState {
original_geometry: previous_geometry,
original_layer: ManagedLayer::Tiling,
});
std::mem::drop(state);
self.floating_layer self.floating_layer
.map_maximized(window, previous_geometry, true); .map_maximized(window, previous_geometry, true);
} }
} else { } else {
self.floating_layer.map(window.clone(), None);
let geometry = self.floating_layer.element_geometry(&window).unwrap();
if was_maximized { if was_maximized {
let mut state = window.maximized_state.lock().unwrap();
*state = Some(MaximizedState {
original_geometry: geometry,
original_layer: ManagedLayer::Floating,
});
std::mem::drop(state);
self.floating_layer.map_maximized(window, from, true); self.floating_layer.map_maximized(window, from, true);
} else { } else {
self.floating_layer.map(window.clone(), None);
// get the right animation // get the right animation
let geometry = self.floating_layer.element_geometry(&window).unwrap();
self.floating_layer self.floating_layer
.remap_minimized(window.clone(), from, geometry.loc); .remap_minimized(window.clone(), from, geometry.loc);
} }

View file

@ -68,7 +68,10 @@ impl ToplevelManagementHandler for State {
{ {
for mapped in workspace for mapped in workspace
.mapped() .mapped()
.filter(|m| m.maximized_state.lock().unwrap().is_some()) .filter(|m| {
m.maximized_state.lock().unwrap().is_some()
&& !m.windows().any(|(ref w, _)| w == window)
})
.cloned() .cloned()
.collect::<Vec<_>>() .collect::<Vec<_>>()
.into_iter() .into_iter()