diff --git a/src/server/event.rs b/src/server/event.rs index 1ad6038..abd74f1 100644 --- a/src/server/event.rs +++ b/src/server/event.rs @@ -464,6 +464,7 @@ impl HandleEvent for Pointer { }; self.scale = surface_data.scale_factor; + let surface_is_popup = matches!(surface_data.role, Some(SurfaceRole::Popup(_))); let mut do_enter = || { debug!("pointer entering {} ({serial})", surface_data.server.id()); self.server.enter( @@ -474,10 +475,12 @@ impl HandleEvent for Pointer { ); let window = surface_data.window.unwrap(); 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() { Some(e) => { let client::wl_pointer::Event::Enter { diff --git a/src/server/mod.rs b/src/server/mod.rs index 0d00346..5c14c75 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -1202,8 +1202,8 @@ impl ServerState { initial_scale = parent_surface.scale_factor; debug!( - "creating popup ({:?}) {:?} {:?} {:?} {surface_key:?} (scale: {initial_scale})", - window.window, parent, window.attrs.dims, surface_id + "creating popup ({:?}) {:?} {:?} {:?} {:?} {surface_key:?} (scale: {initial_scale})", + window.window, parent, window.attrs.dims, surface_id, xdg_surface.id() ); let positioner = self.xdg_wm_base.create_positioner(&self.qh, ()); diff --git a/src/server/tests.rs b/src/server/tests.rs index 22887a2..baa68f6 100644 --- a/src/server/tests.rs +++ b/src/server/tests.rs @@ -703,6 +703,7 @@ impl TestFixture { (surface, id) } + #[track_caller] fn create_popup( &mut self, comp: &Compositor, @@ -746,13 +747,13 @@ impl TestFixture { surface_data.role ); - let toplevel_xdg = &self + let parent_xdg = &self .testwl .get_surface_data(parent_surface) .unwrap() .xdg() .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; 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 })); } +#[test] +fn subpopup_positioning() { + let (mut f, comp) = TestFixture::new_with_compositor(); + TestObject::::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. #[test] fn popup_pointer_motion_workaround() {}