mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-18 13:55:23 -05:00
Allow the usage of scancodes in the config
This change should allow the usage of scancodes in the configuration file. When a VirtualKeyCode for glutin is not present, this should now allow the user to use the scancodes instead. If the user specifiecs a key with its scancode even though the key has a VirtualKeyCode, it should still work. The behavior of directly specifying a VirtualKeyCode should be unchanged by this. This fixes #1265.
This commit is contained in:
parent
15e0deae2b
commit
a727801f60
6 changed files with 219 additions and 184 deletions
|
@ -10,8 +10,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
- Add support for windows
|
||||
- Add terminfo capabilities advertising support for changing the window title
|
||||
- Allow using scancodes in the key_bindings section
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed erroneous results when using the `indexed_colors` config option
|
||||
|
||||
## Version 0.2.1
|
||||
|
|
|
@ -324,6 +324,12 @@ live_config_reload: true
|
|||
# A full list with available key codes can be found here:
|
||||
# https://docs.rs/glutin/*/glutin/enum.VirtualKeyCode.html#variants
|
||||
#
|
||||
# Instead of using the name of the keys, the `key` field also supports using
|
||||
# the scancode of the desired key. Scancodes have to be specified as a
|
||||
# decimal number.
|
||||
# This command will allow you to display the hex scancodes for certain keys:
|
||||
# `showkey --scancodes`
|
||||
#
|
||||
# Values for `mods`:
|
||||
# - Command
|
||||
# - Control
|
||||
|
|
|
@ -321,6 +321,12 @@ live_config_reload: true
|
|||
# A full list with available key codes can be found here:
|
||||
# https://docs.rs/glutin/*/glutin/enum.VirtualKeyCode.html#variants
|
||||
#
|
||||
# Instead of using the name of the keys, the `key` field also supports using
|
||||
# the scancode of the desired key. Scancodes have to be specified as a
|
||||
# decimal number.
|
||||
# This command will allow you to display the hex scancodes for certain keys:
|
||||
# `showkey --scancodes`
|
||||
#
|
||||
# Values for `mods`:
|
||||
# - Command
|
||||
# - Control
|
||||
|
|
342
src/config.rs
342
src/config.rs
|
@ -837,7 +837,7 @@ impl<'a> de::Deserialize<'a> for MouseButton {
|
|||
/// Bindings are deserialized into a `RawBinding` before being parsed as a
|
||||
/// `KeyBinding` or `MouseBinding`.
|
||||
struct RawBinding {
|
||||
key: Option<::glutin::VirtualKeyCode>,
|
||||
key: Option<Key>,
|
||||
mouse: Option<::glutin::MouseButton>,
|
||||
mods: ModifiersState,
|
||||
mode: TermMode,
|
||||
|
@ -941,7 +941,7 @@ impl<'a> de::Deserialize<'a> for RawBinding {
|
|||
where V: MapAccess<'a>,
|
||||
{
|
||||
let mut mods: Option<ModifiersState> = None;
|
||||
let mut key: Option<::glutin::VirtualKeyCode> = None;
|
||||
let mut key: Option<Key> = None;
|
||||
let mut chars: Option<String> = None;
|
||||
let mut action: Option<::input::Action> = None;
|
||||
let mut mode: Option<TermMode> = None;
|
||||
|
@ -958,8 +958,21 @@ impl<'a> de::Deserialize<'a> for RawBinding {
|
|||
return Err(<V::Error as Error>::duplicate_field("key"));
|
||||
}
|
||||
|
||||
let coherent_key = map.next_value::<Key>()?;
|
||||
key = Some(coherent_key.to_glutin_key());
|
||||
let val = map.next_value::<serde_yaml::Value>()?;
|
||||
if val.is_u64() {
|
||||
let scancode = val.as_u64().unwrap();
|
||||
if scancode > u64::from(::std::u32::MAX) {
|
||||
return Err(<V::Error as Error>::custom(format!(
|
||||
"invalid key binding, scancode too big: {}",
|
||||
scancode
|
||||
)));
|
||||
}
|
||||
key = Some(Key::Scancode(scancode as u32));
|
||||
} else {
|
||||
let k = Key::deserialize(val)
|
||||
.map_err(V::Error::custom)?;
|
||||
key = Some(k);
|
||||
}
|
||||
},
|
||||
Field::Mods => {
|
||||
if mods.is_some() {
|
||||
|
@ -2059,8 +2072,9 @@ mod tests {
|
|||
}
|
||||
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(enum_variant_names))]
|
||||
#[derive(Deserialize, Copy, Clone)]
|
||||
enum Key {
|
||||
#[derive(Deserialize, Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum Key {
|
||||
Scancode(u32),
|
||||
Key1,
|
||||
Key2,
|
||||
Key3,
|
||||
|
@ -2218,164 +2232,164 @@ enum Key {
|
|||
}
|
||||
|
||||
impl Key {
|
||||
fn to_glutin_key(self) -> ::glutin::VirtualKeyCode {
|
||||
use ::glutin::VirtualKeyCode::*;
|
||||
// Thank you, vim macros!
|
||||
match self {
|
||||
Key::Key1 => Key1,
|
||||
Key::Key2 => Key2,
|
||||
Key::Key3 => Key3,
|
||||
Key::Key4 => Key4,
|
||||
Key::Key5 => Key5,
|
||||
Key::Key6 => Key6,
|
||||
Key::Key7 => Key7,
|
||||
Key::Key8 => Key8,
|
||||
Key::Key9 => Key9,
|
||||
Key::Key0 => Key0,
|
||||
Key::A => A,
|
||||
Key::B => B,
|
||||
Key::C => C,
|
||||
Key::D => D,
|
||||
Key::E => E,
|
||||
Key::F => F,
|
||||
Key::G => G,
|
||||
Key::H => H,
|
||||
Key::I => I,
|
||||
Key::J => J,
|
||||
Key::K => K,
|
||||
Key::L => L,
|
||||
Key::M => M,
|
||||
Key::N => N,
|
||||
Key::O => O,
|
||||
Key::P => P,
|
||||
Key::Q => Q,
|
||||
Key::R => R,
|
||||
Key::S => S,
|
||||
Key::T => T,
|
||||
Key::U => U,
|
||||
Key::V => V,
|
||||
Key::W => W,
|
||||
Key::X => X,
|
||||
Key::Y => Y,
|
||||
Key::Z => Z,
|
||||
Key::Escape => Escape,
|
||||
Key::F1 => F1,
|
||||
Key::F2 => F2,
|
||||
Key::F3 => F3,
|
||||
Key::F4 => F4,
|
||||
Key::F5 => F5,
|
||||
Key::F6 => F6,
|
||||
Key::F7 => F7,
|
||||
Key::F8 => F8,
|
||||
Key::F9 => F9,
|
||||
Key::F10 => F10,
|
||||
Key::F11 => F11,
|
||||
Key::F12 => F12,
|
||||
Key::F13 => F13,
|
||||
Key::F14 => F14,
|
||||
Key::F15 => F15,
|
||||
Key::Snapshot => Snapshot,
|
||||
Key::Scroll => Scroll,
|
||||
Key::Pause => Pause,
|
||||
Key::Insert => Insert,
|
||||
Key::Home => Home,
|
||||
Key::Delete => Delete,
|
||||
Key::End => End,
|
||||
Key::PageDown => PageDown,
|
||||
Key::PageUp => PageUp,
|
||||
Key::Left => Left,
|
||||
Key::Up => Up,
|
||||
Key::Right => Right,
|
||||
Key::Down => Down,
|
||||
Key::Back => Back,
|
||||
Key::Return => Return,
|
||||
Key::Space => Space,
|
||||
Key::Compose => Compose,
|
||||
Key::Numlock => Numlock,
|
||||
Key::Numpad0 => Numpad0,
|
||||
Key::Numpad1 => Numpad1,
|
||||
Key::Numpad2 => Numpad2,
|
||||
Key::Numpad3 => Numpad3,
|
||||
Key::Numpad4 => Numpad4,
|
||||
Key::Numpad5 => Numpad5,
|
||||
Key::Numpad6 => Numpad6,
|
||||
Key::Numpad7 => Numpad7,
|
||||
Key::Numpad8 => Numpad8,
|
||||
Key::Numpad9 => Numpad9,
|
||||
Key::AbntC1 => AbntC1,
|
||||
Key::AbntC2 => AbntC2,
|
||||
Key::Add => Add,
|
||||
Key::Apostrophe => Apostrophe,
|
||||
Key::Apps => Apps,
|
||||
Key::At => At,
|
||||
Key::Ax => Ax,
|
||||
Key::Backslash => Backslash,
|
||||
Key::Calculator => Calculator,
|
||||
Key::Capital => Capital,
|
||||
Key::Colon => Colon,
|
||||
Key::Comma => Comma,
|
||||
Key::Convert => Convert,
|
||||
Key::Decimal => Decimal,
|
||||
Key::Divide => Divide,
|
||||
Key::Equals => Equals,
|
||||
Key::Grave => Grave,
|
||||
Key::Kana => Kana,
|
||||
Key::Kanji => Kanji,
|
||||
Key::LAlt => LAlt,
|
||||
Key::LBracket => LBracket,
|
||||
Key::LControl => LControl,
|
||||
Key::LMenu => LMenu,
|
||||
Key::LShift => LShift,
|
||||
Key::LWin => LWin,
|
||||
Key::Mail => Mail,
|
||||
Key::MediaSelect => MediaSelect,
|
||||
Key::MediaStop => MediaStop,
|
||||
Key::Minus => Minus,
|
||||
Key::Multiply => Multiply,
|
||||
Key::Mute => Mute,
|
||||
Key::MyComputer => MyComputer,
|
||||
Key::NavigateForward => NavigateForward,
|
||||
Key::NavigateBackward => NavigateBackward,
|
||||
Key::NextTrack => NextTrack,
|
||||
Key::NoConvert => NoConvert,
|
||||
Key::NumpadComma => NumpadComma,
|
||||
Key::NumpadEnter => NumpadEnter,
|
||||
Key::NumpadEquals => NumpadEquals,
|
||||
Key::OEM102 => OEM102,
|
||||
Key::Period => Period,
|
||||
Key::PlayPause => PlayPause,
|
||||
Key::Power => Power,
|
||||
Key::PrevTrack => PrevTrack,
|
||||
Key::RAlt => RAlt,
|
||||
Key::RBracket => RBracket,
|
||||
Key::RControl => RControl,
|
||||
Key::RMenu => RMenu,
|
||||
Key::RShift => RShift,
|
||||
Key::RWin => RWin,
|
||||
Key::Semicolon => Semicolon,
|
||||
Key::Slash => Slash,
|
||||
Key::Sleep => Sleep,
|
||||
Key::Stop => Stop,
|
||||
Key::Subtract => Subtract,
|
||||
Key::Sysrq => Sysrq,
|
||||
Key::Tab => Tab,
|
||||
Key::Underline => Underline,
|
||||
Key::Unlabeled => Unlabeled,
|
||||
Key::VolumeDown => VolumeDown,
|
||||
Key::VolumeUp => VolumeUp,
|
||||
Key::Wake => Wake,
|
||||
Key::WebBack => WebBack,
|
||||
Key::WebFavorites => WebFavorites,
|
||||
Key::WebForward => WebForward,
|
||||
Key::WebHome => WebHome,
|
||||
Key::WebRefresh => WebRefresh,
|
||||
Key::WebSearch => WebSearch,
|
||||
Key::WebStop => WebStop,
|
||||
Key::Yen => Yen,
|
||||
Key::Caret => Caret,
|
||||
Key::Copy => Copy,
|
||||
Key::Paste => Paste,
|
||||
Key::Cut => Cut,
|
||||
pub fn from_glutin_input(key: ::glutin::VirtualKeyCode) -> Self {
|
||||
use glutin::VirtualKeyCode::*;
|
||||
// Thank you, vim macros and regex!
|
||||
match key {
|
||||
Key1 => Key::Key1,
|
||||
Key2 => Key::Key2,
|
||||
Key3 => Key::Key3,
|
||||
Key4 => Key::Key4,
|
||||
Key5 => Key::Key5,
|
||||
Key6 => Key::Key6,
|
||||
Key7 => Key::Key7,
|
||||
Key8 => Key::Key8,
|
||||
Key9 => Key::Key9,
|
||||
Key0 => Key::Key0,
|
||||
A => Key::A,
|
||||
B => Key::B,
|
||||
C => Key::C,
|
||||
D => Key::D,
|
||||
E => Key::E,
|
||||
F => Key::F,
|
||||
G => Key::G,
|
||||
H => Key::H,
|
||||
I => Key::I,
|
||||
J => Key::J,
|
||||
K => Key::K,
|
||||
L => Key::L,
|
||||
M => Key::M,
|
||||
N => Key::N,
|
||||
O => Key::O,
|
||||
P => Key::P,
|
||||
Q => Key::Q,
|
||||
R => Key::R,
|
||||
S => Key::S,
|
||||
T => Key::T,
|
||||
U => Key::U,
|
||||
V => Key::V,
|
||||
W => Key::W,
|
||||
X => Key::X,
|
||||
Y => Key::Y,
|
||||
Z => Key::Z,
|
||||
Escape => Key::Escape,
|
||||
F1 => Key::F1,
|
||||
F2 => Key::F2,
|
||||
F3 => Key::F3,
|
||||
F4 => Key::F4,
|
||||
F5 => Key::F5,
|
||||
F6 => Key::F6,
|
||||
F7 => Key::F7,
|
||||
F8 => Key::F8,
|
||||
F9 => Key::F9,
|
||||
F10 => Key::F10,
|
||||
F11 => Key::F11,
|
||||
F12 => Key::F12,
|
||||
F13 => Key::F13,
|
||||
F14 => Key::F14,
|
||||
F15 => Key::F15,
|
||||
Snapshot => Key::Snapshot,
|
||||
Scroll => Key::Scroll,
|
||||
Pause => Key::Pause,
|
||||
Insert => Key::Insert,
|
||||
Home => Key::Home,
|
||||
Delete => Key::Delete,
|
||||
End => Key::End,
|
||||
PageDown => Key::PageDown,
|
||||
PageUp => Key::PageUp,
|
||||
Left => Key::Left,
|
||||
Up => Key::Up,
|
||||
Right => Key::Right,
|
||||
Down => Key::Down,
|
||||
Back => Key::Back,
|
||||
Return => Key::Return,
|
||||
Space => Key::Space,
|
||||
Compose => Key::Compose,
|
||||
Numlock => Key::Numlock,
|
||||
Numpad0 => Key::Numpad0,
|
||||
Numpad1 => Key::Numpad1,
|
||||
Numpad2 => Key::Numpad2,
|
||||
Numpad3 => Key::Numpad3,
|
||||
Numpad4 => Key::Numpad4,
|
||||
Numpad5 => Key::Numpad5,
|
||||
Numpad6 => Key::Numpad6,
|
||||
Numpad7 => Key::Numpad7,
|
||||
Numpad8 => Key::Numpad8,
|
||||
Numpad9 => Key::Numpad9,
|
||||
AbntC1 => Key::AbntC1,
|
||||
AbntC2 => Key::AbntC2,
|
||||
Add => Key::Add,
|
||||
Apostrophe => Key::Apostrophe,
|
||||
Apps => Key::Apps,
|
||||
At => Key::At,
|
||||
Ax => Key::Ax,
|
||||
Backslash => Key::Backslash,
|
||||
Calculator => Key::Calculator,
|
||||
Capital => Key::Capital,
|
||||
Colon => Key::Colon,
|
||||
Comma => Key::Comma,
|
||||
Convert => Key::Convert,
|
||||
Decimal => Key::Decimal,
|
||||
Divide => Key::Divide,
|
||||
Equals => Key::Equals,
|
||||
Grave => Key::Grave,
|
||||
Kana => Key::Kana,
|
||||
Kanji => Key::Kanji,
|
||||
LAlt => Key::LAlt,
|
||||
LBracket => Key::LBracket,
|
||||
LControl => Key::LControl,
|
||||
LMenu => Key::LMenu,
|
||||
LShift => Key::LShift,
|
||||
LWin => Key::LWin,
|
||||
Mail => Key::Mail,
|
||||
MediaSelect => Key::MediaSelect,
|
||||
MediaStop => Key::MediaStop,
|
||||
Minus => Key::Minus,
|
||||
Multiply => Key::Multiply,
|
||||
Mute => Key::Mute,
|
||||
MyComputer => Key::MyComputer,
|
||||
NavigateForward => Key::NavigateForward,
|
||||
NavigateBackward => Key::NavigateBackward,
|
||||
NextTrack => Key::NextTrack,
|
||||
NoConvert => Key::NoConvert,
|
||||
NumpadComma => Key::NumpadComma,
|
||||
NumpadEnter => Key::NumpadEnter,
|
||||
NumpadEquals => Key::NumpadEquals,
|
||||
OEM102 => Key::OEM102,
|
||||
Period => Key::Period,
|
||||
PlayPause => Key::PlayPause,
|
||||
Power => Key::Power,
|
||||
PrevTrack => Key::PrevTrack,
|
||||
RAlt => Key::RAlt,
|
||||
RBracket => Key::RBracket,
|
||||
RControl => Key::RControl,
|
||||
RMenu => Key::RMenu,
|
||||
RShift => Key::RShift,
|
||||
RWin => Key::RWin,
|
||||
Semicolon => Key::Semicolon,
|
||||
Slash => Key::Slash,
|
||||
Sleep => Key::Sleep,
|
||||
Stop => Key::Stop,
|
||||
Subtract => Key::Subtract,
|
||||
Sysrq => Key::Sysrq,
|
||||
Tab => Key::Tab,
|
||||
Underline => Key::Underline,
|
||||
Unlabeled => Key::Unlabeled,
|
||||
VolumeDown => Key::VolumeDown,
|
||||
VolumeUp => Key::VolumeUp,
|
||||
Wake => Key::Wake,
|
||||
WebBack => Key::WebBack,
|
||||
WebFavorites => Key::WebFavorites,
|
||||
WebForward => Key::WebForward,
|
||||
WebHome => Key::WebHome,
|
||||
WebRefresh => Key::WebRefresh,
|
||||
WebSearch => Key::WebSearch,
|
||||
WebStop => Key::WebStop,
|
||||
Yen => Key::Yen,
|
||||
Caret => Key::Caret,
|
||||
Copy => Key::Copy,
|
||||
Paste => Key::Paste,
|
||||
Cut => Key::Cut,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -334,9 +334,8 @@ impl<N: Notify> Processor<N> {
|
|||
processor.ctx.terminal.dirty = true;
|
||||
},
|
||||
KeyboardInput { input, .. } => {
|
||||
let glutin::KeyboardInput { state, virtual_keycode, modifiers, .. } = input;
|
||||
processor.process_key(state, virtual_keycode, modifiers);
|
||||
if state == ElementState::Pressed {
|
||||
processor.process_key(input);
|
||||
if input.state == ElementState::Pressed {
|
||||
// Hide cursor while typing
|
||||
*hide_cursor = true;
|
||||
}
|
||||
|
|
42
src/input.rs
42
src/input.rs
|
@ -26,9 +26,9 @@ use std::time::Instant;
|
|||
use std::os::unix::process::CommandExt;
|
||||
|
||||
use copypasta::{Clipboard, Load, Buffer as ClipboardBuffer};
|
||||
use glutin::{ElementState, VirtualKeyCode, MouseButton, TouchPhase, MouseScrollDelta, ModifiersState};
|
||||
use glutin::{ElementState, MouseButton, TouchPhase, MouseScrollDelta, ModifiersState, KeyboardInput};
|
||||
|
||||
use config;
|
||||
use config::{self, Key};
|
||||
use grid::Scroll;
|
||||
use event::{ClickState, Mouse};
|
||||
use index::{Line, Column, Side, Point};
|
||||
|
@ -100,7 +100,7 @@ pub struct Binding<T> {
|
|||
}
|
||||
|
||||
/// Bindings that are triggered by a keyboard key
|
||||
pub type KeyBinding = Binding<VirtualKeyCode>;
|
||||
pub type KeyBinding = Binding<Key>;
|
||||
|
||||
/// Bindings that are triggered by a mouse button
|
||||
pub type MouseBinding = Binding<MouseButton>;
|
||||
|
@ -618,24 +618,18 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> {
|
|||
/// Process key input
|
||||
///
|
||||
/// If a keybinding was run, returns true. Otherwise returns false.
|
||||
pub fn process_key(
|
||||
&mut self,
|
||||
state: ElementState,
|
||||
key: Option<VirtualKeyCode>,
|
||||
mods: ModifiersState,
|
||||
) {
|
||||
match (key, state) {
|
||||
(Some(key), ElementState::Pressed) => {
|
||||
*self.ctx.last_modifiers() = mods;
|
||||
pub fn process_key(&mut self, input: KeyboardInput) {
|
||||
match input.state {
|
||||
ElementState::Pressed => {
|
||||
*self.ctx.last_modifiers() = input.modifiers;
|
||||
*self.ctx.received_count() = 0;
|
||||
*self.ctx.suppress_chars() = false;
|
||||
|
||||
if self.process_key_bindings(mods, key) {
|
||||
if self.process_key_bindings(input) {
|
||||
*self.ctx.suppress_chars() = true;
|
||||
}
|
||||
},
|
||||
(_, ElementState::Released) => *self.ctx.suppress_chars() = false,
|
||||
_ => ()
|
||||
ElementState::Released => *self.ctx.suppress_chars() = false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -668,10 +662,24 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> {
|
|||
/// for its action to be executed.
|
||||
///
|
||||
/// Returns true if an action is executed.
|
||||
fn process_key_bindings(&mut self, mods: ModifiersState, key: VirtualKeyCode) -> bool {
|
||||
fn process_key_bindings(&mut self, input: KeyboardInput) -> bool {
|
||||
let mut has_binding = false;
|
||||
for binding in self.key_bindings {
|
||||
if binding.is_triggered_by(self.ctx.terminal_mode(), mods, &key) {
|
||||
let is_triggered = match binding.trigger {
|
||||
Key::Scancode(_) => binding.is_triggered_by(
|
||||
self.ctx.terminal_mode(),
|
||||
input.modifiers,
|
||||
&Key::Scancode(input.scancode),
|
||||
),
|
||||
_ => if let Some(key) = input.virtual_keycode {
|
||||
let key = Key::from_glutin_input(key);
|
||||
binding.is_triggered_by(self.ctx.terminal_mode(), input.modifiers, &key)
|
||||
} else {
|
||||
false
|
||||
},
|
||||
};
|
||||
|
||||
if is_triggered {
|
||||
// binding was triggered; run the action
|
||||
binding.execute(&mut self.ctx);
|
||||
has_binding = true;
|
||||
|
|
Loading…
Reference in a new issue