diff options
author | Kirill Chibisov <contact@kchibisov.com> | 2022-07-01 11:40:27 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-01 11:40:27 +0300 |
commit | ebc6922eaae28173532235222f9790c8ab3fdaa7 (patch) | |
tree | 7f3e50f0dddb3fb74d3969d46b90e3dd8e207f54 | |
parent | 28e3fc7c64a7f375ad843145a0a8f78e31bff05e (diff) | |
download | alacritty-ebc6922eaae28173532235222f9790c8ab3fdaa7.tar.gz alacritty-ebc6922eaae28173532235222f9790c8ab3fdaa7.zip |
Add `cursor.blink_timeout` config option
This option should prevent extensive power usage due to cursor blinking
when there's no user activity being performed.
Fixes #5992.
-rw-r--r-- | CHANGELOG.md | 2 | ||||
-rw-r--r-- | alacritty.yml | 5 | ||||
-rw-r--r-- | alacritty/src/event.rs | 59 | ||||
-rw-r--r-- | alacritty/src/scheduler.rs | 1 | ||||
-rw-r--r-- | alacritty/src/window_context.rs | 3 | ||||
-rw-r--r-- | alacritty_terminal/src/config/mod.rs | 18 |
6 files changed, 75 insertions, 13 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 8591416e..6c8816d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,12 +21,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Escape sequence to reset underline color (`CSI 59 m`) - Vi mode keybinding (z) to center view around vi mode cursor - Accept hexadecimal values starting with `0x` for `--embed` +- Config option `cursor.blink_timeout` to timeout cursor blinking after inactivity ### Changed - The `--help` output was reworked with a new colorful syntax - OSC 52 is now disabled on unfocused windows - `SpawnNewInstance` no longer inherits initial `--command` +- Blinking cursor will timeout after `5` seconds by default ### Fixed diff --git a/alacritty.yml b/alacritty.yml index 3ba6a7f5..511a10d6 100644 --- a/alacritty.yml +++ b/alacritty.yml @@ -412,6 +412,11 @@ # Cursor blinking interval in milliseconds. #blink_interval: 750 + # Time after which cursor stops blinking, in seconds. + # + # Specifying '0' will disable timeout for blinking. + #blink_timeout: 5 + # If this is `true`, the cursor will be rendered as a hollow box when the # window is not focused. #unfocused_hollow: true diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index 2955ab8c..f91ef962 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -90,6 +90,7 @@ pub enum EventType { Scroll(Scroll), CreateWindow(WindowOptions), BlinkCursor, + BlinkCursorTimeout, SearchNext, } @@ -180,6 +181,7 @@ pub struct ActionContext<'a, N, T> { pub display: &'a mut Display, pub message_buffer: &'a mut MessageBuffer, pub config: &'a mut UiConfig, + pub cursor_blink_timed_out: &'a mut bool, pub event_loop: &'a EventLoopWindowTarget<Event>, pub event_proxy: &'a EventLoopProxy<Event>, pub scheduler: &'a mut Scheduler, @@ -647,14 +649,15 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon fn on_typing_start(&mut self) { // Disable cursor blinking. let timer_id = TimerId::new(Topic::BlinkCursor, self.display.window.id()); - if let Some(timer) = self.scheduler.unschedule(timer_id) { - let interval = - Duration::from_millis(self.config.terminal_config.cursor.blink_interval()); - self.scheduler.schedule(timer.event, interval, true, timer.id); + if self.scheduler.unschedule(timer_id).is_some() { + self.schedule_blinking(); self.display.cursor_hidden = false; - *self.dirty = true; + } else if *self.cursor_blink_timed_out { + self.update_cursor_blinking(); } + *self.dirty = true; + // Hide mouse cursor. if self.config.mouse.hide_when_typing { self.display.window.set_mouse_visible(false); @@ -945,18 +948,44 @@ impl<'a, N: Notify + 'a, T: EventListener> ActionContext<'a, N, T> { blinking &= vi_mode || self.terminal().mode().contains(TermMode::SHOW_CURSOR); // Update cursor blinking state. - let timer_id = TimerId::new(Topic::BlinkCursor, self.display.window.id()); - self.scheduler.unschedule(timer_id); + let window_id = self.display.window.id(); + self.scheduler.unschedule(TimerId::new(Topic::BlinkCursor, window_id)); + self.scheduler.unschedule(TimerId::new(Topic::BlinkTimeout, window_id)); + + // Reset blinkinig timeout. + *self.cursor_blink_timed_out = false; + if blinking && self.terminal.is_focused { - let event = Event::new(EventType::BlinkCursor, self.display.window.id()); - let interval = - Duration::from_millis(self.config.terminal_config.cursor.blink_interval()); - self.scheduler.schedule(event, interval, true, timer_id); + self.schedule_blinking(); + self.schedule_blinking_timeout(); } else { self.display.cursor_hidden = false; *self.dirty = true; } } + + fn schedule_blinking(&mut self) { + let window_id = self.display.window.id(); + let timer_id = TimerId::new(Topic::BlinkCursor, window_id); + let event = Event::new(EventType::BlinkCursor, window_id); + let blinking_interval = + Duration::from_millis(self.config.terminal_config.cursor.blink_interval()); + self.scheduler.schedule(event, blinking_interval, true, timer_id); + } + + fn schedule_blinking_timeout(&mut self) { + let blinking_timeout = self.config.terminal_config.cursor.blink_timeout(); + if blinking_timeout == 0 { + return; + } + + let window_id = self.display.window.id(); + let blinking_timeout_interval = Duration::from_secs(blinking_timeout); + let event = Event::new(EventType::BlinkCursorTimeout, window_id); + let timer_id = TimerId::new(Topic::BlinkTimeout, window_id); + + self.scheduler.schedule(event, blinking_timeout_interval, false, timer_id); + } } #[derive(Debug, Eq, PartialEq)] @@ -1048,6 +1077,14 @@ impl input::Processor<EventProxy, ActionContext<'_, Notifier, EventProxy>> { self.ctx.display.cursor_hidden ^= true; *self.ctx.dirty = true; }, + EventType::BlinkCursorTimeout => { + // Disable blinking after timeout reached. + let timer_id = TimerId::new(Topic::BlinkCursor, self.ctx.display.window.id()); + self.ctx.scheduler.unschedule(timer_id); + self.ctx.display.cursor_hidden = false; + *self.ctx.cursor_blink_timed_out = true; + *self.ctx.dirty = true; + }, EventType::Message(message) => { self.ctx.message_buffer.push(message); self.ctx.display.pending_update.dirty = true; diff --git a/alacritty/src/scheduler.rs b/alacritty/src/scheduler.rs index 924f5904..08388b94 100644 --- a/alacritty/src/scheduler.rs +++ b/alacritty/src/scheduler.rs @@ -27,6 +27,7 @@ pub enum Topic { SelectionScrolling, DelayedSearch, BlinkCursor, + BlinkTimeout, } /// Event scheduled to be emitted at a specific time. diff --git a/alacritty/src/window_context.rs b/alacritty/src/window_context.rs index f04a8e04..a45b9404 100644 --- a/alacritty/src/window_context.rs +++ b/alacritty/src/window_context.rs @@ -43,6 +43,7 @@ pub struct WindowContext { pub display: Display, event_queue: Vec<GlutinEvent<'static, Event>>, terminal: Arc<FairMutex<Term<EventProxy>>>, + cursor_blink_timed_out: bool, modifiers: ModifiersState, search_state: SearchState, received_count: usize, @@ -151,6 +152,7 @@ impl WindowContext { master_fd, #[cfg(not(windows))] shell_pid, + cursor_blink_timed_out: Default::default(), suppress_chars: Default::default(), message_buffer: Default::default(), received_count: Default::default(), @@ -267,6 +269,7 @@ impl WindowContext { let old_is_searching = self.search_state.history_index.is_some(); let context = ActionContext { + cursor_blink_timed_out: &mut self.cursor_blink_timed_out, message_buffer: &mut self.message_buffer, received_count: &mut self.received_count, suppress_chars: &mut self.suppress_chars, diff --git a/alacritty_terminal/src/config/mod.rs b/alacritty_terminal/src/config/mod.rs index 40c42d4f..5822d591 100644 --- a/alacritty_terminal/src/config/mod.rs +++ b/alacritty_terminal/src/config/mod.rs @@ -1,4 +1,4 @@ -use std::cmp::max; +use std::cmp; use std::collections::HashMap; use std::path::PathBuf; @@ -13,6 +13,7 @@ use crate::ansi::{CursorShape, CursorStyle}; pub use crate::config::scrolling::{Scrolling, MAX_SCROLLBACK_LINES}; pub const LOG_TARGET_CONFIG: &str = "alacritty_config_derive"; + const MIN_BLINK_INTERVAL: u64 = 10; /// Top-level config type. @@ -75,6 +76,7 @@ pub struct Cursor { thickness: Percentage, blink_interval: u64, + blink_timeout: u8, } impl Default for Cursor { @@ -83,6 +85,7 @@ impl Default for Cursor { thickness: Percentage(0.15), unfocused_hollow: true, blink_interval: 750, + blink_timeout: 5, style: Default::default(), vi_mode_style: Default::default(), } @@ -107,7 +110,18 @@ impl Cursor { #[inline] pub fn blink_interval(self) -> u64 { - max(self.blink_interval, MIN_BLINK_INTERVAL) + cmp::max(self.blink_interval, MIN_BLINK_INTERVAL) + } + + #[inline] + pub fn blink_timeout(self) -> u64 { + const MILLIS_IN_SECOND: u64 = 1000; + match self.blink_timeout { + 0 => 0, + blink_timeout => { + cmp::max(self.blink_interval * 5 / MILLIS_IN_SECOND, blink_timeout as u64) + }, + } } } |