From d393e11bc56f95d6773c7f16560848d1c69e8a7b Mon Sep 17 00:00:00 2001 From: Amine Hassane Date: Sun, 21 Apr 2024 14:48:26 +0100 Subject: [PATCH] wayland: implement wl_touch --- src/backend.rs | 23 ++++++ src/backends/metal/input.rs | 64 ++++++++++++++++- src/ifs/wl_seat.rs | 18 ++++- src/ifs/wl_seat/event_handling.rs | 116 +++++++++++++++++++++++++++++- src/ifs/wl_seat/touch_owner.rs | 93 ++++++++++++++++++++++++ src/ifs/wl_seat/wl_touch.rs | 86 ++++++++++++++++++---- src/ifs/wl_surface.rs | 27 +++++++ src/libinput/event.rs | 62 +++++++++++++--- src/libinput/sys.rs | 16 +++++ src/tree.rs | 37 ++++++++++ wire/wl_touch.txt | 2 +- 11 files changed, 515 insertions(+), 29 deletions(-) create mode 100644 src/ifs/wl_seat/touch_owner.rs diff --git a/src/backend.rs b/src/backend.rs index da81118f..f10314ce 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -203,6 +203,23 @@ pub enum KeyState { Pressed, } +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub struct TouchPosition { + pub x: Fixed, + pub y: Fixed, + pub x_transformed: Fixed, + pub y_transformed: Fixed, +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub enum TouchEvent { + Down { pos: TouchPosition }, + Up, + Motion { pos: TouchPosition }, + Cancel, + Frame, +} + #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum ScrollAxis { Horizontal = HORIZONTAL_SCROLL as _, @@ -244,6 +261,12 @@ pub enum InputEvent { state: KeyState, }, + Touch { + seat_slot: i32, + time_usec: u64, + event: TouchEvent, + }, + AxisPx { dist: Fixed, axis: ScrollAxis, diff --git a/src/backends/metal/input.rs b/src/backends/metal/input.rs index 0f168bf7..faf06e7d 100644 --- a/src/backends/metal/input.rs +++ b/src/backends/metal/input.rs @@ -1,6 +1,6 @@ use { crate::{ - backend::{AxisSource, InputEvent, KeyState, ScrollAxis}, + backend::{AxisSource, InputEvent, KeyState, ScrollAxis, TouchEvent, TouchPosition}, backends::metal::MetalBackend, fixed::Fixed, libinput::{ @@ -91,6 +91,11 @@ impl MetalBackend { c::LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS => { self.handle_pointer_axis(event, AxisSource::Continuous) } + c::LIBINPUT_EVENT_TOUCH_DOWN => self.handle_touch_down(event), + c::LIBINPUT_EVENT_TOUCH_UP => self.handle_touch_up(event), + c::LIBINPUT_EVENT_TOUCH_MOTION => self.handle_touch_motion(event), + c::LIBINPUT_EVENT_TOUCH_CANCEL => self.handle_touch_cancel(event), + c::LIBINPUT_EVENT_TOUCH_FRAME => self.handle_touch_frame(event), _ => {} } } @@ -217,4 +222,61 @@ impl MetalBackend { dy_unaccelerated: Fixed::from_f64(dy_unaccelerated), }); } + + fn handle_touch_down(self: &Rc, event: LibInputEvent) { + let (event, dev) = unpack!(self, event, touch_event); + let pos = TouchPosition { + x: Fixed::from_f64(event.x()), + y: Fixed::from_f64(event.y()), + x_transformed: Fixed::from_f64(event.x_transformed(1)), + y_transformed: Fixed::from_f64(event.y_transformed(1)), + }; + dev.event(InputEvent::Touch { + seat_slot: event.seat_slot(), + time_usec: event.time_usec(), + event: TouchEvent::Down { pos }, + }) + } + + fn handle_touch_up(self: &Rc, event: LibInputEvent) { + let (event, dev) = unpack!(self, event, touch_event); + dev.event(InputEvent::Touch { + seat_slot: event.seat_slot(), + time_usec: event.time_usec(), + event: TouchEvent::Up, + }) + } + + fn handle_touch_motion(self: &Rc, event: LibInputEvent) { + let (event, dev) = unpack!(self, event, touch_event); + let pos = TouchPosition { + x: Fixed::from_f64(event.x()), + y: Fixed::from_f64(event.y()), + x_transformed: Fixed::from_f64(event.x_transformed(1)), + y_transformed: Fixed::from_f64(event.y_transformed(1)), + }; + dev.event(InputEvent::Touch { + seat_slot: event.seat_slot(), + time_usec: event.time_usec(), + event: TouchEvent::Motion { pos }, + }) + } + + fn handle_touch_cancel(self: &Rc, event: LibInputEvent) { + let (event, dev) = unpack!(self, event, touch_event); + dev.event(InputEvent::Touch { + seat_slot: event.seat_slot(), + time_usec: event.time_usec(), + event: TouchEvent::Cancel, + }) + } + + fn handle_touch_frame(self: &Rc, event: LibInputEvent) { + let (event, dev) = unpack!(self, event, touch_event); + dev.event(InputEvent::Touch { + seat_slot: 0, + time_usec: event.time_usec(), + event: TouchEvent::Frame, + }) + } } diff --git a/src/ifs/wl_seat.rs b/src/ifs/wl_seat.rs index 04805b19..bd2344fd 100644 --- a/src/ifs/wl_seat.rs +++ b/src/ifs/wl_seat.rs @@ -1,6 +1,8 @@ mod event_handling; mod kb_owner; mod pointer_owner; +mod touch_owner; + pub mod text_input; pub mod wl_keyboard; pub mod wl_pointer; @@ -41,6 +43,7 @@ use { zwp_input_method_keyboard_grab_v2::ZwpInputMethodKeyboardGrabV2, zwp_input_method_v2::ZwpInputMethodV2, zwp_text_input_v3::ZwpTextInputV3, }, + touch_owner::TouchOwnerHolder, wl_keyboard::{WlKeyboard, WlKeyboardError, REPEAT_INFO_SINCE}, wl_pointer::WlPointer, wl_touch::WlTouch, @@ -66,7 +69,7 @@ use { }, wire::{ wl_seat::*, ExtIdleNotificationV1Id, WlDataDeviceId, WlKeyboardId, WlPointerId, - WlSeatId, ZwlrDataControlDeviceV1Id, ZwpPrimarySelectionDeviceV1Id, + WlSeatId, WlTouchId, ZwlrDataControlDeviceV1Id, ZwpPrimarySelectionDeviceV1Id, ZwpRelativePointerV1Id, ZwpTextInputV3Id, }, xkbcommon::{DynKeyboardState, KeyboardState, KeymapId, XkbKeymap, XkbState}, @@ -90,7 +93,6 @@ pub use { pub const POINTER: u32 = 1; const KEYBOARD: u32 = 2; -#[allow(dead_code)] const TOUCH: u32 = 4; #[allow(dead_code)] @@ -138,6 +140,7 @@ pub struct WlSeatGlobal { pointer_stack_modified: Cell, found_tree: RefCell>, keyboard_node: CloneCell>, + touch_node: CloneCell>, bindings: RefCell>>>, x_data_devices: SmallMap, 1>, data_devices: RefCell>>>, @@ -162,6 +165,7 @@ pub struct WlSeatGlobal { primary_selection_serial: Cell, pointer_owner: PointerOwnerHolder, kb_owner: KbOwnerHolder, + touch_owner: TouchOwnerHolder, dropped_dnd: RefCell>, shortcuts: RefCell>>, queue_link: Cell>>>, @@ -213,6 +217,7 @@ impl WlSeatGlobal { pointer_stack_modified: Cell::new(false), found_tree: RefCell::new(vec![]), keyboard_node: CloneCell::new(state.root.clone()), + touch_node: CloneCell::new(state.root.clone()), bindings: Default::default(), x_data_devices: Default::default(), data_devices: RefCell::new(Default::default()), @@ -230,6 +235,7 @@ impl WlSeatGlobal { primary_selection_serial: Cell::new(0), pointer_owner: Default::default(), kb_owner: Default::default(), + touch_owner: Default::default(), dropped_dnd: RefCell::new(None), shortcuts: Default::default(), queue_link: Cell::new(None), @@ -1053,6 +1059,7 @@ impl WlSeatGlobal { mem::take(self.pointer_stack.borrow_mut().deref_mut()); mem::take(self.found_tree.borrow_mut().deref_mut()); self.keyboard_node.set(self.state.root.clone()); + self.touch_node.set(self.state.root.clone()); self.state .root .clone() @@ -1068,6 +1075,7 @@ impl WlSeatGlobal { self.primary_selection.set(None); self.pointer_owner.clear(); self.kb_owner.clear(); + self.touch_owner.clear(); *self.dropped_dnd.borrow_mut() = None; self.queue_link.set(None); self.tree_changed_handler.set(None); @@ -1100,6 +1108,7 @@ impl WlSeatGlobal { pointers: Default::default(), relative_pointers: Default::default(), keyboards: Default::default(), + touches: Default::default(), version, tracker: Default::default(), }); @@ -1192,6 +1201,7 @@ pub struct WlSeat { pointers: CopyHashMap>, relative_pointers: CopyHashMap>, keyboards: CopyHashMap>, + touches: CopyHashMap>, version: Version, tracker: Tracker, } @@ -1202,7 +1212,7 @@ impl WlSeat { fn send_capabilities(self: &Rc) { self.client.event(Capabilities { self_id: self.id, - capabilities: POINTER | KEYBOARD, + capabilities: POINTER | KEYBOARD | TOUCH, }) } @@ -1261,6 +1271,7 @@ impl WlSeatRequestHandler for WlSeat { let p = Rc::new(WlTouch::new(req.id, slf)); track!(self.client, p); self.client.add_client_obj(&p)?; + self.touches.set(req.id, p); Ok(()) } @@ -1298,6 +1309,7 @@ impl Object for WlSeat { self.pointers.clear(); self.relative_pointers.clear(); self.keyboards.clear(); + self.touches.clear(); } } diff --git a/src/ifs/wl_seat/event_handling.rs b/src/ifs/wl_seat/event_handling.rs index 92d86a21..54688834 100644 --- a/src/ifs/wl_seat/event_handling.rs +++ b/src/ifs/wl_seat/event_handling.rs @@ -1,6 +1,6 @@ use { crate::{ - backend::{ConnectorId, InputEvent, KeyState, AXIS_120}, + backend::{ConnectorId, InputEvent, KeyState, TouchEvent, TouchPosition, AXIS_120}, client::ClientId, config::InvokedShortcut, fixed::Fixed, @@ -23,6 +23,7 @@ use { AXIS_STOP_SINCE_VERSION, AXIS_VALUE120_SINCE_VERSION, IDENTICAL, INVERTED, POINTER_FRAME_SINCE_VERSION, WHEEL_TILT, WHEEL_TILT_SINCE_VERSION, }, + wl_touch::WlTouch, zwp_pointer_constraints_v1::{ConstraintType, SeatConstraintStatus}, zwp_relative_pointer_v1::ZwpRelativePointerV1, Dnd, SeatId, WlSeat, WlSeatGlobal, CHANGE_CURSOR_MOVED, @@ -180,6 +181,7 @@ impl WlSeatGlobal { | InputEvent::ConnectorPosition { time_usec, .. } | InputEvent::Motion { time_usec, .. } | InputEvent::Button { time_usec, .. } + | InputEvent::Touch { time_usec, .. } | InputEvent::AxisFrame { time_usec, .. } => { self.last_input_usec.set(time_usec); if self.idle_notifications.is_not_empty() { @@ -217,6 +219,11 @@ impl WlSeatGlobal { button, state, } => self.button_event(time_usec, button, state), + InputEvent::Touch { + seat_slot, + time_usec, + event, + } => self.touch_event(seat_slot, time_usec, event), InputEvent::AxisSource { source } => self.pointer_owner.axis_source(source), InputEvent::Axis120 { @@ -234,6 +241,34 @@ impl WlSeatGlobal { } } + fn touch_event(self: &Rc, id: i32, time_usec: u64, event: TouchEvent) { + let pos_transformed = |pos: TouchPosition| { + let output_pos = self.output.get().global.pos.get(); + let x = Fixed::from_f64(pos.x_transformed.to_f64() * f64::from(output_pos.width())); + let y = Fixed::from_f64(pos.y_transformed.to_f64() * f64::from(output_pos.height())); + (x, y) + }; + match event { + TouchEvent::Down { pos } => { + let (x, y) = pos_transformed(pos); + self.touch_owner.down(self, time_usec, id, x, y); + } + TouchEvent::Up => { + self.touch_owner.up(self, time_usec, id); + } + TouchEvent::Motion { pos } => { + let (x, y) = pos_transformed(pos); + self.touch_owner.motion(self, time_usec, id, x, y); + } + TouchEvent::Frame => { + self.touch_owner.frame(self); + } + TouchEvent::Cancel => { + self.touch_owner.cancel(self); + } + } + } + fn connector_position_event( self: &Rc, time_usec: u64, @@ -480,7 +515,8 @@ impl WlSeatGlobal { } pub fn focus_node(self: &Rc, node: Rc) { - self.kb_owner.set_kb_node(self, node); + self.kb_owner.set_kb_node(self, node.clone()); + self.touch_owner.set_touch_node(self, node); } fn for_each_seat(&self, ver: Version, client: ClientId, mut f: C) @@ -533,6 +569,18 @@ impl WlSeatGlobal { }) } + fn for_each_touch(&self, ver: Version, client: ClientId, mut f: C) + where + C: FnMut(&Rc), + { + self.for_each_seat(ver, client, |seat| { + let touches = seat.touches.lock(); + for touch in touches.values() { + f(touch); + } + }) + } + pub fn for_each_data_device(&self, ver: Version, client: ClientId, mut f: C) where C: FnMut(&Rc), @@ -608,6 +656,16 @@ impl WlSeatGlobal { // client.flush(); } + pub fn surface_touch_event(&self, ver: Version, surface: &WlSurface, mut f: F) + where + F: FnMut(&Rc), + { + let client = &surface.client; + self.for_each_touch(ver, client.id, |p| { + f(p); + }); + } + fn set_new_position(self: &Rc, time_usec: u64, x: Fixed, y: Fixed) { self.pos_time_usec.set(time_usec); self.pos.set((x, y)); @@ -869,6 +927,60 @@ impl WlSeatGlobal { } } +// Touch callbacks +impl WlSeatGlobal { + fn get_relative_pos(surface: &WlSurface, x: Fixed, y: Fixed) -> (Fixed, Fixed) { + let surface_pos = surface.buffer_abs_pos.get(); + let (x_rel, y_rel) = (x - surface_pos.x1(), y - surface_pos.y1()); + (x_rel, y_rel) + } + + pub fn touch_down_surface( + &self, + surface: &WlSurface, + time_usec: u64, + id: i32, + x: Fixed, + y: Fixed, + ) { + let serial = surface.client.next_serial(); + let time = (time_usec / 1000) as _; + let (x_rel, y_rel) = Self::get_relative_pos(surface, x, y); + self.surface_touch_event(Version::ALL, surface, |t| { + t.send_down(serial, time, surface.id, id, x_rel, y_rel) + }); + } + + pub fn touch_up_surface(&self, surface: &WlSurface, time_usec: u64, id: i32) { + let serial = surface.client.next_serial(); + let time = (time_usec / 1000) as _; + self.surface_touch_event(Version::ALL, surface, |t| t.send_up(serial, time, id)) + } + + pub fn touch_motion_surface( + &self, + surface: &WlSurface, + time_usec: u64, + id: i32, + x: Fixed, + y: Fixed, + ) { + let time = (time_usec / 1000) as _; + let (x_rel, y_rel) = Self::get_relative_pos(surface, x, y); + self.surface_touch_event(Version::ALL, surface, |t| { + t.send_motion(time, id, x_rel, y_rel) + }); + } + + pub fn touch_frame(&self, surface: &WlSurface) { + self.surface_touch_event(Version::ALL, surface, |t| t.send_frame()) + } + + pub fn touch_cancel(&self, surface: &WlSurface) { + self.surface_touch_event(Version::ALL, surface, |t| t.send_cancel()) + } +} + // Dnd callbacks impl WlSeatGlobal { pub fn dnd_surface_leave(&self, surface: &WlSurface, dnd: &Dnd) { diff --git a/src/ifs/wl_seat/touch_owner.rs b/src/ifs/wl_seat/touch_owner.rs new file mode 100644 index 00000000..06fdc2ef --- /dev/null +++ b/src/ifs/wl_seat/touch_owner.rs @@ -0,0 +1,93 @@ +use { + crate::{fixed::Fixed, ifs::wl_seat::WlSeatGlobal, tree::Node, utils::clonecell::CloneCell}, + std::rc::Rc, +}; + +pub struct TouchOwnerHolder { + default: Rc, + owner: CloneCell>, +} + +impl Default for TouchOwnerHolder { + fn default() -> Self { + Self { + default: Rc::new(DefaultTouchOwner), + owner: CloneCell::new(Rc::new(DefaultTouchOwner)), + } + } +} + +impl TouchOwnerHolder { + pub fn down(&self, seat: &Rc, time_usec: u64, id: i32, x: Fixed, y: Fixed) { + self.owner.get().down(seat, time_usec, id, x, y) + } + + pub fn up(&self, seat: &Rc, time_usec: u64, id: i32) { + self.owner.get().up(seat, time_usec, id) + } + + pub fn motion(&self, seat: &Rc, time_usec: u64, id: i32, x: Fixed, y: Fixed) { + self.owner.get().motion(seat, time_usec, id, x, y) + } + + pub fn frame(&self, seat: &Rc) { + self.owner.get().frame(seat) + } + + pub fn cancel(&self, seat: &Rc) { + self.owner.get().cancel(seat) + } + + pub fn set_touch_node(&self, seat: &Rc, node: Rc) { + self.owner.get().set_touch_node(seat, node); + } + + pub fn clear(&self) { + self.owner.set(self.default.clone()); + } +} + +struct DefaultTouchOwner; + +trait TouchOwner { + fn down(&self, seat: &Rc, time_usec: u64, id: i32, x: Fixed, y: Fixed); + fn up(&self, seat: &Rc, time_usec: u64, id: i32); + fn motion(&self, seat: &Rc, time_usec: u64, id: i32, x: Fixed, y: Fixed); + fn frame(&self, seat: &Rc); + fn cancel(&self, seat: &Rc); + fn set_touch_node(&self, seat: &Rc, node: Rc); +} + +impl TouchOwner for DefaultTouchOwner { + fn down(&self, seat: &Rc, time_usec: u64, id: i32, x: Fixed, y: Fixed) { + seat.touch_node + .get() + .node_on_touch_down(seat, time_usec, id, x, y); + } + + fn up(&self, seat: &Rc, time_usec: u64, id: i32) { + seat.touch_node.get().node_on_touch_up(seat, time_usec, id); + } + + fn motion(&self, seat: &Rc, time_usec: u64, id: i32, x: Fixed, y: Fixed) { + seat.touch_node + .get() + .node_on_touch_motion(seat, time_usec, id, x, y); + } + + fn frame(&self, seat: &Rc) { + seat.touch_node.get().node_on_touch_frame(seat); + } + + fn cancel(&self, seat: &Rc) { + seat.touch_node.get().node_on_touch_cancel(seat); + } + + fn set_touch_node(&self, seat: &Rc, node: Rc) { + let old = seat.touch_node.get(); + if old.node_id() == node.node_id() { + return; + } + seat.touch_node.set(node.clone()); + } +} diff --git a/src/ifs/wl_seat/wl_touch.rs b/src/ifs/wl_seat/wl_touch.rs index 6a7a5a8d..384f4543 100644 --- a/src/ifs/wl_seat/wl_touch.rs +++ b/src/ifs/wl_seat/wl_touch.rs @@ -1,29 +1,20 @@ use { crate::{ client::ClientError, + fixed::Fixed, ifs::wl_seat::WlSeat, leaks::Tracker, - object::Object, - wire::{wl_touch::*, WlTouchId}, + object::{Object, Version}, + wire::{wl_touch::*, WlSurfaceId, WlTouchId}, }, std::rc::Rc, thiserror::Error, }; #[allow(dead_code)] -const DOWN: u32 = 0; +pub const SHAPE_SINCE_VERSION: Version = Version(6); #[allow(dead_code)] -const UP: u32 = 1; -#[allow(dead_code)] -const MOTION: u32 = 2; -#[allow(dead_code)] -const FRAME: u32 = 3; -#[allow(dead_code)] -const CANCEL: u32 = 4; -#[allow(dead_code)] -const SHAPE: u32 = 5; -#[allow(dead_code)] -const ORIENTATION: u32 = 6; +pub const ORIENTATION_DIRECTION_SINCE_VERSION: Version = Version(6); pub struct WlTouch { id: WlTouchId, @@ -39,12 +30,79 @@ impl WlTouch { tracker: Default::default(), } } + + pub fn send_down( + &self, + serial: u32, + time: u32, + surface: WlSurfaceId, + id: i32, + x: Fixed, + y: Fixed, + ) { + self.seat.client.event(Down { + self_id: self.id, + serial, + time, + surface, + id, + x, + y, + }) + } + + pub fn send_up(&self, serial: u32, time: u32, id: i32) { + self.seat.client.event(Up { + self_id: self.id, + serial, + time, + id, + }) + } + + pub fn send_motion(&self, time: u32, id: i32, x: Fixed, y: Fixed) { + self.seat.client.event(Motion { + self_id: self.id, + time, + id, + x, + y, + }) + } + + pub fn send_frame(&self) { + self.seat.client.event(Frame { self_id: self.id }) + } + + pub fn send_cancel(&self) { + self.seat.client.event(Cancel { self_id: self.id }) + } + + #[allow(dead_code)] + pub fn send_shape(&self, id: i32, major: Fixed, minor: Fixed) { + self.seat.client.event(Shape { + self_id: self.id, + id, + major, + minor, + }) + } + + #[allow(dead_code)] + pub fn send_orientation(&self, id: i32, orientation: Fixed) { + self.seat.client.event(Orientation { + self_id: self.id, + id, + orientation, + }) + } } impl WlTouchRequestHandler for WlTouch { type Error = WlTouchError; fn release(&self, _req: Release, _slf: &Rc) -> Result<(), Self::Error> { + self.seat.touches.remove(&self.id); self.seat.client.remove_obj(self)?; Ok(()) } diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index 778c7ea3..ae0b931a 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -1433,6 +1433,33 @@ impl Node for WlSurface { seat.mods_surface(self, kb_state); } + fn node_on_touch_down(&self, seat: &WlSeatGlobal, time_usec: u64, id: i32, x: Fixed, y: Fixed) { + seat.touch_down_surface(&self, time_usec, id, x, y) + } + + fn node_on_touch_up(&self, seat: &WlSeatGlobal, time_usec: u64, id: i32) { + seat.touch_up_surface(&self, time_usec, id) + } + + fn node_on_touch_motion( + &self, + seat: &WlSeatGlobal, + time_usec: u64, + id: i32, + x: Fixed, + y: Fixed, + ) { + seat.touch_motion_surface(&self, time_usec, id, x, y) + } + + fn node_on_touch_frame(&self, seat: &WlSeatGlobal) { + seat.touch_frame(&self) + } + + fn node_on_touch_cancel(&self, seat: &WlSeatGlobal) { + seat.touch_cancel(&self) + } + fn node_on_button( self: Rc, seat: &Rc, diff --git a/src/libinput/event.rs b/src/libinput/event.rs index 90514e54..8e3c4a30 100644 --- a/src/libinput/event.rs +++ b/src/libinput/event.rs @@ -5,14 +5,18 @@ use { sys::{ libinput_event, libinput_event_destroy, libinput_event_get_device, libinput_event_get_keyboard_event, libinput_event_get_pointer_event, - libinput_event_get_type, libinput_event_keyboard, libinput_event_keyboard_get_key, - libinput_event_keyboard_get_key_state, libinput_event_keyboard_get_time_usec, - libinput_event_pointer, libinput_event_pointer_get_button, - libinput_event_pointer_get_button_state, libinput_event_pointer_get_dx, - libinput_event_pointer_get_dx_unaccelerated, libinput_event_pointer_get_dy, - libinput_event_pointer_get_dy_unaccelerated, libinput_event_pointer_get_scroll_value, - libinput_event_pointer_get_scroll_value_v120, libinput_event_pointer_get_time_usec, - libinput_event_pointer_has_axis, + libinput_event_get_touch_event, libinput_event_get_type, libinput_event_keyboard, + libinput_event_keyboard_get_key, libinput_event_keyboard_get_key_state, + libinput_event_keyboard_get_time_usec, libinput_event_pointer, + libinput_event_pointer_get_button, libinput_event_pointer_get_button_state, + libinput_event_pointer_get_dx, libinput_event_pointer_get_dx_unaccelerated, + libinput_event_pointer_get_dy, libinput_event_pointer_get_dy_unaccelerated, + libinput_event_pointer_get_scroll_value, libinput_event_pointer_get_scroll_value_v120, + libinput_event_pointer_get_time_usec, libinput_event_pointer_has_axis, + libinput_event_touch, libinput_event_touch_get_seat_slot, + libinput_event_touch_get_time_usec, libinput_event_touch_get_x, + libinput_event_touch_get_x_transformed, libinput_event_touch_get_y, + libinput_event_touch_get_y_transformed, }, }, std::marker::PhantomData, @@ -33,6 +37,11 @@ pub struct LibInputEventPointer<'a> { pub(super) _phantom: PhantomData<&'a ()>, } +pub struct LibInputEventTouch<'a> { + pub(super) event: *mut libinput_event_touch, + pub(super) _phantom: PhantomData<&'a ()>, +} + impl<'a> Drop for LibInputEvent<'a> { fn drop(&mut self) { unsafe { @@ -76,6 +85,18 @@ impl<'a> LibInputEvent<'a> { }) } } + + pub fn touch_event(&self) -> Option { + let res = unsafe { libinput_event_get_touch_event(self.event) }; + if res.is_null() { + None + } else { + Some(LibInputEventTouch { + event: res, + _phantom: Default::default(), + }) + } + } } impl<'a> LibInputEventKeyboard<'a> { @@ -134,3 +155,28 @@ impl<'a> LibInputEventPointer<'a> { unsafe { libinput_event_pointer_get_time_usec(self.event) } } } + +impl<'a> LibInputEventTouch<'a> { + pub fn seat_slot(&self) -> i32 { + unsafe { libinput_event_touch_get_seat_slot(self.event) } + } + pub fn x(&self) -> f64 { + unsafe { libinput_event_touch_get_x(self.event) } + } + + pub fn y(&self) -> f64 { + unsafe { libinput_event_touch_get_y(self.event) } + } + + pub fn x_transformed(&self, width: u32) -> f64 { + unsafe { libinput_event_touch_get_x_transformed(self.event, width) } + } + + pub fn y_transformed(&self, height: u32) -> f64 { + unsafe { libinput_event_touch_get_y_transformed(self.event, height) } + } + + pub fn time_usec(&self) -> u64 { + unsafe { libinput_event_touch_get_time_usec(self.event) } + } +} diff --git a/src/libinput/sys.rs b/src/libinput/sys.rs index 77e90a1e..f18800a3 100644 --- a/src/libinput/sys.rs +++ b/src/libinput/sys.rs @@ -14,6 +14,8 @@ pub struct libinput_event(u8); pub struct libinput_event_keyboard(u8); #[repr(transparent)] pub struct libinput_event_pointer(u8); +#[repr(transparent)] +pub struct libinput_event_touch(u8); #[link(name = "input")] extern "C" { @@ -140,6 +142,20 @@ extern "C" { // event: *mut libinput_event_pointer, // axis: libinput_pointer_axis, // ) -> f64; + + pub fn libinput_event_get_touch_event(event: *mut libinput_event) -> *mut libinput_event_touch; + pub fn libinput_event_touch_get_seat_slot(event: *mut libinput_event_touch) -> i32; + pub fn libinput_event_touch_get_time_usec(event: *mut libinput_event_touch) -> u64; + pub fn libinput_event_touch_get_x(event: *mut libinput_event_touch) -> f64; + pub fn libinput_event_touch_get_x_transformed( + event: *mut libinput_event_touch, + width: u32, + ) -> f64; + pub fn libinput_event_touch_get_y(event: *mut libinput_event_touch) -> f64; + pub fn libinput_event_touch_get_y_transformed( + event: *mut libinput_event_touch, + height: u32, + ) -> f64; } #[repr(C)] diff --git a/src/tree.rs b/src/tree.rs index edc13dec..d1458899 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -192,6 +192,43 @@ pub trait Node: 'static { let _ = kb_state; } + fn node_on_touch_down(&self, seat: &WlSeatGlobal, time_usec: u64, id: i32, x: Fixed, y: Fixed) { + let _ = seat; + let _ = time_usec; + let _ = id; + let _ = x; + let _ = y; + } + + fn node_on_touch_up(&self, seat: &WlSeatGlobal, time_usec: u64, id: i32) { + let _ = seat; + let _ = time_usec; + let _ = id; + } + + fn node_on_touch_motion( + &self, + seat: &WlSeatGlobal, + time_usec: u64, + id: i32, + x: Fixed, + y: Fixed, + ) { + let _ = seat; + let _ = time_usec; + let _ = id; + let _ = x; + let _ = y; + } + + fn node_on_touch_frame(&self, seat: &WlSeatGlobal) { + let _ = seat; + } + + fn node_on_touch_cancel(&self, seat: &WlSeatGlobal) { + let _ = seat; + } + fn node_on_button( self: Rc, seat: &Rc, diff --git a/wire/wl_touch.txt b/wire/wl_touch.txt index 11ec77dd..a5a21c3f 100644 --- a/wire/wl_touch.txt +++ b/wire/wl_touch.txt @@ -23,7 +23,7 @@ event up { event motion { time: u32, - id: u32, + id: i32, x: fixed, y: fixed, }