diff --git a/druid-shell/src/platform/web/window.rs b/druid-shell/src/platform/web/window.rs index c94b6d1fb0..860afb5e5b 100644 --- a/druid-shell/src/platform/web/window.rs +++ b/druid-shell/src/platform/web/window.rs @@ -19,6 +19,7 @@ use std::cell::{Cell, RefCell}; use std::ffi::OsString; use std::rc::{Rc, Weak}; use std::sync::{Arc, Mutex}; +use std::time::Duration; use instant::Instant; @@ -44,6 +45,9 @@ use crate::region::Region; use crate::window; use crate::window::{FileDialogToken, IdleToken, TimerToken, WinHandler, WindowLevel}; +// This is the default timing on windows. +const MULTI_CLICK_INTERVAL: Duration = Duration::from_millis(500); + // This is a macro instead of a function since KeyboardEvent and MouseEvent has identical functions // to query modifier key states. macro_rules! get_modifiers { @@ -97,6 +101,13 @@ struct WindowState { canvas: web_sys::HtmlCanvasElement, context: web_sys::CanvasRenderingContext2d, invalid: RefCell, + click_counter: ClickCounter, +} + +#[derive(Debug, Clone)] +struct ClickCounter { + last_click: Cell, + click_count: Cell, } // TODO: support custom cursors @@ -162,16 +173,42 @@ impl WindowState { } } +impl ClickCounter { + fn new() -> ClickCounter { + ClickCounter { + // @cmyr: I had a weird panic here once? + last_click: Cell::new( + Instant::now() + .checked_sub(MULTI_CLICK_INTERVAL) + .unwrap_or_else(Instant::now), + ), + click_count: Cell::new(0), + } + } + + fn current_click_count(&self) -> u8 { + let click_time = Instant::now(); + let last_time = self.last_click.replace(click_time); + if click_time - last_time > MULTI_CLICK_INTERVAL { + self.click_count.set(0); + } + let click_count = self.click_count.get().saturating_add(1); + self.click_count.set(click_count); + click_count + } +} + fn setup_mouse_down_callback(ws: &Rc) { let state = ws.clone(); register_canvas_event_listener(ws, "mousedown", move |event: web_sys::MouseEvent| { if let Some(button) = mouse_button(event.button()) { + let count = state.click_counter.current_click_count(); let buttons = mouse_buttons(event.buttons()); let event = MouseEvent { pos: Point::new(event.offset_x() as f64, event.offset_y() as f64), buttons, mods: get_modifiers!(event), - count: 1, + count, focus: false, button, wheel_delta: Vec2::ZERO, @@ -416,6 +453,7 @@ impl WindowBuilder { canvas, context, invalid: RefCell::new(Region::EMPTY), + click_counter: ClickCounter::new(), }); setup_web_callbacks(&window);