diff --git a/src/windowing/popup_manager.rs b/src/windowing/popup_manager.rs index aa37721..9e1d588 100644 --- a/src/windowing/popup_manager.rs +++ b/src/windowing/popup_manager.rs @@ -185,4 +185,21 @@ impl PopupManager { .get(index) .map(|popup| Rc::clone(&popup.window)) } + + pub fn destroy_popup(&self, index: usize) { + let mut popups = self.popups.borrow_mut(); + if index < popups.len() { + info!("Destroying popup at index {index}"); + popups.remove(index); + } + } + + pub fn find_popup_index_by_xdg_popup_id(&self, xdg_popup_id: &ObjectId) -> Option { + for (index, popup) in self.popups.borrow().iter().enumerate() { + if popup.surface.xdg_popup.id() == *xdg_popup_id { + return Some(index); + } + } + None + } } diff --git a/src/windowing/state/dispatches.rs b/src/windowing/state/dispatches.rs index 1022a81..f91c5a6 100644 --- a/src/windowing/state/dispatches.rs +++ b/src/windowing/state/dispatches.rs @@ -187,7 +187,7 @@ impl Dispatch for WindowState { wl_pointer::Event::Leave { .. } => { state.dispatch_to_active_window(WindowEvent::PointerExited); - state.active_window = None; + state.clear_active_window(); } wl_pointer::Event::Button { @@ -251,8 +251,8 @@ impl Dispatch for WindowState { impl Dispatch for WindowState { fn event( - _state: &mut Self, - _xdg_popup: &XdgPopup, + state: &mut Self, + xdg_popup: &XdgPopup, event: xdg_popup::Event, _data: &(), _conn: &Connection, @@ -268,7 +268,20 @@ impl Dispatch for WindowState { info!("XdgPopup Configure: position=({x}, {y}), size=({width}x{height})"); } xdg_popup::Event::PopupDone => { - info!("XdgPopup dismissed"); + info!("XdgPopup dismissed by compositor"); + let popup_id = xdg_popup.id(); + let popup_index = state + .popup_manager + .as_ref() + .and_then(|pm| pm.find_popup_index_by_xdg_popup_id(&popup_id)); + + if let Some(index) = popup_index { + info!("Destroying popup at index {index}"); + state.clear_active_window_if_popup(index); + if let Some(popup_manager) = &state.popup_manager { + popup_manager.destroy_popup(index); + } + } } xdg_popup::Event::Repositioned { token } => { info!("XdgPopup repositioned with token {token}"); diff --git a/src/windowing/state/mod.rs b/src/windowing/state/mod.rs index 50577d9..e1df235 100644 --- a/src/windowing/state/mod.rs +++ b/src/windowing/state/mod.rs @@ -358,4 +358,14 @@ impl WindowState { } } } + + pub(super) const fn clear_active_window(&mut self) { + self.active_window = None; + } + + pub(super) fn clear_active_window_if_popup(&mut self, popup_index: usize) { + if self.active_window == Some(ActiveWindow::Popup(popup_index)) { + self.active_window = None; + } + } }