Fixed blink problems

This commit is contained in:
Mikayla Maki 2022-08-17 14:41:28 -07:00
parent 5ad746e53f
commit acce0042f9
6 changed files with 89 additions and 122 deletions

View file

@ -106,15 +106,12 @@
//May take 4 values: //May take 4 values:
// 1. Never blink the cursor, ignoring the terminal mode // 1. Never blink the cursor, ignoring the terminal mode
// "blinking": "never", // "blinking": "never",
// 2. Default the cursor blink to off, but allow the terminal to // 2. Default the cursor blink to on, but allow the terminal to
// turn blinking on
// "blinking": "off",
// 3. Default the cursor blink to on, but allow the terminal to
// turn blinking off // turn blinking off
// "blinking": "on", // "blinking": "terminal_controlled",
// 4. Always blink the cursor, ignoring the terminal mode // 3. Always blink the cursor, ignoring the terminal mode
// "blinking": "always", // "blinking": "always",
"blinking": "on", "blinking": "terminal_controlled",
//Any key-value pairs added to this list will be added to the terminal's //Any key-value pairs added to this list will be added to the terminal's
//enviroment. Use `:` to seperate multiple values. //enviroment. Use `:` to seperate multiple values.
"env": { "env": {

View file

@ -1801,7 +1801,7 @@ impl Cursor {
pub fn paint(&self, origin: Vector2F, cx: &mut PaintContext) { pub fn paint(&self, origin: Vector2F, cx: &mut PaintContext) {
let bounds = match self.shape { let bounds = match self.shape {
CursorShape::Bar => RectF::new(self.origin + origin, vec2f(2.0, self.line_height)), CursorShape::Bar => RectF::new(self.origin + origin, vec2f(2.0, self.line_height)),
CursorShape::Block => RectF::new( CursorShape::Block | CursorShape::Hollow => RectF::new(
self.origin + origin, self.origin + origin,
vec2f(self.block_width, self.line_height), vec2f(self.block_width, self.line_height),
), ),
@ -1809,58 +1809,27 @@ impl Cursor {
self.origin + origin + Vector2F::new(0.0, self.line_height - 2.0), self.origin + origin + Vector2F::new(0.0, self.line_height - 2.0),
vec2f(self.block_width, 2.0), vec2f(self.block_width, 2.0),
), ),
CursorShape::Hollow => RectF::new(
self.origin + origin + Vector2F::new(0.0, self.line_height - 1.0),
vec2f(self.block_width, 1.0),
),
}; };
//Draw text under the hollow block if need be //Draw background or border quad
if matches!(self.shape, CursorShape::Hollow) { if matches!(self.shape, CursorShape::Hollow) {
if let Some(block_text) = &self.block_text {
block_text.paint(self.origin + origin, bounds, self.line_height, cx);
}
}
cx.scene.push_quad(Quad {
bounds,
background: Some(self.color),
border: Border::new(0., Color::black()),
corner_radius: 0.,
});
if matches!(self.shape, CursorShape::Hollow) {
//Top
cx.scene.push_quad(Quad { cx.scene.push_quad(Quad {
bounds: RectF::new( bounds,
self.origin + origin + Vector2F::new(0.0, -1.0), background: None,
vec2f(self.block_width + 1., 1.0), border: Border::all(1., self.color),
),
background: Some(self.color),
border: Border::new(0., Color::black()),
corner_radius: 0.,
});
//Left
cx.scene.push_quad(Quad {
bounds: RectF::new(self.origin + origin, vec2f(1.0, self.line_height)),
background: Some(self.color),
border: Border::new(0., Color::black()),
corner_radius: 0.,
});
//Right
cx.scene.push_quad(Quad {
bounds: RectF::new(
self.origin + origin + vec2f(self.block_width, 0.),
vec2f(1.0, self.line_height),
),
background: Some(self.color),
border: Border::new(0., Color::black()),
corner_radius: 0., corner_radius: 0.,
}); });
} else { } else {
if let Some(block_text) = &self.block_text { cx.scene.push_quad(Quad {
block_text.paint(self.origin + origin, bounds, self.line_height, cx); bounds,
} background: Some(self.color),
border: Default::default(),
corner_radius: 0.,
});
}
if let Some(block_text) = &self.block_text {
block_text.paint(self.origin + origin, bounds, self.line_height, cx);
} }
} }
} }

View file

@ -90,14 +90,13 @@ pub struct TerminalSettings {
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum TerminalBlink { pub enum TerminalBlink {
Never, Never,
On, TerminalControlled,
Off,
Always, Always,
} }
impl Default for TerminalBlink { impl Default for TerminalBlink {
fn default() -> Self { fn default() -> Self {
TerminalBlink::On TerminalBlink::TerminalControlled
} }
} }

View file

@ -21,7 +21,7 @@ use gpui::{
}; };
use itertools::Itertools; use itertools::Itertools;
use ordered_float::OrderedFloat; use ordered_float::OrderedFloat;
use settings::{Settings, TerminalBlink}; use settings::Settings;
use theme::TerminalStyle; use theme::TerminalStyle;
use util::ResultExt; use util::ResultExt;
@ -201,7 +201,7 @@ pub struct TerminalEl {
view: WeakViewHandle<ConnectedView>, view: WeakViewHandle<ConnectedView>,
modal: bool, modal: bool,
focused: bool, focused: bool,
blink_state: bool, cursor_visible: bool,
} }
impl TerminalEl { impl TerminalEl {
@ -210,14 +210,14 @@ impl TerminalEl {
terminal: WeakModelHandle<Terminal>, terminal: WeakModelHandle<Terminal>,
modal: bool, modal: bool,
focused: bool, focused: bool,
blink_state: bool, cursor_visible: bool,
) -> TerminalEl { ) -> TerminalEl {
TerminalEl { TerminalEl {
view, view,
terminal, terminal,
modal, modal,
focused, focused,
blink_state, cursor_visible,
} }
} }
@ -571,33 +571,6 @@ impl TerminalEl {
(point, side) (point, side)
} }
pub fn should_show_cursor(
settings: Option<TerminalBlink>,
blinking_on: bool,
focused: bool,
blink_show: bool,
) -> bool {
if !focused {
true
} else {
match settings {
Some(setting) => match setting {
TerminalBlink::Never => true,
TerminalBlink::On | TerminalBlink::Off if blinking_on => blink_show,
TerminalBlink::On | TerminalBlink::Off /*if !blinking_on */ => true,
TerminalBlink::Always => focused && blink_show,
},
None => {
if blinking_on {
blink_show
} else {
false
}
}
}
}
}
} }
impl Element for TerminalEl { impl Element for TerminalEl {
@ -610,7 +583,6 @@ impl Element for TerminalEl {
cx: &mut gpui::LayoutContext, cx: &mut gpui::LayoutContext,
) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) { ) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) {
let settings = cx.global::<Settings>(); let settings = cx.global::<Settings>();
let blink_settings = settings.terminal_overrides.blinking.clone();
let font_cache = cx.font_cache(); let font_cache = cx.font_cache();
//Setup layout information //Setup layout information
@ -629,13 +601,13 @@ impl Element for TerminalEl {
terminal_theme.colors.background terminal_theme.colors.background
}; };
let (cells, selection, cursor, display_offset, cursor_text, blink_mode) = self let (cells, selection, cursor, display_offset, cursor_text) = self
.terminal .terminal
.upgrade(cx) .upgrade(cx)
.unwrap() .unwrap()
.update(cx.app, |terminal, mcx| { .update(cx.app, |terminal, mcx| {
terminal.set_size(dimensions); terminal.set_size(dimensions);
terminal.render_lock(mcx, |content, cursor_text, blink_mode| { terminal.render_lock(mcx, |content, cursor_text| {
let mut cells = vec![]; let mut cells = vec![];
cells.extend( cells.extend(
content content
@ -659,7 +631,6 @@ impl Element for TerminalEl {
content.cursor, content.cursor,
content.display_offset, content.display_offset,
cursor_text, cursor_text,
blink_mode,
) )
}) })
}); });
@ -676,14 +647,7 @@ impl Element for TerminalEl {
//Layout cursor //Layout cursor
let cursor = { let cursor = {
if !TerminalEl::should_show_cursor( if self.cursor_visible {
blink_settings,
blink_mode,
self.focused,
self.blink_state,
) {
None
} else {
let cursor_point = DisplayCursor::from(cursor.point, display_offset); let cursor_point = DisplayCursor::from(cursor.point, display_offset);
let cursor_text = { let cursor_text = {
let str_trxt = cursor_text.to_string(); let str_trxt = cursor_text.to_string();
@ -710,22 +674,24 @@ impl Element for TerminalEl {
TerminalEl::shape_cursor(cursor_point, dimensions, &cursor_text).map( TerminalEl::shape_cursor(cursor_point, dimensions, &cursor_text).map(
move |(cursor_position, block_width)| { move |(cursor_position, block_width)| {
let (shape, color) = if self.focused { let shape = if self.focused {
(CursorShape::Block, terminal_theme.colors.cursor) CursorShape::Block
} else { } else {
(CursorShape::Hollow, terminal_theme.colors.foreground) CursorShape::Hollow
}; };
Cursor::new( Cursor::new(
cursor_position, cursor_position,
block_width, block_width,
dimensions.line_height, dimensions.line_height,
color, terminal_theme.colors.cursor,
shape, shape,
Some(cursor_text), Some(cursor_text),
) )
}, },
) )
} else {
None
} }
}; };

View file

@ -11,6 +11,7 @@ use gpui::{
AnyViewHandle, AppContext, Element, ElementBox, ModelHandle, MutableAppContext, View, AnyViewHandle, AppContext, Element, ElementBox, ModelHandle, MutableAppContext, View,
ViewContext, ViewHandle, ViewContext, ViewHandle,
}; };
use settings::{Settings, TerminalBlink};
use smol::Timer; use smol::Timer;
use workspace::pane; use workspace::pane;
@ -67,7 +68,8 @@ pub struct ConnectedView {
// Only for styling purposes. Doesn't effect behavior // Only for styling purposes. Doesn't effect behavior
modal: bool, modal: bool,
context_menu: ViewHandle<ContextMenu>, context_menu: ViewHandle<ContextMenu>,
show_cursor: bool, blink_state: bool,
blinking_on: bool,
blinking_paused: bool, blinking_paused: bool,
blink_epoch: usize, blink_epoch: usize,
} }
@ -91,7 +93,7 @@ impl ConnectedView {
this.has_bell = true; this.has_bell = true;
cx.emit(Event::Wakeup); cx.emit(Event::Wakeup);
} }
Event::BlinkChanged => this.blinking_on = !this.blinking_on,
_ => cx.emit(*event), _ => cx.emit(*event),
}) })
.detach(); .detach();
@ -102,7 +104,8 @@ impl ConnectedView {
has_bell: false, has_bell: false,
modal, modal,
context_menu: cx.add_view(ContextMenu::new), context_menu: cx.add_view(ContextMenu::new),
show_cursor: true, blink_state: true,
blinking_on: false,
blinking_paused: false, blinking_paused: false,
blink_epoch: 0, blink_epoch: 0,
} }
@ -153,14 +156,46 @@ impl ConnectedView {
cx.notify(); cx.notify();
} }
//Following code copied from editor cursor //2 -> Character palette shows up! But it's incorrectly positioned
pub fn blink_show(&self) -> bool {
self.blinking_paused || self.show_cursor pub fn should_show_cursor(
&self,
focused: bool,
cx: &mut gpui::RenderContext<'_, Self>,
) -> bool {
//Don't blink the cursor when not focused, blinking is disabled, or paused
if !focused
|| !self.blinking_on
|| self.blinking_paused
|| self
.terminal
.read(cx)
.last_mode
.contains(TermMode::ALT_SCREEN)
{
return true;
}
let setting = {
let settings = cx.global::<Settings>();
settings
.terminal_overrides
.blinking
.clone()
.unwrap_or(TerminalBlink::TerminalControlled)
};
match setting {
//If the user requested to never blink, don't blink it.
TerminalBlink::Never => true,
//If the terminal is controlling it, check terminal mode
TerminalBlink::TerminalControlled | TerminalBlink::Always => self.blink_state,
}
} }
fn blink_cursors(&mut self, epoch: usize, cx: &mut ViewContext<Self>) { fn blink_cursors(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
if epoch == self.blink_epoch && !self.blinking_paused { if epoch == self.blink_epoch && !self.blinking_paused {
self.show_cursor = !self.show_cursor; self.blink_state = !self.blink_state;
cx.notify(); cx.notify();
let epoch = self.next_blink_epoch(); let epoch = self.next_blink_epoch();
@ -178,7 +213,7 @@ impl ConnectedView {
} }
pub fn pause_cursor_blinking(&mut self, cx: &mut ViewContext<Self>) { pub fn pause_cursor_blinking(&mut self, cx: &mut ViewContext<Self>) {
self.show_cursor = true; self.blink_state = true;
cx.notify(); cx.notify();
let epoch = self.next_blink_epoch(); let epoch = self.next_blink_epoch();
@ -280,7 +315,7 @@ impl View for ConnectedView {
terminal_handle, terminal_handle,
self.modal, self.modal,
focused, focused,
self.blink_show(), self.should_show_cursor(focused, cx),
) )
.contained() .contained()
.boxed(), .boxed(),

View file

@ -19,6 +19,8 @@ use alacritty_terminal::{
}; };
use anyhow::{bail, Result}; use anyhow::{bail, Result};
//When you type a key, scroll does not happen in terminal !!!TODO
use futures::{ use futures::{
channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}, channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender},
FutureExt, FutureExt,
@ -62,6 +64,7 @@ pub enum Event {
CloseTerminal, CloseTerminal,
Bell, Bell,
Wakeup, Wakeup,
BlinkChanged,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -295,14 +298,12 @@ impl TerminalBuilder {
//Start off blinking if we need to //Start off blinking if we need to
match blink_settings { match blink_settings {
Some(setting) => match setting { None | Some(TerminalBlink::TerminalControlled) | Some(TerminalBlink::Always) => {
TerminalBlink::On | TerminalBlink::Always => { term.set_mode(alacritty_terminal::ansi::Mode::BlinkingCursor)
term.set_mode(alacritty_terminal::ansi::Mode::BlinkingCursor) }
} _ => {}
_ => {}
},
None => term.set_mode(alacritty_terminal::ansi::Mode::BlinkingCursor),
} }
let term = Arc::new(FairMutex::new(term)); let term = Arc::new(FairMutex::new(term));
//Setup the pty... //Setup the pty...
@ -479,7 +480,7 @@ impl Terminal {
self.notify_pty(format(self.cur_size.into())) self.notify_pty(format(self.cur_size.into()))
} }
AlacTermEvent::CursorBlinkingChange => { AlacTermEvent::CursorBlinkingChange => {
//TODO whatever state we need to set to get the cursor blinking cx.emit(Event::BlinkChanged);
} }
AlacTermEvent::Bell => { AlacTermEvent::Bell => {
cx.emit(Event::Bell); cx.emit(Event::Bell);
@ -595,7 +596,7 @@ impl Terminal {
pub fn render_lock<F, T>(&mut self, cx: &mut ModelContext<Self>, f: F) -> T pub fn render_lock<F, T>(&mut self, cx: &mut ModelContext<Self>, f: F) -> T
where where
F: FnOnce(RenderableContent, char, bool) -> T, F: FnOnce(RenderableContent, char) -> T,
{ {
let m = self.term.clone(); //Arc clone let m = self.term.clone(); //Arc clone
let mut term = m.lock(); let mut term = m.lock();
@ -611,7 +612,7 @@ impl Terminal {
let cursor_text = term.grid()[content.cursor.point].c; let cursor_text = term.grid()[content.cursor.point].c;
f(content, cursor_text, term.cursor_style().blinking) f(content, cursor_text)
} }
///Scroll the terminal ///Scroll the terminal