#![allow(non_camel_case_types)]
pub mod lib_input_event_type {
pub const LIBINPUT_EVENT_NONE: i32 = 0;
pub const LIBINPUT_EVENT_DEVICE_ADDED: i32 = 1;
pub const LIBINPUT_EVENT_DEVICE_REMOVED: i32 = 2;
pub const LIBINPUT_EVENT_KEYBOARD_KEY: i32 = 300;
pub const LIBINPUT_EVENT_POINTER_MOTION: i32 = 400;
pub const LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: i32 = 401;
pub const LIBINPUT_EVENT_POINTER_BUTTON: i32 = 402;
pub const LIBINPUT_EVENT_POINTER_AXIS: i32 = 403;
pub const LIBINPUT_EVENT_POINTER_SCROLL_WHEEL: i32 = 404;
pub const LIBINPUT_EVENT_POINTER_SCROLL_FINGER: i32 = 405;
pub const LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS: i32 = 406;
pub const LIBINPUT_EVENT_TOUCH_DOWN: i32 = 500;
pub const LIBINPUT_EVENT_TOUCH_UP: i32 = 501;
pub const LIBINPUT_EVENT_TOUCH_MOTION: i32 = 502;
pub const LIBINPUT_EVENT_TOUCH_CANCEL: i32 = 503;
pub const LIBINPUT_EVENT_TOUCH_FRAME: i32 = 504;
pub const LIBINPUT_EVENT_TABLET_TOOL_AXIS: i32 = 600;
pub const LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY: i32 = 601;
pub const LIBINPUT_EVENT_TABLET_TOOL_TIP: i32 = 602;
pub const LIBINPUT_EVENT_TABLET_TOOL_BUTTON: i32 = 603;
pub const LIBINPUT_EVENT_TABLET_PAD_BUTTON: i32 = 700;
pub const LIBINPUT_EVENT_TABLET_PAD_RING: i32 = 701;
pub const LIBINPUT_EVENT_TABLET_PAD_STRIP: i32 = 702;
pub const LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN: i32 = 800;
pub const LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE: i32 = 801;
pub const LIBINPUT_EVENT_GESTURE_SWIPE_END: i32 = 802;
pub const LIBINPUT_EVENT_GESTURE_PINCH_BEGIN: i32 = 803;
pub const LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: i32 = 804;
pub const LIBINPUT_EVENT_GESTURE_PINCH_END: i32 = 805;
pub const LIBINPUT_EVENT_SWITCH_TOGGLE: i32 = 900;
}
pub mod lib_input_pointer_axis_source {
pub const LIBINPUT_POINTER_AXIS_SOURCE_WHEEL: i32 = 1;
pub const LIBINPUT_POINTER_AXIS_SOURCE_FINGER: i32 = 2;
pub const LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS: i32 = 3;
pub const LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT: i32 = 4;
}
pub mod lib_input_pointer_axis {
pub const LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL: i32 = 0;
pub const LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL: i32 = 1;
}
#[cfg(target_os = "linux")]
pub use imp::LibInput;
#[cfg(target_os = "linux")]
mod imp {
use std::ffi::{c_char, c_double, c_int, c_void, CString};
#[repr(C)]
pub(crate) struct libinput_interface {
open_restricted: unsafe extern "C" fn(path: *const c_char, flags: c_int, user_data: *mut c_void) -> c_int,
close_restricted: unsafe extern "C" fn(fd: c_int, user_data: *mut c_void),
}
unsafe extern "C" fn open_restricted(path: *const c_char, flags: c_int, _user_data: *mut c_void) -> c_int {
let fd = unsafe { libc::open(path, flags, 0) };
if fd == -1 {
return -std::io::Error::last_os_error().raw_os_error().unwrap_or(libc::EIO);
}
fd
}
unsafe extern "C" fn close_restricted(fd: c_int, _user_data: *mut c_void) {
unsafe {
libc::close(fd);
}
}
static INTERFACE: libinput_interface = libinput_interface { open_restricted, close_restricted };
ferroui_base::native_functions! {
pub struct LibInput(lib) {
lib::libinput_path_create_context: unsafe extern "C" fn(*const libinput_interface, *mut c_void) -> *mut c_void;
lib::libinput_path_add_device: unsafe extern "C" fn(*mut c_void, *const c_char) -> *mut c_void;
lib::libinput_path_remove_device: unsafe extern "C" fn(*mut c_void);
lib::libinput_device_config_calibration_set_matrix: unsafe extern "C" fn(*mut c_void, *const f32) -> c_int;
lib::libinput_get_fd: unsafe extern "C" fn(*mut c_void) -> c_int;
lib::libinput_dispatch: unsafe extern "C" fn(*mut c_void) -> c_int;
lib::libinput_get_event: unsafe extern "C" fn(*mut c_void) -> *mut c_void;
lib::libinput_event_get_type: unsafe extern "C" fn(*mut c_void) -> c_int;
lib::libinput_event_destroy: unsafe extern "C" fn(*mut c_void);
lib::libinput_event_get_touch_event: unsafe extern "C" fn(*mut c_void) -> *mut c_void;
lib::libinput_event_touch_get_slot: unsafe extern "C" fn(*mut c_void) -> c_int;
lib::libinput_event_touch_get_time_usec: unsafe extern "C" fn(*mut c_void) -> u64;
lib::libinput_event_touch_get_x_transformed: unsafe extern "C" fn(*mut c_void, u32) -> c_double;
lib::libinput_event_touch_get_y_transformed: unsafe extern "C" fn(*mut c_void, u32) -> c_double;
lib::libinput_event_get_pointer_event: unsafe extern "C" fn(*mut c_void) -> *mut c_void;
lib::libinput_event_pointer_get_time_usec: unsafe extern "C" fn(*mut c_void) -> u64;
lib::libinput_event_pointer_get_absolute_x_transformed: unsafe extern "C" fn(*mut c_void, u32) -> c_double;
lib::libinput_event_pointer_get_absolute_y_transformed: unsafe extern "C" fn(*mut c_void, u32) -> c_double;
lib::libinput_event_pointer_get_button: unsafe extern "C" fn(*mut c_void) -> u32;
lib::libinput_event_pointer_get_button_state: unsafe extern "C" fn(*mut c_void) -> c_int;
lib::libinput_event_pointer_get_axis_source: unsafe extern "C" fn(*mut c_void) -> c_int;
lib::libinput_event_pointer_get_axis_value_discrete: unsafe extern "C" fn(*mut c_void, c_int) -> c_double;
lib::libinput_event_pointer_get_scroll_value_v120: unsafe extern "C" fn(*mut c_void, c_int) -> c_double;
}
}
pub struct Context<'a> {
lib: &'a LibInput,
ctx: *mut c_void,
}
pub struct Event<'a> {
lib: &'a LibInput,
ev: *mut c_void,
}
impl LibInput {
pub fn path_create_context(&self) -> Option<Context<'_>> {
let ctx = unsafe { (self.libinput_path_create_context)(&INTERFACE, std::ptr::null_mut()) };
(!ctx.is_null()).then_some(Context { lib: self, ctx })
}
}
impl<'a> Context<'a> {
pub fn path_add_device(&self, path: &str, calibration: &[f32; 6]) -> bool {
let Ok(path) = CString::new(path) else {
return false;
};
let device = unsafe { (self.lib.libinput_path_add_device)(self.ctx, path.as_ptr()) };
if device.is_null() {
return false;
}
unsafe {
(self.lib.libinput_device_config_calibration_set_matrix)(device, calibration.as_ptr());
}
true
}
pub fn get_fd(&self) -> i32 {
unsafe { (self.lib.libinput_get_fd)(self.ctx) }
}
pub fn dispatch(&self) {
unsafe {
(self.lib.libinput_dispatch)(self.ctx);
}
}
pub fn get_event(&self) -> Option<Event<'a>> {
let ev = unsafe { (self.lib.libinput_get_event)(self.ctx) };
(!ev.is_null()).then_some(Event { lib: self.lib, ev })
}
}
impl Event<'_> {
pub fn get_type(&self) -> i32 {
unsafe { (self.lib.libinput_event_get_type)(self.ev) }
}
pub fn touch(&self, with_position: bool, range: u32) -> Option<(i32, u64, f64, f64)> {
unsafe {
let tev = (self.lib.libinput_event_get_touch_event)(self.ev);
if tev.is_null() {
return None;
}
let slot = (self.lib.libinput_event_touch_get_slot)(tev);
let time = (self.lib.libinput_event_touch_get_time_usec)(tev);
let (x, y) = if with_position {
(
(self.lib.libinput_event_touch_get_x_transformed)(tev, range),
(self.lib.libinput_event_touch_get_y_transformed)(tev, range),
)
} else {
(0.0, 0.0)
};
Some((slot, time, x, y))
}
}
fn pointer(&self) -> *mut c_void {
unsafe { (self.lib.libinput_event_get_pointer_event)(self.ev) }
}
pub fn pointer_time_usec(&self) -> u64 {
unsafe { (self.lib.libinput_event_pointer_get_time_usec)(self.pointer()) }
}
pub fn pointer_absolute(&self, range: u32) -> (f64, f64) {
unsafe {
let pev = self.pointer();
(
(self.lib.libinput_event_pointer_get_absolute_x_transformed)(pev, range),
(self.lib.libinput_event_pointer_get_absolute_y_transformed)(pev, range),
)
}
}
pub fn pointer_button(&self) -> (u32, i32) {
unsafe {
let pev = self.pointer();
(
(self.lib.libinput_event_pointer_get_button)(pev),
(self.lib.libinput_event_pointer_get_button_state)(pev),
)
}
}
pub fn pointer_axis(&self) -> (i32, f64) {
unsafe {
let pev = self.pointer();
let source = (self.lib.libinput_event_pointer_get_axis_source)(pev);
let value = if source == super::lib_input_pointer_axis_source::LIBINPUT_POINTER_AXIS_SOURCE_WHEEL {
(self.lib.libinput_event_pointer_get_axis_value_discrete)(
pev,
super::lib_input_pointer_axis::LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
)
} else {
0.0
};
(source, value)
}
}
pub fn pointer_scroll_value_v120(&self) -> f64 {
unsafe {
(self.lib.libinput_event_pointer_get_scroll_value_v120)(
self.pointer(),
super::lib_input_pointer_axis::LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
)
}
}
}
impl Drop for Event<'_> {
fn drop(&mut self) {
unsafe {
(self.lib.libinput_event_destroy)(self.ev);
}
}
}
}