X11: Double click (#9739)

This copies the logic from #9608 to the X11 client.

Fixes #9707.

Release Notes:
- N/A

Co-authored-by: Mikayla Maki <mikayla@zed.dev>
This commit is contained in:
Paul 2024-03-25 19:44:31 +01:00 committed by GitHub
parent 030e299b27
commit 4789c02a19
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,6 +1,6 @@
use std::cell::RefCell; use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
use std::time::Duration; use std::time::{Duration, Instant};
use collections::HashMap; use collections::HashMap;
use copypasta::x11_clipboard::{Clipboard, Primary, X11ClipboardContext}; use copypasta::x11_clipboard::{Clipboard, Primary, X11ClipboardContext};
@ -19,11 +19,13 @@ use xkbcommon::xkb as xkbc;
use crate::platform::linux::client::Client; use crate::platform::linux::client::Client;
use crate::platform::{LinuxPlatformInner, PlatformWindow}; use crate::platform::{LinuxPlatformInner, PlatformWindow};
use crate::{ use crate::{
AnyWindowHandle, Bounds, CursorStyle, DisplayId, PlatformDisplay, PlatformInput, Point, px, AnyWindowHandle, Bounds, CursorStyle, DisplayId, Pixels, PlatformDisplay, PlatformInput,
ScrollDelta, Size, TouchPhase, WindowParams, Point, ScrollDelta, Size, TouchPhase, WindowParams,
}; };
use super::{super::SCROLL_LINES, X11Display, X11Window, X11WindowState, XcbAtoms}; use super::{super::SCROLL_LINES, X11Display, X11Window, X11WindowState, XcbAtoms};
use crate::platform::linux::platform::DOUBLE_CLICK_INTERVAL;
use crate::platform::linux::util::is_within_click_distance;
use calloop::{ use calloop::{
generic::{FdWrapper, Generic}, generic::{FdWrapper, Generic},
RegistrationToken, RegistrationToken,
@ -39,6 +41,13 @@ struct X11ClientState {
xkb: xkbc::State, xkb: xkbc::State,
clipboard: Rc<RefCell<X11ClipboardContext<Clipboard>>>, clipboard: Rc<RefCell<X11ClipboardContext<Clipboard>>>,
primary: Rc<RefCell<X11ClipboardContext<Primary>>>, primary: Rc<RefCell<X11ClipboardContext<Primary>>>,
click_state: ClickState,
}
struct ClickState {
last_click: Instant,
last_location: Point<Pixels>,
current_count: usize,
} }
pub(crate) struct X11Client { pub(crate) struct X11Client {
@ -85,6 +94,11 @@ impl X11Client {
let xcb_connection = Rc::new(xcb_connection); let xcb_connection = Rc::new(xcb_connection);
let click_state = ClickState {
last_click: Instant::now(),
last_location: Point::new(px(0.0), px(0.0)),
current_count: 0,
};
let client: Rc<X11Client> = Rc::new(Self { let client: Rc<X11Client> = Rc::new(Self {
platform_inner: inner.clone(), platform_inner: inner.clone(),
xcb_connection: Rc::clone(&xcb_connection), xcb_connection: Rc::clone(&xcb_connection),
@ -95,6 +109,7 @@ impl X11Client {
xkb: xkb_state, xkb: xkb_state,
clipboard: Rc::new(RefCell::new(clipboard)), clipboard: Rc::new(RefCell::new(clipboard)),
primary: Rc::new(RefCell::new(primary)), primary: Rc::new(RefCell::new(primary)),
click_state,
}), }),
}); });
@ -213,11 +228,25 @@ impl X11Client {
let position = let position =
Point::new((event.event_x as f32).into(), (event.event_y as f32).into()); Point::new((event.event_x as f32).into(), (event.event_y as f32).into());
if let Some(button) = super::button_of_key(event.detail) { if let Some(button) = super::button_of_key(event.detail) {
let mut state = self.state.borrow_mut();
let click_elapsed = state.click_state.last_click.elapsed();
if click_elapsed < DOUBLE_CLICK_INTERVAL
&& is_within_click_distance(state.click_state.last_location, position)
{
state.click_state.current_count += 1;
} else {
state.click_state.current_count = 1;
}
state.click_state.last_click = Instant::now();
state.click_state.last_location = position;
window.handle_input(PlatformInput::MouseDown(crate::MouseDownEvent { window.handle_input(PlatformInput::MouseDown(crate::MouseDownEvent {
button, button,
position, position,
modifiers, modifiers,
click_count: 1, click_count: state.click_state.current_count,
first_mouse: false, first_mouse: false,
})); }));
} else if event.detail >= 4 && event.detail <= 5 { } else if event.detail >= 4 && event.detail <= 5 {
@ -239,12 +268,13 @@ impl X11Client {
let modifiers = super::modifiers_from_state(event.state); let modifiers = super::modifiers_from_state(event.state);
let position = let position =
Point::new((event.event_x as f32).into(), (event.event_y as f32).into()); Point::new((event.event_x as f32).into(), (event.event_y as f32).into());
let state = self.state.borrow();
if let Some(button) = super::button_of_key(event.detail) { if let Some(button) = super::button_of_key(event.detail) {
window.handle_input(PlatformInput::MouseUp(crate::MouseUpEvent { window.handle_input(PlatformInput::MouseUp(crate::MouseUpEvent {
button, button,
position, position,
modifiers, modifiers,
click_count: 1, click_count: state.click_state.current_count,
})); }));
} }
} }