2017-09-21 22:34:24 -04:00
2019-09-29 23:49:23 -04:00
use crate ::Device ;
2017-09-21 22:34:24 -04:00
use libc ::{ c_int , input_event } ;
2019-10-05 19:39:54 -04:00
use uinput_sys ::{ KEY_LEFTSHIFT , KEY_RIGHTSHIFT , KEY_CAPSLOCK } ;
2017-09-21 22:34:24 -04:00
use std ::fs ::File ;
use std ::io ::Read ;
use std ::collections ::HashMap ;
2019-09-29 23:49:23 -04:00
use crate ::{ Error , Result } ;
2017-11-15 01:08:38 -05:00
2017-09-21 22:34:24 -04:00
// 1 is down, 0 is up
const DOWN : i32 = 1 ;
const UP : i32 = 0 ;
const INVERT_KEY_FLAG : char = '^' ;
const CAPS_MODIFY_KEY_FLAG : char = '*' ;
const HALF_KEY_SEPARATOR : char = ':' ;
const LEFTSHIFT_INDEX : usize = KEY_LEFTSHIFT as usize ;
const RIGHTSHIFT_INDEX : usize = KEY_RIGHTSHIFT as usize ;
const CAPSLOCK_INDEX : usize = KEY_CAPSLOCK as usize ;
const KEY_LEFTSHIFT_U16 : u16 = KEY_LEFTSHIFT as u16 ;
const KEY_RIGHTSHIFT_U16 : u16 = KEY_RIGHTSHIFT as u16 ;
const KEY_CAPSLOCK_U16 : u16 = KEY_CAPSLOCK as u16 ;
trait KeyMapper {
2017-11-15 01:08:38 -05:00
fn send_event ( & self , key_state : & [ bool ] , event : & mut input_event , device : & Device ) -> Result < ( ) > ;
2017-09-21 22:34:24 -04:00
}
pub struct KeyMaps {
keymaps : Vec < Box < KeyMapper > > ,
keymap_index_keys : HashMap < u16 , usize > ,
switch_layout_keys : Vec < usize > ,
key_state : [ bool ; KEY_MAX ] ,
revert_default_key : u16 ,
revert_keymap_index : usize ,
// above do not change, below does
chosen_keymap_index : usize ,
current_keymap_index : usize ,
}
2017-11-15 22:59:17 -05:00
fn parse_key ( key_map : & HashMap < & 'static str , c_int > , key : & str ) -> u16 {
2017-09-21 22:34:24 -04:00
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 as u16 ,
None = > panic! ( " unknown key: {} " , key . trim ( ) )
}
}
2017-11-15 22:59:17 -05:00
fn parse_keymap_numeric ( key_map : & HashMap < & 'static str , c_int > , keymap : & str ) -> Vec < u16 > {
2017-09-21 22:34:24 -04:00
keymap . split ( " , " ) . map ( | k | parse_key ( key_map , k ) ) . collect ( )
}
2017-11-15 22:59:17 -05:00
fn parse_key_half_inverted ( key_map : & HashMap < & 'static str , c_int > , key : & str ) -> HalfInvertedKey {
2017-09-21 22:34:24 -04:00
HalfInvertedKey {
code : parse_key ( key_map , key ) ,
invert_shift : key . contains ( INVERT_KEY_FLAG ) ,
capslock_nomodify : key . contains ( CAPS_MODIFY_KEY_FLAG ) ,
}
}
// maybe shortcut to this if not contains * or :
2017-11-15 22:59:17 -05:00
fn parse_keymap_u16 ( key_map : & HashMap < & 'static str , c_int > , keymap : & str ) -> Vec < u16 > {
2017-09-23 01:29:23 -04:00
keymap . split ( " , " ) . map ( | k | parse_key ( key_map , k ) ) . collect ( )
}
// todo: how do I return an iterator here instead of .collect to Vec?
2017-11-15 22:59:17 -05:00
fn parse_keymap ( key_map : & HashMap < & 'static str , c_int > , keymap : & str ) -> Vec < Key > {
2017-09-23 01:29:23 -04:00
keymap . split ( " , " ) . map ( | k | {
let ret : Key = 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 ( ) ) ;
}
let mut shift_half = parse_key_half_inverted ( key_map , keys [ 1 ] ) ;
shift_half . invert_shift = ! shift_half . invert_shift ;
Key ::FullKey ( parse_key_half_inverted ( key_map , keys [ 0 ] ) , shift_half )
} else if k . contains ( INVERT_KEY_FLAG ) | | k . contains ( CAPS_MODIFY_KEY_FLAG ) {
Key ::HalfKey ( parse_key_half_inverted ( key_map , k ) )
} else {
Key ::Direct ( parse_key ( key_map , k ) )
} ;
ret
} ) . collect ( )
2017-09-21 22:34:24 -04:00
}
impl KeyMaps {
2017-11-15 22:59:17 -05:00
pub fn from_cfg < P : AsRef < Path > > ( key_map : & HashMap < & 'static str , c_int > , path : P ) -> KeyMaps {
2017-09-21 22:34:24 -04:00
let key_map_config = parse_cfg ( path ) . expect ( " provided config cannot be found/parsed " ) ;
KeyMaps ::new ( key_map , key_map_config )
}
2017-11-15 22:59:17 -05:00
pub fn new ( key_map : & HashMap < & 'static str , c_int > , config : KeymapConfig ) -> KeyMaps {
2017-09-21 22:34:24 -04:00
if config . keymaps . len ( ) < 2 {
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 ( ) {
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 ] ) ;
2017-09-22 00:30:56 -04:00
//println!("base_keymap : {:?}", base_keymap);
2017-09-23 00:46:42 -04:00
let mut keymaps : Vec < Box < KeyMapper > > = vec! ( Box ::new ( Key ::Noop ) ) ; // todo: can we share the box?
2017-09-21 22:34:24 -04:00
let mut keymap_index_keys : HashMap < u16 , usize > = HashMap ::new ( ) ;
for ( x , v ) in config . keymaps . iter ( ) . enumerate ( ) {
keymap_index_keys . insert ( * key_map . get ( & * x . to_string ( ) ) . unwrap ( ) as u16 , x ) ;
if x = = 0 {
continue ;
}
2017-09-23 01:29:23 -04:00
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 ( ) ;
let mut i : usize = 0 ;
for key_code in v {
// todo: if these are the same, do Noop instead
keymap . map ( base_keymap [ i ] , key_code ) ;
i = i + 1 ;
if i > base_keymap . len ( ) {
panic! ( " all keymaps must be the same length, keymap index 0 length: {} , index {} length: {} , " , base_keymap . len ( ) , x , i ) ;
2017-09-21 22:34:24 -04:00
}
}
2017-09-23 01:29:23 -04:00
keymaps . push ( Box ::new ( keymap ) ) ;
} else {
// this is a simple keymap
let v = parse_keymap_u16 ( key_map , v ) ;
let mut keymap = CodeKeyMap ::new ( ) ;
let mut i : usize = 0 ;
for key_code in v {
keymap . map ( base_keymap [ i ] , key_code ) ;
i = i + 1 ;
if i > base_keymap . len ( ) {
panic! ( " all keymaps must be the same length, keymap index 0 length: {} , index {} length: {} , " , base_keymap . len ( ) , x , i ) ;
}
2017-09-21 22:34:24 -04:00
}
2017-09-23 01:29:23 -04:00
keymaps . push ( Box ::new ( keymap ) ) ;
2017-09-21 22:34:24 -04:00
}
}
//println!("keymaps: {:?}", keymaps);
//println!("keymap_index_keys: {:?}", keymap_index_keys);
KeyMaps {
keymaps : keymaps ,
keymap_index_keys : keymap_index_keys ,
switch_layout_keys : config . switch_layout_keys . iter ( ) . map ( | k | parse_key ( key_map , k ) as usize ) . collect ( ) ,
key_state : [ false ; KEY_MAX ] ,
// todo: detect key state? at least CAPSLOCK...
revert_default_key : parse_key ( key_map , & config . revert_default_key ) ,
revert_keymap_index : config . revert_keymap_index ,
chosen_keymap_index : config . default_keymap_index ,
current_keymap_index : config . default_keymap_index ,
}
}
}
//impl KeyMapper for KeyMaps {
impl KeyMaps {
2017-11-15 01:08:38 -05:00
pub fn send_event ( & mut self , mut event : & mut input_event , device : & Device ) -> Result < ( ) > {
2017-09-21 22:34:24 -04:00
//println!("type: {} code: {} value: {}", event.type_, event.code, event.value);
if event . value ! = 2 {
// todo: index check here...
if event . code = = KEY_CAPSLOCK_U16 {
if event . value = = DOWN {
self . key_state [ CAPSLOCK_INDEX ] = ! self . key_state [ CAPSLOCK_INDEX ] ;
}
} else {
self . key_state [ event . code as usize ] = event . value = = DOWN ;
}
let mut switch_layout_keys_pressed = true ;
for layout_switch_key in self . switch_layout_keys . iter_mut ( ) {
if ! self . key_state [ * layout_switch_key ] {
switch_layout_keys_pressed = false ;
break ;
}
}
//println!("switch_layout_keys_pressed: {}", self.switch_layout_keys_pressed);
if switch_layout_keys_pressed {
let new_index = self . keymap_index_keys . get ( & event . code ) ;
if new_index . is_some ( ) {
self . chosen_keymap_index = * new_index . unwrap ( ) ;
self . current_keymap_index = self . chosen_keymap_index ; // todo: what if revert_default_key is held? for now ignore
2017-11-15 01:08:38 -05:00
return Ok ( ( ) ) ; // we don't want to also send this keypress, so bail
2017-09-21 22:34:24 -04:00
}
}
if event . code = = self . revert_default_key {
match event . value {
// todo: 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... fix that...
DOWN = > self . current_keymap_index = self . revert_keymap_index ,
UP = > self . current_keymap_index = self . chosen_keymap_index ,
_ = > ( ) // do nothing for 2
}
}
}
2017-11-15 01:08:38 -05:00
self . keymaps [ self . current_keymap_index ] . send_event ( & self . key_state , & mut event , device )
2017-09-21 22:34:24 -04:00
}
}
// 249 is one more than KEY_MICMUTE which is max key in uinput-sys event.rs
const KEY_MAX : usize = 249 ;
struct KeyMap {
2017-09-23 00:47:20 -04:00
//keymap: Vec<Key>,
keymap : [ Key ; KEY_MAX ] ,
2017-09-21 22:34:24 -04:00
}
impl KeyMap {
pub fn new ( ) -> Self {
//let mut keymap = [0u16; KEY_MAX];
//let mut keymap : [Box<KeyMapper>; KEY_MAX] = [Box::new(NOOP); KEY_MAX];
//let mut keymap : [Box<KeyMapper>; KEY_MAX] = [Box::new(0u16); KEY_MAX];
2017-09-23 00:47:20 -04:00
let keymap : [ Key ; KEY_MAX ] = [ Key ::Noop ; KEY_MAX ] ;
/*
2017-09-23 00:46:42 -04:00
let mut keymap : Vec < Key > = Vec ::with_capacity ( KEY_MAX ) ;
2017-09-21 22:34:24 -04:00
#[ allow(unused_variables) ]
for x in 0 .. KEY_MAX {
2017-09-23 00:46:42 -04:00
keymap . push ( Key ::Noop ) ;
2017-09-21 22:34:24 -04:00
}
2017-09-23 00:47:20 -04:00
* /
2017-09-21 22:34:24 -04:00
// which is rustier
/*
for x in 0 .. KEY_MAX {
keymap [ x as usize ] = x as u16 ;
}
for ( x , v ) in keymap . iter_mut ( ) . enumerate ( ) {
* v = x as u16 ;
}
* /
//println!("keymap: {:?}", &keymap[..]);
KeyMap {
keymap : keymap
}
}
/*
pub fn map ( & mut self , from : u16 , to : u16 ) {
self . keymap [ from as usize ] = to ;
}
* /
2017-09-23 00:46:42 -04:00
pub fn map ( & mut self , from : u16 , to : Key ) {
2017-09-21 22:34:24 -04:00
self . keymap [ from as usize ] = to ;
}
}
impl KeyMapper for KeyMap {
2017-11-15 01:08:38 -05:00
fn send_event ( & self , key_state : & [ bool ] , event : & mut input_event , device : & Device ) -> Result < ( ) > {
self . keymap [ event . code as usize ] . send_event ( key_state , event , device )
2017-09-21 22:34:24 -04:00
}
}
2017-09-23 01:29:23 -04:00
struct CodeKeyMap {
//keymap: Vec<Key>,
keymap : [ u16 ; KEY_MAX ] ,
}
impl CodeKeyMap {
pub fn new ( ) -> Self {
let mut keymap = [ 0 u16 ; KEY_MAX ] ;
// which is rustier
/*
for x in 0 .. KEY_MAX {
keymap [ x as usize ] = x as u16 ;
}
* /
for ( x , v ) in keymap . iter_mut ( ) . enumerate ( ) {
* v = x as u16 ;
}
//println!("keymap: {:?}", &keymap[..]);
CodeKeyMap {
keymap : keymap
}
}
pub fn map ( & mut self , from : u16 , to : u16 ) {
self . keymap [ from as usize ] = to ;
}
}
impl KeyMapper for CodeKeyMap {
2017-11-15 01:08:38 -05:00
fn send_event ( & self , key_state : & [ bool ] , event : & mut input_event , device : & Device ) -> Result < ( ) > {
self . keymap [ event . code as usize ] . send_event ( key_state , event , device )
2017-09-23 01:29:23 -04:00
}
}
2017-11-15 01:08:38 -05:00
#[ allow(unused_variables, unused_mut) ]
2017-09-21 22:34:24 -04:00
impl KeyMapper for u16 {
2017-11-15 01:08:38 -05:00
fn send_event ( & self , key_state : & [ bool ] , mut event : & mut input_event , device : & Device ) -> Result < ( ) > {
2017-09-21 22:34:24 -04:00
event . code = * self ;
2017-11-15 01:08:38 -05:00
device . write_event ( event )
2017-09-21 22:34:24 -04:00
}
}
// todo:capslock_nomodify is like a whole-key thing, not a half-key thing, split code/invert_shift to own struct, send into send_key from *InvertedKey, maybe anyway, consider it, maybe 1 char for whole key and another for half?
2017-09-23 00:47:20 -04:00
#[ derive(Clone, Copy) ]
2017-09-21 22:34:24 -04:00
struct HalfInvertedKey {
code : u16 ,
// code this is describing
invert_shift : bool ,
// true to invert shift for this code
capslock_nomodify : bool ,
// true means capslock does not normally modify this, but you would like it to
}
impl HalfInvertedKey {
2017-11-15 01:08:38 -05:00
fn send_key ( & self , key_state : & [ bool ] , event : & mut input_event , device : & Device , left_shift : bool , right_shift : bool , caps_lock : bool ) -> Result < ( ) > {
2017-09-22 23:57:26 -04:00
let code = self . code ;
2017-09-21 22:34:24 -04:00
let value = event . value ;
let mut invert_shift = self . invert_shift ;
if value = = DOWN {
if caps_lock & & self . capslock_nomodify {
invert_shift = ! invert_shift ;
}
if invert_shift {
if left_shift {
event . code = KEY_LEFTSHIFT_U16 ;
event . value = UP ;
} else if right_shift {
event . code = KEY_RIGHTSHIFT_U16 ;
event . value = UP ;
} else {
event . code = KEY_LEFTSHIFT_U16 ;
event . value = DOWN ;
}
//event.code.send_event(key_state, event, device);
2017-11-15 01:08:38 -05:00
device . write_event ( event ) ? ;
2017-12-06 00:06:44 -05:00
// SYN_REPORT after, then key, then key's SYN_REPORT
device . synchronize ( ) ? ;
2017-09-21 22:34:24 -04:00
event . code = code ; // not needed since u16 does it
event . value = value ;
}
}
2017-11-15 01:08:38 -05:00
code . send_event ( key_state , event , device ) ? ;
2017-09-21 22:34:24 -04:00
if value = = UP {
if caps_lock & & self . capslock_nomodify {
invert_shift = ! invert_shift ;
}
if invert_shift {
if left_shift {
event . code = KEY_LEFTSHIFT_U16 ;
event . value = DOWN ;
} else if right_shift {
event . code = KEY_RIGHTSHIFT_U16 ;
event . value = DOWN ;
} else {
event . code = KEY_LEFTSHIFT_U16 ;
event . value = UP ;
}
//event.code.send_event(key_state, event, device);
2017-12-06 00:06:44 -05:00
// SYN_REPORT first after key, then shift, then key's SYN_REPORT which will be used for shift's
device . synchronize ( ) ? ;
2017-11-15 01:08:38 -05:00
device . write_event ( event ) ? ;
2017-09-21 22:34:24 -04:00
// neither of these are needed now...
event . code = code ; // not needed since u16 does it
event . value = value ;
}
}
2017-11-15 01:08:38 -05:00
Ok ( ( ) )
2017-09-21 22:34:24 -04:00
}
}
impl KeyMapper for HalfInvertedKey {
2017-11-15 01:08:38 -05:00
fn send_event ( & self , key_state : & [ bool ] , event : & mut input_event , device : & Device ) -> Result < ( ) > {
2017-09-21 22:34:24 -04:00
let left_shift = key_state [ LEFTSHIFT_INDEX ] ;
let right_shift = key_state [ RIGHTSHIFT_INDEX ] ;
let caps_lock = key_state [ CAPSLOCK_INDEX ] ;
2017-11-15 01:08:38 -05:00
self . send_key ( key_state , event , device , left_shift , right_shift , caps_lock )
2017-09-21 22:34:24 -04:00
}
}
2017-09-23 00:47:20 -04:00
#[ derive(Clone, Copy) ]
2017-09-23 00:46:42 -04:00
enum Key {
Noop ,
Direct ( u16 ) ,
HalfKey ( HalfInvertedKey ) ,
FullKey ( HalfInvertedKey , HalfInvertedKey ) ,
2017-09-21 22:34:24 -04:00
}
2017-09-23 00:46:42 -04:00
impl KeyMapper for Key {
2017-11-15 01:08:38 -05:00
fn send_event ( & self , key_state : & [ bool ] , event : & mut input_event , device : & Device ) -> Result < ( ) > {
2017-09-23 00:46:42 -04:00
match * self {
Key ::Noop = > {
2017-11-15 01:08:38 -05:00
device . write_event ( event )
2017-09-23 00:46:42 -04:00
} ,
Key ::Direct ( code ) = > {
2017-11-15 01:08:38 -05:00
code . send_event ( key_state , event , device )
2017-09-23 00:46:42 -04:00
} ,
Key ::HalfKey ( ref key_half ) = > {
2017-11-15 01:08:38 -05:00
key_half . send_event ( key_state , event , device )
2017-09-23 00:46:42 -04:00
} ,
Key ::FullKey ( ref noshift_half , ref shift_half ) = > {
let left_shift = key_state [ LEFTSHIFT_INDEX ] ;
let right_shift = key_state [ RIGHTSHIFT_INDEX ] ;
let caps_lock = key_state [ CAPSLOCK_INDEX ] ;
if caps_lock ! = ( left_shift | | right_shift ) {
2017-11-15 01:08:38 -05:00
shift_half . send_key ( key_state , event , device , left_shift , right_shift , caps_lock )
2017-09-23 00:46:42 -04:00
} else {
2017-11-15 01:08:38 -05:00
noshift_half . send_key ( key_state , event , device , left_shift , right_shift , caps_lock )
2017-09-23 00:46:42 -04:00
}
} ,
2017-09-21 22:34:24 -04:00
}
}
}
use std ::path ::Path ;
2019-09-30 22:55:16 -04:00
use serde ::Deserialize ;
2017-09-21 22:34:24 -04:00
#[ derive(Deserialize, Debug) ]
pub struct KeymapConfig {
switch_layout_keys : Vec < String > ,
revert_default_key : String ,
revert_keymap_index : usize ,
default_keymap_index : usize ,
keymaps : Vec < String >
}
2017-11-15 01:08:38 -05:00
fn parse_cfg < P : AsRef < Path > > ( path : P ) -> Result < KeymapConfig > {
2017-09-21 22:34:24 -04:00
let mut f = File ::open ( path ) ? ;
let mut input = String ::new ( ) ;
f . read_to_string ( & mut input ) ? ;
//toml::from_str(&input)?
match toml ::from_str ( & input ) {
Ok ( toml ) = > Ok ( toml ) ,
2017-11-15 01:08:38 -05:00
Err ( _ ) = > Err ( Error ::NotFound ) // todo: something better
2017-09-21 22:34:24 -04:00
}
}