feat(wayland): cursor stuff
This commit is contained in:
@@ -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(())
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user