зеркало из https://github.com/mozilla/gecko-dev.git
Bug 845925 - Add scroll/pinch actions using touch action chains to the python touch layer, r=mdas
This commit is contained in:
Родитель
80dfb44965
Коммит
89729a754e
|
@ -0,0 +1,71 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from marionette import MultiActions, Actions
|
||||
|
||||
#axis is y or x
|
||||
#direction is 0 for positive, and -1 for negative
|
||||
#length is the total length we want to scroll
|
||||
#increments is how much we want to move per scrolling
|
||||
#wait_period is the seconds we wait between scrolling
|
||||
#scroll_back is whether we want to scroll back to original view
|
||||
def smooth_scroll(marionette_session, start_element, axis, direction, length, increments=None, wait_period=None, scroll_back=None):
|
||||
if axis not in ["x", "y"]:
|
||||
raise Exception("Axis must be either 'x' or 'y'")
|
||||
if direction not in [-1, 0]:
|
||||
raise Exception("Direction must either be -1 negative or 0 positive")
|
||||
increments = increments or 100
|
||||
wait_period = wait_period or 0.05
|
||||
scroll_back = scroll_back or False
|
||||
current = 0
|
||||
if axis is "x":
|
||||
if direction is -1:
|
||||
offset = [-increments, 0]
|
||||
else:
|
||||
offset = [increments, 0]
|
||||
else:
|
||||
if direction is -1:
|
||||
offset = [0, -increments]
|
||||
else:
|
||||
offset = [0, increments]
|
||||
action = Actions(marionette_session)
|
||||
action.press(start_element)
|
||||
while (current < length):
|
||||
current += increments
|
||||
action.move_by_offset(*offset).wait(wait_period)
|
||||
if scroll_back:
|
||||
offset = [-value for value in offset]
|
||||
while (current > 0):
|
||||
current -= increments
|
||||
action.move_by_offset(*offset).wait(wait_period)
|
||||
action.release()
|
||||
action.perform()
|
||||
|
||||
#element is the target
|
||||
#x1,x2 are 1st finger starting position relative to the target
|
||||
#x3,y3 are 1st finger ending position relative to the target
|
||||
#x2,y2 are 2nd finger starting position relative to the target
|
||||
#x4,y4 are 2nd finger ending position relative to the target
|
||||
#duration is the amount of time in milliseconds we want to complete the pinch.
|
||||
def pinch(marionette_session, element, x1, y1, x2, y2, x3, y3, x4, y4, duration=200):
|
||||
time = 0
|
||||
time_increment = 10
|
||||
if time_increment >= duration:
|
||||
time_increment = duration
|
||||
move_x1 = time_increment*1.0/duration * (x3 - x1)
|
||||
move_y1 = time_increment*1.0/duration * (y3 - y1)
|
||||
move_x2 = time_increment*1.0/duration * (x4 - x2)
|
||||
move_y2 = time_increment*1.0/duration * (y4 - y2)
|
||||
multiAction = MultiActions(marionette_session)
|
||||
action1 = Actions(marionette_session)
|
||||
action2 = Actions(marionette_session)
|
||||
action1.press(element, x1, y1)
|
||||
action2.press(element, x2, y2)
|
||||
while (time < duration):
|
||||
time += time_increment
|
||||
action1.move_by_offset(move_x1, move_y1).wait(time_increment/1000)
|
||||
action2.move_by_offset(move_x2, move_y2).wait(time_increment/1000)
|
||||
action1.release()
|
||||
action2.release()
|
||||
multiAction.add(action1).add(action2).perform()
|
|
@ -138,6 +138,22 @@ class Actions(object):
|
|||
self.action_chain.append(['cancel'])
|
||||
return self
|
||||
|
||||
def flick(self, element, x1, y1, x2, y2, duration=200):
|
||||
element = element.id
|
||||
time = 0
|
||||
time_increment = 10
|
||||
if time_increment >= duration:
|
||||
time_increment = duration
|
||||
move_x = time_increment*1.0/duration * (x2 - x1)
|
||||
move_y = time_increment*1.0/duration * (y2 - y1)
|
||||
self.action_chain.append(['press', element, x1, y1])
|
||||
while (time < duration):
|
||||
time += time_increment
|
||||
self.action_chain.append(['moveByOffset', move_x, move_y])
|
||||
self.action_chain.append(['wait', time_increment/1000])
|
||||
self.action_chain.append(['release'])
|
||||
return self
|
||||
|
||||
def long_press(self, element, time_in_seconds):
|
||||
element = element.id
|
||||
self.action_chain.append(['press', element])
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
import os
|
||||
from errors import ElementNotVisibleException
|
||||
|
||||
from marionette import Actions
|
||||
from gestures import pinch
|
||||
"""
|
||||
Adds touch support in Marionette
|
||||
"""
|
||||
|
@ -35,8 +36,9 @@ class MarionetteTouchMixin(object):
|
|||
|
||||
def flick(self, element, x1, y1, x2, y2, duration=200):
|
||||
self.check_element(element)
|
||||
# there's 'flick' which is pixels per second, but I'd rather have the library support it than piece it together here.
|
||||
self.execute_script("%s.swipe.apply(this, arguments);" % self.library_name, [element, x1, y1, x2, y2, duration])
|
||||
action = Actions(self.marionette)
|
||||
action.flick(element, x1, y1, x2, y2, duration).perform()
|
||||
|
||||
def pinch(self, *args, **kwargs):
|
||||
raise Exception("Pinch is unsupported")
|
||||
def pinch(self, element, x1, y1, x2, y2, x3, y3, x4, y4, duration = 200):
|
||||
self.check_element(element)
|
||||
pinch(element, x1, y1, x2, y2, x3, y3, x4, y4, duration)
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
import time
|
||||
from marionette_test import MarionetteTestCase
|
||||
from gestures import smooth_scroll, pinch
|
||||
|
||||
class testGestures(MarionetteTestCase):
|
||||
def test_smooth_scroll(self):
|
||||
testTouch = self.marionette.absolute_url("testAction.html")
|
||||
self.marionette.navigate(testTouch)
|
||||
button = self.marionette.find_element("id", "mozLinkScrollStart")
|
||||
smooth_scroll(self.marionette, button, "y", -1, 250)
|
||||
time.sleep(15)
|
||||
self.assertEqual("End", self.marionette.execute_script("return document.getElementById('mozLinkScroll').innerHTML;"))
|
||||
|
||||
def test_pinch(self):
|
||||
testTouch = self.marionette.absolute_url("testAction.html")
|
||||
self.marionette.navigate(testTouch)
|
||||
button = self.marionette.find_element("id", "mozLinkScrollStart")
|
||||
pinch(self.marionette, button, 0, 0, 0, 0, 0, -50, 0, 50)
|
||||
time.sleep(15)
|
|
@ -6,6 +6,7 @@ import time
|
|||
from marionette_test import MarionetteTestCase
|
||||
from marionette import Actions
|
||||
from errors import NoSuchElementException, MarionetteException
|
||||
from unittest import skip
|
||||
|
||||
class testSingleFinger(MarionetteTestCase):
|
||||
def test_wait(self):
|
||||
|
@ -131,6 +132,7 @@ class testSingleFinger(MarionetteTestCase):
|
|||
time.sleep(10)
|
||||
self.assertEqual("ContextEnd", self.marionette.execute_script("return document.getElementById('mozLinkCopy').innerHTML;"))
|
||||
|
||||
@skip("Skipping due to Bug 865334")
|
||||
def test_long_press_fail(self):
|
||||
testTouch = self.marionette.absolute_url("testAction.html")
|
||||
self.marionette.navigate(testTouch)
|
||||
|
@ -144,3 +146,13 @@ class testSingleFinger(MarionetteTestCase):
|
|||
self.marionette.navigate(testTouch)
|
||||
self.assertRaises(MarionetteException, self.marionette.send_mouse_event, "boolean")
|
||||
|
||||
def test_chain_flick(self):
|
||||
testTouch = self.marionette.absolute_url("testAction.html")
|
||||
self.marionette.navigate(testTouch)
|
||||
button = self.marionette.find_element("id", "mozLinkScrollStart")
|
||||
action = Actions(self.marionette)
|
||||
action.flick(button, 0, 0, 0, -250).perform()
|
||||
time.sleep(15)
|
||||
self.assertEqual("End", self.marionette.execute_script("return document.getElementById('mozLinkScroll').innerHTML;"))
|
||||
self.assertEqual("Start", self.marionette.execute_script("return document.getElementById('mozLinkScrollStart').innerHTML;"))
|
||||
|
||||
|
|
|
@ -11,6 +11,9 @@ b2g = true
|
|||
; true if the test should be skipped
|
||||
skip = false
|
||||
|
||||
; true if the test requires unagi
|
||||
unagi = false
|
||||
|
||||
[test_getstatus.py]
|
||||
[test_import_script.py]
|
||||
[test_import_script_content.py.py]
|
||||
|
@ -48,14 +51,15 @@ b2g = false
|
|||
b2g = true
|
||||
browser = false
|
||||
|
||||
[test_cancel.py]
|
||||
b2g = true
|
||||
browser = false
|
||||
|
||||
[test_press_release.py]
|
||||
b2g = true
|
||||
browser = false
|
||||
|
||||
[test_gesture.py]
|
||||
b2g = true
|
||||
browser = false
|
||||
unagi = true
|
||||
|
||||
[test_single_finger.py]
|
||||
b2g = true
|
||||
browser = false
|
||||
|
@ -68,6 +72,10 @@ browser = false
|
|||
b2g = true
|
||||
browser = false
|
||||
|
||||
[test_cancel.py]
|
||||
b2g = true
|
||||
browser = false
|
||||
|
||||
[test_simpletest_pass.js]
|
||||
[test_simpletest_sanity.py]
|
||||
[test_simpletest_chrome.js]
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
<button id="mozLinkPos" style="position:absolute;left:0px;top:355px;" type="button" allowevents=true>Button2</button>
|
||||
<!-- "mozLinkCopy" listens for a touchdown and touchup -->
|
||||
<button id="mozLinkCopy" style="position:absolute;left:0px;top:455px;" type="button" allowevents=true>Button3</button>
|
||||
<!-- "mozLinkScroll" listens for scroll -->
|
||||
<button id="mozLinkScroll" style="position:absolute;left:0px;top:655px;" type="button" allowevents=true>Button8</button>
|
||||
<!-- "mozLinkScrollStart" listens for scroll -->
|
||||
<button id="mozLinkScrollStart" style="position:absolute;left:0px;top:405px;" type="button" allowevents=true>Button9</button>
|
||||
<!-- "mozLinkStart" and "mozLinkEnd" work together to perform touchdown on mozLinkStart, horizontal move and then touchup on mozLinkEnd -->
|
||||
<button id="mozLinkStart" style="position:absolute;left:10px;top:200px;" type="button" allowevents=true>Press</button>
|
||||
<button id="mozLinkEnd" style="position:absolute;left:140px;top:200px;" type="button" allowevents=true>Release</button>
|
||||
|
@ -32,6 +36,7 @@
|
|||
var fourth = document.getElementById("mozLinkCopy2");
|
||||
var fifth = document.getElementById("mozLinkCancel");
|
||||
var sixth = document.getElementById("mozMouse");
|
||||
var seventh = document.getElementById("mozLinkScrollStart");
|
||||
// touchmove and touchend must be performed on the same element as touchstart
|
||||
// here is press for vertical move
|
||||
press.addEventListener("touchstart", function(){changePressText("mozLink")}, false);
|
||||
|
@ -59,6 +64,9 @@
|
|||
sixth.addEventListener("mousedown", function(){changeMouseText("MouseDown")}, false);
|
||||
sixth.addEventListener("mouseup", function(){changeMouseText("MouseUp")}, false);
|
||||
sixth.addEventListener("click", function(){changeMouseText("MouseClick")}, false);
|
||||
// here is seventh for a scroll
|
||||
seventh.addEventListener("touchstart", function(){changePressText("mozLinkScrollStart")}, false);
|
||||
seventh.addEventListener("touchend", function(){changeScrollText("mozLinkScroll")}, false);
|
||||
function changeMouseText(strId) {
|
||||
var mouse = document.getElementById("mozMouse");
|
||||
switch(strId) {
|
||||
|
@ -193,13 +201,23 @@
|
|||
}
|
||||
}
|
||||
|
||||
function changeScrollText(strId) {
|
||||
var seventh = document.getElementById(strId);
|
||||
if (elementInViewport(seventh)) {
|
||||
seventh.innerHTML = "End";
|
||||
}
|
||||
else {
|
||||
seventh.innerHTML = "Error";
|
||||
}
|
||||
}
|
||||
|
||||
function changeTimePress() {
|
||||
var fourth = document.getElementById("mozLinkCopy2");
|
||||
var d = new Date();
|
||||
fourth.innerHTML = d.getTime();
|
||||
var newButton = document.createElement("button");
|
||||
newButton.id = "delayed";
|
||||
newButton.setAttribute("style", "position:absolute;left:80px;top:105px;");
|
||||
newButton.setAttribute("style", "position:absolute;left:220px;top:455px;");
|
||||
var content = document.createTextNode("Button6");
|
||||
newButton.appendChild(content);
|
||||
document.body.appendChild(newButton);
|
||||
|
@ -224,6 +242,22 @@
|
|||
var context = document.getElementById("mozLinkCopy");
|
||||
context.innerHTML = "Context";
|
||||
}
|
||||
|
||||
function elementInViewport(el) {
|
||||
var top = el.offsetTop;
|
||||
var left = el.offsetLeft;
|
||||
var width = el.offsetWidth;
|
||||
var height = el.offsetHeight;
|
||||
while(el.offsetParent) {
|
||||
el = el.offsetParent;
|
||||
top += el.offsetTop;
|
||||
left += el.offsetLeft;
|
||||
}
|
||||
return (top >= window.pageYOffset &&
|
||||
left >= window.pageXOffset &&
|
||||
(top + height) <= (window.pageYOffset + window.innerHeight) &&
|
||||
(left + width) <= (window.pageXOffset + window.innerWidth));
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -747,7 +747,7 @@ function touch(target, duration, xt, yt, then) {
|
|||
|
||||
/**
|
||||
* This function generates the coordinates of the element
|
||||
* @param 'x0', 'y0', 'x1', and 'y1' are the relative to the viewport.
|
||||
* @param 'x0', 'y0', 'x1', and 'y1' are the relative to the target.
|
||||
* If they are not specified, then the center of the target is used.
|
||||
*/
|
||||
function coordinates(target, x0, y0, x1, y1) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче