Merge lp:~elopio/autopilot/fix1257055-slow_drag into lp:~elopio/autopilot/fix1266601-Pointer-pressed-move

Proposed by Leo Arias
Status: Superseded
Proposed branch: lp:~elopio/autopilot/fix1257055-slow_drag
Merge into: lp:~elopio/autopilot/fix1266601-Pointer-pressed-move
Diff against target: 295 lines (+212/-16) (has conflicts)
3 files modified
autopilot/input/_X11.py (+2/-2)
autopilot/input/_uinput.py (+22/-12)
autopilot/tests/unit/test_input.py (+188/-2)
Text conflict in autopilot/tests/unit/test_input.py
To merge this branch: bzr merge lp:~elopio/autopilot/fix1257055-slow_drag
Reviewer Review Type Date Requested Status
Leo Arias Pending
Review via email: mp+202203@code.launchpad.net

This proposal has been superseded by a proposal from 2014-01-19.

Commit message

Added the drags with rate.

To post a comment you must log in.
421. By Leo Arias

Updated the copyright years.

422. By Leo Arias

Added the rate to the Pointer drag.

423. By Leo Arias

Renamed MockTouch to MockUinputTouch.

424. By Leo Arias

Merged with trunk.

425. By Leo Arias

Added python-evdev as a build-dep.

426. By Leo Arias

Merged with prerequisite branch.

427. By Leo Arias

Fixed the imports.

428. By Leo Arias

Added comments for the rate parameter.

429. By Leo Arias

Updated the tests.

430. By Leo Arias

Removed unused import.

431. By Leo Arias

Removed extra line.

432. By Leo Arias

s/should/must

433. By Leo Arias

Added a test with time_between_events.

434. By Leo Arias

We can't use the real Mouse, so switch to touch backend for now.

435. By Leo Arias

Updated the fake.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'autopilot/input/_X11.py'
2--- autopilot/input/_X11.py 2013-11-07 05:53:36 +0000
3+++ autopilot/input/_X11.py 2014-01-19 00:39:05 +0000
4@@ -455,7 +455,7 @@
5 x, y = coord["root_x"], coord["root_y"]
6 return x, y
7
8- def drag(self, x1, y1, x2, y2):
9+ def drag(self, x1, y1, x2, y2, rate=10):
10 """Performs a press, move and release.
11
12 This is to keep a common API between Mouse and Finger as long as
13@@ -464,7 +464,7 @@
14 """
15 self.move(x1, y1)
16 self.press()
17- self.move(x2, y2)
18+ self.move(x2, y2, rate=rate)
19 self.release()
20
21 @classmethod
22
23=== modified file 'autopilot/input/_uinput.py'
24--- autopilot/input/_uinput.py 2013-11-07 05:53:36 +0000
25+++ autopilot/input/_uinput.py 2014-01-19 00:39:05 +0000
26@@ -361,23 +361,33 @@
27 raise RuntimeError("Attempting to move without finger being down.")
28 self._finger_move(x, y)
29
30- def drag(self, x1, y1, x2, y2):
31+ def drag(self, x1, y1, x2, y2, rate=10):
32 """Perform a drag gesture from (x1,y1) to (x2,y2)"""
33 logger.debug("Dragging from %d,%d to %d,%d", x1, y1, x2, y2)
34 self._finger_down(x1, y1)
35
36- # Let's drag in 100 steps for now...
37- dx = 1.0 * (x2 - x1) / 100
38- dy = 1.0 * (y2 - y1) / 100
39- cur_x = x1 + dx
40- cur_y = y1 + dy
41- for i in range(0, 100):
42- self._finger_move(int(cur_x), int(cur_y))
43+ current_x, current_y = x1, y1
44+ while current_x != x2 or current_y != y2:
45+ dx = abs(x2 - current_x)
46+ dy = abs(y2 - current_y)
47+
48+ intx = float(dx) / max(dx, dy)
49+ inty = float(dy) / max(dx, dy)
50+
51+ step_x = min(rate * intx, dx)
52+ step_y = min(rate * inty, dy)
53+
54+ if x2 < current_x:
55+ step_x *= -1
56+ if y2 < current_y:
57+ step_y *= -1
58+
59+ current_x += step_x
60+ current_y += step_y
61+ self._finger_move(current_x, current_y)
62+
63 sleep(0.002)
64- cur_x += dx
65- cur_y += dy
66- # Make sure we actually end up at target
67- self._finger_move(x2, y2)
68+
69 self._finger_up()
70
71 def _finger_down(self, x, y):
72
73=== modified file 'autopilot/tests/unit/test_input.py'
74--- autopilot/tests/unit/test_input.py 2014-01-07 00:21:08 +0000
75+++ autopilot/tests/unit/test_input.py 2014-01-19 00:39:05 +0000
76@@ -1,7 +1,7 @@
77 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
78 #
79 # Autopilot Functional Test Tool
80-# Copyright (C) 2013 Canonical
81+# Copyright (C) 2013, 2014 Canonical
82 #
83 # This program is free software: you can redistribute it and/or modify
84 # it under the terms of the GNU General Public License as published by
85@@ -17,12 +17,18 @@
86 # along with this program. If not, see <http://www.gnu.org/licenses/>.
87 #
88
89-from mock import patch
90+import testscenarios
91+
92+from mock import call, Mock, patch
93 from testtools import TestCase
94 from testtools.matchers import raises
95
96+<<<<<<< TREE
97 from autopilot import input
98 from autopilot.input import _uinput
99+=======
100+from autopilot.input import _uinput, _X11
101+>>>>>>> MERGE-SOURCE
102 from autopilot.input._common import get_center_point
103
104
105@@ -153,6 +159,7 @@
106
107 self.assertEqual(123, x)
108 self.assertEqual(345, y)
109+<<<<<<< TREE
110
111
112 class PointerWithTouchBackendTestCase(TestCase):
113@@ -182,3 +189,182 @@
114 self.pointer.move(1, 1)
115
116 self.assertFalse(mock_move.called)
117+=======
118+
119+
120+class PartialMock(object):
121+ """Mock some of the methods of an object, and record their calls."""
122+
123+ def __init__(self, real_object, *args):
124+ super(PartialMock, self).__init__()
125+ self._mock_manager = Mock()
126+ self._real_object = real_object
127+ self.patched_attributes = args
128+
129+ def __getattr__(self, name):
130+ """Forward all the calls to the real object."""
131+ return self._real_object.__getattribute__(name)
132+
133+ @property
134+ def mock_calls(self):
135+ """Return the calls recorded for the mocked attributes."""
136+ return self._mock_manager.mock_calls
137+
138+ def __enter__(self):
139+ self._start_patchers()
140+ return self
141+
142+ def _start_patchers(self):
143+ self._patchers = []
144+ for attribute in self.patched_attributes:
145+ patcher = patch.object(self._real_object, attribute)
146+ self._patchers.append(patcher)
147+
148+ self._mock_manager.attach_mock(patcher.start(), attribute)
149+
150+ def __exit__(self, exc_type, exc_val, exc_tb):
151+ self._stop_patchers()
152+
153+ def _stop_patchers(self):
154+ for patcher in self._patchers:
155+ patcher.stop()
156+
157+
158+class MockX11Mouse(PartialMock):
159+ """Mock for the X11 Mouse Touch.
160+
161+ It records the calls to press, release and move, but doesn't perform them.
162+
163+ """
164+
165+ def __init__(self):
166+ super(MockX11Mouse, self).__init__(
167+ _X11.Mouse(), 'press', 'release', 'move')
168+
169+ def get_move_call_args_list(self):
170+ return self._mock_manager.move.call_args_list
171+
172+
173+class X11MouseTestCase(TestCase):
174+
175+ def test_drag_should_call_move_with_rate(self):
176+ expected_first_move_call = call(0, 0)
177+ expected_second_move_call = call(100, 100, rate=1)
178+ with MockX11Mouse() as mock_mouse:
179+ mock_mouse.drag(0, 0, 100, 100, rate=1)
180+
181+ self.assertEqual(
182+ [expected_first_move_call, expected_second_move_call],
183+ mock_mouse.get_move_call_args_list())
184+
185+ def test_drag_with_default_rate(self):
186+ expected_first_move_call = call(0, 0)
187+ expected_second_move_call = call(100, 100, rate=10)
188+ with MockX11Mouse() as mock_mouse:
189+ mock_mouse.drag(0, 0, 100, 100)
190+
191+ self.assertEqual(
192+ [expected_first_move_call, expected_second_move_call],
193+ mock_mouse.get_move_call_args_list())
194+
195+
196+class MockTouch(PartialMock):
197+ """Mock for the uinput Touch.
198+
199+ It records the calls to _finger_down, _finger_up and _finger_move, but
200+ doesn't perform them.
201+
202+ """
203+
204+ def __init__(self):
205+ super(MockTouch, self).__init__(
206+ _uinput.Touch(), '_finger_down', '_finger_up', '_finger_move')
207+
208+ def get_finger_move_call_args_list(self):
209+ return self._mock_manager._finger_move.call_args_list
210+
211+
212+class UinputTouchTestCase(TestCase):
213+
214+ def test_drag_finger_actions(self):
215+ expected_finger_calls = [
216+ call._finger_down(0, 0),
217+ call._finger_move(10, 10),
218+ call._finger_up()
219+ ]
220+ with MockTouch() as mock_touch:
221+ mock_touch.drag(0, 0, 10, 10)
222+ self.assertEqual(mock_touch.mock_calls, expected_finger_calls)
223+
224+ def test_drag_should_call_move_with_rate(self):
225+ expected_move_calls = [call(5, 5), call(10, 10), call(15, 15)]
226+ with MockTouch() as mock_touch:
227+ mock_touch.drag(0, 0, 15, 15, rate=5)
228+
229+ self.assertEqual(
230+ expected_move_calls, mock_touch.get_finger_move_call_args_list())
231+
232+ def test_drag_with_default_rate(self):
233+ expected_move_calls = [call(10, 10), call(20, 20)]
234+ with MockTouch() as mock_touch:
235+ mock_touch.drag(0, 0, 20, 20)
236+
237+ self.assertEqual(
238+ expected_move_calls, mock_touch.get_finger_move_call_args_list())
239+
240+ def test_drag_to_same_place_should_not_move(self):
241+ expected_finger_calls = [
242+ call._finger_down(0, 0),
243+ call._finger_up()
244+ ]
245+ with MockTouch() as mock_touch:
246+ mock_touch.drag(0, 0, 0, 0)
247+ self.assertEqual(mock_touch.mock_calls, expected_finger_calls)
248+
249+
250+class DragUinputTouchTestCase(testscenarios.TestWithScenarios, TestCase):
251+
252+ scenarios = [
253+ ('drag to top', dict(
254+ start_x=50, start_y=50, stop_x=50, stop_y=30,
255+ expected_moves=[call(50, 40), call(50, 30)])),
256+ ('drag to bottom', dict(
257+ start_x=50, start_y=50, stop_x=50, stop_y=70,
258+ expected_moves=[call(50, 60), call(50, 70)])),
259+ ('drag to left', dict(
260+ start_x=50, start_y=50, stop_x=30, stop_y=50,
261+ expected_moves=[call(40, 50), call(30, 50)])),
262+ ('drag to right', dict(
263+ start_x=50, start_y=50, stop_x=70, stop_y=50,
264+ expected_moves=[call(60, 50), call(70, 50)])),
265+
266+ ('drag to top-left', dict(
267+ start_x=50, start_y=50, stop_x=30, stop_y=30,
268+ expected_moves=[call(40, 40), call(30, 30)])),
269+ ('drag to top-right', dict(
270+ start_x=50, start_y=50, stop_x=70, stop_y=30,
271+ expected_moves=[call(60, 40), call(70, 30)])),
272+ ('drag to bottom-left', dict(
273+ start_x=50, start_y=50, stop_x=30, stop_y=70,
274+ expected_moves=[call(40, 60), call(30, 70)])),
275+ ('drag to bottom-right', dict(
276+ start_x=50, start_y=50, stop_x=70, stop_y=70,
277+ expected_moves=[call(60, 60), call(70, 70)])),
278+
279+ ('drag less than rate', dict(
280+ start_x=50, start_y=50, stop_x=55, stop_y=55,
281+ expected_moves=[call(55, 55)])),
282+
283+ ('drag with last move less than rate', dict(
284+ start_x=50, start_y=50, stop_x=65, stop_y=65,
285+ expected_moves=[call(60, 60), call(65, 65)])),
286+ ]
287+
288+ def test_drag_moves(self):
289+ with MockTouch() as mock_touch:
290+ mock_touch.drag(
291+ self.start_x, self.start_y, self.stop_x, self.stop_y)
292+
293+ self.assertEqual(
294+ self.expected_moves, mock_touch.get_finger_move_call_args_list())
295+>>>>>>> MERGE-SOURCE

Subscribers

People subscribed via source and target branches

to all changes: