fix(shell): distinguish between unmapping and destroying surfaces
Previously, `unmap_surface` automatically pushed all unmapped windows into the `pending_windows` list. This behavior is correct for X11 windows (which may be remapped) but incorrect for Wayland `toplevel_destroyed` events, where the role is permanently gone. This caused issues with clients like Telegram that reuse `wl_surface`s. Because the destroyed toplevel remained in `pending_windows`, a subsequent cleanup commit (e.g., null buffer) triggered a configure event. This prematurely marked the surface as `configured` in the shell state. Consequently, when the client attached a new `xdg_toplevel` role, the compositor skipped the mandatory initial configure event (assuming it was already done), causing the window to never appear. This refactors `unmap_surface` to return `Option<PendingWindow>` instead of mutating global state. - XWayland: Explicitly saves the pending window (behavior preserved). - XDG Shell: Drops the pending window, preventing ghost state interactions. Fixes #1816
This commit is contained in:
parent
e6a3a3a9c9
commit
15b6b678c1
3 changed files with 11 additions and 5 deletions
|
|
@ -2832,7 +2832,8 @@ impl Shell {
|
||||||
surface: &S,
|
surface: &S,
|
||||||
seat: &Seat<State>,
|
seat: &Seat<State>,
|
||||||
toplevel_info: &mut ToplevelInfoState<State, CosmicSurface>,
|
toplevel_info: &mut ToplevelInfoState<State, CosmicSurface>,
|
||||||
) where
|
) -> Option<PendingWindow>
|
||||||
|
where
|
||||||
CosmicSurface: PartialEq<S>,
|
CosmicSurface: PartialEq<S>,
|
||||||
{
|
{
|
||||||
for set in self.workspaces.sets.values_mut() {
|
for set in self.workspaces.sets.values_mut() {
|
||||||
|
|
@ -2890,15 +2891,16 @@ impl Shell {
|
||||||
|
|
||||||
if let Some(surface) = surface {
|
if let Some(surface) = surface {
|
||||||
toplevel_info.remove_toplevel(&surface);
|
toplevel_info.remove_toplevel(&surface);
|
||||||
self.pending_windows.push(PendingWindow {
|
return Some(PendingWindow {
|
||||||
surface,
|
surface,
|
||||||
seat: seat.clone(),
|
seat: seat.clone(),
|
||||||
fullscreen: None,
|
fullscreen: None,
|
||||||
maximized: false,
|
maximized: false,
|
||||||
});
|
});
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_current(
|
pub fn move_current(
|
||||||
|
|
|
||||||
|
|
@ -321,7 +321,7 @@ impl XdgShellHandler for State {
|
||||||
let output = shell
|
let output = shell
|
||||||
.visible_output_for_surface(surface.wl_surface())
|
.visible_output_for_surface(surface.wl_surface())
|
||||||
.cloned();
|
.cloned();
|
||||||
shell.unmap_surface(
|
let _ = shell.unmap_surface(
|
||||||
surface.wl_surface(),
|
surface.wl_surface(),
|
||||||
&seat,
|
&seat,
|
||||||
&mut self.common.toplevel_info_state,
|
&mut self.common.toplevel_info_state,
|
||||||
|
|
|
||||||
|
|
@ -873,7 +873,11 @@ impl XwmHandler for State {
|
||||||
shell.override_redirect_windows.retain(|or| or != &window);
|
shell.override_redirect_windows.retain(|or| or != &window);
|
||||||
} else {
|
} else {
|
||||||
let seat = shell.seats.last_active().clone();
|
let seat = shell.seats.last_active().clone();
|
||||||
shell.unmap_surface(&window, &seat, &mut self.common.toplevel_info_state);
|
if let Some(pending) =
|
||||||
|
shell.unmap_surface(&window, &seat, &mut self.common.toplevel_info_state)
|
||||||
|
{
|
||||||
|
shell.pending_windows.push(pending);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let outputs = if let Some(wl_surface) = window.wl_surface() {
|
let outputs = if let Some(wl_surface) = window.wl_surface() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue