1
0
Fork 0
forked from wry/wry
wry/src/ifs/wp_cursor_shape_device_v1.rs
2026-03-07 18:12:13 +01:00

201 lines
6.7 KiB
Rust

use {
crate::{
client::{Client, ClientError},
cursor::KnownCursor,
ifs::wl_seat::{WlSeatGlobal, tablet::TabletToolOpt},
leaks::Tracker,
object::{Object, Version},
wire::{WpCursorShapeDeviceV1Id, wp_cursor_shape_device_v1::*},
},
std::rc::Rc,
thiserror::Error,
};
const DEFAULT: u32 = 1;
const CONTEXT_MENU: u32 = 2;
const HELP: u32 = 3;
const POINTER: u32 = 4;
const PROGRESS: u32 = 5;
const WAIT: u32 = 6;
const CELL: u32 = 7;
const CROSSHAIR: u32 = 8;
const TEXT: u32 = 9;
const VERTICAL_TEXT: u32 = 10;
const ALIAS: u32 = 11;
const COPY: u32 = 12;
const MOVE: u32 = 13;
const NO_DROP: u32 = 14;
const NOT_ALLOWED: u32 = 15;
const GRAB: u32 = 16;
const GRABBING: u32 = 17;
const E_RESIZE: u32 = 18;
const N_RESIZE: u32 = 19;
const NE_RESIZE: u32 = 20;
const NW_RESIZE: u32 = 21;
const S_RESIZE: u32 = 22;
const SE_RESIZE: u32 = 23;
const SW_RESIZE: u32 = 24;
const W_RESIZE: u32 = 25;
const EW_RESIZE: u32 = 26;
const NS_RESIZE: u32 = 27;
const NESW_RESIZE: u32 = 28;
const NWSE_RESIZE: u32 = 29;
const COL_RESIZE: u32 = 30;
const ROW_RESIZE: u32 = 31;
const ALL_SCROLL: u32 = 32;
const ZOOM_IN: u32 = 33;
const ZOOM_OUT: u32 = 34;
const DND_ASK: u32 = 35;
const ALL_RESIZE: u32 = 36;
const V2: Version = Version(2);
pub enum CursorShapeCursorUser {
Seat(Rc<WlSeatGlobal>),
TabletTool(Rc<TabletToolOpt>),
}
pub struct WpCursorShapeDeviceV1 {
pub id: WpCursorShapeDeviceV1Id,
pub client: Rc<Client>,
pub cursor_user: CursorShapeCursorUser,
pub tracker: Tracker<Self>,
pub version: Version,
}
impl WpCursorShapeDeviceV1RequestHandler for WpCursorShapeDeviceV1 {
type Error = WpCursorShapeDeviceV1Error;
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.client.remove_obj(self)?;
Ok(())
}
fn set_shape(&self, req: SetShape, _slf: &Rc<Self>) -> Result<(), Self::Error> {
let cursor = KnownCursor::from_shape(req.shape, self.version)
.ok_or(WpCursorShapeDeviceV1Error::UnknownShape(req.shape))?;
let tablet_tool;
let (node_client_id, user) = match &self.cursor_user {
CursorShapeCursorUser::Seat(s) => match s.pointer_node() {
Some(n) => (n.node_client_id(), s.pointer_cursor()),
_ => return Ok(()),
},
CursorShapeCursorUser::TabletTool(t) => match t.get() {
Some(t) => {
tablet_tool = t;
(tablet_tool.node().node_client_id(), tablet_tool.cursor())
}
_ => return Ok(()),
},
};
if node_client_id != Some(self.client.id) {
return Ok(());
}
user.set_known(cursor);
Ok(())
}
}
impl KnownCursor {
pub fn from_shape(shape: u32, version: Version) -> Option<Self> {
let cursor = match shape {
DEFAULT => KnownCursor::Default,
CONTEXT_MENU => KnownCursor::ContextMenu,
HELP => KnownCursor::Help,
POINTER => KnownCursor::Pointer,
PROGRESS => KnownCursor::Progress,
WAIT => KnownCursor::Wait,
CELL => KnownCursor::Cell,
CROSSHAIR => KnownCursor::Crosshair,
TEXT => KnownCursor::Text,
VERTICAL_TEXT => KnownCursor::VerticalText,
ALIAS => KnownCursor::Alias,
COPY => KnownCursor::Copy,
MOVE => KnownCursor::Move,
NO_DROP => KnownCursor::NoDrop,
NOT_ALLOWED => KnownCursor::NotAllowed,
GRAB => KnownCursor::Grab,
GRABBING => KnownCursor::Grabbing,
E_RESIZE => KnownCursor::EResize,
N_RESIZE => KnownCursor::NResize,
NE_RESIZE => KnownCursor::NeResize,
NW_RESIZE => KnownCursor::NwResize,
S_RESIZE => KnownCursor::SResize,
SE_RESIZE => KnownCursor::SeResize,
SW_RESIZE => KnownCursor::SwResize,
W_RESIZE => KnownCursor::WResize,
EW_RESIZE => KnownCursor::EwResize,
NS_RESIZE => KnownCursor::NsResize,
NESW_RESIZE => KnownCursor::NeswResize,
NWSE_RESIZE => KnownCursor::NwseResize,
COL_RESIZE => KnownCursor::ColResize,
ROW_RESIZE => KnownCursor::RowResize,
ALL_SCROLL => KnownCursor::AllScroll,
ZOOM_IN => KnownCursor::ZoomIn,
ZOOM_OUT => KnownCursor::ZoomOut,
DND_ASK if version >= V2 => KnownCursor::DndAsk,
ALL_RESIZE if version >= V2 => KnownCursor::AllResize,
_ => return None,
};
Some(cursor)
}
pub fn to_shape(self) -> u32 {
match self {
KnownCursor::Default => DEFAULT,
KnownCursor::ContextMenu => CONTEXT_MENU,
KnownCursor::Help => HELP,
KnownCursor::Pointer => POINTER,
KnownCursor::Progress => PROGRESS,
KnownCursor::Wait => WAIT,
KnownCursor::Cell => CELL,
KnownCursor::Crosshair => CROSSHAIR,
KnownCursor::Text => TEXT,
KnownCursor::VerticalText => VERTICAL_TEXT,
KnownCursor::Alias => ALIAS,
KnownCursor::Copy => COPY,
KnownCursor::Move => MOVE,
KnownCursor::NoDrop => NO_DROP,
KnownCursor::NotAllowed => NOT_ALLOWED,
KnownCursor::Grab => GRAB,
KnownCursor::Grabbing => GRABBING,
KnownCursor::EResize => E_RESIZE,
KnownCursor::NResize => N_RESIZE,
KnownCursor::NeResize => NE_RESIZE,
KnownCursor::NwResize => NW_RESIZE,
KnownCursor::SResize => S_RESIZE,
KnownCursor::SeResize => SE_RESIZE,
KnownCursor::SwResize => SW_RESIZE,
KnownCursor::WResize => W_RESIZE,
KnownCursor::EwResize => EW_RESIZE,
KnownCursor::NsResize => NS_RESIZE,
KnownCursor::NeswResize => NESW_RESIZE,
KnownCursor::NwseResize => NWSE_RESIZE,
KnownCursor::ColResize => COL_RESIZE,
KnownCursor::RowResize => ROW_RESIZE,
KnownCursor::AllScroll => ALL_SCROLL,
KnownCursor::ZoomIn => ZOOM_IN,
KnownCursor::ZoomOut => ZOOM_OUT,
KnownCursor::DndAsk => DND_ASK,
KnownCursor::AllResize => ALL_RESIZE,
}
}
}
object_base! {
self = WpCursorShapeDeviceV1;
version = self.version;
}
impl Object for WpCursorShapeDeviceV1 {}
simple_add_obj!(WpCursorShapeDeviceV1);
#[derive(Debug, Error)]
pub enum WpCursorShapeDeviceV1Error {
#[error(transparent)]
ClientError(Box<ClientError>),
#[error("Shape {0} is unknown")]
UnknownShape(u32),
}
efrom!(WpCursorShapeDeviceV1Error, ClientError);