Mir

Merge lp:~andreas-pokorny/mir/fix-1539009-proper-accumulation-of-batched-events into lp:mir

Proposed by Andreas Pokorny
Status: Merged
Approved by: Cemil Azizoglu
Approved revision: no longer in the source branch.
Merged at revision: 3330
Proposed branch: lp:~andreas-pokorny/mir/fix-1539009-proper-accumulation-of-batched-events
Merge into: lp:mir
Diff against target: 316 lines (+273/-2)
4 files modified
3rd_party/android-input/android/frameworks/base/include/androidfw/Input.h (+1/-0)
3rd_party/android-input/android/frameworks/base/services/input/Input.cpp (+19/-2)
tests/unit-tests/input/android/CMakeLists.txt (+1/-0)
tests/unit-tests/input/android/test_input_consumer.cpp (+252/-0)
To merge this branch: bzr merge lp:~andreas-pokorny/mir/fix-1539009-proper-accumulation-of-batched-events
Reviewer Review Type Date Requested Status
Cemil Azizoglu (community) Approve
Alan Griffiths Approve
Daniel van Vugt Approve
PS Jenkins bot (community) continuous-integration Approve
Mir CI Bot continuous-integration Approve
Review via email: mp+286697@code.launchpad.net

Commit message

Fix relative axis in motion events

scroll and relative movement are axis that have to be accumulated when notified in batches. InputConsumer batches those when the consume rate is a lower and somewhat delayed compared to the arrival of the events. The given change does not fix InputConsumer but adds code in MotionEvent to accumulate the relevant axis values as needed.

(LP: #1539009)

Description of the change

Not quite the MP I hoped this to be.. But at least we have a starting point of features the InputConsumer should support. The code is horribly convoluted..

So as soon as we know what InputConsumer is supposed to do we can start replacing it..

To post a comment you must log in.
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Coooool.

Is this a full or partial fix for bug 1539009 then?

review: Needs Information
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

I'm not sure this is working. MIR_CLIENT_INPUT_RECEIVER_REPORT=log should show dx mostly agreeing with the change in absolute x. But what I see is still a large discrepancy:

BEFORE:

[2016-02-22 18:20:29.458772] <DEBUG> input-receiver: Received event:pointer_event(when=160587554000 (6.085664ms ago), from=6, motion, button_state=0, x=98, y=280, dx=3, dy=0, vscroll=0, hscroll=0, modifiers=1)

[2016-02-22 18:20:29.475780] <DEBUG> input-receiver: Received event:pointer_event(when=160604556000 (6.092153ms ago), from=6, motion, button_state=0, x=118, y=278, dx=3, dy=0, vscroll=0, hscroll=0, modifiers=1)

[2016-02-22 18:20:29.492779] <DEBUG> input-receiver: Received event:pointer_event(when=160621554000 (6.093218ms ago), from=6, motion, button_state=0, x=136, y=277, dx=3, dy=0, vscroll=0, hscroll=0, modifiers=1)

[2016-02-22 18:20:29.509860] <DEBUG> input-receiver: Received event:pointer_event(when=160638553000 (6.173124ms ago), from=6, motion, button_state=0, x=148, y=276, dx=1, dy=-1, vscroll=0, hscroll=0, modifiers=1)

[2016-02-22 18:20:29.526800] <DEBUG> input-receiver: Received event:pointer_event(when=160654555000 (7.112560ms ago), from=6, motion, button_state=0, x=159, y=276, dx=2, dy=0, vscroll=0, hscroll=0, modifiers=1)

AFTER:

[2016-02-22 18:21:18.085902] <DEBUG> input-receiver: Received event:pointer_event(when=209214636000 (6.131677ms ago), from=6, motion, button_state=0, x=115, y=171, dx=4, dy=0, vscroll=0, hscroll=0, modifiers=1)

[2016-02-22 18:21:18.102987] <DEBUG> input-receiver: Received event:pointer_event(when=209231631000 (6.222729ms ago), from=6, motion, button_state=0, x=187, y=171, dx=4, dy=0, vscroll=0, hscroll=0, modifiers=1)

[2016-02-22 18:21:18.119989] <DEBUG> input-receiver: Received event:pointer_event(when=209248633000 (6.222841ms ago), from=6, motion, button_state=0, x=259, y=165, dx=4, dy=-2, vscroll=0, hscroll=0, modifiers=1)

[2016-02-22 18:21:18.136985] <DEBUG> input-receiver: Received event:pointer_event(when=209265631000 (6.220547ms ago), from=6, motion, button_state=0, x=315, y=161, dx=2, dy=0, vscroll=0, hscroll=0, modifiers=1)

[2016-02-22 18:21:18.153992] <DEBUG> input-receiver: Received event:pointer_event(when=209282580000 (6.273110ms ago), from=6, motion, button_state=0, x=340, y=155, dx=1, dy=0, vscroll=0, hscroll=0, modifiers=1)

[2016-02-22 18:21:18.170721] <DEBUG> input-receiver: Received event:pointer_event(when=209295634000 (9.946535ms ago), from=6, motion, button_state=0, x=345, y=152, dx=1, dy=-1, vscroll=0, hscroll=0, modifiers=1)

review: Needs Information
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

> Coooool.
>
> Is this a full or partial fix for bug 1539009 then?

uh it should solve the test case :).. I have to look how the trace is generated .. there are two paths to access axis I believe I only fixed one of them..

Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

> I'm not sure this is working. MIR_CLIENT_INPUT_RECEIVER_REPORT=log should show
> dx mostly agreeing with the change in absolute x. But what I see is still a
> large discrepancy:
>
> BEFORE:
>
> [2016-02-22 18:20:29.458772] <DEBUG> input-receiver: Received
> event:pointer_event(when=160587554000 (6.085664ms ago), from=6, motion,
> button_state=0, x=98, y=280, dx=3, dy=0, vscroll=0, hscroll=0, modifiers=1)
>
> [2016-02-22 18:20:29.475780] <DEBUG> input-receiver: Received
> event:pointer_event(when=160604556000 (6.092153ms ago), from=6, motion,
> button_state=0, x=118, y=278, dx=3, dy=0, vscroll=0, hscroll=0, modifiers=1)
>
> [2016-02-22 18:20:29.492779] <DEBUG> input-receiver: Received
> event:pointer_event(when=160621554000 (6.093218ms ago), from=6, motion,
> button_state=0, x=136, y=277, dx=3, dy=0, vscroll=0, hscroll=0, modifiers=1)
>
> [2016-02-22 18:20:29.509860] <DEBUG> input-receiver: Received
> event:pointer_event(when=160638553000 (6.173124ms ago), from=6, motion,
> button_state=0, x=148, y=276, dx=1, dy=-1, vscroll=0, hscroll=0, modifiers=1)
>
> [2016-02-22 18:20:29.526800] <DEBUG> input-receiver: Received
> event:pointer_event(when=160654555000 (7.112560ms ago), from=6, motion,
> button_state=0, x=159, y=276, dx=2, dy=0, vscroll=0, hscroll=0, modifiers=1)
>
>
> AFTER:
>
> [2016-02-22 18:21:18.085902] <DEBUG> input-receiver: Received
> event:pointer_event(when=209214636000 (6.131677ms ago), from=6, motion,
> button_state=0, x=115, y=171, dx=4, dy=0, vscroll=0, hscroll=0, modifiers=1)
>
> [2016-02-22 18:21:18.102987] <DEBUG> input-receiver: Received
> event:pointer_event(when=209231631000 (6.222729ms ago), from=6, motion,
> button_state=0, x=187, y=171, dx=4, dy=0, vscroll=0, hscroll=0, modifiers=1)
>
> [2016-02-22 18:21:18.119989] <DEBUG> input-receiver: Received
> event:pointer_event(when=209248633000 (6.222841ms ago), from=6, motion,
> button_state=0, x=259, y=165, dx=4, dy=-2, vscroll=0, hscroll=0, modifiers=1)
>
> [2016-02-22 18:21:18.136985] <DEBUG> input-receiver: Received
> event:pointer_event(when=209265631000 (6.220547ms ago), from=6, motion,
> button_state=0, x=315, y=161, dx=2, dy=0, vscroll=0, hscroll=0, modifiers=1)
>
> [2016-02-22 18:21:18.153992] <DEBUG> input-receiver: Received
> event:pointer_event(when=209282580000 (6.273110ms ago), from=6, motion,
> button_state=0, x=340, y=155, dx=1, dy=0, vscroll=0, hscroll=0, modifiers=1)
>
> [2016-02-22 18:21:18.170721] <DEBUG> input-receiver: Received
> event:pointer_event(when=209295634000 (9.946535ms ago), from=6, motion,
> button_state=0, x=345, y=152, dx=1, dy=-1, vscroll=0, hscroll=0, modifiers=1)

Yes should be fixed now..

Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

PASSED: Continuous integration, rev:3312
https://mir-jenkins.ubuntu.com/job/mir-ci/352/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/144
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/157
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/153
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/153
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/149
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/149/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/149
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/149/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/149
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/149/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/149
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/149/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/352/rebuild

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

PASSED: Continuous integration, rev:3312
http://jenkins.qa.ubuntu.com/job/mir-ci/6342/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-android-vivid-i386-build/5993
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-clang-vivid-amd64-build/4900
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-vivid-touch/5949
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-xenial-touch/466
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-xenial-amd64-ci/666
        deb: http://jenkins.qa.ubuntu.com/job/mir-xenial-amd64-ci/666/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-xenial-i386-ci/666
        deb: http://jenkins.qa.ubuntu.com/job/mir-xenial-i386-ci/666/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-vivid-armhf/5946
        deb: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-vivid-armhf/5946/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-runner-touch/8320
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27793
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-xenial-armhf/462
        deb: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-xenial-armhf/462/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-runner-xenial-touch/315
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27797

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/mir-ci/6342/rebuild

review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Approved: I have now verified the fix works, using manual test case:
https://bugs.launchpad.net/mir/+bug/1539009/comments/8

It also seems my previous concern might have been a mistake in the way I tested it yesterday.

review: Approve
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Without the fix:

[1456212286.328351] <DEBUG> input-receiver: Received event:pointer_event(when=17346454506000 (0.229968ms ago), from=6, enter, button_state=0, x=3, y=213, dx=9, dy=1, vscroll=0, hscroll=0, modifiers=1)

[1456212286.348252] <DEBUG> input-receiver: Received event:pointer_event(when=17346468512000 (6.119945ms ago), from=6, motion, button_state=0, x=128, y=221, dx=10, dy=0, vscroll=0, hscroll=0, modifiers=1)

[1456212286.365179] <DEBUG> input-receiver: Received event:pointer_event(when=17346485512000 (6.047213ms ago), from=6, motion, button_state=0, x=293, y=223, dx=11, dy=0, vscroll=0, hscroll=0, modifiers=1)

[1456212286.381260] <DEBUG> input-receiver: Received event:pointer_event(when=17346506476000 (1.171607ms ago), from=6, motion, button_state=0, x=501, y=212, dx=10, dy=-1, vscroll=0, hscroll=0, modifiers=1)

[1456212286.381314] <DEBUG> input-receiver: Received event:pointer_event(when=17346507451000 (0.251745ms ago), from=6, leave, button_state=0, x=512, y=212, dx=11, dy=0, vscroll=0, hscroll=0, modifiers=1)

--------
With the fix:

[2016-02-23 15:25:59.513071] <DEBUG> input-receiver: Received event:pointer_event(when=17419639254000 (0.202009ms ago), from=6, enter, button_state=0, x=0, y=182, dx=8, dy=0, vscroll=0, hscroll=0, modifiers=1)

[2016-02-23 15:25:59.534141] <DEBUG> input-receiver: Received event:pointer_event(when=17419655249000 (5.275370ms ago), from=6, motion, button_state=0, x=138, y=195, dx=146, dy=13, vscroll=0, hscroll=0, modifiers=1)

[2016-02-23 15:25:59.551953] <DEBUG> input-receiver: Received event:pointer_event(when=17419672219000 (6.118942ms ago), from=6, motion, button_state=0, x=302, y=206, dx=164, dy=11, vscroll=0, hscroll=0, modifiers=1)

[2016-02-23 15:25:59.568163] <DEBUG> input-receiver: Received event:pointer_event(when=17419689296000 (5.250705ms ago), from=6, motion, button_state=0, x=470, y=208, dx=168, dy=2, vscroll=0, hscroll=0, modifiers=1)

[2016-02-23 15:25:59.568234] <DEBUG> input-receiver: Received event:pointer_event(when=17419693301000 (1.327157ms ago), from=6, motion, button_state=0, x=508, y=206, dx=38, dy=-2, vscroll=0, hscroll=0, modifiers=1)

[2016-02-23 15:25:59.568261] <DEBUG> input-receiver: Received event:pointer_event(when=17419694296000 (0.360347ms ago), from=6, leave, button_state=0, x=518, y=206, dx=10, dy=0, vscroll=0, hscroll=0, modifiers=1)

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

Looks reasonable, and Daniel's tested the bug is fixed.

review: Approve
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

Looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '3rd_party/android-input/android/frameworks/base/include/androidfw/Input.h'
2--- 3rd_party/android-input/android/frameworks/base/include/androidfw/Input.h 2016-01-29 08:18:22 +0000
3+++ 3rd_party/android-input/android/frameworks/base/include/androidfw/Input.h 2016-02-22 14:07:25 +0000
4@@ -554,6 +554,7 @@
5 }
6
7 protected:
8+ float getAccumulatedAxisValue(int32_t axis, size_t pointerIndex) const;
9 int32_t mAction;
10 int32_t mFlags;
11 int32_t mEdgeFlags;
12
13=== modified file '3rd_party/android-input/android/frameworks/base/services/input/Input.cpp'
14--- 3rd_party/android-input/android/frameworks/base/services/input/Input.cpp 2016-01-29 08:18:22 +0000
15+++ 3rd_party/android-input/android/frameworks/base/services/input/Input.cpp 2016-02-22 14:07:25 +0000
16@@ -359,12 +359,29 @@
17 return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
18 }
19
20+float MotionEvent::getAccumulatedAxisValue(int32_t axis, size_t pointerIndex) const {
21+ float acc = 0;
22+ auto const pointerCount = getPointerCount();
23+ for (size_t i = 0, num_entries = getHistorySize() + 1; i != num_entries; ++i)
24+ acc += mSamplePointerCoords[i * pointerCount + pointerIndex].getAxisValue(axis);
25+ return acc;
26+}
27+
28 float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const {
29- return getRawPointerCoords(pointerIndex)->getAxisValue(axis);
30+ switch (axis)
31+ {
32+ case AMOTION_EVENT_AXIS_RX: // joystick rotation axis are abused as relative x and y
33+ case AMOTION_EVENT_AXIS_RY:
34+ case AMOTION_EVENT_AXIS_VSCROLL:
35+ case AMOTION_EVENT_AXIS_HSCROLL:
36+ return getAccumulatedAxisValue(axis, pointerIndex);
37+ default:
38+ return getRawPointerCoords(pointerIndex)->getAxisValue(axis);
39+ }
40 }
41
42 float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const {
43- float value = getRawPointerCoords(pointerIndex)->getAxisValue(axis);
44+ float value = getRawAxisValue(axis, pointerIndex);
45 switch (axis) {
46 case AMOTION_EVENT_AXIS_X:
47 return value + mXOffset;
48
49=== modified file 'tests/unit-tests/input/android/CMakeLists.txt'
50--- tests/unit-tests/input/android/CMakeLists.txt 2016-01-29 08:18:22 +0000
51+++ tests/unit-tests/input/android/CMakeLists.txt 2016-02-22 14:07:25 +0000
52@@ -3,6 +3,7 @@
53 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_input_channel_factory.cpp
54 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_communication_package.cpp
55 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_input_sender.cpp
56+ ${CMAKE_CURRENT_SOURCE_DIR}/test_input_consumer.cpp
57 )
58
59 set(
60
61=== added file 'tests/unit-tests/input/android/test_input_consumer.cpp'
62--- tests/unit-tests/input/android/test_input_consumer.cpp 1970-01-01 00:00:00 +0000
63+++ tests/unit-tests/input/android/test_input_consumer.cpp 2016-02-22 14:07:25 +0000
64@@ -0,0 +1,252 @@
65+/*
66+ * Copyright © 2016 Canonical Ltd.
67+ *
68+ * This program is free software: you can redistribute it and/or modify it
69+ * under the terms of the GNU General Public License version 3,
70+ * as published by the Free Software Foundation.
71+ *
72+ * This program is distributed in the hope that it will be useful,
73+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
74+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
75+ * GNU General Public License for more details.
76+ *
77+ * You should have received a copy of the GNU General Public License
78+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
79+ *
80+ * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
81+ */
82+
83+#include "androidfw/Input.h"
84+#include "androidfw/InputTransport.h"
85+#include "src/server/input/android/android_input_channel.h"
86+#include "mir/input/android/event_conversion_helpers.h"
87+#include "mir/input/android/android_input_lexicon.h"
88+#include "mir/geometry/displacement.h"
89+#include "mir/geometry/point.h"
90+
91+#include <gtest/gtest.h>
92+#include <chrono>
93+#include <vector>
94+#include <cstring>
95+
96+using namespace std::literals::chrono_literals;
97+namespace mia = mir::input::android;
98+namespace geom = mir::geometry;
99+
100+namespace
101+{
102+struct EventFactory : android::InputEventFactoryInterface
103+{
104+ android::KeyEvent key;
105+ android::MotionEvent motion;
106+ android::KeyEvent* createKeyEvent()
107+ {
108+ return &key;
109+ }
110+ android::MotionEvent* createMotionEvent()
111+ {
112+ return &motion;
113+ }
114+};
115+}
116+
117+struct InputConsumerTest : ::testing::Test
118+{
119+ MOCK_METHOD3(pointer_movement,void(geom::Point pos, geom::Displacement movement, geom::Displacement scroll));
120+ uint32_t seq{0};
121+ mir::cookie::Blob default_cookie;
122+ EventFactory events;
123+ std::chrono::milliseconds current_frame_time = 0ms;
124+ mia::AndroidInputChannel channel;
125+ geom::Displacement no_move{0,0};
126+ geom::Displacement no_scroll{0,0};
127+ geom::Point origin{0,0};
128+ droidinput::sp<droidinput::InputChannel> client_channel =
129+ new droidinput::InputChannel("test_client", channel.client_fd());
130+ droidinput::sp<droidinput::InputChannel> server_channel =
131+ new droidinput::InputChannel("test_server", channel.server_fd());
132+
133+ droidinput::InputPublisher publisher{server_channel};
134+ droidinput::InputConsumer consumer{client_channel};
135+
136+ InputConsumerTest()
137+ {
138+ std::memset(&default_cookie, 0, sizeof default_cookie);
139+ }
140+
141+ const MirInputDeviceId touchscreen_device = 2;
142+ const MirInputDeviceId mouse_device = 3;
143+ struct TouchEvent
144+ {
145+ int action; // only one action per event - android InputTransport restriction
146+ std::vector<geom::Point> positions;
147+ std::chrono::nanoseconds tp;
148+ };
149+ void send_touch_event(TouchEvent const& event)
150+ {
151+ std::vector<droidinput::PointerCoords> coords(event.positions.size());
152+ std::vector<droidinput::PointerProperties> properties(event.positions.size());
153+ std::memset(coords.data(), 0, sizeof coords[0] * coords.size());
154+ std::memset(properties.data(), 0, sizeof properties[0] * properties.size());
155+ auto const x_offset = 0.0f;
156+ auto const y_offset = 0.0f;
157+ auto const x_precision = 0;
158+ auto const y_precision = 0;
159+ auto const flags = 0;
160+ auto const edge_flags = 0;
161+ auto const button_state = 0;
162+ int contacts_in_event = 0;
163+ for (auto const& contact : event.positions)
164+ {
165+ coords[contacts_in_event].setAxisValue(AMOTION_EVENT_AXIS_X, contact.x.as_float());
166+ coords[contacts_in_event].setAxisValue(AMOTION_EVENT_AXIS_Y, contact.y.as_float());
167+ coords[contacts_in_event].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 5);
168+ coords[contacts_in_event].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 5);
169+ coords[contacts_in_event].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 5);
170+ coords[contacts_in_event].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 0.7);
171+ properties[contacts_in_event].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
172+ properties[contacts_in_event].id = contacts_in_event;
173+ }
174+
175+ publisher.publishMotionEvent(++seq, touchscreen_device, AINPUT_SOURCE_TOUCHSCREEN, event.action, flags,
176+ edge_flags, 0, button_state, x_offset, y_offset, x_precision, y_precision,
177+ default_cookie, event.tp, event.tp, contacts_in_event, properties.data(),
178+ coords.data());
179+ }
180+
181+ struct PointerEvent
182+ {
183+ MirPointerAction action;
184+ MirPointerButtons buttons;
185+ geom::Point position;
186+ geom::Displacement movement;
187+ geom::Displacement scroll;
188+ std::chrono::nanoseconds tp;
189+ };
190+ void send_pointer_event(PointerEvent const& event)
191+ {
192+ droidinput::PointerCoords pointer_coord;
193+ droidinput::PointerProperties pointer_properties;
194+ std::memset(&pointer_coord, 0, sizeof(pointer_coord));
195+ std::memset(&pointer_properties, 0, sizeof(pointer_properties));
196+
197+ pointer_coord.setAxisValue(AMOTION_EVENT_AXIS_X, event.position.x.as_float());
198+ pointer_coord.setAxisValue(AMOTION_EVENT_AXIS_Y, event.position.y.as_float());
199+ pointer_coord.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, event.scroll.dx.as_float());
200+ pointer_coord.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, event.scroll.dy.as_float());
201+ pointer_coord.setAxisValue(AMOTION_EVENT_AXIS_RX, event.movement.dx.as_float());
202+ pointer_coord.setAxisValue(AMOTION_EVENT_AXIS_RY, event.movement.dy.as_float());
203+ pointer_properties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE;
204+ pointer_properties.id = 0;
205+
206+ auto const x_offset = 0.0f;
207+ auto const y_offset = 0.0f;
208+ auto const x_precision = 0;
209+ auto const y_precision = 0;
210+ auto const flags = 0;
211+ auto const buttons = 0;
212+ auto const modifiers = 0;
213+ auto const edge_flags = 0;
214+ publisher.publishMotionEvent(++seq, mouse_device, AINPUT_SOURCE_MOUSE,
215+ mia::android_pointer_action_from_mir(event.action, event.buttons), flags,
216+ edge_flags, modifiers, buttons, x_offset, y_offset, x_precision, y_precision,
217+ default_cookie, event.tp, event.tp, 1, &pointer_properties, &pointer_coord);
218+ }
219+
220+ void handle_event(droidinput::InputEvent* event)
221+ {
222+ if (event->getType() == AINPUT_EVENT_TYPE_KEY)
223+ {
224+ }
225+ else
226+ {
227+
228+ if (mia::android_source_id_is_pointer_device(event->getSource()))
229+ {
230+ auto mev = static_cast<const droidinput::MotionEvent*>(event);
231+ pointer_movement(
232+ {mev->getX(0), mev->getY(0)},
233+ {mev->getRawAxisValue(AMOTION_EVENT_AXIS_RX, 0),
234+ mev->getRawAxisValue(AMOTION_EVENT_AXIS_RY, 0)},
235+ {mev->getRawAxisValue(AMOTION_EVENT_AXIS_HSCROLL, 0),
236+ mev->getRawAxisValue(AMOTION_EVENT_AXIS_VSCROLL, 0)}
237+ );
238+ }
239+ }
240+ }
241+ void receive_events()
242+ {
243+ const auto fake_update_rate = 1ms;
244+
245+ android::InputEvent *received_event = nullptr;
246+ uint32_t seq_id;
247+ do
248+ {
249+ auto result = consumer.consume(&events, true, current_frame_time, &seq_id, &received_event);
250+
251+ if (result == droidinput::OK)
252+ handle_event(received_event);
253+
254+ if (consumer.hasPendingBatch())
255+ current_frame_time += fake_update_rate;
256+ } while(consumer.hasPendingBatch() || consumer.hasDeferredEvent());
257+ }
258+
259+ void advance_frame_time_to(std::chrono::milliseconds time)
260+ {
261+ current_frame_time = time;
262+ }
263+
264+};
265+
266+TEST_F(InputConsumerTest, emits_single_move_event_on_old_pointer_messages)
267+{
268+ EXPECT_CALL(*this, pointer_movement(geom::Point{4,11}, geom::Displacement{2,1}, no_scroll));
269+
270+ send_pointer_event({mir_pointer_action_motion, 0, {2.0, 10.0}, {0.0, 0.0}, no_scroll, 0ns});
271+ send_pointer_event({mir_pointer_action_motion, 0, {3.0, 11.0}, {1.0, 1.0}, no_scroll, 1ms});
272+ send_pointer_event({mir_pointer_action_motion, 0, {4.0, 11.0}, {1.0, 0.0}, no_scroll, 2ms});
273+
274+ advance_frame_time_to(16ms);
275+ receive_events();
276+}
277+
278+TEST_F(InputConsumerTest, emits_move_events_on_recent_messages)
279+{
280+ EXPECT_CALL(*this, pointer_movement(geom::Point{10, 5}, geom::Displacement{0, 0}, no_scroll));
281+ EXPECT_CALL(*this, pointer_movement(geom::Point{15, 8}, geom::Displacement{5, 3}, no_scroll));
282+ EXPECT_CALL(*this, pointer_movement(geom::Point{12,10}, geom::Displacement{-3, 2}, no_scroll));
283+
284+ send_pointer_event({mir_pointer_action_motion, 0, {10.0, 5.0}, {0.0, 0.0}, no_scroll, 0ns});
285+ send_pointer_event({mir_pointer_action_motion, 0, {15.0, 8.0}, {5.0, 3.0}, no_scroll, 1ms});
286+ send_pointer_event({mir_pointer_action_motion, 0, {12.0, 10.0}, {-3.0,2.0}, no_scroll, 2ms});
287+
288+ advance_frame_time_to(2ms);
289+ receive_events();
290+}
291+
292+TEST_F(InputConsumerTest, emits_scroll_events_on_each_recent_scroll_messages)
293+{
294+ EXPECT_CALL(*this, pointer_movement(origin, no_move, geom::Displacement{3, 0}));
295+ EXPECT_CALL(*this, pointer_movement(origin, no_move, geom::Displacement{0, 5}));
296+ EXPECT_CALL(*this, pointer_movement(origin, no_move, geom::Displacement{2, 5}));
297+
298+ send_pointer_event({mir_pointer_action_motion, 0, origin, no_move, {3.0, 0.0}, 0ns});
299+ send_pointer_event({mir_pointer_action_motion, 0, origin, no_move, {0.0, 5.0}, 1ms});
300+ send_pointer_event({mir_pointer_action_motion, 0, origin, no_move, {2.0, 5.0}, 2ms});
301+
302+ advance_frame_time_to(2ms);
303+ receive_events();
304+}
305+
306+TEST_F(InputConsumerTest, emits_accumulated_scroll_event_on_old_messages)
307+{
308+ EXPECT_CALL(*this, pointer_movement(origin, no_move, geom::Displacement{5, 10}));
309+
310+ send_pointer_event({mir_pointer_action_motion, 0, origin, no_move, {3.0, 0.0}, 0ns});
311+ send_pointer_event({mir_pointer_action_motion, 0, origin, no_move, {0.0, 5.0}, 1ms});
312+ send_pointer_event({mir_pointer_action_motion, 0, origin, no_move, {2.0, 5.0}, 2ms});
313+
314+ advance_frame_time_to(16ms);
315+ receive_events();
316+}

Subscribers

People subscribed via source and target branches