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 <dennis@kobert.dev>
This commit is contained in:
Timon 2025-09-25 14:52:41 +00:00 committed by Dennis Kobert
parent ed22e6a63d
commit d06c8164e1
No known key found for this signature in database
GPG Key ID: 5A4358CB9530F933
1 changed files with 45 additions and 30 deletions

View File

@ -151,7 +151,7 @@ impl InputState {
fn mouse_input(&mut self, button: &MouseButton, state: &ElementState) -> ClickCount { fn mouse_input(&mut self, button: &MouseButton, state: &ElementState) -> ClickCount {
self.mouse_state.update(button, state); 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 { 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 { pub(crate) struct MousePosition {
x: usize, x: usize,
y: usize, y: usize,
@ -233,7 +233,7 @@ struct ClickTracker {
right: Option<ClickRecord>, right: Option<ClickRecord>,
} }
impl ClickTracker { 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 { let record = match button {
MouseButton::Left => &mut self.left, MouseButton::Left => &mut self.left,
MouseButton::Right => &mut self.right, MouseButton::Right => &mut self.right,
@ -241,53 +241,56 @@ impl ClickTracker {
_ => return ClickCount::Single, _ => return ClickCount::Single,
}; };
let now = Instant::now();
let Some(record) = record else { let Some(record) = record else {
*record = Some(ClickRecord { *record = Some(ClickRecord { position, ..Default::default() });
time: now,
position: position.clone(),
down_count: ClickCount::Single,
up_count: ClickCount::Single,
});
return ClickCount::Single; 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 dx = position.x.abs_diff(record.position.x);
let dy = position.y.abs_diff(record.position.y); let dy = position.y.abs_diff(record.position.y);
let within_dist = dx <= MULTICLICK_ALLOWED_TRAVEL && dy <= MULTICLICK_ALLOWED_TRAVEL; 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 }; let count = if within_time && within_dist { ClickCount::Double } else { ClickCount::Single };
*record = match state { *record = match state {
ElementState::Pressed => ClickRecord { ElementState::Pressed => ClickRecord { down_count: count, ..*record },
time: now, ElementState::Released => ClickRecord { up_count: count, ..*record },
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(),
},
}; };
count count
} }
} }
#[derive(Clone)] #[derive(Clone, Copy, PartialEq, Default)]
enum ClickCount { enum ClickCount {
#[default]
Single, Single,
Double, Double,
} }
impl Default for ClickCount {
fn default() -> Self {
Self::Single
}
}
impl From<ClickCount> for i32 { impl From<ClickCount> for i32 {
fn from(count: ClickCount) -> i32 { fn from(count: ClickCount) -> i32 {
match count { match count {
@ -297,6 +300,7 @@ impl From<ClickCount> for i32 {
} }
} }
#[derive(Clone, Copy)]
struct ClickRecord { struct ClickRecord {
time: Instant, time: Instant,
position: MousePosition, position: MousePosition,
@ -304,6 +308,17 @@ struct ClickRecord {
up_count: ClickCount, 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); struct CefModifiers(u32);
impl CefModifiers { impl CefModifiers {
fn new(input_state: &InputState, location: &winit::keyboard::KeyLocation, is_repeat: bool) -> Self { fn new(input_state: &InputState, location: &winit::keyboard::KeyLocation, is_repeat: bool) -> Self {