mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-14 22:14:23 +00:00
Fixed blink problems
This commit is contained in:
parent
5ad746e53f
commit
acce0042f9
6 changed files with 89 additions and 122 deletions
|
@ -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": {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue