Merge lp:~andreas-pokorny/mir/store-device-config into lp:mir
- store-device-config
- Merge into development-branch
Status: | Superseded |
---|---|
Proposed branch: | lp:~andreas-pokorny/mir/store-device-config |
Merge into: | lp:mir |
Prerequisite: | lp:~andreas-pokorny/mir/wait-for-input-config-before-emitting-input-state |
Diff against target: |
1605 lines (+753/-181) 18 files modified
src/include/server/mir/default_server_configuration.h (+1/-0) src/server/graphics/nested/input_platform.cpp (+29/-41) src/server/graphics/nested/input_platform.h (+0/-2) src/server/input/default_configuration.cpp (+7/-3) src/server/input/default_device.cpp (+69/-11) src/server/input/default_device.h (+12/-0) src/server/input/default_input_device_hub.cpp (+175/-35) src/server/input/default_input_device_hub.h (+31/-7) tests/acceptance-tests/test_client_input.cpp (+3/-2) tests/acceptance-tests/test_input_device_hub.cpp (+4/-2) tests/acceptance-tests/test_nested_input.cpp (+8/-7) tests/include/mir/test/doubles/mock_device.h (+71/-0) tests/integration-tests/input/test_single_seat_setup.cpp (+26/-26) tests/unit-tests/input/CMakeLists.txt (+1/-0) tests/unit-tests/input/test_config_changer.cpp (+3/-30) tests/unit-tests/input/test_default_device.cpp (+127/-0) tests/unit-tests/input/test_default_input_device_hub.cpp (+67/-15) tests/unit-tests/input/test_external_input_device_hub.cpp (+119/-0) |
To merge this branch: | bzr merge lp:~andreas-pokorny/mir/store-device-config |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir CI Bot | continuous-integration | Approve | |
Mir development team | Pending | ||
Review via email: mp+319436@code.launchpad.net |
This proposal has been superseded by a proposal from 2017-03-14.
Commit message
Store device configurations and device ids
With this change previous configurations of input devices are restored when they reappear.
Description of the change
Store device ids of removed devices to restore them after a vt-switch.
Mir CI Bot (mir-ci-bot) wrote : | # |
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:4072
https:/
Executed test runs:
SUCCESS: https:/
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:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | === modified file 'src/include/server/mir/default_server_configuration.h' |
2 | --- src/include/server/mir/default_server_configuration.h 2017-03-13 08:12:52 +0000 |
3 | +++ src/include/server/mir/default_server_configuration.h 2017-03-14 20:52:46 +0000 |
4 | @@ -384,6 +384,7 @@ |
5 | CachedPtr<input::InputManager> input_manager; |
6 | CachedPtr<input::SurfaceInputDispatcher> surface_input_dispatcher; |
7 | CachedPtr<input::DefaultInputDeviceHub> default_input_device_hub; |
8 | + CachedPtr<input::InputDeviceHub> input_device_hub; |
9 | CachedPtr<dispatch::MultiplexingDispatchable> input_reading_multiplexer; |
10 | CachedPtr<input::InputDispatcher> input_dispatcher; |
11 | CachedPtr<shell::InputTargeter> input_targeter; |
12 | |
13 | === modified file 'src/server/graphics/nested/input_platform.cpp' |
14 | --- src/server/graphics/nested/input_platform.cpp 2017-03-14 20:52:46 +0000 |
15 | +++ src/server/graphics/nested/input_platform.cpp 2017-03-14 02:26:28 +0000 |
16 | @@ -338,9 +338,34 @@ |
17 | { |
18 | std::lock_guard<std::mutex> lock(devices_guard); |
19 | if (!devices.empty()) |
20 | - handle_device_state(event); |
21 | - else |
22 | - early_device_states.push_back(mir::events::clone_event(event)); |
23 | + { |
24 | + auto const* device_state = mir_event_get_input_device_state_event(&event); |
25 | + for (size_t index = 0, end_index = mir_input_device_state_event_device_count(device_state); |
26 | + index != end_index; ++index) |
27 | + { |
28 | + auto it = devices.find(mir_input_device_state_event_device_id(device_state, index)); |
29 | + if (it != end(devices) && it->second->destination) |
30 | + { |
31 | + auto dest = it->second->destination; |
32 | + auto key_count = mir_input_device_state_event_device_pressed_keys_count(device_state, index); |
33 | + std::vector<uint32_t> scan_codes; |
34 | + for (uint32_t i = 0; i < key_count; i++) |
35 | + { |
36 | + scan_codes.push_back(mir_input_device_state_event_device_pressed_keys_for_index(device_state, index, i)); |
37 | + } |
38 | + |
39 | + dest->key_state(scan_codes); |
40 | + dest->pointer_state( |
41 | + mir_input_device_state_event_device_pointer_buttons(device_state, index)); |
42 | + } |
43 | + } |
44 | + |
45 | + auto& front = begin(devices)->second; |
46 | + auto device_state_event = front->builder->device_state_event( |
47 | + mir_input_device_state_event_pointer_axis(device_state, mir_pointer_axis_x), |
48 | + mir_input_device_state_event_pointer_axis(device_state, mir_pointer_axis_y)); |
49 | + front->destination->handle_input(*device_state_event); |
50 | + } |
51 | } |
52 | }); |
53 | } |
54 | @@ -396,13 +421,7 @@ |
55 | for (auto new_dev : new_devs) |
56 | { |
57 | input_device_registry->add_device(new_dev.first); |
58 | - } |
59 | - for (auto const& event : early_device_states) |
60 | - { |
61 | - handle_device_state(*event); |
62 | - } |
63 | - for (auto new_dev : new_devs) |
64 | - { |
65 | + |
66 | auto early_event_queue = unknown_device_events.find(new_dev.second); |
67 | if (early_event_queue != end(unknown_device_events)) |
68 | { |
69 | @@ -414,7 +433,6 @@ |
70 | } |
71 | } |
72 | unknown_device_events.clear(); |
73 | - early_device_states.clear(); |
74 | } |
75 | |
76 | void mgn::InputPlatform::config_changed() |
77 | @@ -443,33 +461,3 @@ |
78 | } |
79 | state = started; |
80 | } |
81 | - |
82 | -void mgn::InputPlatform::handle_device_state(MirEvent const& event) |
83 | -{ |
84 | - auto const* device_state = mir_event_get_input_device_state_event(&event); |
85 | - for (size_t index = 0, end_index = mir_input_device_state_event_device_count(device_state); |
86 | - index != end_index; ++index) |
87 | - { |
88 | - auto it = devices.find(mir_input_device_state_event_device_id(device_state, index)); |
89 | - if (it != end(devices) && it->second->destination) |
90 | - { |
91 | - auto dest = it->second->destination; |
92 | - auto key_count = mir_input_device_state_event_device_pressed_keys_count(device_state, index); |
93 | - std::vector<uint32_t> scan_codes; |
94 | - for (uint32_t i = 0; i < key_count; i++) |
95 | - { |
96 | - scan_codes.push_back(mir_input_device_state_event_device_pressed_keys_for_index(device_state, index, i)); |
97 | - } |
98 | - |
99 | - dest->key_state(scan_codes); |
100 | - dest->pointer_state( |
101 | - mir_input_device_state_event_device_pointer_buttons(device_state, index)); |
102 | - } |
103 | - } |
104 | - |
105 | - auto& front = begin(devices)->second; |
106 | - auto device_state_event = front->builder->device_state_event( |
107 | - mir_input_device_state_event_pointer_axis(device_state, mir_pointer_axis_x), |
108 | - mir_input_device_state_event_pointer_axis(device_state, mir_pointer_axis_y)); |
109 | - front->destination->handle_input(*device_state_event); |
110 | -} |
111 | |
112 | === modified file 'src/server/graphics/nested/input_platform.h' |
113 | --- src/server/graphics/nested/input_platform.h 2017-03-14 20:52:46 +0000 |
114 | +++ src/server/graphics/nested/input_platform.h 2017-02-15 07:38:33 +0000 |
115 | @@ -58,7 +58,6 @@ |
116 | void config_changed(); |
117 | void update_devices(); |
118 | void update_devices_locked(); |
119 | - void handle_device_state(MirEvent const& event); |
120 | struct InputDevice; |
121 | std::shared_ptr<HostConnection> const connection; |
122 | std::shared_ptr<input::InputDeviceRegistry> const input_device_registry; |
123 | @@ -71,7 +70,6 @@ |
124 | std::unordered_map<MirInputDeviceId, std::shared_ptr<InputDevice>> devices; |
125 | std::unordered_map<MirInputDeviceId, std::vector<std::pair<EventUPtr, mir::geometry::Rectangle>>> |
126 | unknown_device_events; |
127 | - std::vector<EventUPtr> early_device_states; |
128 | enum State |
129 | { |
130 | started, stopped, paused |
131 | |
132 | === modified file 'src/server/input/default_configuration.cpp' |
133 | --- src/server/input/default_configuration.cpp 2017-03-14 02:26:28 +0000 |
134 | +++ src/server/input/default_configuration.cpp 2017-03-14 20:52:46 +0000 |
135 | @@ -301,7 +301,12 @@ |
136 | |
137 | std::shared_ptr<mi::InputDeviceHub> mir::DefaultServerConfiguration::the_input_device_hub() |
138 | { |
139 | - return the_default_input_device_hub(); |
140 | + return input_device_hub( |
141 | + [this]() |
142 | + { |
143 | + return std::make_shared<mi::ExternalInputDeviceHub>(the_default_input_device_hub(), |
144 | + the_main_loop()); |
145 | + }); |
146 | } |
147 | |
148 | std::shared_ptr<mi::DefaultInputDeviceHub> mir::DefaultServerConfiguration::the_default_input_device_hub() |
149 | @@ -314,7 +319,6 @@ |
150 | auto hub = std::make_shared<mi::DefaultInputDeviceHub>( |
151 | the_seat(), |
152 | the_input_reading_multiplexer(), |
153 | - the_main_loop(), |
154 | the_cookie_authority(), |
155 | the_key_mapper(), |
156 | the_server_status_listener()); |
157 | @@ -359,7 +363,7 @@ |
158 | return input_configuration_changer( |
159 | [this]() |
160 | { |
161 | - return std::make_shared<mi::ConfigChanger>(the_input_manager(), the_input_device_hub(), the_session_container(), the_session_event_handler_register()); |
162 | + return std::make_shared<mi::ConfigChanger>(the_input_manager(), the_default_input_device_hub(), the_session_container(), the_session_event_handler_register()); |
163 | } |
164 | ); |
165 | } |
166 | |
167 | === modified file 'src/server/input/default_device.cpp' |
168 | --- src/server/input/default_device.cpp 2017-02-28 08:53:57 +0000 |
169 | +++ src/server/input/default_device.cpp 2017-03-14 20:52:46 +0000 |
170 | @@ -60,6 +60,23 @@ |
171 | { |
172 | } |
173 | |
174 | +mi::DefaultDevice::DefaultDevice(MirInputDevice const& config, |
175 | + std::shared_ptr<dispatch::ActionQueue> const& actions, |
176 | + InputDevice& device, |
177 | + std::shared_ptr<KeyMapper> const& key_mapper, |
178 | + std::function<void(Device*)> const& callback) |
179 | + : DefaultDevice(config.id(), actions, device, key_mapper, callback) |
180 | +{ |
181 | + if (config.has_touchpad_config()) |
182 | + set_touchpad_configuration(config.touchpad_config()); |
183 | + if (config.has_keyboard_config()) |
184 | + set_keyboard_configuration(config.keyboard_config()); |
185 | + if (config.has_pointer_config()) |
186 | + set_pointer_configuration(config.pointer_config()); |
187 | + if (config.has_touchscreen_config()) |
188 | + set_touchscreen_configuration(config.touchscreen_config()); |
189 | +} |
190 | + |
191 | mi::DeviceCapabilities mi::DefaultDevice::capabilities() const |
192 | { |
193 | return info.capabilities; |
194 | @@ -117,6 +134,12 @@ |
195 | if (conf.cursor_acceleration_bias() < -1.0 || conf.cursor_acceleration_bias() > 1.0) |
196 | BOOST_THROW_EXCEPTION(std::invalid_argument("Cursor acceleration bias out of range")); |
197 | |
198 | + set_pointer_configuration(conf); |
199 | + device_changed_callback(this); |
200 | +} |
201 | + |
202 | +void mi::DefaultDevice::set_pointer_configuration(MirPointerConfig const& conf) |
203 | +{ |
204 | PointerSettings settings; |
205 | settings.handedness = conf.handedness(); |
206 | settings.acceleration = conf.acceleration(); |
207 | @@ -133,7 +156,6 @@ |
208 | { |
209 | dev->apply_settings(settings); |
210 | }); |
211 | - device_changed_callback(this); |
212 | } |
213 | |
214 | void mi::DefaultDevice::apply_touchpad_configuration(MirTouchpadConfig const& conf) |
215 | @@ -148,6 +170,12 @@ |
216 | conf.button_down_scroll_button() == mi::no_scroll_button) |
217 | BOOST_THROW_EXCEPTION(std::invalid_argument("No scroll button configured")); |
218 | |
219 | + set_touchpad_configuration(conf); |
220 | + device_changed_callback(this); |
221 | +} |
222 | + |
223 | +void mi::DefaultDevice::set_touchpad_configuration(MirTouchpadConfig const& conf) |
224 | +{ |
225 | TouchpadSettings settings; |
226 | settings.click_mode= conf.click_mode(); |
227 | settings.scroll_mode = conf.scroll_mode(); |
228 | @@ -166,7 +194,6 @@ |
229 | { |
230 | dev->apply_settings(settings); |
231 | }); |
232 | - device_changed_callback(this); |
233 | } |
234 | |
235 | mir::optional_value<MirKeyboardConfig> mi::DefaultDevice::keyboard_configuration() const |
236 | @@ -180,15 +207,18 @@ |
237 | if (!contains(info.capabilities, mi::DeviceCapability::keyboard)) |
238 | BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot apply a keyboard configuration")); |
239 | |
240 | - { |
241 | - std::lock_guard<std::mutex> lock(config_mutex); |
242 | - if (keyboard.value().device_keymap() != conf.device_keymap()) |
243 | - keyboard = conf; |
244 | - else |
245 | - return; |
246 | - } |
247 | + set_keyboard_configuration(conf); |
248 | + device_changed_callback(this); |
249 | +} |
250 | + |
251 | +void mi::DefaultDevice::set_keyboard_configuration(MirKeyboardConfig const& conf) |
252 | +{ |
253 | + std::lock_guard<std::mutex> lock(config_mutex); |
254 | + if (keyboard.value().device_keymap() != conf.device_keymap()) |
255 | + keyboard = conf; |
256 | + else |
257 | + return; |
258 | key_mapper->set_keymap_for_device(device_id, conf.device_keymap()); |
259 | - device_changed_callback(this); |
260 | } |
261 | |
262 | mir::optional_value<MirTouchscreenConfig> mi::DefaultDevice::touchscreen_configuration() const |
263 | @@ -206,6 +236,12 @@ |
264 | if (!touchscreen.is_set()) |
265 | BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot apply a touchscreen configuration")); |
266 | |
267 | + set_touchscreen_configuration(config); |
268 | + device_changed_callback(this); |
269 | +} |
270 | + |
271 | +void mi::DefaultDevice::set_touchscreen_configuration(MirTouchscreenConfig const& config) |
272 | +{ |
273 | TouchscreenSettings settings; |
274 | settings.output_id = config.output_id(); |
275 | settings.mapping_mode = config.mapping_mode(); |
276 | @@ -216,5 +252,27 @@ |
277 | { |
278 | dev->apply_settings(settings); |
279 | }); |
280 | - device_changed_callback(this); |
281 | +} |
282 | + |
283 | +MirInputDevice mi::DefaultDevice::config() const |
284 | +{ |
285 | + auto stored_dev = MirInputDevice( |
286 | + id(), |
287 | + capabilities(), |
288 | + name(), |
289 | + unique_id()); |
290 | + auto pointer_conf = pointer_configuration(); |
291 | + if (pointer_conf.is_set()) |
292 | + stored_dev.set_pointer_config(pointer_conf.value()); |
293 | + auto touchpad_conf = touchpad_configuration(); |
294 | + if (touchpad_conf.is_set()) |
295 | + stored_dev.set_touchpad_config(touchpad_conf.value()); |
296 | + auto keyboard_conf = keyboard_configuration(); |
297 | + if (keyboard_conf.is_set()) |
298 | + stored_dev.set_keyboard_config(keyboard_conf.value()); |
299 | + auto touchscreen_conf = touchscreen_configuration(); |
300 | + if (touchscreen_conf.is_set()) |
301 | + stored_dev.set_touchscreen_config(touchscreen_conf.value()); |
302 | + |
303 | + return stored_dev; |
304 | } |
305 | |
306 | === modified file 'src/server/input/default_device.h' |
307 | --- src/server/input/default_device.h 2017-02-28 08:53:57 +0000 |
308 | +++ src/server/input/default_device.h 2017-03-14 20:52:46 +0000 |
309 | @@ -58,6 +58,11 @@ |
310 | InputDevice& device, |
311 | std::shared_ptr<KeyMapper> const& key_mapper, |
312 | std::function<void(Device*)> const& change_callback); |
313 | + DefaultDevice(MirInputDevice const& config, |
314 | + std::shared_ptr<dispatch::ActionQueue> const& actions, |
315 | + InputDevice& device, |
316 | + std::shared_ptr<KeyMapper> const& key_mapper, |
317 | + std::function<void(Device*)> const& change_callback); |
318 | MirInputDeviceId id() const override; |
319 | DeviceCapabilities capabilities() const override; |
320 | std::string name() const override; |
321 | @@ -71,7 +76,14 @@ |
322 | void apply_keyboard_configuration(MirKeyboardConfig const&) override; |
323 | optional_value<MirTouchscreenConfig> touchscreen_configuration() const override; |
324 | void apply_touchscreen_configuration(MirTouchscreenConfig const&) override; |
325 | + |
326 | + MirInputDevice config() const; |
327 | private: |
328 | + void set_pointer_configuration(MirPointerConfig const&); |
329 | + void set_touchpad_configuration(MirTouchpadConfig const&); |
330 | + void set_keyboard_configuration(MirKeyboardConfig const&); |
331 | + void set_touchscreen_configuration(MirTouchscreenConfig const&); |
332 | + |
333 | void wake_hub_for_device_change(); |
334 | MirInputDeviceId const device_id; |
335 | InputDevice& device; |
336 | |
337 | === modified file 'src/server/input/default_input_device_hub.cpp' |
338 | --- src/server/input/default_input_device_hub.cpp 2017-03-14 02:26:28 +0000 |
339 | +++ src/server/input/default_input_device_hub.cpp 2017-03-14 20:52:46 +0000 |
340 | @@ -41,16 +41,129 @@ |
341 | |
342 | namespace mi = mir::input; |
343 | |
344 | +struct mi::ExternalInputDeviceHub::Internal : InputDeviceObserver |
345 | +{ |
346 | + Internal(std::shared_ptr<mi::InputDeviceHub> const& hub, |
347 | + std::shared_ptr<ServerActionQueue> const& queue) : |
348 | + hub{hub}, observer_queue{queue} |
349 | + {} |
350 | + void device_added(std::shared_ptr<Device> const& device) override; |
351 | + void device_changed(std::shared_ptr<Device> const& device) override; |
352 | + void device_removed(std::shared_ptr<Device> const& device) override; |
353 | + void changes_complete() override; |
354 | + |
355 | + std::weak_ptr<InputDeviceHub> hub; |
356 | + std::shared_ptr<ServerActionQueue> const observer_queue; |
357 | + ThreadSafeList<std::shared_ptr<InputDeviceObserver>> observers; |
358 | + std::vector<std::shared_ptr<Device>> devices_added; |
359 | + std::vector<std::shared_ptr<Device>> devices_changed; |
360 | + std::vector<std::shared_ptr<Device>> devices_removed; |
361 | + std::vector<std::shared_ptr<Device>> handles; |
362 | +}; |
363 | + |
364 | +mi::ExternalInputDeviceHub::ExternalInputDeviceHub(std::shared_ptr<mi::InputDeviceHub> const& hub, std::shared_ptr<mir::ServerActionQueue> const& queue) |
365 | + : data{std::make_shared<mi::ExternalInputDeviceHub::Internal>(hub, queue)} |
366 | +{ |
367 | + hub->add_observer(data); |
368 | +} |
369 | + |
370 | +mi::ExternalInputDeviceHub::~ExternalInputDeviceHub() |
371 | +{ |
372 | + data->observer_queue->pause_processing_for(data.get()); |
373 | +} |
374 | + |
375 | +void mi::ExternalInputDeviceHub::add_observer(std::shared_ptr<InputDeviceObserver> const& observer) |
376 | +{ |
377 | + auto hub = data->hub.lock(); |
378 | + if (hub) |
379 | + { |
380 | + data->observer_queue->enqueue( |
381 | + data.get(), |
382 | + [observer, data = this->data] |
383 | + { |
384 | + for (auto const& item : data->handles) |
385 | + observer->device_added(item); |
386 | + observer->changes_complete(); |
387 | + data->observers.add(observer); |
388 | + }); |
389 | + } |
390 | +} |
391 | + |
392 | +void mi::ExternalInputDeviceHub::remove_observer(std::weak_ptr<InputDeviceObserver> const& obs) |
393 | +{ |
394 | + auto observer = obs.lock(); |
395 | + data->observers.remove(observer); |
396 | +} |
397 | + |
398 | +void mi::ExternalInputDeviceHub::for_each_input_device(std::function<void(Device const& device)> const& callback) |
399 | +{ |
400 | + auto hub = data->hub.lock(); |
401 | + hub->for_each_input_device(callback); |
402 | +} |
403 | + |
404 | +void mi::ExternalInputDeviceHub::for_each_mutable_input_device(std::function<void(Device& device)> const& callback) |
405 | +{ |
406 | + auto hub = data->hub.lock(); |
407 | + hub->for_each_mutable_input_device(callback); |
408 | +} |
409 | + |
410 | +void mi::ExternalInputDeviceHub::Internal::device_added(std::shared_ptr<Device> const& device) |
411 | +{ |
412 | + devices_added.push_back(device); |
413 | +} |
414 | + |
415 | +void mi::ExternalInputDeviceHub::Internal::device_changed(std::shared_ptr<Device> const& device) |
416 | +{ |
417 | + devices_changed.push_back(device); |
418 | +} |
419 | + |
420 | +void mi::ExternalInputDeviceHub::Internal::device_removed(std::shared_ptr<Device> const& device) |
421 | +{ |
422 | + devices_removed.push_back(device); |
423 | +} |
424 | + |
425 | +void mi::ExternalInputDeviceHub::Internal::changes_complete() |
426 | +{ |
427 | + decltype(devices_added) added, changed, removed; |
428 | + |
429 | + std::swap(devices_added, added); |
430 | + std::swap(devices_changed, changed); |
431 | + std::swap(devices_removed, removed); |
432 | + |
433 | + if (!(added.empty() && changed.empty() && removed.empty())) |
434 | + observer_queue->enqueue( |
435 | + this, |
436 | + [this, added, changed, removed] |
437 | + { |
438 | + observers.for_each([&](std::shared_ptr<InputDeviceObserver> const& observer) |
439 | + { |
440 | + for (auto const& dev : added) |
441 | + observer->device_added(dev); |
442 | + for (auto const& dev : changed) |
443 | + observer->device_changed(dev); |
444 | + for (auto const& dev : removed) |
445 | + observer->device_removed(dev); |
446 | + observer->changes_complete(); |
447 | + }); |
448 | + |
449 | + auto end_it = handles.end(); |
450 | + for (auto const& dev : removed) |
451 | + end_it = remove(begin(handles), end(handles), dev); |
452 | + if (end_it != handles.end()) |
453 | + handles.erase(end_it, end(handles)); |
454 | + for (auto const& dev : added) |
455 | + handles.push_back(dev); |
456 | + }); |
457 | +} |
458 | + |
459 | mi::DefaultInputDeviceHub::DefaultInputDeviceHub( |
460 | std::shared_ptr<mi::Seat> const& seat, |
461 | std::shared_ptr<dispatch::MultiplexingDispatchable> const& input_multiplexer, |
462 | - std::shared_ptr<mir::ServerActionQueue> const& observer_queue, |
463 | std::shared_ptr<mir::cookie::Authority> const& cookie_authority, |
464 | std::shared_ptr<mi::KeyMapper> const& key_mapper, |
465 | std::shared_ptr<mir::ServerStatusListener> const& server_status_listener) |
466 | : seat{seat}, |
467 | input_dispatchable{input_multiplexer}, |
468 | - observer_queue(observer_queue), |
469 | device_queue(std::make_shared<dispatch::ActionQueue>()), |
470 | cookie_authority(cookie_authority), |
471 | key_mapper(key_mapper), |
472 | @@ -74,24 +187,16 @@ |
473 | |
474 | if (it == end(devices)) |
475 | { |
476 | - auto id = create_new_device_id(); |
477 | - auto handle = std::make_shared<DefaultDevice>(id, device_queue, *device, key_mapper, [this](Device *d){device_changed(d);}); |
478 | + auto handle = restore_or_create_device(*device); |
479 | // send input device info to observer loop.. |
480 | devices.push_back(std::make_unique<RegisteredDevice>( |
481 | - device, id, input_dispatchable, cookie_authority, handle)); |
482 | + device, handle->id(), input_dispatchable, cookie_authority, handle)); |
483 | |
484 | auto const& dev = devices.back(); |
485 | + add_device_handle(handle); |
486 | |
487 | seat->add_device(*handle); |
488 | dev->start(seat); |
489 | - |
490 | - // pass input device handle to observer loop.. |
491 | - observer_queue->enqueue(this, |
492 | - [this, handle]() |
493 | - { |
494 | - add_device_handle(handle); |
495 | - }); |
496 | - |
497 | } |
498 | else |
499 | { |
500 | @@ -112,19 +217,14 @@ |
501 | { |
502 | if (item->device_matches(device)) |
503 | { |
504 | + store_device_config(*item->handle); |
505 | auto seat = item->seat; |
506 | if (seat) |
507 | { |
508 | seat->remove_device(*item->handle); |
509 | item->stop(); |
510 | } |
511 | - // send input device info to observer queue.. |
512 | - observer_queue->enqueue( |
513 | - this, |
514 | - [this,id = item->id()]() |
515 | - { |
516 | - remove_device_handle(id); |
517 | - }); |
518 | + remove_device_handle(item->id()); |
519 | |
520 | return true; |
521 | } |
522 | @@ -230,18 +330,15 @@ |
523 | |
524 | void mi::DefaultInputDeviceHub::add_observer(std::shared_ptr<InputDeviceObserver> const& observer) |
525 | { |
526 | - observer_queue->enqueue( |
527 | - this, |
528 | - [observer,this] |
529 | + device_queue->enqueue( |
530 | + [this,observer]() |
531 | { |
532 | - observers.add(observer); |
533 | + std::unique_lock<std::mutex> lock(handles_guard); |
534 | for (auto const& item : handles) |
535 | - { |
536 | observer->device_added(item); |
537 | - } |
538 | observer->changes_complete(); |
539 | - } |
540 | - ); |
541 | + observers.add(observer); |
542 | + }); |
543 | } |
544 | |
545 | void mi::DefaultInputDeviceHub::for_each_input_device(std::function<void(Device const&)> const& callback) |
546 | @@ -270,12 +367,7 @@ |
547 | void mi::DefaultInputDeviceHub::remove_observer(std::weak_ptr<InputDeviceObserver> const& element) |
548 | { |
549 | auto observer = element.lock(); |
550 | - |
551 | - observer_queue->enqueue(this, |
552 | - [observer, this] |
553 | - { |
554 | - observers.remove(observer); |
555 | - }); |
556 | + observers.remove(observer); |
557 | } |
558 | |
559 | void mi::DefaultInputDeviceHub::add_device_handle(std::shared_ptr<DefaultDevice> const& handle) |
560 | @@ -285,7 +377,7 @@ |
561 | handles.push_back(handle); |
562 | } |
563 | |
564 | - observers.for_each([&handle](std::shared_ptr<InputDeviceObserver> const& observer) |
565 | + observers.for_each([&handle, this](std::shared_ptr<InputDeviceObserver> const& observer) |
566 | { |
567 | observer->device_added(handle); |
568 | observer->changes_complete(); |
569 | @@ -396,3 +488,51 @@ |
570 | } |
571 | } |
572 | |
573 | +void mi::DefaultInputDeviceHub::store_device_config(mi::DefaultDevice const& dev) |
574 | +{ |
575 | + std::lock_guard<std::mutex> lock(stored_configurations_guard); |
576 | + stored_devices.push_back(dev.config()); |
577 | +} |
578 | + |
579 | +mir::optional_value<MirInputDevice> |
580 | +mi::DefaultInputDeviceHub::get_stored_device_config(std::string const& id) |
581 | +{ |
582 | + mir::optional_value<MirInputDevice> optional_config; |
583 | + std::lock_guard<std::mutex> lock(stored_configurations_guard); |
584 | + auto pos = remove_if( |
585 | + begin(stored_devices), |
586 | + end(stored_devices), |
587 | + [&optional_config,id](auto const& handle) |
588 | + { |
589 | + if (id == handle.unique_id()) |
590 | + { |
591 | + optional_config = handle; |
592 | + return true; |
593 | + } |
594 | + return false; |
595 | + }); |
596 | + stored_devices.erase(pos, end(stored_devices)); |
597 | + |
598 | + return optional_config; |
599 | +} |
600 | + |
601 | +std::shared_ptr<mi::DefaultDevice> |
602 | +mi::DefaultInputDeviceHub::restore_or_create_device(mi::InputDevice& device) |
603 | +{ |
604 | + auto device_config = get_stored_device_config(device.get_device_info().unique_id); |
605 | + |
606 | + if (device_config.is_set()) |
607 | + return std::make_shared<DefaultDevice>( |
608 | + device_config.value(), |
609 | + device_queue, |
610 | + device, |
611 | + key_mapper, |
612 | + [this](Device *d){device_changed(d);}); |
613 | + else |
614 | + return std::make_shared<DefaultDevice>( |
615 | + create_new_device_id(), |
616 | + device_queue, |
617 | + device, |
618 | + key_mapper, |
619 | + [this](Device *d){device_changed(d);}); |
620 | +} |
621 | |
622 | === modified file 'src/server/input/default_input_device_hub.h' |
623 | --- src/server/input/default_input_device_hub.h 2017-03-14 02:26:28 +0000 |
624 | +++ src/server/input/default_input_device_hub.h 2017-03-14 20:52:46 +0000 |
625 | @@ -25,9 +25,11 @@ |
626 | #include "mir/input/input_sink.h" |
627 | #include "mir/input/seat.h" |
628 | #include "mir/input/input_device_hub.h" |
629 | +#include "mir/input/input_device_observer.h" |
630 | #include "mir/input/input_device_info.h" |
631 | #include "mir/input/mir_input_config.h" |
632 | #include "mir/thread_safe_list.h" |
633 | +#include "mir/optional_value.h" |
634 | |
635 | #include "mir_toolkit/event.h" |
636 | |
637 | @@ -57,13 +59,31 @@ |
638 | class DefaultDevice; |
639 | class Seat; |
640 | class KeyMapper; |
641 | - |
642 | -class DefaultInputDeviceHub : public InputDeviceRegistry, public InputDeviceHub |
643 | +class DefaultInputDeviceHub; |
644 | + |
645 | +struct ExternalInputDeviceHub : InputDeviceHub |
646 | +{ |
647 | + ExternalInputDeviceHub(std::shared_ptr<InputDeviceHub> const& actual_hub, |
648 | + std::shared_ptr<ServerActionQueue> const& observer_queue); |
649 | + ~ExternalInputDeviceHub(); |
650 | + |
651 | + void add_observer(std::shared_ptr<InputDeviceObserver> const&) override; |
652 | + void remove_observer(std::weak_ptr<InputDeviceObserver> const&) override; |
653 | + void for_each_input_device(std::function<void(Device const& device)> const& callback) override; |
654 | + void for_each_mutable_input_device(std::function<void(Device& device)> const& callback) override; |
655 | + |
656 | +private: |
657 | + struct Internal; |
658 | + std::shared_ptr<Internal> data; |
659 | +}; |
660 | + |
661 | +class DefaultInputDeviceHub : |
662 | + public InputDeviceRegistry, |
663 | + public InputDeviceHub |
664 | { |
665 | public: |
666 | DefaultInputDeviceHub(std::shared_ptr<Seat> const& seat, |
667 | std::shared_ptr<dispatch::MultiplexingDispatchable> const& input_multiplexer, |
668 | - std::shared_ptr<ServerActionQueue> const& observer_queue, |
669 | std::shared_ptr<cookie::Authority> const& cookie_authority, |
670 | std::shared_ptr<KeyMapper> const& key_mapper, |
671 | std::shared_ptr<ServerStatusListener> const& server_status_listener); |
672 | @@ -77,8 +97,6 @@ |
673 | void remove_observer(std::weak_ptr<InputDeviceObserver> const&) override; |
674 | void for_each_input_device(std::function<void(Device const& device)> const& callback) override; |
675 | void for_each_mutable_input_device(std::function<void(Device& device)> const& callback) override; |
676 | - |
677 | - |
678 | private: |
679 | void update_spots(); |
680 | void add_device_handle(std::shared_ptr<DefaultDevice> const& handle); |
681 | @@ -86,10 +104,13 @@ |
682 | void device_changed(Device* dev); |
683 | void emit_changed_devices(); |
684 | MirInputDeviceId create_new_device_id(); |
685 | + void store_device_config(DefaultDevice const& dev); |
686 | + std::shared_ptr<DefaultDevice> restore_or_create_device(InputDevice& dev); |
687 | + mir::optional_value<MirInputDevice> get_stored_device_config(std::string const& id); |
688 | + |
689 | std::shared_ptr<Seat> const seat; |
690 | std::shared_ptr<dispatch::MultiplexingDispatchable> const input_dispatchable; |
691 | - std::mutex handles_guard; |
692 | - std::shared_ptr<ServerActionQueue> const observer_queue; |
693 | + std::mutex mutable handles_guard; |
694 | std::shared_ptr<dispatch::ActionQueue> const device_queue; |
695 | std::shared_ptr<cookie::Authority> const cookie_authority; |
696 | std::shared_ptr<KeyMapper> const key_mapper; |
697 | @@ -130,6 +151,9 @@ |
698 | std::mutex changed_devices_guard; |
699 | std::unique_ptr<std::vector<std::shared_ptr<Device>>> changed_devices; |
700 | |
701 | + std::mutex stored_configurations_guard; |
702 | + std::vector<MirInputDevice> stored_devices; |
703 | + |
704 | MirInputDeviceId device_id_generator; |
705 | bool ready{false}; |
706 | }; |
707 | |
708 | === modified file 'tests/acceptance-tests/test_client_input.cpp' |
709 | --- tests/acceptance-tests/test_client_input.cpp 2017-03-14 02:26:28 +0000 |
710 | +++ tests/acceptance-tests/test_client_input.cpp 2017-03-14 20:52:46 +0000 |
711 | @@ -343,12 +343,13 @@ |
712 | devices_available.raise(); |
713 | }); |
714 | |
715 | - server.the_input_device_hub()->add_observer(counter); |
716 | + auto hub = server.the_input_device_hub(); |
717 | + hub->add_observer(counter); |
718 | |
719 | devices_available.wait_for(5s); |
720 | ASSERT_THAT(counter->count_devices, Eq(expected_number_of_input_devices)); |
721 | |
722 | - server.the_input_device_hub()->remove_observer(counter); |
723 | + hub->remove_observer(counter); |
724 | } |
725 | |
726 | MirInputDevice const* get_device_with_capabilities(MirInputConfig const* config, MirInputDeviceCapabilities caps) |
727 | |
728 | === modified file 'tests/acceptance-tests/test_input_device_hub.cpp' |
729 | --- tests/acceptance-tests/test_input_device_hub.cpp 2017-01-18 02:29:37 +0000 |
730 | +++ tests/acceptance-tests/test_input_device_hub.cpp 2017-03-14 20:52:46 +0000 |
731 | @@ -60,7 +60,8 @@ |
732 | EXPECT_CALL(observer, changes_complete()) |
733 | .WillOnce(mt::WakeUp(&observer_registered)); |
734 | |
735 | - server.the_input_device_hub()->add_observer(mt::fake_shared(observer)); |
736 | + auto device_hub = server.the_input_device_hub(); |
737 | + device_hub->add_observer(mt::fake_shared(observer)); |
738 | observer_registered.wait_for(std::chrono::seconds{4}); |
739 | } |
740 | |
741 | @@ -75,7 +76,8 @@ |
742 | EXPECT_CALL(observer, changes_complete()) |
743 | .WillOnce(mt::WakeUp(&callbacks_received)); |
744 | |
745 | - server.the_input_device_hub()->add_observer(mt::fake_shared(observer)); |
746 | + auto device_hub = server.the_input_device_hub(); |
747 | + device_hub->add_observer(mt::fake_shared(observer)); |
748 | observer_registered.wait_for(std::chrono::seconds{4}); |
749 | |
750 | keep_on_living = mtf::add_fake_input_device(mi::InputDeviceInfo{"keyboard", "keyboard-uid", mir::input::DeviceCapability::keyboard}); |
751 | |
752 | === modified file 'tests/acceptance-tests/test_nested_input.cpp' |
753 | --- tests/acceptance-tests/test_nested_input.cpp 2017-03-14 14:01:42 +0000 |
754 | +++ tests/acceptance-tests/test_nested_input.cpp 2017-03-14 20:52:46 +0000 |
755 | @@ -112,13 +112,12 @@ |
756 | |
757 | struct NestedInput : public mtf::HeadlessInProcessServer |
758 | { |
759 | - |
760 | void SetUp() |
761 | { |
762 | initial_display_layout(display_geometry); |
763 | mtf::HeadlessInProcessServer::SetUp(); |
764 | } |
765 | - |
766 | + |
767 | mtd::NestedMockEGL mock_egl; |
768 | |
769 | std::unique_ptr<mtf::FakeInputDevice> fake_keyboard{ |
770 | @@ -301,13 +300,12 @@ |
771 | NestedServerWithMockEventFilter nested_mir{new_connection()}; |
772 | auto nested_hub = nested_mir.server.the_input_device_hub(); |
773 | |
774 | - EXPECT_CALL(*mock_observer, device_added(_)).Times(1); |
775 | - EXPECT_CALL(*mock_observer, changes_complete()) |
776 | - .Times(1) |
777 | + EXPECT_CALL(*mock_observer, device_added(_)) |
778 | .WillOnce(mt::WakeUp(&input_device_changes_complete)); |
779 | |
780 | nested_hub->add_observer(mock_observer); |
781 | input_device_changes_complete.wait_for(10s); |
782 | + nested_hub->remove_observer(mock_observer); |
783 | } |
784 | |
785 | TEST_F(NestedInput, device_added_on_host_triggeres_nested_device_observer) |
786 | @@ -315,15 +313,18 @@ |
787 | NestedServerWithMockEventFilter nested_mir{new_connection()}; |
788 | auto nested_hub = nested_mir.server.the_input_device_hub(); |
789 | |
790 | - EXPECT_CALL(*mock_observer, changes_complete()).Times(1) |
791 | + // wait until we see the keyboard from the fixture: |
792 | + EXPECT_CALL(*mock_observer, device_added(_)).Times(1) |
793 | .WillOnce(mt::WakeUp(&input_device_changes_complete)); |
794 | nested_hub->add_observer(mock_observer); |
795 | |
796 | input_device_changes_complete.wait_for(10s); |
797 | EXPECT_THAT(input_device_changes_complete.raised(), Eq(true)); |
798 | input_device_changes_complete.reset(); |
799 | + ::testing::Mock::VerifyAndClearExpectations(&mock_observer); |
800 | |
801 | - EXPECT_CALL(*mock_observer, changes_complete()) |
802 | + // wait for the fake mouse |
803 | + EXPECT_CALL(*mock_observer, device_added(_)).Times(1) |
804 | .WillOnce(mt::WakeUp(&input_device_changes_complete)); |
805 | |
806 | auto mouse = mtf::add_fake_input_device(mi::InputDeviceInfo{"mouse", "mouse-uid" , mi::DeviceCapability::pointer}); |
807 | |
808 | === added file 'tests/include/mir/test/doubles/mock_device.h' |
809 | --- tests/include/mir/test/doubles/mock_device.h 1970-01-01 00:00:00 +0000 |
810 | +++ tests/include/mir/test/doubles/mock_device.h 2017-03-14 20:52:46 +0000 |
811 | @@ -0,0 +1,71 @@ |
812 | +/* |
813 | + * Copyright © 2017 Canonical Ltd. |
814 | + * |
815 | + * This program is free software: you can redistribute it and/or modify |
816 | + * it under the terms of the GNU General Public License version 3 as |
817 | + * published by the Free Software Foundation. |
818 | + * |
819 | + * This program is distributed in the hope that it will be useful, |
820 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
821 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
822 | + * GNU General Public License for more details. |
823 | + * |
824 | + * You should have received a copy of the GNU General Public License |
825 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
826 | + * |
827 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
828 | + */ |
829 | + |
830 | +#ifndef MIR_TEST_DOUBLES_MOCK_DEVICE_H_ |
831 | +#define MIR_TEST_DOUBLES_MOCK_DEVICE_H_ |
832 | + |
833 | +#include "mir/input/device.h" |
834 | +#include "mir/input/device_capability.h" |
835 | +#include "mir/input/mir_pointer_config.h" |
836 | +#include "mir/input/mir_keyboard_config.h" |
837 | +#include "mir/input/mir_touchpad_config.h" |
838 | +#include "mir/input/mir_touchscreen_config.h" |
839 | +#include "mir/optional_value.h" |
840 | + |
841 | +#include <string> |
842 | + |
843 | +namespace mir |
844 | +{ |
845 | +namespace test |
846 | +{ |
847 | +namespace doubles |
848 | +{ |
849 | + |
850 | +struct MockDevice : input::Device |
851 | +{ |
852 | + MockDevice(MirInputDeviceId id, input::DeviceCapabilities caps, std::string const& name, std::string const& unique_id) |
853 | + { |
854 | + ON_CALL(*this, id()).WillByDefault(testing::Return(id)); |
855 | + ON_CALL(*this, name()).WillByDefault(testing::Return(name)); |
856 | + ON_CALL(*this, unique_id()).WillByDefault(testing::Return(unique_id)); |
857 | + ON_CALL(*this, capabilities()).WillByDefault(testing::Return(caps)); |
858 | + ON_CALL(*this, pointer_configuration()).WillByDefault(testing::Return(MirPointerConfig{})); |
859 | + ON_CALL(*this, keyboard_configuration()).WillByDefault(testing::Return(MirKeyboardConfig{})); |
860 | + ON_CALL(*this, touchpad_configuration()).WillByDefault(testing::Return(MirTouchpadConfig{})); |
861 | + ON_CALL(*this, touchscreen_configuration()).WillByDefault(testing::Return(MirTouchscreenConfig{})); |
862 | + } |
863 | + |
864 | + MOCK_CONST_METHOD0(id, MirInputDeviceId()); |
865 | + MOCK_CONST_METHOD0(capabilities, input::DeviceCapabilities()); |
866 | + MOCK_CONST_METHOD0(name, std::string()); |
867 | + MOCK_CONST_METHOD0(unique_id, std::string()); |
868 | + MOCK_CONST_METHOD0(pointer_configuration, optional_value<MirPointerConfig>()); |
869 | + MOCK_CONST_METHOD0(touchpad_configuration, optional_value<MirTouchpadConfig>()); |
870 | + MOCK_CONST_METHOD0(keyboard_configuration, optional_value<MirKeyboardConfig>()); |
871 | + MOCK_CONST_METHOD0(touchscreen_configuration, optional_value<MirTouchscreenConfig>()); |
872 | + MOCK_METHOD1(apply_pointer_configuration, void(MirPointerConfig const&)); |
873 | + MOCK_METHOD1(apply_touchpad_configuration, void(MirTouchpadConfig const&)); |
874 | + MOCK_METHOD1(apply_keyboard_configuration, void(MirKeyboardConfig const&)); |
875 | + MOCK_METHOD1(apply_touchscreen_configuration, void(MirTouchscreenConfig const&)); |
876 | +}; |
877 | +} |
878 | +} |
879 | +} |
880 | + |
881 | +#endif |
882 | + |
883 | |
884 | === modified file 'tests/integration-tests/input/test_single_seat_setup.cpp' |
885 | --- tests/integration-tests/input/test_single_seat_setup.cpp 2017-03-14 02:26:28 +0000 |
886 | +++ tests/integration-tests/input/test_single_seat_setup.cpp 2017-03-14 20:52:46 +0000 |
887 | @@ -51,6 +51,7 @@ |
888 | #include "mir/input/input_device_info.h" |
889 | #include "mir/geometry/rectangles.h" |
890 | #include "mir/test/input_config_matchers.h" |
891 | +#include "mir/test/fd_utils.h" |
892 | |
893 | #include <gmock/gmock.h> |
894 | #include <gtest/gtest.h> |
895 | @@ -131,9 +132,9 @@ |
896 | mt::fake_shared(mock_cursor_listener), mt::fake_shared(display_config), |
897 | mt::fake_shared(key_mapper), mt::fake_shared(clock), |
898 | mt::fake_shared(mock_seat_observer)}; |
899 | - mi::DefaultInputDeviceHub hub{mt::fake_shared(seat), mt::fake_shared(multiplexer), |
900 | - mt::fake_shared(observer_loop), cookie_authority, |
901 | - mt::fake_shared(key_mapper), mt::fake_shared(mock_status_listener)}; |
902 | + mi::DefaultInputDeviceHub hub{mt::fake_shared(seat), mt::fake_shared(multiplexer), |
903 | + cookie_authority, mt::fake_shared(key_mapper), |
904 | + mt::fake_shared(mock_status_listener)}; |
905 | NiceMock<mtd::MockInputDeviceObserver> mock_observer; |
906 | mi::ConfigChanger changer{ |
907 | mt::fake_shared(mock_input_manager), |
908 | @@ -151,6 +152,21 @@ |
909 | |
910 | std::chrono::nanoseconds arbitrary_timestamp; |
911 | |
912 | + void SetUp() |
913 | + { |
914 | + // execute registration of ConfigChanger |
915 | + expect_and_execute_multiplexer(); |
916 | + } |
917 | + |
918 | + void expect_and_execute_multiplexer(int count = 1) |
919 | + { |
920 | + for (int i = 0; i != count; ++i) |
921 | + { |
922 | + mt::fd_becomes_readable(multiplexer.watch_fd(), 5s); |
923 | + multiplexer.dispatch(mir::dispatch::FdEvent::readable); |
924 | + } |
925 | + } |
926 | + |
927 | void capture_input_sink(NiceMock<mtd::MockInputDevice>& dev, mi::InputSink*& sink, mi::EventBuilder*& builder) |
928 | { |
929 | ON_CALL(dev,start(_,_)) |
930 | @@ -173,14 +189,13 @@ |
931 | |
932 | capture_input_sink(device, sink, builder); |
933 | |
934 | - EXPECT_CALL(mock_observer,device_added(_)) |
935 | + EXPECT_CALL(mock_observer, device_added(_)) |
936 | .WillOnce(SaveArg<0>(&handle)); |
937 | |
938 | hub.add_observer(mt::fake_shared(mock_observer)); |
939 | + expect_and_execute_multiplexer(1); |
940 | hub.add_device(mt::fake_shared(device)); |
941 | |
942 | - observer_loop.trigger_server_actions(); |
943 | - |
944 | auto event = builder->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, |
945 | KEY_A); |
946 | |
947 | @@ -198,8 +213,6 @@ |
948 | |
949 | hub.add_device(mt::fake_shared(device)); |
950 | |
951 | - observer_loop.trigger_server_actions(); |
952 | - |
953 | auto touch_event_1 = builder->touch_event( |
954 | arbitrary_timestamp, |
955 | {{0, mir_touch_action_down, mir_touch_tooltype_finger, 21.0f, 34.0f, 50.0f, 15.0f, 5.0f, 4.0f}}); |
956 | @@ -245,7 +258,6 @@ |
957 | capture_input_sink(device, sink, builder); |
958 | |
959 | hub.add_device(mt::fake_shared(device)); |
960 | - observer_loop.trigger_server_actions(); |
961 | sink->handle_input( |
962 | *builder->pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 0.0f, 0.0f, 10.0f, 10.0f)); |
963 | sink->handle_input( |
964 | @@ -265,7 +277,6 @@ |
965 | mi::EventBuilder* builder; |
966 | capture_input_sink(device, sink, builder); |
967 | hub.add_device(mt::fake_shared(device)); |
968 | - observer_loop.trigger_server_actions(); |
969 | |
970 | sink->handle_input( |
971 | *builder->pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 0.0f, 0.0f, 10.0f, 20.0f)); |
972 | @@ -295,8 +306,8 @@ |
973 | ON_CALL(mock_observer, device_added(_)).WillByDefault(SaveArg<0>(&dev)); |
974 | |
975 | hub.add_observer(mt::fake_shared(mock_observer)); |
976 | + expect_and_execute_multiplexer(); |
977 | hub.add_device(mt::fake_shared(touchpad)); |
978 | - observer_loop.trigger_server_actions(); |
979 | |
980 | EXPECT_CALL(touchpad, apply_settings(Matcher<mi::PointerSettings const&>(_))); |
981 | |
982 | @@ -311,8 +322,8 @@ |
983 | ON_CALL(mock_observer, device_added(_)).WillByDefault(SaveArg<0>(&dev)); |
984 | |
985 | hub.add_observer(mt::fake_shared(mock_observer)); |
986 | + expect_and_execute_multiplexer(); |
987 | hub.add_device(mt::fake_shared(touchpad)); |
988 | - observer_loop.trigger_server_actions(); |
989 | |
990 | EXPECT_CALL(touchpad, apply_settings(Matcher<mi::TouchpadSettings const&>(_))); |
991 | |
992 | @@ -334,9 +345,9 @@ |
993 | .WillOnce(SaveArg<0>(&key_handle)); |
994 | |
995 | hub.add_observer(mt::fake_shared(mock_observer)); |
996 | + expect_and_execute_multiplexer(); |
997 | hub.add_device(mt::fake_shared(another_device)); |
998 | |
999 | - observer_loop.trigger_server_actions(); |
1000 | |
1001 | const MirInputEventModifiers shift_left = mir_input_event_modifier_shift_left | mir_input_event_modifier_shift; |
1002 | auto shift_down = |
1003 | @@ -370,11 +381,10 @@ |
1004 | .WillOnce(SaveArg<0>(&key_handle)); |
1005 | |
1006 | hub.add_observer(mt::fake_shared(mock_observer)); |
1007 | + expect_and_execute_multiplexer(); |
1008 | hub.add_device(mt::fake_shared(device)); |
1009 | hub.add_device(mt::fake_shared(another_device)); |
1010 | |
1011 | - observer_loop.trigger_server_actions(); |
1012 | - |
1013 | const MirInputEventModifiers r_alt_modifier = mir_input_event_modifier_alt_right | mir_input_event_modifier_alt; |
1014 | auto key = |
1015 | key_event_builder->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_RIGHTALT); |
1016 | @@ -415,6 +425,7 @@ |
1017 | .WillOnce(SaveArg<0>(&key_handle_2)); |
1018 | |
1019 | hub.add_observer(mt::fake_shared(mock_observer)); |
1020 | + expect_and_execute_multiplexer(); |
1021 | hub.add_device(mt::fake_shared(device)); |
1022 | hub.add_device(mt::fake_shared(another_device)); |
1023 | hub.add_device(mt::fake_shared(third_device)); |
1024 | @@ -423,8 +434,6 @@ |
1025 | const MirInputEventModifiers l_ctrl_modifier = mir_input_event_modifier_ctrl_left | mir_input_event_modifier_ctrl; |
1026 | const MirInputEventModifiers combined_modifier = r_alt_modifier | l_ctrl_modifier; |
1027 | |
1028 | - observer_loop.trigger_server_actions(); |
1029 | - |
1030 | auto alt_down = key_event_builder_1->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_RIGHTALT); |
1031 | auto ctrl_down = key_event_builder_2->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_LEFTCTRL); |
1032 | auto ctrl_up = key_event_builder_2->key_event(arbitrary_timestamp, mir_keyboard_action_up, 0, KEY_LEFTCTRL); |
1033 | @@ -462,8 +471,6 @@ |
1034 | hub.add_device(mt::fake_shared(device)); |
1035 | hub.add_device(mt::fake_shared(another_device)); |
1036 | |
1037 | - observer_loop.trigger_server_actions(); |
1038 | - |
1039 | auto motion_1 = |
1040 | mouse_event_builder_1->pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 0, 0, 23, 20); |
1041 | auto motion_2 = |
1042 | @@ -495,8 +502,6 @@ |
1043 | hub.add_device(mt::fake_shared(device)); |
1044 | hub.add_device(mt::fake_shared(another_device)); |
1045 | |
1046 | - observer_loop.trigger_server_actions(); |
1047 | - |
1048 | auto motion_1 = |
1049 | mouse_event_builder_1->pointer_event(arbitrary_timestamp, mir_pointer_action_button_down, mir_pointer_button_primary, 0, 0, 0, 0); |
1050 | auto motion_2 = |
1051 | @@ -525,7 +530,6 @@ |
1052 | |
1053 | EXPECT_CALL(session, send_input_config(UnorderedElementsAre(DeviceMatches(device.get_device_info())))); |
1054 | hub.add_device(mt::fake_shared(device)); |
1055 | - observer_loop.trigger_server_actions(); |
1056 | } |
1057 | |
1058 | TEST_F(SingleSeatInputDeviceHubSetup, input_device_changes_sent_to_session_multiple_devices) |
1059 | @@ -534,25 +538,21 @@ |
1060 | stub_session_container.insert_session(mt::fake_shared(session)); |
1061 | |
1062 | hub.add_device(mt::fake_shared(device)); |
1063 | - observer_loop.trigger_server_actions(); |
1064 | |
1065 | EXPECT_CALL(session, |
1066 | send_input_config(UnorderedElementsAre(DeviceMatches(device.get_device_info()), |
1067 | DeviceMatches(another_device.get_device_info())))); |
1068 | hub.add_device(mt::fake_shared(another_device)); |
1069 | - observer_loop.trigger_server_actions(); |
1070 | } |
1071 | |
1072 | TEST_F(SingleSeatInputDeviceHubSetup, input_device_changes_sent_to_sink_removal) |
1073 | { |
1074 | hub.add_device(mt::fake_shared(device)); |
1075 | hub.add_device(mt::fake_shared(another_device)); |
1076 | - observer_loop.trigger_server_actions(); |
1077 | |
1078 | NiceMock<mtd::MockSceneSession> session; |
1079 | stub_session_container.insert_session(mt::fake_shared(session)); |
1080 | EXPECT_CALL(session, |
1081 | send_input_config(UnorderedElementsAre(DeviceMatches(another_device.get_device_info())))); |
1082 | hub.remove_device(mt::fake_shared(device)); |
1083 | - observer_loop.trigger_server_actions(); |
1084 | } |
1085 | |
1086 | === modified file 'tests/unit-tests/input/CMakeLists.txt' |
1087 | --- tests/unit-tests/input/CMakeLists.txt 2017-03-13 08:12:52 +0000 |
1088 | +++ tests/unit-tests/input/CMakeLists.txt 2017-03-14 20:52:46 +0000 |
1089 | @@ -8,6 +8,7 @@ |
1090 | ${CMAKE_CURRENT_SOURCE_DIR}/test_input_event.cpp |
1091 | ${CMAKE_CURRENT_SOURCE_DIR}/test_config_changer.cpp |
1092 | ${CMAKE_CURRENT_SOURCE_DIR}/test_event_builders.cpp |
1093 | + ${CMAKE_CURRENT_SOURCE_DIR}/test_external_input_device_hub.cpp |
1094 | ${CMAKE_CURRENT_SOURCE_DIR}/test_default_device.cpp |
1095 | ${CMAKE_CURRENT_SOURCE_DIR}/test_default_input_device_hub.cpp |
1096 | ${CMAKE_CURRENT_SOURCE_DIR}/test_default_input_manager.cpp |
1097 | |
1098 | === modified file 'tests/unit-tests/input/test_config_changer.cpp' |
1099 | --- tests/unit-tests/input/test_config_changer.cpp 2017-02-28 08:53:57 +0000 |
1100 | +++ tests/unit-tests/input/test_config_changer.cpp 2017-03-14 20:52:46 +0000 |
1101 | @@ -29,6 +29,7 @@ |
1102 | |
1103 | #include "mir/test/doubles/mock_input_device_hub.h" |
1104 | #include "mir/test/doubles/mock_input_manager.h" |
1105 | +#include "mir/test/doubles/mock_device.h" |
1106 | #include "mir/test/doubles/mock_scene_session.h" |
1107 | #include "mir/test/doubles/stub_session.h" |
1108 | #include "mir/test/doubles/stub_session_container.h" |
1109 | @@ -47,34 +48,6 @@ |
1110 | namespace |
1111 | { |
1112 | |
1113 | -struct MockDevice : mir::input::Device |
1114 | -{ |
1115 | - MockDevice(MirInputDeviceId id, mi::DeviceCapabilities caps, std::string const& name, std::string const& unique_id) |
1116 | - { |
1117 | - ON_CALL(*this, id()).WillByDefault(Return(id)); |
1118 | - ON_CALL(*this, name()).WillByDefault(Return(name)); |
1119 | - ON_CALL(*this, unique_id()).WillByDefault(Return(unique_id)); |
1120 | - ON_CALL(*this, capabilities()).WillByDefault(Return(caps)); |
1121 | - ON_CALL(*this, pointer_configuration()).WillByDefault(Return(MirPointerConfig{})); |
1122 | - ON_CALL(*this, keyboard_configuration()).WillByDefault(Return(MirKeyboardConfig{})); |
1123 | - ON_CALL(*this, touchpad_configuration()).WillByDefault(Return(MirTouchpadConfig{})); |
1124 | - ON_CALL(*this, touchscreen_configuration()).WillByDefault(Return(MirTouchscreenConfig{})); |
1125 | - } |
1126 | - |
1127 | - MOCK_CONST_METHOD0(id, MirInputDeviceId()); |
1128 | - MOCK_CONST_METHOD0(capabilities, mir::input::DeviceCapabilities()); |
1129 | - MOCK_CONST_METHOD0(name, std::string()); |
1130 | - MOCK_CONST_METHOD0(unique_id, std::string()); |
1131 | - MOCK_CONST_METHOD0(pointer_configuration, mir::optional_value<MirPointerConfig>()); |
1132 | - MOCK_CONST_METHOD0(touchpad_configuration, mir::optional_value<MirTouchpadConfig>()); |
1133 | - MOCK_CONST_METHOD0(keyboard_configuration, mir::optional_value<MirKeyboardConfig>()); |
1134 | - MOCK_CONST_METHOD0(touchscreen_configuration, mir::optional_value<MirTouchscreenConfig>()); |
1135 | - MOCK_METHOD1(apply_pointer_configuration, void(MirPointerConfig const&)); |
1136 | - MOCK_METHOD1(apply_touchpad_configuration, void(MirTouchpadConfig const&)); |
1137 | - MOCK_METHOD1(apply_keyboard_configuration, void(MirKeyboardConfig const&)); |
1138 | - MOCK_METHOD1(apply_touchscreen_configuration, void(MirTouchscreenConfig const&)); |
1139 | -}; |
1140 | - |
1141 | struct FakeInputDeviceHub : mir::input::InputDeviceHub |
1142 | { |
1143 | std::shared_ptr<mi::InputDeviceObserver> observer; |
1144 | @@ -86,8 +59,8 @@ |
1145 | mi::DeviceCapability::keyboard | mi::DeviceCapability::alpha_numeric | |
1146 | mi::DeviceCapability::touchscreen; |
1147 | |
1148 | - NiceMock<MockDevice> first_device{first_id, caps, first, first}; |
1149 | - NiceMock<MockDevice> second_device{second_id, caps, second, second}; |
1150 | + NiceMock<mtd::MockDevice> first_device{first_id, caps, first, first}; |
1151 | + NiceMock<mtd::MockDevice> second_device{second_id, caps, second, second}; |
1152 | std::vector<std::shared_ptr<mir::input::Device>> active_devices; |
1153 | |
1154 | void add_observer(std::shared_ptr<mi::InputDeviceObserver> const& obs) override |
1155 | |
1156 | === modified file 'tests/unit-tests/input/test_default_device.cpp' |
1157 | --- tests/unit-tests/input/test_default_device.cpp 2017-02-28 08:53:57 +0000 |
1158 | +++ tests/unit-tests/input/test_default_device.cpp 2017-03-14 20:52:46 +0000 |
1159 | @@ -18,6 +18,7 @@ |
1160 | |
1161 | #include "src/server/input/default_device.h" |
1162 | #include "mir/input/input_device.h" |
1163 | +#include "mir/input/mir_input_config.h" |
1164 | #include "mir/input/mir_touchpad_config.h" |
1165 | #include "mir/input/mir_pointer_config.h" |
1166 | #include "mir/input/mir_touchscreen_config.h" |
1167 | @@ -57,6 +58,7 @@ |
1168 | NiceMock<MockInputDevice> touchscreen; |
1169 | NiceMock<mtd::MockKeyMapper> key_mapper; |
1170 | std::shared_ptr<md::ActionQueue> queue{std::make_shared<md::ActionQueue>()}; |
1171 | + std::function<void(mi::Device*)> const change_callback{[](mi::Device*){}}; |
1172 | |
1173 | DefaultDevice() |
1174 | { |
1175 | @@ -181,3 +183,128 @@ |
1176 | |
1177 | queue->dispatch(md::FdEvent::readable); |
1178 | } |
1179 | + |
1180 | +TEST_F(DefaultDevice, touchpad_device_can_be_constructed_from_input_config) |
1181 | +{ |
1182 | + MirTouchpadConfig const tpd_conf{mir_touchpad_click_mode_finger_count, mir_touchpad_scroll_mode_edge_scroll, 0, false, true, true, true}; |
1183 | + MirPointerConfig const ptr_conf{mir_pointer_handedness_right, mir_pointer_acceleration_adaptive, 0.5, -1.0, 1.0}; |
1184 | + MirInputDevice conf(MirInputDeviceId{17}, mi::DeviceCapability::touchpad|mi::DeviceCapability::pointer, "touchpad", "toouchpad-event7"); |
1185 | + conf.set_touchpad_config(tpd_conf); |
1186 | + conf.set_pointer_config(ptr_conf); |
1187 | + mi::DefaultDevice dev(conf, queue, touchpad, mt::fake_shared(key_mapper), change_callback); |
1188 | + |
1189 | + EXPECT_EQ(tpd_conf, dev.touchpad_configuration().value()); |
1190 | + EXPECT_EQ(ptr_conf, dev.pointer_configuration().value()); |
1191 | +} |
1192 | + |
1193 | +TEST_F(DefaultDevice, pointer_device_can_be_constructed_from_input_config) |
1194 | +{ |
1195 | + MirPointerConfig const ptr_config{mir_pointer_handedness_left, mir_pointer_acceleration_none, 0, 1.0, 1.0}; |
1196 | + MirInputDevice conf(MirInputDeviceId{11}, mi::DeviceCapability::pointer, "pointer", "pointer-event7"); |
1197 | + conf.set_pointer_config(ptr_config); |
1198 | + mi::DefaultDevice dev(conf, queue, mouse, mt::fake_shared(key_mapper), change_callback); |
1199 | + |
1200 | + EXPECT_EQ(ptr_config, dev.pointer_configuration().value()); |
1201 | +} |
1202 | + |
1203 | +TEST_F(DefaultDevice, keyboard_device_can_be_constructed_from_input_config) |
1204 | +{ |
1205 | + MirKeyboardConfig const kbd_config{mi::Keymap{"pc104", "dvorak", "", ""}}; |
1206 | + MirInputDevice conf(MirInputDeviceId{3}, mi::DeviceCapability::keyboard, "keyboard", "keyboard-event3c"); |
1207 | + conf.set_keyboard_config(kbd_config); |
1208 | + mi::DefaultDevice dev(conf, queue, keyboard, mt::fake_shared(key_mapper), change_callback); |
1209 | + |
1210 | + EXPECT_EQ(kbd_config, dev.keyboard_configuration().value()); |
1211 | +} |
1212 | + |
1213 | +TEST_F(DefaultDevice, touchscreen_device_can_be_constructed_from_input_config) |
1214 | +{ |
1215 | + MirTouchscreenConfig const ts_config{0, mir_touchscreen_mapping_mode_to_display_wall}; |
1216 | + MirInputDevice conf(MirInputDeviceId{5}, mi::DeviceCapability::touchscreen, "ts", "ts-event7"); |
1217 | + conf.set_touchscreen_config(ts_config); |
1218 | + |
1219 | + mi::DefaultDevice dev(conf, queue, touchscreen, mt::fake_shared(key_mapper), change_callback); |
1220 | + |
1221 | + EXPECT_EQ(ts_config, dev.touchscreen_configuration().value()); |
1222 | +} |
1223 | + |
1224 | +TEST_F(DefaultDevice, device_config_can_be_querried_from_touchpad) |
1225 | +{ |
1226 | + MirInputDeviceId const device_id{17}; |
1227 | + mi::DefaultDevice dev(device_id, queue, touchpad, mt::fake_shared(key_mapper), change_callback); |
1228 | + |
1229 | + auto dev_info = touchpad.get_device_info(); |
1230 | + MirInputDevice conf(device_id, dev_info.capabilities, dev_info.name, dev_info.unique_id); |
1231 | + MirTouchpadConfig const tpd_conf{ |
1232 | + mir_touchpad_click_mode_finger_count, |
1233 | + mir_touchpad_scroll_mode_edge_scroll, |
1234 | + 0, |
1235 | + false, |
1236 | + true, |
1237 | + true, |
1238 | + true}; |
1239 | + MirPointerConfig const ptr_conf{ |
1240 | + mir_pointer_handedness_right, |
1241 | + mir_pointer_acceleration_adaptive, |
1242 | + 0.5, |
1243 | + -1.0, |
1244 | + 1.0}; |
1245 | + |
1246 | + conf.set_touchpad_config(tpd_conf); |
1247 | + conf.set_pointer_config(ptr_conf); |
1248 | + |
1249 | + dev.apply_touchpad_configuration(tpd_conf); |
1250 | + dev.apply_pointer_configuration(ptr_conf); |
1251 | + |
1252 | + EXPECT_EQ(conf, dev.config()); |
1253 | +} |
1254 | + |
1255 | +TEST_F(DefaultDevice, device_config_can_be_querried_from_pointer_device) |
1256 | +{ |
1257 | + MirInputDeviceId const device_id{11}; |
1258 | + mi::DefaultDevice dev(device_id, queue, mouse, mt::fake_shared(key_mapper), change_callback); |
1259 | + |
1260 | + auto dev_info = mouse.get_device_info(); |
1261 | + MirInputDevice conf(device_id, dev_info.capabilities, dev_info.name, dev_info.unique_id); |
1262 | + MirPointerConfig const ptr_config{ |
1263 | + mir_pointer_handedness_left, |
1264 | + mir_pointer_acceleration_none, |
1265 | + 0, |
1266 | + 1.0, |
1267 | + 1.0}; |
1268 | + |
1269 | + conf.set_pointer_config(ptr_config); |
1270 | + dev.apply_pointer_configuration(ptr_config); |
1271 | + |
1272 | + EXPECT_EQ(conf, dev.config()); |
1273 | +} |
1274 | + |
1275 | +TEST_F(DefaultDevice, device_config_can_be_querried_from_keyboard_device) |
1276 | +{ |
1277 | + MirInputDeviceId const device_id{3}; |
1278 | + mi::DefaultDevice dev(device_id, queue, keyboard, mt::fake_shared(key_mapper), change_callback); |
1279 | + |
1280 | + auto dev_info = keyboard.get_device_info(); |
1281 | + MirInputDevice conf(device_id, dev_info.capabilities, dev_info.name, dev_info.unique_id); |
1282 | + MirKeyboardConfig const kbd_config{mi::Keymap{"pc104", "dvorak", "", ""}}; |
1283 | + |
1284 | + conf.set_keyboard_config(kbd_config); |
1285 | + dev.apply_keyboard_configuration(kbd_config); |
1286 | + |
1287 | + EXPECT_EQ(kbd_config, dev.keyboard_configuration().value()); |
1288 | +} |
1289 | + |
1290 | +TEST_F(DefaultDevice, device_config_can_be_querried_from_touchscreen) |
1291 | +{ |
1292 | + MirInputDeviceId const device_id{5}; |
1293 | + mi::DefaultDevice dev(device_id, queue, touchscreen, mt::fake_shared(key_mapper), change_callback); |
1294 | + |
1295 | + auto dev_info = touchscreen.get_device_info(); |
1296 | + MirInputDevice conf(device_id, dev_info.capabilities, dev_info.name, dev_info.unique_id); |
1297 | + MirTouchscreenConfig const ts_config{0, mir_touchscreen_mapping_mode_to_display_wall}; |
1298 | + |
1299 | + conf.set_touchscreen_config(ts_config); |
1300 | + dev.apply_touchscreen_configuration(ts_config); |
1301 | + |
1302 | + EXPECT_EQ(ts_config, dev.touchscreen_configuration().value()); |
1303 | +} |
1304 | |
1305 | === modified file 'tests/unit-tests/input/test_default_input_device_hub.cpp' |
1306 | --- tests/unit-tests/input/test_default_input_device_hub.cpp 2017-03-13 08:12:52 +0000 |
1307 | +++ tests/unit-tests/input/test_default_input_device_hub.cpp 2017-03-14 20:52:46 +0000 |
1308 | @@ -30,6 +30,7 @@ |
1309 | #include "mir/test/doubles/triggered_main_loop.h" |
1310 | #include "mir/test/event_matchers.h" |
1311 | #include "mir/test/fake_shared.h" |
1312 | +#include "mir/test/fd_utils.h" |
1313 | |
1314 | #include "mir/dispatch/action_queue.h" |
1315 | #include "mir/geometry/rectangles.h" |
1316 | @@ -77,14 +78,14 @@ |
1317 | |
1318 | struct InputDeviceHubTest : ::testing::Test |
1319 | { |
1320 | - mtd::TriggeredMainLoop observer_loop; |
1321 | std::shared_ptr<mir::cookie::Authority> cookie_authority = mir::cookie::Authority::create(); |
1322 | mir::dispatch::MultiplexingDispatchable multiplexer; |
1323 | NiceMock<mtd::MockInputSeat> mock_seat; |
1324 | NiceMock<mtd::MockKeyMapper> mock_key_mapper; |
1325 | NiceMock<mtd::MockServerStatusListener> mock_server_status_listener; |
1326 | mi::DefaultInputDeviceHub hub{mt::fake_shared(mock_seat), mt::fake_shared(multiplexer), |
1327 | - mt::fake_shared(observer_loop), cookie_authority, mt::fake_shared(mock_key_mapper), mt::fake_shared(mock_server_status_listener)}; |
1328 | + cookie_authority, mt::fake_shared(mock_key_mapper), |
1329 | + mt::fake_shared(mock_server_status_listener)}; |
1330 | NiceMock<mtd::MockInputDeviceObserver> mock_observer; |
1331 | NiceMock<mtd::MockInputDevice> device{"device","dev-1", mi::DeviceCapability::unknown}; |
1332 | NiceMock<mtd::MockInputDevice> another_device{"another_device","dev-2", mi::DeviceCapability::keyboard}; |
1333 | @@ -104,6 +105,12 @@ |
1334 | } |
1335 | )); |
1336 | } |
1337 | + |
1338 | + void expect_and_execute_multiplexer() |
1339 | + { |
1340 | + mt::fd_becomes_readable(multiplexer.watch_fd(), 2s); |
1341 | + multiplexer.dispatch(mir::dispatch::FdEvent::readable); |
1342 | + } |
1343 | }; |
1344 | |
1345 | TEST_F(InputDeviceHubTest, input_device_hub_starts_device) |
1346 | @@ -161,8 +168,7 @@ |
1347 | hub.add_device(mt::fake_shared(another_device)); |
1348 | hub.add_observer(mt::fake_shared(mock_observer)); |
1349 | |
1350 | - observer_loop.trigger_server_actions(); |
1351 | - |
1352 | + expect_and_execute_multiplexer(); |
1353 | EXPECT_THAT(handle_1,Ne(handle_2)); |
1354 | EXPECT_THAT(handle_1->unique_id(),Ne(handle_2->unique_id())); |
1355 | } |
1356 | @@ -208,10 +214,13 @@ |
1357 | EXPECT_CALL(mock_observer, changes_complete()); |
1358 | |
1359 | hub.add_observer(mt::fake_shared(mock_observer)); |
1360 | + expect_and_execute_multiplexer(); |
1361 | + |
1362 | hub.add_device(mt::fake_shared(device)); |
1363 | + expect_and_execute_multiplexer(); |
1364 | + |
1365 | hub.remove_device(mt::fake_shared(device)); |
1366 | - |
1367 | - observer_loop.trigger_server_actions(); |
1368 | + expect_and_execute_multiplexer(); |
1369 | } |
1370 | |
1371 | TEST_F(InputDeviceHubTest, emit_ready_to_receive_input_after_first_device_added) |
1372 | @@ -219,8 +228,6 @@ |
1373 | EXPECT_CALL(mock_server_status_listener, ready_for_user_input()).Times(1); |
1374 | hub.add_device(mt::fake_shared(device)); |
1375 | hub.add_device(mt::fake_shared(another_device)); |
1376 | - |
1377 | - observer_loop.trigger_server_actions(); |
1378 | } |
1379 | |
1380 | TEST_F(InputDeviceHubTest, emit_stop_receiving_input_after_last_device_added) |
1381 | @@ -231,7 +238,6 @@ |
1382 | |
1383 | hub.remove_device(mt::fake_shared(device)); |
1384 | hub.remove_device(mt::fake_shared(another_device)); |
1385 | - observer_loop.trigger_server_actions(); |
1386 | } |
1387 | |
1388 | TEST_F(InputDeviceHubTest, when_pointer_configuration_is_applied_successfully_observer_is_triggerd) |
1389 | @@ -243,13 +249,13 @@ |
1390 | |
1391 | hub.add_device(mt::fake_shared(mouse)); |
1392 | hub.add_observer(mt::fake_shared(mock_observer)); |
1393 | - observer_loop.trigger_server_actions(); |
1394 | + expect_and_execute_multiplexer(); |
1395 | |
1396 | EXPECT_CALL(mock_observer, device_changed(WithName("mouse"))); |
1397 | EXPECT_CALL(mock_observer, changes_complete()); |
1398 | |
1399 | dev_ptr->apply_pointer_configuration(pointer_conf); |
1400 | - observer_loop.trigger_server_actions(); |
1401 | + expect_and_execute_multiplexer(); |
1402 | } |
1403 | |
1404 | TEST_F(InputDeviceHubTest, when_tpd_configuration_is_applied_successfully_observer_is_triggerd) |
1405 | @@ -261,13 +267,13 @@ |
1406 | |
1407 | hub.add_device(mt::fake_shared(touchpad)); |
1408 | hub.add_observer(mt::fake_shared(mock_observer)); |
1409 | - observer_loop.trigger_server_actions(); |
1410 | + expect_and_execute_multiplexer(); |
1411 | |
1412 | EXPECT_CALL(mock_observer, device_changed(WithName("tpd"))); |
1413 | EXPECT_CALL(mock_observer, changes_complete()); |
1414 | |
1415 | dev_ptr->apply_touchpad_configuration(tpd_conf); |
1416 | - observer_loop.trigger_server_actions(); |
1417 | + expect_and_execute_multiplexer(); |
1418 | } |
1419 | |
1420 | TEST_F(InputDeviceHubTest, when_configuration_attempt_fails_observer_is_not_triggerd) |
1421 | @@ -279,12 +285,58 @@ |
1422 | |
1423 | hub.add_device(mt::fake_shared(mouse)); |
1424 | hub.add_observer(mt::fake_shared(mock_observer)); |
1425 | - observer_loop.trigger_server_actions(); |
1426 | + expect_and_execute_multiplexer(); |
1427 | |
1428 | EXPECT_CALL(mock_observer, device_changed(WithName("mouse"))).Times(0); |
1429 | EXPECT_CALL(mock_observer, changes_complete()).Times(0); |
1430 | |
1431 | try {dev_ptr->apply_touchpad_configuration(tpd_conf); } catch (...) {} |
1432 | - observer_loop.trigger_server_actions(); |
1433 | + expect_and_execute_multiplexer(); |
1434 | ::testing::Mock::VerifyAndClearExpectations(&mock_observer); |
1435 | } |
1436 | + |
1437 | +TEST_F(InputDeviceHubTest, restores_device_id_when_device_reappears) |
1438 | +{ |
1439 | + std::shared_ptr<mi::Device> dev_ptr; |
1440 | + |
1441 | + ON_CALL(mock_observer, device_added(WithName("mouse"))).WillByDefault(SaveArg<0>(&dev_ptr)); |
1442 | + |
1443 | + hub.add_device(mt::fake_shared(mouse)); |
1444 | + hub.add_observer(mt::fake_shared(mock_observer)); |
1445 | + expect_and_execute_multiplexer(); |
1446 | + |
1447 | + auto device_id = dev_ptr->id(); |
1448 | + |
1449 | + hub.remove_device(mt::fake_shared(mouse)); |
1450 | + dev_ptr.reset(); |
1451 | + hub.add_device(mt::fake_shared(mouse)); |
1452 | + |
1453 | + ASSERT_THAT(dev_ptr, Ne(nullptr)); |
1454 | + |
1455 | + EXPECT_THAT(dev_ptr->id(), Eq(device_id)); |
1456 | +} |
1457 | + |
1458 | +TEST_F(InputDeviceHubTest, restores_configuration_when_device_reappears) |
1459 | +{ |
1460 | + std::shared_ptr<mi::Device> dev_ptr; |
1461 | + MirPointerConfig ptr_config; |
1462 | + ptr_config.handedness(mir_pointer_handedness_left); |
1463 | + ptr_config.acceleration(mir_pointer_acceleration_adaptive); |
1464 | + ptr_config.cursor_acceleration_bias(0.6); |
1465 | + |
1466 | + ON_CALL(mock_observer, device_added(WithName("mouse"))).WillByDefault(SaveArg<0>(&dev_ptr)); |
1467 | + |
1468 | + hub.add_device(mt::fake_shared(mouse)); |
1469 | + hub.add_observer(mt::fake_shared(mock_observer)); |
1470 | + expect_and_execute_multiplexer(); |
1471 | + |
1472 | + dev_ptr->apply_pointer_configuration(ptr_config); |
1473 | + |
1474 | + hub.remove_device(mt::fake_shared(mouse)); |
1475 | + dev_ptr.reset(); |
1476 | + hub.add_device(mt::fake_shared(mouse)); |
1477 | + |
1478 | + ASSERT_THAT(dev_ptr, Ne(nullptr)); |
1479 | + |
1480 | + EXPECT_THAT(dev_ptr->pointer_configuration().value(), Eq(ptr_config)); |
1481 | +} |
1482 | |
1483 | === added file 'tests/unit-tests/input/test_external_input_device_hub.cpp' |
1484 | --- tests/unit-tests/input/test_external_input_device_hub.cpp 1970-01-01 00:00:00 +0000 |
1485 | +++ tests/unit-tests/input/test_external_input_device_hub.cpp 2017-03-14 20:52:46 +0000 |
1486 | @@ -0,0 +1,119 @@ |
1487 | +/* |
1488 | + * Copyright © 2017 Canonical Ltd. |
1489 | + * |
1490 | + * This program is free software: you can redistribute it and/or modify |
1491 | + * it under the terms of the GNU General Public License version 3 as |
1492 | + * published by the Free Software Foundation. |
1493 | + * |
1494 | + * This program is distributed in the hope that it will be useful, |
1495 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1496 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1497 | + * GNU General Public License for more details. |
1498 | + * |
1499 | + * You should have received a copy of the GNU General Public License |
1500 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1501 | + * |
1502 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
1503 | + */ |
1504 | + |
1505 | +#include "src/server/input/default_input_device_hub.h" |
1506 | +#include "mir/test/doubles/mock_input_device_hub.h" |
1507 | +#include "mir/test/doubles/mock_device.h" |
1508 | +#include "mir/test/doubles/mock_input_device_observer.h" |
1509 | +#include "mir/test/doubles/triggered_main_loop.h" |
1510 | +#include "mir/test/fake_shared.h" |
1511 | + |
1512 | +namespace mt = mir::test; |
1513 | +namespace mtd = mt::doubles; |
1514 | +namespace mi = mir::input; |
1515 | +using namespace testing; |
1516 | + |
1517 | +namespace |
1518 | +{ |
1519 | + |
1520 | +struct WrappedHub : mtd::MockInputDeviceHub |
1521 | +{ |
1522 | + std::shared_ptr<mi::InputDeviceObserver> external_hub; |
1523 | + void add_observer(std::shared_ptr<mi::InputDeviceObserver> const& observer) |
1524 | + { |
1525 | + external_hub = observer; |
1526 | + } |
1527 | +}; |
1528 | + |
1529 | +struct ExternalInputDeviceHub : ::testing::Test |
1530 | +{ |
1531 | + mtd::TriggeredMainLoop server_actions; |
1532 | + std::shared_ptr<WrappedHub> wrapped_hub{std::make_shared<WrappedHub>()}; |
1533 | + mi::ExternalInputDeviceHub hub{wrapped_hub, mt::fake_shared(server_actions)}; |
1534 | + NiceMock<mtd::MockInputDeviceObserver> mock_observer; |
1535 | + |
1536 | + NiceMock<mtd::MockDevice> device{1, mi::DeviceCapability::unknown, "name", "name-id-1"}; |
1537 | + NiceMock<mtd::MockDevice> another_device{2, mi::DeviceCapability::keyboard, "keyboard", "keyboard-id-2"}; |
1538 | + |
1539 | + void submit_device_to_hub(std::shared_ptr<mi::Device> const& dev) |
1540 | + { |
1541 | + wrapped_hub->external_hub->device_added(dev); |
1542 | + wrapped_hub->external_hub->changes_complete(); |
1543 | + } |
1544 | + |
1545 | + void remove_device_to_hub(std::shared_ptr<mi::Device> const& dev) |
1546 | + { |
1547 | + wrapped_hub->external_hub->device_removed(dev); |
1548 | + wrapped_hub->external_hub->changes_complete(); |
1549 | + } |
1550 | +}; |
1551 | +} |
1552 | + |
1553 | +TEST_F(ExternalInputDeviceHub, is_observer_to_wrapped_hub) |
1554 | +{ |
1555 | + EXPECT_THAT(wrapped_hub->external_hub, Ne(nullptr)); |
1556 | +} |
1557 | + |
1558 | +TEST_F(ExternalInputDeviceHub, new_observer_is_called_through_server_action) |
1559 | +{ |
1560 | + EXPECT_CALL(mock_observer, changes_complete()).Times(1); |
1561 | + hub.add_observer(mt::fake_shared(mock_observer)); |
1562 | + server_actions.trigger_server_actions(); |
1563 | +} |
1564 | + |
1565 | +TEST_F(ExternalInputDeviceHub, informs_observer_about_existing_devices) |
1566 | +{ |
1567 | + submit_device_to_hub(mt::fake_shared(device)); |
1568 | + submit_device_to_hub(mt::fake_shared(another_device)); |
1569 | + |
1570 | + EXPECT_CALL(mock_observer, device_added(_)).Times(2); |
1571 | + EXPECT_CALL(mock_observer, changes_complete()).Times(1); |
1572 | + hub.add_observer(mt::fake_shared(mock_observer)); |
1573 | + server_actions.trigger_server_actions(); |
1574 | +} |
1575 | + |
1576 | +TEST_F(ExternalInputDeviceHub, informs_observer_about_added_devices) |
1577 | +{ |
1578 | + InSequence seq; |
1579 | + |
1580 | + EXPECT_CALL(mock_observer, changes_complete()); |
1581 | + EXPECT_CALL(mock_observer, device_added(_)); |
1582 | + EXPECT_CALL(mock_observer, changes_complete()); |
1583 | + hub.add_observer(mt::fake_shared(mock_observer)); |
1584 | + server_actions.trigger_server_actions(); |
1585 | + |
1586 | + submit_device_to_hub(mt::fake_shared(device)); |
1587 | + |
1588 | + server_actions.trigger_server_actions(); |
1589 | +} |
1590 | + |
1591 | +TEST_F(ExternalInputDeviceHub, triggers_observer_on_removed_devices) |
1592 | +{ |
1593 | + submit_device_to_hub(mt::fake_shared(device)); |
1594 | + |
1595 | + EXPECT_CALL(mock_observer, device_added(_)).Times(1); |
1596 | + EXPECT_CALL(mock_observer, changes_complete()).Times(1); |
1597 | + hub.add_observer(mt::fake_shared(mock_observer)); |
1598 | + server_actions.trigger_server_actions(); |
1599 | + |
1600 | + EXPECT_CALL(mock_observer, device_removed(_)).Times(1); |
1601 | + EXPECT_CALL(mock_observer, changes_complete()).Times(1); |
1602 | + |
1603 | + remove_device_to_hub(mt::fake_shared(device)); |
1604 | + server_actions.trigger_server_actions(); |
1605 | +} |
FAILED: Continuous integration, rev:4070 /mir-jenkins. ubuntu. com/job/ mir-ci/ 3121/ /mir-jenkins. ubuntu. com/job/ build-mir/ 4189/console /mir-jenkins. ubuntu. com/job/ build-0- fetch/4276 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= vivid+overlay/ 4266 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial+ overlay/ 4266 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= zesty/4266 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= zesty/4216/ console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial+ overlay/ 4216 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial+ overlay/ 4216/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= zesty/4216 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= zesty/4216/ artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 4216 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 4216/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 4216 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 4216/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial+ overlay/ 4216 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial+ overlay/ 4216/artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: 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: /mir-jenkins. ubuntu. com/job/ mir-ci/ 3121/rebuild
https:/