mirror of
https://github.com/alacritty/alacritty
synced 2024-09-29 04:23:53 +00:00
Refactor input processing to take action context
Various functions take some permutation of the current selection, the terminal, and a notifier. Instead of having to juggle some number of arguments everywhere, the `ActionContext` is constructed and then passed around.
This commit is contained in:
parent
7cdf06e2be
commit
3b7c7377c9
33
src/event.rs
33
src/event.rs
|
@ -8,7 +8,7 @@ use glutin;
|
||||||
|
|
||||||
use config::Config;
|
use config::Config;
|
||||||
use display::OnResize;
|
use display::OnResize;
|
||||||
use input;
|
use input::{self, ActionContext};
|
||||||
use selection::Selection;
|
use selection::Selection;
|
||||||
use sync::FairMutex;
|
use sync::FairMutex;
|
||||||
use term::{Term, SizeInfo};
|
use term::{Term, SizeInfo};
|
||||||
|
@ -98,18 +98,29 @@ impl<N: input::Notify> Processor<N> {
|
||||||
// Acquire term lock
|
// Acquire term lock
|
||||||
let terminal = self.terminal.lock();
|
let terminal = self.terminal.lock();
|
||||||
let processor = &mut self.input_processor;
|
let processor = &mut self.input_processor;
|
||||||
let notifier = &mut self.notifier;
|
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut context = ActionContext {
|
||||||
|
terminal: &terminal,
|
||||||
|
notifier: &mut self.notifier,
|
||||||
|
selection: &mut self.selection,
|
||||||
|
};
|
||||||
|
|
||||||
|
processor.process_key(&mut context, state, key, mods, string);
|
||||||
|
}
|
||||||
self.selection.clear();
|
self.selection.clear();
|
||||||
|
|
||||||
processor.process_key(state, key, mods, notifier, *terminal.mode(), string);
|
|
||||||
},
|
},
|
||||||
glutin::Event::MouseInput(state, button) => {
|
glutin::Event::MouseInput(state, button) => {
|
||||||
let terminal = self.terminal.lock();
|
let terminal = self.terminal.lock();
|
||||||
let processor = &mut self.input_processor;
|
let processor = &mut self.input_processor;
|
||||||
let notifier = &mut self.notifier;
|
|
||||||
|
|
||||||
processor.mouse_input(&mut self.selection, state, button, notifier, &terminal);
|
let mut context = ActionContext {
|
||||||
|
terminal: &terminal,
|
||||||
|
notifier: &mut self.notifier,
|
||||||
|
selection: &mut self.selection,
|
||||||
|
};
|
||||||
|
|
||||||
|
processor.mouse_input(&mut context, state, button);
|
||||||
*wakeup_request = true;
|
*wakeup_request = true;
|
||||||
},
|
},
|
||||||
glutin::Event::MouseMoved(x, y) => {
|
glutin::Event::MouseMoved(x, y) => {
|
||||||
|
@ -131,11 +142,17 @@ impl<N: input::Notify> Processor<N> {
|
||||||
terminal.dirty = true;
|
terminal.dirty = true;
|
||||||
},
|
},
|
||||||
glutin::Event::MouseWheel(scroll_delta, touch_phase) => {
|
glutin::Event::MouseWheel(scroll_delta, touch_phase) => {
|
||||||
|
let mut terminal = self.terminal.lock();
|
||||||
let processor = &mut self.input_processor;
|
let processor = &mut self.input_processor;
|
||||||
let notifier = &mut self.notifier;
|
|
||||||
|
let mut context = ActionContext {
|
||||||
|
terminal: &terminal,
|
||||||
|
notifier: &mut self.notifier,
|
||||||
|
selection: &mut self.selection,
|
||||||
|
};
|
||||||
|
|
||||||
processor.on_mouse_wheel(
|
processor.on_mouse_wheel(
|
||||||
notifier,
|
&mut context,
|
||||||
scroll_delta,
|
scroll_delta,
|
||||||
touch_phase,
|
touch_phase,
|
||||||
);
|
);
|
||||||
|
|
121
src/input.rs
121
src/input.rs
|
@ -25,7 +25,7 @@
|
||||||
//! TODO handling xmodmap would be good
|
//! TODO handling xmodmap would be good
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use copypasta::{Clipboard, Load};
|
use copypasta::{Clipboard, Load, Store};
|
||||||
use glutin::{ElementState, VirtualKeyCode, MouseButton};
|
use glutin::{ElementState, VirtualKeyCode, MouseButton};
|
||||||
use glutin::{Mods, mods};
|
use glutin::{Mods, mods};
|
||||||
use glutin::{TouchPhase, MouseScrollDelta};
|
use glutin::{TouchPhase, MouseScrollDelta};
|
||||||
|
@ -142,8 +142,8 @@ impl KeyBinding {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn execute<N: Notify>(&self, notifier: &mut N, mode: &TermMode) {
|
fn execute<'a, N: Notify>(&self, context: &mut ActionContext<'a, N>) {
|
||||||
self.binding.action.execute(notifier, mode)
|
self.binding.action.execute(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,8 +162,8 @@ impl MouseBinding {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn execute<N: Notify>(&self, notifier: &mut N, mode: &TermMode) {
|
fn execute<'a, N: Notify>(&self, context: &mut ActionContext<'a, N>) {
|
||||||
self.binding.action.execute(notifier, mode)
|
self.binding.action.execute(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,25 +175,32 @@ pub enum Action {
|
||||||
/// Paste contents of system clipboard
|
/// Paste contents of system clipboard
|
||||||
Paste,
|
Paste,
|
||||||
|
|
||||||
|
// Store current selection into clipboard
|
||||||
|
Copy,
|
||||||
|
|
||||||
/// Paste contents of selection buffer
|
/// Paste contents of selection buffer
|
||||||
PasteSelection,
|
PasteSelection,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Action {
|
impl Action {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn execute<N: Notify>(&self, notifier: &mut N, mode: &TermMode) {
|
fn execute<'a, N: Notify>(&self, ctx: &mut ActionContext<'a, N>) {
|
||||||
match *self {
|
match *self {
|
||||||
Action::Esc(ref s) => notifier.notify(s.clone().into_bytes()),
|
Action::Esc(ref s) => ctx.notifier.notify(s.clone().into_bytes()),
|
||||||
|
Action::Copy => {
|
||||||
|
// so... need access to terminal state. and the selection.
|
||||||
|
unimplemented!();
|
||||||
|
},
|
||||||
Action::Paste | Action::PasteSelection => {
|
Action::Paste | Action::PasteSelection => {
|
||||||
let clip = Clipboard::new().expect("get clipboard");
|
let clip = Clipboard::new().expect("get clipboard");
|
||||||
clip.load_selection()
|
clip.load_selection()
|
||||||
.map(|contents| {
|
.map(|contents| {
|
||||||
if mode.contains(mode::BRACKETED_PASTE) {
|
if ctx.terminal.mode().contains(mode::BRACKETED_PASTE) {
|
||||||
notifier.notify(&b"\x1b[200~"[..]);
|
ctx.notifier.notify(&b"\x1b[200~"[..]);
|
||||||
notifier.notify(contents.into_bytes());
|
ctx.notifier.notify(contents.into_bytes());
|
||||||
notifier.notify(&b"\x1b[201~"[..]);
|
ctx.notifier.notify(&b"\x1b[201~"[..]);
|
||||||
} else {
|
} else {
|
||||||
notifier.notify(contents.into_bytes());
|
ctx.notifier.notify(contents.into_bytes());
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
|
@ -240,11 +247,11 @@ impl Binding {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// key mods escape appkey appcursor crlf
|
pub struct ActionContext<'a, N: 'a> {
|
||||||
//
|
pub notifier: &'a mut N,
|
||||||
// notes: appkey = DECPAM (application keypad mode); not enabled is "normal keypad"
|
pub terminal: &'a Term,
|
||||||
// appcursor = DECCKM (application cursor mode);
|
pub selection: &'a mut Selection
|
||||||
// crlf = LNM (Linefeed/new line); wtf is this
|
}
|
||||||
|
|
||||||
impl Processor {
|
impl Processor {
|
||||||
pub fn resize(&mut self, size_info: &term::SizeInfo) {
|
pub fn resize(&mut self, size_info: &term::SizeInfo) {
|
||||||
|
@ -292,10 +299,10 @@ impl Processor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mouse_report<N: Notify>(
|
pub fn mouse_report<'a, N: Notify>(
|
||||||
&mut self,
|
&mut self,
|
||||||
button: u8,
|
button: u8,
|
||||||
notifier: &mut N,
|
context: &mut ActionContext<'a, N>
|
||||||
) {
|
) {
|
||||||
let (line, column) = (self.mouse.line, self.mouse.column);
|
let (line, column) = (self.mouse.line, self.mouse.column);
|
||||||
|
|
||||||
|
@ -309,34 +316,32 @@ impl Processor {
|
||||||
32 + 1 + line.0 as u8,
|
32 + 1 + line.0 as u8,
|
||||||
];
|
];
|
||||||
|
|
||||||
notifier.notify(msg);
|
context.notifier.notify(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_mouse_press<N: Notify>(
|
pub fn on_mouse_press<'a, N: Notify>(
|
||||||
&mut self,
|
&mut self,
|
||||||
notifier: &mut N,
|
context: &mut ActionContext<'a, N>
|
||||||
terminal: &Term,
|
|
||||||
selection: &mut Selection
|
|
||||||
) {
|
) {
|
||||||
if terminal.mode().contains(mode::MOUSE_REPORT_CLICK) {
|
if context.terminal.mode().contains(mode::MOUSE_REPORT_CLICK) {
|
||||||
self.mouse_report(0, notifier);
|
self.mouse_report(0, context);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
selection.clear();
|
context.selection.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_mouse_release<N: Notify>(&mut self, notifier: &mut N, terminal: &Term) {
|
pub fn on_mouse_release<'a, N: Notify>(&mut self, context: &mut ActionContext<'a, N>) {
|
||||||
if terminal.mode().contains(mode::MOUSE_REPORT_CLICK) {
|
if context.terminal.mode().contains(mode::MOUSE_REPORT_CLICK) {
|
||||||
self.mouse_report(3, notifier);
|
self.mouse_report(3, context);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_mouse_wheel<N: Notify>(
|
pub fn on_mouse_wheel<'a, N: Notify>(
|
||||||
&mut self,
|
&mut self,
|
||||||
notifier: &mut N,
|
context: &mut ActionContext<'a, N>,
|
||||||
delta: MouseScrollDelta,
|
delta: MouseScrollDelta,
|
||||||
phase: TouchPhase,
|
phase: TouchPhase,
|
||||||
) {
|
) {
|
||||||
|
@ -349,7 +354,7 @@ impl Processor {
|
||||||
};
|
};
|
||||||
|
|
||||||
for _ in 0..(lines.abs() as usize) {
|
for _ in 0..(lines.abs() as usize) {
|
||||||
self.mouse_report(code, notifier);
|
self.mouse_report(code, context);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
MouseScrollDelta::PixelDelta(_x, y) => {
|
MouseScrollDelta::PixelDelta(_x, y) => {
|
||||||
|
@ -371,7 +376,7 @@ impl Processor {
|
||||||
65
|
65
|
||||||
};
|
};
|
||||||
|
|
||||||
self.mouse_report(button, notifier);
|
self.mouse_report(button, context);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -380,13 +385,11 @@ impl Processor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mouse_input<N: Notify>(
|
pub fn mouse_input<'a, N: Notify>(
|
||||||
&mut self,
|
&mut self,
|
||||||
selection: &mut Selection,
|
context: &mut ActionContext<'a, N>,
|
||||||
state: ElementState,
|
state: ElementState,
|
||||||
button: MouseButton,
|
button: MouseButton,
|
||||||
notifier: &mut N,
|
|
||||||
terminal: &Term
|
|
||||||
) {
|
) {
|
||||||
if let MouseButton::Left = button {
|
if let MouseButton::Left = button {
|
||||||
// TODO handle state changes
|
// TODO handle state changes
|
||||||
|
@ -394,10 +397,10 @@ impl Processor {
|
||||||
self.mouse.left_button_state = state;
|
self.mouse.left_button_state = state;
|
||||||
match state {
|
match state {
|
||||||
ElementState::Pressed => {
|
ElementState::Pressed => {
|
||||||
self.on_mouse_press(notifier, terminal, selection);
|
self.on_mouse_press(context);
|
||||||
},
|
},
|
||||||
ElementState::Released => {
|
ElementState::Released => {
|
||||||
self.on_mouse_release(notifier, terminal);
|
self.on_mouse_release(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -408,21 +411,19 @@ impl Processor {
|
||||||
}
|
}
|
||||||
|
|
||||||
Processor::process_mouse_bindings(
|
Processor::process_mouse_bindings(
|
||||||
|
context,
|
||||||
&self.mouse_bindings[..],
|
&self.mouse_bindings[..],
|
||||||
*terminal.mode(),
|
|
||||||
notifier,
|
|
||||||
mods::NONE,
|
mods::NONE,
|
||||||
button
|
button
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_key<N: Notify>(
|
pub fn process_key<'a, N: Notify>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
context: &mut ActionContext<'a, N>,
|
||||||
state: ElementState,
|
state: ElementState,
|
||||||
key: Option<VirtualKeyCode>,
|
key: Option<VirtualKeyCode>,
|
||||||
mods: Mods,
|
mods: Mods,
|
||||||
notifier: &mut N,
|
|
||||||
mode: TermMode,
|
|
||||||
string: Option<String>,
|
string: Option<String>,
|
||||||
) {
|
) {
|
||||||
if let Some(key) = key {
|
if let Some(key) = key {
|
||||||
|
@ -431,13 +432,13 @@ impl Processor {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if Processor::process_key_bindings(&self.key_bindings[..], mode, notifier, mods, key) {
|
if Processor::process_key_bindings(context, &self.key_bindings[..], mods, key) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Didn't process a binding; print the provided character
|
// Didn't process a binding; print the provided character
|
||||||
if let Some(string) = string {
|
if let Some(string) = string {
|
||||||
notifier.notify(string.into_bytes());
|
context.notifier.notify(string.into_bytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -448,19 +449,16 @@ impl Processor {
|
||||||
/// for its action to be executed.
|
/// for its action to be executed.
|
||||||
///
|
///
|
||||||
/// Returns true if an action is executed.
|
/// Returns true if an action is executed.
|
||||||
fn process_key_bindings<N>(
|
fn process_key_bindings<'a, N: Notify>(
|
||||||
|
context: &mut ActionContext<'a, N>,
|
||||||
bindings: &[KeyBinding],
|
bindings: &[KeyBinding],
|
||||||
mode: TermMode,
|
|
||||||
notifier: &mut N,
|
|
||||||
mods: Mods,
|
mods: Mods,
|
||||||
key: VirtualKeyCode
|
key: VirtualKeyCode
|
||||||
) -> bool
|
) -> bool {
|
||||||
where N: Notify
|
|
||||||
{
|
|
||||||
for binding in bindings {
|
for binding in bindings {
|
||||||
if binding.is_triggered_by(&mode, &mods, &key) {
|
if binding.is_triggered_by(context.terminal.mode(), &mods, &key) {
|
||||||
// binding was triggered; run the action
|
// binding was triggered; run the action
|
||||||
binding.execute(notifier, &mode);
|
binding.execute(context);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -474,19 +472,16 @@ impl Processor {
|
||||||
/// for its action to be executed.
|
/// for its action to be executed.
|
||||||
///
|
///
|
||||||
/// Returns true if an action is executed.
|
/// Returns true if an action is executed.
|
||||||
fn process_mouse_bindings<N>(
|
fn process_mouse_bindings<'a, N: Notify>(
|
||||||
|
context: &mut ActionContext<'a, N>,
|
||||||
bindings: &[MouseBinding],
|
bindings: &[MouseBinding],
|
||||||
mode: TermMode,
|
|
||||||
notifier: &mut N,
|
|
||||||
mods: Mods,
|
mods: Mods,
|
||||||
button: MouseButton
|
button: MouseButton
|
||||||
) -> bool
|
) -> bool {
|
||||||
where N: Notify
|
|
||||||
{
|
|
||||||
for binding in bindings {
|
for binding in bindings {
|
||||||
if binding.is_triggered_by(&mode, &mods, &button) {
|
if binding.is_triggered_by(context.terminal.mode(), &mods, &button) {
|
||||||
// binding was triggered; run the action
|
// binding was triggered; run the action
|
||||||
binding.execute(notifier, &mode);
|
binding.execute(context);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue