1 | //! # Libinput bindings for rust |
2 | //! |
3 | //! These bindings closely follow libinput's concepts and it's original API. |
4 | //! Please refer to the [libinput documentation](https://wayland.freedesktop.org/libinput/doc/latest/) |
5 | //! to understand the general structure and concepts. |
6 | //! |
7 | //! ## Differences to the C-Library: |
8 | //! |
9 | //! - Refcounting does not need to be done manually. Just call `clone` when you need an additional reference. |
10 | //! - Libinput logging cannot (currently) not be customized. |
11 | //! |
12 | //! ## Userdata handling |
13 | //! |
14 | //! Multiple types in the libinput library allow to attach a pointer of an arbitrary type, so called `userdata`. |
15 | //! Using this data is unsafe as there is no way to find out what type is stored in the libinput struct. |
16 | //! Additionally multiple references to the same libinput object may exist and userdata may be shared mutably. |
17 | //! |
18 | //! This is why using and setting userdata is an unsafe operation (except when creating an object). |
19 | //! |
20 | //! If you heavily rely on userdata, you should always stored them wrapped in a `Mutex` and use the same |
21 | //! type for every userdata access to further simplify usage. |
22 | //! |
23 | //! You need to be especially cautious when initializing libinput types from raw pointers, you obtained |
24 | //! from other libraries which may set their own userdata. If accessing their userdata make sure no shared |
25 | //! mutable access may happen and don't store something else instead, if the library does not explicitly |
26 | //! allow this. |
27 | //! |
28 | //! Generally usage of this api is error-prone and discouraged if not needed. |
29 | //! |
30 | //! ## Getting started |
31 | //! To get started check out the [`Libinput` struct](./struct.Libinput.html). |
32 | //! |
33 | //! Here's a small example that prints all events: |
34 | //! |
35 | //! ``` |
36 | //! use input::{Libinput, LibinputInterface}; |
37 | //! use std::fs::{File, OpenOptions}; |
38 | //! use std::os::unix::{fs::OpenOptionsExt, io::OwnedFd}; |
39 | //! use std::path::Path; |
40 | //! |
41 | //! extern crate libc; |
42 | //! use libc::{O_RDONLY, O_RDWR, O_WRONLY}; |
43 | //! |
44 | //! struct Interface; |
45 | //! |
46 | //! impl LibinputInterface for Interface { |
47 | //! fn open_restricted(&mut self, path: &Path, flags: i32) -> Result<OwnedFd, i32> { |
48 | //! OpenOptions::new() |
49 | //! .custom_flags(flags) |
50 | //! .read((flags & O_RDONLY != 0) | (flags & O_RDWR != 0)) |
51 | //! .write((flags & O_WRONLY != 0) | (flags & O_RDWR != 0)) |
52 | //! .open(path) |
53 | //! .map(|file| file.into()) |
54 | //! .map_err(|err| err.raw_os_error().unwrap()) |
55 | //! } |
56 | //! fn close_restricted(&mut self, fd: OwnedFd) { |
57 | //! unsafe { |
58 | //! File::from(fd); |
59 | //! } |
60 | //! } |
61 | //! } |
62 | //! |
63 | //! fn main() { |
64 | //! # // Preventing infinite execution (in particular on CI) |
65 | //! # std::thread::spawn(|| { |
66 | //! # std::thread::sleep(std::time::Duration::from_secs(5)); |
67 | //! # std::process::exit(0); |
68 | //! # }); |
69 | //! # |
70 | //! let mut input = Libinput::new_with_udev(Interface); |
71 | //! input.udev_assign_seat("seat0" ).unwrap(); |
72 | //! loop { |
73 | //! input.dispatch().unwrap(); |
74 | //! for event in &mut input { |
75 | //! println!("Got event: {:?}" , event); |
76 | //! } |
77 | //! } |
78 | //! } |
79 | //! ``` |
80 | |
81 | #![deny (missing_docs)] |
82 | |
83 | /// Unsafe raw C API. |
84 | pub mod ffi { |
85 | pub use input_sys::*; |
86 | } |
87 | |
88 | /// Trait for types that allow to optain the underlying raw libinput pointer. |
89 | pub trait AsRaw<T> { |
90 | /// Receive a raw pointer representing this type. |
91 | fn as_raw(&self) -> *const T; |
92 | |
93 | #[doc (hidden)] |
94 | fn as_raw_mut(&self) -> *mut T { |
95 | self.as_raw() as *mut _ |
96 | } |
97 | } |
98 | |
99 | /// Trait to receive the underlying context |
100 | pub trait Context { |
101 | /// Returns the underlying libinput context |
102 | fn context(&self) -> &Libinput; |
103 | } |
104 | |
105 | /// Trait for types that allow to be initialized from a raw pointer |
106 | pub trait FromRaw<T> { |
107 | #[doc (hidden)] |
108 | unsafe fn try_from_raw(ffi: *mut T, context: &context::Libinput) -> Option<Self> |
109 | where |
110 | Self: Sized; |
111 | |
112 | /// Create a new instance of this type from a raw pointer and it's context. |
113 | /// If the type of the struct is a valid libinput type, but is unknown to this library, it panics instead. |
114 | /// |
115 | /// ## Warning |
116 | /// |
117 | /// If you make use of [`Userdata`](./trait.Userdata.html) make sure you use the correct types |
118 | /// to allow receiving the set userdata. When dealing with raw pointers initialized by other |
119 | /// libraries this must be done extra carefully to select a correct representation. |
120 | /// |
121 | /// If unsure using `()` is always a safe option.. |
122 | /// |
123 | /// # Safety |
124 | /// |
125 | /// If the pointer is pointing to a different struct, invalid memory or `NULL` the returned |
126 | /// struct may panic on use or cause other undefined behavior. |
127 | unsafe fn from_raw(ffi: *mut T, context: &context::Libinput) -> Self; |
128 | } |
129 | |
130 | macro_rules! ffi_ref_struct { |
131 | ($(#[$attr:meta])* struct $struct_name:ident, $ffi_name:path, $ref_fn:path, $unref_fn:path) => ( |
132 | #[derive(Eq)] |
133 | $(#[$attr])* |
134 | pub struct $struct_name |
135 | { |
136 | ffi: *mut $ffi_name, |
137 | context: $crate::context::Libinput, |
138 | } |
139 | |
140 | impl ::std::fmt::Debug for $struct_name { |
141 | fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { |
142 | write!(f, "{} @{:p}" , stringify!($struct_name), self.as_raw()) |
143 | } |
144 | } |
145 | |
146 | impl $crate::FromRaw<$ffi_name> for $struct_name |
147 | { |
148 | unsafe fn try_from_raw(ffi: *mut $ffi_name, context: &$crate::Libinput) -> Option<Self> { |
149 | Some(Self::from_raw(ffi, context)) |
150 | } |
151 | unsafe fn from_raw(ffi: *mut $ffi_name, context: &$crate::Libinput) -> Self { |
152 | $struct_name { |
153 | ffi: $ref_fn(ffi), |
154 | context: context.clone(), |
155 | } |
156 | } |
157 | } |
158 | |
159 | impl $crate::AsRaw<$ffi_name> for $struct_name |
160 | { |
161 | fn as_raw(&self) -> *const $ffi_name { |
162 | self.ffi as *const _ |
163 | } |
164 | } |
165 | |
166 | impl $crate::Context for $struct_name |
167 | { |
168 | fn context(&self) -> &$crate::Libinput { |
169 | &self.context |
170 | } |
171 | } |
172 | |
173 | impl Clone for $struct_name { |
174 | fn clone(&self) -> Self { |
175 | unsafe { $struct_name::from_raw(self.as_raw_mut(), &self.context) } |
176 | } |
177 | } |
178 | |
179 | impl Drop for $struct_name |
180 | { |
181 | fn drop(&mut self) { |
182 | unsafe { |
183 | $unref_fn(self.ffi); |
184 | } |
185 | } |
186 | } |
187 | |
188 | impl PartialEq for $struct_name { |
189 | fn eq(&self, other: &Self) -> bool { |
190 | self.as_raw() == other.as_raw() |
191 | } |
192 | } |
193 | |
194 | impl ::std::hash::Hash for $struct_name { |
195 | fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) { |
196 | self.as_raw().hash(state); |
197 | } |
198 | } |
199 | ) |
200 | } |
201 | |
202 | macro_rules! ffi_func { |
203 | ($(#[$attr:meta])* fn $name:ident, $ffi_fn:path, bool) => ( |
204 | $(#[$attr])* |
205 | fn $name(&self) -> bool { |
206 | unsafe { $ffi_fn(self.as_raw_mut()) != 0 } |
207 | } |
208 | ); |
209 | ($(#[$attr:meta])* pub fn $name:ident, $ffi_fn:path, bool) => ( |
210 | $(#[$attr])* |
211 | pub fn $name(&self) -> bool { |
212 | unsafe { $ffi_fn(self.as_raw_mut()) != 0 } |
213 | } |
214 | ); |
215 | ($(#[$attr:meta])* fn $name:ident, $ffi_fn:path, $return_type:ty) => ( |
216 | $(#[$attr])* |
217 | fn $name(&self) -> $return_type { |
218 | unsafe { $ffi_fn(self.as_raw_mut()) as $return_type } |
219 | } |
220 | ); |
221 | ($(#[$attr:meta])* pub fn $name:ident, $ffi_fn:path, $return_type:ty) => ( |
222 | $(#[$attr])* |
223 | pub fn $name(&self) -> $return_type { |
224 | unsafe { $ffi_fn(self.as_raw_mut()) as $return_type } |
225 | } |
226 | ); |
227 | } |
228 | |
229 | mod context; |
230 | mod device; |
231 | pub mod event; |
232 | mod seat; |
233 | |
234 | pub use context::*; |
235 | pub use device::*; |
236 | pub use event::Event; |
237 | pub use seat::*; |
238 | |