Commit ed37c35d authored by Lan Wei's avatar Lan Wei Committed by Commit Bot

[Chromedirver] Add pointerevent's properties to Chromedirver

The pointerevent' spec has properties e.g. width, height, pressure...,
so we are working on adding the pointerevent's properties to Webdriver
Action API to simulate the inputs from devices such as touchscreen and
stylus, which have these additional properties. This CL adds these
properties to ChromeDriver's ExecutePerformActions.

Bug: 1139172
Change-Id: Ic45f04d9e8c1d61a7f4e1fb867f701bf5c890af6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2488551Reviewed-by: default avatarJohn Chen <johnchen@chromium.org>
Commit-Queue: Lan Wei <lanwei@chromium.org>
Cr-Commit-Position: refs/heads/master@{#820291}
parent 565cc3bc
...@@ -1201,6 +1201,108 @@ class ChromeDriverTest(ChromeDriverBaseTestWithWebServer): ...@@ -1201,6 +1201,108 @@ class ChromeDriverTest(ChromeDriverBaseTestWithWebServer):
self._driver.ReleaseActions() self._driver.ReleaseActions()
def testActionsPenPointerEventProperties(self):
self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
self._driver.ExecuteScript(
'''
document.body.innerHTML = "<div>test</div>";
var div = document.getElementsByTagName("div")[0];
div.style["width"] = "100px";
div.style["height"] = "100px";
window.events = [];
div.addEventListener("pointerdown", event => {
window.events.push(
{type: event.type,
x: event.clientX,
y: event.clientY,
width: event.width,
height: event.height,
pressure: event.pressure,
tiltX: event.tiltX,
tiltY: event.tiltY,
twist: event.twist});
});
''')
time.sleep(1)
actions = ({"actions": [{
"type":"pointer",
"actions":[{"type": "pointerMove", "x": 30, "y": 30},
{"type": "pointerDown", "button": 0, "pressure":0.55,
"tiltX":-36, "tiltY":83, "twist":266},
{"type": "pointerMove", "x": 50, "y": 50},
{"type": "pointerUp", "button": 0}],
"parameters": {"pointerType": "mouse"},
"id": "pointer1"}]})
self._driver.PerformActions(actions)
time.sleep(1)
events = self._driver.ExecuteScript('return window.events')
self.assertEquals(1, len(events))
self.assertEquals("pointerdown", events[0]['type'])
self.assertAlmostEqual(30, events[0]['x'], delta=1)
self.assertAlmostEqual(30, events[0]['y'], delta=1)
self.assertEquals(1.0, round(events[0]['width'], 2))
self.assertEquals(1.0, round(events[0]['height'], 2))
self.assertEquals(0.55, round(events[0]['pressure'], 2))
self.assertEquals(-36, events[0]['tiltX'])
self.assertEquals(83, events[0]['tiltY'])
self.assertEquals(266, events[0]['twist'])
def testActionsPenPointerEventPressure(self):
self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
self._driver.ExecuteScript(
'''
document.body.innerHTML = "<div>test</div>";
var div = document.getElementsByTagName("div")[0];
div.style["width"] = "100px";
div.style["height"] = "100px";
window.events = [];
var event_list = ["pointerdown", "pointermove", "pointerup"];
for (var i = 0; i < event_list.length; i++) {
div.addEventListener(event_list[i], event => {
window.events.push(
{type: event.type,
x: event.clientX,
y: event.clientY,
pressure: event.pressure,
twist: event.twist});
});
}
''')
time.sleep(1)
actions = ({"actions": [{
"type":"pointer",
"actions":[{"type": "pointerMove", "x": 30, "y": 30},
{"type": "pointerDown", "button": 0,
"twist":30},
{"type": "pointerMove", "x": 50, "y": 50},
{"type": "pointerUp", "button": 0}],
"parameters": {"pointerType": "pen"},
"id": "pointer1"}]})
self._driver.PerformActions(actions)
time.sleep(1)
events = self._driver.ExecuteScript('return window.events')
self.assertEquals(4, len(events))
self.assertEquals("pointermove", events[0]['type'])
self.assertAlmostEqual(30, events[0]['x'], delta=1)
self.assertAlmostEqual(30, events[0]['y'], delta=1)
self.assertEquals(0.0, round(events[0]['pressure'], 2))
self.assertEquals(0, events[0]['twist'])
self.assertEquals("pointerdown", events[1]['type'])
self.assertAlmostEqual(30, events[1]['x'], delta=1)
self.assertAlmostEqual(30, events[1]['y'], delta=1)
self.assertEquals(0.5, round(events[1]['pressure'], 2))
self.assertEquals(30, events[1]['twist'])
self.assertEquals("pointermove", events[2]['type'])
self.assertAlmostEqual(50, events[2]['x'], delta=1)
self.assertAlmostEqual(50, events[2]['y'], delta=1)
self.assertEquals(0.5, round(events[2]['pressure'], 2))
self.assertEquals(0, events[2]['twist'])
self.assertEquals("pointerup", events[3]['type'])
self.assertAlmostEqual(50, events[3]['x'], delta=1)
self.assertAlmostEqual(50, events[3]['y'], delta=1)
self.assertEquals(0.0, round(events[3]['pressure'], 2))
self.assertEquals(0, events[3]['twist'])
def testActionsPause(self): def testActionsPause(self):
self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html')) self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
self._driver.ExecuteScript( self._driver.ExecuteScript(
......
...@@ -1452,6 +1452,64 @@ Status ProcessInputActionSequence( ...@@ -1452,6 +1452,64 @@ Status ProcessInputActionSequence(
if (status.IsError()) if (status.IsError())
return status; return status;
} }
// Process Pointer Event's properties.
double width = 1;
if (action_item->HasKey("width") &&
(!action_item->GetDouble("width", &width) || width < 0)) {
return Status(kInvalidArgument,
"'width' must be a non-negative number");
}
action->SetDouble("width", width);
double height = 1;
if (action_item->HasKey("height") &&
(!action_item->GetDouble("height", &height) || height < 0)) {
return Status(kInvalidArgument,
"'height' must be a non-negative number");
}
action->SetDouble("height", height);
double pressure = 0.5;
if (action_item->HasKey("pressure") &&
(!action_item->GetDouble("pressure", &pressure) || pressure < 0 ||
pressure > 1)) {
return Status(
kInvalidArgument,
"'pressure' must be a non-negative number in the range of [0,1]");
}
action->SetDouble("pressure", pressure);
double tangentialPressure = 0;
if (action_item->HasKey("tangentialPressure") &&
(!action_item->GetDouble("tangentialPressure", &tangentialPressure) ||
tangentialPressure < -1 || tangentialPressure > 1)) {
return Status(
kInvalidArgument,
"'tangentialPressure' must be a number in the range of [-1,1]");
}
action->SetDouble("tangentialPressure", tangentialPressure);
int tiltX = 0;
if (action_item->HasKey("tiltX") &&
(!action_item->GetInteger("tiltX", &tiltX) || tiltX < -90 ||
tiltX > 90)) {
return Status(kInvalidArgument,
"'tiltX' must be an integer in the range of [-90,90]");
}
action->SetInteger("tiltX", tiltX);
int tiltY = 0;
if (action_item->HasKey("tiltY") &&
(!action_item->GetInteger("tiltY", &tiltY) || tiltY < -90 ||
tiltY > 90)) {
return Status(kInvalidArgument,
"'tiltY' must be an integer in the range of [-90,90]");
}
action->SetInteger("tiltY", tiltY);
int twist = 0;
if (action_item->HasKey("twist") &&
(!action_item->GetInteger("twist", &twist) || twist < 0 ||
twist > 359)) {
return Status(kInvalidArgument,
"'twist' must be an integer in the range of [0,359]");
}
action->SetInteger("twist", twist);
} }
action_list->push_back(std::move(action)); action_list->push_back(std::move(action));
} }
...@@ -1671,6 +1729,17 @@ Status ExecutePerformActions(Session* session, ...@@ -1671,6 +1729,17 @@ Status ExecutePerformActions(Session* session,
} }
} }
double width = 1, height = 1;
action->GetDouble("width", &width);
action->GetDouble("height", &height);
double pressure = 0.5, tangential_pressure = 0;
action->GetDouble("pressure", &pressure);
action->GetDouble("tangentialPressure", &tangential_pressure);
int tilt_x = 0, tilt_y = 0, twist = 0;
action->GetInteger("tiltX", &tilt_x);
action->GetInteger("tiltY", &tilt_y);
action->GetInteger("twist", &twist);
std::string pointer_type; std::string pointer_type;
action->GetString("pointerType", &pointer_type); action->GetString("pointerType", &pointer_type);
if (pointer_type == "mouse" || pointer_type == "pen") { if (pointer_type == "mouse" || pointer_type == "pen") {
...@@ -1694,6 +1763,11 @@ Status ExecutePerformActions(Session* session, ...@@ -1694,6 +1763,11 @@ Status ExecutePerformActions(Session* session,
click_count); click_count);
event.pointer_type = StringToPointerType(pointer_type); event.pointer_type = StringToPointerType(pointer_type);
event.modifiers = session->sticky_modifiers; event.modifiers = session->sticky_modifiers;
event.tangentialPressure = tangential_pressure;
event.tiltX = tilt_x;
event.tiltY = tilt_y;
event.twist = twist;
if (event.type == kPressedMouseEventType) { if (event.type == kPressedMouseEventType) {
base::TimeTicks timestamp = base::TimeTicks::Now(); base::TimeTicks timestamp = base::TimeTicks::Now();
event.click_count = GetMouseClickCount( event.click_count = GetMouseClickCount(
...@@ -1711,13 +1785,20 @@ Status ExecutePerformActions(Session* session, ...@@ -1711,13 +1785,20 @@ Status ExecutePerformActions(Session* session,
action_input_states[j]->FindKey("pressed")->GetInt() | action_input_states[j]->FindKey("pressed")->GetInt() |
(1 << event.button)); (1 << event.button));
} else if (event.type == kReleasedMouseEventType) { } else if (event.type == kReleasedMouseEventType) {
pressure = 0;
event.click_count = session->click_count; event.click_count = session->click_count;
buttons[id] &= ~StringToModifierMouseButton(button_type[id]); buttons[id] &= ~StringToModifierMouseButton(button_type[id]);
action_input_states[j]->SetInteger( action_input_states[j]->SetInteger(
"pressed", "pressed",
action_input_states[j]->FindKey("pressed")->GetInt() & action_input_states[j]->FindKey("pressed")->GetInt() &
~(1 << event.button)); ~(1 << event.button));
} else if (event.type == kMovedMouseEventType) {
if (!(action_input_states[j]->FindKey("pressed")->GetInt() |
(1 << event.button))) {
pressure = 0;
}
} }
event.force = pressure;
dispatch_mouse_events.push_back(event); dispatch_mouse_events.push_back(event);
Status status = web_view->DispatchMouseEvents( Status status = web_view->DispatchMouseEvents(
dispatch_mouse_events, session->GetCurrentFrameId(), dispatch_mouse_events, session->GetCurrentFrameId(),
...@@ -1731,6 +1812,13 @@ Status ExecutePerformActions(Session* session, ...@@ -1731,6 +1812,13 @@ Status ExecutePerformActions(Session* session,
TouchEvent event(StringToTouchEventType(action_type), TouchEvent event(StringToTouchEventType(action_type),
action_locations[id].x(), action_locations[id].x(),
action_locations[id].y()); action_locations[id].y());
event.radiusX = width / 2.f;
event.radiusY = height / 2.f;
event.force = pressure;
event.tangentialPressure = tangential_pressure;
event.tiltX = tilt_x;
event.tiltY = tilt_y;
event.twist = twist;
if (event.type == kTouchStart) { if (event.type == kTouchStart) {
session->input_cancel_list.emplace_back( session->input_cancel_list.emplace_back(
action_input_states[j], nullptr, &event, nullptr); action_input_states[j], nullptr, &event, nullptr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment