focus-stack: Keep dragged surface in focus stack in move_request()

Replacement for https://github.com/pop-os/cosmic-comp/pull/1687, that
works correctly with multiple outputs.

We don't want another window to show a focus indicator while a window is
being dragged, so keep the window in the focus stack. If a window is
being moved out of a stack, change the focus from the stack to the
window.

`refresh_focus_stack()` doesn't seem to be called here, but for good
measure, make sure that calling that function also won't remove a
`CosmicMapped` from the focus stack if it is currently part of a move
grab for the seat.
This commit is contained in:
Ian Douglas Scott 2025-10-30 13:59:26 -07:00 committed by Ian Douglas Scott
parent e09fcec9f3
commit 7fd033295f
3 changed files with 29 additions and 13 deletions

View file

@ -7,7 +7,7 @@ use crate::{
element::{AsGlowRenderer, FromGlesError},
},
shell::{
ANIMATION_DURATION, OverviewMode,
ANIMATION_DURATION, OverviewMode, SeatMoveGrabState,
layout::{floating::FloatingLayout, tiling::TilingLayout},
},
state::State,
@ -455,17 +455,33 @@ impl Workspace {
}
pub fn refresh_focus_stack(&mut self) {
for stack in self.focus_stack.0.values_mut() {
for (seat, stack) in self.focus_stack.0.iter_mut() {
let fullscreen = self
.fullscreen
.as_ref()
.filter(|f| f.alive())
.filter(|f| f.ended_at.is_none())
.map(|f| &f.surface);
// Move grab is treated as focused, so don't change focus to a
// window while grab exists.
let move_grab_state = seat
.user_data()
.get::<SeatMoveGrabState>()
.unwrap()
.lock()
.unwrap();
let move_mapped = if let Some(move_grab_state) = &*move_grab_state {
Some(move_grab_state.element())
} else {
None
};
let mapped = || {
self.floating_layer
.mapped()
.chain(self.tiling_layer.mapped().map(|(w, _)| w))
.chain(move_mapped.iter())
};
stack.retain(|w| match w {
FocusTarget::Fullscreen(s) => fullscreen.is_some_and(|f| f == s),