Mir

Merge lp:~andreas-pokorny/mir/fix-1531517-0.18 into lp:mir/0.18

Proposed by Andreas Pokorny
Status: Merged
Merged at revision: 3186
Proposed branch: lp:~andreas-pokorny/mir/fix-1531517-0.18
Merge into: lp:mir/0.18
Diff against target: 424 lines (+329/-10)
5 files modified
CMakeLists.txt (+1/-1)
src/client/symbols.map (+7/-0)
src/server/input/android/input_sender.cpp (+152/-8)
src/server/input/android/input_sender.h (+4/-0)
tests/unit-tests/input/android/test_android_input_sender.cpp (+165/-1)
To merge this branch: bzr merge lp:~andreas-pokorny/mir/fix-1531517-0.18
Reviewer Review Type Date Requested Status
Kevin DuBois (community) Approve
Review via email: mp+282452@code.launchpad.net

This proposal supersedes a proposal from 2016-01-13.

Commit message

Never encode more than one action per event

Android InputTransport has only one action parameter per event. Within that the contact that caused the action is also encoded. So until we replace or extend the input transport protocol, we have to split up MirEvents, to not lose touch up/down changes.
Additionally in this version of the fix. also a recent lp:mir cleanup that affected the tool type encoding of pointer events.

Description of the change

Similar to the change in lp:mir - but this fix also pulls in some clenaups in pointer event sending.

To post a comment you must log in.
Revision history for this message
Kevin DuBois (kdub) wrote :

I'm guessing that we are going to release this? if so, we should bump MIR_VERSION_PATCH from 0 to 1.

review: Needs Fixing
Revision history for this message
Kevin DuBois (kdub) wrote :

l35: stray comment was added.

other than that, lgtm

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2015-12-03 16:20:03 +0000
3+++ CMakeLists.txt 2016-01-15 11:15:53 +0000
4@@ -28,7 +28,7 @@
5
6 set(MIR_VERSION_MAJOR 0)
7 set(MIR_VERSION_MINOR 18)
8-set(MIR_VERSION_PATCH 0)
9+set(MIR_VERSION_PATCH 1)
10
11 add_definitions(-DMIR_VERSION_MAJOR=${MIR_VERSION_MAJOR})
12 add_definitions(-DMIR_VERSION_MINOR=${MIR_VERSION_MINOR})
13
14=== modified file 'src/client/symbols.map'
15--- src/client/symbols.map 2015-12-07 12:35:30 +0000
16+++ src/client/symbols.map 2016-01-15 11:15:53 +0000
17@@ -253,3 +253,10 @@
18 };
19 } MIR_CLIENT_DETAIL_9;
20
21+MIR_CLIENT_DETAIL_9v18v1 {
22+ global:
23+ extern "C++" {
24+ mir::input::android::android_pointer_action_from_mir*;
25+ };
26+} MIR_CLIENT_DETAIL_9v18;
27+
28
29=== modified file 'src/server/input/android/input_sender.cpp'
30--- src/server/input/android/input_sender.cpp 2015-08-20 23:33:42 +0000
31+++ src/server/input/android/input_sender.cpp 2016-01-15 11:15:53 +0000
32@@ -180,16 +180,24 @@
33
34 droidinput::status_t error_status;
35
36- auto event_time = mir_input_event_get_event_time(mir_event_get_input_event(&event.event));
37- if (event.event.type == mir_event_type_key)
38+ auto input_event = mir_event_get_input_event(&event.event);
39+ auto event_time = mir_input_event_get_event_time(input_event);
40+ switch(mir_input_event_get_type(input_event))
41 {
42- error_status = send_key_event(event.sequence_id, event.event.key);
43+ case mir_input_event_type_key:
44+ error_status = send_key_event(event.sequence_id, event.event);
45 state.report->published_key_event(event.channel->server_fd(), event.sequence_id, event_time);
46- }
47- else
48- {
49- error_status = send_motion_event(event.sequence_id, event.event.motion);
50- state.report->published_motion_event(event.channel->server_fd(), event.sequence_id, event_time);
51+ break;
52+ case mir_input_event_type_pointer:
53+ error_status = send_pointer_event(event.sequence_id, event.event);
54+ state.report->published_motion_event(event.channel->server_fd(), event.sequence_id, event_time);
55+ break;
56+ case mir_input_event_type_touch:
57+ error_status = send_touch_event(event.sequence_id, event.event);
58+ state.report->published_motion_event(event.channel->server_fd(), event.sequence_id, event_time);
59+ break;
60+ default:
61+ BOOST_THROW_EXCEPTION(std::runtime_error("unknown input event type"));
62 }
63
64 if (error_status == droidinput::OK)
65@@ -213,6 +221,142 @@
66 }
67 }
68
69+droidinput::status_t mia::InputSender::ActiveTransfer::send_key_event(uint32_t seq, MirEvent const& event)
70+{
71+ int32_t repeat_count = 0;
72+ auto input_event = mir_event_get_input_event(&event);
73+ auto key_event = mir_input_event_get_keyboard_event(input_event);
74+ auto const android_action = mia::android_keyboard_action_from_mir(repeat_count, mir_keyboard_event_action(key_event));
75+ std::chrono::nanoseconds const event_time{mir_input_event_get_event_time(input_event)};
76+ auto const flags = 0;
77+ return publisher.publishKeyEvent(seq,
78+ mir_input_event_get_device_id(input_event),
79+ AINPUT_SOURCE_KEYBOARD,
80+ android_action,
81+ flags,
82+ mir_keyboard_event_key_code(key_event),
83+ mir_keyboard_event_scan_code(key_event),
84+ mia::android_modifiers_from_mir(mir_keyboard_event_modifiers(key_event)),
85+ repeat_count,
86+ event.key.mac,
87+ event_time,
88+ event_time);
89+}
90+
91+droidinput::status_t mia::InputSender::ActiveTransfer::send_touch_event(uint32_t seq, MirEvent const& event)
92+{
93+ droidinput::status_t ret = droidinput::OK;
94+ droidinput::PointerCoords coords[MIR_INPUT_EVENT_MAX_POINTER_COUNT];
95+ droidinput::PointerProperties properties[MIR_INPUT_EVENT_MAX_POINTER_COUNT];
96+ auto input_event = mir_event_get_input_event(&event);
97+ auto touch = mir_input_event_get_touch_event(input_event);
98+ std::chrono::nanoseconds const event_time{mir_input_event_get_event_time(input_event)};
99+ auto const x_offset = 0.0f;
100+ auto const y_offset = 0.0f;
101+ auto const x_precision = 0;
102+ auto const y_precision = 0;
103+ auto const flags = 0;
104+ auto const edge_flags = 0;
105+ auto const button_state = 0;
106+
107+ struct StateChange
108+ {
109+ int android_action;
110+ size_t index;
111+ };
112+
113+ std::vector<StateChange> state_changes;
114+ for (size_t i = 0, e = mir_touch_event_point_count(touch); i != e; ++i)
115+ {
116+ auto const action = mir_touch_event_action(touch, i);
117+ if (action == mir_touch_action_down)
118+ state_changes.push_back(StateChange{AMOTION_EVENT_ACTION_DOWN, i});
119+ if (action == mir_touch_action_up)
120+ state_changes.push_back(StateChange{AMOTION_EVENT_ACTION_UP, i});
121+ }
122+
123+ if (state_changes.empty())
124+ state_changes.push_back(StateChange{AMOTION_EVENT_ACTION_MOVE, 0});
125+
126+ for (auto state_change : state_changes)
127+ {
128+ std::memset(&coords, 0, sizeof(coords));
129+ std::memset(&properties, 0, sizeof(properties));
130+
131+ int contacts_in_event = 0;
132+ int action_index = 0;
133+ for (size_t i = 0, e = mir_touch_event_point_count(touch); i != e; ++i)
134+ {
135+ auto const action = mir_touch_event_action(touch, i);
136+
137+ if (i == state_change.index)
138+ action_index = contacts_in_event;
139+
140+ // before a touch up state change got processed it is treated as 'change', skipped otherwise
141+ // after a touch down state change got processed it is treated as 'change', skipped otherwise
142+ if (i == state_change.index
143+ || (i < state_change.index && action != mir_touch_action_up)
144+ || (i > state_change.index && action != mir_touch_action_down))
145+ {
146+ coords[contacts_in_event].setAxisValue(AMOTION_EVENT_AXIS_X, mir_touch_event_axis_value(touch, i, mir_touch_axis_x));
147+ coords[contacts_in_event].setAxisValue(AMOTION_EVENT_AXIS_Y, mir_touch_event_axis_value(touch, i, mir_touch_axis_y));
148+ coords[contacts_in_event].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, mir_touch_event_axis_value(touch, i, mir_touch_axis_touch_major));
149+ coords[contacts_in_event].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, mir_touch_event_axis_value(touch, i, mir_touch_axis_touch_minor));
150+ coords[contacts_in_event].setAxisValue(AMOTION_EVENT_AXIS_SIZE, mir_touch_event_axis_value(touch, i, mir_touch_axis_size));
151+ coords[contacts_in_event].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, mir_touch_event_axis_value(touch, i, mir_touch_axis_pressure));
152+ properties[contacts_in_event].toolType = mia::android_tool_type_from_mir(mir_touch_event_tooltype(touch, i));
153+ properties[contacts_in_event].id = mir_touch_event_id(touch, i);
154+ ++contacts_in_event;
155+ }
156+ }
157+
158+ state_change.android_action |= (action_index << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
159+
160+ ret = publisher.publishMotionEvent(seq, mir_input_event_get_device_id(input_event), AINPUT_SOURCE_TOUCHSCREEN,
161+ state_change.android_action, flags, edge_flags,
162+ mia::android_modifiers_from_mir(mir_touch_event_modifiers(touch)),
163+ button_state, x_offset, y_offset, x_precision, y_precision, event.motion.mac,
164+ event_time, event_time, contacts_in_event, properties, coords);
165+ }
166+
167+ return ret;
168+}
169+
170+droidinput::status_t mia::InputSender::ActiveTransfer::send_pointer_event(uint32_t seq, MirEvent const& event)
171+{
172+ droidinput::PointerCoords pointer_coord;
173+ droidinput::PointerProperties pointer_properties;
174+ std::memset(&pointer_coord, 0, sizeof(pointer_coord));
175+ std::memset(&pointer_properties, 0, sizeof(pointer_properties));
176+
177+ auto input_event = mir_event_get_input_event(&event);
178+ auto pointer = mir_input_event_get_pointer_event(input_event);
179+ pointer_coord.setAxisValue(AMOTION_EVENT_AXIS_X, mir_pointer_event_axis_value(pointer, mir_pointer_axis_x));
180+ pointer_coord.setAxisValue(AMOTION_EVENT_AXIS_Y, mir_pointer_event_axis_value(pointer, mir_pointer_axis_y));
181+ pointer_coord.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, mir_pointer_event_axis_value(pointer, mir_pointer_axis_hscroll));
182+ pointer_coord.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, mir_pointer_event_axis_value(pointer, mir_pointer_axis_vscroll));
183+ pointer_coord.setAxisValue(AMOTION_EVENT_AXIS_RX, mir_pointer_event_axis_value(pointer, mir_pointer_axis_relative_x));
184+ pointer_coord.setAxisValue(AMOTION_EVENT_AXIS_RY, mir_pointer_event_axis_value(pointer, mir_pointer_axis_relative_y));
185+ pointer_properties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE;
186+ pointer_properties.id = 0;
187+
188+ std::chrono::nanoseconds const event_time{mir_input_event_get_event_time(input_event)};
189+ auto const x_offset = 0.0f;
190+ auto const y_offset = 0.0f;
191+ auto const x_precision = 0;
192+ auto const y_precision = 0;
193+ auto const flags = 0;
194+ auto const edge_flags = 0;
195+ return publisher.publishMotionEvent(
196+ seq, mir_input_event_get_device_id(input_event), AINPUT_SOURCE_MOUSE,
197+ mia::android_pointer_action_from_mir(mir_pointer_event_action(pointer), mir_pointer_event_buttons(pointer)),
198+ flags, edge_flags, mia::android_modifiers_from_mir(mir_pointer_event_modifiers(pointer)),
199+ mia::android_pointer_buttons_from_mir(mir_pointer_event_buttons(pointer)), x_offset, y_offset, x_precision,
200+ y_precision, event.motion.mac, event_time, event_time, 1, &pointer_properties, &pointer_coord);
201+}
202+
203+
204+
205 mia::InputSender::ActiveTransfer::~ActiveTransfer()
206 {
207 unsubscribe();
208
209=== modified file 'src/server/input/android/input_sender.h'
210--- src/server/input/android/input_sender.h 2015-08-14 14:51:26 +0000
211+++ src/server/input/android/input_sender.h 2016-01-15 11:15:53 +0000
212@@ -97,6 +97,10 @@
213
214 private:
215 void on_finish_signal();
216+ droidinput::status_t send_key_event(uint32_t sequence_id, MirEvent const& event);
217+ droidinput::status_t send_touch_event(uint32_t sequence_id, MirEvent const& event);
218+ droidinput::status_t send_pointer_event(uint32_t sequence_id, MirEvent const& event);
219+
220 void on_response_timeout();
221 void update_timer();
222 void cancel_timer();
223
224=== modified file 'tests/unit-tests/input/android/test_android_input_sender.cpp'
225--- tests/unit-tests/input/android/test_android_input_sender.cpp 2015-08-13 21:44:58 +0000
226+++ tests/unit-tests/input/android/test_android_input_sender.cpp 2016-01-15 11:15:53 +0000
227@@ -22,6 +22,7 @@
228 #include "src/server/input/android/android_input_channel.h"
229 #include "src/server/input/android/input_sender.h"
230 #include "src/server/report/null_report_factory.h"
231+#include "src/server/input/default_event_builder.h"
232
233 #include "mir/test/doubles/stub_scene_surface.h"
234 #include "mir/test/doubles/mock_input_surface.h"
235@@ -36,6 +37,7 @@
236 #include "androidfw/InputTransport.h"
237
238 #include "mir/input/input_report.h"
239+#include "mir/cookie_factory.h"
240
241 #include <gtest/gtest.h>
242 #include <gmock/gmock.h>
243@@ -92,6 +94,14 @@
244 std::shared_ptr<ms::Observer> observer;
245 };
246
247+class StubCookieFactory : public mir::cookie::CookieFactory
248+{
249+public:
250+ MirCookie timestamp_to_cookie(uint64_t const&) override { return {0, 0};}
251+ bool attest_timestamp(MirCookie const&) override {return true;}
252+ StubCookieFactory() = default;
253+};
254+
255 }
256
257 class AndroidInputSender : public ::testing::Test
258@@ -101,7 +111,14 @@
259 size_t const test_pointer_count = 2;
260 float test_x_coord[2] = {12, 23};
261 float test_y_coord[2] = {17, 9};
262-
263+ MirTouchTooltype const tool = mir_touch_tooltype_finger;
264+ float const pressure = 0.6f;
265+ float const major = 8;
266+ float const minor = 4;
267+ float const size = 8;
268+ StubCookieFactory cookie_factory;
269+ mi::DefaultEventBuilder builder{MirInputDeviceId(), mt::fake_shared(cookie_factory)};
270+
271 AndroidInputSender()
272 : key_event(mev::make_event(MirInputDeviceId(), std::chrono::nanoseconds(1), 0, mir_keyboard_action_down,
273 7, test_scan_code, mir_input_event_modifier_none)),
274@@ -394,3 +411,150 @@
275 ::close(channel->client_fd());
276 sender.send_event(*key_event, channel);
277 }
278+
279+TEST_F(AndroidInputSender, encodes_multiple_touch_contact_downs_as_multiple_events)
280+{
281+ // TODO When the rework of the transport encoding is finished we might want to revisit this decision
282+ register_surface();
283+
284+ auto touch_ev_with_simultaneous_down = builder.touch_event(std::chrono::nanoseconds(86));
285+ builder.add_touch(*touch_ev_with_simultaneous_down, 2, mir_touch_action_down, tool, 50, 60, pressure, major, minor, size);
286+ builder.add_touch(*touch_ev_with_simultaneous_down, 4, mir_touch_action_down, tool, 80, 90, pressure, major, minor, size);
287+
288+ sender.send_event(*touch_ev_with_simultaneous_down, channel);
289+
290+ EXPECT_EQ(droidinput::OK, consumer.consume(&event_factory, true, std::chrono::nanoseconds(86), &seq, &event));
291+ EXPECT_EQ(&client_motion_event, event);
292+ EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, client_motion_event.getActionMasked());
293+ EXPECT_EQ(0, client_motion_event.getActionIndex());
294+ EXPECT_EQ(2, client_motion_event.getPointerId(0));
295+ EXPECT_EQ(1, client_motion_event.getPointerCount());
296+
297+ EXPECT_EQ(droidinput::OK, consumer.consume(&event_factory, true, std::chrono::nanoseconds(86), &seq, &event));
298+ EXPECT_EQ(&client_motion_event, event);
299+ EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, client_motion_event.getActionMasked());
300+ EXPECT_EQ(1, client_motion_event.getActionIndex());
301+ EXPECT_EQ(2, client_motion_event.getPointerId(0));
302+ EXPECT_EQ(4, client_motion_event.getPointerId(1));
303+ EXPECT_EQ(2, client_motion_event.getPointerCount());
304+}
305+
306+TEST_F(AndroidInputSender, encodes_multiple_touch_contact_downs_as_multiple_events_but_keeps_only_moved_contacts_in_place)
307+{
308+ // TODO When the rework of the transport encoding is finished we might want to revisit this decision
309+ register_surface();
310+
311+ auto touch_ev_with_simultaneous_down = builder.touch_event(std::chrono::nanoseconds(86));
312+ builder.add_touch(*touch_ev_with_simultaneous_down, 2, mir_touch_action_down, tool, 50, 60, pressure, major, minor, size);
313+ builder.add_touch(*touch_ev_with_simultaneous_down, 3, mir_touch_action_change, tool, 10, 10, pressure, major, minor, size);
314+ builder.add_touch(*touch_ev_with_simultaneous_down, 4, mir_touch_action_down, tool, 80, 90, pressure, major, minor, size);
315+
316+ sender.send_event(*touch_ev_with_simultaneous_down, channel);
317+
318+ EXPECT_EQ(droidinput::OK, consumer.consume(&event_factory, true, std::chrono::nanoseconds(86), &seq, &event));
319+ EXPECT_EQ(&client_motion_event, event);
320+ EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, client_motion_event.getActionMasked());
321+ EXPECT_EQ(0, client_motion_event.getActionIndex());
322+ EXPECT_EQ(2, client_motion_event.getPointerId(0));
323+ EXPECT_EQ(3, client_motion_event.getPointerId(1));
324+ EXPECT_EQ(2, client_motion_event.getPointerCount());
325+
326+ EXPECT_EQ(droidinput::OK, consumer.consume(&event_factory, true, std::chrono::nanoseconds(86), &seq, &event));
327+ EXPECT_EQ(&client_motion_event, event);
328+ EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, client_motion_event.getActionMasked());
329+ EXPECT_EQ(2, client_motion_event.getActionIndex());
330+ EXPECT_EQ(2, client_motion_event.getPointerId(0));
331+ EXPECT_EQ(3, client_motion_event.getPointerId(1));
332+ EXPECT_EQ(4, client_motion_event.getPointerId(2));
333+ EXPECT_EQ(3, client_motion_event.getPointerCount());
334+}
335+
336+TEST_F(AndroidInputSender, encodes_multiple_releases_in_several_events)
337+{
338+ // TODO When the rework of the transport encoding is finished we might want to revisit this decision
339+ register_surface();
340+
341+ auto touch_ev_with_simultaneous_down = builder.touch_event(std::chrono::nanoseconds(86));
342+ builder.add_touch(*touch_ev_with_simultaneous_down, 2, mir_touch_action_up, tool, 50, 60, pressure, major, minor, size);
343+ builder.add_touch(*touch_ev_with_simultaneous_down, 3, mir_touch_action_change, tool, 10, 10, pressure, major, minor, size);
344+ builder.add_touch(*touch_ev_with_simultaneous_down, 4, mir_touch_action_up, tool, 80, 90, pressure, major, minor, size);
345+
346+ sender.send_event(*touch_ev_with_simultaneous_down, channel);
347+
348+ EXPECT_EQ(droidinput::OK, consumer.consume(&event_factory, true, std::chrono::nanoseconds(86), &seq, &event));
349+ EXPECT_EQ(&client_motion_event, event);
350+ EXPECT_EQ(AMOTION_EVENT_ACTION_UP, client_motion_event.getActionMasked());
351+ EXPECT_EQ(0, client_motion_event.getActionIndex());
352+ EXPECT_EQ(2, client_motion_event.getPointerId(0));
353+ EXPECT_EQ(3, client_motion_event.getPointerId(1));
354+ EXPECT_EQ(4, client_motion_event.getPointerId(2));
355+ EXPECT_EQ(3, client_motion_event.getPointerCount());
356+
357+ EXPECT_EQ(droidinput::OK, consumer.consume(&event_factory, true, std::chrono::nanoseconds(86), &seq, &event));
358+ EXPECT_EQ(&client_motion_event, event);
359+ EXPECT_EQ(AMOTION_EVENT_ACTION_UP, client_motion_event.getActionMasked());
360+ EXPECT_EQ(1, client_motion_event.getActionIndex());
361+ EXPECT_EQ(3, client_motion_event.getPointerId(0));
362+ EXPECT_EQ(4, client_motion_event.getPointerId(1));
363+ EXPECT_EQ(2, client_motion_event.getPointerCount());
364+}
365+
366+TEST_F(AndroidInputSender, encodes_combinations_of_up_and_down_one_by_one)
367+{
368+ // TODO When the rework of the transport encoding is finished we might want to revisit this decision
369+ register_surface();
370+
371+ auto touch_ev_with_simultaneous_down = builder.touch_event(std::chrono::nanoseconds(86));
372+ builder.add_touch(*touch_ev_with_simultaneous_down, 2, mir_touch_action_up, tool, 50, 60, pressure, major, minor, size);
373+ builder.add_touch(*touch_ev_with_simultaneous_down, 3, mir_touch_action_change, tool, 10, 10, pressure, major, minor, size);
374+ builder.add_touch(*touch_ev_with_simultaneous_down, 4, mir_touch_action_down, tool, 80, 90, pressure, major, minor, size);
375+
376+ sender.send_event(*touch_ev_with_simultaneous_down, channel);
377+
378+ EXPECT_EQ(droidinput::OK, consumer.consume(&event_factory, true, std::chrono::nanoseconds(86), &seq, &event));
379+ EXPECT_EQ(&client_motion_event, event);
380+ EXPECT_EQ(AMOTION_EVENT_ACTION_UP, client_motion_event.getActionMasked());
381+ EXPECT_EQ(0, client_motion_event.getActionIndex());
382+ EXPECT_EQ(2, client_motion_event.getPointerId(0));
383+ EXPECT_EQ(3, client_motion_event.getPointerId(1));
384+ EXPECT_EQ(2, client_motion_event.getPointerCount());
385+
386+ EXPECT_EQ(droidinput::OK, consumer.consume(&event_factory, true, std::chrono::nanoseconds(86), &seq, &event));
387+ EXPECT_EQ(&client_motion_event, event);
388+ EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, client_motion_event.getActionMasked());
389+ EXPECT_EQ(1, client_motion_event.getActionIndex());
390+ EXPECT_EQ(3, client_motion_event.getPointerId(0));
391+ EXPECT_EQ(4, client_motion_event.getPointerId(1));
392+ EXPECT_EQ(2, client_motion_event.getPointerCount());
393+}
394+
395+TEST_F(AndroidInputSender, encodes_combinations_of_down_and_up_one_by_one)
396+{
397+ // TODO When the rework of the transport encoding is finished we might want to revisit this decision
398+ register_surface();
399+
400+ auto touch_ev_with_simultaneous_down = builder.touch_event(std::chrono::nanoseconds(86));
401+ builder.add_touch(*touch_ev_with_simultaneous_down, 2, mir_touch_action_down, tool, 50, 60, pressure, major, minor, size);
402+ builder.add_touch(*touch_ev_with_simultaneous_down, 3, mir_touch_action_change, tool, 10, 10, pressure, major, minor, size);
403+ builder.add_touch(*touch_ev_with_simultaneous_down, 4, mir_touch_action_up, tool, 80, 90, pressure, major, minor, size);
404+
405+ sender.send_event(*touch_ev_with_simultaneous_down, channel);
406+
407+ EXPECT_EQ(droidinput::OK, consumer.consume(&event_factory, true, std::chrono::nanoseconds(86), &seq, &event));
408+ EXPECT_EQ(&client_motion_event, event);
409+ EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, client_motion_event.getActionMasked());
410+ EXPECT_EQ(0, client_motion_event.getActionIndex());
411+ EXPECT_EQ(2, client_motion_event.getPointerId(0));
412+ EXPECT_EQ(3, client_motion_event.getPointerId(1));
413+ EXPECT_EQ(4, client_motion_event.getPointerId(2));
414+ EXPECT_EQ(3, client_motion_event.getPointerCount());
415+
416+ EXPECT_EQ(droidinput::OK, consumer.consume(&event_factory, true, std::chrono::nanoseconds(86), &seq, &event));
417+ EXPECT_EQ(&client_motion_event, event);
418+ EXPECT_EQ(AMOTION_EVENT_ACTION_UP, client_motion_event.getActionMasked());
419+ EXPECT_EQ(2, client_motion_event.getActionIndex());
420+ EXPECT_EQ(2, client_motion_event.getPointerId(0));
421+ EXPECT_EQ(3, client_motion_event.getPointerId(1));
422+ EXPECT_EQ(4, client_motion_event.getPointerId(2));
423+ EXPECT_EQ(3, client_motion_event.getPointerCount());
424+}

Subscribers

People subscribed via source and target branches