@@ -643,49 +643,64 @@ impl Element for TerminalEl {
);
//Layout cursor
- let cursor = {
- let cursor_point = DisplayCursor::from(cursor.point, display_offset);
- let cursor_text = {
- let str_trxt = cursor_text.to_string();
-
- let color = if self.focused {
- terminal_theme.colors.background
- } else {
- terminal_theme.colors.foreground
- };
+ //TODO: This logic can be a lot better
+ let show_cursor = if let Some(view_handle) = self.view.upgrade(cx) {
+ if view_handle.read(cx).show_cursor() {
+ false
+ } else {
+ true
+ }
+ } else {
+ true
+ };
- cx.text_layout_cache.layout_str(
- &str_trxt,
- text_style.font_size,
- &[(
- str_trxt.len(),
- RunStyle {
- font_id: text_style.font_id,
- color,
- underline: Default::default(),
- },
- )],
- )
- };
+ let cursor = {
+ if show_cursor {
+ None
+ } else {
+ let cursor_point = DisplayCursor::from(cursor.point, display_offset);
+ let cursor_text = {
+ let str_trxt = cursor_text.to_string();
- TerminalEl::shape_cursor(cursor_point, dimensions, &cursor_text).map(
- move |(cursor_position, block_width)| {
- let (shape, color) = if self.focused {
- (CursorShape::Block, terminal_theme.colors.cursor)
+ let color = if self.focused {
+ terminal_theme.colors.background
} else {
- (CursorShape::Underscore, terminal_theme.colors.foreground)
+ terminal_theme.colors.foreground
};
- Cursor::new(
- cursor_position,
- block_width,
- dimensions.line_height,
- color,
- shape,
- Some(cursor_text),
+ cx.text_layout_cache.layout_str(
+ &str_trxt,
+ text_style.font_size,
+ &[(
+ str_trxt.len(),
+ RunStyle {
+ font_id: text_style.font_id,
+ color,
+ underline: Default::default(),
+ },
+ )],
)
- },
- )
+ };
+
+ TerminalEl::shape_cursor(cursor_point, dimensions, &cursor_text).map(
+ move |(cursor_position, block_width)| {
+ let (shape, color) = if self.focused {
+ (CursorShape::Block, terminal_theme.colors.cursor)
+ } else {
+ (CursorShape::Underscore, terminal_theme.colors.foreground)
+ };
+
+ Cursor::new(
+ cursor_position,
+ block_width,
+ dimensions.line_height,
+ color,
+ shape,
+ Some(cursor_text),
+ )
+ },
+ )
+ }
};
//Done!
@@ -818,7 +833,10 @@ impl Element for TerminalEl {
//TODO Talk to keith about how to catch events emitted from an element.
if let Some(view) = self.view.upgrade(cx.app) {
- view.update(cx.app, |view, cx| view.clear_bel(cx))
+ view.update(cx.app, |view, cx| {
+ view.clear_bel(cx);
+ view.pause_cursor_blinking(cx);
+ })
}
self.terminal
@@ -1,3 +1,5 @@
+use std::time::Duration;
+
use alacritty_terminal::term::TermMode;
use context_menu::{ContextMenu, ContextMenuItem};
use gpui::{
@@ -9,10 +11,13 @@ use gpui::{
AnyViewHandle, AppContext, Element, ElementBox, ModelHandle, MutableAppContext, View,
ViewContext, ViewHandle,
};
+use smol::Timer;
use workspace::pane;
use crate::{connected_el::TerminalEl, Event, Terminal};
+const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
+
///Event to transmit the scroll from the element to the view
#[derive(Clone, Debug, PartialEq)]
pub struct ScrollTerminal(pub i32);
@@ -51,6 +56,9 @@ pub struct ConnectedView {
// Only for styling purposes. Doesn't effect behavior
modal: bool,
context_menu: ViewHandle<ContextMenu>,
+ show_cursor: bool,
+ blinking_paused: bool,
+ blink_epoch: usize,
}
impl ConnectedView {
@@ -83,6 +91,9 @@ impl ConnectedView {
has_bell: false,
modal,
context_menu: cx.add_view(ContextMenu::new),
+ show_cursor: true,
+ blinking_paused: false,
+ blink_epoch: 0,
}
}
@@ -120,6 +131,59 @@ impl ConnectedView {
cx.notify();
}
+ //Following code copied from editor cursor
+ pub fn show_cursor(&self) -> bool {
+ self.blinking_paused || self.show_cursor
+ }
+
+ fn blink_cursors(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
+ if epoch == self.blink_epoch && !self.blinking_paused {
+ self.show_cursor = !self.show_cursor;
+ cx.notify();
+
+ let epoch = self.next_blink_epoch();
+ cx.spawn(|this, mut cx| {
+ let this = this.downgrade();
+ async move {
+ Timer::after(CURSOR_BLINK_INTERVAL).await;
+ if let Some(this) = this.upgrade(&cx) {
+ this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx));
+ }
+ }
+ })
+ .detach();
+ }
+ }
+
+ pub fn pause_cursor_blinking(&mut self, cx: &mut ViewContext<Self>) {
+ self.show_cursor = true;
+ cx.notify();
+
+ let epoch = self.next_blink_epoch();
+ cx.spawn(|this, mut cx| {
+ let this = this.downgrade();
+ async move {
+ Timer::after(CURSOR_BLINK_INTERVAL).await;
+ if let Some(this) = this.upgrade(&cx) {
+ this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
+ }
+ }
+ })
+ .detach();
+ }
+
+ fn next_blink_epoch(&mut self) -> usize {
+ self.blink_epoch += 1;
+ self.blink_epoch
+ }
+
+ fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
+ if epoch == self.blink_epoch {
+ self.blinking_paused = false;
+ self.blink_cursors(epoch, cx);
+ }
+ }
+
///Attempt to paste the clipboard into the terminal
fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
self.terminal.update(cx, |term, _| term.copy())
@@ -200,6 +264,7 @@ impl View for ConnectedView {
fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
self.has_new_content = false;
self.terminal.read(cx).focus_in();
+ self.blink_cursors(self.blink_epoch, cx);
cx.notify();
}
@@ -208,6 +273,7 @@ impl View for ConnectedView {
cx.notify();
}
+ //IME stuff
fn selected_text_range(&self, cx: &AppContext) -> Option<std::ops::Range<usize>> {
if self
.terminal