Merge lp:~robertcarr/mir/refactor-input-acceptance-take-1 into lp:mir
- refactor-input-acceptance-take-1
- Merge into development-branch
Proposed by
Robert Carr
Status: | Superseded |
---|---|
Proposed branch: | lp:~robertcarr/mir/refactor-input-acceptance-take-1 |
Merge into: | lp:mir |
Diff against target: |
1600 lines (+720/-471) 17 files modified
doc/component_reports.md (+1/-0) include/shared/mir/input/input_platform.h (+3/-1) include/shared/mir/input/input_receiver_report.h (+48/-0) include/shared/mir/input/null_input_receiver_report.h (+46/-0) include/test/mir_test_framework/input_testing_server_configuration.h (+2/-1) src/client/CMakeLists.txt (+1/-0) src/client/default_connection_configuration.cpp (+20/-2) src/client/default_connection_configuration.h (+9/-0) src/client/logging/input_receiver_report.cpp (+125/-0) src/client/logging/input_receiver_report.h (+54/-0) src/shared/input/android/android_input_platform.cpp (+11/-3) src/shared/input/android/android_input_platform.h (+4/-1) src/shared/input/android/android_input_receiver.cpp (+9/-2) src/shared/input/android/android_input_receiver.h (+7/-2) tests/acceptance-tests/test_client_input.cpp (+367/-452) tests/unit-tests/client/input/test_android_input_receiver.cpp (+8/-5) tests/unit-tests/client/input/test_android_input_receiver_thread.cpp (+5/-2) |
To merge this branch: | bzr merge lp:~robertcarr/mir/refactor-input-acceptance-take-1 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir development team | Pending | ||
Review via email: mp+194264@code.launchpad.net |
This proposal has been superseded by a proposal from 2013-11-07.
Commit message
Simplify input acceptance tests with a better shared fixture.
Description of the change
First take at simplifying input acceptance tests with a better shared fixture.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'doc/component_reports.md' |
2 | --- doc/component_reports.md 2013-10-24 11:41:30 +0000 |
3 | +++ doc/component_reports.md 2013-11-07 00:22:14 +0000 |
4 | @@ -40,6 +40,7 @@ |
5 | Report | Handlers |
6 | ------------------- | -------- |
7 | rpc-report | log,lttng |
8 | +input-receiver | log |
9 | |
10 | For example, to enable the logging RPC report, one should set the |
11 | `MIR_CLIENT_RPC_REPORT=log` environment variable. |
12 | |
13 | === modified file 'include/shared/mir/input/input_platform.h' |
14 | --- include/shared/mir/input/input_platform.h 2013-05-13 23:20:52 +0000 |
15 | +++ include/shared/mir/input/input_platform.h 2013-11-07 00:22:14 +0000 |
16 | @@ -31,6 +31,7 @@ |
17 | namespace receiver |
18 | { |
19 | class InputReceiverThread; |
20 | +class InputReceiverReport; |
21 | |
22 | // Interface for MirSurface to construct input dispatcher threads. |
23 | class InputPlatform |
24 | @@ -39,8 +40,9 @@ |
25 | virtual ~InputPlatform() {}; |
26 | |
27 | virtual std::shared_ptr<InputReceiverThread> create_input_thread(int fd, std::function<void(MirEvent *)> const& callback) = 0; |
28 | - |
29 | + |
30 | static std::shared_ptr<InputPlatform> create(); |
31 | + static std::shared_ptr<InputPlatform> create(std::shared_ptr<InputReceiverReport> const& report); |
32 | |
33 | protected: |
34 | InputPlatform() = default; |
35 | |
36 | === added file 'include/shared/mir/input/input_receiver_report.h' |
37 | --- include/shared/mir/input/input_receiver_report.h 1970-01-01 00:00:00 +0000 |
38 | +++ include/shared/mir/input/input_receiver_report.h 2013-11-07 00:22:14 +0000 |
39 | @@ -0,0 +1,48 @@ |
40 | +/* |
41 | + * Copyright © 2013 Canonical Ltd. |
42 | + * |
43 | + * This program is free software: you can redistribute it and/or modify |
44 | + * it under the terms of the GNU Lesser General Public License version 3 as |
45 | + * published by the Free Software Foundation. |
46 | + * |
47 | + * This program is distributed in the hope that it will be useful, |
48 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
49 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
50 | + * GNU Lesser General Public License for more details. |
51 | + * |
52 | + * You should have received a copy of the GNU Lesser General Public License |
53 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
54 | + * |
55 | + * Authored by: Robert Carr <robert.carr@canonical.com> |
56 | + */ |
57 | + |
58 | +#ifndef MIR_CLIENT_INPUT_RECEIVER_REPORT_H_ |
59 | +#define MIR_CLIENT_INPUT_RECEIVER_REPORT_H_ |
60 | + |
61 | +#include <mir_toolkit/event.h> |
62 | + |
63 | +namespace mir |
64 | +{ |
65 | +namespace input |
66 | +{ |
67 | +namespace receiver |
68 | +{ |
69 | + |
70 | +class InputReceiverReport |
71 | +{ |
72 | +public: |
73 | + virtual ~InputReceiverReport() = default; |
74 | + |
75 | + virtual void received_event(MirEvent const& event) = 0; |
76 | + |
77 | +protected: |
78 | + InputReceiverReport() = default; |
79 | + InputReceiverReport(InputReceiverReport const&) = delete; |
80 | + InputReceiverReport& operator=(InputReceiverReport const&) = delete; |
81 | +}; |
82 | + |
83 | +} |
84 | +} |
85 | +} |
86 | + |
87 | +#endif /* MIR_CLIENT_INPUT_RECEIVER_REPORT_H_ */ |
88 | |
89 | === added file 'include/shared/mir/input/null_input_receiver_report.h' |
90 | --- include/shared/mir/input/null_input_receiver_report.h 1970-01-01 00:00:00 +0000 |
91 | +++ include/shared/mir/input/null_input_receiver_report.h 2013-11-07 00:22:14 +0000 |
92 | @@ -0,0 +1,46 @@ |
93 | +/* |
94 | + * Copyright © 2013 Canonical Ltd. |
95 | + * |
96 | + * This program is free software: you can redistribute it and/or modify |
97 | + * it under the terms of the GNU Lesser General Public License version 3 as |
98 | + * published by the Free Software Foundation. |
99 | + * |
100 | + * This program is distributed in the hope that it will be useful, |
101 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
102 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
103 | + * GNU Lesser General Public License for more details. |
104 | + * |
105 | + * You should have received a copy of the GNU Lesser General Public License |
106 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
107 | + * |
108 | + * Authored by: Robert Carr <robert.carr@canonical.com> |
109 | + */ |
110 | + |
111 | +#ifndef MIR_CLIENT_NULL_INPUT_RECEIVER_REPORT_H_ |
112 | +#define MIR_CLIENT_NULL_INPUT_RECEIVER_REPORT_H_ |
113 | + |
114 | +#include "mir/input/input_receiver_report.h" |
115 | + |
116 | +#include <mir_toolkit/event.h> |
117 | + |
118 | +namespace mir |
119 | +{ |
120 | +namespace input |
121 | +{ |
122 | +namespace receiver |
123 | +{ |
124 | + |
125 | +class NullInputReceiverReport : public InputReceiverReport |
126 | +{ |
127 | +public: |
128 | + NullInputReceiverReport() = default; |
129 | + virtual ~NullInputReceiverReport() = default; |
130 | + |
131 | + void received_event(MirEvent const& /* event */) {} |
132 | +}; |
133 | + |
134 | +} |
135 | +} |
136 | +} |
137 | + |
138 | +#endif /* MIR_CLIENT_NULL_INPUT_RECEIVER_REPORT_H_ */ |
139 | |
140 | === modified file 'include/test/mir_test_framework/input_testing_server_configuration.h' |
141 | --- include/test/mir_test_framework/input_testing_server_configuration.h 2013-08-28 03:41:48 +0000 |
142 | +++ include/test/mir_test_framework/input_testing_server_configuration.h 2013-11-07 00:22:14 +0000 |
143 | @@ -65,9 +65,10 @@ |
144 | std::shared_ptr<mir::input::InputConfiguration> the_input_configuration() override; |
145 | std::shared_ptr<mir::frontend::Shell> the_frontend_shell() override; |
146 | |
147 | + mir::input::android::FakeEventHub* fake_event_hub; |
148 | + |
149 | protected: |
150 | virtual void inject_input() = 0; |
151 | - mir::input::android::FakeEventHub* fake_event_hub; |
152 | |
153 | void wait_until_client_appears(std::string const& surface_name); |
154 | |
155 | |
156 | === modified file 'src/client/CMakeLists.txt' |
157 | --- src/client/CMakeLists.txt 2013-10-21 16:02:28 +0000 |
158 | +++ src/client/CMakeLists.txt 2013-11-07 00:22:14 +0000 |
159 | @@ -29,6 +29,7 @@ |
160 | mir_wait_handle.cpp |
161 | mir_surface.cpp |
162 | logging/rpc_report.cpp |
163 | + logging/input_receiver_report.cpp |
164 | default_connection_configuration.cpp |
165 | surface_map.cpp |
166 | lifecycle_control.cpp |
167 | |
168 | === modified file 'src/client/default_connection_configuration.cpp' |
169 | --- src/client/default_connection_configuration.cpp 2013-08-28 03:41:48 +0000 |
170 | +++ src/client/default_connection_configuration.cpp 2013-11-07 00:22:14 +0000 |
171 | @@ -24,7 +24,9 @@ |
172 | #include "mir/logging/dumb_console_logger.h" |
173 | #include "native_client_platform_factory.h" |
174 | #include "mir/input/input_platform.h" |
175 | +#include "mir/input/null_input_receiver_report.h" |
176 | #include "logging/rpc_report.h" |
177 | +#include "logging/input_receiver_report.h" |
178 | #include "lttng/rpc_report.h" |
179 | #include "connection_surface_map.h" |
180 | #include "lifecycle_control.h" |
181 | @@ -88,9 +90,9 @@ |
182 | mcl::DefaultConnectionConfiguration::the_input_platform() |
183 | { |
184 | return input_platform( |
185 | - [] |
186 | + [this] |
187 | { |
188 | - return mir::input::receiver::InputPlatform::create(); |
189 | + return mir::input::receiver::InputPlatform::create(the_input_receiver_report()); |
190 | }); |
191 | } |
192 | |
193 | @@ -118,6 +120,22 @@ |
194 | }); |
195 | } |
196 | |
197 | +std::shared_ptr<mir::input::receiver::InputReceiverReport> |
198 | +mcl::DefaultConnectionConfiguration::the_input_receiver_report() |
199 | +{ |
200 | + return input_receiver_report( |
201 | + [this] () -> std::shared_ptr<mir::input::receiver::InputReceiverReport> |
202 | + { |
203 | + auto val_raw = getenv("MIR_CLIENT_INPUT_RECEIVER_REPORT"); |
204 | + std::string const val{val_raw ? val_raw : off_opt_val}; |
205 | + |
206 | + if (val == log_opt_val) |
207 | + return std::make_shared<mcl::logging::InputReceiverReport>(the_logger()); |
208 | + else |
209 | + return std::make_shared<mir::input::receiver::NullInputReceiverReport>(); |
210 | + }); |
211 | +} |
212 | + |
213 | std::shared_ptr<mcl::DisplayConfiguration> mcl::DefaultConnectionConfiguration::the_display_configuration() |
214 | { |
215 | return display_configuration( |
216 | |
217 | === modified file 'src/client/default_connection_configuration.h' |
218 | --- src/client/default_connection_configuration.h 2013-08-28 03:41:48 +0000 |
219 | +++ src/client/default_connection_configuration.h 2013-11-07 00:22:14 +0000 |
220 | @@ -27,6 +27,13 @@ |
221 | |
222 | namespace mir |
223 | { |
224 | +namespace input |
225 | +{ |
226 | +namespace receiver |
227 | +{ |
228 | +class InputReceiverReport; |
229 | +} |
230 | +} |
231 | namespace client |
232 | { |
233 | |
234 | @@ -50,6 +57,7 @@ |
235 | |
236 | virtual std::string the_socket_file(); |
237 | virtual std::shared_ptr<rpc::RpcReport> the_rpc_report(); |
238 | + virtual std::shared_ptr<input::receiver::InputReceiverReport> the_input_receiver_report(); |
239 | |
240 | protected: |
241 | CachedPtr<rpc::MirBasicRpcChannel> rpc_channel; |
242 | @@ -61,6 +69,7 @@ |
243 | CachedPtr<LifecycleControl> lifecycle_control; |
244 | |
245 | CachedPtr<rpc::RpcReport> rpc_report; |
246 | + CachedPtr<input::receiver::InputReceiverReport> input_receiver_report; |
247 | |
248 | private: |
249 | std::string const socket_file; |
250 | |
251 | === added file 'src/client/logging/input_receiver_report.cpp' |
252 | --- src/client/logging/input_receiver_report.cpp 1970-01-01 00:00:00 +0000 |
253 | +++ src/client/logging/input_receiver_report.cpp 2013-11-07 00:22:14 +0000 |
254 | @@ -0,0 +1,125 @@ |
255 | +/* |
256 | + * Copyright © 2013 Canonical Ltd. |
257 | + * |
258 | + * This program is free software: you can redistribute it and/or modify |
259 | + * it under the terms of the GNU Lesser General Public License version 3 as |
260 | + * published by the Free Software Foundation. |
261 | + * |
262 | + * This program is distributed in the hope that it will be useful, |
263 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
264 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
265 | + * GNU Lesser General Public License for more details. |
266 | + * |
267 | + * You should have received a copy of the GNU Lesser General Public License |
268 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
269 | + * |
270 | + * Authored by: Robert Carr <robert.carr@canonical.com> |
271 | + */ |
272 | + |
273 | +#include "input_receiver_report.h" |
274 | + |
275 | +#include "mir/logging/logger.h" |
276 | + |
277 | +#include <boost/throw_exception.hpp> |
278 | + |
279 | +#include <sstream> |
280 | +#include <stdexcept> |
281 | + |
282 | +namespace ml = mir::logging; |
283 | +namespace mcll = mir::client::logging; |
284 | + |
285 | +namespace |
286 | +{ |
287 | +std::string const component{"input-receiver"}; |
288 | +} |
289 | + |
290 | +mcll::InputReceiverReport::InputReceiverReport(std::shared_ptr<ml::Logger> const& logger) |
291 | + : logger{logger} |
292 | +{ |
293 | +} |
294 | + |
295 | +namespace |
296 | +{ |
297 | + |
298 | +static void format_key_event(std::stringstream &ss, MirKeyEvent const& ev) |
299 | +{ |
300 | + ss << "MirKeyEvent {" << std::endl; |
301 | + ss << " device_id: " << ev.device_id << std::endl; |
302 | + ss << " source_id: " << ev.source_id << std::endl; |
303 | + ss << " action: " << ev.action << std::endl; |
304 | + ss << " flags: " << ev.flags << std::endl; |
305 | + ss << " modifiers: " << ev.modifiers << std::endl; |
306 | + ss << " key_code: " << ev.key_code << std::endl; |
307 | + ss << " scan_code: " << ev.scan_code << std::endl; |
308 | + ss << " repeat_count: " << ev.repeat_count << std::endl; |
309 | + ss << " down_time: " << ev.down_time << std::endl; |
310 | + ss << " event_time: " << ev.event_time << std::endl; |
311 | + ss << " is_system_key: " << ev.is_system_key << std::endl; |
312 | + ss << "}"; |
313 | +} |
314 | +static void format_motion_event(std::stringstream &ss, MirMotionEvent const& ev) |
315 | +{ |
316 | + ss << "MirMotionEvent{" << std::endl; |
317 | + ss << " type: motion" << std::endl; |
318 | + ss << " device_id: " << ev.device_id << std::endl; |
319 | + ss << " source_id: " << ev.source_id << std::endl; |
320 | + ss << " action: " << ev.action << std::endl; |
321 | + ss << " flags: " << ev.flags << std::endl; |
322 | + ss << " modifiers: " << ev.modifiers << std::endl; |
323 | + ss << " edge_flags: " << ev.edge_flags << std::endl; |
324 | + ss << " button_state: " << ev.button_state << std::endl; |
325 | + ss << " x_offset: " << ev.x_offset << std::endl; |
326 | + ss << " y_offset: " << ev.y_offset << std::endl; |
327 | + ss << " x_precision: " << ev.x_precision << std::endl; |
328 | + ss << " y_precision: " << ev.y_precision << std::endl; |
329 | + ss << " down_time: " << ev.down_time << std::endl; |
330 | + ss << " event_time: " << ev.event_time << std::endl; |
331 | + ss << " pointer_count: " << ev.pointer_count << std::endl; |
332 | + for (unsigned int i = 0; i < ev.pointer_count; i++) |
333 | + { |
334 | + ss << " pointer[" << i << "]{" << std::endl; |
335 | + ss << " id: " << ev.pointer_coordinates[i].id << std::endl; |
336 | + ss << " x: " << ev.pointer_coordinates[i].x << std::endl; |
337 | + ss << " raw_x: " << ev.pointer_coordinates[i].raw_x << std::endl; |
338 | + ss << " y: " << ev.pointer_coordinates[i].y << std::endl; |
339 | + ss << " raw_y: " << ev.pointer_coordinates[i].raw_y << std::endl; |
340 | + ss << " touch_major: " << ev.pointer_coordinates[i].touch_major << std::endl; |
341 | + ss << " touch_minor: " << ev.pointer_coordinates[i].touch_minor << std::endl; |
342 | + ss << " size: " << ev.pointer_coordinates[i].size << std::endl; |
343 | + ss << " pressure: " << ev.pointer_coordinates[i].pressure << std::endl; |
344 | + ss << " orientation: " << ev.pointer_coordinates[i].orientation << std::endl; |
345 | + ss << " vscroll: " << ev.pointer_coordinates[i].vscroll << std::endl; |
346 | + ss << " hscroll: " << ev.pointer_coordinates[i].hscroll << std::endl; |
347 | + ss << " }" << std::endl; |
348 | + } |
349 | + ss << "}"; |
350 | +} |
351 | + |
352 | +static void format_event(std::stringstream &ss, MirEvent const& ev) |
353 | +{ |
354 | + switch (ev.type) |
355 | + { |
356 | + case mir_event_type_key: |
357 | + format_key_event(ss, ev.key); |
358 | + break; |
359 | + case mir_event_type_motion: |
360 | + format_motion_event(ss, ev.motion); |
361 | + break; |
362 | + default: |
363 | + BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected event type")); |
364 | + } |
365 | +} |
366 | + |
367 | +} |
368 | + |
369 | +void mcll::InputReceiverReport::received_event( |
370 | + MirEvent const& event) |
371 | +{ |
372 | + std::stringstream ss; |
373 | + |
374 | + ss << "Received event:" << std::endl; |
375 | + |
376 | + format_event(ss, event); |
377 | + |
378 | + logger->log<ml::Logger::debug>(ss.str(), component); |
379 | +} |
380 | |
381 | === added file 'src/client/logging/input_receiver_report.h' |
382 | --- src/client/logging/input_receiver_report.h 1970-01-01 00:00:00 +0000 |
383 | +++ src/client/logging/input_receiver_report.h 2013-11-07 00:22:14 +0000 |
384 | @@ -0,0 +1,54 @@ |
385 | +/* |
386 | + * Copyright © 2013 Canonical Ltd. |
387 | + * |
388 | + * This program is free software: you can redistribute it and/or modify |
389 | + * it under the terms of the GNU Lesser General Public License version 3 as |
390 | + * published by the Free Software Foundation. |
391 | + * |
392 | + * This program is distributed in the hope that it will be useful, |
393 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
394 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
395 | + * GNU Lesser General Public License for more details. |
396 | + * |
397 | + * You should have received a copy of the GNU Lesser General Public License |
398 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
399 | + * |
400 | + * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com> |
401 | + */ |
402 | + |
403 | +#ifndef MIR_CLIENT_LOGGING_INPUT_RECEIVER_REPORT_H_ |
404 | +#define MIR_CLIENT_LOGGING_INPUT_RECEIVER_REPORT_H_ |
405 | + |
406 | +#include "mir/input/input_receiver_report.h" |
407 | + |
408 | +#include <memory> |
409 | + |
410 | +namespace mir |
411 | +{ |
412 | + |
413 | +namespace logging |
414 | +{ |
415 | +class Logger; |
416 | +} |
417 | + |
418 | +namespace client |
419 | +{ |
420 | +namespace logging |
421 | +{ |
422 | + |
423 | +class InputReceiverReport : public input::receiver::InputReceiverReport |
424 | +{ |
425 | +public: |
426 | + InputReceiverReport(std::shared_ptr<mir::logging::Logger> const& logger); |
427 | + |
428 | + void received_event(MirEvent const& event) override; |
429 | + |
430 | +private: |
431 | + std::shared_ptr<mir::logging::Logger> const logger; |
432 | +}; |
433 | + |
434 | +} |
435 | +} |
436 | +} |
437 | + |
438 | +#endif /* MIR_CLIENT_LOGGING_INPUT_RECEIVER_REPORT_H_ */ |
439 | |
440 | === modified file 'src/shared/input/android/android_input_platform.cpp' |
441 | --- src/shared/input/android/android_input_platform.cpp 2013-05-13 23:20:52 +0000 |
442 | +++ src/shared/input/android/android_input_platform.cpp 2013-11-07 00:22:14 +0000 |
443 | @@ -20,10 +20,13 @@ |
444 | #include "android_input_receiver.h" |
445 | #include "android_input_receiver_thread.h" |
446 | |
447 | +#include "mir/input/null_input_receiver_report.h" |
448 | + |
449 | namespace mircv = mir::input::receiver; |
450 | namespace mircva = mircv::android; |
451 | |
452 | -mircva::AndroidInputPlatform::AndroidInputPlatform() |
453 | +mircva::AndroidInputPlatform::AndroidInputPlatform(std::shared_ptr<mircv::InputReceiverReport> const& report) |
454 | + : report(report) |
455 | { |
456 | } |
457 | |
458 | @@ -34,11 +37,16 @@ |
459 | std::shared_ptr<mircv::InputReceiverThread> mircva::AndroidInputPlatform::create_input_thread( |
460 | int fd, std::function<void(MirEvent*)> const& callback) |
461 | { |
462 | - auto receiver = std::make_shared<mircva::InputReceiver>(fd); |
463 | + auto receiver = std::make_shared<mircva::InputReceiver>(fd, report); |
464 | return std::make_shared<mircva::InputReceiverThread>(receiver, callback); |
465 | } |
466 | |
467 | std::shared_ptr<mircv::InputPlatform> mircv::InputPlatform::create() |
468 | { |
469 | - return std::make_shared<mircva::AndroidInputPlatform>(); |
470 | + return create(std::make_shared<mircv::NullInputReceiverReport>()); |
471 | +} |
472 | + |
473 | +std::shared_ptr<mircv::InputPlatform> mircv::InputPlatform::create(std::shared_ptr<mircv::InputReceiverReport> const& report) |
474 | +{ |
475 | + return std::make_shared<mircva::AndroidInputPlatform>(report); |
476 | } |
477 | |
478 | === modified file 'src/shared/input/android/android_input_platform.h' |
479 | --- src/shared/input/android/android_input_platform.h 2013-05-13 23:20:52 +0000 |
480 | +++ src/shared/input/android/android_input_platform.h 2013-11-07 00:22:14 +0000 |
481 | @@ -34,7 +34,7 @@ |
482 | class AndroidInputPlatform : public InputPlatform |
483 | { |
484 | public: |
485 | - AndroidInputPlatform(); |
486 | + AndroidInputPlatform(std::shared_ptr<InputReceiverReport> const& report); |
487 | virtual ~AndroidInputPlatform(); |
488 | |
489 | std::shared_ptr<InputReceiverThread> create_input_thread(int fd, std::function<void(MirEvent *)> const& callback); |
490 | @@ -42,6 +42,9 @@ |
491 | protected: |
492 | AndroidInputPlatform(const AndroidInputPlatform&) = delete; |
493 | AndroidInputPlatform& operator=(const AndroidInputPlatform&) = delete; |
494 | + |
495 | +private: |
496 | + std::shared_ptr<InputReceiverReport> const report; |
497 | }; |
498 | |
499 | } |
500 | |
501 | === modified file 'src/shared/input/android/android_input_receiver.cpp' |
502 | --- src/shared/input/android/android_input_receiver.cpp 2013-05-24 18:20:37 +0000 |
503 | +++ src/shared/input/android/android_input_receiver.cpp 2013-11-07 00:22:14 +0000 |
504 | @@ -19,6 +19,7 @@ |
505 | #include "android_input_receiver.h" |
506 | |
507 | #include "mir/input/xkb_mapper.h" |
508 | +#include "mir/input/input_receiver_report.h" |
509 | #include "mir/input/android/android_input_lexicon.h" |
510 | |
511 | #include <androidfw/InputTransport.h> |
512 | @@ -29,8 +30,10 @@ |
513 | |
514 | namespace mia = mir::input::android; |
515 | |
516 | -mircva::InputReceiver::InputReceiver(droidinput::sp<droidinput::InputChannel> const& input_channel) |
517 | +mircva::InputReceiver::InputReceiver(droidinput::sp<droidinput::InputChannel> const& input_channel, |
518 | + std::shared_ptr<mircv::InputReceiverReport> const& report) |
519 | : input_channel(input_channel), |
520 | + report(report), |
521 | input_consumer(std::make_shared<droidinput::InputConsumer>(input_channel)), |
522 | looper(new droidinput::Looper(true)), |
523 | fd_added(false), |
524 | @@ -38,8 +41,10 @@ |
525 | { |
526 | } |
527 | |
528 | -mircva::InputReceiver::InputReceiver(int fd) |
529 | +mircva::InputReceiver::InputReceiver(int fd, |
530 | + std::shared_ptr<mircv::InputReceiverReport> const& report) |
531 | : input_channel(new droidinput::InputChannel(droidinput::String8(""), fd)), |
532 | + report(report), |
533 | input_consumer(std::make_shared<droidinput::InputConsumer>(input_channel)), |
534 | looper(new droidinput::Looper(true)), |
535 | fd_added(false), |
536 | @@ -84,6 +89,8 @@ |
537 | map_key_event(xkb_mapper, ev); |
538 | |
539 | input_consumer->sendFinishedSignal(event_sequence_id, true); |
540 | + |
541 | + report->received_event(ev); |
542 | |
543 | return true; |
544 | } |
545 | |
546 | === modified file 'src/shared/input/android/android_input_receiver.h' |
547 | --- src/shared/input/android/android_input_receiver.h 2013-05-24 18:20:37 +0000 |
548 | +++ src/shared/input/android/android_input_receiver.h 2013-11-07 00:22:14 +0000 |
549 | @@ -43,6 +43,7 @@ |
550 | namespace receiver |
551 | { |
552 | class XKBMapper; |
553 | +class InputReceiverReport; |
554 | |
555 | namespace android |
556 | { |
557 | @@ -51,8 +52,10 @@ |
558 | class InputReceiver |
559 | { |
560 | public: |
561 | - InputReceiver(droidinput::sp<droidinput::InputChannel> const& input_channel); |
562 | - InputReceiver(int fd); |
563 | + InputReceiver(droidinput::sp<droidinput::InputChannel> const& input_channel, |
564 | + std::shared_ptr<InputReceiverReport> const& report); |
565 | + InputReceiver(int fd, |
566 | + std::shared_ptr<InputReceiverReport> const& report); |
567 | |
568 | virtual ~InputReceiver(); |
569 | int fd() const; |
570 | @@ -71,6 +74,8 @@ |
571 | |
572 | private: |
573 | droidinput::sp<droidinput::InputChannel> input_channel; |
574 | + std::shared_ptr<InputReceiverReport> const report; |
575 | + |
576 | std::shared_ptr<droidinput::InputConsumer> input_consumer; |
577 | droidinput::PreallocatedInputEventFactory event_factory; |
578 | droidinput::sp<droidinput::Looper> looper; |
579 | |
580 | === modified file 'tests/acceptance-tests/test_client_input.cpp' |
581 | --- tests/acceptance-tests/test_client_input.cpp 2013-10-28 21:41:27 +0000 |
582 | +++ tests/acceptance-tests/test_client_input.cpp 2013-11-07 00:22:14 +0000 |
583 | @@ -248,6 +248,16 @@ |
584 | return true; |
585 | } |
586 | |
587 | +MATCHER(HoverMoveEvent, "") |
588 | +{ |
589 | + if (arg->type != mir_event_type_motion) |
590 | + return false; |
591 | + if (arg->motion.action != mir_motion_action_hover_move) |
592 | + return false; |
593 | + |
594 | + return true; |
595 | +} |
596 | + |
597 | MATCHER_P2(ButtonDownEvent, x, y, "") |
598 | { |
599 | if (arg->type != mir_event_type_motion) |
600 | @@ -302,194 +312,6 @@ |
601 | |
602 | } |
603 | |
604 | - |
605 | -using TestClientInput = BespokeDisplayServerTestFixture; |
606 | - |
607 | -TEST_F(TestClientInput, clients_receive_key_input) |
608 | -{ |
609 | - using namespace ::testing; |
610 | - |
611 | - int const num_events_produced = 3; |
612 | - static std::string const test_client_name = "1"; |
613 | - |
614 | - mtf::CrossProcessSync fence; |
615 | - |
616 | - struct ServerConfiguration : mtf::InputTestingServerConfiguration |
617 | - { |
618 | - mtf::CrossProcessSync input_cb_setup_fence; |
619 | - |
620 | - ServerConfiguration(const mtf::CrossProcessSync& input_cb_setup_fence) |
621 | - : input_cb_setup_fence(input_cb_setup_fence) |
622 | - { |
623 | - } |
624 | - |
625 | - void inject_input() |
626 | - { |
627 | - wait_until_client_appears(test_client_name); |
628 | - input_cb_setup_fence.wait_for_signal_ready_for(); |
629 | - |
630 | - for (int i = 0; i < num_events_produced; i++) |
631 | - fake_event_hub->synthesize_event(mis::a_key_down_event() |
632 | - .of_scancode(KEY_ENTER)); |
633 | - } |
634 | - } server_config(fence); |
635 | - launch_server_process(server_config); |
636 | - |
637 | - struct KeyReceivingClient : InputClient |
638 | - { |
639 | - KeyReceivingClient(const mtf::CrossProcessSync& fence) : InputClient(fence, test_client_name) {} |
640 | - void expect_input(mt::WaitCondition& events_received) override |
641 | - { |
642 | - using namespace ::testing; |
643 | - InSequence seq; |
644 | - |
645 | - EXPECT_CALL(*handler, handle_input(KeyDownEvent())).Times(2); |
646 | - EXPECT_CALL(*handler, handle_input(KeyDownEvent())).Times(1) |
647 | - .WillOnce(mt::WakeUp(&events_received)); |
648 | - } |
649 | - } client_config(fence); |
650 | - launch_client_process(client_config); |
651 | -} |
652 | - |
653 | -TEST_F(TestClientInput, clients_receive_us_english_mapped_keys) |
654 | -{ |
655 | - using namespace ::testing; |
656 | - static std::string const test_client_name = "1"; |
657 | - mtf::CrossProcessSync fence; |
658 | - |
659 | - struct ServerConfiguration : mtf::InputTestingServerConfiguration |
660 | - { |
661 | - mtf::CrossProcessSync input_cb_setup_fence; |
662 | - |
663 | - ServerConfiguration(const mtf::CrossProcessSync& input_cb_setup_fence) |
664 | - : input_cb_setup_fence(input_cb_setup_fence) |
665 | - { |
666 | - } |
667 | - |
668 | - void inject_input() |
669 | - { |
670 | - wait_until_client_appears(test_client_name); |
671 | - input_cb_setup_fence.wait_for_signal_ready_for(); |
672 | - |
673 | - fake_event_hub->synthesize_event(mis::a_key_down_event() |
674 | - .of_scancode(KEY_LEFTSHIFT)); |
675 | - fake_event_hub->synthesize_event(mis::a_key_down_event() |
676 | - .of_scancode(KEY_4)); |
677 | - |
678 | - } |
679 | - } server_config{fence}; |
680 | - launch_server_process(server_config); |
681 | - |
682 | - struct KeyReceivingClient : InputClient |
683 | - { |
684 | - KeyReceivingClient(const mtf::CrossProcessSync& fence) : InputClient(fence, test_client_name) {} |
685 | - |
686 | - void expect_input(mt::WaitCondition& events_received) override |
687 | - { |
688 | - using namespace ::testing; |
689 | - |
690 | - InSequence seq; |
691 | - EXPECT_CALL(*handler, handle_input(AllOf(KeyDownEvent(), KeyOfSymbol(XKB_KEY_Shift_L)))).Times(1); |
692 | - EXPECT_CALL(*handler, handle_input(AllOf(KeyDownEvent(), KeyOfSymbol(XKB_KEY_dollar)))).Times(1) |
693 | - .WillOnce(mt::WakeUp(&events_received)); |
694 | - } |
695 | - } client_config{fence}; |
696 | - launch_client_process(client_config); |
697 | -} |
698 | - |
699 | -TEST_F(TestClientInput, clients_receive_motion_inside_window) |
700 | -{ |
701 | - using namespace ::testing; |
702 | - static std::string const test_client_name = "1"; |
703 | - mtf::CrossProcessSync fence; |
704 | - |
705 | - struct ServerConfiguration : public mtf::InputTestingServerConfiguration |
706 | - { |
707 | - mtf::CrossProcessSync input_cb_setup_fence; |
708 | - |
709 | - ServerConfiguration(const mtf::CrossProcessSync& input_cb_setup_fence) |
710 | - : input_cb_setup_fence(input_cb_setup_fence) |
711 | - { |
712 | - } |
713 | - |
714 | - void inject_input() |
715 | - { |
716 | - wait_until_client_appears(test_client_name); |
717 | - input_cb_setup_fence.wait_for_signal_ready_for(); |
718 | - |
719 | - fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(InputClient::surface_width - 1, |
720 | - InputClient::surface_height - 1)); |
721 | - fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(2,2)); |
722 | - } |
723 | - } server_config{fence}; |
724 | - launch_server_process(server_config); |
725 | - |
726 | - struct MotionReceivingClient : InputClient |
727 | - { |
728 | - MotionReceivingClient(const mtf::CrossProcessSync& fence) : InputClient(fence, test_client_name) {} |
729 | - |
730 | - void expect_input(mt::WaitCondition& events_received) override |
731 | - { |
732 | - using namespace ::testing; |
733 | - |
734 | - InSequence seq; |
735 | - |
736 | - // We should see the cursor enter |
737 | - EXPECT_CALL(*handler, handle_input(HoverEnterEvent())).Times(1); |
738 | - EXPECT_CALL(*handler, handle_input( |
739 | - MotionEventWithPosition(InputClient::surface_width - 1, |
740 | - InputClient::surface_height - 1))).Times(1) |
741 | - .WillOnce(mt::WakeUp(&events_received)); |
742 | - // But we should not receive an event for the second movement outside of our surface! |
743 | - } |
744 | - } client_config{fence}; |
745 | - launch_client_process(client_config); |
746 | -} |
747 | - |
748 | -TEST_F(TestClientInput, clients_receive_button_events_inside_window) |
749 | -{ |
750 | - using namespace ::testing; |
751 | - |
752 | - static std::string const test_client_name = "1"; |
753 | - mtf::CrossProcessSync fence; |
754 | - |
755 | - struct ServerConfiguration : public mtf::InputTestingServerConfiguration |
756 | - { |
757 | - mtf::CrossProcessSync input_cb_setup_fence; |
758 | - |
759 | - ServerConfiguration(const mtf::CrossProcessSync& input_cb_setup_fence) |
760 | - : input_cb_setup_fence(input_cb_setup_fence) |
761 | - { |
762 | - } |
763 | - |
764 | - void inject_input() |
765 | - { |
766 | - wait_until_client_appears(test_client_name); |
767 | - input_cb_setup_fence.wait_for_signal_ready_for(); |
768 | - |
769 | - fake_event_hub->synthesize_event(mis::a_button_down_event().of_button(BTN_LEFT).with_action(mis::EventAction::Down)); |
770 | - } |
771 | - } server_config{fence}; |
772 | - launch_server_process(server_config); |
773 | - |
774 | - struct ButtonReceivingClient : InputClient |
775 | - { |
776 | - ButtonReceivingClient(const mtf::CrossProcessSync& fence) : InputClient(fence, test_client_name) {} |
777 | - |
778 | - void expect_input(mt::WaitCondition& events_received) override |
779 | - { |
780 | - using namespace ::testing; |
781 | - |
782 | - InSequence seq; |
783 | - |
784 | - // The cursor starts at (0, 0). |
785 | - EXPECT_CALL(*handler, handle_input(ButtonDownEvent(0, 0))).Times(1) |
786 | - .WillOnce(mt::WakeUp(&events_received)); |
787 | - } |
788 | - } client_config{fence}; |
789 | - launch_client_process(client_config); |
790 | -} |
791 | - |
792 | namespace |
793 | { |
794 | typedef std::map<std::string, geom::Rectangle> GeometryMap; |
795 | @@ -497,34 +319,251 @@ |
796 | |
797 | struct StaticPlacementStrategy : public msh::PlacementStrategy |
798 | { |
799 | - StaticPlacementStrategy(GeometryMap const& positions, |
800 | + StaticPlacementStrategy(std::shared_ptr<msh::PlacementStrategy> const& underlying_strategy, |
801 | + GeometryMap const& positions, |
802 | DepthMap const& depths) |
803 | - : surface_geometry_by_name(positions), |
804 | + : underlying_strategy(underlying_strategy), |
805 | + surface_geometry_by_name(positions), |
806 | surface_depths_by_name(depths) |
807 | { |
808 | } |
809 | |
810 | - StaticPlacementStrategy(GeometryMap const& positions) |
811 | - : StaticPlacementStrategy(positions, DepthMap()) |
812 | + StaticPlacementStrategy(std::shared_ptr<msh::PlacementStrategy> const& underlying_strategy, |
813 | + GeometryMap const& positions) |
814 | + : StaticPlacementStrategy(underlying_strategy, positions, DepthMap()) |
815 | { |
816 | } |
817 | |
818 | - msh::SurfaceCreationParameters place(msh::Session const&, msh::SurfaceCreationParameters const& request_parameters) |
819 | + msh::SurfaceCreationParameters place(msh::Session const& session, msh::SurfaceCreationParameters const& request_parameters) |
820 | { |
821 | auto placed = request_parameters; |
822 | auto const& name = request_parameters.name; |
823 | - auto geometry = surface_geometry_by_name[name]; |
824 | - |
825 | - placed.top_left = geometry.top_left; |
826 | - placed.size = geometry.size; |
827 | + |
828 | + auto it = surface_geometry_by_name.find(name); |
829 | + if (it != surface_geometry_by_name.end()) |
830 | + { |
831 | + auto const& geometry = it->second; |
832 | + placed.top_left = geometry.top_left; |
833 | + placed.size = geometry.size; |
834 | + } |
835 | + else |
836 | + { |
837 | + placed = underlying_strategy->place(session, placed); |
838 | + } |
839 | placed.depth = surface_depths_by_name[name]; |
840 | |
841 | return placed; |
842 | } |
843 | + |
844 | + std::shared_ptr<msh::PlacementStrategy> const underlying_strategy; |
845 | GeometryMap surface_geometry_by_name; |
846 | DepthMap surface_depths_by_name; |
847 | }; |
848 | |
849 | +std::shared_ptr<mtf::InputTestingServerConfiguration> |
850 | +make_event_producing_server(mtf::CrossProcessSync const& client_ready_fence, |
851 | + int number_of_clients, |
852 | + std::function<void(mtf::InputTestingServerConfiguration& server)> const& produce_events, |
853 | + GeometryMap const& client_geometry_map, DepthMap const& client_depth_map) |
854 | +{ |
855 | + struct ServerConfiguration : mtf::InputTestingServerConfiguration |
856 | + { |
857 | + mtf::CrossProcessSync input_cb_setup_fence; |
858 | + int const number_of_clients; |
859 | + std::function<void(mtf::InputTestingServerConfiguration& server)> const produce_events; |
860 | + GeometryMap const client_geometry; |
861 | + DepthMap const client_depth; |
862 | + |
863 | + ServerConfiguration(mtf::CrossProcessSync const& input_cb_setup_fence, int number_of_clients, |
864 | + std::function<void(mtf::InputTestingServerConfiguration& server)> const& produce_events, |
865 | + GeometryMap const& client_geometry, DepthMap const& client_depth) |
866 | + : input_cb_setup_fence(input_cb_setup_fence), |
867 | + number_of_clients(number_of_clients), |
868 | + produce_events(produce_events), |
869 | + client_geometry(client_geometry), |
870 | + client_depth(client_depth) |
871 | + { |
872 | + } |
873 | + |
874 | + std::shared_ptr<msh::PlacementStrategy> the_shell_placement_strategy() override |
875 | + { |
876 | + return std::make_shared<StaticPlacementStrategy>(InputTestingServerConfiguration::the_shell_placement_strategy(), |
877 | + client_geometry, client_depth); |
878 | + } |
879 | + |
880 | + void inject_input() |
881 | + { |
882 | + for (int i = 1; i < number_of_clients + 1; i++) |
883 | + EXPECT_EQ(i, input_cb_setup_fence.wait_for_signal_ready_for()); |
884 | + produce_events(*this); |
885 | + } |
886 | + }; |
887 | + return std::make_shared<ServerConfiguration>(client_ready_fence, number_of_clients, |
888 | + produce_events, client_geometry_map, client_depth_map); |
889 | +} |
890 | + |
891 | +std::shared_ptr<mtf::InputTestingServerConfiguration> |
892 | +make_event_producing_server(mtf::CrossProcessSync const& client_ready_fence, int number_of_clients, |
893 | + std::function<void(mtf::InputTestingServerConfiguration& server)> const& produce_events) |
894 | +{ |
895 | + return make_event_producing_server(client_ready_fence, number_of_clients, |
896 | + produce_events, GeometryMap(), DepthMap()); |
897 | +} |
898 | + |
899 | +std::shared_ptr<InputClient> |
900 | +make_event_expecting_client(std::string const& client_name, mtf::CrossProcessSync const& client_ready_fence, |
901 | + std::function<void(MockInputHandler &, mt::WaitCondition&)> const& expect_input) |
902 | +{ |
903 | + struct EventReceivingClient : InputClient |
904 | + { |
905 | + std::function<void(MockInputHandler&, mt::WaitCondition&)> const expect_cb; |
906 | + |
907 | + EventReceivingClient(mtf::CrossProcessSync const& client_ready_fence, std::string const& client_name, |
908 | + std::function<void(MockInputHandler&, mt::WaitCondition&)> const& expect_cb) |
909 | + : InputClient(client_ready_fence, client_name), |
910 | + expect_cb(expect_cb) |
911 | + { |
912 | + } |
913 | + void expect_input(mt::WaitCondition& events_received) override |
914 | + { |
915 | + expect_cb(*handler, events_received); |
916 | + } |
917 | + }; |
918 | + return std::make_shared<EventReceivingClient>(client_ready_fence, client_name, expect_input); |
919 | +} |
920 | + |
921 | +std::shared_ptr<InputClient> |
922 | +make_event_expecting_client(mtf::CrossProcessSync const& client_ready_fence, |
923 | + std::function<void(MockInputHandler &, mt::WaitCondition&)> const& expect_input) |
924 | +{ |
925 | + return make_event_expecting_client("input-test-client", client_ready_fence, expect_input); |
926 | +} |
927 | + |
928 | +} |
929 | + |
930 | + |
931 | +using TestClientInput = BespokeDisplayServerTestFixture; |
932 | + |
933 | +TEST_F(TestClientInput, clients_receive_key_input) |
934 | +{ |
935 | + using namespace ::testing; |
936 | + |
937 | + static std::string const test_client_name = "1"; |
938 | + |
939 | + mtf::CrossProcessSync fence; |
940 | + |
941 | + auto server_config = make_event_producing_server(fence, 1, |
942 | + [&](mtf::InputTestingServerConfiguration& server) |
943 | + { |
944 | + int const num_events_produced = 3; |
945 | + |
946 | + for (int i = 0; i < num_events_produced; i++) |
947 | + server.fake_event_hub->synthesize_event(mis::a_key_down_event() |
948 | + .of_scancode(KEY_ENTER)); |
949 | + }); |
950 | + launch_server_process(*server_config); |
951 | + |
952 | + auto client_config = make_event_expecting_client(fence, |
953 | + [&](MockInputHandler& handler, mt::WaitCondition& events_received) |
954 | + { |
955 | + using namespace ::testing; |
956 | + InSequence seq; |
957 | + |
958 | + EXPECT_CALL(handler, handle_input(KeyDownEvent())).Times(2); |
959 | + EXPECT_CALL(handler, handle_input(KeyDownEvent())).Times(1) |
960 | + .WillOnce(mt::WakeUp(&events_received)); |
961 | + |
962 | + }); |
963 | + launch_client_process(*client_config); |
964 | +} |
965 | + |
966 | +TEST_F(TestClientInput, clients_receive_us_english_mapped_keys) |
967 | +{ |
968 | + using namespace ::testing; |
969 | + static std::string const test_client_name = "1"; |
970 | + mtf::CrossProcessSync fence; |
971 | + |
972 | + auto server_config = make_event_producing_server(fence, 1, |
973 | + [&](mtf::InputTestingServerConfiguration& server) |
974 | + { |
975 | + server.fake_event_hub->synthesize_event(mis::a_key_down_event() |
976 | + .of_scancode(KEY_LEFTSHIFT)); |
977 | + server.fake_event_hub->synthesize_event(mis::a_key_down_event() |
978 | + .of_scancode(KEY_4)); |
979 | + }); |
980 | + launch_server_process(*server_config); |
981 | + |
982 | + auto client_config = make_event_expecting_client(fence, |
983 | + [&](MockInputHandler& handler, mt::WaitCondition& events_received) |
984 | + { |
985 | + using namespace ::testing; |
986 | + InSequence seq; |
987 | + |
988 | + EXPECT_CALL(handler, handle_input(AllOf(KeyDownEvent(), KeyOfSymbol(XKB_KEY_Shift_L)))).Times(1); |
989 | + EXPECT_CALL(handler, handle_input(AllOf(KeyDownEvent(), KeyOfSymbol(XKB_KEY_dollar)))).Times(1) |
990 | + .WillOnce(mt::WakeUp(&events_received)); |
991 | + }); |
992 | + launch_client_process(*client_config); |
993 | +} |
994 | + |
995 | +TEST_F(TestClientInput, clients_receive_motion_inside_window) |
996 | +{ |
997 | + using namespace ::testing; |
998 | + static std::string const test_client_name = "1"; |
999 | + mtf::CrossProcessSync fence; |
1000 | + |
1001 | + auto server_config = make_event_producing_server(fence, 1, |
1002 | + [&](mtf::InputTestingServerConfiguration& server) |
1003 | + { |
1004 | + server.fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(InputClient::surface_width - 1, |
1005 | + InputClient::surface_height - 1)); |
1006 | + server.fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(2,2)); |
1007 | + }); |
1008 | + launch_server_process(*server_config); |
1009 | + |
1010 | + auto client_config = make_event_expecting_client(fence, |
1011 | + [&](MockInputHandler& handler, mt::WaitCondition& events_received) |
1012 | + { |
1013 | + using namespace ::testing; |
1014 | + InSequence seq; |
1015 | + |
1016 | + // We should see the cursor enter |
1017 | + EXPECT_CALL(handler, handle_input(HoverEnterEvent())).Times(1); |
1018 | + EXPECT_CALL(handler, handle_input( |
1019 | + MotionEventWithPosition(InputClient::surface_width - 1, |
1020 | + InputClient::surface_height - 1))).Times(1) |
1021 | + .WillOnce(mt::WakeUp(&events_received)); |
1022 | + // But we should not receive an event for the second movement outside of our surface! |
1023 | + }); |
1024 | + launch_client_process(*client_config); |
1025 | +} |
1026 | + |
1027 | +TEST_F(TestClientInput, clients_receive_button_events_inside_window) |
1028 | +{ |
1029 | + using namespace ::testing; |
1030 | + |
1031 | + static std::string const test_client_name = "1"; |
1032 | + mtf::CrossProcessSync fence; |
1033 | + |
1034 | + auto server_config = make_event_producing_server(fence, 1, |
1035 | + [&](mtf::InputTestingServerConfiguration& server) |
1036 | + { |
1037 | + server.fake_event_hub->synthesize_event(mis::a_button_down_event() |
1038 | + .of_button(BTN_LEFT).with_action(mis::EventAction::Down)); |
1039 | + }); |
1040 | + launch_server_process(*server_config); |
1041 | + |
1042 | + auto client_config = make_event_expecting_client(fence, |
1043 | + [&](MockInputHandler& handler, mt::WaitCondition& events_received) |
1044 | + { |
1045 | + using namespace ::testing; |
1046 | + InSequence seq; |
1047 | + |
1048 | + // The cursor starts at (0, 0). |
1049 | + EXPECT_CALL(handler, handle_input(ButtonDownEvent(0, 0))).Times(1) |
1050 | + .WillOnce(mt::WakeUp(&events_received)); |
1051 | + }); |
1052 | + launch_client_process(*client_config); |
1053 | } |
1054 | |
1055 | TEST_F(TestClientInput, multiple_clients_receive_motion_inside_windows) |
1056 | @@ -539,77 +578,42 @@ |
1057 | static std::string const test_client_2 = "2"; |
1058 | mtf::CrossProcessSync fence; |
1059 | |
1060 | - struct ServerConfiguration : mtf::InputTestingServerConfiguration |
1061 | - { |
1062 | - mtf::CrossProcessSync input_cb_setup_fence; |
1063 | - |
1064 | - ServerConfiguration(const mtf::CrossProcessSync& input_cb_setup_fence) |
1065 | - : input_cb_setup_fence(input_cb_setup_fence) |
1066 | - { |
1067 | - } |
1068 | - |
1069 | - std::shared_ptr<msh::PlacementStrategy> the_shell_placement_strategy() override |
1070 | - { |
1071 | - static GeometryMap positions; |
1072 | - positions[test_client_1] = geom::Rectangle{geom::Point{0, 0}, |
1073 | - geom::Size{client_width, client_height}}; |
1074 | - positions[test_client_2] = geom::Rectangle{geom::Point{screen_width/2, screen_height/2}, |
1075 | - geom::Size{client_width, client_height}}; |
1076 | - |
1077 | - return std::make_shared<StaticPlacementStrategy>(positions); |
1078 | - } |
1079 | - |
1080 | - void inject_input() override |
1081 | - { |
1082 | - wait_until_client_appears(test_client_1); |
1083 | - EXPECT_EQ(1, input_cb_setup_fence.wait_for_signal_ready_for()); |
1084 | - wait_until_client_appears(test_client_2); |
1085 | - EXPECT_EQ(2, input_cb_setup_fence.wait_for_signal_ready_for()); |
1086 | - |
1087 | + static GeometryMap positions; |
1088 | + positions[test_client_1] = geom::Rectangle{geom::Point{0, 0}, |
1089 | + geom::Size{client_width, client_height}}; |
1090 | + positions[test_client_2] = geom::Rectangle{geom::Point{screen_width/2, screen_height/2}, |
1091 | + geom::Size{client_width, client_height}}; |
1092 | + |
1093 | + auto server_config = make_event_producing_server(fence, 2, |
1094 | + [&](mtf::InputTestingServerConfiguration& server) |
1095 | + { |
1096 | // In the bounds of the first surface |
1097 | - fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(screen_width/2-1, screen_height/2-1)); |
1098 | + server.fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(screen_width/2-1, screen_height/2-1)); |
1099 | // In the bounds of the second surface |
1100 | - fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(screen_width/2, screen_height/2)); |
1101 | - } |
1102 | - } server_config{fence}; |
1103 | - |
1104 | - launch_server_process(server_config); |
1105 | - |
1106 | - struct InputClientOne : InputClient |
1107 | - { |
1108 | - InputClientOne(const mtf::CrossProcessSync& fence) |
1109 | - : InputClient(fence, test_client_1) |
1110 | - { |
1111 | - } |
1112 | - |
1113 | - void expect_input(mt::WaitCondition& events_received) override |
1114 | - { |
1115 | - InSequence seq; |
1116 | - EXPECT_CALL(*handler, handle_input(HoverEnterEvent())).Times(1); |
1117 | - EXPECT_CALL(*handler, handle_input(MotionEventWithPosition(client_width - 1, client_height - 1))).Times(1); |
1118 | - EXPECT_CALL(*handler, handle_input(HoverExitEvent())).Times(1) |
1119 | - .WillOnce(mt::WakeUp(&events_received)); |
1120 | - } |
1121 | - } client_1{fence}; |
1122 | - |
1123 | - struct InputClientTwo : InputClient |
1124 | - { |
1125 | - InputClientTwo(const mtf::CrossProcessSync& fence) |
1126 | - : InputClient(fence, test_client_2) |
1127 | - { |
1128 | - } |
1129 | - |
1130 | - void expect_input(mt::WaitCondition& events_received) override |
1131 | - { |
1132 | - InSequence seq; |
1133 | - EXPECT_CALL(*handler, handle_input(HoverEnterEvent())).Times(1); |
1134 | - EXPECT_CALL(*handler, handle_input(MotionEventWithPosition(client_width - 1, client_height - 1))).Times(1) |
1135 | - .WillOnce(mt::WakeUp(&events_received)); |
1136 | - } |
1137 | - } client_2{fence}; |
1138 | - |
1139 | - launch_client_process(client_1); |
1140 | - launch_client_process(client_2); |
1141 | + server.fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(screen_width/2, screen_height/2)); |
1142 | + }, positions, DepthMap()); |
1143 | + launch_server_process(*server_config); |
1144 | + |
1145 | + auto client_1 = make_event_expecting_client(test_client_1, fence, |
1146 | + [&](MockInputHandler& handler, mt::WaitCondition& events_received) |
1147 | + { |
1148 | + InSequence seq; |
1149 | + EXPECT_CALL(handler, handle_input(HoverEnterEvent())).Times(1); |
1150 | + EXPECT_CALL(handler, handle_input(MotionEventWithPosition(client_width - 1, client_height - 1))).Times(1); |
1151 | + EXPECT_CALL(handler, handle_input(HoverExitEvent())).Times(1) |
1152 | + .WillOnce(mt::WakeUp(&events_received)); |
1153 | + }); |
1154 | + auto client_2 = make_event_expecting_client(test_client_2, fence, |
1155 | + [&](MockInputHandler& handler, mt::WaitCondition& events_received) |
1156 | + { |
1157 | + InSequence seq; |
1158 | + EXPECT_CALL(handler, handle_input(HoverEnterEvent())).Times(1); |
1159 | + EXPECT_CALL(handler, handle_input(MotionEventWithPosition(client_width - 1, client_height - 1))).Times(1) |
1160 | + .WillOnce(mt::WakeUp(&events_received)); |
1161 | + }); |
1162 | + |
1163 | + launch_client_process(*client_1); |
1164 | + launch_client_process(*client_2); |
1165 | } |
1166 | |
1167 | namespace |
1168 | @@ -639,6 +643,7 @@ |
1169 | std::vector<geom::Rectangle> const input_rectangles; |
1170 | }; |
1171 | } |
1172 | + |
1173 | TEST_F(TestClientInput, clients_do_not_receive_motion_outside_input_region) |
1174 | { |
1175 | using namespace ::testing; |
1176 | @@ -670,7 +675,7 @@ |
1177 | static GeometryMap positions; |
1178 | positions[test_client_name] = screen_geometry; |
1179 | |
1180 | - return std::make_shared<StaticPlacementStrategy>(positions); |
1181 | + return std::make_shared<StaticPlacementStrategy>(InputTestingServerConfiguration::the_shell_placement_strategy(), positions); |
1182 | } |
1183 | std::shared_ptr<msh::SurfaceFactory> the_shell_surface_factory() override |
1184 | { |
1185 | @@ -697,35 +702,26 @@ |
1186 | fake_event_hub->synthesize_event(mis::a_button_up_event().of_button(BTN_LEFT)); |
1187 | } |
1188 | } server_config{fence}; |
1189 | - |
1190 | launch_server_process(server_config); |
1191 | |
1192 | - struct ClientConfig : InputClient |
1193 | - { |
1194 | - ClientConfig(const mtf::CrossProcessSync& fence) |
1195 | - : InputClient(fence, test_client_name) |
1196 | - { |
1197 | - } |
1198 | - |
1199 | - void expect_input(mt::WaitCondition& events_received) override |
1200 | - { |
1201 | - |
1202 | - EXPECT_CALL(*handler, handle_input(HoverEnterEvent())).Times(AnyNumber()); |
1203 | - EXPECT_CALL(*handler, handle_input(HoverExitEvent())).Times(AnyNumber()); |
1204 | - EXPECT_CALL(*handler, handle_input(MovementEvent())).Times(AnyNumber()); |
1205 | + auto client_config = make_event_expecting_client(test_client_name, fence, |
1206 | + [&](MockInputHandler& handler, mt::WaitCondition& events_received) |
1207 | + { |
1208 | + EXPECT_CALL(handler, handle_input(HoverEnterEvent())).Times(AnyNumber()); |
1209 | + EXPECT_CALL(handler, handle_input(HoverExitEvent())).Times(AnyNumber()); |
1210 | + EXPECT_CALL(handler, handle_input(MovementEvent())).Times(AnyNumber()); |
1211 | |
1212 | { |
1213 | // We should see two of the three button pairs. |
1214 | InSequence seq; |
1215 | - EXPECT_CALL(*handler, handle_input(ButtonDownEvent(1, 1))).Times(1); |
1216 | - EXPECT_CALL(*handler, handle_input(ButtonUpEvent(1, 1))).Times(1); |
1217 | - EXPECT_CALL(*handler, handle_input(ButtonDownEvent(99, 99))).Times(1); |
1218 | - EXPECT_CALL(*handler, handle_input(ButtonUpEvent(99, 99))).Times(1) |
1219 | + EXPECT_CALL(handler, handle_input(ButtonDownEvent(1, 1))).Times(1); |
1220 | + EXPECT_CALL(handler, handle_input(ButtonUpEvent(1, 1))).Times(1); |
1221 | + EXPECT_CALL(handler, handle_input(ButtonDownEvent(99, 99))).Times(1); |
1222 | + EXPECT_CALL(handler, handle_input(ButtonUpEvent(99, 99))).Times(1) |
1223 | .WillOnce(mt::WakeUp(&events_received)); |
1224 | } |
1225 | - } |
1226 | - } client_config{fence}; |
1227 | - launch_client_process(client_config); |
1228 | + }); |
1229 | + launch_client_process(*client_config); |
1230 | } |
1231 | |
1232 | TEST_F(TestClientInput, surfaces_obscure_motion_events_by_stacking) |
1233 | @@ -742,98 +738,62 @@ |
1234 | static geom::Rectangle const screen_geometry{geom::Point{0, 0}, |
1235 | geom::Size{screen_width, screen_height}}; |
1236 | |
1237 | - struct ServerConfiguration : mtf::InputTestingServerConfiguration |
1238 | - { |
1239 | - mtf::CrossProcessSync input_cb_setup_fence; |
1240 | - |
1241 | - ServerConfiguration(const mtf::CrossProcessSync& input_cb_setup_fence) |
1242 | - : input_cb_setup_fence(input_cb_setup_fence) |
1243 | - { |
1244 | - } |
1245 | - |
1246 | - std::shared_ptr<msh::PlacementStrategy> the_shell_placement_strategy() override |
1247 | - { |
1248 | - static GeometryMap positions; |
1249 | - positions[test_client_name_1] = screen_geometry; |
1250 | - |
1251 | - auto smaller_geometry = screen_geometry; |
1252 | - smaller_geometry.size.width = geom::Width{screen_width/2}; |
1253 | - positions[test_client_name_2] = smaller_geometry; |
1254 | - |
1255 | - static DepthMap depths; |
1256 | - depths[test_client_name_1] = ms::DepthId{0}; |
1257 | - depths[test_client_name_2] = ms::DepthId{1}; |
1258 | - |
1259 | - return std::make_shared<StaticPlacementStrategy>(positions, depths); |
1260 | - } |
1261 | - |
1262 | - void inject_input() override |
1263 | - { |
1264 | - wait_until_client_appears(test_client_name_1); |
1265 | - input_cb_setup_fence.wait_for_signal_ready_for(); |
1266 | - wait_until_client_appears(test_client_name_2); |
1267 | - input_cb_setup_fence.wait_for_signal_ready_for(); |
1268 | - |
1269 | + static GeometryMap positions; |
1270 | + positions[test_client_name_1] = screen_geometry; |
1271 | + |
1272 | + auto smaller_geometry = screen_geometry; |
1273 | + smaller_geometry.size.width = geom::Width{screen_width/2}; |
1274 | + positions[test_client_name_2] = smaller_geometry; |
1275 | + |
1276 | + static DepthMap depths; |
1277 | + depths[test_client_name_1] = ms::DepthId{0}; |
1278 | + depths[test_client_name_2] = ms::DepthId{1}; |
1279 | + |
1280 | + auto server_config = make_event_producing_server(fence, 2, |
1281 | + [&](mtf::InputTestingServerConfiguration& server) |
1282 | + { |
1283 | // First we will move the cursor in to the region where client 2 obscures client 1 |
1284 | - fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(1, 1)); |
1285 | - fake_event_hub->synthesize_event(mis::a_button_down_event().of_button(BTN_LEFT).with_action(mis::EventAction::Down)); |
1286 | - fake_event_hub->synthesize_event(mis::a_button_up_event().of_button(BTN_LEFT)); |
1287 | + server.fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(1, 1)); |
1288 | + server.fake_event_hub->synthesize_event(mis::a_button_down_event().of_button(BTN_LEFT).with_action(mis::EventAction::Down)); |
1289 | + server.fake_event_hub->synthesize_event(mis::a_button_up_event().of_button(BTN_LEFT)); |
1290 | // Now we move to the unobscured region of client 1 |
1291 | - fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(50, 0)); |
1292 | - fake_event_hub->synthesize_event(mis::a_button_down_event().of_button(BTN_LEFT).with_action(mis::EventAction::Down)); |
1293 | - fake_event_hub->synthesize_event(mis::a_button_up_event().of_button(BTN_LEFT)); |
1294 | - } |
1295 | - } server_config{fence}; |
1296 | - |
1297 | - launch_server_process(server_config); |
1298 | - |
1299 | - struct ClientConfigOne : InputClient |
1300 | - { |
1301 | - ClientConfigOne(const mtf::CrossProcessSync& fence) |
1302 | - : InputClient(fence, test_client_name_1) |
1303 | - { |
1304 | - } |
1305 | - |
1306 | - void expect_input(mt::WaitCondition& events_received) override |
1307 | - { |
1308 | - EXPECT_CALL(*handler, handle_input(HoverEnterEvent())).Times(AnyNumber()); |
1309 | - EXPECT_CALL(*handler, handle_input(HoverExitEvent())).Times(AnyNumber()); |
1310 | - EXPECT_CALL(*handler, handle_input(MovementEvent())).Times(AnyNumber()); |
1311 | - |
1312 | + server.fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(50, 0)); |
1313 | + server.fake_event_hub->synthesize_event(mis::a_button_down_event().of_button(BTN_LEFT).with_action(mis::EventAction::Down)); |
1314 | + server.fake_event_hub->synthesize_event(mis::a_button_up_event().of_button(BTN_LEFT)); |
1315 | + }, positions, depths); |
1316 | + launch_server_process(*server_config); |
1317 | + |
1318 | + auto client_config_1 = make_event_expecting_client(test_client_name_1, fence, |
1319 | + [&](MockInputHandler& handler, mt::WaitCondition& events_received) |
1320 | + { |
1321 | + EXPECT_CALL(handler, handle_input(HoverEnterEvent())).Times(AnyNumber()); |
1322 | + EXPECT_CALL(handler, handle_input(HoverExitEvent())).Times(AnyNumber()); |
1323 | + EXPECT_CALL(handler, handle_input(MovementEvent())).Times(AnyNumber()); |
1324 | { |
1325 | // We should only see one button event sequence. |
1326 | InSequence seq; |
1327 | - EXPECT_CALL(*handler, handle_input(ButtonDownEvent(51, 1))).Times(1); |
1328 | - EXPECT_CALL(*handler, handle_input(ButtonUpEvent(51, 1))).Times(1) |
1329 | + EXPECT_CALL(handler, handle_input(ButtonDownEvent(51, 1))).Times(1); |
1330 | + EXPECT_CALL(handler, handle_input(ButtonUpEvent(51, 1))).Times(1) |
1331 | .WillOnce(mt::WakeUp(&events_received)); |
1332 | } |
1333 | - } |
1334 | - } client_config_1{fence}; |
1335 | - launch_client_process(client_config_1); |
1336 | - |
1337 | - struct ClientConfigTwo : InputClient |
1338 | - { |
1339 | - ClientConfigTwo(const mtf::CrossProcessSync& fence) |
1340 | - : InputClient(fence, test_client_name_2) |
1341 | - { |
1342 | - } |
1343 | - |
1344 | - void expect_input(mt::WaitCondition& events_received) override |
1345 | - { |
1346 | - EXPECT_CALL(*handler, handle_input(HoverEnterEvent())).Times(AnyNumber()); |
1347 | - EXPECT_CALL(*handler, handle_input(HoverExitEvent())).Times(AnyNumber()); |
1348 | - EXPECT_CALL(*handler, handle_input(MovementEvent())).Times(AnyNumber()); |
1349 | - |
1350 | + }); |
1351 | + auto client_config_2 = make_event_expecting_client(test_client_name_2, fence, |
1352 | + [&](MockInputHandler& handler, mt::WaitCondition& events_received) |
1353 | + { |
1354 | + EXPECT_CALL(handler, handle_input(HoverEnterEvent())).Times(AnyNumber()); |
1355 | + EXPECT_CALL(handler, handle_input(HoverExitEvent())).Times(AnyNumber()); |
1356 | + EXPECT_CALL(handler, handle_input(MovementEvent())).Times(AnyNumber()); |
1357 | { |
1358 | // Likewise we should only see one button sequence. |
1359 | InSequence seq; |
1360 | - EXPECT_CALL(*handler, handle_input(ButtonDownEvent(1, 1))).Times(1); |
1361 | - EXPECT_CALL(*handler, handle_input(ButtonUpEvent(1, 1))).Times(1) |
1362 | + EXPECT_CALL(handler, handle_input(ButtonDownEvent(1, 1))).Times(1); |
1363 | + EXPECT_CALL(handler, handle_input(ButtonUpEvent(1, 1))).Times(1) |
1364 | .WillOnce(mt::WakeUp(&events_received)); |
1365 | } |
1366 | - } |
1367 | - } client_config_2{fence}; |
1368 | - launch_client_process(client_config_2); |
1369 | + }); |
1370 | + |
1371 | + launch_client_process(*client_config_1); |
1372 | + launch_client_process(*client_config_2); |
1373 | } |
1374 | |
1375 | namespace |
1376 | @@ -853,93 +813,48 @@ |
1377 | static std::string const test_client_name = "1"; |
1378 | static std::string const test_client_2_name = "2"; |
1379 | mtf::CrossProcessSync fence, first_client_ready_fence, second_client_done_fence; |
1380 | - |
1381 | - struct ServerConfiguration : public mtf::InputTestingServerConfiguration |
1382 | - { |
1383 | - mtf::CrossProcessSync input_cb_setup_fence; |
1384 | - mtf::CrossProcessSync second_client_done_fence; |
1385 | - |
1386 | - ServerConfiguration(const mtf::CrossProcessSync& input_cb_setup_fence, |
1387 | - const mtf::CrossProcessSync& second_client_done_fence) |
1388 | - : input_cb_setup_fence(input_cb_setup_fence), |
1389 | - second_client_done_fence(second_client_done_fence) |
1390 | - { |
1391 | - } |
1392 | - |
1393 | - void hide_session_by_name(std::string const& session_name) |
1394 | - { |
1395 | - the_shell_session_container()->for_each([&](std::shared_ptr<msh::Session> const& session) -> void |
1396 | - { |
1397 | - if (session->name() == session_name) |
1398 | - session->hide(); |
1399 | - }); |
1400 | - } |
1401 | - |
1402 | - void inject_input() |
1403 | - { |
1404 | - wait_until_client_appears(test_client_name); |
1405 | - wait_until_client_appears(test_client_2_name); |
1406 | - input_cb_setup_fence.wait_for_signal_ready_for(); |
1407 | - |
1408 | + |
1409 | + static DepthMap depths; |
1410 | + depths[test_client_name] = ms::DepthId{0}; |
1411 | + depths[test_client_2_name] = ms::DepthId{1}; |
1412 | + |
1413 | + auto server_config = make_event_producing_server(fence, 2, |
1414 | + [&](mtf::InputTestingServerConfiguration& server) |
1415 | + { |
1416 | // We send one event and then hide the surface on top before sending the next. |
1417 | - // So we expect each of the two surfaces to receive one event pair. |
1418 | - fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(1,1)); |
1419 | - |
1420 | + // So we expect each of the two surfaces to receive one even |
1421 | + server.fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(1,1)); |
1422 | // We use a fence to ensure we do not hide the client |
1423 | // before event dispatch occurs |
1424 | second_client_done_fence.wait_for_signal_ready_for(); |
1425 | - hide_session_by_name(test_client_2_name); |
1426 | - |
1427 | - fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(1,1)); |
1428 | - } |
1429 | - } server_config{fence, second_client_done_fence}; |
1430 | - launch_server_process(server_config); |
1431 | - |
1432 | - struct ButtonClientOne : InputClient |
1433 | - { |
1434 | - ButtonClientOne(const mtf::CrossProcessSync& fence) |
1435 | - : InputClient(fence, test_client_name) |
1436 | - { |
1437 | - } |
1438 | - |
1439 | - void expect_input(mt::WaitCondition& events_received) override |
1440 | - { |
1441 | - EXPECT_CALL(*handler, handle_input(HoverEnterEvent())).Times(AnyNumber()); |
1442 | - EXPECT_CALL(*handler, handle_input(HoverExitEvent())).Times(AnyNumber()); |
1443 | - EXPECT_CALL(*handler, handle_input(MotionEventWithPosition(2, 2))).Times(1) |
1444 | + |
1445 | + server.the_shell_session_container()->for_each([&](std::shared_ptr<msh::Session> const& session) -> void |
1446 | + { |
1447 | + if (session->name() == test_client_2_name) |
1448 | + session->hide(); |
1449 | + }); |
1450 | + |
1451 | + server.fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(1,1)); |
1452 | + }, GeometryMap(), depths); |
1453 | + launch_server_process(*server_config); |
1454 | + |
1455 | + auto client_config_1 = make_event_expecting_client(test_client_name, fence, |
1456 | + [&](MockInputHandler& handler, mt::WaitCondition& events_received) |
1457 | + { |
1458 | + EXPECT_CALL(handler, handle_input(HoverEnterEvent())).Times(AnyNumber()); |
1459 | + EXPECT_CALL(handler, handle_input(HoverExitEvent())).Times(AnyNumber()); |
1460 | + EXPECT_CALL(handler, handle_input(MotionEventWithPosition(2, 2))).Times(1) |
1461 | .WillOnce(mt::WakeUp(&events_received)); |
1462 | - } |
1463 | - } client_1{first_client_ready_fence}; |
1464 | - struct ButtonClientTwo : InputClient |
1465 | - { |
1466 | - mtf::CrossProcessSync first_client_ready; |
1467 | - mtf::CrossProcessSync done_fence; |
1468 | - |
1469 | - ButtonClientTwo(mtf::CrossProcessSync const& fence, mtf::CrossProcessSync const& first_client_ready, |
1470 | - mtf::CrossProcessSync const& done_fence) |
1471 | - : InputClient(fence, test_client_2_name), |
1472 | - first_client_ready(first_client_ready), |
1473 | - done_fence(done_fence) |
1474 | - { |
1475 | - } |
1476 | - void exec() |
1477 | - { |
1478 | - // Ensure we stack on top of the first client |
1479 | - first_client_ready.wait_for_signal_ready_for(); |
1480 | - InputClient::exec(); |
1481 | - } |
1482 | - |
1483 | - void expect_input(mt::WaitCondition& events_received) override |
1484 | - { |
1485 | - EXPECT_CALL(*handler, handle_input(HoverEnterEvent())).Times(AnyNumber()); |
1486 | - EXPECT_CALL(*handler, handle_input(HoverExitEvent())).Times(AnyNumber()); |
1487 | - EXPECT_CALL(*handler, handle_input(MotionEventWithPosition(1, 1))).Times(1) |
1488 | - .WillOnce(DoAll(SignalFence(&done_fence), mt::WakeUp(&events_received))); |
1489 | - } |
1490 | - } client_2{fence, first_client_ready_fence, second_client_done_fence}; |
1491 | - |
1492 | - // Client 2 is launched second so will be the first to receive input |
1493 | - |
1494 | - launch_client_process(client_1); |
1495 | - launch_client_process(client_2); |
1496 | + }); |
1497 | + auto client_config_2 = make_event_expecting_client(test_client_2_name, fence, |
1498 | + [&](MockInputHandler& handler, mt::WaitCondition& events_received) |
1499 | + { |
1500 | + EXPECT_CALL(handler, handle_input(HoverEnterEvent())).Times(AnyNumber()); |
1501 | + EXPECT_CALL(handler, handle_input(HoverExitEvent())).Times(AnyNumber()); |
1502 | + EXPECT_CALL(handler, handle_input(MotionEventWithPosition(1, 1))).Times(1) |
1503 | + .WillOnce(DoAll(SignalFence(&second_client_done_fence), mt::WakeUp(&events_received))); |
1504 | + }); |
1505 | + |
1506 | + launch_client_process(*client_config_1); |
1507 | + launch_client_process(*client_config_2); |
1508 | } |
1509 | |
1510 | === modified file 'tests/unit-tests/client/input/test_android_input_receiver.cpp' |
1511 | --- tests/unit-tests/client/input/test_android_input_receiver.cpp 2013-05-31 16:06:07 +0000 |
1512 | +++ tests/unit-tests/client/input/test_android_input_receiver.cpp 2013-11-07 00:22:14 +0000 |
1513 | @@ -17,8 +17,10 @@ |
1514 | */ |
1515 | |
1516 | #include "src/shared/input/android/android_input_receiver.h" |
1517 | +#include "mir/input/null_input_receiver_report.h" |
1518 | #include "mir_toolkit/event.h" |
1519 | |
1520 | + |
1521 | #include <androidfw/InputTransport.h> |
1522 | |
1523 | #include <gmock/gmock.h> |
1524 | @@ -27,7 +29,8 @@ |
1525 | #include <unistd.h> |
1526 | #include <memory> |
1527 | |
1528 | -namespace mircva = mir::input::receiver::android; |
1529 | +namespace mircv = mir::input::receiver; |
1530 | +namespace mircva = mircv::android; |
1531 | |
1532 | namespace droidinput = android; |
1533 | |
1534 | @@ -142,14 +145,14 @@ |
1535 | |
1536 | TEST_F(AndroidInputReceiverSetup, receiever_takes_channel_fd) |
1537 | { |
1538 | - mircva::InputReceiver receiver(client_fd); |
1539 | + mircva::InputReceiver receiver(client_fd, std::make_shared<mircv::NullInputReceiverReport>()); |
1540 | |
1541 | EXPECT_EQ(client_fd, receiver.fd()); |
1542 | } |
1543 | |
1544 | TEST_F(AndroidInputReceiverSetup, receiver_receives_key_events) |
1545 | { |
1546 | - mircva::InputReceiver receiver(client_fd); |
1547 | + mircva::InputReceiver receiver(client_fd, std::make_shared<mircv::NullInputReceiverReport>()); |
1548 | TestingInputProducer producer(server_fd); |
1549 | |
1550 | producer.produce_a_key_event(); |
1551 | @@ -165,7 +168,7 @@ |
1552 | |
1553 | TEST_F(AndroidInputReceiverSetup, receiver_handles_events) |
1554 | { |
1555 | - mircva::InputReceiver receiver(client_fd); |
1556 | + mircva::InputReceiver receiver(client_fd, std::make_shared<mircv::NullInputReceiverReport>()); |
1557 | TestingInputProducer producer(server_fd); |
1558 | |
1559 | producer.produce_a_key_event(); |
1560 | @@ -181,7 +184,7 @@ |
1561 | |
1562 | TEST_F(AndroidInputReceiverSetup, receiver_consumes_batched_motion_events) |
1563 | { |
1564 | - mircva::InputReceiver receiver(client_fd); |
1565 | + mircva::InputReceiver receiver(client_fd, std::make_shared<mircv::NullInputReceiverReport>()); |
1566 | TestingInputProducer producer(server_fd); |
1567 | |
1568 | // Produce 3 motion events before client handles any. |
1569 | |
1570 | === modified file 'tests/unit-tests/client/input/test_android_input_receiver_thread.cpp' |
1571 | --- tests/unit-tests/client/input/test_android_input_receiver_thread.cpp 2013-05-13 23:20:52 +0000 |
1572 | +++ tests/unit-tests/client/input/test_android_input_receiver_thread.cpp 2013-11-07 00:22:14 +0000 |
1573 | @@ -19,6 +19,8 @@ |
1574 | #include "src/shared/input/android/android_input_receiver_thread.h" |
1575 | #include "src/shared/input/android/android_input_receiver.h" |
1576 | |
1577 | +#include "mir/input/null_input_receiver_report.h" |
1578 | + |
1579 | #include "mir_toolkit/mir_client_library.h" |
1580 | |
1581 | #include <gtest/gtest.h> |
1582 | @@ -30,7 +32,8 @@ |
1583 | |
1584 | #include <fcntl.h> |
1585 | |
1586 | -namespace mircva = mir::input::receiver::android; |
1587 | +namespace mircv = mir::input::receiver; |
1588 | +namespace mircva = mircv::android; |
1589 | |
1590 | namespace |
1591 | { |
1592 | @@ -43,7 +46,7 @@ |
1593 | struct MockInputReceiver : public mircva::InputReceiver |
1594 | { |
1595 | MockInputReceiver(int fd) |
1596 | - : InputReceiver(fd) |
1597 | + : InputReceiver(fd, std::make_shared<mircv::NullInputReceiverReport>()) |
1598 | { |
1599 | } |
1600 | MOCK_METHOD1(next_event, bool(MirEvent &)); |