keymap_ui: Dismiss context menu less frequently (#34387)

Finn Evers created

This PR fixes an issue where the context menu in the keymap UI would be
immediately dismissed after being opened when using a trackpad on MacOS.

Right clicking on MacOS almost always fires a scroll event with a delta
of 0 pixels right after (which is not the case when using a mouse). The
fired scroll event caused the context menu to be removed on the next
frame. This change ensures the menu is only removed when a vertical
scroll is actually happening.

Release Notes:

- N/A

Change summary

crates/settings_ui/src/keybindings.rs | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)

Detailed changes

crates/settings_ui/src/keybindings.rs 🔗

@@ -11,9 +11,9 @@ use fs::Fs;
 use fuzzy::{StringMatch, StringMatchCandidate};
 use gpui::{
     Action, AnimationExt, AppContext as _, AsyncApp, ClickEvent, Context, DismissEvent, Entity,
-    EventEmitter, FocusHandle, Focusable, Global, KeyContext, KeyDownEvent, Keystroke,
-    ModifiersChangedEvent, MouseButton, Point, ScrollStrategy, StyledText, Subscription,
-    WeakEntity, actions, anchored, deferred, div,
+    EventEmitter, FocusHandle, Focusable, Global, IsZero, KeyContext, KeyDownEvent, Keystroke,
+    ModifiersChangedEvent, MouseButton, Point, ScrollStrategy, ScrollWheelEvent, StyledText,
+    Subscription, WeakEntity, actions, anchored, deferred, div,
 };
 use language::{Language, LanguageConfig, ToOffset as _};
 use settings::{BaseKeymap, KeybindSource, KeymapFile, SettingsAssets};
@@ -1182,9 +1182,13 @@ impl Render for KeymapEditor {
                         }),
                     ),
             )
-            .on_scroll_wheel(cx.listener(|this, _, _, cx| {
-                this.context_menu.take();
-                cx.notify();
+            .on_scroll_wheel(cx.listener(|this, event: &ScrollWheelEvent, _, cx| {
+                // This ensures that the menu is not dismissed in cases where scroll events
+                // with a delta of zero are emitted
+                if !event.delta.pixel_delta(px(1.)).y.is_zero() {
+                    this.context_menu.take();
+                    cx.notify();
+                }
             }))
             .children(self.context_menu.as_ref().map(|(menu, position, _)| {
                 deferred(