From dd431631b43ce33bd21494122ab74db691fec549 Mon Sep 17 00:00:00 2001 From: Finn Evers Date: Wed, 10 Dec 2025 15:28:19 +0100 Subject: [PATCH] editor: Ensure completion menu scrollbar does not become stale (#44536) Only by reusing the previous scroll handle, we can ensure that both the scrollbar remains usable and also that the scrollbar does not flicker. Previously, the scrollbar would hold the reference to an outdated handle. I tried invalidating the handle the scrollbar uses, but that leads to flickering, which is worse. Hence, let's just reuse the scrollbar here. Release Notes: - Fixed an issue where the scrollbar would become stale in the code completions menu after the items were updated. --- crates/editor/src/code_context_menus.rs | 13 +++++++++++-- crates/editor/src/editor.rs | 10 +++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/crates/editor/src/code_context_menus.rs b/crates/editor/src/code_context_menus.rs index dcd9667420..d255effdb7 100644 --- a/crates/editor/src/code_context_menus.rs +++ b/crates/editor/src/code_context_menus.rs @@ -206,6 +206,13 @@ impl CodeContextMenu { CodeContextMenu::CodeActions(_) => (), } } + + pub fn primary_scroll_handle(&self) -> UniformListScrollHandle { + match self { + CodeContextMenu::Completions(menu) => menu.scroll_handle.clone(), + CodeContextMenu::CodeActions(menu) => menu.scroll_handle.clone(), + } + } } pub enum ContextMenuOrigin { @@ -303,6 +310,7 @@ impl CompletionsMenu { is_incomplete: bool, buffer: Entity, completions: Box<[Completion]>, + scroll_handle: Option, display_options: CompletionDisplayOptions, snippet_sort_order: SnippetSortOrder, language_registry: Option>, @@ -332,7 +340,7 @@ impl CompletionsMenu { selected_item: 0, filter_task: Task::ready(()), cancel_filter: Arc::new(AtomicBool::new(false)), - scroll_handle: UniformListScrollHandle::new(), + scroll_handle: scroll_handle.unwrap_or_else(UniformListScrollHandle::new), scroll_handle_aside: ScrollHandle::new(), resolve_completions: true, last_rendered_range: RefCell::new(None).into(), @@ -354,6 +362,7 @@ impl CompletionsMenu { choices: &Vec, selection: Range, buffer: Entity, + scroll_handle: Option, snippet_sort_order: SnippetSortOrder, ) -> Self { let completions = choices @@ -404,7 +413,7 @@ impl CompletionsMenu { selected_item: 0, filter_task: Task::ready(()), cancel_filter: Arc::new(AtomicBool::new(false)), - scroll_handle: UniformListScrollHandle::new(), + scroll_handle: scroll_handle.unwrap_or_else(UniformListScrollHandle::new), scroll_handle_aside: ScrollHandle::new(), resolve_completions: false, show_completion_documentation: false, diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index d841bf858b..aa22675864 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -5882,6 +5882,11 @@ impl Editor { is_incomplete, buffer.clone(), completions.into(), + editor + .context_menu() + .borrow_mut() + .as_ref() + .map(|menu| menu.primary_scroll_handle()), display_options, snippet_sort_order, languages, @@ -10016,13 +10021,16 @@ impl Editor { let id = post_inc(&mut self.next_completion_id); let snippet_sort_order = EditorSettings::get_global(cx).snippet_sort_order; - *self.context_menu.borrow_mut() = Some(CodeContextMenu::Completions( + let mut context_menu = self.context_menu.borrow_mut(); + let old_menu = context_menu.take(); + *context_menu = Some(CodeContextMenu::Completions( CompletionsMenu::new_snippet_choices( id, true, choices, selection, buffer, + old_menu.map(|menu| menu.primary_scroll_handle()), snippet_sort_order, ), ));