mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-18 13:55:23 -05:00
Crappy cursor blinking impl
This commit is contained in:
parent
08b5ae52c1
commit
b88f95eab9
6 changed files with 132 additions and 19 deletions
|
@ -36,6 +36,10 @@ dpi:
|
||||||
# Display tabs using this many cells (changes require restart)
|
# Display tabs using this many cells (changes require restart)
|
||||||
tabspaces: 8
|
tabspaces: 8
|
||||||
|
|
||||||
|
# Cursor blinking
|
||||||
|
cursor_blink_interval: 300
|
||||||
|
cursor_blink: true
|
||||||
|
|
||||||
# When true, bold text is drawn using the bright variant of colors.
|
# When true, bold text is drawn using the bright variant of colors.
|
||||||
draw_bold_text_with_bright_colors: true
|
draw_bold_text_with_bright_colors: true
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,10 @@ dpi:
|
||||||
# Display tabs using this many cells (changes require restart)
|
# Display tabs using this many cells (changes require restart)
|
||||||
tabspaces: 8
|
tabspaces: 8
|
||||||
|
|
||||||
|
# Cursor blinking
|
||||||
|
cursor_blink_interval: 300
|
||||||
|
cursor_blink: true
|
||||||
|
|
||||||
# When true, bold text is drawn using the bright variant of colors.
|
# When true, bold text is drawn using the bright variant of colors.
|
||||||
draw_bold_text_with_bright_colors: true
|
draw_bold_text_with_bright_colors: true
|
||||||
|
|
||||||
|
|
|
@ -171,6 +171,7 @@ impl<'a> Shell<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Top-level config type
|
/// Top-level config type
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
@ -202,6 +203,11 @@ pub struct Config {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
custom_cursor_colors: bool,
|
custom_cursor_colors: bool,
|
||||||
|
|
||||||
|
// TODO these should be optional
|
||||||
|
#[serde(deserialize_with="deserialize_duration_ms")]
|
||||||
|
cursor_blink_interval: Duration,
|
||||||
|
cursor_blink: bool,
|
||||||
|
|
||||||
/// Should draw bold text with brighter colors intead of bold font
|
/// Should draw bold text with brighter colors intead of bold font
|
||||||
#[serde(default="true_bool")]
|
#[serde(default="true_bool")]
|
||||||
draw_bold_text_with_bright_colors: bool,
|
draw_bold_text_with_bright_colors: bool,
|
||||||
|
@ -278,6 +284,8 @@ impl Default for Config {
|
||||||
font: Default::default(),
|
font: Default::default(),
|
||||||
render_timer: Default::default(),
|
render_timer: Default::default(),
|
||||||
custom_cursor_colors: false,
|
custom_cursor_colors: false,
|
||||||
|
cursor_blink: true,
|
||||||
|
cursor_blink_interval: Duration::from_millis(300),
|
||||||
colors: Default::default(),
|
colors: Default::default(),
|
||||||
key_bindings: Vec::new(),
|
key_bindings: Vec::new(),
|
||||||
mouse_bindings: Vec::new(),
|
mouse_bindings: Vec::new(),
|
||||||
|
@ -1142,6 +1150,14 @@ impl Config {
|
||||||
|
|
||||||
Ok(contents)
|
Ok(contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cursor_blink_interval(&self) -> Duration {
|
||||||
|
self.cursor_blink_interval
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn blink_enabled(&self) -> bool {
|
||||||
|
self.cursor_blink
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Window Dimensions
|
/// Window Dimensions
|
||||||
|
|
|
@ -7,11 +7,13 @@ use std::os::unix::io::AsRawFd;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use mio::{self, Events, PollOpt, Ready};
|
use mio::{self, Events, PollOpt, Ready};
|
||||||
|
use mio::timer::{self, Timer, Timeout};
|
||||||
use mio::unix::EventedFd;
|
use mio::unix::EventedFd;
|
||||||
|
|
||||||
use ansi;
|
use ansi;
|
||||||
use display;
|
use display;
|
||||||
use event;
|
use event;
|
||||||
|
use config::Config;
|
||||||
use term::Term;
|
use term::Term;
|
||||||
use util::thread;
|
use util::thread;
|
||||||
use sync::FairMutex;
|
use sync::FairMutex;
|
||||||
|
@ -23,7 +25,11 @@ pub enum Msg {
|
||||||
Input(Cow<'static, [u8]>),
|
Input(Cow<'static, [u8]>),
|
||||||
|
|
||||||
/// Indicates that the `EventLoop` should shut down, as Alacritty is shutting down
|
/// Indicates that the `EventLoop` should shut down, as Alacritty is shutting down
|
||||||
Shutdown
|
Shutdown,
|
||||||
|
|
||||||
|
/// Enable or disable blinking events. Passing true will enable them, and
|
||||||
|
/// false will disable them.
|
||||||
|
Blink(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The main event!.. loop.
|
/// The main event!.. loop.
|
||||||
|
@ -35,6 +41,8 @@ pub struct EventLoop<Io> {
|
||||||
pty: Io,
|
pty: Io,
|
||||||
rx: mio::channel::Receiver<Msg>,
|
rx: mio::channel::Receiver<Msg>,
|
||||||
tx: mio::channel::Sender<Msg>,
|
tx: mio::channel::Sender<Msg>,
|
||||||
|
timer: Timer<()>,
|
||||||
|
blink_timeout: Option<Timeout>,
|
||||||
terminal: Arc<FairMutex<Term>>,
|
terminal: Arc<FairMutex<Term>>,
|
||||||
display: display::Notifier,
|
display: display::Notifier,
|
||||||
ref_test: bool,
|
ref_test: bool,
|
||||||
|
@ -171,20 +179,41 @@ const CHANNEL: mio::Token = mio::Token(0);
|
||||||
/// `mio::Token` for the pty file descriptor
|
/// `mio::Token` for the pty file descriptor
|
||||||
const PTY: mio::Token = mio::Token(1);
|
const PTY: mio::Token = mio::Token(1);
|
||||||
|
|
||||||
|
/// `mio::Token` for timers
|
||||||
|
const TIMER: mio::Token = mio::Token(2);
|
||||||
|
|
||||||
impl<Io> EventLoop<Io>
|
impl<Io> EventLoop<Io>
|
||||||
where Io: io::Read + io::Write + Send + AsRawFd + 'static
|
where Io: io::Read + io::Write + Send + AsRawFd + 'static
|
||||||
{
|
{
|
||||||
/// Create a new event loop
|
/// Create a new event loop
|
||||||
pub fn new(
|
pub fn new(
|
||||||
terminal: Arc<FairMutex<Term>>,
|
terminal: Arc<FairMutex<Term>>,
|
||||||
|
config: &Config,
|
||||||
display: display::Notifier,
|
display: display::Notifier,
|
||||||
pty: Io,
|
pty: Io,
|
||||||
ref_test: bool,
|
ref_test: bool,
|
||||||
) -> EventLoop<Io> {
|
) -> EventLoop<Io> {
|
||||||
let (tx, rx) = ::mio::channel::channel();
|
let (tx, rx) = ::mio::channel::channel();
|
||||||
|
let mut timer = timer::Builder::default()
|
||||||
|
.capacity(2)
|
||||||
|
.num_slots(2)
|
||||||
|
.build();
|
||||||
|
let timeout = {
|
||||||
|
let term = terminal.lock();
|
||||||
|
if term.mode().contains(::term::mode::CURSOR_BLINK) {
|
||||||
|
println!("setup blink");
|
||||||
|
let timeout = timer.set_timeout(term.cursor_blink_interval, ()).unwrap();
|
||||||
|
Some(timeout)
|
||||||
|
} else {
|
||||||
|
println!("no setup blink");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
EventLoop {
|
EventLoop {
|
||||||
poll: mio::Poll::new().expect("create mio Poll"),
|
poll: mio::Poll::new().expect("create mio Poll"),
|
||||||
pty: pty,
|
pty: pty,
|
||||||
|
timer: timer,
|
||||||
|
blink_timeout: timeout,
|
||||||
tx: tx,
|
tx: tx,
|
||||||
rx: rx,
|
rx: rx,
|
||||||
terminal: terminal,
|
terminal: terminal,
|
||||||
|
@ -201,7 +230,7 @@ impl<Io> EventLoop<Io>
|
||||||
//
|
//
|
||||||
// Returns a `DrainResult` indicating the result of receiving from the channe;
|
// Returns a `DrainResult` indicating the result of receiving from the channe;
|
||||||
//
|
//
|
||||||
fn drain_recv_channel(&self, state: &mut State) -> DrainResult {
|
fn drain_recv_channel(&mut self, state: &mut State) -> DrainResult {
|
||||||
let mut received_item = false;
|
let mut received_item = false;
|
||||||
while let Ok(msg) = self.rx.try_recv() {
|
while let Ok(msg) = self.rx.try_recv() {
|
||||||
received_item = true;
|
received_item = true;
|
||||||
|
@ -209,6 +238,20 @@ impl<Io> EventLoop<Io>
|
||||||
Msg::Input(input) => {
|
Msg::Input(input) => {
|
||||||
state.write_list.push_back(input);
|
state.write_list.push_back(input);
|
||||||
},
|
},
|
||||||
|
Msg::Blink(true) => {
|
||||||
|
// Set timeout if it's not running
|
||||||
|
if self.blink_timeout.is_none() {
|
||||||
|
let mut terminal = self.terminal.lock();
|
||||||
|
let interval = terminal.cursor_blink_interval;
|
||||||
|
self.blink_timeout = Some(self.timer.set_timeout(interval, ()).unwrap());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Msg::Blink(false) => {
|
||||||
|
// Cancel timeout if it's running
|
||||||
|
if let Some(timeout) = self.blink_timeout.take() {
|
||||||
|
self.timer.cancel_timeout(&timeout);
|
||||||
|
}
|
||||||
|
},
|
||||||
Msg::Shutdown => {
|
Msg::Shutdown => {
|
||||||
return DrainResult::Shutdown;
|
return DrainResult::Shutdown;
|
||||||
}
|
}
|
||||||
|
@ -342,6 +385,25 @@ impl<Io> EventLoop<Io>
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_timers(&mut self) {
|
||||||
|
if self.timer.poll().is_some() {
|
||||||
|
println!("timers!");
|
||||||
|
// Dispatch blink
|
||||||
|
let mut terminal = self.terminal.lock();
|
||||||
|
terminal.toggle_blink_state();
|
||||||
|
if !terminal.dirty {
|
||||||
|
self.display.notify();
|
||||||
|
terminal.dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reregister timer
|
||||||
|
println!("set_timeout {:?}", terminal.cursor_blink_interval);
|
||||||
|
self.timer.set_timeout(terminal.cursor_blink_interval, ()).unwrap();
|
||||||
|
} else {
|
||||||
|
println!("timers :(");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn spawn(
|
pub fn spawn(
|
||||||
mut self,
|
mut self,
|
||||||
state: Option<State>
|
state: Option<State>
|
||||||
|
@ -357,6 +419,7 @@ impl<Io> EventLoop<Io>
|
||||||
|
|
||||||
self.poll.register(&self.rx, CHANNEL, Ready::readable(), poll_opts).unwrap();
|
self.poll.register(&self.rx, CHANNEL, Ready::readable(), poll_opts).unwrap();
|
||||||
self.poll.register(&fd, PTY, Ready::readable(), poll_opts).unwrap();
|
self.poll.register(&fd, PTY, Ready::readable(), poll_opts).unwrap();
|
||||||
|
self.poll.register(&self.timer, TIMER, Ready::readable(), poll_opts).unwrap();
|
||||||
|
|
||||||
let mut events = Events::with_capacity(1024);
|
let mut events = Events::with_capacity(1024);
|
||||||
|
|
||||||
|
@ -383,6 +446,13 @@ impl<Io> EventLoop<Io>
|
||||||
break 'event_loop;
|
break 'event_loop;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
TIMER => {
|
||||||
|
self.handle_timers();
|
||||||
|
println!("reregister timer");
|
||||||
|
self.poll
|
||||||
|
.reregister(&self.timer, TIMER, Ready::readable(), poll_opts)
|
||||||
|
.expect("reregister timer");
|
||||||
|
},
|
||||||
PTY => {
|
PTY => {
|
||||||
let kind = event.kind();
|
let kind = event.kind();
|
||||||
|
|
||||||
|
|
|
@ -123,6 +123,7 @@ fn run(mut config: Config, options: cli::Options) -> Result<(), Box<Error>> {
|
||||||
// consumes it periodically.
|
// consumes it periodically.
|
||||||
let event_loop = EventLoop::new(
|
let event_loop = EventLoop::new(
|
||||||
terminal.clone(),
|
terminal.clone(),
|
||||||
|
&config,
|
||||||
display.notifier(),
|
display.notifier(),
|
||||||
pty.reader(),
|
pty.reader(),
|
||||||
options.ref_test,
|
options.ref_test,
|
||||||
|
|
|
@ -114,6 +114,7 @@ impl<'a> RenderableCellsIter<'a> {
|
||||||
cursor: &'b Point,
|
cursor: &'b Point,
|
||||||
colors: &'b color::List,
|
colors: &'b color::List,
|
||||||
mode: TermMode,
|
mode: TermMode,
|
||||||
|
cursor_blink: bool,
|
||||||
config: &'b Config,
|
config: &'b Config,
|
||||||
selection: Option<RangeInclusive<index::Linear>>,
|
selection: Option<RangeInclusive<index::Linear>>,
|
||||||
cursor_style: CursorStyle,
|
cursor_style: CursorStyle,
|
||||||
|
@ -131,7 +132,7 @@ impl<'a> RenderableCellsIter<'a> {
|
||||||
config: config,
|
config: config,
|
||||||
colors: colors,
|
colors: colors,
|
||||||
cursor_cells: ArrayDeque::new(),
|
cursor_cells: ArrayDeque::new(),
|
||||||
}.initialize(cursor_style)
|
}.initialize(cursor_style, cursor_blink)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn populate_block_cursor(&mut self) {
|
fn populate_block_cursor(&mut self) {
|
||||||
|
@ -242,8 +243,8 @@ impl<'a> RenderableCellsIter<'a> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initialize(mut self, cursor_style: CursorStyle) -> Self {
|
fn initialize(mut self, cursor_style: CursorStyle, blink: bool) -> Self {
|
||||||
if self.cursor_is_visible() {
|
if !blink && self.cursor_is_visible() {
|
||||||
match cursor_style {
|
match cursor_style {
|
||||||
CursorStyle::Block => {
|
CursorStyle::Block => {
|
||||||
self.populate_block_cursor();
|
self.populate_block_cursor();
|
||||||
|
@ -391,19 +392,20 @@ impl<'a> Iterator for RenderableCellsIter<'a> {
|
||||||
pub mod mode {
|
pub mod mode {
|
||||||
bitflags! {
|
bitflags! {
|
||||||
pub flags TermMode: u16 {
|
pub flags TermMode: u16 {
|
||||||
const SHOW_CURSOR = 0b000000000001,
|
const SHOW_CURSOR = 0b0000000000001,
|
||||||
const APP_CURSOR = 0b000000000010,
|
const APP_CURSOR = 0b0000000000010,
|
||||||
const APP_KEYPAD = 0b000000000100,
|
const APP_KEYPAD = 0b0000000000100,
|
||||||
const MOUSE_REPORT_CLICK = 0b000000001000,
|
const MOUSE_REPORT_CLICK = 0b0000000001000,
|
||||||
const BRACKETED_PASTE = 0b000000010000,
|
const BRACKETED_PASTE = 0b0000000010000,
|
||||||
const SGR_MOUSE = 0b000000100000,
|
const SGR_MOUSE = 0b0000000100000,
|
||||||
const MOUSE_MOTION = 0b000001000000,
|
const MOUSE_MOTION = 0b0000001000000,
|
||||||
const LINE_WRAP = 0b000010000000,
|
const LINE_WRAP = 0b0000010000000,
|
||||||
const LINE_FEED_NEW_LINE = 0b000100000000,
|
const LINE_FEED_NEW_LINE = 0b0000100000000,
|
||||||
const ORIGIN = 0b001000000000,
|
const ORIGIN = 0b0001000000000,
|
||||||
const INSERT = 0b010000000000,
|
const INSERT = 0b0010000000000,
|
||||||
const FOCUS_IN_OUT = 0b100000000000,
|
const FOCUS_IN_OUT = 0b0100000000000,
|
||||||
const ANY = 0b111111111111,
|
const CURSOR_BLINK = 0b1000000000000,
|
||||||
|
const ANY = 0b1111111111111,
|
||||||
const NONE = 0,
|
const NONE = 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -677,6 +679,9 @@ pub struct Term {
|
||||||
colors: color::List,
|
colors: color::List,
|
||||||
|
|
||||||
cursor_style: CursorStyle,
|
cursor_style: CursorStyle,
|
||||||
|
|
||||||
|
pub cursor_blink_interval: Duration,
|
||||||
|
pub cursor_blink: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Terminal size info
|
/// Terminal size info
|
||||||
|
@ -741,6 +746,10 @@ impl Term {
|
||||||
self.next_title.take()
|
self.next_title.take()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn toggle_blink_state(&mut self) {
|
||||||
|
self.cursor_blink = !self.cursor_blink;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new(config : &Config, size: SizeInfo) -> Term {
|
pub fn new(config : &Config, size: SizeInfo) -> Term {
|
||||||
let template = Cell::default();
|
let template = Cell::default();
|
||||||
|
|
||||||
|
@ -756,11 +765,19 @@ impl Term {
|
||||||
let alt = grid.clone();
|
let alt = grid.clone();
|
||||||
let scroll_region = Line(0)..grid.num_lines();
|
let scroll_region = Line(0)..grid.num_lines();
|
||||||
|
|
||||||
|
let mut mode = TermMode::default();
|
||||||
|
if config.blink_enabled() {
|
||||||
|
println!("enable blink from term");
|
||||||
|
mode.insert(mode::CURSOR_BLINK);
|
||||||
|
}
|
||||||
|
|
||||||
Term {
|
Term {
|
||||||
next_title: None,
|
next_title: None,
|
||||||
dirty: false,
|
dirty: false,
|
||||||
visual_bell: VisualBell::new(config),
|
visual_bell: VisualBell::new(config),
|
||||||
input_needs_wrap: false,
|
input_needs_wrap: false,
|
||||||
|
cursor_blink_interval: config.cursor_blink_interval(),
|
||||||
|
cursor_blink: false,
|
||||||
grid: grid,
|
grid: grid,
|
||||||
alt_grid: alt,
|
alt_grid: alt,
|
||||||
alt: false,
|
alt: false,
|
||||||
|
@ -769,7 +786,7 @@ impl Term {
|
||||||
cursor_save: Default::default(),
|
cursor_save: Default::default(),
|
||||||
cursor_save_alt: Default::default(),
|
cursor_save_alt: Default::default(),
|
||||||
tabs: tabs,
|
tabs: tabs,
|
||||||
mode: Default::default(),
|
mode: mode,
|
||||||
scroll_region: scroll_region,
|
scroll_region: scroll_region,
|
||||||
size_info: size,
|
size_info: size,
|
||||||
empty_cell: template,
|
empty_cell: template,
|
||||||
|
@ -949,6 +966,7 @@ impl Term {
|
||||||
&self.cursor.point,
|
&self.cursor.point,
|
||||||
&self.colors,
|
&self.colors,
|
||||||
self.mode,
|
self.mode,
|
||||||
|
self.cursor_blink,
|
||||||
config,
|
config,
|
||||||
selection,
|
selection,
|
||||||
self.cursor_style
|
self.cursor_style
|
||||||
|
|
Loading…
Reference in a new issue