Avoid parenting popups to other popups

Fixes #36
This commit is contained in:
Shawn Wallace 2025-04-22 21:39:20 -04:00
parent 2b5288b4b9
commit c31679aa41
3 changed files with 47 additions and 6 deletions

View file

@ -464,6 +464,7 @@ impl HandleEvent for Pointer {
}; };
self.scale = surface_data.scale_factor; self.scale = surface_data.scale_factor;
let surface_is_popup = matches!(surface_data.role, Some(SurfaceRole::Popup(_)));
let mut do_enter = || { let mut do_enter = || {
debug!("pointer entering {} ({serial})", surface_data.server.id()); debug!("pointer entering {} ({serial})", surface_data.server.id());
self.server.enter( self.server.enter(
@ -474,10 +475,12 @@ impl HandleEvent for Pointer {
); );
let window = surface_data.window.unwrap(); let window = surface_data.window.unwrap();
state.connection.as_mut().unwrap().raise_to_top(window); state.connection.as_mut().unwrap().raise_to_top(window);
state.last_hovered = Some(window); if !surface_is_popup {
state.last_hovered = Some(window);
}
}; };
if matches!(surface_data.role, Some(SurfaceRole::Popup(_))) { if surface_is_popup {
match self.pending_enter.0.take() { match self.pending_enter.0.take() {
Some(e) => { Some(e) => {
let client::wl_pointer::Event::Enter { let client::wl_pointer::Event::Enter {

View file

@ -1202,8 +1202,8 @@ impl<C: XConnection> ServerState<C> {
initial_scale = parent_surface.scale_factor; initial_scale = parent_surface.scale_factor;
debug!( debug!(
"creating popup ({:?}) {:?} {:?} {:?} {surface_key:?} (scale: {initial_scale})", "creating popup ({:?}) {:?} {:?} {:?} {:?} {surface_key:?} (scale: {initial_scale})",
window.window, parent, window.attrs.dims, surface_id window.window, parent, window.attrs.dims, surface_id, xdg_surface.id()
); );
let positioner = self.xdg_wm_base.create_positioner(&self.qh, ()); let positioner = self.xdg_wm_base.create_positioner(&self.qh, ());

View file

@ -703,6 +703,7 @@ impl TestFixture {
(surface, id) (surface, id)
} }
#[track_caller]
fn create_popup( fn create_popup(
&mut self, &mut self,
comp: &Compositor, comp: &Compositor,
@ -746,13 +747,13 @@ impl TestFixture {
surface_data.role surface_data.role
); );
let toplevel_xdg = &self let parent_xdg = &self
.testwl .testwl
.get_surface_data(parent_surface) .get_surface_data(parent_surface)
.unwrap() .unwrap()
.xdg() .xdg()
.surface; .surface;
assert_eq!(&surface_data.popup().parent, toplevel_xdg); assert_eq!(surface_data.popup().parent.id(), parent_xdg.id());
let pos = &surface_data.popup().positioner_state; let pos = &surface_data.popup().positioner_state;
if check_size_and_pos { if check_size_and_pos {
@ -2146,6 +2147,43 @@ fn toplevel_size_limits_scaled() {
assert_eq!(toplevel.max_size, Some(testwl::Vec2 { x: 100, y: 100 })); assert_eq!(toplevel.max_size, Some(testwl::Vec2 { x: 100, y: 100 }));
} }
#[test]
fn subpopup_positioning() {
let (mut f, comp) = TestFixture::new_with_compositor();
TestObject::<WlPointer>::from_request(&comp.seat.obj, wl_seat::Request::GetPointer {});
let win_toplevel = unsafe { Window::new(1) };
let (_, id_toplevel) = f.create_toplevel(&comp, win_toplevel);
f.testwl.move_pointer_to(id_toplevel, 0.0, 0.0);
f.run();
let win_popup = unsafe { Window::new(2) };
let (_, id_popup) = f.create_popup(
&comp,
PopupBuilder::new(win_popup, win_toplevel, id_toplevel)
.x(25)
.y(25),
);
f.testwl.move_pointer_to(id_popup, 1.0, 1.0);
f.run();
println!("{:?}", f.satellite.last_hovered);
let win_subpopup = unsafe { Window::new(3) };
f.create_popup(
&comp,
PopupBuilder::new(win_subpopup, win_toplevel, id_toplevel)
.x(50)
.y(50),
);
let dims = f.connection().window(win_subpopup).dims;
assert_eq!(dims.x, 50);
assert_eq!(dims.y, 50);
}
/// See Pointer::handle_event for an explanation. /// See Pointer::handle_event for an explanation.
#[test] #[test]
fn popup_pointer_motion_workaround() {} fn popup_pointer_motion_workaround() {}