aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/compositing/compositor.rs7
-rw-r--r--components/constellation/constellation.rs35
-rw-r--r--components/script/dom/activation.rs2
-rw-r--r--components/script/dom/document.rs36
-rw-r--r--components/script/dom/mouseevent.rs10
-rw-r--r--components/script/dom/webidls/MouseEvent.webidl4
-rw-r--r--components/script/script_thread.rs15
-rw-r--r--components/script_traits/lib.rs17
8 files changed, 111 insertions, 15 deletions
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs
index 2b1322bfc63..5f5e32bbd75 100644
--- a/components/compositing/compositor.rs
+++ b/components/compositing/compositor.rs
@@ -662,6 +662,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
result.point_in_viewport.to_untyped(),
Some(UntrustedNodeAddress(result.tag.0 as *const c_void)),
Some(result.point_relative_to_item.to_untyped()),
+ MouseButton::Left as u16,
);
let pipeline_id = PipelineId::from_webrender(result.pipeline);
@@ -705,7 +706,11 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
let results = self.hit_test_at_point(cursor);
if let Some(item) = results.items.first() {
let node_address = Some(UntrustedNodeAddress(item.tag.0 as *const c_void));
- let event = MouseMoveEvent(Some(item.point_in_viewport.to_untyped()), node_address);
+ let event = MouseMoveEvent(
+ Some(item.point_in_viewport.to_untyped()),
+ node_address,
+ MouseButton::Left as u16,
+ );
let pipeline_id = PipelineId::from_webrender(item.pipeline);
let msg = ConstellationMsg::ForwardEvent(pipeline_id, event);
if let Err(e) = self.constellation_chan.send(msg) {
diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs
index 713afb633e9..11967e10038 100644
--- a/components/constellation/constellation.rs
+++ b/components/constellation/constellation.rs
@@ -135,6 +135,8 @@ use net_traits::storage_thread::{StorageThreadMsg, StorageType};
use net_traits::{self, FetchResponseMsg, IpcSend, ResourceThreads};
use profile_traits::mem;
use profile_traits::time;
+use script_traits::CompositorEvent::{MouseButtonEvent, MouseMoveEvent};
+use script_traits::MouseEventType;
use script_traits::{webdriver_msg, LogEntry, ScriptToConstellationChan, ServiceWorkerMsg};
use script_traits::{
AnimationState, AnimationTickType, AuxiliaryBrowsingContextLoadInfo, CompositorEvent,
@@ -373,6 +375,10 @@ pub struct Constellation<Message, LTF, STF> {
/// Navigation requests from script awaiting approval from the embedder.
pending_approval_navigations: PendingApprovalNavigations,
+
+ /// Bitmask which indicates which combination of mouse buttons are
+ /// currently being pressed.
+ pressed_mouse_buttons: u16,
}
/// State needed to construct a constellation.
@@ -715,6 +721,7 @@ where
webvr_chan: state.webvr_chan,
canvas_chan: CanvasPaintThread::start(),
pending_approval_navigations: HashMap::new(),
+ pressed_mouse_buttons: 0,
};
constellation.run();
@@ -1798,6 +1805,34 @@ where
}
fn forward_event(&mut self, destination_pipeline_id: PipelineId, event: CompositorEvent) {
+ if let MouseButtonEvent(event_type, button, ..) = &event {
+ match event_type {
+ MouseEventType::MouseDown | MouseEventType::Click => {
+ self.pressed_mouse_buttons |= *button as u16;
+ },
+ MouseEventType::MouseUp => {
+ self.pressed_mouse_buttons &= !(*button as u16);
+ },
+ }
+ }
+
+ let event = match event {
+ MouseButtonEvent(event_type, button, point, node_address, point_in_node, _) => {
+ MouseButtonEvent(
+ event_type,
+ button,
+ point,
+ node_address,
+ point_in_node,
+ self.pressed_mouse_buttons,
+ )
+ },
+ MouseMoveEvent(point, node_address, _) => {
+ MouseMoveEvent(point, node_address, self.pressed_mouse_buttons)
+ },
+ _ => event,
+ };
+
let msg = ConstellationControlMsg::SendEvent(destination_pipeline_id, event);
let result = match self.pipelines.get(&destination_pipeline_id) {
None => {
diff --git a/components/script/dom/activation.rs b/components/script/dom/activation.rs
index b838ac4156a..e4658de2e9f 100644
--- a/components/script/dom/activation.rs
+++ b/components/script/dom/activation.rs
@@ -12,6 +12,7 @@ use crate::dom::mouseevent::MouseEvent;
use crate::dom::node::window_from_node;
use crate::dom::window::ReflowReason;
use script_layout_interface::message::ReflowGoal;
+use script_traits::MouseButton;
/// Trait for elements with defined activation behavior
pub trait Activatable {
@@ -96,6 +97,7 @@ pub fn synthetic_click_activation(
alt_key,
meta_key,
0,
+ MouseButton::Left as u16,
None,
None,
);
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index eeec8060fff..7eb43c81b79 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -926,6 +926,7 @@ impl Document {
mouse_event_type: MouseEventType,
node_address: Option<UntrustedNodeAddress>,
point_in_node: Option<Point2D<f32>>,
+ pressed_mouse_buttons: u16,
) {
let mouse_event_type_string = match mouse_event_type {
MouseEventType::Click => "click".to_owned(),
@@ -976,6 +977,7 @@ impl Document {
false,
false,
0i16,
+ pressed_mouse_buttons,
None,
point_in_node,
);
@@ -1007,14 +1009,19 @@ impl Document {
if let MouseEventType::Click = mouse_event_type {
self.commit_focus_transaction(FocusType::Element);
- self.maybe_fire_dblclick(client_point, node);
+ self.maybe_fire_dblclick(client_point, node, pressed_mouse_buttons);
}
self.window
.reflow(ReflowGoal::Full, ReflowReason::MouseEvent);
}
- fn maybe_fire_dblclick(&self, click_pos: Point2D<f32>, target: &Node) {
+ fn maybe_fire_dblclick(
+ &self,
+ click_pos: Point2D<f32>,
+ target: &Node,
+ pressed_mouse_buttons: u16,
+ ) {
// https://w3c.github.io/uievents/#event-type-dblclick
let now = Instant::now();
@@ -1053,6 +1060,7 @@ impl Document {
false,
false,
0i16,
+ pressed_mouse_buttons,
None,
None,
);
@@ -1073,6 +1081,7 @@ impl Document {
client_point: Point2D<f32>,
target: &EventTarget,
event_name: FireMouseEventType,
+ pressed_mouse_buttons: u16,
) {
let client_x = client_point.x.to_i32().unwrap_or(0);
let client_y = client_point.y.to_i32().unwrap_or(0);
@@ -1093,6 +1102,7 @@ impl Document {
false,
false,
0i16,
+ pressed_mouse_buttons,
None,
None,
);
@@ -1107,6 +1117,7 @@ impl Document {
client_point: Option<Point2D<f32>>,
prev_mouse_over_target: &MutNullableDom<Element>,
node_address: Option<UntrustedNodeAddress>,
+ pressed_mouse_buttons: u16,
) {
let client_point = match client_point {
None => {
@@ -1132,7 +1143,12 @@ impl Document {
None => return,
};
- self.fire_mouse_event(client_point, new_target.upcast(), FireMouseEventType::Move);
+ self.fire_mouse_event(
+ client_point,
+ new_target.upcast(),
+ FireMouseEventType::Move,
+ pressed_mouse_buttons,
+ );
// Nothing more to do here, mousemove is sent,
// and the element under the mouse hasn't changed.
@@ -1165,7 +1181,12 @@ impl Document {
}
// Remove hover state to old target and its parents
- self.fire_mouse_event(client_point, old_target.upcast(), FireMouseEventType::Out);
+ self.fire_mouse_event(
+ client_point,
+ old_target.upcast(),
+ FireMouseEventType::Out,
+ pressed_mouse_buttons,
+ );
// TODO: Fire mouseleave here only if the old target is
// not an ancestor of the new target.
@@ -1184,7 +1205,12 @@ impl Document {
element.set_hover_state(true);
}
- self.fire_mouse_event(client_point, &new_target.upcast(), FireMouseEventType::Over);
+ self.fire_mouse_event(
+ client_point,
+ &new_target.upcast(),
+ FireMouseEventType::Over,
+ pressed_mouse_buttons,
+ );
// TODO: Fire mouseenter here.
}
diff --git a/components/script/dom/mouseevent.rs b/components/script/dom/mouseevent.rs
index 6ae1c2efab9..6fcadbbeaf8 100644
--- a/components/script/dom/mouseevent.rs
+++ b/components/script/dom/mouseevent.rs
@@ -32,6 +32,7 @@ pub struct MouseEvent {
alt_key: Cell<bool>,
meta_key: Cell<bool>,
button: Cell<i16>,
+ buttons: Cell<u16>,
related_target: MutNullableDom<EventTarget>,
point_in_target: Cell<Option<Point2D<f32>>>,
}
@@ -49,6 +50,7 @@ impl MouseEvent {
alt_key: Cell::new(false),
meta_key: Cell::new(false),
button: Cell::new(0),
+ buttons: Cell::new(0),
related_target: Default::default(),
point_in_target: Cell::new(None),
}
@@ -78,6 +80,7 @@ impl MouseEvent {
shift_key: bool,
meta_key: bool,
button: i16,
+ buttons: u16,
related_target: Option<&EventTarget>,
point_in_target: Option<Point2D<f32>>,
) -> DomRoot<MouseEvent> {
@@ -99,6 +102,7 @@ impl MouseEvent {
button,
related_target,
);
+ ev.buttons.set(buttons);
ev.point_in_target.set(point_in_target);
ev
}
@@ -126,6 +130,7 @@ impl MouseEvent {
init.parent.shiftKey,
init.parent.metaKey,
init.button,
+ 0,
init.relatedTarget.deref(),
None,
);
@@ -183,6 +188,11 @@ impl MouseEventMethods for MouseEvent {
self.button.get()
}
+ // https://w3c.github.io/uievents/#dom-mouseevent-buttons
+ fn Buttons(&self) -> u16 {
+ self.buttons.get()
+ }
+
// https://w3c.github.io/uievents/#widl-MouseEvent-relatedTarget
fn GetRelatedTarget(&self) -> Option<DomRoot<EventTarget>> {
self.related_target.get()
diff --git a/components/script/dom/webidls/MouseEvent.webidl b/components/script/dom/webidls/MouseEvent.webidl
index 5e5a03790fa..29d5872f65e 100644
--- a/components/script/dom/webidls/MouseEvent.webidl
+++ b/components/script/dom/webidls/MouseEvent.webidl
@@ -17,7 +17,7 @@ interface MouseEvent : UIEvent {
readonly attribute short button;
readonly attribute EventTarget? relatedTarget;
// Introduced in DOM Level 3
- //readonly attribute unsigned short buttons;
+ readonly attribute unsigned short buttons;
//boolean getModifierState (DOMString keyArg);
[Pref="dom.mouseevent.which.enabled"]
@@ -31,7 +31,7 @@ dictionary MouseEventInit : EventModifierInit {
long clientX = 0;
long clientY = 0;
short button = 0;
- //unsigned short buttons = 0;
+ unsigned short buttons = 0;
EventTarget? relatedTarget = null;
};
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index cc0500805aa..f45a4349a55 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -3060,7 +3060,14 @@ impl ScriptThread {
self.handle_resize_event(pipeline_id, new_size, size_type);
},
- MouseButtonEvent(event_type, button, point, node_address, point_in_node) => {
+ MouseButtonEvent(
+ event_type,
+ button,
+ point,
+ node_address,
+ point_in_node,
+ pressed_mouse_buttons,
+ ) => {
self.handle_mouse_event(
pipeline_id,
event_type,
@@ -3068,10 +3075,11 @@ impl ScriptThread {
point,
node_address,
point_in_node,
+ pressed_mouse_buttons,
);
},
- MouseMoveEvent(point, node_address) => {
+ MouseMoveEvent(point, node_address, pressed_mouse_buttons) => {
let document = match { self.documents.borrow().find_document(pipeline_id) } {
Some(document) => document,
None => return warn!("Message sent to closed pipeline {}.", pipeline_id),
@@ -3086,6 +3094,7 @@ impl ScriptThread {
point,
&self.topmost_mouse_over_target,
node_address,
+ pressed_mouse_buttons,
);
// Short-circuit if nothing changed
@@ -3185,6 +3194,7 @@ impl ScriptThread {
point: Point2D<f32>,
node_address: Option<UntrustedNodeAddress>,
point_in_node: Option<Point2D<f32>>,
+ pressed_mouse_buttons: u16,
) {
let document = match { self.documents.borrow().find_document(pipeline_id) } {
Some(document) => document,
@@ -3197,6 +3207,7 @@ impl ScriptThread {
mouse_event_type,
node_address,
point_in_node,
+ pressed_mouse_buttons,
);
}
diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs
index 0e5fc316037..d5a030323f6 100644
--- a/components/script_traits/lib.rs
+++ b/components/script_traits/lib.rs
@@ -444,11 +444,11 @@ pub struct TouchId(pub i32);
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub enum MouseButton {
/// The left mouse button.
- Left,
- /// The middle mouse button.
- Middle,
+ Left = 1,
/// The right mouse button.
- Right,
+ Right = 2,
+ /// The middle mouse button.
+ Middle = 4,
}
/// The types of mouse events
@@ -474,9 +474,16 @@ pub enum CompositorEvent {
Point2D<f32>,
Option<UntrustedNodeAddress>,
Option<Point2D<f32>>,
+ // Bitmask of MouseButton values representing the currently pressed buttons
+ u16,
),
/// The mouse was moved over a point (or was moved out of the recognizable region).
- MouseMoveEvent(Option<Point2D<f32>>, Option<UntrustedNodeAddress>),
+ MouseMoveEvent(
+ Option<Point2D<f32>>,
+ Option<UntrustedNodeAddress>,
+ // Bitmask of MouseButton values representing the currently pressed buttons
+ u16,
+ ),
/// A touch event was generated with a touch ID and location.
TouchEvent(
TouchEventType,