Merge lp:~andreas-pokorny/mir/move-key-repeat-into-input-platforms into lp:mir
- move-key-repeat-into-input-platforms
- Merge into development-branch
Status: | Work in progress |
---|---|
Proposed branch: | lp:~andreas-pokorny/mir/move-key-repeat-into-input-platforms |
Merge into: | lp:mir |
Prerequisite: | lp:~andreas-pokorny/mir/add-key-repeat-utility |
Diff against target: |
1902 lines (+514/-581) 31 files modified
include/platform/mir/input/input_device.h (+4/-0) include/platform/mir/input/keyboard_settings.h (+42/-0) src/platforms/evdev/key_repeater.cpp (+2/-0) src/platforms/evdev/key_repeater.h (+1/-0) src/platforms/evdev/libinput_device.cpp (+45/-5) src/platforms/evdev/libinput_device.h (+15/-5) src/platforms/evdev/platform.cpp (+15/-7) src/platforms/evdev/platform.h (+7/-0) src/platforms/mesa/server/x11/input/input_device.cpp (+52/-3) src/platforms/mesa/server/x11/input/input_device.h (+5/-1) src/platforms/mesa/server/x11/input/input_platform.cpp (+9/-12) src/server/input/CMakeLists.txt (+0/-1) src/server/input/default_configuration.cpp (+7/-26) src/server/input/default_input_device_hub.cpp (+12/-2) src/server/input/default_input_device_hub.h (+3/-1) src/server/input/key_repeat_dispatcher.cpp (+0/-186) src/server/input/key_repeat_dispatcher.h (+0/-84) tests/include/mir/test/doubles/mock_input_device.h (+3/-0) tests/include/mir/test/doubles/mock_x11.h (+8/-0) tests/include/mir_test_framework/stub_input_platform.h (+15/-0) tests/mir_test_doubles/mock_input_device.cpp (+8/-0) tests/mir_test_doubles/mock_x11.cpp (+35/-0) tests/mir_test_framework/fake_input_device_impl.cpp (+54/-14) tests/mir_test_framework/fake_input_device_impl.h (+15/-1) tests/mir_test_framework/stub_input_platform.cpp (+21/-0) tests/unit-tests/input/CMakeLists.txt (+0/-1) tests/unit-tests/input/evdev/test_evdev_device_detection.cpp (+8/-1) tests/unit-tests/input/evdev/test_libinput_device.cpp (+42/-10) tests/unit-tests/input/test_default_device.cpp (+6/-37) tests/unit-tests/input/test_key_repeat_dispatcher.cpp (+0/-184) tests/unit-tests/input/test_x11_platform.cpp (+80/-0) |
To merge this branch: | bzr merge lp:~andreas-pokorny/mir/move-key-repeat-into-input-platforms |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Daniel van Vugt | Needs Information | ||
Kevin DuBois (community) | Approve | ||
Mir CI Bot | continuous-integration | Needs Fixing | |
Brandon Schaefer (community) | Approve | ||
Review via email: mp+289963@code.launchpad.net |
Commit message
Introduces KeyboardSettings to configure key repeat and moves the responsibility out to input platforms
X11 forwards the settings to Xkb, while evdev and stub input implement the repeat handling via the KeyRepeater introduced in a previous change. With that the key repeat is also closer to be being runtime configureable. (wiring to mir::input::Device or the client API still outstanding).
Description of the change
This moves the key repeat tracking into the input platform. With that the dynamic_
Kludge: The mir option MIR_SERVER_
Mir CI Bot (mir-ci-bot) wrote : | # |
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3421
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Brandon Schaefer (brandontschaefer) wrote : | # |
Yay for deleting code!
+ std::shared_
+ : report{report},
+ std::unique_
+ : report(report),
+mix::XInputDev
+ : display{display}, info(device_info)
+ std::shared_
+ : x11_connection{
The : needs to go on the same line as the ctor (at lease according to the coding style). I see most of those were on the init list line before this branch. Feel free to fix them (just a nit).
+class Alarm;
I dont see that namespace used? (Unless i missed it :). Do we need this forward dec?
Do we just not care about the key_code here?
sink->
Changes make sense.
- 3422. By Andreas Pokorny
-
removed fwd decl
Andreas Pokorny (andreas-pokorny) wrote : | # |
> Yay for deleting code!
>
> + std::shared_
> clock)
> + : report{report},
>
> + std::unique_
> + : report(report),
>
> +mix::XInputDev
> std::shared_
> + : display{display}, info(device_info)
>
> + std::shared_
> + : x11_connection{
>
> The : needs to go on the same line as the ctor (at lease according to the
> coding style). I see most of those were on the init list line before this
> branch. Feel free to fix them (just a nit).
We have both variants in the style guide - for some reason our current clang-format setup seems to prefer the version above..
>
> +class Alarm;
> I dont see that namespace used? (Unless i missed it :). Do we need this
> forward dec?
ack removed.
> Do we just not care about the key_code here?
> sink->handle_
> mir_keyboard_
I guess testing that the actual key code is repeated might be reasonable thing to test..
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3422
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Brandon Schaefer (brandontschaefer) wrote : | # |
(Besides the conflicts, this looks good to me :)
- 3423. By Andreas Pokorny
-
merge prereq
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3423
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Kevin DuBois (kdub) wrote : | # |
nits:
+ KeyboardSettings() {}
not needed
1122: + settings.
why indent further?
1031: braces around multiline if/else
lgtm otherwise
Daniel van Vugt (vanvugt) wrote : | # |
The prerequisite branch is on hold. So should that make this one on hold too?
Unmerged revisions
- 3423. By Andreas Pokorny
-
merge prereq
- 3422. By Andreas Pokorny
-
removed fwd decl
- 3421. By Andreas Pokorny
-
update libinput test fixture
- 3420. By Andreas Pokorny
-
Update X11 Unit tests
- 3419. By Andreas Pokorny
-
add missing file - KeyboardSettings
- 3418. By Andreas Pokorny
-
merge prereq
- 3417. By Andreas Pokorny
-
Integrate Key repeater into stub intput platform
- 3416. By Andreas Pokorny
-
Integrate Key Repeater
- 3415. By Andreas Pokorny
-
Add Key repeat utility
Similar to the key press tracking in KeyRepeatDispat
cher, this class will support the evdev platform and fake input devices in implementing repeat handling. - 3414. By Andreas Pokorny
-
Add mir::dispatch:
:AlarmFactory Implementation of mir::time:
:AlarmFactory that works with mir::dispatch: :Dispatchable and supports all the state transitions required by the test suite accumulated in test_glib_ main_loop. cpp. With this change several GPL interfaces defined inside the mirserver API have been moved to mircommon and LGPL.
Preview Diff
1 | === modified file 'include/platform/mir/input/input_device.h' | |||
2 | --- include/platform/mir/input/input_device.h 2016-01-29 08:18:22 +0000 | |||
3 | +++ include/platform/mir/input/input_device.h 2016-03-31 19:18:58 +0000 | |||
4 | @@ -39,6 +39,7 @@ | |||
5 | 39 | 39 | ||
6 | 40 | class PointerSettings; | 40 | class PointerSettings; |
7 | 41 | class TouchpadSettings; | 41 | class TouchpadSettings; |
8 | 42 | class KeyboardSettings; | ||
9 | 42 | 43 | ||
10 | 43 | /** | 44 | /** |
11 | 44 | * Represents an input device. | 45 | * Represents an input device. |
12 | @@ -65,6 +66,9 @@ | |||
13 | 65 | 66 | ||
14 | 66 | virtual optional_value<TouchpadSettings> get_touchpad_settings() const = 0; | 67 | virtual optional_value<TouchpadSettings> get_touchpad_settings() const = 0; |
15 | 67 | virtual void apply_settings(TouchpadSettings const&) = 0; | 68 | virtual void apply_settings(TouchpadSettings const&) = 0; |
16 | 69 | |||
17 | 70 | virtual optional_value<KeyboardSettings> get_keyboard_settings() const = 0; | ||
18 | 71 | virtual void apply_settings(KeyboardSettings const&) = 0; | ||
19 | 68 | protected: | 72 | protected: |
20 | 69 | InputDevice(InputDevice const&) = delete; | 73 | InputDevice(InputDevice const&) = delete; |
21 | 70 | InputDevice& operator=(InputDevice const&) = delete; | 74 | InputDevice& operator=(InputDevice const&) = delete; |
22 | 71 | 75 | ||
23 | === added file 'include/platform/mir/input/keyboard_settings.h' | |||
24 | --- include/platform/mir/input/keyboard_settings.h 1970-01-01 00:00:00 +0000 | |||
25 | +++ include/platform/mir/input/keyboard_settings.h 2016-03-31 19:18:58 +0000 | |||
26 | @@ -0,0 +1,42 @@ | |||
27 | 1 | /* | ||
28 | 2 | * Copyright © 2016 Canonical Ltd. | ||
29 | 3 | * | ||
30 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
31 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
32 | 6 | * as published by the Free Software Foundation. | ||
33 | 7 | * | ||
34 | 8 | * This program is distributed in the hope that it will be useful, | ||
35 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
36 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
37 | 11 | * GNU Lesser General Public License for more details. | ||
38 | 12 | * | ||
39 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
40 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
41 | 15 | * | ||
42 | 16 | * Authored by: | ||
43 | 17 | * Andreas Pokorny <andreas.pokorny@canonical.com> | ||
44 | 18 | */ | ||
45 | 19 | |||
46 | 20 | #ifndef MIR_INPUT_KEY_BOARD_SETTINGS_H_ | ||
47 | 21 | #define MIR_INPUT_KEY_BOARD_SETTINGS_H_ | ||
48 | 22 | |||
49 | 23 | #include "mir_toolkit/mir_input_device.h" | ||
50 | 24 | #include <chrono> | ||
51 | 25 | |||
52 | 26 | namespace mir | ||
53 | 27 | { | ||
54 | 28 | namespace input | ||
55 | 29 | { | ||
56 | 30 | |||
57 | 31 | struct KeyboardSettings | ||
58 | 32 | { | ||
59 | 33 | KeyboardSettings() {} | ||
60 | 34 | bool repeat_enabled{true}; | ||
61 | 35 | std::chrono::milliseconds repeat_delay{50}; | ||
62 | 36 | std::chrono::milliseconds repeat_interval{500}; | ||
63 | 37 | }; | ||
64 | 38 | |||
65 | 39 | } | ||
66 | 40 | } | ||
67 | 41 | |||
68 | 42 | #endif | ||
69 | 0 | 43 | ||
70 | === modified file 'src/platforms/evdev/key_repeater.cpp' | |||
71 | --- src/platforms/evdev/key_repeater.cpp 2016-03-31 19:18:58 +0000 | |||
72 | +++ src/platforms/evdev/key_repeater.cpp 2016-03-31 19:18:58 +0000 | |||
73 | @@ -29,6 +29,8 @@ | |||
74 | 29 | { | 29 | { |
75 | 30 | } | 30 | } |
76 | 31 | 31 | ||
77 | 32 | mie::KeyRepeater::~KeyRepeater() = default; | ||
78 | 33 | |||
79 | 32 | void mie::KeyRepeater::enable(std::chrono::milliseconds repeat_delay, std::chrono::milliseconds repeat_interval) | 34 | void mie::KeyRepeater::enable(std::chrono::milliseconds repeat_delay, std::chrono::milliseconds repeat_interval) |
80 | 33 | { | 35 | { |
81 | 34 | enabled_ = true; | 36 | enabled_ = true; |
82 | 35 | 37 | ||
83 | === modified file 'src/platforms/evdev/key_repeater.h' | |||
84 | --- src/platforms/evdev/key_repeater.h 2016-03-31 19:18:58 +0000 | |||
85 | +++ src/platforms/evdev/key_repeater.h 2016-03-31 19:18:58 +0000 | |||
86 | @@ -39,6 +39,7 @@ | |||
87 | 39 | struct KeyRepeater | 39 | struct KeyRepeater |
88 | 40 | { | 40 | { |
89 | 41 | KeyRepeater(std::shared_ptr<mir::time::AlarmFactory> const& alarm_factory, std::function<void(int32_t keycode)> const& send_repeat_key); | 41 | KeyRepeater(std::shared_ptr<mir::time::AlarmFactory> const& alarm_factory, std::function<void(int32_t keycode)> const& send_repeat_key); |
90 | 42 | ~KeyRepeater(); | ||
91 | 42 | void enable(std::chrono::milliseconds repeat_delay, std::chrono::milliseconds repeat_interval); | 43 | void enable(std::chrono::milliseconds repeat_delay, std::chrono::milliseconds repeat_interval); |
92 | 43 | void disable(); | 44 | void disable(); |
93 | 44 | bool enabled() const; | 45 | bool enabled() const; |
94 | 45 | 46 | ||
95 | === modified file 'src/platforms/evdev/libinput_device.cpp' | |||
96 | --- src/platforms/evdev/libinput_device.cpp 2016-03-23 06:39:56 +0000 | |||
97 | +++ src/platforms/evdev/libinput_device.cpp 2016-03-31 19:18:58 +0000 | |||
98 | @@ -27,11 +27,11 @@ | |||
99 | 27 | #include "mir/input/device_capability.h" | 27 | #include "mir/input/device_capability.h" |
100 | 28 | #include "mir/input/pointer_settings.h" | 28 | #include "mir/input/pointer_settings.h" |
101 | 29 | #include "mir/input/touchpad_settings.h" | 29 | #include "mir/input/touchpad_settings.h" |
102 | 30 | #include "mir/input/keyboard_settings.h" | ||
103 | 30 | #include "mir/input/input_device_info.h" | 31 | #include "mir/input/input_device_info.h" |
104 | 31 | #include "mir/events/event_builders.h" | 32 | #include "mir/events/event_builders.h" |
105 | 32 | #include "mir/geometry/displacement.h" | 33 | #include "mir/geometry/displacement.h" |
108 | 33 | #include "mir/dispatch/dispatchable.h" | 34 | #include "mir/time/clock.h" |
107 | 34 | #include "mir/fd.h" | ||
109 | 35 | #define MIR_LOG_COMPONENT "evdev" | 35 | #define MIR_LOG_COMPONENT "evdev" |
110 | 36 | #include "mir/log.h" | 36 | #include "mir/log.h" |
111 | 37 | #include "mir/raii.h" | 37 | #include "mir/raii.h" |
112 | @@ -45,13 +45,19 @@ | |||
113 | 45 | #include <sstream> | 45 | #include <sstream> |
114 | 46 | #include <algorithm> | 46 | #include <algorithm> |
115 | 47 | 47 | ||
116 | 48 | namespace md = mir::dispatch; | ||
117 | 49 | namespace mi = mir::input; | 48 | namespace mi = mir::input; |
118 | 50 | namespace mie = mi::evdev; | 49 | namespace mie = mi::evdev; |
119 | 51 | using namespace std::literals::chrono_literals; | 50 | using namespace std::literals::chrono_literals; |
120 | 52 | 51 | ||
123 | 53 | mie::LibInputDevice::LibInputDevice(std::shared_ptr<mi::InputReport> const& report, LibInputDevicePtr dev) | 52 | mie::LibInputDevice::LibInputDevice(std::shared_ptr<mi::InputReport> const& report, |
124 | 54 | : report{report}, pointer_pos{0, 0}, button_state{0} | 53 | LibInputDevicePtr dev, |
125 | 54 | std::shared_ptr<mir::time::AlarmFactory> const& alarm_factory, | ||
126 | 55 | std::shared_ptr<mir::time::Clock> const& clock) | ||
127 | 56 | : report{report}, | ||
128 | 57 | repeater{alarm_factory, [this](auto code) { this->handle_repeat(code); }}, | ||
129 | 58 | clock{clock}, | ||
130 | 59 | pointer_pos{0, 0}, | ||
131 | 60 | button_state{0} | ||
132 | 55 | { | 61 | { |
133 | 56 | add_device_of_group(std::move(dev)); | 62 | add_device_of_group(std::move(dev)); |
134 | 57 | } | 63 | } |
135 | @@ -135,6 +141,11 @@ | |||
136 | 135 | auto const code = libinput_event_keyboard_get_key(keyboard); | 141 | auto const code = libinput_event_keyboard_get_key(keyboard); |
137 | 136 | report->received_event_from_kernel(time.count(), EV_KEY, code, action); | 142 | report->received_event_from_kernel(time.count(), EV_KEY, code, action); |
138 | 137 | 143 | ||
139 | 144 | if (action == mir_keyboard_action_down) | ||
140 | 145 | repeater.press(code); | ||
141 | 146 | else | ||
142 | 147 | repeater.release(code); | ||
143 | 148 | |||
144 | 138 | return builder->key_event(time, action, xkb_keysym_t{0}, code); | 149 | return builder->key_event(time, action, xkb_keysym_t{0}, code); |
145 | 139 | } | 150 | } |
146 | 140 | 151 | ||
147 | @@ -476,3 +487,32 @@ | |||
148 | 476 | LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED : | 487 | LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED : |
149 | 477 | LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED); | 488 | LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED); |
150 | 478 | } | 489 | } |
151 | 490 | |||
152 | 491 | mir::optional_value<mi::KeyboardSettings> mie::LibInputDevice::get_keyboard_settings() const | ||
153 | 492 | { | ||
154 | 493 | if (!contains(info.capabilities, mi::DeviceCapability::keyboard)) | ||
155 | 494 | return {}; | ||
156 | 495 | mi::KeyboardSettings settings; | ||
157 | 496 | |||
158 | 497 | settings.repeat_enabled = repeater.enabled(); | ||
159 | 498 | settings.repeat_delay = repeater.delay(); | ||
160 | 499 | settings.repeat_interval = repeater.interval(); | ||
161 | 500 | return settings; | ||
162 | 501 | } | ||
163 | 502 | |||
164 | 503 | void mie::LibInputDevice::apply_settings(mi::KeyboardSettings const& settings) | ||
165 | 504 | { | ||
166 | 505 | if (!contains(info.capabilities, mi::DeviceCapability::keyboard)) | ||
167 | 506 | return; | ||
168 | 507 | |||
169 | 508 | if (settings.repeat_enabled) | ||
170 | 509 | repeater.enable(settings.repeat_delay, settings.repeat_interval); | ||
171 | 510 | else | ||
172 | 511 | repeater.disable(); | ||
173 | 512 | } | ||
174 | 513 | |||
175 | 514 | void mie::LibInputDevice::handle_repeat(int32_t code) | ||
176 | 515 | { | ||
177 | 516 | auto const event_time = clock->now().time_since_epoch(); | ||
178 | 517 | sink->handle_input(*builder->key_event(event_time, mir_keyboard_action_repeat, 0, code)); | ||
179 | 518 | } | ||
180 | 479 | 519 | ||
181 | === modified file 'src/platforms/evdev/libinput_device.h' | |||
182 | --- src/platforms/evdev/libinput_device.h 2016-03-23 06:39:56 +0000 | |||
183 | +++ src/platforms/evdev/libinput_device.h 2016-03-31 19:18:58 +0000 | |||
184 | @@ -21,6 +21,7 @@ | |||
185 | 21 | 21 | ||
186 | 22 | #include "libinput_ptr.h" | 22 | #include "libinput_ptr.h" |
187 | 23 | #include "libinput_device_ptr.h" | 23 | #include "libinput_device_ptr.h" |
188 | 24 | #include "key_repeater.h" | ||
189 | 24 | 25 | ||
190 | 25 | #include "mir/input/event_builder.h" | 26 | #include "mir/input/event_builder.h" |
191 | 26 | #include "mir/input/input_device.h" | 27 | #include "mir/input/input_device.h" |
192 | @@ -38,18 +39,23 @@ | |||
193 | 38 | 39 | ||
194 | 39 | namespace mir | 40 | namespace mir |
195 | 40 | { | 41 | { |
196 | 42 | namespace time | ||
197 | 43 | { | ||
198 | 44 | class Clock; | ||
199 | 45 | class AlarmFactory; | ||
200 | 46 | } | ||
201 | 41 | namespace input | 47 | namespace input |
202 | 42 | { | 48 | { |
203 | 43 | class InputReport; | 49 | class InputReport; |
204 | 44 | namespace evdev | 50 | namespace evdev |
205 | 45 | { | 51 | { |
206 | 46 | struct PointerState; | ||
207 | 47 | struct KeyboardState; | ||
208 | 48 | 52 | ||
209 | 49 | class LibInputDevice : public input::InputDevice | 53 | class LibInputDevice : public input::InputDevice |
210 | 50 | { | 54 | { |
211 | 51 | public: | 55 | public: |
213 | 52 | LibInputDevice(std::shared_ptr<InputReport> const& report, LibInputDevicePtr dev); | 56 | LibInputDevice(std::shared_ptr<InputReport> const& report, LibInputDevicePtr dev, |
214 | 57 | std::shared_ptr<mir::time::AlarmFactory> const& alarm_factory, | ||
215 | 58 | std::shared_ptr<mir::time::Clock> const& clock); | ||
216 | 53 | ~LibInputDevice(); | 59 | ~LibInputDevice(); |
217 | 54 | void start(InputSink* sink, EventBuilder* builder) override; | 60 | void start(InputSink* sink, EventBuilder* builder) override; |
218 | 55 | void stop() override; | 61 | void stop() override; |
219 | @@ -58,6 +64,8 @@ | |||
220 | 58 | void apply_settings(PointerSettings const&) override; | 64 | void apply_settings(PointerSettings const&) override; |
221 | 59 | optional_value<TouchpadSettings> get_touchpad_settings() const override; | 65 | optional_value<TouchpadSettings> get_touchpad_settings() const override; |
222 | 60 | void apply_settings(TouchpadSettings const&) override; | 66 | void apply_settings(TouchpadSettings const&) override; |
223 | 67 | optional_value<KeyboardSettings> get_keyboard_settings() const override; | ||
224 | 68 | void apply_settings(KeyboardSettings const&) override; | ||
225 | 61 | 69 | ||
226 | 62 | void process_event(libinput_event* event); | 70 | void process_event(libinput_event* event); |
227 | 63 | ::libinput_device* device() const; | 71 | ::libinput_device* device() const; |
228 | @@ -75,10 +83,11 @@ | |||
229 | 75 | void handle_touch_motion(libinput_event_touch* touch); | 83 | void handle_touch_motion(libinput_event_touch* touch); |
230 | 76 | void update_device_info(); | 84 | void update_device_info(); |
231 | 77 | 85 | ||
233 | 78 | std::shared_ptr<InputReport> report; | 86 | std::shared_ptr<InputReport> const report; |
234 | 87 | KeyRepeater repeater; | ||
235 | 88 | std::shared_ptr<mir::time::Clock> const clock; | ||
236 | 79 | std::shared_ptr<::libinput> lib; | 89 | std::shared_ptr<::libinput> lib; |
237 | 80 | std::vector<LibInputDevicePtr> devices; | 90 | std::vector<LibInputDevicePtr> devices; |
238 | 81 | std::shared_ptr<dispatch::Dispatchable> dispatchable_fd; | ||
239 | 82 | 91 | ||
240 | 83 | InputSink* sink{nullptr}; | 92 | InputSink* sink{nullptr}; |
241 | 84 | EventBuilder* builder{nullptr}; | 93 | EventBuilder* builder{nullptr}; |
242 | @@ -98,6 +107,7 @@ | |||
243 | 98 | std::map<MirTouchId,ContactData> last_seen_properties; | 107 | std::map<MirTouchId,ContactData> last_seen_properties; |
244 | 99 | 108 | ||
245 | 100 | void update_contact_data(ContactData &data, MirTouchAction action, libinput_event_touch* touch); | 109 | void update_contact_data(ContactData &data, MirTouchAction action, libinput_event_touch* touch); |
246 | 110 | void handle_repeat(int32_t code); | ||
247 | 101 | }; | 111 | }; |
248 | 102 | } | 112 | } |
249 | 103 | } | 113 | } |
250 | 104 | 114 | ||
251 | === modified file 'src/platforms/evdev/platform.cpp' | |||
252 | --- src/platforms/evdev/platform.cpp 2016-03-23 06:39:56 +0000 | |||
253 | +++ src/platforms/evdev/platform.cpp 2016-03-31 19:18:58 +0000 | |||
254 | @@ -22,7 +22,10 @@ | |||
255 | 22 | #include "mir/udev/wrapper.h" | 22 | #include "mir/udev/wrapper.h" |
256 | 23 | #include "mir/dispatch/dispatchable.h" | 23 | #include "mir/dispatch/dispatchable.h" |
257 | 24 | #include "mir/dispatch/readable_fd.h" | 24 | #include "mir/dispatch/readable_fd.h" |
258 | 25 | #include "mir/dispatch/alarm_factory.h" | ||
259 | 25 | #include "mir/dispatch/multiplexing_dispatchable.h" | 26 | #include "mir/dispatch/multiplexing_dispatchable.h" |
260 | 27 | #include "mir/time/steady_clock.h" | ||
261 | 28 | #include "mir/time/steady_timer_fd.h" | ||
262 | 26 | #include "mir/module_properties.h" | 29 | #include "mir/module_properties.h" |
263 | 27 | #include "mir/assert_module_entry_point.h" | 30 | #include "mir/assert_module_entry_point.h" |
264 | 28 | 31 | ||
265 | @@ -43,6 +46,7 @@ | |||
266 | 43 | 46 | ||
267 | 44 | namespace mi = mir::input; | 47 | namespace mi = mir::input; |
268 | 45 | namespace md = mir::dispatch; | 48 | namespace md = mir::dispatch; |
269 | 49 | namespace mt = mir::time; | ||
270 | 46 | namespace mu = mir::udev; | 50 | namespace mu = mir::udev; |
271 | 47 | namespace mie = mi::evdev; | 51 | namespace mie = mi::evdev; |
272 | 48 | 52 | ||
273 | @@ -68,12 +72,14 @@ | |||
274 | 68 | } // namespace | 72 | } // namespace |
275 | 69 | 73 | ||
276 | 70 | mie::Platform::Platform(std::shared_ptr<InputDeviceRegistry> const& registry, | 74 | mie::Platform::Platform(std::shared_ptr<InputDeviceRegistry> const& registry, |
283 | 71 | std::shared_ptr<InputReport> const& report, | 75 | std::shared_ptr<InputReport> const& report, |
284 | 72 | std::unique_ptr<udev::Context>&& udev_context) : | 76 | std::unique_ptr<udev::Context>&& udev_context) |
285 | 73 | report(report), | 77 | : report(report), |
286 | 74 | udev_context(std::move(udev_context)), | 78 | udev_context(std::move(udev_context)), |
287 | 75 | input_device_registry(registry), | 79 | input_device_registry(registry), |
288 | 76 | platform_dispatchable{std::make_shared<md::MultiplexingDispatchable>()} | 80 | platform_dispatchable{std::make_shared<md::MultiplexingDispatchable>()}, |
289 | 81 | clock{std::make_shared<mt::SteadyClock>()}, | ||
290 | 82 | alarm_factory{std::make_shared<md::AlarmFactory>(clock, std::make_shared<mt::SteadyTimerFd>())} | ||
291 | 77 | { | 83 | { |
292 | 78 | } | 84 | } |
293 | 79 | 85 | ||
294 | @@ -91,6 +97,7 @@ | |||
295 | 91 | Fd{IntOwnedFd{libinput_get_fd(lib.get())}}, [this]{process_input_events();} | 97 | Fd{IntOwnedFd{libinput_get_fd(lib.get())}}, [this]{process_input_events();} |
296 | 92 | ); | 98 | ); |
297 | 93 | platform_dispatchable->add_watch(libinput_dispatchable); | 99 | platform_dispatchable->add_watch(libinput_dispatchable); |
298 | 100 | platform_dispatchable->add_watch(alarm_factory); | ||
299 | 94 | } | 101 | } |
300 | 95 | 102 | ||
301 | 96 | void mie::Platform::process_input_events() | 103 | void mie::Platform::process_input_events() |
302 | @@ -145,7 +152,7 @@ | |||
303 | 145 | 152 | ||
304 | 146 | try | 153 | try |
305 | 147 | { | 154 | { |
307 | 148 | devices.emplace_back(std::make_shared<mie::LibInputDevice>(report, move(device_ptr))); | 155 | devices.emplace_back(std::make_shared<mie::LibInputDevice>(report, move(device_ptr), alarm_factory, clock)); |
308 | 149 | 156 | ||
309 | 150 | input_device_registry->add_device(devices.back()); | 157 | input_device_registry->add_device(devices.back()); |
310 | 151 | 158 | ||
311 | @@ -186,6 +193,7 @@ | |||
312 | 186 | 193 | ||
313 | 187 | void mie::Platform::stop() | 194 | void mie::Platform::stop() |
314 | 188 | { | 195 | { |
315 | 196 | platform_dispatchable->remove_watch(alarm_factory); | ||
316 | 189 | platform_dispatchable->remove_watch(libinput_dispatchable); | 197 | platform_dispatchable->remove_watch(libinput_dispatchable); |
317 | 190 | while (!devices.empty()) | 198 | while (!devices.empty()) |
318 | 191 | { | 199 | { |
319 | 192 | 200 | ||
320 | === modified file 'src/platforms/evdev/platform.h' | |||
321 | --- src/platforms/evdev/platform.h 2016-03-23 06:39:56 +0000 | |||
322 | +++ src/platforms/evdev/platform.h 2016-03-31 19:18:58 +0000 | |||
323 | @@ -37,10 +37,15 @@ | |||
324 | 37 | class Monitor; | 37 | class Monitor; |
325 | 38 | class Context; | 38 | class Context; |
326 | 39 | } | 39 | } |
327 | 40 | namespace time | ||
328 | 41 | { | ||
329 | 42 | class Clock; | ||
330 | 43 | } | ||
331 | 40 | namespace dispatch | 44 | namespace dispatch |
332 | 41 | { | 45 | { |
333 | 42 | class MultiplexingDispatchable; | 46 | class MultiplexingDispatchable; |
334 | 43 | class ReadableFd; | 47 | class ReadableFd; |
335 | 48 | class AlarmFactory; | ||
336 | 44 | } | 49 | } |
337 | 45 | namespace input | 50 | namespace input |
338 | 46 | { | 51 | { |
339 | @@ -73,6 +78,8 @@ | |||
340 | 73 | std::shared_ptr<udev::Context> const udev_context; | 78 | std::shared_ptr<udev::Context> const udev_context; |
341 | 74 | std::shared_ptr<InputDeviceRegistry> const input_device_registry; | 79 | std::shared_ptr<InputDeviceRegistry> const input_device_registry; |
342 | 75 | std::shared_ptr<dispatch::MultiplexingDispatchable> const platform_dispatchable; | 80 | std::shared_ptr<dispatch::MultiplexingDispatchable> const platform_dispatchable; |
343 | 81 | std::shared_ptr<time::Clock> const clock; | ||
344 | 82 | std::shared_ptr<dispatch::AlarmFactory> const alarm_factory; | ||
345 | 76 | std::shared_ptr<::libinput> lib; | 83 | std::shared_ptr<::libinput> lib; |
346 | 77 | std::shared_ptr<dispatch::ReadableFd> libinput_dispatchable; | 84 | std::shared_ptr<dispatch::ReadableFd> libinput_dispatchable; |
347 | 78 | 85 | ||
348 | 79 | 86 | ||
349 | === modified file 'src/platforms/mesa/server/x11/input/input_device.cpp' | |||
350 | --- src/platforms/mesa/server/x11/input/input_device.cpp 2016-03-23 06:39:56 +0000 | |||
351 | +++ src/platforms/mesa/server/x11/input/input_device.cpp 2016-03-31 19:18:58 +0000 | |||
352 | @@ -20,13 +20,16 @@ | |||
353 | 20 | 20 | ||
354 | 21 | #include "mir/input/pointer_settings.h" | 21 | #include "mir/input/pointer_settings.h" |
355 | 22 | #include "mir/input/touchpad_settings.h" | 22 | #include "mir/input/touchpad_settings.h" |
356 | 23 | #include "mir/input/keyboard_settings.h" | ||
357 | 23 | #include "mir/input/input_device_info.h" | 24 | #include "mir/input/input_device_info.h" |
358 | 24 | #include "mir/input/device_capability.h" | 25 | #include "mir/input/device_capability.h" |
359 | 25 | #include "mir/input/event_builder.h" | 26 | #include "mir/input/event_builder.h" |
360 | 26 | #include "mir/input/input_sink.h" | 27 | #include "mir/input/input_sink.h" |
361 | 27 | 28 | ||
362 | 29 | #include "mir/raii.h" | ||
363 | 30 | |||
364 | 28 | #include <X11/Xlib.h> | 31 | #include <X11/Xlib.h> |
366 | 29 | #include <iostream> | 32 | #include <X11/XKBlib.h> |
367 | 30 | 33 | ||
368 | 31 | namespace mi = mir::input; | 34 | namespace mi = mir::input; |
369 | 32 | namespace geom = mir::geometry; | 35 | namespace geom = mir::geometry; |
370 | @@ -69,8 +72,8 @@ | |||
371 | 69 | 72 | ||
372 | 70 | } | 73 | } |
373 | 71 | 74 | ||
376 | 72 | mix::XInputDevice::XInputDevice(InputDeviceInfo const& device_info) | 75 | mix::XInputDevice::XInputDevice(InputDeviceInfo const& device_info, std::shared_ptr<::Display> const& display) |
377 | 73 | : info(device_info) | 76 | : display{display}, info(device_info) |
378 | 74 | { | 77 | { |
379 | 75 | } | 78 | } |
380 | 76 | 79 | ||
381 | @@ -210,3 +213,49 @@ | |||
382 | 210 | ) | 213 | ) |
383 | 211 | ); | 214 | ); |
384 | 212 | } | 215 | } |
385 | 216 | |||
386 | 217 | void mix::XInputDevice::apply_settings(mi::KeyboardSettings const& settings) | ||
387 | 218 | { | ||
388 | 219 | if (!contains(info.capabilities, mi::DeviceCapability::keyboard)) | ||
389 | 220 | return; | ||
390 | 221 | |||
391 | 222 | XKeyboardControl repeat_enabled; | ||
392 | 223 | repeat_enabled.auto_repeat_mode = settings.repeat_enabled; | ||
393 | 224 | XChangeKeyboardControl(display.get(), KBAutoRepeatMode, &repeat_enabled); | ||
394 | 225 | |||
395 | 226 | int xkbopcode, xkbevent, xkberror; | ||
396 | 227 | int xkbmajor = XkbMajorVersion, xkbminor = XkbMinorVersion; | ||
397 | 228 | if (XkbQueryExtension(display.get(), &xkbopcode, &xkbevent, &xkberror, &xkbmajor, &xkbminor)) | ||
398 | 229 | { | ||
399 | 230 | auto xkb = raii::deleter_for(XkbAllocKeyboard(), [](XkbDescPtr ptr){XkbFreeKeyboard(ptr, 0, True);}); | ||
400 | 231 | |||
401 | 232 | XkbGetControls(display.get(), XkbRepeatKeysMask, xkb.get()); | ||
402 | 233 | xkb->ctrls->repeat_delay = settings.repeat_delay.count(); | ||
403 | 234 | xkb->ctrls->repeat_interval = settings.repeat_interval.count(); | ||
404 | 235 | XkbSetControls(display.get(), XkbRepeatKeysMask, xkb.get()); | ||
405 | 236 | } | ||
406 | 237 | } | ||
407 | 238 | |||
408 | 239 | mir::optional_value<mi::KeyboardSettings> mix::XInputDevice::get_keyboard_settings() const | ||
409 | 240 | { | ||
410 | 241 | if (!contains(info.capabilities, mi::DeviceCapability::keyboard)) | ||
411 | 242 | return {}; | ||
412 | 243 | |||
413 | 244 | KeyboardSettings settings; | ||
414 | 245 | XKeyboardState repeat_enabled; | ||
415 | 246 | XGetKeyboardControl(display.get(), &repeat_enabled); | ||
416 | 247 | settings.repeat_enabled = repeat_enabled.global_auto_repeat; | ||
417 | 248 | |||
418 | 249 | int xkbopcode, xkbevent, xkberror; | ||
419 | 250 | int xkbmajor = XkbMajorVersion, xkbminor = XkbMinorVersion; | ||
420 | 251 | if (XkbQueryExtension(display.get(), &xkbopcode, &xkbevent, &xkberror, &xkbmajor, &xkbminor)) | ||
421 | 252 | { | ||
422 | 253 | auto xkb = raii::deleter_for(XkbAllocKeyboard(), [](XkbDescPtr ptr){ XkbFreeKeyboard(ptr, 0, True);}); | ||
423 | 254 | |||
424 | 255 | XkbGetControls(display.get(), XkbRepeatKeysMask, xkb.get()); | ||
425 | 256 | settings.repeat_delay = std::chrono::milliseconds{xkb->ctrls->repeat_delay}; | ||
426 | 257 | settings.repeat_interval = std::chrono::milliseconds{xkb->ctrls->repeat_interval}; | ||
427 | 258 | } | ||
428 | 259 | |||
429 | 260 | return settings; | ||
430 | 261 | } | ||
431 | 213 | 262 | ||
432 | === modified file 'src/platforms/mesa/server/x11/input/input_device.h' | |||
433 | --- src/platforms/mesa/server/x11/input/input_device.h 2016-03-23 06:39:56 +0000 | |||
434 | +++ src/platforms/mesa/server/x11/input/input_device.h 2016-03-31 19:18:58 +0000 | |||
435 | @@ -26,6 +26,7 @@ | |||
436 | 26 | #include "mir/geometry/displacement.h" | 26 | #include "mir/geometry/displacement.h" |
437 | 27 | #include "mir/optional_value.h" | 27 | #include "mir/optional_value.h" |
438 | 28 | 28 | ||
439 | 29 | #include <X11/Xlib.h> | ||
440 | 29 | #include <chrono> | 30 | #include <chrono> |
441 | 30 | 31 | ||
442 | 31 | namespace mir | 32 | namespace mir |
443 | @@ -39,7 +40,7 @@ | |||
444 | 39 | class XInputDevice : public input::InputDevice | 40 | class XInputDevice : public input::InputDevice |
445 | 40 | { | 41 | { |
446 | 41 | public: | 42 | public: |
448 | 42 | XInputDevice(InputDeviceInfo const& info); | 43 | XInputDevice(InputDeviceInfo const& info, std::shared_ptr<::Display> const& display); |
449 | 43 | 44 | ||
450 | 44 | std::shared_ptr<dispatch::Dispatchable> dispatchable(); | 45 | std::shared_ptr<dispatch::Dispatchable> dispatchable(); |
451 | 45 | void start(InputSink* destination, EventBuilder* builder) override; | 46 | void start(InputSink* destination, EventBuilder* builder) override; |
452 | @@ -50,6 +51,8 @@ | |||
453 | 50 | void apply_settings(PointerSettings const& settings) override; | 51 | void apply_settings(PointerSettings const& settings) override; |
454 | 51 | optional_value<TouchpadSettings> get_touchpad_settings() const override; | 52 | optional_value<TouchpadSettings> get_touchpad_settings() const override; |
455 | 52 | void apply_settings(TouchpadSettings const& settings) override; | 53 | void apply_settings(TouchpadSettings const& settings) override; |
456 | 54 | optional_value<KeyboardSettings> get_keyboard_settings() const override; | ||
457 | 55 | void apply_settings(KeyboardSettings const& settings) override; | ||
458 | 53 | 56 | ||
459 | 54 | bool started() const; | 57 | bool started() const; |
460 | 55 | void key_press(std::chrono::nanoseconds event_time, xkb_keysym_t key_sym, int32_t key_code); | 58 | void key_press(std::chrono::nanoseconds event_time, xkb_keysym_t key_sym, int32_t key_code); |
461 | @@ -60,6 +63,7 @@ | |||
462 | 60 | void pointer_motion(std::chrono::nanoseconds event_time, mir::geometry::Point const& pos, mir::geometry::Displacement scroll); | 63 | void pointer_motion(std::chrono::nanoseconds event_time, mir::geometry::Point const& pos, mir::geometry::Displacement scroll); |
463 | 61 | 64 | ||
464 | 62 | private: | 65 | private: |
465 | 66 | std::shared_ptr<::Display> const display; | ||
466 | 63 | MirPointerButtons button_state{0}; | 67 | MirPointerButtons button_state{0}; |
467 | 64 | InputSink* sink{nullptr}; | 68 | InputSink* sink{nullptr}; |
468 | 65 | EventBuilder* builder{nullptr}; | 69 | EventBuilder* builder{nullptr}; |
469 | 66 | 70 | ||
470 | === modified file 'src/platforms/mesa/server/x11/input/input_platform.cpp' | |||
471 | --- src/platforms/mesa/server/x11/input/input_platform.cpp 2016-03-23 06:39:56 +0000 | |||
472 | +++ src/platforms/mesa/server/x11/input/input_platform.cpp 2016-03-31 19:18:58 +0000 | |||
473 | @@ -46,18 +46,15 @@ | |||
474 | 46 | namespace mix = mi::X; | 46 | namespace mix = mi::X; |
475 | 47 | 47 | ||
476 | 48 | mix::XInputPlatform::XInputPlatform(std::shared_ptr<mi::InputDeviceRegistry> const& input_device_registry, | 48 | mix::XInputPlatform::XInputPlatform(std::shared_ptr<mi::InputDeviceRegistry> const& input_device_registry, |
489 | 49 | std::shared_ptr<::Display> const& conn) : | 49 | std::shared_ptr<::Display> const& conn) |
490 | 50 | x11_connection{conn}, | 50 | : x11_connection{conn}, |
491 | 51 | xcon_dispatchable(std::make_shared<md::ReadableFd>( | 51 | xcon_dispatchable(std::make_shared<md::ReadableFd>(mir::Fd{mir::IntOwnedFd{XConnectionNumber(conn.get())}}, |
492 | 52 | mir::Fd{mir::IntOwnedFd{XConnectionNumber(conn.get())}}, [this]() | 52 | [this]() { process_input_event(); })), |
493 | 53 | { | 53 | registry(input_device_registry), |
494 | 54 | process_input_event(); | 54 | core_keyboard(std::make_shared<mix::XInputDevice>( |
495 | 55 | })), | 55 | mi::InputDeviceInfo{"x11-keyboard-device", "x11-key-dev-1", mi::DeviceCapability::keyboard}, conn)), |
496 | 56 | registry(input_device_registry), | 56 | core_pointer(std::make_shared<mix::XInputDevice>( |
497 | 57 | core_keyboard(std::make_shared<mix::XInputDevice>( | 57 | mi::InputDeviceInfo{"x11-mouse-device", "x11-mouse-dev-1", mi::DeviceCapability::pointer}, conn)) |
486 | 58 | mi::InputDeviceInfo{"x11-keyboard-device", "x11-key-dev-1", mi::DeviceCapability::keyboard})), | ||
487 | 59 | core_pointer(std::make_shared<mix::XInputDevice>( | ||
488 | 60 | mi::InputDeviceInfo{"x11-mouse-device", "x11-mouse-dev-1", mi::DeviceCapability::pointer})) | ||
498 | 61 | { | 58 | { |
499 | 62 | } | 59 | } |
500 | 63 | 60 | ||
501 | 64 | 61 | ||
502 | === modified file 'src/server/input/CMakeLists.txt' | |||
503 | --- src/server/input/CMakeLists.txt 2016-03-23 06:39:56 +0000 | |||
504 | +++ src/server/input/CMakeLists.txt 2016-03-31 19:18:58 +0000 | |||
505 | @@ -16,7 +16,6 @@ | |||
506 | 16 | event_filter_chain_dispatcher.cpp | 16 | event_filter_chain_dispatcher.cpp |
507 | 17 | input_modifier_utils.cpp | 17 | input_modifier_utils.cpp |
508 | 18 | input_probe.cpp | 18 | input_probe.cpp |
509 | 19 | key_repeat_dispatcher.cpp | ||
510 | 20 | null_input_channel_factory.cpp | 19 | null_input_channel_factory.cpp |
511 | 21 | null_input_dispatcher.cpp | 20 | null_input_dispatcher.cpp |
512 | 22 | seat_input_device_tracker.cpp | 21 | seat_input_device_tracker.cpp |
513 | 23 | 22 | ||
514 | === modified file 'src/server/input/default_configuration.cpp' | |||
515 | --- src/server/input/default_configuration.cpp 2016-03-23 06:39:56 +0000 | |||
516 | +++ src/server/input/default_configuration.cpp 2016-03-31 19:18:58 +0000 | |||
517 | @@ -20,7 +20,6 @@ | |||
518 | 20 | 20 | ||
519 | 21 | #include "android/input_sender.h" | 21 | #include "android/input_sender.h" |
520 | 22 | #include "android/input_channel_factory.h" | 22 | #include "android/input_channel_factory.h" |
521 | 23 | #include "key_repeat_dispatcher.h" | ||
522 | 24 | #include "display_input_region.h" | 23 | #include "display_input_region.h" |
523 | 25 | #include "event_filter_chain_dispatcher.h" | 24 | #include "event_filter_chain_dispatcher.h" |
524 | 26 | #include "cursor_controller.h" | 25 | #include "cursor_controller.h" |
525 | @@ -143,15 +142,7 @@ | |||
526 | 143 | return input_dispatcher( | 142 | return input_dispatcher( |
527 | 144 | [this]() | 143 | [this]() |
528 | 145 | { | 144 | { |
538 | 146 | std::chrono::milliseconds const key_repeat_timeout{500}; | 145 | return the_event_filter_chain_dispatcher(); |
530 | 147 | std::chrono::milliseconds const key_repeat_delay{50}; | ||
531 | 148 | |||
532 | 149 | auto const options = the_options(); | ||
533 | 150 | auto enable_repeat = options->get<bool>(options::enable_key_repeat_opt); | ||
534 | 151 | |||
535 | 152 | return std::make_shared<mi::KeyRepeatDispatcher>( | ||
536 | 153 | the_event_filter_chain_dispatcher(), the_main_loop(), the_cookie_authority(), | ||
537 | 154 | enable_repeat, key_repeat_timeout, key_repeat_delay); | ||
539 | 155 | }); | 146 | }); |
540 | 156 | } | 147 | } |
541 | 157 | 148 | ||
542 | @@ -297,18 +288,13 @@ | |||
543 | 297 | return default_input_device_hub( | 288 | return default_input_device_hub( |
544 | 298 | [this]() | 289 | [this]() |
545 | 299 | { | 290 | { |
549 | 300 | auto input_dispatcher = the_input_dispatcher(); | 291 | return std::make_shared<mi::DefaultInputDeviceHub>( |
547 | 301 | auto key_repeater = std::dynamic_pointer_cast<mi::KeyRepeatDispatcher>(input_dispatcher); | ||
548 | 302 | auto hub = std::make_shared<mi::DefaultInputDeviceHub>( | ||
550 | 303 | the_global_event_sink(), | 292 | the_global_event_sink(), |
551 | 304 | the_seat(), | 293 | the_seat(), |
552 | 305 | the_input_reading_multiplexer(), | 294 | the_input_reading_multiplexer(), |
553 | 306 | the_main_loop(), | 295 | the_main_loop(), |
559 | 307 | the_cookie_authority()); | 296 | the_cookie_authority(), |
560 | 308 | 297 | the_options()->get<bool>(options::enable_key_repeat_opt)); | |
556 | 309 | if (key_repeater) | ||
557 | 310 | key_repeater->set_input_device_hub(hub); | ||
558 | 311 | return hub; | ||
561 | 312 | }); | 298 | }); |
562 | 313 | } | 299 | } |
563 | 314 | 300 | ||
564 | @@ -324,18 +310,13 @@ | |||
565 | 324 | return default_input_device_hub( | 310 | return default_input_device_hub( |
566 | 325 | [this]() | 311 | [this]() |
567 | 326 | { | 312 | { |
571 | 327 | auto input_dispatcher = the_input_dispatcher(); | 313 | return std::make_shared<mi::DefaultInputDeviceHub>( |
569 | 328 | auto key_repeater = std::dynamic_pointer_cast<mi::KeyRepeatDispatcher>(input_dispatcher); | ||
570 | 329 | auto hub = std::make_shared<mi::DefaultInputDeviceHub>( | ||
572 | 330 | the_global_event_sink(), | 314 | the_global_event_sink(), |
573 | 331 | the_seat(), | 315 | the_seat(), |
574 | 332 | the_input_reading_multiplexer(), | 316 | the_input_reading_multiplexer(), |
575 | 333 | the_main_loop(), | 317 | the_main_loop(), |
581 | 334 | the_cookie_authority()); | 318 | the_cookie_authority(), |
582 | 335 | 319 | the_options()->get<bool>(options::enable_key_repeat_opt)); | |
578 | 336 | if (key_repeater) | ||
579 | 337 | key_repeater->set_input_device_hub(hub); | ||
580 | 338 | return hub; | ||
583 | 339 | }); | 320 | }); |
584 | 340 | } | 321 | } |
585 | 341 | } | 322 | } |
586 | 342 | 323 | ||
587 | === modified file 'src/server/input/default_input_device_hub.cpp' | |||
588 | --- src/server/input/default_input_device_hub.cpp 2016-03-23 06:39:56 +0000 | |||
589 | +++ src/server/input/default_input_device_hub.cpp 2016-03-31 19:18:58 +0000 | |||
590 | @@ -21,6 +21,7 @@ | |||
591 | 21 | 21 | ||
592 | 22 | #include "mir/input/input_device.h" | 22 | #include "mir/input/input_device.h" |
593 | 23 | #include "mir/input/input_device_observer.h" | 23 | #include "mir/input/input_device_observer.h" |
594 | 24 | #include "mir/input/keyboard_settings.h" | ||
595 | 24 | #include "mir/geometry/point.h" | 25 | #include "mir/geometry/point.h" |
596 | 25 | #include "mir/dispatch/multiplexing_dispatchable.h" | 26 | #include "mir/dispatch/multiplexing_dispatchable.h" |
597 | 26 | #include "mir/dispatch/action_queue.h" | 27 | #include "mir/dispatch/action_queue.h" |
598 | @@ -43,14 +44,16 @@ | |||
599 | 43 | std::shared_ptr<mi::Seat> const& seat, | 44 | std::shared_ptr<mi::Seat> const& seat, |
600 | 44 | std::shared_ptr<dispatch::MultiplexingDispatchable> const& input_multiplexer, | 45 | std::shared_ptr<dispatch::MultiplexingDispatchable> const& input_multiplexer, |
601 | 45 | std::shared_ptr<mir::ServerActionQueue> const& observer_queue, | 46 | std::shared_ptr<mir::ServerActionQueue> const& observer_queue, |
603 | 46 | std::shared_ptr<mir::cookie::Authority> const& cookie_authority) | 47 | std::shared_ptr<mir::cookie::Authority> const& cookie_authority, |
604 | 48 | bool repeat_enabled) | ||
605 | 47 | : seat{seat}, | 49 | : seat{seat}, |
606 | 48 | sink{sink}, | 50 | sink{sink}, |
607 | 49 | input_dispatchable{input_multiplexer}, | 51 | input_dispatchable{input_multiplexer}, |
608 | 50 | observer_queue(observer_queue), | 52 | observer_queue(observer_queue), |
609 | 51 | device_queue(std::make_shared<dispatch::ActionQueue>()), | 53 | device_queue(std::make_shared<dispatch::ActionQueue>()), |
610 | 52 | cookie_authority(cookie_authority), | 54 | cookie_authority(cookie_authority), |
612 | 53 | device_id_generator{0} | 55 | device_id_generator{0}, |
613 | 56 | repeat_enabled{repeat_enabled} | ||
614 | 54 | { | 57 | { |
615 | 55 | input_dispatchable->add_watch(device_queue); | 58 | input_dispatchable->add_watch(device_queue); |
616 | 56 | } | 59 | } |
617 | @@ -60,6 +63,13 @@ | |||
618 | 60 | if (!device) | 63 | if (!device) |
619 | 61 | BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid input device")); | 64 | BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid input device")); |
620 | 62 | 65 | ||
621 | 66 | if (contains(device->get_device_info().capabilities, mir::input::DeviceCapability::keyboard)) | ||
622 | 67 | { | ||
623 | 68 | auto key_settings = device->get_keyboard_settings().value(); | ||
624 | 69 | key_settings.repeat_enabled = repeat_enabled; | ||
625 | 70 | device->apply_settings(key_settings); | ||
626 | 71 | } | ||
627 | 72 | |||
628 | 63 | auto it = find_if(devices.cbegin(), | 73 | auto it = find_if(devices.cbegin(), |
629 | 64 | devices.cend(), | 74 | devices.cend(), |
630 | 65 | [&device](std::unique_ptr<RegisteredDevice> const& item) | 75 | [&device](std::unique_ptr<RegisteredDevice> const& item) |
631 | 66 | 76 | ||
632 | === modified file 'src/server/input/default_input_device_hub.h' | |||
633 | --- src/server/input/default_input_device_hub.h 2016-03-23 06:39:56 +0000 | |||
634 | +++ src/server/input/default_input_device_hub.h 2016-03-31 19:18:58 +0000 | |||
635 | @@ -65,7 +65,8 @@ | |||
636 | 65 | std::shared_ptr<Seat> const& seat, | 65 | std::shared_ptr<Seat> const& seat, |
637 | 66 | std::shared_ptr<dispatch::MultiplexingDispatchable> const& input_multiplexer, | 66 | std::shared_ptr<dispatch::MultiplexingDispatchable> const& input_multiplexer, |
638 | 67 | std::shared_ptr<ServerActionQueue> const& observer_queue, | 67 | std::shared_ptr<ServerActionQueue> const& observer_queue, |
640 | 68 | std::shared_ptr<cookie::Authority> const& cookie_authority); | 68 | std::shared_ptr<cookie::Authority> const& cookie_authority, |
641 | 69 | bool repeat_enabled = true); | ||
642 | 69 | 70 | ||
643 | 70 | // InputDeviceRegistry - calls from mi::Platform | 71 | // InputDeviceRegistry - calls from mi::Platform |
644 | 71 | void add_device(std::shared_ptr<InputDevice> const& device) override; | 72 | void add_device(std::shared_ptr<InputDevice> const& device) override; |
645 | @@ -117,6 +118,7 @@ | |||
646 | 117 | std::vector<std::shared_ptr<InputDeviceObserver>> observers; | 118 | std::vector<std::shared_ptr<InputDeviceObserver>> observers; |
647 | 118 | 119 | ||
648 | 119 | MirInputDeviceId device_id_generator; | 120 | MirInputDeviceId device_id_generator; |
649 | 121 | bool repeat_enabled; | ||
650 | 120 | }; | 122 | }; |
651 | 121 | 123 | ||
652 | 122 | } | 124 | } |
653 | 123 | 125 | ||
654 | === removed file 'src/server/input/key_repeat_dispatcher.cpp' | |||
655 | --- src/server/input/key_repeat_dispatcher.cpp 2016-03-29 23:37:32 +0000 | |||
656 | +++ src/server/input/key_repeat_dispatcher.cpp 1970-01-01 00:00:00 +0000 | |||
657 | @@ -1,186 +0,0 @@ | |||
658 | 1 | /* | ||
659 | 2 | * Copyright © 2012 Canonical Ltd. | ||
660 | 3 | * | ||
661 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
662 | 5 | * under the terms of the GNU General Public License version 3, | ||
663 | 6 | * as published by the Free Software Foundation. | ||
664 | 7 | * | ||
665 | 8 | * This program is distributed in the hope that it will be useful, | ||
666 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
667 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
668 | 11 | * GNU General Public License for more details. | ||
669 | 12 | * | ||
670 | 13 | * You should have received a copy of the GNU General Public License | ||
671 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
672 | 15 | * | ||
673 | 16 | * Authored by: Robert Carr <robert.carr@canonical.com> | ||
674 | 17 | */ | ||
675 | 18 | |||
676 | 19 | #include "key_repeat_dispatcher.h" | ||
677 | 20 | |||
678 | 21 | #include "mir/input/device.h" | ||
679 | 22 | #include "mir/input/input_device_hub.h" | ||
680 | 23 | #include "mir/time/alarm_factory.h" | ||
681 | 24 | #include "mir/time/alarm.h" | ||
682 | 25 | #include "mir/events/event_private.h" | ||
683 | 26 | #include "mir/cookie/authority.h" | ||
684 | 27 | |||
685 | 28 | #include <boost/throw_exception.hpp> | ||
686 | 29 | |||
687 | 30 | #include <algorithm> | ||
688 | 31 | #include <stdexcept> | ||
689 | 32 | #include <string.h> | ||
690 | 33 | |||
691 | 34 | namespace mi = mir::input; | ||
692 | 35 | |||
693 | 36 | namespace | ||
694 | 37 | { | ||
695 | 38 | struct DeviceRemovalFilter : mi::InputDeviceObserver | ||
696 | 39 | { | ||
697 | 40 | DeviceRemovalFilter(std::function<void(MirInputDeviceId)> const& on_removal) | ||
698 | 41 | : on_removal(on_removal) {} | ||
699 | 42 | |||
700 | 43 | void device_added(std::shared_ptr<mi::Device> const&) override | ||
701 | 44 | { | ||
702 | 45 | } | ||
703 | 46 | |||
704 | 47 | void device_changed(std::shared_ptr<mi::Device> const&) override | ||
705 | 48 | { | ||
706 | 49 | } | ||
707 | 50 | |||
708 | 51 | void device_removed(std::shared_ptr<mi::Device> const& device) override | ||
709 | 52 | { | ||
710 | 53 | on_removal(device->id()); | ||
711 | 54 | } | ||
712 | 55 | |||
713 | 56 | void changes_complete() override | ||
714 | 57 | { | ||
715 | 58 | } | ||
716 | 59 | std::function<void(MirInputDeviceId)> on_removal; | ||
717 | 60 | }; | ||
718 | 61 | |||
719 | 62 | } | ||
720 | 63 | |||
721 | 64 | mi::KeyRepeatDispatcher::KeyRepeatDispatcher( | ||
722 | 65 | std::shared_ptr<mi::InputDispatcher> const& next_dispatcher, | ||
723 | 66 | std::shared_ptr<mir::time::AlarmFactory> const& factory, | ||
724 | 67 | std::shared_ptr<mir::cookie::Authority> const& cookie_authority, | ||
725 | 68 | bool repeat_enabled, | ||
726 | 69 | std::chrono::milliseconds repeat_timeout, | ||
727 | 70 | std::chrono::milliseconds repeat_delay) | ||
728 | 71 | : next_dispatcher(next_dispatcher), | ||
729 | 72 | alarm_factory(factory), | ||
730 | 73 | cookie_authority(cookie_authority), | ||
731 | 74 | repeat_enabled(repeat_enabled), | ||
732 | 75 | repeat_timeout(repeat_timeout), | ||
733 | 76 | repeat_delay(repeat_delay) | ||
734 | 77 | { | ||
735 | 78 | } | ||
736 | 79 | |||
737 | 80 | void mi::KeyRepeatDispatcher::set_input_device_hub(std::shared_ptr<InputDeviceHub> const& hub) | ||
738 | 81 | { | ||
739 | 82 | hub->add_observer(std::make_shared<DeviceRemovalFilter>( | ||
740 | 83 | [this](MirInputDeviceId id) | ||
741 | 84 | { | ||
742 | 85 | std::unique_lock<std::mutex> lock(repeat_state_mutex); | ||
743 | 86 | repeat_state_by_device.erase(id); // destructor cancels alarms | ||
744 | 87 | } | ||
745 | 88 | )); | ||
746 | 89 | } | ||
747 | 90 | |||
748 | 91 | mi::KeyRepeatDispatcher::KeyboardState& mi::KeyRepeatDispatcher::ensure_state_for_device_locked(std::lock_guard<std::mutex> const&, MirInputDeviceId id) | ||
749 | 92 | { | ||
750 | 93 | repeat_state_by_device.insert(std::make_pair(id, KeyboardState())); | ||
751 | 94 | return repeat_state_by_device[id]; | ||
752 | 95 | } | ||
753 | 96 | |||
754 | 97 | bool mi::KeyRepeatDispatcher::dispatch(MirEvent const& event) | ||
755 | 98 | { | ||
756 | 99 | if (!repeat_enabled) // if we made this mutable we'd need a guard | ||
757 | 100 | { | ||
758 | 101 | return next_dispatcher->dispatch(event); | ||
759 | 102 | } | ||
760 | 103 | |||
761 | 104 | if (mir_event_get_type(&event) == mir_event_type_input) | ||
762 | 105 | { | ||
763 | 106 | auto iev = mir_event_get_input_event(&event); | ||
764 | 107 | if (mir_input_event_get_type(iev) != mir_input_event_type_key) | ||
765 | 108 | return next_dispatcher->dispatch(event); | ||
766 | 109 | if (!handle_key_input(mir_input_event_get_device_id(iev), mir_input_event_get_keyboard_event(iev))) | ||
767 | 110 | return next_dispatcher->dispatch(event); | ||
768 | 111 | else | ||
769 | 112 | return true; | ||
770 | 113 | } | ||
771 | 114 | return next_dispatcher->dispatch(event); | ||
772 | 115 | } | ||
773 | 116 | |||
774 | 117 | // Returns true if the original event has been handled, that is ::dispatch should not pass it on. | ||
775 | 118 | bool mi::KeyRepeatDispatcher::handle_key_input(MirInputDeviceId id, MirKeyboardEvent const* kev) | ||
776 | 119 | { | ||
777 | 120 | std::lock_guard<std::mutex> lg(repeat_state_mutex); | ||
778 | 121 | auto& device_state = ensure_state_for_device_locked(lg, id); | ||
779 | 122 | |||
780 | 123 | auto scan_code = mir_keyboard_event_scan_code(kev); | ||
781 | 124 | |||
782 | 125 | switch (mir_keyboard_event_action(kev)) | ||
783 | 126 | { | ||
784 | 127 | case mir_keyboard_action_up: | ||
785 | 128 | { | ||
786 | 129 | auto it = device_state.repeat_alarms_by_scancode.find(scan_code); | ||
787 | 130 | if (it == device_state.repeat_alarms_by_scancode.end()) | ||
788 | 131 | { | ||
789 | 132 | return false; | ||
790 | 133 | } | ||
791 | 134 | device_state.repeat_alarms_by_scancode.erase(it); | ||
792 | 135 | break; | ||
793 | 136 | } | ||
794 | 137 | case mir_keyboard_action_down: | ||
795 | 138 | { | ||
796 | 139 | MirKeyboardEvent new_kev = *kev; | ||
797 | 140 | new_kev.action = mir_keyboard_action_repeat; | ||
798 | 141 | |||
799 | 142 | auto it = device_state.repeat_alarms_by_scancode.find(scan_code); | ||
800 | 143 | if (it != device_state.repeat_alarms_by_scancode.end()) | ||
801 | 144 | { | ||
802 | 145 | // When we receive a duplicated down we just replace the action | ||
803 | 146 | next_dispatcher->dispatch(new_kev); | ||
804 | 147 | return true; | ||
805 | 148 | } | ||
806 | 149 | auto& capture_alarm = device_state.repeat_alarms_by_scancode[scan_code]; | ||
807 | 150 | std::shared_ptr<mir::time::Alarm> alarm = alarm_factory->create_alarm([this, &capture_alarm, new_kev]() mutable | ||
808 | 151 | { | ||
809 | 152 | std::lock_guard<std::mutex> lg(repeat_state_mutex); | ||
810 | 153 | |||
811 | 154 | new_kev.event_time = std::chrono::steady_clock::now().time_since_epoch(); | ||
812 | 155 | auto const cookie = cookie_authority->make_cookie(new_kev.event_time.count()); | ||
813 | 156 | auto const serialized_cookie = cookie->serialize(); | ||
814 | 157 | std::copy_n(std::begin(serialized_cookie), new_kev.cookie.size(), std::begin(new_kev.cookie)); | ||
815 | 158 | next_dispatcher->dispatch(new_kev); | ||
816 | 159 | |||
817 | 160 | capture_alarm->reschedule_in(repeat_delay); | ||
818 | 161 | }); | ||
819 | 162 | alarm->reschedule_in(repeat_timeout); | ||
820 | 163 | device_state.repeat_alarms_by_scancode[scan_code] = {alarm}; | ||
821 | 164 | } | ||
822 | 165 | case mir_keyboard_action_repeat: | ||
823 | 166 | // Should we consume existing repeats? | ||
824 | 167 | break; | ||
825 | 168 | default: | ||
826 | 169 | BOOST_THROW_EXCEPTION(std::logic_error("Unexpected key event action")); | ||
827 | 170 | } | ||
828 | 171 | return false; | ||
829 | 172 | } | ||
830 | 173 | |||
831 | 174 | void mi::KeyRepeatDispatcher::start() | ||
832 | 175 | { | ||
833 | 176 | next_dispatcher->start(); | ||
834 | 177 | } | ||
835 | 178 | |||
836 | 179 | void mi::KeyRepeatDispatcher::stop() | ||
837 | 180 | { | ||
838 | 181 | std::lock_guard<std::mutex> lg(repeat_state_mutex); | ||
839 | 182 | |||
840 | 183 | repeat_state_by_device.clear(); | ||
841 | 184 | |||
842 | 185 | next_dispatcher->stop(); | ||
843 | 186 | } | ||
844 | 187 | 0 | ||
845 | === removed file 'src/server/input/key_repeat_dispatcher.h' | |||
846 | --- src/server/input/key_repeat_dispatcher.h 2016-03-23 06:39:56 +0000 | |||
847 | +++ src/server/input/key_repeat_dispatcher.h 1970-01-01 00:00:00 +0000 | |||
848 | @@ -1,84 +0,0 @@ | |||
849 | 1 | /* | ||
850 | 2 | * Copyright © 2015-2016 Canonical Ltd. | ||
851 | 3 | * | ||
852 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
853 | 5 | * under the terms of the GNU General Public License version 3, | ||
854 | 6 | * as published by the Free Software Foundation. | ||
855 | 7 | * | ||
856 | 8 | * This program is distributed in the hope that it will be useful, | ||
857 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
858 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
859 | 11 | * GNU General Public License for more details. | ||
860 | 12 | * | ||
861 | 13 | * You should have received a copy of the GNU General Public License | ||
862 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
863 | 15 | * | ||
864 | 16 | * Authored by: Robert Carr <robert.carr@canonical.com> | ||
865 | 17 | */ | ||
866 | 18 | |||
867 | 19 | #ifndef MIR_INPUT_KEY_REPEAT_DISPATCHER_H_ | ||
868 | 20 | #define MIR_INPUT_KEY_REPEAT_DISPATCHER_H_ | ||
869 | 21 | |||
870 | 22 | #include "mir/input/input_dispatcher.h" | ||
871 | 23 | #include "mir/input/input_device_observer.h" | ||
872 | 24 | |||
873 | 25 | #include <memory> | ||
874 | 26 | #include <chrono> | ||
875 | 27 | #include <mutex> | ||
876 | 28 | #include <unordered_map> | ||
877 | 29 | |||
878 | 30 | namespace mir | ||
879 | 31 | { | ||
880 | 32 | namespace cookie | ||
881 | 33 | { | ||
882 | 34 | class Authority; | ||
883 | 35 | } | ||
884 | 36 | namespace time | ||
885 | 37 | { | ||
886 | 38 | class AlarmFactory; | ||
887 | 39 | class Alarm; | ||
888 | 40 | } | ||
889 | 41 | namespace input | ||
890 | 42 | { | ||
891 | 43 | class InputDeviceHub; | ||
892 | 44 | class KeyRepeatDispatcher : public InputDispatcher | ||
893 | 45 | { | ||
894 | 46 | public: | ||
895 | 47 | KeyRepeatDispatcher(std::shared_ptr<InputDispatcher> const& next_dispatcher, | ||
896 | 48 | std::shared_ptr<time::AlarmFactory> const& factory, | ||
897 | 49 | std::shared_ptr<cookie::Authority> const& cookie_authority, | ||
898 | 50 | bool repeat_enabled, | ||
899 | 51 | std::chrono::milliseconds repeat_timeout, /* timeout before sending first repeat */ | ||
900 | 52 | std::chrono::milliseconds repeat_delay /* delay between repeated keys */); | ||
901 | 53 | |||
902 | 54 | // InputDispatcher | ||
903 | 55 | bool dispatch(MirEvent const& event) override; | ||
904 | 56 | void start() override; | ||
905 | 57 | void stop() override; | ||
906 | 58 | |||
907 | 59 | void set_input_device_hub(std::shared_ptr<InputDeviceHub> const& hub); | ||
908 | 60 | |||
909 | 61 | private: | ||
910 | 62 | std::mutex repeat_state_mutex; | ||
911 | 63 | |||
912 | 64 | std::shared_ptr<InputDispatcher> const next_dispatcher; | ||
913 | 65 | std::shared_ptr<time::AlarmFactory> const alarm_factory; | ||
914 | 66 | std::shared_ptr<cookie::Authority> const cookie_authority; | ||
915 | 67 | bool const repeat_enabled; | ||
916 | 68 | std::chrono::milliseconds repeat_timeout; | ||
917 | 69 | std::chrono::milliseconds repeat_delay; | ||
918 | 70 | |||
919 | 71 | struct KeyboardState | ||
920 | 72 | { | ||
921 | 73 | std::unordered_map<int, std::shared_ptr<mir::time::Alarm>> repeat_alarms_by_scancode; | ||
922 | 74 | }; | ||
923 | 75 | std::unordered_map<MirInputDeviceId, KeyboardState> repeat_state_by_device; | ||
924 | 76 | KeyboardState& ensure_state_for_device_locked(std::lock_guard<std::mutex> const&, MirInputDeviceId id); | ||
925 | 77 | |||
926 | 78 | bool handle_key_input(MirInputDeviceId id, MirKeyboardEvent const* ev); | ||
927 | 79 | }; | ||
928 | 80 | |||
929 | 81 | } | ||
930 | 82 | } | ||
931 | 83 | |||
932 | 84 | #endif // MIR_INPUT_KEY_REPEAT_DISPATCHER_H_ | ||
933 | 85 | 0 | ||
934 | === modified file 'tests/include/mir/test/doubles/mock_input_device.h' | |||
935 | --- tests/include/mir/test/doubles/mock_input_device.h 2015-12-18 21:07:54 +0000 | |||
936 | +++ tests/include/mir/test/doubles/mock_input_device.h 2016-03-31 19:18:58 +0000 | |||
937 | @@ -23,6 +23,7 @@ | |||
938 | 23 | #include "mir/input/input_device_info.h" // needed for fake device setup | 23 | #include "mir/input/input_device_info.h" // needed for fake device setup |
939 | 24 | #include "mir/input/pointer_settings.h" | 24 | #include "mir/input/pointer_settings.h" |
940 | 25 | #include "mir/input/touchpad_settings.h" | 25 | #include "mir/input/touchpad_settings.h" |
941 | 26 | #include "mir/input/keyboard_settings.h" | ||
942 | 26 | 27 | ||
943 | 27 | #include <gmock/gmock.h> | 28 | #include <gmock/gmock.h> |
944 | 28 | 29 | ||
945 | @@ -44,6 +45,8 @@ | |||
946 | 44 | MOCK_METHOD1(apply_settings, void(input::PointerSettings const&)); | 45 | MOCK_METHOD1(apply_settings, void(input::PointerSettings const&)); |
947 | 45 | MOCK_CONST_METHOD0(get_touchpad_settings, mir::optional_value<input::TouchpadSettings>()); | 46 | MOCK_CONST_METHOD0(get_touchpad_settings, mir::optional_value<input::TouchpadSettings>()); |
948 | 46 | MOCK_METHOD1(apply_settings, void(input::TouchpadSettings const&)); | 47 | MOCK_METHOD1(apply_settings, void(input::TouchpadSettings const&)); |
949 | 48 | MOCK_CONST_METHOD0(get_keyboard_settings, mir::optional_value<input::KeyboardSettings>()); | ||
950 | 49 | MOCK_METHOD1(apply_settings, void(input::KeyboardSettings const&)); | ||
951 | 47 | }; | 50 | }; |
952 | 48 | } | 51 | } |
953 | 49 | } | 52 | } |
954 | 50 | 53 | ||
955 | === modified file 'tests/include/mir/test/doubles/mock_x11.h' | |||
956 | --- tests/include/mir/test/doubles/mock_x11.h 2016-03-23 06:39:56 +0000 | |||
957 | +++ tests/include/mir/test/doubles/mock_x11.h 2016-03-31 19:18:58 +0000 | |||
958 | @@ -22,6 +22,7 @@ | |||
959 | 22 | #include <gmock/gmock.h> | 22 | #include <gmock/gmock.h> |
960 | 23 | 23 | ||
961 | 24 | #include <X11/Xlib.h> | 24 | #include <X11/Xlib.h> |
962 | 25 | #include <X11/XKBlib.h> | ||
963 | 25 | #include <X11/Xutil.h> | 26 | #include <X11/Xutil.h> |
964 | 26 | 27 | ||
965 | 27 | namespace mir | 28 | namespace mir |
966 | @@ -81,6 +82,13 @@ | |||
967 | 81 | MOCK_METHOD1(XSetErrorHandler, XErrorHandler(XErrorHandler)); | 82 | MOCK_METHOD1(XSetErrorHandler, XErrorHandler(XErrorHandler)); |
968 | 82 | MOCK_METHOD0(XInitThreads, Status()); | 83 | MOCK_METHOD0(XInitThreads, Status()); |
969 | 83 | MOCK_METHOD3(XSetWMHints, int(Display*, Window, XWMHints*)); | 84 | MOCK_METHOD3(XSetWMHints, int(Display*, Window, XWMHints*)); |
970 | 85 | MOCK_METHOD3(XChangeKeyboardControl, int(Display*, unsigned long, XKeyboardControl*)); | ||
971 | 86 | MOCK_METHOD2(XGetKeyboardControl, int(Display*, XKeyboardState*)); | ||
972 | 87 | MOCK_METHOD6(XkbQueryExtension, Bool(Display*, int*, int*, int*, int*, int*)); | ||
973 | 88 | MOCK_METHOD3(XkbFreeKeyboard, void(XkbDescPtr, unsigned int, Bool)); | ||
974 | 89 | MOCK_METHOD0(XkbAllocKeyboard, XkbDescPtr()); | ||
975 | 90 | MOCK_METHOD3(XkbGetControls, Status(Display*, unsigned long, XkbDescPtr)); | ||
976 | 91 | MOCK_METHOD3(XkbSetControls, Bool(Display*, unsigned long, XkbDescPtr)); | ||
977 | 84 | 92 | ||
978 | 85 | FakeX11Resources fake_x11; | 93 | FakeX11Resources fake_x11; |
979 | 86 | }; | 94 | }; |
980 | 87 | 95 | ||
981 | === modified file 'tests/include/mir_test_framework/stub_input_platform.h' | |||
982 | --- tests/include/mir_test_framework/stub_input_platform.h 2016-01-29 08:18:22 +0000 | |||
983 | +++ tests/include/mir_test_framework/stub_input_platform.h 2016-03-31 19:18:58 +0000 | |||
984 | @@ -26,8 +26,16 @@ | |||
985 | 26 | 26 | ||
986 | 27 | namespace mir | 27 | namespace mir |
987 | 28 | { | 28 | { |
988 | 29 | namespace time | ||
989 | 30 | { | ||
990 | 31 | class AlarmFactory; | ||
991 | 32 | class Clock; | ||
992 | 33 | class SteadyTimerFd; | ||
993 | 34 | class SteadyClock; | ||
994 | 35 | } | ||
995 | 29 | namespace dispatch | 36 | namespace dispatch |
996 | 30 | { | 37 | { |
997 | 38 | class AlarmFactory; | ||
998 | 31 | class ActionQueue; | 39 | class ActionQueue; |
999 | 32 | class MultiplexingDispatchable; | 40 | class MultiplexingDispatchable; |
1000 | 33 | } | 41 | } |
1001 | @@ -53,6 +61,8 @@ | |||
1002 | 53 | static void remove(std::shared_ptr<mir::input::InputDevice> const& dev); | 61 | static void remove(std::shared_ptr<mir::input::InputDevice> const& dev); |
1003 | 54 | static void register_dispatchable(std::shared_ptr<mir::dispatch::Dispatchable> const& queue); | 62 | static void register_dispatchable(std::shared_ptr<mir::dispatch::Dispatchable> const& queue); |
1004 | 55 | static void unregister_dispatchable(std::shared_ptr<mir::dispatch::Dispatchable> const& queue); | 63 | static void unregister_dispatchable(std::shared_ptr<mir::dispatch::Dispatchable> const& queue); |
1005 | 64 | static std::shared_ptr<mir::time::AlarmFactory> get_alarm_factory(); | ||
1006 | 65 | static std::shared_ptr<mir::time::Clock> get_clock(); | ||
1007 | 56 | 66 | ||
1008 | 57 | private: | 67 | private: |
1009 | 58 | std::shared_ptr<mir::dispatch::MultiplexingDispatchable> const platform_dispatchable; | 68 | std::shared_ptr<mir::dispatch::MultiplexingDispatchable> const platform_dispatchable; |
1010 | @@ -61,6 +71,11 @@ | |||
1011 | 61 | static std::atomic<StubInputPlatform*> stub_input_platform; | 71 | static std::atomic<StubInputPlatform*> stub_input_platform; |
1012 | 62 | static std::vector<std::weak_ptr<mir::input::InputDevice>> device_store; | 72 | static std::vector<std::weak_ptr<mir::input::InputDevice>> device_store; |
1013 | 63 | static std::mutex device_store_guard; | 73 | static std::mutex device_store_guard; |
1014 | 74 | static std::shared_ptr<mir::time::SteadyClock> steady_clock; | ||
1015 | 75 | static std::shared_ptr<mir::time::SteadyTimerFd> steady_timer_fd; | ||
1016 | 76 | static std::shared_ptr<mir::dispatch::AlarmFactory> alarm_factory; | ||
1017 | 77 | |||
1018 | 78 | |||
1019 | 64 | }; | 79 | }; |
1020 | 65 | 80 | ||
1021 | 66 | } | 81 | } |
1022 | 67 | 82 | ||
1023 | === modified file 'tests/mir_test_doubles/mock_input_device.cpp' | |||
1024 | --- tests/mir_test_doubles/mock_input_device.cpp 2015-12-18 21:07:54 +0000 | |||
1025 | +++ tests/mir_test_doubles/mock_input_device.cpp 2016-03-31 19:18:58 +0000 | |||
1026 | @@ -40,4 +40,12 @@ | |||
1027 | 40 | else | 40 | else |
1028 | 41 | ON_CALL(*this, get_touchpad_settings()) | 41 | ON_CALL(*this, get_touchpad_settings()) |
1029 | 42 | .WillByDefault(Return(mir::optional_value<input::TouchpadSettings>())); | 42 | .WillByDefault(Return(mir::optional_value<input::TouchpadSettings>())); |
1030 | 43 | |||
1031 | 44 | if (contains(caps, input::DeviceCapability::keyboard)) | ||
1032 | 45 | ON_CALL(*this, get_keyboard_settings()) | ||
1033 | 46 | .WillByDefault(Return(input::KeyboardSettings())); | ||
1034 | 47 | else | ||
1035 | 48 | ON_CALL(*this, get_keyboard_settings()) | ||
1036 | 49 | .WillByDefault(Return(mir::optional_value<input::KeyboardSettings>())); | ||
1037 | 50 | |||
1038 | 43 | } | 51 | } |
1039 | 44 | 52 | ||
1040 | === modified file 'tests/mir_test_doubles/mock_x11.cpp' | |||
1041 | --- tests/mir_test_doubles/mock_x11.cpp 2016-03-23 06:39:56 +0000 | |||
1042 | +++ tests/mir_test_doubles/mock_x11.cpp 2016-03-31 19:18:58 +0000 | |||
1043 | @@ -195,3 +195,38 @@ | |||
1044 | 195 | { | 195 | { |
1045 | 196 | return global_mock->XPending(display); | 196 | return global_mock->XPending(display); |
1046 | 197 | } | 197 | } |
1047 | 198 | |||
1048 | 199 | int XChangeKeyboardControl(Display* display, unsigned long value_mask, XKeyboardControl* control) | ||
1049 | 200 | { | ||
1050 | 201 | return global_mock->XChangeKeyboardControl(display, value_mask, control); | ||
1051 | 202 | } | ||
1052 | 203 | |||
1053 | 204 | int XGetKeyboardControl(Display* display, XKeyboardState* control) | ||
1054 | 205 | { | ||
1055 | 206 | return global_mock->XGetKeyboardControl(display, control); | ||
1056 | 207 | } | ||
1057 | 208 | |||
1058 | 209 | Bool XkbQueryExtension(Display* dpy, int* opcode, int* event_base, int* error_base, int* major, int* minor) | ||
1059 | 210 | { | ||
1060 | 211 | return global_mock->XkbQueryExtension(dpy, opcode, event_base, error_base, major, minor); | ||
1061 | 212 | } | ||
1062 | 213 | |||
1063 | 214 | void XkbFreeKeyboard(XkbDescPtr xkb, unsigned int which, Bool free_desc) | ||
1064 | 215 | { | ||
1065 | 216 | global_mock->XkbFreeKeyboard(xkb, which, free_desc); | ||
1066 | 217 | } | ||
1067 | 218 | |||
1068 | 219 | XkbDescPtr XkbAllocKeyboard() | ||
1069 | 220 | { | ||
1070 | 221 | return global_mock->XkbAllocKeyboard(); | ||
1071 | 222 | } | ||
1072 | 223 | |||
1073 | 224 | Status XkbGetControls(Display* dpy, unsigned long which, XkbDescPtr desc) | ||
1074 | 225 | { | ||
1075 | 226 | return global_mock->XkbGetControls(dpy, which, desc); | ||
1076 | 227 | } | ||
1077 | 228 | |||
1078 | 229 | Bool XkbSetControls(Display* dpy, unsigned long which, XkbDescPtr desc) | ||
1079 | 230 | { | ||
1080 | 231 | return global_mock->XkbSetControls(dpy, which, desc); | ||
1081 | 232 | } | ||
1082 | 198 | 233 | ||
1083 | === modified file 'tests/mir_test_framework/fake_input_device_impl.cpp' | |||
1084 | --- tests/mir_test_framework/fake_input_device_impl.cpp 2016-03-23 06:39:56 +0000 | |||
1085 | +++ tests/mir_test_framework/fake_input_device_impl.cpp 2016-03-31 19:18:58 +0000 | |||
1086 | @@ -24,7 +24,9 @@ | |||
1087 | 24 | #include "mir/input/input_sink.h" | 24 | #include "mir/input/input_sink.h" |
1088 | 25 | #include "mir/input/pointer_settings.h" | 25 | #include "mir/input/pointer_settings.h" |
1089 | 26 | #include "mir/input/touchpad_settings.h" | 26 | #include "mir/input/touchpad_settings.h" |
1090 | 27 | #include "mir/input/keyboard_settings.h" | ||
1091 | 27 | #include "mir/input/event_builder.h" | 28 | #include "mir/input/event_builder.h" |
1092 | 29 | #include "mir/time/clock.h" | ||
1093 | 28 | #include "mir/dispatch/action_queue.h" | 30 | #include "mir/dispatch/action_queue.h" |
1094 | 29 | #include "mir/geometry/displacement.h" | 31 | #include "mir/geometry/displacement.h" |
1095 | 30 | #include "src/platforms/evdev/button_utils.h" | 32 | #include "src/platforms/evdev/button_utils.h" |
1096 | @@ -41,7 +43,9 @@ | |||
1097 | 41 | namespace mtf = mir_test_framework; | 43 | namespace mtf = mir_test_framework; |
1098 | 42 | 44 | ||
1099 | 43 | mtf::FakeInputDeviceImpl::FakeInputDeviceImpl(mi::InputDeviceInfo const& info) | 45 | mtf::FakeInputDeviceImpl::FakeInputDeviceImpl(mi::InputDeviceInfo const& info) |
1101 | 44 | : queue{std::make_shared<md::ActionQueue>()}, device{std::make_shared<InputDevice>(info, queue)} | 46 | : queue{std::make_shared<md::ActionQueue>()}, |
1102 | 47 | device{std::make_shared<InputDevice>( | ||
1103 | 48 | info, queue, mtf::StubInputPlatform::get_clock(), mtf::StubInputPlatform::get_alarm_factory())} | ||
1104 | 45 | { | 49 | { |
1105 | 46 | mtf::StubInputPlatform::add(device); | 50 | mtf::StubInputPlatform::add(device); |
1106 | 47 | } | 51 | } |
1107 | @@ -92,24 +96,31 @@ | |||
1108 | 92 | } | 96 | } |
1109 | 93 | 97 | ||
1110 | 94 | mtf::FakeInputDeviceImpl::InputDevice::InputDevice(mi::InputDeviceInfo const& info, | 98 | mtf::FakeInputDeviceImpl::InputDevice::InputDevice(mi::InputDeviceInfo const& info, |
1113 | 95 | std::shared_ptr<mir::dispatch::Dispatchable> const& dispatchable) | 99 | std::shared_ptr<mir::dispatch::Dispatchable> const& dispatchable, |
1114 | 96 | : info(info), queue{dispatchable}, buttons{0} | 100 | std::shared_ptr<mir::time::Clock> const& clock, |
1115 | 101 | std::shared_ptr<mir::time::AlarmFactory> const& alarm_factory) | ||
1116 | 102 | : info(info), queue{dispatchable}, clock{clock}, buttons{0}, repeater{alarm_factory, [this](auto key_code) { | ||
1117 | 103 | this->handle_repeat(key_code);}} | ||
1118 | 97 | { | 104 | { |
1122 | 98 | // the default setup results in a direct mapping of input velocity to output velocity. | 105 | // the default setup results in a direct mapping of input velocity to output velocity. |
1123 | 99 | settings.acceleration = mir_pointer_acceleration_none; | 106 | settings.acceleration = mir_pointer_acceleration_none; |
1124 | 100 | settings.cursor_acceleration_bias = 0.0; | 107 | settings.cursor_acceleration_bias = 0.0; |
1125 | 101 | } | 108 | } |
1126 | 102 | 109 | ||
1127 | 103 | void mtf::FakeInputDeviceImpl::InputDevice::synthesize_events(synthesis::KeyParameters const& key_params) | 110 | void mtf::FakeInputDeviceImpl::InputDevice::synthesize_events(synthesis::KeyParameters const& key_params) |
1128 | 104 | { | 111 | { |
1129 | 105 | xkb_keysym_t key_code = 0; | 112 | xkb_keysym_t key_code = 0; |
1130 | 106 | 113 | ||
1133 | 107 | auto event_time = std::chrono::duration_cast<std::chrono::nanoseconds>( | 114 | auto const event_time = clock->now().time_since_epoch(); |
1132 | 108 | std::chrono::steady_clock::now().time_since_epoch()); | ||
1134 | 109 | 115 | ||
1135 | 110 | auto input_action = | 116 | auto input_action = |
1136 | 111 | (key_params.action == synthesis::EventAction::Down) ? mir_keyboard_action_down : mir_keyboard_action_up; | 117 | (key_params.action == synthesis::EventAction::Down) ? mir_keyboard_action_down : mir_keyboard_action_up; |
1137 | 112 | 118 | ||
1138 | 119 | if (input_action == mir_keyboard_action_down) | ||
1139 | 120 | repeater.press(key_params.scancode); | ||
1140 | 121 | else | ||
1141 | 122 | repeater.release(key_params.scancode); | ||
1142 | 123 | |||
1143 | 113 | auto key_event = builder->key_event(event_time, input_action, key_code, key_params.scancode); | 124 | auto key_event = builder->key_event(event_time, input_action, key_code, key_params.scancode); |
1144 | 114 | 125 | ||
1145 | 115 | if (!sink) | 126 | if (!sink) |
1146 | @@ -119,8 +130,7 @@ | |||
1147 | 119 | 130 | ||
1148 | 120 | void mtf::FakeInputDeviceImpl::InputDevice::synthesize_events(synthesis::ButtonParameters const& button) | 131 | void mtf::FakeInputDeviceImpl::InputDevice::synthesize_events(synthesis::ButtonParameters const& button) |
1149 | 121 | { | 132 | { |
1152 | 122 | auto event_time = std::chrono::duration_cast<std::chrono::nanoseconds>( | 133 | auto const event_time = clock->now().time_since_epoch(); |
1151 | 123 | std::chrono::steady_clock::now().time_since_epoch()); | ||
1153 | 124 | auto action = update_buttons(button.action, mie::to_pointer_button(button.button, settings.handedness)); | 134 | auto action = update_buttons(button.action, mie::to_pointer_button(button.button, settings.handedness)); |
1154 | 125 | auto button_event = builder->pointer_event(event_time, | 135 | auto button_event = builder->pointer_event(event_time, |
1155 | 126 | action, | 136 | action, |
1156 | @@ -154,8 +164,7 @@ | |||
1157 | 154 | if (!sink) | 164 | if (!sink) |
1158 | 155 | BOOST_THROW_EXCEPTION(std::runtime_error("Device is not started.")); | 165 | BOOST_THROW_EXCEPTION(std::runtime_error("Device is not started.")); |
1159 | 156 | 166 | ||
1162 | 157 | auto event_time = std::chrono::duration_cast<std::chrono::nanoseconds>( | 167 | auto const event_time = clock->now().time_since_epoch(); |
1161 | 158 | std::chrono::steady_clock::now().time_since_epoch()); | ||
1163 | 159 | // constant scaling is used here to simplify checking for the | 168 | // constant scaling is used here to simplify checking for the |
1164 | 160 | // expected results. Default settings of the device lead to no | 169 | // expected results. Default settings of the device lead to no |
1165 | 161 | // scaling at all. | 170 | // scaling at all. |
1166 | @@ -179,8 +188,7 @@ | |||
1167 | 179 | if (!sink) | 188 | if (!sink) |
1168 | 180 | BOOST_THROW_EXCEPTION(std::runtime_error("Device is not started.")); | 189 | BOOST_THROW_EXCEPTION(std::runtime_error("Device is not started.")); |
1169 | 181 | 190 | ||
1172 | 182 | auto event_time = std::chrono::duration_cast<std::chrono::nanoseconds>( | 191 | auto const event_time = clock->now().time_since_epoch(); |
1171 | 183 | std::chrono::steady_clock::now().time_since_epoch()); | ||
1173 | 184 | 192 | ||
1174 | 185 | auto touch_event = builder->touch_event(event_time); | 193 | auto touch_event = builder->touch_event(event_time); |
1175 | 186 | 194 | ||
1176 | @@ -247,6 +255,29 @@ | |||
1177 | 247 | // forwards already interpreted events. | 255 | // forwards already interpreted events. |
1178 | 248 | } | 256 | } |
1179 | 249 | 257 | ||
1180 | 258 | mir::optional_value<mi::KeyboardSettings> mtf::FakeInputDeviceImpl::InputDevice::get_keyboard_settings() const | ||
1181 | 259 | { | ||
1182 | 260 | if (!contains(info.capabilities, mi::DeviceCapability::keyboard)) | ||
1183 | 261 | return {}; | ||
1184 | 262 | mi::KeyboardSettings settings; | ||
1185 | 263 | |||
1186 | 264 | settings.repeat_enabled = repeater.enabled(); | ||
1187 | 265 | settings.repeat_delay = repeater.delay(); | ||
1188 | 266 | settings.repeat_interval = repeater.interval(); | ||
1189 | 267 | return settings; | ||
1190 | 268 | } | ||
1191 | 269 | |||
1192 | 270 | void mtf::FakeInputDeviceImpl::InputDevice::apply_settings(mi::KeyboardSettings const& settings) | ||
1193 | 271 | { | ||
1194 | 272 | if (!contains(info.capabilities, mi::DeviceCapability::keyboard)) | ||
1195 | 273 | return; | ||
1196 | 274 | |||
1197 | 275 | if (settings.repeat_enabled) | ||
1198 | 276 | repeater.enable(settings.repeat_delay, settings.repeat_interval); | ||
1199 | 277 | else | ||
1200 | 278 | repeater.disable(); | ||
1201 | 279 | } | ||
1202 | 280 | |||
1203 | 250 | void mtf::FakeInputDeviceImpl::InputDevice::map_touch_coordinates(float& x, float& y) | 281 | void mtf::FakeInputDeviceImpl::InputDevice::map_touch_coordinates(float& x, float& y) |
1204 | 251 | { | 282 | { |
1205 | 252 | // TODO take orientation of input sink into account? | 283 | // TODO take orientation of input sink into account? |
1206 | @@ -258,6 +289,15 @@ | |||
1207 | 258 | y = (y - float(FakeInputDevice::minimum_touch_axis_value))*y_scale + area.top_left.y.as_float(); | 289 | y = (y - float(FakeInputDevice::minimum_touch_axis_value))*y_scale + area.top_left.y.as_float(); |
1208 | 259 | } | 290 | } |
1209 | 260 | 291 | ||
1210 | 292 | void mtf::FakeInputDeviceImpl::InputDevice::handle_repeat(int32_t code) | ||
1211 | 293 | { | ||
1212 | 294 | if (!sink) | ||
1213 | 295 | BOOST_THROW_EXCEPTION(std::runtime_error("Device is not started.")); | ||
1214 | 296 | auto const event_time = clock->now().time_since_epoch(); | ||
1215 | 297 | auto key_event = builder->key_event(event_time, mir_keyboard_action_repeat, 0, code); | ||
1216 | 298 | sink->handle_input(*key_event); | ||
1217 | 299 | } | ||
1218 | 300 | |||
1219 | 261 | void mtf::FakeInputDeviceImpl::InputDevice::start(mi::InputSink* destination, mi::EventBuilder* event_builder) | 301 | void mtf::FakeInputDeviceImpl::InputDevice::start(mi::InputSink* destination, mi::EventBuilder* event_builder) |
1220 | 262 | { | 302 | { |
1221 | 263 | sink = destination; | 303 | sink = destination; |
1222 | 264 | 304 | ||
1223 | === modified file 'tests/mir_test_framework/fake_input_device_impl.h' | |||
1224 | --- tests/mir_test_framework/fake_input_device_impl.h 2016-03-23 06:39:56 +0000 | |||
1225 | +++ tests/mir_test_framework/fake_input_device_impl.h 2016-03-31 19:18:58 +0000 | |||
1226 | @@ -20,6 +20,7 @@ | |||
1227 | 20 | #define MIR_TEST_FRAMEWORK_FAKE_INPUT_DEVICE_IMPL_H_ | 20 | #define MIR_TEST_FRAMEWORK_FAKE_INPUT_DEVICE_IMPL_H_ |
1228 | 21 | 21 | ||
1229 | 22 | #include "mir_test_framework/fake_input_device.h" | 22 | #include "mir_test_framework/fake_input_device.h" |
1230 | 23 | #include "src/platforms/evdev/key_repeater.h" | ||
1231 | 23 | 24 | ||
1232 | 24 | #include "mir/input/input_device.h" | 25 | #include "mir/input/input_device.h" |
1233 | 25 | #include "mir/input/pointer_settings.h" | 26 | #include "mir/input/pointer_settings.h" |
1234 | @@ -28,6 +29,11 @@ | |||
1235 | 28 | 29 | ||
1236 | 29 | namespace mir | 30 | namespace mir |
1237 | 30 | { | 31 | { |
1238 | 32 | namespace time | ||
1239 | 33 | { | ||
1240 | 34 | class Clock; | ||
1241 | 35 | class AlarmFactory; | ||
1242 | 36 | } | ||
1243 | 31 | namespace dispatch | 37 | namespace dispatch |
1244 | 32 | { | 38 | { |
1245 | 33 | class ActionQueue; | 39 | class ActionQueue; |
1246 | @@ -52,7 +58,10 @@ | |||
1247 | 52 | { | 58 | { |
1248 | 53 | public: | 59 | public: |
1249 | 54 | InputDevice(mir::input::InputDeviceInfo const& info, | 60 | InputDevice(mir::input::InputDeviceInfo const& info, |
1251 | 55 | std::shared_ptr<mir::dispatch::Dispatchable> const& dispatchable); | 61 | std::shared_ptr<mir::dispatch::Dispatchable> const& dispatchable, |
1252 | 62 | std::shared_ptr<mir::time::Clock> const& clock, | ||
1253 | 63 | std::shared_ptr<mir::time::AlarmFactory> const& alarm_factory | ||
1254 | 64 | ); | ||
1255 | 56 | 65 | ||
1256 | 57 | void start(mir::input::InputSink* destination, mir::input::EventBuilder* builder) override; | 66 | void start(mir::input::InputSink* destination, mir::input::EventBuilder* builder) override; |
1257 | 58 | void stop() override; | 67 | void stop() override; |
1258 | @@ -70,19 +79,24 @@ | |||
1259 | 70 | void apply_settings(mir::input::PointerSettings const& settings) override; | 79 | void apply_settings(mir::input::PointerSettings const& settings) override; |
1260 | 71 | mir::optional_value<mir::input::TouchpadSettings> get_touchpad_settings() const override; | 80 | mir::optional_value<mir::input::TouchpadSettings> get_touchpad_settings() const override; |
1261 | 72 | void apply_settings(mir::input::TouchpadSettings const& settings) override; | 81 | void apply_settings(mir::input::TouchpadSettings const& settings) override; |
1262 | 82 | mir::optional_value<mir::input::KeyboardSettings> get_keyboard_settings() const override; | ||
1263 | 83 | void apply_settings(mir::input::KeyboardSettings const& settings) override; | ||
1264 | 73 | 84 | ||
1265 | 74 | private: | 85 | private: |
1266 | 75 | MirPointerAction update_buttons(synthesis::EventAction action, MirPointerButton button); | 86 | MirPointerAction update_buttons(synthesis::EventAction action, MirPointerButton button); |
1267 | 76 | void update_position(int rel_x, int rel_y); | 87 | void update_position(int rel_x, int rel_y); |
1268 | 77 | void map_touch_coordinates(float& x, float& y); | 88 | void map_touch_coordinates(float& x, float& y); |
1269 | 89 | void handle_repeat(int32_t code); | ||
1270 | 78 | 90 | ||
1271 | 79 | mir::input::InputSink* sink{nullptr}; | 91 | mir::input::InputSink* sink{nullptr}; |
1272 | 80 | mir::input::EventBuilder* builder{nullptr}; | 92 | mir::input::EventBuilder* builder{nullptr}; |
1273 | 81 | mir::input::InputDeviceInfo info; | 93 | mir::input::InputDeviceInfo info; |
1274 | 82 | std::shared_ptr<mir::dispatch::Dispatchable> const queue; | 94 | std::shared_ptr<mir::dispatch::Dispatchable> const queue; |
1275 | 95 | std::shared_ptr<mir::time::Clock> const clock; | ||
1276 | 83 | mir::geometry::Point pos, scroll; | 96 | mir::geometry::Point pos, scroll; |
1277 | 84 | MirPointerButtons buttons; | 97 | MirPointerButtons buttons; |
1278 | 85 | mir::input::PointerSettings settings; | 98 | mir::input::PointerSettings settings; |
1279 | 99 | mir::input::evdev::KeyRepeater repeater; | ||
1280 | 86 | }; | 100 | }; |
1281 | 87 | std::shared_ptr<mir::dispatch::ActionQueue> queue; | 101 | std::shared_ptr<mir::dispatch::ActionQueue> queue; |
1282 | 88 | std::shared_ptr<InputDevice> device; | 102 | std::shared_ptr<InputDevice> device; |
1283 | 89 | 103 | ||
1284 | === modified file 'tests/mir_test_framework/stub_input_platform.cpp' | |||
1285 | --- tests/mir_test_framework/stub_input_platform.cpp 2016-03-23 06:39:56 +0000 | |||
1286 | +++ tests/mir_test_framework/stub_input_platform.cpp 2016-03-31 19:18:58 +0000 | |||
1287 | @@ -19,7 +19,10 @@ | |||
1288 | 19 | #include "mir_test_framework/stub_input_platform.h" | 19 | #include "mir_test_framework/stub_input_platform.h" |
1289 | 20 | 20 | ||
1290 | 21 | #include "mir/input/input_device_registry.h" | 21 | #include "mir/input/input_device_registry.h" |
1291 | 22 | #include "mir/time/steady_timer_fd.h" | ||
1292 | 23 | #include "mir/time/steady_clock.h" | ||
1293 | 22 | #include "mir/dispatch/action_queue.h" | 24 | #include "mir/dispatch/action_queue.h" |
1294 | 25 | #include "mir/dispatch/alarm_factory.h" | ||
1295 | 23 | #include "mir/dispatch/multiplexing_dispatchable.h" | 26 | #include "mir/dispatch/multiplexing_dispatchable.h" |
1296 | 24 | #include "mir/module_deleter.h" | 27 | #include "mir/module_deleter.h" |
1297 | 25 | 28 | ||
1298 | @@ -27,6 +30,8 @@ | |||
1299 | 27 | 30 | ||
1300 | 28 | namespace mtf = mir_test_framework; | 31 | namespace mtf = mir_test_framework; |
1301 | 29 | namespace mi = mir::input; | 32 | namespace mi = mir::input; |
1302 | 33 | namespace md = mir::dispatch; | ||
1303 | 34 | namespace mt = mir::time; | ||
1304 | 30 | 35 | ||
1305 | 31 | mtf::StubInputPlatform::StubInputPlatform( | 36 | mtf::StubInputPlatform::StubInputPlatform( |
1306 | 32 | std::shared_ptr<mi::InputDeviceRegistry> const& input_device_registry) | 37 | std::shared_ptr<mi::InputDeviceRegistry> const& input_device_registry) |
1307 | @@ -36,10 +41,12 @@ | |||
1308 | 36 | { | 41 | { |
1309 | 37 | stub_input_platform = this; | 42 | stub_input_platform = this; |
1310 | 38 | platform_dispatchable->add_watch(platform_queue); | 43 | platform_dispatchable->add_watch(platform_queue); |
1311 | 44 | platform_dispatchable->add_watch(alarm_factory); | ||
1312 | 39 | } | 45 | } |
1313 | 40 | 46 | ||
1314 | 41 | mtf::StubInputPlatform::~StubInputPlatform() | 47 | mtf::StubInputPlatform::~StubInputPlatform() |
1315 | 42 | { | 48 | { |
1316 | 49 | platform_dispatchable->remove_watch(alarm_factory); | ||
1317 | 43 | std::lock_guard<decltype(device_store_guard)> lk{device_store_guard}; | 50 | std::lock_guard<decltype(device_store_guard)> lk{device_store_guard}; |
1318 | 44 | device_store.clear(); | 51 | device_store.clear(); |
1319 | 45 | stub_input_platform = nullptr; | 52 | stub_input_platform = nullptr; |
1320 | @@ -128,6 +135,20 @@ | |||
1321 | 128 | input_platform->platform_dispatchable->remove_watch(queue); | 135 | input_platform->platform_dispatchable->remove_watch(queue); |
1322 | 129 | } | 136 | } |
1323 | 130 | 137 | ||
1324 | 138 | std::shared_ptr<mt::AlarmFactory> mtf::StubInputPlatform::get_alarm_factory() | ||
1325 | 139 | { | ||
1326 | 140 | return alarm_factory; | ||
1327 | 141 | } | ||
1328 | 142 | |||
1329 | 143 | std::shared_ptr<mt::Clock> mtf::StubInputPlatform::get_clock() | ||
1330 | 144 | { | ||
1331 | 145 | return steady_clock; | ||
1332 | 146 | } | ||
1333 | 147 | |||
1334 | 148 | std::shared_ptr<mt::SteadyClock> mtf::StubInputPlatform::steady_clock{std::make_shared<mt::SteadyClock>()}; | ||
1335 | 149 | std::shared_ptr<mt::SteadyTimerFd> mtf::StubInputPlatform::steady_timer_fd{std::make_shared<mt::SteadyTimerFd>()}; | ||
1336 | 150 | std::shared_ptr<md::AlarmFactory> mtf::StubInputPlatform::alarm_factory{ | ||
1337 | 151 | std::make_shared<md::AlarmFactory>(mtf::StubInputPlatform::steady_clock, mtf::StubInputPlatform::steady_timer_fd)}; | ||
1338 | 131 | std::atomic<mtf::StubInputPlatform*> mtf::StubInputPlatform::stub_input_platform{nullptr}; | 152 | std::atomic<mtf::StubInputPlatform*> mtf::StubInputPlatform::stub_input_platform{nullptr}; |
1339 | 132 | std::vector<std::weak_ptr<mir::input::InputDevice>> mtf::StubInputPlatform::device_store; | 153 | std::vector<std::weak_ptr<mir::input::InputDevice>> mtf::StubInputPlatform::device_store; |
1340 | 133 | std::mutex mtf::StubInputPlatform::device_store_guard; | 154 | std::mutex mtf::StubInputPlatform::device_store_guard; |
1341 | 134 | 155 | ||
1342 | === modified file 'tests/unit-tests/input/CMakeLists.txt' | |||
1343 | --- tests/unit-tests/input/CMakeLists.txt 2016-03-31 19:18:58 +0000 | |||
1344 | +++ tests/unit-tests/input/CMakeLists.txt 2016-03-31 19:18:58 +0000 | |||
1345 | @@ -14,7 +14,6 @@ | |||
1346 | 14 | ${CMAKE_CURRENT_SOURCE_DIR}/test_default_input_manager.cpp | 14 | ${CMAKE_CURRENT_SOURCE_DIR}/test_default_input_manager.cpp |
1347 | 15 | ${CMAKE_CURRENT_SOURCE_DIR}/test_surface_input_dispatcher.cpp | 15 | ${CMAKE_CURRENT_SOURCE_DIR}/test_surface_input_dispatcher.cpp |
1348 | 16 | ${CMAKE_CURRENT_SOURCE_DIR}/test_seat_input_device_tracker.cpp | 16 | ${CMAKE_CURRENT_SOURCE_DIR}/test_seat_input_device_tracker.cpp |
1349 | 17 | ${CMAKE_CURRENT_SOURCE_DIR}/test_key_repeat_dispatcher.cpp | ||
1350 | 18 | ${CMAKE_CURRENT_SOURCE_DIR}/test_key_repeater.cpp | 17 | ${CMAKE_CURRENT_SOURCE_DIR}/test_key_repeater.cpp |
1351 | 19 | ${CMAKE_CURRENT_SOURCE_DIR}/test_validator.cpp | 18 | ${CMAKE_CURRENT_SOURCE_DIR}/test_validator.cpp |
1352 | 20 | ) | 19 | ) |
1353 | 21 | 20 | ||
1354 | === modified file 'tests/unit-tests/input/evdev/test_evdev_device_detection.cpp' | |||
1355 | --- tests/unit-tests/input/evdev/test_evdev_device_detection.cpp 2016-03-23 06:39:56 +0000 | |||
1356 | +++ tests/unit-tests/input/evdev/test_evdev_device_detection.cpp 2016-03-31 19:18:58 +0000 | |||
1357 | @@ -22,13 +22,18 @@ | |||
1358 | 22 | #include "src/platforms/evdev/libinput_device.h" | 22 | #include "src/platforms/evdev/libinput_device.h" |
1359 | 23 | #include "src/server/report/null_report_factory.h" | 23 | #include "src/server/report/null_report_factory.h" |
1360 | 24 | 24 | ||
1361 | 25 | #include "mir/test/doubles/mock_alarm_factory.h" | ||
1362 | 26 | #include "mir/test/doubles/advanceable_clock.h" | ||
1363 | 25 | #include "mir_test_framework/libinput_environment.h" | 27 | #include "mir_test_framework/libinput_environment.h" |
1364 | 28 | #include "mir/test/fake_shared.h" | ||
1365 | 26 | 29 | ||
1366 | 27 | #include <gtest/gtest.h> | 30 | #include <gtest/gtest.h> |
1367 | 28 | #include <gmock/gmock.h> | 31 | #include <gmock/gmock.h> |
1368 | 29 | #include <tuple> | 32 | #include <tuple> |
1369 | 30 | 33 | ||
1370 | 31 | namespace mtf = mir_test_framework; | 34 | namespace mtf = mir_test_framework; |
1371 | 35 | namespace mt = mir::test; | ||
1372 | 36 | namespace mtd = mt::doubles; | ||
1373 | 32 | namespace mi = mir::input; | 37 | namespace mi = mir::input; |
1374 | 33 | namespace mie = mi::evdev; | 38 | namespace mie = mi::evdev; |
1375 | 34 | 39 | ||
1376 | @@ -44,7 +49,9 @@ | |||
1377 | 44 | udev* ctx = reinterpret_cast<udev*>(1); | 49 | udev* ctx = reinterpret_cast<udev*>(1); |
1378 | 45 | auto dev = env.setup_device(std::get<0>(param)); | 50 | auto dev = env.setup_device(std::get<0>(param)); |
1379 | 46 | std::shared_ptr<libinput> lib = mie::make_libinput(ctx); | 51 | std::shared_ptr<libinput> lib = mie::make_libinput(ctx); |
1381 | 47 | mie::LibInputDevice device(mir::report::null_input_report(), mie::make_libinput_device(lib, dev)); | 52 | ::testing::NiceMock<mtd::MockAlarmFactory> mock_alarm_factory; |
1382 | 53 | mtd::AdvanceableClock clock; | ||
1383 | 54 | mie::LibInputDevice device(mir::report::null_input_report(), mie::make_libinput_device(lib, dev), mt::fake_shared(mock_alarm_factory), mt::fake_shared(clock)); | ||
1384 | 48 | auto info = device.get_device_info(); | 55 | auto info = device.get_device_info(); |
1385 | 49 | EXPECT_THAT(info.capabilities, Eq(std::get<1>(param))); | 56 | EXPECT_THAT(info.capabilities, Eq(std::get<1>(param))); |
1386 | 50 | } | 57 | } |
1387 | 51 | 58 | ||
1388 | === modified file 'tests/unit-tests/input/evdev/test_libinput_device.cpp' | |||
1389 | --- tests/unit-tests/input/evdev/test_libinput_device.cpp 2016-03-23 06:39:56 +0000 | |||
1390 | +++ tests/unit-tests/input/evdev/test_libinput_device.cpp 2016-03-31 19:18:58 +0000 | |||
1391 | @@ -25,12 +25,16 @@ | |||
1392 | 25 | #include "mir/input/input_sink.h" | 25 | #include "mir/input/input_sink.h" |
1393 | 26 | #include "mir/input/pointer_settings.h" | 26 | #include "mir/input/pointer_settings.h" |
1394 | 27 | #include "mir/input/touchpad_settings.h" | 27 | #include "mir/input/touchpad_settings.h" |
1395 | 28 | #include "mir/input/keyboard_settings.h" | ||
1396 | 28 | #include "mir/flags.h" | 29 | #include "mir/flags.h" |
1397 | 29 | #include "mir/geometry/point.h" | 30 | #include "mir/geometry/point.h" |
1398 | 30 | #include "mir/geometry/rectangle.h" | 31 | #include "mir/geometry/rectangle.h" |
1399 | 31 | #include "mir/test/event_matchers.h" | 32 | #include "mir/test/event_matchers.h" |
1400 | 32 | #include "mir/test/doubles/mock_libinput.h" | 33 | #include "mir/test/doubles/mock_libinput.h" |
1401 | 34 | #include "mir/test/doubles/fake_alarm_factory.h" | ||
1402 | 35 | #include "mir/test/doubles/advanceable_clock.h" | ||
1403 | 33 | #include "mir/test/gmock_fixes.h" | 36 | #include "mir/test/gmock_fixes.h" |
1404 | 37 | #include "mir/test/fake_shared.h" | ||
1405 | 34 | #include "mir/udev/wrapper.h" | 38 | #include "mir/udev/wrapper.h" |
1406 | 35 | #include "mir/cookie/authority.h" | 39 | #include "mir/cookie/authority.h" |
1407 | 36 | #include "mir_test_framework/libinput_environment.h" | 40 | #include "mir_test_framework/libinput_environment.h" |
1408 | @@ -60,6 +64,7 @@ | |||
1409 | 60 | }; | 64 | }; |
1410 | 61 | 65 | ||
1411 | 62 | using namespace ::testing; | 66 | using namespace ::testing; |
1412 | 67 | using namespace std::chrono_literals; | ||
1413 | 63 | 68 | ||
1414 | 64 | struct MockInputSink : mi::InputSink | 69 | struct MockInputSink : mi::InputSink |
1415 | 65 | { | 70 | { |
1416 | @@ -124,6 +129,8 @@ | |||
1417 | 124 | struct LibInputDevice : public ::testing::Test | 129 | struct LibInputDevice : public ::testing::Test |
1418 | 125 | { | 130 | { |
1419 | 126 | mtf::LibInputEnvironment env; | 131 | mtf::LibInputEnvironment env; |
1420 | 132 | mtd::AdvanceableClock clock; | ||
1421 | 133 | mtd::FakeAlarmFactory alarm_factory; | ||
1422 | 127 | ::testing::NiceMock<MockInputSink> mock_sink; | 134 | ::testing::NiceMock<MockInputSink> mock_sink; |
1423 | 128 | ::testing::NiceMock<MockEventBuilder> mock_builder; | 135 | ::testing::NiceMock<MockEventBuilder> mock_builder; |
1424 | 129 | std::shared_ptr<libinput> lib; | 136 | std::shared_ptr<libinput> lib; |
1425 | @@ -243,33 +250,33 @@ | |||
1426 | 243 | struct LibInputDeviceOnLaptopKeyboard : public LibInputDevice | 250 | struct LibInputDeviceOnLaptopKeyboard : public LibInputDevice |
1427 | 244 | { | 251 | { |
1428 | 245 | libinput_device*const fake_device = setup_laptop_keyboard(); | 252 | libinput_device*const fake_device = setup_laptop_keyboard(); |
1430 | 246 | mie::LibInputDevice keyboard{mir::report::null_input_report(), mie::make_libinput_device(lib, fake_device)}; | 253 | mie::LibInputDevice keyboard{mir::report::null_input_report(), mie::make_libinput_device(lib, fake_device), mt::fake_shared(alarm_factory), mt::fake_shared(clock)}; |
1431 | 247 | }; | 254 | }; |
1432 | 248 | 255 | ||
1433 | 249 | struct LibInputDeviceOnMouse : public LibInputDevice | 256 | struct LibInputDeviceOnMouse : public LibInputDevice |
1434 | 250 | { | 257 | { |
1435 | 251 | libinput_device*const fake_device = setup_mouse(); | 258 | libinput_device*const fake_device = setup_mouse(); |
1437 | 252 | mie::LibInputDevice mouse{mir::report::null_input_report(), mie::make_libinput_device(lib, fake_device)}; | 259 | mie::LibInputDevice mouse{mir::report::null_input_report(), mie::make_libinput_device(lib, fake_device), mt::fake_shared(alarm_factory), mt::fake_shared(clock)}; |
1438 | 253 | }; | 260 | }; |
1439 | 254 | 261 | ||
1440 | 255 | struct LibInputDeviceOnLaptopKeyboardAndMouse : public LibInputDevice | 262 | struct LibInputDeviceOnLaptopKeyboardAndMouse : public LibInputDevice |
1441 | 256 | { | 263 | { |
1442 | 257 | libinput_device*const fake_device = setup_mouse(); | 264 | libinput_device*const fake_device = setup_mouse(); |
1443 | 258 | libinput_device*const fake_device_2 = setup_laptop_keyboard(); | 265 | libinput_device*const fake_device_2 = setup_laptop_keyboard(); |
1446 | 259 | mie::LibInputDevice keyboard{mir::report::null_input_report(), mie::make_libinput_device(lib, fake_device_2)}; | 266 | mie::LibInputDevice keyboard{mir::report::null_input_report(), mie::make_libinput_device(lib, fake_device_2), mt::fake_shared(alarm_factory), mt::fake_shared(clock)}; |
1447 | 260 | mie::LibInputDevice mouse{mir::report::null_input_report(), mie::make_libinput_device(lib, fake_device)}; | 267 | mie::LibInputDevice mouse{mir::report::null_input_report(), mie::make_libinput_device(lib, fake_device), mt::fake_shared(alarm_factory), mt::fake_shared(clock)}; |
1448 | 261 | }; | 268 | }; |
1449 | 262 | 269 | ||
1450 | 263 | struct LibInputDeviceOnTouchScreen : public LibInputDevice | 270 | struct LibInputDeviceOnTouchScreen : public LibInputDevice |
1451 | 264 | { | 271 | { |
1452 | 265 | libinput_device*const fake_device = setup_touchscreen(); | 272 | libinput_device*const fake_device = setup_touchscreen(); |
1454 | 266 | mie::LibInputDevice touch_screen{mir::report::null_input_report(), mie::make_libinput_device(lib, fake_device)}; | 273 | mie::LibInputDevice touch_screen{mir::report::null_input_report(), mie::make_libinput_device(lib, fake_device), mt::fake_shared(alarm_factory), mt::fake_shared(clock)}; |
1455 | 267 | }; | 274 | }; |
1456 | 268 | 275 | ||
1457 | 269 | struct LibInputDeviceOnTouchpad : public LibInputDevice | 276 | struct LibInputDeviceOnTouchpad : public LibInputDevice |
1458 | 270 | { | 277 | { |
1459 | 271 | libinput_device*const fake_device = setup_touchpad(); | 278 | libinput_device*const fake_device = setup_touchpad(); |
1461 | 272 | mie::LibInputDevice touchpad{mir::report::null_input_report(), mie::make_libinput_device(lib, fake_device)}; | 279 | mie::LibInputDevice touchpad{mir::report::null_input_report(), mie::make_libinput_device(lib, fake_device), mt::fake_shared(alarm_factory), mt::fake_shared(clock)}; |
1462 | 273 | }; | 280 | }; |
1463 | 274 | } | 281 | } |
1464 | 275 | 282 | ||
1465 | @@ -284,7 +291,7 @@ | |||
1466 | 284 | .Times(1); | 291 | .Times(1); |
1467 | 285 | 292 | ||
1468 | 286 | mie::LibInputDevice dev(mir::report::null_input_report(), | 293 | mie::LibInputDevice dev(mir::report::null_input_report(), |
1470 | 287 | mie::make_libinput_device(lib, fake_device)); | 294 | mie::make_libinput_device(lib, fake_device), mt::fake_shared(alarm_factory), mt::fake_shared(clock)); |
1471 | 288 | dev.start(&mock_sink, &mock_builder); | 295 | dev.start(&mock_sink, &mock_builder); |
1472 | 289 | } | 296 | } |
1473 | 290 | 297 | ||
1474 | @@ -299,7 +306,7 @@ | |||
1475 | 299 | EXPECT_CALL(env.mock_libinput, libinput_device_ref(second_fake_device)).Times(1); | 306 | EXPECT_CALL(env.mock_libinput, libinput_device_ref(second_fake_device)).Times(1); |
1476 | 300 | 307 | ||
1477 | 301 | mie::LibInputDevice dev(mir::report::null_input_report(), | 308 | mie::LibInputDevice dev(mir::report::null_input_report(), |
1479 | 302 | mie::make_libinput_device(lib, fake_device)); | 309 | mie::make_libinput_device(lib, fake_device), mt::fake_shared(alarm_factory), mt::fake_shared(clock)); |
1480 | 303 | dev.add_device_of_group(mie::make_libinput_device(lib, second_fake_device)); | 310 | dev.add_device_of_group(mie::make_libinput_device(lib, second_fake_device)); |
1481 | 304 | dev.start(&mock_sink, &mock_builder); | 311 | dev.start(&mock_sink, &mock_builder); |
1482 | 305 | } | 312 | } |
1483 | @@ -310,7 +317,7 @@ | |||
1484 | 310 | auto second_fake_device = setup_trackpad(); | 317 | auto second_fake_device = setup_trackpad(); |
1485 | 311 | 318 | ||
1486 | 312 | mie::LibInputDevice dev(mir::report::null_input_report(), | 319 | mie::LibInputDevice dev(mir::report::null_input_report(), |
1488 | 313 | mie::make_libinput_device(lib, fake_device)); | 320 | mie::make_libinput_device(lib, fake_device), mt::fake_shared(alarm_factory), mt::fake_shared(clock)); |
1489 | 314 | dev.add_device_of_group(mie::make_libinput_device(lib, second_fake_device)); | 321 | dev.add_device_of_group(mie::make_libinput_device(lib, second_fake_device)); |
1490 | 315 | auto info = dev.get_device_info(); | 322 | auto info = dev.get_device_info(); |
1491 | 316 | 323 | ||
1492 | @@ -327,7 +334,7 @@ | |||
1493 | 327 | EXPECT_CALL(env.mock_libinput, libinput_device_unref(fake_device)) | 334 | EXPECT_CALL(env.mock_libinput, libinput_device_unref(fake_device)) |
1494 | 328 | .Times(1); | 335 | .Times(1); |
1495 | 329 | 336 | ||
1497 | 330 | mie::LibInputDevice dev(mir::report::null_input_report(), mie::make_libinput_device(lib, fake_device)); | 337 | mie::LibInputDevice dev(mir::report::null_input_report(), mie::make_libinput_device(lib, fake_device), mt::fake_shared(alarm_factory), mt::fake_shared(clock)); |
1498 | 331 | } | 338 | } |
1499 | 332 | 339 | ||
1500 | 333 | TEST_F(LibInputDeviceOnLaptopKeyboard, process_event_converts_key_event) | 340 | TEST_F(LibInputDeviceOnLaptopKeyboard, process_event_converts_key_event) |
1501 | @@ -343,6 +350,31 @@ | |||
1502 | 343 | process_events(keyboard); | 350 | process_events(keyboard); |
1503 | 344 | } | 351 | } |
1504 | 345 | 352 | ||
1505 | 353 | TEST_F(LibInputDeviceOnLaptopKeyboard, key_press_triggers_repeat) | ||
1506 | 354 | { | ||
1507 | 355 | mi::KeyboardSettings keyboard_settings; | ||
1508 | 356 | keyboard_settings.repeat_delay = 600ms; | ||
1509 | 357 | keyboard_settings.repeat_interval = 200ms; | ||
1510 | 358 | std::function<void()> timer_callback; | ||
1511 | 359 | |||
1512 | 360 | EXPECT_CALL(mock_sink, handle_input(AllOf( | ||
1513 | 361 | mt::KeyOfScanCode(KEY_A), | ||
1514 | 362 | mt::KeyDownEvent()))) | ||
1515 | 363 | .Times(1); | ||
1516 | 364 | EXPECT_CALL(mock_sink, handle_input(AllOf( | ||
1517 | 365 | mt::KeyOfScanCode(KEY_A), | ||
1518 | 366 | mt::KeyRepeatEvent()))) | ||
1519 | 367 | .Times(2); | ||
1520 | 368 | |||
1521 | 369 | keyboard.start(&mock_sink, &mock_builder); | ||
1522 | 370 | keyboard.apply_settings(keyboard_settings); | ||
1523 | 371 | env.mock_libinput.setup_key_event(fake_device, event_time_1, KEY_A, LIBINPUT_KEY_STATE_PRESSED); | ||
1524 | 372 | process_events(keyboard); | ||
1525 | 373 | |||
1526 | 374 | alarm_factory.advance_by(601ms); | ||
1527 | 375 | alarm_factory.advance_by(201ms); | ||
1528 | 376 | } | ||
1529 | 377 | |||
1530 | 346 | TEST_F(LibInputDeviceOnLaptopKeyboard, process_event_accumulates_key_state) | 378 | TEST_F(LibInputDeviceOnLaptopKeyboard, process_event_accumulates_key_state) |
1531 | 347 | { | 379 | { |
1532 | 348 | InSequence seq; | 380 | InSequence seq; |
1533 | 349 | 381 | ||
1534 | === modified file 'tests/unit-tests/input/test_default_device.cpp' | |||
1535 | --- tests/unit-tests/input/test_default_device.cpp 2016-03-23 06:39:56 +0000 | |||
1536 | +++ tests/unit-tests/input/test_default_device.cpp 2016-03-31 19:18:58 +0000 | |||
1537 | @@ -21,54 +21,23 @@ | |||
1538 | 21 | #include "mir/input/touchpad_configuration.h" | 21 | #include "mir/input/touchpad_configuration.h" |
1539 | 22 | #include "mir/input/pointer_configuration.h" | 22 | #include "mir/input/pointer_configuration.h" |
1540 | 23 | #include "mir/dispatch/action_queue.h" | 23 | #include "mir/dispatch/action_queue.h" |
1541 | 24 | #include "mir/test/doubles/mock_input_device.h" | ||
1542 | 24 | #include <gtest/gtest.h> | 25 | #include <gtest/gtest.h> |
1543 | 25 | #include <gmock/gmock.h> | 26 | #include <gmock/gmock.h> |
1544 | 26 | #include <stdexcept> | 27 | #include <stdexcept> |
1545 | 27 | 28 | ||
1546 | 28 | namespace mi = mir::input; | 29 | namespace mi = mir::input; |
1547 | 30 | namespace mtd = mir::test::doubles; | ||
1548 | 29 | namespace md = mir::dispatch; | 31 | namespace md = mir::dispatch; |
1549 | 30 | using namespace ::testing; | 32 | using namespace ::testing; |
1550 | 31 | namespace | 33 | namespace |
1551 | 32 | { | 34 | { |
1552 | 33 | struct MockInputDevice : public mi::InputDevice | ||
1553 | 34 | { | ||
1554 | 35 | MOCK_METHOD2(start, void(mi::InputSink* destination, mi::EventBuilder* builder)); | ||
1555 | 36 | MOCK_METHOD0(stop, void()); | ||
1556 | 37 | MOCK_METHOD0(get_device_info, mi::InputDeviceInfo()); | ||
1557 | 38 | MOCK_CONST_METHOD0(get_pointer_settings, mir::optional_value<mi::PointerSettings>()); | ||
1558 | 39 | MOCK_METHOD1(apply_settings, void(mi::PointerSettings const&)); | ||
1559 | 40 | MOCK_CONST_METHOD0(get_touchpad_settings, mir::optional_value<mi::TouchpadSettings>()); | ||
1560 | 41 | MOCK_METHOD1(apply_settings, void(mi::TouchpadSettings const&)); | ||
1561 | 42 | }; | ||
1562 | 43 | |||
1563 | 44 | struct DefaultDevice : Test | 35 | struct DefaultDevice : Test |
1564 | 45 | { | 36 | { |
1568 | 46 | NiceMock<MockInputDevice> touchpad; | 37 | NiceMock<mtd::MockInputDevice> touchpad{"name", "unique", mi::DeviceCapability::touchpad|mi::DeviceCapability::pointer}; |
1569 | 47 | NiceMock<MockInputDevice> mouse; | 38 | NiceMock<mtd::MockInputDevice> mouse{"name", "unique", mi::DeviceCapability::pointer}; |
1570 | 48 | NiceMock<MockInputDevice> keyboard; | 39 | NiceMock<mtd::MockInputDevice> keyboard{"name", "unique", mi::DeviceCapability::keyboard}; |
1571 | 49 | std::shared_ptr<md::ActionQueue> queue{std::make_shared<md::ActionQueue>()}; | 40 | std::shared_ptr<md::ActionQueue> queue{std::make_shared<md::ActionQueue>()}; |
1572 | 50 | |||
1573 | 51 | DefaultDevice() | ||
1574 | 52 | { | ||
1575 | 53 | using optional_pointer_settings = mir::optional_value<mi::PointerSettings>; | ||
1576 | 54 | using optional_touchpad_settings = mir::optional_value<mi::TouchpadSettings>; | ||
1577 | 55 | ON_CALL(touchpad, get_device_info()) | ||
1578 | 56 | .WillByDefault(Return(mi::InputDeviceInfo{"name", "unique", mi::DeviceCapability::touchpad|mi::DeviceCapability::pointer})); | ||
1579 | 57 | ON_CALL(touchpad, get_pointer_settings()) | ||
1580 | 58 | .WillByDefault(Return(optional_pointer_settings{mi::PointerSettings{}})); | ||
1581 | 59 | ON_CALL(touchpad, get_touchpad_settings()) | ||
1582 | 60 | .WillByDefault(Return(optional_touchpad_settings{mi::TouchpadSettings{}})); | ||
1583 | 61 | |||
1584 | 62 | ON_CALL(mouse, get_device_info()) | ||
1585 | 63 | .WillByDefault(Return(mi::InputDeviceInfo{"name", "unique", mi::DeviceCapability::pointer})); | ||
1586 | 64 | ON_CALL(mouse, get_pointer_settings()).WillByDefault(Return(optional_pointer_settings{mi::PointerSettings{}})); | ||
1587 | 65 | ON_CALL(mouse, get_touchpad_settings()).WillByDefault(Return(optional_touchpad_settings{})); | ||
1588 | 66 | |||
1589 | 67 | ON_CALL(keyboard, get_device_info()) | ||
1590 | 68 | .WillByDefault(Return(mi::InputDeviceInfo{"name", "unique", mi::DeviceCapability::keyboard})); | ||
1591 | 69 | ON_CALL(keyboard, get_pointer_settings()).WillByDefault(Return(optional_pointer_settings{})); | ||
1592 | 70 | ON_CALL(keyboard, get_touchpad_settings()).WillByDefault(Return(optional_touchpad_settings{})); | ||
1593 | 71 | } | ||
1594 | 72 | }; | 41 | }; |
1595 | 73 | 42 | ||
1596 | 74 | } | 43 | } |
1597 | @@ -91,7 +60,6 @@ | |||
1598 | 91 | EXPECT_THROW({dev.apply_pointer_configuration(pointer_conf);}, std::invalid_argument); | 60 | EXPECT_THROW({dev.apply_pointer_configuration(pointer_conf);}, std::invalid_argument); |
1599 | 92 | } | 61 | } |
1600 | 93 | 62 | ||
1601 | 94 | |||
1602 | 95 | TEST_F(DefaultDevice, accepts_pointer_config_on_mice) | 63 | TEST_F(DefaultDevice, accepts_pointer_config_on_mice) |
1603 | 96 | { | 64 | { |
1604 | 97 | mi::DefaultDevice dev(MirInputDeviceId{17}, queue, mouse); | 65 | mi::DefaultDevice dev(MirInputDeviceId{17}, queue, mouse); |
1605 | @@ -118,6 +86,7 @@ | |||
1606 | 118 | queue->dispatch(md::FdEvent::readable); | 86 | queue->dispatch(md::FdEvent::readable); |
1607 | 119 | } | 87 | } |
1608 | 120 | 88 | ||
1609 | 89 | |||
1610 | 121 | TEST_F(DefaultDevice, ensures_cursor_accleration_bias_is_in_range) | 90 | TEST_F(DefaultDevice, ensures_cursor_accleration_bias_is_in_range) |
1611 | 122 | { | 91 | { |
1612 | 123 | mi::DefaultDevice dev(MirInputDeviceId{17}, queue, touchpad); | 92 | mi::DefaultDevice dev(MirInputDeviceId{17}, queue, touchpad); |
1613 | 124 | 93 | ||
1614 | === removed file 'tests/unit-tests/input/test_key_repeat_dispatcher.cpp' | |||
1615 | --- tests/unit-tests/input/test_key_repeat_dispatcher.cpp 2016-03-23 06:39:56 +0000 | |||
1616 | +++ tests/unit-tests/input/test_key_repeat_dispatcher.cpp 1970-01-01 00:00:00 +0000 | |||
1617 | @@ -1,184 +0,0 @@ | |||
1618 | 1 | /* | ||
1619 | 2 | * Copyright © 2015 Canonical Ltd. | ||
1620 | 3 | * | ||
1621 | 4 | * This program is free software: you can redistribute it and/or modify | ||
1622 | 5 | * it under the terms of the GNU General Public License version 3 as | ||
1623 | 6 | * published by the Free Software Foundation. | ||
1624 | 7 | * | ||
1625 | 8 | * This program is distributed in the hope that it will be useful, | ||
1626 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1627 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1628 | 11 | * GNU General Public License for more details. | ||
1629 | 12 | * | ||
1630 | 13 | * You should have received a copy of the GNU General Public License | ||
1631 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1632 | 15 | * | ||
1633 | 16 | * Authored by: Robert Carr <robert.carr@canonical.com> | ||
1634 | 17 | */ | ||
1635 | 18 | |||
1636 | 19 | #include "src/server/input/key_repeat_dispatcher.h" | ||
1637 | 20 | |||
1638 | 21 | #include "mir/events/event_private.h" | ||
1639 | 22 | #include "mir/events/event_builders.h" | ||
1640 | 23 | #include "mir/time/alarm.h" | ||
1641 | 24 | #include "mir/time/alarm_factory.h" | ||
1642 | 25 | #include "mir/cookie/authority.h" | ||
1643 | 26 | #include "mir/input/input_device_observer.h" | ||
1644 | 27 | #include "mir/input/pointer_configuration.h" | ||
1645 | 28 | #include "mir/input/touchpad_configuration.h" | ||
1646 | 29 | #include "mir/input/device.h" | ||
1647 | 30 | |||
1648 | 31 | #include "mir/test/fake_shared.h" | ||
1649 | 32 | #include "mir/test/event_matchers.h" | ||
1650 | 33 | #include "mir/test/doubles/mock_input_dispatcher.h" | ||
1651 | 34 | #include "mir/test/doubles/mock_input_device_hub.h" | ||
1652 | 35 | |||
1653 | 36 | #include <gtest/gtest.h> | ||
1654 | 37 | #include <gmock/gmock.h> | ||
1655 | 38 | |||
1656 | 39 | namespace mi = mir::input; | ||
1657 | 40 | namespace mev = mir::events; | ||
1658 | 41 | namespace mt = mir::test; | ||
1659 | 42 | namespace mtd = mt::doubles; | ||
1660 | 43 | |||
1661 | 44 | using namespace ::testing; | ||
1662 | 45 | |||
1663 | 46 | namespace | ||
1664 | 47 | { | ||
1665 | 48 | struct MockAlarm : public mir::time::Alarm | ||
1666 | 49 | { | ||
1667 | 50 | MOCK_METHOD0(cancel, bool()); | ||
1668 | 51 | MOCK_CONST_METHOD0(state, mir::time::Alarm::State()); | ||
1669 | 52 | MOCK_METHOD1(reschedule_in, bool(std::chrono::milliseconds)); | ||
1670 | 53 | MOCK_METHOD1(reschedule_for, bool(mir::time::Timestamp)); | ||
1671 | 54 | |||
1672 | 55 | // destructor cancels the alarm | ||
1673 | 56 | ~MockAlarm() | ||
1674 | 57 | { | ||
1675 | 58 | cancel(); | ||
1676 | 59 | } | ||
1677 | 60 | }; | ||
1678 | 61 | |||
1679 | 62 | struct MockAlarmFactory : public mir::time::AlarmFactory | ||
1680 | 63 | { | ||
1681 | 64 | MOCK_METHOD1(create_alarm_adapter, mir::time::Alarm*(std::function<void()> const&)); | ||
1682 | 65 | std::unique_ptr<mir::time::Alarm> create_alarm(std::function<void()> const& cb) | ||
1683 | 66 | { | ||
1684 | 67 | return std::unique_ptr<mir::time::Alarm>(create_alarm_adapter(cb)); | ||
1685 | 68 | } | ||
1686 | 69 | |||
1687 | 70 | std::unique_ptr<mir::time::Alarm> create_alarm(std::shared_ptr<mir::LockableCallback> const&) | ||
1688 | 71 | { | ||
1689 | 72 | return nullptr; | ||
1690 | 73 | } | ||
1691 | 74 | }; | ||
1692 | 75 | |||
1693 | 76 | struct StubDevice : public mi::Device | ||
1694 | 77 | { | ||
1695 | 78 | MirInputDeviceId device_id; | ||
1696 | 79 | StubDevice(MirInputDeviceId id) : device_id(id) {} | ||
1697 | 80 | MirInputDeviceId id() const { return device_id;} | ||
1698 | 81 | mi::DeviceCapabilities capabilities() const {return mi::DeviceCapability::keyboard;} | ||
1699 | 82 | std::string name() const {return {};} | ||
1700 | 83 | std::string unique_id() const {return {};} | ||
1701 | 84 | |||
1702 | 85 | mir::optional_value<mi::PointerConfiguration> pointer_configuration() const {return {};} | ||
1703 | 86 | void apply_pointer_configuration(mi::PointerConfiguration const&) {;} | ||
1704 | 87 | mir::optional_value<mi::TouchpadConfiguration> touchpad_configuration() const {return {};} | ||
1705 | 88 | void apply_touchpad_configuration(mi::TouchpadConfiguration const&) {} | ||
1706 | 89 | }; | ||
1707 | 90 | |||
1708 | 91 | struct KeyRepeatDispatcher : public testing::Test | ||
1709 | 92 | { | ||
1710 | 93 | KeyRepeatDispatcher() | ||
1711 | 94 | : dispatcher(mock_next_dispatcher, mock_alarm_factory, cookie_authority, true, repeat_time, repeat_delay) | ||
1712 | 95 | { | ||
1713 | 96 | ON_CALL(hub,add_observer(_)).WillByDefault(SaveArg<0>(&observer)); | ||
1714 | 97 | dispatcher.set_input_device_hub(mt::fake_shared(hub)); | ||
1715 | 98 | } | ||
1716 | 99 | void simulate_device_removal() | ||
1717 | 100 | { | ||
1718 | 101 | StubDevice dev(test_device); | ||
1719 | 102 | observer->device_removed(mt::fake_shared(dev)); | ||
1720 | 103 | observer->changes_complete(); | ||
1721 | 104 | } | ||
1722 | 105 | |||
1723 | 106 | const MirInputDeviceId test_device = 123; | ||
1724 | 107 | std::shared_ptr<mtd::MockInputDispatcher> mock_next_dispatcher = std::make_shared<mtd::MockInputDispatcher>(); | ||
1725 | 108 | std::shared_ptr<MockAlarmFactory> mock_alarm_factory = std::make_shared<MockAlarmFactory>(); | ||
1726 | 109 | std::shared_ptr<mir::cookie::Authority> cookie_authority = mir::cookie::Authority::create(); | ||
1727 | 110 | std::chrono::milliseconds const repeat_time{2}; | ||
1728 | 111 | std::chrono::milliseconds const repeat_delay{1}; | ||
1729 | 112 | std::shared_ptr<mi::InputDeviceObserver> observer; | ||
1730 | 113 | NiceMock<mtd::MockInputDeviceHub> hub; | ||
1731 | 114 | mi::KeyRepeatDispatcher dispatcher; | ||
1732 | 115 | |||
1733 | 116 | mir::EventUPtr a_key_down_event() | ||
1734 | 117 | { | ||
1735 | 118 | return mev::make_event(test_device, std::chrono::nanoseconds(0), std::vector<uint8_t>{}, mir_keyboard_action_down, 0, 0, mir_input_event_modifier_alt); | ||
1736 | 119 | } | ||
1737 | 120 | |||
1738 | 121 | mir::EventUPtr a_key_up_event() | ||
1739 | 122 | { | ||
1740 | 123 | return mev::make_event(test_device, std::chrono::nanoseconds(0), std::vector<uint8_t>{}, mir_keyboard_action_up, 0, 0, mir_input_event_modifier_alt); | ||
1741 | 124 | } | ||
1742 | 125 | }; | ||
1743 | 126 | } | ||
1744 | 127 | |||
1745 | 128 | TEST_F(KeyRepeatDispatcher, forwards_start_stop) | ||
1746 | 129 | { | ||
1747 | 130 | InSequence seq; | ||
1748 | 131 | EXPECT_CALL(*mock_next_dispatcher, start()).Times(1); | ||
1749 | 132 | EXPECT_CALL(*mock_next_dispatcher, stop()).Times(1); | ||
1750 | 133 | |||
1751 | 134 | dispatcher.start(); | ||
1752 | 135 | dispatcher.stop(); | ||
1753 | 136 | } | ||
1754 | 137 | |||
1755 | 138 | TEST_F(KeyRepeatDispatcher, schedules_alarm_to_repeat_key_down) | ||
1756 | 139 | { | ||
1757 | 140 | MockAlarm *mock_alarm = new MockAlarm; // deleted by AlarmFactory | ||
1758 | 141 | std::function<void()> alarm_function; | ||
1759 | 142 | |||
1760 | 143 | InSequence seq; | ||
1761 | 144 | EXPECT_CALL(*mock_alarm_factory, create_alarm_adapter(_)).Times(1). | ||
1762 | 145 | WillOnce(DoAll(SaveArg<0>(&alarm_function), Return(mock_alarm))); | ||
1763 | 146 | // Once for initial down and again when invoked | ||
1764 | 147 | EXPECT_CALL(*mock_alarm, reschedule_in(repeat_time)).Times(1).WillOnce(Return(true)); | ||
1765 | 148 | EXPECT_CALL(*mock_next_dispatcher, dispatch(mt::KeyDownEvent())).Times(1); | ||
1766 | 149 | EXPECT_CALL(*mock_next_dispatcher, dispatch(mt::KeyRepeatEvent())).Times(1); | ||
1767 | 150 | EXPECT_CALL(*mock_alarm, reschedule_in(repeat_delay)).Times(1).WillOnce(Return(true)); | ||
1768 | 151 | EXPECT_CALL(*mock_next_dispatcher, dispatch(mt::KeyUpEvent())).Times(1); | ||
1769 | 152 | |||
1770 | 153 | // Schedule the repeat | ||
1771 | 154 | dispatcher.dispatch(*a_key_down_event()); | ||
1772 | 155 | // Trigger the repeat | ||
1773 | 156 | alarm_function(); | ||
1774 | 157 | // Trigger the cancel | ||
1775 | 158 | dispatcher.dispatch(*a_key_up_event()); | ||
1776 | 159 | } | ||
1777 | 160 | |||
1778 | 161 | TEST_F(KeyRepeatDispatcher, stops_repeat_on_device_removal) | ||
1779 | 162 | { | ||
1780 | 163 | MockAlarm *mock_alarm = new MockAlarm; | ||
1781 | 164 | std::function<void()> alarm_function; | ||
1782 | 165 | bool alarm_canceled = false; | ||
1783 | 166 | |||
1784 | 167 | InSequence seq; | ||
1785 | 168 | EXPECT_CALL(*mock_alarm_factory, create_alarm_adapter(_)).Times(1). | ||
1786 | 169 | WillOnce(DoAll(SaveArg<0>(&alarm_function), Return(mock_alarm))); | ||
1787 | 170 | // Once for initial down and again when invoked | ||
1788 | 171 | EXPECT_CALL(*mock_alarm, reschedule_in(repeat_time)).Times(1).WillOnce(Return(true)); | ||
1789 | 172 | EXPECT_CALL(*mock_next_dispatcher, dispatch(mt::KeyDownEvent())).Times(1); | ||
1790 | 173 | EXPECT_CALL(*mock_next_dispatcher, dispatch(mt::KeyRepeatEvent())).Times(1); | ||
1791 | 174 | EXPECT_CALL(*mock_alarm, reschedule_in(repeat_delay)).Times(1).WillOnce(Return(true)); | ||
1792 | 175 | ON_CALL(*mock_alarm, cancel()).WillByDefault(Invoke([&](){alarm_canceled = true; return true;})); | ||
1793 | 176 | |||
1794 | 177 | dispatcher.dispatch(*a_key_down_event()); | ||
1795 | 178 | |||
1796 | 179 | alarm_function(); | ||
1797 | 180 | Mock::VerifyAndClearExpectations(mock_alarm); // mock_alarm will be deleted after this | ||
1798 | 181 | |||
1799 | 182 | simulate_device_removal(); | ||
1800 | 183 | EXPECT_THAT(alarm_canceled, Eq(true)); | ||
1801 | 184 | } | ||
1802 | 185 | 0 | ||
1803 | === modified file 'tests/unit-tests/input/test_x11_platform.cpp' | |||
1804 | --- tests/unit-tests/input/test_x11_platform.cpp 2016-03-23 06:39:56 +0000 | |||
1805 | +++ tests/unit-tests/input/test_x11_platform.cpp 2016-03-31 19:18:58 +0000 | |||
1806 | @@ -34,12 +34,15 @@ | |||
1807 | 34 | #include "mir/cookie/authority.h" | 34 | #include "mir/cookie/authority.h" |
1808 | 35 | #include "mir/test/event_matchers.h" | 35 | #include "mir/test/event_matchers.h" |
1809 | 36 | 36 | ||
1810 | 37 | #include "mir/input/keyboard_settings.h" | ||
1811 | 38 | |||
1812 | 37 | namespace md = mir::dispatch; | 39 | namespace md = mir::dispatch; |
1813 | 38 | namespace mi = mir::input; | 40 | namespace mi = mir::input; |
1814 | 39 | namespace mt = mir::test; | 41 | namespace mt = mir::test; |
1815 | 40 | namespace mtd = mt::doubles; | 42 | namespace mtd = mt::doubles; |
1816 | 41 | 43 | ||
1817 | 42 | using namespace ::testing; | 44 | using namespace ::testing; |
1818 | 45 | using namespace std::chrono_literals; | ||
1819 | 43 | 46 | ||
1820 | 44 | namespace | 47 | namespace |
1821 | 45 | { | 48 | { |
1822 | @@ -245,3 +248,80 @@ | |||
1823 | 245 | 248 | ||
1824 | 246 | process_input_event(); | 249 | process_input_event(); |
1825 | 247 | } | 250 | } |
1826 | 251 | |||
1827 | 252 | TEST_F(X11PlatformTest, keyboard_device_forwards_x11_repeat_settings) | ||
1828 | 253 | { | ||
1829 | 254 | XkbControlsRec ctrls_desc; | ||
1830 | 255 | XkbDescRec xkb_desc; | ||
1831 | 256 | ctrls_desc.repeat_delay = 600; | ||
1832 | 257 | ctrls_desc.repeat_interval = 100; | ||
1833 | 258 | EXPECT_CALL(mock_x11, XGetKeyboardControl(_,_)) | ||
1834 | 259 | .WillOnce(Invoke([](Display*, XKeyboardState* state) | ||
1835 | 260 | { | ||
1836 | 261 | state->global_auto_repeat = 1; | ||
1837 | 262 | return 1; | ||
1838 | 263 | })); | ||
1839 | 264 | EXPECT_CALL(mock_x11, XkbQueryExtension(_,_,_,_,_,_)) | ||
1840 | 265 | .WillOnce(Return(1)); | ||
1841 | 266 | EXPECT_CALL(mock_x11, XkbAllocKeyboard()) | ||
1842 | 267 | .WillOnce(Return(&xkb_desc)); | ||
1843 | 268 | EXPECT_CALL(mock_x11, XkbGetControls(_,XkbRepeatKeysMask, &xkb_desc)) | ||
1844 | 269 | .WillOnce(Invoke([&](Display*, int, XkbDescPtr) | ||
1845 | 270 | { | ||
1846 | 271 | xkb_desc.ctrls = &ctrls_desc; | ||
1847 | 272 | return 1; | ||
1848 | 273 | })); | ||
1849 | 274 | EXPECT_CALL(mock_x11, XkbFreeKeyboard(&xkb_desc, _, _)); | ||
1850 | 275 | |||
1851 | 276 | |||
1852 | 277 | capture_devices(); x11_platform.start(); | ||
1853 | 278 | |||
1854 | 279 | for (auto const device : devices) | ||
1855 | 280 | { | ||
1856 | 281 | if (contains(device->get_device_info().capabilities,mi::DeviceCapability::keyboard)) | ||
1857 | 282 | { | ||
1858 | 283 | auto settings = device->get_keyboard_settings(); | ||
1859 | 284 | EXPECT_THAT(settings.value().repeat_enabled, Eq(true)); | ||
1860 | 285 | EXPECT_THAT(settings.value().repeat_delay, Eq(600ms)); | ||
1861 | 286 | EXPECT_THAT(settings.value().repeat_interval, Eq(100ms)); | ||
1862 | 287 | } | ||
1863 | 288 | } | ||
1864 | 289 | } | ||
1865 | 290 | |||
1866 | 291 | TEST_F(X11PlatformTest, keyboard_device_forwards_settings_to_x11) | ||
1867 | 292 | { | ||
1868 | 293 | XkbControlsRec ctrls_desc; | ||
1869 | 294 | XkbDescRec xkb_desc; | ||
1870 | 295 | |||
1871 | 296 | EXPECT_CALL(mock_x11, XChangeKeyboardControl(_, KBAutoRepeatMode,_)); | ||
1872 | 297 | EXPECT_CALL(mock_x11, XkbQueryExtension(_,_,_,_,_,_)) | ||
1873 | 298 | .WillOnce(Return(1)); | ||
1874 | 299 | EXPECT_CALL(mock_x11, XkbAllocKeyboard()) | ||
1875 | 300 | .WillOnce(Return(&xkb_desc)); | ||
1876 | 301 | EXPECT_CALL(mock_x11, XkbGetControls(_,XkbRepeatKeysMask, &xkb_desc)) | ||
1877 | 302 | .WillOnce(Invoke([&](Display*, int, XkbDescPtr) | ||
1878 | 303 | { | ||
1879 | 304 | xkb_desc.ctrls = &ctrls_desc; | ||
1880 | 305 | return 1; | ||
1881 | 306 | })); | ||
1882 | 307 | EXPECT_CALL(mock_x11, XkbSetControls(_,XkbRepeatKeysMask, &xkb_desc)) | ||
1883 | 308 | .WillOnce(Return(1)); | ||
1884 | 309 | EXPECT_CALL(mock_x11, XkbFreeKeyboard(&xkb_desc, _, _)); | ||
1885 | 310 | |||
1886 | 311 | |||
1887 | 312 | capture_devices(); x11_platform.start(); | ||
1888 | 313 | |||
1889 | 314 | for (auto const device : devices) | ||
1890 | 315 | { | ||
1891 | 316 | if (contains(device->get_device_info().capabilities,mi::DeviceCapability::keyboard)) | ||
1892 | 317 | { | ||
1893 | 318 | mi::KeyboardSettings settings; | ||
1894 | 319 | settings.repeat_interval = 23ms; | ||
1895 | 320 | settings.repeat_delay = 1000ms; | ||
1896 | 321 | device->apply_settings(settings); | ||
1897 | 322 | |||
1898 | 323 | EXPECT_THAT(ctrls_desc.repeat_delay, Eq(1000)); | ||
1899 | 324 | EXPECT_THAT(ctrls_desc.repeat_interval, Eq(23)); | ||
1900 | 325 | } | ||
1901 | 326 | } | ||
1902 | 327 | } |
FAILED: Continuous integration, rev:3421 /mir-jenkins. ubuntu. com/job/ mir-ci/ 644/ /mir-jenkins. ubuntu. com/job/ build-mir/ 580/console /mir-jenkins. ubuntu. com/job/ build-0- fetch/616 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= vivid+overlay/ 608 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial/ 608 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= vivid+overlay/ 590/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial/ 590/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 590/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 590/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 590/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial/ 590/console
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
deb: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild: /mir-jenkins. ubuntu. com/job/ mir-ci/ 644/rebuild
https:/