Format all code

This commit is contained in:
Travis Burtrum 2025-02-07 00:35:49 -05:00
parent 270cdca14f
commit 82421be440
Signed by: moparisthebest
GPG Key ID: 88C93BFE27BC8229
12 changed files with 1599 additions and 1455 deletions

View File

@ -1,7 +1,4 @@
use std::fmt;
use std::error;
use std::ffi;
use std::io;
use std::{error, ffi, fmt, io};
#[cfg(target_os = "linux")]
use nix;

View File

@ -1,7 +1,4 @@
use std::collections::HashMap;
use std::hash::Hash;
use std::convert::TryFrom;
use std::{collections::HashMap, convert::TryFrom, hash::Hash};
#[cfg(feature = "toml_serde")]
use std::path::Path;
@ -23,7 +20,7 @@ pub enum KeyState {
}
pub trait KeyEvent<T>
where
where
T: Into<usize>,
{
fn code(&self) -> T;
@ -31,7 +28,7 @@ pub trait KeyEvent<T>
}
pub trait Keyboard<T, E, R = ()>
where
where
T: Into<usize> + Copy,
E: KeyEvent<T>,
{
@ -44,7 +41,14 @@ pub trait Keyboard<T, E, R = ()>
fn caps_lock_code(&self) -> T;
fn block_key(&self) -> Result<R>;
fn send_half_inverted_key(&self, half_inverted_key: &HalfInvertedKey<T>, event: &mut E, left_shift: bool, right_shift: bool, caps_lock: bool) -> Result<R> {
fn send_half_inverted_key(
&self,
half_inverted_key: &HalfInvertedKey<T>,
event: &mut E,
left_shift: bool,
right_shift: bool,
caps_lock: bool,
) -> Result<R> {
let value = event.value();
let mut invert_shift = half_inverted_key.invert_shift;
if value == KeyState::DOWN {
@ -87,7 +91,7 @@ pub trait Keyboard<T, E, R = ()>
}
pub trait KeyMapper<K, T, E, R>
where
where
T: Into<usize> + Copy,
E: KeyEvent<T>,
K: Keyboard<T, E, R>,
@ -96,7 +100,7 @@ pub trait KeyMapper<K, T, E, R>
}
pub struct KeyMaps<K, T, E, R = ()>
where
where
T: Into<usize> + Copy + Clone + Eq + Hash,
E: KeyEvent<T>,
K: Keyboard<T, E, R>,
@ -113,17 +117,25 @@ pub struct KeyMaps<K, T, E, R = ()>
}
fn parse_key<T: Clone + Copy>(key_map: &HashMap<&'static str, T>, key: &str) -> T {
match key_map.get(key.trim_matches(|c: char| c.is_whitespace() || c == INVERT_KEY_FLAG || c == CAPS_MODIFY_KEY_FLAG)) {
match key_map.get(key.trim_matches(|c: char| {
c.is_whitespace() || c == INVERT_KEY_FLAG || c == CAPS_MODIFY_KEY_FLAG
})) {
Some(key_code) => *key_code,
None => panic!("unknown key: {}", key.trim())
None => panic!("unknown key: {}", key.trim()),
}
}
fn parse_keymap_numeric<T: Clone + Copy>(key_map: &HashMap<&'static str, T>, keymap: &str) -> Vec<T> {
fn parse_keymap_numeric<T: Clone + Copy>(
key_map: &HashMap<&'static str, T>,
keymap: &str,
) -> Vec<T> {
keymap.split(",").map(|k| parse_key(key_map, k)).collect()
}
fn parse_key_half_inverted<T: Clone + Copy>(key_map: &HashMap<&'static str, T>, key: &str) -> HalfInvertedKey<T> {
fn parse_key_half_inverted<T: Clone + Copy>(
key_map: &HashMap<&'static str, T>,
key: &str,
) -> HalfInvertedKey<T> {
HalfInvertedKey {
code: parse_key(key_map, key),
invert_shift: key.contains(INVERT_KEY_FLAG),
@ -138,11 +150,16 @@ fn parse_keymap_u16<T: Clone + Copy>(key_map: &HashMap<&'static str, T>, keymap:
// todo: how do I return an iterator here instead of .collect to Vec?
fn parse_keymap<T: Copy>(key_map: &HashMap<&'static str, T>, keymap: &str) -> Vec<Key<T>> {
keymap.split(",").map(|k| {
keymap
.split(",")
.map(|k| {
let ret: Key<T> = if k.contains(HALF_KEY_SEPARATOR) {
let keys: Vec<&str> = k.split(HALF_KEY_SEPARATOR).collect();
if keys.len() != 2 {
panic!("split key can only have 2 keys, 1 :, has {} keys", keys.len());
panic!(
"split key can only have 2 keys, 1 :, has {} keys",
keys.len()
);
}
let mut shift_half = parse_key_half_inverted(key_map, keys[1]);
shift_half.invert_shift = !shift_half.invert_shift;
@ -153,38 +170,50 @@ fn parse_keymap<T: Copy>(key_map: &HashMap<&'static str, T>, keymap: &str) -> Ve
Key::Direct(parse_key(key_map, k))
};
ret
}).collect()
})
.collect()
}
impl<K, T, E, R> KeyMaps<K, T, E, R>
where
where
T: Into<usize> + TryFrom<usize> + Copy + Clone + Eq + Hash + Default + 'static,
E: KeyEvent<T>,
K: Keyboard<T, E, R>,
{
#[cfg(feature = "toml_serde")]
pub fn from_cfg<P: AsRef<Path>>(key_map: &HashMap<&'static str, T>, path: P) -> KeyMaps<K, T, E, R> {
pub fn from_cfg<P: AsRef<Path>>(
key_map: &HashMap<&'static str, T>,
path: P,
) -> KeyMaps<K, T, E, R> {
let key_map_config = parse_cfg(path).expect("provided config cannot be found/parsed");
KeyMaps::new(key_map, key_map_config)
}
pub fn new(key_map: &HashMap<&'static str, T>, config: KeymapConfig) -> KeyMaps<K, T, E, R> {
if config.keymaps.len() < 2 {
panic!("must have at least 2 keymaps (original and mapped) but only have {},", config.keymaps.len());
panic!(
"must have at least 2 keymaps (original and mapped) but only have {},",
config.keymaps.len()
);
}
if config.default_keymap_index >= config.keymaps.len() || config.revert_keymap_index >= config.keymaps.len() {
if config.default_keymap_index >= config.keymaps.len()
|| config.revert_keymap_index >= config.keymaps.len()
{
panic!("default_keymap_index ({}) and revert_keymap_index ({}) must be less than keymaps length ({}),", config.default_keymap_index, config.revert_keymap_index, config.keymaps.len());
}
let base_keymap = parse_keymap_numeric(key_map, &config.keymaps[0]);
//println!("base_keymap : {:?}", base_keymap);
let mut keymaps: Vec<Box<dyn KeyMapper<K, T, E, R>>> = vec!(Box::new(Key::Noop)); // todo: can we share the box?
let mut keymaps: Vec<Box<dyn KeyMapper<K, T, E, R>>> = vec![Box::new(Key::Noop)]; // todo: can we share the box?
let mut keymap_index_keys: HashMap<T, usize> = HashMap::new();
for (x, v) in config.keymaps.iter().enumerate() {
keymap_index_keys.insert(*key_map.get(&*x.to_string()).unwrap(), x);
if x == 0 {
continue;
}
if v.contains(HALF_KEY_SEPARATOR) || v.contains(INVERT_KEY_FLAG) || v.contains(CAPS_MODIFY_KEY_FLAG) {
if v.contains(HALF_KEY_SEPARATOR)
|| v.contains(INVERT_KEY_FLAG)
|| v.contains(CAPS_MODIFY_KEY_FLAG)
{
// we need KeyMap, the complicated more memory taking one
let v = parse_keymap(key_map, v);
let mut keymap = KeyMap::new();
@ -241,7 +270,11 @@ impl<K, T, E, R> KeyMaps<K, T, E, R>
KeyMaps {
keymaps: keymaps,
keymap_index_keys: keymap_index_keys,
switch_layout_keys: config.switch_layout_keys.iter().map(|k| parse_key(key_map, k).into()).collect(),
switch_layout_keys: config
.switch_layout_keys
.iter()
.map(|k| parse_key(key_map, k).into())
.collect(),
key_state: [false; KEY_MAX],
// todo: detect key state? at least CAPSLOCK...
revert_default_keys,
@ -250,17 +283,18 @@ impl<K, T, E, R> KeyMaps<K, T, E, R>
current_keymap_index: config.default_keymap_index,
}
}
//}
//}
//impl KeyMapper for KeyMaps {
//impl KeyMaps {
pub fn send_event(&mut self, mut event: &mut E, device: &K) -> Result<R> {
//impl KeyMapper for KeyMaps {
//impl KeyMaps {
pub fn send_event(&mut self, mut event: &mut E, device: &K) -> Result<R> {
let value = event.value();
if value != KeyState::OTHER {
// todo: index check here...
if event.code() == device.caps_lock_code() {
if value == KeyState::DOWN {
self.key_state[device.caps_lock_code().into()] = !self.key_state[device.caps_lock_code().into()];
self.key_state[device.caps_lock_code().into()] =
!self.key_state[device.caps_lock_code().into()];
}
} else {
let idx = event.code().into();
@ -291,23 +325,30 @@ pub fn send_event(&mut self, mut event: &mut E, device: &K) -> Result<R> {
KeyState::DOWN => {
// todo: should we release currently held keys and then press them back down here, kinda the opposite of below? not for now...
self.current_keymap_index = self.revert_keymap_index
},
}
KeyState::UP => {
self.current_keymap_index = self.chosen_keymap_index;
#[cfg(not(target_os = "macos"))] {
#[cfg(not(target_os = "macos"))]
{
// need to release all currently held down keys, except this one, otherwise ctrl+c will get c stuck because code c value 1 will be sent, but then we'll let go of ctrl, and code j value 0 is sent, so c is never released
let orig_code = event.code();
for (idx, key_down) in self.key_state.iter_mut().enumerate() {
if *key_down {
device.send_mod_code_value(T::try_from(idx).unwrap_or_else(|_| panic!("cannot convert from usize to T ????")), true, event)?;
device.send_mod_code_value(
T::try_from(idx).unwrap_or_else(|_| {
panic!("cannot convert from usize to T ????")
}),
true,
event,
)?;
*key_down = false;
}
}
// todo: seems like we should not send this here, and instead just set the original code back, and pass it through the keymaps?
return device.send_mod_code_value(orig_code, true, event)
return device.send_mod_code_value(orig_code, true, event);
}
},
_ => () // do nothing for 2
}
_ => (), // do nothing for 2
}
}
}
@ -325,7 +366,7 @@ struct KeyMap<T: Into<usize> + Copy> {
impl<T: Into<usize> + Copy> KeyMap<T> {
pub fn new() -> Self {
KeyMap {
keymap: [Key::Noop; KEY_MAX]
keymap: [Key::Noop; KEY_MAX],
}
}
@ -335,7 +376,7 @@ impl<T: Into<usize> + Copy> KeyMap<T> {
}
impl<K, T, E, R> KeyMapper<K, T, E, R> for KeyMap<T>
where
where
T: Into<usize> + Copy,
E: KeyEvent<T>,
K: Keyboard<T, E, R>,
@ -356,9 +397,7 @@ impl<T: Into<usize> + TryFrom<usize> + Copy + Default> CodeKeyMap<T> {
*v = T::try_from(x).unwrap_or_else(|_| panic!("cannot convert from usize to T ????"));
}
//println!("keymap: {:?}", &keymap[..]);
CodeKeyMap {
keymap
}
CodeKeyMap { keymap }
}
pub fn map(&mut self, from: T, to: T) {
@ -367,7 +406,7 @@ impl<T: Into<usize> + TryFrom<usize> + Copy + Default> CodeKeyMap<T> {
}
impl<K, T, E, R> KeyMapper<K, T, E, R> for CodeKeyMap<T>
where
where
T: Into<usize> + TryFrom<usize> + Copy + Default,
E: KeyEvent<T>,
K: Keyboard<T, E, R>,
@ -390,7 +429,7 @@ pub struct HalfInvertedKey<T: Clone + Copy> {
}
impl<K, T, E, R> KeyMapper<K, T, E, R> for HalfInvertedKey<T>
where
where
T: Into<usize> + Clone + Copy,
E: KeyEvent<T>,
K: Keyboard<T, E, R>,
@ -405,8 +444,8 @@ impl<K, T, E, R> KeyMapper<K, T, E, R> for HalfInvertedKey<T>
#[derive(Clone, Copy)]
enum Key<T>
where
T: Copy + Clone
where
T: Copy + Clone,
{
Noop,
Direct(T),
@ -415,32 +454,38 @@ enum Key<T>
}
impl<K, T, E, R> KeyMapper<K, T, E, R> for Key<T>
where
where
T: Into<usize> + Copy,
E: KeyEvent<T>,
K: Keyboard<T, E, R>,
{
fn send_event(&self, key_state: &[bool], event: &mut E, device: &K) -> Result<R> {
match *self {
Key::Noop => {
device.send(event)
},
Key::Direct(code) => {
device.send_mod_code(code, event)
},
Key::HalfKey(ref key_half) => {
key_half.send_event(key_state, event, device)
},
Key::Noop => device.send(event),
Key::Direct(code) => device.send_mod_code(code, event),
Key::HalfKey(ref key_half) => key_half.send_event(key_state, event, device),
Key::FullKey(ref noshift_half, ref shift_half) => {
let left_shift = key_state[device.left_shift_code().into()];
let right_shift = key_state[device.right_shift_code().into()];
let caps_lock = key_state[device.caps_lock_code().into()];
if caps_lock != (left_shift || right_shift) {
device.send_half_inverted_key(shift_half, event, left_shift, right_shift, caps_lock)
device.send_half_inverted_key(
shift_half,
event,
left_shift,
right_shift,
caps_lock,
)
} else {
device.send_half_inverted_key(noshift_half, event, left_shift, right_shift, caps_lock)
device.send_half_inverted_key(
noshift_half,
event,
left_shift,
right_shift,
caps_lock,
)
}
}
},
}
}
}
@ -453,7 +498,7 @@ pub struct KeymapConfig {
revert_default_keys: Option<Vec<String>>,
revert_keymap_index: usize,
default_keymap_index: usize,
keymaps: Vec<String>
keymaps: Vec<String>,
}
#[cfg(feature = "toml_serde")]
@ -473,7 +518,7 @@ pub struct KeymapConfig {
revert_default_keys: Option<Vec<&'static str>>,
revert_keymap_index: usize,
default_keymap_index: usize,
keymaps: Vec<&'static str>
keymaps: Vec<&'static str>,
}
#[cfg(not(feature = "toml_serde"))]
@ -528,4 +573,3 @@ impl Default for KeymapConfig {
}
}
}

View File

@ -1,12 +1,7 @@
use std::path::Path;
use std::{mem, slice};
use std::ffi::CString;
use crate::{Device, Result};
use libc::c_int;
use nix::{self, fcntl, unistd, ioctl_write_ptr, ioctl_none};
use nix::sys::stat;
use crate::{Result, Device};
use std::collections::hash_map::Values;
use std::os::raw::c_char;
use nix::{self, fcntl, ioctl_none, ioctl_write_ptr, sys::stat, unistd};
use std::{collections::hash_map::Values, ffi::CString, mem, os::raw::c_char, path::Path, slice};
use crate::linux::device::codes::*;
@ -50,7 +45,11 @@ impl Builder {
/// Create a builder from the specified path.
pub fn open<P: AsRef<Path>>(path: P) -> Result<Self> {
Ok(Builder {
fd: fcntl::open(path.as_ref(), fcntl::OFlag::O_WRONLY | fcntl::OFlag::O_NONBLOCK, stat::Mode::empty())?,
fd: fcntl::open(
path.as_ref(),
fcntl::OFlag::O_WRONLY | fcntl::OFlag::O_NONBLOCK,
stat::Mode::empty(),
)?,
def: unsafe { mem::zeroed() },
abs: None,
})
@ -70,8 +69,7 @@ impl Builder {
Err(nix::Error::EINVAL)?;
}
(&mut self.def.name)[..bytes.len()]
.clone_from_slice(unsafe { mem::transmute(bytes) });
(&mut self.def.name)[..bytes.len()].clone_from_slice(unsafe { mem::transmute(bytes) });
Ok(self)
}

View File

@ -1,4 +1,4 @@
use libc::{c_int};
use libc::c_int;
pub const INPUT_PROP_POINTER: c_int = 0x00; /* needs a pointer */
pub const INPUT_PROP_DIRECT: c_int = 0x01; /* direct input devices */
@ -702,7 +702,6 @@ pub const ABS_MT_DISTANCE: c_int = 0x3b; /* Contact hover distance */
pub const ABS_MT_TOOL_X: c_int = 0x3c; /* Center X tool position */
pub const ABS_MT_TOOL_Y: c_int = 0x3d; /* Center Y tool position */
pub const ABS_MAX: c_int = 0x3f;
pub const ABS_CNT: c_int = ABS_MAX + 1;

View File

@ -1,7 +1,7 @@
use std::{mem, ptr, slice};
use libc::{timeval, gettimeofday, input_event, c_int};
use nix::{unistd, ioctl_none};
use crate::Result;
use libc::{c_int, gettimeofday, input_event, timeval};
use nix::{ioctl_none, unistd};
use std::{mem, ptr, slice};
use crate::linux::device::codes::*;
@ -15,15 +15,16 @@ pub struct Device {
impl Device {
/// Wrap a file descriptor in a `Device`.
pub fn new(fd: c_int) -> Self {
Device {
fd: fd
}
Device { fd: fd }
}
#[doc(hidden)]
pub fn write(&self, kind: c_int, code: c_int, value: c_int) -> Result<()> {
let mut event = input_event {
time: timeval { tv_sec: 0, tv_usec: 0 },
time: timeval {
tv_sec: 0,
tv_usec: 0,
},
type_: kind as u16,
code: code as u16,
value: value as i32,

View File

@ -1,15 +1,14 @@
use std::mem;
use std::fs::File;
use std::io::Read;
use std::os::unix::io::AsRawFd;
use libc::{input_event, c_int};
use nix::{ioctl_write_ptr, ioctl_read_buf};
use libc::{c_int, input_event};
use nix::{ioctl_read_buf, ioctl_write_ptr};
use std::{fs::File, io::Read, mem, os::unix::io::AsRawFd};
#[cfg(feature = "epoll_inotify")]
use std::os::unix::prelude::RawFd;
use crate::{Error,Result};
use crate::linux::{EV_KEY, KEY_MAX, NAME, KEY_W, KEY_A, KEY_S, KEY_D, BTN_LEFT};
use crate::{
linux::{BTN_LEFT, EV_KEY, KEY_A, KEY_D, KEY_MAX, KEY_S, KEY_W, NAME},
Error, Result,
};
ioctl_write_ptr!(eviocgrab, b'E', 0x90, c_int);
ioctl_read_buf!(eviocgname, b'E', 0x06, u8);
@ -73,16 +72,19 @@ impl InputDevice {
unsafe {
eviocgbit_ev_key(raw_fd, &mut key_bits)?;
};
let key_unsupported = |key : c_int| (key_bits[key as usize / 8] & (1 << (key % 8))) == 0;
if key_unsupported(KEY_W) || key_unsupported(KEY_A) || key_unsupported(KEY_S) || key_unsupported(KEY_D) || !key_unsupported(BTN_LEFT) {
let key_unsupported = |key: c_int| (key_bits[key as usize / 8] & (1 << (key % 8))) == 0;
if key_unsupported(KEY_W)
|| key_unsupported(KEY_A)
|| key_unsupported(KEY_S)
|| key_unsupported(KEY_D)
|| !key_unsupported(BTN_LEFT)
{
return Err(Error::NotAKeyboard);
}
// is it another running copy of rusty-keys ?
let mut name = [0u8; NAME.len()];
unsafe {
eviocgname(raw_fd, &mut name)?
};
unsafe { eviocgname(raw_fd, &mut name)? };
// exclude anything starting with "Yubico" also
if NAME.as_bytes() == &name || "Yubico".as_bytes() == &name[0..6] {
return Err(Error::NotAKeyboard);
@ -110,7 +112,7 @@ impl InputDevice {
#[cfg(feature = "epoll_inotify")]
pub fn epoll_add(mut self, epoll_fd: RawFd, data: u64) -> Result<Self> {
use nix::fcntl::{OFlag, fcntl, FcntlArg};
use nix::fcntl::{fcntl, FcntlArg, OFlag};
if None != self.epoll_fd {
return Err(Error::EpollAlreadyAdded);
@ -123,7 +125,12 @@ impl InputDevice {
fcntl(raw_fd, FcntlArg::F_SETFL(flags | OFlag::O_NONBLOCK))?;
let epoll_event = epoll::Event::new(epoll::Events::EPOLLIN | epoll::Events::EPOLLET, data);
epoll::ctl(epoll_fd, epoll::ControlOptions::EPOLL_CTL_ADD, raw_fd, epoll_event)?;
epoll::ctl(
epoll_fd,
epoll::ControlOptions::EPOLL_CTL_ADD,
raw_fd,
epoll_event,
)?;
self.epoll_fd = Some(epoll_fd);
Ok(self)
}
@ -134,7 +141,12 @@ impl InputDevice {
// set this to None first, if we end up returning an Err early, we can't do anything else anyway...
self.epoll_fd = None;
let empty_event = epoll::Event::new(epoll::Events::empty(), 0);
epoll::ctl(epoll_fd, epoll::ControlOptions::EPOLL_CTL_DEL, self.device_file.as_raw_fd(), empty_event)?;
epoll::ctl(
epoll_fd,
epoll::ControlOptions::EPOLL_CTL_DEL,
self.device_file.as_raw_fd(),
empty_event,
)?;
}
Ok(self)
}

View File

@ -1,15 +1,12 @@
use crate::*;
use crate::linux::device::codes::*;
pub mod device;
pub use device::{Device,InputDevice, Builder};
pub use device::{Builder, Device, InputDevice};
use libc::input_event;
use std::process::exit;
use std::env;
use std::collections::HashMap;
use std::{collections::HashMap, env, process::exit};
#[cfg(feature = "epoll_inotify")]
const INPUT_FOLDER: &str = "/dev/input/";
@ -48,7 +45,12 @@ impl Keyboard<u16, input_event> for Device {
Keyboard::send(self, event)
}
fn send_mod_code_value(&self, code: u16, up_not_down: bool, event: &mut input_event) -> Result<()> {
fn send_mod_code_value(
&self,
code: u16,
up_not_down: bool,
event: &mut input_event,
) -> Result<()> {
event.code = code;
let value = event.value;
if up_not_down {
@ -86,12 +88,15 @@ impl Keyboard<u16, input_event> for Device {
#[derive(Debug)]
struct Config {
device_files: Vec<String>,
config_file: String
config_file: String,
}
impl Config {
fn new(device_files: Vec<String>, config_file: String) -> Self {
Config { device_files: device_files, config_file: config_file }
Config {
device_files: device_files,
config_file: config_file,
}
}
}
@ -138,7 +143,16 @@ pub fn main_res() -> Result<()> {
let (device_files, mut inotify) = if config.device_files.len() > 0 {
// we operate on exactly the devices sent in and never watch for new devices
(config.device_files.iter().map(|device_file| InputDevice::open(&device_file).expect("device_file does not exist!")).collect(), None)
(
config
.device_files
.iter()
.map(|device_file| {
InputDevice::open(&device_file).expect("device_file does not exist!")
})
.collect(),
None,
)
} else {
use std::os::unix::io::AsRawFd;
// we want to wait forever starting new threads for any new keyboard devices
@ -148,8 +162,16 @@ pub fn main_res() -> Result<()> {
let device_files = get_keyboard_devices();
let mut inotify = Inotify::init()?;
inotify.add_watch(INPUT_FOLDER, WatchMask::CREATE)?;
let epoll_event = epoll::Event::new(epoll::Events::EPOLLIN | epoll::Events::EPOLLET, INOTIFY_DATA);
epoll::ctl(epoll_fd, epoll::ControlOptions::EPOLL_CTL_ADD, inotify.as_raw_fd(), epoll_event)?;
let epoll_event = epoll::Event::new(
epoll::Events::EPOLLIN | epoll::Events::EPOLLET,
INOTIFY_DATA,
);
epoll::ctl(
epoll_fd,
epoll::ControlOptions::EPOLL_CTL_ADD,
inotify.as_raw_fd(),
epoll_event,
)?;
(device_files, Some(inotify))
};
let mut input_devices = Vec::with_capacity(device_files.len());
@ -196,24 +218,37 @@ pub fn main_res() -> Result<()> {
} else if event.data == INOTIFY_DATA {
if let Some(inotify) = &mut inotify {
for event in inotify.read_events(&mut inotify_buf)? {
if let Some(device_file) = event.name.and_then(|name| name.to_str()) {
if let Some(device_file) = event.name.and_then(|name| name.to_str())
{
// check if this is an eligible keyboard device
let mut path = std::path::PathBuf::new();
path.push(INPUT_FOLDER);
path.push(device_file);
if let Ok(input_device) = InputDevice::open(path).and_then(|id| id.valid_keyboard_device()) {
println!("starting mapping for new keyboard: {}", device_file);
if let Ok(input_device) = InputDevice::open(path)
.and_then(|id| id.valid_keyboard_device())
{
println!(
"starting mapping for new keyboard: {}",
device_file
);
let idx = input_devices.iter().position(|id| id.is_none()).unwrap_or(input_devices.len());
let idx = input_devices
.iter()
.position(|id| id.is_none())
.unwrap_or(input_devices.len());
let input_device = input_device.grab()?.epoll_add(epoll_fd, idx as u64)?;
let input_device =
input_device.grab()?.epoll_add(epoll_fd, idx as u64)?;
if idx == input_devices.len() {
input_devices.push(Some(input_device));
} else {
// simply replacing None here
let _ = std::mem::replace(&mut input_devices[idx], Some(input_device));
let _ = std::mem::replace(
&mut input_devices[idx],
Some(input_device),
);
}
}
}
@ -247,7 +282,12 @@ fn parse_args() -> Config {
let mut opts = Options::new();
opts.optflag("h", "help", "prints this help message");
opts.optflag("v", "version", "prints the version");
opts.optopt("c", "config", "specify the keymap config file to use (default: /etc/rusty-keys/keymap.toml)", "FILE");
opts.optopt(
"c",
"config",
"specify the keymap config file to use (default: /etc/rusty-keys/keymap.toml)",
"FILE",
);
let matches = opts.parse(&args[1..]);
if matches.is_err() {
@ -265,7 +305,9 @@ fn parse_args() -> Config {
exit(0);
}
let config_file = matches.opt_str("c").unwrap_or("/etc/rusty-keys/keymap.toml".to_owned());
let config_file = matches
.opt_str("c")
.unwrap_or("/etc/rusty-keys/keymap.toml".to_owned());
Config::new(matches.free, config_file)
}
@ -276,7 +318,9 @@ fn get_keyboard_devices() -> Vec<InputDevice> {
if let Ok(entries) = std::fs::read_dir(INPUT_FOLDER) {
for entry in entries {
if let Ok(entry) = entry {
if let Ok(input_device) = InputDevice::open(entry.path()).and_then(|id|id.valid_keyboard_device()) {
if let Ok(input_device) =
InputDevice::open(entry.path()).and_then(|id| id.valid_keyboard_device())
{
res.push(input_device);
}
}
@ -594,6 +638,9 @@ pub fn key_map() -> HashMap<&'static str, u16> {
("PDOT", KEY_KPDOT),
("PENT", KEY_KPENTER),
("TOUCHPAD_TOGGLE", KEY_TOUCHPAD_TOGGLE),
].iter().cloned().map(|(m, v)| (m, v as u16)).collect()
}
]
.iter()
.cloned()
.map(|(m, v)| (m, v as u16))
.collect()
}

View File

@ -1,6 +1,5 @@
use std::collections::HashMap;
use core_graphics::event::CGKeyCode;
use std::collections::HashMap;
pub const KEY_RESERVED: CGKeyCode = 0x31;
pub const KEY_ESC: CGKeyCode = 0x00;
@ -564,5 +563,9 @@ pub fn key_map() -> HashMap<&'static str, CGKeyCode> {
("P0", KEY_KP0),
("PDOT", KEY_KPDOT),
("PENT", KEY_KPENTER),
].iter().cloned().map(|(m, v)| (m, v)).collect()
]
.iter()
.cloned()
.map(|(m, v)| (m, v))
.collect()
}

View File

@ -4,8 +4,7 @@
#![allow(improper_ctypes)]
use crate::*;
use std::env;
use std::process::exit;
use std::{env, process::exit};
use getopts::Options;
use std::fs::File;
@ -13,9 +12,10 @@ use std::fs::File;
pub mod codes;
use codes::*;
use core_graphics::event::CGKeyCode;
use core_graphics::event::*;
use core_graphics::event_source::*;
use core_graphics::{
event::{CGKeyCode, *},
event_source::*,
};
use core_graphics::event::{CGEventTapLocation, CGEventType};
@ -62,8 +62,12 @@ impl KeyEvent<CGKeyCode> for CGEvent {
KEY_CAPSLOCK => NX_DEVICECAPSLOCKMASK,
_ => panic!("unhandled key: {}", self.code()),
};
if (flags & mask) != 0 { KeyState::DOWN } else { KeyState::UP }
},
if (flags & mask) != 0 {
KeyState::DOWN
} else {
KeyState::UP
}
}
CGEventType::KeyDown => KeyState::DOWN,
CGEventType::KeyUp => KeyState::UP,
CGEventType::TapDisabledByTimeout => {
@ -71,11 +75,11 @@ impl KeyEvent<CGKeyCode> for CGEvent {
todo!("implement register listener");
//register_listener(channel);
//KeyState::OTHER
},
}
_ => {
println!("Received unknown EventType: {:?}", event_type);
KeyState::OTHER
},
}
}
}
}
@ -99,15 +103,21 @@ impl Keyboard<CGKeyCode, CGEvent, Option<CGEvent>> for CGEventSource {
self.send_mod_code_value(code, event.value() == KeyState::UP, event)
}
fn send_mod_code_value(&self, code: CGKeyCode, up_not_down: bool, _event: &mut CGEvent) -> Result<Option<CGEvent>> {
fn send_mod_code_value(
&self,
code: CGKeyCode,
up_not_down: bool,
_event: &mut CGEvent,
) -> Result<Option<CGEvent>> {
//println!("send_mod_code_value orig: {} code: {}, up_not_down: {}", event.code(), code, up_not_down);
//return Ok(None);
let event =
CGEvent::new_keyboard_event(self.clone(), code, !up_not_down)
let event = CGEvent::new_keyboard_event(self.clone(), code, !up_not_down)
.expect("Failed creating event");
match tapLocation {
CGEventTapLocation::HID => event.set_integer_value_field(EventField::EVENT_SOURCE_USER_DATA, uniqueHIDUserData),
CGEventTapLocation::HID => {
event.set_integer_value_field(EventField::EVENT_SOURCE_USER_DATA, uniqueHIDUserData)
}
_ => {}
};
event.post(tapLocation);
@ -146,12 +156,14 @@ pub fn main_res() -> Result<()> {
let key_maps = MacOSKeyMaps::from_cfg(&key_map, &config.config_file);
//println!("key_maps: {}", key_maps);
let callback_pointer: CallbackPointer = (key_maps, CGEventSource::new(CGEventSourceStateID::Private).expect("Failed creating event source"));
let callback_pointer: CallbackPointer = (
key_maps,
CGEventSource::new(CGEventSourceStateID::Private).expect("Failed creating event source"),
);
let mask = CGEventMaskBit(CGEventType::KeyDown)
| CGEventMaskBit(CGEventType::KeyUp)
| CGEventMaskBit(CGEventType::FlagsChanged)
;
| CGEventMaskBit(CGEventType::FlagsChanged);
unsafe {
let options = 0;
@ -191,12 +203,14 @@ pub fn main_res() -> Result<()> {
#[derive(Debug)]
struct Config {
config_file: String
config_file: String,
}
impl Config {
fn new(config_file: String) -> Self {
Config { config_file: config_file }
Config {
config_file: config_file,
}
}
}
@ -224,7 +238,10 @@ fn parse_args() -> Config {
default_configs.push("keymap.toml".to_string());
let c_msg = format!("specify the keymap config file to use (default in order: {:?})", default_configs);
let c_msg = format!(
"specify the keymap config file to use (default in order: {:?})",
default_configs
);
let mut opts = Options::new();
opts.optflag("h", "help", "prints this help message");
@ -278,16 +295,17 @@ type CGEventTapOptions = u32;
type CGEventTapPlacement = u32;
// Callback Type
type CGEventTapCallBack = extern "C" fn(Pointer, CGEventType, CGEvent, &mut CallbackPointer) -> CGEvent;
type CGEventTapCallBack =
extern "C" fn(Pointer, CGEventType, CGEvent, &mut CallbackPointer) -> CGEvent;
// Constants
const kCGSessionEventTap: CGEventTapLocation = CGEventTapLocation::HID;
const kCGHeadInsertEventTap: CGEventTapPlacement = 0;
// Link to ApplicationServices/ApplicationServices.h and Carbon/Carbon.h
#[link(name = "ApplicationServices", kind = "framework")]
#[link(name = "Carbon", kind = "framework")]
extern {
// Link to ApplicationServices/ApplicationServices.h and Carbon/Carbon.h
#[link(name = "ApplicationServices", kind = "framework")]
#[link(name = "Carbon", kind = "framework")]
extern "C" {
/// Pass through to the default loop modes
pub static kCFRunLoopCommonModes: Pointer;
@ -364,14 +382,10 @@ const kCGHeadInsertEventTap: CGEventTapPlacement = 0;
) -> Pointer;
/// Adds a CFRunLoopSource object to a run loop mode.
pub fn CFRunLoopAddSource(
run_loop: Pointer,
run_loop_source: Pointer,
mode: Pointer,
);
pub fn CFRunLoopAddSource(run_loop: Pointer, run_loop_source: Pointer, mode: Pointer);
pub fn CGEventTapEnable(port: CFMachPortRef, enable: bool);
}
}
const NX_DEVICELCTLKEYMASK: u64 = 0x00000001;
const NX_DEVICERCTLKEYMASK: u64 = 0x00002000;
@ -388,7 +402,12 @@ const NX_DEVICECAPSLOCKMASK: u64 = 1 << 16;
/// to which the event tap is added as a source.
#[no_mangle]
#[allow(unused_variables, improper_ctypes_definitions)]
pub extern fn callback(proxy: Pointer, event_type: CGEventType, mut event: CGEvent, callback_pointer: &mut CallbackPointer) -> CGEvent {
pub extern "C" fn callback(
proxy: Pointer,
event_type: CGEventType,
mut event: CGEvent,
callback_pointer: &mut CallbackPointer,
) -> CGEvent {
let (key_maps, event_source) = callback_pointer;
match tapLocation {
CGEventTapLocation::HID => {
@ -400,15 +419,16 @@ pub extern fn callback(proxy: Pointer, event_type: CGEventType, mut event: CGEve
_ => {}
};
key_maps.send_event(&mut event, &event_source).expect("macos shouldn't error...")
key_maps
.send_event(&mut event, &event_source)
.expect("macos shouldn't error...")
.unwrap_or_else(|| {
event.set_type(CGEventType::Null);
event
}) // None means return NULL
}
}
/// Redefine macro for bitshifting from header as function here
pub fn CGEventMaskBit(eventType: CGEventType) -> CGEventMask {
/// Redefine macro for bitshifting from header as function here
pub fn CGEventMaskBit(eventType: CGEventType) -> CGEventMask {
1 << (eventType as u32)
}
}

View File

@ -1,4 +1,3 @@
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
fn main() {
let ret = rusty_keys::main_res();

View File

@ -1,6 +1,5 @@
use std::{collections::HashMap, convert::TryFrom};
use winapi::shared::minwindef::DWORD;
use std::collections::HashMap;
use std::convert::TryFrom;
// https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
@ -557,7 +556,11 @@ pub fn key_map() -> HashMap<&'static str, USizeableDWORD> {
("P0", KEY_KP0),
("PDOT", KEY_KPDOT),
("PENT", KEY_KPENTER),
].iter().cloned().map(|(m, v)| (m, USizeableDWORD(v))).collect()
]
.iter()
.cloned()
.map(|(m, v)| (m, USizeableDWORD(v)))
.collect()
}
// https://www.reddit.com/r/rust/comments/9xth8g/why_no_from_conversion_from_u32_to_usize/

View File

@ -1,24 +1,32 @@
#![windows_subsystem = "windows"]
use crate::*;
use std::env;
use std::process::exit;
use std::{env, process::exit};
use getopts::Options;
use std::fs::File;
use winapi::um::winuser::{KBDLLHOOKSTRUCT, WH_KEYBOARD_LL, MSG, GetMessageW, CallNextHookEx, SetWindowsHookExW, INPUT_KEYBOARD, MapVirtualKeyW, LPINPUT, INPUT, KEYBDINPUT, SendInput, KEYEVENTF_SCANCODE, KEYEVENTF_KEYUP, WM_KEYUP, WM_KEYDOWN, MAPVK_VK_TO_VSC, ShowWindow, SW_HIDE};
use winapi::shared::windef::{HHOOK__, HWND};
use winapi::shared::minwindef::{LRESULT, WPARAM, LPARAM, HINSTANCE};
use winapi::shared::basetsd::ULONG_PTR;
use winapi::ctypes::c_int;
use winapi::{
ctypes::c_int,
shared::{
basetsd::ULONG_PTR,
minwindef::{HINSTANCE, LPARAM, LRESULT, WPARAM},
windef::{HHOOK__, HWND},
},
um::winuser::{
CallNextHookEx, GetMessageW, MapVirtualKeyW, SendInput, SetWindowsHookExW, ShowWindow,
INPUT, INPUT_KEYBOARD, KBDLLHOOKSTRUCT, KEYBDINPUT, KEYEVENTF_KEYUP, KEYEVENTF_SCANCODE,
LPINPUT, MAPVK_VK_TO_VSC, MSG, SW_HIDE, WH_KEYBOARD_LL, WM_KEYDOWN, WM_KEYUP,
},
};
pub mod codes;
use codes::*;
use std::sync::atomic::{AtomicPtr, Ordering};
use std::mem::{zeroed, size_of};
use winapi::_core::ptr::null_mut;
use winapi::_core::mem::transmute_copy;
use std::{
mem::{size_of, zeroed},
sync::atomic::{AtomicPtr, Ordering},
};
use winapi::_core::{mem::transmute_copy, ptr::null_mut};
use lazy_static::lazy_static;
use std::sync::Mutex;
@ -65,7 +73,12 @@ impl Keyboard<USizeableDWORD, InputEvent, LRESULT> for Device {
self.send_mod_code_value(code, event.value as u32 == WM_KEYUP, event)
}
fn send_mod_code_value(&self, code: USizeableDWORD, up_not_down: bool, _event: &mut InputEvent) -> Result<LRESULT> {
fn send_mod_code_value(
&self,
code: USizeableDWORD,
up_not_down: bool,
_event: &mut InputEvent,
) -> Result<LRESULT> {
let flags = if up_not_down {
KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP
} else {
@ -132,7 +145,7 @@ unsafe extern "system" fn keybd_proc(code: c_int, w_param: WPARAM, l_param: LPAR
kb_struct.vkCode, kb_struct.scanCode, kb_struct.flags, kb_struct.time, kb_struct.dwExtraInfo);
*/
let mut input_event = InputEvent{
let mut input_event = InputEvent {
code,
value: w_param,
kb_hook_pointer: l_param,
@ -142,13 +155,17 @@ unsafe extern "system" fn keybd_proc(code: c_int, w_param: WPARAM, l_param: LPAR
// .unwrap() is ok because windows impl can actually never can fail
//DEVICE.send(&mut input_event).unwrap()
//KEY_MAPPER.send_event(&mut input_event, &DEVICE).unwrap()
KEY_MAPPER.lock().unwrap().send_event(&mut input_event, &DEVICE).unwrap()
KEY_MAPPER
.lock()
.unwrap()
.send_event(&mut input_event, &DEVICE)
.unwrap()
}
fn set_hook(
hook_id: i32,
hook_ptr: &AtomicPtr<HHOOK__>,
hook_proc: unsafe extern "system" fn (c_int, WPARAM, LPARAM) -> LRESULT,
hook_proc: unsafe extern "system" fn(c_int, WPARAM, LPARAM) -> LRESULT,
) {
hook_ptr.store(
unsafe { SetWindowsHookExW(hook_id, Some(hook_proc), 0 as HINSTANCE, 0) },
@ -172,7 +189,6 @@ fn send_keybd_input(flags: u32, key_code: USizeableDWORD) {
unsafe { SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int) };
}
pub fn main_res() -> Result<()> {
// this is just to cause the lazy_static init to run first, so if -h or -v is wanted, we do that
// and exit immediately... todo: how to avoid mutex/lazy_static entirely???
@ -188,7 +204,7 @@ pub fn main_res() -> Result<()> {
// hide window
// todo: probably should be tray icon someplace in future to quit, and error messages as windows popups etc...
let hwnd = GetConsoleWindow();
ShowWindow( hwnd, SW_HIDE );
ShowWindow(hwnd, SW_HIDE);
}
let mut msg: MSG = unsafe { zeroed() };
@ -201,12 +217,14 @@ pub fn main_res() -> Result<()> {
#[derive(Debug)]
struct Config {
config_file: String
config_file: String,
}
impl Config {
fn new(config_file: String) -> Self {
Config { config_file: config_file }
Config {
config_file: config_file,
}
}
}
@ -234,7 +252,10 @@ fn parse_args() -> Config {
default_configs.push("keymap.toml".to_string());
let c_msg = format!("specify the keymap config file to use (default in order: {:?})", default_configs);
let c_msg = format!(
"specify the keymap config file to use (default in order: {:?})",
default_configs
);
let mut opts = Options::new();
opts.optflag("h", "help", "prints this help message");