aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
Diffstat (limited to 'components/script')
-rw-r--r--components/script/dom/bindings/trace.rs3
-rw-r--r--components/script/dom/document.rs57
2 files changed, 59 insertions, 1 deletions
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index 507e19e4bcb..1f46b3f649c 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -85,7 +85,7 @@ use std::rc::Rc;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicUsize};
use std::sync::mpsc::{Receiver, Sender};
-use std::time::SystemTime;
+use std::time::{SystemTime, Instant};
use string_cache::{Atom, Namespace, QualName};
use style::attr::{AttrIdentifier, AttrValue, LengthOrPercentageOrAuto};
use style::domrefcell::DOMRefCell;
@@ -341,6 +341,7 @@ no_jsmanaged_fields!(USVString);
no_jsmanaged_fields!(ReferrerPolicy);
no_jsmanaged_fields!(ResourceThreads);
no_jsmanaged_fields!(SystemTime);
+no_jsmanaged_fields!(Instant);
no_jsmanaged_fields!(RelativePos);
no_jsmanaged_fields!(OpaqueStyleAndLayoutData);
no_jsmanaged_fields!(PathBuf);
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 4322e348c92..d0eebc77c80 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -119,6 +119,7 @@ use std::iter::once;
use std::mem;
use std::rc::Rc;
use std::sync::Arc;
+use std::time::{Duration, Instant};
use string_cache::{Atom, QualName};
use style::attr::AttrValue;
use style::context::ReflowGoal;
@@ -247,6 +248,9 @@ pub struct Document {
referrer: Option<String>,
/// https://html.spec.whatwg.org/multipage/#target-element
target_element: MutNullableHeap<JS<Element>>,
+ /// https://w3c.github.io/uievents/#event-type-dblclick
+ #[ignore_heap_size_of = "Defined in std"]
+ last_click_info: DOMRefCell<Option<(Instant, Point2D<f32>)>>,
}
#[derive(JSTraceable, HeapSizeOf)]
@@ -774,12 +778,64 @@ impl Document {
if let MouseEventType::Click = mouse_event_type {
self.commit_focus_transaction(FocusType::Element);
+ self.maybe_fire_dblclick(client_point, node);
}
+
self.window.reflow(ReflowGoal::ForDisplay,
ReflowQueryType::NoQuery,
ReflowReason::MouseEvent);
}
+ fn maybe_fire_dblclick(&self, click_pos: Point2D<f32>, target: &Node) {
+ // https://w3c.github.io/uievents/#event-type-dblclick
+ let now = Instant::now();
+
+ let opt = self.last_click_info.borrow_mut().take();
+
+ if let Some((last_time, last_pos)) = opt {
+ let DBL_CLICK_TIMEOUT = Duration::from_millis(PREFS.get("dom.document.dblclick_timeout").as_u64()
+ .unwrap_or(300));
+ let DBL_CLICK_DIST_THRESHOLD = PREFS.get("dom.document.dblclick_dist").as_u64().unwrap_or(1);
+
+ // Calculate distance between this click and the previous click.
+ let line = click_pos - last_pos;
+ let dist = (line.dot(line) as f64).sqrt();
+
+ if now.duration_since(last_time) < DBL_CLICK_TIMEOUT &&
+ dist < DBL_CLICK_DIST_THRESHOLD as f64 {
+ // A double click has occurred if this click is within a certain time and dist. of previous click.
+ let clickCount = 2;
+ let client_x = click_pos.x as i32;
+ let client_y = click_pos.y as i32;
+
+ let event = MouseEvent::new(&self.window,
+ DOMString::from("dblclick"),
+ EventBubbles::Bubbles,
+ EventCancelable::Cancelable,
+ Some(&self.window),
+ clickCount,
+ client_x,
+ client_y,
+ client_x,
+ client_y,
+ false,
+ false,
+ false,
+ false,
+ 0i16,
+ None);
+ event.upcast::<Event>().fire(target.upcast());
+
+ // When a double click occurs, self.last_click_info is left as None so that a
+ // third sequential click will not cause another double click.
+ return;
+ }
+ }
+
+ // Update last_click_info with the time and position of the click.
+ *self.last_click_info.borrow_mut() = Some((now, click_pos));
+ }
+
pub fn handle_touchpad_pressure_event(&self,
js_runtime: *mut JSRuntime,
client_point: Point2D<f32>,
@@ -1759,6 +1815,7 @@ impl Document {
referrer: referrer,
referrer_policy: Cell::new(referrer_policy),
target_element: MutNullableHeap::new(None),
+ last_click_info: DOMRefCell::new(None),
}
}