diff --git a/src/wayland/panel_item.rs b/src/wayland/panel_item.rs index ae626a7..5e9e881 100644 --- a/src/wayland/panel_item.rs +++ b/src/wayland/panel_item.rs @@ -99,6 +99,7 @@ impl Default for ToplevelState { pub struct PanelItem { node: Weak, client_credentials: Option, + toplevel_surface: WlWeak, pub toplevel: WlWeak, pub cursor: Mutex>>, seat_data: SeatData, @@ -119,6 +120,12 @@ impl PanelItem { let panel_item = Arc::new(PanelItem { node: Arc::downgrade(&node), client_credentials, + toplevel_surface: toplevel + .data::() + .unwrap() + .xdg_surface_data + .wl_surface + .clone(), toplevel: toplevel.downgrade(), cursor: Mutex::new(None), seat_data, @@ -283,7 +290,7 @@ impl PanelItem { let Some(pointer) = panel_item.seat_data.pointer() else { return Ok(()) }; pointer.leave(0, &wl_surface); - *panel_item.seat_data.pointer_active.lock() = false; + *panel_item.seat_data.pointer_focus.lock() = None; pointer.frame(); core_surface.flush_clients(); @@ -302,11 +309,21 @@ impl PanelItem { let mut position: Vector2 = deserialize(data)?; position.x = position.x.clamp(0.0, pointer_surface_size.x as f64); position.y = position.y.clamp(0.0, pointer_surface_size.y as f64); - if panel_item.seat_data.pointer_active() { - pointer.motion(0, position.x, position.y); - } else { + + let mut pointer_focus = panel_item.seat_data.pointer_focus.lock(); + if let Some(old_surface) = pointer_focus + .as_ref() + .and_then(|surf| surf.upgrade().ok()) + .filter(|surf| surf.id() != wl_surface.id()) + { + pointer.leave(0, &old_surface); + *pointer_focus = None; + } + if pointer_focus.is_none() { pointer.enter(0, &wl_surface, position.x, position.y); - *panel_item.seat_data.pointer_active.lock() = true; + *pointer_focus = Some(wl_surface.downgrade()); + } else { + pointer.motion(0, position.x, position.y); } pointer.frame(); core_surface.flush_clients(); diff --git a/src/wayland/seat.rs b/src/wayland/seat.rs index 7a5dac9..2cf1bfe 100644 --- a/src/wayland/seat.rs +++ b/src/wayland/seat.rs @@ -17,12 +17,14 @@ use smithay::{ wl_surface::WlSurface, wl_touch::{self, WlTouch}, }, - Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource, + Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource, Weak as WlWeak, }, wayland::compositor, }; -use std::sync::Arc; -use std::{ops::Deref, sync::Weak}; +use std::{ + ops::Deref, + sync::{Arc, Weak}, +}; use xkbcommon::xkb::{self, Keymap}; pub struct Cursor { @@ -79,7 +81,7 @@ impl SeatData { global_id: OnceCell::new(), panel_item: OnceCell::new(), pointer: OnceCell::new(), - pointer_active: Mutex::new(false), + pointer_focus: Mutex::new(None), keyboard: OnceCell::new(), keyboard_info: Mutex::new(None), touch: OnceCell::new(), @@ -106,7 +108,7 @@ pub struct SeatDataInner { global_id: OnceCell, pub panel_item: OnceCell>, pointer: OnceCell, - pub pointer_active: Mutex, + pub pointer_focus: Mutex>>, keyboard: OnceCell, pub keyboard_info: Mutex>, touch: OnceCell, @@ -116,7 +118,13 @@ impl SeatDataInner { self.pointer.get() } pub fn pointer_active(&self) -> bool { - *self.pointer_active.lock() + self.pointer_focus.lock().is_some() + } + pub fn pointer_focused_surface(&self) -> Option { + self.pointer_focus + .lock() + .as_ref() + .and_then(|focus| focus.upgrade().ok()) } pub fn keyboard(&self) -> Option<&WlKeyboard> { self.keyboard.get()