aboutsummaryrefslogtreecommitdiff
path: root/alacritty/src/event.rs
diff options
context:
space:
mode:
authorChristian Duerr <contact@christianduerr.com>2020-06-18 01:02:56 +0000
committerGitHub <noreply@github.com>2020-06-18 01:02:56 +0000
commit87e5b1aa25ea61937fa5f79668d2a46e88707c5e (patch)
tree59205d2e00072a5f8737dc104f57fc940db0c2ec /alacritty/src/event.rs
parentd526649ee67237a1bedad8228f1f017035ddad3f (diff)
downloadr-alacritty-87e5b1aa25ea61937fa5f79668d2a46e88707c5e.tar.gz
r-alacritty-87e5b1aa25ea61937fa5f79668d2a46e88707c5e.tar.bz2
r-alacritty-87e5b1aa25ea61937fa5f79668d2a46e88707c5e.zip
Add automatic scrolling during selection
This adds a new `Scheduler` which allows for staging events to be processed at a later time. If there is a selection active and the mouse is above or below the window, the viewport will now scroll torwards the direction of the mouse. The amount of lines scrolled depends on the distance of the mouse to the boundaries used for selection scrolling. To make it possible to scroll while in fullscreen, the selection scrolling area includes the padding of the window and is at least 5 pixels high in case there is not enough padding present.
Diffstat (limited to 'alacritty/src/event.rs')
-rw-r--r--alacritty/src/event.rs132
1 files changed, 85 insertions, 47 deletions
diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs
index 4e2a0578..084ebe1e 100644
--- a/alacritty/src/event.rs
+++ b/alacritty/src/event.rs
@@ -30,7 +30,7 @@ use font::{self, Size};
use alacritty_terminal::config::Font;
use alacritty_terminal::config::LOG_TARGET_CONFIG;
use alacritty_terminal::event::OnResize;
-use alacritty_terminal::event::{Event, EventListener, Notify};
+use alacritty_terminal::event::{Event as TerminalEvent, EventListener, Notify};
use alacritty_terminal::grid::Scroll;
use alacritty_terminal::index::{Column, Line, Point, Side};
use alacritty_terminal::message_bar::{Message, MessageBuffer};
@@ -40,7 +40,7 @@ use alacritty_terminal::term::cell::Cell;
use alacritty_terminal::term::{ClipboardType, SizeInfo, Term, TermMode};
#[cfg(not(windows))]
use alacritty_terminal::tty;
-use alacritty_terminal::util::{limit, start_daemon};
+use alacritty_terminal::util::start_daemon;
use crate::cli::Options;
use crate::clipboard::Clipboard;
@@ -48,9 +48,32 @@ use crate::config;
use crate::config::Config;
use crate::display::Display;
use crate::input::{self, ActionContext as _, FONT_SIZE_STEP};
+use crate::scheduler::Scheduler;
use crate::url::{Url, Urls};
use crate::window::Window;
+/// Events dispatched through the UI event loop.
+#[derive(Debug, Clone)]
+pub enum Event {
+ TerminalEvent(TerminalEvent),
+ DPRChanged(f64, (u32, u32)),
+ Scroll(Scroll),
+ ConfigReload(PathBuf),
+ Message(Message),
+}
+
+impl From<Event> for GlutinEvent<'_, Event> {
+ fn from(event: Event) -> Self {
+ GlutinEvent::UserEvent(event)
+ }
+}
+
+impl From<TerminalEvent> for Event {
+ fn from(event: TerminalEvent) -> Self {
+ Event::TerminalEvent(event)
+ }
+}
+
#[derive(Default, Clone, Debug, PartialEq)]
pub struct DisplayUpdate {
pub dimensions: Option<PhysicalSize<u32>>,
@@ -80,6 +103,7 @@ pub struct ActionContext<'a, N, T> {
pub config: &'a mut Config,
pub event_loop: &'a EventLoopWindowTarget<Event>,
pub urls: &'a Urls,
+ pub scheduler: &'a mut Scheduler,
font_size: &'a mut Size,
}
@@ -248,6 +272,25 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon
}
}
+ /// Spawn URL launcher when clicking on URLs.
+ fn launch_url(&self, url: Url) {
+ if self.mouse.block_url_launcher {
+ return;
+ }
+
+ if let Some(ref launcher) = self.config.ui_config.mouse.url.launcher {
+ let mut args = launcher.args().to_vec();
+ let start = self.terminal.visible_to_buffer(url.start());
+ let end = self.terminal.visible_to_buffer(url.end());
+ args.push(self.terminal.bounds_to_string(start, end));
+
+ match start_daemon(launcher.program(), &args) {
+ Ok(_) => debug!("Launched {} with args {:?}", launcher.program(), args),
+ Err(_) => warn!("Unable to launch {} with args {:?}", launcher.program(), args),
+ }
+ }
+ }
+
fn change_font_size(&mut self, delta: f32) {
*self.font_size = max(*self.font_size + delta, Size::new(FONT_SIZE_STEP));
let font = self.config.font.clone().with_size(*self.font_size);
@@ -282,27 +325,12 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon
self.urls
}
- fn clipboard(&mut self) -> &mut Clipboard {
+ fn clipboard_mut(&mut self) -> &mut Clipboard {
self.clipboard
}
- /// Spawn URL launcher when clicking on URLs.
- fn launch_url(&self, url: Url) {
- if self.mouse.block_url_launcher {
- return;
- }
-
- if let Some(ref launcher) = self.config.ui_config.mouse.url.launcher {
- let mut args = launcher.args().to_vec();
- let start = self.terminal.visible_to_buffer(url.start());
- let end = self.terminal.visible_to_buffer(url.end());
- args.push(self.terminal.bounds_to_string(start, end));
-
- match start_daemon(launcher.program(), &args) {
- Ok(_) => debug!("Launched {} with args {:?}", launcher.program(), args),
- Err(_) => warn!("Unable to launch {} with args {:?}", launcher.program(), args),
- }
- }
+ fn scheduler_mut(&mut self) -> &mut Scheduler {
+ self.scheduler
}
}
@@ -369,7 +397,7 @@ pub struct Processor<N> {
message_buffer: MessageBuffer,
display: Display,
font_size: Size,
- event_queue: Vec<GlutinEvent<'static, alacritty_terminal::event::Event>>,
+ event_queue: Vec<GlutinEvent<'static, Event>>,
}
impl<N: Notify + OnResize> Processor<N> {
@@ -432,6 +460,8 @@ impl<N: Notify + OnResize> Processor<N> {
where
T: EventListener,
{
+ let mut scheduler = Scheduler::new();
+
event_loop.run_return(|event, event_loop, control_flow| {
if self.config.debug.print_events {
info!("glutin event: {:?}", event);
@@ -444,13 +474,16 @@ impl<N: Notify + OnResize> Processor<N> {
match event {
// Check for shutdown.
- GlutinEvent::UserEvent(Event::Exit) => {
+ GlutinEvent::UserEvent(Event::TerminalEvent(TerminalEvent::Exit)) => {
*control_flow = ControlFlow::Exit;
return;
},
// Process events.
GlutinEvent::RedrawEventsCleared => {
- *control_flow = ControlFlow::Wait;
+ *control_flow = match scheduler.update(&mut self.event_queue) {
+ Some(instant) => ControlFlow::WaitUntil(instant),
+ None => ControlFlow::Wait,
+ };
if self.event_queue_empty() {
return;
@@ -463,8 +496,7 @@ impl<N: Notify + OnResize> Processor<N> {
} => {
*control_flow = ControlFlow::Poll;
let size = (new_inner_size.width, new_inner_size.height);
- let event = GlutinEvent::UserEvent(Event::DPRChanged(scale_factor, size));
- self.event_queue.push(event);
+ self.event_queue.push(Event::DPRChanged(scale_factor, size).into());
return;
},
// Transmute to extend lifetime, which exists only for `ScaleFactorChanged` event.
@@ -495,6 +527,7 @@ impl<N: Notify + OnResize> Processor<N> {
font_size: &mut self.font_size,
config: &mut self.config,
urls: &self.display.urls,
+ scheduler: &mut scheduler,
event_loop,
};
let mut processor = input::Processor::new(context, &self.display.highlighted_url);
@@ -529,7 +562,8 @@ impl<N: Notify + OnResize> Processor<N> {
// Request immediate re-draw if visual bell animation is not finished yet.
if !terminal.visual_bell.completed() {
- self.event_queue.push(GlutinEvent::UserEvent(Event::Wakeup));
+ let event: Event = TerminalEvent::Wakeup.into();
+ self.event_queue.push(event.into());
}
// Redraw screen.
@@ -571,26 +605,29 @@ impl<N: Notify + OnResize> Processor<N> {
processor.ctx.size_info.dpr = scale_factor;
processor.ctx.terminal.dirty = true;
},
- Event::Title(title) => processor.ctx.window.set_title(&title),
- Event::Wakeup => processor.ctx.terminal.dirty = true,
- Event::Urgent => {
- processor.ctx.window.set_urgent(!processor.ctx.terminal.is_focused)
- },
- Event::ConfigReload(path) => Self::reload_config(&path, processor),
Event::Message(message) => {
processor.ctx.message_buffer.push(message);
processor.ctx.display_update_pending.message_buffer = true;
processor.ctx.terminal.dirty = true;
},
- Event::ClipboardStore(clipboard_type, content) => {
- processor.ctx.clipboard.store(clipboard_type, content);
- },
- Event::ClipboardLoad(clipboard_type, format) => {
- let text = format(processor.ctx.clipboard.load(clipboard_type).as_str());
- processor.ctx.write_to_pty(text.into_bytes());
+ Event::ConfigReload(path) => Self::reload_config(&path, processor),
+ Event::Scroll(scroll) => processor.ctx.scroll(scroll),
+ Event::TerminalEvent(event) => match event {
+ TerminalEvent::Title(title) => processor.ctx.window.set_title(&title),
+ TerminalEvent::Wakeup => processor.ctx.terminal.dirty = true,
+ TerminalEvent::Urgent => {
+ processor.ctx.window.set_urgent(!processor.ctx.terminal.is_focused)
+ },
+ TerminalEvent::ClipboardStore(clipboard_type, content) => {
+ processor.ctx.clipboard.store(clipboard_type, content);
+ },
+ TerminalEvent::ClipboardLoad(clipboard_type, format) => {
+ let text = format(processor.ctx.clipboard.load(clipboard_type).as_str());
+ processor.ctx.write_to_pty(text.into_bytes());
+ },
+ TerminalEvent::MouseCursorDirty => processor.reset_mouse_cursor(),
+ TerminalEvent::Exit => (),
},
- Event::MouseCursorDirty => processor.reset_mouse_cursor(),
- Event::Exit => (),
},
GlutinEvent::RedrawRequested(_) => processor.ctx.terminal.dirty = true,
GlutinEvent::WindowEvent { event, window_id, .. } => {
@@ -624,12 +661,8 @@ impl<N: Notify + OnResize> Processor<N> {
processor.modifiers_input(modifiers)
},
WindowEvent::CursorMoved { position, .. } => {
- let (x, y) = position.into();
- let x = limit(x, 0, processor.ctx.size_info.width as i32);
- let y = limit(y, 0, processor.ctx.size_info.height as i32);
-
processor.ctx.window.set_mouse_visible(true);
- processor.mouse_moved(x as usize, y as usize);
+ processor.mouse_moved(position);
},
WindowEvent::MouseWheel { delta, phase, .. } => {
processor.ctx.window.set_mouse_visible(true);
@@ -796,10 +829,15 @@ impl EventProxy {
pub fn new(proxy: EventLoopProxy<Event>) -> Self {
EventProxy(proxy)
}
+
+ /// Send an event to the event loop.
+ pub fn send_event(&self, event: Event) {
+ let _ = self.0.send_event(event);
+ }
}
impl EventListener for EventProxy {
- fn send_event(&self, event: Event) {
- let _ = self.0.send_event(event);
+ fn send_event(&self, event: TerminalEvent) {
+ let _ = self.0.send_event(Event::TerminalEvent(event));
}
}