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.
This commit is contained in:
parent
c687eca3fa
commit
66e7228f41
|
@ -7,7 +7,7 @@ dependencies = [
|
||||||
"errno 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"errno 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"font 0.1.0",
|
"font 0.1.0",
|
||||||
"gl_generator 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"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)",
|
"parking_lot 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -285,9 +285,10 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glutin"
|
name = "glutin"
|
||||||
version = "0.6.1"
|
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 = [
|
dependencies = [
|
||||||
"android_glue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"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)",
|
"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"
|
gl_generator = "0.5"
|
||||||
|
|
||||||
[dependencies.glutin]
|
[dependencies.glutin]
|
||||||
version = "*"
|
git = "https://github.com/jwilm/glutin"
|
||||||
# git = "https://github.com/jwilm/glutin"
|
rev = "d287fa96e3a8b2568b189067eedd28807c4568d6"
|
||||||
# rev = "c95e6973ace3cbf321123a64588b27f032675be9"
|
|
||||||
# version = "*"
|
|
||||||
# path = "../glutin"
|
|
||||||
|
|
202
src/input.rs
202
src/input.rs
|
@ -26,72 +26,10 @@
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
use glutin::{ElementState, VirtualKeyCode};
|
use glutin::{ElementState, VirtualKeyCode};
|
||||||
|
use glutin::{Mods, mods};
|
||||||
|
|
||||||
use term::mode::{self, TermMode};
|
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.
|
/// Processes input from glutin.
|
||||||
///
|
///
|
||||||
/// An escape sequence may be emitted in case specific keys or key combinations
|
/// 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
|
/// TODO also need terminal state when processing input
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Processor {
|
pub struct Processor;
|
||||||
/// Active modifier keys
|
|
||||||
mods: modifier::Keys,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Types that are notified of escape sequences from the input::Processor.
|
/// Types that are notified of escape sequences from the input::Processor.
|
||||||
pub trait Notify {
|
pub trait Notify {
|
||||||
|
@ -125,7 +60,7 @@ impl<'a, W: Write> Notify for WriteNotifier<'a, W> {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Binding {
|
pub struct Binding {
|
||||||
/// Modifier keys required to activate binding
|
/// Modifier keys required to activate binding
|
||||||
mods: modifier::Keys,
|
mods: Mods,
|
||||||
/// String to send to pty if mods and mode match
|
/// String to send to pty if mods and mode match
|
||||||
send: &'static str,
|
send: &'static str,
|
||||||
/// Terminal mode required to activate binding
|
/// Terminal mode required to activate binding
|
||||||
|
@ -136,98 +71,98 @@ pub struct Binding {
|
||||||
|
|
||||||
/// Bindings for the LEFT key.
|
/// Bindings for the LEFT key.
|
||||||
static LEFT_BINDINGS: &'static [Binding] = &[
|
static LEFT_BINDINGS: &'static [Binding] = &[
|
||||||
Binding { mods: modifier::SHIFT, send: "\x1b[1;2D", mode: mode::ANY, notmode: mode::NONE },
|
Binding { mods: mods::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: mods::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: mods::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: mods::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::ANY, send: "\x1bOD", mode: mode::APP_CURSOR, notmode: mode::NONE },
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Bindings for the RIGHT key
|
/// Bindings for the RIGHT key
|
||||||
static RIGHT_BINDINGS: &'static [Binding] = &[
|
static RIGHT_BINDINGS: &'static [Binding] = &[
|
||||||
Binding { mods: modifier::SHIFT, send: "\x1b[1;2C", mode: mode::ANY, notmode: mode::NONE },
|
Binding { mods: mods::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: mods::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: mods::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: mods::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::ANY, send: "\x1bOC", mode: mode::APP_CURSOR, notmode: mode::NONE },
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Bindings for the UP key
|
/// Bindings for the UP key
|
||||||
static UP_BINDINGS: &'static [Binding] = &[
|
static UP_BINDINGS: &'static [Binding] = &[
|
||||||
Binding { mods: modifier::SHIFT, send: "\x1b[1;2A", mode: mode::ANY, notmode: mode::NONE },
|
Binding { mods: mods::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: mods::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: mods::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: mods::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::ANY, send: "\x1bOA", mode: mode::APP_CURSOR, notmode: mode::NONE },
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Bindings for the DOWN key
|
/// Bindings for the DOWN key
|
||||||
static DOWN_BINDINGS: &'static [Binding] = &[
|
static DOWN_BINDINGS: &'static [Binding] = &[
|
||||||
Binding { mods: modifier::SHIFT, send: "\x1b[1;2B", mode: mode::ANY, notmode: mode::NONE },
|
Binding { mods: mods::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: mods::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: mods::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: mods::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::ANY, send: "\x1bOB", mode: mode::APP_CURSOR, notmode: mode::NONE },
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Bindings for the F1 key
|
/// Bindings for the F1 key
|
||||||
static F1_BINDINGS: &'static [Binding] = &[
|
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
|
/// Bindings for the F2 key
|
||||||
static F2_BINDINGS: &'static [Binding] = &[
|
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
|
/// Bindings for the F3 key
|
||||||
static F3_BINDINGS: &'static [Binding] = &[
|
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
|
/// Bindings for the F4 key
|
||||||
static F4_BINDINGS: &'static [Binding] = &[
|
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
|
/// Bindings for the F5 key
|
||||||
static F5_BINDINGS: &'static [Binding] = &[
|
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
|
/// Bindings for the F6 key
|
||||||
static F6_BINDINGS: &'static [Binding] = &[
|
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
|
/// Bindings for the F7 key
|
||||||
static F7_BINDINGS: &'static [Binding] = &[
|
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
|
/// Bindings for the F8 key
|
||||||
static F8_BINDINGS: &'static [Binding] = &[
|
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
|
/// Bindings for the F9 key
|
||||||
static F9_BINDINGS: &'static [Binding] = &[
|
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
|
/// Bindings for the F10 key
|
||||||
static F10_BINDINGS: &'static [Binding] = &[
|
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
|
/// Bindings for the F11 key
|
||||||
static F11_BINDINGS: &'static [Binding] = &[
|
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
|
/// Bindings for the F11 key
|
||||||
static F12_BINDINGS: &'static [Binding] = &[
|
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
|
/// 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
|
/// since DEL and BACKSPACE are inverted. This binding is a work around to that
|
||||||
/// capture.
|
/// capture.
|
||||||
static H_BINDINGS: &'static [Binding] = &[
|
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
|
/// Bindings for the Backspace key
|
||||||
static BACKSPACE_BINDINGS: &'static [Binding] = &[
|
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
|
/// Bindings for the Delete key
|
||||||
static DELETE_BINDINGS: &'static [Binding] = &[
|
static DELETE_BINDINGS: &'static [Binding] = &[
|
||||||
Binding { mods: modifier::ANY, send: "\x1b[3~", mode: mode::APP_KEYPAD, notmode: mode::NONE },
|
Binding { mods: mods::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[P", mode: mode::ANY, notmode: mode::APP_KEYPAD },
|
||||||
];
|
];
|
||||||
|
|
||||||
// key mods escape appkey appcursor crlf
|
// key mods escape appkey appcursor crlf
|
||||||
|
@ -264,25 +199,12 @@ impl Processor {
|
||||||
pub fn process<N>(&mut self,
|
pub fn process<N>(&mut self,
|
||||||
state: ElementState,
|
state: ElementState,
|
||||||
key: Option<VirtualKeyCode>,
|
key: Option<VirtualKeyCode>,
|
||||||
|
mods: Mods,
|
||||||
notifier: &mut N,
|
notifier: &mut N,
|
||||||
mode: TermMode)
|
mode: TermMode)
|
||||||
where N: Notify
|
where N: Notify
|
||||||
{
|
{
|
||||||
if let Some(key) = key {
|
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
|
// Ignore release events
|
||||||
if state == ElementState::Released {
|
if state == ElementState::Released {
|
||||||
return;
|
return;
|
||||||
|
@ -330,16 +252,20 @@ impl Processor {
|
||||||
// Log something by default
|
// Log something by default
|
||||||
_ => {
|
_ => {
|
||||||
println!("Unhandled key: {:?}; state: {:?}; mods: {:?}",
|
println!("Unhandled key: {:?}; state: {:?}; mods: {:?}",
|
||||||
key, state, self.mods);
|
key, state, mods);
|
||||||
return;
|
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
|
where N: Notify
|
||||||
{
|
{
|
||||||
// Check each binding
|
// Check each binding
|
||||||
|
@ -349,7 +275,7 @@ impl Processor {
|
||||||
// TermMode negative
|
// TermMode negative
|
||||||
if binding.notmode.is_empty() || !mode.intersects(binding.notmode) {
|
if binding.notmode.is_empty() || !mode.intersects(binding.notmode) {
|
||||||
// Modifier keys
|
// Modifier keys
|
||||||
if binding.mods.is_all() || self.mods.intersects(binding.mods) {
|
if binding.mods.is_all() || mods.intersects(binding.mods) {
|
||||||
// everything matches
|
// everything matches
|
||||||
notifier.notify(binding.send);
|
notifier.notify(binding.send);
|
||||||
break;
|
break;
|
||||||
|
@ -363,6 +289,7 @@ impl Processor {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use term::mode::{self, TermMode};
|
use term::mode::{self, TermMode};
|
||||||
|
use glutin::mods;
|
||||||
|
|
||||||
use super::Processor;
|
use super::Processor;
|
||||||
use super::modifier;
|
use super::modifier;
|
||||||
|
@ -393,10 +320,9 @@ mod tests {
|
||||||
let bindings = &[$binding];
|
let bindings = &[$binding];
|
||||||
|
|
||||||
let mut processor = Processor::new();
|
let mut processor = Processor::new();
|
||||||
processor.mods.insert($mods);
|
|
||||||
let mut receiver = Receiver::default();
|
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);
|
assert_eq!(receiver.got, $expect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -404,57 +330,57 @@ mod tests {
|
||||||
|
|
||||||
test_process_binding! {
|
test_process_binding! {
|
||||||
name: process_binding_nomode_shiftmod_require_shift,
|
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")),
|
expect: Some(String::from("\x1b[1;2D")),
|
||||||
mode: mode::NONE,
|
mode: mode::NONE,
|
||||||
mods: modifier::SHIFT
|
mods: mods::SHIFT
|
||||||
}
|
}
|
||||||
|
|
||||||
test_process_binding! {
|
test_process_binding! {
|
||||||
name: process_binding_nomode_nomod_require_shift,
|
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,
|
expect: None,
|
||||||
mode: mode::NONE,
|
mode: mode::NONE,
|
||||||
mods: modifier::NONE
|
mods: mods::NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
test_process_binding! {
|
test_process_binding! {
|
||||||
name: process_binding_nomode_controlmod,
|
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")),
|
expect: Some(String::from("\x1b[1;5D")),
|
||||||
mode: mode::NONE,
|
mode: mode::NONE,
|
||||||
mods: modifier::CONTROL
|
mods: mods::CONTROL
|
||||||
}
|
}
|
||||||
|
|
||||||
test_process_binding! {
|
test_process_binding! {
|
||||||
name: process_binding_nomode_nomod_require_not_appcursor,
|
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")),
|
expect: Some(String::from("\x1b[D")),
|
||||||
mode: mode::NONE,
|
mode: mode::NONE,
|
||||||
mods: modifier::NONE
|
mods: mods::NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
test_process_binding! {
|
test_process_binding! {
|
||||||
name: process_binding_appcursormode_nomod_require_appcursor,
|
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")),
|
expect: Some(String::from("\x1bOD")),
|
||||||
mode: mode::APP_CURSOR,
|
mode: mode::APP_CURSOR,
|
||||||
mods: modifier::NONE
|
mods: mods::NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
test_process_binding! {
|
test_process_binding! {
|
||||||
name: process_binding_nomode_nomod_require_appcursor,
|
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,
|
expect: None,
|
||||||
mode: mode::NONE,
|
mode: mode::NONE,
|
||||||
mods: modifier::NONE
|
mods: mods::NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
test_process_binding! {
|
test_process_binding! {
|
||||||
name: process_binding_appcursormode_appkeypadmode_nomod_require_appcursor,
|
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")),
|
expect: Some(String::from("\x1bOD")),
|
||||||
mode: mode::APP_CURSOR | mode::APP_KEYPAD,
|
mode: mode::APP_CURSOR | mode::APP_KEYPAD,
|
||||||
mods: modifier::NONE
|
mods: mods::NONE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -242,9 +242,10 @@ fn main() {
|
||||||
glutin::Event::Resized(w, h) => {
|
glutin::Event::Resized(w, h) => {
|
||||||
new_size = Some((w, h));
|
new_size = Some((w, h));
|
||||||
},
|
},
|
||||||
glutin::Event::KeyboardInput(state, _code, key) => {
|
glutin::Event::KeyboardInput(state, _code, key, mods) => {
|
||||||
input_processor.process(state,
|
input_processor.process(state,
|
||||||
key,
|
key,
|
||||||
|
mods,
|
||||||
&mut input::WriteNotifier(&mut writer),
|
&mut input::WriteNotifier(&mut writer),
|
||||||
*terminal.mode())
|
*terminal.mode())
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue