mirror of
https://github.com/servo/servo.git
synced 2025-06-25 09:34:32 +01:00
Auto merge of #13130 - samuknet:dblclick, r=nox
'dblclick' event <!-- Please describe your changes on the following line: --> * Add field to document struct to store information about last 'click' event * Add code to `handle_mouse_event` function to detect and fire double click events --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [ X] `./mach build -d` does not report any errors - [X ] `./mach test-tidy` does not report any errors - [X ] These changes fix #12767 (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [X ] These changes do not require tests because it is input related <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/13130) <!-- Reviewable:end -->
This commit is contained in:
commit
67bfd0df4b
2 changed files with 59 additions and 1 deletions
|
@ -87,7 +87,7 @@ use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{AtomicBool, AtomicUsize};
|
use std::sync::atomic::{AtomicBool, AtomicUsize};
|
||||||
use std::sync::mpsc::{Receiver, Sender};
|
use std::sync::mpsc::{Receiver, Sender};
|
||||||
use std::time::SystemTime;
|
use std::time::{SystemTime, Instant};
|
||||||
use string_cache::{Atom, Namespace, QualName};
|
use string_cache::{Atom, Namespace, QualName};
|
||||||
use style::attr::{AttrIdentifier, AttrValue, LengthOrPercentageOrAuto};
|
use style::attr::{AttrIdentifier, AttrValue, LengthOrPercentageOrAuto};
|
||||||
use style::domrefcell::DOMRefCell;
|
use style::domrefcell::DOMRefCell;
|
||||||
|
@ -346,6 +346,7 @@ no_jsmanaged_fields!(ResponseBody);
|
||||||
no_jsmanaged_fields!(ResourceThreads);
|
no_jsmanaged_fields!(ResourceThreads);
|
||||||
no_jsmanaged_fields!(StatusCode);
|
no_jsmanaged_fields!(StatusCode);
|
||||||
no_jsmanaged_fields!(SystemTime);
|
no_jsmanaged_fields!(SystemTime);
|
||||||
|
no_jsmanaged_fields!(Instant);
|
||||||
no_jsmanaged_fields!(RelativePos);
|
no_jsmanaged_fields!(RelativePos);
|
||||||
no_jsmanaged_fields!(OpaqueStyleAndLayoutData);
|
no_jsmanaged_fields!(OpaqueStyleAndLayoutData);
|
||||||
no_jsmanaged_fields!(PathBuf);
|
no_jsmanaged_fields!(PathBuf);
|
||||||
|
|
|
@ -119,6 +119,7 @@ use std::iter::once;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::time::{Duration, Instant};
|
||||||
use string_cache::{Atom, QualName};
|
use string_cache::{Atom, QualName};
|
||||||
use style::attr::AttrValue;
|
use style::attr::AttrValue;
|
||||||
use style::context::ReflowGoal;
|
use style::context::ReflowGoal;
|
||||||
|
@ -247,6 +248,9 @@ pub struct Document {
|
||||||
referrer: Option<String>,
|
referrer: Option<String>,
|
||||||
/// https://html.spec.whatwg.org/multipage/#target-element
|
/// https://html.spec.whatwg.org/multipage/#target-element
|
||||||
target_element: MutNullableHeap<JS<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)]
|
#[derive(JSTraceable, HeapSizeOf)]
|
||||||
|
@ -774,12 +778,64 @@ impl Document {
|
||||||
|
|
||||||
if let MouseEventType::Click = mouse_event_type {
|
if let MouseEventType::Click = mouse_event_type {
|
||||||
self.commit_focus_transaction(FocusType::Element);
|
self.commit_focus_transaction(FocusType::Element);
|
||||||
|
self.maybe_fire_dblclick(client_point, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.window.reflow(ReflowGoal::ForDisplay,
|
self.window.reflow(ReflowGoal::ForDisplay,
|
||||||
ReflowQueryType::NoQuery,
|
ReflowQueryType::NoQuery,
|
||||||
ReflowReason::MouseEvent);
|
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,
|
pub fn handle_touchpad_pressure_event(&self,
|
||||||
js_runtime: *mut JSRuntime,
|
js_runtime: *mut JSRuntime,
|
||||||
client_point: Point2D<f32>,
|
client_point: Point2D<f32>,
|
||||||
|
@ -1759,6 +1815,7 @@ impl Document {
|
||||||
referrer: referrer,
|
referrer: referrer,
|
||||||
referrer_policy: Cell::new(referrer_policy),
|
referrer_policy: Cell::new(referrer_policy),
|
||||||
target_element: MutNullableHeap::new(None),
|
target_element: MutNullableHeap::new(None),
|
||||||
|
last_click_info: DOMRefCell::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue