rich_sdl2_rust/event/
touch.rs

1//! Controls touch devices, fingers, and gestures.
2
3use static_assertions::assert_not_impl_all;
4use std::{cell::Cell, marker::PhantomData, ptr::NonNull};
5
6use crate::{bind, file::RwOps, Result, Sdl, SdlError};
7
8pub mod gesture;
9
10/// A finger input, which having coordinates and pressures.
11pub struct TouchFinger<'device> {
12    ptr: NonNull<bind::SDL_Finger>,
13    _phantom: PhantomData<&'device ()>,
14}
15
16impl std::fmt::Debug for TouchFinger<'_> {
17    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18        f.debug_struct("TouchFinger")
19            .field("id", &self.id())
20            .finish_non_exhaustive()
21    }
22}
23
24impl TouchFinger<'_> {
25    /// Returns the id of the finger.
26    #[must_use]
27    pub fn id(&self) -> i64 {
28        unsafe { self.ptr.as_ref() }.id
29    }
30    /// Returns the x pos of the finger.
31    #[must_use]
32    pub fn x(&self) -> f32 {
33        unsafe { self.ptr.as_ref() }.x
34    }
35    /// Returns the y pos of the finger.
36    #[must_use]
37    pub fn y(&self) -> f32 {
38        unsafe { self.ptr.as_ref() }.y
39    }
40    /// Returns the pressures of the finger.
41    #[must_use]
42    pub fn pressure(&self) -> f32 {
43        unsafe { self.ptr.as_ref() }.pressure
44    }
45}
46
47/// A device that receives the finger input.
48#[derive(Debug, Clone)]
49pub struct TouchDevice(bind::SDL_TouchID, PhantomData<Cell<u8>>);
50
51assert_not_impl_all!(TouchDevice: Send, Sync);
52
53impl TouchDevice {
54    /// Setup the system and recognize all touch devices.
55    #[must_use]
56    pub fn all_devices() -> Vec<Self> {
57        let num = unsafe { bind::SDL_GetNumTouchDevices() };
58        (0..num)
59            .map(|index| {
60                let id = unsafe { bind::SDL_GetTouchDevice(index) };
61                Self(id, PhantomData)
62            })
63            .collect()
64    }
65
66    /// Starts to record the gesture. After invoking this and record, then an event [`gesture::GestureEvent::DollarRecord`] will occur. Please handle the event.
67    #[must_use]
68    pub fn record(&self) -> bool {
69        unsafe { bind::SDL_RecordGesture(self.0) == 1 }
70    }
71
72    /// Returns all the touching fingers.
73    #[must_use]
74    pub fn touch_fingers(&self) -> Vec<TouchFinger> {
75        let num = unsafe { bind::SDL_GetNumTouchFingers(self.0) };
76        (0..num)
77            .filter_map(|index| {
78                let ptr = unsafe { bind::SDL_GetTouchFinger(self.0, index) };
79                (!ptr.is_null()).then(|| TouchFinger {
80                    ptr: NonNull::new(ptr).unwrap(),
81                    _phantom: PhantomData,
82                })
83            })
84            .collect()
85    }
86
87    /// Loads $1 template from `src` and returns the numbers of loaded templates.
88    ///
89    /// # Errors
90    ///
91    /// Returns `Err` if failed to load template data from `src`.
92    pub fn load_dollar_templates(&self, src: &RwOps) -> Result<usize> {
93        let ret = unsafe { bind::SDL_LoadDollarTemplates(self.0, src.ptr().as_ptr()) };
94        if ret <= 0 {
95            Err(SdlError::Others { msg: Sdl::error() })
96        } else {
97            Ok(ret as usize)
98        }
99    }
100}