input/
lib.rs

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::*;