feat(wayland): cursor stuff

This commit is contained in:
Nova
2025-09-09 03:13:22 -07:00
parent bd1b54cf03
commit 550087841f
5 changed files with 68 additions and 14 deletions

View File

@@ -1,3 +1,4 @@
use crate::nodes::items::panel::Geometry;
use crate::wayland::core::{seat::fixed_from_f32, surface::Surface};
use mint::Vector2;
use std::sync::Arc;
@@ -15,6 +16,7 @@ pub struct Pointer {
pub id: ObjectId,
version: u32,
focused_surface: Mutex<Weak<Surface>>,
cursor_surface: Mutex<Option<Arc<Surface>>>,
}
impl Pointer {
pub fn new(id: ObjectId, version: u32) -> Self {
@@ -22,6 +24,7 @@ impl Pointer {
id,
version,
focused_surface: Mutex::new(Weak::new()),
cursor_surface: Mutex::new(None),
}
}
@@ -167,19 +170,45 @@ impl Pointer {
*focused = Weak::new();
Ok(())
}
pub async fn cursor_surface(&self) -> Option<Arc<Surface>> {
self.cursor_surface.lock().await.clone()
}
}
impl WlPointer for Pointer {
/// https://wayland.app/protocols/wayland#wl_pointer:request:set_cursor
async fn set_cursor(
&self,
_client: &mut Client,
client: &mut Client,
_sender_id: ObjectId,
_serial: u32,
_surface: Option<ObjectId>,
_hotspot_x: i32,
_hotspot_y: i32,
surface: Option<ObjectId>,
hotspot_x: i32,
hotspot_y: i32,
) -> Result<()> {
if let Some(focused_surface) = self.focused_surface.lock().await.upgrade()
&& let Some(panel_item) = focused_surface.panel_item.lock().upgrade()
{
panel_item.set_cursor(surface.and_then(|s| client.get::<Surface>(s)).map(|s| {
let size = s
.current_state()
.buffer
.map(|b| b.buffer.size())
.unwrap_or([16; 2].into());
Geometry {
origin: [-hotspot_x, -hotspot_y].into(),
size: [size.x as u32, size.y as u32].into(),
}
}));
}
let Some(surface) = surface else {
return Ok(());
};
let Some(surface) = client.get::<Surface>(surface) else {
return Ok(());
};
self.cursor_surface.lock().await.replace(surface);
Ok(())
}

View File

@@ -154,6 +154,13 @@ impl Seat {
}
Ok(())
}
pub async fn cursor_surface(&self) -> Option<Arc<Surface>> {
let Some(pointer) = self.pointer.get() else {
return None;
};
pointer.cursor_surface().await
}
}
impl WlSeat for Seat {
/// https://wayland.app/protocols/wayland#wl_seat:request:get_pointer

View File

@@ -1,6 +1,6 @@
use super::toplevel::Toplevel;
use crate::{
core::error::Result,
core::{error::Result, task},
nodes::{
drawable::model::ModelPart,
items::panel::{
@@ -9,7 +9,10 @@ use crate::{
},
wayland::{
Message,
core::{seat::SeatMessage, surface::Surface},
core::{
seat::{Seat, SeatMessage},
surface::Surface,
},
},
};
use dashmap::DashMap;
@@ -20,14 +23,16 @@ use tracing;
#[derive(Debug)]
pub struct XdgBackend {
seat: Weak<Seat>,
toplevel: Weak<Toplevel>,
children: DashMap<u64, (Weak<Surface>, ChildInfo)>,
}
impl XdgBackend {
pub fn new(toplevel: Arc<Toplevel>) -> Self {
pub fn new(seat: &Arc<Seat>, toplevel: &Arc<Toplevel>) -> Self {
Self {
toplevel: Arc::downgrade(&toplevel),
seat: Arc::downgrade(seat),
toplevel: Arc::downgrade(toplevel),
children: DashMap::new(),
}
}
@@ -127,7 +132,18 @@ impl Backend for XdgBackend {
})
}
fn apply_cursor_material(&self, _model_part: &Arc<ModelPart>) {}
fn apply_cursor_material(&self, model_part: &Arc<ModelPart>) {
let model_part = model_part.clone();
let Some(seat) = self.seat.upgrade() else {
return;
};
let _ = task::new(|| "apply cursor material", async move {
let Some(cursor) = seat.cursor_surface().await else {
return;
};
cursor.apply_material(&model_part);
});
}
fn apply_surface_material(&self, surface: SurfaceId, model_part: &Arc<ModelPart>) {
if let Some(surface) = self.surface_from_id(&surface) {
surface.apply_material(model_part);

View File

@@ -80,7 +80,9 @@ impl XdgSurface for Surface {
toplevel.reconfigure(client).await?;
let toplevel_weak = Arc::downgrade(&toplevel);
let pid = client.get::<Display>(ObjectId::DISPLAY).unwrap().pid;
let display = client.get::<Display>(ObjectId::DISPLAY).unwrap();
let seat = Arc::downgrade(display.seat.get().unwrap());
let pid = display.pid;
let configured = self.configured.clone();
self.wl_surface.add_commit_handler(move |surface, state| {
let Some(toplevel) = toplevel_weak.upgrade() else {
@@ -92,7 +94,7 @@ impl XdgSurface for Surface {
&& configured.load(std::sync::atomic::Ordering::SeqCst)
&& state.has_valid_buffer()
{
let mapped_inner = MappedInner::create(toplevel.clone(), pid);
let mapped_inner = MappedInner::create(&seat.upgrade().unwrap(), &toplevel, pid);
*surface.panel_item.lock() = Arc::downgrade(&mapped_inner.panel_item);
mapped_lock.replace(mapped_inner);
return false;

View File

@@ -4,7 +4,7 @@ use crate::{
Node,
items::panel::{PanelItem, SurfaceId},
},
wayland::core::surface::Surface,
wayland::core::{seat::Seat, surface::Surface},
};
use mint::Vector2;
use parking_lot::Mutex;
@@ -21,9 +21,9 @@ pub struct MappedInner {
pub panel_item: Arc<PanelItem<XdgBackend>>,
}
impl MappedInner {
pub fn create(toplevel: Arc<Toplevel>, pid: Option<i32>) -> Self {
pub fn create(seat: &Arc<Seat>, toplevel: &Arc<Toplevel>, pid: Option<i32>) -> Self {
let (panel_item_node, panel_item) =
PanelItem::create(Box::new(XdgBackend::new(toplevel)), pid);
PanelItem::create(Box::new(XdgBackend::new(seat, toplevel)), pid);
Self {
panel_item_node,