Basic cursor blinking :)

This commit is contained in:
Mikayla Maki
2022-08-15 17:00:44 -07:00
parent a24e5b128c
commit 7b3a7727c6
3 changed files with 123 additions and 38 deletions
+56 -38
View File
@@ -643,49 +643,64 @@ impl Element for TerminalEl {
);
//Layout cursor
//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
};
let cursor = {
let cursor_point = DisplayCursor::from(cursor.point, display_offset);
let cursor_text = {
let str_trxt = cursor_text.to_string();
if show_cursor {
None
} else {
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
};
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)
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
+66
View File
@@ -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
+1
View File
@@ -287,6 +287,7 @@ impl TerminalBuilder {
setup_env(&config);
//Spawn a task so the Alacritty EventLoop can communicate with us in a view context
//TODO: Remove with a bounded sender which can be dispatched on &self
let (events_tx, events_rx) = unbounded();
//Set up the terminal...
let term = Term::new(&config, &initial_size, ZedListener(events_tx.clone()));