Mir

Merge lp:~andreas-pokorny/mir/key-repeater-on-timer-fd-utility into lp:mir

Proposed by Andreas Pokorny
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
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.

To post a comment you must log in.
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3757
https://mir-jenkins.ubuntu.com/job/mir-ci/1948/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/2484/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2547
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2539
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2539
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2539
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2513/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2513
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2513/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2513
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2513/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2513/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2513/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2513
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2513/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/1948/rebuild

review: Needs Fixing (continuous-integration)
3758. By Andreas Pokorny

relative! instead of TFD_TIMER_ABSTIME

Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3758
https://mir-jenkins.ubuntu.com/job/mir-ci/1951/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/2489/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2552
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2544
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2544
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2544
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2518/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2518
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2518/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2518
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2518/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2518/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2518/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2518
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2518/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/1951/rebuild

review: Needs Fixing (continuous-integration)

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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'include/common/mir/time/steady_timer_fd.h'
--- include/common/mir/time/steady_timer_fd.h 1970-01-01 00:00:00 +0000
+++ include/common/mir/time/steady_timer_fd.h 2016-10-12 07:29:58 +0000
@@ -0,0 +1,46 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
17 */
18
19#ifndef MIR_TIME_STEADY_TIMER_FD_
20#define MIR_TIME_STEADY_TIMER_FD_
21
22#include "mir/time/timer_fd.h"
23
24namespace mir
25{
26namespace time
27{
28
29/**
30 * SteadyTimerFd implements TimerFd using timer fds and using CLOCK_MONOTONIC.
31 */
32class SteadyTimerFd : public TimerFd
33{
34public:
35 SteadyTimerFd();
36 Fd const& get_fd() override;
37 void schedule_in(Duration duration) override;
38 void cancel() override;
39private:
40 mir::Fd timer;
41};
42
43}
44}
45
46#endif
047
=== added file 'include/common/mir/time/timer_fd.h'
--- include/common/mir/time/timer_fd.h 1970-01-01 00:00:00 +0000
+++ include/common/mir/time/timer_fd.h 2016-10-12 07:29:58 +0000
@@ -0,0 +1,65 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
17 */
18
19#ifndef MIR_TIME_TIMER_FD_H_
20#define MIR_TIME_TIMER_FD_H_
21
22#include "mir/fd.h"
23#include "mir/time/types.h"
24
25#include <chrono>
26
27namespace mir
28{
29namespace time
30{
31
32/**
33 * TimerFd is a timer that notifies via a file descriptor.
34 */
35class TimerFd
36{
37public:
38 TimerFd() = default;
39 virtual ~TimerFd() = default;
40
41 /**
42 * Get access to the file descriptor
43 */
44 virtual Fd const& get_fd() = 0;
45
46 /**
47 * Configure the timer monitored by the file descriptor to expire after the given \a duration.
48 *
49 * \param[in] duration the time to delay
50 */
51 virtual void schedule_in(Duration duration) = 0;
52 /**
53 * Cancel the timer.
54 *
55 * After that call the timer can be configured again using schedule_for.
56 */
57 virtual void cancel() = 0;
58protected:
59 TimerFd(TimerFd const&) = delete;
60 TimerFd& operator=(TimerFd const&) = delete;
61};
62
63}
64}
65#endif
066
=== modified file 'src/common/symbols.map'
--- src/common/symbols.map 2016-10-12 06:03:15 +0000
+++ src/common/symbols.map 2016-10-12 07:29:58 +0000
@@ -364,6 +364,12 @@
364 mir::output_type_name*;364 mir::output_type_name*;
365 MirSurfaceOutputEvent::refresh_rate*;365 MirSurfaceOutputEvent::refresh_rate*;
366 MirSurfaceOutputEvent::set_refresh_rate*;366 MirSurfaceOutputEvent::set_refresh_rate*;
367 mir::time::SteadyTimerFd::SteadyTimerFd*;
368 mir::time::SteadyTimerFd::get_fd*;
369 mir::time::SteadyTimerFd::schedule_in*;
370 mir::time::SteadyTimerFd::cancel*;
371 typeinfo?for?mir::time::SteadyTimerFd;
372 vtable?for?mir::time::SteadyTimerFd;
367 };373 };
368 local: *;374 local: *;
369};375};
370376
=== modified file 'src/common/time/CMakeLists.txt'
--- src/common/time/CMakeLists.txt 2015-02-22 07:46:25 +0000
+++ src/common/time/CMakeLists.txt 2016-10-12 07:29:58 +0000
@@ -1,5 +1,8 @@
1ADD_LIBRARY(1ADD_LIBRARY(
2 mirtime OBJECT2 mirtime OBJECT
33
4 ${CMAKE_SOURCE_DIR}/include/common/mir/time/timer_fd.h
5 ${CMAKE_SOURCE_DIR}/include/common/mir/time/steady_timer_fd.h
4 steady_clock.cpp6 steady_clock.cpp
7 steady_timer_fd.cpp
5)8)
69
=== added file 'src/common/time/steady_timer_fd.cpp'
--- src/common/time/steady_timer_fd.cpp 1970-01-01 00:00:00 +0000
+++ src/common/time/steady_timer_fd.cpp 2016-10-12 07:29:58 +0000
@@ -0,0 +1,54 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
17 */
18
19#include "mir/time/steady_timer_fd.h"
20#include <sys/timerfd.h>
21#include <chrono>
22
23namespace mt = mir::time;
24
25mt::SteadyTimerFd::SteadyTimerFd()
26 : timer{timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK)}
27{
28}
29
30mir::Fd const& mt::SteadyTimerFd::get_fd()
31{
32 return timer;
33}
34
35void mt::SteadyTimerFd::schedule_in(mir::time::Duration delay)
36{
37 using namespace std::chrono;
38 auto const in_seconds = duration_cast<seconds>(delay);
39 itimerspec delay_spec;
40
41 delay_spec.it_value.tv_sec = in_seconds.count();
42 delay_spec.it_value.tv_nsec = nanoseconds(delay - in_seconds).count();
43 delay_spec.it_interval.tv_sec = 0;
44 delay_spec.it_interval.tv_nsec = 0;
45
46 const int relative_timeout = 0;
47 timerfd_settime(timer, relative_timeout, &delay_spec, nullptr);
48}
49
50void mt::SteadyTimerFd::cancel()
51{
52 const itimerspec cancel_timer = {{0,0},{0,0}};
53 timerfd_settime(timer, 0, &cancel_timer, nullptr);
54}
055
=== modified file 'src/platforms/evdev/CMakeLists.txt'
--- src/platforms/evdev/CMakeLists.txt 2016-08-10 07:57:05 +0000
+++ src/platforms/evdev/CMakeLists.txt 2016-10-12 07:29:58 +0000
@@ -18,13 +18,22 @@
18add_library(mirevdevutilsobjects OBJECT18add_library(mirevdevutilsobjects OBJECT
19 evdev_device_detection.cpp19 evdev_device_detection.cpp
20 button_utils.cpp20 button_utils.cpp
21 key_repeater.cpp
22 key_repeater.h
23 steady_timer_fd_factory.cpp
24 steady_timer_fd_factory.h
21 )25 )
2226
23add_library(mirplatforminputevdevobjects OBJECT27add_library(mirplatforminputevdevobjects OBJECT
24 libinput_device.cpp28 libinput_device.cpp
29 libinput_device.h
25 libinput_device_ptr.cpp30 libinput_device_ptr.cpp
31 libinput_device_ptr.h
26 libinput_ptr.cpp32 libinput_ptr.cpp
33 libinput_ptr.h
27 platform.cpp34 platform.cpp
35 platform.h
36 timer_fd_factory.h
28 )37 )
2938
30add_library(mirplatforminputevdev MODULE39add_library(mirplatforminputevdev MODULE
3140
=== added file 'src/platforms/evdev/key_repeater.cpp'
--- src/platforms/evdev/key_repeater.cpp 1970-01-01 00:00:00 +0000
+++ src/platforms/evdev/key_repeater.cpp 2016-10-12 07:29:58 +0000
@@ -0,0 +1,102 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
17 */
18
19#include "timer_fd_factory.h"
20#include "key_repeater.h"
21
22#include "mir/time/timer_fd.h"
23
24namespace mie = mir::input::evdev;
25namespace mt = mir::time;
26
27mie::KeyRepeater::KeyRepeater(TimerFdFactory const& timers,
28 std::function<void(int32_t keycode)> const& send_repeat_key)
29 : timers{timers}, send_repeat{send_repeat_key}
30{
31}
32
33mie::KeyRepeater::~KeyRepeater() = default;
34
35void mie::KeyRepeater::enable(std::chrono::milliseconds repeat_delay, std::chrono::milliseconds repeat_interval)
36{
37 enabled_ = true;
38 this->repeat_delay = repeat_delay;
39 this->repeat_interval = repeat_interval;
40}
41
42void mie::KeyRepeater::disable()
43{
44 enabled_ = false;
45 if (timer)
46 {
47 timer->cancel();
48 timer.reset();
49 }
50 depressed_keys.clear();
51}
52
53void mie::KeyRepeater::press(int32_t code)
54{
55 if (enabled_)
56 {
57 if (!timer)
58 {
59 timer = timers.create_timer([this]{handle_timeout();});
60 timer->schedule_in(repeat_delay);
61 }
62 depressed_keys.insert(code);
63 }
64}
65
66void mie::KeyRepeater::release(int32_t code)
67{
68 bool const was_pressed = depressed_keys.erase(code);
69 if (was_pressed && depressed_keys.empty() && timer)
70 {
71 timer->cancel();
72 timer.reset();
73 }
74}
75
76void mie::KeyRepeater::handle_timeout()
77{
78 if (enabled_)
79 {
80 if (!timer)
81 timer = timers.create_timer([this]{handle_timeout();});
82 timer->schedule_in(repeat_interval);
83
84 for (auto const code : depressed_keys)
85 send_repeat(code);
86 }
87}
88
89bool mie::KeyRepeater::enabled() const
90{
91 return enabled_;
92}
93
94std::chrono::milliseconds mie::KeyRepeater::delay() const
95{
96 return repeat_delay;
97}
98
99std::chrono::milliseconds mie::KeyRepeater::interval() const
100{
101 return repeat_interval;
102}
0103
=== added file 'src/platforms/evdev/key_repeater.h'
--- src/platforms/evdev/key_repeater.h 1970-01-01 00:00:00 +0000
+++ src/platforms/evdev/key_repeater.h 2016-10-12 07:29:58 +0000
@@ -0,0 +1,67 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
17 */
18
19#ifndef MIR_INPUT_EVDEV_KEY_REPEATER_H_
20#define MIR_INPUT_EVDEV_KEY_REPEATER_H_
21
22#include <memory>
23#include <chrono>
24#include <unordered_set>
25#include <functional>
26
27namespace mir
28{
29namespace time
30{
31class TimerFd;
32}
33namespace input
34{
35namespace evdev
36{
37class TimerFdFactory;
38
39struct KeyRepeater
40{
41 KeyRepeater(TimerFdFactory const& timers,
42 std::function<void(int32_t keycode)> const& send_repeat_key);
43 ~KeyRepeater();
44 void enable(std::chrono::milliseconds repeat_delay, std::chrono::milliseconds repeat_interval);
45 void disable();
46 bool enabled() const;
47 std::chrono::milliseconds delay() const;
48 std::chrono::milliseconds interval() const;
49 void press(int32_t code);
50 void release(int32_t code);
51
52private:
53 void handle_timeout();
54 TimerFdFactory const& timers;
55 bool enabled_{true};
56
57 std::chrono::milliseconds repeat_delay{500};
58 std::chrono::milliseconds repeat_interval{50};
59
60 std::function<void(int32_t)> send_repeat;
61 std::unordered_set<int32_t> depressed_keys;
62 std::unique_ptr<mir::time::TimerFd> timer;
63};
64}
65}
66}
67#endif
068
=== added file 'src/platforms/evdev/steady_timer_fd_factory.cpp'
--- src/platforms/evdev/steady_timer_fd_factory.cpp 1970-01-01 00:00:00 +0000
+++ src/platforms/evdev/steady_timer_fd_factory.cpp 2016-10-12 07:29:58 +0000
@@ -0,0 +1,67 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
17 */
18
19#include "steady_timer_fd_factory.h"
20#include "mir/time/steady_timer_fd.h"
21#include "mir/dispatch/readable_fd.h"
22
23namespace mie = mir::input::evdev;
24namespace md = mir::dispatch;
25namespace mt = mir::time;
26
27namespace
28{
29
30struct DispatchableTimerFd : mt::SteadyTimerFd
31{
32public:
33 DispatchableTimerFd(md::MultiplexingDispatchable& dispatchable,
34 std::function<void()> const& callback) :
35 readable_fd{std::make_shared<md::ReadableFd>(get_fd(), callback)},
36 dispatchable{dispatchable}
37 {
38 }
39
40 void schedule_in(mir::time::Duration delay) override
41 {
42 mt::SteadyTimerFd::schedule_in(delay);
43 dispatchable.add_watch(readable_fd);
44 }
45
46 void cancel() override
47 {
48 mt::SteadyTimerFd::cancel();
49 dispatchable.remove_watch(readable_fd);
50 }
51
52private:
53 std::shared_ptr<md::ReadableFd> const readable_fd;
54 md::MultiplexingDispatchable& dispatchable;
55};
56
57}
58
59mie::SteadyTimerFdFactory::SteadyTimerFdFactory(md::MultiplexingDispatchable& dispatchable)
60 : dispatchable(dispatchable)
61{
62}
63
64std::unique_ptr<mt::TimerFd> mie::SteadyTimerFdFactory::SteadyTimerFdFactory::create_timer(std::function<void()> const& callback_on_timeout) const
65{
66 return std::make_unique<DispatchableTimerFd>(dispatchable, callback_on_timeout);
67}
068
=== added file 'src/platforms/evdev/steady_timer_fd_factory.h'
--- src/platforms/evdev/steady_timer_fd_factory.h 1970-01-01 00:00:00 +0000
+++ src/platforms/evdev/steady_timer_fd_factory.h 2016-10-12 07:29:58 +0000
@@ -0,0 +1,48 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
17 */
18
19#ifndef MIR_INPUT_EVDEV_STEADY_TIMER_FD_FACTORY_H_
20#define MIR_INPUT_EVDEV_STEADY_TIMER_FD_FACTORY_H_
21
22#include "timer_fd_factory.h"
23
24#include "mir/dispatch/multiplexing_dispatchable.h"
25#include "mir/time/timer_fd.h"
26
27#include <memory>
28
29namespace mir
30{
31namespace input
32{
33namespace evdev
34{
35struct SteadyTimerFdFactory : TimerFdFactory
36{
37public:
38 SteadyTimerFdFactory(mir::dispatch::MultiplexingDispatchable& dispatchable);
39 std::unique_ptr<mir::time::TimerFd> create_timer(std::function<void()> const& call_on_timeout) const override;
40private:
41 mir::dispatch::MultiplexingDispatchable& dispatchable;
42};
43
44}
45}
46}
47
48#endif
049
=== added file 'src/platforms/evdev/timer_fd_factory.h'
--- src/platforms/evdev/timer_fd_factory.h 1970-01-01 00:00:00 +0000
+++ src/platforms/evdev/timer_fd_factory.h 2016-10-12 07:29:58 +0000
@@ -0,0 +1,47 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
17 */
18
19#ifndef MIR_INPUT_EVDEV_TIMER_FD_FACTORY_H
20#define MIR_INPUT_EVDEV_TIMER_FD_FACTORY_H
21
22#include "mir/time/timer_fd.h"
23#include <functional>
24
25namespace mir
26{
27namespace input
28{
29namespace evdev
30{
31struct TimerFdFactory
32{
33public:
34 TimerFdFactory() = default;
35 virtual std::unique_ptr<mir::time::TimerFd> create_timer(std::function<void()> const& callback_on_timeout) const = 0;
36protected:
37 virtual ~TimerFdFactory() = default;
38private:
39 TimerFdFactory(TimerFdFactory const&) = delete;
40 TimerFdFactory& operator=(TimerFdFactory const&) = delete;
41};
42
43}
44}
45}
46
47#endif
048
=== added file 'tests/include/mir/test/doubles/fake_timer_fd_factory.h'
--- tests/include/mir/test/doubles/fake_timer_fd_factory.h 1970-01-01 00:00:00 +0000
+++ tests/include/mir/test/doubles/fake_timer_fd_factory.h 2016-10-12 07:29:58 +0000
@@ -0,0 +1,69 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
17 */
18
19#ifndef MIR_TEST_DOUBLES_FAKE_TIMER_FD_FACTORY_H_
20#define MIR_TEST_DOUBLES_FAKE_TIMER_FD_FACTORY_H_
21
22#include "mir/test/doubles/stub_timer_fd.h"
23#include "src/platforms/evdev/timer_fd_factory.h"
24
25#include "mir/time/types.h"
26
27#include <gmock/gmock.h>
28#include <memory>
29
30namespace mir
31{
32namespace test
33{
34namespace doubles
35{
36struct MockTimerFd : StubTimerFd
37{
38 MOCK_METHOD1(schedule_in, void(mir::time::Duration));
39 MOCK_METHOD0(cancel, void());
40};
41
42struct FakeTimerFdFactory : mir::input::evdev::TimerFdFactory
43{
44 using NiceTimerFd = testing::NiceMock<MockTimerFd>;
45 std::unique_ptr<NiceTimerFd> mutable prepared_timer;
46 std::function<void()> mutable execute_last_timer;
47 MOCK_CONST_METHOD2(timer_created, void(NiceTimerFd* timer, std::function<void()> const&));
48
49 inline std::unique_ptr<mir::time::TimerFd> create_timer(std::function<void()> const& callback) const override
50 {
51 execute_last_timer = callback;
52 if (!prepared_timer)
53 {
54 auto new_timer = std::make_unique<NiceTimerFd>();
55 timer_created(new_timer.get(), callback);
56 return new_timer;
57 }
58 else
59 {
60 timer_created(prepared_timer.get(), callback);
61 return std::move(prepared_timer);
62 }
63 }
64};
65}
66}
67}
68
69#endif
070
=== added file 'tests/include/mir/test/doubles/stub_timer_fd.h'
--- tests/include/mir/test/doubles/stub_timer_fd.h 1970-01-01 00:00:00 +0000
+++ tests/include/mir/test/doubles/stub_timer_fd.h 2016-10-12 07:29:58 +0000
@@ -0,0 +1,49 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
17 */
18
19#ifndef MIR_TEST_DOUBLES_STUB_TIMER_FD_H
20#define MIR_TEST_DOUBLES_STUB_TIMER_FD_H
21
22#include "mir/time/timer_fd.h"
23
24namespace mir
25{
26namespace test
27{
28namespace doubles
29{
30struct StubTimerFd : mir::time::TimerFd
31{
32 Fd const& get_fd() override
33 {
34 return fd;
35 }
36 void schedule_in(mir::time::Duration) override
37 {
38 }
39 void cancel() override
40 {
41 }
42
43 mir::Fd fd{IntOwnedFd{-1}};
44};
45}
46}
47}
48
49#endif
050
=== modified file 'tests/unit-tests/input/CMakeLists.txt'
--- tests/unit-tests/input/CMakeLists.txt 2016-07-18 07:38:38 +0000
+++ tests/unit-tests/input/CMakeLists.txt 2016-10-12 07:29:58 +0000
@@ -18,6 +18,7 @@
18 ${CMAKE_CURRENT_SOURCE_DIR}/test_key_repeat_dispatcher.cpp18 ${CMAKE_CURRENT_SOURCE_DIR}/test_key_repeat_dispatcher.cpp
19 ${CMAKE_CURRENT_SOURCE_DIR}/test_validator.cpp19 ${CMAKE_CURRENT_SOURCE_DIR}/test_validator.cpp
20 ${CMAKE_CURRENT_SOURCE_DIR}/test_nested_input_platform.cpp20 ${CMAKE_CURRENT_SOURCE_DIR}/test_nested_input_platform.cpp
21 ${CMAKE_CURRENT_SOURCE_DIR}/test_key_repeater.cpp
21)22)
2223
23list(APPEND UMOCK_UNIT_TEST_SOURCES24list(APPEND UMOCK_UNIT_TEST_SOURCES
2425
=== added file 'tests/unit-tests/input/test_key_repeater.cpp'
--- tests/unit-tests/input/test_key_repeater.cpp 1970-01-01 00:00:00 +0000
+++ tests/unit-tests/input/test_key_repeater.cpp 2016-10-12 07:29:58 +0000
@@ -0,0 +1,138 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
17 */
18
19#include "src/platforms/evdev/key_repeater.h"
20#include "mir/test/doubles/fake_timer_fd_factory.h"
21#include "mir/test/fake_shared.h"
22
23#include <gtest/gtest.h>
24#include <gmock/gmock.h>
25
26#include <memory>
27#include <chrono>
28
29namespace mt = mir::test;
30namespace mtd = mt::doubles;
31namespace mie = mir::input::evdev;
32
33using namespace ::testing;
34using namespace std::chrono_literals;
35
36namespace
37{
38struct KeyRepeater : Test
39{
40 MOCK_METHOD1(repeat_called, void(int32_t));
41
42 NiceMock<mtd::FakeTimerFdFactory> fake_timers;
43 mie::KeyRepeater repeater{
44 fake_timers,
45 [this](int32_t code)
46 {
47 repeat_called(code);
48 }};
49
50 const int32_t a_key = 32;
51 const int32_t another_key = 10;
52 const int32_t third_key = 54;
53};
54}
55
56TEST_F(KeyRepeater, no_repeat_alarm_when_disabled)
57{
58 repeater.disable();
59 EXPECT_CALL(fake_timers, timer_created(_,_)).Times(0);
60
61 repeater.press(a_key);
62 repeater.release(a_key);
63}
64
65TEST_F(KeyRepeater, repeat_enabled_by_default)
66{
67 EXPECT_THAT(repeater.enabled(), Eq(true));
68}
69
70TEST_F(KeyRepeater, alarm_canceled_on_disable)
71{
72 fake_timers.prepared_timer = std::make_unique<mtd::FakeTimerFdFactory::NiceTimerFd>();
73 EXPECT_CALL(*fake_timers.prepared_timer.get(), cancel()).Times(1);
74
75 repeater.press(a_key);
76 repeater.disable();
77}
78
79TEST_F(KeyRepeater, alarm_canceled_on_release)
80{
81 fake_timers.prepared_timer = std::make_unique<NiceMock<mtd::MockTimerFd>>();
82 EXPECT_CALL(*fake_timers.prepared_timer.get(), schedule_in(_));
83 EXPECT_CALL(*fake_timers.prepared_timer.get(), cancel());
84
85 repeater.press(a_key);
86 repeater.release(a_key);
87}
88
89TEST_F(KeyRepeater, alarm_rescheduled_on_timeout)
90{
91 fake_timers.prepared_timer = std::make_unique<NiceMock<mtd::MockTimerFd>>();
92 std::function<void()> timer_callback;
93 mir::time::Duration const delay = 50ms;
94 mir::time::Duration const interval = 10ms;
95 EXPECT_CALL(*fake_timers.prepared_timer.get(), schedule_in(delay));
96 EXPECT_CALL(*fake_timers.prepared_timer.get(), schedule_in(interval));
97
98 repeater.enable(50ms, 10ms);
99 repeater.press(a_key);
100 fake_timers.execute_last_timer();
101}
102
103TEST_F(KeyRepeater, callback_called_on_timeout)
104{
105 EXPECT_CALL(*this, repeat_called(a_key)).Times(1);
106
107 repeater.press(a_key);
108 fake_timers.execute_last_timer();
109}
110
111TEST_F(KeyRepeater, one_alarm_for_all_keys)
112{
113 EXPECT_CALL(fake_timers, timer_created(_,_)).Times(1);
114 repeater.press(a_key);
115 repeater.press(another_key);
116}
117
118TEST_F(KeyRepeater, alarm_canceld_on_release_of_last_key)
119{
120 fake_timers.prepared_timer = std::make_unique<NiceMock<mtd::MockTimerFd>>();
121 auto & prepared_timer = *fake_timers.prepared_timer.get();
122 EXPECT_CALL(fake_timers, timer_created(_,_)).Times(1);
123 EXPECT_CALL(prepared_timer, schedule_in(_)).Times(1);
124 EXPECT_CALL(prepared_timer, cancel()).Times(0);
125 repeater.press(a_key);
126 repeater.press(another_key);
127 repeater.press(third_key);
128 testing::Mock::VerifyAndClear(&prepared_timer);
129
130 EXPECT_CALL(prepared_timer, cancel()).Times(0);
131 repeater.release(another_key);
132 repeater.release(a_key);
133
134 testing::Mock::VerifyAndClear(&prepared_timer);
135
136 EXPECT_CALL(prepared_timer, cancel()).Times(1);
137 repeater.release(third_key);
138}

Subscribers

People subscribed via source and target branches