From 18dc12218fb7157aa7a4175416000cd509639483 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Tue, 16 Aug 2022 13:01:35 -0700 Subject: [PATCH 01/10] Begin work on IME changes --- crates/gpui/src/platform/mac/window.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index b597dfb778b9b50a67097f4c1dc1590abdc4fac1..c36cdf7fe671675437a4f2ba9890d399cc7995dd 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -278,6 +278,18 @@ unsafe fn build_classes() { pub struct Window(Rc>); +///Used to track what the IME does when we send it a keystroke. +///This is only used to handle the case where the IME mysteriously +///swallows certain keys. +/// +///Basically a direct copy of the approach that WezTerm uses in: +///github.com/wez/wezterm : d5755f3e : window/src/os/macos/window.rs +enum ImeState { + Continue, + Acted, + None, +} + struct WindowState { id: usize, native_window: id, @@ -299,6 +311,10 @@ struct WindowState { layer: id, traffic_light_position: Option, previous_modifiers_changed_event: Option, + //State tracking what the IME did after the last request + ime_state: ImeState, + //Retains the last IME keystroke that was in the 'Acted' state + last_ime_key: Option, } struct InsertText { From 94ba282e76064e727fa170f260db7896080fcd05 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Tue, 16 Aug 2022 22:12:06 -0700 Subject: [PATCH 02/10] Checkpoint, alt-n l is very broken. Bisecting. --- crates/gpui/src/platform/mac/window.rs | 86 ++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 4 deletions(-) diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index c36cdf7fe671675437a4f2ba9890d399cc7995dd..507b04bd1a997c75e7e150eaa83eadf6e8d3a4e0 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -313,8 +313,8 @@ struct WindowState { previous_modifiers_changed_event: Option, //State tracking what the IME did after the last request ime_state: ImeState, - //Retains the last IME keystroke that was in the 'Acted' state - last_ime_key: Option, + //Retains the last IME Text + ime_text: Option, } struct InsertText { @@ -411,6 +411,8 @@ impl Window { layer, traffic_light_position: options.traffic_light_position, previous_modifiers_changed_event: None, + ime_state: ImeState::None, + ime_text: None, }))); (*native_window).set_ivar( @@ -774,6 +776,9 @@ extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent: let mut window_state_borrow = window_state.as_ref().borrow_mut(); let event = unsafe { Event::from_native(native_event, Some(window_state_borrow.size().y())) }; + + println!("Handle key event! {:?}", event); + if let Some(event) = event { if key_equivalent { window_state_borrow.performed_key_equivalent = true; @@ -811,7 +816,9 @@ extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent: let mut handled = false; let mut window_state_borrow = window_state.borrow_mut(); + let ime_text = window_state_borrow.ime_text.clone(); if let Some((event, insert_text)) = window_state_borrow.pending_key_down.take() { + let is_held = event.is_held; if let Some(mut callback) = window_state_borrow.event_callback.take() { drop(window_state_borrow); @@ -830,6 +837,18 @@ extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent: input_handler .replace_text_in_range(insert.replacement_range, &insert.text) }); + } else if !is_composing && is_held { + if let Some(last_insert_text) = ime_text { + //MacOS IME is a bit funky, and even when you've told it there's nothing to + //inter it will still swallow certain keys (e.g. 'f', 'j') and not others + //(e.g. 'n'). This is a problem for certain kinds of views, like the terminal + with_input_handler(this, |input_handler| { + if input_handler.selected_text_range().is_none() { + handled = true; + input_handler.replace_text_in_range(None, &last_insert_text) + } + }); + } } } @@ -1180,11 +1199,24 @@ extern "C" fn insert_text(this: &Object, _: Sel, text: id, replacement_range: NS .unwrap(); let replacement_range = replacement_range.to_range(); + window_state.borrow_mut().ime_text = Some(text.to_string()); + window_state.borrow_mut().ime_state = ImeState::Acted; + + //Conceptually incorrect let is_composing = with_input_handler(this, |input_handler| input_handler.marked_text_range()) .flatten() .is_some(); + println!( + "Insert text, is_composing {}, text {}, have pending key down? {:?}", + is_composing, + &text, + &pending_key_down.is_some() + ); + + //Handle key event is going to be returned to soon! Make sure it + //has the new text from the IME match pending_key_down { None | Some(_) if is_composing || text.chars().count() > 1 => { with_input_handler(this, |input_handler| { @@ -1202,6 +1234,30 @@ extern "C" fn insert_text(this: &Object, _: Sel, text: id, replacement_range: NS _ => unreachable!(), } + + // if let Some(mut pending_key_down) = pending_key_down { + // pending_key_down.1 = Some(InsertText { + // replacement_range, + // text: text.to_string(), + // }); + // window_state.borrow_mut().pending_key_down = Some(pending_key_down); + + // //Modifier key combos (˜ˆ) (success / failure) + // //Press-and-hold replacements ((hold i) 1 -> î) (success / failure) + // //Pop down chinese composition menu + // //Handwriting menu + // //Emoji Picker (😤) + + // //Regression -> alt-i l only causes 'l' to be placed, instead of ˆl + // // + // } + // //If no pending key down, then handle_key_event isn't going to + // //insert the text for us. Do it ourselves + // else { + // with_input_handler(this, |input_handler| { + // input_handler.replace_text_in_range(replacement_range, text) + // }); + // } } } @@ -1213,7 +1269,8 @@ extern "C" fn set_marked_text( replacement_range: NSRange, ) { unsafe { - get_window_state(this).borrow_mut().pending_key_down.take(); + let window_state = get_window_state(this); + window_state.borrow_mut().pending_key_down.take(); let is_attributed_string: BOOL = msg_send![text, isKindOfClass: [class!(NSAttributedString)]]; @@ -1228,6 +1285,11 @@ extern "C" fn set_marked_text( .to_str() .unwrap(); + window_state.borrow_mut().ime_state = ImeState::Acted; + window_state.borrow_mut().ime_text = Some(text.to_string()); + + println!("set_marked_text({selected_range:?}, {replacement_range:?}, {text:?})"); + with_input_handler(this, |input_handler| { input_handler.replace_and_mark_text_in_range(replacement_range, text, selected_range); }); @@ -1235,6 +1297,15 @@ extern "C" fn set_marked_text( } extern "C" fn unmark_text(this: &Object, _: Sel) { + unsafe { + let state = get_window_state(this); + let mut borrow = state.borrow_mut(); + borrow.ime_state = ImeState::Acted; + borrow.ime_text.take(); + } + + println!("unmark_text()"); + with_input_handler(this, |input_handler| input_handler.unmark_text()); } @@ -1261,7 +1332,14 @@ extern "C" fn attributed_substring_for_proposed_range( .unwrap_or(nil) } -extern "C" fn do_command_by_selector(_: &Object, _: Sel, _: Sel) {} +extern "C" fn do_command_by_selector(this: &Object, _: Sel, _: Sel) { + unsafe { + let state = get_window_state(this); + let mut borrow = state.borrow_mut(); + borrow.ime_state = ImeState::Continue; + borrow.ime_text.take(); + } +} async fn synthetic_drag( window_state: Weak>, From 1f82c0c8bf2bb90cf46bf4d7952bc3d427acb27e Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Tue, 16 Aug 2022 23:00:09 -0700 Subject: [PATCH 03/10] Repeat key problems fixed. --- crates/gpui/src/platform/mac/window.rs | 38 -------------------------- 1 file changed, 38 deletions(-) diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index 8c31f686cbb5f27208d856f2d4420f08eec55c6e..5db530b9cfbb03c2ac74204a44f8a57630fce16d 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -777,8 +777,6 @@ extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent: let event = unsafe { Event::from_native(native_event, Some(window_state_borrow.size().y())) }; - println!("Handle key event! {:?}", event); - if let Some(event) = event { if key_equivalent { window_state_borrow.performed_key_equivalent = true; @@ -1202,19 +1200,11 @@ extern "C" fn insert_text(this: &Object, _: Sel, text: id, replacement_range: NS window_state.borrow_mut().ime_text = Some(text.to_string()); window_state.borrow_mut().ime_state = ImeState::Acted; - //Conceptually incorrect let is_composing = with_input_handler(this, |input_handler| input_handler.marked_text_range()) .flatten() .is_some(); - println!( - "Insert text, is_composing {}, text {}, have pending key down? {:?}", - is_composing, - &text, - &pending_key_down.is_some() - ); - if is_composing || text.chars().count() > 1 || pending_key_down.is_none() { with_input_handler(this, |input_handler| { input_handler.replace_text_in_range(replacement_range, text) @@ -1227,30 +1217,6 @@ extern "C" fn insert_text(this: &Object, _: Sel, text: id, replacement_range: NS }); window_state.borrow_mut().pending_key_down = Some(pending_key_down); } - - // if let Some(mut pending_key_down) = pending_key_down { - // pending_key_down.1 = Some(InsertText { - // replacement_range, - // text: text.to_string(), - // }); - // window_state.borrow_mut().pending_key_down = Some(pending_key_down); - - // //Modifier key combos (˜ˆ) (success / failure) - // //Press-and-hold replacements ((hold i) 1 -> î) (success / failure) - // //Pop down chinese composition menu - // //Handwriting menu - // //Emoji Picker (😤) - - // //Regression -> alt-i l only causes 'l' to be placed, instead of ˆl - // // - // } - // //If no pending key down, then handle_key_event isn't going to - // //insert the text for us. Do it ourselves - // else { - // with_input_handler(this, |input_handler| { - // input_handler.replace_text_in_range(replacement_range, text) - // }); - // } } } @@ -1281,8 +1247,6 @@ extern "C" fn set_marked_text( window_state.borrow_mut().ime_state = ImeState::Acted; window_state.borrow_mut().ime_text = Some(text.to_string()); - println!("set_marked_text({selected_range:?}, {replacement_range:?}, {text:?})"); - with_input_handler(this, |input_handler| { input_handler.replace_and_mark_text_in_range(replacement_range, text, selected_range); }); @@ -1297,8 +1261,6 @@ extern "C" fn unmark_text(this: &Object, _: Sel) { borrow.ime_text.take(); } - println!("unmark_text()"); - with_input_handler(this, |input_handler| input_handler.unmark_text()); } From bf7b3150e4f7cac308aff12281ae7085b8465dec Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Tue, 16 Aug 2022 23:10:05 -0700 Subject: [PATCH 04/10] Added show character palette. Need to position correctly. --- assets/keymaps/default.json | 2 ++ crates/terminal/src/connected_view.rs | 17 ++++++++++++++++- crates/terminal/src/mappings/keys.rs | 1 - 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/assets/keymaps/default.json b/assets/keymaps/default.json index 6f34facc421e203b5b276fd8704ed1265b34c2dd..b40a076c499db29a99d80db17c39d3c3295afc6b 100644 --- a/assets/keymaps/default.json +++ b/assets/keymaps/default.json @@ -420,6 +420,7 @@ "enter": "terminal::Enter", "ctrl-c": "terminal::CtrlC", // Useful terminal actions: + "ctrl-cmd-space": "terminal::ShowCharacterPalette", "cmd-c": "terminal::Copy", "cmd-v": "terminal::Paste", "cmd-k": "terminal::Clear" @@ -428,6 +429,7 @@ { "context": "ModalTerminal", "bindings": { + "ctrl-cmd-space": "terminal::ShowCharacterPalette", "shift-escape": "terminal::DeployModal" } } diff --git a/crates/terminal/src/connected_view.rs b/crates/terminal/src/connected_view.rs index 6f16ac9bcdd2a25fc70fbd391468cf974768d4ad..905c27d2b9bfce0d35678c2cca3fa03a3858ed4b 100644 --- a/crates/terminal/src/connected_view.rs +++ b/crates/terminal/src/connected_view.rs @@ -29,7 +29,17 @@ pub struct DeployContextMenu { actions!( terminal, - [Up, Down, CtrlC, Escape, Enter, Clear, Copy, Paste,] + [ + Up, + Down, + CtrlC, + Escape, + Enter, + Clear, + Copy, + Paste, + ShowCharacterPalette + ] ); impl_internal_actions!(project_panel, [DeployContextMenu]); @@ -45,6 +55,7 @@ pub fn init(cx: &mut MutableAppContext) { cx.add_action(ConnectedView::copy); cx.add_action(ConnectedView::paste); cx.add_action(ConnectedView::clear); + cx.add_action(ConnectedView::show_character_palette); } ///A terminal view, maintains the PTY's file handles and communicates with the terminal @@ -126,6 +137,10 @@ impl ConnectedView { cx.notify(); } + fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext) { + cx.show_character_palette(); + } + fn clear(&mut self, _: &Clear, cx: &mut ViewContext) { self.terminal.update(cx, |term, _| term.clear()); cx.notify(); diff --git a/crates/terminal/src/mappings/keys.rs b/crates/terminal/src/mappings/keys.rs index e07a3249984d07502e59ad473ba7f6e3f6d4b522..002759d78ddff932ea928706b7741a45ff4cb0f7 100644 --- a/crates/terminal/src/mappings/keys.rs +++ b/crates/terminal/src/mappings/keys.rs @@ -53,7 +53,6 @@ pub fn to_esc_str(keystroke: &Keystroke, mode: &TermMode) -> Option { // Manual Bindings including modifiers let manual_esc_str = match (keystroke.key.as_ref(), &modifiers) { //Basic special keys - ("space", Modifiers::None) => Some(" ".to_string()), ("tab", Modifiers::None) => Some("\x09".to_string()), ("escape", Modifiers::None) => Some("\x1b".to_string()), ("enter", Modifiers::None) => Some("\x0d".to_string()), From 5ad746e53f2326ddef644cf9773775b58a41ae17 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Tue, 16 Aug 2022 23:10:49 -0700 Subject: [PATCH 05/10] Added alt screen mode check --- crates/terminal/src/connected_view.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/terminal/src/connected_view.rs b/crates/terminal/src/connected_view.rs index 905c27d2b9bfce0d35678c2cca3fa03a3858ed4b..8de728b63886435d047a6c403f4d4ef883e5ef22 100644 --- a/crates/terminal/src/connected_view.rs +++ b/crates/terminal/src/connected_view.rs @@ -138,7 +138,14 @@ impl ConnectedView { } fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext) { - cx.show_character_palette(); + if self + .terminal + .read(cx) + .last_mode + .contains(TermMode::ALT_SCREEN) + { + cx.show_character_palette(); + } } fn clear(&mut self, _: &Clear, cx: &mut ViewContext) { From acce0042f90474263314180a71181c9e004a5392 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 17 Aug 2022 14:41:28 -0700 Subject: [PATCH 06/10] Fixed blink problems --- assets/settings/default.json | 11 ++--- crates/editor/src/element.rs | 55 ++++++------------------ crates/settings/src/settings.rs | 5 +-- crates/terminal/src/connected_el.rs | 60 ++++++--------------------- crates/terminal/src/connected_view.rs | 53 +++++++++++++++++++---- crates/terminal/src/terminal.rs | 21 +++++----- 6 files changed, 86 insertions(+), 119 deletions(-) diff --git a/assets/settings/default.json b/assets/settings/default.json index c6f08f4e5696ee22e7a795c3f10176ac4d98fdf2..144a34ba14acdc994aef9114f3f0dc267458c899 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -106,15 +106,12 @@ //May take 4 values: // 1. Never blink the cursor, ignoring the terminal mode // "blinking": "never", - // 2. Default the cursor blink to off, but allow the terminal to - // turn blinking on - // "blinking": "off", - // 3. Default the cursor blink to on, but allow the terminal to + // 2. Default the cursor blink to on, but allow the terminal to // turn blinking off - // "blinking": "on", - // 4. Always blink the cursor, ignoring the terminal mode + // "blinking": "terminal_controlled", + // 3. Always blink the cursor, ignoring the terminal mode // "blinking": "always", - "blinking": "on", + "blinking": "terminal_controlled", //Any key-value pairs added to this list will be added to the terminal's //enviroment. Use `:` to seperate multiple values. "env": { diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 6140731579455a9a98887bf524a5372edb5bad24..a68847904746f2afdca4b9143f7285d42228eea6 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1801,7 +1801,7 @@ impl Cursor { pub fn paint(&self, origin: Vector2F, cx: &mut PaintContext) { let bounds = match self.shape { 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, 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), 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 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 { - bounds: RectF::new( - self.origin + origin + Vector2F::new(0.0, -1.0), - vec2f(self.block_width + 1., 1.0), - ), - 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()), + bounds, + background: None, + border: Border::all(1., self.color), corner_radius: 0., }); - //Right + } else { cx.scene.push_quad(Quad { - bounds: RectF::new( - self.origin + origin + vec2f(self.block_width, 0.), - vec2f(1.0, self.line_height), - ), + bounds, background: Some(self.color), - border: Border::new(0., Color::black()), + border: Default::default(), corner_radius: 0., }); - } else { - if let Some(block_text) = &self.block_text { - block_text.paint(self.origin + origin, bounds, self.line_height, cx); - } + } + + if let Some(block_text) = &self.block_text { + block_text.paint(self.origin + origin, bounds, self.line_height, cx); } } } diff --git a/crates/settings/src/settings.rs b/crates/settings/src/settings.rs index 9c1a17a46215a0617c0473d460e6dd6fcff4a71a..124d5c292ab99c2ddced19277ae0324c00e303e1 100644 --- a/crates/settings/src/settings.rs +++ b/crates/settings/src/settings.rs @@ -90,14 +90,13 @@ pub struct TerminalSettings { #[serde(rename_all = "snake_case")] pub enum TerminalBlink { Never, - On, - Off, + TerminalControlled, Always, } impl Default for TerminalBlink { fn default() -> Self { - TerminalBlink::On + TerminalBlink::TerminalControlled } } diff --git a/crates/terminal/src/connected_el.rs b/crates/terminal/src/connected_el.rs index d017aad65b419f7b67c8ceed7e53bdd5c9106e86..b472a1c78ffa0a8fc74ec3ec00f3fe51a2d20ad1 100644 --- a/crates/terminal/src/connected_el.rs +++ b/crates/terminal/src/connected_el.rs @@ -21,7 +21,7 @@ use gpui::{ }; use itertools::Itertools; use ordered_float::OrderedFloat; -use settings::{Settings, TerminalBlink}; +use settings::Settings; use theme::TerminalStyle; use util::ResultExt; @@ -201,7 +201,7 @@ pub struct TerminalEl { view: WeakViewHandle, modal: bool, focused: bool, - blink_state: bool, + cursor_visible: bool, } impl TerminalEl { @@ -210,14 +210,14 @@ impl TerminalEl { terminal: WeakModelHandle, modal: bool, focused: bool, - blink_state: bool, + cursor_visible: bool, ) -> TerminalEl { TerminalEl { view, terminal, modal, focused, - blink_state, + cursor_visible, } } @@ -571,33 +571,6 @@ impl TerminalEl { (point, side) } - - pub fn should_show_cursor( - settings: Option, - 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 { @@ -610,7 +583,6 @@ impl Element for TerminalEl { cx: &mut gpui::LayoutContext, ) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) { let settings = cx.global::(); - let blink_settings = settings.terminal_overrides.blinking.clone(); let font_cache = cx.font_cache(); //Setup layout information @@ -629,13 +601,13 @@ impl Element for TerminalEl { 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 .upgrade(cx) .unwrap() .update(cx.app, |terminal, mcx| { terminal.set_size(dimensions); - terminal.render_lock(mcx, |content, cursor_text, blink_mode| { + terminal.render_lock(mcx, |content, cursor_text| { let mut cells = vec![]; cells.extend( content @@ -659,7 +631,6 @@ impl Element for TerminalEl { content.cursor, content.display_offset, cursor_text, - blink_mode, ) }) }); @@ -676,14 +647,7 @@ impl Element for TerminalEl { //Layout cursor let cursor = { - if !TerminalEl::should_show_cursor( - blink_settings, - blink_mode, - self.focused, - self.blink_state, - ) { - None - } else { + if self.cursor_visible { let cursor_point = DisplayCursor::from(cursor.point, display_offset); let cursor_text = { let str_trxt = cursor_text.to_string(); @@ -710,22 +674,24 @@ 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) + let shape = if self.focused { + CursorShape::Block } else { - (CursorShape::Hollow, terminal_theme.colors.foreground) + CursorShape::Hollow }; Cursor::new( cursor_position, block_width, dimensions.line_height, - color, + terminal_theme.colors.cursor, shape, Some(cursor_text), ) }, ) + } else { + None } }; diff --git a/crates/terminal/src/connected_view.rs b/crates/terminal/src/connected_view.rs index 8de728b63886435d047a6c403f4d4ef883e5ef22..be272d91196ca1446877205e76966205516132b7 100644 --- a/crates/terminal/src/connected_view.rs +++ b/crates/terminal/src/connected_view.rs @@ -11,6 +11,7 @@ use gpui::{ AnyViewHandle, AppContext, Element, ElementBox, ModelHandle, MutableAppContext, View, ViewContext, ViewHandle, }; +use settings::{Settings, TerminalBlink}; use smol::Timer; use workspace::pane; @@ -67,7 +68,8 @@ pub struct ConnectedView { // Only for styling purposes. Doesn't effect behavior modal: bool, context_menu: ViewHandle, - show_cursor: bool, + blink_state: bool, + blinking_on: bool, blinking_paused: bool, blink_epoch: usize, } @@ -91,7 +93,7 @@ impl ConnectedView { this.has_bell = true; cx.emit(Event::Wakeup); } - + Event::BlinkChanged => this.blinking_on = !this.blinking_on, _ => cx.emit(*event), }) .detach(); @@ -102,7 +104,8 @@ impl ConnectedView { has_bell: false, modal, context_menu: cx.add_view(ContextMenu::new), - show_cursor: true, + blink_state: true, + blinking_on: false, blinking_paused: false, blink_epoch: 0, } @@ -153,14 +156,46 @@ impl ConnectedView { cx.notify(); } - //Following code copied from editor cursor - pub fn blink_show(&self) -> bool { - self.blinking_paused || self.show_cursor + //2 -> Character palette shows up! But it's incorrectly positioned + + 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 + .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) { if epoch == self.blink_epoch && !self.blinking_paused { - self.show_cursor = !self.show_cursor; + self.blink_state = !self.blink_state; cx.notify(); let epoch = self.next_blink_epoch(); @@ -178,7 +213,7 @@ impl ConnectedView { } pub fn pause_cursor_blinking(&mut self, cx: &mut ViewContext) { - self.show_cursor = true; + self.blink_state = true; cx.notify(); let epoch = self.next_blink_epoch(); @@ -280,7 +315,7 @@ impl View for ConnectedView { terminal_handle, self.modal, focused, - self.blink_show(), + self.should_show_cursor(focused, cx), ) .contained() .boxed(), diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index 0debf4fa918e3a0129d2ad16ab4ca42c65f1a826..8b574f859702913ee87dee9902bed4bfa0ca9e3f 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -19,6 +19,8 @@ use alacritty_terminal::{ }; use anyhow::{bail, Result}; +//When you type a key, scroll does not happen in terminal !!!TODO + use futures::{ channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}, FutureExt, @@ -62,6 +64,7 @@ pub enum Event { CloseTerminal, Bell, Wakeup, + BlinkChanged, } #[derive(Clone, Debug)] @@ -295,14 +298,12 @@ impl TerminalBuilder { //Start off blinking if we need to match blink_settings { - Some(setting) => match setting { - TerminalBlink::On | TerminalBlink::Always => { - term.set_mode(alacritty_terminal::ansi::Mode::BlinkingCursor) - } - _ => {} - }, - None => term.set_mode(alacritty_terminal::ansi::Mode::BlinkingCursor), + None | Some(TerminalBlink::TerminalControlled) | Some(TerminalBlink::Always) => { + term.set_mode(alacritty_terminal::ansi::Mode::BlinkingCursor) + } + _ => {} } + let term = Arc::new(FairMutex::new(term)); //Setup the pty... @@ -479,7 +480,7 @@ impl Terminal { self.notify_pty(format(self.cur_size.into())) } AlacTermEvent::CursorBlinkingChange => { - //TODO whatever state we need to set to get the cursor blinking + cx.emit(Event::BlinkChanged); } AlacTermEvent::Bell => { cx.emit(Event::Bell); @@ -595,7 +596,7 @@ impl Terminal { pub fn render_lock(&mut self, cx: &mut ModelContext, f: F) -> T where - F: FnOnce(RenderableContent, char, bool) -> T, + F: FnOnce(RenderableContent, char) -> T, { let m = self.term.clone(); //Arc clone let mut term = m.lock(); @@ -611,7 +612,7 @@ impl Terminal { let cursor_text = term.grid()[content.cursor.point].c; - f(content, cursor_text, term.cursor_style().blinking) + f(content, cursor_text) } ///Scroll the terminal From 6652d4186469a469c9ab44fbd4c7fd42c6bd0bac Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 18 Aug 2022 11:28:18 -0700 Subject: [PATCH 07/10] Fixed cursor blinking, added other cursor shape rendering --- assets/settings/default.json | 8 +- crates/gpui/src/platform/mac/window.rs | 1 - crates/settings/src/settings.rs | 4 +- crates/terminal/src/connected_el.rs | 103 +++++++++++++------------ crates/terminal/src/connected_view.rs | 12 +-- crates/terminal/src/terminal.rs | 7 +- 6 files changed, 70 insertions(+), 65 deletions(-) diff --git a/assets/settings/default.json b/assets/settings/default.json index 144a34ba14acdc994aef9114f3f0dc267458c899..739b34d743fbac5596ac0c4b2acd7ddf89f951d1 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -105,12 +105,12 @@ //Set the cursor blinking behavior in the terminal. //May take 4 values: // 1. Never blink the cursor, ignoring the terminal mode - // "blinking": "never", - // 2. Default the cursor blink to on, but allow the terminal to - // turn blinking off + // "blinking": "off", + // 2. Default the cursor blink to off, but allow the terminal to + // set blinking // "blinking": "terminal_controlled", // 3. Always blink the cursor, ignoring the terminal mode - // "blinking": "always", + // "blinking": "on", "blinking": "terminal_controlled", //Any key-value pairs added to this list will be added to the terminal's //enviroment. Use `:` to seperate multiple values. diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index 5db530b9cfbb03c2ac74204a44f8a57630fce16d..503f2b87c5e271b116beb8ec0538b720e88cc804 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -1159,7 +1159,6 @@ extern "C" fn first_rect_for_character_range( let window = get_window_state(this).borrow().native_window; NSView::frame(window) }; - with_input_handler(this, |input_handler| { input_handler.rect_for_range(range.to_range()?) }) diff --git a/crates/settings/src/settings.rs b/crates/settings/src/settings.rs index 124d5c292ab99c2ddced19277ae0324c00e303e1..9defb6f41094d95ba3e8f31126664a1c5194bc40 100644 --- a/crates/settings/src/settings.rs +++ b/crates/settings/src/settings.rs @@ -89,9 +89,9 @@ pub struct TerminalSettings { #[derive(Clone, Debug, Deserialize, PartialEq, Eq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum TerminalBlink { - Never, + Off, TerminalControlled, - Always, + On, } impl Default for TerminalBlink { diff --git a/crates/terminal/src/connected_el.rs b/crates/terminal/src/connected_el.rs index b472a1c78ffa0a8fc74ec3ec00f3fe51a2d20ad1..230c8025031bd92b6028ecf58347c72ec55e3f3e 100644 --- a/crates/terminal/src/connected_el.rs +++ b/crates/terminal/src/connected_el.rs @@ -645,54 +645,59 @@ impl Element for TerminalEl { selection, ); - //Layout cursor - let cursor = { - if self.cursor_visible { - let cursor_point = DisplayCursor::from(cursor.point, display_offset); - let cursor_text = { - let str_trxt = cursor_text.to_string(); + //Layout cursor. Rectangle is used for IME, so we should lay it out even + //if we don't end up showing it. + let cursor = if let alacritty_terminal::ansi::CursorShape::Hidden = cursor.shape { + 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 + }; - 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 = match cursor.shape { + alacritty_terminal::ansi::CursorShape::Block if !self.focused => { + CursorShape::Hollow + } + alacritty_terminal::ansi::CursorShape::Block => CursorShape::Block, + alacritty_terminal::ansi::CursorShape::Underline => CursorShape::Underscore, + alacritty_terminal::ansi::CursorShape::Beam => CursorShape::Bar, + alacritty_terminal::ansi::CursorShape::HollowBlock => CursorShape::Hollow, + //This case is handled in the wrapping if + alacritty_terminal::ansi::CursorShape::Hidden => CursorShape::Block, }; - 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(), - }, - )], + Cursor::new( + cursor_position, + block_width, + dimensions.line_height, + terminal_theme.colors.cursor, + shape, + Some(cursor_text), ) - }; - - TerminalEl::shape_cursor(cursor_point, dimensions, &cursor_text).map( - move |(cursor_position, block_width)| { - let shape = if self.focused { - CursorShape::Block - } else { - CursorShape::Hollow - }; - - Cursor::new( - cursor_position, - block_width, - dimensions.line_height, - terminal_theme.colors.cursor, - shape, - Some(cursor_text), - ) - }, - ) - } else { - None - } + }, + ) }; //Done! @@ -783,10 +788,12 @@ impl Element for TerminalEl { }); //Draw cursor - if let Some(cursor) = &layout.cursor { - cx.paint_layer(clip_bounds, |cx| { - cursor.paint(origin, cx); - }) + if self.cursor_visible { + if let Some(cursor) = &layout.cursor { + cx.paint_layer(clip_bounds, |cx| { + cursor.paint(origin, cx); + }) + } } }); } diff --git a/crates/terminal/src/connected_view.rs b/crates/terminal/src/connected_view.rs index be272d91196ca1446877205e76966205516132b7..d4bbe7e0b55eee8ba98bdb15efab3c4c839c81d3 100644 --- a/crates/terminal/src/connected_view.rs +++ b/crates/terminal/src/connected_view.rs @@ -141,13 +141,17 @@ impl ConnectedView { } fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext) { - if self + if !self .terminal .read(cx) .last_mode .contains(TermMode::ALT_SCREEN) { cx.show_character_palette(); + } else { + self.terminal + .read(cx) + .try_keystroke(&Keystroke::parse("ctrl-cmd-space").unwrap()); } } @@ -156,8 +160,6 @@ impl ConnectedView { cx.notify(); } - //2 -> Character palette shows up! But it's incorrectly positioned - pub fn should_show_cursor( &self, focused: bool, @@ -187,9 +189,9 @@ impl ConnectedView { match setting { //If the user requested to never blink, don't blink it. - TerminalBlink::Never => true, + TerminalBlink::Off => true, //If the terminal is controlling it, check terminal mode - TerminalBlink::TerminalControlled | TerminalBlink::Always => self.blink_state, + TerminalBlink::TerminalControlled | TerminalBlink::On => self.blink_state, } } diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index 8b574f859702913ee87dee9902bed4bfa0ca9e3f..628020d3bc688fa08b34161065fe09cabc12e026 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -297,11 +297,8 @@ impl TerminalBuilder { let mut term = Term::new(&config, &initial_size, ZedListener(events_tx.clone())); //Start off blinking if we need to - match blink_settings { - None | Some(TerminalBlink::TerminalControlled) | Some(TerminalBlink::Always) => { - term.set_mode(alacritty_terminal::ansi::Mode::BlinkingCursor) - } - _ => {} + if let Some(TerminalBlink::On) = blink_settings { + term.set_mode(alacritty_terminal::ansi::Mode::BlinkingCursor) } let term = Arc::new(FairMutex::new(term)); From d545e59b4953c210880d638981db6e634cf70a72 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 18 Aug 2022 12:57:19 -0700 Subject: [PATCH 08/10] Finished IME for now --- crates/editor/src/element.rs | 4 ++++ crates/terminal/src/connected_el.rs | 20 +++++++++----------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index a68847904746f2afdca4b9143f7285d42228eea6..c935df7d07a47479b032cc16aad0d585c04a3c2a 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1832,6 +1832,10 @@ impl Cursor { block_text.paint(self.origin + origin, bounds, self.line_height, cx); } } + + pub fn shape(&self) -> CursorShape { + self.shape + } } #[derive(Debug)] diff --git a/crates/terminal/src/connected_el.rs b/crates/terminal/src/connected_el.rs index 230c8025031bd92b6028ecf58347c72ec55e3f3e..f21727af66eb69dcc2ed67c12054787f7660bdbb 100644 --- a/crates/terminal/src/connected_el.rs +++ b/crates/terminal/src/connected_el.rs @@ -1,5 +1,5 @@ use alacritty_terminal::{ - ansi::{Color as AnsiColor, Color::Named, NamedColor}, + ansi::{Color as AnsiColor, Color::Named, CursorShape as AlacCursorShape, NamedColor}, grid::{Dimensions, Scroll}, index::{Column as GridCol, Line as GridLine, Point, Side}, selection::SelectionRange, @@ -647,7 +647,7 @@ impl Element for TerminalEl { //Layout cursor. Rectangle is used for IME, so we should lay it out even //if we don't end up showing it. - let cursor = if let alacritty_terminal::ansi::CursorShape::Hidden = cursor.shape { + let cursor = if let AlacCursorShape::Hidden = cursor.shape { None } else { let cursor_point = DisplayCursor::from(cursor.point, display_offset); @@ -677,15 +677,13 @@ impl Element for TerminalEl { TerminalEl::shape_cursor(cursor_point, dimensions, &cursor_text).map( move |(cursor_position, block_width)| { let shape = match cursor.shape { - alacritty_terminal::ansi::CursorShape::Block if !self.focused => { - CursorShape::Hollow - } - alacritty_terminal::ansi::CursorShape::Block => CursorShape::Block, - alacritty_terminal::ansi::CursorShape::Underline => CursorShape::Underscore, - alacritty_terminal::ansi::CursorShape::Beam => CursorShape::Bar, - alacritty_terminal::ansi::CursorShape::HollowBlock => CursorShape::Hollow, - //This case is handled in the wrapping if - alacritty_terminal::ansi::CursorShape::Hidden => CursorShape::Block, + AlacCursorShape::Block if !self.focused => CursorShape::Hollow, + AlacCursorShape::Block => CursorShape::Block, + AlacCursorShape::Underline => CursorShape::Underscore, + AlacCursorShape::Beam => CursorShape::Bar, + AlacCursorShape::HollowBlock => CursorShape::Hollow, + //This case is handled in the if wrapping the whole cursor layout + AlacCursorShape::Hidden => unreachable!(), }; Cursor::new( From aa98e5c3f7c08087d8742473909dcc8807a96ce1 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 18 Aug 2022 13:22:48 -0700 Subject: [PATCH 09/10] Fixed scrolling on text input --- crates/terminal/README.md | 15 ++++++++-- crates/terminal/src/connected_view.rs | 42 ++++++++++++++------------- crates/terminal/src/terminal.rs | 33 ++++++++++----------- 3 files changed, 50 insertions(+), 40 deletions(-) diff --git a/crates/terminal/README.md b/crates/terminal/README.md index 99ab583ebbf8590b0137c0acc066ba2f7f261313..cdfdaffe854ef51533bd63f2bfb24199fd7b830c 100644 --- a/crates/terminal/README.md +++ b/crates/terminal/README.md @@ -4,6 +4,17 @@ This crate is split into two conceptual halves: - The terminal.rs file and the src/mappings/ folder, these contain the code for interacting with Alacritty and maintaining the pty event loop. Some behavior in this file is constrained by terminal protocols and standards. The Zed init function is also placed here. - Everything else. These other files integrate the `Terminal` struct created in terminal.rs into the rest of GPUI. The main entry point for GPUI is the terminal_view.rs file and the modal.rs file. -Terminals are created externally, and so can fail in unexpected ways However, GPUI currently does not have an API for models than can fail to instantiate. `TerminalBuilder` solves this by using Rust's type system to split `Terminal` instantiation into a 2 step process: first attempt to create the file handles with `TerminalBuilder::new()`, check the result, then call `TerminalBuilder::subscribe(cx)` from within a model context. -The TerminalView struct abstracts over failed and successful terminals, and provides a standardized way of instantiating an always-successful view of a terminal. +ttys are created externally, and so can fail in unexpected ways. However, GPUI currently does not have an API for models than can fail to instantiate. `TerminalBuilder` solves this by using Rust's type system to split tty instantiation into a 2 step process: first attempt to create the file handles with `TerminalBuilder::new()`, check the result, then call `TerminalBuilder::subscribe(cx)` from within a model context. + +The TerminalView struct abstracts over failed and successful terminals, passing focus through to the associated view and allowing clients to build a terminal without worrying about errors. + +#Input + +There are currently 3 distinct paths for getting keystrokes to the terminal: + +1. Terminal specific characters and bindings. Things like ctrl-a mapping to ASCII control character 1, ANSI escape codes associated with the function keys, etc. These are caught with a raw key-down handler in the element and are processed immediately. This is done with the `try_keystroke()` method on Terminal + +2. GPU Action handlers. GPUI clobbers a few vital keys by adding bindings to them in the global context. These keys are synthesized and then dispatched through the same `try_keystroke()` API as the above mappings + +3. IME text. When the special character mappings fail, we pass the keystroke back to GPUI to hand it to the IME system. This comes back to us in the `View::replace_text_in_range()` method, and we then send that to the terminal directly, bypassing `try_keystroke()`. diff --git a/crates/terminal/src/connected_view.rs b/crates/terminal/src/connected_view.rs index d4bbe7e0b55eee8ba98bdb15efab3c4c839c81d3..5b521748bb02b869d6d6688e76c8a6d6d8d0068b 100644 --- a/crates/terminal/src/connected_view.rs +++ b/crates/terminal/src/connected_view.rs @@ -149,9 +149,9 @@ impl ConnectedView { { cx.show_character_palette(); } else { - self.terminal - .read(cx) - .try_keystroke(&Keystroke::parse("ctrl-cmd-space").unwrap()); + self.terminal.update(cx, |term, _| { + term.try_keystroke(&Keystroke::parse("ctrl-cmd-space").unwrap()) + }); } } @@ -258,41 +258,41 @@ impl ConnectedView { ///Synthesize the keyboard event corresponding to 'up' fn up(&mut self, _: &Up, cx: &mut ViewContext) { self.clear_bel(cx); - self.terminal - .read(cx) - .try_keystroke(&Keystroke::parse("up").unwrap()); + self.terminal.update(cx, |term, _| { + term.try_keystroke(&Keystroke::parse("up").unwrap()) + }); } ///Synthesize the keyboard event corresponding to 'down' fn down(&mut self, _: &Down, cx: &mut ViewContext) { self.clear_bel(cx); - self.terminal - .read(cx) - .try_keystroke(&Keystroke::parse("down").unwrap()); + self.terminal.update(cx, |term, _| { + term.try_keystroke(&Keystroke::parse("down").unwrap()) + }); } ///Synthesize the keyboard event corresponding to 'ctrl-c' fn ctrl_c(&mut self, _: &CtrlC, cx: &mut ViewContext) { self.clear_bel(cx); - self.terminal - .read(cx) - .try_keystroke(&Keystroke::parse("ctrl-c").unwrap()); + self.terminal.update(cx, |term, _| { + term.try_keystroke(&Keystroke::parse("ctrl-c").unwrap()) + }); } ///Synthesize the keyboard event corresponding to 'escape' fn escape(&mut self, _: &Escape, cx: &mut ViewContext) { self.clear_bel(cx); - self.terminal - .read(cx) - .try_keystroke(&Keystroke::parse("escape").unwrap()); + self.terminal.update(cx, |term, _| { + term.try_keystroke(&Keystroke::parse("escape").unwrap()) + }); } ///Synthesize the keyboard event corresponding to 'enter' fn enter(&mut self, _: &Enter, cx: &mut ViewContext) { self.clear_bel(cx); - self.terminal - .read(cx) - .try_keystroke(&Keystroke::parse("enter").unwrap()); + self.terminal.update(cx, |term, _| { + term.try_keystroke(&Keystroke::parse("enter").unwrap()) + }); } } @@ -358,8 +358,10 @@ impl View for ConnectedView { text: &str, cx: &mut ViewContext, ) { - self.terminal - .update(cx, |terminal, _| terminal.write_to_pty(text.into())); + self.terminal.update(cx, |terminal, _| { + terminal.write_to_pty(text.into()); + terminal.scroll(alacritty_terminal::grid::Scroll::Bottom); + }); } fn keymap_context(&self, _: &gpui::AppContext) -> gpui::keymap::Context { diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index 628020d3bc688fa08b34161065fe09cabc12e026..f550688edc74b2a5cd88ecfed3ea7e1ade4b0dd8 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -467,14 +467,14 @@ impl Terminal { AlacTermEvent::ClipboardStore(_, data) => { cx.write_to_clipboard(ClipboardItem::new(data.to_string())) } - AlacTermEvent::ClipboardLoad(_, format) => self.notify_pty(format( + AlacTermEvent::ClipboardLoad(_, format) => self.write_to_pty(format( &cx.read_from_clipboard() .map(|ci| ci.text().to_string()) .unwrap_or_else(|| "".to_string()), )), - AlacTermEvent::PtyWrite(out) => self.notify_pty(out.clone()), + AlacTermEvent::PtyWrite(out) => self.write_to_pty(out.clone()), AlacTermEvent::TextAreaSizeRequest(format) => { - self.notify_pty(format(self.cur_size.into())) + self.write_to_pty(format(self.cur_size.into())) } AlacTermEvent::CursorBlinkingChange => { cx.emit(Event::BlinkChanged); @@ -517,7 +517,7 @@ impl Terminal { let term_style = &cx.global::().theme.terminal; to_alac_rgb(get_color_at_index(index, &term_style.colors)) }); - self.notify_pty(format(color)) + self.write_to_pty(format(color)) } } InternalEvent::Resize(new_size) => { @@ -528,7 +528,7 @@ impl Terminal { term.resize(*new_size); } InternalEvent::Clear => { - self.notify_pty("\x0c".to_string()); + self.write_to_pty("\x0c".to_string()); term.clear_screen(ClearMode::Saved); } InternalEvent::Scroll(scroll) => term.scroll_display(*scroll), @@ -548,12 +548,8 @@ impl Terminal { } } - pub fn notify_pty(&self, txt: String) { - self.pty_tx.notify(txt.into_bytes()); - } - ///Write the Input payload to the tty. - pub fn write_to_pty(&mut self, input: String) { + pub fn write_to_pty(&self, input: String) { self.pty_tx.notify(input.into_bytes()); } @@ -566,10 +562,11 @@ impl Terminal { self.events.push(InternalEvent::Clear) } - pub fn try_keystroke(&self, keystroke: &Keystroke) -> bool { + pub fn try_keystroke(&mut self, keystroke: &Keystroke) -> bool { let esc = to_esc_str(keystroke, &self.last_mode); if let Some(esc) = esc { - self.notify_pty(esc); + self.write_to_pty(esc); + self.scroll(Scroll::Bottom); true } else { false @@ -579,11 +576,11 @@ impl Terminal { ///Paste text into the terminal pub fn paste(&self, text: &str) { if self.last_mode.contains(TermMode::BRACKETED_PASTE) { - self.notify_pty("\x1b[200~".to_string()); - self.notify_pty(text.replace('\x1b', "")); - self.notify_pty("\x1b[201~".to_string()); + self.write_to_pty("\x1b[200~".to_string()); + self.write_to_pty(text.replace('\x1b', "")); + self.write_to_pty("\x1b[201~".to_string()); } else { - self.notify_pty(text.replace("\r\n", "\r").replace('\n', "\r")); + self.write_to_pty(text.replace("\r\n", "\r").replace('\n', "\r")); } } @@ -619,13 +616,13 @@ impl Terminal { pub fn focus_in(&self) { if self.last_mode.contains(TermMode::FOCUS_IN_OUT) { - self.notify_pty("\x1b[I".to_string()); + self.write_to_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()); + self.write_to_pty("\x1b[O".to_string()); } } From 2c4ea7f01d97752f13a5ae6816ee772a98548a59 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 18 Aug 2022 13:24:00 -0700 Subject: [PATCH 10/10] Remove todo --- crates/terminal/src/terminal.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index f550688edc74b2a5cd88ecfed3ea7e1ade4b0dd8..5254ffbe7fbcdf474249fa80fe46ebd1e3a30cf8 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -19,8 +19,6 @@ use alacritty_terminal::{ }; use anyhow::{bail, Result}; -//When you type a key, scroll does not happen in terminal !!!TODO - use futures::{ channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}, FutureExt,