2016-09-01 13:24:20 -04:00
|
|
|
//! Process window events
|
2016-12-26 18:33:27 -05:00
|
|
|
use std::borrow::Cow;
|
2016-11-19 19:16:20 -05:00
|
|
|
use std::fs::File;
|
|
|
|
use std::io::Write;
|
2016-12-29 15:30:30 -05:00
|
|
|
use std::sync::mpsc;
|
2017-01-14 20:53:48 -05:00
|
|
|
use std::time::{Instant};
|
2016-09-01 13:24:20 -04:00
|
|
|
|
2016-12-29 15:30:30 -05:00
|
|
|
use serde_json as json;
|
|
|
|
use parking_lot::MutexGuard;
|
2017-07-20 13:50:50 -04:00
|
|
|
use glutin::{self, ModifiersState, Event, ElementState};
|
2017-02-02 01:13:08 -05:00
|
|
|
use copypasta::{Clipboard, Load, Store};
|
2016-12-11 01:44:13 -05:00
|
|
|
|
2017-01-14 20:53:48 -05:00
|
|
|
use config::{self, Config};
|
2017-01-08 16:09:02 -05:00
|
|
|
use cli::Options;
|
2016-12-12 12:31:48 -05:00
|
|
|
use display::OnResize;
|
2017-02-02 01:13:08 -05:00
|
|
|
use index::{Line, Column, Side, Point};
|
|
|
|
use input::{self, MouseBinding, KeyBinding};
|
2016-12-22 13:43:06 -05:00
|
|
|
use selection::Selection;
|
2016-09-23 13:12:11 -04:00
|
|
|
use sync::FairMutex;
|
2017-02-02 01:13:08 -05:00
|
|
|
use term::{Term, SizeInfo, TermMode};
|
2016-12-29 20:39:30 -05:00
|
|
|
use util::limit;
|
2017-02-02 01:13:08 -05:00
|
|
|
use util::fmt::Red;
|
2016-12-12 12:31:48 -05:00
|
|
|
use window::Window;
|
2016-09-01 13:24:20 -04:00
|
|
|
|
2016-12-26 18:33:27 -05:00
|
|
|
/// Byte sequences are sent to a `Notify` in response to some events
|
|
|
|
pub trait Notify {
|
|
|
|
/// Notify that an escape sequence should be written to the pty
|
|
|
|
///
|
|
|
|
/// TODO this needs to be able to error somehow
|
|
|
|
fn notify<B: Into<Cow<'static, [u8]>>>(&mut self, B);
|
|
|
|
}
|
|
|
|
|
2017-02-02 01:13:08 -05:00
|
|
|
pub struct ActionContext<'a, N: 'a> {
|
|
|
|
pub notifier: &'a mut N,
|
|
|
|
pub terminal: &'a mut Term,
|
2017-06-16 00:43:28 -04:00
|
|
|
pub selection: &'a mut Option<Selection>,
|
2017-02-02 01:13:08 -05:00
|
|
|
pub size_info: &'a SizeInfo,
|
|
|
|
pub mouse: &'a mut Mouse,
|
2017-06-16 15:56:55 -04:00
|
|
|
pub selection_modified: bool,
|
2017-07-20 13:50:50 -04:00
|
|
|
pub received_count: &'a mut usize,
|
|
|
|
pub suppress_chars: &'a mut bool,
|
|
|
|
pub last_modifiers: &'a mut ModifiersState,
|
2017-02-02 01:13:08 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, N: Notify + 'a> input::ActionContext for ActionContext<'a, N> {
|
|
|
|
fn write_to_pty<B: Into<Cow<'static, [u8]>>>(&mut self, val: B) {
|
|
|
|
self.notifier.notify(val);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn terminal_mode(&self) -> TermMode {
|
|
|
|
*self.terminal.mode()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn size_info(&self) -> SizeInfo {
|
|
|
|
*self.size_info
|
|
|
|
}
|
|
|
|
|
|
|
|
fn copy_selection(&self, buffer: ::copypasta::Buffer) {
|
2018-01-05 20:42:55 -05:00
|
|
|
if let Some(ref selection) = *self.selection {
|
2018-05-11 14:22:36 -04:00
|
|
|
if let Some(ref span) = selection.to_span(self.terminal) {
|
|
|
|
let buf = self.terminal.string_from_selection(&span);
|
|
|
|
if !buf.is_empty() {
|
|
|
|
Clipboard::new()
|
|
|
|
.and_then(|mut clipboard| clipboard.store(buf, buffer))
|
|
|
|
.unwrap_or_else(|err| {
|
|
|
|
warn!("Error storing selection to clipboard. {}", Red(err));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2017-02-02 01:13:08 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn clear_selection(&mut self) {
|
2017-06-16 00:43:28 -04:00
|
|
|
*self.selection = None;
|
2017-06-16 15:56:55 -04:00
|
|
|
self.selection_modified = true;
|
2017-02-02 01:13:08 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn update_selection(&mut self, point: Point, side: Side) {
|
2017-06-16 15:56:55 -04:00
|
|
|
self.selection_modified = true;
|
2017-06-16 00:43:28 -04:00
|
|
|
// Update selection if one exists
|
2018-01-05 20:42:55 -05:00
|
|
|
if let Some(ref mut selection) = *self.selection {
|
2017-06-16 00:43:28 -04:00
|
|
|
selection.update(point, side);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, start a regular selection
|
|
|
|
self.simple_selection(point, side);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn simple_selection(&mut self, point: Point, side: Side) {
|
|
|
|
*self.selection = Some(Selection::simple(point, side));
|
2017-06-16 15:56:55 -04:00
|
|
|
self.selection_modified = true;
|
2017-02-02 01:13:08 -05:00
|
|
|
}
|
|
|
|
|
2017-01-14 20:53:48 -05:00
|
|
|
fn semantic_selection(&mut self, point: Point) {
|
2018-01-05 20:42:55 -05:00
|
|
|
*self.selection = Some(Selection::semantic(point, self.terminal));
|
2017-06-16 15:56:55 -04:00
|
|
|
self.selection_modified = true;
|
2017-01-14 20:53:48 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn line_selection(&mut self, point: Point) {
|
2017-06-16 00:43:28 -04:00
|
|
|
*self.selection = Some(Selection::lines(point));
|
2017-06-16 15:56:55 -04:00
|
|
|
self.selection_modified = true;
|
2017-01-14 20:53:48 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn mouse_coords(&self) -> Option<Point> {
|
|
|
|
self.terminal.pixels_to_coords(self.mouse.x as usize, self.mouse.y as usize)
|
|
|
|
}
|
|
|
|
|
2017-10-14 13:35:56 -04:00
|
|
|
fn change_font_size(&mut self, delta: i8) {
|
|
|
|
self.terminal.change_font_size(delta);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn reset_font_size(&mut self) {
|
|
|
|
self.terminal.reset_font_size();
|
|
|
|
}
|
|
|
|
|
2017-02-02 01:13:08 -05:00
|
|
|
#[inline]
|
|
|
|
fn mouse_mut(&mut self) -> &mut Mouse {
|
|
|
|
self.mouse
|
|
|
|
}
|
2017-07-20 13:50:50 -04:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn received_count(&mut self) -> &mut usize {
|
|
|
|
&mut self.received_count
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn suppress_chars(&mut self) -> &mut bool {
|
|
|
|
&mut self.suppress_chars
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn last_modifiers(&mut self) -> &mut ModifiersState {
|
|
|
|
&mut self.last_modifiers
|
|
|
|
}
|
2017-02-02 01:13:08 -05:00
|
|
|
}
|
|
|
|
|
2017-01-14 20:53:48 -05:00
|
|
|
pub enum ClickState {
|
|
|
|
None,
|
|
|
|
Click,
|
|
|
|
DoubleClick,
|
|
|
|
TripleClick,
|
|
|
|
}
|
|
|
|
|
2016-12-26 18:33:27 -05:00
|
|
|
/// State of the mouse
|
|
|
|
pub struct Mouse {
|
|
|
|
pub x: u32,
|
|
|
|
pub y: u32,
|
|
|
|
pub left_button_state: ElementState,
|
2018-01-26 16:28:43 -05:00
|
|
|
pub middle_button_state: ElementState,
|
|
|
|
pub right_button_state: ElementState,
|
2017-01-14 20:53:48 -05:00
|
|
|
pub last_click_timestamp: Instant,
|
|
|
|
pub click_state: ClickState,
|
2016-12-26 18:33:27 -05:00
|
|
|
pub scroll_px: i32,
|
|
|
|
pub line: Line,
|
|
|
|
pub column: Column,
|
2017-09-02 15:29:03 -04:00
|
|
|
pub cell_side: Side,
|
|
|
|
pub lines_scrolled: f32,
|
2016-12-26 18:33:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for Mouse {
|
|
|
|
fn default() -> Mouse {
|
|
|
|
Mouse {
|
|
|
|
x: 0,
|
|
|
|
y: 0,
|
2017-01-14 20:53:48 -05:00
|
|
|
last_click_timestamp: Instant::now(),
|
2016-12-26 18:33:27 -05:00
|
|
|
left_button_state: ElementState::Released,
|
2018-01-26 16:28:43 -05:00
|
|
|
middle_button_state: ElementState::Released,
|
|
|
|
right_button_state: ElementState::Released,
|
2017-01-14 20:53:48 -05:00
|
|
|
click_state: ClickState::None,
|
2016-12-26 18:33:27 -05:00
|
|
|
scroll_px: 0,
|
|
|
|
line: Line(0),
|
|
|
|
column: Column(0),
|
|
|
|
cell_side: Side::Left,
|
2017-09-02 15:29:03 -04:00
|
|
|
lines_scrolled: 0.0,
|
2016-12-26 18:33:27 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-01 13:24:20 -04:00
|
|
|
/// The event processor
|
2016-12-26 18:33:27 -05:00
|
|
|
///
|
|
|
|
/// Stores some state from received events and dispatches actions when they are
|
|
|
|
/// triggered.
|
2016-09-24 19:11:50 -04:00
|
|
|
pub struct Processor<N> {
|
2016-12-26 18:33:27 -05:00
|
|
|
key_bindings: Vec<KeyBinding>,
|
|
|
|
mouse_bindings: Vec<MouseBinding>,
|
2017-01-14 20:53:48 -05:00
|
|
|
mouse_config: config::Mouse,
|
2017-01-08 16:09:02 -05:00
|
|
|
print_events: bool,
|
2017-02-03 18:34:52 -05:00
|
|
|
wait_for_event: bool,
|
2016-09-24 19:11:50 -04:00
|
|
|
notifier: N,
|
2016-12-26 18:33:27 -05:00
|
|
|
mouse: Mouse,
|
2016-09-01 13:24:20 -04:00
|
|
|
resize_tx: mpsc::Sender<(u32, u32)>,
|
2016-11-19 19:16:20 -05:00
|
|
|
ref_test: bool,
|
2016-12-26 18:33:27 -05:00
|
|
|
size_info: SizeInfo,
|
2017-06-16 00:43:28 -04:00
|
|
|
pub selection: Option<Selection>,
|
2017-02-22 14:52:37 -05:00
|
|
|
hide_cursor_when_typing: bool,
|
|
|
|
hide_cursor: bool,
|
2017-07-20 13:50:50 -04:00
|
|
|
received_count: usize,
|
|
|
|
suppress_chars: bool,
|
|
|
|
last_modifiers: ModifiersState,
|
|
|
|
pending_events: Vec<Event>,
|
2016-09-01 13:24:20 -04:00
|
|
|
}
|
|
|
|
|
2016-12-12 12:31:48 -05:00
|
|
|
/// Notify that the terminal was resized
|
|
|
|
///
|
|
|
|
/// Currently this just forwards the notice to the input processor.
|
|
|
|
impl<N> OnResize for Processor<N> {
|
|
|
|
fn on_resize(&mut self, size: &SizeInfo) {
|
2016-12-26 18:33:27 -05:00
|
|
|
self.size_info = size.to_owned();
|
2017-08-21 13:59:45 -04:00
|
|
|
self.selection = None;
|
2016-12-12 12:31:48 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-26 18:33:27 -05:00
|
|
|
impl<N: Notify> Processor<N> {
|
2016-09-01 13:24:20 -04:00
|
|
|
/// Create a new event processor
|
|
|
|
///
|
|
|
|
/// Takes a writer which is expected to be hooked up to the write end of a
|
|
|
|
/// pty.
|
2016-09-24 19:11:50 -04:00
|
|
|
pub fn new(
|
|
|
|
notifier: N,
|
2016-11-15 12:38:50 -05:00
|
|
|
resize_tx: mpsc::Sender<(u32, u32)>,
|
2017-01-08 16:09:02 -05:00
|
|
|
options: &Options,
|
2016-11-15 12:38:50 -05:00
|
|
|
config: &Config,
|
2016-11-19 19:16:20 -05:00
|
|
|
ref_test: bool,
|
2016-12-29 15:30:30 -05:00
|
|
|
size_info: SizeInfo,
|
2016-09-24 19:11:50 -04:00
|
|
|
) -> Processor<N> {
|
2016-09-01 13:24:20 -04:00
|
|
|
Processor {
|
2016-12-26 18:33:27 -05:00
|
|
|
key_bindings: config.key_bindings().to_vec(),
|
|
|
|
mouse_bindings: config.mouse_bindings().to_vec(),
|
2017-01-14 20:53:48 -05:00
|
|
|
mouse_config: config.mouse().to_owned(),
|
2017-01-08 16:09:02 -05:00
|
|
|
print_events: options.print_events,
|
2017-02-03 18:34:52 -05:00
|
|
|
wait_for_event: true,
|
2018-03-04 17:40:15 -05:00
|
|
|
notifier,
|
|
|
|
resize_tx,
|
|
|
|
ref_test,
|
2016-12-26 18:33:27 -05:00
|
|
|
mouse: Default::default(),
|
2017-06-16 00:43:28 -04:00
|
|
|
selection: None,
|
2018-03-04 17:40:15 -05:00
|
|
|
size_info,
|
2017-02-22 14:52:37 -05:00
|
|
|
hide_cursor_when_typing: config.hide_cursor_when_typing(),
|
|
|
|
hide_cursor: false,
|
2017-07-20 13:50:50 -04:00
|
|
|
received_count: 0,
|
|
|
|
suppress_chars: false,
|
|
|
|
last_modifiers: Default::default(),
|
|
|
|
pending_events: Vec::with_capacity(4),
|
2016-09-01 13:24:20 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-26 18:33:27 -05:00
|
|
|
/// Handle events from glutin
|
|
|
|
///
|
|
|
|
/// Doesn't take self mutably due to borrow checking. Kinda uggo but w/e.
|
|
|
|
fn handle_event<'a>(
|
2017-02-02 01:13:08 -05:00
|
|
|
processor: &mut input::Processor<'a, ActionContext<'a, N>>,
|
2017-07-20 13:50:50 -04:00
|
|
|
event: Event,
|
2016-12-26 18:33:27 -05:00
|
|
|
ref_test: bool,
|
|
|
|
resize_tx: &mpsc::Sender<(u32, u32)>,
|
2017-02-22 14:52:37 -05:00
|
|
|
hide_cursor: &mut bool,
|
2017-10-21 19:03:58 -04:00
|
|
|
window_is_focused: &mut bool,
|
2016-12-26 18:33:27 -05:00
|
|
|
) {
|
2016-09-01 13:24:20 -04:00
|
|
|
match event {
|
2017-07-20 13:50:50 -04:00
|
|
|
// Pass on device events
|
2018-01-05 20:42:55 -05:00
|
|
|
Event::DeviceEvent { .. } | Event::Suspended { .. } => (),
|
2017-07-20 13:50:50 -04:00
|
|
|
Event::WindowEvent { event, .. } => {
|
|
|
|
use glutin::WindowEvent::*;
|
|
|
|
match event {
|
2018-05-14 23:21:06 -04:00
|
|
|
CloseRequested => {
|
2017-07-20 13:50:50 -04:00
|
|
|
if ref_test {
|
|
|
|
// dump grid state
|
|
|
|
let grid = processor.ctx.terminal.grid();
|
|
|
|
|
|
|
|
let serialized_grid = json::to_string(&grid)
|
|
|
|
.expect("serialize grid");
|
|
|
|
|
|
|
|
let serialized_size = json::to_string(processor.ctx.terminal.size_info())
|
|
|
|
.expect("serialize size");
|
|
|
|
|
|
|
|
File::create("./grid.json")
|
|
|
|
.and_then(|mut f| f.write_all(serialized_grid.as_bytes()))
|
|
|
|
.expect("write grid.json");
|
|
|
|
|
|
|
|
File::create("./size.json")
|
|
|
|
.and_then(|mut f| f.write_all(serialized_size.as_bytes()))
|
|
|
|
.expect("write size.json");
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME should do a more graceful shutdown
|
|
|
|
::std::process::exit(0);
|
|
|
|
},
|
|
|
|
Resized(w, h) => {
|
|
|
|
resize_tx.send((w, h)).expect("send new size");
|
|
|
|
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 {
|
|
|
|
// Hide cursor while typing
|
|
|
|
*hide_cursor = true;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
ReceivedCharacter(c) => {
|
|
|
|
processor.received_char(c);
|
|
|
|
},
|
2017-12-28 15:36:30 -05:00
|
|
|
MouseInput { state, button, modifiers, .. } => {
|
2017-07-20 13:50:50 -04:00
|
|
|
*hide_cursor = false;
|
2018-01-03 11:52:49 -05:00
|
|
|
processor.mouse_input(state, button, modifiers);
|
2017-07-20 13:50:50 -04:00
|
|
|
processor.ctx.terminal.dirty = true;
|
|
|
|
},
|
2017-12-28 15:36:30 -05:00
|
|
|
CursorMoved { position: (x, y), modifiers, .. } => {
|
2017-07-20 13:50:50 -04:00
|
|
|
let x = x as i32;
|
|
|
|
let y = y as i32;
|
|
|
|
let x = limit(x, 0, processor.ctx.size_info.width as i32);
|
|
|
|
let y = limit(y, 0, processor.ctx.size_info.height as i32);
|
|
|
|
|
|
|
|
*hide_cursor = false;
|
2018-01-03 11:55:39 -05:00
|
|
|
processor.mouse_moved(x as u32, y as u32, modifiers);
|
2017-07-20 13:50:50 -04:00
|
|
|
|
|
|
|
if !processor.ctx.selection.is_none() {
|
|
|
|
processor.ctx.terminal.dirty = true;
|
|
|
|
}
|
|
|
|
},
|
2018-03-08 16:50:04 -05:00
|
|
|
MouseWheel { delta, phase, modifiers, .. } => {
|
2017-07-20 13:50:50 -04:00
|
|
|
*hide_cursor = false;
|
2018-03-08 16:50:04 -05:00
|
|
|
processor.on_mouse_wheel(delta, phase, modifiers);
|
2017-07-20 13:50:50 -04:00
|
|
|
},
|
|
|
|
Refresh => {
|
|
|
|
processor.ctx.terminal.dirty = true;
|
|
|
|
},
|
|
|
|
Focused(is_focused) => {
|
2017-10-21 19:03:58 -04:00
|
|
|
*window_is_focused = is_focused;
|
|
|
|
|
2017-07-20 13:50:50 -04:00
|
|
|
if is_focused {
|
|
|
|
processor.ctx.terminal.dirty = true;
|
2017-10-21 19:03:58 -04:00
|
|
|
processor.ctx.terminal.next_is_urgent = Some(false);
|
2017-07-20 13:50:50 -04:00
|
|
|
} else {
|
2017-12-09 18:33:58 -05:00
|
|
|
processor.ctx.terminal.dirty = true;
|
2017-07-20 13:50:50 -04:00
|
|
|
*hide_cursor = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
processor.on_focus_change(is_focused);
|
2018-05-11 11:31:06 -04:00
|
|
|
},
|
|
|
|
DroppedFile(path) => {
|
|
|
|
use input::ActionContext;
|
|
|
|
let path: String = path.to_string_lossy().into();
|
|
|
|
processor.ctx.write_to_pty(path.into_bytes());
|
2017-07-20 13:50:50 -04:00
|
|
|
}
|
|
|
|
_ => (),
|
2017-02-22 15:59:01 -05:00
|
|
|
}
|
2016-11-23 23:25:37 -05:00
|
|
|
},
|
2017-07-20 13:50:50 -04:00
|
|
|
Event::Awakened => {
|
2016-12-29 21:38:22 -05:00
|
|
|
processor.ctx.terminal.dirty = true;
|
2017-05-29 12:51:49 -04:00
|
|
|
}
|
2016-09-01 13:24:20 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-03 18:34:52 -05:00
|
|
|
/// Process events. When `wait_for_event` is set, this method is guaranteed
|
|
|
|
/// to process at least one event.
|
2016-12-29 15:30:30 -05:00
|
|
|
pub fn process_events<'a>(
|
|
|
|
&mut self,
|
|
|
|
term: &'a FairMutex<Term>,
|
2017-02-22 15:46:08 -05:00
|
|
|
window: &mut Window
|
2016-12-29 21:38:22 -05:00
|
|
|
) -> MutexGuard<'a, Term> {
|
2016-12-29 15:30:30 -05:00
|
|
|
// Terminal is lazily initialized the first time an event is returned
|
|
|
|
// from the blocking WaitEventsIterator. Otherwise, the pty reader would
|
|
|
|
// be blocked the entire time we wait for input!
|
2016-12-29 21:38:22 -05:00
|
|
|
let mut terminal;
|
2016-12-29 15:30:30 -05:00
|
|
|
|
2017-07-20 13:50:50 -04:00
|
|
|
self.pending_events.clear();
|
|
|
|
|
2016-12-29 15:30:30 -05:00
|
|
|
{
|
|
|
|
// Ditto on lazy initialization for context and processor.
|
|
|
|
let context;
|
2017-02-02 01:13:08 -05:00
|
|
|
let mut processor: input::Processor<ActionContext<N>>;
|
2016-12-29 15:30:30 -05:00
|
|
|
|
2017-07-20 13:50:50 -04:00
|
|
|
let print_events = self.print_events;
|
2016-12-26 18:33:27 -05:00
|
|
|
|
2017-07-20 13:50:50 -04:00
|
|
|
let ref_test = self.ref_test;
|
|
|
|
let resize_tx = &self.resize_tx;
|
|
|
|
|
|
|
|
if self.wait_for_event {
|
|
|
|
// A Vec is used here since wait_events can potentially yield
|
|
|
|
// multiple events before the interrupt is handled. For example,
|
|
|
|
// Resize and Moved events.
|
|
|
|
let pending_events = &mut self.pending_events;
|
|
|
|
window.wait_events(|e| {
|
|
|
|
pending_events.push(e);
|
|
|
|
glutin::ControlFlow::Break
|
|
|
|
});
|
|
|
|
}
|
2017-02-03 18:34:52 -05:00
|
|
|
|
|
|
|
terminal = term.lock();
|
|
|
|
|
|
|
|
context = ActionContext {
|
|
|
|
terminal: &mut terminal,
|
|
|
|
notifier: &mut self.notifier,
|
|
|
|
selection: &mut self.selection,
|
|
|
|
mouse: &mut self.mouse,
|
|
|
|
size_info: &self.size_info,
|
2017-06-16 15:56:55 -04:00
|
|
|
selection_modified: false,
|
2017-07-20 13:50:50 -04:00
|
|
|
received_count: &mut self.received_count,
|
|
|
|
suppress_chars: &mut self.suppress_chars,
|
|
|
|
last_modifiers: &mut self.last_modifiers,
|
2017-02-03 18:34:52 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
processor = input::Processor {
|
|
|
|
ctx: context,
|
|
|
|
mouse_config: &self.mouse_config,
|
|
|
|
key_bindings: &self.key_bindings[..],
|
2017-07-20 13:50:50 -04:00
|
|
|
mouse_bindings: &self.mouse_bindings[..],
|
2017-02-03 18:34:52 -05:00
|
|
|
};
|
|
|
|
|
2017-10-21 19:03:58 -04:00
|
|
|
let mut window_is_focused = window.is_focused;
|
|
|
|
|
2017-07-20 13:50:50 -04:00
|
|
|
// Scope needed to that hide_cursor isn't borrowed after the scope
|
|
|
|
// ends.
|
|
|
|
{
|
|
|
|
let hide_cursor = &mut self.hide_cursor;
|
|
|
|
let mut process = |event| {
|
|
|
|
if print_events {
|
|
|
|
println!("glutin event: {:?}", event);
|
|
|
|
}
|
|
|
|
Processor::handle_event(
|
|
|
|
&mut processor,
|
|
|
|
event,
|
|
|
|
ref_test,
|
|
|
|
resize_tx,
|
|
|
|
hide_cursor,
|
2017-10-21 19:03:58 -04:00
|
|
|
&mut window_is_focused,
|
2017-07-20 13:50:50 -04:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
for event in self.pending_events.drain(..) {
|
|
|
|
process(event);
|
|
|
|
}
|
2016-12-26 18:33:27 -05:00
|
|
|
|
2017-07-20 13:50:50 -04:00
|
|
|
window.poll_events(process);
|
2016-12-29 15:30:30 -05:00
|
|
|
}
|
2017-02-22 14:52:37 -05:00
|
|
|
|
|
|
|
if self.hide_cursor_when_typing {
|
|
|
|
window.set_cursor_visible(!self.hide_cursor);
|
|
|
|
}
|
2017-06-16 15:56:55 -04:00
|
|
|
|
2017-10-21 19:03:58 -04:00
|
|
|
window.is_focused = window_is_focused;
|
|
|
|
|
2017-06-16 15:56:55 -04:00
|
|
|
if processor.ctx.selection_modified {
|
|
|
|
processor.ctx.terminal.dirty = true;
|
|
|
|
}
|
2016-09-01 13:24:20 -04:00
|
|
|
}
|
2016-12-11 02:32:12 -05:00
|
|
|
|
2017-02-03 18:34:52 -05:00
|
|
|
self.wait_for_event = !terminal.dirty;
|
|
|
|
|
2016-12-29 21:38:22 -05:00
|
|
|
terminal
|
2016-09-01 13:24:20 -04:00
|
|
|
}
|
2016-11-15 12:38:50 -05:00
|
|
|
|
|
|
|
pub fn update_config(&mut self, config: &Config) {
|
2016-12-26 18:33:27 -05:00
|
|
|
self.key_bindings = config.key_bindings().to_vec();
|
|
|
|
self.mouse_bindings = config.mouse_bindings().to_vec();
|
2017-01-14 20:53:48 -05:00
|
|
|
self.mouse_config = config.mouse().to_owned();
|
2016-11-15 12:38:50 -05:00
|
|
|
}
|
2016-09-01 13:24:20 -04:00
|
|
|
}
|