Merge lp:~andreas-pokorny/mir/key-repeater-on-timer-fd-utility into lp:mir
- key-repeater-on-timer-fd-utility
- Merge into development-branch
Status: | Work in progress |
---|---|
Proposed branch: | lp:~andreas-pokorny/mir/key-repeater-on-timer-fd-utility |
Merge into: | lp:mir |
Diff against target: |
875 lines (+771/-0) 15 files modified
include/common/mir/time/steady_timer_fd.h (+46/-0) include/common/mir/time/timer_fd.h (+65/-0) src/common/symbols.map (+6/-0) src/common/time/CMakeLists.txt (+3/-0) src/common/time/steady_timer_fd.cpp (+54/-0) src/platforms/evdev/CMakeLists.txt (+9/-0) src/platforms/evdev/key_repeater.cpp (+102/-0) src/platforms/evdev/key_repeater.h (+67/-0) src/platforms/evdev/steady_timer_fd_factory.cpp (+67/-0) src/platforms/evdev/steady_timer_fd_factory.h (+48/-0) src/platforms/evdev/timer_fd_factory.h (+47/-0) tests/include/mir/test/doubles/fake_timer_fd_factory.h (+69/-0) tests/include/mir/test/doubles/stub_timer_fd.h (+49/-0) tests/unit-tests/input/CMakeLists.txt (+1/-0) tests/unit-tests/input/test_key_repeater.cpp (+138/-0) |
To merge this branch: | bzr merge lp:~andreas-pokorny/mir/key-repeater-on-timer-fd-utility |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir CI Bot | continuous-integration | Needs Fixing | |
Mir development team | Pending | ||
Review via email: mp+308212@code.launchpad.net |
Commit message
Add a simpler key repeater utility class for stub and evdev input platform
The key repeater is meant to be integrated with the Dispatchable classes and will replace the key repeater that currently abuses the main loop in inject repeated keys inside the mirserver. It uses a new mircommon steady_timer_fd utility that wrapps CLOCK_MONOTONIC timer fds.
This is a preparation step to move the repeat handling inside the input platforms, which will evade another mirserver direct event structure manipulation.
Description of the change
This is a simplified version of the key repeater found in the last attempt. This time there is no interesting alarm provider to review, that integrates with Dispatchable and fulfillls all of our AlarmFactory requirements... Instead a trivial timer fd wrapper - but still tracking all pressed keys.
Mir CI Bot (mir-ci-bot) wrote : | # |
- 3758. By Andreas Pokorny
-
relative! instead of TFD_TIMER_ABSTIME
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3758
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unmerged revisions
- 3758. By Andreas Pokorny
-
relative! instead of TFD_TIMER_ABSTIME
- 3757. By Andreas Pokorny
-
Add a simpler key repeater utility class for stub and evdev input platform
The key repeater is meant to be integrated with the Dispatchable classes and will replace the key repeater that currently abuses the main loop in inject repeated keys inside the mirserver. It uses a new mircommon steady_timer_fd utility that wrapps CLOCK_MONOTONIC timer fds.
This is a preparation step to move the repeat handling inside the input platforms, which will evade another mirserver event type fumbling location.
Preview Diff
1 | === added file 'include/common/mir/time/steady_timer_fd.h' |
2 | --- include/common/mir/time/steady_timer_fd.h 1970-01-01 00:00:00 +0000 |
3 | +++ include/common/mir/time/steady_timer_fd.h 2016-10-12 07:29:58 +0000 |
4 | @@ -0,0 +1,46 @@ |
5 | +/* |
6 | + * Copyright © 2016 Canonical Ltd. |
7 | + * |
8 | + * This program is free software: you can redistribute it and/or modify it |
9 | + * under the terms of the GNU Lesser General Public License version 3, |
10 | + * as published by the Free Software Foundation. |
11 | + * |
12 | + * This program is distributed in the hope that it will be useful, |
13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | + * GNU Lesser General Public License for more details. |
16 | + * |
17 | + * You should have received a copy of the GNU Lesser General Public License |
18 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | + * |
20 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
21 | + */ |
22 | + |
23 | +#ifndef MIR_TIME_STEADY_TIMER_FD_ |
24 | +#define MIR_TIME_STEADY_TIMER_FD_ |
25 | + |
26 | +#include "mir/time/timer_fd.h" |
27 | + |
28 | +namespace mir |
29 | +{ |
30 | +namespace time |
31 | +{ |
32 | + |
33 | +/** |
34 | + * SteadyTimerFd implements TimerFd using timer fds and using CLOCK_MONOTONIC. |
35 | + */ |
36 | +class SteadyTimerFd : public TimerFd |
37 | +{ |
38 | +public: |
39 | + SteadyTimerFd(); |
40 | + Fd const& get_fd() override; |
41 | + void schedule_in(Duration duration) override; |
42 | + void cancel() override; |
43 | +private: |
44 | + mir::Fd timer; |
45 | +}; |
46 | + |
47 | +} |
48 | +} |
49 | + |
50 | +#endif |
51 | |
52 | === added file 'include/common/mir/time/timer_fd.h' |
53 | --- include/common/mir/time/timer_fd.h 1970-01-01 00:00:00 +0000 |
54 | +++ include/common/mir/time/timer_fd.h 2016-10-12 07:29:58 +0000 |
55 | @@ -0,0 +1,65 @@ |
56 | +/* |
57 | + * Copyright © 2016 Canonical Ltd. |
58 | + * |
59 | + * This program is free software: you can redistribute it and/or modify it |
60 | + * under the terms of the GNU Lesser General Public License version 3, |
61 | + * as published by the Free Software Foundation. |
62 | + * |
63 | + * This program is distributed in the hope that it will be useful, |
64 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
65 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
66 | + * GNU Lesser General Public License for more details. |
67 | + * |
68 | + * You should have received a copy of the GNU Lesser General Public License |
69 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
70 | + * |
71 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
72 | + */ |
73 | + |
74 | +#ifndef MIR_TIME_TIMER_FD_H_ |
75 | +#define MIR_TIME_TIMER_FD_H_ |
76 | + |
77 | +#include "mir/fd.h" |
78 | +#include "mir/time/types.h" |
79 | + |
80 | +#include <chrono> |
81 | + |
82 | +namespace mir |
83 | +{ |
84 | +namespace time |
85 | +{ |
86 | + |
87 | +/** |
88 | + * TimerFd is a timer that notifies via a file descriptor. |
89 | + */ |
90 | +class TimerFd |
91 | +{ |
92 | +public: |
93 | + TimerFd() = default; |
94 | + virtual ~TimerFd() = default; |
95 | + |
96 | + /** |
97 | + * Get access to the file descriptor |
98 | + */ |
99 | + virtual Fd const& get_fd() = 0; |
100 | + |
101 | + /** |
102 | + * Configure the timer monitored by the file descriptor to expire after the given \a duration. |
103 | + * |
104 | + * \param[in] duration the time to delay |
105 | + */ |
106 | + virtual void schedule_in(Duration duration) = 0; |
107 | + /** |
108 | + * Cancel the timer. |
109 | + * |
110 | + * After that call the timer can be configured again using schedule_for. |
111 | + */ |
112 | + virtual void cancel() = 0; |
113 | +protected: |
114 | + TimerFd(TimerFd const&) = delete; |
115 | + TimerFd& operator=(TimerFd const&) = delete; |
116 | +}; |
117 | + |
118 | +} |
119 | +} |
120 | +#endif |
121 | |
122 | === modified file 'src/common/symbols.map' |
123 | --- src/common/symbols.map 2016-10-12 06:03:15 +0000 |
124 | +++ src/common/symbols.map 2016-10-12 07:29:58 +0000 |
125 | @@ -364,6 +364,12 @@ |
126 | mir::output_type_name*; |
127 | MirSurfaceOutputEvent::refresh_rate*; |
128 | MirSurfaceOutputEvent::set_refresh_rate*; |
129 | + mir::time::SteadyTimerFd::SteadyTimerFd*; |
130 | + mir::time::SteadyTimerFd::get_fd*; |
131 | + mir::time::SteadyTimerFd::schedule_in*; |
132 | + mir::time::SteadyTimerFd::cancel*; |
133 | + typeinfo?for?mir::time::SteadyTimerFd; |
134 | + vtable?for?mir::time::SteadyTimerFd; |
135 | }; |
136 | local: *; |
137 | }; |
138 | |
139 | === modified file 'src/common/time/CMakeLists.txt' |
140 | --- src/common/time/CMakeLists.txt 2015-02-22 07:46:25 +0000 |
141 | +++ src/common/time/CMakeLists.txt 2016-10-12 07:29:58 +0000 |
142 | @@ -1,5 +1,8 @@ |
143 | ADD_LIBRARY( |
144 | mirtime OBJECT |
145 | |
146 | + ${CMAKE_SOURCE_DIR}/include/common/mir/time/timer_fd.h |
147 | + ${CMAKE_SOURCE_DIR}/include/common/mir/time/steady_timer_fd.h |
148 | steady_clock.cpp |
149 | + steady_timer_fd.cpp |
150 | ) |
151 | |
152 | === added file 'src/common/time/steady_timer_fd.cpp' |
153 | --- src/common/time/steady_timer_fd.cpp 1970-01-01 00:00:00 +0000 |
154 | +++ src/common/time/steady_timer_fd.cpp 2016-10-12 07:29:58 +0000 |
155 | @@ -0,0 +1,54 @@ |
156 | +/* |
157 | + * Copyright © 2016 Canonical Ltd. |
158 | + * |
159 | + * This program is free software: you can redistribute it and/or modify it |
160 | + * under the terms of the GNU Lesser General Public License version 3, |
161 | + * as published by the Free Software Foundation. |
162 | + * |
163 | + * This program is distributed in the hope that it will be useful, |
164 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
165 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
166 | + * GNU Lesser General Public License for more details. |
167 | + * |
168 | + * You should have received a copy of the GNU Lesser General Public License |
169 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
170 | + * |
171 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
172 | + */ |
173 | + |
174 | +#include "mir/time/steady_timer_fd.h" |
175 | +#include <sys/timerfd.h> |
176 | +#include <chrono> |
177 | + |
178 | +namespace mt = mir::time; |
179 | + |
180 | +mt::SteadyTimerFd::SteadyTimerFd() |
181 | + : timer{timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK)} |
182 | +{ |
183 | +} |
184 | + |
185 | +mir::Fd const& mt::SteadyTimerFd::get_fd() |
186 | +{ |
187 | + return timer; |
188 | +} |
189 | + |
190 | +void mt::SteadyTimerFd::schedule_in(mir::time::Duration delay) |
191 | +{ |
192 | + using namespace std::chrono; |
193 | + auto const in_seconds = duration_cast<seconds>(delay); |
194 | + itimerspec delay_spec; |
195 | + |
196 | + delay_spec.it_value.tv_sec = in_seconds.count(); |
197 | + delay_spec.it_value.tv_nsec = nanoseconds(delay - in_seconds).count(); |
198 | + delay_spec.it_interval.tv_sec = 0; |
199 | + delay_spec.it_interval.tv_nsec = 0; |
200 | + |
201 | + const int relative_timeout = 0; |
202 | + timerfd_settime(timer, relative_timeout, &delay_spec, nullptr); |
203 | +} |
204 | + |
205 | +void mt::SteadyTimerFd::cancel() |
206 | +{ |
207 | + const itimerspec cancel_timer = {{0,0},{0,0}}; |
208 | + timerfd_settime(timer, 0, &cancel_timer, nullptr); |
209 | +} |
210 | |
211 | === modified file 'src/platforms/evdev/CMakeLists.txt' |
212 | --- src/platforms/evdev/CMakeLists.txt 2016-08-10 07:57:05 +0000 |
213 | +++ src/platforms/evdev/CMakeLists.txt 2016-10-12 07:29:58 +0000 |
214 | @@ -18,13 +18,22 @@ |
215 | add_library(mirevdevutilsobjects OBJECT |
216 | evdev_device_detection.cpp |
217 | button_utils.cpp |
218 | + key_repeater.cpp |
219 | + key_repeater.h |
220 | + steady_timer_fd_factory.cpp |
221 | + steady_timer_fd_factory.h |
222 | ) |
223 | |
224 | add_library(mirplatforminputevdevobjects OBJECT |
225 | libinput_device.cpp |
226 | + libinput_device.h |
227 | libinput_device_ptr.cpp |
228 | + libinput_device_ptr.h |
229 | libinput_ptr.cpp |
230 | + libinput_ptr.h |
231 | platform.cpp |
232 | + platform.h |
233 | + timer_fd_factory.h |
234 | ) |
235 | |
236 | add_library(mirplatforminputevdev MODULE |
237 | |
238 | === added file 'src/platforms/evdev/key_repeater.cpp' |
239 | --- src/platforms/evdev/key_repeater.cpp 1970-01-01 00:00:00 +0000 |
240 | +++ src/platforms/evdev/key_repeater.cpp 2016-10-12 07:29:58 +0000 |
241 | @@ -0,0 +1,102 @@ |
242 | +/* |
243 | + * Copyright © 2016 Canonical Ltd. |
244 | + * |
245 | + * This program is free software: you can redistribute it and/or modify it |
246 | + * under the terms of the GNU General Public License version 3, |
247 | + * as published by the Free Software Foundation. |
248 | + * |
249 | + * This program is distributed in the hope that it will be useful, |
250 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
251 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
252 | + * GNU General Public License for more details. |
253 | + * |
254 | + * You should have received a copy of the GNU General Public License |
255 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
256 | + * |
257 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
258 | + */ |
259 | + |
260 | +#include "timer_fd_factory.h" |
261 | +#include "key_repeater.h" |
262 | + |
263 | +#include "mir/time/timer_fd.h" |
264 | + |
265 | +namespace mie = mir::input::evdev; |
266 | +namespace mt = mir::time; |
267 | + |
268 | +mie::KeyRepeater::KeyRepeater(TimerFdFactory const& timers, |
269 | + std::function<void(int32_t keycode)> const& send_repeat_key) |
270 | + : timers{timers}, send_repeat{send_repeat_key} |
271 | +{ |
272 | +} |
273 | + |
274 | +mie::KeyRepeater::~KeyRepeater() = default; |
275 | + |
276 | +void mie::KeyRepeater::enable(std::chrono::milliseconds repeat_delay, std::chrono::milliseconds repeat_interval) |
277 | +{ |
278 | + enabled_ = true; |
279 | + this->repeat_delay = repeat_delay; |
280 | + this->repeat_interval = repeat_interval; |
281 | +} |
282 | + |
283 | +void mie::KeyRepeater::disable() |
284 | +{ |
285 | + enabled_ = false; |
286 | + if (timer) |
287 | + { |
288 | + timer->cancel(); |
289 | + timer.reset(); |
290 | + } |
291 | + depressed_keys.clear(); |
292 | +} |
293 | + |
294 | +void mie::KeyRepeater::press(int32_t code) |
295 | +{ |
296 | + if (enabled_) |
297 | + { |
298 | + if (!timer) |
299 | + { |
300 | + timer = timers.create_timer([this]{handle_timeout();}); |
301 | + timer->schedule_in(repeat_delay); |
302 | + } |
303 | + depressed_keys.insert(code); |
304 | + } |
305 | +} |
306 | + |
307 | +void mie::KeyRepeater::release(int32_t code) |
308 | +{ |
309 | + bool const was_pressed = depressed_keys.erase(code); |
310 | + if (was_pressed && depressed_keys.empty() && timer) |
311 | + { |
312 | + timer->cancel(); |
313 | + timer.reset(); |
314 | + } |
315 | +} |
316 | + |
317 | +void mie::KeyRepeater::handle_timeout() |
318 | +{ |
319 | + if (enabled_) |
320 | + { |
321 | + if (!timer) |
322 | + timer = timers.create_timer([this]{handle_timeout();}); |
323 | + timer->schedule_in(repeat_interval); |
324 | + |
325 | + for (auto const code : depressed_keys) |
326 | + send_repeat(code); |
327 | + } |
328 | +} |
329 | + |
330 | +bool mie::KeyRepeater::enabled() const |
331 | +{ |
332 | + return enabled_; |
333 | +} |
334 | + |
335 | +std::chrono::milliseconds mie::KeyRepeater::delay() const |
336 | +{ |
337 | + return repeat_delay; |
338 | +} |
339 | + |
340 | +std::chrono::milliseconds mie::KeyRepeater::interval() const |
341 | +{ |
342 | + return repeat_interval; |
343 | +} |
344 | |
345 | === added file 'src/platforms/evdev/key_repeater.h' |
346 | --- src/platforms/evdev/key_repeater.h 1970-01-01 00:00:00 +0000 |
347 | +++ src/platforms/evdev/key_repeater.h 2016-10-12 07:29:58 +0000 |
348 | @@ -0,0 +1,67 @@ |
349 | +/* |
350 | + * Copyright © 2016 Canonical Ltd. |
351 | + * |
352 | + * This program is free software: you can redistribute it and/or modify it |
353 | + * under the terms of the GNU General Public License version 3, |
354 | + * as published by the Free Software Foundation. |
355 | + * |
356 | + * This program is distributed in the hope that it will be useful, |
357 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
358 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
359 | + * GNU General Public License for more details. |
360 | + * |
361 | + * You should have received a copy of the GNU General Public License |
362 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
363 | + * |
364 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
365 | + */ |
366 | + |
367 | +#ifndef MIR_INPUT_EVDEV_KEY_REPEATER_H_ |
368 | +#define MIR_INPUT_EVDEV_KEY_REPEATER_H_ |
369 | + |
370 | +#include <memory> |
371 | +#include <chrono> |
372 | +#include <unordered_set> |
373 | +#include <functional> |
374 | + |
375 | +namespace mir |
376 | +{ |
377 | +namespace time |
378 | +{ |
379 | +class TimerFd; |
380 | +} |
381 | +namespace input |
382 | +{ |
383 | +namespace evdev |
384 | +{ |
385 | +class TimerFdFactory; |
386 | + |
387 | +struct KeyRepeater |
388 | +{ |
389 | + KeyRepeater(TimerFdFactory const& timers, |
390 | + std::function<void(int32_t keycode)> const& send_repeat_key); |
391 | + ~KeyRepeater(); |
392 | + void enable(std::chrono::milliseconds repeat_delay, std::chrono::milliseconds repeat_interval); |
393 | + void disable(); |
394 | + bool enabled() const; |
395 | + std::chrono::milliseconds delay() const; |
396 | + std::chrono::milliseconds interval() const; |
397 | + void press(int32_t code); |
398 | + void release(int32_t code); |
399 | + |
400 | +private: |
401 | + void handle_timeout(); |
402 | + TimerFdFactory const& timers; |
403 | + bool enabled_{true}; |
404 | + |
405 | + std::chrono::milliseconds repeat_delay{500}; |
406 | + std::chrono::milliseconds repeat_interval{50}; |
407 | + |
408 | + std::function<void(int32_t)> send_repeat; |
409 | + std::unordered_set<int32_t> depressed_keys; |
410 | + std::unique_ptr<mir::time::TimerFd> timer; |
411 | +}; |
412 | +} |
413 | +} |
414 | +} |
415 | +#endif |
416 | |
417 | === added file 'src/platforms/evdev/steady_timer_fd_factory.cpp' |
418 | --- src/platforms/evdev/steady_timer_fd_factory.cpp 1970-01-01 00:00:00 +0000 |
419 | +++ src/platforms/evdev/steady_timer_fd_factory.cpp 2016-10-12 07:29:58 +0000 |
420 | @@ -0,0 +1,67 @@ |
421 | +/* |
422 | + * Copyright © 2016 Canonical Ltd. |
423 | + * |
424 | + * This program is free software: you can redistribute it and/or modify it |
425 | + * under the terms of the GNU Lesser General Public License version 3, |
426 | + * as published by the Free Software Foundation. |
427 | + * |
428 | + * This program is distributed in the hope that it will be useful, |
429 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
430 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
431 | + * GNU Lesser General Public License for more details. |
432 | + * |
433 | + * You should have received a copy of the GNU Lesser General Public License |
434 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
435 | + * |
436 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
437 | + */ |
438 | + |
439 | +#include "steady_timer_fd_factory.h" |
440 | +#include "mir/time/steady_timer_fd.h" |
441 | +#include "mir/dispatch/readable_fd.h" |
442 | + |
443 | +namespace mie = mir::input::evdev; |
444 | +namespace md = mir::dispatch; |
445 | +namespace mt = mir::time; |
446 | + |
447 | +namespace |
448 | +{ |
449 | + |
450 | +struct DispatchableTimerFd : mt::SteadyTimerFd |
451 | +{ |
452 | +public: |
453 | + DispatchableTimerFd(md::MultiplexingDispatchable& dispatchable, |
454 | + std::function<void()> const& callback) : |
455 | + readable_fd{std::make_shared<md::ReadableFd>(get_fd(), callback)}, |
456 | + dispatchable{dispatchable} |
457 | + { |
458 | + } |
459 | + |
460 | + void schedule_in(mir::time::Duration delay) override |
461 | + { |
462 | + mt::SteadyTimerFd::schedule_in(delay); |
463 | + dispatchable.add_watch(readable_fd); |
464 | + } |
465 | + |
466 | + void cancel() override |
467 | + { |
468 | + mt::SteadyTimerFd::cancel(); |
469 | + dispatchable.remove_watch(readable_fd); |
470 | + } |
471 | + |
472 | +private: |
473 | + std::shared_ptr<md::ReadableFd> const readable_fd; |
474 | + md::MultiplexingDispatchable& dispatchable; |
475 | +}; |
476 | + |
477 | +} |
478 | + |
479 | +mie::SteadyTimerFdFactory::SteadyTimerFdFactory(md::MultiplexingDispatchable& dispatchable) |
480 | + : dispatchable(dispatchable) |
481 | +{ |
482 | +} |
483 | + |
484 | +std::unique_ptr<mt::TimerFd> mie::SteadyTimerFdFactory::SteadyTimerFdFactory::create_timer(std::function<void()> const& callback_on_timeout) const |
485 | +{ |
486 | + return std::make_unique<DispatchableTimerFd>(dispatchable, callback_on_timeout); |
487 | +} |
488 | |
489 | === added file 'src/platforms/evdev/steady_timer_fd_factory.h' |
490 | --- src/platforms/evdev/steady_timer_fd_factory.h 1970-01-01 00:00:00 +0000 |
491 | +++ src/platforms/evdev/steady_timer_fd_factory.h 2016-10-12 07:29:58 +0000 |
492 | @@ -0,0 +1,48 @@ |
493 | +/* |
494 | + * Copyright © 2016 Canonical Ltd. |
495 | + * |
496 | + * This program is free software: you can redistribute it and/or modify it |
497 | + * under the terms of the GNU Lesser General Public License version 3, |
498 | + * as published by the Free Software Foundation. |
499 | + * |
500 | + * This program is distributed in the hope that it will be useful, |
501 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
502 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
503 | + * GNU Lesser General Public License for more details. |
504 | + * |
505 | + * You should have received a copy of the GNU Lesser General Public License |
506 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
507 | + * |
508 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
509 | + */ |
510 | + |
511 | +#ifndef MIR_INPUT_EVDEV_STEADY_TIMER_FD_FACTORY_H_ |
512 | +#define MIR_INPUT_EVDEV_STEADY_TIMER_FD_FACTORY_H_ |
513 | + |
514 | +#include "timer_fd_factory.h" |
515 | + |
516 | +#include "mir/dispatch/multiplexing_dispatchable.h" |
517 | +#include "mir/time/timer_fd.h" |
518 | + |
519 | +#include <memory> |
520 | + |
521 | +namespace mir |
522 | +{ |
523 | +namespace input |
524 | +{ |
525 | +namespace evdev |
526 | +{ |
527 | +struct SteadyTimerFdFactory : TimerFdFactory |
528 | +{ |
529 | +public: |
530 | + SteadyTimerFdFactory(mir::dispatch::MultiplexingDispatchable& dispatchable); |
531 | + std::unique_ptr<mir::time::TimerFd> create_timer(std::function<void()> const& call_on_timeout) const override; |
532 | +private: |
533 | + mir::dispatch::MultiplexingDispatchable& dispatchable; |
534 | +}; |
535 | + |
536 | +} |
537 | +} |
538 | +} |
539 | + |
540 | +#endif |
541 | |
542 | === added file 'src/platforms/evdev/timer_fd_factory.h' |
543 | --- src/platforms/evdev/timer_fd_factory.h 1970-01-01 00:00:00 +0000 |
544 | +++ src/platforms/evdev/timer_fd_factory.h 2016-10-12 07:29:58 +0000 |
545 | @@ -0,0 +1,47 @@ |
546 | +/* |
547 | + * Copyright © 2016 Canonical Ltd. |
548 | + * |
549 | + * This program is free software: you can redistribute it and/or modify it |
550 | + * under the terms of the GNU Lesser General Public License version 3, |
551 | + * as published by the Free Software Foundation. |
552 | + * |
553 | + * This program is distributed in the hope that it will be useful, |
554 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
555 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
556 | + * GNU Lesser General Public License for more details. |
557 | + * |
558 | + * You should have received a copy of the GNU Lesser General Public License |
559 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
560 | + * |
561 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
562 | + */ |
563 | + |
564 | +#ifndef MIR_INPUT_EVDEV_TIMER_FD_FACTORY_H |
565 | +#define MIR_INPUT_EVDEV_TIMER_FD_FACTORY_H |
566 | + |
567 | +#include "mir/time/timer_fd.h" |
568 | +#include <functional> |
569 | + |
570 | +namespace mir |
571 | +{ |
572 | +namespace input |
573 | +{ |
574 | +namespace evdev |
575 | +{ |
576 | +struct TimerFdFactory |
577 | +{ |
578 | +public: |
579 | + TimerFdFactory() = default; |
580 | + virtual std::unique_ptr<mir::time::TimerFd> create_timer(std::function<void()> const& callback_on_timeout) const = 0; |
581 | +protected: |
582 | + virtual ~TimerFdFactory() = default; |
583 | +private: |
584 | + TimerFdFactory(TimerFdFactory const&) = delete; |
585 | + TimerFdFactory& operator=(TimerFdFactory const&) = delete; |
586 | +}; |
587 | + |
588 | +} |
589 | +} |
590 | +} |
591 | + |
592 | +#endif |
593 | |
594 | === added file 'tests/include/mir/test/doubles/fake_timer_fd_factory.h' |
595 | --- tests/include/mir/test/doubles/fake_timer_fd_factory.h 1970-01-01 00:00:00 +0000 |
596 | +++ tests/include/mir/test/doubles/fake_timer_fd_factory.h 2016-10-12 07:29:58 +0000 |
597 | @@ -0,0 +1,69 @@ |
598 | +/* |
599 | + * Copyright © 2016 Canonical Ltd. |
600 | + * |
601 | + * This program is free software: you can redistribute it and/or modify |
602 | + * it under the terms of the GNU General Public License version 3 as |
603 | + * published by the Free Software Foundation. |
604 | + * |
605 | + * This program is distributed in the hope that it will be useful, |
606 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
607 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
608 | + * GNU General Public License for more details. |
609 | + * |
610 | + * You should have received a copy of the GNU General Public License |
611 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
612 | + * |
613 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
614 | + */ |
615 | + |
616 | +#ifndef MIR_TEST_DOUBLES_FAKE_TIMER_FD_FACTORY_H_ |
617 | +#define MIR_TEST_DOUBLES_FAKE_TIMER_FD_FACTORY_H_ |
618 | + |
619 | +#include "mir/test/doubles/stub_timer_fd.h" |
620 | +#include "src/platforms/evdev/timer_fd_factory.h" |
621 | + |
622 | +#include "mir/time/types.h" |
623 | + |
624 | +#include <gmock/gmock.h> |
625 | +#include <memory> |
626 | + |
627 | +namespace mir |
628 | +{ |
629 | +namespace test |
630 | +{ |
631 | +namespace doubles |
632 | +{ |
633 | +struct MockTimerFd : StubTimerFd |
634 | +{ |
635 | + MOCK_METHOD1(schedule_in, void(mir::time::Duration)); |
636 | + MOCK_METHOD0(cancel, void()); |
637 | +}; |
638 | + |
639 | +struct FakeTimerFdFactory : mir::input::evdev::TimerFdFactory |
640 | +{ |
641 | + using NiceTimerFd = testing::NiceMock<MockTimerFd>; |
642 | + std::unique_ptr<NiceTimerFd> mutable prepared_timer; |
643 | + std::function<void()> mutable execute_last_timer; |
644 | + MOCK_CONST_METHOD2(timer_created, void(NiceTimerFd* timer, std::function<void()> const&)); |
645 | + |
646 | + inline std::unique_ptr<mir::time::TimerFd> create_timer(std::function<void()> const& callback) const override |
647 | + { |
648 | + execute_last_timer = callback; |
649 | + if (!prepared_timer) |
650 | + { |
651 | + auto new_timer = std::make_unique<NiceTimerFd>(); |
652 | + timer_created(new_timer.get(), callback); |
653 | + return new_timer; |
654 | + } |
655 | + else |
656 | + { |
657 | + timer_created(prepared_timer.get(), callback); |
658 | + return std::move(prepared_timer); |
659 | + } |
660 | + } |
661 | +}; |
662 | +} |
663 | +} |
664 | +} |
665 | + |
666 | +#endif |
667 | |
668 | === added file 'tests/include/mir/test/doubles/stub_timer_fd.h' |
669 | --- tests/include/mir/test/doubles/stub_timer_fd.h 1970-01-01 00:00:00 +0000 |
670 | +++ tests/include/mir/test/doubles/stub_timer_fd.h 2016-10-12 07:29:58 +0000 |
671 | @@ -0,0 +1,49 @@ |
672 | +/* |
673 | + * Copyright © 2016 Canonical Ltd. |
674 | + * |
675 | + * This program is free software: you can redistribute it and/or modify it |
676 | + * under the terms of the GNU General Public License version 3, |
677 | + * as published by the Free Software Foundation. |
678 | + * |
679 | + * This program is distributed in the hope that it will be useful, |
680 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
681 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
682 | + * GNU General Public License for more details. |
683 | + * |
684 | + * You should have received a copy of the GNU General Public License |
685 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
686 | + * |
687 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
688 | + */ |
689 | + |
690 | +#ifndef MIR_TEST_DOUBLES_STUB_TIMER_FD_H |
691 | +#define MIR_TEST_DOUBLES_STUB_TIMER_FD_H |
692 | + |
693 | +#include "mir/time/timer_fd.h" |
694 | + |
695 | +namespace mir |
696 | +{ |
697 | +namespace test |
698 | +{ |
699 | +namespace doubles |
700 | +{ |
701 | +struct StubTimerFd : mir::time::TimerFd |
702 | +{ |
703 | + Fd const& get_fd() override |
704 | + { |
705 | + return fd; |
706 | + } |
707 | + void schedule_in(mir::time::Duration) override |
708 | + { |
709 | + } |
710 | + void cancel() override |
711 | + { |
712 | + } |
713 | + |
714 | + mir::Fd fd{IntOwnedFd{-1}}; |
715 | +}; |
716 | +} |
717 | +} |
718 | +} |
719 | + |
720 | +#endif |
721 | |
722 | === modified file 'tests/unit-tests/input/CMakeLists.txt' |
723 | --- tests/unit-tests/input/CMakeLists.txt 2016-07-18 07:38:38 +0000 |
724 | +++ tests/unit-tests/input/CMakeLists.txt 2016-10-12 07:29:58 +0000 |
725 | @@ -18,6 +18,7 @@ |
726 | ${CMAKE_CURRENT_SOURCE_DIR}/test_key_repeat_dispatcher.cpp |
727 | ${CMAKE_CURRENT_SOURCE_DIR}/test_validator.cpp |
728 | ${CMAKE_CURRENT_SOURCE_DIR}/test_nested_input_platform.cpp |
729 | + ${CMAKE_CURRENT_SOURCE_DIR}/test_key_repeater.cpp |
730 | ) |
731 | |
732 | list(APPEND UMOCK_UNIT_TEST_SOURCES |
733 | |
734 | === added file 'tests/unit-tests/input/test_key_repeater.cpp' |
735 | --- tests/unit-tests/input/test_key_repeater.cpp 1970-01-01 00:00:00 +0000 |
736 | +++ tests/unit-tests/input/test_key_repeater.cpp 2016-10-12 07:29:58 +0000 |
737 | @@ -0,0 +1,138 @@ |
738 | +/* |
739 | + * Copyright © 2016 Canonical Ltd. |
740 | + * |
741 | + * This program is free software: you can redistribute it and/or modify |
742 | + * it under the terms of the GNU General Public License version 3 as |
743 | + * published by the Free Software Foundation. |
744 | + * |
745 | + * This program is distributed in the hope that it will be useful, |
746 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
747 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
748 | + * GNU General Public License for more details. |
749 | + * |
750 | + * You should have received a copy of the GNU General Public License |
751 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
752 | + * |
753 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
754 | + */ |
755 | + |
756 | +#include "src/platforms/evdev/key_repeater.h" |
757 | +#include "mir/test/doubles/fake_timer_fd_factory.h" |
758 | +#include "mir/test/fake_shared.h" |
759 | + |
760 | +#include <gtest/gtest.h> |
761 | +#include <gmock/gmock.h> |
762 | + |
763 | +#include <memory> |
764 | +#include <chrono> |
765 | + |
766 | +namespace mt = mir::test; |
767 | +namespace mtd = mt::doubles; |
768 | +namespace mie = mir::input::evdev; |
769 | + |
770 | +using namespace ::testing; |
771 | +using namespace std::chrono_literals; |
772 | + |
773 | +namespace |
774 | +{ |
775 | +struct KeyRepeater : Test |
776 | +{ |
777 | + MOCK_METHOD1(repeat_called, void(int32_t)); |
778 | + |
779 | + NiceMock<mtd::FakeTimerFdFactory> fake_timers; |
780 | + mie::KeyRepeater repeater{ |
781 | + fake_timers, |
782 | + [this](int32_t code) |
783 | + { |
784 | + repeat_called(code); |
785 | + }}; |
786 | + |
787 | + const int32_t a_key = 32; |
788 | + const int32_t another_key = 10; |
789 | + const int32_t third_key = 54; |
790 | +}; |
791 | +} |
792 | + |
793 | +TEST_F(KeyRepeater, no_repeat_alarm_when_disabled) |
794 | +{ |
795 | + repeater.disable(); |
796 | + EXPECT_CALL(fake_timers, timer_created(_,_)).Times(0); |
797 | + |
798 | + repeater.press(a_key); |
799 | + repeater.release(a_key); |
800 | +} |
801 | + |
802 | +TEST_F(KeyRepeater, repeat_enabled_by_default) |
803 | +{ |
804 | + EXPECT_THAT(repeater.enabled(), Eq(true)); |
805 | +} |
806 | + |
807 | +TEST_F(KeyRepeater, alarm_canceled_on_disable) |
808 | +{ |
809 | + fake_timers.prepared_timer = std::make_unique<mtd::FakeTimerFdFactory::NiceTimerFd>(); |
810 | + EXPECT_CALL(*fake_timers.prepared_timer.get(), cancel()).Times(1); |
811 | + |
812 | + repeater.press(a_key); |
813 | + repeater.disable(); |
814 | +} |
815 | + |
816 | +TEST_F(KeyRepeater, alarm_canceled_on_release) |
817 | +{ |
818 | + fake_timers.prepared_timer = std::make_unique<NiceMock<mtd::MockTimerFd>>(); |
819 | + EXPECT_CALL(*fake_timers.prepared_timer.get(), schedule_in(_)); |
820 | + EXPECT_CALL(*fake_timers.prepared_timer.get(), cancel()); |
821 | + |
822 | + repeater.press(a_key); |
823 | + repeater.release(a_key); |
824 | +} |
825 | + |
826 | +TEST_F(KeyRepeater, alarm_rescheduled_on_timeout) |
827 | +{ |
828 | + fake_timers.prepared_timer = std::make_unique<NiceMock<mtd::MockTimerFd>>(); |
829 | + std::function<void()> timer_callback; |
830 | + mir::time::Duration const delay = 50ms; |
831 | + mir::time::Duration const interval = 10ms; |
832 | + EXPECT_CALL(*fake_timers.prepared_timer.get(), schedule_in(delay)); |
833 | + EXPECT_CALL(*fake_timers.prepared_timer.get(), schedule_in(interval)); |
834 | + |
835 | + repeater.enable(50ms, 10ms); |
836 | + repeater.press(a_key); |
837 | + fake_timers.execute_last_timer(); |
838 | +} |
839 | + |
840 | +TEST_F(KeyRepeater, callback_called_on_timeout) |
841 | +{ |
842 | + EXPECT_CALL(*this, repeat_called(a_key)).Times(1); |
843 | + |
844 | + repeater.press(a_key); |
845 | + fake_timers.execute_last_timer(); |
846 | +} |
847 | + |
848 | +TEST_F(KeyRepeater, one_alarm_for_all_keys) |
849 | +{ |
850 | + EXPECT_CALL(fake_timers, timer_created(_,_)).Times(1); |
851 | + repeater.press(a_key); |
852 | + repeater.press(another_key); |
853 | +} |
854 | + |
855 | +TEST_F(KeyRepeater, alarm_canceld_on_release_of_last_key) |
856 | +{ |
857 | + fake_timers.prepared_timer = std::make_unique<NiceMock<mtd::MockTimerFd>>(); |
858 | + auto & prepared_timer = *fake_timers.prepared_timer.get(); |
859 | + EXPECT_CALL(fake_timers, timer_created(_,_)).Times(1); |
860 | + EXPECT_CALL(prepared_timer, schedule_in(_)).Times(1); |
861 | + EXPECT_CALL(prepared_timer, cancel()).Times(0); |
862 | + repeater.press(a_key); |
863 | + repeater.press(another_key); |
864 | + repeater.press(third_key); |
865 | + testing::Mock::VerifyAndClear(&prepared_timer); |
866 | + |
867 | + EXPECT_CALL(prepared_timer, cancel()).Times(0); |
868 | + repeater.release(another_key); |
869 | + repeater.release(a_key); |
870 | + |
871 | + testing::Mock::VerifyAndClear(&prepared_timer); |
872 | + |
873 | + EXPECT_CALL(prepared_timer, cancel()).Times(1); |
874 | + repeater.release(third_key); |
875 | +} |
FAILED: Continuous integration, rev:3757 /mir-jenkins. ubuntu. com/job/ mir-ci/ 1948/ /mir-jenkins. ubuntu. com/job/ build-mir/ 2484/console /mir-jenkins. ubuntu. com/job/ build-0- fetch/2547 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= vivid+overlay/ 2539 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial+ overlay/ 2539 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= yakkety/ 2539 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= yakkety/ 2513/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial+ overlay/ 2513 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial+ overlay/ 2513/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= yakkety/ 2513 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= yakkety/ 2513/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 2513/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 2513/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial+ overlay/ 2513 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial+ overlay/ 2513/artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild: /mir-jenkins. ubuntu. com/job/ mir-ci/ 1948/rebuild
https:/