Merge lp:~mir-team/mir/touchspot-visualizer into lp:mir
- touchspot-visualizer
- Merge into development-branch
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Robert Carr | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 1824 | ||||
Proposed branch: | lp:~mir-team/mir/touchspot-visualizer | ||||
Merge into: | lp:mir | ||||
Prerequisite: | lp:~mir-team/mir/sha1sum-script | ||||
Diff against target: |
983 lines (+465/-48) 26 files modified
include/server/mir/default_server_configuration.h (+3/-0) include/server/mir/input/android/default_android_input_configuration.h (+3/-0) include/server/mir/input/touch_visualizer.h (+58/-0) include/test/mir_test/event_factory.h (+12/-1) include/test/mir_test/fake_event_hub_input_configuration.h (+2/-0) include/test/mir_test_doubles/stub_touch_visualizer.h (+43/-0) include/test/mir_test_framework/input_testing_server_configuration.h (+1/-1) server-ABI-sha1sums (+3/-2) src/server/input/android/android_input_reader_policy.cpp (+7/-2) src/server/input/android/android_input_reader_policy.h (+4/-1) src/server/input/android/android_pointer_controller.cpp (+27/-13) src/server/input/android/android_pointer_controller.h (+15/-9) src/server/input/android/default_android_input_configuration.cpp (+3/-1) src/server/input/default_configuration.cpp (+18/-0) tests/acceptance-tests/CMakeLists.txt (+1/-0) tests/acceptance-tests/test_client_input.cpp (+2/-2) tests/acceptance-tests/test_server_shutdown.cpp (+2/-1) tests/acceptance-tests/test_touchspot_visualization.cpp (+222/-0) tests/integration-tests/input/android/test_android_cursor_listener.cpp (+3/-0) tests/integration-tests/input/android/test_android_input_manager.cpp (+5/-1) tests/mir_test_doubles/event_factory.cpp (+13/-5) tests/mir_test_doubles/fake_event_hub.cpp (+8/-5) tests/mir_test_doubles/fake_event_hub_input_configuration.cpp (+2/-1) tests/mir_test_framework/input_testing_server_options.cpp (+2/-1) tests/unit-tests/input/android/test_android_input_reader_policy.cpp (+3/-1) tests/unit-tests/input/android/test_android_pointer_controller.cpp (+3/-1) |
||||
To merge this branch: | bzr merge lp:~mir-team/mir/touchspot-visualizer | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Cemil Azizoglu (community) | Approve | ||
Alan Griffiths | Approve | ||
Kevin DuBois | Pending | ||
Daniel van Vugt | Pending | ||
Review via email: mp+228903@code.launchpad.net |
This proposal supersedes a proposal from 2014-06-26.
Commit message
Expose an interface for touch visualization.
Description of the change
Expose an interface for touch visualization. There is no in-tree implementation yet as that is blocked on the yet to come cursor-
This goes ahead and exposes the TouchVisualizer interface though, as Unity with QtCompositor will need a custom implementation anyway, so this unblocks downstreams.
Requested by QA.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal | # |
The change in InputTestingSer
Namely, in extremely fast running tests (i.e. clientless tests), the tests could complete in the input threads, before on_start ever finishes, causing crashes in the TestingServerSt
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal | # |
Aren't touchspots just multiple cursors? (and, consquently, if cursors are a renderable, aren't touchspots just renderables too?) This interface seems to be making a distinctions. I'm okay with this approach, given that we don't require compositors to always implement a touch-spot visualization.
Will the DefaultDisplayB
Oh, and also are we intending USC or unity8 to paint the touch-spots?
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1730
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:1731
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal | # |
> Aren't touchspots just multiple cursors? (and, consquently, if cursors are a
> renderable, aren't touchspots just renderables too?) This interface seems to
> be making a distinctions. I'm okay with this approach, given that we don't
> require compositors to always implement a touch-spot visualization.
I think we've been down this road with surfaces - which can supply renderables but are not renderables. I suspect the same is true of cursors and touchspots.
> Oh, and also are we intending USC or unity8 to paint the touch-spots?
I can imagine that apps (or nested mir servers) would want the facility to take over drawing from the session mir (or system mir).
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
Yep, touch spot visualization is a nice feature to have eventually...
(1) It looks like we should be exposing MirMotionEvent instead of defining new structures to translate to. Spot, Action etc are redundant with MirMotionEvent which is already publicly defined. I don't think we need to define new types as it only creates the need for more translation logic.
Given a copy of the latest MirMotionEvent struct, a compositor would easily have all the information it needs to visualize the touch points. Literally just send the latest MirMotionEvent to the compositor and you're done. So I don't think the complexity of the new interfaces here is justified.
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal | # |
> Given a copy of the latest MirMotionEvent struct, a compositor would easily
> have all the information it needs to visualize the touch points. Literally
> just send the latest MirMotionEvent to the compositor and you're done. So I
> don't think the complexity of the new interfaces here is justified.
I agree on the complexity of the new interfaces point.
I think that we already have the interfaces hooked up all the way to the compositor via the Renderables/
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal | # |
Alan/Kevin: My plan is to have a sort of controller object insert touchspot renderables in the scene. This is just the interface that object implements towards the input stack.
Daniel: Of course this could be implemented at the level of say InputFilter, and pass the motion events on to the compositor. This requires every compositor implementor to implement some stateful tracking of the touchspots, which is a slight burden compared to the ease of an instaneous visualize-
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
I don't think the compositor would have to do any stateful tracking. MirMotionEvent already maintains the state as persistent pointer_coordinate indices (e.g. fingerpaint relies on this fact to choose colours). And regardless I don't see any of that as a requirement to instantaneously rendering little circles... unless you also wanted to add animations for gesture outcomes (like tap). I suspect that's excessive. All we want is instantaneous touch locations (empty/filled circles), which requires no state tracking.
OK, the structure conversion already exists, I know. So I guess in the absence of any expensive conversion then next priority should be to not increase complexity with too many new types. What if we typedef a struct for the existing MirMotionEvent.
void TouchVisualizer
Also, I feel that that interface is backwards. Perhaps we don't want a rendering interface to give to the input system. What if we reversed it and simply gave the compositor a "Touchscreen" interface from which it could get the list of touches? That somehow feels cleaner.
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
Hmm, I forgot you will need to force a redraw on every touch (even when no surfaces need redrawing). That's an interesting point to consider as we now have three future features all with the a similar requirement:
1. Software cursors
2. Desktop zoom
3. Touchspot visualization
All of these features have a requirement to force a redraw based on input events only (even when no surfaces have changed). So it would be nice to establish a common interface for triggering recomposition. One less bespoke than was proposed in lp:~vanvugt/mir/zoom ...
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:1732
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal | # |
>> Also, I feel that that interface is backwards. Perhaps we don't want a rendering interface to >> give to the input system. What if we reversed it and simply gave the compositor a
>> "Touchscreen" interface from which it could get the list of touches? That somehow feels cleaner.
I don't plan to implement this in the compositor. Rather a controller object will insert touchspot renderables in to the scene.
You seem to be proposing 'ask don't tell' ;)
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
I think it's potentially bad idea for minor stuff like touch spots to ever be part of the scene. You're committing yourself to the overhead of maintaining structures/objects for trivial textures. That's certainly sub-optimal in complexity and performance. I'd rather we didn't commit all future shells to performance limitations imposed by the Qt scene graph approach.
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal | # |
> Alan/Kevin: My plan is to have a sort of controller object insert touchspot
> renderables in the scene. This is just the interface that object implements
> towards the input stack.
ah, I mis-saw on the first pass. Well, my concerns are addressed, so +1 from me.
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal | # |
>> "Touchscreen" interface from which it could get the list of touches? That somehow feels
>> cleaner.
>> I'd rather we didn't commit all future shells to performance limitations imposed by the Qt
>> scene graph approach.
In this approach, the TouchspotVisualizer could be implemented by a controller object which manipulates the scene, or by a part of the compositor/renderer which implements direct mode rendering.
If we had this "Touchscreen" interface to query the list we would be set for direct mode but would need an additional notification interface and state tracker (reproducing information we already have) for retained mode.
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal | # |
>> I think it's potentially bad idea for minor stuff like touch spots to ever be part of the
>> scene.
>> You're committing yourself to the overhead of maintaining structures/objects for trivial
>> textures. That's certainly sub-optimal in complexity and performance.
So part of the in cursor and touchspot visualizations being a render-able is a performance based goal. A renderable representation makes it easy to allow hardware backends to render the input visualizations as overlays when appropriate (HWC, drm cursor API, or future DRM unified planes API), while still supporting a software fallback when required.
If we didn't have a retained representation of the input visualizations it seems like this could be really difficult.
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
Forgive me for not understanding anything that ends in "...Controller". That still doesn't fit my mental model of anything after all these years. :(
"If we had this "Touchscreen" interface to query the list we would be set for direct mode but would need an additional notification interface" ...
Yeah I realized that in my last comment on 2014-07-08. I guess it's not terrible for those three features to trigger redraws via different interfaces. But maybe not ideal either.
I might propose some changes that would aid in reducing the redundant structs concern I raised on 2014-07-07. I'll say "Needs fixing" based on that still. Also...
(2) The name "TouchVisualizer" feels sub-optimal even as a notification interface. The first reason is that it sounds like something independent of the compositor, but couldn't be if it's visualizing. On the other hand, if you generalized the name to not involve rendering at all (like "TouchObserver") then that's solved.
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
Update: On development-branch, pointer_coordinates is now defined as an array of MirMotionPointer. That new typedef might help avoid redundant new types here.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:1734
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:1735
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal | # |
>> I might propose some changes that would aid in reducing the redundant structs concern I raised on
>> 2014-07-07. I'll say "Needs fixing" based on that still. Also...
To me its more important to reduce the coupling between data structures than the number of types. There is a distinct concept here: one is a client input event (which is quite a few things...), the other is an instantaneous list of active touches in the global screen coordinate space.
Anyone else have thoughts?
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal | # |
>> The name "TouchVisualizer" feels sub-optimal even as a notification interface. The first reason is >> that it sounds like something independent of the compositor, but couldn't be if it's visualizing.
It's independent of the compositor in Qt Scenegraph and the cursor-
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
I still disagree with adding redundant types. That's unnecessary complexity; bad for maintenance. But it's probably not a blocking objection.
Looks like this needs another proper review from someone still.
Cemil Azizoglu (cemil-azizoglu) wrote : Posted in a previous version of this proposal | # |
Reviewed mostly for learning.
LGTM (but don't count this as a proper review)
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1736
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:1739
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1740
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1741
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Robert Carr (robertcarr) wrote : | # |
P.S. Only a resubmit because of adding dependency on sha1sum-script
Alan Griffiths (alan-griffiths) wrote : | # |
983 +#!/bin/sh
984 +find include/client include/
Looks like you've confused bzr (not hard) as this looks like the prerequisite.
Robert Carr (robertcarr) wrote : | # |
Hopefully bzr is less confused.
Alan Griffiths (alan-griffiths) wrote : | # |
> Hopefully bzr is less confused.
Yes.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1742
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) : | # |
Preview Diff
1 | === modified file 'include/server/mir/default_server_configuration.h' |
2 | --- include/server/mir/default_server_configuration.h 2014-07-22 11:22:48 +0000 |
3 | +++ include/server/mir/default_server_configuration.h 2014-08-04 16:03:26 +0000 |
4 | @@ -120,6 +120,7 @@ |
5 | class InputChannelFactory; |
6 | class InputConfiguration; |
7 | class CursorListener; |
8 | +class TouchVisualizer; |
9 | class InputRegion; |
10 | class InputSender; |
11 | class InputSendObserver; |
12 | @@ -285,6 +286,7 @@ |
13 | virtual std::shared_ptr<shell::InputTargeter> the_input_targeter(); |
14 | virtual std::shared_ptr<input::InputTargets> the_input_targets(); |
15 | virtual std::shared_ptr<input::CursorListener> the_cursor_listener(); |
16 | + virtual std::shared_ptr<input::TouchVisualizer> the_touch_visualizer(); |
17 | virtual std::shared_ptr<input::InputRegion> the_input_region(); |
18 | /** @} */ |
19 | |
20 | @@ -343,6 +345,7 @@ |
21 | CachedPtr<input::InputRegion> input_region; |
22 | CachedPtr<shell::InputTargeter> input_targeter; |
23 | CachedPtr<input::CursorListener> cursor_listener; |
24 | + CachedPtr<input::TouchVisualizer> touch_visualizer; |
25 | CachedPtr<graphics::Platform> graphics_platform; |
26 | CachedPtr<graphics::NativePlatform> graphics_native_platform; |
27 | CachedPtr<graphics::BufferInitializer> buffer_initializer; |
28 | |
29 | === modified file 'include/server/mir/input/android/default_android_input_configuration.h' |
30 | --- include/server/mir/input/android/default_android_input_configuration.h 2014-06-24 15:28:09 +0000 |
31 | +++ include/server/mir/input/android/default_android_input_configuration.h 2014-08-04 16:03:26 +0000 |
32 | @@ -40,6 +40,7 @@ |
33 | { |
34 | class InputRegion; |
35 | class CursorListener; |
36 | +class TouchVisualizer; |
37 | class InputReport; |
38 | class InputDispatcher; |
39 | |
40 | @@ -53,6 +54,7 @@ |
41 | DefaultInputConfiguration(std::shared_ptr<input::InputDispatcher> const& dispatcher, |
42 | std::shared_ptr<input::InputRegion> const& input_region, |
43 | std::shared_ptr<CursorListener> const& cursor_listener, |
44 | + std::shared_ptr<TouchVisualizer> const& touch_visualizer, |
45 | std::shared_ptr<input::InputReport> const& input_report); |
46 | virtual ~DefaultInputConfiguration(); |
47 | |
48 | @@ -78,6 +80,7 @@ |
49 | std::shared_ptr<input::InputDispatcher> const input_dispatcher; |
50 | std::shared_ptr<input::InputRegion> const input_region; |
51 | std::shared_ptr<CursorListener> const cursor_listener; |
52 | + std::shared_ptr<TouchVisualizer> const touch_visualizer; |
53 | std::shared_ptr<input::InputReport> const input_report; |
54 | }; |
55 | } |
56 | |
57 | === added file 'include/server/mir/input/touch_visualizer.h' |
58 | --- include/server/mir/input/touch_visualizer.h 1970-01-01 00:00:00 +0000 |
59 | +++ include/server/mir/input/touch_visualizer.h 2014-08-04 16:03:26 +0000 |
60 | @@ -0,0 +1,58 @@ |
61 | +/* |
62 | + * Copyright © 2014 Canonical Ltd. |
63 | + * |
64 | + * This program is free software: you can redistribute it and/or modify it |
65 | + * under the terms of the GNU General Public License version 3, |
66 | + * as published by the Free Software Foundation. |
67 | + * |
68 | + * This program is distributed in the hope that it will be useful, |
69 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
70 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
71 | + * GNU General Public License for more details. |
72 | + * |
73 | + * You should have received a copy of the GNU General Public License |
74 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
75 | + * |
76 | + * Authored by: Robert Carr <robert.carr@canonical.com> |
77 | + */ |
78 | + |
79 | +#ifndef MIR_INPUT_TOUCH_VISUALIZER_H_ |
80 | +#define MIR_INPUT_TOUCH_VISUALIZER_H_ |
81 | + |
82 | +#include "mir/geometry/point.h" |
83 | + |
84 | +#include <vector> |
85 | + |
86 | +namespace mir |
87 | +{ |
88 | +namespace input |
89 | +{ |
90 | + |
91 | +/// An interface for listening to a low level stream of touches, in order to provide |
92 | +// a "spot" style visualization. |
93 | +class TouchVisualizer |
94 | +{ |
95 | +public: |
96 | + virtual ~TouchVisualizer() = default; |
97 | + |
98 | + struct Spot |
99 | + { |
100 | + geometry::Point touch_location; |
101 | + |
102 | + // If pressure is non-zero, it indicates a press at the spot, as |
103 | + // opposed to a hover. |
104 | + float pressure; |
105 | + }; |
106 | + |
107 | + virtual void visualize_touches(std::vector<Spot> const& touches) = 0; |
108 | + |
109 | +protected: |
110 | + TouchVisualizer() = default; |
111 | + TouchVisualizer(const TouchVisualizer&) = delete; |
112 | + TouchVisualizer& operator=(const TouchVisualizer&) = delete; |
113 | +}; |
114 | + |
115 | +} |
116 | +} |
117 | + |
118 | +#endif // MIR_INPUT_TOUCH_VISUALIZER_H_ |
119 | |
120 | === modified file 'include/test/mir_test/event_factory.h' |
121 | --- include/test/mir_test/event_factory.h 2014-06-09 18:45:21 +0000 |
122 | +++ include/test/mir_test/event_factory.h 2014-08-04 16:03:26 +0000 |
123 | @@ -19,6 +19,8 @@ |
124 | #ifndef MIR_TEST_EVENT_FACTORY_H |
125 | #define MIR_TEST_EVENT_FACTORY_H |
126 | |
127 | +#include "mir/geometry/point.h" |
128 | + |
129 | namespace mir |
130 | { |
131 | namespace input |
132 | @@ -78,13 +80,22 @@ |
133 | class TouchParameters |
134 | { |
135 | public: |
136 | + enum class Action |
137 | + { |
138 | + Tap = 0, |
139 | + Move, |
140 | + Release |
141 | + }; |
142 | + |
143 | TouchParameters(); |
144 | TouchParameters& from_device(int device_id); |
145 | - TouchParameters& at_position(int abs_x, int abs_y); |
146 | + TouchParameters& at_position(geometry::Point abs_pos); |
147 | + TouchParameters& with_action(Action touch_action); |
148 | |
149 | int device_id; |
150 | int abs_x; |
151 | int abs_y; |
152 | + Action action; |
153 | }; |
154 | TouchParameters a_touch_event(); |
155 | |
156 | |
157 | === modified file 'include/test/mir_test/fake_event_hub_input_configuration.h' |
158 | --- include/test/mir_test/fake_event_hub_input_configuration.h 2014-06-02 17:07:02 +0000 |
159 | +++ include/test/mir_test/fake_event_hub_input_configuration.h 2014-08-04 16:03:26 +0000 |
160 | @@ -35,6 +35,7 @@ |
161 | namespace input |
162 | { |
163 | class CursorListener; |
164 | +class TouchVisualizer; |
165 | class EventFilter; |
166 | class InputReport; |
167 | |
168 | @@ -55,6 +56,7 @@ |
169 | std::shared_ptr<input::InputDispatcher> const& input_dispatcher, |
170 | std::shared_ptr<input::InputRegion> const& input_region, |
171 | std::shared_ptr<input::CursorListener> const& cursor_listener, |
172 | + std::shared_ptr<input::TouchVisualizer> const& touch_visualizer, |
173 | std::shared_ptr<input::InputReport> const& input_report); |
174 | |
175 | virtual ~FakeEventHubInputConfiguration(); |
176 | |
177 | === added file 'include/test/mir_test_doubles/stub_touch_visualizer.h' |
178 | --- include/test/mir_test_doubles/stub_touch_visualizer.h 1970-01-01 00:00:00 +0000 |
179 | +++ include/test/mir_test_doubles/stub_touch_visualizer.h 2014-08-04 16:03:26 +0000 |
180 | @@ -0,0 +1,43 @@ |
181 | +/* |
182 | + * Copyright © 2014 Canonical Ltd. |
183 | + * |
184 | + * This program is free software: you can redistribute it and/or modify it |
185 | + * under the terms of the GNU General Public License version 3, |
186 | + * as published by the Free Software Foundation. |
187 | + * |
188 | + * This program is distributed in the hope that it will be useful, |
189 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
190 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
191 | + * GNU General Public License for more details. |
192 | + * |
193 | + * You should have received a copy of the GNU General Public License |
194 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
195 | + * |
196 | + * Authored by: Robert Carr <robert.carr@canonical.com> |
197 | + */ |
198 | + |
199 | +#ifndef MIR_TEST_DOUBLES_STUB_TOUCH_VISUALIZER_H_ |
200 | +#define MIR_TEST_DOUBLES_STUB_TOUCH_VISUALIZER_H_ |
201 | + |
202 | +#include "mir/input/touch_visualizer.h" |
203 | + |
204 | +namespace mir |
205 | +{ |
206 | +namespace test |
207 | +{ |
208 | +namespace doubles |
209 | +{ |
210 | + |
211 | +struct StubTouchVisualizer : public input::TouchVisualizer |
212 | +{ |
213 | + void visualize_touches(std::vector<Spot> const&) override |
214 | + { |
215 | + } |
216 | +}; |
217 | + |
218 | +} |
219 | +} |
220 | +} // namespace mir |
221 | + |
222 | +#endif // MIR_TEST_DOUBLES_STUB_TOUCH_VISUALIZER_H_ |
223 | + |
224 | |
225 | === modified file 'include/test/mir_test_framework/input_testing_server_configuration.h' |
226 | --- include/test/mir_test_framework/input_testing_server_configuration.h 2014-06-23 18:07:24 +0000 |
227 | +++ include/test/mir_test_framework/input_testing_server_configuration.h 2014-08-04 16:03:26 +0000 |
228 | @@ -58,7 +58,7 @@ |
229 | InputTestingServerConfiguration(); |
230 | explicit InputTestingServerConfiguration(std::vector<geometry::Rectangle> const& display_rects); |
231 | |
232 | - void exec(); |
233 | + void on_start(); |
234 | void on_exit(); |
235 | |
236 | std::shared_ptr<mir::input::InputConfiguration> the_input_configuration() override; |
237 | |
238 | === modified file 'server-ABI-sha1sums' |
239 | --- server-ABI-sha1sums 2014-08-04 16:03:26 +0000 |
240 | +++ server-ABI-sha1sums 2014-08-04 16:03:26 +0000 |
241 | @@ -57,7 +57,7 @@ |
242 | 51391bd29f7499f8cbb89e4ba33acf2b72d93592 include/server/mir/compositor/renderer.h |
243 | 686a839fd0cd5fa469344dc49190ff9d578efc25 include/server/mir/compositor/scene_element.h |
244 | 4fcf34e424128b87ddc76733594e32e09ebbd486 include/server/mir/compositor/scene.h |
245 | -4aa04639e1fd20395aa33ab15c5ce21c60bb79e9 include/server/mir/default_server_configuration.h |
246 | +488dcb1e275e32b5dde03cdfdb1538d3694cb8fe include/server/mir/default_server_configuration.h |
247 | bbb15c910dbc8d7c9a4cc982890486b7e16197e4 include/server/mir/default_server_status_listener.h |
248 | 215f6cf88826381cd3ec37a6d2179a70093c0bc5 include/server/mir/display_changer.h |
249 | af1ff0714be973ac76d56006a2e5991f68cd1dec include/server/mir/display_server.h |
250 | @@ -86,7 +86,7 @@ |
251 | 5aa4c4db5468d9b9fe8e98a64444538aadd6e17b include/server/mir/frontend/template_protobuf_message_processor.h |
252 | ba79552edce545fafc9a4f401411c44d0cb3b2cf include/server/mir/graphics/gl_extensions_base.h |
253 | 2489a0e7922b6c7abe383726a30e17edbee51048 include/server/mir/graphics/surfaceless_egl_context.h |
254 | -2997940c93db57b1c4d51b1786ff65503de9d013 include/server/mir/input/android/default_android_input_configuration.h |
255 | +36ad5c3d722a5c8f252eb7538a5fb2bff46d2189 include/server/mir/input/android/default_android_input_configuration.h |
256 | f95c2bddf13d15993ef5d6a0ad7b9106ae550b87 include/server/mir/input/composite_event_filter.h |
257 | 67719acb03b35d383dfefd65e8dfb872c42bcc11 include/server/mir/input/cursor_images.h |
258 | c1e96c372d7856d59947f3145d273b1285b569bc include/server/mir/input/cursor_listener.h |
259 | @@ -103,6 +103,7 @@ |
260 | 51cda18e314f1e36177a7ebfab0d1dd12867cdf0 include/server/mir/input/input_send_observer.h |
261 | 59e757018c337db25df0c68556664eb7536e4321 include/server/mir/input/input_targets.h |
262 | 15119bf95b4512c8b91df7c20edf56a3c0734957 include/server/mir/input/surface.h |
263 | +d647ce6beffdc31a597769587bb3ab17ec679491 include/server/mir/input/touch_visualizer.h |
264 | 204089f848c4d63ade96f92a0b8cfc1c33f1ce63 include/server/mir/input/vt_filter.h |
265 | 5ba863e9bb4dc9802aa74a7864f576df25142c2d include/server/mir/logging/glog_logger.h |
266 | 964069b241f1e8211386bb8735ee0f752b666949 include/server/mir/main_loop.h |
267 | |
268 | === modified file 'src/server/input/android/android_input_reader_policy.cpp' |
269 | --- src/server/input/android/android_input_reader_policy.cpp 2014-06-09 18:45:21 +0000 |
270 | +++ src/server/input/android/android_input_reader_policy.cpp 2014-08-04 16:03:26 +0000 |
271 | @@ -26,9 +26,10 @@ |
272 | namespace mia = mir::input::android; |
273 | |
274 | mia::InputReaderPolicy::InputReaderPolicy(std::shared_ptr<mi::InputRegion> const& input_region, |
275 | - std::shared_ptr<CursorListener> const& cursor_listener) |
276 | + std::shared_ptr<CursorListener> const& cursor_listener, |
277 | + std::shared_ptr<TouchVisualizer> const& touch_visualizer) |
278 | : input_region(input_region), |
279 | - pointer_controller(new mia::PointerController(input_region, cursor_listener)) |
280 | + pointer_controller(new mia::PointerController(input_region, cursor_listener, touch_visualizer)) |
281 | { |
282 | } |
283 | |
284 | @@ -50,6 +51,10 @@ |
285 | default_display_orientation); |
286 | |
287 | out_config->pointerVelocityControlParameters.acceleration = 1.0; |
288 | + |
289 | + // This only enables passing through the touch coordinates from the InputReader to the TouchVisualizer |
290 | + // the touch visualizer still decides whether or not to render anything. |
291 | + out_config->showTouches = true; |
292 | } |
293 | |
294 | droidinput::sp<droidinput::PointerControllerInterface> mia::InputReaderPolicy::obtainPointerController(int32_t /*device_id*/) |
295 | |
296 | === modified file 'src/server/input/android/android_input_reader_policy.h' |
297 | --- src/server/input/android/android_input_reader_policy.h 2014-06-09 18:45:21 +0000 |
298 | +++ src/server/input/android/android_input_reader_policy.h 2014-08-04 16:03:26 +0000 |
299 | @@ -28,6 +28,8 @@ |
300 | { |
301 | class CursorListener; |
302 | class InputRegion; |
303 | +class TouchVisualizer; |
304 | + |
305 | namespace android |
306 | { |
307 | |
308 | @@ -35,7 +37,8 @@ |
309 | { |
310 | public: |
311 | explicit InputReaderPolicy(std::shared_ptr<InputRegion> const& input_region, |
312 | - std::shared_ptr<CursorListener> const& cursor_listener); |
313 | + std::shared_ptr<CursorListener> const& cursor_listener, |
314 | + std::shared_ptr<TouchVisualizer> const& touch_visualizer); |
315 | |
316 | virtual ~InputReaderPolicy() {} |
317 | |
318 | |
319 | === modified file 'src/server/input/android/android_pointer_controller.cpp' |
320 | --- src/server/input/android/android_pointer_controller.cpp 2013-08-28 03:41:48 +0000 |
321 | +++ src/server/input/android/android_pointer_controller.cpp 2014-08-04 16:03:26 +0000 |
322 | @@ -17,6 +17,7 @@ |
323 | */ |
324 | |
325 | #include "mir/input/input_region.h" |
326 | +#include "mir/input/touch_visualizer.h" |
327 | #include "mir/geometry/rectangle.h" |
328 | #include "mir/geometry/point.h" |
329 | |
330 | @@ -29,24 +30,15 @@ |
331 | namespace geom = mir::geometry; |
332 | |
333 | mia::PointerController::PointerController( |
334 | - std::shared_ptr<mi::InputRegion> const& input_region) |
335 | - : state(0), |
336 | - x(0.0), |
337 | - y(0.0), |
338 | - input_region(input_region), |
339 | - cursor_listener(std::shared_ptr<mi::CursorListener>()) |
340 | -{ |
341 | -} |
342 | - |
343 | -mia::PointerController::PointerController( |
344 | std::shared_ptr<mi::InputRegion> const& input_region, |
345 | - std::shared_ptr<mi::CursorListener> const& cursor_listener) |
346 | + std::shared_ptr<mi::CursorListener> const& cursor_listener, |
347 | + std::shared_ptr<mi::TouchVisualizer> const& touch_visualizer) |
348 | : state(0), |
349 | x(0.0), |
350 | y(0.0), |
351 | input_region(input_region), |
352 | - cursor_listener(cursor_listener) |
353 | - |
354 | + cursor_listener(cursor_listener), |
355 | + touch_visualizer(touch_visualizer) |
356 | { |
357 | } |
358 | |
359 | @@ -117,3 +109,25 @@ |
360 | *out_x = x; |
361 | *out_y = y; |
362 | } |
363 | + |
364 | +void mia::PointerController::setSpots(const droidinput::PointerCoords* spot_coords, uint32_t spot_count) |
365 | +{ |
366 | + std::vector<mi::TouchVisualizer::Spot> touches; |
367 | + for (uint32_t i = 0; i < spot_count; i++) |
368 | + { |
369 | + droidinput::PointerCoords const& coords = spot_coords[i]; |
370 | + |
371 | + auto x = coords.getX(); |
372 | + auto y = coords.getY(); |
373 | + auto pressure = coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE); |
374 | + |
375 | + touches.push_back({{x, y}, pressure}); |
376 | + } |
377 | + |
378 | + touch_visualizer->visualize_touches(touches); |
379 | +} |
380 | + |
381 | +void mia::PointerController::clearSpots() |
382 | +{ |
383 | + touch_visualizer->visualize_touches({}); |
384 | +} |
385 | |
386 | === modified file 'src/server/input/android/android_pointer_controller.h' |
387 | --- src/server/input/android/android_pointer_controller.h 2013-08-28 03:41:48 +0000 |
388 | +++ src/server/input/android/android_pointer_controller.h 2014-08-04 16:03:26 +0000 |
389 | @@ -30,22 +30,27 @@ |
390 | { |
391 | namespace input |
392 | { |
393 | +class TouchVisualizer; |
394 | class InputRegion; |
395 | + |
396 | namespace android |
397 | { |
398 | class PointerController : public DummyPointerController |
399 | { |
400 | public: |
401 | - explicit PointerController(std::shared_ptr<InputRegion> const& input_region); |
402 | explicit PointerController(std::shared_ptr<InputRegion> const& input_region, |
403 | - std::shared_ptr<CursorListener> const& cursor_listener); |
404 | - |
405 | - virtual bool getBounds(float* out_min_x, float* out_min_y, float* out_max_x, float* out_max_y) const; |
406 | - virtual void move(float delta_x, float delta_y); |
407 | - virtual void setButtonState(int32_t button_state); |
408 | - virtual int32_t getButtonState() const; |
409 | - virtual void setPosition(float x, float y); |
410 | - virtual void getPosition(float *out_x, float *out_y) const; |
411 | + std::shared_ptr<CursorListener> const& cursor_listener, |
412 | + std::shared_ptr<TouchVisualizer> const& touch_visualizer); |
413 | + |
414 | + bool getBounds(float* out_min_x, float* out_min_y, float* out_max_x, float* out_max_y) const; |
415 | + void move(float delta_x, float delta_y); |
416 | + void setButtonState(int32_t button_state); |
417 | + int32_t getButtonState() const; |
418 | + void setPosition(float x, float y); |
419 | + void getPosition(float *out_x, float *out_y) const; |
420 | + |
421 | + void setSpots(const droidinput::PointerCoords* spot_coords, uint32_t spot_count); |
422 | + void clearSpots(); |
423 | |
424 | private: |
425 | bool get_bounds_locked(float *out_min_x, float* out_min_y, float* out_max_x, float* out_max_y) const; |
426 | @@ -57,6 +62,7 @@ |
427 | |
428 | std::shared_ptr<InputRegion> const input_region; |
429 | std::shared_ptr<CursorListener> cursor_listener; |
430 | + std::shared_ptr<TouchVisualizer> const touch_visualizer; |
431 | }; |
432 | } |
433 | } |
434 | |
435 | === modified file 'src/server/input/android/default_android_input_configuration.cpp' |
436 | --- src/server/input/android/default_android_input_configuration.cpp 2014-06-24 15:28:09 +0000 |
437 | +++ src/server/input/android/default_android_input_configuration.cpp 2014-08-04 16:03:26 +0000 |
438 | @@ -52,10 +52,12 @@ |
439 | std::shared_ptr<mi::InputDispatcher> const& input_dispatcher, |
440 | std::shared_ptr<mi::InputRegion> const& input_region, |
441 | std::shared_ptr<CursorListener> const& cursor_listener, |
442 | + std::shared_ptr<TouchVisualizer> const& touch_visualizer, |
443 | std::shared_ptr<mi::InputReport> const& input_report) : |
444 | input_dispatcher(input_dispatcher), |
445 | input_region(input_region), |
446 | cursor_listener(cursor_listener), |
447 | + touch_visualizer(touch_visualizer), |
448 | input_report(input_report) |
449 | { |
450 | } |
451 | @@ -78,7 +80,7 @@ |
452 | return reader_policy( |
453 | [this]() |
454 | { |
455 | - return std::make_shared<mia::InputReaderPolicy>(input_region, cursor_listener); |
456 | + return std::make_shared<mia::InputReaderPolicy>(input_region, cursor_listener, touch_visualizer); |
457 | }); |
458 | } |
459 | |
460 | |
461 | === modified file 'src/server/input/default_configuration.cpp' |
462 | --- src/server/input/default_configuration.cpp 2014-07-09 10:48:47 +0000 |
463 | +++ src/server/input/default_configuration.cpp 2014-08-04 16:03:26 +0000 |
464 | @@ -38,6 +38,7 @@ |
465 | #include "null_input_channel_factory.h" |
466 | |
467 | #include "mir/input/android/default_android_input_configuration.h" |
468 | +#include "mir/input/touch_visualizer.h" |
469 | #include "mir/options/configuration.h" |
470 | #include "mir/options/option.h" |
471 | #include "mir/compositor/scene.h" |
472 | @@ -92,6 +93,7 @@ |
473 | the_input_dispatcher(), |
474 | the_input_region(), |
475 | the_cursor_listener(), |
476 | + the_touch_visualizer(), |
477 | the_input_report() |
478 | ); |
479 | } |
480 | @@ -238,6 +240,22 @@ |
481 | |
482 | } |
483 | |
484 | +std::shared_ptr<mi::TouchVisualizer> |
485 | +mir::DefaultServerConfiguration::the_touch_visualizer() |
486 | +{ |
487 | + struct NullTouchVisualizer : public mi::TouchVisualizer |
488 | + { |
489 | + void visualize_touches(std::vector<Spot> const& /* touches */) override |
490 | + { |
491 | + } |
492 | + }; |
493 | + return touch_visualizer( |
494 | + [this]() |
495 | + { |
496 | + return std::make_shared<NullTouchVisualizer>(); |
497 | + }); |
498 | +} |
499 | + |
500 | std::shared_ptr<mg::CursorImage> |
501 | mir::DefaultServerConfiguration::the_default_cursor_image() |
502 | { |
503 | |
504 | === modified file 'tests/acceptance-tests/CMakeLists.txt' |
505 | --- tests/acceptance-tests/CMakeLists.txt 2014-07-30 15:15:16 +0000 |
506 | +++ tests/acceptance-tests/CMakeLists.txt 2014-08-04 16:03:26 +0000 |
507 | @@ -38,6 +38,7 @@ |
508 | test_client_cursor_api.cpp |
509 | test_large_messages.cpp |
510 | test_client_surface_visibility.cpp |
511 | + test_touchspot_visualization.cpp |
512 | test_client_with_custom_display_config_deadlock.cpp |
513 | test_macros.cpp |
514 | test_stale_frames.cpp |
515 | |
516 | === modified file 'tests/acceptance-tests/test_client_input.cpp' |
517 | --- tests/acceptance-tests/test_client_input.cpp 2014-06-26 16:03:00 +0000 |
518 | +++ tests/acceptance-tests/test_client_input.cpp 2014-08-04 16:03:26 +0000 |
519 | @@ -536,8 +536,8 @@ |
520 | |
521 | server_configuration.produce_events = [&](mtf::InputTestingServerConfiguration& server) |
522 | { |
523 | - server.fake_event_hub->synthesize_event(mis::a_touch_event().at_position(abs_touch_x_1, abs_touch_y_1)); |
524 | - server.fake_event_hub->synthesize_event(mis::a_touch_event().at_position(abs_touch_x_2, abs_touch_y_2)); |
525 | + server.fake_event_hub->synthesize_event(mis::a_touch_event().at_position({abs_touch_x_1, abs_touch_y_1})); |
526 | + server.fake_event_hub->synthesize_event(mis::a_touch_event().at_position({abs_touch_x_2, abs_touch_y_2})); |
527 | }; |
528 | server_configuration.client_geometries[arbitrary_client_name] = ServerConfiguration::display_bounds; |
529 | start_server(); |
530 | |
531 | === modified file 'tests/acceptance-tests/test_server_shutdown.cpp' |
532 | --- tests/acceptance-tests/test_server_shutdown.cpp 2014-07-21 03:35:31 +0000 |
533 | +++ tests/acceptance-tests/test_server_shutdown.cpp 2014-08-04 16:03:26 +0000 |
534 | @@ -127,7 +127,8 @@ |
535 | std::make_shared<mtd::FakeEventHubInputConfiguration>( |
536 | the_input_dispatcher(), |
537 | the_input_region(), |
538 | - std::shared_ptr<mi::CursorListener>(), |
539 | + the_cursor_listener(), |
540 | + the_touch_visualizer(), |
541 | the_input_report()); |
542 | } |
543 | |
544 | |
545 | === added file 'tests/acceptance-tests/test_touchspot_visualization.cpp' |
546 | --- tests/acceptance-tests/test_touchspot_visualization.cpp 1970-01-01 00:00:00 +0000 |
547 | +++ tests/acceptance-tests/test_touchspot_visualization.cpp 2014-08-04 16:03:26 +0000 |
548 | @@ -0,0 +1,222 @@ |
549 | +/* |
550 | + * Copyright © 2014 Canonical Ltd. |
551 | + * |
552 | + * This program is free software: you can redistribute it and/or modify |
553 | + * it under the terms of the GNU General Public License version 3 as |
554 | + * published by the Free Software Foundation. |
555 | + * |
556 | + * This program is distributed in the hope that it will be useful, |
557 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
558 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
559 | + * GNU General Public License for more details. |
560 | + * |
561 | + * You should have received a copy of the GNU General Public License |
562 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
563 | + * |
564 | + * Authored by: Robert Carr <robert.carr@canonical.com> |
565 | + */ |
566 | + |
567 | +#include "mir/input/touch_visualizer.h" |
568 | + |
569 | +#include "mir_test/fake_event_hub.h" |
570 | +#include "mir_test/barrier.h" |
571 | +#include "mir_test/fake_shared.h" |
572 | + |
573 | +#include "mir_test_framework/deferred_in_process_server.h" |
574 | +#include "mir_test_framework/input_testing_server_configuration.h" |
575 | + |
576 | +#include <gtest/gtest.h> |
577 | +#include <gmock/gmock.h> |
578 | + |
579 | +#include <vector> |
580 | +#include <functional> |
581 | + |
582 | +namespace mi = mir::input; |
583 | +namespace mis = mi::synthesis; |
584 | +namespace mt = mir::test; |
585 | +namespace geom = mir::geometry; |
586 | +namespace mtf = mir_test_framework; |
587 | + |
588 | +namespace |
589 | +{ |
590 | + |
591 | +ACTION_P(UnblockBarrier, barrier) |
592 | +{ |
593 | + barrier->ready(); |
594 | +} |
595 | + |
596 | +MATCHER(NoSpots, "") |
597 | +{ |
598 | + if (arg.size() > 0) |
599 | + return false; |
600 | + return true; |
601 | +} |
602 | + |
603 | +static bool |
604 | +spots_have_position_and_pressure(std::vector<mi::TouchVisualizer::Spot> const& spots, |
605 | + std::vector<geom::Point> const& positions, float pressure) |
606 | +{ |
607 | + if (spots.size() != positions.size()) |
608 | + return false; |
609 | + auto spots_it = spots.begin(); |
610 | + auto positions_it = positions.begin(); |
611 | + |
612 | + while (spots_it != spots.end()) |
613 | + { |
614 | + auto const& spot = *spots_it; |
615 | + if (spot.touch_location != *positions_it) |
616 | + return false; |
617 | + if (spot.pressure != pressure) |
618 | + return false; |
619 | + spots_it++; |
620 | + positions_it++; |
621 | + } |
622 | + return true; |
623 | +} |
624 | + |
625 | +MATCHER_P(TouchedSpotsAt, positions, "") |
626 | +{ |
627 | + return spots_have_position_and_pressure(arg, positions, 1.0); |
628 | +} |
629 | + |
630 | +struct MockTouchVisualizer : public mi::TouchVisualizer |
631 | +{ |
632 | + MOCK_METHOD1(visualize_touches, void(std::vector<mi::TouchVisualizer::Spot> const&)); |
633 | +}; |
634 | + |
635 | +struct ServerConfiguration : mtf::InputTestingServerConfiguration |
636 | +{ |
637 | + mt::Barrier& test_complete; |
638 | + |
639 | + MockTouchVisualizer mock_visualizer; |
640 | + |
641 | + std::function<void(mtf::InputTestingServerConfiguration& server)> produce_events; |
642 | + std::function<void(MockTouchVisualizer& visualizer, mt::Barrier& test_complete)> expect_touchspots; |
643 | + |
644 | + static geom::Rectangle const display_bounds; |
645 | + |
646 | + ServerConfiguration(mt::Barrier& test_complete) |
647 | + : InputTestingServerConfiguration({display_bounds}), |
648 | + test_complete(test_complete) |
649 | + { |
650 | + } |
651 | + |
652 | + std::shared_ptr<mi::TouchVisualizer> the_touch_visualizer() override |
653 | + { |
654 | + return mt::fake_shared(mock_visualizer); |
655 | + } |
656 | + |
657 | + void inject_input() override |
658 | + { |
659 | + produce_events(*this); |
660 | + } |
661 | + |
662 | + void establish_expectations() |
663 | + { |
664 | + // We need to do this before we start the input stack to avoid races |
665 | + // with the initial spot clearing. |
666 | + expect_touchspots(mock_visualizer, test_complete); |
667 | + } |
668 | +}; |
669 | + |
670 | +geom::Rectangle const ServerConfiguration::display_bounds = {{0, 0}, {1600, 1600}}; |
671 | + |
672 | +struct TestTouchspotVisualizations : mtf::DeferredInProcessServer |
673 | +{ |
674 | + mt::Barrier test_complete_fence{2}; |
675 | + ServerConfiguration server_configuration{test_complete_fence}; |
676 | + |
677 | + mir::DefaultServerConfiguration& server_config() override { return server_configuration; } |
678 | + |
679 | + void start_server() |
680 | + { |
681 | + server_configuration.establish_expectations(); |
682 | + |
683 | + DeferredInProcessServer::start_server(); |
684 | + server_configuration.exec(); |
685 | + } |
686 | + |
687 | + void TearDown() |
688 | + { |
689 | + test_complete_fence.ready(); |
690 | + server_configuration.on_exit(); |
691 | + DeferredInProcessServer::TearDown(); |
692 | + } |
693 | +}; |
694 | + |
695 | +geom::Point transform_to_screen_space(geom::Point in_touchpad_space) |
696 | +{ |
697 | + auto minimum_touch = mi::android::FakeEventHub::TouchScreenMinAxisValue; |
698 | + auto maximum_touch = mi::android::FakeEventHub::TouchScreenMaxAxisValue; |
699 | + |
700 | + auto display_width = ServerConfiguration::display_bounds.size.width.as_uint32_t(); |
701 | + auto display_height = ServerConfiguration::display_bounds.size.height.as_uint32_t(); |
702 | + |
703 | + float scale_x = float(display_width) / (maximum_touch - minimum_touch + 1); |
704 | + float scale_y = float(display_height) / (maximum_touch - minimum_touch + 1); |
705 | + |
706 | + return {scale_x * in_touchpad_space.x.as_uint32_t(), scale_y * in_touchpad_space.y.as_uint32_t()}; |
707 | +} |
708 | + |
709 | +} |
710 | + |
711 | +using namespace ::testing; |
712 | + |
713 | +TEST_F(TestTouchspotVisualizations, touch_is_given_to_touchspot_visualizer) |
714 | +{ |
715 | + auto minimum_touch = mi::android::FakeEventHub::TouchScreenMinAxisValue; |
716 | + |
717 | + static geom::Point abs_touch = { minimum_touch, minimum_touch }; |
718 | + static std::vector<geom::Point> expected_spots = { transform_to_screen_space(abs_touch) }; |
719 | + |
720 | + server_configuration.produce_events = [&](mtf::InputTestingServerConfiguration& server) |
721 | + { |
722 | + server.fake_event_hub->synthesize_event(mis::a_touch_event().at_position(abs_touch)); |
723 | + server.fake_event_hub->synthesize_event(mis::a_touch_event().at_position(abs_touch) |
724 | + .with_action(mis::TouchParameters::Action::Release)); |
725 | + }; |
726 | + server_configuration.expect_touchspots = [&](MockTouchVisualizer &visualizer, mt::Barrier& test_complete) |
727 | + { |
728 | + InSequence seq; |
729 | + |
730 | + // First we will see the spots cleared, as this is the start of a new gesture. |
731 | + EXPECT_CALL(visualizer, visualize_touches(NoSpots())).Times(1); |
732 | + EXPECT_CALL(visualizer, visualize_touches(TouchedSpotsAt(expected_spots))); |
733 | + EXPECT_CALL(visualizer, visualize_touches(NoSpots())).Times(1). |
734 | + WillOnce(UnblockBarrier(&test_complete)); |
735 | + }; |
736 | + start_server(); |
737 | +} |
738 | + |
739 | +TEST_F(TestTouchspotVisualizations, touchspots_follow_gesture) |
740 | +{ |
741 | + auto minimum_touch = mi::android::FakeEventHub::TouchScreenMinAxisValue; |
742 | + auto maximum_touch = mi::android::FakeEventHub::TouchScreenMaxAxisValue; |
743 | + |
744 | + static geom::Point abs_touch = { minimum_touch, minimum_touch }; |
745 | + static geom::Point abs_touch_2 = { maximum_touch, maximum_touch }; |
746 | + static std::vector<geom::Point> expected_spots_1 = |
747 | + { transform_to_screen_space(abs_touch) }; |
748 | + static std::vector<geom::Point> expected_spots_2 = |
749 | + { transform_to_screen_space(abs_touch_2) }; |
750 | + |
751 | + server_configuration.produce_events = [&](mtf::InputTestingServerConfiguration& server) |
752 | + { |
753 | + server.fake_event_hub->synthesize_event(mis::a_touch_event().at_position(abs_touch)); |
754 | + server.fake_event_hub->synthesize_event(mis::a_touch_event().at_position(abs_touch_2) |
755 | + .with_action(mis::TouchParameters::Action::Move)); |
756 | + server.fake_event_hub->synthesize_event(mis::a_touch_event().at_position(abs_touch_2) |
757 | + .with_action(mis::TouchParameters::Action::Release)); |
758 | + }; |
759 | + server_configuration.expect_touchspots = [&](MockTouchVisualizer &visualizer, mt::Barrier& test_complete) |
760 | + { |
761 | + InSequence seq; |
762 | + |
763 | + EXPECT_CALL(visualizer, visualize_touches(NoSpots())).Times(1); |
764 | + EXPECT_CALL(visualizer, visualize_touches(TouchedSpotsAt(expected_spots_1))).Times(1); |
765 | + EXPECT_CALL(visualizer, visualize_touches(TouchedSpotsAt(expected_spots_2))).Times(1); |
766 | + EXPECT_CALL(visualizer, visualize_touches(NoSpots())). |
767 | + Times(1).WillOnce(UnblockBarrier(&test_complete)); |
768 | + }; |
769 | + start_server(); |
770 | +} |
771 | |
772 | === modified file 'tests/integration-tests/input/android/test_android_cursor_listener.cpp' |
773 | --- tests/integration-tests/input/android/test_android_cursor_listener.cpp 2014-06-03 11:04:15 +0000 |
774 | +++ tests/integration-tests/input/android/test_android_cursor_listener.cpp 2014-08-04 16:03:26 +0000 |
775 | @@ -36,6 +36,7 @@ |
776 | #include "mir_test/fake_event_hub_input_configuration.h" |
777 | #include "mir_test_doubles/mock_event_filter.h" |
778 | #include "mir_test_doubles/stub_input_enumerator.h" |
779 | +#include "mir_test_doubles/stub_touch_visualizer.h" |
780 | #include "mir_test/wait_condition.h" |
781 | #include "mir_test/event_factory.h" |
782 | |
783 | @@ -97,6 +98,7 @@ |
784 | mt::fake_shared(dispatcher), |
785 | mt::fake_shared(input_region), |
786 | mt::fake_shared(cursor_listener), |
787 | + mt::fake_shared(touch_visualizer), |
788 | null_report); |
789 | |
790 | fake_event_hub = configuration->the_fake_event_hub(); |
791 | @@ -117,6 +119,7 @@ |
792 | mia::FakeEventHub* fake_event_hub; |
793 | std::shared_ptr<mi::InputManager> input_manager; |
794 | MockCursorListener cursor_listener; |
795 | + mtd::StubTouchVisualizer touch_visualizer; |
796 | StubInputRegion input_region; |
797 | }; |
798 | |
799 | |
800 | === modified file 'tests/integration-tests/input/android/test_android_input_manager.cpp' |
801 | --- tests/integration-tests/input/android/test_android_input_manager.cpp 2014-06-03 11:04:15 +0000 |
802 | +++ tests/integration-tests/input/android/test_android_input_manager.cpp 2014-08-04 16:03:26 +0000 |
803 | @@ -41,6 +41,7 @@ |
804 | #include "mir_test_doubles/stub_input_targets.h" |
805 | #include "mir_test_doubles/stub_scene.h" |
806 | #include "mir_test_doubles/stub_input_enumerator.h" |
807 | +#include "mir_test_doubles/stub_touch_visualizer.h" |
808 | #include "mir_test/wait_condition.h" |
809 | #include "mir_test/event_factory.h" |
810 | #include "mir_test/event_matchers.h" |
811 | @@ -107,6 +108,7 @@ |
812 | mt::fake_shared(dispatcher), |
813 | mt::fake_shared(input_region), |
814 | null_cursor_listener, |
815 | + mt::fake_shared(touch_visualizer), |
816 | mr::null_input_report()); |
817 | |
818 | fake_event_hub = configuration->the_fake_event_hub(); |
819 | @@ -128,6 +130,7 @@ |
820 | mia::FakeEventHub* fake_event_hub; |
821 | std::shared_ptr<mi::InputManager> input_manager; |
822 | StubInputRegion input_region; |
823 | + mtd::StubTouchVisualizer touch_visualizer; |
824 | }; |
825 | |
826 | } |
827 | @@ -268,7 +271,8 @@ |
828 | { |
829 | input_registrar->set_dispatcher(android_dispatcher); |
830 | configuration = std::make_shared<mtd::FakeEventHubInputConfiguration>( |
831 | - mt::fake_shared(dispatcher), mt::fake_shared(input_region), null_cursor_listener, null_report); |
832 | + mt::fake_shared(dispatcher), mt::fake_shared(input_region), null_cursor_listener, |
833 | + std::make_shared<mtd::StubTouchVisualizer>(), null_report); |
834 | fake_event_hub = configuration->the_fake_event_hub(); |
835 | |
836 | input_manager = configuration->the_input_manager(); |
837 | |
838 | === modified file 'tests/mir_test_doubles/event_factory.cpp' |
839 | --- tests/mir_test_doubles/event_factory.cpp 2014-06-09 18:45:21 +0000 |
840 | +++ tests/mir_test_doubles/event_factory.cpp 2014-08-04 16:03:26 +0000 |
841 | @@ -18,6 +18,7 @@ |
842 | #include "mir_test/event_factory.h" |
843 | |
844 | namespace mis = mir::input::synthesis; |
845 | +namespace geom = mir::geometry; |
846 | |
847 | mis::KeyParameters::KeyParameters() : |
848 | device_id(0), |
849 | @@ -117,7 +118,8 @@ |
850 | mis::TouchParameters::TouchParameters() : |
851 | device_id(0), |
852 | abs_x(0), |
853 | - abs_y(0) |
854 | + abs_y(0), |
855 | + action(Action::Tap) |
856 | { |
857 | } |
858 | |
859 | @@ -127,10 +129,16 @@ |
860 | return *this; |
861 | } |
862 | |
863 | -mis::TouchParameters& mis::TouchParameters::at_position(int new_abs_x, int new_abs_y) |
864 | -{ |
865 | - abs_x = new_abs_x; |
866 | - abs_y = new_abs_y; |
867 | +mis::TouchParameters& mis::TouchParameters::at_position(geom::Point abs_pos) |
868 | +{ |
869 | + abs_x = abs_pos.x.as_int(); |
870 | + abs_y = abs_pos.y.as_int(); |
871 | + return *this; |
872 | +} |
873 | + |
874 | +mis::TouchParameters& mis::TouchParameters::with_action(Action touch_action) |
875 | +{ |
876 | + action = touch_action; |
877 | return *this; |
878 | } |
879 | |
880 | |
881 | === modified file 'tests/mir_test_doubles/fake_event_hub.cpp' |
882 | --- tests/mir_test_doubles/fake_event_hub.cpp 2014-06-09 18:45:21 +0000 |
883 | +++ tests/mir_test_doubles/fake_event_hub.cpp 2014-08-04 16:03:26 +0000 |
884 | @@ -571,11 +571,14 @@ |
885 | event.code = ABS_Y; |
886 | event.value = parameters.abs_y; |
887 | events_available.push_back(event); |
888 | - |
889 | - event.type = EV_KEY; |
890 | - event.code = BTN_TOUCH; |
891 | - event.value = 1; |
892 | - events_available.push_back(event); |
893 | + |
894 | + if (parameters.action != mis::TouchParameters::Action::Move) |
895 | + { |
896 | + event.type = EV_KEY; |
897 | + event.code = BTN_TOUCH; |
898 | + event.value = (parameters.action == mis::TouchParameters::Action::Tap); |
899 | + events_available.push_back(event); |
900 | + } |
901 | |
902 | // Cursor motion events require a sync as per droidinput::CursorInputMapper::process |
903 | event.type = EV_SYN; |
904 | |
905 | === modified file 'tests/mir_test_doubles/fake_event_hub_input_configuration.cpp' |
906 | --- tests/mir_test_doubles/fake_event_hub_input_configuration.cpp 2014-06-02 17:07:02 +0000 |
907 | +++ tests/mir_test_doubles/fake_event_hub_input_configuration.cpp 2014-08-04 16:03:26 +0000 |
908 | @@ -28,8 +28,9 @@ |
909 | std::shared_ptr<mir::input::InputDispatcher> const& dispatcher, |
910 | std::shared_ptr<input::InputRegion> const& input_region, |
911 | std::shared_ptr<input::CursorListener> const& cursor_listener, |
912 | + std::shared_ptr<input::TouchVisualizer> const& touch_visualizer, |
913 | std::shared_ptr<mi::InputReport> const& input_report) : |
914 | - DefaultInputConfiguration(dispatcher, input_region, cursor_listener, input_report), |
915 | + DefaultInputConfiguration(dispatcher, input_region, cursor_listener, touch_visualizer, input_report), |
916 | event_hub(std::make_shared<mia::FakeEventHub>()) |
917 | { |
918 | } |
919 | |
920 | === modified file 'tests/mir_test_framework/input_testing_server_options.cpp' |
921 | --- tests/mir_test_framework/input_testing_server_options.cpp 2014-06-23 22:25:17 +0000 |
922 | +++ tests/mir_test_framework/input_testing_server_options.cpp 2014-08-04 16:03:26 +0000 |
923 | @@ -53,7 +53,7 @@ |
924 | { |
925 | } |
926 | |
927 | -void mtf::InputTestingServerConfiguration::exec() |
928 | +void mtf::InputTestingServerConfiguration::on_start() |
929 | { |
930 | input_injection_thread = std::thread(std::mem_fn(&mtf::InputTestingServerConfiguration::inject_input), this); |
931 | } |
932 | @@ -86,6 +86,7 @@ |
933 | the_input_dispatcher(), |
934 | the_input_region(), |
935 | the_cursor_listener(), |
936 | + the_touch_visualizer(), |
937 | the_input_report()); |
938 | fake_event_hub = input_configuration->the_fake_event_hub(); |
939 | |
940 | |
941 | === modified file 'tests/unit-tests/input/android/test_android_input_reader_policy.cpp' |
942 | --- tests/unit-tests/input/android/test_android_input_reader_policy.cpp 2013-08-28 03:41:48 +0000 |
943 | +++ tests/unit-tests/input/android/test_android_input_reader_policy.cpp 2014-08-04 16:03:26 +0000 |
944 | @@ -17,6 +17,7 @@ |
945 | */ |
946 | |
947 | #include "mir_test_doubles/mock_input_region.h" |
948 | +#include "mir_test_doubles/stub_touch_visualizer.h" |
949 | #include "mir_test/fake_shared.h" |
950 | |
951 | #include "src/server/input/android/android_input_reader_policy.h" |
952 | @@ -45,7 +46,8 @@ |
953 | { |
954 | reader_policy = std::make_shared<mia::InputReaderPolicy>( |
955 | mt::fake_shared(input_region), |
956 | - std::shared_ptr<mi::CursorListener>()); |
957 | + std::shared_ptr<mi::CursorListener>(), |
958 | + std::make_shared<mtd::StubTouchVisualizer>()); |
959 | |
960 | ON_CALL(input_region, bounding_rectangle()).WillByDefault(Return(default_view_area)); |
961 | } |
962 | |
963 | === modified file 'tests/unit-tests/input/android/test_android_pointer_controller.cpp' |
964 | --- tests/unit-tests/input/android/test_android_pointer_controller.cpp 2013-08-28 03:41:48 +0000 |
965 | +++ tests/unit-tests/input/android/test_android_pointer_controller.cpp 2014-08-04 16:03:26 +0000 |
966 | @@ -19,6 +19,7 @@ |
967 | #include "src/server/input/android/android_pointer_controller.h" |
968 | |
969 | #include "mir_test_doubles/mock_input_region.h" |
970 | +#include "mir_test_doubles/stub_touch_visualizer.h" |
971 | #include "mir_test/event_factory.h" |
972 | #include "mir_test/fake_shared.h" |
973 | |
974 | @@ -45,7 +46,8 @@ |
975 | public: |
976 | void SetUp() |
977 | { |
978 | - controller = std::make_shared<mia::PointerController>(mt::fake_shared(input_region)); |
979 | + controller = std::make_shared<mia::PointerController>(mt::fake_shared(input_region), std::shared_ptr<mi::CursorListener>(), |
980 | + std::make_shared<mtd::StubTouchVisualizer>()); |
981 | } |
982 | protected: |
983 | mtd::MockInputRegion input_region; |
FAILED: Continuous integration, rev:1726 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- ci/2013/ jenkins. qa.ubuntu. com/job/ mir-android- utopic- i386-build/ 721 jenkins. qa.ubuntu. com/job/ mir-clang- utopic- amd64-build/ 727/console jenkins. qa.ubuntu. com/job/ mir-mediumtests -utopic- touch/721 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- utopic- amd64-ci/ 534 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- utopic- amd64-ci/ 534/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- utopic- armhf-ci/ 532 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- utopic- armhf-ci/ 532/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/2161 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/2161/ artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ mir-mediumtests -runner- mako/1886 s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 8908
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/mir- team-mir- development- branch- ci/2013/ rebuild
http://