Fix linux double click (#18504)

Patrick MARIE created

Closes #17573

Release Notes:

- Check that double clicks on Linux are triggered by same button.

Change summary

crates/gpui/src/platform/linux/wayland/client.rs |  7 +++++++
crates/gpui/src/platform/linux/x11/client.rs     | 10 ++++++++--
2 files changed, 15 insertions(+), 2 deletions(-)

Detailed changes

crates/gpui/src/platform/linux/wayland/client.rs 🔗

@@ -236,6 +236,7 @@ pub struct DragState {
 }
 
 pub struct ClickState {
+    last_mouse_button: Option<MouseButton>,
     last_click: Instant,
     last_location: Point<Pixels>,
     current_count: usize,
@@ -535,6 +536,7 @@ impl WaylandClient {
             },
             click: ClickState {
                 last_click: Instant::now(),
+                last_mouse_button: None,
                 last_location: Point::default(),
                 current_count: 0,
             },
@@ -1524,6 +1526,10 @@ impl Dispatch<wl_pointer::WlPointer, ()> for WaylandClientStatePtr {
                         let click_elapsed = state.click.last_click.elapsed();
 
                         if click_elapsed < DOUBLE_CLICK_INTERVAL
+                            && state
+                                .click
+                                .last_mouse_button
+                                .is_some_and(|prev_button| prev_button == button)
                             && is_within_click_distance(
                                 state.click.last_location,
                                 state.mouse_location.unwrap(),
@@ -1535,6 +1541,7 @@ impl Dispatch<wl_pointer::WlPointer, ()> for WaylandClientStatePtr {
                         }
 
                         state.click.last_click = Instant::now();
+                        state.click.last_mouse_button = Some(button);
                         state.click.last_location = state.mouse_location.unwrap();
 
                         state.button_pressed = Some(button);

crates/gpui/src/platform/linux/x11/client.rs 🔗

@@ -37,8 +37,8 @@ use crate::platform::linux::LinuxClient;
 use crate::platform::{LinuxCommon, PlatformWindow};
 use crate::{
     modifiers_from_xinput_info, point, px, AnyWindowHandle, Bounds, ClipboardItem, CursorStyle,
-    DisplayId, FileDropEvent, Keystroke, Modifiers, ModifiersChangedEvent, Pixels, Platform,
-    PlatformDisplay, PlatformInput, Point, ScaledPixels, ScrollDelta, Size, TouchPhase,
+    DisplayId, FileDropEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton, Pixels,
+    Platform, PlatformDisplay, PlatformInput, Point, ScaledPixels, ScrollDelta, Size, TouchPhase,
     WindowParams, X11Window,
 };
 
@@ -122,6 +122,7 @@ pub struct X11ClientState {
     pub(crate) event_loop: Option<calloop::EventLoop<'static, X11Client>>,
 
     pub(crate) last_click: Instant,
+    pub(crate) last_mouse_button: Option<MouseButton>,
     pub(crate) last_location: Point<Pixels>,
     pub(crate) current_count: usize,
 
@@ -404,6 +405,7 @@ impl X11Client {
             loop_handle: handle,
             common,
             last_click: Instant::now(),
+            last_mouse_button: None,
             last_location: Point::new(px(0.0), px(0.0)),
             current_count: 0,
             scale_factor,
@@ -952,6 +954,9 @@ impl X11Client {
                     let click_elapsed = state.last_click.elapsed();
 
                     if click_elapsed < DOUBLE_CLICK_INTERVAL
+                        && state
+                            .last_mouse_button
+                            .is_some_and(|prev_button| prev_button == button)
                         && is_within_click_distance(state.last_location, position)
                     {
                         state.current_count += 1;
@@ -960,6 +965,7 @@ impl X11Client {
                     }
 
                     state.last_click = Instant::now();
+                    state.last_mouse_button = Some(button);
                     state.last_location = position;
                     let current_count = state.current_count;