diff --git a/src/bridge/events.rs b/src/bridge/events.rs index af867ad7..7f5bd30a 100644 --- a/src/bridge/events.rs +++ b/src/bridge/events.rs @@ -601,7 +601,7 @@ fn parse_mode_change(mode_change_arguments: Vec) -> Result { "insert" => EditorMode::Insert, "visual" => EditorMode::Visual, "replace" => EditorMode::Replace, - "cmdline_normal" => EditorMode::CmdLine, + "cmdline_normal" | "cmdline_insert" | "cmdline_replace" => EditorMode::CmdLine, _ => EditorMode::Unknown(mode_name), }, mode_index: parse_u64(mode_index)?, diff --git a/src/editor/mod.rs b/src/editor/mod.rs index 6aa2fc8f..15e880ec 100644 --- a/src/editor/mod.rs +++ b/src/editor/mod.rs @@ -20,7 +20,7 @@ use winit::event_loop::EventLoopProxy; use winit::window::Theme; use crate::{ - bridge::{GridLineCell, GuiOption, NeovimHandler, RedrawEvent, WindowAnchor}, + bridge::{EditorMode, GridLineCell, GuiOption, NeovimHandler, RedrawEvent, WindowAnchor}, clipboard::ClipboardHandle, profiling::{tracy_named_frame, tracy_zone}, renderer::{DrawCommand, WindowDrawCommand, rendered_window::BASE_GRID_ID}, @@ -36,8 +36,6 @@ pub use style::{Colors, Style, UnderlineStyle}; pub use window::*; use intro::{IntroMessageExtender, IntroProcessing}; - -const MODE_CMDLINE: u64 = 4; pub const MSG_ZINDEX: u64 = 200; // See the documenation for nvim_open_win #[derive(Clone, Debug, PartialEq, Eq)] @@ -116,6 +114,7 @@ pub struct Editor { pub mode_list: Vec, pub draw_command_batcher: DrawCommandBatcher, pub current_mode_index: Option, + current_mode: EditorMode, pub ui_ready: bool, event_loop_proxy: EventLoopProxy, route_id: RouteId, @@ -158,6 +157,7 @@ impl Editor { mode_list: Vec::new(), draw_command_batcher: DrawCommandBatcher::new(), current_mode_index: None, + current_mode: EditorMode::Normal, ui_ready: false, settings, event_loop_proxy, @@ -202,6 +202,7 @@ impl Editor { } else { self.current_mode_index = None } + self.current_mode = mode.clone(); self.draw_command_batcher.queue(DrawCommand::ModeChanged(mode)); } RedrawEvent::MouseOn => { @@ -657,8 +658,7 @@ impl Editor { let already_there = self.cursor.parent_window_id == grid; // This ^ check alone is a bit buggy though, since it fails when the cursor is // technically still in the edit window but "temporarily" at the cmdline. (#1207) - let using_cmdline = - self.current_mode_index.map(|current| current == MODE_CMDLINE).unwrap_or(false); + let using_cmdline = matches!(self.current_mode, EditorMode::CmdLine); if !intentional && !already_there && !using_cmdline { trace!( diff --git a/src/renderer/cursor_renderer/mod.rs b/src/renderer/cursor_renderer/mod.rs index 07c78f23..b8c89dcc 100644 --- a/src/renderer/cursor_renderer/mod.rs +++ b/src/renderer/cursor_renderer/mod.rs @@ -135,6 +135,8 @@ impl Corner { } if immediate_movement { + self.animation_x.reset(); + self.animation_y.reset(); self.current_position = corner_destination; return false; } @@ -214,6 +216,38 @@ impl Corner { } } +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum CmdlineCtx { + Inactive, + Active { window: u64 }, + Exiting { window: u64 }, +} + +impl CmdlineCtx { + fn active(current_window: u64) -> Self { + Self::Active { window: current_window } + } + + fn exiting_or_inactive(window: u64, current_window: u64) -> Self { + if current_window == window { Self::Exiting { window } } else { Self::Inactive } + } + + fn advance(self, current_mode: &EditorMode, current_window: u64) -> Self { + let in_cmdline = matches!(current_mode, EditorMode::CmdLine); + + if in_cmdline { + return Self::active(current_window); + } + + match self { + Self::Inactive => Self::Inactive, + Self::Active { window } | Self::Exiting { window } => { + Self::exiting_or_inactive(window, current_window) + } + } + } +} + pub struct CursorRenderer { pub corners: Vec, cursor: Cursor, @@ -221,7 +255,7 @@ pub struct CursorRenderer { blink_status: BlinkStatus, previous_cursor_position: Option<(u64, GridPos)>, previous_cursor_shape: Option, - previous_editor_mode: EditorMode, + cmdline_ctx: CmdlineCtx, cursor_vfxs: Vec>, previous_vfx_mode: cursor_vfx::VfxModeList, window_has_focus: bool, @@ -239,7 +273,7 @@ impl CursorRenderer { blink_status: BlinkStatus::new(), previous_cursor_position: None, previous_cursor_shape: None, - previous_editor_mode: EditorMode::Normal, + cmdline_ctx: CmdlineCtx::Inactive, cursor_vfxs: vec![], previous_vfx_mode: cursor_vfx::VfxModeList::default(), window_has_focus: true, @@ -434,8 +468,9 @@ impl CursorRenderer { let in_insert_mode = matches!(current_mode, EditorMode::Insert); - let changed_to_from_cmdline = !matches!(self.previous_editor_mode, EditorMode::CmdLine) - ^ matches!(current_mode, EditorMode::CmdLine); + let next_cmdline_ctx = self.cmdline_ctx.advance(current_mode, self.cursor.parent_window_id); + let changed_to_from_cmdline = !matches!(self.cmdline_ctx, CmdlineCtx::Inactive) + ^ !matches!(next_cmdline_ctx, CmdlineCtx::Inactive); let center_destination = self.destination + cursor_dimensions.to_vector() * 0.5; @@ -455,7 +490,7 @@ impl CursorRenderer { if center_destination != PixelPos::ZERO { let immediate_movement = !settings.animate_in_insert_mode && in_insert_mode - || !settings.animate_command_line && !changed_to_from_cmdline; + || !settings.animate_command_line && changed_to_from_cmdline; if self.jumped { // Caclculate the direction alignment for each corner and generate a sorted list // This way we know which corner is the front and which is the back @@ -522,14 +557,11 @@ impl CursorRenderer { animating |= vfx_animating; } self.jumped = false; + self.cmdline_ctx = next_cmdline_ctx; let blink_animating = settings.smooth_blink && self.blink_status.should_animate(); animating |= blink_animating; - - if !animating { - self.previous_editor_mode = current_mode.clone(); - } tracy_plot!("cursor animating", animating as u8 as f64); animating }