Desktop: Fix drag followed by a click causing a double click (#3721)

* Fix drag followed by a click causing a double click

* Review

* Fix quadruple click bug and cleanup

bug: quadruple bypassing time and distance check logic

* Improve readability

---------

Co-authored-by: Timon <me@timon.zip>
This commit is contained in:
Vishnu Tejas 2026-03-24 05:51:02 +05:30 committed by GitHub
parent 11b7af61ef
commit 36366b34f2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 29 additions and 32 deletions

View File

@ -133,51 +133,46 @@ impl ClickTracker {
}; };
let Some(record) = record else { 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; return ClickCount::Single;
}; };
let prev_time = record.time;
let prev_position = record.position;
let prev_count: ClickCount = record.down_count;
let now = Instant::now(); let now = Instant::now();
record.time = now; let within_time = now.saturating_duration_since(record.time) <= MULTICLICK_TIMEOUT;
record.position = position;
match state { let (prev_count, prev_position) = match state {
ElementState::Pressed if record.down_count == ClickCount::Triple => { ElementState::Pressed => (record.down_count, record.down_position),
*record = ClickRecord { ElementState::Released => (record.up_count, record.up_position),
down_count: ClickCount::Double, };
..*record
};
return ClickCount::Double;
}
ElementState::Released if record.up_count == ClickCount::Triple => {
*record = ClickRecord {
up_count: ClickCount::Double,
..*record
};
return ClickCount::Double;
}
_ => {}
}
let dx = position.x.abs_diff(prev_position.x); let dx = position.x.abs_diff(prev_position.x);
let dy = position.y.abs_diff(prev_position.y); let dy = position.y.abs_diff(prev_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(prev_time) <= MULTICLICK_TIMEOUT;
let count = match (prev_count, within_time, within_dist) { let count = match (prev_count, within_time, within_dist) {
(ClickCount::Single, true, true) => ClickCount::Double,
(ClickCount::Double, true, true) => ClickCount::Triple, (ClickCount::Double, true, true) => ClickCount::Triple,
(_, true, true) => ClickCount::Double, (ClickCount::Triple, true, true) => ClickCount::Double,
_ => ClickCount::Single, _ => ClickCount::Single,
}; };
*record = match state { record.time = now;
ElementState::Pressed => ClickRecord { down_count: count, ..*record },
ElementState::Released => ClickRecord { up_count: count, ..*record }, match state {
}; ElementState::Pressed => {
record.down_position = position;
record.down_count = count;
}
ElementState::Released => {
record.up_position = position;
record.up_count = count;
}
}
count count
} }
} }
@ -202,7 +197,8 @@ impl From<ClickCount> for i32 {
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
struct ClickRecord { struct ClickRecord {
time: Instant, time: Instant,
position: MousePosition, down_position: MousePosition,
up_position: MousePosition,
down_count: ClickCount, down_count: ClickCount,
up_count: ClickCount, up_count: ClickCount,
} }
@ -211,7 +207,8 @@ impl Default for ClickRecord {
fn default() -> Self { fn default() -> Self {
Self { Self {
time: Instant::now(), time: Instant::now(),
position: Default::default(), down_position: Default::default(),
up_position: Default::default(),
down_count: Default::default(), down_count: Default::default(),
up_count: Default::default(), up_count: Default::default(),
} }