mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Auto merge of #23988 - georgeroman:implement_pointer_up_and_down_actions, r=jdm
Implement pointerDown and pointerUp webdriver actions <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/23988) <!-- Reviewable:end -->
This commit is contained in:
commit
3658a8cc59
5 changed files with 160 additions and 28 deletions
|
@ -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), _) => {
|
(Msg::PendingPaintMetric(pipeline_id, epoch), _) => {
|
||||||
self.pending_paint_metrics.insert(pipeline_id, epoch);
|
self.pending_paint_metrics.insert(pipeline_id, epoch);
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,7 +14,7 @@ use msg::constellation_msg::{PipelineId, TopLevelBrowsingContextId};
|
||||||
use net_traits::image::base::Image;
|
use net_traits::image::base::Image;
|
||||||
use profile_traits::mem;
|
use profile_traits::mem;
|
||||||
use profile_traits::time;
|
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 std::fmt::{Debug, Error, Formatter};
|
||||||
use style_traits::viewport::ViewportConstraints;
|
use style_traits::viewport::ViewportConstraints;
|
||||||
use webrender_api;
|
use webrender_api;
|
||||||
|
@ -106,6 +106,8 @@ pub enum Msg {
|
||||||
PendingPaintMetric(PipelineId, Epoch),
|
PendingPaintMetric(PipelineId, Epoch),
|
||||||
/// The load of a page has completed
|
/// The load of a page has completed
|
||||||
LoadComplete(TopLevelBrowsingContextId),
|
LoadComplete(TopLevelBrowsingContextId),
|
||||||
|
/// WebDriver mouse button event
|
||||||
|
WebDriverMouseButtonEvent(MouseEventType, MouseButton, f32, f32),
|
||||||
|
|
||||||
/// Get Window Informations size and position.
|
/// Get Window Informations size and position.
|
||||||
GetClientWindow(IpcSender<(DeviceIntSize, DeviceIntPoint)>),
|
GetClientWindow(IpcSender<(DeviceIntSize, DeviceIntPoint)>),
|
||||||
|
@ -132,6 +134,7 @@ impl Debug for Msg {
|
||||||
Msg::Dispatch(..) => write!(f, "Dispatch"),
|
Msg::Dispatch(..) => write!(f, "Dispatch"),
|
||||||
Msg::PendingPaintMetric(..) => write!(f, "PendingPaintMetric"),
|
Msg::PendingPaintMetric(..) => write!(f, "PendingPaintMetric"),
|
||||||
Msg::LoadComplete(..) => write!(f, "LoadComplete"),
|
Msg::LoadComplete(..) => write!(f, "LoadComplete"),
|
||||||
|
Msg::WebDriverMouseButtonEvent(..) => write!(f, "WebDriverMouseButtonEvent"),
|
||||||
Msg::GetClientWindow(..) => write!(f, "GetClientWindow"),
|
Msg::GetClientWindow(..) => write!(f, "GetClientWindow"),
|
||||||
Msg::GetScreenSize(..) => write!(f, "GetScreenSize"),
|
Msg::GetScreenSize(..) => write!(f, "GetScreenSize"),
|
||||||
Msg::GetScreenAvailSize(..) => write!(f, "GetScreenAvailSize"),
|
Msg::GetScreenAvailSize(..) => write!(f, "GetScreenAvailSize"),
|
||||||
|
|
|
@ -3490,6 +3490,15 @@ where
|
||||||
return self.handle_send_error(pipeline_id, e);
|
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) => {
|
WebDriverCommandMsg::TakeScreenshot(_, reply) => {
|
||||||
self.compositor_proxy
|
self.compositor_proxy
|
||||||
.send(ToCompositorMsg::CreatePng(reply));
|
.send(ToCompositorMsg::CreatePng(reply));
|
||||||
|
|
|
@ -798,6 +798,8 @@ pub enum WebDriverCommandMsg {
|
||||||
SendKeys(BrowsingContextId, Vec<WebDriverInputEvent>),
|
SendKeys(BrowsingContextId, Vec<WebDriverInputEvent>),
|
||||||
/// Act as if keys were pressed or release in the browsing context with the given ID.
|
/// Act as if keys were pressed or release in the browsing context with the given ID.
|
||||||
KeyboardAction(BrowsingContextId, KeyboardEvent),
|
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.
|
/// Set the window size.
|
||||||
SetWindowSize(
|
SetWindowSize(
|
||||||
TopLevelBrowsingContextId,
|
TopLevelBrowsingContextId,
|
||||||
|
|
|
@ -4,12 +4,15 @@
|
||||||
|
|
||||||
use crate::Handler;
|
use crate::Handler;
|
||||||
use keyboard_types::webdriver::KeyInputState;
|
use keyboard_types::webdriver::KeyInputState;
|
||||||
use script_traits::{ConstellationMsg, WebDriverCommandMsg};
|
use script_traits::{ConstellationMsg, MouseButton, MouseEventType, WebDriverCommandMsg};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use webdriver::actions::{ActionSequence, ActionsType, GeneralAction, NullActionItem};
|
use webdriver::actions::{ActionSequence, ActionsType, GeneralAction, NullActionItem};
|
||||||
use webdriver::actions::{KeyAction, KeyActionItem, KeyDownAction, KeyUpAction};
|
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
|
// https://w3c.github.io/webdriver/#dfn-input-source-state
|
||||||
pub(crate) enum InputSourceState {
|
pub(crate) enum InputSourceState {
|
||||||
|
@ -20,23 +23,23 @@ pub(crate) enum InputSourceState {
|
||||||
|
|
||||||
// https://w3c.github.io/webdriver/#dfn-pointer-input-source
|
// https://w3c.github.io/webdriver/#dfn-pointer-input-source
|
||||||
pub(crate) struct PointerInputState {
|
pub(crate) struct PointerInputState {
|
||||||
_subtype: PointerType,
|
subtype: PointerType,
|
||||||
_pressed: HashSet<u64>,
|
pressed: HashSet<u64>,
|
||||||
_x: u64,
|
x: u64,
|
||||||
_y: u64,
|
y: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PointerInputState {
|
impl PointerInputState {
|
||||||
pub fn new(subtype: &PointerType) -> PointerInputState {
|
pub fn new(subtype: &PointerType) -> PointerInputState {
|
||||||
PointerInputState {
|
PointerInputState {
|
||||||
_subtype: match subtype {
|
subtype: match subtype {
|
||||||
PointerType::Mouse => PointerType::Mouse,
|
PointerType::Mouse => PointerType::Mouse,
|
||||||
PointerType::Pen => PointerType::Pen,
|
PointerType::Pen => PointerType::Pen,
|
||||||
PointerType::Touch => PointerType::Touch,
|
PointerType::Touch => PointerType::Touch,
|
||||||
},
|
},
|
||||||
_pressed: HashSet::new(),
|
pressed: HashSet::new(),
|
||||||
_x: 0,
|
x: 0,
|
||||||
_y: 0,
|
y: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,6 +72,18 @@ fn compute_tick_duration(tick_actions: &ActionSequence) -> u64 {
|
||||||
duration
|
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 {
|
impl Handler {
|
||||||
// https://w3c.github.io/webdriver/#dfn-dispatch-actions
|
// https://w3c.github.io/webdriver/#dfn-dispatch-actions
|
||||||
pub(crate) fn dispatch_actions(&mut self, actions_by_tick: &[ActionSequence]) {
|
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
|
// 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;
|
let source_id = &tick_actions.id;
|
||||||
match &tick_actions.actions {
|
match &tick_actions.actions {
|
||||||
ActionsType::Null { actions } => {
|
ActionsType::Null { actions } => {
|
||||||
|
@ -111,10 +126,10 @@ impl Handler {
|
||||||
.or_insert(InputSourceState::Key(KeyInputState::new()));
|
.or_insert(InputSourceState::Key(KeyInputState::new()));
|
||||||
match action {
|
match action {
|
||||||
KeyAction::Down(action) => {
|
KeyAction::Down(action) => {
|
||||||
self.dispatch_keydown_action(&source_id, &action, tick_duration)
|
self.dispatch_keydown_action(&source_id, &action)
|
||||||
},
|
},
|
||||||
KeyAction::Up(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 {
|
match action {
|
||||||
PointerAction::Cancel => (),
|
PointerAction::Cancel => (),
|
||||||
PointerAction::Down(_action) => (),
|
PointerAction::Down(action) => {
|
||||||
|
self.dispatch_pointerdown_action(&source_id, &action)
|
||||||
|
},
|
||||||
PointerAction::Move(_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
|
// https://w3c.github.io/webdriver/#dfn-dispatch-a-keydown-action
|
||||||
fn dispatch_keydown_action(
|
fn dispatch_keydown_action(&mut self, source_id: &str, action: &KeyDownAction) {
|
||||||
&mut self,
|
|
||||||
source_id: &str,
|
|
||||||
action: &KeyDownAction,
|
|
||||||
_tick_duration: u64,
|
|
||||||
) {
|
|
||||||
let session = self.session.as_mut().unwrap();
|
let session = self.session.as_mut().unwrap();
|
||||||
|
|
||||||
let raw_key = action.value.chars().next().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
|
// https://w3c.github.io/webdriver/#dfn-dispatch-a-keyup-action
|
||||||
fn dispatch_keyup_action(
|
fn dispatch_keyup_action(&mut self, source_id: &str, action: &KeyUpAction) {
|
||||||
&mut self,
|
|
||||||
source_id: &str,
|
|
||||||
action: &KeyUpAction,
|
|
||||||
_tick_duration: u64,
|
|
||||||
) {
|
|
||||||
let session = self.session.as_mut().unwrap();
|
let session = self.session.as_mut().unwrap();
|
||||||
|
|
||||||
let raw_key = action.value.chars().next().unwrap();
|
let raw_key = action.value.chars().next().unwrap();
|
||||||
|
@ -217,4 +226,96 @@ impl Handler {
|
||||||
.unwrap();
|
.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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue