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

[ChromeDirver] Support double click in ExecutePerformActions

In test_driver actions API, for mouse clicks, if the two clicks' time
interval and two click location range is small enough, we will set the
click count to 2 and generate double click event.

This CL fixes these tests:
webdriver/tests/perform_actions/pointer_pause_dblclick.py
webdriver/tests/perform_actions/pointer_dblclick.py

Bug: chromedriver:1897
Change-Id: Id147cbb83cb7e39b8240ce126e87fd217e25d263
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1549561
Commit-Queue: Lan Wei <lanwei@chromium.org>
Reviewed-by: default avatarJohn Chen <johnchen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#647054}
parent 2015e4f1
...@@ -72,7 +72,9 @@ Session::Session(const std::string& id) ...@@ -72,7 +72,9 @@ Session::Session(const std::string& id)
page_load_timeout(kDefaultPageLoadTimeout), page_load_timeout(kDefaultPageLoadTimeout),
script_timeout(kDefaultScriptTimeout), script_timeout(kDefaultScriptTimeout),
auto_reporting_enabled(false), auto_reporting_enabled(false),
strict_file_interactability(false){} strict_file_interactability(false),
click_count(0),
mouse_click_timestamp(base::TimeTicks::Now()) {}
Session::Session(const std::string& id, std::unique_ptr<Chrome> chrome) Session::Session(const std::string& id, std::unique_ptr<Chrome> chrome)
: id(id), : id(id),
...@@ -88,7 +90,9 @@ Session::Session(const std::string& id, std::unique_ptr<Chrome> chrome) ...@@ -88,7 +90,9 @@ Session::Session(const std::string& id, std::unique_ptr<Chrome> chrome)
page_load_timeout(kDefaultPageLoadTimeout), page_load_timeout(kDefaultPageLoadTimeout),
script_timeout(kDefaultScriptTimeout), script_timeout(kDefaultScriptTimeout),
auto_reporting_enabled(false), auto_reporting_enabled(false),
strict_file_interactability(false){} strict_file_interactability(false),
click_count(0),
mouse_click_timestamp(base::TimeTicks::Now()) {}
Session::~Session() {} Session::~Session() {}
......
...@@ -125,6 +125,8 @@ struct Session { ...@@ -125,6 +125,8 @@ struct Session {
std::vector<std::unique_ptr<CommandListener>> command_listeners; std::vector<std::unique_ptr<CommandListener>> command_listeners;
bool strict_file_interactability; bool strict_file_interactability;
std::string unhandled_prompt_behavior; std::string unhandled_prompt_behavior;
int click_count;
base::TimeTicks mouse_click_timestamp;
}; };
Session* GetThreadLocalSession(); Session* GetThreadLocalSession();
......
...@@ -700,7 +700,7 @@ class ChromeDriverTest(ChromeDriverBaseTestWithWebServer): ...@@ -700,7 +700,7 @@ class ChromeDriverTest(ChromeDriverBaseTestWithWebServer):
def testActionsMouseMove(self): def testActionsMouseMove(self):
self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html')) self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
div = self._driver.ExecuteScript( self._driver.ExecuteScript(
'document.body.innerHTML = "<div>old</div>";' 'document.body.innerHTML = "<div>old</div>";'
'var div = document.getElementsByTagName("div")[0];' 'var div = document.getElementsByTagName("div")[0];'
'div.style["width"] = "100px";' 'div.style["width"] = "100px";'
...@@ -720,7 +720,7 @@ class ChromeDriverTest(ChromeDriverBaseTestWithWebServer): ...@@ -720,7 +720,7 @@ class ChromeDriverTest(ChromeDriverBaseTestWithWebServer):
def testActionsMouseClick(self): def testActionsMouseClick(self):
self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html')) self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
div = self._driver.ExecuteScript( self._driver.ExecuteScript(
'document.body.innerHTML = "<div>old</div>";' 'document.body.innerHTML = "<div>old</div>";'
'var div = document.getElementsByTagName("div")[0];' 'var div = document.getElementsByTagName("div")[0];'
'div.style["width"] = "100px";' 'div.style["width"] = "100px";'
...@@ -740,9 +740,33 @@ class ChromeDriverTest(ChromeDriverBaseTestWithWebServer): ...@@ -740,9 +740,33 @@ class ChromeDriverTest(ChromeDriverBaseTestWithWebServer):
self._driver.PerformActions(actions) self._driver.PerformActions(actions)
self.assertEquals(1, len(self._driver.FindElements('tag name', 'br'))) self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
def testActionsMouseDoubleClick(self):
self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
self._driver.ExecuteScript(
'document.body.innerHTML = "<div>old</div>";'
'var div = document.getElementsByTagName("div")[0];'
'div.style["width"] = "100px";'
'div.style["height"] = "100px";'
'div.addEventListener("dblclick", function() {'
' var div = document.getElementsByTagName("div")[0];'
' div.innerHTML="new<br>";'
'});'
'return div;')
actions = ({"actions": [{
"type":"pointer",
"actions":[{"type": "pointerMove", "x": 10, "y": 10},
{"type": "pointerDown", "button": 0},
{"type": "pointerUp", "button": 0},
{"type": "pointerDown", "button": 0},
{"type": "pointerUp", "button": 0}],
"parameters": {"pointerType": "mouse"},
"id": "pointer1"}]})
self._driver.PerformActions(actions)
self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
def testActionsTouchTap(self): def testActionsTouchTap(self):
self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html')) self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
div = self._driver.ExecuteScript( self._driver.ExecuteScript(
'document.body.innerHTML = "<div>old</div>";' 'document.body.innerHTML = "<div>old</div>";'
'var div = document.getElementsByTagName("div")[0];' 'var div = document.getElementsByTagName("div")[0];'
'div.style["width"] = "100px";' 'div.style["width"] = "100px";'
......
...@@ -421,6 +421,32 @@ Status ElementInViewCenter(Session* session, ...@@ -421,6 +421,32 @@ Status ElementInViewCenter(Session* session,
return Status(kOk); return Status(kOk);
} }
bool IsRepeatedClickEvent(float x,
float y,
float last_x,
float last_y,
int click_count,
const base::TimeTicks& timestamp,
const base::TimeTicks& last_mouse_click_time) {
const int kDoubleClickTimeMS = 500;
const int kDoubleClickRange = 4;
if (click_count == 0)
return false;
base::TimeDelta time_difference = timestamp - last_mouse_click_time;
if (time_difference.InMilliseconds() > kDoubleClickTimeMS)
return false;
if (std::abs(x - last_x) > kDoubleClickRange / 2)
return false;
if (std::abs(y - last_y) > kDoubleClickRange / 2)
return false;
return true;
}
} // namespace } // namespace
Status ExecuteWindowCommand(const WindowCommand& command, Status ExecuteWindowCommand(const WindowCommand& command,
...@@ -1468,6 +1494,19 @@ Status ExecutePerformActions(Session* session, ...@@ -1468,6 +1494,19 @@ Status ExecutePerformActions(Session* session,
event.y = mouse_locations[j].y(); event.y = mouse_locations[j].y();
} }
event.modifiers = key_modifiers; event.modifiers = key_modifiers;
if (event.type == kPressedMouseEventType) {
base::TimeTicks timestamp = base::TimeTicks::Now();
bool is_repeated_click = IsRepeatedClickEvent(
event.x, event.y, session->mouse_position.x,
session->mouse_position.y, session->click_count, timestamp,
session->mouse_click_timestamp);
event.click_count = is_repeated_click ? 2 : 1;
session->mouse_position = WebPoint(event.x, event.y);
session->click_count = event.click_count;
session->mouse_click_timestamp = timestamp;
} else if (event.type == kReleasedMouseEventType) {
event.click_count = session->click_count;
}
dispatch_mouse_events.push_back(event); dispatch_mouse_events.push_back(event);
} }
} }
...@@ -1552,6 +1591,9 @@ Status ExecuteReleaseActions(Session* session, ...@@ -1552,6 +1591,9 @@ Status ExecuteReleaseActions(Session* session,
session->input_cancel_list.clear(); session->input_cancel_list.clear();
session->input_state_table.Clear(); session->input_state_table.Clear();
session->active_input_sources.Clear(); session->active_input_sources.Clear();
session->mouse_position = WebPoint(0, 0);
session->click_count = 0;
session->mouse_click_timestamp = base::TimeTicks::Now();
return Status(kOk); return Status(kOk);
} }
......
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