@@ -200,6 +200,7 @@ pub struct TerminalEl {
terminal: WeakModelHandle<Terminal>,
view: WeakViewHandle<ConnectedView>,
modal: bool,
+ focused: bool,
}
impl TerminalEl {
@@ -207,11 +208,13 @@ impl TerminalEl {
view: WeakViewHandle<ConnectedView>,
terminal: WeakModelHandle<Terminal>,
modal: bool,
+ focused: bool,
) -> TerminalEl {
TerminalEl {
view,
terminal,
modal,
+ focused,
}
}
@@ -644,6 +647,13 @@ impl Element for TerminalEl {
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,
@@ -651,7 +661,7 @@ impl Element for TerminalEl {
str_trxt.len(),
RunStyle {
font_id: text_style.font_id,
- color: terminal_theme.colors.background,
+ color,
underline: Default::default(),
},
)],
@@ -660,12 +670,18 @@ impl Element for TerminalEl {
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,
- terminal_theme.colors.cursor,
- CursorShape::Block,
+ color,
+ shape,
Some(cursor_text),
)
},
@@ -181,9 +181,15 @@ impl View for ConnectedView {
fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> ElementBox {
let terminal_handle = self.terminal.clone().downgrade();
+ let self_id = cx.view_id();
+ let focused = cx
+ .focused_view_id(cx.window_id())
+ .filter(|view_id| *view_id == self_id)
+ .is_some();
+
Stack::new()
.with_child(
- TerminalEl::new(cx.handle(), terminal_handle, self.modal)
+ TerminalEl::new(cx.handle(), terminal_handle, self.modal, focused)
.contained()
.boxed(),
)
@@ -191,8 +197,15 @@ impl View for ConnectedView {
.boxed()
}
- fn on_focus_in(&mut self, _: AnyViewHandle, _cx: &mut ViewContext<Self>) {
+ fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
self.has_new_content = false;
+ self.terminal.read(cx).focus_in();
+ cx.notify();
+ }
+
+ fn on_focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
+ self.terminal.read(cx).focus_out();
+ cx.notify();
}
fn selected_text_range(&self, cx: &AppContext) -> Option<std::ops::Range<usize>> {
@@ -601,18 +601,23 @@ impl Terminal {
f(content, cursor_text)
}
- // fn estimate_utilization(last_processed: usize) -> f32 {
- // let buffer_utilization = (last_processed as f32 / (READ_BUFFER_SIZE as f32)).clamp(0., 1.);
-
- // //Scale result to bias low, then high
- // buffer_utilization * buffer_utilization
- // }
-
///Scroll the terminal
pub fn scroll(&mut self, scroll: Scroll) {
self.events.push(InternalEvent::Scroll(scroll));
}
+ pub fn focus_in(&self) {
+ if self.last_mode.contains(TermMode::FOCUS_IN_OUT) {
+ self.notify_pty("\x1b[I".to_string());
+ }
+ }
+
+ pub fn focus_out(&self) {
+ if self.last_mode.contains(TermMode::FOCUS_IN_OUT) {
+ self.notify_pty("\x1b[O".to_string());
+ }
+ }
+
pub fn click(&mut self, point: Point, side: Direction, clicks: usize) {
let selection_type = match clicks {
0 => return, //This is a release