diff options
author | Joe Wilm <joe@jwilm.com> | 2016-07-30 12:47:22 -0700 |
---|---|---|
committer | Joe Wilm <joe@jwilm.com> | 2016-07-30 12:52:53 -0700 |
commit | 66e7228f41a9fef79fec2cf57d8e9ac92e936855 (patch) | |
tree | 498421f6bc1ebeb06d39c8b901d45ff4c90a1b6b | |
parent | c687eca3fadef5d64daf5fce5582e0037c45d5b4 (diff) | |
download | alacritty-66e7228f41a9fef79fec2cf57d8e9ac92e936855.tar.gz alacritty-66e7228f41a9fef79fec2cf57d8e9ac92e936855.zip |
Input expects modifier keys from Glutin
This is experimental on a separate branch of Glutin. It's intended to
fix the problem of certain key events not being delivered on alt-tab and
breaking the modifier state tracking.
-rw-r--r-- | Cargo.lock | 5 | ||||
-rw-r--r-- | Cargo.toml | 7 | ||||
-rw-r--r-- | src/input.rs | 202 | ||||
-rw-r--r-- | src/main.rs | 3 |
4 files changed, 71 insertions, 146 deletions
@@ -7,7 +7,7 @@ dependencies = [ "errno 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "font 0.1.0", "gl_generator 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "glutin 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "glutin 0.6.1 (git+https://github.com/jwilm/glutin?rev=d287fa96e3a8b2568b189067eedd28807c4568d6)", "libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "notify 2.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -285,9 +285,10 @@ dependencies = [ [[package]] name = "glutin" version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/jwilm/glutin?rev=d287fa96e3a8b2568b189067eedd28807c4568d6#d287fa96e3a8b2568b189067eedd28807c4568d6" dependencies = [ "android_glue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "cgl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "cocoa 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -22,8 +22,5 @@ serde_macros = "0.7" gl_generator = "0.5" [dependencies.glutin] -version = "*" -# git = "https://github.com/jwilm/glutin" -# rev = "c95e6973ace3cbf321123a64588b27f032675be9" -# version = "*" -# path = "../glutin" +git = "https://github.com/jwilm/glutin" +rev = "d287fa96e3a8b2568b189067eedd28807c4568d6" diff --git a/src/input.rs b/src/input.rs index 3dba1a64..d859abd1 100644 --- a/src/input.rs +++ b/src/input.rs @@ -26,72 +26,10 @@ use std::io::Write; use glutin::{ElementState, VirtualKeyCode}; +use glutin::{Mods, mods}; use term::mode::{self, TermMode}; -/// Modifier keys -/// -/// Contains a bitflags for modifier keys which are now namespaced thanks to -/// this module wrapper. -mod modifier { - use glutin::ElementState; - - bitflags! { - /// Flags indicating active modifier keys - pub flags Keys: u8 { - /// Left shift - const SHIFT_LEFT = 0b00000001, - /// Right shift - const SHIFT_RIGHT = 0b00000010, - /// Left meta - const META_LEFT = 0b00000100, - /// Right meta - const META_RIGHT = 0b00001000, - /// Left control - const CONTROL_LEFT = 0b00010000, - /// Right control - const CONTROL_RIGHT = 0b00100000, - /// Left alt - const ALT_LEFT = 0b01000000, - /// Right alt - const ALT_RIGHT = 0b10000000, - /// Any shift key - const SHIFT = SHIFT_LEFT.bits - | SHIFT_RIGHT.bits, - /// Any control key - const CONTROL = CONTROL_LEFT.bits - | CONTROL_RIGHT.bits, - /// Any alt key - const ALT = ALT_LEFT.bits - | ALT_RIGHT.bits, - /// Any meta key - const META = META_LEFT.bits - | META_RIGHT.bits, - /// Any mod - const ANY = 0b11111111, - /// No mod - const NONE = 0b00000000, - } - } - - impl Default for Keys { - fn default() -> Keys { - Keys::empty() - } - } - - impl Keys { - /// Take appropriate action given a modifier key and its state - #[inline] - pub fn update(&mut self, state: ElementState, key: Keys) { - match state { - ElementState::Pressed => self.insert(key), - ElementState::Released => self.remove(key), - } - } - } -} - /// Processes input from glutin. /// /// An escape sequence may be emitted in case specific keys or key combinations @@ -99,10 +37,7 @@ mod modifier { /// /// TODO also need terminal state when processing input #[derive(Default)] -pub struct Processor { - /// Active modifier keys - mods: modifier::Keys, -} +pub struct Processor; /// Types that are notified of escape sequences from the input::Processor. pub trait Notify { @@ -125,7 +60,7 @@ impl<'a, W: Write> Notify for WriteNotifier<'a, W> { #[derive(Debug)] pub struct Binding { /// Modifier keys required to activate binding - mods: modifier::Keys, + mods: Mods, /// String to send to pty if mods and mode match send: &'static str, /// Terminal mode required to activate binding @@ -136,98 +71,98 @@ pub struct Binding { /// Bindings for the LEFT key. static LEFT_BINDINGS: &'static [Binding] = &[ - Binding { mods: modifier::SHIFT, send: "\x1b[1;2D", mode: mode::ANY, notmode: mode::NONE }, - Binding { mods: modifier::CONTROL, send: "\x1b[1;5D", mode: mode::ANY, notmode: mode::NONE }, - Binding { mods: modifier::ALT, send: "\x1b[1;3D", mode: mode::ANY, notmode: mode::NONE }, - Binding { mods: modifier::ANY, send: "\x1b[D", mode: mode::ANY, notmode: mode::APP_CURSOR }, - Binding { mods: modifier::ANY, send: "\x1bOD", mode: mode::APP_CURSOR, notmode: mode::NONE }, + Binding { mods: mods::SHIFT, send: "\x1b[1;2D", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::CONTROL, send: "\x1b[1;5D", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::ALT, send: "\x1b[1;3D", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::ANY, send: "\x1b[D", mode: mode::ANY, notmode: mode::APP_CURSOR }, + Binding { mods: mods::ANY, send: "\x1bOD", mode: mode::APP_CURSOR, notmode: mode::NONE }, ]; /// Bindings for the RIGHT key static RIGHT_BINDINGS: &'static [Binding] = &[ - Binding { mods: modifier::SHIFT, send: "\x1b[1;2C", mode: mode::ANY, notmode: mode::NONE }, - Binding { mods: modifier::CONTROL, send: "\x1b[1;5C", mode: mode::ANY, notmode: mode::NONE }, - Binding { mods: modifier::ALT, send: "\x1b[1;3C", mode: mode::ANY, notmode: mode::NONE }, - Binding { mods: modifier::ANY, send: "\x1b[C", mode: mode::ANY, notmode: mode::APP_CURSOR }, - Binding { mods: modifier::ANY, send: "\x1bOC", mode: mode::APP_CURSOR, notmode: mode::NONE }, + Binding { mods: mods::SHIFT, send: "\x1b[1;2C", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::CONTROL, send: "\x1b[1;5C", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::ALT, send: "\x1b[1;3C", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::ANY, send: "\x1b[C", mode: mode::ANY, notmode: mode::APP_CURSOR }, + Binding { mods: mods::ANY, send: "\x1bOC", mode: mode::APP_CURSOR, notmode: mode::NONE }, ]; /// Bindings for the UP key static UP_BINDINGS: &'static [Binding] = &[ - Binding { mods: modifier::SHIFT, send: "\x1b[1;2A", mode: mode::ANY, notmode: mode::NONE }, - Binding { mods: modifier::CONTROL, send: "\x1b[1;5A", mode: mode::ANY, notmode: mode::NONE }, - Binding { mods: modifier::ALT, send: "\x1b[1;3A", mode: mode::ANY, notmode: mode::NONE }, - Binding { mods: modifier::ANY, send: "\x1b[A", mode: mode::ANY, notmode: mode::APP_CURSOR }, - Binding { mods: modifier::ANY, send: "\x1bOA", mode: mode::APP_CURSOR, notmode: mode::NONE }, + Binding { mods: mods::SHIFT, send: "\x1b[1;2A", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::CONTROL, send: "\x1b[1;5A", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::ALT, send: "\x1b[1;3A", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::ANY, send: "\x1b[A", mode: mode::ANY, notmode: mode::APP_CURSOR }, + Binding { mods: mods::ANY, send: "\x1bOA", mode: mode::APP_CURSOR, notmode: mode::NONE }, ]; /// Bindings for the DOWN key static DOWN_BINDINGS: &'static [Binding] = &[ - Binding { mods: modifier::SHIFT, send: "\x1b[1;2B", mode: mode::ANY, notmode: mode::NONE }, - Binding { mods: modifier::CONTROL, send: "\x1b[1;5B", mode: mode::ANY, notmode: mode::NONE }, - Binding { mods: modifier::ALT, send: "\x1b[1;3B", mode: mode::ANY, notmode: mode::NONE }, - Binding { mods: modifier::ANY, send: "\x1b[B", mode: mode::ANY, notmode: mode::APP_CURSOR }, - Binding { mods: modifier::ANY, send: "\x1bOB", mode: mode::APP_CURSOR, notmode: mode::NONE }, + Binding { mods: mods::SHIFT, send: "\x1b[1;2B", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::CONTROL, send: "\x1b[1;5B", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::ALT, send: "\x1b[1;3B", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::ANY, send: "\x1b[B", mode: mode::ANY, notmode: mode::APP_CURSOR }, + Binding { mods: mods::ANY, send: "\x1bOB", mode: mode::APP_CURSOR, notmode: mode::NONE }, ]; /// Bindings for the F1 key static F1_BINDINGS: &'static [Binding] = &[ - Binding { mods: modifier::ANY, send: "\x1bOP", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::ANY, send: "\x1bOP", mode: mode::ANY, notmode: mode::NONE }, ]; /// Bindings for the F2 key static F2_BINDINGS: &'static [Binding] = &[ - Binding { mods: modifier::ANY, send: "\x1bOQ", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::ANY, send: "\x1bOQ", mode: mode::ANY, notmode: mode::NONE }, ]; /// Bindings for the F3 key static F3_BINDINGS: &'static [Binding] = &[ - Binding { mods: modifier::ANY, send: "\x1bOR", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::ANY, send: "\x1bOR", mode: mode::ANY, notmode: mode::NONE }, ]; /// Bindings for the F4 key static F4_BINDINGS: &'static [Binding] = &[ - Binding { mods: modifier::ANY, send: "\x1bOS", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::ANY, send: "\x1bOS", mode: mode::ANY, notmode: mode::NONE }, ]; /// Bindings for the F5 key static F5_BINDINGS: &'static [Binding] = &[ - Binding { mods: modifier::ANY, send: "\x1b[15~", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::ANY, send: "\x1b[15~", mode: mode::ANY, notmode: mode::NONE }, ]; /// Bindings for the F6 key static F6_BINDINGS: &'static [Binding] = &[ - Binding { mods: modifier::ANY, send: "\x1b[17~", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::ANY, send: "\x1b[17~", mode: mode::ANY, notmode: mode::NONE }, ]; /// Bindings for the F7 key static F7_BINDINGS: &'static [Binding] = &[ - Binding { mods: modifier::ANY, send: "\x1b[18~", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::ANY, send: "\x1b[18~", mode: mode::ANY, notmode: mode::NONE }, ]; /// Bindings for the F8 key static F8_BINDINGS: &'static [Binding] = &[ - Binding { mods: modifier::ANY, send: "\x1b[19~", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::ANY, send: "\x1b[19~", mode: mode::ANY, notmode: mode::NONE }, ]; /// Bindings for the F9 key static F9_BINDINGS: &'static [Binding] = &[ - Binding { mods: modifier::ANY, send: "\x1b[20~", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::ANY, send: "\x1b[20~", mode: mode::ANY, notmode: mode::NONE }, ]; /// Bindings for the F10 key static F10_BINDINGS: &'static [Binding] = &[ - Binding { mods: modifier::ANY, send: "\x1b[21~", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::ANY, send: "\x1b[21~", mode: mode::ANY, notmode: mode::NONE }, ]; /// Bindings for the F11 key static F11_BINDINGS: &'static [Binding] = &[ - Binding { mods: modifier::ANY, send: "\x1b[23~", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::ANY, send: "\x1b[23~", mode: mode::ANY, notmode: mode::NONE }, ]; /// Bindings for the F11 key static F12_BINDINGS: &'static [Binding] = &[ - Binding { mods: modifier::ANY, send: "\x1b[24~", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::ANY, send: "\x1b[24~", mode: mode::ANY, notmode: mode::NONE }, ]; /// Bindings for the H key @@ -236,18 +171,18 @@ static F12_BINDINGS: &'static [Binding] = &[ /// since DEL and BACKSPACE are inverted. This binding is a work around to that /// capture. static H_BINDINGS: &'static [Binding] = &[ - Binding { mods: modifier::CONTROL, send: "\x08", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::CONTROL, send: "\x08", mode: mode::ANY, notmode: mode::NONE }, ]; /// Bindings for the Backspace key static BACKSPACE_BINDINGS: &'static [Binding] = &[ - Binding { mods: modifier::ANY, send: "\x7f", mode: mode::ANY, notmode: mode::NONE }, + Binding { mods: mods::ANY, send: "\x7f", mode: mode::ANY, notmode: mode::NONE }, ]; /// Bindings for the Delete key static DELETE_BINDINGS: &'static [Binding] = &[ - Binding { mods: modifier::ANY, send: "\x1b[3~", mode: mode::APP_KEYPAD, notmode: mode::NONE }, - Binding { mods: modifier::ANY, send: "\x1b[P", mode: mode::ANY, notmode: mode::APP_KEYPAD }, + Binding { mods: mods::ANY, send: "\x1b[3~", mode: mode::APP_KEYPAD, notmode: mode::NONE }, + Binding { mods: mods::ANY, send: "\x1b[P", mode: mode::ANY, notmode: mode::APP_KEYPAD }, ]; // key mods escape appkey appcursor crlf @@ -264,25 +199,12 @@ impl Processor { pub fn process<N>(&mut self, state: ElementState, key: Option<VirtualKeyCode>, + mods: Mods, notifier: &mut N, mode: TermMode) where N: Notify { if let Some(key) = key { - - // Handle state updates - match key { - VirtualKeyCode::LAlt => return self.mods.update(state, modifier::ALT_LEFT), - VirtualKeyCode::RAlt => return self.mods.update(state, modifier::ALT_RIGHT), - VirtualKeyCode::LShift => return self.mods.update(state, modifier::SHIFT_LEFT), - VirtualKeyCode::RShift => return self.mods.update(state, modifier::SHIFT_RIGHT), - VirtualKeyCode::LControl => return self.mods.update(state, modifier::CONTROL_LEFT), - VirtualKeyCode::RControl => return self.mods.update(state, modifier::CONTROL_RIGHT), - VirtualKeyCode::LWin => return self.mods.update(state, modifier::META_LEFT), - VirtualKeyCode::RWin => return self.mods.update(state, modifier::META_RIGHT), - _ => () - } - // Ignore release events if state == ElementState::Released { return; @@ -330,16 +252,20 @@ impl Processor { // Log something by default _ => { println!("Unhandled key: {:?}; state: {:?}; mods: {:?}", - key, state, self.mods); + key, state, mods); return; }, }; - self.process_bindings(bindings, mode, notifier); + self.process_bindings(bindings, mode, notifier, mods); } } - fn process_bindings<N>(&self, bindings: &[Binding], mode: TermMode, notifier: &mut N) + fn process_bindings<N>(&self, + bindings: &[Binding], + mode: TermMode, + notifier: &mut N, + mods: Mods) where N: Notify { // Check each binding @@ -349,7 +275,7 @@ impl Processor { // TermMode negative if binding.notmode.is_empty() || !mode.intersects(binding.notmode) { // Modifier keys - if binding.mods.is_all() || self.mods.intersects(binding.mods) { + if binding.mods.is_all() || mods.intersects(binding.mods) { // everything matches notifier.notify(binding.send); break; @@ -363,6 +289,7 @@ impl Processor { #[cfg(test)] mod tests { use term::mode::{self, TermMode}; + use glutin::mods; use super::Processor; use super::modifier; @@ -393,10 +320,9 @@ mod tests { let bindings = &[$binding]; let mut processor = Processor::new(); - processor.mods.insert($mods); let mut receiver = Receiver::default(); - processor.process_bindings(bindings, $mode, &mut receiver); + processor.process_bindings(bindings, $mode, &mut receiver, $mods); assert_eq!(receiver.got, $expect); } } @@ -404,57 +330,57 @@ mod tests { test_process_binding! { name: process_binding_nomode_shiftmod_require_shift, - binding: Binding { mods: modifier::SHIFT, send: "\x1b[1;2D", mode: mode::ANY, notmode: mode::NONE }, + binding: Binding { mods: mods::SHIFT, send: "\x1b[1;2D", mode: mode::ANY, notmode: mode::NONE }, expect: Some(String::from("\x1b[1;2D")), mode: mode::NONE, - mods: modifier::SHIFT + mods: mods::SHIFT } test_process_binding! { name: process_binding_nomode_nomod_require_shift, - binding: Binding { mods: modifier::SHIFT, send: "\x1b[1;2D", mode: mode::ANY, notmode: mode::NONE }, + binding: Binding { mods: mods::SHIFT, send: "\x1b[1;2D", mode: mode::ANY, notmode: mode::NONE }, expect: None, mode: mode::NONE, - mods: modifier::NONE + mods: mods::NONE } test_process_binding! { name: process_binding_nomode_controlmod, - binding: Binding { mods: modifier::CONTROL, send: "\x1b[1;5D", mode: mode::ANY, notmode: mode::NONE }, + binding: Binding { mods: mods::CONTROL, send: "\x1b[1;5D", mode: mode::ANY, notmode: mode::NONE }, expect: Some(String::from("\x1b[1;5D")), mode: mode::NONE, - mods: modifier::CONTROL + mods: mods::CONTROL } test_process_binding! { name: process_binding_nomode_nomod_require_not_appcursor, - binding: Binding { mods: modifier::ANY, send: "\x1b[D", mode: mode::ANY, notmode: mode::APP_CURSOR }, + binding: Binding { mods: mods::ANY, send: "\x1b[D", mode: mode::ANY, notmode: mode::APP_CURSOR }, expect: Some(String::from("\x1b[D")), mode: mode::NONE, - mods: modifier::NONE + mods: mods::NONE } test_process_binding! { name: process_binding_appcursormode_nomod_require_appcursor, - binding: Binding { mods: modifier::ANY, send: "\x1bOD", mode: mode::APP_CURSOR, notmode: mode::NONE }, + binding: Binding { mods: mods::ANY, send: "\x1bOD", mode: mode::APP_CURSOR, notmode: mode::NONE }, expect: Some(String::from("\x1bOD")), mode: mode::APP_CURSOR, - mods: modifier::NONE + mods: mods::NONE } test_process_binding! { name: process_binding_nomode_nomod_require_appcursor, - binding: Binding { mods: modifier::ANY, send: "\x1bOD", mode: mode::APP_CURSOR, notmode: mode::NONE }, + binding: Binding { mods: mods::ANY, send: "\x1bOD", mode: mode::APP_CURSOR, notmode: mode::NONE }, expect: None, mode: mode::NONE, - mods: modifier::NONE + mods: mods::NONE } test_process_binding! { name: process_binding_appcursormode_appkeypadmode_nomod_require_appcursor, - binding: Binding { mods: modifier::ANY, send: "\x1bOD", mode: mode::APP_CURSOR, notmode: mode::NONE }, + binding: Binding { mods: mods::ANY, send: "\x1bOD", mode: mode::APP_CURSOR, notmode: mode::NONE }, expect: Some(String::from("\x1bOD")), mode: mode::APP_CURSOR | mode::APP_KEYPAD, - mods: modifier::NONE + mods: mods::NONE } } diff --git a/src/main.rs b/src/main.rs index e24ed9f8..2f07ab76 100644 --- a/src/main.rs +++ b/src/main.rs @@ -242,9 +242,10 @@ fn main() { glutin::Event::Resized(w, h) => { new_size = Some((w, h)); }, - glutin::Event::KeyboardInput(state, _code, key) => { + glutin::Event::KeyboardInput(state, _code, key, mods) => { input_processor.process(state, key, + mods, &mut input::WriteNotifier(&mut writer), *terminal.mode()) }, |