Mir

Merge lp:~mir-team/mir/touchspot-visualizer into lp:mir

Proposed by Robert Carr
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
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-is-a-renderable support for non-client-surface-renderables-thingies.

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.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

The change in InputTestingServerConfiguration to call inject_input in on_start rather than exec is to solve an intermittent failure.

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 TestingServerStatusListener. So we wait to inject input until the server is really started.

Revision history for this message
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 DefaultDisplayBufferCompositor or the Scene/SurfaceStack own the TouchVisualizer object?

Oh, and also are we intending USC or unity8 to paint the touch-spots?

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
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).

Revision history for this message
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.

review: Disapprove
Revision history for this message
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/SceneElement system so that the compositor doesn't have to have a different concepts for the touchpoints/cursors/input events.

Revision history for this message
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-these-touches-at-this-point style API. In addition its not that we are translating these structures to Mir event...rather the raw touch tracking in InputReader is synthesized to create MirEvent...so if we are already doing this stateful tracking why not just expose it this way?

Revision history for this message
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.pointer_coordinates and pass that:

   void TouchVisualizer::visualize_touches(MirMotionPointerCoordinates const& p) const;

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.

review: Needs Fixing
Revision history for this message
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 ...

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
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' ;)

Revision history for this message
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.

Revision history for this message
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.

review: Approve
Revision history for this message
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.

Revision history for this message
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.

Revision history for this message
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.

review: Needs Fixing
Revision history for this message
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.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
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?

Revision history for this message
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-is-a-renderable scenario.

Revision history for this message
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.

review: Abstain
Revision history for this message
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)

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
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://code.launchpad.net/~mir-team/mir/touchspot-visualizer/+merge/228903/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-ci/2274/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-android-utopic-i386-build/1147
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-clang-utopic-amd64-build/1153
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-utopic-touch/1137
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-utopic-amd64-ci/796
        deb: http://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-utopic-amd64-ci/796/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-utopic-armhf-ci/797
        deb: http://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-utopic-armhf-ci/797/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-utopic-armhf/72
        deb: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-utopic-armhf/72/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-runner-mako/2261
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/10705

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/mir-team-mir-development-branch-ci/2274/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Robert Carr (robertcarr) wrote :

P.S. Only a resubmit because of adding dependency on sha1sum-script

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

983 +#!/bin/sh
984 +find include/client include/shared/mir_toolkit | egrep "\.h$" | xargs sha1sum

Looks like you've confused bzr (not hard) as this looks like the prerequisite.

review: Needs Fixing
Revision history for this message
Robert Carr (robertcarr) wrote :

Hopefully bzr is less confused.

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

> Hopefully bzr is less confused.

Yes.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

LGTM

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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;

Subscribers

People subscribed via source and target branches