aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/compositing/compositor.rs17
-rw-r--r--components/compositing/compositor_thread.rs5
-rw-r--r--components/constellation/constellation.rs9
-rw-r--r--components/script_traits/lib.rs2
-rw-r--r--components/webdriver_server/actions.rs155
5 files changed, 160 insertions, 28 deletions
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs
index 98de79cc3f8..7ac80ee4832 100644
--- a/components/compositing/compositor.rs
+++ b/components/compositing/compositor.rs
@@ -518,6 +518,23 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
}
},
+ (
+ Msg::WebDriverMouseButtonEvent(mouse_event_type, mouse_button, x, y),
+ ShutdownState::NotShuttingDown,
+ ) => {
+ self.on_mouse_window_event_class(match mouse_event_type {
+ MouseEventType::Click => {
+ MouseWindowEvent::Click(mouse_button, DevicePoint::new(x, y))
+ },
+ MouseEventType::MouseDown => {
+ MouseWindowEvent::MouseDown(mouse_button, DevicePoint::new(x, y))
+ },
+ MouseEventType::MouseUp => {
+ MouseWindowEvent::MouseUp(mouse_button, DevicePoint::new(x, y))
+ },
+ });
+ },
+
(Msg::PendingPaintMetric(pipeline_id, epoch), _) => {
self.pending_paint_metrics.insert(pipeline_id, epoch);
},
diff --git a/components/compositing/compositor_thread.rs b/components/compositing/compositor_thread.rs
index 9250d25e5bf..f095ab65b1c 100644
--- a/components/compositing/compositor_thread.rs
+++ b/components/compositing/compositor_thread.rs
@@ -14,7 +14,7 @@ use msg::constellation_msg::{PipelineId, TopLevelBrowsingContextId};
use net_traits::image::base::Image;
use profile_traits::mem;
use profile_traits::time;
-use script_traits::{AnimationState, ConstellationMsg, EventResult};
+use script_traits::{AnimationState, ConstellationMsg, EventResult, MouseButton, MouseEventType};
use std::fmt::{Debug, Error, Formatter};
use style_traits::viewport::ViewportConstraints;
use webrender_api;
@@ -106,6 +106,8 @@ pub enum Msg {
PendingPaintMetric(PipelineId, Epoch),
/// The load of a page has completed
LoadComplete(TopLevelBrowsingContextId),
+ /// WebDriver mouse button event
+ WebDriverMouseButtonEvent(MouseEventType, MouseButton, f32, f32),
/// Get Window Informations size and position.
GetClientWindow(IpcSender<(DeviceIntSize, DeviceIntPoint)>),
@@ -132,6 +134,7 @@ impl Debug for Msg {
Msg::Dispatch(..) => write!(f, "Dispatch"),
Msg::PendingPaintMetric(..) => write!(f, "PendingPaintMetric"),
Msg::LoadComplete(..) => write!(f, "LoadComplete"),
+ Msg::WebDriverMouseButtonEvent(..) => write!(f, "WebDriverMouseButtonEvent"),
Msg::GetClientWindow(..) => write!(f, "GetClientWindow"),
Msg::GetScreenSize(..) => write!(f, "GetScreenSize"),
Msg::GetScreenAvailSize(..) => write!(f, "GetScreenAvailSize"),
diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs
index ce163430d0a..b443163f8d5 100644
--- a/components/constellation/constellation.rs
+++ b/components/constellation/constellation.rs
@@ -3490,6 +3490,15 @@ where
return self.handle_send_error(pipeline_id, e);
}
},
+ WebDriverCommandMsg::MouseButtonAction(mouse_event_type, mouse_button, x, y) => {
+ self.compositor_proxy
+ .send(ToCompositorMsg::WebDriverMouseButtonEvent(
+ mouse_event_type,
+ mouse_button,
+ x,
+ y,
+ ));
+ },
WebDriverCommandMsg::TakeScreenshot(_, reply) => {
self.compositor_proxy
.send(ToCompositorMsg::CreatePng(reply));
diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs
index 6a293c68ed0..5aac6b47e5e 100644
--- a/components/script_traits/lib.rs
+++ b/components/script_traits/lib.rs
@@ -800,6 +800,8 @@ pub enum WebDriverCommandMsg {
SendKeys(BrowsingContextId, Vec<WebDriverInputEvent>),
/// Act as if keys were pressed or release in the browsing context with the given ID.
KeyboardAction(BrowsingContextId, KeyboardEvent),
+ /// Act as if the mouse was clicked in the browsing context with the given ID.
+ MouseButtonAction(MouseEventType, MouseButton, f32, f32),
/// Set the window size.
SetWindowSize(
TopLevelBrowsingContextId,
diff --git a/components/webdriver_server/actions.rs b/components/webdriver_server/actions.rs
index e86fd7ad059..0182a16bac3 100644
--- a/components/webdriver_server/actions.rs
+++ b/components/webdriver_server/actions.rs
@@ -4,12 +4,15 @@
use crate::Handler;
use keyboard_types::webdriver::KeyInputState;
-use script_traits::{ConstellationMsg, WebDriverCommandMsg};
+use script_traits::{ConstellationMsg, MouseButton, MouseEventType, WebDriverCommandMsg};
use std::cmp;
use std::collections::HashSet;
use webdriver::actions::{ActionSequence, ActionsType, GeneralAction, NullActionItem};
use webdriver::actions::{KeyAction, KeyActionItem, KeyDownAction, KeyUpAction};
-use webdriver::actions::{PointerAction, PointerActionItem, PointerType};
+use webdriver::actions::{
+ PointerAction, PointerActionItem, PointerActionParameters, PointerDownAction,
+};
+use webdriver::actions::{PointerType, PointerUpAction};
// https://w3c.github.io/webdriver/#dfn-input-source-state
pub(crate) enum InputSourceState {
@@ -20,23 +23,23 @@ pub(crate) enum InputSourceState {
// https://w3c.github.io/webdriver/#dfn-pointer-input-source
pub(crate) struct PointerInputState {
- _subtype: PointerType,
- _pressed: HashSet<u64>,
- _x: u64,
- _y: u64,
+ subtype: PointerType,
+ pressed: HashSet<u64>,
+ x: u64,
+ y: u64,
}
impl PointerInputState {
pub fn new(subtype: &PointerType) -> PointerInputState {
PointerInputState {
- _subtype: match subtype {
+ subtype: match subtype {
PointerType::Mouse => PointerType::Mouse,
PointerType::Pen => PointerType::Pen,
PointerType::Touch => PointerType::Touch,
},
- _pressed: HashSet::new(),
- _x: 0,
- _y: 0,
+ pressed: HashSet::new(),
+ x: 0,
+ y: 0,
}
}
}
@@ -69,6 +72,18 @@ fn compute_tick_duration(tick_actions: &ActionSequence) -> u64 {
duration
}
+fn u64_to_mouse_button(button: u64) -> Option<MouseButton> {
+ if MouseButton::Left as u64 == button {
+ Some(MouseButton::Left)
+ } else if MouseButton::Middle as u64 == button {
+ Some(MouseButton::Middle)
+ } else if MouseButton::Right as u64 == button {
+ Some(MouseButton::Right)
+ } else {
+ None
+ }
+}
+
impl Handler {
// https://w3c.github.io/webdriver/#dfn-dispatch-actions
pub(crate) fn dispatch_actions(&mut self, actions_by_tick: &[ActionSequence]) {
@@ -89,7 +104,7 @@ impl Handler {
}
// https://w3c.github.io/webdriver/#dfn-dispatch-tick-actions
- fn dispatch_tick_actions(&mut self, tick_actions: &ActionSequence, tick_duration: u64) {
+ fn dispatch_tick_actions(&mut self, tick_actions: &ActionSequence, _tick_duration: u64) {
let source_id = &tick_actions.id;
match &tick_actions.actions {
ActionsType::Null { actions } => {
@@ -111,10 +126,10 @@ impl Handler {
.or_insert(InputSourceState::Key(KeyInputState::new()));
match action {
KeyAction::Down(action) => {
- self.dispatch_keydown_action(&source_id, &action, tick_duration)
+ self.dispatch_keydown_action(&source_id, &action)
},
KeyAction::Up(action) => {
- self.dispatch_keyup_action(&source_id, &action, tick_duration)
+ self.dispatch_keyup_action(&source_id, &action)
},
};
},
@@ -140,9 +155,13 @@ impl Handler {
)));
match action {
PointerAction::Cancel => (),
- PointerAction::Down(_action) => (),
+ PointerAction::Down(action) => {
+ self.dispatch_pointerdown_action(&source_id, &action)
+ },
PointerAction::Move(_action) => (),
- PointerAction::Up(_action) => (),
+ PointerAction::Up(action) => {
+ self.dispatch_pointerup_action(&source_id, &action)
+ },
}
},
}
@@ -152,12 +171,7 @@ impl Handler {
}
// https://w3c.github.io/webdriver/#dfn-dispatch-a-keydown-action
- fn dispatch_keydown_action(
- &mut self,
- source_id: &str,
- action: &KeyDownAction,
- _tick_duration: u64,
- ) {
+ fn dispatch_keydown_action(&mut self, source_id: &str, action: &KeyDownAction) {
let session = self.session.as_mut().unwrap();
let raw_key = action.value.chars().next().unwrap();
@@ -185,12 +199,7 @@ impl Handler {
}
// https://w3c.github.io/webdriver/#dfn-dispatch-a-keyup-action
- fn dispatch_keyup_action(
- &mut self,
- source_id: &str,
- action: &KeyUpAction,
- _tick_duration: u64,
- ) {
+ fn dispatch_keyup_action(&mut self, source_id: &str, action: &KeyUpAction) {
let session = self.session.as_mut().unwrap();
let raw_key = action.value.chars().next().unwrap();
@@ -217,4 +226,96 @@ impl Handler {
.unwrap();
}
}
+
+ // https://w3c.github.io/webdriver/#dfn-dispatch-a-pointerdown-action
+ fn dispatch_pointerdown_action(&mut self, source_id: &str, action: &PointerDownAction) {
+ let session = self.session.as_mut().unwrap();
+
+ let pointer_input_state = match session.input_state_table.get_mut(source_id).unwrap() {
+ InputSourceState::Null => unreachable!(),
+ InputSourceState::Key(_) => unreachable!(),
+ InputSourceState::Pointer(pointer_input_state) => pointer_input_state,
+ };
+
+ if pointer_input_state.pressed.contains(&action.button) {
+ return;
+ }
+ pointer_input_state.pressed.insert(action.button);
+
+ session.input_cancel_list.push(ActionSequence {
+ id: source_id.into(),
+ actions: ActionsType::Pointer {
+ parameters: PointerActionParameters {
+ pointer_type: match pointer_input_state.subtype {
+ PointerType::Mouse => PointerType::Mouse,
+ PointerType::Pen => PointerType::Pen,
+ PointerType::Touch => PointerType::Touch,
+ },
+ },
+ actions: vec![PointerActionItem::Pointer(PointerAction::Up(
+ PointerUpAction {
+ button: action.button,
+ },
+ ))],
+ },
+ });
+
+ if let Some(button) = u64_to_mouse_button(action.button) {
+ let cmd_msg = WebDriverCommandMsg::MouseButtonAction(
+ MouseEventType::MouseDown,
+ button,
+ pointer_input_state.x as f32,
+ pointer_input_state.y as f32,
+ );
+ self.constellation_chan
+ .send(ConstellationMsg::WebDriverCommand(cmd_msg))
+ .unwrap();
+ }
+ }
+
+ // https://w3c.github.io/webdriver/#dfn-dispatch-a-pointerup-action
+ fn dispatch_pointerup_action(&mut self, source_id: &str, action: &PointerUpAction) {
+ let session = self.session.as_mut().unwrap();
+
+ let pointer_input_state = match session.input_state_table.get_mut(source_id).unwrap() {
+ InputSourceState::Null => unreachable!(),
+ InputSourceState::Key(_) => unreachable!(),
+ InputSourceState::Pointer(pointer_input_state) => pointer_input_state,
+ };
+
+ if !pointer_input_state.pressed.contains(&action.button) {
+ return;
+ }
+ pointer_input_state.pressed.remove(&action.button);
+
+ session.input_cancel_list.push(ActionSequence {
+ id: source_id.into(),
+ actions: ActionsType::Pointer {
+ parameters: PointerActionParameters {
+ pointer_type: match pointer_input_state.subtype {
+ PointerType::Mouse => PointerType::Mouse,
+ PointerType::Pen => PointerType::Pen,
+ PointerType::Touch => PointerType::Touch,
+ },
+ },
+ actions: vec![PointerActionItem::Pointer(PointerAction::Down(
+ PointerDownAction {
+ button: action.button,
+ },
+ ))],
+ },
+ });
+
+ if let Some(button) = u64_to_mouse_button(action.button) {
+ let cmd_msg = WebDriverCommandMsg::MouseButtonAction(
+ MouseEventType::MouseUp,
+ button,
+ pointer_input_state.x as f32,
+ pointer_input_state.y as f32,
+ );
+ self.constellation_chan
+ .send(ConstellationMsg::WebDriverCommand(cmd_msg))
+ .unwrap();
+ }
+ }
}