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 b597dfb778..c36cdf7fe6 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 c36cdf7fe6..507b04bd1a 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 8c31f686cb..5db530b9cf 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 6f34facc42..b40a076c49 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 6f16ac9bcd..905c27d2b9 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 e07a324998..002759d78d 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 905c27d2b9..8de728b638 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 | 61 +++++++-------------------- 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, 89 insertions(+), 122 deletions(-) diff --git a/assets/settings/default.json b/assets/settings/default.json index c6f08f4e56..144a34ba14 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 6140731579..a688479047 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()), - corner_radius: 0., - }); - //Right - cx.scene.push_quad(Quad { - bounds: RectF::new( - self.origin + origin + vec2f(self.block_width, 0.), - 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., }); } else { - 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: Default::default(), + corner_radius: 0., + }); + } + + 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 9c1a17a462..124d5c292a 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 d017aad65b..b472a1c78f 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 8de728b638..be272d9119 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 0debf4fa91..8b574f8597 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 144a34ba14..739b34d743 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 5db530b9cf..503f2b87c5 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 124d5c292a..9defb6f410 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 b472a1c78f..230c802503 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 - }; - - 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 color = if self.focused { + terminal_theme.colors.background + } else { + terminal_theme.colors.foreground }; - 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), - ) - }, + 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(), + }, + )], ) - } else { - None - } + }; + + 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, + }; + + Cursor::new( + cursor_position, + block_width, + dimensions.line_height, + terminal_theme.colors.cursor, + shape, + Some(cursor_text), + ) + }, + ) }; //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 be272d9119..d4bbe7e0b5 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 8b574f8597..628020d3bc 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 a688479047..c935df7d07 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 230c802503..f21727af66 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 99ab583ebb..cdfdaffe85 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 d4bbe7e0b5..5b521748bb 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 628020d3bc..f550688edc 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 f550688edc..5254ffbe7f 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,