Merge lp:~andreas-pokorny/mir/move-config-changer-to-input-thread into lp:mir
- move-config-changer-to-input-thread
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | Andreas Pokorny |
Approved revision: | no longer in the source branch. |
Merged at revision: | 4109 |
Proposed branch: | lp:~andreas-pokorny/mir/move-config-changer-to-input-thread |
Merge into: | lp:mir |
Diff against target: |
1036 lines (+408/-127) 13 files modified
src/include/server/mir/default_server_configuration.h (+1/-0) src/server/input/default_configuration.cpp (+7/-3) src/server/input/default_input_device_hub.cpp (+119/-35) src/server/input/default_input_device_hub.h (+25/-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_input_device_hub.cpp (+21/-15) tests/unit-tests/input/test_external_input_device_hub.cpp (+119/-0) |
To merge this branch: | bzr merge lp:~andreas-pokorny/mir/move-config-changer-to-input-thread |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir CI Bot | continuous-integration | Approve | |
Alexandros Frantzis (community) | Approve | ||
Alan Griffiths | Approve | ||
Review via email: mp+319840@code.launchpad.net |
Commit message
Move execution of InputDeviceObse
To ensure that the messages about available input devices reach clients before respective input events and input device state events the InputDeviceObse
Description of the change
This is the alternative to
lp:~andreas-pokorny/mir/wait-for-input-config-before-emitting-input-state
Instead of catching the case inside the nested input platform the ordering is guaranteed because the mir::input:
Maybe the attached bugs have already been fixed or are just more rare due to other changes:
* removal of the per-surface fds
* updated surface input dispatcher logic in mir::input:
Still this change is closely related as it ensures that the input device state events will occur after respective input config messages. If the Input device state event happens before the first input config message containing the input devices it would be filtered out in the nested platform.
Mir CI Bot (mir-ci-bot) wrote : | # |
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:4086
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:/
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:4087
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:/
Alexandros Frantzis (afrantzis) wrote : | # |
+ return std::make_
+ the_main_loop());
The ExternalInputDe
depending on the order of initialization (i.e., if we haven't already stored a strong reference to default_
Perhaps this doesn't actually happen in our current configuration, but it is currently not easy to reason about the correctness of the lifecycle, and this could be a pain point in future refactorings.
> void mi::ExternalInp
> mi::ExternalInp
> mi::ExternalInp
In the above function we are using the result of weak_ptr.lock() without checking if it's valid. Is it safe to do so?
Looks good otherwise.
Andreas Pokorny (andreas-pokorny) wrote : | # |
> + return
> std::make_
> + the_main_loop());
>
> The ExternalInputDe
> the_default_
> depending on the order of initialization (i.e., if we haven't already stored a
> strong reference to default_
> destroying the default hub we just created.
>
> Perhaps this doesn't actually happen in our current configuration, but it is
> currently not easy to reason about the correctness of the lifecycle, and this
> could be a pain point in future refactorings.
Yes the actual input device hub is kept alive via loaded platform / input manager / DisplayServer and also via ipc factory / Connector / DisplayServer. I am using a weak_ptr to avoid a cycle between hub and observers.
> > void mi::ExternalInp
> > mi::ExternalInp
> > mi::ExternalInp
>
> In the above function we are using the result of weak_ptr.lock() without
> checking if it's valid. Is it safe to do so?
Changed that..
I think I could also wrap weak_ptr to make it match Element concept of ThreadSafeList
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:4088
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:/
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:4089
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:/
Alexandros Frantzis (afrantzis) wrote : | # |
> Yes the actual input device hub is kept alive via loaded platform / input manager / DisplayServer
> and also via ipc factory / Connector / DisplayServer. I am using a weak_ptr to avoid a cycle
> between hub and observers.
Hmm, still... the fact that if one calls mir::DefaultSer
Couldn't mi::ExternalInp
Andreas Pokorny (andreas-pokorny) wrote : | # |
> > Yes the actual input device hub is kept alive via loaded platform / input
> manager / DisplayServer
> > and also via ipc factory / Connector / DisplayServer. I am using a weak_ptr
> to avoid a cycle
> > between hub and observers.
>
> Hmm, still... the fact that if one calls
> mir::DefaultSer
> input-related method, they will get a broken InputDeviceHub is super-
> unintuitive and makes me very uneasy.
>
> Couldn't mi::ExternalInp
> sense for a wrapper to hold a strong reference, not a weak one. The
> Internal/Observer class would continue to hold a weak_ptr (or even a raw
> pointer, if we can guarantee the related lifetimes) to break the cycle.
Oh I have not thought of that... pushed.
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:4090
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:/
Alexandros Frantzis (afrantzis) wrote : | # |
> + std::weak_
Seems this is not needed anymore?
> + auto observer = obs.lock();
Probably needs a validity check, unless there is an implied validity guarantee I am not aware of.
Andreas Pokorny (andreas-pokorny) wrote : | # |
> > + std::weak_
>
> Seems this is not needed anymore?
oh right..
>
> > + auto observer = obs.lock();
>
> Probably needs a validity check, unless there is an implied validity guarantee
> I am not aware of.
Hm only that nothing happens if the validity check fails..
Alexandros Frantzis (afrantzis) wrote : | # |
Looks good.
> Hm only that nothing happens if the validity check fails..
Good point.
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:4091
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-23 16:31:26 +0000 | |||
4 | @@ -384,6 +384,7 @@ | |||
5 | 384 | CachedPtr<input::InputManager> input_manager; | 384 | CachedPtr<input::InputManager> input_manager; |
6 | 385 | CachedPtr<input::SurfaceInputDispatcher> surface_input_dispatcher; | 385 | CachedPtr<input::SurfaceInputDispatcher> surface_input_dispatcher; |
7 | 386 | CachedPtr<input::DefaultInputDeviceHub> default_input_device_hub; | 386 | CachedPtr<input::DefaultInputDeviceHub> default_input_device_hub; |
8 | 387 | CachedPtr<input::InputDeviceHub> input_device_hub; | ||
9 | 387 | CachedPtr<dispatch::MultiplexingDispatchable> input_reading_multiplexer; | 388 | CachedPtr<dispatch::MultiplexingDispatchable> input_reading_multiplexer; |
10 | 388 | CachedPtr<input::InputDispatcher> input_dispatcher; | 389 | CachedPtr<input::InputDispatcher> input_dispatcher; |
11 | 389 | CachedPtr<shell::InputTargeter> input_targeter; | 390 | CachedPtr<shell::InputTargeter> input_targeter; |
12 | 390 | 391 | ||
13 | === modified file 'src/server/input/default_configuration.cpp' | |||
14 | --- src/server/input/default_configuration.cpp 2017-03-14 02:26:28 +0000 | |||
15 | +++ src/server/input/default_configuration.cpp 2017-03-23 16:31:26 +0000 | |||
16 | @@ -301,7 +301,12 @@ | |||
17 | 301 | 301 | ||
18 | 302 | std::shared_ptr<mi::InputDeviceHub> mir::DefaultServerConfiguration::the_input_device_hub() | 302 | std::shared_ptr<mi::InputDeviceHub> mir::DefaultServerConfiguration::the_input_device_hub() |
19 | 303 | { | 303 | { |
21 | 304 | return the_default_input_device_hub(); | 304 | return input_device_hub( |
22 | 305 | [this]() | ||
23 | 306 | { | ||
24 | 307 | return std::make_shared<mi::ExternalInputDeviceHub>(the_default_input_device_hub(), | ||
25 | 308 | the_main_loop()); | ||
26 | 309 | }); | ||
27 | 305 | } | 310 | } |
28 | 306 | 311 | ||
29 | 307 | std::shared_ptr<mi::DefaultInputDeviceHub> mir::DefaultServerConfiguration::the_default_input_device_hub() | 312 | std::shared_ptr<mi::DefaultInputDeviceHub> mir::DefaultServerConfiguration::the_default_input_device_hub() |
30 | @@ -314,7 +319,6 @@ | |||
31 | 314 | auto hub = std::make_shared<mi::DefaultInputDeviceHub>( | 319 | auto hub = std::make_shared<mi::DefaultInputDeviceHub>( |
32 | 315 | the_seat(), | 320 | the_seat(), |
33 | 316 | the_input_reading_multiplexer(), | 321 | the_input_reading_multiplexer(), |
34 | 317 | the_main_loop(), | ||
35 | 318 | the_cookie_authority(), | 322 | the_cookie_authority(), |
36 | 319 | the_key_mapper(), | 323 | the_key_mapper(), |
37 | 320 | the_server_status_listener()); | 324 | the_server_status_listener()); |
38 | @@ -359,7 +363,7 @@ | |||
39 | 359 | return input_configuration_changer( | 363 | return input_configuration_changer( |
40 | 360 | [this]() | 364 | [this]() |
41 | 361 | { | 365 | { |
43 | 362 | return std::make_shared<mi::ConfigChanger>(the_input_manager(), the_input_device_hub(), the_session_container(), the_session_event_handler_register()); | 366 | return std::make_shared<mi::ConfigChanger>(the_input_manager(), the_default_input_device_hub(), the_session_container(), the_session_event_handler_register()); |
44 | 363 | } | 367 | } |
45 | 364 | ); | 368 | ); |
46 | 365 | } | 369 | } |
47 | 366 | 370 | ||
48 | === modified file 'src/server/input/default_input_device_hub.cpp' | |||
49 | --- src/server/input/default_input_device_hub.cpp 2017-03-14 02:26:28 +0000 | |||
50 | +++ src/server/input/default_input_device_hub.cpp 2017-03-23 16:31:26 +0000 | |||
51 | @@ -41,16 +41,122 @@ | |||
52 | 41 | 41 | ||
53 | 42 | namespace mi = mir::input; | 42 | namespace mi = mir::input; |
54 | 43 | 43 | ||
55 | 44 | struct mi::ExternalInputDeviceHub::Internal : InputDeviceObserver | ||
56 | 45 | { | ||
57 | 46 | Internal(std::shared_ptr<ServerActionQueue> const& queue) : | ||
58 | 47 | observer_queue{queue} | ||
59 | 48 | {} | ||
60 | 49 | void device_added(std::shared_ptr<Device> const& device) override; | ||
61 | 50 | void device_changed(std::shared_ptr<Device> const& device) override; | ||
62 | 51 | void device_removed(std::shared_ptr<Device> const& device) override; | ||
63 | 52 | void changes_complete() override; | ||
64 | 53 | |||
65 | 54 | std::shared_ptr<ServerActionQueue> const observer_queue; | ||
66 | 55 | ThreadSafeList<std::shared_ptr<InputDeviceObserver>> observers; | ||
67 | 56 | std::vector<std::shared_ptr<Device>> devices_added; | ||
68 | 57 | std::vector<std::shared_ptr<Device>> devices_changed; | ||
69 | 58 | std::vector<std::shared_ptr<Device>> devices_removed; | ||
70 | 59 | std::vector<std::shared_ptr<Device>> handles; | ||
71 | 60 | }; | ||
72 | 61 | |||
73 | 62 | mi::ExternalInputDeviceHub::ExternalInputDeviceHub(std::shared_ptr<mi::InputDeviceHub> const& hub, std::shared_ptr<mir::ServerActionQueue> const& queue) | ||
74 | 63 | : data{std::make_shared<mi::ExternalInputDeviceHub::Internal>(queue)}, hub{hub} | ||
75 | 64 | { | ||
76 | 65 | hub->add_observer(data); | ||
77 | 66 | } | ||
78 | 67 | |||
79 | 68 | mi::ExternalInputDeviceHub::~ExternalInputDeviceHub() | ||
80 | 69 | { | ||
81 | 70 | data->observer_queue->pause_processing_for(data.get()); | ||
82 | 71 | } | ||
83 | 72 | |||
84 | 73 | void mi::ExternalInputDeviceHub::add_observer(std::shared_ptr<InputDeviceObserver> const& observer) | ||
85 | 74 | { | ||
86 | 75 | data->observer_queue->enqueue( | ||
87 | 76 | data.get(), | ||
88 | 77 | [observer, data = this->data] | ||
89 | 78 | { | ||
90 | 79 | for (auto const& item : data->handles) | ||
91 | 80 | observer->device_added(item); | ||
92 | 81 | observer->changes_complete(); | ||
93 | 82 | data->observers.add(observer); | ||
94 | 83 | }); | ||
95 | 84 | } | ||
96 | 85 | |||
97 | 86 | void mi::ExternalInputDeviceHub::remove_observer(std::weak_ptr<InputDeviceObserver> const& obs) | ||
98 | 87 | { | ||
99 | 88 | auto observer = obs.lock(); | ||
100 | 89 | if (observer) | ||
101 | 90 | data->observers.remove(observer); | ||
102 | 91 | } | ||
103 | 92 | |||
104 | 93 | void mi::ExternalInputDeviceHub::for_each_input_device(std::function<void(Device const& device)> const& callback) | ||
105 | 94 | { | ||
106 | 95 | hub->for_each_input_device(callback); | ||
107 | 96 | } | ||
108 | 97 | |||
109 | 98 | void mi::ExternalInputDeviceHub::for_each_mutable_input_device(std::function<void(Device& device)> const& callback) | ||
110 | 99 | { | ||
111 | 100 | hub->for_each_mutable_input_device(callback); | ||
112 | 101 | } | ||
113 | 102 | |||
114 | 103 | void mi::ExternalInputDeviceHub::Internal::device_added(std::shared_ptr<Device> const& device) | ||
115 | 104 | { | ||
116 | 105 | devices_added.push_back(device); | ||
117 | 106 | } | ||
118 | 107 | |||
119 | 108 | void mi::ExternalInputDeviceHub::Internal::device_changed(std::shared_ptr<Device> const& device) | ||
120 | 109 | { | ||
121 | 110 | devices_changed.push_back(device); | ||
122 | 111 | } | ||
123 | 112 | |||
124 | 113 | void mi::ExternalInputDeviceHub::Internal::device_removed(std::shared_ptr<Device> const& device) | ||
125 | 114 | { | ||
126 | 115 | devices_removed.push_back(device); | ||
127 | 116 | } | ||
128 | 117 | |||
129 | 118 | void mi::ExternalInputDeviceHub::Internal::changes_complete() | ||
130 | 119 | { | ||
131 | 120 | decltype(devices_added) added, changed, removed; | ||
132 | 121 | |||
133 | 122 | std::swap(devices_added, added); | ||
134 | 123 | std::swap(devices_changed, changed); | ||
135 | 124 | std::swap(devices_removed, removed); | ||
136 | 125 | |||
137 | 126 | if (!(added.empty() && changed.empty() && removed.empty())) | ||
138 | 127 | observer_queue->enqueue( | ||
139 | 128 | this, | ||
140 | 129 | [this, added, changed, removed] | ||
141 | 130 | { | ||
142 | 131 | observers.for_each([&](std::shared_ptr<InputDeviceObserver> const& observer) | ||
143 | 132 | { | ||
144 | 133 | for (auto const& dev : added) | ||
145 | 134 | observer->device_added(dev); | ||
146 | 135 | for (auto const& dev : changed) | ||
147 | 136 | observer->device_changed(dev); | ||
148 | 137 | for (auto const& dev : removed) | ||
149 | 138 | observer->device_removed(dev); | ||
150 | 139 | observer->changes_complete(); | ||
151 | 140 | }); | ||
152 | 141 | |||
153 | 142 | auto end_it = handles.end(); | ||
154 | 143 | for (auto const& dev : removed) | ||
155 | 144 | end_it = remove(begin(handles), end(handles), dev); | ||
156 | 145 | if (end_it != handles.end()) | ||
157 | 146 | handles.erase(end_it, end(handles)); | ||
158 | 147 | for (auto const& dev : added) | ||
159 | 148 | handles.push_back(dev); | ||
160 | 149 | }); | ||
161 | 150 | } | ||
162 | 151 | |||
163 | 44 | mi::DefaultInputDeviceHub::DefaultInputDeviceHub( | 152 | mi::DefaultInputDeviceHub::DefaultInputDeviceHub( |
164 | 45 | std::shared_ptr<mi::Seat> const& seat, | 153 | std::shared_ptr<mi::Seat> const& seat, |
165 | 46 | std::shared_ptr<dispatch::MultiplexingDispatchable> const& input_multiplexer, | 154 | std::shared_ptr<dispatch::MultiplexingDispatchable> const& input_multiplexer, |
166 | 47 | std::shared_ptr<mir::ServerActionQueue> const& observer_queue, | ||
167 | 48 | std::shared_ptr<mir::cookie::Authority> const& cookie_authority, | 155 | std::shared_ptr<mir::cookie::Authority> const& cookie_authority, |
168 | 49 | std::shared_ptr<mi::KeyMapper> const& key_mapper, | 156 | std::shared_ptr<mi::KeyMapper> const& key_mapper, |
169 | 50 | std::shared_ptr<mir::ServerStatusListener> const& server_status_listener) | 157 | std::shared_ptr<mir::ServerStatusListener> const& server_status_listener) |
170 | 51 | : seat{seat}, | 158 | : seat{seat}, |
171 | 52 | input_dispatchable{input_multiplexer}, | 159 | input_dispatchable{input_multiplexer}, |
172 | 53 | observer_queue(observer_queue), | ||
173 | 54 | device_queue(std::make_shared<dispatch::ActionQueue>()), | 160 | device_queue(std::make_shared<dispatch::ActionQueue>()), |
174 | 55 | cookie_authority(cookie_authority), | 161 | cookie_authority(cookie_authority), |
175 | 56 | key_mapper(key_mapper), | 162 | key_mapper(key_mapper), |
176 | @@ -81,17 +187,10 @@ | |||
177 | 81 | device, id, input_dispatchable, cookie_authority, handle)); | 187 | device, id, input_dispatchable, cookie_authority, handle)); |
178 | 82 | 188 | ||
179 | 83 | auto const& dev = devices.back(); | 189 | auto const& dev = devices.back(); |
180 | 190 | add_device_handle(handle); | ||
181 | 84 | 191 | ||
182 | 85 | seat->add_device(*handle); | 192 | seat->add_device(*handle); |
183 | 86 | dev->start(seat); | 193 | dev->start(seat); |
184 | 87 | |||
185 | 88 | // pass input device handle to observer loop.. | ||
186 | 89 | observer_queue->enqueue(this, | ||
187 | 90 | [this, handle]() | ||
188 | 91 | { | ||
189 | 92 | add_device_handle(handle); | ||
190 | 93 | }); | ||
191 | 94 | |||
192 | 95 | } | 194 | } |
193 | 96 | else | 195 | else |
194 | 97 | { | 196 | { |
195 | @@ -118,13 +217,7 @@ | |||
196 | 118 | seat->remove_device(*item->handle); | 217 | seat->remove_device(*item->handle); |
197 | 119 | item->stop(); | 218 | item->stop(); |
198 | 120 | } | 219 | } |
206 | 121 | // send input device info to observer queue.. | 220 | remove_device_handle(item->id()); |
200 | 122 | observer_queue->enqueue( | ||
201 | 123 | this, | ||
202 | 124 | [this,id = item->id()]() | ||
203 | 125 | { | ||
204 | 126 | remove_device_handle(id); | ||
205 | 127 | }); | ||
207 | 128 | 221 | ||
208 | 129 | return true; | 222 | return true; |
209 | 130 | } | 223 | } |
210 | @@ -230,18 +323,15 @@ | |||
211 | 230 | 323 | ||
212 | 231 | void mi::DefaultInputDeviceHub::add_observer(std::shared_ptr<InputDeviceObserver> const& observer) | 324 | void mi::DefaultInputDeviceHub::add_observer(std::shared_ptr<InputDeviceObserver> const& observer) |
213 | 232 | { | 325 | { |
217 | 233 | observer_queue->enqueue( | 326 | device_queue->enqueue( |
218 | 234 | this, | 327 | [this,observer]() |
216 | 235 | [observer,this] | ||
219 | 236 | { | 328 | { |
220 | 329 | std::unique_lock<std::mutex> lock(handles_guard); | ||
221 | 330 | for (auto const& item : handles) | ||
222 | 331 | observer->device_added(item); | ||
223 | 332 | observer->changes_complete(); | ||
224 | 237 | observers.add(observer); | 333 | observers.add(observer); |
232 | 238 | for (auto const& item : handles) | 334 | }); |
226 | 239 | { | ||
227 | 240 | observer->device_added(item); | ||
228 | 241 | } | ||
229 | 242 | observer->changes_complete(); | ||
230 | 243 | } | ||
231 | 244 | ); | ||
233 | 245 | } | 335 | } |
234 | 246 | 336 | ||
235 | 247 | void mi::DefaultInputDeviceHub::for_each_input_device(std::function<void(Device const&)> const& callback) | 337 | void mi::DefaultInputDeviceHub::for_each_input_device(std::function<void(Device const&)> const& callback) |
236 | @@ -270,12 +360,7 @@ | |||
237 | 270 | void mi::DefaultInputDeviceHub::remove_observer(std::weak_ptr<InputDeviceObserver> const& element) | 360 | void mi::DefaultInputDeviceHub::remove_observer(std::weak_ptr<InputDeviceObserver> const& element) |
238 | 271 | { | 361 | { |
239 | 272 | auto observer = element.lock(); | 362 | auto observer = element.lock(); |
246 | 273 | 363 | observers.remove(observer); | |
241 | 274 | observer_queue->enqueue(this, | ||
242 | 275 | [observer, this] | ||
243 | 276 | { | ||
244 | 277 | observers.remove(observer); | ||
245 | 278 | }); | ||
247 | 279 | } | 364 | } |
248 | 280 | 365 | ||
249 | 281 | void mi::DefaultInputDeviceHub::add_device_handle(std::shared_ptr<DefaultDevice> const& handle) | 366 | void mi::DefaultInputDeviceHub::add_device_handle(std::shared_ptr<DefaultDevice> const& handle) |
250 | @@ -285,7 +370,7 @@ | |||
251 | 285 | handles.push_back(handle); | 370 | handles.push_back(handle); |
252 | 286 | } | 371 | } |
253 | 287 | 372 | ||
255 | 288 | observers.for_each([&handle](std::shared_ptr<InputDeviceObserver> const& observer) | 373 | observers.for_each([&handle, this](std::shared_ptr<InputDeviceObserver> const& observer) |
256 | 289 | { | 374 | { |
257 | 290 | observer->device_added(handle); | 375 | observer->device_added(handle); |
258 | 291 | observer->changes_complete(); | 376 | observer->changes_complete(); |
259 | @@ -395,4 +480,3 @@ | |||
260 | 395 | }); | 480 | }); |
261 | 396 | } | 481 | } |
262 | 397 | } | 482 | } |
263 | 398 | |||
264 | 399 | 483 | ||
265 | === modified file 'src/server/input/default_input_device_hub.h' | |||
266 | --- src/server/input/default_input_device_hub.h 2017-03-20 11:44:40 +0000 | |||
267 | +++ src/server/input/default_input_device_hub.h 2017-03-23 16:31:26 +0000 | |||
268 | @@ -25,6 +25,7 @@ | |||
269 | 25 | #include "mir/input/input_sink.h" | 25 | #include "mir/input/input_sink.h" |
270 | 26 | #include "mir/input/seat.h" | 26 | #include "mir/input/seat.h" |
271 | 27 | #include "mir/input/input_device_hub.h" | 27 | #include "mir/input/input_device_hub.h" |
272 | 28 | #include "mir/input/input_device_observer.h" | ||
273 | 28 | #include "mir/input/input_device_info.h" | 29 | #include "mir/input/input_device_info.h" |
274 | 29 | #include "mir/input/mir_input_config.h" | 30 | #include "mir/input/mir_input_config.h" |
275 | 30 | #include "mir/thread_safe_list.h" | 31 | #include "mir/thread_safe_list.h" |
276 | @@ -57,13 +58,32 @@ | |||
277 | 57 | class DefaultDevice; | 58 | class DefaultDevice; |
278 | 58 | class Seat; | 59 | class Seat; |
279 | 59 | class KeyMapper; | 60 | class KeyMapper; |
282 | 60 | 61 | class DefaultInputDeviceHub; | |
283 | 61 | class DefaultInputDeviceHub : public InputDeviceRegistry, public InputDeviceHub | 62 | |
284 | 63 | struct ExternalInputDeviceHub : InputDeviceHub | ||
285 | 64 | { | ||
286 | 65 | ExternalInputDeviceHub(std::shared_ptr<InputDeviceHub> const& actual_hub, | ||
287 | 66 | std::shared_ptr<ServerActionQueue> const& observer_queue); | ||
288 | 67 | ~ExternalInputDeviceHub(); | ||
289 | 68 | |||
290 | 69 | void add_observer(std::shared_ptr<InputDeviceObserver> const&) override; | ||
291 | 70 | void remove_observer(std::weak_ptr<InputDeviceObserver> const&) override; | ||
292 | 71 | void for_each_input_device(std::function<void(Device const& device)> const& callback) override; | ||
293 | 72 | void for_each_mutable_input_device(std::function<void(Device& device)> const& callback) override; | ||
294 | 73 | |||
295 | 74 | private: | ||
296 | 75 | struct Internal; | ||
297 | 76 | std::shared_ptr<Internal> data; | ||
298 | 77 | std::shared_ptr<InputDeviceHub> hub; | ||
299 | 78 | }; | ||
300 | 79 | |||
301 | 80 | class DefaultInputDeviceHub : | ||
302 | 81 | public InputDeviceRegistry, | ||
303 | 82 | public InputDeviceHub | ||
304 | 62 | { | 83 | { |
305 | 63 | public: | 84 | public: |
306 | 64 | DefaultInputDeviceHub(std::shared_ptr<Seat> const& seat, | 85 | DefaultInputDeviceHub(std::shared_ptr<Seat> const& seat, |
307 | 65 | std::shared_ptr<dispatch::MultiplexingDispatchable> const& input_multiplexer, | 86 | std::shared_ptr<dispatch::MultiplexingDispatchable> const& input_multiplexer, |
308 | 66 | std::shared_ptr<ServerActionQueue> const& observer_queue, | ||
309 | 67 | std::shared_ptr<cookie::Authority> const& cookie_authority, | 87 | std::shared_ptr<cookie::Authority> const& cookie_authority, |
310 | 68 | std::shared_ptr<KeyMapper> const& key_mapper, | 88 | std::shared_ptr<KeyMapper> const& key_mapper, |
311 | 69 | std::shared_ptr<ServerStatusListener> const& server_status_listener); | 89 | std::shared_ptr<ServerStatusListener> const& server_status_listener); |
312 | @@ -77,18 +97,16 @@ | |||
313 | 77 | void remove_observer(std::weak_ptr<InputDeviceObserver> const&) override; | 97 | void remove_observer(std::weak_ptr<InputDeviceObserver> const&) override; |
314 | 78 | void for_each_input_device(std::function<void(Device const& device)> const& callback) override; | 98 | void for_each_input_device(std::function<void(Device const& device)> const& callback) override; |
315 | 79 | void for_each_mutable_input_device(std::function<void(Device& device)> const& callback) override; | 99 | void for_each_mutable_input_device(std::function<void(Device& device)> const& callback) override; |
316 | 80 | |||
317 | 81 | |||
318 | 82 | private: | 100 | private: |
319 | 83 | void add_device_handle(std::shared_ptr<DefaultDevice> const& handle); | 101 | void add_device_handle(std::shared_ptr<DefaultDevice> const& handle); |
320 | 84 | void remove_device_handle(MirInputDeviceId id); | 102 | void remove_device_handle(MirInputDeviceId id); |
321 | 85 | void device_changed(Device* dev); | 103 | void device_changed(Device* dev); |
322 | 86 | void emit_changed_devices(); | 104 | void emit_changed_devices(); |
323 | 87 | MirInputDeviceId create_new_device_id(); | 105 | MirInputDeviceId create_new_device_id(); |
324 | 106 | |||
325 | 88 | std::shared_ptr<Seat> const seat; | 107 | std::shared_ptr<Seat> const seat; |
326 | 89 | std::shared_ptr<dispatch::MultiplexingDispatchable> const input_dispatchable; | 108 | std::shared_ptr<dispatch::MultiplexingDispatchable> const input_dispatchable; |
329 | 90 | std::mutex handles_guard; | 109 | std::mutex mutable handles_guard; |
328 | 91 | std::shared_ptr<ServerActionQueue> const observer_queue; | ||
330 | 92 | std::shared_ptr<dispatch::ActionQueue> const device_queue; | 110 | std::shared_ptr<dispatch::ActionQueue> const device_queue; |
331 | 93 | std::shared_ptr<cookie::Authority> const cookie_authority; | 111 | std::shared_ptr<cookie::Authority> const cookie_authority; |
332 | 94 | std::shared_ptr<KeyMapper> const key_mapper; | 112 | std::shared_ptr<KeyMapper> const key_mapper; |
333 | 95 | 113 | ||
334 | === modified file 'tests/acceptance-tests/test_client_input.cpp' | |||
335 | --- tests/acceptance-tests/test_client_input.cpp 2017-03-22 07:01:56 +0000 | |||
336 | +++ tests/acceptance-tests/test_client_input.cpp 2017-03-23 16:31:26 +0000 | |||
337 | @@ -343,12 +343,13 @@ | |||
338 | 343 | devices_available.raise(); | 343 | devices_available.raise(); |
339 | 344 | }); | 344 | }); |
340 | 345 | 345 | ||
342 | 346 | server.the_input_device_hub()->add_observer(counter); | 346 | auto hub = server.the_input_device_hub(); |
343 | 347 | hub->add_observer(counter); | ||
344 | 347 | 348 | ||
345 | 348 | devices_available.wait_for(5s); | 349 | devices_available.wait_for(5s); |
346 | 349 | ASSERT_THAT(counter->count_devices, Eq(expected_number_of_input_devices)); | 350 | ASSERT_THAT(counter->count_devices, Eq(expected_number_of_input_devices)); |
347 | 350 | 351 | ||
349 | 351 | server.the_input_device_hub()->remove_observer(counter); | 352 | hub->remove_observer(counter); |
350 | 352 | } | 353 | } |
351 | 353 | 354 | ||
352 | 354 | MirInputDevice const* get_device_with_capabilities(MirInputConfig const* config, MirInputDeviceCapabilities caps) | 355 | MirInputDevice const* get_device_with_capabilities(MirInputConfig const* config, MirInputDeviceCapabilities caps) |
353 | 355 | 356 | ||
354 | === modified file 'tests/acceptance-tests/test_input_device_hub.cpp' | |||
355 | --- tests/acceptance-tests/test_input_device_hub.cpp 2017-01-18 02:29:37 +0000 | |||
356 | +++ tests/acceptance-tests/test_input_device_hub.cpp 2017-03-23 16:31:26 +0000 | |||
357 | @@ -60,7 +60,8 @@ | |||
358 | 60 | EXPECT_CALL(observer, changes_complete()) | 60 | EXPECT_CALL(observer, changes_complete()) |
359 | 61 | .WillOnce(mt::WakeUp(&observer_registered)); | 61 | .WillOnce(mt::WakeUp(&observer_registered)); |
360 | 62 | 62 | ||
362 | 63 | server.the_input_device_hub()->add_observer(mt::fake_shared(observer)); | 63 | auto device_hub = server.the_input_device_hub(); |
363 | 64 | device_hub->add_observer(mt::fake_shared(observer)); | ||
364 | 64 | observer_registered.wait_for(std::chrono::seconds{4}); | 65 | observer_registered.wait_for(std::chrono::seconds{4}); |
365 | 65 | } | 66 | } |
366 | 66 | 67 | ||
367 | @@ -75,7 +76,8 @@ | |||
368 | 75 | EXPECT_CALL(observer, changes_complete()) | 76 | EXPECT_CALL(observer, changes_complete()) |
369 | 76 | .WillOnce(mt::WakeUp(&callbacks_received)); | 77 | .WillOnce(mt::WakeUp(&callbacks_received)); |
370 | 77 | 78 | ||
372 | 78 | server.the_input_device_hub()->add_observer(mt::fake_shared(observer)); | 79 | auto device_hub = server.the_input_device_hub(); |
373 | 80 | device_hub->add_observer(mt::fake_shared(observer)); | ||
374 | 79 | observer_registered.wait_for(std::chrono::seconds{4}); | 81 | observer_registered.wait_for(std::chrono::seconds{4}); |
375 | 80 | 82 | ||
376 | 81 | keep_on_living = mtf::add_fake_input_device(mi::InputDeviceInfo{"keyboard", "keyboard-uid", mir::input::DeviceCapability::keyboard}); | 83 | keep_on_living = mtf::add_fake_input_device(mi::InputDeviceInfo{"keyboard", "keyboard-uid", mir::input::DeviceCapability::keyboard}); |
377 | 82 | 84 | ||
378 | === modified file 'tests/acceptance-tests/test_nested_input.cpp' | |||
379 | --- tests/acceptance-tests/test_nested_input.cpp 2017-03-16 03:23:51 +0000 | |||
380 | +++ tests/acceptance-tests/test_nested_input.cpp 2017-03-23 16:31:26 +0000 | |||
381 | @@ -112,13 +112,12 @@ | |||
382 | 112 | 112 | ||
383 | 113 | struct NestedInput : public mtf::HeadlessInProcessServer | 113 | struct NestedInput : public mtf::HeadlessInProcessServer |
384 | 114 | { | 114 | { |
385 | 115 | |||
386 | 116 | void SetUp() | 115 | void SetUp() |
387 | 117 | { | 116 | { |
388 | 118 | initial_display_layout(display_geometry); | 117 | initial_display_layout(display_geometry); |
389 | 119 | mtf::HeadlessInProcessServer::SetUp(); | 118 | mtf::HeadlessInProcessServer::SetUp(); |
390 | 120 | } | 119 | } |
392 | 121 | 120 | ||
393 | 122 | mtd::NestedMockEGL mock_egl; | 121 | mtd::NestedMockEGL mock_egl; |
394 | 123 | 122 | ||
395 | 124 | std::unique_ptr<mtf::FakeInputDevice> fake_keyboard{ | 123 | std::unique_ptr<mtf::FakeInputDevice> fake_keyboard{ |
396 | @@ -301,13 +300,12 @@ | |||
397 | 301 | NestedServerWithMockEventFilter nested_mir{new_connection()}; | 300 | NestedServerWithMockEventFilter nested_mir{new_connection()}; |
398 | 302 | auto nested_hub = nested_mir.server.the_input_device_hub(); | 301 | auto nested_hub = nested_mir.server.the_input_device_hub(); |
399 | 303 | 302 | ||
403 | 304 | EXPECT_CALL(*mock_observer, device_added(_)).Times(1); | 303 | EXPECT_CALL(*mock_observer, device_added(_)) |
401 | 305 | EXPECT_CALL(*mock_observer, changes_complete()) | ||
402 | 306 | .Times(1) | ||
404 | 307 | .WillOnce(mt::WakeUp(&input_device_changes_complete)); | 304 | .WillOnce(mt::WakeUp(&input_device_changes_complete)); |
405 | 308 | 305 | ||
406 | 309 | nested_hub->add_observer(mock_observer); | 306 | nested_hub->add_observer(mock_observer); |
407 | 310 | input_device_changes_complete.wait_for(10s); | 307 | input_device_changes_complete.wait_for(10s); |
408 | 308 | nested_hub->remove_observer(mock_observer); | ||
409 | 311 | } | 309 | } |
410 | 312 | 310 | ||
411 | 313 | TEST_F(NestedInput, device_added_on_host_triggeres_nested_device_observer) | 311 | TEST_F(NestedInput, device_added_on_host_triggeres_nested_device_observer) |
412 | @@ -315,15 +313,18 @@ | |||
413 | 315 | NestedServerWithMockEventFilter nested_mir{new_connection()}; | 313 | NestedServerWithMockEventFilter nested_mir{new_connection()}; |
414 | 316 | auto nested_hub = nested_mir.server.the_input_device_hub(); | 314 | auto nested_hub = nested_mir.server.the_input_device_hub(); |
415 | 317 | 315 | ||
417 | 318 | EXPECT_CALL(*mock_observer, changes_complete()).Times(1) | 316 | // wait until we see the keyboard from the fixture: |
418 | 317 | EXPECT_CALL(*mock_observer, device_added(_)).Times(1) | ||
419 | 319 | .WillOnce(mt::WakeUp(&input_device_changes_complete)); | 318 | .WillOnce(mt::WakeUp(&input_device_changes_complete)); |
420 | 320 | nested_hub->add_observer(mock_observer); | 319 | nested_hub->add_observer(mock_observer); |
421 | 321 | 320 | ||
422 | 322 | input_device_changes_complete.wait_for(10s); | 321 | input_device_changes_complete.wait_for(10s); |
423 | 323 | EXPECT_THAT(input_device_changes_complete.raised(), Eq(true)); | 322 | EXPECT_THAT(input_device_changes_complete.raised(), Eq(true)); |
424 | 324 | input_device_changes_complete.reset(); | 323 | input_device_changes_complete.reset(); |
425 | 324 | ::testing::Mock::VerifyAndClearExpectations(&mock_observer); | ||
426 | 325 | 325 | ||
428 | 326 | EXPECT_CALL(*mock_observer, changes_complete()) | 326 | // wait for the fake mouse |
429 | 327 | EXPECT_CALL(*mock_observer, device_added(_)).Times(1) | ||
430 | 327 | .WillOnce(mt::WakeUp(&input_device_changes_complete)); | 328 | .WillOnce(mt::WakeUp(&input_device_changes_complete)); |
431 | 328 | 329 | ||
432 | 329 | auto mouse = mtf::add_fake_input_device(mi::InputDeviceInfo{"mouse", "mouse-uid" , mi::DeviceCapability::pointer}); | 330 | auto mouse = mtf::add_fake_input_device(mi::InputDeviceInfo{"mouse", "mouse-uid" , mi::DeviceCapability::pointer}); |
433 | 330 | 331 | ||
434 | === added file 'tests/include/mir/test/doubles/mock_device.h' | |||
435 | --- tests/include/mir/test/doubles/mock_device.h 1970-01-01 00:00:00 +0000 | |||
436 | +++ tests/include/mir/test/doubles/mock_device.h 2017-03-23 16:31:26 +0000 | |||
437 | @@ -0,0 +1,71 @@ | |||
438 | 1 | /* | ||
439 | 2 | * Copyright © 2017 Canonical Ltd. | ||
440 | 3 | * | ||
441 | 4 | * This program is free software: you can redistribute it and/or modify | ||
442 | 5 | * it under the terms of the GNU General Public License version 3 as | ||
443 | 6 | * published by the Free Software Foundation. | ||
444 | 7 | * | ||
445 | 8 | * This program is distributed in the hope that it will be useful, | ||
446 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
447 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
448 | 11 | * GNU General Public License for more details. | ||
449 | 12 | * | ||
450 | 13 | * You should have received a copy of the GNU General Public License | ||
451 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
452 | 15 | * | ||
453 | 16 | * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> | ||
454 | 17 | */ | ||
455 | 18 | |||
456 | 19 | #ifndef MIR_TEST_DOUBLES_MOCK_DEVICE_H_ | ||
457 | 20 | #define MIR_TEST_DOUBLES_MOCK_DEVICE_H_ | ||
458 | 21 | |||
459 | 22 | #include "mir/input/device.h" | ||
460 | 23 | #include "mir/input/device_capability.h" | ||
461 | 24 | #include "mir/input/mir_pointer_config.h" | ||
462 | 25 | #include "mir/input/mir_keyboard_config.h" | ||
463 | 26 | #include "mir/input/mir_touchpad_config.h" | ||
464 | 27 | #include "mir/input/mir_touchscreen_config.h" | ||
465 | 28 | #include "mir/optional_value.h" | ||
466 | 29 | |||
467 | 30 | #include <string> | ||
468 | 31 | |||
469 | 32 | namespace mir | ||
470 | 33 | { | ||
471 | 34 | namespace test | ||
472 | 35 | { | ||
473 | 36 | namespace doubles | ||
474 | 37 | { | ||
475 | 38 | |||
476 | 39 | struct MockDevice : input::Device | ||
477 | 40 | { | ||
478 | 41 | MockDevice(MirInputDeviceId id, input::DeviceCapabilities caps, std::string const& name, std::string const& unique_id) | ||
479 | 42 | { | ||
480 | 43 | ON_CALL(*this, id()).WillByDefault(testing::Return(id)); | ||
481 | 44 | ON_CALL(*this, name()).WillByDefault(testing::Return(name)); | ||
482 | 45 | ON_CALL(*this, unique_id()).WillByDefault(testing::Return(unique_id)); | ||
483 | 46 | ON_CALL(*this, capabilities()).WillByDefault(testing::Return(caps)); | ||
484 | 47 | ON_CALL(*this, pointer_configuration()).WillByDefault(testing::Return(MirPointerConfig{})); | ||
485 | 48 | ON_CALL(*this, keyboard_configuration()).WillByDefault(testing::Return(MirKeyboardConfig{})); | ||
486 | 49 | ON_CALL(*this, touchpad_configuration()).WillByDefault(testing::Return(MirTouchpadConfig{})); | ||
487 | 50 | ON_CALL(*this, touchscreen_configuration()).WillByDefault(testing::Return(MirTouchscreenConfig{})); | ||
488 | 51 | } | ||
489 | 52 | |||
490 | 53 | MOCK_CONST_METHOD0(id, MirInputDeviceId()); | ||
491 | 54 | MOCK_CONST_METHOD0(capabilities, input::DeviceCapabilities()); | ||
492 | 55 | MOCK_CONST_METHOD0(name, std::string()); | ||
493 | 56 | MOCK_CONST_METHOD0(unique_id, std::string()); | ||
494 | 57 | MOCK_CONST_METHOD0(pointer_configuration, optional_value<MirPointerConfig>()); | ||
495 | 58 | MOCK_CONST_METHOD0(touchpad_configuration, optional_value<MirTouchpadConfig>()); | ||
496 | 59 | MOCK_CONST_METHOD0(keyboard_configuration, optional_value<MirKeyboardConfig>()); | ||
497 | 60 | MOCK_CONST_METHOD0(touchscreen_configuration, optional_value<MirTouchscreenConfig>()); | ||
498 | 61 | MOCK_METHOD1(apply_pointer_configuration, void(MirPointerConfig const&)); | ||
499 | 62 | MOCK_METHOD1(apply_touchpad_configuration, void(MirTouchpadConfig const&)); | ||
500 | 63 | MOCK_METHOD1(apply_keyboard_configuration, void(MirKeyboardConfig const&)); | ||
501 | 64 | MOCK_METHOD1(apply_touchscreen_configuration, void(MirTouchscreenConfig const&)); | ||
502 | 65 | }; | ||
503 | 66 | } | ||
504 | 67 | } | ||
505 | 68 | } | ||
506 | 69 | |||
507 | 70 | #endif | ||
508 | 71 | |||
509 | 0 | 72 | ||
510 | === modified file 'tests/integration-tests/input/test_single_seat_setup.cpp' | |||
511 | --- tests/integration-tests/input/test_single_seat_setup.cpp 2017-03-14 02:26:28 +0000 | |||
512 | +++ tests/integration-tests/input/test_single_seat_setup.cpp 2017-03-23 16:31:26 +0000 | |||
513 | @@ -51,6 +51,7 @@ | |||
514 | 51 | #include "mir/input/input_device_info.h" | 51 | #include "mir/input/input_device_info.h" |
515 | 52 | #include "mir/geometry/rectangles.h" | 52 | #include "mir/geometry/rectangles.h" |
516 | 53 | #include "mir/test/input_config_matchers.h" | 53 | #include "mir/test/input_config_matchers.h" |
517 | 54 | #include "mir/test/fd_utils.h" | ||
518 | 54 | 55 | ||
519 | 55 | #include <gmock/gmock.h> | 56 | #include <gmock/gmock.h> |
520 | 56 | #include <gtest/gtest.h> | 57 | #include <gtest/gtest.h> |
521 | @@ -131,9 +132,9 @@ | |||
522 | 131 | mt::fake_shared(mock_cursor_listener), mt::fake_shared(display_config), | 132 | mt::fake_shared(mock_cursor_listener), mt::fake_shared(display_config), |
523 | 132 | mt::fake_shared(key_mapper), mt::fake_shared(clock), | 133 | mt::fake_shared(key_mapper), mt::fake_shared(clock), |
524 | 133 | mt::fake_shared(mock_seat_observer)}; | 134 | mt::fake_shared(mock_seat_observer)}; |
528 | 134 | mi::DefaultInputDeviceHub hub{mt::fake_shared(seat), mt::fake_shared(multiplexer), | 135 | mi::DefaultInputDeviceHub hub{mt::fake_shared(seat), mt::fake_shared(multiplexer), |
529 | 135 | mt::fake_shared(observer_loop), cookie_authority, | 136 | cookie_authority, mt::fake_shared(key_mapper), |
530 | 136 | mt::fake_shared(key_mapper), mt::fake_shared(mock_status_listener)}; | 137 | mt::fake_shared(mock_status_listener)}; |
531 | 137 | NiceMock<mtd::MockInputDeviceObserver> mock_observer; | 138 | NiceMock<mtd::MockInputDeviceObserver> mock_observer; |
532 | 138 | mi::ConfigChanger changer{ | 139 | mi::ConfigChanger changer{ |
533 | 139 | mt::fake_shared(mock_input_manager), | 140 | mt::fake_shared(mock_input_manager), |
534 | @@ -151,6 +152,21 @@ | |||
535 | 151 | 152 | ||
536 | 152 | std::chrono::nanoseconds arbitrary_timestamp; | 153 | std::chrono::nanoseconds arbitrary_timestamp; |
537 | 153 | 154 | ||
538 | 155 | void SetUp() | ||
539 | 156 | { | ||
540 | 157 | // execute registration of ConfigChanger | ||
541 | 158 | expect_and_execute_multiplexer(); | ||
542 | 159 | } | ||
543 | 160 | |||
544 | 161 | void expect_and_execute_multiplexer(int count = 1) | ||
545 | 162 | { | ||
546 | 163 | for (int i = 0; i != count; ++i) | ||
547 | 164 | { | ||
548 | 165 | mt::fd_becomes_readable(multiplexer.watch_fd(), 5s); | ||
549 | 166 | multiplexer.dispatch(mir::dispatch::FdEvent::readable); | ||
550 | 167 | } | ||
551 | 168 | } | ||
552 | 169 | |||
553 | 154 | void capture_input_sink(NiceMock<mtd::MockInputDevice>& dev, mi::InputSink*& sink, mi::EventBuilder*& builder) | 170 | void capture_input_sink(NiceMock<mtd::MockInputDevice>& dev, mi::InputSink*& sink, mi::EventBuilder*& builder) |
554 | 155 | { | 171 | { |
555 | 156 | ON_CALL(dev,start(_,_)) | 172 | ON_CALL(dev,start(_,_)) |
556 | @@ -173,14 +189,13 @@ | |||
557 | 173 | 189 | ||
558 | 174 | capture_input_sink(device, sink, builder); | 190 | capture_input_sink(device, sink, builder); |
559 | 175 | 191 | ||
561 | 176 | EXPECT_CALL(mock_observer,device_added(_)) | 192 | EXPECT_CALL(mock_observer, device_added(_)) |
562 | 177 | .WillOnce(SaveArg<0>(&handle)); | 193 | .WillOnce(SaveArg<0>(&handle)); |
563 | 178 | 194 | ||
564 | 179 | hub.add_observer(mt::fake_shared(mock_observer)); | 195 | hub.add_observer(mt::fake_shared(mock_observer)); |
565 | 196 | expect_and_execute_multiplexer(1); | ||
566 | 180 | hub.add_device(mt::fake_shared(device)); | 197 | hub.add_device(mt::fake_shared(device)); |
567 | 181 | 198 | ||
568 | 182 | observer_loop.trigger_server_actions(); | ||
569 | 183 | |||
570 | 184 | auto event = builder->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, | 199 | auto event = builder->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, |
571 | 185 | KEY_A); | 200 | KEY_A); |
572 | 186 | 201 | ||
573 | @@ -198,8 +213,6 @@ | |||
574 | 198 | 213 | ||
575 | 199 | hub.add_device(mt::fake_shared(device)); | 214 | hub.add_device(mt::fake_shared(device)); |
576 | 200 | 215 | ||
577 | 201 | observer_loop.trigger_server_actions(); | ||
578 | 202 | |||
579 | 203 | auto touch_event_1 = builder->touch_event( | 216 | auto touch_event_1 = builder->touch_event( |
580 | 204 | arbitrary_timestamp, | 217 | arbitrary_timestamp, |
581 | 205 | {{0, mir_touch_action_down, mir_touch_tooltype_finger, 21.0f, 34.0f, 50.0f, 15.0f, 5.0f, 4.0f}}); | 218 | {{0, mir_touch_action_down, mir_touch_tooltype_finger, 21.0f, 34.0f, 50.0f, 15.0f, 5.0f, 4.0f}}); |
582 | @@ -245,7 +258,6 @@ | |||
583 | 245 | capture_input_sink(device, sink, builder); | 258 | capture_input_sink(device, sink, builder); |
584 | 246 | 259 | ||
585 | 247 | hub.add_device(mt::fake_shared(device)); | 260 | hub.add_device(mt::fake_shared(device)); |
586 | 248 | observer_loop.trigger_server_actions(); | ||
587 | 249 | sink->handle_input( | 261 | sink->handle_input( |
588 | 250 | *builder->pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 0.0f, 0.0f, 10.0f, 10.0f)); | 262 | *builder->pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 0.0f, 0.0f, 10.0f, 10.0f)); |
589 | 251 | sink->handle_input( | 263 | sink->handle_input( |
590 | @@ -265,7 +277,6 @@ | |||
591 | 265 | mi::EventBuilder* builder; | 277 | mi::EventBuilder* builder; |
592 | 266 | capture_input_sink(device, sink, builder); | 278 | capture_input_sink(device, sink, builder); |
593 | 267 | hub.add_device(mt::fake_shared(device)); | 279 | hub.add_device(mt::fake_shared(device)); |
594 | 268 | observer_loop.trigger_server_actions(); | ||
595 | 269 | 280 | ||
596 | 270 | sink->handle_input( | 281 | sink->handle_input( |
597 | 271 | *builder->pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 0.0f, 0.0f, 10.0f, 20.0f)); | 282 | *builder->pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 0.0f, 0.0f, 10.0f, 20.0f)); |
598 | @@ -295,8 +306,8 @@ | |||
599 | 295 | ON_CALL(mock_observer, device_added(_)).WillByDefault(SaveArg<0>(&dev)); | 306 | ON_CALL(mock_observer, device_added(_)).WillByDefault(SaveArg<0>(&dev)); |
600 | 296 | 307 | ||
601 | 297 | hub.add_observer(mt::fake_shared(mock_observer)); | 308 | hub.add_observer(mt::fake_shared(mock_observer)); |
602 | 309 | expect_and_execute_multiplexer(); | ||
603 | 298 | hub.add_device(mt::fake_shared(touchpad)); | 310 | hub.add_device(mt::fake_shared(touchpad)); |
604 | 299 | observer_loop.trigger_server_actions(); | ||
605 | 300 | 311 | ||
606 | 301 | EXPECT_CALL(touchpad, apply_settings(Matcher<mi::PointerSettings const&>(_))); | 312 | EXPECT_CALL(touchpad, apply_settings(Matcher<mi::PointerSettings const&>(_))); |
607 | 302 | 313 | ||
608 | @@ -311,8 +322,8 @@ | |||
609 | 311 | ON_CALL(mock_observer, device_added(_)).WillByDefault(SaveArg<0>(&dev)); | 322 | ON_CALL(mock_observer, device_added(_)).WillByDefault(SaveArg<0>(&dev)); |
610 | 312 | 323 | ||
611 | 313 | hub.add_observer(mt::fake_shared(mock_observer)); | 324 | hub.add_observer(mt::fake_shared(mock_observer)); |
612 | 325 | expect_and_execute_multiplexer(); | ||
613 | 314 | hub.add_device(mt::fake_shared(touchpad)); | 326 | hub.add_device(mt::fake_shared(touchpad)); |
614 | 315 | observer_loop.trigger_server_actions(); | ||
615 | 316 | 327 | ||
616 | 317 | EXPECT_CALL(touchpad, apply_settings(Matcher<mi::TouchpadSettings const&>(_))); | 328 | EXPECT_CALL(touchpad, apply_settings(Matcher<mi::TouchpadSettings const&>(_))); |
617 | 318 | 329 | ||
618 | @@ -334,9 +345,9 @@ | |||
619 | 334 | .WillOnce(SaveArg<0>(&key_handle)); | 345 | .WillOnce(SaveArg<0>(&key_handle)); |
620 | 335 | 346 | ||
621 | 336 | hub.add_observer(mt::fake_shared(mock_observer)); | 347 | hub.add_observer(mt::fake_shared(mock_observer)); |
622 | 348 | expect_and_execute_multiplexer(); | ||
623 | 337 | hub.add_device(mt::fake_shared(another_device)); | 349 | hub.add_device(mt::fake_shared(another_device)); |
624 | 338 | 350 | ||
625 | 339 | observer_loop.trigger_server_actions(); | ||
626 | 340 | 351 | ||
627 | 341 | const MirInputEventModifiers shift_left = mir_input_event_modifier_shift_left | mir_input_event_modifier_shift; | 352 | const MirInputEventModifiers shift_left = mir_input_event_modifier_shift_left | mir_input_event_modifier_shift; |
628 | 342 | auto shift_down = | 353 | auto shift_down = |
629 | @@ -370,11 +381,10 @@ | |||
630 | 370 | .WillOnce(SaveArg<0>(&key_handle)); | 381 | .WillOnce(SaveArg<0>(&key_handle)); |
631 | 371 | 382 | ||
632 | 372 | hub.add_observer(mt::fake_shared(mock_observer)); | 383 | hub.add_observer(mt::fake_shared(mock_observer)); |
633 | 384 | expect_and_execute_multiplexer(); | ||
634 | 373 | hub.add_device(mt::fake_shared(device)); | 385 | hub.add_device(mt::fake_shared(device)); |
635 | 374 | hub.add_device(mt::fake_shared(another_device)); | 386 | hub.add_device(mt::fake_shared(another_device)); |
636 | 375 | 387 | ||
637 | 376 | observer_loop.trigger_server_actions(); | ||
638 | 377 | |||
639 | 378 | const MirInputEventModifiers r_alt_modifier = mir_input_event_modifier_alt_right | mir_input_event_modifier_alt; | 388 | const MirInputEventModifiers r_alt_modifier = mir_input_event_modifier_alt_right | mir_input_event_modifier_alt; |
640 | 379 | auto key = | 389 | auto key = |
641 | 380 | key_event_builder->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_RIGHTALT); | 390 | key_event_builder->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_RIGHTALT); |
642 | @@ -415,6 +425,7 @@ | |||
643 | 415 | .WillOnce(SaveArg<0>(&key_handle_2)); | 425 | .WillOnce(SaveArg<0>(&key_handle_2)); |
644 | 416 | 426 | ||
645 | 417 | hub.add_observer(mt::fake_shared(mock_observer)); | 427 | hub.add_observer(mt::fake_shared(mock_observer)); |
646 | 428 | expect_and_execute_multiplexer(); | ||
647 | 418 | hub.add_device(mt::fake_shared(device)); | 429 | hub.add_device(mt::fake_shared(device)); |
648 | 419 | hub.add_device(mt::fake_shared(another_device)); | 430 | hub.add_device(mt::fake_shared(another_device)); |
649 | 420 | hub.add_device(mt::fake_shared(third_device)); | 431 | hub.add_device(mt::fake_shared(third_device)); |
650 | @@ -423,8 +434,6 @@ | |||
651 | 423 | const MirInputEventModifiers l_ctrl_modifier = mir_input_event_modifier_ctrl_left | mir_input_event_modifier_ctrl; | 434 | const MirInputEventModifiers l_ctrl_modifier = mir_input_event_modifier_ctrl_left | mir_input_event_modifier_ctrl; |
652 | 424 | const MirInputEventModifiers combined_modifier = r_alt_modifier | l_ctrl_modifier; | 435 | const MirInputEventModifiers combined_modifier = r_alt_modifier | l_ctrl_modifier; |
653 | 425 | 436 | ||
654 | 426 | observer_loop.trigger_server_actions(); | ||
655 | 427 | |||
656 | 428 | auto alt_down = key_event_builder_1->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_RIGHTALT); | 437 | auto alt_down = key_event_builder_1->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_RIGHTALT); |
657 | 429 | auto ctrl_down = key_event_builder_2->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_LEFTCTRL); | 438 | auto ctrl_down = key_event_builder_2->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_LEFTCTRL); |
658 | 430 | auto ctrl_up = key_event_builder_2->key_event(arbitrary_timestamp, mir_keyboard_action_up, 0, KEY_LEFTCTRL); | 439 | auto ctrl_up = key_event_builder_2->key_event(arbitrary_timestamp, mir_keyboard_action_up, 0, KEY_LEFTCTRL); |
659 | @@ -462,8 +471,6 @@ | |||
660 | 462 | hub.add_device(mt::fake_shared(device)); | 471 | hub.add_device(mt::fake_shared(device)); |
661 | 463 | hub.add_device(mt::fake_shared(another_device)); | 472 | hub.add_device(mt::fake_shared(another_device)); |
662 | 464 | 473 | ||
663 | 465 | observer_loop.trigger_server_actions(); | ||
664 | 466 | |||
665 | 467 | auto motion_1 = | 474 | auto motion_1 = |
666 | 468 | mouse_event_builder_1->pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 0, 0, 23, 20); | 475 | mouse_event_builder_1->pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 0, 0, 23, 20); |
667 | 469 | auto motion_2 = | 476 | auto motion_2 = |
668 | @@ -495,8 +502,6 @@ | |||
669 | 495 | hub.add_device(mt::fake_shared(device)); | 502 | hub.add_device(mt::fake_shared(device)); |
670 | 496 | hub.add_device(mt::fake_shared(another_device)); | 503 | hub.add_device(mt::fake_shared(another_device)); |
671 | 497 | 504 | ||
672 | 498 | observer_loop.trigger_server_actions(); | ||
673 | 499 | |||
674 | 500 | auto motion_1 = | 505 | auto motion_1 = |
675 | 501 | mouse_event_builder_1->pointer_event(arbitrary_timestamp, mir_pointer_action_button_down, mir_pointer_button_primary, 0, 0, 0, 0); | 506 | mouse_event_builder_1->pointer_event(arbitrary_timestamp, mir_pointer_action_button_down, mir_pointer_button_primary, 0, 0, 0, 0); |
676 | 502 | auto motion_2 = | 507 | auto motion_2 = |
677 | @@ -525,7 +530,6 @@ | |||
678 | 525 | 530 | ||
679 | 526 | EXPECT_CALL(session, send_input_config(UnorderedElementsAre(DeviceMatches(device.get_device_info())))); | 531 | EXPECT_CALL(session, send_input_config(UnorderedElementsAre(DeviceMatches(device.get_device_info())))); |
680 | 527 | hub.add_device(mt::fake_shared(device)); | 532 | hub.add_device(mt::fake_shared(device)); |
681 | 528 | observer_loop.trigger_server_actions(); | ||
682 | 529 | } | 533 | } |
683 | 530 | 534 | ||
684 | 531 | TEST_F(SingleSeatInputDeviceHubSetup, input_device_changes_sent_to_session_multiple_devices) | 535 | TEST_F(SingleSeatInputDeviceHubSetup, input_device_changes_sent_to_session_multiple_devices) |
685 | @@ -534,25 +538,21 @@ | |||
686 | 534 | stub_session_container.insert_session(mt::fake_shared(session)); | 538 | stub_session_container.insert_session(mt::fake_shared(session)); |
687 | 535 | 539 | ||
688 | 536 | hub.add_device(mt::fake_shared(device)); | 540 | hub.add_device(mt::fake_shared(device)); |
689 | 537 | observer_loop.trigger_server_actions(); | ||
690 | 538 | 541 | ||
691 | 539 | EXPECT_CALL(session, | 542 | EXPECT_CALL(session, |
692 | 540 | send_input_config(UnorderedElementsAre(DeviceMatches(device.get_device_info()), | 543 | send_input_config(UnorderedElementsAre(DeviceMatches(device.get_device_info()), |
693 | 541 | DeviceMatches(another_device.get_device_info())))); | 544 | DeviceMatches(another_device.get_device_info())))); |
694 | 542 | hub.add_device(mt::fake_shared(another_device)); | 545 | hub.add_device(mt::fake_shared(another_device)); |
695 | 543 | observer_loop.trigger_server_actions(); | ||
696 | 544 | } | 546 | } |
697 | 545 | 547 | ||
698 | 546 | TEST_F(SingleSeatInputDeviceHubSetup, input_device_changes_sent_to_sink_removal) | 548 | TEST_F(SingleSeatInputDeviceHubSetup, input_device_changes_sent_to_sink_removal) |
699 | 547 | { | 549 | { |
700 | 548 | hub.add_device(mt::fake_shared(device)); | 550 | hub.add_device(mt::fake_shared(device)); |
701 | 549 | hub.add_device(mt::fake_shared(another_device)); | 551 | hub.add_device(mt::fake_shared(another_device)); |
702 | 550 | observer_loop.trigger_server_actions(); | ||
703 | 551 | 552 | ||
704 | 552 | NiceMock<mtd::MockSceneSession> session; | 553 | NiceMock<mtd::MockSceneSession> session; |
705 | 553 | stub_session_container.insert_session(mt::fake_shared(session)); | 554 | stub_session_container.insert_session(mt::fake_shared(session)); |
706 | 554 | EXPECT_CALL(session, | 555 | EXPECT_CALL(session, |
707 | 555 | send_input_config(UnorderedElementsAre(DeviceMatches(another_device.get_device_info())))); | 556 | send_input_config(UnorderedElementsAre(DeviceMatches(another_device.get_device_info())))); |
708 | 556 | hub.remove_device(mt::fake_shared(device)); | 557 | hub.remove_device(mt::fake_shared(device)); |
709 | 557 | observer_loop.trigger_server_actions(); | ||
710 | 558 | } | 558 | } |
711 | 559 | 559 | ||
712 | === modified file 'tests/unit-tests/input/CMakeLists.txt' | |||
713 | --- tests/unit-tests/input/CMakeLists.txt 2017-03-13 08:12:52 +0000 | |||
714 | +++ tests/unit-tests/input/CMakeLists.txt 2017-03-23 16:31:26 +0000 | |||
715 | @@ -8,6 +8,7 @@ | |||
716 | 8 | ${CMAKE_CURRENT_SOURCE_DIR}/test_input_event.cpp | 8 | ${CMAKE_CURRENT_SOURCE_DIR}/test_input_event.cpp |
717 | 9 | ${CMAKE_CURRENT_SOURCE_DIR}/test_config_changer.cpp | 9 | ${CMAKE_CURRENT_SOURCE_DIR}/test_config_changer.cpp |
718 | 10 | ${CMAKE_CURRENT_SOURCE_DIR}/test_event_builders.cpp | 10 | ${CMAKE_CURRENT_SOURCE_DIR}/test_event_builders.cpp |
719 | 11 | ${CMAKE_CURRENT_SOURCE_DIR}/test_external_input_device_hub.cpp | ||
720 | 11 | ${CMAKE_CURRENT_SOURCE_DIR}/test_default_device.cpp | 12 | ${CMAKE_CURRENT_SOURCE_DIR}/test_default_device.cpp |
721 | 12 | ${CMAKE_CURRENT_SOURCE_DIR}/test_default_input_device_hub.cpp | 13 | ${CMAKE_CURRENT_SOURCE_DIR}/test_default_input_device_hub.cpp |
722 | 13 | ${CMAKE_CURRENT_SOURCE_DIR}/test_default_input_manager.cpp | 14 | ${CMAKE_CURRENT_SOURCE_DIR}/test_default_input_manager.cpp |
723 | 14 | 15 | ||
724 | === modified file 'tests/unit-tests/input/test_config_changer.cpp' | |||
725 | --- tests/unit-tests/input/test_config_changer.cpp 2017-02-28 08:53:57 +0000 | |||
726 | +++ tests/unit-tests/input/test_config_changer.cpp 2017-03-23 16:31:26 +0000 | |||
727 | @@ -29,6 +29,7 @@ | |||
728 | 29 | 29 | ||
729 | 30 | #include "mir/test/doubles/mock_input_device_hub.h" | 30 | #include "mir/test/doubles/mock_input_device_hub.h" |
730 | 31 | #include "mir/test/doubles/mock_input_manager.h" | 31 | #include "mir/test/doubles/mock_input_manager.h" |
731 | 32 | #include "mir/test/doubles/mock_device.h" | ||
732 | 32 | #include "mir/test/doubles/mock_scene_session.h" | 33 | #include "mir/test/doubles/mock_scene_session.h" |
733 | 33 | #include "mir/test/doubles/stub_session.h" | 34 | #include "mir/test/doubles/stub_session.h" |
734 | 34 | #include "mir/test/doubles/stub_session_container.h" | 35 | #include "mir/test/doubles/stub_session_container.h" |
735 | @@ -47,34 +48,6 @@ | |||
736 | 47 | namespace | 48 | namespace |
737 | 48 | { | 49 | { |
738 | 49 | 50 | ||
739 | 50 | struct MockDevice : mir::input::Device | ||
740 | 51 | { | ||
741 | 52 | MockDevice(MirInputDeviceId id, mi::DeviceCapabilities caps, std::string const& name, std::string const& unique_id) | ||
742 | 53 | { | ||
743 | 54 | ON_CALL(*this, id()).WillByDefault(Return(id)); | ||
744 | 55 | ON_CALL(*this, name()).WillByDefault(Return(name)); | ||
745 | 56 | ON_CALL(*this, unique_id()).WillByDefault(Return(unique_id)); | ||
746 | 57 | ON_CALL(*this, capabilities()).WillByDefault(Return(caps)); | ||
747 | 58 | ON_CALL(*this, pointer_configuration()).WillByDefault(Return(MirPointerConfig{})); | ||
748 | 59 | ON_CALL(*this, keyboard_configuration()).WillByDefault(Return(MirKeyboardConfig{})); | ||
749 | 60 | ON_CALL(*this, touchpad_configuration()).WillByDefault(Return(MirTouchpadConfig{})); | ||
750 | 61 | ON_CALL(*this, touchscreen_configuration()).WillByDefault(Return(MirTouchscreenConfig{})); | ||
751 | 62 | } | ||
752 | 63 | |||
753 | 64 | MOCK_CONST_METHOD0(id, MirInputDeviceId()); | ||
754 | 65 | MOCK_CONST_METHOD0(capabilities, mir::input::DeviceCapabilities()); | ||
755 | 66 | MOCK_CONST_METHOD0(name, std::string()); | ||
756 | 67 | MOCK_CONST_METHOD0(unique_id, std::string()); | ||
757 | 68 | MOCK_CONST_METHOD0(pointer_configuration, mir::optional_value<MirPointerConfig>()); | ||
758 | 69 | MOCK_CONST_METHOD0(touchpad_configuration, mir::optional_value<MirTouchpadConfig>()); | ||
759 | 70 | MOCK_CONST_METHOD0(keyboard_configuration, mir::optional_value<MirKeyboardConfig>()); | ||
760 | 71 | MOCK_CONST_METHOD0(touchscreen_configuration, mir::optional_value<MirTouchscreenConfig>()); | ||
761 | 72 | MOCK_METHOD1(apply_pointer_configuration, void(MirPointerConfig const&)); | ||
762 | 73 | MOCK_METHOD1(apply_touchpad_configuration, void(MirTouchpadConfig const&)); | ||
763 | 74 | MOCK_METHOD1(apply_keyboard_configuration, void(MirKeyboardConfig const&)); | ||
764 | 75 | MOCK_METHOD1(apply_touchscreen_configuration, void(MirTouchscreenConfig const&)); | ||
765 | 76 | }; | ||
766 | 77 | |||
767 | 78 | struct FakeInputDeviceHub : mir::input::InputDeviceHub | 51 | struct FakeInputDeviceHub : mir::input::InputDeviceHub |
768 | 79 | { | 52 | { |
769 | 80 | std::shared_ptr<mi::InputDeviceObserver> observer; | 53 | std::shared_ptr<mi::InputDeviceObserver> observer; |
770 | @@ -86,8 +59,8 @@ | |||
771 | 86 | mi::DeviceCapability::keyboard | mi::DeviceCapability::alpha_numeric | | 59 | mi::DeviceCapability::keyboard | mi::DeviceCapability::alpha_numeric | |
772 | 87 | mi::DeviceCapability::touchscreen; | 60 | mi::DeviceCapability::touchscreen; |
773 | 88 | 61 | ||
776 | 89 | NiceMock<MockDevice> first_device{first_id, caps, first, first}; | 62 | NiceMock<mtd::MockDevice> first_device{first_id, caps, first, first}; |
777 | 90 | NiceMock<MockDevice> second_device{second_id, caps, second, second}; | 63 | NiceMock<mtd::MockDevice> second_device{second_id, caps, second, second}; |
778 | 91 | std::vector<std::shared_ptr<mir::input::Device>> active_devices; | 64 | std::vector<std::shared_ptr<mir::input::Device>> active_devices; |
779 | 92 | 65 | ||
780 | 93 | void add_observer(std::shared_ptr<mi::InputDeviceObserver> const& obs) override | 66 | void add_observer(std::shared_ptr<mi::InputDeviceObserver> const& obs) override |
781 | 94 | 67 | ||
782 | === modified file 'tests/unit-tests/input/test_default_input_device_hub.cpp' | |||
783 | --- tests/unit-tests/input/test_default_input_device_hub.cpp 2017-03-13 08:12:52 +0000 | |||
784 | +++ tests/unit-tests/input/test_default_input_device_hub.cpp 2017-03-23 16:31:26 +0000 | |||
785 | @@ -30,6 +30,7 @@ | |||
786 | 30 | #include "mir/test/doubles/triggered_main_loop.h" | 30 | #include "mir/test/doubles/triggered_main_loop.h" |
787 | 31 | #include "mir/test/event_matchers.h" | 31 | #include "mir/test/event_matchers.h" |
788 | 32 | #include "mir/test/fake_shared.h" | 32 | #include "mir/test/fake_shared.h" |
789 | 33 | #include "mir/test/fd_utils.h" | ||
790 | 33 | 34 | ||
791 | 34 | #include "mir/dispatch/action_queue.h" | 35 | #include "mir/dispatch/action_queue.h" |
792 | 35 | #include "mir/geometry/rectangles.h" | 36 | #include "mir/geometry/rectangles.h" |
793 | @@ -77,14 +78,14 @@ | |||
794 | 77 | 78 | ||
795 | 78 | struct InputDeviceHubTest : ::testing::Test | 79 | struct InputDeviceHubTest : ::testing::Test |
796 | 79 | { | 80 | { |
797 | 80 | mtd::TriggeredMainLoop observer_loop; | ||
798 | 81 | std::shared_ptr<mir::cookie::Authority> cookie_authority = mir::cookie::Authority::create(); | 81 | std::shared_ptr<mir::cookie::Authority> cookie_authority = mir::cookie::Authority::create(); |
799 | 82 | mir::dispatch::MultiplexingDispatchable multiplexer; | 82 | mir::dispatch::MultiplexingDispatchable multiplexer; |
800 | 83 | NiceMock<mtd::MockInputSeat> mock_seat; | 83 | NiceMock<mtd::MockInputSeat> mock_seat; |
801 | 84 | NiceMock<mtd::MockKeyMapper> mock_key_mapper; | 84 | NiceMock<mtd::MockKeyMapper> mock_key_mapper; |
802 | 85 | NiceMock<mtd::MockServerStatusListener> mock_server_status_listener; | 85 | NiceMock<mtd::MockServerStatusListener> mock_server_status_listener; |
803 | 86 | mi::DefaultInputDeviceHub hub{mt::fake_shared(mock_seat), mt::fake_shared(multiplexer), | 86 | mi::DefaultInputDeviceHub hub{mt::fake_shared(mock_seat), mt::fake_shared(multiplexer), |
805 | 87 | mt::fake_shared(observer_loop), cookie_authority, mt::fake_shared(mock_key_mapper), mt::fake_shared(mock_server_status_listener)}; | 87 | cookie_authority, mt::fake_shared(mock_key_mapper), |
806 | 88 | mt::fake_shared(mock_server_status_listener)}; | ||
807 | 88 | NiceMock<mtd::MockInputDeviceObserver> mock_observer; | 89 | NiceMock<mtd::MockInputDeviceObserver> mock_observer; |
808 | 89 | NiceMock<mtd::MockInputDevice> device{"device","dev-1", mi::DeviceCapability::unknown}; | 90 | NiceMock<mtd::MockInputDevice> device{"device","dev-1", mi::DeviceCapability::unknown}; |
809 | 90 | NiceMock<mtd::MockInputDevice> another_device{"another_device","dev-2", mi::DeviceCapability::keyboard}; | 91 | NiceMock<mtd::MockInputDevice> another_device{"another_device","dev-2", mi::DeviceCapability::keyboard}; |
810 | @@ -104,6 +105,12 @@ | |||
811 | 104 | } | 105 | } |
812 | 105 | )); | 106 | )); |
813 | 106 | } | 107 | } |
814 | 108 | |||
815 | 109 | void expect_and_execute_multiplexer() | ||
816 | 110 | { | ||
817 | 111 | mt::fd_becomes_readable(multiplexer.watch_fd(), 2s); | ||
818 | 112 | multiplexer.dispatch(mir::dispatch::FdEvent::readable); | ||
819 | 113 | } | ||
820 | 107 | }; | 114 | }; |
821 | 108 | 115 | ||
822 | 109 | TEST_F(InputDeviceHubTest, input_device_hub_starts_device) | 116 | TEST_F(InputDeviceHubTest, input_device_hub_starts_device) |
823 | @@ -161,8 +168,7 @@ | |||
824 | 161 | hub.add_device(mt::fake_shared(another_device)); | 168 | hub.add_device(mt::fake_shared(another_device)); |
825 | 162 | hub.add_observer(mt::fake_shared(mock_observer)); | 169 | hub.add_observer(mt::fake_shared(mock_observer)); |
826 | 163 | 170 | ||
829 | 164 | observer_loop.trigger_server_actions(); | 171 | expect_and_execute_multiplexer(); |
828 | 165 | |||
830 | 166 | EXPECT_THAT(handle_1,Ne(handle_2)); | 172 | EXPECT_THAT(handle_1,Ne(handle_2)); |
831 | 167 | EXPECT_THAT(handle_1->unique_id(),Ne(handle_2->unique_id())); | 173 | EXPECT_THAT(handle_1->unique_id(),Ne(handle_2->unique_id())); |
832 | 168 | } | 174 | } |
833 | @@ -208,10 +214,13 @@ | |||
834 | 208 | EXPECT_CALL(mock_observer, changes_complete()); | 214 | EXPECT_CALL(mock_observer, changes_complete()); |
835 | 209 | 215 | ||
836 | 210 | hub.add_observer(mt::fake_shared(mock_observer)); | 216 | hub.add_observer(mt::fake_shared(mock_observer)); |
837 | 217 | expect_and_execute_multiplexer(); | ||
838 | 218 | |||
839 | 211 | hub.add_device(mt::fake_shared(device)); | 219 | hub.add_device(mt::fake_shared(device)); |
840 | 220 | expect_and_execute_multiplexer(); | ||
841 | 221 | |||
842 | 212 | hub.remove_device(mt::fake_shared(device)); | 222 | hub.remove_device(mt::fake_shared(device)); |
845 | 213 | 223 | expect_and_execute_multiplexer(); | |
844 | 214 | observer_loop.trigger_server_actions(); | ||
846 | 215 | } | 224 | } |
847 | 216 | 225 | ||
848 | 217 | TEST_F(InputDeviceHubTest, emit_ready_to_receive_input_after_first_device_added) | 226 | TEST_F(InputDeviceHubTest, emit_ready_to_receive_input_after_first_device_added) |
849 | @@ -219,8 +228,6 @@ | |||
850 | 219 | EXPECT_CALL(mock_server_status_listener, ready_for_user_input()).Times(1); | 228 | EXPECT_CALL(mock_server_status_listener, ready_for_user_input()).Times(1); |
851 | 220 | hub.add_device(mt::fake_shared(device)); | 229 | hub.add_device(mt::fake_shared(device)); |
852 | 221 | hub.add_device(mt::fake_shared(another_device)); | 230 | hub.add_device(mt::fake_shared(another_device)); |
853 | 222 | |||
854 | 223 | observer_loop.trigger_server_actions(); | ||
855 | 224 | } | 231 | } |
856 | 225 | 232 | ||
857 | 226 | TEST_F(InputDeviceHubTest, emit_stop_receiving_input_after_last_device_added) | 233 | TEST_F(InputDeviceHubTest, emit_stop_receiving_input_after_last_device_added) |
858 | @@ -231,7 +238,6 @@ | |||
859 | 231 | 238 | ||
860 | 232 | hub.remove_device(mt::fake_shared(device)); | 239 | hub.remove_device(mt::fake_shared(device)); |
861 | 233 | hub.remove_device(mt::fake_shared(another_device)); | 240 | hub.remove_device(mt::fake_shared(another_device)); |
862 | 234 | observer_loop.trigger_server_actions(); | ||
863 | 235 | } | 241 | } |
864 | 236 | 242 | ||
865 | 237 | TEST_F(InputDeviceHubTest, when_pointer_configuration_is_applied_successfully_observer_is_triggerd) | 243 | TEST_F(InputDeviceHubTest, when_pointer_configuration_is_applied_successfully_observer_is_triggerd) |
866 | @@ -243,13 +249,13 @@ | |||
867 | 243 | 249 | ||
868 | 244 | hub.add_device(mt::fake_shared(mouse)); | 250 | hub.add_device(mt::fake_shared(mouse)); |
869 | 245 | hub.add_observer(mt::fake_shared(mock_observer)); | 251 | hub.add_observer(mt::fake_shared(mock_observer)); |
871 | 246 | observer_loop.trigger_server_actions(); | 252 | expect_and_execute_multiplexer(); |
872 | 247 | 253 | ||
873 | 248 | EXPECT_CALL(mock_observer, device_changed(WithName("mouse"))); | 254 | EXPECT_CALL(mock_observer, device_changed(WithName("mouse"))); |
874 | 249 | EXPECT_CALL(mock_observer, changes_complete()); | 255 | EXPECT_CALL(mock_observer, changes_complete()); |
875 | 250 | 256 | ||
876 | 251 | dev_ptr->apply_pointer_configuration(pointer_conf); | 257 | dev_ptr->apply_pointer_configuration(pointer_conf); |
878 | 252 | observer_loop.trigger_server_actions(); | 258 | expect_and_execute_multiplexer(); |
879 | 253 | } | 259 | } |
880 | 254 | 260 | ||
881 | 255 | TEST_F(InputDeviceHubTest, when_tpd_configuration_is_applied_successfully_observer_is_triggerd) | 261 | TEST_F(InputDeviceHubTest, when_tpd_configuration_is_applied_successfully_observer_is_triggerd) |
882 | @@ -261,13 +267,13 @@ | |||
883 | 261 | 267 | ||
884 | 262 | hub.add_device(mt::fake_shared(touchpad)); | 268 | hub.add_device(mt::fake_shared(touchpad)); |
885 | 263 | hub.add_observer(mt::fake_shared(mock_observer)); | 269 | hub.add_observer(mt::fake_shared(mock_observer)); |
887 | 264 | observer_loop.trigger_server_actions(); | 270 | expect_and_execute_multiplexer(); |
888 | 265 | 271 | ||
889 | 266 | EXPECT_CALL(mock_observer, device_changed(WithName("tpd"))); | 272 | EXPECT_CALL(mock_observer, device_changed(WithName("tpd"))); |
890 | 267 | EXPECT_CALL(mock_observer, changes_complete()); | 273 | EXPECT_CALL(mock_observer, changes_complete()); |
891 | 268 | 274 | ||
892 | 269 | dev_ptr->apply_touchpad_configuration(tpd_conf); | 275 | dev_ptr->apply_touchpad_configuration(tpd_conf); |
894 | 270 | observer_loop.trigger_server_actions(); | 276 | expect_and_execute_multiplexer(); |
895 | 271 | } | 277 | } |
896 | 272 | 278 | ||
897 | 273 | TEST_F(InputDeviceHubTest, when_configuration_attempt_fails_observer_is_not_triggerd) | 279 | TEST_F(InputDeviceHubTest, when_configuration_attempt_fails_observer_is_not_triggerd) |
898 | @@ -279,12 +285,12 @@ | |||
899 | 279 | 285 | ||
900 | 280 | hub.add_device(mt::fake_shared(mouse)); | 286 | hub.add_device(mt::fake_shared(mouse)); |
901 | 281 | hub.add_observer(mt::fake_shared(mock_observer)); | 287 | hub.add_observer(mt::fake_shared(mock_observer)); |
903 | 282 | observer_loop.trigger_server_actions(); | 288 | expect_and_execute_multiplexer(); |
904 | 283 | 289 | ||
905 | 284 | EXPECT_CALL(mock_observer, device_changed(WithName("mouse"))).Times(0); | 290 | EXPECT_CALL(mock_observer, device_changed(WithName("mouse"))).Times(0); |
906 | 285 | EXPECT_CALL(mock_observer, changes_complete()).Times(0); | 291 | EXPECT_CALL(mock_observer, changes_complete()).Times(0); |
907 | 286 | 292 | ||
908 | 287 | try {dev_ptr->apply_touchpad_configuration(tpd_conf); } catch (...) {} | 293 | try {dev_ptr->apply_touchpad_configuration(tpd_conf); } catch (...) {} |
910 | 288 | observer_loop.trigger_server_actions(); | 294 | expect_and_execute_multiplexer(); |
911 | 289 | ::testing::Mock::VerifyAndClearExpectations(&mock_observer); | 295 | ::testing::Mock::VerifyAndClearExpectations(&mock_observer); |
912 | 290 | } | 296 | } |
913 | 291 | 297 | ||
914 | === added file 'tests/unit-tests/input/test_external_input_device_hub.cpp' | |||
915 | --- tests/unit-tests/input/test_external_input_device_hub.cpp 1970-01-01 00:00:00 +0000 | |||
916 | +++ tests/unit-tests/input/test_external_input_device_hub.cpp 2017-03-23 16:31:26 +0000 | |||
917 | @@ -0,0 +1,119 @@ | |||
918 | 1 | /* | ||
919 | 2 | * Copyright © 2017 Canonical Ltd. | ||
920 | 3 | * | ||
921 | 4 | * This program is free software: you can redistribute it and/or modify | ||
922 | 5 | * it under the terms of the GNU General Public License version 3 as | ||
923 | 6 | * published by the Free Software Foundation. | ||
924 | 7 | * | ||
925 | 8 | * This program is distributed in the hope that it will be useful, | ||
926 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
927 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
928 | 11 | * GNU General Public License for more details. | ||
929 | 12 | * | ||
930 | 13 | * You should have received a copy of the GNU General Public License | ||
931 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
932 | 15 | * | ||
933 | 16 | * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> | ||
934 | 17 | */ | ||
935 | 18 | |||
936 | 19 | #include "src/server/input/default_input_device_hub.h" | ||
937 | 20 | #include "mir/test/doubles/mock_input_device_hub.h" | ||
938 | 21 | #include "mir/test/doubles/mock_device.h" | ||
939 | 22 | #include "mir/test/doubles/mock_input_device_observer.h" | ||
940 | 23 | #include "mir/test/doubles/triggered_main_loop.h" | ||
941 | 24 | #include "mir/test/fake_shared.h" | ||
942 | 25 | |||
943 | 26 | namespace mt = mir::test; | ||
944 | 27 | namespace mtd = mt::doubles; | ||
945 | 28 | namespace mi = mir::input; | ||
946 | 29 | using namespace testing; | ||
947 | 30 | |||
948 | 31 | namespace | ||
949 | 32 | { | ||
950 | 33 | |||
951 | 34 | struct WrappedHub : mtd::MockInputDeviceHub | ||
952 | 35 | { | ||
953 | 36 | std::shared_ptr<mi::InputDeviceObserver> external_hub; | ||
954 | 37 | void add_observer(std::shared_ptr<mi::InputDeviceObserver> const& observer) | ||
955 | 38 | { | ||
956 | 39 | external_hub = observer; | ||
957 | 40 | } | ||
958 | 41 | }; | ||
959 | 42 | |||
960 | 43 | struct ExternalInputDeviceHub : ::testing::Test | ||
961 | 44 | { | ||
962 | 45 | mtd::TriggeredMainLoop server_actions; | ||
963 | 46 | std::shared_ptr<WrappedHub> wrapped_hub{std::make_shared<WrappedHub>()}; | ||
964 | 47 | mi::ExternalInputDeviceHub hub{wrapped_hub, mt::fake_shared(server_actions)}; | ||
965 | 48 | NiceMock<mtd::MockInputDeviceObserver> mock_observer; | ||
966 | 49 | |||
967 | 50 | NiceMock<mtd::MockDevice> device{1, mi::DeviceCapability::unknown, "name", "name-id-1"}; | ||
968 | 51 | NiceMock<mtd::MockDevice> another_device{2, mi::DeviceCapability::keyboard, "keyboard", "keyboard-id-2"}; | ||
969 | 52 | |||
970 | 53 | void submit_device_to_hub(std::shared_ptr<mi::Device> const& dev) | ||
971 | 54 | { | ||
972 | 55 | wrapped_hub->external_hub->device_added(dev); | ||
973 | 56 | wrapped_hub->external_hub->changes_complete(); | ||
974 | 57 | } | ||
975 | 58 | |||
976 | 59 | void remove_device_to_hub(std::shared_ptr<mi::Device> const& dev) | ||
977 | 60 | { | ||
978 | 61 | wrapped_hub->external_hub->device_removed(dev); | ||
979 | 62 | wrapped_hub->external_hub->changes_complete(); | ||
980 | 63 | } | ||
981 | 64 | }; | ||
982 | 65 | } | ||
983 | 66 | |||
984 | 67 | TEST_F(ExternalInputDeviceHub, is_observer_to_wrapped_hub) | ||
985 | 68 | { | ||
986 | 69 | EXPECT_THAT(wrapped_hub->external_hub, Ne(nullptr)); | ||
987 | 70 | } | ||
988 | 71 | |||
989 | 72 | TEST_F(ExternalInputDeviceHub, new_observer_is_called_through_server_action) | ||
990 | 73 | { | ||
991 | 74 | EXPECT_CALL(mock_observer, changes_complete()).Times(1); | ||
992 | 75 | hub.add_observer(mt::fake_shared(mock_observer)); | ||
993 | 76 | server_actions.trigger_server_actions(); | ||
994 | 77 | } | ||
995 | 78 | |||
996 | 79 | TEST_F(ExternalInputDeviceHub, informs_observer_about_existing_devices) | ||
997 | 80 | { | ||
998 | 81 | submit_device_to_hub(mt::fake_shared(device)); | ||
999 | 82 | submit_device_to_hub(mt::fake_shared(another_device)); | ||
1000 | 83 | |||
1001 | 84 | EXPECT_CALL(mock_observer, device_added(_)).Times(2); | ||
1002 | 85 | EXPECT_CALL(mock_observer, changes_complete()).Times(1); | ||
1003 | 86 | hub.add_observer(mt::fake_shared(mock_observer)); | ||
1004 | 87 | server_actions.trigger_server_actions(); | ||
1005 | 88 | } | ||
1006 | 89 | |||
1007 | 90 | TEST_F(ExternalInputDeviceHub, informs_observer_about_added_devices) | ||
1008 | 91 | { | ||
1009 | 92 | InSequence seq; | ||
1010 | 93 | |||
1011 | 94 | EXPECT_CALL(mock_observer, changes_complete()); | ||
1012 | 95 | EXPECT_CALL(mock_observer, device_added(_)); | ||
1013 | 96 | EXPECT_CALL(mock_observer, changes_complete()); | ||
1014 | 97 | hub.add_observer(mt::fake_shared(mock_observer)); | ||
1015 | 98 | server_actions.trigger_server_actions(); | ||
1016 | 99 | |||
1017 | 100 | submit_device_to_hub(mt::fake_shared(device)); | ||
1018 | 101 | |||
1019 | 102 | server_actions.trigger_server_actions(); | ||
1020 | 103 | } | ||
1021 | 104 | |||
1022 | 105 | TEST_F(ExternalInputDeviceHub, triggers_observer_on_removed_devices) | ||
1023 | 106 | { | ||
1024 | 107 | submit_device_to_hub(mt::fake_shared(device)); | ||
1025 | 108 | |||
1026 | 109 | EXPECT_CALL(mock_observer, device_added(_)).Times(1); | ||
1027 | 110 | EXPECT_CALL(mock_observer, changes_complete()).Times(1); | ||
1028 | 111 | hub.add_observer(mt::fake_shared(mock_observer)); | ||
1029 | 112 | server_actions.trigger_server_actions(); | ||
1030 | 113 | |||
1031 | 114 | EXPECT_CALL(mock_observer, device_removed(_)).Times(1); | ||
1032 | 115 | EXPECT_CALL(mock_observer, changes_complete()).Times(1); | ||
1033 | 116 | |||
1034 | 117 | remove_device_to_hub(mt::fake_shared(device)); | ||
1035 | 118 | server_actions.trigger_server_actions(); | ||
1036 | 119 | } |
PASSED: Continuous integration, rev:4085 /mir-jenkins. ubuntu. com/job/ mir-ci/ 3159/ /mir-jenkins. ubuntu. com/job/ build-mir/ 4238 /mir-jenkins. ubuntu. com/job/ build-0- fetch/4325 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= vivid+overlay/ 4315 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial+ overlay/ 4315 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= zesty/4315 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= zesty/4265 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= zesty/4265/ artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial+ overlay/ 4265 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial+ overlay/ 4265/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= zesty/4265 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= zesty/4265/ artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 4265 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 4265/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 4265 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 4265/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial+ overlay/ 4265 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial+ overlay/ 4265/artifact/ output/ *zip*/output. zip
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: /mir-jenkins. ubuntu. com/job/ mir-ci/ 3159/rebuild
https:/