#![deny(missing_docs)]
#![cfg_attr(feature="cargo-clippy", deny(clippy))]
#![cfg_attr(feature="cargo-clippy", allow(doc_markdown))]
extern crate input_sys;
extern crate libc;
use std::{mem, ptr};
pub mod ffi {
pub use input_sys::*;
}
pub trait AsRaw<T> {
fn as_raw(&self) -> *const T;
#[doc(hidden)]
fn as_raw_mut(&self) -> *mut T {
self.as_raw() as *mut _
}
}
pub trait FromRaw<T> {
unsafe fn from_raw(*mut T) -> Self;
}
pub trait Userdata {
unsafe fn userdata<T: 'static>(&self) -> Option<&T> {
self.userdata_raw().as_ref()
}
unsafe fn userdata_mut<T: 'static>(&mut self) -> Option<&mut T> {
self.userdata_raw().as_mut()
}
unsafe fn set_userdata<T: 'static, U: 'static>(&mut self, new: Option<T>) -> Option<U> {
let old = {
let ptr = self.userdata_raw();
if !ptr.is_null() {
Some(Box::from_raw(ptr as *mut U))
} else {
None
}
};
let mut boxed = Box::new(new);
self.set_userdata_raw(match (*boxed).as_mut() {
Some(value) => value as *mut T,
None => ptr::null_mut(),
});
mem::forget(boxed);
old.map(|x| *x)
}
#[doc(hidden)]
unsafe fn userdata_raw<T: 'static>(&self) -> *mut T;
#[doc(hidden)]
unsafe fn set_userdata_raw<T: 'static>(&self, ptr: *mut T);
}
macro_rules! ffi_ref_struct {
($(#[$attr:meta])* struct $struct_name:ident, $ffi_name:path, $ref_fn:path, $unref_fn:path, $get_userdata_fn:path, $set_userdata_fn:path) => (
#[derive(Eq)]
$(#[$attr])*
pub struct $struct_name
{
ffi: *mut $ffi_name,
}
impl ::std::fmt::Debug for $struct_name {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "$struct_name @{:p}", self.as_raw())
}
}
impl FromRaw<$ffi_name> for $struct_name
{
unsafe fn from_raw(ffi: *mut $ffi_name) -> Self {
$struct_name {
ffi: $ref_fn(ffi),
}
}
}
impl AsRaw<$ffi_name> for $struct_name
{
fn as_raw(&self) -> *const $ffi_name {
self.ffi as *const _
}
}
impl Userdata for $struct_name {
unsafe fn userdata_raw<T: 'static>(&self) -> *mut T {
$get_userdata_fn(self.as_raw_mut()) as *mut T
}
unsafe fn set_userdata_raw<T: 'static>(&self, ptr: *mut T) {
$set_userdata_fn(self.as_raw_mut(), ptr as *mut libc::c_void);
}
}
impl Clone for $struct_name {
fn clone(&self) -> Self {
unsafe { $struct_name::from_raw(self.as_raw_mut()) }
}
}
impl Drop for $struct_name
{
fn drop(&mut self) {
unsafe {
let userdata_ref = $get_userdata_fn(self.as_raw_mut());
if $unref_fn(self.ffi).is_null() {
let _ = Box::from_raw(userdata_ref);
}
}
}
}
impl PartialEq for $struct_name {
fn eq(&self, other: &Self) -> bool {
self.as_raw() == other.as_raw()
}
}
impl ::std::hash::Hash for $struct_name {
fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
self.as_raw().hash(state);
}
}
)
}
macro_rules! ffi_func {
($(#[$attr:meta])* fn $name:ident, $ffi_fn:path, bool) => (
$(#[$attr])*
fn $name(&self) -> bool {
unsafe { $ffi_fn(self.as_raw_mut()) != 0 }
}
);
($(#[$attr:meta])* pub fn $name:ident, $ffi_fn:path, bool) => (
$(#[$attr])*
pub fn $name(&self) -> bool {
unsafe { $ffi_fn(self.as_raw_mut()) != 0 }
}
);
($(#[$attr:meta])* fn $name:ident, $ffi_fn:path, $return_type:ty) => (
$(#[$attr])*
fn $name(&self) -> $return_type {
unsafe { $ffi_fn(self.as_raw_mut()) as $return_type }
}
);
($(#[$attr:meta])* pub fn $name:ident, $ffi_fn:path, $return_type:ty) => (
$(#[$attr])*
pub fn $name(&self) -> $return_type {
unsafe { $ffi_fn(self.as_raw_mut()) as $return_type }
}
);
}
mod context;
mod device;
pub mod event;
mod seat;
pub use context::*;
pub use device::*;
pub use event::Event;
pub use seat::*;