mirror of
https://github.com/servo/servo.git
synced 2025-07-25 00:00:20 +01:00
added dispatching for mousedown and mouseup events, fixes #5705
This commit is contained in:
parent
b0a7d1bf86
commit
c069d1753e
4 changed files with 79 additions and 31 deletions
|
@ -220,8 +220,6 @@ pub trait DocumentHelpers<'a> {
|
||||||
fn title_changed(self);
|
fn title_changed(self);
|
||||||
fn send_title_to_compositor(self);
|
fn send_title_to_compositor(self);
|
||||||
fn dirty_all_nodes(self);
|
fn dirty_all_nodes(self);
|
||||||
fn handle_click_event(self, js_runtime: *mut JSRuntime,
|
|
||||||
button: MouseButton, point: Point2D<f32>);
|
|
||||||
fn dispatch_key_event(self, key: Key, state: KeyState,
|
fn dispatch_key_event(self, key: Key, state: KeyState,
|
||||||
modifiers: KeyModifiers, compositor: &mut Box<ScriptListener+'static>);
|
modifiers: KeyModifiers, compositor: &mut Box<ScriptListener+'static>);
|
||||||
fn node_from_nodes_and_strings(self, nodes: Vec<NodeOrString>)
|
fn node_from_nodes_and_strings(self, nodes: Vec<NodeOrString>)
|
||||||
|
@ -229,6 +227,9 @@ pub trait DocumentHelpers<'a> {
|
||||||
fn get_body_attribute(self, local_name: &Atom) -> DOMString;
|
fn get_body_attribute(self, local_name: &Atom) -> DOMString;
|
||||||
fn set_body_attribute(self, local_name: &Atom, value: DOMString);
|
fn set_body_attribute(self, local_name: &Atom, value: DOMString);
|
||||||
|
|
||||||
|
fn handle_mouse_event(self, js_runtime: *mut JSRuntime,
|
||||||
|
button: MouseButton, point: Point2D<f32>,
|
||||||
|
mouse_event_type: MouseEventType);
|
||||||
/// Handles a mouse-move event coming from the compositor.
|
/// Handles a mouse-move event coming from the compositor.
|
||||||
fn handle_mouse_move_event(self,
|
fn handle_mouse_move_event(self,
|
||||||
js_runtime: *mut JSRuntime,
|
js_runtime: *mut JSRuntime,
|
||||||
|
@ -511,9 +512,15 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_click_event(self, js_runtime: *mut JSRuntime,
|
fn handle_mouse_event(self, js_runtime: *mut JSRuntime,
|
||||||
_button: MouseButton, point: Point2D<f32>) {
|
_button: MouseButton, point: Point2D<f32>,
|
||||||
debug!("ClickEvent: clicked at {:?}", point);
|
mouse_event_type: MouseEventType) {
|
||||||
|
let mouse_event_type_string = match mouse_event_type {
|
||||||
|
MouseEventType::Click => "click".to_owned(),
|
||||||
|
MouseEventType::MouseUp => "mouseup".to_owned(),
|
||||||
|
MouseEventType::MouseDown => "mousedown".to_owned(),
|
||||||
|
};
|
||||||
|
debug!("{}: at {:?}", mouse_event_type_string, point);
|
||||||
let node = match self.hit_test(&point) {
|
let node = match self.hit_test(&point) {
|
||||||
Some(node_address) => {
|
Some(node_address) => {
|
||||||
debug!("node address is {:?}", node_address.0);
|
debug!("node address is {:?}", node_address.0);
|
||||||
|
@ -534,13 +541,15 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
|
||||||
}.root();
|
}.root();
|
||||||
|
|
||||||
let node: JSRef<Node> = NodeCast::from_ref(el.r());
|
let node: JSRef<Node> = NodeCast::from_ref(el.r());
|
||||||
debug!("clicked on {:?}", node.debug_str());
|
debug!("{} on {:?}", mouse_event_type_string, node.debug_str());
|
||||||
// Prevent click event if form control element is disabled.
|
// Prevent click event if form control element is disabled.
|
||||||
|
if let MouseEventType::Click = mouse_event_type {
|
||||||
if node.click_event_filter_by_disabled_state() {
|
if node.click_event_filter_by_disabled_state() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.begin_focus_transaction();
|
self.begin_focus_transaction();
|
||||||
|
}
|
||||||
|
|
||||||
let window = self.window.root();
|
let window = self.window.root();
|
||||||
|
|
||||||
|
@ -548,7 +557,7 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
|
||||||
let x = point.x as i32;
|
let x = point.x as i32;
|
||||||
let y = point.y as i32;
|
let y = point.y as i32;
|
||||||
let event = MouseEvent::new(window.r(),
|
let event = MouseEvent::new(window.r(),
|
||||||
"click".to_owned(),
|
mouse_event_type_string,
|
||||||
EventBubbles::Bubbles,
|
EventBubbles::Bubbles,
|
||||||
EventCancelable::Cancelable,
|
EventCancelable::Cancelable,
|
||||||
Some(window.r()),
|
Some(window.r()),
|
||||||
|
@ -562,9 +571,17 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
|
||||||
// https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#trusted-events
|
// https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#trusted-events
|
||||||
event.set_trusted(true);
|
event.set_trusted(true);
|
||||||
// https://html.spec.whatwg.org/multipage/#run-authentic-click-activation-steps
|
// https://html.spec.whatwg.org/multipage/#run-authentic-click-activation-steps
|
||||||
el.r().authentic_click_activation(event);
|
match mouse_event_type {
|
||||||
|
MouseEventType::Click => el.r().authentic_click_activation(event),
|
||||||
|
_ => {
|
||||||
|
let target: JSRef<EventTarget> = EventTargetCast::from_ref(node);
|
||||||
|
event.fire(target);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if let MouseEventType::Click = mouse_event_type {
|
||||||
self.commit_focus_transaction(FocusType::Element);
|
self.commit_focus_transaction(FocusType::Element);
|
||||||
|
}
|
||||||
window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::MouseEvent);
|
window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::MouseEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -778,6 +795,12 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum MouseEventType {
|
||||||
|
Click,
|
||||||
|
MouseDown,
|
||||||
|
MouseUp,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub enum DocumentSource {
|
pub enum DocumentSource {
|
||||||
FromParser,
|
FromParser,
|
||||||
|
|
|
@ -30,7 +30,7 @@ use dom::bindings::refcounted::{LiveDOMReferences, Trusted, TrustedReference};
|
||||||
use dom::bindings::structuredclone::StructuredCloneData;
|
use dom::bindings::structuredclone::StructuredCloneData;
|
||||||
use dom::bindings::trace::{JSTraceable, trace_collections, RootedVec};
|
use dom::bindings::trace::{JSTraceable, trace_collections, RootedVec};
|
||||||
use dom::bindings::utils::{wrap_for_same_compartment, pre_wrap};
|
use dom::bindings::utils::{wrap_for_same_compartment, pre_wrap};
|
||||||
use dom::document::{Document, IsHTMLDocument, DocumentHelpers, DocumentProgressHandler, DocumentProgressTask, DocumentSource};
|
use dom::document::{Document, IsHTMLDocument, DocumentHelpers, DocumentProgressHandler, DocumentProgressTask, DocumentSource, MouseEventType};
|
||||||
use dom::element::{Element, AttributeHandlers};
|
use dom::element::{Element, AttributeHandlers};
|
||||||
use dom::event::{Event, EventHelpers, EventBubbles, EventCancelable};
|
use dom::event::{Event, EventHelpers, EventBubbles, EventCancelable};
|
||||||
use dom::htmliframeelement::{HTMLIFrameElement, HTMLIFrameElementHelpers};
|
use dom::htmliframeelement::{HTMLIFrameElement, HTMLIFrameElementHelpers};
|
||||||
|
@ -50,7 +50,7 @@ use webdriver_handlers;
|
||||||
use devtools_traits::{DevtoolsControlChan, DevtoolsControlPort, DevtoolsPageInfo};
|
use devtools_traits::{DevtoolsControlChan, DevtoolsControlPort, DevtoolsPageInfo};
|
||||||
use devtools_traits::{DevtoolsControlMsg, DevtoolScriptControlMsg};
|
use devtools_traits::{DevtoolsControlMsg, DevtoolScriptControlMsg};
|
||||||
use devtools_traits::{TimelineMarker, TimelineMarkerType, TracingMetadata};
|
use devtools_traits::{TimelineMarker, TimelineMarkerType, TracingMetadata};
|
||||||
use script_traits::CompositorEvent;
|
use script_traits::{CompositorEvent, MouseButton};
|
||||||
use script_traits::CompositorEvent::{ResizeEvent, ClickEvent};
|
use script_traits::CompositorEvent::{ResizeEvent, ClickEvent};
|
||||||
use script_traits::CompositorEvent::{MouseDownEvent, MouseUpEvent};
|
use script_traits::CompositorEvent::{MouseDownEvent, MouseUpEvent};
|
||||||
use script_traits::CompositorEvent::{MouseMoveEvent, KeyEvent};
|
use script_traits::CompositorEvent::{MouseMoveEvent, KeyEvent};
|
||||||
|
@ -1229,17 +1229,17 @@ impl ScriptTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
ClickEvent(button, point) => {
|
ClickEvent(button, point) => {
|
||||||
let _marker;
|
self.handle_mouse_event(pipeline_id, MouseEventType::Click, button, point);
|
||||||
if self.need_emit_timeline_marker(TimelineMarkerType::DOMEvent) {
|
}
|
||||||
_marker = AutoDOMEventMarker::new(self);
|
|
||||||
}
|
MouseDownEvent(button, point) => {
|
||||||
let page = get_page(&self.root_page(), pipeline_id);
|
self.handle_mouse_event(pipeline_id, MouseEventType::MouseDown, button, point);
|
||||||
let document = page.document().root();
|
}
|
||||||
document.r().handle_click_event(self.js_runtime.rt(), button, point);
|
|
||||||
|
MouseUpEvent(button, point) => {
|
||||||
|
self.handle_mouse_event(pipeline_id, MouseEventType::MouseUp, button, point);
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseDownEvent(..) => {}
|
|
||||||
MouseUpEvent(..) => {}
|
|
||||||
MouseMoveEvent(point) => {
|
MouseMoveEvent(point) => {
|
||||||
let _marker;
|
let _marker;
|
||||||
if self.need_emit_timeline_marker(TimelineMarkerType::DOMEvent) {
|
if self.need_emit_timeline_marker(TimelineMarkerType::DOMEvent) {
|
||||||
|
@ -1267,6 +1267,16 @@ impl ScriptTask {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_mouse_event(&self, pipeline_id: PipelineId, mouse_event_type: MouseEventType, button: MouseButton, point: Point2D<f32>) {
|
||||||
|
let _marker;
|
||||||
|
if self.need_emit_timeline_marker(TimelineMarkerType::DOMEvent) {
|
||||||
|
_marker = AutoDOMEventMarker::new(self);
|
||||||
|
}
|
||||||
|
let page = get_page(&self.root_page(), pipeline_id);
|
||||||
|
let document = page.document().root();
|
||||||
|
document.r().handle_mouse_event(self.js_runtime.rt(), button, point, mouse_event_type);
|
||||||
|
}
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#navigating-across-documents
|
/// https://html.spec.whatwg.org/multipage/#navigating-across-documents
|
||||||
/// The entry point for content to notify that a new load has been requested
|
/// The entry point for content to notify that a new load has been requested
|
||||||
/// for the given pipeline (specifically the "navigate" algorithm).
|
/// for the given pipeline (specifically the "navigate" algorithm).
|
||||||
|
|
|
@ -237,21 +237,22 @@ impl Window {
|
||||||
MouseWindowEvent::MouseDown(MouseButton::Left, TypedPoint2D(x as f32, y as f32))
|
MouseWindowEvent::MouseDown(MouseButton::Left, TypedPoint2D(x as f32, y as f32))
|
||||||
}
|
}
|
||||||
ElementState::Released => {
|
ElementState::Released => {
|
||||||
|
let mouse_up_event = MouseWindowEvent::MouseUp(MouseButton::Left, TypedPoint2D(x as f32, y as f32));
|
||||||
match self.mouse_down_button.get() {
|
match self.mouse_down_button.get() {
|
||||||
None => (),
|
None => mouse_up_event,
|
||||||
Some(but) if button == but => {
|
Some(but) if button == but => {
|
||||||
let pixel_dist = self.mouse_down_point.get() - Point2D(x, y);
|
let pixel_dist = self.mouse_down_point.get() - Point2D(x, y);
|
||||||
let pixel_dist = ((pixel_dist.x * pixel_dist.x +
|
let pixel_dist = ((pixel_dist.x * pixel_dist.x +
|
||||||
pixel_dist.y * pixel_dist.y) as f64).sqrt();
|
pixel_dist.y * pixel_dist.y) as f64).sqrt();
|
||||||
if pixel_dist < max_pixel_dist {
|
if pixel_dist < max_pixel_dist {
|
||||||
let click_event = MouseWindowEvent::Click(
|
self.event_queue.borrow_mut().push(WindowEvent::MouseWindowEventClass(mouse_up_event));
|
||||||
MouseButton::Left, TypedPoint2D(x as f32, y as f32));
|
MouseWindowEvent::Click(MouseButton::Left, TypedPoint2D(x as f32, y as f32))
|
||||||
self.event_queue.borrow_mut().push(WindowEvent::MouseWindowEventClass(click_event));
|
} else {
|
||||||
|
mouse_up_event
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
Some(_) => mouse_up_event,
|
||||||
}
|
}
|
||||||
Some(_) => (),
|
|
||||||
}
|
|
||||||
MouseWindowEvent::MouseUp(MouseButton::Left, TypedPoint2D(x as f32, y as f32))
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.event_queue.borrow_mut().push(WindowEvent::MouseWindowEventClass(event));
|
self.event_queue.borrow_mut().push(WindowEvent::MouseWindowEventClass(event));
|
||||||
|
|
14
tests/html/test_mouse_down_mouse_up_click.html
Normal file
14
tests/html/test_mouse_down_mouse_up_click.html
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<body>
|
||||||
|
<input id="clicked">
|
||||||
|
<script>
|
||||||
|
document.getElementById("clicked").addEventListener("mousedown", function () {
|
||||||
|
window.alert("mousedown"); },
|
||||||
|
false);
|
||||||
|
document.getElementById("clicked").addEventListener('mouseup', function() {
|
||||||
|
window.alert("mouseup"); },
|
||||||
|
false);
|
||||||
|
document.getElementById("clicked").addEventListener("click", function() {
|
||||||
|
window.alert("clicked"); },
|
||||||
|
false);
|
||||||
|
</script>
|
||||||
|
</body>
|
Loading…
Add table
Add a link
Reference in a new issue