From d06c8164e16e181c5c0dbb53ae5d35db383067be Mon Sep 17 00:00:00 2001 From: Timon Date: Thu, 25 Sep 2025 14:52:41 +0000 Subject: [PATCH] Desktop: Forward multi-clicks (double/triple/etc.-clicks) to CEF correctly (#3224) * fix multiclick * Revert "fix multiclick" This reverts commit c4130d12ee3f9e13b531da18d2285ea1a34a65b0. * try another way * use copy * Use struct initializer syntax fror click tracker (#3226) --------- Co-authored-by: Dennis Kobert --- desktop/src/cef/input.rs | 75 ++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 30 deletions(-) diff --git a/desktop/src/cef/input.rs b/desktop/src/cef/input.rs index 6b0badad..e50871b1 100644 --- a/desktop/src/cef/input.rs +++ b/desktop/src/cef/input.rs @@ -151,7 +151,7 @@ impl InputState { fn mouse_input(&mut self, button: &MouseButton, state: &ElementState) -> ClickCount { self.mouse_state.update(button, state); - self.mouse_click_tracker.input(button, state, &self.mouse_position) + self.mouse_click_tracker.input(button, state, self.mouse_position) } fn cef_modifiers(&self, location: &winit::keyboard::KeyLocation, is_repeat: bool) -> CefModifiers { @@ -187,7 +187,7 @@ impl From<&mut InputState> for MouseEvent { } } -#[derive(Default, Clone)] +#[derive(Default, Clone, Copy)] pub(crate) struct MousePosition { x: usize, y: usize, @@ -233,7 +233,7 @@ struct ClickTracker { right: Option, } impl ClickTracker { - fn input(&mut self, button: &MouseButton, state: &ElementState, position: &MousePosition) -> ClickCount { + fn input(&mut self, button: &MouseButton, state: &ElementState, position: MousePosition) -> ClickCount { let record = match button { MouseButton::Left => &mut self.left, MouseButton::Right => &mut self.right, @@ -241,53 +241,56 @@ impl ClickTracker { _ => return ClickCount::Single, }; - let now = Instant::now(); - let Some(record) = record else { - *record = Some(ClickRecord { - time: now, - position: position.clone(), - down_count: ClickCount::Single, - up_count: ClickCount::Single, - }); + *record = Some(ClickRecord { position, ..Default::default() }); return ClickCount::Single; }; + let previous = record.time; + + let now = Instant::now(); + record.time = now; + record.position = position; + + match state { + ElementState::Pressed if record.down_count == ClickCount::Double => { + *record = ClickRecord { + down_count: ClickCount::Single, + ..*record + }; + return ClickCount::Single; + } + ElementState::Released if record.up_count == ClickCount::Double => { + *record = ClickRecord { + up_count: ClickCount::Single, + ..*record + }; + return ClickCount::Single; + } + _ => {} + } + let dx = position.x.abs_diff(record.position.x); let dy = position.y.abs_diff(record.position.y); let within_dist = dx <= MULTICLICK_ALLOWED_TRAVEL && dy <= MULTICLICK_ALLOWED_TRAVEL; - let within_time = now.saturating_duration_since(record.time) <= MULTICLICK_TIMEOUT; + let within_time = now.saturating_duration_since(previous) <= MULTICLICK_TIMEOUT; let count = if within_time && within_dist { ClickCount::Double } else { ClickCount::Single }; *record = match state { - ElementState::Pressed => ClickRecord { - time: now, - position: position.clone(), - down_count: count.clone(), - up_count: record.up_count.clone(), - }, - ElementState::Released => ClickRecord { - time: now, - position: position.clone(), - down_count: record.down_count.clone(), - up_count: count.clone(), - }, + ElementState::Pressed => ClickRecord { down_count: count, ..*record }, + ElementState::Released => ClickRecord { up_count: count, ..*record }, }; count } } -#[derive(Clone)] +#[derive(Clone, Copy, PartialEq, Default)] enum ClickCount { + #[default] Single, Double, } -impl Default for ClickCount { - fn default() -> Self { - Self::Single - } -} impl From for i32 { fn from(count: ClickCount) -> i32 { match count { @@ -297,6 +300,7 @@ impl From for i32 { } } +#[derive(Clone, Copy)] struct ClickRecord { time: Instant, position: MousePosition, @@ -304,6 +308,17 @@ struct ClickRecord { up_count: ClickCount, } +impl Default for ClickRecord { + fn default() -> Self { + Self { + time: Instant::now(), + position: Default::default(), + down_count: Default::default(), + up_count: Default::default(), + } + } +} + struct CefModifiers(u32); impl CefModifiers { fn new(input_state: &InputState, location: &winit::keyboard::KeyLocation, is_repeat: bool) -> Self {