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.
This commit is contained in:
parent
28e3fc7c64
commit
ebc6922eaa
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -27,6 +27,7 @@ pub enum Topic {
|
|||
SelectionScrolling,
|
||||
DelayedSearch,
|
||||
BlinkCursor,
|
||||
BlinkTimeout,
|
||||
}
|
||||
|
||||
/// Event scheduled to be emitted at a specific time.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue