mirror of
https://github.com/servo/servo.git
synced 2025-07-08 07:53:40 +01:00
script: Pass more information to the MouseEvent
constructor (#37672)
- Instead of eagerly computing `pageX` and `pageY`, collect the offset from the content's initial containing block in the compositor and pass that information through to `MouseEvent`. This prevents a layout flush that was happening when eagerly trying to fetch `Document` scroll offsets. - Pass keyboard modifiers properly to `MouseEvent`. - Now all this information is stored and passed as `Point2D` (typed) and `Modifiers` which greatly reduces the amount of arguments that need to be passed around. Testing: It is difficult to test input events as they require WebDriver which isn't completely working yet. I have manually run Speedometer 2.1 and I have verified that this fixes the regression from #37601. Fixes: #37601. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
50cf01cf3d
commit
0346a62214
11 changed files with 374 additions and 369 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -7139,6 +7139,7 @@ dependencies = [
|
||||||
"html5ever",
|
"html5ever",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"jstraceable_derive",
|
"jstraceable_derive",
|
||||||
|
"keyboard-types",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"malloc_size_of_derive",
|
"malloc_size_of_derive",
|
||||||
|
|
|
@ -336,11 +336,23 @@ impl ServoRenderer {
|
||||||
_ => return None,
|
_ => return None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let offset = details
|
||||||
|
.scroll_tree
|
||||||
|
.scroll_offset(pipeline_id.root_scroll_id())
|
||||||
|
.unwrap_or_default();
|
||||||
|
let point_in_initial_containing_block =
|
||||||
|
(item.point_in_viewport + offset).to_untyped();
|
||||||
|
|
||||||
let info = &details.hit_test_items[item.tag.0 as usize];
|
let info = &details.hit_test_items[item.tag.0 as usize];
|
||||||
Some(CompositorHitTestResult {
|
Some(CompositorHitTestResult {
|
||||||
pipeline_id,
|
pipeline_id,
|
||||||
point_in_viewport: item.point_in_viewport.to_untyped(),
|
point_in_viewport: Point2D::from_untyped(item.point_in_viewport.to_untyped()),
|
||||||
point_relative_to_item: item.point_relative_to_item.to_untyped(),
|
point_relative_to_initial_containing_block: Point2D::from_untyped(
|
||||||
|
point_in_initial_containing_block,
|
||||||
|
),
|
||||||
|
point_relative_to_item: Point2D::from_untyped(
|
||||||
|
item.point_relative_to_item.to_untyped(),
|
||||||
|
),
|
||||||
node: UntrustedNodeAddress(info.node as *const c_void),
|
node: UntrustedNodeAddress(info.node as *const c_void),
|
||||||
cursor: info.cursor,
|
cursor: info.cursor,
|
||||||
scroll_tree_node: info.scroll_tree_node,
|
scroll_tree_node: info.scroll_tree_node,
|
||||||
|
|
|
@ -34,7 +34,8 @@ use embedder_traits::{
|
||||||
UntrustedNodeAddress, WheelEvent,
|
UntrustedNodeAddress, WheelEvent,
|
||||||
};
|
};
|
||||||
use encoding_rs::{Encoding, UTF_8};
|
use encoding_rs::{Encoding, UTF_8};
|
||||||
use euclid::default::{Point2D, Rect, Size2D};
|
use euclid::Point2D;
|
||||||
|
use euclid::default::{Rect, Size2D};
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use html5ever::{LocalName, Namespace, QualName, local_name, ns};
|
use html5ever::{LocalName, Namespace, QualName, local_name, ns};
|
||||||
use hyper_serde::Serde;
|
use hyper_serde::Serde;
|
||||||
|
@ -50,7 +51,6 @@ use net_traits::pub_domains::is_pub_domain;
|
||||||
use net_traits::request::{InsecureRequestsPolicy, RequestBuilder};
|
use net_traits::request::{InsecureRequestsPolicy, RequestBuilder};
|
||||||
use net_traits::response::HttpsState;
|
use net_traits::response::HttpsState;
|
||||||
use net_traits::{FetchResponseListener, IpcSend, ReferrerPolicy};
|
use net_traits::{FetchResponseListener, IpcSend, ReferrerPolicy};
|
||||||
use num_traits::ToPrimitive;
|
|
||||||
use percent_encoding::percent_decode;
|
use percent_encoding::percent_decode;
|
||||||
use profile_traits::ipc as profile_ipc;
|
use profile_traits::ipc as profile_ipc;
|
||||||
use profile_traits::time::TimerMetadataFrameType;
|
use profile_traits::time::TimerMetadataFrameType;
|
||||||
|
@ -69,6 +69,7 @@ use style::shared_lock::SharedRwLock as StyleSharedRwLock;
|
||||||
use style::str::{split_html_space_chars, str_join};
|
use style::str::{split_html_space_chars, str_join};
|
||||||
use style::stylesheet_set::DocumentStylesheetSet;
|
use style::stylesheet_set::DocumentStylesheetSet;
|
||||||
use style::stylesheets::{Origin, OriginSet, Stylesheet};
|
use style::stylesheets::{Origin, OriginSet, Stylesheet};
|
||||||
|
use style_traits::CSSPixel;
|
||||||
use stylo_atoms::Atom;
|
use stylo_atoms::Atom;
|
||||||
use url::Host;
|
use url::Host;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
@ -425,7 +426,7 @@ pub(crate) struct Document {
|
||||||
/// <https://w3c.github.io/uievents/#event-type-dblclick>
|
/// <https://w3c.github.io/uievents/#event-type-dblclick>
|
||||||
#[ignore_malloc_size_of = "Defined in std"]
|
#[ignore_malloc_size_of = "Defined in std"]
|
||||||
#[no_trace]
|
#[no_trace]
|
||||||
last_click_info: DomRefCell<Option<(Instant, Point2D<f32>)>>,
|
last_click_info: DomRefCell<Option<(Instant, Point2D<f32, CSSPixel>)>>,
|
||||||
/// <https://html.spec.whatwg.org/multipage/#ignore-destructive-writes-counter>
|
/// <https://html.spec.whatwg.org/multipage/#ignore-destructive-writes-counter>
|
||||||
ignore_destructive_writes_counter: Cell<u32>,
|
ignore_destructive_writes_counter: Cell<u32>,
|
||||||
/// <https://html.spec.whatwg.org/multipage/#ignore-opens-during-unload-counter>
|
/// <https://html.spec.whatwg.org/multipage/#ignore-opens-during-unload-counter>
|
||||||
|
@ -1515,12 +1516,11 @@ impl Document {
|
||||||
pub(crate) fn handle_mouse_button_event(
|
pub(crate) fn handle_mouse_button_event(
|
||||||
&self,
|
&self,
|
||||||
event: MouseButtonEvent,
|
event: MouseButtonEvent,
|
||||||
hit_test_result: Option<CompositorHitTestResult>,
|
input_event: &ConstellationInputEvent,
|
||||||
pressed_mouse_buttons: u16,
|
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) {
|
) {
|
||||||
// Ignore all incoming events without a hit test.
|
// Ignore all incoming events without a hit test.
|
||||||
let Some(hit_test_result) = hit_test_result else {
|
let Some(hit_test_result) = &input_event.hit_test_result else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1556,9 +1556,10 @@ impl Document {
|
||||||
|
|
||||||
let dom_event = DomRoot::upcast::<Event>(MouseEvent::for_platform_mouse_event(
|
let dom_event = DomRoot::upcast::<Event>(MouseEvent::for_platform_mouse_event(
|
||||||
event,
|
event,
|
||||||
pressed_mouse_buttons,
|
input_event.pressed_mouse_buttons,
|
||||||
&self.window,
|
&self.window,
|
||||||
&hit_test_result,
|
hit_test_result,
|
||||||
|
input_event.active_keyboard_modifiers,
|
||||||
can_gc,
|
can_gc,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -1592,23 +1593,13 @@ impl Document {
|
||||||
if self.focus_transaction.borrow().is_some() {
|
if self.focus_transaction.borrow().is_some() {
|
||||||
self.commit_focus_transaction(FocusInitiator::Local, can_gc);
|
self.commit_focus_transaction(FocusInitiator::Local, can_gc);
|
||||||
}
|
}
|
||||||
self.maybe_fire_dblclick(
|
self.maybe_fire_dblclick(node, hit_test_result, input_event, can_gc);
|
||||||
hit_test_result.point_in_viewport,
|
|
||||||
node,
|
|
||||||
pressed_mouse_buttons,
|
|
||||||
can_gc,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the contextmenu event is triggered by right mouse button
|
// When the contextmenu event is triggered by right mouse button
|
||||||
// the contextmenu event MUST be dispatched after the mousedown event.
|
// the contextmenu event MUST be dispatched after the mousedown event.
|
||||||
if let (MouseButtonAction::Down, MouseButton::Right) = (event.action, event.button) {
|
if let (MouseButtonAction::Down, MouseButton::Right) = (event.action, event.button) {
|
||||||
self.maybe_show_context_menu(
|
self.maybe_show_context_menu(node.upcast(), hit_test_result, input_event, can_gc);
|
||||||
node.upcast(),
|
|
||||||
pressed_mouse_buttons,
|
|
||||||
hit_test_result.point_in_viewport,
|
|
||||||
can_gc,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1616,13 +1607,10 @@ impl Document {
|
||||||
fn maybe_show_context_menu(
|
fn maybe_show_context_menu(
|
||||||
&self,
|
&self,
|
||||||
target: &EventTarget,
|
target: &EventTarget,
|
||||||
pressed_mouse_buttons: u16,
|
hit_test_result: &CompositorHitTestResult,
|
||||||
client_point: Point2D<f32>,
|
input_event: &ConstellationInputEvent,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) {
|
) {
|
||||||
let client_x = client_point.x.to_i32().unwrap_or(0);
|
|
||||||
let client_y = client_point.y.to_i32().unwrap_or(0);
|
|
||||||
|
|
||||||
// <https://w3c.github.io/uievents/#contextmenu>
|
// <https://w3c.github.io/uievents/#contextmenu>
|
||||||
let menu_event = PointerEvent::new(
|
let menu_event = PointerEvent::new(
|
||||||
&self.window, // window
|
&self.window, // window
|
||||||
|
@ -1631,32 +1619,30 @@ impl Document {
|
||||||
EventCancelable::Cancelable, // cancelable
|
EventCancelable::Cancelable, // cancelable
|
||||||
Some(&self.window), // view
|
Some(&self.window), // view
|
||||||
0, // detail
|
0, // detail
|
||||||
client_x, // screen_x
|
hit_test_result.point_in_viewport.to_i32(),
|
||||||
client_y, // screen_y
|
hit_test_result.point_in_viewport.to_i32(),
|
||||||
client_x, // client_x
|
hit_test_result
|
||||||
client_y, // client_y
|
.point_relative_to_initial_containing_block
|
||||||
false, // ctrl_key
|
.to_i32(),
|
||||||
false, // alt_key
|
input_event.active_keyboard_modifiers,
|
||||||
false, // shift_key
|
2i16, // button, right mouse button
|
||||||
false, // meta_key
|
input_event.pressed_mouse_buttons,
|
||||||
2i16, // button, right mouse button
|
None, // related_target
|
||||||
pressed_mouse_buttons, // buttons
|
None, // point_in_target
|
||||||
None, // related_target
|
PointerId::Mouse as i32, // pointer_id
|
||||||
None, // point_in_target
|
1, // width
|
||||||
PointerId::Mouse as i32, // pointer_id
|
1, // height
|
||||||
1, // width
|
0.5, // pressure
|
||||||
1, // height
|
0.0, // tangential_pressure
|
||||||
0.5, // pressure
|
0, // tilt_x
|
||||||
0.0, // tangential_pressure
|
0, // tilt_y
|
||||||
0, // tilt_x
|
0, // twist
|
||||||
0, // tilt_y
|
PI / 2.0, // altitude_angle
|
||||||
0, // twist
|
0.0, // azimuth_angle
|
||||||
PI / 2.0, // altitude_angle
|
DOMString::from("mouse"), // pointer_type
|
||||||
0.0, // azimuth_angle
|
true, // is_primary
|
||||||
DOMString::from("mouse"), // pointer_type
|
vec![], // coalesced_events
|
||||||
true, // is_primary
|
vec![], // predicted_events
|
||||||
vec![], // coalesced_events
|
|
||||||
vec![], // predicted_events
|
|
||||||
can_gc,
|
can_gc,
|
||||||
);
|
);
|
||||||
let event = menu_event.upcast::<Event>();
|
let event = menu_event.upcast::<Event>();
|
||||||
|
@ -1678,14 +1664,14 @@ impl Document {
|
||||||
|
|
||||||
fn maybe_fire_dblclick(
|
fn maybe_fire_dblclick(
|
||||||
&self,
|
&self,
|
||||||
click_pos: Point2D<f32>,
|
|
||||||
target: &Node,
|
target: &Node,
|
||||||
pressed_mouse_buttons: u16,
|
hit_test_result: &CompositorHitTestResult,
|
||||||
|
input_event: &ConstellationInputEvent,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) {
|
) {
|
||||||
// https://w3c.github.io/uievents/#event-type-dblclick
|
// https://w3c.github.io/uievents/#event-type-dblclick
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
|
let point_in_viewport = hit_test_result.point_in_viewport;
|
||||||
let opt = self.last_click_info.borrow_mut().take();
|
let opt = self.last_click_info.borrow_mut().take();
|
||||||
|
|
||||||
if let Some((last_time, last_pos)) = opt {
|
if let Some((last_time, last_pos)) = opt {
|
||||||
|
@ -1694,7 +1680,7 @@ impl Document {
|
||||||
let DBL_CLICK_DIST_THRESHOLD = pref!(dom_document_dblclick_dist) as u64;
|
let DBL_CLICK_DIST_THRESHOLD = pref!(dom_document_dblclick_dist) as u64;
|
||||||
|
|
||||||
// Calculate distance between this click and the previous click.
|
// Calculate distance between this click and the previous click.
|
||||||
let line = click_pos - last_pos;
|
let line = point_in_viewport - last_pos;
|
||||||
let dist = (line.dot(line) as f64).sqrt();
|
let dist = (line.dot(line) as f64).sqrt();
|
||||||
|
|
||||||
if now.duration_since(last_time) < DBL_CLICK_TIMEOUT &&
|
if now.duration_since(last_time) < DBL_CLICK_TIMEOUT &&
|
||||||
|
@ -1702,8 +1688,6 @@ impl Document {
|
||||||
{
|
{
|
||||||
// A double click has occurred if this click is within a certain time and dist. of previous click.
|
// A double click has occurred if this click is within a certain time and dist. of previous click.
|
||||||
let click_count = 2;
|
let click_count = 2;
|
||||||
let client_x = click_pos.x as i32;
|
|
||||||
let client_y = click_pos.y as i32;
|
|
||||||
|
|
||||||
let event = MouseEvent::new(
|
let event = MouseEvent::new(
|
||||||
&self.window,
|
&self.window,
|
||||||
|
@ -1712,16 +1696,14 @@ impl Document {
|
||||||
EventCancelable::Cancelable,
|
EventCancelable::Cancelable,
|
||||||
Some(&self.window),
|
Some(&self.window),
|
||||||
click_count,
|
click_count,
|
||||||
client_x,
|
point_in_viewport.to_i32(),
|
||||||
client_y,
|
point_in_viewport.to_i32(),
|
||||||
client_x,
|
hit_test_result
|
||||||
client_y,
|
.point_relative_to_initial_containing_block
|
||||||
false,
|
.to_i32(),
|
||||||
false,
|
input_event.active_keyboard_modifiers,
|
||||||
false,
|
|
||||||
false,
|
|
||||||
0i16,
|
0i16,
|
||||||
pressed_mouse_buttons,
|
input_event.pressed_mouse_buttons,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
can_gc,
|
can_gc,
|
||||||
|
@ -1735,23 +1717,20 @@ impl Document {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update last_click_info with the time and position of the click.
|
// Update last_click_info with the time and position of the click.
|
||||||
*self.last_click_info.borrow_mut() = Some((now, click_pos));
|
*self.last_click_info.borrow_mut() = Some((now, point_in_viewport));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub(crate) fn fire_mouse_event(
|
pub(crate) fn fire_mouse_event(
|
||||||
&self,
|
&self,
|
||||||
client_point: Point2D<f32>,
|
|
||||||
target: &EventTarget,
|
target: &EventTarget,
|
||||||
event_name: FireMouseEventType,
|
event_name: FireMouseEventType,
|
||||||
can_bubble: EventBubbles,
|
can_bubble: EventBubbles,
|
||||||
cancelable: EventCancelable,
|
cancelable: EventCancelable,
|
||||||
pressed_mouse_buttons: u16,
|
hit_test_result: &CompositorHitTestResult,
|
||||||
|
input_event: &ConstellationInputEvent,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) {
|
) {
|
||||||
let client_x = client_point.x.to_i32().unwrap_or(0);
|
|
||||||
let client_y = client_point.y.to_i32().unwrap_or(0);
|
|
||||||
|
|
||||||
MouseEvent::new(
|
MouseEvent::new(
|
||||||
&self.window,
|
&self.window,
|
||||||
DOMString::from(event_name.as_str()),
|
DOMString::from(event_name.as_str()),
|
||||||
|
@ -1759,16 +1738,14 @@ impl Document {
|
||||||
cancelable,
|
cancelable,
|
||||||
Some(&self.window),
|
Some(&self.window),
|
||||||
0i32,
|
0i32,
|
||||||
client_x,
|
hit_test_result.point_in_viewport.to_i32(),
|
||||||
client_y,
|
hit_test_result.point_in_viewport.to_i32(),
|
||||||
client_x,
|
hit_test_result
|
||||||
client_y,
|
.point_relative_to_initial_containing_block
|
||||||
false,
|
.to_i32(),
|
||||||
false,
|
input_event.active_keyboard_modifiers,
|
||||||
false,
|
|
||||||
false,
|
|
||||||
0i16,
|
0i16,
|
||||||
pressed_mouse_buttons,
|
input_event.pressed_mouse_buttons,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
can_gc,
|
can_gc,
|
||||||
|
@ -1989,13 +1966,12 @@ impl Document {
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
pub(crate) unsafe fn handle_mouse_move_event(
|
pub(crate) unsafe fn handle_mouse_move_event(
|
||||||
&self,
|
&self,
|
||||||
hit_test_result: Option<CompositorHitTestResult>,
|
input_event: &ConstellationInputEvent,
|
||||||
pressed_mouse_buttons: u16,
|
|
||||||
prev_mouse_over_target: &MutNullableDom<Element>,
|
prev_mouse_over_target: &MutNullableDom<Element>,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) {
|
) {
|
||||||
// Ignore all incoming events without a hit test.
|
// Ignore all incoming events without a hit test.
|
||||||
let Some(hit_test_result) = hit_test_result else {
|
let Some(hit_test_result) = &input_event.hit_test_result else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2036,12 +2012,12 @@ impl Document {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.fire_mouse_event(
|
self.fire_mouse_event(
|
||||||
hit_test_result.point_in_viewport,
|
|
||||||
old_target.upcast(),
|
old_target.upcast(),
|
||||||
FireMouseEventType::Out,
|
FireMouseEventType::Out,
|
||||||
EventBubbles::Bubbles,
|
EventBubbles::Bubbles,
|
||||||
EventCancelable::Cancelable,
|
EventCancelable::Cancelable,
|
||||||
pressed_mouse_buttons,
|
hit_test_result,
|
||||||
|
input_event,
|
||||||
can_gc,
|
can_gc,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2049,11 +2025,11 @@ impl Document {
|
||||||
let event_target = DomRoot::from_ref(old_target.upcast::<Node>());
|
let event_target = DomRoot::from_ref(old_target.upcast::<Node>());
|
||||||
let moving_into = Some(DomRoot::from_ref(new_target.upcast::<Node>()));
|
let moving_into = Some(DomRoot::from_ref(new_target.upcast::<Node>()));
|
||||||
self.handle_mouse_enter_leave_event(
|
self.handle_mouse_enter_leave_event(
|
||||||
hit_test_result.point_in_viewport,
|
|
||||||
FireMouseEventType::Leave,
|
|
||||||
moving_into,
|
|
||||||
event_target,
|
event_target,
|
||||||
pressed_mouse_buttons,
|
moving_into,
|
||||||
|
FireMouseEventType::Leave,
|
||||||
|
hit_test_result,
|
||||||
|
input_event,
|
||||||
can_gc,
|
can_gc,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2072,12 +2048,12 @@ impl Document {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.fire_mouse_event(
|
self.fire_mouse_event(
|
||||||
hit_test_result.point_in_viewport,
|
|
||||||
new_target.upcast(),
|
new_target.upcast(),
|
||||||
FireMouseEventType::Over,
|
FireMouseEventType::Over,
|
||||||
EventBubbles::Bubbles,
|
EventBubbles::Bubbles,
|
||||||
EventCancelable::Cancelable,
|
EventCancelable::Cancelable,
|
||||||
pressed_mouse_buttons,
|
hit_test_result,
|
||||||
|
input_event,
|
||||||
can_gc,
|
can_gc,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2086,11 +2062,11 @@ impl Document {
|
||||||
.map(|old_target| DomRoot::from_ref(old_target.upcast::<Node>()));
|
.map(|old_target| DomRoot::from_ref(old_target.upcast::<Node>()));
|
||||||
let event_target = DomRoot::from_ref(new_target.upcast::<Node>());
|
let event_target = DomRoot::from_ref(new_target.upcast::<Node>());
|
||||||
self.handle_mouse_enter_leave_event(
|
self.handle_mouse_enter_leave_event(
|
||||||
hit_test_result.point_in_viewport,
|
|
||||||
FireMouseEventType::Enter,
|
|
||||||
moving_from,
|
|
||||||
event_target,
|
event_target,
|
||||||
pressed_mouse_buttons,
|
moving_from,
|
||||||
|
FireMouseEventType::Enter,
|
||||||
|
hit_test_result,
|
||||||
|
input_event,
|
||||||
can_gc,
|
can_gc,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2098,12 +2074,12 @@ impl Document {
|
||||||
// Send mousemove event to topmost target, unless it's an iframe, in which case the
|
// Send mousemove event to topmost target, unless it's an iframe, in which case the
|
||||||
// compositor should have also sent an event to the inner document.
|
// compositor should have also sent an event to the inner document.
|
||||||
self.fire_mouse_event(
|
self.fire_mouse_event(
|
||||||
hit_test_result.point_in_viewport,
|
|
||||||
new_target.upcast(),
|
new_target.upcast(),
|
||||||
FireMouseEventType::Move,
|
FireMouseEventType::Move,
|
||||||
EventBubbles::Bubbles,
|
EventBubbles::Bubbles,
|
||||||
EventCancelable::Cancelable,
|
EventCancelable::Cancelable,
|
||||||
pressed_mouse_buttons,
|
hit_test_result,
|
||||||
|
input_event,
|
||||||
can_gc,
|
can_gc,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2116,12 +2092,11 @@ impl Document {
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
pub(crate) fn handle_mouse_leave_event(
|
pub(crate) fn handle_mouse_leave_event(
|
||||||
&self,
|
&self,
|
||||||
hit_test_result: Option<CompositorHitTestResult>,
|
input_event: &ConstellationInputEvent,
|
||||||
pressed_mouse_buttons: u16,
|
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) {
|
) {
|
||||||
// Ignore all incoming events without a hit test.
|
// Ignore all incoming events without a hit test.
|
||||||
let Some(hit_test_result) = hit_test_result else {
|
let Some(hit_test_result) = &input_event.hit_test_result else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2138,31 +2113,31 @@ impl Document {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.fire_mouse_event(
|
self.fire_mouse_event(
|
||||||
hit_test_result.point_in_viewport,
|
|
||||||
node.upcast(),
|
node.upcast(),
|
||||||
FireMouseEventType::Out,
|
FireMouseEventType::Out,
|
||||||
EventBubbles::Bubbles,
|
EventBubbles::Bubbles,
|
||||||
EventCancelable::Cancelable,
|
EventCancelable::Cancelable,
|
||||||
pressed_mouse_buttons,
|
hit_test_result,
|
||||||
|
input_event,
|
||||||
can_gc,
|
can_gc,
|
||||||
);
|
);
|
||||||
self.handle_mouse_enter_leave_event(
|
self.handle_mouse_enter_leave_event(
|
||||||
hit_test_result.point_in_viewport,
|
|
||||||
FireMouseEventType::Leave,
|
|
||||||
None,
|
|
||||||
node,
|
node,
|
||||||
pressed_mouse_buttons,
|
None,
|
||||||
|
FireMouseEventType::Leave,
|
||||||
|
hit_test_result,
|
||||||
|
input_event,
|
||||||
can_gc,
|
can_gc,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_mouse_enter_leave_event(
|
fn handle_mouse_enter_leave_event(
|
||||||
&self,
|
&self,
|
||||||
client_point: Point2D<f32>,
|
|
||||||
event_type: FireMouseEventType,
|
|
||||||
related_target: Option<DomRoot<Node>>,
|
|
||||||
event_target: DomRoot<Node>,
|
event_target: DomRoot<Node>,
|
||||||
pressed_mouse_buttons: u16,
|
related_target: Option<DomRoot<Node>>,
|
||||||
|
event_type: FireMouseEventType,
|
||||||
|
hit_test_result: &CompositorHitTestResult,
|
||||||
|
input_event: &ConstellationInputEvent,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) {
|
) {
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
|
@ -2197,12 +2172,12 @@ impl Document {
|
||||||
|
|
||||||
for target in targets {
|
for target in targets {
|
||||||
self.fire_mouse_event(
|
self.fire_mouse_event(
|
||||||
client_point,
|
|
||||||
target.upcast(),
|
target.upcast(),
|
||||||
event_type,
|
event_type,
|
||||||
EventBubbles::DoesNotBubble,
|
EventBubbles::DoesNotBubble,
|
||||||
EventCancelable::NotCancelable,
|
EventCancelable::NotCancelable,
|
||||||
pressed_mouse_buttons,
|
hit_test_result,
|
||||||
|
input_event,
|
||||||
can_gc,
|
can_gc,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2853,8 +2853,11 @@ impl VirtualMethods for HTMLInputElement {
|
||||||
// now.
|
// now.
|
||||||
if let Some(point_in_target) = mouse_event.point_in_target() {
|
if let Some(point_in_target) = mouse_event.point_in_target() {
|
||||||
let window = self.owner_window();
|
let window = self.owner_window();
|
||||||
let index =
|
let index = window.text_index_query(
|
||||||
window.text_index_query(self.upcast::<Node>(), point_in_target, can_gc);
|
self.upcast::<Node>(),
|
||||||
|
point_in_target.to_untyped(),
|
||||||
|
can_gc,
|
||||||
|
);
|
||||||
// Position the caret at the click position or at the end of the current
|
// Position the caret at the click position or at the end of the current
|
||||||
// value.
|
// value.
|
||||||
let edit_point_index = match index {
|
let edit_point_index = match index {
|
||||||
|
|
|
@ -7,10 +7,12 @@ use std::default::Default;
|
||||||
|
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use embedder_traits::CompositorHitTestResult;
|
use embedder_traits::CompositorHitTestResult;
|
||||||
use euclid::default::Point2D;
|
use euclid::Point2D;
|
||||||
use js::rust::HandleObject;
|
use js::rust::HandleObject;
|
||||||
|
use keyboard_types::Modifiers;
|
||||||
use script_bindings::codegen::GenericBindings::WindowBinding::WindowMethods;
|
use script_bindings::codegen::GenericBindings::WindowBinding::WindowMethods;
|
||||||
use servo_config::pref;
|
use servo_config::pref;
|
||||||
|
use style_traits::CSSPixel;
|
||||||
|
|
||||||
use crate::dom::bindings::codegen::Bindings::EventBinding::Event_Binding::EventMethods;
|
use crate::dom::bindings::codegen::Bindings::EventBinding::Event_Binding::EventMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::MouseEventBinding;
|
use crate::dom::bindings::codegen::Bindings::MouseEventBinding;
|
||||||
|
@ -33,36 +35,36 @@ use crate::script_runtime::CanGc;
|
||||||
pub(crate) struct MouseEvent {
|
pub(crate) struct MouseEvent {
|
||||||
uievent: UIEvent,
|
uievent: UIEvent,
|
||||||
|
|
||||||
|
/// The point on the screen of where this [`MouseEvent`] was originally triggered,
|
||||||
|
/// to use during the dispatch phase.
|
||||||
|
///
|
||||||
|
/// See:
|
||||||
/// <https://w3c.github.io/uievents/#dom-mouseevent-screenx>
|
/// <https://w3c.github.io/uievents/#dom-mouseevent-screenx>
|
||||||
screen_x: Cell<i32>,
|
|
||||||
|
|
||||||
/// <https://w3c.github.io/uievents/#dom-mouseevent-screeny>
|
/// <https://w3c.github.io/uievents/#dom-mouseevent-screeny>
|
||||||
screen_y: Cell<i32>,
|
#[no_trace]
|
||||||
|
screen_point: Cell<Point2D<i32, CSSPixel>>,
|
||||||
|
|
||||||
|
/// The point in the viewport of where this [`MouseEvent`] was originally triggered,
|
||||||
|
/// to use during the dispatch phase.
|
||||||
|
///
|
||||||
|
/// See:
|
||||||
/// <https://w3c.github.io/uievents/#dom-mouseevent-clientx>
|
/// <https://w3c.github.io/uievents/#dom-mouseevent-clientx>
|
||||||
client_x: Cell<i32>,
|
|
||||||
|
|
||||||
/// <https://w3c.github.io/uievents/#dom-mouseevent-clienty>
|
/// <https://w3c.github.io/uievents/#dom-mouseevent-clienty>
|
||||||
client_y: Cell<i32>,
|
#[no_trace]
|
||||||
|
client_point: Cell<Point2D<i32, CSSPixel>>,
|
||||||
|
|
||||||
page_x: Cell<i32>,
|
/// The point in the initial containing block of where this [`MouseEvent`] was
|
||||||
page_y: Cell<i32>,
|
/// originally triggered to use during the dispatch phase.
|
||||||
x: Cell<i32>,
|
///
|
||||||
y: Cell<i32>,
|
/// See:
|
||||||
offset_x: Cell<i32>,
|
/// <https://w3c.github.io/uievents/#dom-mouseevent-pagex>
|
||||||
offset_y: Cell<i32>,
|
/// <https://w3c.github.io/uievents/#dom-mouseevent-pagey>
|
||||||
|
#[no_trace]
|
||||||
|
page_point: Cell<Point2D<i32, CSSPixel>>,
|
||||||
|
|
||||||
/// <https://w3c.github.io/uievents/#dom-mouseevent-ctrlkey>
|
/// The keyboard modifiers that were active when this mouse event was triggered.
|
||||||
ctrl_key: Cell<bool>,
|
#[no_trace]
|
||||||
|
modifiers: Cell<Modifiers>,
|
||||||
/// <https://w3c.github.io/uievents/#dom-mouseevent-shiftkey>
|
|
||||||
shift_key: Cell<bool>,
|
|
||||||
|
|
||||||
/// <https://w3c.github.io/uievents/#dom-mouseevent-altkey>
|
|
||||||
alt_key: Cell<bool>,
|
|
||||||
|
|
||||||
/// <https://w3c.github.io/uievents/#dom-mouseevent-metakey>
|
|
||||||
meta_key: Cell<bool>,
|
|
||||||
|
|
||||||
/// <https://w3c.github.io/uievents/#dom-mouseevent-button>
|
/// <https://w3c.github.io/uievents/#dom-mouseevent-button>
|
||||||
button: Cell<i16>,
|
button: Cell<i16>,
|
||||||
|
@ -73,27 +75,17 @@ pub(crate) struct MouseEvent {
|
||||||
/// <https://w3c.github.io/uievents/#dom-mouseevent-relatedtarget>
|
/// <https://w3c.github.io/uievents/#dom-mouseevent-relatedtarget>
|
||||||
related_target: MutNullableDom<EventTarget>,
|
related_target: MutNullableDom<EventTarget>,
|
||||||
#[no_trace]
|
#[no_trace]
|
||||||
point_in_target: Cell<Option<Point2D<f32>>>,
|
point_in_target: Cell<Option<Point2D<f32, CSSPixel>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MouseEvent {
|
impl MouseEvent {
|
||||||
pub(crate) fn new_inherited() -> MouseEvent {
|
pub(crate) fn new_inherited() -> MouseEvent {
|
||||||
MouseEvent {
|
MouseEvent {
|
||||||
uievent: UIEvent::new_inherited(),
|
uievent: UIEvent::new_inherited(),
|
||||||
screen_x: Cell::new(0),
|
screen_point: Cell::new(Default::default()),
|
||||||
screen_y: Cell::new(0),
|
client_point: Cell::new(Default::default()),
|
||||||
client_x: Cell::new(0),
|
page_point: Cell::new(Default::default()),
|
||||||
client_y: Cell::new(0),
|
modifiers: Cell::new(Modifiers::empty()),
|
||||||
page_x: Cell::new(0),
|
|
||||||
page_y: Cell::new(0),
|
|
||||||
x: Cell::new(0),
|
|
||||||
y: Cell::new(0),
|
|
||||||
offset_x: Cell::new(0),
|
|
||||||
offset_y: Cell::new(0),
|
|
||||||
ctrl_key: Cell::new(false),
|
|
||||||
shift_key: Cell::new(false),
|
|
||||||
alt_key: Cell::new(false),
|
|
||||||
meta_key: Cell::new(false),
|
|
||||||
button: Cell::new(0),
|
button: Cell::new(0),
|
||||||
buttons: Cell::new(0),
|
buttons: Cell::new(0),
|
||||||
related_target: Default::default(),
|
related_target: Default::default(),
|
||||||
|
@ -121,18 +113,14 @@ impl MouseEvent {
|
||||||
cancelable: EventCancelable,
|
cancelable: EventCancelable,
|
||||||
view: Option<&Window>,
|
view: Option<&Window>,
|
||||||
detail: i32,
|
detail: i32,
|
||||||
screen_x: i32,
|
screen_point: Point2D<i32, CSSPixel>,
|
||||||
screen_y: i32,
|
client_point: Point2D<i32, CSSPixel>,
|
||||||
client_x: i32,
|
page_point: Point2D<i32, CSSPixel>,
|
||||||
client_y: i32,
|
modifiers: Modifiers,
|
||||||
ctrl_key: bool,
|
|
||||||
alt_key: bool,
|
|
||||||
shift_key: bool,
|
|
||||||
meta_key: bool,
|
|
||||||
button: i16,
|
button: i16,
|
||||||
buttons: u16,
|
buttons: u16,
|
||||||
related_target: Option<&EventTarget>,
|
related_target: Option<&EventTarget>,
|
||||||
point_in_target: Option<Point2D<f32>>,
|
point_in_target: Option<Point2D<f32, CSSPixel>>,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> DomRoot<MouseEvent> {
|
) -> DomRoot<MouseEvent> {
|
||||||
Self::new_with_proto(
|
Self::new_with_proto(
|
||||||
|
@ -143,14 +131,10 @@ impl MouseEvent {
|
||||||
cancelable,
|
cancelable,
|
||||||
view,
|
view,
|
||||||
detail,
|
detail,
|
||||||
screen_x,
|
screen_point,
|
||||||
screen_y,
|
client_point,
|
||||||
client_x,
|
page_point,
|
||||||
client_y,
|
modifiers,
|
||||||
ctrl_key,
|
|
||||||
alt_key,
|
|
||||||
shift_key,
|
|
||||||
meta_key,
|
|
||||||
button,
|
button,
|
||||||
buttons,
|
buttons,
|
||||||
related_target,
|
related_target,
|
||||||
|
@ -168,18 +152,14 @@ impl MouseEvent {
|
||||||
cancelable: EventCancelable,
|
cancelable: EventCancelable,
|
||||||
view: Option<&Window>,
|
view: Option<&Window>,
|
||||||
detail: i32,
|
detail: i32,
|
||||||
screen_x: i32,
|
screen_point: Point2D<i32, CSSPixel>,
|
||||||
screen_y: i32,
|
client_point: Point2D<i32, CSSPixel>,
|
||||||
client_x: i32,
|
page_point: Point2D<i32, CSSPixel>,
|
||||||
client_y: i32,
|
modifiers: Modifiers,
|
||||||
ctrl_key: bool,
|
|
||||||
alt_key: bool,
|
|
||||||
shift_key: bool,
|
|
||||||
meta_key: bool,
|
|
||||||
button: i16,
|
button: i16,
|
||||||
buttons: u16,
|
buttons: u16,
|
||||||
related_target: Option<&EventTarget>,
|
related_target: Option<&EventTarget>,
|
||||||
point_in_target: Option<Point2D<f32>>,
|
point_in_target: Option<Point2D<f32, CSSPixel>>,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> DomRoot<MouseEvent> {
|
) -> DomRoot<MouseEvent> {
|
||||||
let ev = MouseEvent::new_uninitialized_with_proto(window, proto, can_gc);
|
let ev = MouseEvent::new_uninitialized_with_proto(window, proto, can_gc);
|
||||||
|
@ -189,14 +169,10 @@ impl MouseEvent {
|
||||||
cancelable,
|
cancelable,
|
||||||
view,
|
view,
|
||||||
detail,
|
detail,
|
||||||
screen_x,
|
screen_point,
|
||||||
screen_y,
|
client_point,
|
||||||
client_x,
|
page_point,
|
||||||
client_y,
|
modifiers,
|
||||||
ctrl_key,
|
|
||||||
alt_key,
|
|
||||||
shift_key,
|
|
||||||
meta_key,
|
|
||||||
button,
|
button,
|
||||||
buttons,
|
buttons,
|
||||||
related_target,
|
related_target,
|
||||||
|
@ -214,18 +190,14 @@ impl MouseEvent {
|
||||||
cancelable: EventCancelable,
|
cancelable: EventCancelable,
|
||||||
view: Option<&Window>,
|
view: Option<&Window>,
|
||||||
detail: i32,
|
detail: i32,
|
||||||
screen_x: i32,
|
screen_point: Point2D<i32, CSSPixel>,
|
||||||
screen_y: i32,
|
client_point: Point2D<i32, CSSPixel>,
|
||||||
client_x: i32,
|
page_point: Point2D<i32, CSSPixel>,
|
||||||
client_y: i32,
|
modifiers: Modifiers,
|
||||||
ctrl_key: bool,
|
|
||||||
alt_key: bool,
|
|
||||||
shift_key: bool,
|
|
||||||
meta_key: bool,
|
|
||||||
button: i16,
|
button: i16,
|
||||||
buttons: u16,
|
buttons: u16,
|
||||||
related_target: Option<&EventTarget>,
|
related_target: Option<&EventTarget>,
|
||||||
point_in_target: Option<Point2D<f32>>,
|
point_in_target: Option<Point2D<f32, CSSPixel>>,
|
||||||
) {
|
) {
|
||||||
self.uievent.initialize_ui_event(
|
self.uievent.initialize_ui_event(
|
||||||
type_,
|
type_,
|
||||||
|
@ -235,32 +207,17 @@ impl MouseEvent {
|
||||||
);
|
);
|
||||||
|
|
||||||
self.uievent.set_detail(detail);
|
self.uievent.set_detail(detail);
|
||||||
|
self.screen_point.set(screen_point);
|
||||||
self.screen_x.set(screen_x);
|
self.client_point.set(client_point);
|
||||||
self.screen_y.set(screen_y);
|
self.page_point.set(page_point);
|
||||||
self.client_x.set(client_x);
|
self.modifiers.set(modifiers);
|
||||||
self.client_y.set(client_y);
|
|
||||||
self.page_x.set(self.PageX());
|
|
||||||
self.page_y.set(self.PageY());
|
|
||||||
|
|
||||||
// skip setting flags as they are absent
|
|
||||||
self.shift_key.set(shift_key);
|
|
||||||
self.ctrl_key.set(ctrl_key);
|
|
||||||
self.alt_key.set(alt_key);
|
|
||||||
self.meta_key.set(meta_key);
|
|
||||||
|
|
||||||
self.button.set(button);
|
self.button.set(button);
|
||||||
self.buttons.set(buttons);
|
self.buttons.set(buttons);
|
||||||
// skip step 3: Initialize PointerLock attributes for MouseEvent with event,
|
|
||||||
// as movementX, movementY is absent
|
|
||||||
|
|
||||||
self.related_target.set(related_target);
|
self.related_target.set(related_target);
|
||||||
|
|
||||||
// below is not in the spec
|
|
||||||
self.point_in_target.set(point_in_target);
|
self.point_in_target.set(point_in_target);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn point_in_target(&self) -> Option<Point2D<f32>> {
|
pub(crate) fn point_in_target(&self) -> Option<Point2D<f32, CSSPixel>> {
|
||||||
self.point_in_target.get()
|
self.point_in_target.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,6 +227,7 @@ impl MouseEvent {
|
||||||
pressed_mouse_buttons: u16,
|
pressed_mouse_buttons: u16,
|
||||||
window: &Window,
|
window: &Window,
|
||||||
hit_test_result: &CompositorHitTestResult,
|
hit_test_result: &CompositorHitTestResult,
|
||||||
|
modifiers: Modifiers,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> DomRoot<Self> {
|
) -> DomRoot<Self> {
|
||||||
let mouse_event_type_string = match event.action {
|
let mouse_event_type_string = match event.action {
|
||||||
|
@ -278,8 +236,11 @@ impl MouseEvent {
|
||||||
embedder_traits::MouseButtonAction::Down => "mousedown",
|
embedder_traits::MouseButtonAction::Down => "mousedown",
|
||||||
};
|
};
|
||||||
|
|
||||||
let client_x = hit_test_result.point_in_viewport.x as i32;
|
let client_point = hit_test_result.point_in_viewport.to_i32();
|
||||||
let client_y = hit_test_result.point_in_viewport.y as i32;
|
let page_point = hit_test_result
|
||||||
|
.point_relative_to_initial_containing_block
|
||||||
|
.to_i32();
|
||||||
|
|
||||||
let click_count = 1;
|
let click_count = 1;
|
||||||
let mouse_event = MouseEvent::new(
|
let mouse_event = MouseEvent::new(
|
||||||
window,
|
window,
|
||||||
|
@ -288,14 +249,10 @@ impl MouseEvent {
|
||||||
EventCancelable::Cancelable,
|
EventCancelable::Cancelable,
|
||||||
Some(window),
|
Some(window),
|
||||||
click_count,
|
click_count,
|
||||||
client_x,
|
client_point, // TODO: Get real screen coordinates?
|
||||||
client_y,
|
client_point,
|
||||||
client_x,
|
page_point,
|
||||||
client_y, // TODO: Get real screen coordinates?
|
modifiers,
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
event.button.into(),
|
event.button.into(),
|
||||||
pressed_mouse_buttons,
|
pressed_mouse_buttons,
|
||||||
None,
|
None,
|
||||||
|
@ -321,6 +278,10 @@ impl MouseEventMethods<crate::DomTypeHolder> for MouseEvent {
|
||||||
) -> Fallible<DomRoot<MouseEvent>> {
|
) -> Fallible<DomRoot<MouseEvent>> {
|
||||||
let bubbles = EventBubbles::from(init.parent.parent.parent.bubbles);
|
let bubbles = EventBubbles::from(init.parent.parent.parent.bubbles);
|
||||||
let cancelable = EventCancelable::from(init.parent.parent.parent.cancelable);
|
let cancelable = EventCancelable::from(init.parent.parent.parent.cancelable);
|
||||||
|
let page_point = Point2D::new(
|
||||||
|
window.ScrollX() + init.clientX,
|
||||||
|
window.ScrollY() + init.clientY,
|
||||||
|
);
|
||||||
let event = MouseEvent::new_with_proto(
|
let event = MouseEvent::new_with_proto(
|
||||||
window,
|
window,
|
||||||
proto,
|
proto,
|
||||||
|
@ -329,14 +290,10 @@ impl MouseEventMethods<crate::DomTypeHolder> for MouseEvent {
|
||||||
cancelable,
|
cancelable,
|
||||||
init.parent.parent.view.as_deref(),
|
init.parent.parent.view.as_deref(),
|
||||||
init.parent.parent.detail,
|
init.parent.parent.detail,
|
||||||
init.screenX,
|
Point2D::new(init.screenX, init.screenY),
|
||||||
init.screenY,
|
Point2D::new(init.clientX, init.clientY),
|
||||||
init.clientX,
|
page_point,
|
||||||
init.clientY,
|
init.parent.modifiers(),
|
||||||
init.parent.ctrlKey,
|
|
||||||
init.parent.altKey,
|
|
||||||
init.parent.shiftKey,
|
|
||||||
init.parent.metaKey,
|
|
||||||
init.button,
|
init.button,
|
||||||
init.buttons,
|
init.buttons,
|
||||||
init.relatedTarget.as_deref(),
|
init.relatedTarget.as_deref(),
|
||||||
|
@ -351,110 +308,128 @@ impl MouseEventMethods<crate::DomTypeHolder> for MouseEvent {
|
||||||
|
|
||||||
/// <https://w3c.github.io/uievents/#widl-MouseEvent-screenX>
|
/// <https://w3c.github.io/uievents/#widl-MouseEvent-screenX>
|
||||||
fn ScreenX(&self) -> i32 {
|
fn ScreenX(&self) -> i32 {
|
||||||
self.screen_x.get()
|
self.screen_point.get().x
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://w3c.github.io/uievents/#widl-MouseEvent-screenY>
|
/// <https://w3c.github.io/uievents/#widl-MouseEvent-screenY>
|
||||||
fn ScreenY(&self) -> i32 {
|
fn ScreenY(&self) -> i32 {
|
||||||
self.screen_y.get()
|
self.screen_point.get().y
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://w3c.github.io/uievents/#widl-MouseEvent-clientX>
|
/// <https://w3c.github.io/uievents/#widl-MouseEvent-clientX>
|
||||||
fn ClientX(&self) -> i32 {
|
fn ClientX(&self) -> i32 {
|
||||||
self.client_x.get()
|
self.client_point.get().x
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://w3c.github.io/uievents/#widl-MouseEvent-clientY>
|
/// <https://w3c.github.io/uievents/#widl-MouseEvent-clientY>
|
||||||
fn ClientY(&self) -> i32 {
|
fn ClientY(&self) -> i32 {
|
||||||
self.client_y.get()
|
self.client_point.get().y
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://drafts.csswg.org/cssom-view/#dom-mouseevent-pagex>
|
/// <https://drafts.csswg.org/cssom-view/#dom-mouseevent-pagex>
|
||||||
fn PageX(&self) -> i32 {
|
fn PageX(&self) -> i32 {
|
||||||
|
// The pageX attribute must follow these steps:
|
||||||
|
// > 1. If the event’s dispatch flag is set, return the horizontal coordinate of the
|
||||||
|
// > position where the event occurred relative to the origin of the initial containing
|
||||||
|
// > block and terminate these steps.
|
||||||
if self.upcast::<Event>().dispatching() {
|
if self.upcast::<Event>().dispatching() {
|
||||||
self.page_x.get()
|
return self.page_point.get().x;
|
||||||
} else {
|
|
||||||
self.global().as_window().ScrollX() + self.client_x.get()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// > 2. Let offset be the value of the scrollX attribute of the event’s associated
|
||||||
|
// > Window object, if there is one, or zero otherwise.
|
||||||
|
// > 3. Return the sum of offset and the value of the event’s clientX attribute.
|
||||||
|
self.global().as_window().ScrollX() + self.ClientX()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://drafts.csswg.org/cssom-view/#dom-mouseevent-pagey>
|
/// <https://drafts.csswg.org/cssom-view/#dom-mouseevent-pagey>
|
||||||
fn PageY(&self) -> i32 {
|
fn PageY(&self) -> i32 {
|
||||||
|
// The pageY attribute must follow these steps:
|
||||||
|
// > 1. If the event’s dispatch flag is set, return the vertical coordinate of the
|
||||||
|
// > position where the event occurred relative to the origin of the initial
|
||||||
|
// > containing block and terminate these steps.
|
||||||
if self.upcast::<Event>().dispatching() {
|
if self.upcast::<Event>().dispatching() {
|
||||||
self.page_y.get()
|
return self.page_point.get().y;
|
||||||
} else {
|
|
||||||
self.global().as_window().ScrollY() + self.client_y.get()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// > 2. Let offset be the value of the scrollY attribute of the event’s associated
|
||||||
|
// > Window object, if there is one, or zero otherwise.
|
||||||
|
// > 3. Return the sum of offset and the value of the event’s clientY attribute.
|
||||||
|
self.global().as_window().ScrollY() + self.ClientY()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://drafts.csswg.org/cssom-view/#dom-mouseevent-x>
|
/// <https://drafts.csswg.org/cssom-view/#dom-mouseevent-x>
|
||||||
fn X(&self) -> i32 {
|
fn X(&self) -> i32 {
|
||||||
self.client_x.get()
|
self.ClientX()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://drafts.csswg.org/cssom-view/#dom-mouseevent-y>
|
/// <https://drafts.csswg.org/cssom-view/#dom-mouseevent-y>
|
||||||
fn Y(&self) -> i32 {
|
fn Y(&self) -> i32 {
|
||||||
self.client_y.get()
|
self.ClientY()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://drafts.csswg.org/cssom-view/#dom-mouseevent-offsetx>
|
/// <https://drafts.csswg.org/cssom-view/#dom-mouseevent-offsetx>
|
||||||
fn OffsetX(&self, can_gc: CanGc) -> i32 {
|
fn OffsetX(&self, can_gc: CanGc) -> i32 {
|
||||||
|
// > The offsetX attribute must follow these steps:
|
||||||
|
// > 1. If the event’s dispatch flag is set, return the x-coordinate of the position
|
||||||
|
// > where the event occurred relative to the origin of the padding edge of the
|
||||||
|
// > target node, ignoring the transforms that apply to the element and its
|
||||||
|
// > ancestors, and terminate these steps.
|
||||||
let event = self.upcast::<Event>();
|
let event = self.upcast::<Event>();
|
||||||
if event.dispatching() {
|
if event.dispatching() {
|
||||||
match event.GetTarget() {
|
let Some(target) = event.GetTarget() else {
|
||||||
Some(target) => {
|
return 0;
|
||||||
if let Some(node) = target.downcast::<Node>() {
|
};
|
||||||
let rect = node.client_rect(can_gc);
|
let Some(node) = target.downcast::<Node>() else {
|
||||||
self.client_x.get() - rect.origin.x
|
return 0;
|
||||||
} else {
|
};
|
||||||
self.offset_x.get()
|
return self.ClientX() - node.client_rect(can_gc).origin.x;
|
||||||
}
|
|
||||||
},
|
|
||||||
None => self.offset_x.get(),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.PageX()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// > 2. Return the value of the event’s pageX attribute.
|
||||||
|
self.PageX()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://drafts.csswg.org/cssom-view/#dom-mouseevent-offsety>
|
/// <https://drafts.csswg.org/cssom-view/#dom-mouseevent-offsety>
|
||||||
fn OffsetY(&self, can_gc: CanGc) -> i32 {
|
fn OffsetY(&self, can_gc: CanGc) -> i32 {
|
||||||
|
// > The offsetY attribute must follow these steps:
|
||||||
|
// > 1. If the event’s dispatch flag is set, return the y-coordinate of the
|
||||||
|
// > position where the event occurred relative to the origin of the padding edge of
|
||||||
|
// > the target node, ignoring the transforms that apply to the element and its
|
||||||
|
// > ancestors, and terminate these steps.
|
||||||
let event = self.upcast::<Event>();
|
let event = self.upcast::<Event>();
|
||||||
if event.dispatching() {
|
if event.dispatching() {
|
||||||
match event.GetTarget() {
|
let Some(target) = event.GetTarget() else {
|
||||||
Some(target) => {
|
return 0;
|
||||||
if let Some(node) = target.downcast::<Node>() {
|
};
|
||||||
let rect = node.client_rect(can_gc);
|
let Some(node) = target.downcast::<Node>() else {
|
||||||
self.client_y.get() - rect.origin.y
|
return 0;
|
||||||
} else {
|
};
|
||||||
self.offset_y.get()
|
return self.ClientY() - node.client_rect(can_gc).origin.y;
|
||||||
}
|
|
||||||
},
|
|
||||||
None => self.offset_y.get(),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.PageY()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2. Return the value of the event’s pageY attribute.
|
||||||
|
self.PageY()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://w3c.github.io/uievents/#dom-mouseevent-ctrlkey>
|
/// <https://w3c.github.io/uievents/#dom-mouseevent-ctrlkey>
|
||||||
fn CtrlKey(&self) -> bool {
|
fn CtrlKey(&self) -> bool {
|
||||||
self.ctrl_key.get()
|
self.modifiers.get().contains(Modifiers::CONTROL)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://w3c.github.io/uievents/#dom-mouseevent-shiftkey>
|
/// <https://w3c.github.io/uievents/#dom-mouseevent-shiftkey>
|
||||||
fn ShiftKey(&self) -> bool {
|
fn ShiftKey(&self) -> bool {
|
||||||
self.shift_key.get()
|
self.modifiers.get().contains(Modifiers::SHIFT)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://w3c.github.io/uievents/#dom-mouseevent-altkey>
|
/// <https://w3c.github.io/uievents/#dom-mouseevent-altkey>
|
||||||
fn AltKey(&self) -> bool {
|
fn AltKey(&self) -> bool {
|
||||||
self.alt_key.get()
|
self.modifiers.get().contains(Modifiers::ALT)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://w3c.github.io/uievents/#dom-mouseevent-metakey>
|
/// <https://w3c.github.io/uievents/#dom-mouseevent-metakey>
|
||||||
fn MetaKey(&self) -> bool {
|
fn MetaKey(&self) -> bool {
|
||||||
self.meta_key.get()
|
self.modifiers.get().contains(Modifiers::META)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://w3c.github.io/uievents/#dom-mouseevent-button>
|
/// <https://w3c.github.io/uievents/#dom-mouseevent-button>
|
||||||
|
@ -515,14 +490,32 @@ impl MouseEventMethods<crate::DomTypeHolder> for MouseEvent {
|
||||||
view_arg,
|
view_arg,
|
||||||
detail_arg,
|
detail_arg,
|
||||||
);
|
);
|
||||||
self.screen_x.set(screen_x_arg);
|
self.screen_point
|
||||||
self.screen_y.set(screen_y_arg);
|
.set(Point2D::new(screen_x_arg, screen_y_arg));
|
||||||
self.client_x.set(client_x_arg);
|
self.client_point
|
||||||
self.client_y.set(client_y_arg);
|
.set(Point2D::new(client_x_arg, client_y_arg));
|
||||||
self.ctrl_key.set(ctrl_key_arg);
|
|
||||||
self.alt_key.set(alt_key_arg);
|
let global = self.global();
|
||||||
self.shift_key.set(shift_key_arg);
|
self.page_point.set(Point2D::new(
|
||||||
self.meta_key.set(meta_key_arg);
|
global.as_window().ScrollX() + client_x_arg,
|
||||||
|
global.as_window().ScrollY() + client_y_arg,
|
||||||
|
));
|
||||||
|
|
||||||
|
let mut modifiers = Modifiers::empty();
|
||||||
|
if ctrl_key_arg {
|
||||||
|
modifiers.insert(Modifiers::CONTROL);
|
||||||
|
}
|
||||||
|
if alt_key_arg {
|
||||||
|
modifiers.insert(Modifiers::ALT);
|
||||||
|
}
|
||||||
|
if shift_key_arg {
|
||||||
|
modifiers.insert(Modifiers::SHIFT);
|
||||||
|
}
|
||||||
|
if meta_key_arg {
|
||||||
|
modifiers.insert(Modifiers::META);
|
||||||
|
}
|
||||||
|
self.modifiers.set(modifiers);
|
||||||
|
|
||||||
self.button.set(button_arg);
|
self.button.set(button_arg);
|
||||||
self.related_target.set(related_target_arg);
|
self.related_target.set(related_target_arg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,13 @@ use bitflags::bitflags;
|
||||||
use devtools_traits::NodeInfo;
|
use devtools_traits::NodeInfo;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use embedder_traits::UntrustedNodeAddress;
|
use embedder_traits::UntrustedNodeAddress;
|
||||||
|
use euclid::Point2D;
|
||||||
use euclid::default::{Rect, Size2D};
|
use euclid::default::{Rect, Size2D};
|
||||||
use html5ever::serialize::HtmlSerializer;
|
use html5ever::serialize::HtmlSerializer;
|
||||||
use html5ever::{Namespace, Prefix, QualName, ns, serialize as html_serialize};
|
use html5ever::{Namespace, Prefix, QualName, ns, serialize as html_serialize};
|
||||||
use js::jsapi::JSObject;
|
use js::jsapi::JSObject;
|
||||||
use js::rust::HandleObject;
|
use js::rust::HandleObject;
|
||||||
|
use keyboard_types::Modifiers;
|
||||||
use layout_api::{
|
use layout_api::{
|
||||||
GenericLayoutData, HTMLCanvasData, HTMLMediaData, LayoutElementType, LayoutNodeType, QueryMsg,
|
GenericLayoutData, HTMLCanvasData, HTMLMediaData, LayoutElementType, LayoutNodeType, QueryMsg,
|
||||||
SVGSVGData, StyleData, TrustedNodeAddress,
|
SVGSVGData, StyleData, TrustedNodeAddress,
|
||||||
|
@ -479,14 +481,10 @@ impl Node {
|
||||||
EventCancelable::Cancelable, // Step 3: cancelable
|
EventCancelable::Cancelable, // Step 3: cancelable
|
||||||
Some(&window), // Step 7: view
|
Some(&window), // Step 7: view
|
||||||
0, // detail uninitialized
|
0, // detail uninitialized
|
||||||
0, // coordinates uninitialized
|
Point2D::zero(), // coordinates uninitialized
|
||||||
0, // coordinates uninitialized
|
Point2D::zero(), // coordinates uninitialized
|
||||||
0, // coordinates uninitialized
|
Point2D::zero(), // coordinates uninitialized
|
||||||
0, // coordinates uninitialized
|
Modifiers::empty(), // empty modifiers
|
||||||
false, // ctrl_key
|
|
||||||
false, // alt_key
|
|
||||||
false, // shift_key
|
|
||||||
false, // meta_key
|
|
||||||
0, // button, left mouse button
|
0, // button, left mouse button
|
||||||
0, // buttons
|
0, // buttons
|
||||||
None, // related_target
|
None, // related_target
|
||||||
|
|
|
@ -5,8 +5,11 @@
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use euclid::default::Point2D;
|
use euclid::Point2D;
|
||||||
use js::rust::HandleObject;
|
use js::rust::HandleObject;
|
||||||
|
use keyboard_types::Modifiers;
|
||||||
|
use script_bindings::codegen::GenericBindings::WindowBinding::WindowMethods;
|
||||||
|
use style_traits::CSSPixel;
|
||||||
|
|
||||||
use super::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods;
|
use super::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods;
|
||||||
use crate::dom::bindings::cell::DomRefCell;
|
use crate::dom::bindings::cell::DomRefCell;
|
||||||
|
@ -95,18 +98,14 @@ impl PointerEvent {
|
||||||
cancelable: EventCancelable,
|
cancelable: EventCancelable,
|
||||||
view: Option<&Window>,
|
view: Option<&Window>,
|
||||||
detail: i32,
|
detail: i32,
|
||||||
screen_x: i32,
|
screen_point: Point2D<i32, CSSPixel>,
|
||||||
screen_y: i32,
|
client_point: Point2D<i32, CSSPixel>,
|
||||||
client_x: i32,
|
page_point: Point2D<i32, CSSPixel>,
|
||||||
client_y: i32,
|
modifiers: Modifiers,
|
||||||
ctrl_key: bool,
|
|
||||||
alt_key: bool,
|
|
||||||
shift_key: bool,
|
|
||||||
meta_key: bool,
|
|
||||||
button: i16,
|
button: i16,
|
||||||
buttons: u16,
|
buttons: u16,
|
||||||
related_target: Option<&EventTarget>,
|
related_target: Option<&EventTarget>,
|
||||||
point_in_target: Option<Point2D<f32>>,
|
point_in_target: Option<Point2D<f32, CSSPixel>>,
|
||||||
pointer_id: i32,
|
pointer_id: i32,
|
||||||
width: i32,
|
width: i32,
|
||||||
height: i32,
|
height: i32,
|
||||||
|
@ -131,14 +130,10 @@ impl PointerEvent {
|
||||||
cancelable,
|
cancelable,
|
||||||
view,
|
view,
|
||||||
detail,
|
detail,
|
||||||
screen_x,
|
screen_point,
|
||||||
screen_y,
|
client_point,
|
||||||
client_x,
|
page_point,
|
||||||
client_y,
|
modifiers,
|
||||||
ctrl_key,
|
|
||||||
alt_key,
|
|
||||||
shift_key,
|
|
||||||
meta_key,
|
|
||||||
button,
|
button,
|
||||||
buttons,
|
buttons,
|
||||||
related_target,
|
related_target,
|
||||||
|
@ -170,18 +165,14 @@ impl PointerEvent {
|
||||||
cancelable: EventCancelable,
|
cancelable: EventCancelable,
|
||||||
view: Option<&Window>,
|
view: Option<&Window>,
|
||||||
detail: i32,
|
detail: i32,
|
||||||
screen_x: i32,
|
screen_point: Point2D<i32, CSSPixel>,
|
||||||
screen_y: i32,
|
client_point: Point2D<i32, CSSPixel>,
|
||||||
client_x: i32,
|
page_point: Point2D<i32, CSSPixel>,
|
||||||
client_y: i32,
|
modifiers: Modifiers,
|
||||||
ctrl_key: bool,
|
|
||||||
alt_key: bool,
|
|
||||||
shift_key: bool,
|
|
||||||
meta_key: bool,
|
|
||||||
button: i16,
|
button: i16,
|
||||||
buttons: u16,
|
buttons: u16,
|
||||||
related_target: Option<&EventTarget>,
|
related_target: Option<&EventTarget>,
|
||||||
point_in_target: Option<Point2D<f32>>,
|
point_in_target: Option<Point2D<f32, CSSPixel>>,
|
||||||
pointer_id: i32,
|
pointer_id: i32,
|
||||||
width: i32,
|
width: i32,
|
||||||
height: i32,
|
height: i32,
|
||||||
|
@ -205,14 +196,10 @@ impl PointerEvent {
|
||||||
cancelable,
|
cancelable,
|
||||||
view,
|
view,
|
||||||
detail,
|
detail,
|
||||||
screen_x,
|
screen_point,
|
||||||
screen_y,
|
client_point,
|
||||||
client_x,
|
page_point,
|
||||||
client_y,
|
modifiers,
|
||||||
ctrl_key,
|
|
||||||
alt_key,
|
|
||||||
shift_key,
|
|
||||||
meta_key,
|
|
||||||
button,
|
button,
|
||||||
buttons,
|
buttons,
|
||||||
related_target,
|
related_target,
|
||||||
|
@ -247,6 +234,10 @@ impl PointerEventMethods<crate::DomTypeHolder> for PointerEvent {
|
||||||
) -> DomRoot<PointerEvent> {
|
) -> DomRoot<PointerEvent> {
|
||||||
let bubbles = EventBubbles::from(init.parent.parent.parent.parent.bubbles);
|
let bubbles = EventBubbles::from(init.parent.parent.parent.parent.bubbles);
|
||||||
let cancelable = EventCancelable::from(init.parent.parent.parent.parent.cancelable);
|
let cancelable = EventCancelable::from(init.parent.parent.parent.parent.cancelable);
|
||||||
|
let page_point = Point2D::new(
|
||||||
|
window.ScrollX() + init.parent.clientX,
|
||||||
|
window.ScrollY() + init.parent.clientY,
|
||||||
|
);
|
||||||
PointerEvent::new_with_proto(
|
PointerEvent::new_with_proto(
|
||||||
window,
|
window,
|
||||||
proto,
|
proto,
|
||||||
|
@ -255,14 +246,10 @@ impl PointerEventMethods<crate::DomTypeHolder> for PointerEvent {
|
||||||
cancelable,
|
cancelable,
|
||||||
init.parent.parent.parent.view.as_deref(),
|
init.parent.parent.parent.view.as_deref(),
|
||||||
init.parent.parent.parent.detail,
|
init.parent.parent.parent.detail,
|
||||||
init.parent.screenX,
|
Point2D::new(init.parent.screenX, init.parent.screenY),
|
||||||
init.parent.screenY,
|
Point2D::new(init.parent.clientX, init.parent.clientY),
|
||||||
init.parent.clientX,
|
page_point,
|
||||||
init.parent.clientY,
|
init.parent.parent.modifiers(),
|
||||||
init.parent.parent.ctrlKey,
|
|
||||||
init.parent.parent.altKey,
|
|
||||||
init.parent.parent.shiftKey,
|
|
||||||
init.parent.parent.metaKey,
|
|
||||||
init.parent.button,
|
init.parent.button,
|
||||||
init.parent.buttons,
|
init.parent.buttons,
|
||||||
init.parent.relatedTarget.as_deref(),
|
init.parent.relatedTarget.as_deref(),
|
||||||
|
|
|
@ -49,9 +49,9 @@ use devtools_traits::{
|
||||||
};
|
};
|
||||||
use embedder_traits::user_content_manager::UserContentManager;
|
use embedder_traits::user_content_manager::UserContentManager;
|
||||||
use embedder_traits::{
|
use embedder_traits::{
|
||||||
CompositorHitTestResult, EmbedderMsg, FocusSequenceNumber, InputEvent,
|
EmbedderMsg, FocusSequenceNumber, InputEvent, JavaScriptEvaluationError,
|
||||||
JavaScriptEvaluationError, JavaScriptEvaluationId, MediaSessionActionType, MouseButton,
|
JavaScriptEvaluationId, MediaSessionActionType, MouseButton, MouseButtonAction,
|
||||||
MouseButtonAction, MouseButtonEvent, Theme, ViewportDetails, WebDriverScriptCommand,
|
MouseButtonEvent, Theme, ViewportDetails, WebDriverScriptCommand,
|
||||||
};
|
};
|
||||||
use euclid::Point2D;
|
use euclid::Point2D;
|
||||||
use euclid::default::Rect;
|
use euclid::default::Rect;
|
||||||
|
@ -1021,20 +1021,14 @@ impl ScriptThread {
|
||||||
fn process_mouse_move_event(
|
fn process_mouse_move_event(
|
||||||
&self,
|
&self,
|
||||||
document: &Document,
|
document: &Document,
|
||||||
hit_test_result: Option<CompositorHitTestResult>,
|
input_event: &ConstellationInputEvent,
|
||||||
pressed_mouse_buttons: u16,
|
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) {
|
) {
|
||||||
// Get the previous target temporarily
|
// Get the previous target temporarily
|
||||||
let prev_mouse_over_target = self.topmost_mouse_over_target.get();
|
let prev_mouse_over_target = self.topmost_mouse_over_target.get();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
document.handle_mouse_move_event(
|
document.handle_mouse_move_event(input_event, &self.topmost_mouse_over_target, can_gc)
|
||||||
hit_test_result,
|
|
||||||
pressed_mouse_buttons,
|
|
||||||
&self.topmost_mouse_over_target,
|
|
||||||
can_gc,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Short-circuit if nothing changed
|
// Short-circuit if nothing changed
|
||||||
|
@ -1109,29 +1103,15 @@ impl ScriptThread {
|
||||||
|
|
||||||
match event.event {
|
match event.event {
|
||||||
InputEvent::MouseButton(mouse_button_event) => {
|
InputEvent::MouseButton(mouse_button_event) => {
|
||||||
document.handle_mouse_button_event(
|
document.handle_mouse_button_event(mouse_button_event, &event, can_gc);
|
||||||
mouse_button_event,
|
|
||||||
event.hit_test_result,
|
|
||||||
event.pressed_mouse_buttons,
|
|
||||||
can_gc,
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
InputEvent::MouseMove(_) => {
|
InputEvent::MouseMove(_) => {
|
||||||
// The event itself is unecessary here, because the point in the viewport is in the hit test.
|
// The event itself is unecessary here, because the point in the viewport is in the hit test.
|
||||||
self.process_mouse_move_event(
|
self.process_mouse_move_event(&document, &event, can_gc);
|
||||||
&document,
|
|
||||||
event.hit_test_result,
|
|
||||||
event.pressed_mouse_buttons,
|
|
||||||
can_gc,
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
InputEvent::MouseLeave(_) => {
|
InputEvent::MouseLeave(_) => {
|
||||||
self.topmost_mouse_over_target.take();
|
self.topmost_mouse_over_target.take();
|
||||||
document.handle_mouse_leave_event(
|
document.handle_mouse_leave_event(&event, can_gc);
|
||||||
event.hit_test_result,
|
|
||||||
event.pressed_mouse_buttons,
|
|
||||||
can_gc,
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
InputEvent::Touch(touch_event) => {
|
InputEvent::Touch(touch_event) => {
|
||||||
let touch_result =
|
let touch_result =
|
||||||
|
|
|
@ -28,6 +28,7 @@ js = { workspace = true }
|
||||||
jstraceable_derive = { path = "../jstraceable_derive" }
|
jstraceable_derive = { path = "../jstraceable_derive" }
|
||||||
libc = { workspace = true }
|
libc = { workspace = true }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
|
keyboard-types = { workspace = true }
|
||||||
malloc_size_of = { workspace = true }
|
malloc_size_of = { workspace = true }
|
||||||
malloc_size_of_derive = { workspace = true }
|
malloc_size_of_derive = { workspace = true }
|
||||||
num-traits = { workspace = true }
|
num-traits = { workspace = true }
|
||||||
|
|
|
@ -22,9 +22,11 @@ use js::rust::{
|
||||||
HandleId, HandleValue, MutableHandleValue, ToString, get_object_class, is_dom_class,
|
HandleId, HandleValue, MutableHandleValue, ToString, get_object_class, is_dom_class,
|
||||||
is_dom_object, maybe_wrap_value,
|
is_dom_object, maybe_wrap_value,
|
||||||
};
|
};
|
||||||
|
use keyboard_types::Modifiers;
|
||||||
use num_traits::Float;
|
use num_traits::Float;
|
||||||
|
|
||||||
use crate::JSTraceable;
|
use crate::JSTraceable;
|
||||||
|
use crate::codegen::GenericBindings::EventModifierInitBinding::EventModifierInit;
|
||||||
use crate::inheritance::Castable;
|
use crate::inheritance::Castable;
|
||||||
use crate::num::Finite;
|
use crate::num::Finite;
|
||||||
use crate::reflector::{DomObject, Reflector};
|
use crate::reflector::{DomObject, Reflector};
|
||||||
|
@ -589,3 +591,52 @@ pub(crate) unsafe fn windowproxy_from_handlevalue<D: crate::DomTypes>(
|
||||||
let ptr = value.to_private() as *const D::WindowProxy;
|
let ptr = value.to_private() as *const D::WindowProxy;
|
||||||
Ok(DomRoot::from_ref(&*ptr))
|
Ok(DomRoot::from_ref(&*ptr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<D: crate::DomTypes> EventModifierInit<D> {
|
||||||
|
pub fn modifiers(&self) -> Modifiers {
|
||||||
|
let mut modifiers = Modifiers::empty();
|
||||||
|
if self.altKey {
|
||||||
|
modifiers.insert(Modifiers::ALT);
|
||||||
|
}
|
||||||
|
if self.ctrlKey {
|
||||||
|
modifiers.insert(Modifiers::CONTROL);
|
||||||
|
}
|
||||||
|
if self.shiftKey {
|
||||||
|
modifiers.insert(Modifiers::SHIFT);
|
||||||
|
}
|
||||||
|
if self.metaKey {
|
||||||
|
modifiers.insert(Modifiers::META);
|
||||||
|
}
|
||||||
|
if self.keyModifierStateAltGraph {
|
||||||
|
modifiers.insert(Modifiers::ALT_GRAPH);
|
||||||
|
}
|
||||||
|
if self.keyModifierStateCapsLock {
|
||||||
|
modifiers.insert(Modifiers::CAPS_LOCK);
|
||||||
|
}
|
||||||
|
if self.keyModifierStateFn {
|
||||||
|
modifiers.insert(Modifiers::FN);
|
||||||
|
}
|
||||||
|
if self.keyModifierStateFnLock {
|
||||||
|
modifiers.insert(Modifiers::FN_LOCK);
|
||||||
|
}
|
||||||
|
if self.keyModifierStateHyper {
|
||||||
|
modifiers.insert(Modifiers::HYPER);
|
||||||
|
}
|
||||||
|
if self.keyModifierStateNumLock {
|
||||||
|
modifiers.insert(Modifiers::NUM_LOCK);
|
||||||
|
}
|
||||||
|
if self.keyModifierStateScrollLock {
|
||||||
|
modifiers.insert(Modifiers::SCROLL_LOCK);
|
||||||
|
}
|
||||||
|
if self.keyModifierStateSuper {
|
||||||
|
modifiers.insert(Modifiers::SUPER);
|
||||||
|
}
|
||||||
|
if self.keyModifierStateSymbol {
|
||||||
|
modifiers.insert(Modifiers::SYMBOL);
|
||||||
|
}
|
||||||
|
if self.keyModifierStateSymbolLock {
|
||||||
|
modifiers.insert(Modifiers::SYMBOL_LOCK);
|
||||||
|
}
|
||||||
|
modifiers
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use base::id::{PipelineId, ScrollTreeNodeId, WebViewId};
|
use base::id::{PipelineId, ScrollTreeNodeId, WebViewId};
|
||||||
use crossbeam_channel::Sender;
|
use crossbeam_channel::Sender;
|
||||||
use euclid::{Scale, Size2D};
|
use euclid::{Point2D, Scale, Size2D};
|
||||||
use http::{HeaderMap, Method, StatusCode};
|
use http::{HeaderMap, Method, StatusCode};
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
|
@ -770,10 +770,14 @@ pub struct CompositorHitTestResult {
|
||||||
pub pipeline_id: PipelineId,
|
pub pipeline_id: PipelineId,
|
||||||
|
|
||||||
/// The hit test point in the item's viewport.
|
/// The hit test point in the item's viewport.
|
||||||
pub point_in_viewport: euclid::default::Point2D<f32>,
|
pub point_in_viewport: Point2D<f32, CSSPixel>,
|
||||||
|
|
||||||
|
/// The hit test point relative to the root scroll node content origin / initial
|
||||||
|
/// containing block.
|
||||||
|
pub point_relative_to_initial_containing_block: Point2D<f32, CSSPixel>,
|
||||||
|
|
||||||
/// The hit test point relative to the item itself.
|
/// The hit test point relative to the item itself.
|
||||||
pub point_relative_to_item: euclid::default::Point2D<f32>,
|
pub point_relative_to_item: Point2D<f32, CSSPixel>,
|
||||||
|
|
||||||
/// The node address of the hit test result.
|
/// The node address of the hit test result.
|
||||||
pub node: UntrustedNodeAddress,
|
pub node: UntrustedNodeAddress,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue