feat(wayland): cursors!

This commit is contained in:
Nova
2022-09-10 08:54:15 -04:00
parent 5323479670
commit 43b2b67254
6 changed files with 522 additions and 278 deletions

View File

@@ -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!(),
}