Merge lp:~andreas-pokorny/mir/send-input-device-state-event into lp:mir
- send-input-device-state-event
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | Andreas Pokorny |
Approved revision: | no longer in the source branch. |
Merged at revision: | 3579 |
Proposed branch: | lp:~andreas-pokorny/mir/send-input-device-state-event |
Merge into: | lp:mir |
Prerequisite: | lp:~andreas-pokorny/mir/filter-keys-in-seat |
Diff against target: |
1462 lines (+556/-103) 34 files modified
include/platform/mir/input/event_builder.h (+3/-0) include/platform/mir/input/input_sink.h (+22/-0) include/test/mir/test/event_matchers.h (+32/-0) src/client/input/android/android_input_lexicon.cpp (+6/-0) src/client/input/android/android_input_receiver.cpp (+0/-3) src/client/input/xkb_mapper.cpp (+8/-1) src/include/common/mir/input/key_mapper.h (+1/-0) src/include/common/mir/input/xkb_mapper.h (+2/-2) src/include/server/mir/input/seat.h (+7/-0) src/server/graphics/nested/display_buffer.cpp (+3/-4) src/server/graphics/nested/input_platform.cpp (+58/-19) src/server/input/android/input_sender.cpp (+28/-19) src/server/input/basic_seat.cpp (+23/-2) src/server/input/basic_seat.h (+10/-1) src/server/input/default_configuration.cpp (+2/-1) src/server/input/default_event_builder.cpp (+11/-2) src/server/input/default_event_builder.h (+6/-1) src/server/input/default_input_device_hub.cpp (+26/-3) src/server/input/default_input_device_hub.h (+5/-1) src/server/input/seat_input_device_tracker.cpp (+54/-15) src/server/input/seat_input_device_tracker.h (+12/-1) src/server/server.cpp (+46/-1) src/server/shell/abstract_shell.cpp (+1/-0) tests/acceptance-tests/test_nested_input.cpp (+79/-11) tests/include/mir/test/doubles/mock_input_seat.h (+6/-1) tests/include/mir/test/doubles/mock_input_sink.h (+2/-0) tests/include/mir/test/doubles/mock_key_mapper.h (+1/-0) tests/integration-tests/input/test_single_seat_setup.cpp (+7/-4) tests/unit-tests/input/android/test_android_input_sender.cpp (+44/-2) tests/unit-tests/input/evdev/test_libinput_device.cpp (+10/-1) tests/unit-tests/input/test_nested_input_platform.cpp (+4/-2) tests/unit-tests/input/test_seat_input_device_tracker.cpp (+10/-5) tests/unit-tests/input/test_x11_platform.cpp (+3/-1) tests/unit-tests/scene/test_abstract_shell.cpp (+24/-0) |
To merge this branch: | bzr merge lp:~andreas-pokorny/mir/send-input-device-state-event |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir CI Bot | continuous-integration | Approve | |
Alan Griffiths | Needs Fixing | ||
Kevin DuBois (community) | Approve | ||
Review via email: mp+297062@code.launchpad.net |
Commit message
Make use of the input device state event
AbstractShell sends that event on focus change, the XkbMapper receives that information and used it to update its xkb_state. Additionally the nested input platform forwards that event.
Description of the change
This change now makes use of the new input device state event. The event needs to update the xkb pressed state inside the xkb_mapper, before any further key input events are mapped by the keymapper. So the device state event is sent "on" focus change. "on" because focus is a surface attribute change and because user input has its own queue. It is also necessary for toolkits so that they can redraw menues based on the current modifier state after a focus change.
The handling in nested input platform is a bit special - since input platforms usually do not need to emit an input device state event - but a nested session might be occluded/
This change also includes the ability to add event filters prior to startup. That combined with the input device state event provides a utility to detect that a nested server is up, running, focused and capable of receiving events.
In upcoming branches I plan to use that to avoid some of the unconditional sleeps in our acceptance tests.
Mir CI Bot (mir-ci-bot) wrote : | # |
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3527
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3528
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3529
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3529
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Andreas Pokorny (andreas-pokorny) wrote : | # |
ah there is a shutdown problem shown in one of the nested server tests.
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3530
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3531
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
FAILURE: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:3532
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Kevin DuBois (kdub) wrote : | # |
nits, otherwise, lgtm
16: + virtual EventUPtr device_
Would be nice if Point/X/Y could be stored as a float in those types.
199, 1232,1233:
+ mutable std::mutex guard;
std::mutex mutable guard; is more like other use of mutable or const
150:
extra line
300:
+ [this](MirEvent const& event, mir::geometry:
[this](auto const& event, auto const& area) is a bit shorter
1158:
aligned to tab after commas, should just have one space.
1432:
+TEST_F(
"as_focus_
Kevin DuBois (kdub) wrote : | # |
CI failure was new and in NestedInput*, probably needs some investigation....
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
https:/
Executed test runs:
FAILURE: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3533
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Andreas Pokorny (andreas-pokorny) wrote : | # |
CI Problem while setting up krillin ^
22:10:51 Slave went offline during the build
22:10:51 ERROR: Connection was broken: java.io.
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3533
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Andreas Pokorny (andreas-pokorny) wrote : | # |
Another problem with the krillin, now while flashing the device:
06:14:39 WARNING:root:Unable to mark device offline automatically
06:14:39 Traceback (most recent call last):
06:14:39 File "./recover", line 124, in <module>
06:14:39 print(recover(
06:14:39 File "./recover", line 114, in recover
06:14:39 return _full_recovery(
06:14:39 File "./recover", line 24, in _full_recovery
06:14:39 device.
06:14:39 File "/var/lib/
06:14:39 subprocess.
06:14:39 File "/usr/lib/
06:14:39 raise CalledProcessEr
06:14:39 subprocess.
06:14:40 Build step 'Execute shell' marked build as failure
06:14:41 Archiving artifacts
06:14:44 [WS-CLEANUP] Deleting project workspace.
06:14:44 Finished: FAILURE
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:3533
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Alan Griffiths (alan-griffiths) wrote : | # |
Nits:
+#include "mir/events/
this isn't needed by the header (or any of the files that include it).
~~~~
+ /**
+ * Set all pressed scan codes.
+ * \param scan_codes currently pressed
+ */
+ virtual void set_key_
+ /**
+ * Set button state of a pointing device.
+ * \param buttons mask of the buttons currently pressed
+ */
+ virtual void set_pointer_
These names seem a little odd for an InputSink. (Maybe it is just my experience with C# and Java suggesting "set_" implies these are properties.) Anyway, "key_state()" or "key_state_is()" would be better than "set_key_state()"
~~~~
- std::mutex guard;
+ mutable std::mutex guard;
We put the cv-qualifier after the type:
std::mutex mutable guard;
~~~~
+#include "mir/event_
Needed?
Mir CI Bot (mir-ci-bot) : | # |
Andreas Pokorny (andreas-pokorny) wrote : | # |
> Nits:
>
> +#include "mir/events/
>
> this isn't needed by the header (or any of the files that include it).
>
> ~~~~
>
> + /**
> + * Set all pressed scan codes.
> + * \param scan_codes currently pressed
> + */
> + virtual void set_key_
> + /**
> + * Set button state of a pointing device.
> + * \param buttons mask of the buttons currently pressed
> + */
> + virtual void set_pointer_
>
> These names seem a little odd for an InputSink. (Maybe it is just my
> experience with C# and Java suggesting "set_" implies these are properties.)
> Anyway, "key_state()" or "key_state_is()" would be better than
> "set_key_state()"
>
> ~~~~
>
> - std::mutex guard;
> + mutable std::mutex guard;
>
> We put the cv-qualifier after the type:
>
> std::mutex mutable guard;
>
> ~~~~
>
> +#include "mir/event_
>
> Needed?
Nah all of that is valid, also fixed what kdub complained about. If the MP lands, I am going to prepare that in a new MP
Preview Diff
1 | === modified file 'include/platform/mir/input/event_builder.h' |
2 | --- include/platform/mir/input/event_builder.h 2016-01-29 08:18:22 +0000 |
3 | +++ include/platform/mir/input/event_builder.h 2016-07-06 21:48:16 +0000 |
4 | @@ -21,6 +21,7 @@ |
5 | #define MIR_INPUT_EVENT_BUILDER_H_ |
6 | |
7 | #include "mir_toolkit/event.h" |
8 | +#include "mir/events/event_builders.h" |
9 | #include <memory> |
10 | #include <chrono> |
11 | |
12 | @@ -51,6 +52,8 @@ |
13 | |
14 | virtual EventUPtr configuration_event(Timestamp timestamp, MirInputConfigurationAction action) = 0; |
15 | |
16 | + virtual EventUPtr device_state_event(float cursor_x, float cursor_y) = 0; |
17 | + |
18 | protected: |
19 | EventBuilder(EventBuilder const&) = delete; |
20 | EventBuilder& operator=(EventBuilder const&) = delete; |
21 | |
22 | === modified file 'include/platform/mir/input/input_sink.h' |
23 | --- include/platform/mir/input/input_sink.h 2016-01-29 08:18:22 +0000 |
24 | +++ include/platform/mir/input/input_sink.h 2016-07-06 21:48:16 +0000 |
25 | @@ -24,6 +24,8 @@ |
26 | #include "mir/geometry/rectangle.h" |
27 | #include "mir/geometry/displacement.h" |
28 | |
29 | +#include <vector> |
30 | + |
31 | namespace mir |
32 | { |
33 | namespace input |
34 | @@ -39,6 +41,26 @@ |
35 | */ |
36 | virtual mir::geometry::Rectangle bounding_rectangle() const = 0; |
37 | |
38 | + /** |
39 | + * \name Device State interface of InputSink |
40 | + * |
41 | + * In scenarios in which the device is not capable of seeing all changes as they occur, |
42 | + * these method should be used to update the input device state as needed |
43 | + * \{ |
44 | + */ |
45 | + /** |
46 | + * Set all pressed scan codes. |
47 | + * \param scan_codes currently pressed |
48 | + */ |
49 | + virtual void set_key_state(std::vector<uint32_t> const& scan_codes) = 0; |
50 | + /** |
51 | + * Set button state of a pointing device. |
52 | + * \param buttons mask of the buttons currently pressed |
53 | + */ |
54 | + virtual void set_pointer_state(MirPointerButtons buttons) = 0; |
55 | + /** |
56 | + * \} |
57 | + */ |
58 | private: |
59 | InputSink(InputSink const&) = delete; |
60 | InputSink& operator=(InputSink const&) = delete; |
61 | |
62 | === modified file 'include/test/mir/test/event_matchers.h' |
63 | --- include/test/mir/test/event_matchers.h 2016-05-03 06:55:25 +0000 |
64 | +++ include/test/mir/test/event_matchers.h 2016-07-06 21:48:16 +0000 |
65 | @@ -503,6 +503,38 @@ |
66 | return false; |
67 | } |
68 | |
69 | +MATCHER(InputDeviceStateEvent, "") |
70 | +{ |
71 | + auto as_address = to_address(arg); |
72 | + if (mir_event_get_type(as_address) == mir_event_type_input_device_state) |
73 | + return true; |
74 | + return false; |
75 | +} |
76 | + |
77 | +MATCHER_P(DeviceStateWithPressedKeys, keys, "") |
78 | +{ |
79 | + auto as_address = to_address(arg); |
80 | + if (mir_event_get_type(as_address) != mir_event_type_input_device_state) |
81 | + return false; |
82 | + auto device_state = mir_event_get_input_device_state_event(as_address); |
83 | + for (size_t index = 0, count = mir_input_device_state_event_device_count(device_state); |
84 | + index != count; ++index) |
85 | + { |
86 | + auto key_count = mir_input_device_state_event_device_pressed_keys_count(device_state, index); |
87 | + auto it_keys = begin(keys); |
88 | + auto end_keys = end(keys); |
89 | + decltype(key_count) num_required_keys = distance(it_keys, end_keys); |
90 | + if (num_required_keys != key_count) |
91 | + continue; |
92 | + |
93 | + auto pressed_keys = mir_input_device_state_event_device_pressed_keys(device_state, index); |
94 | + if (!std::equal(it_keys, end_keys, pressed_keys)) |
95 | + continue; |
96 | + return true; |
97 | + } |
98 | + return false; |
99 | +} |
100 | + |
101 | MATCHER(InputDeviceConfigurationChangedEvent, "") |
102 | { |
103 | auto as_address = to_address(arg); |
104 | |
105 | === modified file 'src/client/input/android/android_input_lexicon.cpp' |
106 | --- src/client/input/android/android_input_lexicon.cpp 2016-01-29 08:18:22 +0000 |
107 | +++ src/client/input/android/android_input_lexicon.cpp 2016-07-06 21:48:16 +0000 |
108 | @@ -20,6 +20,7 @@ |
109 | #include "mir/input/android/android_input_lexicon.h" |
110 | #include "mir/input/android/event_conversion_helpers.h" |
111 | #include "mir/events/event_builders.h" |
112 | +#include "mir/events/event.h" |
113 | #include "mir/cookie/blob.h" |
114 | |
115 | #include <androidfw/Input.h> |
116 | @@ -36,6 +37,11 @@ |
117 | { |
118 | switch(android_event->getType()) |
119 | { |
120 | + case AINPUT_EVENT_TYPE_BUFFER: |
121 | + { |
122 | + auto buf = static_cast<const droidinput::RawBufferEvent*>(android_event); |
123 | + return MirEvent::deserialize(buf->buffer); |
124 | + } |
125 | case AINPUT_EVENT_TYPE_KEY: |
126 | { |
127 | auto kev = static_cast<const droidinput::KeyEvent*>(android_event); |
128 | |
129 | === modified file 'src/client/input/android/android_input_receiver.cpp' |
130 | --- src/client/input/android/android_input_receiver.cpp 2016-06-09 18:38:05 +0000 |
131 | +++ src/client/input/android/android_input_receiver.cpp 2016-07-06 21:48:16 +0000 |
132 | @@ -132,9 +132,6 @@ |
133 | // of XKBMapper per device id (or modify XKBMapper semantics) |
134 | if (mir_event_get_type(&ev) != mir_event_type_input) |
135 | return; |
136 | - if (mir_input_event_get_type(mir_event_get_input_event(&ev)) != |
137 | - mir_input_event_type_key) |
138 | - return; |
139 | |
140 | xkb_mapper->map_event(ev); |
141 | } |
142 | |
143 | === modified file 'src/client/input/xkb_mapper.cpp' |
144 | --- src/client/input/xkb_mapper.cpp 2016-06-24 06:43:18 +0000 |
145 | +++ src/client/input/xkb_mapper.cpp 2016-07-06 21:48:16 +0000 |
146 | @@ -76,7 +76,6 @@ |
147 | // xkb scancodes are offset by 8 from evdev scancodes for compatibility with X protocol. |
148 | return evdev_scan_code + 8; |
149 | } |
150 | - |
151 | } |
152 | |
153 | mi::XKBContextPtr mi::make_unique_context() |
154 | @@ -232,6 +231,14 @@ |
155 | update_modifier(); |
156 | } |
157 | |
158 | +MirInputEventModifiers mircv::XKBMapper::modifiers() const |
159 | +{ |
160 | + std::lock_guard<std::mutex> lg(guard); |
161 | + if (modifier_state.is_set()) |
162 | + return expand_modifiers(modifier_state.value()); |
163 | + return mir_input_event_modifier_none; |
164 | +} |
165 | + |
166 | mircv::XKBMapper::XkbMappingState::XkbMappingState(std::shared_ptr<xkb_keymap> const& keymap) |
167 | : keymap{keymap}, state{make_unique_state(this->keymap.get())} |
168 | { |
169 | |
170 | === modified file 'src/include/common/mir/input/key_mapper.h' |
171 | --- src/include/common/mir/input/key_mapper.h 2016-06-23 15:09:02 +0000 |
172 | +++ src/include/common/mir/input/key_mapper.h 2016-07-06 21:48:16 +0000 |
173 | @@ -88,6 +88,7 @@ |
174 | * masks in input events with the modifier mask evaluated by this Keymapper. |
175 | */ |
176 | virtual void map_event(MirEvent& event) = 0; |
177 | + virtual MirInputEventModifiers modifiers() const = 0; |
178 | |
179 | protected: |
180 | KeyMapper(KeyMapper const&) = delete; |
181 | |
182 | === modified file 'src/include/common/mir/input/xkb_mapper.h' |
183 | --- src/include/common/mir/input/xkb_mapper.h 2016-06-24 06:43:18 +0000 |
184 | +++ src/include/common/mir/input/xkb_mapper.h 2016-07-06 21:48:16 +0000 |
185 | @@ -58,7 +58,7 @@ |
186 | void clear_keymap_for_device(MirInputDeviceId id) override; |
187 | void clear_all_keymaps() override; |
188 | void map_event(MirEvent& event) override; |
189 | - |
190 | + MirInputEventModifiers modifiers() const override; |
191 | |
192 | protected: |
193 | XKBMapper(XKBMapper const&) = delete; |
194 | @@ -69,7 +69,7 @@ |
195 | void set_keymap(XKBKeymapPtr map); |
196 | void update_modifier(); |
197 | |
198 | - std::mutex guard; |
199 | + mutable std::mutex guard; |
200 | |
201 | struct XkbMappingState |
202 | { |
203 | |
204 | === modified file 'src/include/server/mir/input/seat.h' |
205 | --- src/include/server/mir/input/seat.h 2016-06-20 17:10:33 +0000 |
206 | +++ src/include/server/mir/input/seat.h 2016-07-06 21:48:16 +0000 |
207 | @@ -25,9 +25,11 @@ |
208 | #include "mir_toolkit/event.h" |
209 | |
210 | #include <memory> |
211 | +#include <vector> |
212 | |
213 | namespace mir |
214 | { |
215 | +using EventUPtr = std::unique_ptr<MirEvent, void(*)(MirEvent*)>; |
216 | namespace input |
217 | { |
218 | class Device; |
219 | @@ -40,6 +42,11 @@ |
220 | virtual void remove_device(Device const& device) = 0; |
221 | virtual void dispatch_event(MirEvent& event) = 0; |
222 | virtual geometry::Rectangle get_rectangle_for(Device const& dev) = 0; |
223 | + virtual EventUPtr create_device_state() = 0; |
224 | + |
225 | + virtual void set_key_state(Device const& dev, std::vector<uint32_t> const& scan_codes) = 0; |
226 | + virtual void set_pointer_state(Device const& dev, MirPointerButtons buttons) = 0; |
227 | + virtual void set_cursor_position(float cursor_x, float cursor_y) = 0; |
228 | virtual void set_confinement_regions(geometry::Rectangles const& regions) = 0; |
229 | virtual void reset_confinement_regions() = 0; |
230 | private: |
231 | |
232 | === modified file 'src/server/graphics/nested/display_buffer.cpp' |
233 | --- src/server/graphics/nested/display_buffer.cpp 2016-06-09 13:15:34 +0000 |
234 | +++ src/server/graphics/nested/display_buffer.cpp 2016-07-06 21:48:16 +0000 |
235 | @@ -110,10 +110,9 @@ |
236 | |
237 | void mgn::detail::DisplayBuffer::mir_event(MirEvent const& event) |
238 | { |
239 | - if (mir_event_get_type(&event) != mir_event_type_input) |
240 | - return; |
241 | - |
242 | - host_connection->emit_input_event(event, area); |
243 | + if (mir_event_get_type(&event) == mir_event_type_input || |
244 | + mir_event_get_type(&event) == mir_event_type_input_device_state) |
245 | + host_connection->emit_input_event(event, area); |
246 | } |
247 | |
248 | mg::NativeDisplayBuffer* mgn::detail::DisplayBuffer::native_display_buffer() |
249 | |
250 | === modified file 'src/server/graphics/nested/input_platform.cpp' |
251 | --- src/server/graphics/nested/input_platform.cpp 2016-06-07 16:20:53 +0000 |
252 | +++ src/server/graphics/nested/input_platform.cpp 2016-07-06 21:48:16 +0000 |
253 | @@ -31,6 +31,7 @@ |
254 | #include "mir/dispatch/action_queue.h" |
255 | #include "mir/events/event_builders.h" |
256 | #include "mir/events/event_private.h" |
257 | +#include "mir/event_printer.h" |
258 | |
259 | #include <chrono> |
260 | |
261 | @@ -107,13 +108,14 @@ |
262 | case mir_input_event_type_key: |
263 | { |
264 | auto const* key_event = mir_input_event_get_keyboard_event(event); |
265 | - destination->handle_input(*builder->key_event( |
266 | + |
267 | + auto new_kev = builder->key_event( |
268 | event_time, |
269 | mir_keyboard_event_action(key_event), |
270 | mir_keyboard_event_key_code(key_event), |
271 | mir_keyboard_event_scan_code(key_event) |
272 | - )); |
273 | - |
274 | + ); |
275 | + destination->handle_input(*new_kev); |
276 | break; |
277 | } |
278 | case mir_input_event_type_pointer: |
279 | @@ -209,28 +211,65 @@ |
280 | action_queue->enqueue([this]{update_devices();}); |
281 | }); |
282 | |
283 | - connection->set_input_event_callback([this](MirEvent const& event, mir::geometry::Rectangle const& area) { |
284 | - auto const* input_ev = mir_event_get_input_event(&event); |
285 | - auto const id = mir_input_event_get_device_id(input_ev); |
286 | - auto it = devices.find(id); |
287 | - if (it != end(devices)) |
288 | - { |
289 | - it->second->emit_event(input_ev, area); |
290 | - } |
291 | - else // device was not advertised to us yet. |
292 | - { |
293 | - unknown_device_events[id].emplace_back( |
294 | - std::piecewise_construct, |
295 | - std::forward_as_tuple(event.clone(), [](MirEvent* e){delete e;}), |
296 | - std::forward_as_tuple(area)); |
297 | - } |
298 | - }); |
299 | + connection->set_input_event_callback( |
300 | + [this](MirEvent const& event, mir::geometry::Rectangle const& area) |
301 | + { |
302 | + auto const event_type = mir_event_get_type(&event); |
303 | + |
304 | + if (event_type == mir_event_type_input) |
305 | + { |
306 | + auto const* input_ev = mir_event_get_input_event(&event); |
307 | + auto const id = mir_input_event_get_device_id(input_ev); |
308 | + auto it = devices.find(id); |
309 | + if (it != end(devices)) |
310 | + { |
311 | + it->second->emit_event(input_ev, area); |
312 | + } |
313 | + else // device was not advertised to us yet. |
314 | + { |
315 | + unknown_device_events[id].emplace_back( |
316 | + std::piecewise_construct, |
317 | + std::forward_as_tuple(event.clone(), [](MirEvent* e){delete e;}), |
318 | + std::forward_as_tuple(area)); |
319 | + } |
320 | + } |
321 | + else if (event_type == mir_event_type_input_device_state) |
322 | + { |
323 | + if (!devices.empty()) |
324 | + { |
325 | + auto const* device_state = mir_event_get_input_device_state_event(&event); |
326 | + for (size_t index = 0, end_index = mir_input_device_state_event_device_count(device_state); |
327 | + index != end_index; ++index) |
328 | + { |
329 | + auto it = devices.find(mir_input_device_state_event_device_id(device_state, index)); |
330 | + if (it != end(devices) && it->second->destination) |
331 | + { |
332 | + auto dest = it->second->destination; |
333 | + auto key_count = mir_input_device_state_event_device_pressed_keys_count(device_state, index); |
334 | + auto const* scan_codes = mir_input_device_state_event_device_pressed_keys(device_state, index); |
335 | + |
336 | + dest->set_key_state({scan_codes, scan_codes + key_count}); |
337 | + dest->set_pointer_state( |
338 | + mir_input_device_state_event_device_pointer_buttons(device_state, index)); |
339 | + } |
340 | + } |
341 | + |
342 | + auto& front = begin(devices)->second; |
343 | + auto device_state_event = front->builder->device_state_event( |
344 | + mir_input_device_state_event_pointer_axis(device_state, mir_pointer_axis_x), |
345 | + mir_input_device_state_event_pointer_axis(device_state, mir_pointer_axis_y)); |
346 | + front->destination->handle_input(*device_state_event); |
347 | + } |
348 | + } |
349 | + }); |
350 | } |
351 | |
352 | void mgn::InputPlatform::stop() |
353 | { |
354 | std::function<void(mgn::UniqueInputConfig)> reset; |
355 | connection->set_input_device_change_callback(reset); |
356 | + std::function<void(MirEvent const&, mir::geometry::Rectangle const&)> empty_event_callback; |
357 | + connection->set_input_event_callback(empty_event_callback); |
358 | |
359 | for(auto const& device : devices) |
360 | input_device_registry->remove_device(device.second); |
361 | |
362 | === modified file 'src/server/input/android/input_sender.cpp' |
363 | --- src/server/input/android/input_sender.cpp 2016-05-03 06:55:25 +0000 |
364 | +++ src/server/input/android/input_sender.cpp 2016-07-06 21:48:16 +0000 |
365 | @@ -163,29 +163,38 @@ |
366 | |
367 | void mia::InputSender::ActiveTransfer::send(uint32_t sequence_id, MirEvent const& event) |
368 | { |
369 | - if (mir_event_get_type(&event) != mir_event_type_input) |
370 | + auto const type = mir_event_get_type(&event); |
371 | + |
372 | + if (type != mir_event_type_input_device_state && type != mir_event_type_input) |
373 | return; |
374 | |
375 | droidinput::status_t error_status; |
376 | |
377 | - auto event_time = mir_input_event_get_event_time(mir_event_get_input_event(&event)); |
378 | - auto input_event = mir_event_get_input_event(&event); |
379 | - switch(mir_input_event_get_type(input_event)) |
380 | - { |
381 | - case mir_input_event_type_key: |
382 | - error_status = send_key_event(sequence_id, event); |
383 | - state.report->published_key_event(channel->server_fd(), sequence_id, event_time); |
384 | - break; |
385 | - case mir_input_event_type_touch: |
386 | - error_status = send_touch_event(sequence_id, event); |
387 | - state.report->published_motion_event(channel->server_fd(), sequence_id, event_time); |
388 | - break; |
389 | - case mir_input_event_type_pointer: |
390 | - error_status = send_pointer_event(sequence_id, event); |
391 | - state.report->published_motion_event(channel->server_fd(), sequence_id, event_time); |
392 | - break; |
393 | - default: |
394 | - BOOST_THROW_EXCEPTION(std::runtime_error("unknown input event type")); |
395 | + if (type == mir_event_type_input) |
396 | + { |
397 | + auto event_time = mir_input_event_get_event_time(mir_event_get_input_event(&event)); |
398 | + auto input_event = mir_event_get_input_event(&event); |
399 | + switch(mir_input_event_get_type(input_event)) |
400 | + { |
401 | + case mir_input_event_type_key: |
402 | + error_status = send_key_event(sequence_id, event); |
403 | + state.report->published_key_event(channel->server_fd(), sequence_id, event_time); |
404 | + break; |
405 | + case mir_input_event_type_touch: |
406 | + error_status = send_touch_event(sequence_id, event); |
407 | + state.report->published_motion_event(channel->server_fd(), sequence_id, event_time); |
408 | + break; |
409 | + case mir_input_event_type_pointer: |
410 | + error_status = send_pointer_event(sequence_id, event); |
411 | + state.report->published_motion_event(channel->server_fd(), sequence_id, event_time); |
412 | + break; |
413 | + default: |
414 | + BOOST_THROW_EXCEPTION(std::runtime_error("unknown input event type")); |
415 | + } |
416 | + } |
417 | + else |
418 | + { |
419 | + error_status = publisher.publishEventBuffer(sequence_id, MirEvent::serialize(&event)); |
420 | } |
421 | |
422 | switch(error_status) |
423 | |
424 | === modified file 'src/server/input/basic_seat.cpp' |
425 | --- src/server/input/basic_seat.cpp 2016-06-28 13:19:50 +0000 |
426 | +++ src/server/input/basic_seat.cpp 2016-07-06 21:48:16 +0000 |
427 | @@ -30,8 +30,9 @@ |
428 | std::shared_ptr<mi::TouchVisualizer> const& touch_visualizer, |
429 | std::shared_ptr<mi::CursorListener> const& cursor_listener, |
430 | std::shared_ptr<mi::InputRegion> const& input_region, |
431 | - std::shared_ptr<mi::KeyMapper> const& key_mapper) |
432 | - : input_state_tracker{dispatcher, touch_visualizer, cursor_listener, input_region, key_mapper}, input_region{input_region} |
433 | + std::shared_ptr<mi::KeyMapper> const& key_mapper, |
434 | + std::shared_ptr<time::Clock> const& clock) |
435 | + : input_state_tracker{dispatcher, touch_visualizer, cursor_listener, input_region, key_mapper, clock}, input_region{input_region} |
436 | { |
437 | } |
438 | |
439 | @@ -59,6 +60,26 @@ |
440 | return input_region->bounding_rectangle(); |
441 | } |
442 | |
443 | +mir::EventUPtr mi::BasicSeat::create_device_state() |
444 | +{ |
445 | + return input_state_tracker.create_device_state(); |
446 | +} |
447 | + |
448 | +void mi::BasicSeat::set_key_state(Device const& dev, std::vector<uint32_t> const& scan_codes) |
449 | +{ |
450 | + input_state_tracker.set_key_state(dev.id(), scan_codes); |
451 | +} |
452 | + |
453 | +void mi::BasicSeat::set_pointer_state(Device const& dev, MirPointerButtons buttons) |
454 | +{ |
455 | + input_state_tracker.set_pointer_state(dev.id(), buttons); |
456 | +} |
457 | + |
458 | +void mi::BasicSeat::set_cursor_position(float cursor_x, float cursor_y) |
459 | +{ |
460 | + input_state_tracker.set_cursor_position(cursor_x, cursor_y); |
461 | +} |
462 | + |
463 | void mi::BasicSeat::set_confinement_regions(geometry::Rectangles const& regions) |
464 | { |
465 | input_state_tracker.set_confinement_regions(regions); |
466 | |
467 | === modified file 'src/server/input/basic_seat.h' |
468 | --- src/server/input/basic_seat.h 2016-06-28 13:19:50 +0000 |
469 | +++ src/server/input/basic_seat.h 2016-07-06 21:48:16 +0000 |
470 | @@ -28,6 +28,10 @@ |
471 | |
472 | namespace mir |
473 | { |
474 | +namespace time |
475 | +{ |
476 | +class Clock; |
477 | +} |
478 | namespace input |
479 | { |
480 | class TouchVisualizer; |
481 | @@ -43,15 +47,20 @@ |
482 | std::shared_ptr<TouchVisualizer> const& touch_visualizer, |
483 | std::shared_ptr<CursorListener> const& cursor_listener, |
484 | std::shared_ptr<InputRegion> const& input_region, |
485 | - std::shared_ptr<KeyMapper> const& key_mapper); |
486 | + std::shared_ptr<KeyMapper> const& key_mapper, |
487 | + std::shared_ptr<time::Clock> const& clock); |
488 | // Seat methods: |
489 | void add_device(Device const& device) override; |
490 | void remove_device(Device const& device) override; |
491 | void dispatch_event(MirEvent& event) override; |
492 | geometry::Rectangle get_rectangle_for(Device const& dev) override; |
493 | + virtual EventUPtr create_device_state() override; |
494 | virtual void set_confinement_regions(geometry::Rectangles const& regions) override; |
495 | virtual void reset_confinement_regions() override; |
496 | |
497 | + void set_key_state(Device const& dev, std::vector<uint32_t> const& scan_codes) override; |
498 | + void set_pointer_state(Device const& dev, MirPointerButtons buttons) override; |
499 | + void set_cursor_position(float cursor_x, float cursor_y) override; |
500 | private: |
501 | SeatInputDeviceTracker input_state_tracker; |
502 | std::shared_ptr<InputRegion> const input_region; |
503 | |
504 | === modified file 'src/server/input/default_configuration.cpp' |
505 | --- src/server/input/default_configuration.cpp 2016-06-02 08:20:22 +0000 |
506 | +++ src/server/input/default_configuration.cpp 2016-07-06 21:48:16 +0000 |
507 | @@ -332,7 +332,8 @@ |
508 | the_touch_visualizer(), |
509 | the_cursor_listener(), |
510 | the_input_region(), |
511 | - the_key_mapper()); |
512 | + the_key_mapper(), |
513 | + the_clock()); |
514 | }); |
515 | } |
516 | |
517 | |
518 | === modified file 'src/server/input/default_event_builder.cpp' |
519 | --- src/server/input/default_event_builder.cpp 2016-05-03 06:55:25 +0000 |
520 | +++ src/server/input/default_event_builder.cpp 2016-07-06 21:48:16 +0000 |
521 | @@ -18,6 +18,7 @@ |
522 | */ |
523 | |
524 | #include "default_event_builder.h" |
525 | +#include "mir/input/seat.h" |
526 | #include "mir/events/event_builders.h" |
527 | #include "mir/cookie/authority.h" |
528 | #include "mir/events/event_private.h" |
529 | @@ -28,9 +29,11 @@ |
530 | namespace mi = mir::input; |
531 | |
532 | mi::DefaultEventBuilder::DefaultEventBuilder(MirInputDeviceId device_id, |
533 | - std::shared_ptr<mir::cookie::Authority> const& cookie_authority) |
534 | + std::shared_ptr<mir::cookie::Authority> const& cookie_authority, |
535 | + std::shared_ptr<mi::Seat> const& seat) |
536 | : device_id(device_id), |
537 | - cookie_authority(cookie_authority) |
538 | + cookie_authority(cookie_authority), |
539 | + seat(seat) |
540 | { |
541 | } |
542 | |
543 | @@ -86,3 +89,9 @@ |
544 | { |
545 | return me::make_event(action, device_id, timestamp); |
546 | } |
547 | + |
548 | +mir::EventUPtr mi::DefaultEventBuilder::device_state_event(float cursor_x, float cursor_y) |
549 | +{ |
550 | + seat->set_cursor_position(cursor_x, cursor_y); |
551 | + return seat->create_device_state(); |
552 | +} |
553 | |
554 | === modified file 'src/server/input/default_event_builder.h' |
555 | --- src/server/input/default_event_builder.h 2016-01-29 08:18:22 +0000 |
556 | +++ src/server/input/default_event_builder.h 2016-07-06 21:48:16 +0000 |
557 | @@ -31,11 +31,14 @@ |
558 | } |
559 | namespace input |
560 | { |
561 | +class Seat; |
562 | + |
563 | class DefaultEventBuilder : public EventBuilder |
564 | { |
565 | public: |
566 | explicit DefaultEventBuilder(MirInputDeviceId device_id, |
567 | - std::shared_ptr<cookie::Authority> const& cookie_authority); |
568 | + std::shared_ptr<cookie::Authority> const& cookie_authority, |
569 | + std::shared_ptr<Seat> const& seat); |
570 | |
571 | EventUPtr key_event(Timestamp timestamp, MirKeyboardAction action, xkb_keysym_t key_code, int scan_code) override; |
572 | |
573 | @@ -50,9 +53,11 @@ |
574 | |
575 | EventUPtr configuration_event(Timestamp timestamp, MirInputConfigurationAction action) override; |
576 | |
577 | + EventUPtr device_state_event(float cursor_x, float cursor_y) override; |
578 | private: |
579 | MirInputDeviceId const device_id; |
580 | std::shared_ptr<cookie::Authority> const cookie_authority; |
581 | + std::shared_ptr<Seat> const seat; |
582 | }; |
583 | } |
584 | } |
585 | |
586 | === modified file 'src/server/input/default_input_device_hub.cpp' |
587 | --- src/server/input/default_input_device_hub.cpp 2016-06-02 08:20:22 +0000 |
588 | +++ src/server/input/default_input_device_hub.cpp 2016-07-06 21:48:16 +0000 |
589 | @@ -142,7 +142,11 @@ |
590 | std::shared_ptr<dispatch::MultiplexingDispatchable> const& multiplexer, |
591 | std::shared_ptr<mir::cookie::Authority> const& cookie_authority, |
592 | std::shared_ptr<mi::DefaultDevice> const& handle) |
593 | - : handle(handle), device_id(device_id), builder(device_id, cookie_authority), device(dev), multiplexer(multiplexer) |
594 | + : handle(handle), |
595 | + device_id(device_id), |
596 | + cookie_authority(cookie_authority), |
597 | + device(dev), |
598 | + multiplexer(multiplexer) |
599 | { |
600 | } |
601 | |
602 | @@ -160,7 +164,8 @@ |
603 | { |
604 | auto type = mir_event_get_type(&event); |
605 | |
606 | - if (type != mir_event_type_input) |
607 | + if (type != mir_event_type_input && |
608 | + type != mir_event_type_input_device_state) |
609 | BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid input event received from device")); |
610 | |
611 | if (!seat) |
612 | @@ -177,13 +182,15 @@ |
613 | void mi::DefaultInputDeviceHub::RegisteredDevice::start(std::shared_ptr<Seat> const& seat) |
614 | { |
615 | this->seat = seat; |
616 | - device->start(this, &builder); |
617 | + builder = std::make_unique<DefaultEventBuilder>(device_id, cookie_authority, seat); |
618 | + device->start(this, builder.get()); |
619 | } |
620 | |
621 | void mi::DefaultInputDeviceHub::RegisteredDevice::stop() |
622 | { |
623 | device->stop(); |
624 | seat = nullptr; |
625 | + builder.reset(); |
626 | } |
627 | |
628 | mir::geometry::Rectangle mi::DefaultInputDeviceHub::RegisteredDevice::bounding_rectangle() const |
629 | @@ -194,6 +201,22 @@ |
630 | return seat->get_rectangle_for(*handle); |
631 | } |
632 | |
633 | +void mi::DefaultInputDeviceHub::RegisteredDevice::set_key_state(std::vector<uint32_t> const& scan_codes) |
634 | +{ |
635 | + if (!seat) |
636 | + BOOST_THROW_EXCEPTION(std::runtime_error("Device not started and has no seat assigned")); |
637 | + |
638 | + seat->set_key_state(*handle, scan_codes); |
639 | +} |
640 | + |
641 | +void mi::DefaultInputDeviceHub::RegisteredDevice::set_pointer_state(MirPointerButtons buttons) |
642 | +{ |
643 | + if (!seat) |
644 | + BOOST_THROW_EXCEPTION(std::runtime_error("Device not started and has no seat assigned")); |
645 | + |
646 | + seat->set_pointer_state(*handle, buttons); |
647 | +} |
648 | + |
649 | void mi::DefaultInputDeviceHub::add_observer(std::shared_ptr<InputDeviceObserver> const& observer) |
650 | { |
651 | observer_queue->enqueue( |
652 | |
653 | === modified file 'src/server/input/default_input_device_hub.h' |
654 | --- src/server/input/default_input_device_hub.h 2016-06-02 08:20:22 +0000 |
655 | +++ src/server/input/default_input_device_hub.h 2016-07-06 21:48:16 +0000 |
656 | @@ -108,9 +108,13 @@ |
657 | MirInputDeviceId id(); |
658 | std::shared_ptr<Seat> seat; |
659 | const std::shared_ptr<DefaultDevice> handle; |
660 | + |
661 | + void set_key_state(std::vector<uint32_t> const& scan_codes) override; |
662 | + void set_pointer_state(MirPointerButtons buttons) override; |
663 | private: |
664 | MirInputDeviceId device_id; |
665 | - DefaultEventBuilder builder; |
666 | + std::unique_ptr<DefaultEventBuilder> builder; |
667 | + std::shared_ptr<cookie::Authority> cookie_authority; |
668 | std::shared_ptr<InputDevice> const device; |
669 | std::shared_ptr<dispatch::MultiplexingDispatchable> const multiplexer; |
670 | }; |
671 | |
672 | === modified file 'src/server/input/seat_input_device_tracker.cpp' |
673 | --- src/server/input/seat_input_device_tracker.cpp 2016-07-01 20:24:26 +0000 |
674 | +++ src/server/input/seat_input_device_tracker.cpp 2016-07-06 21:48:16 +0000 |
675 | @@ -26,6 +26,7 @@ |
676 | #include "mir/geometry/displacement.h" |
677 | #include "mir/events/event_builders.h" |
678 | #include "mir/events/event_private.h" |
679 | +#include "mir/time/clock.h" |
680 | |
681 | #include "input_modifier_utils.h" |
682 | |
683 | @@ -44,9 +45,10 @@ |
684 | std::shared_ptr<TouchVisualizer> const& touch_visualizer, |
685 | std::shared_ptr<CursorListener> const& cursor_listener, |
686 | std::shared_ptr<InputRegion> const& input_region, |
687 | - std::shared_ptr<KeyMapper> const& key_mapper) |
688 | + std::shared_ptr<KeyMapper> const& key_mapper, |
689 | + std::shared_ptr<time::Clock> const& clock) |
690 | : dispatcher{dispatcher}, touch_visualizer{touch_visualizer}, cursor_listener{cursor_listener}, |
691 | - input_region{input_region}, key_mapper{key_mapper}, buttons{0}, |
692 | + input_region{input_region}, key_mapper{key_mapper}, clock{clock}, buttons{0}, |
693 | confine_function{[input_region](mir::geometry::Point& pos) { input_region->confine(pos); }} |
694 | { |
695 | } |
696 | @@ -77,20 +79,23 @@ |
697 | |
698 | void mi::SeatInputDeviceTracker::dispatch(MirEvent &event) |
699 | { |
700 | - auto input_event = mir_event_get_input_event(&event); |
701 | - |
702 | - if (filter_input_event(input_event)) |
703 | - return; |
704 | - |
705 | - update_seat_properties(input_event); |
706 | - |
707 | - key_mapper->map_event(event); |
708 | - |
709 | - if (mir_input_event_type_pointer == mir_input_event_get_type(input_event)) |
710 | + if (mir_event_get_type(&event) == mir_event_type_input) |
711 | { |
712 | - event.to_input()->to_motion()->set_x(0, cursor_x); |
713 | - event.to_input()->to_motion()->set_y(0, cursor_y); |
714 | - mev::set_button_state(event, button_state()); |
715 | + auto input_event = mir_event_get_input_event(&event); |
716 | + |
717 | + if (filter_input_event(input_event)) |
718 | + return; |
719 | + |
720 | + update_seat_properties(input_event); |
721 | + |
722 | + key_mapper->map_event(event); |
723 | + |
724 | + if (mir_input_event_type_pointer == mir_input_event_get_type(input_event)) |
725 | + { |
726 | + event.to_input()->to_motion()->set_x(0, cursor_x); |
727 | + event.to_input()->to_motion()->set_y(0, cursor_y); |
728 | + mev::set_button_state(event, button_state()); |
729 | + } |
730 | } |
731 | |
732 | dispatcher->dispatch(event); |
733 | @@ -227,6 +232,16 @@ |
734 | cursor_listener->cursor_moved_to(cursor_x, cursor_y); |
735 | } |
736 | |
737 | +mir::EventUPtr mi::SeatInputDeviceTracker::create_device_state() const |
738 | +{ |
739 | + std::vector<mev::InputDeviceState> devices; |
740 | + devices.reserve(device_data.size()); |
741 | + for (auto const& item : device_data) |
742 | + devices.push_back({item.first, item.second.scan_codes, item.second.buttons}); |
743 | + return mev::make_event( |
744 | + clock->now().time_since_epoch(), buttons, key_mapper->modifiers(), cursor_x, cursor_y, std::move(devices)); |
745 | +} |
746 | + |
747 | void mi::SeatInputDeviceTracker::DeviceData::update_scan_codes(MirKeyboardEvent const* event) |
748 | { |
749 | auto const action = mir_keyboard_event_action(event); |
750 | @@ -237,6 +252,30 @@ |
751 | scan_codes.erase(remove(begin(scan_codes), end(scan_codes), scan_code), end(scan_codes)); |
752 | } |
753 | |
754 | +void mi::SeatInputDeviceTracker::set_key_state(MirInputDeviceId id, std::vector<uint32_t> const& scan_codes) |
755 | +{ |
756 | + key_mapper->set_key_state(id, scan_codes); |
757 | + |
758 | + auto device = device_data.find(id); |
759 | + |
760 | + if (device != end(device_data)) |
761 | + device->second.scan_codes = scan_codes; |
762 | +} |
763 | + |
764 | +void mi::SeatInputDeviceTracker::set_pointer_state(MirInputDeviceId id, MirPointerButtons buttons) |
765 | +{ |
766 | + auto device = device_data.find(id); |
767 | + |
768 | + if (device != end(device_data)) |
769 | + device->second.update_button_state(buttons); |
770 | +} |
771 | + |
772 | +void mi::SeatInputDeviceTracker::set_cursor_position(float x, float y) |
773 | +{ |
774 | + cursor_x = x; |
775 | + cursor_y = y; |
776 | +} |
777 | + |
778 | bool mi::SeatInputDeviceTracker::DeviceData::allowed_scan_code_action(MirKeyboardEvent const* event) const |
779 | { |
780 | auto const action = mir_keyboard_event_action(event); |
781 | |
782 | === modified file 'src/server/input/seat_input_device_tracker.h' |
783 | --- src/server/input/seat_input_device_tracker.h 2016-07-01 20:24:26 +0000 |
784 | +++ src/server/input/seat_input_device_tracker.h 2016-07-06 21:48:16 +0000 |
785 | @@ -29,6 +29,11 @@ |
786 | |
787 | namespace mir |
788 | { |
789 | +using EventUPtr = std::unique_ptr<MirEvent, void(*)(MirEvent*)>; |
790 | +namespace time |
791 | +{ |
792 | +class Clock; |
793 | +} |
794 | namespace input |
795 | { |
796 | class CursorListener; |
797 | @@ -50,7 +55,8 @@ |
798 | std::shared_ptr<TouchVisualizer> const& touch_visualizer, |
799 | std::shared_ptr<CursorListener> const& cursor_listener, |
800 | std::shared_ptr<InputRegion> const& input_region, |
801 | - std::shared_ptr<KeyMapper> const& key_mapper); |
802 | + std::shared_ptr<KeyMapper> const& key_mapper, |
803 | + std::shared_ptr<time::Clock> const& clock); |
804 | void add_device(MirInputDeviceId); |
805 | void remove_device(MirInputDeviceId); |
806 | |
807 | @@ -58,7 +64,11 @@ |
808 | |
809 | MirPointerButtons button_state() const; |
810 | geometry::Point cursor_position() const; |
811 | + EventUPtr create_device_state() const; |
812 | |
813 | + void set_key_state(MirInputDeviceId id, std::vector<uint32_t> const& scan_codes); |
814 | + void set_pointer_state(MirInputDeviceId id, MirPointerButtons buttons); |
815 | + void set_cursor_position(float cursor_x, float cursor_y); |
816 | void set_confinement_regions(geometry::Rectangles const& region); |
817 | void reset_confinement_regions(); |
818 | private: |
819 | @@ -74,6 +84,7 @@ |
820 | std::shared_ptr<CursorListener> const cursor_listener; |
821 | std::shared_ptr<InputRegion> const input_region; |
822 | std::shared_ptr<KeyMapper> const key_mapper; |
823 | + std::shared_ptr<time::Clock> const clock; |
824 | |
825 | struct DeviceData |
826 | { |
827 | |
828 | === modified file 'src/server/server.cpp' |
829 | --- src/server/server.cpp 2016-06-22 14:43:28 +0000 |
830 | +++ src/server/server.cpp 2016-07-06 21:48:16 +0000 |
831 | @@ -23,6 +23,8 @@ |
832 | #include "mir/frontend/connector.h" |
833 | #include "mir/graphics/graphic_buffer_allocator.h" |
834 | #include "mir/graphics/display_buffer.h" |
835 | +#include "mir/input/composite_event_filter.h" |
836 | +#include "mir/input/event_filter.h" |
837 | #include "mir/options/default_configuration.h" |
838 | #include "mir/renderer/gl/render_target.h" |
839 | #include "mir/default_server_configuration.h" |
840 | @@ -41,6 +43,37 @@ |
841 | #include <iostream> |
842 | |
843 | namespace mo = mir::options; |
844 | +namespace mi = mir::input; |
845 | + |
846 | +namespace |
847 | +{ |
848 | +struct TemporaryCompositeEventFilter : public mi::CompositeEventFilter |
849 | +{ |
850 | + bool handle(MirEvent const&) override { return false; } |
851 | + void append(std::shared_ptr<mi::EventFilter> const& filter) override |
852 | + { |
853 | + append_event_filters.push_back(filter); |
854 | + } |
855 | + void prepend(std::shared_ptr<mi::EventFilter> const& filter) override |
856 | + { |
857 | + prepend_event_filters.push_back(filter); |
858 | + } |
859 | + |
860 | + void move_filters(std::shared_ptr<mi::CompositeEventFilter> const& composite_event_filter) |
861 | + { |
862 | + for (auto const& filter : prepend_event_filters) |
863 | + composite_event_filter->prepend(filter); |
864 | + |
865 | + for (auto const& filter : append_event_filters) |
866 | + composite_event_filter->append(filter); |
867 | + |
868 | + append_event_filters.clear(); |
869 | + prepend_event_filters.clear(); |
870 | + } |
871 | + std::vector<std::shared_ptr<mi::EventFilter>> prepend_event_filters; |
872 | + std::vector<std::shared_ptr<mi::EventFilter>> append_event_filters; |
873 | +}; |
874 | +} |
875 | |
876 | #define FOREACH_WRAPPER(MACRO)\ |
877 | MACRO(cursor)\ |
878 | @@ -76,7 +109,6 @@ |
879 | MACRO(the_buffer_stream_factory)\ |
880 | MACRO(the_compositor)\ |
881 | MACRO(the_compositor_report)\ |
882 | - MACRO(the_composite_event_filter)\ |
883 | MACRO(the_cursor_listener)\ |
884 | MACRO(the_cursor)\ |
885 | MACRO(the_display)\ |
886 | @@ -121,6 +153,8 @@ |
887 | std::function<void()> exception_handler{}; |
888 | Terminator terminator{}; |
889 | EmergencyCleanupHandler emergency_cleanup_handler; |
890 | + std::shared_ptr<TemporaryCompositeEventFilter> temporary_event_filter{ |
891 | + std::make_shared<TemporaryCompositeEventFilter>()}; |
892 | |
893 | std::function<void(int argc, char const* const* argv)> command_line_hander{}; |
894 | |
895 | @@ -386,6 +420,9 @@ |
896 | verify_accessing_allowed(self->server_config); |
897 | |
898 | auto const emergency_cleanup = self->server_config->the_emergency_cleanup(); |
899 | + auto const composite_event_filter = self->server_config->the_composite_event_filter(); |
900 | + |
901 | + self->temporary_event_filter->move_filters(composite_event_filter); |
902 | |
903 | if (self->emergency_cleanup_handler) |
904 | emergency_cleanup->add(self->emergency_cleanup_handler); |
905 | @@ -498,6 +535,14 @@ |
906 | |
907 | #undef MIR_SERVER_WRAP |
908 | |
909 | +auto mir::Server::the_composite_event_filter() const -> decltype(self->server_config->the_composite_event_filter()) |
910 | +{ |
911 | + if (self->server_config) |
912 | + return self->server_config->the_composite_event_filter(); |
913 | + else |
914 | + return self->temporary_event_filter; |
915 | +} |
916 | + |
917 | void mir::Server::add_configuration_option( |
918 | std::string const& option, |
919 | std::string const& description, |
920 | |
921 | === modified file 'src/server/shell/abstract_shell.cpp' |
922 | --- src/server/shell/abstract_shell.cpp 2016-06-20 17:10:33 +0000 |
923 | +++ src/server/shell/abstract_shell.cpp 2016-07-06 21:48:16 +0000 |
924 | @@ -254,6 +254,7 @@ |
925 | |
926 | // Ensure the surface has really taken the focus before notifying it that it is focused |
927 | input_targeter->set_focus(surface); |
928 | + surface->consume(seat->create_device_state().get()); |
929 | surface->configure(mir_surface_attrib_focus, mir_surface_focused); |
930 | } |
931 | else |
932 | |
933 | === modified file 'tests/acceptance-tests/test_nested_input.cpp' |
934 | --- tests/acceptance-tests/test_nested_input.cpp 2016-05-03 06:55:25 +0000 |
935 | +++ tests/acceptance-tests/test_nested_input.cpp 2016-07-06 21:48:16 +0000 |
936 | @@ -75,19 +75,24 @@ |
937 | |
938 | struct NestedServerWithMockEventFilter : mtf::HeadlessNestedServerRunner |
939 | { |
940 | - NestedServerWithMockEventFilter(std:: string const& connection_string) |
941 | - : mtf::HeadlessNestedServerRunner(connection_string) |
942 | + NestedServerWithMockEventFilter(std::string const& connection_string, |
943 | + std::shared_ptr<MockEventFilter> const& event_filter) |
944 | + : mtf::HeadlessNestedServerRunner(connection_string), mock_event_filter{event_filter} |
945 | { |
946 | + server.the_composite_event_filter()->append(mock_event_filter); |
947 | start_server(); |
948 | - server.the_composite_event_filter()->append(mock_event_filter); |
949 | - |
950 | - } |
951 | + } |
952 | + NestedServerWithMockEventFilter(std::string const& connection_string) |
953 | + : NestedServerWithMockEventFilter(connection_string, std::make_shared<MockEventFilter>()) |
954 | + { |
955 | + } |
956 | + |
957 | ~NestedServerWithMockEventFilter() |
958 | { |
959 | stop_server(); |
960 | } |
961 | |
962 | - std::shared_ptr<MockEventFilter> const mock_event_filter = std::make_shared<MockEventFilter>(); |
963 | + std::shared_ptr<MockEventFilter> const mock_event_filter; |
964 | }; |
965 | |
966 | struct NestedInput : public mtf::HeadlessInProcessServer |
967 | @@ -121,14 +126,52 @@ |
968 | // Ensure the nested server posts a frame |
969 | connection = mir_connect_sync(connect_string.c_str(), __PRETTY_FUNCTION__); |
970 | surface = mtf::make_any_surface(connection); |
971 | + mir_surface_set_event_handler(surface, handle_event, this); |
972 | mir_buffer_stream_swap_buffers_sync(mir_surface_get_buffer_stream(surface)); |
973 | } |
974 | |
975 | + MOCK_METHOD1(handle_input, void(MirEvent const*)); |
976 | + |
977 | + void handle_surface_event(MirSurfaceEvent const* event) |
978 | + { |
979 | + auto const attrib = mir_surface_event_get_attribute(event); |
980 | + auto const value = mir_surface_event_get_attribute_value(event); |
981 | + |
982 | + if (mir_surface_attrib_visibility == attrib && |
983 | + mir_surface_visibility_exposed == value) |
984 | + exposed = true; |
985 | + |
986 | + if (mir_surface_attrib_focus == attrib && |
987 | + mir_surface_focused == value) |
988 | + focused = true; |
989 | + |
990 | + if (exposed && focused) |
991 | + ready_to_accept_events.raise(); |
992 | + } |
993 | + |
994 | + static void handle_event(MirSurface*, MirEvent const* ev, void* context) |
995 | + { |
996 | + auto const client = static_cast<ExposedSurface*>(context); |
997 | + auto type = mir_event_get_type(ev); |
998 | + if (type == mir_event_type_surface) |
999 | + { |
1000 | + auto surface_event = mir_event_get_surface_event(ev); |
1001 | + client->handle_surface_event(surface_event); |
1002 | + |
1003 | + } |
1004 | + if (type == mir_event_type_input) |
1005 | + client->handle_input(ev); |
1006 | + } |
1007 | + |
1008 | + static void null_event_handler(MirSurface*, MirEvent const*, void*) {}; |
1009 | ~ExposedSurface() |
1010 | { |
1011 | + mir_surface_set_event_handler(surface, null_event_handler, nullptr); |
1012 | mir_surface_release_sync(surface); |
1013 | mir_connection_release(connection); |
1014 | } |
1015 | + mir::test::Signal ready_to_accept_events; |
1016 | + |
1017 | protected: |
1018 | ExposedSurface(ExposedSurface const&) = delete; |
1019 | ExposedSurface& operator=(ExposedSurface const&) = delete; |
1020 | @@ -136,28 +179,32 @@ |
1021 | private: |
1022 | MirConnection *connection; |
1023 | MirSurface *surface; |
1024 | + bool exposed{false}; |
1025 | + bool focused{false}; |
1026 | }; |
1027 | |
1028 | } |
1029 | |
1030 | TEST_F(NestedInput, nested_event_filter_receives_keyboard_from_host) |
1031 | { |
1032 | - NestedServerWithMockEventFilter nested_mir{new_connection()}; |
1033 | - ExposedSurface client(nested_mir.new_connection()); |
1034 | + MockEventFilter nested_event_filter; |
1035 | std::atomic<int> num_key_a_events{0}; |
1036 | - |
1037 | auto const increase_key_a_events = [&num_key_a_events] { ++num_key_a_events; }; |
1038 | |
1039 | InSequence seq; |
1040 | - EXPECT_CALL(*nested_mir.mock_event_filter, handle(mt::KeyOfScanCode(KEY_A))). |
1041 | + EXPECT_CALL(nested_event_filter, handle(mt::InputDeviceStateEvent())); |
1042 | + EXPECT_CALL(nested_event_filter, handle(mt::KeyOfScanCode(KEY_A))). |
1043 | Times(AtLeast(1)). |
1044 | WillRepeatedly(DoAll(InvokeWithoutArgs(increase_key_a_events), Return(true))); |
1045 | |
1046 | - EXPECT_CALL(*nested_mir.mock_event_filter, handle(mt::KeyOfScanCode(KEY_RIGHTSHIFT))). |
1047 | + EXPECT_CALL(nested_event_filter, handle(mt::KeyOfScanCode(KEY_RIGHTSHIFT))). |
1048 | Times(2). |
1049 | WillOnce(Return(true)). |
1050 | WillOnce(DoAll(mt::WakeUp(&all_events_received), Return(true))); |
1051 | |
1052 | + NestedServerWithMockEventFilter nested_mir{new_connection(), mt::fake_shared(nested_event_filter)}; |
1053 | + ExposedSurface client(nested_mir.new_connection()); |
1054 | + |
1055 | // Because we are testing a nested setup, it's difficult to guarantee |
1056 | // that the nested framebuffer surface (and consenquently the client surface |
1057 | // contained in it) is going to be ready (i.e., exposed and focused) to receive |
1058 | @@ -229,3 +276,24 @@ |
1059 | |
1060 | input_device_changes_complete.wait_for(10s); |
1061 | } |
1062 | + |
1063 | +TEST_F(NestedInput, on_input_device_state_nested_server_emits_input_device_state) |
1064 | +{ |
1065 | + MockEventFilter nested_event_filter; |
1066 | + NestedServerWithMockEventFilter nested_mir{new_connection(), mt::fake_shared(nested_event_filter)}; |
1067 | + ExposedSurface client_to_nested_mir(nested_mir.new_connection()); |
1068 | + |
1069 | + client_to_nested_mir.ready_to_accept_events.wait_for(1s); |
1070 | + ExposedSurface client_to_host(new_connection()); |
1071 | + client_to_host.ready_to_accept_events.wait_for(1s); |
1072 | + |
1073 | + EXPECT_CALL(client_to_host, handle_input(mt::KeyOfScanCode(KEY_LEFTALT))); |
1074 | + EXPECT_CALL(nested_event_filter, |
1075 | + handle(mt::DeviceStateWithPressedKeys(std::vector<uint32_t>({KEY_LEFTALT, KEY_TAB})))) |
1076 | + .WillOnce(DoAll(mt::WakeUp(&all_events_received), Return(true))); |
1077 | + |
1078 | + fake_keyboard->emit_event(mis::a_key_down_event().of_scancode(KEY_LEFTALT)); |
1079 | + fake_keyboard->emit_event(mis::a_key_down_event().of_scancode(KEY_TAB)); |
1080 | + |
1081 | + all_events_received.wait_for(2s); |
1082 | +} |
1083 | |
1084 | === modified file 'tests/include/mir/test/doubles/mock_input_seat.h' |
1085 | --- tests/include/mir/test/doubles/mock_input_seat.h 2016-06-27 20:44:49 +0000 |
1086 | +++ tests/include/mir/test/doubles/mock_input_seat.h 2016-07-06 21:48:16 +0000 |
1087 | @@ -20,9 +20,10 @@ |
1088 | #define MIR_TEST_DOUBLES_MOCK_INPUT_SEAT_H_ |
1089 | |
1090 | #include "mir/input/seat.h" |
1091 | +#include "mir/input/device.h" |
1092 | +#include "mir/test/gmock_fixes.h" |
1093 | |
1094 | #include <gmock/gmock.h> |
1095 | -#include "mir/input/device.h" |
1096 | |
1097 | namespace mir |
1098 | { |
1099 | @@ -36,6 +37,10 @@ |
1100 | MOCK_METHOD1(remove_device, void(input::Device const& device)); |
1101 | MOCK_METHOD1(dispatch_event, void(MirEvent& event)); |
1102 | MOCK_METHOD1(get_rectangle_for, geometry::Rectangle(input::Device const& dev)); |
1103 | + MOCK_METHOD0(create_device_state, mir::EventUPtr()); |
1104 | + MOCK_METHOD2(set_key_state, void(input::Device const&, std::vector<uint32_t> const&)); |
1105 | + MOCK_METHOD2(set_pointer_state, void (input::Device const&, MirPointerButtons)); |
1106 | + MOCK_METHOD2(set_cursor_position, void (float, float)); |
1107 | MOCK_METHOD1(set_confinement_regions, void(geometry::Rectangles const&)); |
1108 | MOCK_METHOD0(reset_confinement_regions, void()); |
1109 | }; |
1110 | |
1111 | === modified file 'tests/include/mir/test/doubles/mock_input_sink.h' |
1112 | --- tests/include/mir/test/doubles/mock_input_sink.h 2015-07-21 17:57:15 +0000 |
1113 | +++ tests/include/mir/test/doubles/mock_input_sink.h 2016-07-06 21:48:16 +0000 |
1114 | @@ -35,6 +35,8 @@ |
1115 | MOCK_METHOD1(handle_input, void(MirEvent&)); |
1116 | MOCK_METHOD1(confine_pointer, void(mir::geometry::Point&)); |
1117 | MOCK_CONST_METHOD0(bounding_rectangle, mir::geometry::Rectangle()); |
1118 | + MOCK_METHOD1(set_key_state, void(std::vector<uint32_t> const&)); |
1119 | + MOCK_METHOD1(set_pointer_state, void(MirPointerButtons)); |
1120 | }; |
1121 | |
1122 | } |
1123 | |
1124 | === modified file 'tests/include/mir/test/doubles/mock_key_mapper.h' |
1125 | --- tests/include/mir/test/doubles/mock_key_mapper.h 2016-06-24 06:43:18 +0000 |
1126 | +++ tests/include/mir/test/doubles/mock_key_mapper.h 2016-07-06 21:48:16 +0000 |
1127 | @@ -40,6 +40,7 @@ |
1128 | MOCK_METHOD1(clear_keymap_for_device, void(MirInputDeviceId id)); |
1129 | MOCK_METHOD0(clear_all_keymaps, void()); |
1130 | MOCK_METHOD1(map_event, void(MirEvent& event)); |
1131 | + MOCK_CONST_METHOD0(modifiers, MirInputEventModifiers()); |
1132 | }; |
1133 | |
1134 | |
1135 | |
1136 | === modified file 'tests/integration-tests/input/test_single_seat_setup.cpp' |
1137 | --- tests/integration-tests/input/test_single_seat_setup.cpp 2016-06-02 08:20:22 +0000 |
1138 | +++ tests/integration-tests/input/test_single_seat_setup.cpp 2016-07-06 21:48:16 +0000 |
1139 | @@ -28,6 +28,7 @@ |
1140 | #include "mir/test/doubles/mock_event_sink.h" |
1141 | #include "mir/test/doubles/triggered_main_loop.h" |
1142 | #include "mir/test/event_matchers.h" |
1143 | +#include "mir/test/doubles/advanceable_clock.h" |
1144 | #include "mir/test/fake_shared.h" |
1145 | |
1146 | #include "mir/dispatch/multiplexing_dispatchable.h" |
1147 | @@ -81,10 +82,12 @@ |
1148 | NiceMock<mtd::MockTouchVisualizer> mock_visualizer; |
1149 | mi::receiver::XKBMapper key_mapper; |
1150 | mir::dispatch::MultiplexingDispatchable multiplexer; |
1151 | - mi::BasicSeat seat{mt::fake_shared(mock_dispatcher), mt::fake_shared(mock_visualizer), |
1152 | - mt::fake_shared(mock_cursor_listener), mt::fake_shared(mock_region), mt::fake_shared(key_mapper)}; |
1153 | - mi::DefaultInputDeviceHub hub{mt::fake_shared(mock_sink), mt::fake_shared(seat), mt::fake_shared(multiplexer), mt::fake_shared(observer_loop), |
1154 | - cookie_authority, mt::fake_shared(key_mapper)}; |
1155 | + mtd::AdvanceableClock clock; |
1156 | + mi::BasicSeat seat{mt::fake_shared(mock_dispatcher), mt::fake_shared(mock_visualizer), |
1157 | + mt::fake_shared(mock_cursor_listener), mt::fake_shared(mock_region), |
1158 | + mt::fake_shared(key_mapper), mt::fake_shared(clock)}; |
1159 | + mi::DefaultInputDeviceHub hub{mt::fake_shared(mock_sink), mt::fake_shared(seat), mt::fake_shared(multiplexer), |
1160 | + mt::fake_shared(observer_loop), cookie_authority, mt::fake_shared(key_mapper)}; |
1161 | NiceMock<mtd::MockInputDeviceObserver> mock_observer; |
1162 | |
1163 | mi::DeviceCapabilities const keyboard_caps = mi::DeviceCapability::keyboard | mi::DeviceCapability::alpha_numeric; |
1164 | |
1165 | === modified file 'tests/unit-tests/input/android/test_android_input_sender.cpp' |
1166 | --- tests/unit-tests/input/android/test_android_input_sender.cpp 2016-06-07 17:00:15 +0000 |
1167 | +++ tests/unit-tests/input/android/test_android_input_sender.cpp 2016-07-06 21:48:16 +0000 |
1168 | @@ -17,6 +17,7 @@ |
1169 | */ |
1170 | |
1171 | #include "mir/events/event_private.h" |
1172 | +#include "mir/events/event_builders.h" |
1173 | |
1174 | #include "src/server/input/channel.h" |
1175 | #include "src/server/input/android/input_sender.h" |
1176 | @@ -25,6 +26,7 @@ |
1177 | |
1178 | #include "mir/test/doubles/stub_scene_surface.h" |
1179 | #include "mir/test/doubles/mock_input_surface.h" |
1180 | +#include "mir/test/doubles/mock_input_seat.h" |
1181 | #include "mir/test/doubles/stub_scene.h" |
1182 | #include "mir/test/doubles/mock_scene.h" |
1183 | #include "mir/test/doubles/triggered_main_loop.h" |
1184 | @@ -54,7 +56,7 @@ |
1185 | namespace mtd = mt::doubles; |
1186 | namespace droidinput = android; |
1187 | |
1188 | -using testing::_; |
1189 | +using namespace testing; |
1190 | |
1191 | namespace |
1192 | { |
1193 | @@ -108,10 +110,11 @@ |
1194 | mir::geometry::Displacement const movement{10, -10}; |
1195 | std::shared_ptr<mir::cookie::Authority> const cookie_authority; |
1196 | mi::DefaultEventBuilder builder; |
1197 | + mtd::MockInputSeat seat; |
1198 | |
1199 | AndroidInputSender() |
1200 | : cookie_authority(mir::cookie::Authority::create_from({0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88})), |
1201 | - builder(MirInputDeviceId(), cookie_authority), |
1202 | + builder(MirInputDeviceId(), cookie_authority, mt::fake_shared(seat)), |
1203 | key_event(builder.key_event(std::chrono::nanoseconds(1), mir_keyboard_action_down, 7, test_scan_code)), |
1204 | motion_event(builder.touch_event(std::chrono::nanoseconds(-1))), |
1205 | pointer_event(builder.pointer_event(std::chrono::nanoseconds(123), mir_pointer_action_motion, |
1206 | @@ -128,6 +131,7 @@ |
1207 | |
1208 | ON_CALL(event_factory, createKeyEvent()).WillByDefault(Return(&client_key_event)); |
1209 | ON_CALL(event_factory, createMotionEvent()).WillByDefault(Return(&client_motion_event)); |
1210 | + ON_CALL(event_factory, createRawBufferEvent()).WillByDefault(Return(&client_raw_event)); |
1211 | } |
1212 | |
1213 | void register_surface() |
1214 | @@ -154,6 +158,7 @@ |
1215 | |
1216 | droidinput::MotionEvent client_motion_event; |
1217 | droidinput::KeyEvent client_key_event; |
1218 | + droidinput::RawBufferEvent client_raw_event; |
1219 | |
1220 | testing::NiceMock<MockInputEventFactory> event_factory; |
1221 | |
1222 | @@ -490,3 +495,40 @@ |
1223 | EXPECT_EQ(4, client_motion_event.getPointerId(2)); |
1224 | EXPECT_EQ(3, client_motion_event.getPointerCount()); |
1225 | } |
1226 | + |
1227 | +TEST_F(AndroidInputSender, encodes_input_device_state_event_as_raw_buffer_event) |
1228 | +{ |
1229 | + const float cursor_x = 50.0f; |
1230 | + const float cursor_y = 60.0f; |
1231 | + const auto timestamp = std::chrono::nanoseconds(10); |
1232 | + register_surface(); |
1233 | + std::vector<mir::events::InputDeviceState> states; |
1234 | + states.push_back({MirInputDeviceId{23}, {50, 60, 80}, 0}); |
1235 | + states.push_back({MirInputDeviceId{21}, {}, mir_pointer_button_primary}); |
1236 | + |
1237 | + auto device_state = mir::events::make_event(timestamp, mir_pointer_button_primary, mir_input_event_modifier_caps_lock, |
1238 | + cursor_x, cursor_y, std::move(states)); |
1239 | + |
1240 | + sender.send_event(*device_state, channel); |
1241 | + EXPECT_EQ(droidinput::OK, consumer.consume(&event_factory, true, std::chrono::nanoseconds(86), &seq, &event)); |
1242 | + EXPECT_EQ(&client_raw_event, event); |
1243 | + |
1244 | + auto dest_event = MirEvent::deserialize(client_raw_event.buffer); |
1245 | + ASSERT_THAT(mir_event_get_type(dest_event.get()), mir_event_type_input_device_state); |
1246 | + |
1247 | + auto input_device_state = mir_event_get_input_device_state_event(dest_event.get()); |
1248 | + EXPECT_THAT(mir_input_device_state_event_time(input_device_state), Eq(timestamp.count())); |
1249 | + EXPECT_THAT(mir_input_device_state_event_modifiers(input_device_state), Eq(mir_input_event_modifier_caps_lock)); |
1250 | + EXPECT_THAT(mir_input_device_state_event_device_count(input_device_state), Eq(2)); |
1251 | + |
1252 | + EXPECT_THAT(mir_input_device_state_event_device_id(input_device_state, 0), Eq(MirInputDeviceId{23})); |
1253 | + EXPECT_THAT(mir_input_device_state_event_device_pressed_keys_count(input_device_state, 0), Eq(3)); |
1254 | + EXPECT_THAT(mir_input_device_state_event_device_pressed_keys(input_device_state, 0)[0], Eq(50)); |
1255 | + EXPECT_THAT(mir_input_device_state_event_device_pressed_keys(input_device_state, 0)[1], Eq(60)); |
1256 | + EXPECT_THAT(mir_input_device_state_event_device_pressed_keys(input_device_state, 0)[2], Eq(80)); |
1257 | + EXPECT_THAT(mir_input_device_state_event_device_pointer_buttons(input_device_state, 0), 0); |
1258 | + |
1259 | + EXPECT_THAT(mir_input_device_state_event_device_id(input_device_state, 1), Eq(MirInputDeviceId{21})); |
1260 | + EXPECT_THAT(mir_input_device_state_event_device_pressed_keys_count(input_device_state, 1), Eq(0)); |
1261 | + EXPECT_THAT(mir_input_device_state_event_device_pointer_buttons(input_device_state, 1), mir_pointer_button_primary); |
1262 | +} |
1263 | |
1264 | === modified file 'tests/unit-tests/input/evdev/test_libinput_device.cpp' |
1265 | --- tests/unit-tests/input/evdev/test_libinput_device.cpp 2016-05-03 06:55:25 +0000 |
1266 | +++ tests/unit-tests/input/evdev/test_libinput_device.cpp 2016-07-06 21:48:16 +0000 |
1267 | @@ -30,7 +30,9 @@ |
1268 | #include "mir/geometry/rectangle.h" |
1269 | #include "mir/test/event_matchers.h" |
1270 | #include "mir/test/doubles/mock_libinput.h" |
1271 | +#include "mir/test/doubles/mock_input_seat.h" |
1272 | #include "mir/test/gmock_fixes.h" |
1273 | +#include "mir/test/fake_shared.h" |
1274 | #include "mir/udev/wrapper.h" |
1275 | #include "mir/cookie/authority.h" |
1276 | #include "mir_test_framework/libinput_environment.h" |
1277 | @@ -71,12 +73,15 @@ |
1278 | MOCK_METHOD1(handle_input,void(MirEvent &)); |
1279 | MOCK_METHOD1(confine_pointer, void(geom::Point&)); |
1280 | MOCK_CONST_METHOD0(bounding_rectangle, geom::Rectangle()); |
1281 | + MOCK_METHOD1(set_key_state, void(std::vector<uint32_t> const&)); |
1282 | + MOCK_METHOD1(set_pointer_state, void(MirPointerButtons)); |
1283 | }; |
1284 | |
1285 | struct MockEventBuilder : mi::EventBuilder |
1286 | { |
1287 | std::shared_ptr<mir::cookie::Authority> const cookie_authority = mir::cookie::Authority::create(); |
1288 | - mi::DefaultEventBuilder builder{MirInputDeviceId{3}, cookie_authority}; |
1289 | + mtd::MockInputSeat seat; |
1290 | + mi::DefaultEventBuilder builder{MirInputDeviceId{3}, cookie_authority, mt::fake_shared(seat)}; |
1291 | MockEventBuilder() |
1292 | { |
1293 | ON_CALL(*this, key_event(_,_,_,_)) |
1294 | @@ -119,6 +124,10 @@ |
1295 | MOCK_METHOD7(pointer_event, |
1296 | mir::EventUPtr(Timestamp, MirPointerAction, MirPointerButtons, float, float, float, float)); |
1297 | MOCK_METHOD2(configuration_event, mir::EventUPtr(Timestamp, MirInputConfigurationAction)); |
1298 | + mir::EventUPtr device_state_event(float, float) override |
1299 | + { |
1300 | + return {nullptr,[](MirEvent*){}}; |
1301 | + } |
1302 | }; |
1303 | |
1304 | struct LibInputDevice : public ::testing::Test |
1305 | |
1306 | === modified file 'tests/unit-tests/input/test_nested_input_platform.cpp' |
1307 | --- tests/unit-tests/input/test_nested_input_platform.cpp 2016-06-09 13:15:34 +0000 |
1308 | +++ tests/unit-tests/input/test_nested_input_platform.cpp 2016-07-06 21:48:16 +0000 |
1309 | @@ -31,6 +31,7 @@ |
1310 | |
1311 | #include "mir/test/doubles/mock_input_device_registry.h" |
1312 | #include "mir/test/doubles/mock_input_sink.h" |
1313 | +#include "mir/test/doubles/mock_input_seat.h" |
1314 | #include "mir/test/doubles/stub_host_connection.h" |
1315 | #include "mir/test/fake_shared.h" |
1316 | #include "mir/test/event_matchers.h" |
1317 | @@ -72,6 +73,7 @@ |
1318 | { |
1319 | NiceMock<mtd::MockInputDeviceRegistry> mock_input_device_registry; |
1320 | NiceMock<MockHostConnection> mock_host_connection; |
1321 | + NiceMock<mtd::MockInputSeat> mock_seat; |
1322 | mgn::InputPlatform platform{mt::fake_shared(mock_host_connection), mt::fake_shared(mock_input_device_registry), |
1323 | mr::null_input_report()}; |
1324 | mi::DeviceData a_keyboard{1, mir_input_device_capability_keyboard, "keys" , "keys-evdev2"}; |
1325 | @@ -141,7 +143,7 @@ |
1326 | { |
1327 | auto nested_input_device = capture_input_device(a_mouse); |
1328 | NiceMock<mtd::MockInputSink> event_sink; |
1329 | - mi::DefaultEventBuilder builder(MirInputDeviceId{12}, mir::cookie::Authority::create()); |
1330 | + mi::DefaultEventBuilder builder(MirInputDeviceId{12}, mir::cookie::Authority::create(), mt::fake_shared(mock_seat)); |
1331 | |
1332 | ASSERT_THAT(nested_input_device, Ne(nullptr)); |
1333 | nested_input_device->start(&event_sink, &builder); |
1334 | @@ -165,7 +167,7 @@ |
1335 | auto nested_input_device = capture_input_device(a_keyboard); |
1336 | auto const scan_code = 45; |
1337 | NiceMock<mtd::MockInputSink> event_sink; |
1338 | - mi::DefaultEventBuilder builder(MirInputDeviceId{18}, mir::cookie::Authority::create()); |
1339 | + mi::DefaultEventBuilder builder(MirInputDeviceId{18}, mir::cookie::Authority::create(), mt::fake_shared(mock_seat)); |
1340 | |
1341 | ASSERT_THAT(nested_input_device, Ne(nullptr)); |
1342 | nested_input_device->start(&event_sink, &builder); |
1343 | |
1344 | === modified file 'tests/unit-tests/input/test_seat_input_device_tracker.cpp' |
1345 | --- tests/unit-tests/input/test_seat_input_device_tracker.cpp 2016-07-01 20:24:26 +0000 |
1346 | +++ tests/unit-tests/input/test_seat_input_device_tracker.cpp 2016-07-06 21:48:16 +0000 |
1347 | @@ -25,6 +25,8 @@ |
1348 | #include "mir/test/doubles/mock_input_region.h" |
1349 | #include "mir/test/doubles/mock_cursor_listener.h" |
1350 | #include "mir/test/doubles/mock_touch_visualizer.h" |
1351 | +#include "mir/test/doubles/mock_input_seat.h" |
1352 | +#include "mir/test/doubles/advanceable_clock.h" |
1353 | #include "mir/test/event_matchers.h" |
1354 | #include "mir/test/fake_shared.h" |
1355 | |
1356 | @@ -53,17 +55,20 @@ |
1357 | Nice<mtd::MockInputRegion> mock_region; |
1358 | Nice<mtd::MockCursorListener> mock_cursor_listener; |
1359 | Nice<mtd::MockTouchVisualizer> mock_visualizer; |
1360 | + Nice<mtd::MockInputSeat> mock_seat; |
1361 | MirInputDeviceId some_device{8712}; |
1362 | MirInputDeviceId another_device{1246}; |
1363 | MirInputDeviceId third_device{86}; |
1364 | std::shared_ptr<mir::cookie::Authority> cookie_factory = mir::cookie::Authority::create(); |
1365 | + mtd::AdvanceableClock clock; |
1366 | |
1367 | - mi::DefaultEventBuilder some_device_builder{some_device, cookie_factory}; |
1368 | - mi::DefaultEventBuilder another_device_builder{another_device, cookie_factory}; |
1369 | - mi::DefaultEventBuilder third_device_builder{third_device, cookie_factory}; |
1370 | + mi::DefaultEventBuilder some_device_builder{some_device, cookie_factory, mt::fake_shared(mock_seat)}; |
1371 | + mi::DefaultEventBuilder another_device_builder{another_device, cookie_factory, mt::fake_shared(mock_seat)}; |
1372 | + mi::DefaultEventBuilder third_device_builder{third_device, cookie_factory, mt::fake_shared(mock_seat)}; |
1373 | mi::receiver::XKBMapper mapper; |
1374 | - mi::SeatInputDeviceTracker tracker{mt::fake_shared(mock_dispatcher), mt::fake_shared(mock_visualizer), |
1375 | - mt::fake_shared(mock_cursor_listener), mt::fake_shared(mock_region), mt::fake_shared(mapper)}; |
1376 | + mi::SeatInputDeviceTracker tracker{ |
1377 | + mt::fake_shared(mock_dispatcher), mt::fake_shared(mock_visualizer), mt::fake_shared(mock_cursor_listener), |
1378 | + mt::fake_shared(mock_region), mt::fake_shared(mapper), mt::fake_shared(clock)}; |
1379 | |
1380 | std::chrono::nanoseconds arbitrary_timestamp; |
1381 | }; |
1382 | |
1383 | === modified file 'tests/unit-tests/input/test_x11_platform.cpp' |
1384 | --- tests/unit-tests/input/test_x11_platform.cpp 2016-05-03 06:55:25 +0000 |
1385 | +++ tests/unit-tests/input/test_x11_platform.cpp 2016-07-06 21:48:16 +0000 |
1386 | @@ -28,6 +28,7 @@ |
1387 | #include "mir_toolkit/event.h" |
1388 | #include "mir_toolkit/events/input/input_event.h" |
1389 | #include "mir/test/doubles/mock_input_sink.h" |
1390 | +#include "mir/test/doubles/mock_input_seat.h" |
1391 | #include "mir/test/doubles/mock_input_device_registry.h" |
1392 | #include "mir/test/doubles/mock_x11.h" |
1393 | #include "mir/test/fake_shared.h" |
1394 | @@ -48,9 +49,10 @@ |
1395 | { |
1396 | NiceMock<mtd::MockInputSink> mock_pointer_sink; |
1397 | NiceMock<mtd::MockInputSink> mock_keyboard_sink; |
1398 | + NiceMock<mtd::MockInputSeat> mock_seat; |
1399 | NiceMock<mtd::MockX11> mock_x11; |
1400 | NiceMock<mtd::MockInputDeviceRegistry> mock_registry; |
1401 | - mir::input::DefaultEventBuilder builder{0, mir::cookie::Authority::create()}; |
1402 | + mir::input::DefaultEventBuilder builder{0, mir::cookie::Authority::create(), mt::fake_shared(mock_seat)}; |
1403 | |
1404 | mir::input::X::XInputPlatform x11_platform{ |
1405 | mt::fake_shared(mock_registry), |
1406 | |
1407 | === modified file 'tests/unit-tests/scene/test_abstract_shell.cpp' |
1408 | --- tests/unit-tests/scene/test_abstract_shell.cpp 2016-06-20 17:10:33 +0000 |
1409 | +++ tests/unit-tests/scene/test_abstract_shell.cpp 2016-07-06 21:48:16 +0000 |
1410 | @@ -44,6 +44,7 @@ |
1411 | #include "mir/test/doubles/mock_input_seat.h" |
1412 | |
1413 | #include "mir/test/fake_shared.h" |
1414 | +#include "mir/test/event_matchers.h" |
1415 | |
1416 | #include <gmock/gmock.h> |
1417 | #include <gtest/gtest.h> |
1418 | @@ -54,10 +55,12 @@ |
1419 | namespace msh = mir::shell; |
1420 | namespace geom = mir::geometry; |
1421 | namespace mg = mir::graphics; |
1422 | +namespace mev = mir::events; |
1423 | |
1424 | namespace mt = mir::test; |
1425 | namespace mtd = mir::test::doubles; |
1426 | using namespace ::testing; |
1427 | +using namespace std::chrono_literals; |
1428 | |
1429 | namespace |
1430 | { |
1431 | @@ -145,6 +148,13 @@ |
1432 | .WillByDefault(Return(geom::Size{})); |
1433 | ON_CALL(surface_factory, create_surface(_,_)) |
1434 | .WillByDefault(Return(mt::fake_shared(mock_surface))); |
1435 | + ON_CALL(seat, create_device_state()) |
1436 | + .WillByDefault(Invoke( |
1437 | + []() |
1438 | + { |
1439 | + return mev::make_event(0ns, 0, mir_input_event_modifier_none, 0.0f, 0.0f, |
1440 | + std::vector<mev::InputDeviceState>()); |
1441 | + })); |
1442 | } |
1443 | |
1444 | std::chrono::nanoseconds const event_timestamp = std::chrono::nanoseconds(0); |
1445 | @@ -603,3 +613,17 @@ |
1446 | |
1447 | focus_controller.raise(surfaces); |
1448 | } |
1449 | + |
1450 | +TEST_F(AbstractShell, as_focus_controller_emits_input_device_state_event_on_focus_change) |
1451 | +{ |
1452 | + EXPECT_CALL(mock_surface, consume(mt::InputDeviceStateEvent())).Times(1); |
1453 | + |
1454 | + auto session = shell.open_session(__LINE__, "some", std::shared_ptr<mf::EventSink>()); |
1455 | + auto creation_params = ms::a_surface() |
1456 | + .with_buffer_stream(session->create_buffer_stream(properties)); |
1457 | + auto surface_id = shell.create_surface(session, creation_params, nullptr); |
1458 | + auto surface = session->surface(surface_id); |
1459 | + |
1460 | + msh::FocusController& focus_controller = shell; |
1461 | + focus_controller.set_focus_to(session, surface); |
1462 | +} |
FAILED: Continuous integration, rev:3526 /mir-jenkins. ubuntu. com/job/ mir-ci/ 1150/ /mir-jenkins. ubuntu. com/job/ build-mir/ 1279/console /mir-jenkins. ubuntu. com/job/ build-0- fetch/1329 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= vivid+overlay/ 1320 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial/ 1320 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= vivid+overlay/ 1289/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial/ 1289/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 1289/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 1289/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial/ 1289/console
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild: /mir-jenkins. ubuntu. com/job/ mir-ci/ 1150/rebuild
https:/