Mir

Merge lp:~andreas-pokorny/mir/combine-modifier-state-accross-devices into lp:mir

Proposed by Andreas Pokorny
Status: Superseded
Proposed branch: lp:~andreas-pokorny/mir/combine-modifier-state-accross-devices
Merge into: lp:mir
Diff against target: 1479 lines (+586/-279)
24 files modified
include/client/mir/events/event_builders.h (+2/-0)
include/platform/mir/input/event_builder.h (+5/-7)
include/test/mir/test/event_matchers.h (+8/-0)
src/client/events/event_builders.cpp (+22/-0)
src/client/symbols.map (+8/-0)
src/platforms/evdev/CMakeLists.txt (+2/-3)
src/platforms/evdev/button_utils.cpp (+37/-0)
src/platforms/evdev/button_utils.h (+35/-0)
src/platforms/evdev/libinput_device.cpp (+12/-34)
src/platforms/evdev/libinput_device.h (+0/-1)
src/platforms/mesa/server/x11/input/input_platform.cpp (+5/-37)
src/server/input/CMakeLists.txt (+2/-0)
src/server/input/default_event_builder.cpp (+12/-14)
src/server/input/default_event_builder.h (+5/-7)
src/server/input/default_input_device_hub.cpp (+22/-58)
src/server/input/default_input_device_hub.h (+6/-10)
src/server/input/input_modifier_utils.cpp (+4/-18)
src/server/input/input_modifier_utils.h (+2/-6)
src/server/input/seat.cpp (+153/-0)
src/server/input/seat.h (+72/-0)
tests/mir_test_framework/fake_input_device_impl.cpp (+3/-14)
tests/mir_test_framework/fake_input_device_impl.h (+0/-1)
tests/unit-tests/input/evdev/test_libinput_device.cpp (+23/-55)
tests/unit-tests/input/test_default_input_device_hub.cpp (+146/-14)
To merge this branch: bzr merge lp:~andreas-pokorny/mir/combine-modifier-state-accross-devices
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Mir development team Pending
Review via email: mp+274372@code.launchpad.net

This proposal has been superseded by a proposal from 2015-10-14.

Commit message

Rework Modifier tracking to combine modifiers within

The platform is no longer in charge of the modifier. Instead the new input stack tracks it when the events are received. To reduce the complexity of InputDeviceHub this behavior and similar parts are moved to mir::input::Seat which represents a group of input devices that belong to a user session. (Currently all of them).

Collateral changes:
- allow changing the modifier of MirEvent after creation -> additional symbols to 'hidden' C++ client API
- reduction of EventBuilder interface
- moving of modifier utils to server

Description of the change

This fixes the problem that caused the revert of the input platform probing mp..

To post a comment you must log in.
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: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/client/mir/events/event_builders.h'
2--- include/client/mir/events/event_builders.h 2015-10-02 04:27:33 +0000
3+++ include/client/mir/events/event_builders.h 2015-10-14 12:41:48 +0000
4@@ -58,6 +58,8 @@
5 uint64_t mac, MirKeyboardAction action, xkb_keysym_t key_code,
6 int scan_code, MirInputEventModifiers modifiers);
7
8+void set_modifier(MirEvent& event, MirInputEventModifiers modifiers);
9+
10 // Deprecated version without mac
11 EventUPtr make_event(MirInputDeviceId device_id, std::chrono::nanoseconds timestamp,
12 MirKeyboardAction action, xkb_keysym_t key_code,
13
14=== modified file 'include/platform/mir/input/event_builder.h'
15--- include/platform/mir/input/event_builder.h 2015-08-24 23:25:00 +0000
16+++ include/platform/mir/input/event_builder.h 2015-10-14 12:41:48 +0000
17@@ -38,18 +38,16 @@
18 virtual ~EventBuilder() = default;
19 using Timestamp = std::chrono::nanoseconds;
20
21- virtual EventUPtr key_event(Timestamp timestamp, MirKeyboardAction action, xkb_keysym_t key_code, int scan_code,
22- MirInputEventModifiers modifiers) = 0;
23+ virtual EventUPtr key_event(Timestamp timestamp, MirKeyboardAction action, xkb_keysym_t key_code, int scan_code) = 0;
24
25- virtual EventUPtr touch_event(Timestamp timestamp, MirInputEventModifiers modifiers) = 0;
26+ virtual EventUPtr touch_event(Timestamp timestamp) = 0;
27 virtual void add_touch(MirEvent& event, MirTouchId touch_id, MirTouchAction action, MirTouchTooltype tooltype,
28 float x_axis_value, float y_axis_value, float pressure_value, float touch_major_value,
29 float touch_minor_value, float size_value) = 0;
30
31- virtual EventUPtr pointer_event(Timestamp timestamp, MirInputEventModifiers modifiers, MirPointerAction action,
32- MirPointerButtons buttons_pressed, float x_axis_value, float y_axis_value,
33- float hscroll_value, float vscroll_value, float relative_x_value,
34- float relative_y_value) = 0;
35+ virtual EventUPtr pointer_event(Timestamp timestamp, MirPointerAction action, MirPointerButtons buttons_pressed,
36+ float x_axis_value, float y_axis_value, float hscroll_value, float vscroll_value,
37+ float relative_x_value, float relative_y_value) = 0;
38
39 virtual EventUPtr configuration_event(Timestamp timestamp, MirInputConfigurationAction action) = 0;
40
41
42=== modified file 'include/test/mir/test/event_matchers.h'
43--- include/test/mir/test/event_matchers.h 2015-10-13 16:25:36 +0000
44+++ include/test/mir/test/event_matchers.h 2015-10-14 12:41:48 +0000
45@@ -353,6 +353,14 @@
46 return true;
47 }
48
49+MATCHER_P(PointerEventWithModifiers, modifiers, "")
50+{
51+ auto pev = maybe_pointer_event(to_address(arg));
52+ if (pev && mir_pointer_event_modifiers(pev) == modifiers)
53+ return true;
54+ return false;
55+}
56+
57 MATCHER_P2(PointerEventWithDiff, dx, dy, "")
58 {
59 auto pev = maybe_pointer_event(to_address(arg));
60
61=== modified file 'src/client/events/event_builders.cpp'
62--- src/client/events/event_builders.cpp 2015-10-07 12:07:00 +0000
63+++ src/client/events/event_builders.cpp 2015-10-14 12:41:48 +0000
64@@ -165,6 +165,28 @@
65 return make_event_uptr(e);
66 }
67
68+
69+void mev::set_modifier(MirEvent& event, MirInputEventModifiers modifiers)
70+{
71+ switch(event.type)
72+ {
73+ case mir_event_type_key:
74+ {
75+ auto& kev = event.key;
76+ kev.modifiers = modifiers;
77+ break;
78+ }
79+ case mir_event_type_motion:
80+ {
81+ auto& mev = event.motion;
82+ mev.modifiers = modifiers;
83+ break;
84+ }
85+ default:
86+ BOOST_THROW_EXCEPTION(std::invalid_argument("Input event modifiers are only valid for pointer, key and touch events."));
87+ }
88+}
89+
90 // Deprecated version without mac
91 mir::EventUPtr mev::make_event(MirInputDeviceId device_id, std::chrono::nanoseconds timestamp,
92 MirKeyboardAction action, xkb_keysym_t key_code,
93
94=== modified file 'src/client/symbols.map'
95--- src/client/symbols.map 2015-10-08 21:11:44 +0000
96+++ src/client/symbols.map 2015-10-14 12:41:48 +0000
97@@ -243,3 +243,11 @@
98 mir::operator???std::ostream???Mir*
99 };
100 };
101+
102+MIR_CLIENT_DETAIL_v0.18.0 {
103+ global:
104+ extern "C++" {
105+ mir::events::set_modifier*;
106+ };
107+} MIR_CLIENT_DETAIL_9;
108+
109
110=== modified file 'src/platforms/evdev/CMakeLists.txt'
111--- src/platforms/evdev/CMakeLists.txt 2015-10-05 20:17:26 +0000
112+++ src/platforms/evdev/CMakeLists.txt 2015-10-14 12:41:48 +0000
113@@ -8,7 +8,7 @@
114
115 add_library(mirevdevutilsobjects OBJECT
116 evdev_device_detection.cpp
117- input_modifier_utils.cpp
118+ button_utils.cpp
119 )
120
121 add_library(mirplatforminputevdevobjects OBJECT
122@@ -34,8 +34,7 @@
123 )
124
125 target_link_libraries(mirplatforminputevdev
126- mirplatform
127- mirclient
128+ mirplatform # udev wrapper
129 ${Boost_PROGRAM_OPTIONS_LIBRARY}
130 ${LIBINPUT_LDFLAGS} ${LIBINPUT_LIBRARIES}
131 )
132
133=== added file 'src/platforms/evdev/button_utils.cpp'
134--- src/platforms/evdev/button_utils.cpp 1970-01-01 00:00:00 +0000
135+++ src/platforms/evdev/button_utils.cpp 2015-10-14 12:41:48 +0000
136@@ -0,0 +1,37 @@
137+/*
138+ * Copyright © 2015 Canonical Ltd.
139+ *
140+ * This program is free software: you can redistribute it and/or modify it
141+ * under the terms of the GNU General Public License version 3,
142+ * as published by the Free Software Foundation.
143+ *
144+ * This program is distributed in the hope that it will be useful,
145+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
146+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
147+ * GNU General Public License for more details.
148+ *
149+ * You should have received a copy of the GNU General Public License
150+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
151+ *
152+ * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
153+ */
154+
155+#include "button_utils.h"
156+#include "boost/throw_exception.hpp"
157+
158+#include "linux/input.h"
159+
160+#include <stdexcept>
161+
162+MirPointerButton mir::input::evdev::to_pointer_button(int button)
163+{
164+ switch(button)
165+ {
166+ case BTN_LEFT: return mir_pointer_button_primary;
167+ case BTN_RIGHT: return mir_pointer_button_secondary;
168+ case BTN_MIDDLE: return mir_pointer_button_tertiary;
169+ case BTN_BACK: return mir_pointer_button_back;
170+ case BTN_FORWARD: return mir_pointer_button_forward;
171+ }
172+ BOOST_THROW_EXCEPTION(std::runtime_error("Invalid mouse button"));
173+}
174
175=== added file 'src/platforms/evdev/button_utils.h'
176--- src/platforms/evdev/button_utils.h 1970-01-01 00:00:00 +0000
177+++ src/platforms/evdev/button_utils.h 2015-10-14 12:41:48 +0000
178@@ -0,0 +1,35 @@
179+/*
180+ * Copyright © 2015 Canonical Ltd.
181+ *
182+ * This program is free software: you can redistribute it and/or modify it
183+ * under the terms of the GNU General Public License version 3,
184+ * as published by the Free Software Foundation.
185+ *
186+ * This program is distributed in the hope that it will be useful,
187+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
188+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
189+ * GNU General Public License for more details.
190+ *
191+ * You should have received a copy of the GNU General Public License
192+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
193+ *
194+ * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
195+ */
196+
197+#ifndef MIR_INPUT_EVDEV_BUTTON_UTILS_H_
198+#define MIR_INPUT_EVDEV_BUTTON_UTILS_H_
199+
200+#include "mir_toolkit/event.h"
201+
202+namespace mir
203+{
204+namespace input
205+{
206+namespace evdev
207+{
208+MirPointerButton to_pointer_button(int button);
209+}
210+}
211+}
212+
213+#endif
214
215=== modified file 'src/platforms/evdev/libinput_device.cpp'
216--- src/platforms/evdev/libinput_device.cpp 2015-10-07 15:32:10 +0000
217+++ src/platforms/evdev/libinput_device.cpp 2015-10-14 12:41:48 +0000
218@@ -19,8 +19,8 @@
219 #include "libinput_device.h"
220 #include "libinput_ptr.h"
221 #include "libinput_device_ptr.h"
222-#include "input_modifier_utils.h"
223 #include "evdev_device_detection.h"
224+#include "button_utils.h"
225
226 #include "mir/input/input_sink.h"
227 #include "mir/input/input_report.h"
228@@ -53,8 +53,7 @@
229
230 mie::LibInputDevice::LibInputDevice(std::shared_ptr<mi::InputReport> const& report, char const* path,
231 LibInputDevicePtr dev)
232- : report{report}, accumulated_touch_event{nullptr, null_deleter}, pointer_pos{0, 0}, modifier_state{0},
233- button_state{0}
234+ : report{report}, accumulated_touch_event{nullptr, null_deleter}, pointer_pos{0, 0}, button_state{0}
235 {
236 add_device_of_group(path, std::move(dev));
237 }
238@@ -138,18 +137,7 @@
239 auto const code = libinput_event_keyboard_get_key(keyboard);
240 report->received_event_from_kernel(time.count(), EV_KEY, code, action);
241
242- auto event = builder->key_event(time,
243- action,
244- xkb_keysym_t{0},
245- code,
246- mie::expand_modifiers(modifier_state));
247-
248- if (action == mir_keyboard_action_down)
249- modifier_state |= mie::to_modifiers(code);
250- else
251- modifier_state &= ~mie::to_modifiers(code);
252-
253- return event;
254+ return builder->key_event(time, action, xkb_keysym_t{0}, code);
255 }
256
257 mir::EventUPtr mie::LibInputDevice::convert_button_event(libinput_event_pointer* pointer)
258@@ -172,11 +160,8 @@
259 else
260 button_state = MirPointerButton(button_state & ~uint32_t(pointer_button));
261
262- auto event = builder->pointer_event(time, mie::expand_modifiers(modifier_state), action, button_state,
263- pointer_pos.x.as_float(), pointer_pos.y.as_float(), hscroll_value,
264- vscroll_value, relative_x_value, relative_y_value);
265-
266- return event;
267+ return builder->pointer_event(time, action, button_state, pointer_pos.x.as_float(), pointer_pos.y.as_float(),
268+ hscroll_value, vscroll_value, relative_x_value, relative_y_value);
269 }
270
271 mir::EventUPtr mie::LibInputDevice::convert_motion_event(libinput_event_pointer* pointer)
272@@ -195,11 +180,8 @@
273
274 sink->confine_pointer(pointer_pos);
275
276- auto event = builder->pointer_event(time, mie::expand_modifiers(modifier_state), action, button_state,
277- pointer_pos.x.as_float(), pointer_pos.y.as_float(), hscroll_value,
278- vscroll_value, movement.dx.as_float(), movement.dy.as_float());
279-
280- return event;
281+ return builder->pointer_event(time, action, button_state, pointer_pos.x.as_float(), pointer_pos.y.as_float(),
282+ hscroll_value, vscroll_value, movement.dx.as_float(), movement.dy.as_float());
283 }
284
285 mir::EventUPtr mie::LibInputDevice::convert_absolute_motion_event(libinput_event_pointer* pointer)
286@@ -219,10 +201,8 @@
287
288 sink->confine_pointer(pointer_pos);
289
290- auto event = builder->pointer_event(time, mie::expand_modifiers(modifier_state), action, button_state,
291- pointer_pos.x.as_float(), pointer_pos.y.as_float(), hscroll_value,
292- vscroll_value, movement.dx.as_float(), movement.dy.as_float());
293- return event;
294+ return builder->pointer_event(time, action, button_state, pointer_pos.x.as_float(), pointer_pos.y.as_float(),
295+ hscroll_value, vscroll_value, movement.dx.as_float(), movement.dy.as_float());
296 }
297
298 mir::EventUPtr mie::LibInputDevice::convert_axis_event(libinput_event_pointer* pointer)
299@@ -239,10 +219,8 @@
300 : 0.0f;
301
302 report->received_event_from_kernel(time.count(), EV_REL, 0, 0);
303- auto event = builder->pointer_event(time, mie::expand_modifiers(modifier_state), action, button_state,
304- pointer_pos.x.as_float(), pointer_pos.y.as_float(), hscroll_value,
305- vscroll_value, relative_x_value, relative_y_value);
306- return event;
307+ return builder->pointer_event(time, action, button_state, pointer_pos.x.as_float(), pointer_pos.y.as_float(),
308+ hscroll_value, vscroll_value, relative_x_value, relative_y_value);
309 }
310
311 MirEvent& mie::LibInputDevice::get_accumulated_touch_event(std::chrono::nanoseconds timestamp)
312@@ -250,7 +228,7 @@
313 if (!accumulated_touch_event)
314 {
315 report->received_event_from_kernel(timestamp.count(), EV_SYN, 0, 0);
316- accumulated_touch_event = builder->touch_event(timestamp, mie::expand_modifiers(modifier_state));
317+ accumulated_touch_event = builder->touch_event(timestamp);
318 }
319
320 return *accumulated_touch_event;
321
322=== modified file 'src/platforms/evdev/libinput_device.h'
323--- src/platforms/evdev/libinput_device.h 2015-10-07 15:32:10 +0000
324+++ src/platforms/evdev/libinput_device.h 2015-10-14 12:41:48 +0000
325@@ -84,7 +84,6 @@
326
327 InputDeviceInfo info;
328 mir::geometry::Point pointer_pos;
329- MirInputEventModifiers modifier_state;
330 MirPointerButtons button_state;
331
332 struct ContactData
333
334=== modified file 'src/platforms/mesa/server/x11/input/input_platform.cpp'
335--- src/platforms/mesa/server/x11/input/input_platform.cpp 2015-10-13 16:25:36 +0000
336+++ src/platforms/mesa/server/x11/input/input_platform.cpp 2015-10-14 12:41:48 +0000
337@@ -127,16 +127,6 @@
338 #endif
339 XLookupString(&xkev, str, STRMAX, &keysym, NULL);
340
341- MirInputEventModifiers modifiers = mir_input_event_modifier_none;
342- if (xkev.state & ShiftMask)
343- modifiers |= mir_input_event_modifier_shift;
344- if (xkev.state & ControlMask)
345- modifiers |= mir_input_event_modifier_ctrl;
346- if (xkev.state & Mod1Mask)
347- modifiers |= mir_input_event_modifier_alt;
348- if (xkev.state & Mod4Mask)
349- modifiers |= mir_input_event_modifier_meta;
350-
351 auto event_time =
352 std::chrono::duration_cast<std::chrono::nanoseconds>(
353 std::chrono::milliseconds{xkev.time});
354@@ -155,8 +145,7 @@
355 mir_keyboard_action_down :
356 mir_keyboard_action_up,
357 keysym,
358- xkev.keycode-8,
359- modifiers
360+ xkev.keycode-8
361 )
362 );
363 break;
364@@ -177,16 +166,6 @@
365 xbev.subwindow, xbev.time, xbev.x, xbev.y, xbev.x_root,
366 xbev.y_root, xbev.state, xbev.button, xbev.same_screen);
367 #endif
368- MirInputEventModifiers modifiers = mir_input_event_modifier_none;
369- if (xbev.state & ShiftMask)
370- modifiers |= mir_input_event_modifier_shift;
371- if (xbev.state & ControlMask)
372- modifiers |= mir_input_event_modifier_ctrl;
373- if (xbev.state & Mod1Mask)
374- modifiers |= mir_input_event_modifier_alt;
375- if (xbev.state & Mod4Mask)
376- modifiers |= mir_input_event_modifier_meta;
377-
378 auto event_time =
379 std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::milliseconds{xbev.time});
380
381@@ -207,13 +186,12 @@
382
383 #ifdef MIR_ON_X11_INPUT_VERBOSE
384 mir::log_info("Mir button event : x=%d, y=%d, "
385- "buttons_pressed=0x%0X, modifiers=0x%0X, event_time=%" PRId64,
386- xbev.x, xbev.y, buttons_pressed, modifiers, event_time);
387+ "buttons_pressed=0x%0X, event_time=%" PRId64,
388+ xbev.x, xbev.y, buttons_pressed, event_time);
389 #endif
390 core_pointer->sink->handle_input(
391 *core_pointer->builder->pointer_event(
392 event_time,
393- modifiers,
394 xbev.type == ButtonPress ?
395 mir_pointer_action_button_down :
396 mir_pointer_action_button_up,
397@@ -242,15 +220,6 @@
398 xmev.root, xmev.subwindow, xmev.time, xmev.x, xmev.y, xmev.x_root,
399 xmev.y_root, xmev.state, xmev.is_hint == NotifyNormal ? "no" : "yes", xmev.same_screen);
400 #endif
401- MirInputEventModifiers modifiers = mir_input_event_modifier_none;
402- if (xmev.state & ShiftMask)
403- modifiers |= mir_input_event_modifier_shift;
404- if (xmev.state & ControlMask)
405- modifiers |= mir_input_event_modifier_ctrl;
406- if (xmev.state & Mod1Mask)
407- modifiers |= mir_input_event_modifier_alt;
408- if (xmev.state & Mod4Mask)
409- modifiers |= mir_input_event_modifier_meta;
410
411 auto event_time =
412 std::chrono::duration_cast<std::chrono::nanoseconds>(
413@@ -270,13 +239,12 @@
414
415 #ifdef MIR_ON_X11_INPUT_VERBOSE
416 mir::log_info("Mir pointer event : "
417- "x=%d, y=%d, buttons_pressed=0x%0X, modifiers=0x%0X, event_time=%" PRId64,
418- xmev.x, xmev.y, buttons_pressed, modifiers, event_time);
419+ "x=%d, y=%d, buttons_pressed=0x%0X, event_time=%" PRId64,
420+ xmev.x, xmev.y, buttons_pressed, event_time);
421 #endif
422 core_pointer->sink->handle_input(
423 *core_pointer->builder->pointer_event(
424 event_time,
425- modifiers,
426 mir_pointer_action_motion,
427 buttons_pressed,
428 xmev.x,
429
430=== modified file 'src/server/input/CMakeLists.txt'
431--- src/server/input/CMakeLists.txt 2015-10-12 19:30:14 +0000
432+++ src/server/input/CMakeLists.txt 2015-10-14 12:41:48 +0000
433@@ -8,6 +8,8 @@
434 default_event_builder.cpp
435 default_input_manager.cpp
436 default_input_device_hub.cpp
437+ input_modifier_utils.cpp
438+ seat.cpp
439
440 surface_input_dispatcher.cpp
441 event_filter_chain_dispatcher.cpp
442
443=== modified file 'src/server/input/default_event_builder.cpp'
444--- src/server/input/default_event_builder.cpp 2015-10-09 00:15:44 +0000
445+++ src/server/input/default_event_builder.cpp 2015-10-14 12:41:48 +0000
446@@ -33,21 +33,21 @@
447 }
448
449 mir::EventUPtr mi::DefaultEventBuilder::key_event(Timestamp timestamp, MirKeyboardAction action, xkb_keysym_t key_code,
450- int scan_code, MirInputEventModifiers modifiers)
451+ int scan_code)
452 {
453 uint64_t mac = cookie_factory->timestamp_to_cookie(timestamp.count()).mac;
454- return me::make_event(device_id, timestamp, mac, action, key_code, scan_code, modifiers);
455+ return me::make_event(device_id, timestamp, mac, action, key_code, scan_code, mir_input_event_modifier_none);
456 }
457
458-mir::EventUPtr mi::DefaultEventBuilder::touch_event(Timestamp timestamp, MirInputEventModifiers modifiers)
459+mir::EventUPtr mi::DefaultEventBuilder::touch_event(Timestamp timestamp)
460 {
461- return me::make_event(device_id, timestamp, 0, modifiers);
462+ return me::make_event(device_id, timestamp, 0, mir_input_event_modifier_none);
463 }
464
465 void mi::DefaultEventBuilder::add_touch(MirEvent& event, MirTouchId touch_id, MirTouchAction action,
466- MirTouchTooltype tooltype, float x_axis_value, float y_axis_value,
467- float pressure_value, float touch_major_value,
468- float touch_minor_value, float size_value)
469+ MirTouchTooltype tooltype, float x_axis_value, float y_axis_value,
470+ float pressure_value, float touch_major_value, float touch_minor_value,
471+ float size_value)
472 {
473 if (action == mir_touch_action_up || action == mir_touch_action_down)
474 {
475@@ -59,17 +59,15 @@
476 touch_minor_value, size_value);
477 }
478
479-mir::EventUPtr mi::DefaultEventBuilder::pointer_event(Timestamp timestamp, MirInputEventModifiers modifiers,
480- MirPointerAction action, MirPointerButtons buttons_pressed,
481- float x_axis_value, float y_axis_value, float hscroll_value,
482- float vscroll_value, float relative_x_value,
483- float relative_y_value)
484+mir::EventUPtr mi::DefaultEventBuilder::pointer_event(Timestamp timestamp, MirPointerAction action,
485+ MirPointerButtons buttons_pressed, float x_axis_value,
486+ float y_axis_value, float hscroll_value, float vscroll_value,
487+ float relative_x_value, float relative_y_value)
488 {
489 uint64_t mac = 0;
490 if (action == mir_pointer_action_button_up || action == mir_pointer_action_button_down)
491 mac = cookie_factory->timestamp_to_cookie(timestamp.count()).mac;
492-
493- return me::make_event(device_id, timestamp, mac, modifiers, action, buttons_pressed, x_axis_value, y_axis_value,
494+ return me::make_event(device_id, timestamp, mac, mir_input_event_modifier_none, action, buttons_pressed, x_axis_value, y_axis_value,
495 hscroll_value, vscroll_value, relative_x_value, relative_y_value);
496 }
497
498
499=== modified file 'src/server/input/default_event_builder.h'
500--- src/server/input/default_event_builder.h 2015-10-08 00:23:43 +0000
501+++ src/server/input/default_event_builder.h 2015-10-14 12:41:48 +0000
502@@ -37,18 +37,16 @@
503 explicit DefaultEventBuilder(MirInputDeviceId device_id,
504 std::shared_ptr<cookie::CookieFactory> const& cookie_factory);
505
506- EventUPtr key_event(Timestamp timestamp, MirKeyboardAction action, xkb_keysym_t key_code, int scan_code,
507- MirInputEventModifiers modifiers) override;
508+ EventUPtr key_event(Timestamp timestamp, MirKeyboardAction action, xkb_keysym_t key_code, int scan_code) override;
509
510- EventUPtr touch_event(Timestamp timestamp, MirInputEventModifiers modifiers) override;
511+ EventUPtr touch_event(Timestamp timestamp) override;
512 void add_touch(MirEvent& event, MirTouchId touch_id, MirTouchAction action, MirTouchTooltype tooltype,
513 float x_axis_value, float y_axis_value, float pressure_value, float touch_major_value,
514 float touch_minor_value, float size_value) override;
515
516- EventUPtr pointer_event(Timestamp timestamp, MirInputEventModifiers modifiers, MirPointerAction action,
517- MirPointerButtons buttons_pressed, float x_axis_value, float y_axis_value,
518- float hscroll_value, float vscroll_value, float relative_x_value,
519- float relative_y_value) override;
520+ EventUPtr pointer_event(Timestamp timestamp, MirPointerAction action, MirPointerButtons buttons_pressed,
521+ float x_axis_value, float y_axis_value, float hscroll_value, float vscroll_value,
522+ float relative_x_value, float relative_y_value) override;
523
524 EventUPtr configuration_event(Timestamp timestamp, MirInputConfigurationAction action) override;
525
526
527=== modified file 'src/server/input/default_input_device_hub.cpp'
528--- src/server/input/default_input_device_hub.cpp 2015-10-08 00:23:43 +0000
529+++ src/server/input/default_input_device_hub.cpp 2015-10-14 12:41:48 +0000
530@@ -19,11 +19,13 @@
531 #include "default_input_device_hub.h"
532 #include "device_handle.h"
533
534+#include "seat.h"
535 #include "mir/input/input_dispatcher.h"
536 #include "mir/input/input_device.h"
537 #include "mir/input/input_device_observer.h"
538-#include "mir/input/cursor_listener.h"
539 #include "mir/input/input_region.h"
540+#include "mir/geometry/point.h"
541+#include "mir/events/event_builders.h"
542 #include "mir/dispatch/multiplexing_dispatchable.h"
543 #include "mir/server_action_queue.h"
544 #include "mir/cookie_factory.h"
545@@ -36,6 +38,8 @@
546 #include <atomic>
547
548 namespace mi = mir::input;
549+namespace geom = mir::geometry;
550+namespace mev = mir::events;
551
552 mi::DefaultInputDeviceHub::DefaultInputDeviceHub(
553 std::shared_ptr<mi::InputDispatcher> const& input_dispatcher,
554@@ -45,9 +49,13 @@
555 std::shared_ptr<CursorListener> const& cursor_listener,
556 std::shared_ptr<InputRegion> const& input_region,
557 std::shared_ptr<mir::cookie::CookieFactory> const& cookie_factory)
558- : input_dispatcher(input_dispatcher), input_dispatchable{input_multiplexer}, observer_queue(observer_queue),
559- touch_visualizer(touch_visualizer), cursor_listener(cursor_listener), input_region(input_region),
560- cookie_factory(cookie_factory), device_id_generator{0}
561+ : input_dispatcher(input_dispatcher),
562+ input_dispatchable{input_multiplexer},
563+ observer_queue(observer_queue),
564+ input_region(input_region),
565+ cookie_factory(cookie_factory),
566+ seat(touch_visualizer, cursor_listener),
567+ device_id_generator{0}
568 {
569 }
570
571@@ -67,9 +75,10 @@
572 {
573 // send input device info to observer loop..
574 devices.push_back(std::make_unique<RegisteredDevice>(
575- device, create_new_device_id(), input_dispatcher, input_dispatchable, cookie_factory, this));
576+ device, create_new_device_id(), input_dispatcher, input_dispatchable, cookie_factory, this, &seat));
577
578 auto const& dev = devices.back();
579+ seat.add_device(dev->id());
580
581 auto handle = std::make_shared<DefaultDevice>(
582 dev->id(), device->get_device_info());
583@@ -104,6 +113,7 @@
584 if (item->device_matches(device))
585 {
586 item->stop();
587+ seat.remove_device(item->id());
588
589 // send input device info to observer queue..
590 observer_queue->enqueue(
591@@ -131,9 +141,10 @@
592 std::shared_ptr<InputDispatcher> const& dispatcher,
593 std::shared_ptr<dispatch::MultiplexingDispatchable> const& multiplexer,
594 std::shared_ptr<mir::cookie::CookieFactory> const& cookie_factory,
595- DefaultInputDeviceHub* hub)
596+ DefaultInputDeviceHub* hub,
597+ Seat* seat)
598 : device_id(device_id), builder(device_id, cookie_factory), device(dev), dispatcher(dispatcher),
599- multiplexer(multiplexer), hub(hub)
600+ multiplexer(multiplexer), hub(hub), seat(seat)
601 {
602 }
603
604@@ -154,50 +165,13 @@
605 if (type != mir_event_type_input)
606 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid input event receivd from device"));
607
608- update_spots(mir_event_get_input_event(&event));
609- notify_cursor_listener(mir_event_get_input_event(&event));
610+ seat->update_seat_properties(mir_event_get_input_event(&event));
611+
612+ mev::set_modifier(event, seat->event_modifier());
613+
614 dispatcher->dispatch(event);
615 }
616
617-void mi::DefaultInputDeviceHub::RegisteredDevice::notify_cursor_listener(MirInputEvent const* event)
618-{
619- if (mir_input_event_get_type(event) != mir_input_event_type_pointer)
620- return;
621-
622- auto pointer_ev = mir_input_event_get_pointer_event(event);
623- hub->cursor_listener->cursor_moved_to(
624- mir_pointer_event_axis_value(pointer_ev, mir_pointer_axis_x),
625- mir_pointer_event_axis_value(pointer_ev, mir_pointer_axis_y)
626- );
627-}
628-
629-void mi::DefaultInputDeviceHub::RegisteredDevice::update_spots(MirInputEvent const* event)
630-{
631- if (mir_input_event_get_type(event) != mir_input_event_type_touch)
632- return;
633-
634- auto const* touch_event = mir_input_event_get_touch_event(event);
635- auto count = mir_touch_event_point_count(touch_event);
636- touch_spots.reserve(count);
637- touch_spots.clear();
638- for (decltype(count) i = 0; i != count; ++i)
639- {
640- if (mir_touch_event_action(touch_event, i) == mir_touch_action_up)
641- continue;
642- touch_spots.push_back(mi::TouchVisualizer::Spot{
643- {mir_touch_event_axis_value(touch_event, i, mir_touch_axis_x),
644- mir_touch_event_axis_value(touch_event, i, mir_touch_axis_y)},
645- mir_touch_event_axis_value(touch_event, i, mir_touch_axis_pressure)});
646- }
647-
648- hub->update_spots();
649-}
650-
651-std::vector<mir::input::TouchVisualizer::Spot> const& mi::DefaultInputDeviceHub::RegisteredDevice::spots() const
652-{
653- return touch_spots;
654-}
655-
656 bool mi::DefaultInputDeviceHub::RegisteredDevice::device_matches(std::shared_ptr<InputDevice> const& dev) const
657 {
658 return dev == device;
659@@ -278,13 +252,3 @@
660
661 handles.erase(handle_it, end(handles));
662 }
663-
664-void mi::DefaultInputDeviceHub::update_spots()
665-{
666- std::vector<TouchVisualizer::Spot> spots;
667-
668- for (auto const& dev : devices)
669- spots.insert(end(spots), begin(dev->spots()), end(dev->spots()));
670-
671- touch_visualizer->visualize_touches(spots);
672-}
673
674=== modified file 'src/server/input/default_input_device_hub.h'
675--- src/server/input/default_input_device_hub.h 2015-10-08 00:23:43 +0000
676+++ src/server/input/default_input_device_hub.h 2015-10-14 12:41:48 +0000
677@@ -20,12 +20,12 @@
678 #define MIR_INPUT_DEFAULT_INPUT_DEVICE_HUB_H_
679
680 #include "default_event_builder.h"
681+#include "seat.h"
682
683 #include "mir/input/input_device_registry.h"
684 #include "mir/input/input_sink.h"
685 #include "mir/input/input_device_hub.h"
686 #include "mir/input/input_device_info.h"
687-#include "mir/input/touch_visualizer.h"
688
689 #include "mir_toolkit/event.h"
690
691@@ -82,10 +82,9 @@
692 std::shared_ptr<InputDispatcher> const input_dispatcher;
693 std::shared_ptr<dispatch::MultiplexingDispatchable> const input_dispatchable;
694 std::shared_ptr<ServerActionQueue> const observer_queue;
695- std::shared_ptr<TouchVisualizer> const touch_visualizer;
696- std::shared_ptr<CursorListener> const cursor_listener;
697 std::shared_ptr<InputRegion> const input_region;
698 std::shared_ptr<cookie::CookieFactory> const cookie_factory;
699+ Seat seat;
700
701 struct RegisteredDevice : public InputSink
702 {
703@@ -95,8 +94,8 @@
704 std::shared_ptr<InputDispatcher> const& dispatcher,
705 std::shared_ptr<dispatch::MultiplexingDispatchable> const& multiplexer,
706 std::shared_ptr<cookie::CookieFactory> const& cookie_factory,
707- DefaultInputDeviceHub* hub);
708-
709+ DefaultInputDeviceHub* hub,
710+ Seat* seat);
711 void handle_input(MirEvent& event) override;
712 void confine_pointer(mir::geometry::Point& position) override;
713 mir::geometry::Rectangle bounding_rectangle() const override;
714@@ -104,24 +103,21 @@
715 void start();
716 void stop();
717 MirInputDeviceId id();
718- std::vector<TouchVisualizer::Spot> const& spots() const;
719 private:
720- void update_spots(MirInputEvent const* event);
721- void notify_cursor_listener(MirInputEvent const* event);
722 MirInputDeviceId device_id;
723 DefaultEventBuilder builder;
724 std::shared_ptr<InputDevice> const device;
725 std::shared_ptr<InputDispatcher> const dispatcher;
726 std::shared_ptr<dispatch::MultiplexingDispatchable> const multiplexer;
727 DefaultInputDeviceHub* hub;
728- std::vector<TouchVisualizer::Spot> touch_spots;
729+ Seat* seat;
730 friend class DefaultInputDeviceHub;
731 };
732
733 std::vector<std::shared_ptr<DefaultDevice>> handles;
734 std::vector<std::unique_ptr<RegisteredDevice>> devices;
735 std::vector<std::shared_ptr<InputDeviceObserver>> observers;
736-
737+
738 MirInputDeviceId device_id_generator;
739 };
740
741
742=== renamed file 'src/platforms/evdev/input_modifier_utils.cpp' => 'src/server/input/input_modifier_utils.cpp'
743--- src/platforms/evdev/input_modifier_utils.cpp 2015-09-17 06:40:14 +0000
744+++ src/server/input/input_modifier_utils.cpp 2015-10-14 12:41:48 +0000
745@@ -25,22 +25,9 @@
746
747 #include <stdexcept>
748
749-namespace mie = mir::input::evdev;
750-
751-MirPointerButton mie::to_pointer_button(int button)
752-{
753- switch(button)
754- {
755- case BTN_LEFT: return mir_pointer_button_primary;
756- case BTN_RIGHT: return mir_pointer_button_secondary;
757- case BTN_MIDDLE: return mir_pointer_button_tertiary;
758- case BTN_BACK: return mir_pointer_button_back;
759- case BTN_FORWARD: return mir_pointer_button_forward;
760- }
761- BOOST_THROW_EXCEPTION(std::runtime_error("Invalid mouse button"));
762-}
763-
764-MirInputEventModifiers mie::to_modifiers(int32_t scan_code)
765+namespace mi = mir::input;
766+
767+MirInputEventModifiers mi::to_modifiers(int32_t scan_code)
768 {
769 switch(scan_code)
770 {
771@@ -71,7 +58,7 @@
772 }
773 }
774
775-MirInputEventModifiers mie::expand_modifiers(MirInputEventModifiers modifiers)
776+MirInputEventModifiers mi::expand_modifiers(MirInputEventModifiers modifiers)
777 {
778 if (modifiers == 0)
779 return mir_input_event_modifier_none;
780@@ -91,4 +78,3 @@
781 return modifiers;
782 }
783
784-
785
786=== renamed file 'src/platforms/evdev/input_modifier_utils.h' => 'src/server/input/input_modifier_utils.h'
787--- src/platforms/evdev/input_modifier_utils.h 2015-09-17 06:40:14 +0000
788+++ src/server/input/input_modifier_utils.h 2015-10-14 12:41:48 +0000
789@@ -16,8 +16,8 @@
790 * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
791 */
792
793-#ifndef MIR_INPUT_EVDEV_INPUT_MODIFIER_UTILS_H_
794-#define MIR_INPUT_EVDEV_INPUT_MODIFIER_UTILS_H_
795+#ifndef MIR_INPUT_INPUT_MODIFIER_UTILS_H_
796+#define MIR_INPUT_INPUT_MODIFIER_UTILS_H_
797
798 #include "mir_toolkit/event.h"
799
800@@ -25,13 +25,9 @@
801 {
802 namespace input
803 {
804-namespace evdev
805-{
806-MirPointerButton to_pointer_button(int button);
807 MirInputEventModifiers to_modifiers(int32_t scan_code);
808 MirInputEventModifiers expand_modifiers(MirInputEventModifiers modifiers);
809 }
810 }
811-}
812
813 #endif
814
815=== added file 'src/server/input/seat.cpp'
816--- src/server/input/seat.cpp 1970-01-01 00:00:00 +0000
817+++ src/server/input/seat.cpp 2015-10-14 12:41:48 +0000
818@@ -0,0 +1,153 @@
819+/*
820+ * Copyright © 2015 Canonical Ltd.
821+ *
822+ * This program is free software: you can redistribute it and/or modify it
823+ * under the terms of the GNU General Public License version 3,
824+ * as published by the Free Software Foundation.
825+ *
826+ * This program is distributed in the hope that it will be useful,
827+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
828+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
829+ * GNU General Public License for more details.
830+ *
831+ * You should have received a copy of the GNU General Public License
832+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
833+ *
834+ * Authored by:
835+ * Andreas Pokorny <andreas.pokorny@canonical.com>
836+ */
837+
838+#include "seat.h"
839+#include "mir/input/device.h"
840+#include "mir/input/cursor_listener.h"
841+
842+#include "input_modifier_utils.h"
843+
844+#include <boost/throw_exception.hpp>
845+
846+#include <stdexcept>
847+#include <algorithm>
848+
849+namespace mi = mir::input;
850+
851+mi::Seat::Seat(std::shared_ptr<TouchVisualizer> const& touch_visualizer,
852+ std::shared_ptr<CursorListener> const& cursor_listener)
853+ : touch_visualizer{touch_visualizer}, cursor_listener{cursor_listener}, modifier{0}
854+{
855+}
856+
857+void mi::Seat::add_device(MirInputDeviceId id)
858+{
859+ device_data[id];
860+}
861+
862+void mi::Seat::remove_device(MirInputDeviceId id)
863+{
864+ auto stored_data = device_data.find(id);
865+
866+ if (stored_data == end(device_data))
867+ BOOST_THROW_EXCEPTION(std::logic_error("Modifier for unknown device changed"));
868+
869+ bool mod_update_needed = stored_data->second.mod != mir_input_event_modifier_none;
870+ bool spot_update_needed = !stored_data->second.spots.empty();
871+
872+ device_data.erase(stored_data);
873+
874+ if (mod_update_needed)
875+ update_modifier();
876+ if (spot_update_needed)
877+ update_spots();
878+}
879+
880+MirInputEventModifiers mi::Seat::event_modifier() const
881+{
882+ return expand_modifiers(modifier);
883+}
884+
885+void mi::Seat::update_seat_properties(MirInputEvent const* event)
886+{
887+ auto id = mir_input_event_get_device_id(event);
888+
889+ auto stored_data = device_data.find(id);
890+
891+ if (stored_data == end(device_data))
892+ BOOST_THROW_EXCEPTION(std::logic_error("Modifier for unknown device changed"));
893+
894+ switch(mir_input_event_get_type(event))
895+ {
896+ case mir_input_event_type_key:
897+ {
898+ auto const* key = mir_input_event_get_keyboard_event(event);
899+ if (stored_data->second.update_modifier(mir_keyboard_event_action(key),
900+ mir_keyboard_event_scan_code(key)))
901+ update_modifier();
902+ break;
903+ }
904+ case mir_input_event_type_touch:
905+ if (stored_data->second.update_spots(mir_input_event_get_touch_event(event)))
906+ update_spots();
907+ break;
908+ case mir_input_event_type_pointer:
909+ update_cursor(mir_input_event_get_pointer_event(event));
910+ break;
911+ default:
912+ break;
913+ }
914+}
915+
916+bool mi::Seat::DeviceData::update_modifier(MirKeyboardAction key_action, int scan_code)
917+{
918+ auto mod_change = to_modifiers(scan_code);
919+
920+ if (mod_change == 0 || key_action == mir_keyboard_action_repeat)
921+ return false;
922+
923+ if (key_action == mir_keyboard_action_down)
924+ mod |= mod_change;
925+ else if (key_action == mir_keyboard_action_up)
926+ mod &= ~mod_change;
927+
928+ return true;
929+}
930+
931+bool mi::Seat::DeviceData::update_spots(MirTouchEvent const* event)
932+{
933+ auto count = mir_touch_event_point_count(event);
934+ spots.clear();
935+ for (decltype(count) i = 0; i != count; ++i)
936+ {
937+ if (mir_touch_event_action(event, i) == mir_touch_action_up)
938+ continue;
939+ spots.push_back({{mir_touch_event_axis_value(event, i, mir_touch_axis_x),
940+ mir_touch_event_axis_value(event, i, mir_touch_axis_y)},
941+ mir_touch_event_axis_value(event, i, mir_touch_axis_pressure)});
942+ }
943+ return true;
944+}
945+
946+void mi::Seat::update_spots()
947+{
948+ spots.clear();
949+ for (auto const& dev : device_data)
950+ spots.insert(end(spots), begin(dev.second.spots), end(dev.second.spots));
951+
952+ touch_visualizer->visualize_touches(spots);
953+}
954+
955+void mi::Seat::update_modifier()
956+{
957+ modifier = std::accumulate(begin(device_data),
958+ end(device_data),
959+ MirInputEventModifiers{0},
960+ [](auto const& acc, auto const& item)
961+ {
962+ return acc | item.second.mod;
963+ });
964+}
965+
966+void mi::Seat::update_cursor(MirPointerEvent const* event)
967+{
968+ cursor_listener->cursor_moved_to(mir_pointer_event_axis_value(event, mir_pointer_axis_x),
969+ mir_pointer_event_axis_value(event, mir_pointer_axis_y));
970+}
971+
972
973=== added file 'src/server/input/seat.h'
974--- src/server/input/seat.h 1970-01-01 00:00:00 +0000
975+++ src/server/input/seat.h 2015-10-14 12:41:48 +0000
976@@ -0,0 +1,72 @@
977+/*
978+ * Copyright © 2015 Canonical Ltd.
979+ *
980+ * This program is free software: you can redistribute it and/or modify it
981+ * under the terms of the GNU General Public License version 3,
982+ * as published by the Free Software Foundation.
983+ *
984+ * This program is distributed in the hope that it will be useful,
985+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
986+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
987+ * GNU General Public License for more details.
988+ *
989+ * You should have received a copy of the GNU General Public License
990+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
991+ *
992+ * Authored by:
993+ * Andreas Pokorny <andreas.pokorny@canonical.com>
994+ */
995+
996+#ifndef MIR_INPUT_DEFAULT_SEAT_H_
997+#define MIR_INPUT_DEFAULT_SEAT_H_
998+
999+#include "mir/input/touch_visualizer.h"
1000+#include "mir_toolkit/event.h"
1001+#include <unordered_map>
1002+#include <memory>
1003+
1004+namespace mir
1005+{
1006+namespace input
1007+{
1008+class CursorListener;
1009+
1010+/*
1011+ * The seat bundles a group of devices. A cursor position, input event modifiers and the visible touch spots are properties
1012+ * controlled by this grouping of input devices.
1013+ */
1014+struct Seat
1015+{
1016+ Seat(std::shared_ptr<TouchVisualizer> const& touch_visualizer, std::shared_ptr<CursorListener> const& cursor_listener);
1017+ void add_device(MirInputDeviceId);
1018+ void remove_device(MirInputDeviceId);
1019+
1020+ MirInputEventModifiers event_modifier() const;
1021+ void update_seat_properties(MirInputEvent const* event);
1022+private:
1023+ void update_cursor(MirPointerEvent const* event);
1024+ void update_spots();
1025+ void update_modifier();
1026+
1027+ std::shared_ptr<TouchVisualizer> const touch_visualizer;
1028+ std::shared_ptr<CursorListener> const cursor_listener;
1029+
1030+ struct DeviceData
1031+ {
1032+ DeviceData() {}
1033+ bool update_modifier(MirKeyboardAction action, int scan_code);
1034+ bool update_spots(MirTouchEvent const* event);
1035+
1036+ MirInputEventModifiers mod{0};
1037+ std::vector<TouchVisualizer::Spot> spots;
1038+ };
1039+
1040+ MirInputEventModifiers modifier;
1041+ std::unordered_map<MirInputDeviceId, DeviceData> device_data;
1042+ std::vector<TouchVisualizer::Spot> spots;
1043+};
1044+
1045+}
1046+}
1047+
1048+#endif
1049
1050=== modified file 'tests/mir_test_framework/fake_input_device_impl.cpp'
1051--- tests/mir_test_framework/fake_input_device_impl.cpp 2015-10-12 08:08:58 +0000
1052+++ tests/mir_test_framework/fake_input_device_impl.cpp 2015-10-14 12:41:48 +0000
1053@@ -25,7 +25,7 @@
1054 #include "mir/input/event_builder.h"
1055 #include "mir/dispatch/action_queue.h"
1056 #include "mir/geometry/displacement.h"
1057-#include "src/platforms/evdev/input_modifier_utils.h"
1058+#include "src/platforms/evdev/button_utils.h"
1059
1060 #include "boost/throw_exception.hpp"
1061
1062@@ -100,13 +100,7 @@
1063 auto input_action =
1064 (key_params.action == synthesis::EventAction::Down) ? mir_keyboard_action_down : mir_keyboard_action_up;
1065
1066- auto event_modifiers = mie::expand_modifiers(modifiers);
1067- auto key_event = builder->key_event(event_time, input_action, key_code, key_params.scancode, event_modifiers);
1068-
1069- if (key_params.action == synthesis::EventAction::Down)
1070- modifiers |= mie::to_modifiers(key_params.scancode);
1071- else
1072- modifiers &= ~mie::to_modifiers(key_params.scancode);
1073+ auto key_event = builder->key_event(event_time, input_action, key_code, key_params.scancode);
1074
1075 if (!sink)
1076 BOOST_THROW_EXCEPTION(std::runtime_error("Device is not started."));
1077@@ -118,9 +112,7 @@
1078 auto event_time = std::chrono::duration_cast<std::chrono::nanoseconds>(
1079 std::chrono::system_clock::now().time_since_epoch());
1080 auto action = update_buttons(button.action, mie::to_pointer_button(button.button));
1081- auto event_modifiers = mie::expand_modifiers(modifiers);
1082 auto button_event = builder->pointer_event(event_time,
1083- event_modifiers,
1084 action,
1085 buttons,
1086 pos.x.as_float(),
1087@@ -156,10 +148,8 @@
1088
1089 auto event_time = std::chrono::duration_cast<std::chrono::nanoseconds>(
1090 std::chrono::system_clock::now().time_since_epoch());
1091- auto event_modifiers = mie::expand_modifiers(modifiers);
1092 update_position(pointer.rel_x, pointer.rel_y);
1093 auto pointer_event = builder->pointer_event(event_time,
1094- event_modifiers,
1095 mir_pointer_action_motion,
1096 buttons,
1097 pos.x.as_float(),
1098@@ -185,9 +175,8 @@
1099
1100 auto event_time = std::chrono::duration_cast<std::chrono::nanoseconds>(
1101 std::chrono::system_clock::now().time_since_epoch());
1102- auto event_modifiers = mie::expand_modifiers(modifiers);
1103
1104- auto touch_event = builder->touch_event(event_time, event_modifiers);
1105+ auto touch_event = builder->touch_event(event_time);
1106
1107 auto touch_action = mir_touch_action_up;
1108 if (touch.action == synthesis::TouchParameters::Action::Tap)
1109
1110=== modified file 'tests/mir_test_framework/fake_input_device_impl.h'
1111--- tests/mir_test_framework/fake_input_device_impl.h 2015-09-01 07:41:29 +0000
1112+++ tests/mir_test_framework/fake_input_device_impl.h 2015-10-14 12:41:48 +0000
1113@@ -73,7 +73,6 @@
1114 mir::input::EventBuilder* builder{nullptr};
1115 mir::input::InputDeviceInfo info;
1116 std::shared_ptr<mir::dispatch::Dispatchable> const queue;
1117- uint32_t modifiers{0};
1118 mir::geometry::Point pos, scroll;
1119 MirPointerButtons buttons;
1120 };
1121
1122=== modified file 'tests/unit-tests/input/evdev/test_libinput_device.cpp'
1123--- tests/unit-tests/input/evdev/test_libinput_device.cpp 2015-10-07 16:41:50 +0000
1124+++ tests/unit-tests/input/evdev/test_libinput_device.cpp 2015-10-14 12:41:48 +0000
1125@@ -73,16 +73,15 @@
1126 mi::DefaultEventBuilder builder{MirInputDeviceId{3}, cookie_factory};
1127 MockEventBuilder()
1128 {
1129- ON_CALL(*this, key_event(_,_,_,_,_))
1130- .WillByDefault(Invoke([this](Timestamp time, MirKeyboardAction action, xkb_keysym_t key, int scan_code,
1131- MirInputEventModifiers modifier)
1132+ ON_CALL(*this, key_event(_,_,_,_))
1133+ .WillByDefault(Invoke([this](Timestamp time, MirKeyboardAction action, xkb_keysym_t key, int scan_code)
1134 {
1135- return builder.key_event(time, action, key, scan_code, modifier);
1136+ return builder.key_event(time, action, key, scan_code);
1137 }));
1138- ON_CALL(*this, touch_event(_,_))
1139- .WillByDefault(Invoke([this](Timestamp time, MirInputEventModifiers modifier)
1140+ ON_CALL(*this, touch_event(_))
1141+ .WillByDefault(Invoke([this](Timestamp time)
1142 {
1143- return builder.touch_event(time, modifier);
1144+ return builder.touch_event(time);
1145 }));
1146 ON_CALL(*this, add_touch(_,_,_,_,_,_,_,_,_,_))
1147 .WillByDefault(Invoke([this](MirEvent& event, MirTouchId id, MirTouchAction action,
1148@@ -92,13 +91,12 @@
1149 return builder.add_touch(event, id, action, tooltype, x, y, major, minor,
1150 pressure, size);
1151 }));
1152- ON_CALL(*this, pointer_event(_,_,_,_,_,_,_,_,_,_))
1153- .WillByDefault(Invoke([this](Timestamp time, MirInputEventModifiers modifier, MirPointerAction action,
1154- MirPointerButtons buttons, float x, float y, float hscroll, float vscroll,
1155- float relative_x, float relative_y)
1156+ ON_CALL(*this, pointer_event(_, _, _, _, _, _, _, _, _))
1157+ .WillByDefault(Invoke([this](Timestamp time, MirPointerAction action, MirPointerButtons buttons, float x,
1158+ float y, float hscroll, float vscroll, float relative_x, float relative_y)
1159 {
1160- return builder.pointer_event(time, modifier, action, buttons, x, y, hscroll,
1161- vscroll, relative_x, relative_y);
1162+ return builder.pointer_event(time, action, buttons, x, y, hscroll, vscroll,
1163+ relative_x, relative_y);
1164 }));
1165 ON_CALL(*this, configuration_event(_,_))
1166 .WillByDefault(Invoke([this](Timestamp time, MirInputConfigurationAction action)
1167@@ -107,14 +105,14 @@
1168 }));
1169 }
1170 using EventBuilder::Timestamp;
1171- MOCK_METHOD5(key_event, mir::EventUPtr(Timestamp, MirKeyboardAction, xkb_keysym_t, int, MirInputEventModifiers));
1172+ MOCK_METHOD4(key_event, mir::EventUPtr(Timestamp, MirKeyboardAction, xkb_keysym_t, int));
1173
1174- MOCK_METHOD2(touch_event, mir::EventUPtr(Timestamp, MirInputEventModifiers));
1175+ MOCK_METHOD1(touch_event, mir::EventUPtr(Timestamp));
1176 MOCK_METHOD10(add_touch, void(MirEvent&, MirTouchId, MirTouchAction, MirTouchTooltype, float, float, float, float,
1177 float, float));
1178
1179- MOCK_METHOD10(pointer_event, mir::EventUPtr(Timestamp, MirInputEventModifiers, MirPointerAction, MirPointerButtons,
1180- float, float, float, float, float, float));
1181+ MOCK_METHOD9(pointer_event, mir::EventUPtr(Timestamp, MirPointerAction, MirPointerButtons, float, float, float,
1182+ float, float, float));
1183 MOCK_METHOD2(configuration_event, mir::EventUPtr(Timestamp, MirInputConfigurationAction));
1184 };
1185
1186@@ -374,9 +372,9 @@
1187 setup_key_event(fake_event_1, event_time_1, KEY_A, LIBINPUT_KEY_STATE_PRESSED);
1188 setup_key_event(fake_event_2, event_time_2, KEY_A, LIBINPUT_KEY_STATE_RELEASED);
1189
1190- EXPECT_CALL(mock_builder, key_event(time_stamp_1, mir_keyboard_action_down, _, KEY_A, mir_input_event_modifier_none));
1191+ EXPECT_CALL(mock_builder, key_event(time_stamp_1, mir_keyboard_action_down, _, KEY_A));
1192 EXPECT_CALL(mock_sink, handle_input(AllOf(mt::KeyOfScanCode(KEY_A),mt::KeyDownEvent())));
1193- EXPECT_CALL(mock_builder, key_event(time_stamp_2, mir_keyboard_action_up, _, KEY_A, mir_input_event_modifier_none));
1194+ EXPECT_CALL(mock_builder, key_event(time_stamp_2, mir_keyboard_action_up, _, KEY_A));
1195 EXPECT_CALL(mock_sink, handle_input(AllOf(mt::KeyOfScanCode(KEY_A),mt::KeyUpEvent())));
1196
1197 dev.start(&mock_sink, &mock_builder);
1198@@ -384,36 +382,6 @@
1199 dev.process_event(fake_event_2);
1200 }
1201
1202-TEST_F(LibInputDevice, process_event_accumulates_key_state)
1203-{
1204- std::shared_ptr<libinput> lib = mie::make_libinput();
1205- mie::LibInputDevice dev(mir::report::null_input_report(), path, mie::make_libinput_device(lib.get(), path));
1206-
1207-
1208- setup_key_event(fake_event_1, event_time_1, KEY_C, LIBINPUT_KEY_STATE_PRESSED);
1209- setup_key_event(fake_event_2, event_time_2, KEY_LEFTALT, LIBINPUT_KEY_STATE_PRESSED);
1210- setup_key_event(fake_event_3, event_time_3, KEY_C, LIBINPUT_KEY_STATE_RELEASED);
1211-
1212- InSequence seq;
1213- EXPECT_CALL(mock_builder, key_event(time_stamp_1, mir_keyboard_action_down, _, KEY_C, mir_input_event_modifier_none));
1214- EXPECT_CALL(mock_sink, handle_input(AllOf(mt::KeyOfScanCode(KEY_C),mt::KeyDownEvent())));
1215- EXPECT_CALL(mock_builder, key_event(time_stamp_2, mir_keyboard_action_down, _, KEY_LEFTALT, mir_input_event_modifier_none));
1216- EXPECT_CALL(mock_sink, handle_input(AllOf(mt::KeyOfScanCode(KEY_LEFTALT),mt::KeyDownEvent())));
1217- EXPECT_CALL(mock_builder, key_event(time_stamp_3, mir_keyboard_action_up, _, KEY_C, mir_input_event_modifier_alt|mir_input_event_modifier_alt_left));
1218- EXPECT_CALL(mock_sink, handle_input(AllOf(mt::KeyOfScanCode(KEY_C),
1219- mt::KeyWithModifiers(
1220- MirInputEventModifiers{
1221- mir_input_event_modifier_alt|
1222- mir_input_event_modifier_alt_left
1223- }),
1224- mt::KeyUpEvent())));
1225-
1226- dev.start(&mock_sink, &mock_builder);
1227- dev.process_event(fake_event_1);
1228- dev.process_event(fake_event_2);
1229- dev.process_event(fake_event_3);
1230-}
1231-
1232 TEST_F(LibInputDevice, process_event_converts_pointer_event)
1233 {
1234 std::shared_ptr<libinput> lib = mie::make_libinput();
1235@@ -499,9 +467,9 @@
1236
1237 InSequence seq;
1238 // expect two scroll events..
1239- EXPECT_CALL(mock_builder, pointer_event(time_stamp_1, mir_input_event_modifier_none, mir_pointer_action_motion, 0, 0.0f, 0.0f, 0.0f, 20.0f, 0.0f, 0.0f));
1240+ EXPECT_CALL(mock_builder, pointer_event(time_stamp_1, mir_pointer_action_motion, 0, 0.0f, 0.0f, 0.0f, 20.0f, 0.0f, 0.0f));
1241 EXPECT_CALL(mock_sink, handle_input(mt::PointerAxisChange(mir_pointer_axis_vscroll, 20.0f)));
1242- EXPECT_CALL(mock_builder, pointer_event(time_stamp_2, mir_input_event_modifier_none, mir_pointer_action_motion, 0, 0.0f, 0.0f, 5.0f, 0.0f, 0.0f, 0.0f));
1243+ EXPECT_CALL(mock_builder, pointer_event(time_stamp_2, mir_pointer_action_motion, 0, 0.0f, 0.0f, 5.0f, 0.0f, 0.0f, 0.0f));
1244 EXPECT_CALL(mock_sink, handle_input(mt::PointerAxisChange(mir_pointer_axis_hscroll, 5.0f)));
1245
1246 dev.start(&mock_sink, &mock_builder);
1247@@ -525,7 +493,7 @@
1248 setup_touch_frame(fake_event_2);
1249
1250 InSequence seq;
1251- EXPECT_CALL(mock_builder, touch_event(time_stamp_1, mir_input_event_modifier_none));
1252+ EXPECT_CALL(mock_builder, touch_event(time_stamp_1));
1253 EXPECT_CALL(mock_builder, add_touch(_, MirTouchId{0}, mir_touch_action_down, mir_touch_tooltype_finger, x, y,
1254 pressure, major, minor, major));
1255 EXPECT_CALL(mock_sink, handle_input(mt::TouchEvent(x,y)));
1256@@ -551,7 +519,7 @@
1257 setup_touch_frame(fake_event_2);
1258
1259 InSequence seq;
1260- EXPECT_CALL(mock_builder, touch_event(time_stamp_1, mir_input_event_modifier_none));
1261+ EXPECT_CALL(mock_builder, touch_event(time_stamp_1));
1262 EXPECT_CALL(mock_builder, add_touch(_, MirTouchId{0}, mir_touch_action_change, mir_touch_tooltype_finger, x, y,
1263 pressure, major, minor, major));
1264 EXPECT_CALL(mock_sink, handle_input(mt::TouchMovementEvent()));
1265@@ -579,12 +547,12 @@
1266 setup_touch_frame(fake_event_4);
1267
1268 InSequence seq;
1269- EXPECT_CALL(mock_builder, touch_event(time_stamp_1, mir_input_event_modifier_none));
1270+ EXPECT_CALL(mock_builder, touch_event(time_stamp_1));
1271 EXPECT_CALL(mock_builder, add_touch(_, MirTouchId{slot}, mir_touch_action_down, mir_touch_tooltype_finger, x, y,
1272 pressure, major, minor, major));
1273 EXPECT_CALL(mock_sink, handle_input(mt::TouchEvent(x,y)));
1274
1275- EXPECT_CALL(mock_builder, touch_event(time_stamp_2, mir_input_event_modifier_none));
1276+ EXPECT_CALL(mock_builder, touch_event(time_stamp_2));
1277 EXPECT_CALL(mock_builder, add_touch(_, MirTouchId{slot}, mir_touch_action_up, mir_touch_tooltype_finger, x, y,
1278 pressure, major, minor, major));
1279 EXPECT_CALL(mock_sink, handle_input(mt::TouchUpEvent(x,y)));
1280
1281=== modified file 'tests/unit-tests/input/test_default_input_device_hub.cpp'
1282--- tests/unit-tests/input/test_default_input_device_hub.cpp 2015-10-07 16:41:50 +0000
1283+++ tests/unit-tests/input/test_default_input_device_hub.cpp 2015-10-14 12:41:48 +0000
1284@@ -268,7 +268,7 @@
1285 observer_loop.trigger_server_actions();
1286
1287 auto event = builder->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0,
1288- KEY_A, mir_input_event_modifier_none);
1289+ KEY_A);
1290
1291 EXPECT_CALL(mock_dispatcher, dispatch(AllOf(mt::InputDeviceIdMatches(handle->id()), mt::MirKeyEventMatches(event.get()))));
1292
1293@@ -287,23 +287,23 @@
1294
1295 observer_loop.trigger_server_actions();
1296
1297- auto touch_event_1 = builder->touch_event(arbitrary_timestamp, mir_input_event_modifier_none);
1298+ auto touch_event_1 = builder->touch_event(arbitrary_timestamp);
1299 builder->add_touch(*touch_event_1, 0, mir_touch_action_down, mir_touch_tooltype_finger, 21.0f, 34.0f, 50.0f, 15.0f,
1300 5.0f, 4.0f);
1301
1302- auto touch_event_2 = builder->touch_event(arbitrary_timestamp, mir_input_event_modifier_none);
1303+ auto touch_event_2 = builder->touch_event(arbitrary_timestamp);
1304 builder->add_touch(*touch_event_2, 0, mir_touch_action_change, mir_touch_tooltype_finger, 24.0f, 34.0f, 50.0f,
1305 15.0f, 5.0f, 4.0f);
1306 builder->add_touch(*touch_event_2, 1, mir_touch_action_down, mir_touch_tooltype_finger, 60.0f, 34.0f, 50.0f, 15.0f,
1307 5.0f, 4.0f);
1308
1309- auto touch_event_3 = builder->touch_event(arbitrary_timestamp, mir_input_event_modifier_none);
1310+ auto touch_event_3 = builder->touch_event(arbitrary_timestamp);
1311 builder->add_touch(*touch_event_3, 0, mir_touch_action_up, mir_touch_tooltype_finger, 24.0f, 34.0f, 50.0f, 15.0f,
1312 5.0f, 4.0f);
1313 builder->add_touch(*touch_event_3, 1, mir_touch_action_change, mir_touch_tooltype_finger, 70.0f, 30.0f, 50.0f,
1314 15.0f, 5.0f, 4.0f);
1315
1316- auto touch_event_4 = builder->touch_event(arbitrary_timestamp, mir_input_event_modifier_none);
1317+ auto touch_event_4 = builder->touch_event(arbitrary_timestamp);
1318 builder->add_touch(*touch_event_4, 1, mir_touch_action_up, mir_touch_tooltype_finger, 70.0f, 35.0f, 50.0f, 15.0f,
1319 5.0f, 4.0f);
1320
1321@@ -372,17 +372,149 @@
1322 using namespace ::testing;
1323
1324 auto x = 12.2f, y = 14.3f;
1325- auto const mac = 0;
1326-
1327- auto event = mir::events::make_event(0, 0ns, mac, mir_input_event_modifier_none, mir_pointer_action_motion, 0,
1328- x, y, 0.0f, 0.0f, 0.0f, 0.0f);
1329+
1330+ mi::InputSink* sink;
1331+ mi::EventBuilder* builder;
1332+ capture_input_sink(device, sink, builder);
1333+ hub.add_device(mt::fake_shared(device));
1334+
1335+ auto event = builder->pointer_event(0ns, mir_pointer_action_motion, 0, x, y, 0.0f, 0.0f, 0.0f, 0.0f);
1336
1337 EXPECT_CALL(mock_cursor_listener, cursor_moved_to(x, y)).Times(1);
1338
1339- mi::InputSink* sink;
1340- mi::EventBuilder* builder;
1341- capture_input_sink(device, sink, builder);
1342- hub.add_device(mt::fake_shared(device));
1343-
1344 sink->handle_input(*event);
1345 }
1346+
1347+TEST_F(InputDeviceHubTest, input_sink_tracks_modifier)
1348+{
1349+ using namespace ::testing;
1350+
1351+ mi::InputSink* key_board_sink;
1352+ mi::EventBuilder* key_event_builder;
1353+ std::shared_ptr<mi::Device> key_handle;
1354+
1355+ capture_input_sink(device, key_board_sink, key_event_builder);
1356+
1357+ InSequence seq;
1358+ EXPECT_CALL(mock_observer,device_added(_))
1359+ .WillOnce(SaveArg<0>(&key_handle));
1360+
1361+ hub.add_observer(mt::fake_shared(mock_observer));
1362+ hub.add_device(mt::fake_shared(device));
1363+
1364+ observer_loop.trigger_server_actions();
1365+
1366+ const MirInputEventModifiers shift_left = mir_input_event_modifier_shift_left | mir_input_event_modifier_shift;
1367+ auto shift_down =
1368+ key_event_builder->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_LEFTSHIFT);
1369+ auto shift_up =
1370+ key_event_builder->key_event(arbitrary_timestamp, mir_keyboard_action_up, 0, KEY_LEFTSHIFT);
1371+
1372+ EXPECT_CALL(mock_dispatcher, dispatch(mt::KeyWithModifiers(shift_left)));
1373+ EXPECT_CALL(mock_dispatcher, dispatch(mt::KeyWithModifiers(mir_input_event_modifier_none)));
1374+
1375+ key_board_sink->handle_input(*shift_down);
1376+ key_board_sink->handle_input(*shift_up);
1377+}
1378+
1379+TEST_F(InputDeviceHubTest, input_sink_unifies_modifier_state_accross_devices)
1380+{
1381+ using namespace ::testing;
1382+
1383+ mi::InputSink* mouse_sink;
1384+ mi::EventBuilder* mouse_event_builder;
1385+ mi::InputSink* key_board_sink;
1386+ mi::EventBuilder* key_event_builder;
1387+ std::shared_ptr<mi::Device> mouse_handle;
1388+ std::shared_ptr<mi::Device> key_handle;
1389+
1390+ capture_input_sink(device, mouse_sink, mouse_event_builder);
1391+ capture_input_sink(another_device, key_board_sink, key_event_builder);
1392+
1393+ InSequence seq;
1394+ EXPECT_CALL(mock_observer,device_added(_))
1395+ .WillOnce(SaveArg<0>(&mouse_handle));
1396+ EXPECT_CALL(mock_observer,device_added(_))
1397+ .WillOnce(SaveArg<0>(&key_handle));
1398+
1399+ hub.add_observer(mt::fake_shared(mock_observer));
1400+ hub.add_device(mt::fake_shared(device));
1401+ hub.add_device(mt::fake_shared(another_device));
1402+
1403+ observer_loop.trigger_server_actions();
1404+
1405+ const MirInputEventModifiers r_alt_modifier = mir_input_event_modifier_alt_right | mir_input_event_modifier_alt;
1406+ auto key =
1407+ key_event_builder->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_RIGHTALT);
1408+ auto motion =
1409+ mouse_event_builder->pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 12, 40, 0, 0, 12, 40);
1410+
1411+ EXPECT_CALL(mock_dispatcher, dispatch(mt::KeyWithModifiers(r_alt_modifier)));
1412+ EXPECT_CALL(mock_dispatcher, dispatch(mt::PointerEventWithModifiers(r_alt_modifier)));
1413+
1414+ key_board_sink->handle_input(*key);
1415+ mouse_sink->handle_input(*motion);
1416+
1417+ EXPECT_THAT(key_handle->id(), Ne(mouse_handle->id()));
1418+}
1419+
1420+TEST_F(InputDeviceHubTest, input_sink_reduces_modifier_state_accross_devices)
1421+{
1422+ using namespace ::testing;
1423+
1424+ mi::InputSink* mouse_sink;
1425+ mi::EventBuilder* mouse_event_builder;
1426+ mi::InputSink* key_board_sink_1;
1427+ mi::EventBuilder* key_event_builder_1;
1428+ mi::InputSink* key_board_sink_2;
1429+ mi::EventBuilder* key_event_builder_2;
1430+ std::shared_ptr<mi::Device> mouse_handle;
1431+ std::shared_ptr<mi::Device> key_handle_1;
1432+ std::shared_ptr<mi::Device> key_handle_2;
1433+
1434+ capture_input_sink(device, mouse_sink, mouse_event_builder);
1435+ capture_input_sink(another_device, key_board_sink_1, key_event_builder_1);
1436+ capture_input_sink(third_device, key_board_sink_2, key_event_builder_2);
1437+
1438+ InSequence seq;
1439+ EXPECT_CALL(mock_observer, device_added(_))
1440+ .WillOnce(SaveArg<0>(&mouse_handle));
1441+ EXPECT_CALL(mock_observer, device_added(_))
1442+ .WillOnce(SaveArg<0>(&key_handle_1));
1443+ EXPECT_CALL(mock_observer, device_added(_))
1444+ .WillOnce(SaveArg<0>(&key_handle_2));
1445+
1446+ hub.add_observer(mt::fake_shared(mock_observer));
1447+ hub.add_device(mt::fake_shared(device));
1448+ hub.add_device(mt::fake_shared(another_device));
1449+ hub.add_device(mt::fake_shared(third_device));
1450+
1451+ const MirInputEventModifiers r_alt_modifier = mir_input_event_modifier_alt_right | mir_input_event_modifier_alt;
1452+ const MirInputEventModifiers l_ctrl_modifier = mir_input_event_modifier_ctrl_left | mir_input_event_modifier_ctrl;
1453+ const MirInputEventModifiers combined_modifier = r_alt_modifier | l_ctrl_modifier;
1454+
1455+ observer_loop.trigger_server_actions();
1456+
1457+ auto alt_down = key_event_builder_1->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_RIGHTALT);
1458+ auto ctrl_down = key_event_builder_2->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_LEFTCTRL);
1459+ auto ctrl_up = key_event_builder_2->key_event(arbitrary_timestamp, mir_keyboard_action_up, 0, KEY_LEFTCTRL);
1460+
1461+ auto motion_1 =
1462+ mouse_event_builder->pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 12, 40, 0, 0, 12, 40);
1463+ auto motion_2 =
1464+ mouse_event_builder->pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 30, 50, 0, 0, 18, 10);
1465+
1466+ EXPECT_CALL(mock_dispatcher, dispatch(mt::KeyWithModifiers(r_alt_modifier)));
1467+ EXPECT_CALL(mock_dispatcher, dispatch(mt::KeyWithModifiers(combined_modifier)));
1468+ EXPECT_CALL(mock_dispatcher, dispatch(mt::PointerEventWithModifiers(combined_modifier)));
1469+ EXPECT_CALL(mock_dispatcher, dispatch(mt::KeyWithModifiers(r_alt_modifier)));
1470+ EXPECT_CALL(mock_dispatcher, dispatch(mt::PointerEventWithModifiers(r_alt_modifier)));
1471+
1472+ key_board_sink_1->handle_input(*alt_down);
1473+ key_board_sink_2->handle_input(*ctrl_down);
1474+ mouse_sink->handle_input(*motion_1);
1475+ key_board_sink_2->handle_input(*ctrl_up);
1476+ mouse_sink->handle_input(*motion_2);
1477+
1478+ EXPECT_THAT(key_handle_1->id(), Ne(key_handle_2->id()));
1479+}

Subscribers

People subscribed via source and target branches