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 crate::wayland::core::{seat::fixed_from_f32, surface::Surface};
|
||||||
use mint::Vector2;
|
use mint::Vector2;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -15,6 +16,7 @@ pub struct Pointer {
|
|||||||
pub id: ObjectId,
|
pub id: ObjectId,
|
||||||
version: u32,
|
version: u32,
|
||||||
focused_surface: Mutex<Weak<Surface>>,
|
focused_surface: Mutex<Weak<Surface>>,
|
||||||
|
cursor_surface: Mutex<Option<Arc<Surface>>>,
|
||||||
}
|
}
|
||||||
impl Pointer {
|
impl Pointer {
|
||||||
pub fn new(id: ObjectId, version: u32) -> Self {
|
pub fn new(id: ObjectId, version: u32) -> Self {
|
||||||
@@ -22,6 +24,7 @@ impl Pointer {
|
|||||||
id,
|
id,
|
||||||
version,
|
version,
|
||||||
focused_surface: Mutex::new(Weak::new()),
|
focused_surface: Mutex::new(Weak::new()),
|
||||||
|
cursor_surface: Mutex::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,19 +170,45 @@ impl Pointer {
|
|||||||
*focused = Weak::new();
|
*focused = Weak::new();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn cursor_surface(&self) -> Option<Arc<Surface>> {
|
||||||
|
self.cursor_surface.lock().await.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WlPointer for Pointer {
|
impl WlPointer for Pointer {
|
||||||
/// https://wayland.app/protocols/wayland#wl_pointer:request:set_cursor
|
/// https://wayland.app/protocols/wayland#wl_pointer:request:set_cursor
|
||||||
async fn set_cursor(
|
async fn set_cursor(
|
||||||
&self,
|
&self,
|
||||||
_client: &mut Client,
|
client: &mut Client,
|
||||||
_sender_id: ObjectId,
|
_sender_id: ObjectId,
|
||||||
_serial: u32,
|
_serial: u32,
|
||||||
_surface: Option<ObjectId>,
|
surface: Option<ObjectId>,
|
||||||
_hotspot_x: i32,
|
hotspot_x: i32,
|
||||||
_hotspot_y: i32,
|
hotspot_y: i32,
|
||||||
) -> Result<()> {
|
) -> 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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -154,6 +154,13 @@ impl Seat {
|
|||||||
}
|
}
|
||||||
Ok(())
|
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 {
|
impl WlSeat for Seat {
|
||||||
/// https://wayland.app/protocols/wayland#wl_seat:request:get_pointer
|
/// https://wayland.app/protocols/wayland#wl_seat:request:get_pointer
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use super::toplevel::Toplevel;
|
use super::toplevel::Toplevel;
|
||||||
use crate::{
|
use crate::{
|
||||||
core::error::Result,
|
core::{error::Result, task},
|
||||||
nodes::{
|
nodes::{
|
||||||
drawable::model::ModelPart,
|
drawable::model::ModelPart,
|
||||||
items::panel::{
|
items::panel::{
|
||||||
@@ -9,7 +9,10 @@ use crate::{
|
|||||||
},
|
},
|
||||||
wayland::{
|
wayland::{
|
||||||
Message,
|
Message,
|
||||||
core::{seat::SeatMessage, surface::Surface},
|
core::{
|
||||||
|
seat::{Seat, SeatMessage},
|
||||||
|
surface::Surface,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
@@ -20,14 +23,16 @@ use tracing;
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct XdgBackend {
|
pub struct XdgBackend {
|
||||||
|
seat: Weak<Seat>,
|
||||||
toplevel: Weak<Toplevel>,
|
toplevel: Weak<Toplevel>,
|
||||||
children: DashMap<u64, (Weak<Surface>, ChildInfo)>,
|
children: DashMap<u64, (Weak<Surface>, ChildInfo)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl XdgBackend {
|
impl XdgBackend {
|
||||||
pub fn new(toplevel: Arc<Toplevel>) -> Self {
|
pub fn new(seat: &Arc<Seat>, toplevel: &Arc<Toplevel>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
toplevel: Arc::downgrade(&toplevel),
|
seat: Arc::downgrade(seat),
|
||||||
|
toplevel: Arc::downgrade(toplevel),
|
||||||
children: DashMap::new(),
|
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>) {
|
fn apply_surface_material(&self, surface: SurfaceId, model_part: &Arc<ModelPart>) {
|
||||||
if let Some(surface) = self.surface_from_id(&surface) {
|
if let Some(surface) = self.surface_from_id(&surface) {
|
||||||
surface.apply_material(model_part);
|
surface.apply_material(model_part);
|
||||||
|
|||||||
@@ -80,7 +80,9 @@ impl XdgSurface for Surface {
|
|||||||
toplevel.reconfigure(client).await?;
|
toplevel.reconfigure(client).await?;
|
||||||
|
|
||||||
let toplevel_weak = Arc::downgrade(&toplevel);
|
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();
|
let configured = self.configured.clone();
|
||||||
self.wl_surface.add_commit_handler(move |surface, state| {
|
self.wl_surface.add_commit_handler(move |surface, state| {
|
||||||
let Some(toplevel) = toplevel_weak.upgrade() else {
|
let Some(toplevel) = toplevel_weak.upgrade() else {
|
||||||
@@ -92,7 +94,7 @@ impl XdgSurface for Surface {
|
|||||||
&& configured.load(std::sync::atomic::Ordering::SeqCst)
|
&& configured.load(std::sync::atomic::Ordering::SeqCst)
|
||||||
&& state.has_valid_buffer()
|
&& 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);
|
*surface.panel_item.lock() = Arc::downgrade(&mapped_inner.panel_item);
|
||||||
mapped_lock.replace(mapped_inner);
|
mapped_lock.replace(mapped_inner);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use crate::{
|
|||||||
Node,
|
Node,
|
||||||
items::panel::{PanelItem, SurfaceId},
|
items::panel::{PanelItem, SurfaceId},
|
||||||
},
|
},
|
||||||
wayland::core::surface::Surface,
|
wayland::core::{seat::Seat, surface::Surface},
|
||||||
};
|
};
|
||||||
use mint::Vector2;
|
use mint::Vector2;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
@@ -21,9 +21,9 @@ pub struct MappedInner {
|
|||||||
pub panel_item: Arc<PanelItem<XdgBackend>>,
|
pub panel_item: Arc<PanelItem<XdgBackend>>,
|
||||||
}
|
}
|
||||||
impl MappedInner {
|
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) =
|
let (panel_item_node, panel_item) =
|
||||||
PanelItem::create(Box::new(XdgBackend::new(toplevel)), pid);
|
PanelItem::create(Box::new(XdgBackend::new(seat, toplevel)), pid);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
panel_item_node,
|
panel_item_node,
|
||||||
|
|||||||
Reference in New Issue
Block a user