From e18da9ef6d8019ac726e050d9b15cab931d9e738 Mon Sep 17 00:00:00 2001 From: Finn Eitreim <48069764+feitreim@users.noreply.github.com> Date: Mon, 20 Apr 2026 14:57:19 -0400 Subject: [PATCH] vim: Prevent flickering during movement actions (#52270) ## Context Closes #52202 Some actions we're unnecessarily delayed during execution by a yield_now().await call, causing flickering while moving around. Video Before: https://github.com/user-attachments/assets/f9922915-8bc7-4e9e-8ce9-18a1e898b69e Video After: https://github.com/user-attachments/assets/a46a6338-3fef-4784-8fd7-ecec07a28cf6 ## How to Review when we call the yield in workspace.rs ## Self-Review Checklist - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - vim: fixed screen flickering during motions. Co-authored-by: Cameron Mcloughlin --- crates/workspace/src/workspace.rs | 37 +++++++++++++++++-------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 50e74a02bff299407b2844ca5da1638f244e1c03..40d6a36969267efb9e8de4e1207a9c95878e84ed 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -3364,24 +3364,27 @@ impl Workspace { }; keystroke }; - cx.update(|window, cx| { - let focused = window.focused(cx); - window.dispatch_keystroke(keystroke.clone(), cx); - if window.focused(cx) != focused { - // dispatch_keystroke may cause the focus to change. - // draw's side effect is to schedule the FocusChanged events in the current flush effect cycle - // And we need that to happen before the next keystroke to keep vim mode happy... - // (Note that the tests always do this implicitly, so you must manually test with something like: - // "bindings": { "g z": ["workspace::SendKeystrokes", ": j u"]} - // ) - window.draw(cx).clear(); - } - }) - .ok(); + let focus_changed = cx + .update(|window, cx| { + let focused = window.focused(cx); + window.dispatch_keystroke(keystroke.clone(), cx); + if window.focused(cx) != focused { + // dispatch_keystroke may cause the focus to change. + // draw's side effect is to schedule the FocusChanged events in the current flush effect cycle + // And we need that to happen before the next keystroke to keep vim mode happy... + // (Note that the tests always do this implicitly, so you must manually test with something like: + // "bindings": { "g z": ["workspace::SendKeystrokes", ": j u"]} + // ) + window.draw(cx).clear(); + return true; + } + false + }) + .unwrap_or(false); - // Yield between synthetic keystrokes so deferred focus and - // other effects can settle before dispatching the next key. - yield_now().await; + if focus_changed { + yield_now().await; + } } *keystrokes.borrow_mut() = Default::default();