mirror of
https://github.com/k0kubun/xremap
synced 2024-11-02 03:40:25 +00:00
Use nix crate to call select(2)
This commit is contained in:
parent
fc30cb8bca
commit
e5ac6af6bd
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -78,9 +78,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f305c2c2e4c39a82f7bf0bf65fb557f9070ce06781d4f2454295cc34b1c43188"
|
checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cc",
|
"cc",
|
||||||
@ -115,7 +115,7 @@ name = "xremap"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"evdev",
|
"evdev",
|
||||||
"libc",
|
"nix",
|
||||||
"yaml-rust",
|
"yaml-rust",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -7,5 +7,5 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
evdev = "0.11.3"
|
evdev = "0.11.3"
|
||||||
libc = "0.2"
|
nix = "0.23.1"
|
||||||
yaml-rust = "0.4"
|
yaml-rust = "0.4"
|
||||||
|
16
src/input.rs
16
src/input.rs
@ -1,10 +1,26 @@
|
|||||||
extern crate evdev;
|
extern crate evdev;
|
||||||
|
extern crate nix;
|
||||||
|
|
||||||
use evdev::Device;
|
use evdev::Device;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
use nix::sys::select::FdSet;
|
||||||
|
use nix::sys::select::select;
|
||||||
|
use std::os::unix::io::{AsRawFd};
|
||||||
|
|
||||||
pub fn select_device() -> Result<Device, Box<dyn Error>> {
|
pub fn select_device() -> Result<Device, Box<dyn Error>> {
|
||||||
// TODO: stop hard-coding the device
|
// TODO: stop hard-coding the device
|
||||||
let device = Device::open("/dev/input/event19")?;
|
let device = Device::open("/dev/input/event19")?;
|
||||||
return Ok(device);
|
return Ok(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_readable(device: &mut Device) -> Result<bool, Box<dyn Error>> {
|
||||||
|
let mut read_fds = FdSet::new();
|
||||||
|
read_fds.insert(device.as_raw_fd());
|
||||||
|
select(None, &mut read_fds, None, None, None)?;
|
||||||
|
for fd in read_fds.fds(None) {
|
||||||
|
if fd == device.as_raw_fd() {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
@ -5,7 +5,6 @@ use std::process::exit;
|
|||||||
|
|
||||||
mod input;
|
mod input;
|
||||||
mod output;
|
mod output;
|
||||||
mod select;
|
|
||||||
mod transform;
|
mod transform;
|
||||||
mod config;
|
mod config;
|
||||||
|
|
||||||
@ -18,7 +17,7 @@ fn event_loop() -> Result<(), Box<dyn Error>> {
|
|||||||
.map_err(|e| format!("Failed to grab an input device: {}", e))?;
|
.map_err(|e| format!("Failed to grab an input device: {}", e))?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if !select::is_readable(&mut input_device)? {
|
if !input::is_readable(&mut input_device)? {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
extern crate evdev;
|
|
||||||
|
|
||||||
use evdev::Device;
|
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
|
||||||
use std::{io, mem, ptr};
|
|
||||||
use std::error::Error;
|
|
||||||
|
|
||||||
// A call of this function blocks until the argument device becomes readable.
|
|
||||||
// TODO: support selecting multiple devices
|
|
||||||
pub fn is_readable(device: &mut Device) -> Result<bool, Box<dyn Error>> {
|
|
||||||
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),
|
|
||||||
}?;
|
|
||||||
return Ok(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