diff --git a/src/wayland/handlers/xdg_shell/mod.rs b/src/wayland/handlers/xdg_shell/mod.rs index 98b8acf6..b8288019 100644 --- a/src/wayland/handlers/xdg_shell/mod.rs +++ b/src/wayland/handlers/xdg_shell/mod.rs @@ -317,8 +317,45 @@ impl XdgShellHandler for State { } fn toplevel_destroyed(&mut self, surface: ToplevelSurface) { + for (popup, _) in smithay::desktop::PopupManager::popups_for_surface(surface.wl_surface()) { + if let smithay::desktop::PopupKind::Xdg(ref xdg_popup) = popup { + xdg_popup.send_popup_done(); + } + } + let (output, clients) = { let mut shell = self.common.shell.write(); + + for seat in shell.seats.iter() { + if let Some(data) = seat.user_data().get::() { + let mut should_ungrab = false; + let grab = data.take(); + if let Some(ref grab) = grab { + if grab.has_ended() { + should_ungrab = true; + } else if let Some(target) = grab.current_grab() { + if let Some(wl_surface) = target.wl_surface() { + if wl_surface.as_ref() == surface.wl_surface() + || smithay::desktop::PopupManager::popups_for_surface( + surface.wl_surface(), + ) + .any(|(p, _)| p.wl_surface() == wl_surface.as_ref()) + { + should_ungrab = true; + } + } + } + } + if should_ungrab { + if let Some(mut grab) = grab { + grab.ungrab(PopupUngrabStrategy::All); + } + } else { + data.set(grab); + } + } + } + let seat = shell.seats.last_active().clone(); // Clean up pending_windows for surfaces that were never mapped.