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.
84pub mod ffi {
85 pub use input_sys::*;
86}
87
88/// Trait for types that allow to optain the underlying raw libinput pointer.
89pub 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
100pub 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
106pub 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
130macro_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
202macro_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
229mod context;
230mod device;
231pub mod event;
232mod seat;
233
234pub use context::*;
235pub use device::*;
236pub use event::Event;
237pub use seat::*;
238