From b600ef7a1a57177f069756a7dc19ef86ef21685d Mon Sep 17 00:00:00 2001 From: Vishnu Tejas E Date: Wed, 18 Feb 2026 18:54:04 +0530 Subject: [PATCH 1/4] Fix drag followed by a click causing a double click --- desktop/src/cef/input/state.rs | 43 +++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/desktop/src/cef/input/state.rs b/desktop/src/cef/input/state.rs index 2c3355dca8..2ed90e66aa 100644 --- a/desktop/src/cef/input/state.rs +++ b/desktop/src/cef/input/state.rs @@ -91,6 +91,13 @@ impl From<&PhysicalPosition> for MousePosition { } } } +impl MousePosition { + fn within_distance(self, other: Self) -> bool { + let dx = self.x.abs_diff(other.x); + let dy = self.y.abs_diff(other.y); + dx <= MULTICLICK_ALLOWED_TRAVEL && dy <= MULTICLICK_ALLOWED_TRAVEL + } +} #[derive(Default, Clone)] pub(crate) struct MouseState { @@ -133,21 +140,23 @@ impl ClickTracker { }; let Some(record) = record else { - *record = Some(ClickRecord { position, ..Default::default() }); + *record = Some(ClickRecord { + down_position: position, + up_position: position, + ..Default::default() + }); return ClickCount::Single; }; let prev_time = record.time; - let prev_position = record.position; - let prev_count: ClickCount = record.down_count; let now = Instant::now(); record.time = now; - record.position = position; match state { ElementState::Pressed if record.down_count == ClickCount::Triple => { *record = ClickRecord { + down_position: position, down_count: ClickCount::Double, ..*record }; @@ -155,6 +164,7 @@ impl ClickTracker { } ElementState::Released if record.up_count == ClickCount::Triple => { *record = ClickRecord { + up_position: position, up_count: ClickCount::Double, ..*record }; @@ -163,10 +173,11 @@ impl ClickTracker { _ => {} } - let dx = position.x.abs_diff(prev_position.x); - let dy = position.y.abs_diff(prev_position.y); - let within_dist = dx <= MULTICLICK_ALLOWED_TRAVEL && dy <= MULTICLICK_ALLOWED_TRAVEL; let within_time = now.saturating_duration_since(prev_time) <= MULTICLICK_TIMEOUT; + let (prev_count, within_dist) = match state { + ElementState::Pressed => (record.down_count, position.within_distance(record.down_position)), + ElementState::Released => (record.up_count, position.within_distance(record.up_position)), + }; let count = match (prev_count, within_time, within_dist) { (ClickCount::Double, true, true) => ClickCount::Triple, @@ -175,8 +186,16 @@ impl ClickTracker { }; *record = match state { - ElementState::Pressed => ClickRecord { down_count: count, ..*record }, - ElementState::Released => ClickRecord { up_count: count, ..*record }, + ElementState::Pressed => ClickRecord { + down_position: position, + down_count: count, + ..*record + }, + ElementState::Released => ClickRecord { + up_position: position, + up_count: count, + ..*record + }, }; count } @@ -202,7 +221,8 @@ impl From for i32 { #[derive(Clone, Copy)] struct ClickRecord { time: Instant, - position: MousePosition, + down_position: MousePosition, + up_position: MousePosition, down_count: ClickCount, up_count: ClickCount, } @@ -211,7 +231,8 @@ impl Default for ClickRecord { fn default() -> Self { Self { time: Instant::now(), - position: Default::default(), + down_position: Default::default(), + up_position: Default::default(), down_count: Default::default(), up_count: Default::default(), } From e10e680aa2800996b102b945d83ab159b8d1484d Mon Sep 17 00:00:00 2001 From: Timon Date: Thu, 5 Mar 2026 20:28:30 +0000 Subject: [PATCH 2/4] Review --- desktop/src/cef/input/state.rs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/desktop/src/cef/input/state.rs b/desktop/src/cef/input/state.rs index 2ed90e66aa..9bec0ae198 100644 --- a/desktop/src/cef/input/state.rs +++ b/desktop/src/cef/input/state.rs @@ -91,13 +91,6 @@ impl From<&PhysicalPosition> for MousePosition { } } } -impl MousePosition { - fn within_distance(self, other: Self) -> bool { - let dx = self.x.abs_diff(other.x); - let dy = self.y.abs_diff(other.y); - dx <= MULTICLICK_ALLOWED_TRAVEL && dy <= MULTICLICK_ALLOWED_TRAVEL - } -} #[derive(Default, Clone)] pub(crate) struct MouseState { @@ -173,13 +166,22 @@ impl ClickTracker { _ => {} } - let within_time = now.saturating_duration_since(prev_time) <= MULTICLICK_TIMEOUT; - let (prev_count, within_dist) = match state { - ElementState::Pressed => (record.down_count, position.within_distance(record.down_position)), - ElementState::Released => (record.up_count, position.within_distance(record.up_position)), + let prev_count = match state { + ElementState::Pressed => record.down_count, + ElementState::Released => record.up_count, }; - let count = match (prev_count, within_time, within_dist) { + let prev_position = match state { + ElementState::Pressed => record.down_position, + ElementState::Released => record.up_position, + }; + let within_dist_x = position.x.abs_diff(prev_position.x) <= MULTICLICK_ALLOWED_TRAVEL; + let within_dist_y = position.y.abs_diff(prev_position.y) <= MULTICLICK_ALLOWED_TRAVEL; + let within_dist = within_dist_x && within_dist_y; + + let within_time = now.saturating_duration_since(prev_time) <= MULTICLICK_TIMEOUT; + + let count = match (prev_count, within_dist, within_time) { (ClickCount::Double, true, true) => ClickCount::Triple, (_, true, true) => ClickCount::Double, _ => ClickCount::Single, From b46a26c22f077facfdc1d6693ff5ec3bb42ebd67 Mon Sep 17 00:00:00 2001 From: Timon Date: Thu, 5 Mar 2026 20:50:56 +0000 Subject: [PATCH 3/4] Fix quadruple click bug and cleanup bug: quadruple bypassing time and distance check logic --- desktop/src/cef/input/state.rs | 70 ++++++++++------------------------ 1 file changed, 21 insertions(+), 49 deletions(-) diff --git a/desktop/src/cef/input/state.rs b/desktop/src/cef/input/state.rs index 9bec0ae198..1da8e57d49 100644 --- a/desktop/src/cef/input/state.rs +++ b/desktop/src/cef/input/state.rs @@ -141,64 +141,36 @@ impl ClickTracker { return ClickCount::Single; }; - let prev_time = record.time; - let now = Instant::now(); - record.time = now; + let within_time = now.saturating_duration_since(record.time) <= MULTICLICK_TIMEOUT; - match state { - ElementState::Pressed if record.down_count == ClickCount::Triple => { - *record = ClickRecord { - down_position: position, - down_count: ClickCount::Double, - ..*record - }; - return ClickCount::Double; - } - ElementState::Released if record.up_count == ClickCount::Triple => { - *record = ClickRecord { - up_position: position, - up_count: ClickCount::Double, - ..*record - }; - return ClickCount::Double; - } - _ => {} - } - - let prev_count = match state { - ElementState::Pressed => record.down_count, - ElementState::Released => record.up_count, - }; - - let prev_position = match state { - ElementState::Pressed => record.down_position, - ElementState::Released => record.up_position, + let (prev_count, prev_position) = match state { + ElementState::Pressed => (record.down_count, record.down_position), + ElementState::Released => (record.up_count, record.up_position), }; - let within_dist_x = position.x.abs_diff(prev_position.x) <= MULTICLICK_ALLOWED_TRAVEL; - let within_dist_y = position.y.abs_diff(prev_position.y) <= MULTICLICK_ALLOWED_TRAVEL; - let within_dist = within_dist_x && within_dist_y; - let within_time = now.saturating_duration_since(prev_time) <= MULTICLICK_TIMEOUT; + let within_dist = position.x.abs_diff(prev_position.x) <= MULTICLICK_ALLOWED_TRAVEL && position.y.abs_diff(prev_position.y) <= MULTICLICK_ALLOWED_TRAVEL; - let count = match (prev_count, within_dist, within_time) { + let count = match (prev_count, within_time, within_dist) { + (ClickCount::Single, true, true) => ClickCount::Double, (ClickCount::Double, true, true) => ClickCount::Triple, - (_, true, true) => ClickCount::Double, + (ClickCount::Triple, true, true) => ClickCount::Double, _ => ClickCount::Single, }; - *record = match state { - ElementState::Pressed => ClickRecord { - down_position: position, - down_count: count, - ..*record - }, - ElementState::Released => ClickRecord { - up_position: position, - up_count: count, - ..*record - }, - }; + record.time = now; + + match state { + ElementState::Pressed => { + record.down_position = position; + record.down_count = count; + } + ElementState::Released => { + record.up_position = position; + record.up_count = count; + } + } + count } } From 753057da41c9a9796ee8cb0fb03d68de30d9041d Mon Sep 17 00:00:00 2001 From: Timon Date: Thu, 5 Mar 2026 21:00:30 +0000 Subject: [PATCH 4/4] Improve readability --- desktop/src/cef/input/state.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/desktop/src/cef/input/state.rs b/desktop/src/cef/input/state.rs index 1da8e57d49..45d3c9c7ac 100644 --- a/desktop/src/cef/input/state.rs +++ b/desktop/src/cef/input/state.rs @@ -149,7 +149,9 @@ impl ClickTracker { ElementState::Released => (record.up_count, record.up_position), }; - let within_dist = position.x.abs_diff(prev_position.x) <= MULTICLICK_ALLOWED_TRAVEL && position.y.abs_diff(prev_position.y) <= MULTICLICK_ALLOWED_TRAVEL; + let dx = position.x.abs_diff(prev_position.x); + let dy = position.y.abs_diff(prev_position.y); + let within_dist = dx <= MULTICLICK_ALLOWED_TRAVEL && dy <= MULTICLICK_ALLOWED_TRAVEL; let count = match (prev_count, within_time, within_dist) { (ClickCount::Single, true, true) => ClickCount::Double,