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 dcd96674207f02101b4066924b011d2b9ebd7a08..d255effdb72a003014dff0805fa34a23d11c8c81 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 d841bf858b8a77f502b8bfb2499118f9e714572e..aa226758648ac0d140edc6aa7b019c6271910848 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, ), ));