fix: release active popup grabs on toplevel destruction
If a window with an active popup grab is closed or crashes unexpectedly, the input grab state can get stuck, freezing keyboard and mouse clicks.
This patch iterates over all seats and releases the active seat grab if it is owned by the destroyed window or one of its child popups.
Signed-off-by: littlezabi <zohaibjozvi@gmail.com>
This commit is contained in:
parent
d7d6be3cdb
commit
1d72227a30
1 changed files with 37 additions and 0 deletions
|
|
@ -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::<PopupGrabData>() {
|
||||
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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue