mirror of
https://github.com/k0kubun/xremap
synced 2024-11-02 03:40:25 +00:00
Prepare for calling select(2)
This commit is contained in:
parent
e9c5afb054
commit
efb1db6d3b
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -109,4 +109,5 @@ name = "xremap"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"evdev",
|
||||
"libc",
|
||||
]
|
||||
|
@ -7,3 +7,4 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
evdev = "0.11.3"
|
||||
libc = "0.2"
|
||||
|
@ -1,5 +1,7 @@
|
||||
extern crate evdev;
|
||||
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::{io, mem, ptr};
|
||||
use evdev::Device;
|
||||
|
||||
pub fn select_device() -> Device {
|
||||
|
@ -1,10 +1,14 @@
|
||||
use std::error::Error;
|
||||
|
||||
mod input;
|
||||
mod select;
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let mut device = input::select_device();
|
||||
device.grab()?;
|
||||
if select::is_readable(&mut device) {
|
||||
println!("event!")
|
||||
}
|
||||
device.ungrab()?;
|
||||
Ok(())
|
||||
}
|
||||
|
61
src/select.rs
Normal file
61
src/select.rs
Normal file
@ -0,0 +1,61 @@
|
||||
extern crate evdev;
|
||||
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::{io, mem, ptr};
|
||||
use evdev::Device;
|
||||
|
||||
// A call of this function blocks until the argument device becomes readable.
|
||||
// TODO: support selecting multiple devices
|
||||
pub fn is_readable(device: &mut Device) -> bool {
|
||||
let mut fd_set = FdSet::new(); // TODO: maybe this should be prepared in the caller
|
||||
fd_set.set(device.as_raw_fd());
|
||||
|
||||
let result = match unsafe {
|
||||
libc::select(
|
||||
device.as_raw_fd() + 1,
|
||||
to_fdset_ptr(Some(&mut fd_set)),
|
||||
to_fdset_ptr(None),
|
||||
to_fdset_ptr(None),
|
||||
to_ptr::<libc::timeval>(None) as *mut libc::timeval,
|
||||
)
|
||||
} {
|
||||
-1 => Err(io::Error::last_os_error()),
|
||||
res => Ok(res as usize),
|
||||
}.unwrap();
|
||||
return result == 1 && fd_set.is_set(device.as_raw_fd())
|
||||
}
|
||||
|
||||
fn to_fdset_ptr(opt: Option<&mut FdSet>) -> *mut libc::fd_set {
|
||||
match opt {
|
||||
None => ptr::null_mut(),
|
||||
Some(&mut FdSet(ref mut raw_fd_set)) => raw_fd_set,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_ptr<T>(opt: Option<&T>) -> *const T {
|
||||
match opt {
|
||||
None => ptr::null::<T>(),
|
||||
Some(p) => p,
|
||||
}
|
||||
}
|
||||
|
||||
struct FdSet(libc::fd_set);
|
||||
|
||||
impl FdSet {
|
||||
fn new() -> FdSet {
|
||||
unsafe {
|
||||
// Is the memory released properly?
|
||||
let mut raw_fd_set = mem::MaybeUninit::<libc::fd_set>::uninit();
|
||||
libc::FD_ZERO(raw_fd_set.as_mut_ptr());
|
||||
FdSet(raw_fd_set.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
fn set(&mut self, fd: RawFd) {
|
||||
unsafe { libc::FD_SET(fd, &mut self.0) }
|
||||
}
|
||||
|
||||
fn is_set(&mut self, fd: RawFd) -> bool {
|
||||
unsafe { libc::FD_ISSET(fd, &mut self.0) }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user