feat(wayland): cursors!
This commit is contained in:
@@ -1,21 +1,30 @@
|
||||
use super::{state::WaylandState, surface::CoreSurface, GLOBAL_DESTROY_QUEUE};
|
||||
use crate::nodes::item::Item;
|
||||
use mint::Vector2;
|
||||
use nanoid::nanoid;
|
||||
use once_cell::sync::OnceCell;
|
||||
use parking_lot::Mutex;
|
||||
use smithay::reexports::wayland_server::{
|
||||
backend::{ClientId, GlobalId},
|
||||
delegate_dispatch, delegate_global_dispatch,
|
||||
protocol::{
|
||||
wl_keyboard::{self, WlKeyboard},
|
||||
wl_pointer::{self, WlPointer},
|
||||
wl_seat::{self, Capability, WlSeat, EVT_NAME_SINCE},
|
||||
wl_touch::{self, WlTouch},
|
||||
use smithay::{
|
||||
reexports::wayland_server::{
|
||||
backend::{ClientId, GlobalId},
|
||||
delegate_dispatch, delegate_global_dispatch,
|
||||
protocol::{
|
||||
wl_keyboard::{self, WlKeyboard},
|
||||
wl_pointer::{self, WlPointer},
|
||||
wl_seat::{self, Capability, WlSeat, EVT_NAME_SINCE},
|
||||
wl_touch::{self, WlTouch},
|
||||
},
|
||||
Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource,
|
||||
},
|
||||
Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource,
|
||||
wayland::compositor,
|
||||
};
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
use std::{ops::Deref, sync::Weak};
|
||||
|
||||
use super::state::WaylandState;
|
||||
pub struct Cursor {
|
||||
pub core_surface: Weak<CoreSurface>,
|
||||
pub hotspot: Vector2<i32>,
|
||||
}
|
||||
|
||||
pub struct SeatDelegate;
|
||||
|
||||
@@ -26,6 +35,9 @@ impl SeatData {
|
||||
let seat_data = SeatData(Arc::new(SeatDataInner {
|
||||
client,
|
||||
global_id: OnceCell::new(),
|
||||
panel_item: OnceCell::new(),
|
||||
cursor: Mutex::new(None),
|
||||
cursor_changed: Mutex::new(false),
|
||||
pointer: OnceCell::new(),
|
||||
pointer_active: Mutex::new(false),
|
||||
keyboard: OnceCell::new(),
|
||||
@@ -52,6 +64,9 @@ impl Deref for SeatData {
|
||||
pub struct SeatDataInner {
|
||||
client: ClientId,
|
||||
pub global_id: OnceCell<GlobalId>,
|
||||
pub panel_item: OnceCell<Weak<Item>>,
|
||||
pub cursor: Mutex<Option<Arc<Mutex<Cursor>>>>,
|
||||
pub cursor_changed: Mutex<bool>,
|
||||
pointer: OnceCell<WlPointer>,
|
||||
pub pointer_active: Mutex<bool>,
|
||||
keyboard: OnceCell<WlKeyboard>,
|
||||
@@ -69,6 +84,12 @@ impl SeatDataInner {
|
||||
self.touch.get()
|
||||
}
|
||||
}
|
||||
impl Drop for SeatDataInner {
|
||||
fn drop(&mut self) {
|
||||
let id = self.global_id.take().unwrap();
|
||||
tokio::spawn(async move { GLOBAL_DESTROY_QUEUE.get().unwrap().send(id).await });
|
||||
}
|
||||
}
|
||||
|
||||
impl GlobalDispatch<WlSeat, SeatData, WaylandState> for SeatDelegate {
|
||||
fn bind(
|
||||
@@ -123,21 +144,50 @@ delegate_dispatch!(WaylandState: [WlSeat: SeatData] => SeatDelegate);
|
||||
|
||||
impl Dispatch<WlPointer, SeatData, WaylandState> for SeatDelegate {
|
||||
fn request(
|
||||
_state: &mut WaylandState,
|
||||
state: &mut WaylandState,
|
||||
_client: &Client,
|
||||
_resource: &WlPointer,
|
||||
request: <WlPointer as Resource>::Request,
|
||||
_data: &SeatData,
|
||||
_dh: &DisplayHandle,
|
||||
seat_data: &SeatData,
|
||||
dh: &DisplayHandle,
|
||||
_data_init: &mut DataInit<'_, WaylandState>,
|
||||
) {
|
||||
match request {
|
||||
wl_pointer::Request::SetCursor {
|
||||
serial: _,
|
||||
surface: _,
|
||||
hotspot_x: _,
|
||||
hotspot_y: _,
|
||||
} => (),
|
||||
surface,
|
||||
hotspot_x,
|
||||
hotspot_y,
|
||||
} => {
|
||||
if !*seat_data.pointer_active.lock() {
|
||||
return;
|
||||
}
|
||||
*seat_data.0.cursor_changed.lock() = true;
|
||||
if let Some(surface) = surface.as_ref() {
|
||||
compositor::with_states(surface, |data| {
|
||||
data.data_map.insert_if_missing_threadsafe(|| {
|
||||
CoreSurface::new(&state.display, dh.clone(), surface)
|
||||
});
|
||||
if !data.data_map.insert_if_missing_threadsafe(|| {
|
||||
Arc::new(Mutex::new(Cursor {
|
||||
core_surface: Arc::downgrade(
|
||||
data.data_map.get::<Arc<CoreSurface>>().unwrap(),
|
||||
),
|
||||
hotspot: Vector2::from([hotspot_x, hotspot_y]),
|
||||
}))
|
||||
}) {
|
||||
let mut cursor =
|
||||
data.data_map.get::<Arc<Mutex<Cursor>>>().unwrap().lock();
|
||||
cursor.hotspot = Vector2::from([hotspot_x, hotspot_y]);
|
||||
}
|
||||
})
|
||||
}
|
||||
*seat_data.cursor.lock() = surface.and_then(|surf| {
|
||||
compositor::with_states(&surf, |data| {
|
||||
data.data_map.get::<Arc<Mutex<Cursor>>>().cloned()
|
||||
})
|
||||
});
|
||||
}
|
||||
wl_pointer::Request::Release => (),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user