Merge lp:~veebers/autopilot/add_OSK_keyboard_backend into lp:autopilot
- add_OSK_keyboard_backend
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Thomi Richards |
Approved revision: | 327 |
Merged at revision: | 313 |
Proposed branch: | lp:~veebers/autopilot/add_OSK_keyboard_backend |
Merge into: | lp:autopilot |
Diff against target: |
601 lines (+444/-8) 5 files modified
autopilot/input/__init__.py (+67/-3) autopilot/input/_osk.py (+121/-0) autopilot/tests/functional/test_input_stack.py (+130/-1) docs/faq/faq.rst (+30/-3) docs/tutorial/advanced_autopilot.rst (+96/-1) |
To merge this branch: | bzr merge lp:~veebers/autopilot/add_OSK_keyboard_backend |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Thomi Richards (community) | Approve | ||
PS Jenkins bot | continuous-integration | Approve | |
Review via email: mp+181456@code.launchpad.net |
Commit message
Adds the Ubuntu Keyboard OSK as an input backend
Description of the change
Adds the Ubuntu Keyboard OSK as an input backend
PS Jenkins bot (ps-jenkins) wrote : | # |
- 323. By Christopher Lee
-
Documentation updates.
- 324. By Christopher Lee
-
Fix exception raised and docs
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:324
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 325. By Christopher Lee
-
Further docs improvements
- 326. By Christopher Lee
-
Minor doc change
Thomi Richards (thomir-deactivatedaccount) wrote : | # |
LGTM
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:325
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:326
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 327. By Christopher Lee
-
Re-order OSK Keyboard backend priority
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:327
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Thomi Richards (thomir-deactivatedaccount) wrote : | # |
Still LGTM
Preview Diff
1 | === modified file 'autopilot/input/__init__.py' |
2 | --- autopilot/input/__init__.py 2013-07-23 04:04:43 +0000 |
3 | +++ autopilot/input/__init__.py 2013-08-23 05:01:40 +0000 |
4 | @@ -56,6 +56,7 @@ |
5 | """ |
6 | |
7 | from collections import OrderedDict |
8 | +from contextlib import contextmanager |
9 | from autopilot.utilities import _pick_backend, CleanupRegistered |
10 | from autopilot.input._common import get_center_point |
11 | |
12 | @@ -81,12 +82,21 @@ |
13 | For more infomration on picking specific backends, see |
14 | :ref:`tut-picking-backends` |
15 | |
16 | + For details regarding backend limitations please see: |
17 | + :ref:`Keyboard backend limitations<keyboard_backend_limitations>` |
18 | + |
19 | + .. warning:: The **OSK** (On Screen Keyboard) backend option does not |
20 | + implement either :py:meth:`press` or :py:meth:`release` methods due to |
21 | + technical implementation details and will raise a NotImplementedError |
22 | + exception if used. |
23 | + |
24 | :param preferred_backend: A string containing a hint as to which |
25 | backend you would like. Possible backends are: |
26 | |
27 | * ``X11`` - Generate keyboard events using the X11 client |
28 | libraries. |
29 | * ``UInput`` - Use UInput kernel-level device driver. |
30 | + * ``OSK`` - Use the graphical On Screen Keyboard as a backend. |
31 | |
32 | :raises: RuntimeError if autopilot cannot instantate any of the |
33 | possible backends. |
34 | @@ -104,17 +114,67 @@ |
35 | from autopilot.input._uinput import Keyboard |
36 | return Keyboard() |
37 | |
38 | + def get_osk_kb(): |
39 | + try: |
40 | + from autopilot.input._osk import Keyboard |
41 | + return Keyboard() |
42 | + except ImportError as e: |
43 | + e.args += ("Unable to import the OSK backend",) |
44 | + raise |
45 | + |
46 | backends = OrderedDict() |
47 | backends['X11'] = get_x11_kb |
48 | backends['UInput'] = get_uinput_kb |
49 | + backends['OSK'] = get_osk_kb |
50 | return _pick_backend(backends, preferred_backend) |
51 | |
52 | + @contextmanager |
53 | + def focused_type(self, input_target, pointer=None): |
54 | + """Type into an input widget. |
55 | + |
56 | + This context manager takes care of making sure a particular |
57 | + *input_target* UI control is selected before any text is entered. |
58 | + |
59 | + Some backends extend this method to perform cleanup actions at the end |
60 | + of the context manager block. For example, the OSK backend dismisses |
61 | + the keyboard. |
62 | + |
63 | + If the *pointer* argument is None (default) then either a Mouse or |
64 | + Touch pointer will be created based on the current platform. |
65 | + |
66 | + An example of using the context manager (with an OSK backend):: |
67 | + |
68 | + from autopilot.input import Keyboard |
69 | + |
70 | + text_area = self._launch_test_input_area() |
71 | + keyboard = Keyboard.create('OSK') |
72 | + with keyboard.focused_type(text_area) as kb: |
73 | + kb.type("Hello World.") |
74 | + self.assertThat(text_area.text, Equals("Hello World")) |
75 | + # Upon leaving the context managers scope the keyboard is dismissed |
76 | + # with a swipe |
77 | + |
78 | + """ |
79 | + if pointer is None: |
80 | + from autopilot.platform import model |
81 | + if model() == 'Desktop': |
82 | + pointer = Pointer(Mouse.create()) |
83 | + else: |
84 | + pointer = Pointer(Touch.create()) |
85 | + |
86 | + pointer.click_object(input_target) |
87 | + yield self |
88 | + |
89 | def press(self, keys, delay=0.2): |
90 | """Send key press events only. |
91 | |
92 | :param keys: Keys you want pressed. |
93 | :param delay: The delay (in Seconds) after pressing the keys before |
94 | returning control to the caller. |
95 | + :raises: NotImplementedError If called when using the OSK Backend. |
96 | + |
97 | + .. warning:: The **OSK** backend does not implement the press method |
98 | + and will raise a NotImplementedError if called. |
99 | |
100 | Example: |
101 | |
102 | @@ -131,6 +191,10 @@ |
103 | :param keys: Keys you want released. |
104 | :param delay: The delay (in Seconds) after releasing the keys before |
105 | returning control to the caller. |
106 | + :raises: NotImplementedError If called when using the OSK Backend. |
107 | + |
108 | + .. warning:: The **OSK** backend does not implement the press method |
109 | + and will raise a NotImplementedError if called. |
110 | |
111 | Example: |
112 | |
113 | @@ -219,14 +283,14 @@ |
114 | from autopilot.platform import model |
115 | if model() != 'Desktop': |
116 | logger.info( |
117 | - "You cannot create a Mouse on the phablet devices. " |
118 | - "consider using a Touch or Pointer device. " |
119 | + "You cannot create a Mouse on the devices where X11 is not " |
120 | + "available. consider using a Touch or Pointer device. " |
121 | "For more information, see: " |
122 | "http://unity.ubuntu.com/autopilot/api/input.html" |
123 | "#autopilot-unified-input-system" |
124 | ) |
125 | raise RuntimeError( |
126 | - "Cannot create a Mouse on the phablet devices." |
127 | + "Cannot create a Mouse on devices where X11 is not available." |
128 | ) |
129 | |
130 | backends = OrderedDict() |
131 | |
132 | === added file 'autopilot/input/_osk.py' |
133 | --- autopilot/input/_osk.py 1970-01-01 00:00:00 +0000 |
134 | +++ autopilot/input/_osk.py 2013-08-23 05:01:40 +0000 |
135 | @@ -0,0 +1,121 @@ |
136 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
137 | +# |
138 | +# Autopilot Functional Test Tool |
139 | +# Copyright (C) 2013 Canonical |
140 | +# |
141 | +# This program is free software: you can redistribute it and/or modify |
142 | +# it under the terms of the GNU General Public License as published by |
143 | +# the Free Software Foundation, either version 3 of the License, or |
144 | +# (at your option) any later version. |
145 | +# |
146 | +# This program is distributed in the hope that it will be useful, |
147 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
148 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
149 | +# GNU General Public License for more details. |
150 | +# |
151 | +# You should have received a copy of the GNU General Public License |
152 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
153 | +# |
154 | + |
155 | +import logging |
156 | +from time import sleep |
157 | +from contextlib import contextmanager |
158 | + |
159 | +from ubuntu_keyboard.emulators.keyboard import ( |
160 | + Keyboard as KeyboardDriver, |
161 | + UnsupportedKey, |
162 | +) |
163 | + |
164 | +from autopilot.input import Keyboard as KeyboardBase |
165 | + |
166 | + |
167 | +logger = logging.getLogger(__name__) |
168 | + |
169 | + |
170 | +class Keyboard(KeyboardBase): |
171 | + |
172 | + _keyboard = KeyboardDriver() |
173 | + |
174 | + @contextmanager |
175 | + def focused_type(self, input_target, pointer=None): |
176 | + """Ensures that the keyboard is up and ready for input as well as |
177 | + dismisses the keyboard afterward. |
178 | + |
179 | + """ |
180 | + with super(Keyboard, self).focused_type(input_target, pointer): |
181 | + try: |
182 | + self._keyboard.wait_for_keyboard_ready() |
183 | + yield self |
184 | + finally: |
185 | + self._keyboard.dismiss() |
186 | + |
187 | + def press(self, keys, delay=0.2): |
188 | + raise NotImplementedError( |
189 | + "OSK Backend does not support the press method" |
190 | + ) |
191 | + |
192 | + def release(self, keys, delay=0.2): |
193 | + raise NotImplementedError( |
194 | + "OSK Backend does not support the release method" |
195 | + ) |
196 | + |
197 | + def press_and_release(self, key, delay=0.2): |
198 | + """Press and release the key *key*. |
199 | + |
200 | + The 'key' argument must be a string of the single key you want pressed |
201 | + and released. |
202 | + |
203 | + For example:: |
204 | + |
205 | + press_and_release('A') |
206 | + |
207 | + presses then releases the 'A' key. |
208 | + |
209 | + :raises: *UnsupportedKey* if the provided key is not supported by the |
210 | + OSK Backend (or the current OSK langauge layout.) |
211 | + :raises: *ValueError* if there is more than a single key supplied in |
212 | + the *key* argument. |
213 | + |
214 | + """ |
215 | + |
216 | + if len(self._sanitise_keys(key)) != 1: |
217 | + raise ValueError("Only a single key can be passed in.") |
218 | + |
219 | + try: |
220 | + self._keyboard.press_key(key) |
221 | + sleep(delay) |
222 | + except UnsupportedKey as e: |
223 | + e.args += ("OSK Backend is unable to type the key '%s" % key,) |
224 | + raise |
225 | + |
226 | + def type(self, string, delay=0.1): |
227 | + """Simulate a user typing a string of text. |
228 | + |
229 | + Only 'normal' keys can be typed with this method. There is no such |
230 | + thing as Alt or Ctrl on the Onscreen Keyboard. |
231 | + |
232 | + The OSK class back end will take care of ensuring that capitalized |
233 | + keys are in fact capitalized. |
234 | + |
235 | + :raises: *UnsupportedKey* if there is a key within the string that is |
236 | + not supported by the OSK Backend (or the current OSK langauge layout.) |
237 | + |
238 | + """ |
239 | + if not isinstance(string, basestring): |
240 | + raise TypeError("'string' argument must be a string.") |
241 | + logger.debug("Typing text: %s", string) |
242 | + self._keyboard.type(string, delay) |
243 | + |
244 | + @classmethod |
245 | + def on_test_end(cls, test_instance): |
246 | + """Dismiss (swipe hide) the keyboard. |
247 | + |
248 | + """ |
249 | + logger.debug("Dismissing the OSK with a swipe.") |
250 | + cls._keyboard.dismiss() |
251 | + |
252 | + def _sanitise_keys(self, keys): |
253 | + if keys == '+': |
254 | + return [keys] |
255 | + else: |
256 | + return keys.split('+') |
257 | |
258 | === modified file 'autopilot/tests/functional/test_input_stack.py' |
259 | --- autopilot/tests/functional/test_input_stack.py 2013-07-24 08:26:10 +0000 |
260 | +++ autopilot/tests/functional/test_input_stack.py 2013-08-23 05:01:40 +0000 |
261 | @@ -21,11 +21,13 @@ |
262 | import json |
263 | import os |
264 | from tempfile import mktemp |
265 | -from testtools import TestCase |
266 | +from testtools import TestCase, skipIf |
267 | from testtools.matchers import IsInstance, Equals, raises |
268 | +from textwrap import dedent |
269 | from unittest import SkipTest |
270 | from mock import patch |
271 | |
272 | +from autopilot import platform |
273 | from autopilot.testcase import AutopilotTestCase, multiply_scenarios |
274 | from autopilot.input import Keyboard, Mouse, Pointer, Touch |
275 | from autopilot.input._common import get_center_point |
276 | @@ -106,6 +108,24 @@ |
277 | "app shows: " + text_edit.plainText |
278 | ) |
279 | |
280 | + def test_typing_with_contextmanager(self): |
281 | + """Typing text must produce the correct characters in the target |
282 | + app. |
283 | + |
284 | + """ |
285 | + app_proxy = self.start_mock_app() |
286 | + text_edit = app_proxy.select_single('QTextEdit') |
287 | + |
288 | + keyboard = Keyboard.create(self.backend) |
289 | + with keyboard.focused_type(text_edit) as kb: |
290 | + kb.type(self.input, 0.01) |
291 | + |
292 | + self.assertThat( |
293 | + text_edit.plainText, |
294 | + Eventually(Equals(self.input)), |
295 | + "app shows: " + text_edit.plainText |
296 | + ) |
297 | + |
298 | def test_keyboard_keys_are_released(self): |
299 | """Typing characters must not leave keys pressed.""" |
300 | app_proxy = self.start_mock_app() |
301 | @@ -137,6 +157,115 @@ |
302 | ) |
303 | |
304 | |
305 | +@skipIf(platform.model() == 'Desktop', "Only on device") |
306 | +class OSKBackendTests(AutopilotTestCase): |
307 | + """Testing the Onscreen Keyboard (Ubuntu Keyboard) backend specifically. |
308 | + |
309 | + There are limitations (i.e. on device only, window-mocker doesn't work on |
310 | + the device, can't type all the characters that X11/UInput can.) that |
311 | + necessitate this split into it's own test class. |
312 | + |
313 | + """ |
314 | + |
315 | + scenarios = [ |
316 | + ('lower_alpha', dict(input='abcdefghijklmnopqrstuvwxyz')), |
317 | + ('upper_alpha', dict(input='ABCDEFGHIJKLMNOPQRSTUVWXYZ')), |
318 | + ('numeric', dict(input='0123456789')), |
319 | + ('punctuation', dict(input='`~!@#$%^&*()_-+={}[]|\\:;"\'<>,.?/')), |
320 | + ] |
321 | + |
322 | + def launch_test_input_area(self): |
323 | + self.app = self._launch_simple_input() |
324 | + text_area = self.app.select_single("QQuickTextInput") |
325 | + |
326 | + return text_area |
327 | + |
328 | + def _start_qml_script(self, script_contents): |
329 | + """Launch a qml script.""" |
330 | + qml_path = mktemp(suffix='.qml') |
331 | + open(qml_path, 'w').write(script_contents) |
332 | + self.addCleanup(os.remove, qml_path) |
333 | + |
334 | + return self.launch_test_application( |
335 | + "qmlscene", |
336 | + qml_path, |
337 | + app_type='qt', |
338 | + ) |
339 | + |
340 | + def _launch_simple_input(self): |
341 | + simple_script = dedent(""" |
342 | + import QtQuick 2.0 |
343 | + import Ubuntu.Components 0.1 |
344 | + |
345 | + Rectangle { |
346 | + id: window |
347 | + objectName: "windowRectangle" |
348 | + color: "lightgrey" |
349 | + |
350 | + Text { |
351 | + id: inputLabel |
352 | + text: "OSK Tests" |
353 | + font.pixelSize: units.gu(3) |
354 | + anchors { |
355 | + left: input.left |
356 | + top: parent.top |
357 | + topMargin: 25 |
358 | + bottomMargin: 25 |
359 | + } |
360 | + } |
361 | + |
362 | + TextField { |
363 | + id: input; |
364 | + objectName: "input" |
365 | + anchors { |
366 | + top: inputLabel.bottom |
367 | + horizontalCenter: parent.horizontalCenter |
368 | + topMargin: 10 |
369 | + } |
370 | + inputMethodHints: Qt.ImhNoPredictiveText |
371 | + } |
372 | + } |
373 | + |
374 | + """) |
375 | + |
376 | + return self._start_qml_script(simple_script) |
377 | + |
378 | + def test_can_type_string(self): |
379 | + """Typing text must produce the expected characters in the input |
380 | + field. |
381 | + |
382 | + """ |
383 | + |
384 | + text_area = self.launch_test_input_area() |
385 | + keyboard = Keyboard.create('OSK') |
386 | + pointer = Pointer(Touch.create()) |
387 | + pointer.click_object(text_area) |
388 | + keyboard._keyboard.wait_for_keyboard_ready() |
389 | + |
390 | + keyboard.type(self.input) |
391 | + |
392 | + self.assertThat(text_area.text, Eventually(Equals(self.input))) |
393 | + |
394 | + def test_focused_typing_contextmanager(self): |
395 | + """Typing text using the 'focused_typing' context manager must not only |
396 | + produce the expected characters in the input field but also cleanup the |
397 | + OSK afterwards too. |
398 | + |
399 | + """ |
400 | + text_area = self.launch_test_input_area() |
401 | + keyboard = Keyboard.create('OSK') |
402 | + with keyboard.focused_type(text_area) as kb: |
403 | + kb.type(self.input) |
404 | + self.assertThat( |
405 | + text_area.text, |
406 | + Eventually(Equals(self.input)) |
407 | + ) |
408 | + self.assertThat( |
409 | + keyboard._keyboard.is_available, |
410 | + Eventually(Equals(False)) |
411 | + ) |
412 | + |
413 | + |
414 | class MouseTestCase(AutopilotTestCase): |
415 | |
416 | def test_move_to_nonint_point(self): |
417 | |
418 | === modified file 'docs/faq/faq.rst' |
419 | --- docs/faq/faq.rst 2013-07-24 08:38:59 +0000 |
420 | +++ docs/faq/faq.rst 2013-08-23 05:01:40 +0000 |
421 | @@ -20,7 +20,7 @@ |
422 | |
423 | **I am running the latest development image!** |
424 | |
425 | -In that case you can install autopilot directly - either by installing the ``autopilot-desktop`` or ``autopilot-touch`` packages, depending on whether you are installing to a desktop or phablet device. |
426 | +In that case you can install autopilot directly - either by installing the ``autopilot-desktop`` or ``autopilot-touch`` packages, depending on whether you are installing to a desktop or an Ubuntu Touch device. |
427 | |
428 | **I am running the Ubuntu release previous to the development release!** |
429 | |
430 | @@ -108,8 +108,8 @@ |
431 | |
432 | In general, autopilot tests are more relaxed about the 'one assertion per test' rule. However, care should still be taken to produce tests that are as small and understandable as possible. |
433 | |
434 | -How do I write a test that uses either a Mouse or a Touch device interchangeably? |
435 | -============================================================================================== |
436 | +Q. How do I write a test that uses either a Mouse or a Touch device interchangeably? |
437 | +==================================================================================== |
438 | |
439 | The :class:`autopilot.input.Pointer` class is a simple wrapper that unifies some of the differences between the :class:`~autopilot.input.Touch` and :class:`~autopilot.input.Mouse` classes. To use it, pass in the device you want to use under the hood, like so:: |
440 | |
441 | @@ -136,6 +136,33 @@ |
442 | |
443 | If you only want to use the mouse on certain platforms, use the :mod:`autopilot.platform` module to determine the current platform at runtime. |
444 | |
445 | +Q. How do I use the Onscreen Keyboard (OSK) to input text in my test? |
446 | +===================================================================== |
447 | + |
448 | +The OSK is an backend option for the :meth:`autopilot.input.Keyboard.create` |
449 | +method (see this :ref:`Advanced Autopilot<adv_picking_backend>` section for |
450 | +details regarding backend selection.) |
451 | + |
452 | +Unlike the other backends (X11, UInput) the OSK has a GUI presence and thus can |
453 | +be displayed on the screen. |
454 | + |
455 | +The :class:`autopilot.input.Keyboard` class provides a context manager that |
456 | +handles any cleanup required when dealing with the input backends. |
457 | + |
458 | +For example in the instance when the backend is the OSK, when leaving the scope |
459 | +of the context manager the OSK will be dismissed with a swipe:: |
460 | + |
461 | + from autopilot.input import Keyboard |
462 | + |
463 | + text_area = self._launch_test_input_area() |
464 | + keyboard = Keyboard.create('OSK') |
465 | + with keyboard.focused_type(text_area) as kb: |
466 | + kb.type("Hello World.") |
467 | + self.assertThat(text_area.text, Equals("Hello World")) |
468 | + # At this point now the OSK has been swiped away. |
469 | + self.assertThat() |
470 | + |
471 | + |
472 | Autopilot Qt & Gtk Support |
473 | ++++++++++++++++++++++++++ |
474 | |
475 | |
476 | === modified file 'docs/tutorial/advanced_autopilot.rst' |
477 | --- docs/tutorial/advanced_autopilot.rst 2013-07-24 08:38:59 +0000 |
478 | +++ docs/tutorial/advanced_autopilot.rst 2013-08-23 05:01:40 +0000 |
479 | @@ -199,10 +199,12 @@ |
480 | |
481 | The code snippet above will create an instance of the Keyboard class that uses X11 on Desktop systems, and UInput on other systems. On the rare occaison when test authors need to construct these objects themselves, we expect that the default creation pattern to be used. |
482 | |
483 | +.. _adv_picking_backend: |
484 | + |
485 | Picking a Backend |
486 | +++++++++++++++++ |
487 | |
488 | -Test authors may sometimes want to pick a specific backend. The possible backends are documented in the API documentation for each class. For example, the documentation for the :meth:`autopilot.input.Keyboard.create` method says there are two backends available: the ``X11`` backend, and the ``UInput`` backend. These backends can be specified in the create method. For example, to specify that you want a Keyboard that uses X11 to generate it's input events:: |
489 | +Test authors may sometimes want to pick a specific backend. The possible backends are documented in the API documentation for each class. For example, the documentation for the :meth:`autopilot.input.Keyboard.create` method says there are three backends available: the ``X11`` backend, the ``UInput`` backend, and the ``OSK`` backend. These backends can be specified in the create method. For example, to specify that you want a Keyboard that uses X11 to generate it's input events:: |
490 | |
491 | >>> from autopilot.input import Keyboard |
492 | >>> kbd = Keyboard.create("X11") |
493 | @@ -212,8 +214,15 @@ |
494 | >>> from autopilot.input import Keyboard |
495 | >>> kbd = Keyboard.create("UInput") |
496 | |
497 | +Finally, for the Onscreen Keyboard:: |
498 | + |
499 | + >>> from autopilot.input import Keyboard |
500 | + >>> kbd = Keyboard.create("OSK") |
501 | + |
502 | .. warning:: Care must be taken when specifying specific backends. There is no guarantee that the backend you ask for is going to be available across all platforms. For that reason, using the default creation method is encouraged. |
503 | |
504 | +.. warning:: The **OSK** backend has some known implementation limitations, please see :meth:`autopilot.input.Keyboard.create` method documenation for further details. |
505 | + |
506 | Possible Errors when Creating Backends |
507 | ++++++++++++++++++++++++++++++++++++++ |
508 | |
509 | @@ -249,6 +258,92 @@ |
510 | 'UInputError(\'"/dev/uinput" cannot be opened for writing\',)' |
511 | 'BackendException(\'Error while initialising backend. Original exception was: "/dev/uinput" cannot be opened for writing\',)' |
512 | |
513 | +Keyboard Backends |
514 | +================= |
515 | + |
516 | +A quick introduction to the Keyboard backends |
517 | ++++++++++++++++++++++++++++++++++++++++++++++ |
518 | + |
519 | +Each backend has a different method of operating behind the scenes to provide |
520 | +the Keyboard interface. |
521 | + |
522 | +Here is a quick overview of how each backend works. |
523 | + |
524 | +.. list-table:: |
525 | + :widths: 15, 85 |
526 | + :header-rows: 1 |
527 | + |
528 | + * - Backend |
529 | + - Description |
530 | + * - X11 |
531 | + - The X11 backend generates X11 events using a mock input device which it |
532 | + then syncs with X to actually action the input. |
533 | + * - Uinput |
534 | + - The UInput backend injects events directly in to the kernel using the |
535 | + UInput device driver to produce input. |
536 | + * - OSK |
537 | + - The Onscreen Keyboard backend uses the GUI pop-up keyboard to enter |
538 | + input. Using a pointer object it taps on the required keys to get the |
539 | + expected output. |
540 | + |
541 | +.. _keyboard_backend_limitations: |
542 | + |
543 | +Limitations of the different Keyboard backends |
544 | +++++++++++++++++++++++++++++++++++++++++++++++ |
545 | + |
546 | +While every effort has been made so that the Keyboard devices act the same |
547 | +regardless of which backend or platform is in use, the simple fact is that |
548 | +there can be some technical limitations for some backends. |
549 | + |
550 | +Some of these limitations are hidden when using the "create" method and won't |
551 | +cause any concern (i.e. X11 backend on desktop, UInput on an Ubuntu Touch device.) |
552 | +while others will raise exceptions (that are fully documented in the API docs). |
553 | + |
554 | +Here is a list of known limitations: |
555 | + |
556 | +**X11** |
557 | + |
558 | +* Only available on desktop platforms |
559 | + |
560 | + - X11 isn't available on Ubuntu Touch devices |
561 | + |
562 | +**UInput** |
563 | + |
564 | +* Requires correct device access permissions |
565 | + |
566 | + - The user (or group) that are running the autopilot tests need read/write |
567 | + access to the UInput device (usually /dev/uinput). |
568 | + |
569 | +* Specific kernel support is required |
570 | + |
571 | + - The kernel on the system running the tests must be running a kernel that |
572 | + includes UInput support (as well as have the module loaded. |
573 | + |
574 | +**OSK** |
575 | + |
576 | +* Currently only available on Ubuntu Touch devices |
577 | + |
578 | + - At the time of writing this the OSK/Ubuntu Keyboard is only |
579 | + supported/available on the Ubuntu Touch devices. It is possible that it |
580 | + will be available on the desktop in the near future. |
581 | + |
582 | +* Unable to type 'special' keys i.e. Alt |
583 | + |
584 | + - This shouldn't be an issue as applications running on Ubuntu Touch devices |
585 | + will be using the expected patterns of use on these platforms. |
586 | + |
587 | +* The following methods have limitations or are not implemented: |
588 | + |
589 | + - :meth:`autopilot.input.Keyboard.press`: Raises NotImplementedError if |
590 | + called. |
591 | + |
592 | + - :meth:`autopilot.input.Keyboard.release`: Raises NotImplementedError if |
593 | + called. |
594 | + |
595 | + - :meth:`autopilot.input.Keyboard.press_and_release`: can can only handle |
596 | + single keys/characters. Raises either ValueError if passed more than a |
597 | + single character key or UnsupportedKey if passed a key that is not |
598 | + supported by the OSK backend (or the current language layout). |
599 | |
600 | |
601 | Process Control |
PASSED: Continuous integration, rev:322 jenkins. qa.ubuntu. com/job/ autopilot- ci/202/ jenkins. qa.ubuntu. com/job/ autopilot- saucy-amd64- ci/130 jenkins. qa.ubuntu. com/job/ autopilot- saucy-armhf- ci/130
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins: 8080/job/ autopilot- ci/202/ rebuild
http://