rusty_keys/
keymapper.rs

1
2use device::Device;
3
4use ffi::*;
5use libc::{c_int, input_event};
6
7use std::fs::File;
8use std::io::Read;
9use std::collections::HashMap;
10
11// 1 is down, 0 is up
12const DOWN: i32 = 1;
13const UP: i32 = 0;
14const INVERT_KEY_FLAG: char = '^';
15const CAPS_MODIFY_KEY_FLAG: char = '*';
16const HALF_KEY_SEPARATOR: char = ':';
17
18const LEFTSHIFT_INDEX: usize = KEY_LEFTSHIFT as usize;
19const RIGHTSHIFT_INDEX: usize = KEY_RIGHTSHIFT as usize;
20const CAPSLOCK_INDEX: usize = KEY_CAPSLOCK as usize;
21
22const KEY_LEFTSHIFT_U16: u16 = KEY_LEFTSHIFT as u16;
23const KEY_RIGHTSHIFT_U16: u16 = KEY_RIGHTSHIFT as u16;
24const KEY_CAPSLOCK_U16: u16 = KEY_CAPSLOCK as u16;
25
26trait KeyMapper {
27    fn send_event(&self, key_state: &[bool], event: &mut input_event, device: &Device);
28}
29
30pub struct KeyMaps {
31    keymaps: Vec<Box<KeyMapper>>,
32    keymap_index_keys: HashMap<u16, usize>,
33    switch_layout_keys: Vec<usize>,
34    key_state: [bool; KEY_MAX],
35    revert_default_key: u16,
36    revert_keymap_index: usize,
37    // above do not change, below does
38    chosen_keymap_index: usize,
39    current_keymap_index: usize,
40}
41
42fn parse_key(key_map: &HashMap<&'static str, *const c_int>, key: &str) -> u16 {
43    match key_map.get(key.trim_matches(|c: char| c.is_whitespace() || c == INVERT_KEY_FLAG || c == CAPS_MODIFY_KEY_FLAG)) {
44        Some(key_code) => *key_code as u16,
45        None => panic!("unknown key: {}", key.trim())
46    }
47}
48
49fn parse_keymap_numeric(key_map: &HashMap<&'static str, *const c_int>, keymap: &str) -> Vec<u16> {
50    keymap.split(",").map(|k| parse_key(key_map, k)).collect()
51}
52
53fn parse_key_half_inverted(key_map: &HashMap<&'static str, *const c_int>, key: &str) -> HalfInvertedKey {
54    HalfInvertedKey {
55        code: parse_key(key_map, key),
56        invert_shift: key.contains(INVERT_KEY_FLAG),
57        capslock_nomodify: key.contains(CAPS_MODIFY_KEY_FLAG),
58    }
59}
60
61// maybe shortcut to this if not contains * or :
62fn parse_keymap_u16(key_map: &HashMap<&'static str, *const c_int>, keymap: &str) -> Vec<u16> {
63    keymap.split(",").map(|k| parse_key(key_map, k)).collect()
64}
65
66// todo: how do I return an iterator here instead of .collect to Vec?
67fn parse_keymap(key_map: &HashMap<&'static str, *const c_int>, keymap: &str) -> Vec<Key> {
68    keymap.split(",").map(|k| {
69        let ret: Key = if k.contains(HALF_KEY_SEPARATOR) {
70            let keys: Vec<&str> = k.split(HALF_KEY_SEPARATOR).collect();
71            if keys.len() != 2 {
72                panic!("split key can only have 2 keys, 1 :, has {} keys", keys.len());
73            }
74            let mut shift_half = parse_key_half_inverted(key_map, keys[1]);
75            shift_half.invert_shift = !shift_half.invert_shift;
76            Key::FullKey(parse_key_half_inverted(key_map, keys[0]), shift_half)
77        } else if k.contains(INVERT_KEY_FLAG) || k.contains(CAPS_MODIFY_KEY_FLAG) {
78            Key::HalfKey(parse_key_half_inverted(key_map, k))
79        } else {
80            Key::Direct(parse_key(key_map, k))
81        };
82        ret
83    }).collect()
84}
85
86impl KeyMaps {
87    pub fn from_cfg<P: AsRef<Path>>(key_map: &HashMap<&'static str, *const c_int>, path: P) -> KeyMaps {
88        let key_map_config = parse_cfg(path).expect("provided config cannot be found/parsed");
89        KeyMaps::new(key_map, key_map_config)
90    }
91
92    pub fn new(key_map: &HashMap<&'static str, *const c_int>, config: KeymapConfig) -> KeyMaps {
93        if config.keymaps.len() < 2 {
94            panic!("must have at least 2 keymaps (original and mapped) but only have {},", config.keymaps.len());
95        }
96        if config.default_keymap_index >= config.keymaps.len() || config.revert_keymap_index >= config.keymaps.len() {
97            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());
98        }
99        let base_keymap = parse_keymap_numeric(key_map, &config.keymaps[0]);
100        //println!("base_keymap      : {:?}", base_keymap);
101        let mut keymaps: Vec<Box<KeyMapper>> = vec!(Box::new(Key::Noop)); // todo: can we share the box?
102        let mut keymap_index_keys: HashMap<u16, usize> = HashMap::new();
103        for (x, v) in config.keymaps.iter().enumerate() {
104            keymap_index_keys.insert(*key_map.get(&*x.to_string()).unwrap() as u16, x);
105            if x == 0 {
106                continue;
107            }
108            if v.contains(HALF_KEY_SEPARATOR) || v.contains(INVERT_KEY_FLAG) || v.contains(CAPS_MODIFY_KEY_FLAG) {
109                // we need KeyMap, the complicated more memory taking one
110                let v = parse_keymap(key_map, v);
111                let mut keymap = KeyMap::new();
112                let mut i: usize = 0;
113                for key_code in v {
114                    // todo: if these are the same, do Noop instead
115                    keymap.map(base_keymap[i], key_code);
116                    i = i + 1;
117                    if i > base_keymap.len() {
118                        panic!("all keymaps must be the same length, keymap index 0 length: {}, index {} length: {},", base_keymap.len(), x, i);
119                    }
120                }
121                keymaps.push(Box::new(keymap));
122            } else {
123                // this is a simple keymap
124                let v = parse_keymap_u16(key_map, v);
125                let mut keymap = CodeKeyMap::new();
126                let mut i: usize = 0;
127                for key_code in v {
128                    keymap.map(base_keymap[i], key_code);
129                    i = i + 1;
130                    if i > base_keymap.len() {
131                        panic!("all keymaps must be the same length, keymap index 0 length: {}, index {} length: {},", base_keymap.len(), x, i);
132                    }
133                }
134                keymaps.push(Box::new(keymap));
135            }
136        }
137        //println!("keymaps: {:?}", keymaps);
138        //println!("keymap_index_keys: {:?}", keymap_index_keys);
139
140        KeyMaps {
141            keymaps: keymaps,
142            keymap_index_keys: keymap_index_keys,
143            switch_layout_keys: config.switch_layout_keys.iter().map(|k| parse_key(key_map, k) as usize).collect(),
144            key_state: [false; KEY_MAX],
145            // todo: detect key state? at least CAPSLOCK...
146            revert_default_key: parse_key(key_map, &config.revert_default_key),
147            revert_keymap_index: config.revert_keymap_index,
148            chosen_keymap_index: config.default_keymap_index,
149            current_keymap_index: config.default_keymap_index,
150        }
151    }
152}
153
154//impl KeyMapper for KeyMaps {
155impl KeyMaps {
156    pub fn send_event(&mut self, mut event: &mut input_event, device: &Device) {
157        //println!("type: {} code: {} value: {}", event.type_, event.code, event.value);
158        if event.value != 2 {
159            // todo: index check here...
160            if event.code == KEY_CAPSLOCK_U16 {
161                if event.value == DOWN {
162                    self.key_state[CAPSLOCK_INDEX] = !self.key_state[CAPSLOCK_INDEX];
163                }
164            } else {
165                self.key_state[event.code as usize] = event.value == DOWN;
166            }
167            let mut switch_layout_keys_pressed = true;
168            for layout_switch_key in self.switch_layout_keys.iter_mut() {
169                if !self.key_state[*layout_switch_key] {
170                    switch_layout_keys_pressed = false;
171                    break;
172                }
173            }
174            //println!("switch_layout_keys_pressed: {}", self.switch_layout_keys_pressed);
175            if switch_layout_keys_pressed {
176                let new_index = self.keymap_index_keys.get(&event.code);
177                if new_index.is_some() {
178                    self.chosen_keymap_index = *new_index.unwrap();
179                    self.current_keymap_index = self.chosen_keymap_index; // todo: what if revert_default_key is held? for now ignore
180                    return; // we don't want to also send this keypress, so bail
181                }
182            }
183            if event.code == self.revert_default_key {
184                match event.value {
185                    // 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...
186                    DOWN => self.current_keymap_index = self.revert_keymap_index,
187                    UP => self.current_keymap_index = self.chosen_keymap_index,
188                    _ => () // do nothing for 2
189                }
190            }
191        }
192        self.keymaps[self.current_keymap_index].send_event(&self.key_state, &mut event, device);
193    }
194}
195
196// 249 is one more than KEY_MICMUTE which is max key in uinput-sys event.rs
197const KEY_MAX: usize = 249;
198
199struct KeyMap {
200    //keymap: Vec<Key>,
201    keymap: [Key; KEY_MAX],
202}
203
204impl KeyMap {
205    pub fn new() -> Self {
206        //let mut keymap = [0u16; KEY_MAX];
207        //let mut keymap : [Box<KeyMapper>; KEY_MAX] = [Box::new(NOOP); KEY_MAX];
208        //let mut keymap : [Box<KeyMapper>; KEY_MAX] = [Box::new(0u16); KEY_MAX];
209        let keymap : [Key; KEY_MAX] = [Key::Noop; KEY_MAX];
210        /*
211        let mut keymap: Vec<Key> = Vec::with_capacity(KEY_MAX);
212        #[allow(unused_variables)]
213        for x in 0..KEY_MAX {
214            keymap.push(Key::Noop);
215        }
216        */
217        // which is rustier
218        /*
219        for x  in 0..KEY_MAX {
220            keymap[x as usize] = x as u16;
221        }
222        for (x, v) in keymap.iter_mut().enumerate() {
223            *v = x as u16;
224        }
225        */
226        //println!("keymap: {:?}", &keymap[..]);
227        KeyMap {
228            keymap: keymap
229        }
230    }
231    /*
232        pub fn map(&mut self, from : u16, to: u16) {
233            self.keymap[from as usize] = to;
234        }
235    */
236    pub fn map(&mut self, from: u16, to: Key) {
237        self.keymap[from as usize] = to;
238    }
239}
240
241impl KeyMapper for KeyMap {
242    fn send_event(&self, key_state: &[bool], event: &mut input_event, device: &Device) {
243        self.keymap[event.code as usize].send_event(key_state, event, device);
244        //event.code = self.keymap[event.code as usize];
245        //device.write_event(event).expect("could not write event?");
246    }
247}
248
249struct CodeKeyMap {
250    //keymap: Vec<Key>,
251    keymap: [u16; KEY_MAX],
252}
253
254impl CodeKeyMap {
255    pub fn new() -> Self {
256        let mut keymap = [0u16; KEY_MAX];
257        // which is rustier
258        /*
259        for x  in 0..KEY_MAX {
260            keymap[x as usize] = x as u16;
261        }
262        */
263        for (x, v) in keymap.iter_mut().enumerate() {
264            *v = x as u16;
265        }
266        //println!("keymap: {:?}", &keymap[..]);
267        CodeKeyMap {
268            keymap: keymap
269        }
270    }
271
272    pub fn map(&mut self, from: u16, to: u16) {
273        self.keymap[from as usize] = to;
274    }
275}
276
277impl KeyMapper for CodeKeyMap {
278    fn send_event(&self, key_state: &[bool], event: &mut input_event, device: &Device) {
279        self.keymap[event.code as usize].send_event(key_state, event, device);
280    }
281}
282
283#[allow(unused_variables)]
284impl KeyMapper for u16 {
285    fn send_event(&self, key_state: &[bool], mut event: &mut input_event, device: &Device) {
286        event.code = *self;
287        device.write_event(event).expect("could not write event?");
288    }
289}
290
291// 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?
292#[derive(Clone, Copy)]
293struct HalfInvertedKey {
294    code: u16,
295    // code this is describing
296    invert_shift: bool,
297    // true to invert shift for this code
298    capslock_nomodify: bool,
299    // true means capslock does not normally modify this, but you would like it to
300}
301
302impl HalfInvertedKey {
303    fn send_key(&self, key_state: &[bool], event: &mut input_event, device: &Device, left_shift: bool, right_shift: bool, caps_lock: bool) {
304        let code = self.code;
305        let value = event.value;
306        let mut invert_shift = self.invert_shift;
307        if value == DOWN {
308            if caps_lock && self.capslock_nomodify {
309                invert_shift = !invert_shift;
310            }
311            if invert_shift {
312                if left_shift {
313                    event.code = KEY_LEFTSHIFT_U16;
314                    event.value = UP;
315                } else if right_shift {
316                    event.code = KEY_RIGHTSHIFT_U16;
317                    event.value = UP;
318                } else {
319                    event.code = KEY_LEFTSHIFT_U16;
320                    event.value = DOWN;
321                }
322                //event.code.send_event(key_state, event, device);
323                device.write_event(event).expect("could not write event?");
324                event.code = code; // not needed since u16 does it
325                event.value = value;
326            }
327        }
328        code.send_event(key_state, event, device);
329        if value == UP {
330            if caps_lock && self.capslock_nomodify {
331                invert_shift = !invert_shift;
332            }
333            if invert_shift {
334                if left_shift {
335                    event.code = KEY_LEFTSHIFT_U16;
336                    event.value = DOWN;
337                } else if right_shift {
338                    event.code = KEY_RIGHTSHIFT_U16;
339                    event.value = DOWN;
340                } else {
341                    event.code = KEY_LEFTSHIFT_U16;
342                    event.value = UP;
343                }
344                //event.code.send_event(key_state, event, device);
345                device.write_event(event).expect("could not write event?");
346                // neither of these are needed now...
347                event.code = code; // not needed since u16 does it
348                event.value = value;
349            }
350        }
351    }
352}
353
354impl KeyMapper for HalfInvertedKey {
355    fn send_event(&self, key_state: &[bool], event: &mut input_event, device: &Device) {
356        let left_shift = key_state[LEFTSHIFT_INDEX];
357        let right_shift = key_state[RIGHTSHIFT_INDEX];
358        let caps_lock = key_state[CAPSLOCK_INDEX];
359        self.send_key(key_state, event, device, left_shift, right_shift, caps_lock);
360    }
361}
362
363#[derive(Clone, Copy)]
364enum Key {
365    Noop,
366    Direct(u16),
367    HalfKey(HalfInvertedKey),
368    FullKey(HalfInvertedKey, HalfInvertedKey),
369}
370
371impl KeyMapper for Key {
372    fn send_event(&self, key_state: &[bool], event: &mut input_event, device: &Device) {
373        match *self {
374            Key::Noop => {
375                device.write_event(event).expect("could not write event?");
376            },
377            Key::Direct(code) => {
378                code.send_event(key_state, event, device);
379            },
380            Key::HalfKey(ref key_half) => {
381                key_half.send_event(key_state, event, device);
382            },
383            Key::FullKey(ref noshift_half, ref shift_half) => {
384                let left_shift = key_state[LEFTSHIFT_INDEX];
385                let right_shift = key_state[RIGHTSHIFT_INDEX];
386                let caps_lock = key_state[CAPSLOCK_INDEX];
387                if caps_lock != (left_shift || right_shift) {
388                    shift_half.send_key(key_state, event, device, left_shift, right_shift, caps_lock);
389                } else {
390                    noshift_half.send_key(key_state, event, device, left_shift, right_shift, caps_lock);
391                }
392            },
393        }
394    }
395}
396
397extern crate toml;
398
399use std::path::Path;
400
401#[derive(Deserialize, Debug)]
402pub struct KeymapConfig {
403    switch_layout_keys: Vec<String>,
404    revert_default_key: String,
405    revert_keymap_index: usize,
406    default_keymap_index: usize,
407    keymaps: Vec<String>
408}
409
410/*
411‎c`p‎: no, ? converts the error with From<> in its expansion
412‎c`p‎: so unless io::Error: From<toml::Error> it isnt going to work
413c`p‎: the idea with your own error type is that MyError: From<io::Error> + From<toml::Error> + etc etc
414‎c`p‎: ie enum MyError { Io(io::Error), Toml(toml::Error), ... }
415c`p‎: error-chain does all this stuff for you
416*/
417
418use std::io::{Error, ErrorKind};
419
420fn parse_cfg<P: AsRef<Path>>(path: P) -> Result<KeymapConfig, Error> {
421    let mut f = File::open(path)?;
422    let mut input = String::new();
423    f.read_to_string(&mut input)?;
424    //toml::from_str(&input)?
425    match toml::from_str(&input) {
426        Ok(toml) => Ok(toml),
427        Err(_) => Err(Error::new(ErrorKind::Other, "oh no!"))
428    }
429}
430
431impl KeyMaps {
432    pub fn key_map() -> HashMap<&'static str, *const c_int> {
433        [
434            // generated like:
435            // grep -o 'KEY_[^ :;]*' ~/.cargo/registry/src/github.com-1ecc6299db9ec823/uinput-sys-0.1.3/src/events.rs | sed 's/^KEY_//' | awk '{print "(\""$1"\", KEY_"$1"),"}'
436            ("RESERVED", KEY_RESERVED),
437            ("ESC", KEY_ESC),
438            ("1", KEY_1),
439            ("2", KEY_2),
440            ("3", KEY_3),
441            ("4", KEY_4),
442            ("5", KEY_5),
443            ("6", KEY_6),
444            ("7", KEY_7),
445            ("8", KEY_8),
446            ("9", KEY_9),
447            ("10", KEY_10),
448            ("MINUS", KEY_MINUS),
449            ("EQUAL", KEY_EQUAL),
450            ("BACKSPACE", KEY_BACKSPACE),
451            ("TAB", KEY_TAB),
452            ("Q", KEY_Q),
453            ("W", KEY_W),
454            ("E", KEY_E),
455            ("R", KEY_R),
456            ("T", KEY_T),
457            ("Y", KEY_Y),
458            ("U", KEY_U),
459            ("I", KEY_I),
460            ("O", KEY_O),
461            ("P", KEY_P),
462            ("LEFTBRACE", KEY_LEFTBRACE),
463            ("RIGHTBRACE", KEY_RIGHTBRACE),
464            ("ENTER", KEY_ENTER),
465            ("LEFTCTRL", KEY_LEFTCTRL),
466            ("A", KEY_A),
467            ("S", KEY_S),
468            ("D", KEY_D),
469            ("F", KEY_F),
470            ("G", KEY_G),
471            ("H", KEY_H),
472            ("J", KEY_J),
473            ("K", KEY_K),
474            ("L", KEY_L),
475            ("SEMICOLON", KEY_SEMICOLON),
476            ("APOSTROPHE", KEY_APOSTROPHE),
477            ("GRAVE", KEY_GRAVE),
478            ("LEFTSHIFT", KEY_LEFTSHIFT),
479            ("BACKSLASH", KEY_BACKSLASH),
480            ("Z", KEY_Z),
481            ("X", KEY_X),
482            ("C", KEY_C),
483            ("V", KEY_V),
484            ("B", KEY_B),
485            ("N", KEY_N),
486            ("M", KEY_M),
487            ("COMMA", KEY_COMMA),
488            ("DOT", KEY_DOT),
489            ("SLASH", KEY_SLASH),
490            ("RIGHTSHIFT", KEY_RIGHTSHIFT),
491            ("KPASTERISK", KEY_KPASTERISK),
492            ("LEFTALT", KEY_LEFTALT),
493            ("SPACE", KEY_SPACE),
494            ("CAPSLOCK", KEY_CAPSLOCK),
495            ("F1", KEY_F1),
496            ("F2", KEY_F2),
497            ("F3", KEY_F3),
498            ("F4", KEY_F4),
499            ("F5", KEY_F5),
500            ("F6", KEY_F6),
501            ("F7", KEY_F7),
502            ("F8", KEY_F8),
503            ("F9", KEY_F9),
504            ("F10", KEY_F10),
505            ("NUMLOCK", KEY_NUMLOCK),
506            ("SCROLLLOCK", KEY_SCROLLLOCK),
507            ("KP7", KEY_KP7),
508            ("KP8", KEY_KP8),
509            ("KP9", KEY_KP9),
510            ("KPMINUS", KEY_KPMINUS),
511            ("KP4", KEY_KP4),
512            ("KP5", KEY_KP5),
513            ("KP6", KEY_KP6),
514            ("KPPLUS", KEY_KPPLUS),
515            ("KP1", KEY_KP1),
516            ("KP2", KEY_KP2),
517            ("KP3", KEY_KP3),
518            ("KP0", KEY_KP0),
519            ("KPDOT", KEY_KPDOT),
520            ("ZENKAKUHANKAKU", KEY_ZENKAKUHANKAKU),
521            ("102ND", KEY_102ND),
522            ("F11", KEY_F11),
523            ("F12", KEY_F12),
524            ("RO", KEY_RO),
525            ("KATAKANA", KEY_KATAKANA),
526            ("HIRAGANA", KEY_HIRAGANA),
527            ("HENKAN", KEY_HENKAN),
528            ("KATAKANAHIRAGANA", KEY_KATAKANAHIRAGANA),
529            ("MUHENKAN", KEY_MUHENKAN),
530            ("KPJPCOMMA", KEY_KPJPCOMMA),
531            ("KPENTER", KEY_KPENTER),
532            ("RIGHTCTRL", KEY_RIGHTCTRL),
533            ("KPSLASH", KEY_KPSLASH),
534            ("SYSRQ", KEY_SYSRQ),
535            ("RIGHTALT", KEY_RIGHTALT),
536            ("LINEFEED", KEY_LINEFEED),
537            ("HOME", KEY_HOME),
538            ("UP", KEY_UP),
539            ("PAGEUP", KEY_PAGEUP),
540            ("LEFT", KEY_LEFT),
541            ("RIGHT", KEY_RIGHT),
542            ("END", KEY_END),
543            ("DOWN", KEY_DOWN),
544            ("PAGEDOWN", KEY_PAGEDOWN),
545            ("INSERT", KEY_INSERT),
546            ("DELETE", KEY_DELETE),
547            ("MACRO", KEY_MACRO),
548            ("MUTE", KEY_MUTE),
549            ("VOLUMEDOWN", KEY_VOLUMEDOWN),
550            ("VOLUMEUP", KEY_VOLUMEUP),
551            ("POWER", KEY_POWER),
552            ("KPEQUAL", KEY_KPEQUAL),
553            ("KPPLUSMINUS", KEY_KPPLUSMINUS),
554            ("PAUSE", KEY_PAUSE),
555            ("SCALE", KEY_SCALE),
556            ("KPCOMMA", KEY_KPCOMMA),
557            ("HANGEUL", KEY_HANGEUL),
558            ("HANGUEL", KEY_HANGUEL),
559            ("HANGEUL", KEY_HANGEUL),
560            ("HANJA", KEY_HANJA),
561            ("YEN", KEY_YEN),
562            ("LEFTMETA", KEY_LEFTMETA),
563            ("RIGHTMETA", KEY_RIGHTMETA),
564            ("COMPOSE", KEY_COMPOSE),
565            ("STOP", KEY_STOP),
566            ("AGAIN", KEY_AGAIN),
567            ("PROPS", KEY_PROPS),
568            ("UNDO", KEY_UNDO),
569            ("FRONT", KEY_FRONT),
570            ("COPY", KEY_COPY),
571            ("OPEN", KEY_OPEN),
572            ("PASTE", KEY_PASTE),
573            ("FIND", KEY_FIND),
574            ("CUT", KEY_CUT),
575            ("HELP", KEY_HELP),
576            ("MENU", KEY_MENU),
577            ("CALC", KEY_CALC),
578            ("SETUP", KEY_SETUP),
579            ("SLEEP", KEY_SLEEP),
580            ("WAKEUP", KEY_WAKEUP),
581            ("FILE", KEY_FILE),
582            ("SENDFILE", KEY_SENDFILE),
583            ("DELETEFILE", KEY_DELETEFILE),
584            ("XFER", KEY_XFER),
585            ("PROG1", KEY_PROG1),
586            ("PROG2", KEY_PROG2),
587            ("WWW", KEY_WWW),
588            ("MSDOS", KEY_MSDOS),
589            ("COFFEE", KEY_COFFEE),
590            ("SCREENLOCK", KEY_SCREENLOCK),
591            ("COFFEE", KEY_COFFEE),
592            ("ROTATE_DISPLAY", KEY_ROTATE_DISPLAY),
593            ("DIRECTION", KEY_DIRECTION),
594            ("ROTATE_DISPLAY", KEY_ROTATE_DISPLAY),
595            ("CYCLEWINDOWS", KEY_CYCLEWINDOWS),
596            ("MAIL", KEY_MAIL),
597            ("BOOKMARKS", KEY_BOOKMARKS),
598            ("COMPUTER", KEY_COMPUTER),
599            ("BACK", KEY_BACK),
600            ("FORWARD", KEY_FORWARD),
601            ("CLOSECD", KEY_CLOSECD),
602            ("EJECTCD", KEY_EJECTCD),
603            ("EJECTCLOSECD", KEY_EJECTCLOSECD),
604            ("NEXTSONG", KEY_NEXTSONG),
605            ("PLAYPAUSE", KEY_PLAYPAUSE),
606            ("PREVIOUSSONG", KEY_PREVIOUSSONG),
607            ("STOPCD", KEY_STOPCD),
608            ("RECORD", KEY_RECORD),
609            ("REWIND", KEY_REWIND),
610            ("PHONE", KEY_PHONE),
611            ("ISO", KEY_ISO),
612            ("CONFIG", KEY_CONFIG),
613            ("HOMEPAGE", KEY_HOMEPAGE),
614            ("REFRESH", KEY_REFRESH),
615            ("EXIT", KEY_EXIT),
616            ("MOVE", KEY_MOVE),
617            ("EDIT", KEY_EDIT),
618            ("SCROLLUP", KEY_SCROLLUP),
619            ("SCROLLDOWN", KEY_SCROLLDOWN),
620            ("KPLEFTPAREN", KEY_KPLEFTPAREN),
621            ("KPRIGHTPAREN", KEY_KPRIGHTPAREN),
622            ("NEW", KEY_NEW),
623            ("REDO", KEY_REDO),
624            ("F13", KEY_F13),
625            ("F14", KEY_F14),
626            ("F15", KEY_F15),
627            ("F16", KEY_F16),
628            ("F17", KEY_F17),
629            ("F18", KEY_F18),
630            ("F19", KEY_F19),
631            ("F20", KEY_F20),
632            ("F21", KEY_F21),
633            ("F22", KEY_F22),
634            ("F23", KEY_F23),
635            ("F24", KEY_F24),
636            ("PLAYCD", KEY_PLAYCD),
637            ("PAUSECD", KEY_PAUSECD),
638            ("PROG3", KEY_PROG3),
639            ("PROG4", KEY_PROG4),
640            ("DASHBOARD", KEY_DASHBOARD),
641            ("SUSPEND", KEY_SUSPEND),
642            ("CLOSE", KEY_CLOSE),
643            ("PLAY", KEY_PLAY),
644            ("FASTFORWARD", KEY_FASTFORWARD),
645            ("BASSBOOST", KEY_BASSBOOST),
646            ("PRINT", KEY_PRINT),
647            ("HP", KEY_HP),
648            ("CAMERA", KEY_CAMERA),
649            ("SOUND", KEY_SOUND),
650            ("QUESTION", KEY_QUESTION),
651            ("EMAIL", KEY_EMAIL),
652            ("CHAT", KEY_CHAT),
653            ("SEARCH", KEY_SEARCH),
654            ("CONNECT", KEY_CONNECT),
655            ("FINANCE", KEY_FINANCE),
656            ("SPORT", KEY_SPORT),
657            ("SHOP", KEY_SHOP),
658            ("ALTERASE", KEY_ALTERASE),
659            ("CANCEL", KEY_CANCEL),
660            ("BRIGHTNESSDOWN", KEY_BRIGHTNESSDOWN),
661            ("BRIGHTNESSUP", KEY_BRIGHTNESSUP),
662            ("MEDIA", KEY_MEDIA),
663            ("SWITCHVIDEOMODE", KEY_SWITCHVIDEOMODE),
664            ("KBDILLUMTOGGLE", KEY_KBDILLUMTOGGLE),
665            ("KBDILLUMDOWN", KEY_KBDILLUMDOWN),
666            ("KBDILLUMUP", KEY_KBDILLUMUP),
667            ("SEND", KEY_SEND),
668            ("REPLY", KEY_REPLY),
669            ("FORWARDMAIL", KEY_FORWARDMAIL),
670            ("SAVE", KEY_SAVE),
671            ("DOCUMENTS", KEY_DOCUMENTS),
672            ("BATTERY", KEY_BATTERY),
673            ("BLUETOOTH", KEY_BLUETOOTH),
674            ("WLAN", KEY_WLAN),
675            ("UWB", KEY_UWB),
676            ("UNKNOWN", KEY_UNKNOWN),
677            ("VIDEO_NEXT", KEY_VIDEO_NEXT),
678            ("VIDEO_PREV", KEY_VIDEO_PREV),
679            ("BRIGHTNESS_CYCLE", KEY_BRIGHTNESS_CYCLE),
680            ("BRIGHTNESS_AUTO", KEY_BRIGHTNESS_AUTO),
681            ("BRIGHTNESS_ZERO", KEY_BRIGHTNESS_ZERO),
682            ("BRIGHTNESS_AUTO", KEY_BRIGHTNESS_AUTO),
683            ("DISPLAY_OFF", KEY_DISPLAY_OFF),
684            ("WWAN", KEY_WWAN),
685            ("WIMAX", KEY_WIMAX),
686            ("WWAN", KEY_WWAN),
687            ("RFKILL", KEY_RFKILL),
688            ("MICMUTE", KEY_MICMUTE),
689            // below manual shortcuts
690            ("PSCR", KEY_SYSRQ),
691            ("SLCK", KEY_SCROLLLOCK),
692            ("BRK", KEY_PAUSE),
693            ("GRV", KEY_GRAVE),
694            ("0", KEY_10), // dumb or named wrong?
695            ("MINS", KEY_MINUS),
696            ("EQL", KEY_EQUAL),
697            ("BSPC", KEY_BACKSPACE),
698            ("LBRC", KEY_LEFTBRACE),
699            ("RBRC", KEY_RIGHTBRACE),
700            ("BSLS", KEY_BACKSLASH),
701            ("SCLN", KEY_SEMICOLON),
702            ("QUOT", KEY_APOSTROPHE),
703            ("ENT", KEY_ENTER),
704            ("COMM", KEY_COMMA),
705            ("DOT", KEY_DOT),
706            ("SLSH", KEY_SLASH),
707            ("CAPS", KEY_CAPSLOCK),
708            ("LSFT", KEY_LEFTSHIFT),
709            ("RSFT", KEY_RIGHTSHIFT),
710            ("SPC", KEY_SPACE),
711            ("APP", KEY_COMPOSE),
712            ("LCTL", KEY_LEFTCTRL),
713            ("RCTL", KEY_RIGHTCTRL),
714            ("LALT", KEY_LEFTALT),
715            ("RALT", KEY_RIGHTALT),
716            ("LGUI", KEY_LEFTMETA),
717            ("RGUI", KEY_RIGHTMETA),
718            ("INS", KEY_INSERT),
719            ("PGUP", KEY_PAGEUP),
720            ("PGDN", KEY_PAGEDOWN),
721            ("DEL", KEY_DELETE),
722            ("RGHT", KEY_RIGHT),
723            ("NLCK", KEY_NUMLOCK),
724            ("PSLS", KEY_KPSLASH),
725            ("PAST", KEY_KPASTERISK),
726            ("PMNS", KEY_KPMINUS),
727            ("P7", KEY_KP7),
728            ("P8", KEY_KP8),
729            ("P9", KEY_KP9),
730            ("P4", KEY_KP4),
731            ("P5", KEY_KP5),
732            ("P6", KEY_KP6),
733            ("PPLS", KEY_KPPLUS),
734            ("P1", KEY_KP1),
735            ("P2", KEY_KP2),
736            ("P3", KEY_KP3),
737            ("P0", KEY_KP0),
738            ("PDOT", KEY_KPDOT),
739            ("PENT", KEY_KPENTER),
740        ].iter().cloned().map(|(m, v)| (m, v as *const c_int)).collect()
741    }
742}