aboutsummaryrefslogtreecommitdiff
path: root/src/click.rs
diff options
context:
space:
mode:
authorPolesznyák Márk <contact@pml68.dev>2026-02-05 14:20:35 +0100
committerPolesznyák Márk <contact@pml68.dev>2026-02-05 14:21:32 +0100
commit5eddb62f3cae4740680eaa81d448c3eeda88068a (patch)
treef45e6b7afaa8ed3a2a5dea5e65685f83017c0eb7 /src/click.rs
parentchore: bump MSRV to match iced's (diff)
downloadiced_selection-5eddb62f3cae4740680eaa81d448c3eeda88068a.tar.gz
feat: make click interval for double & triple clicks customizable
Diffstat (limited to '')
-rw-r--r--src/click.rs87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/click.rs b/src/click.rs
new file mode 100644
index 0000000..83e6956
--- /dev/null
+++ b/src/click.rs
@@ -0,0 +1,87 @@
+use crate::core::Point;
+use crate::core::mouse::Button;
+use crate::core::time::{Duration, Instant};
+
+/// A mouse click.
+#[derive(Debug, Clone, Copy)]
+pub struct Click {
+ kind: Kind,
+ button: Button,
+ position: Point,
+ time: Instant,
+ click_interval: Duration,
+}
+
+/// The kind of mouse click.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum Kind {
+ /// A single click
+ Single,
+
+ /// A double click
+ Double,
+
+ /// A triple click
+ Triple,
+}
+
+impl Kind {
+ fn next(self) -> Kind {
+ match self {
+ Kind::Single => Kind::Double,
+ Kind::Double => Kind::Triple,
+ Kind::Triple => Kind::Double,
+ }
+ }
+}
+
+impl Click {
+ /// Creates a new [`Click`] with the given position and previous last
+ /// [`Click`].
+ pub fn new(
+ position: Point,
+ button: Button,
+ previous: Option<Click>,
+ click_interval: Option<Duration>,
+ ) -> Click {
+ let time = Instant::now();
+
+ let kind = if let Some(previous) = previous {
+ if previous.is_consecutive(position, time)
+ && button == previous.button
+ {
+ previous.kind.next()
+ } else {
+ Kind::Single
+ }
+ } else {
+ Kind::Single
+ };
+
+ Click {
+ kind,
+ button,
+ position,
+ time,
+ click_interval: click_interval
+ .unwrap_or(Duration::from_millis(300)),
+ }
+ }
+
+ pub fn kind(&self) -> Kind {
+ self.kind
+ }
+
+ fn is_consecutive(&self, new_position: Point, time: Instant) -> bool {
+ let duration = if time > self.time {
+ Some(time - self.time)
+ } else {
+ None
+ };
+
+ self.position.distance(new_position) < 6.0
+ && duration
+ .map(|duration| duration <= self.click_interval)
+ .unwrap_or(false)
+ }
+}