fix(wayland): deliver popup Done to the parent window's widgets too

This commit is contained in:
Hojjat 2026-09-08 15:00:54 -06:00 • committed by Ashley Wulber
parent 511180679b
commit ffe1f1dbe3
3 changed files with 18 additions and 5 deletions

View file

@ -333,6 +333,7 @@ pub struct SctkSubsurface {
pub struct SctkPopupData {
pub(crate) id: core::window::Id,
pub(crate) parent: PopupParent,
pub(crate) parent_window: core::window::Id,
pub(crate) toplevel: WlSurface,
pub(crate) positioner: Arc<XdgPositioner>,
pub(crate) grab: bool,
@ -902,6 +903,7 @@ impl SctkState {
data: SctkPopupData {
id: settings.id,
parent: parent.clone(),
parent_window: settings.parent,
toplevel: toplevel.clone(),
positioner: positioner.clone(),
grab: settings.grab,
@ -1314,7 +1316,7 @@ impl SctkState {
existing.data.positioner = Arc::new(positioner);
existing.set_size(size.0, size.1, TOKEN_CTR.fetch_add(1, std::sync::atomic::Ordering::Relaxed));
_ = send_event(&self.events_sender, &self.proxy,
SctkEvent::PopupEvent { variant: crate::sctk_event::PopupEventVariant::Size(size.0, size.1), toplevel_id: existing.data.parent.wl_surface().clone(), parent_id: existing.data.parent.wl_surface().clone(), id: existing.popup.wl_surface().clone() });
SctkEvent::PopupEvent { variant: crate::sctk_event::PopupEventVariant::Size(size.0, size.1), toplevel_id: existing.data.parent.wl_surface().clone(), parent_id: existing.data.parent.wl_surface().clone(), id: existing.popup.wl_surface().clone(), parent_window: existing.data.parent_window });
return Ok(());
} else if !self.destroyed.is_empty() || self.popmgr.popup_id(settings.id).is_some() || self.popmgr.active_grab().is_some()
{
@ -1362,6 +1364,7 @@ impl SctkState {
TimeoutAction::Drop
}
} else {
let parent_window = settings.parent;
match state.get_popup(settings) {
Ok((id, parent_id, toplevel_id, surface, common)) => {
let wl_surface = surface.wl_surface().clone();
@ -1369,7 +1372,7 @@ impl SctkState {
send_event(&state.events_sender, &state.proxy,
SctkEvent::PopupEvent {
variant: crate::platform_specific::wayland::sctk_event::PopupEventVariant::Created(queue_handle.clone(), surface, id, common, state.connection.display()),
toplevel_id, parent_id, id: wl_surface });
toplevel_id, parent_id, id: wl_surface, parent_window });
}
Err(err) => {
log::error!("Failed to create popup. {err:?}");
@ -1380,6 +1383,7 @@ impl SctkState {
});
}
} else {
let parent_window = settings.parent;
match self.get_popup(settings) {
Ok((id, parent_id, toplevel_id, surface, common)) => {
let wl_surface = surface.wl_surface().clone();
@ -1388,7 +1392,7 @@ impl SctkState {
variant: crate::platform_specific::wayland::sctk_event::PopupEventVariant::Created(
self.queue_handle.clone(), surface, id, common, self.connection.display()
),
toplevel_id, parent_id, id: wl_surface }
toplevel_id, parent_id, id: wl_surface, parent_window }
);
}
Err(err) => {
@ -1413,7 +1417,7 @@ impl SctkState {
sctk_popup.set_size(width, height, TOKEN_CTR.fetch_add(1, std::sync::atomic::Ordering::Relaxed));
let surface = sctk_popup.popup.wl_surface().clone();
_ = send_event(&self.events_sender, &self.proxy,
SctkEvent::PopupEvent { variant: crate::sctk_event::PopupEventVariant::Size(width, height), toplevel_id: sctk_popup.data.parent.wl_surface().clone(), parent_id: sctk_popup.data.parent.wl_surface().clone(), id: surface });
SctkEvent::PopupEvent { variant: crate::sctk_event::PopupEventVariant::Size(width, height), toplevel_id: sctk_popup.data.parent.wl_surface().clone(), parent_id: sctk_popup.data.parent.wl_surface().clone(), id: surface, parent_window: sctk_popup.data.parent_window });
}
},
platform_specific::wayland::popup::Action::Reposition { id, positioner } => {
@ -1453,7 +1457,7 @@ impl SctkState {
sctk_popup.data.positioner.set_size(w as i32, h as i32);
sctk_popup.popup.reposition(&sctk_popup.data.positioner, TOKEN_CTR.fetch_add(1, std::sync::atomic::Ordering::Relaxed)); let surface = sctk_popup.popup.wl_surface().clone();
_ = send_event(&self.events_sender, &self.proxy,
SctkEvent::PopupEvent { variant: crate::sctk_event::PopupEventVariant::Size(size.0, size.1), toplevel_id: sctk_popup.data.parent.wl_surface().clone(), parent_id: sctk_popup.data.parent.wl_surface().clone(), id: surface });
SctkEvent::PopupEvent { variant: crate::sctk_event::PopupEventVariant::Size(size.0, size.1), toplevel_id: sctk_popup.data.parent.wl_surface().clone(), parent_id: sctk_popup.data.parent.wl_surface().clone(), id: surface, parent_window: sctk_popup.data.parent_window });
}
},
}
@ -1852,6 +1856,7 @@ impl SctkState {
&self.proxy,
SctkEvent::PopupEvent {
variant: crate::sctk_event::PopupEventVariant::Done,
parent_window: popup.data.parent_window,
toplevel_id: popup.data.toplevel.clone(),
parent_id: popup.data.parent.wl_surface().clone(),
id: popup.popup.wl_surface().clone(),

View file

@ -38,6 +38,7 @@ impl PopupHandler for SctkState {
first,
),
id: popup.wl_surface().clone(),
parent_window: sctk_popup.data.parent_window,
toplevel_id: sctk_popup.data.toplevel.clone(),
parent_id: match &sctk_popup.data.parent {
PopupParent::LayerSurface(s) => s.clone(),
@ -70,6 +71,7 @@ impl PopupHandler for SctkState {
self.sctk_events.push(SctkEvent::PopupEvent {
variant: PopupEventVariant::Done,
parent_window: popup.data.parent_window,
toplevel_id: popup.data.toplevel.clone(),
parent_id: popup.data.parent.wl_surface().clone(),
id: popup.popup.wl_surface().clone(),

View file

@ -155,6 +155,9 @@ pub enum SctkEvent {
parent_id: WlSurface,
/// the id of this popup
id: WlSurface,
/// Window id of the parent surface, as passed in the popup settings. Needed to route
/// `Done` to the parent's widgets.
parent_window: SurfaceId,
},
SubsurfaceEvent(SubsurfaceEventVariant),
@ -920,6 +923,7 @@ impl SctkEvent {
SctkEvent::PopupEvent {
variant,
id: surface,
parent_window,
..
} => {
match variant {
@ -958,6 +962,8 @@ impl SctkEvent {
)
})
{
// tell the parent's widgets so menus can reset when the compositor dismisses them.
events.push((Some(parent_window), e.1.clone()));
events.push(e)
}
}