1
0
Fork 0
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:
Joe Wilm 2017-07-03 19:41:58 -07:00
parent 08b5ae52c1
commit b88f95eab9
6 changed files with 132 additions and 19 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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();

View file

@ -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,

View file

@ -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