Basic cursor blinking :)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()));
|
||||
|
||||
Reference in New Issue
Block a user