parent
d3a46b7c8a
commit
d8a9c28fa7
5 changed files with 94 additions and 17 deletions
|
|
@ -385,17 +385,23 @@ impl HandleEvent for Pointer {
|
|||
ref surface,
|
||||
surface_x,
|
||||
surface_y,
|
||||
} => {
|
||||
let do_enter = || {
|
||||
debug!("entering surface ({serial})");
|
||||
if let Some(surface) = state.get_server_surface_from_client(surface.clone()) {
|
||||
self.server.enter(serial, surface, surface_x, surface_y)
|
||||
} else {
|
||||
warn!("could not enter surface: stale surface");
|
||||
}
|
||||
};
|
||||
} => 'enter: {
|
||||
let surface_key: ObjectKey = surface.data().copied().unwrap();
|
||||
let surface_data: &SurfaceData = state.objects[surface_key].as_ref();
|
||||
let Some(surface_data): Option<&SurfaceData> =
|
||||
state.objects.get(surface_key).map(|o| o.as_ref())
|
||||
else {
|
||||
warn!("could not enter surface: stale surface");
|
||||
break 'enter;
|
||||
};
|
||||
|
||||
let mut do_enter = || {
|
||||
debug!("entering surface ({serial})");
|
||||
self.server
|
||||
.enter(serial, &surface_data.server, surface_x, surface_y);
|
||||
let window = surface_data.window.unwrap();
|
||||
state.connection.as_mut().unwrap().raise_to_top(window);
|
||||
state.last_hovered = Some(window);
|
||||
};
|
||||
|
||||
if matches!(surface_data.role, Some(SurfaceRole::Popup(_))) {
|
||||
match self.pending_enter.0.take() {
|
||||
|
|
|
|||
|
|
@ -427,6 +427,7 @@ pub struct ServerState<C: XConnection> {
|
|||
qh: ClientQueueHandle,
|
||||
to_focus: Option<x::Window>,
|
||||
last_focused_toplevel: Option<x::Window>,
|
||||
last_hovered: Option<x::Window>,
|
||||
connection: Option<C>,
|
||||
|
||||
xdg_wm_base: XdgWmBase,
|
||||
|
|
@ -468,6 +469,7 @@ impl<C: XConnection> ServerState<C> {
|
|||
dh,
|
||||
to_focus: None,
|
||||
last_focused_toplevel: None,
|
||||
last_hovered: None,
|
||||
connection: None,
|
||||
objects: Default::default(),
|
||||
associated_windows: Default::default(),
|
||||
|
|
@ -629,6 +631,9 @@ impl<C: XConnection> ServerState<C> {
|
|||
if matches!(self.last_focused_toplevel, Some(x) if x == window) {
|
||||
self.last_focused_toplevel.take();
|
||||
}
|
||||
if self.last_hovered == Some(window) {
|
||||
self.last_hovered.take();
|
||||
}
|
||||
win.mapped = false;
|
||||
|
||||
if let Some(key) = win.surface_key.take() {
|
||||
|
|
@ -792,9 +797,10 @@ impl<C: XConnection> ServerState<C> {
|
|||
let window_data = self.windows.get_mut(&window).unwrap();
|
||||
if window_data.attrs.override_redirect {
|
||||
// Override redirect is hard to convert to Wayland!
|
||||
// We will just make them be popups for the last focused toplevel.
|
||||
if let Some(win) = self.last_focused_toplevel {
|
||||
window_data.attrs.popup_for = Some(win)
|
||||
if let Some(win) = self.last_hovered {
|
||||
window_data.attrs.popup_for = Some(win);
|
||||
} else if let Some(win) = self.last_focused_toplevel {
|
||||
window_data.attrs.popup_for = Some(win);
|
||||
}
|
||||
}
|
||||
let window = self.windows.get(&window).unwrap();
|
||||
|
|
@ -932,6 +938,9 @@ impl<C: XConnection> ServerState<C> {
|
|||
if self.last_focused_toplevel == Some(window) {
|
||||
self.last_focused_toplevel.take();
|
||||
}
|
||||
if self.last_hovered == Some(window) {
|
||||
self.last_hovered.take();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ use wayland_client::{
|
|||
wl_compositor::WlCompositor,
|
||||
wl_display::WlDisplay,
|
||||
wl_keyboard::WlKeyboard,
|
||||
wl_pointer::WlPointer,
|
||||
wl_registry::WlRegistry,
|
||||
wl_seat::{self, WlSeat},
|
||||
wl_shm::{Format, WlShm},
|
||||
|
|
@ -206,6 +207,13 @@ impl super::XConnection for FakeXConnection {
|
|||
);
|
||||
self.focused_window = window.into();
|
||||
}
|
||||
|
||||
fn raise_to_top(&mut self, window: Window) {
|
||||
assert!(
|
||||
self.windows.contains_key(&window),
|
||||
"Unknown window: {window:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
type FakeServerState = ServerState<FakeXConnection>;
|
||||
|
|
@ -1120,6 +1128,56 @@ fn clipboard_x11_then_wayland() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn raise_window_on_pointer_event() {
|
||||
let (mut f, comp) = TestFixture::new_with_compositor();
|
||||
TestObject::<WlPointer>::from_request(&comp.seat.obj, wl_seat::Request::GetPointer {});
|
||||
let win1 = unsafe { Window::new(1) };
|
||||
let (_, id1) = f.create_toplevel(&comp, win1);
|
||||
f.testwl.configure_toplevel(id1, 100, 100, vec![]);
|
||||
|
||||
let win2 = unsafe { Window::new(2) };
|
||||
let (_, id2) = f.create_toplevel(&comp, win2);
|
||||
assert_eq!(f.connection().focused_window, Some(win2));
|
||||
|
||||
f.testwl.move_pointer_to(id2, 0.0, 0.0);
|
||||
f.run();
|
||||
assert_eq!(f.connection().focused_window, Some(win2));
|
||||
assert_eq!(f.exwayland.last_hovered, Some(win2));
|
||||
|
||||
f.testwl.move_pointer_to(id1, 0.0, 0.0);
|
||||
f.run();
|
||||
assert_eq!(f.connection().focused_window, Some(win2));
|
||||
assert_eq!(f.exwayland.last_hovered, Some(win1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn override_redirect_choose_hover_window() {
|
||||
let (mut f, comp) = TestFixture::new_with_compositor();
|
||||
TestObject::<WlPointer>::from_request(&comp.seat.obj, wl_seat::Request::GetPointer {});
|
||||
let win1 = unsafe { Window::new(1) };
|
||||
let (_, id1) = f.create_toplevel(&comp, win1);
|
||||
f.testwl.configure_toplevel(id1, 100, 100, vec![]);
|
||||
|
||||
let win2 = unsafe { Window::new(2) };
|
||||
let _ = f.create_toplevel(&comp, win2);
|
||||
assert_eq!(f.connection().focused_window, Some(win2));
|
||||
|
||||
f.testwl.move_pointer_to(id1, 0.0, 0.0);
|
||||
f.run();
|
||||
assert_eq!(f.exwayland.last_hovered, Some(win1));
|
||||
|
||||
let win3 = unsafe { Window::new(3) };
|
||||
let (buffer, surface) = comp.create_surface();
|
||||
f.new_window(win3, true, WindowData::default(), None);
|
||||
f.map_window(&comp, win3, &surface.obj, &buffer);
|
||||
f.run();
|
||||
let id3 = f.check_new_surface();
|
||||
let popup_data = f.testwl.get_surface_data(id3).unwrap();
|
||||
let win1_xdg = &f.testwl.get_surface_data(id1).unwrap().xdg().surface;
|
||||
assert_eq!(&popup_data.popup().parent, win1_xdg);
|
||||
}
|
||||
|
||||
/// See Pointer::handle_event for an explanation.
|
||||
#[test]
|
||||
fn popup_pointer_motion_workaround() {}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue