Merge lp:~andreas-pokorny/mir/fix-1549701 into lp:mir
- fix-1549701
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | Andreas Pokorny |
Approved revision: | no longer in the source branch. |
Merged at revision: | 3451 |
Proposed branch: | lp:~andreas-pokorny/mir/fix-1549701 |
Merge into: | lp:mir |
Diff against target: |
299 lines (+137/-21) 4 files modified
src/server/input/default_configuration.cpp (+37/-1) src/server/input/key_repeat_dispatcher.cpp (+34/-15) src/server/input/key_repeat_dispatcher.h (+7/-1) tests/unit-tests/input/test_key_repeat_dispatcher.cpp (+59/-4) |
To merge this branch: | bzr merge lp:~andreas-pokorny/mir/fix-1549701 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir CI Bot | continuous-integration | Approve | |
Alberto Aguirre (community) | Approve | ||
Alan Griffiths | Approve | ||
Kevin DuBois (community) | Approve | ||
Cemil Azizoglu (community) | Approve | ||
Review via email: mp+290366@code.launchpad.net |
Commit message
Disable key repeat on arale & mtk-tpd (LP: #1549701)
The arale touchscreen driver simulates a button. When the screen is turned off while the button is held and then released mir will not receive the release event or any notice that the device is off. To avoid that mir keeps on sending repeat events, repeats for the touchscreen are disabled.
Description of the change
This is the lp:mir version of the input quirk for mx4
Mir CI Bot (mir-ci-bot) wrote : | # |
Cemil Azizoglu (cemil-azizoglu) wrote : | # |
Ugh all the device specific names/vars are a bit messy but I see why you'd need them.
Alberto Aguirre (albaguirre) wrote : | # |
209 "#include "linux/
I guess this is only available for newer kernels...
Alan Griffiths (alan-griffiths) wrote : | # |
The abbreviations(?) "mtk_tpd" and "mtk" are used without explanation: e.g. KeyRepeatDispat
Could we find better names?
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3429
https:/
Executed test runs:
ABORTED: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3431
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3431
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
https:/
Executed test runs:
FAILURE: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
https:/
Executed test runs:
FAILURE: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
https:/
Executed test runs:
FAILURE: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
https:/
Executed test runs:
FAILURE: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
https:/
Executed test runs:
FAILURE: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3432
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3432
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3432
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) : | # |
Preview Diff
1 | === modified file 'src/server/input/default_configuration.cpp' |
2 | --- src/server/input/default_configuration.cpp 2016-04-05 21:20:21 +0000 |
3 | +++ src/server/input/default_configuration.cpp 2016-04-08 06:59:01 +0000 |
4 | @@ -48,6 +48,7 @@ |
5 | #include "mir/abnormal_exit.h" |
6 | #include "mir/glib_main_loop.h" |
7 | #include "mir/log.h" |
8 | +#include "mir/shared_library.h" |
9 | #include "mir/dispatch/action_queue.h" |
10 | |
11 | #include "mir_toolkit/cursors.h" |
12 | @@ -60,6 +61,41 @@ |
13 | namespace msh = mir::shell; |
14 | namespace md = mir::dispatch; |
15 | |
16 | +namespace |
17 | +{ |
18 | + |
19 | +bool is_arale() |
20 | +{ |
21 | +#ifdef __ARM_EABI__ |
22 | + try |
23 | + { |
24 | + auto const android_properties = "libandroid-properties.so.1"; |
25 | + auto const arale_device_name = "arale"; |
26 | + int const property_value_max = 92; |
27 | + |
28 | + mir::SharedLibrary android_properties_lib(android_properties); |
29 | + int (*property_get)(char const*, char*, char const*) = nullptr; |
30 | + property_get = android_properties_lib.load_function<decltype(property_get)>("property_get"); |
31 | + |
32 | + char default_value[] = ""; |
33 | + char value[property_value_max]; |
34 | + |
35 | + if (property_get == nullptr) |
36 | + return false; |
37 | + |
38 | + property_get("ro.product.device", value, default_value); |
39 | + |
40 | + return std::strcmp(arale_device_name, value) == 0; |
41 | + } |
42 | + catch(...) |
43 | + { |
44 | + } |
45 | +#endif |
46 | + return false; |
47 | +} |
48 | + |
49 | +} |
50 | + |
51 | std::shared_ptr<mi::InputRegion> mir::DefaultServerConfiguration::the_input_region() |
52 | { |
53 | return input_region( |
54 | @@ -151,7 +187,7 @@ |
55 | |
56 | return std::make_shared<mi::KeyRepeatDispatcher>( |
57 | the_event_filter_chain_dispatcher(), the_main_loop(), the_cookie_authority(), |
58 | - enable_repeat, key_repeat_timeout, key_repeat_delay); |
59 | + enable_repeat, key_repeat_timeout, key_repeat_delay, is_arale()); |
60 | }); |
61 | } |
62 | |
63 | |
64 | === modified file 'src/server/input/key_repeat_dispatcher.cpp' |
65 | --- src/server/input/key_repeat_dispatcher.cpp 2016-04-01 20:44:08 +0000 |
66 | +++ src/server/input/key_repeat_dispatcher.cpp 2016-04-08 06:59:01 +0000 |
67 | @@ -37,11 +37,16 @@ |
68 | { |
69 | struct DeviceRemovalFilter : mi::InputDeviceObserver |
70 | { |
71 | - DeviceRemovalFilter(std::function<void(MirInputDeviceId)> const& on_removal) |
72 | - : on_removal(on_removal) {} |
73 | + DeviceRemovalFilter(mi::KeyRepeatDispatcher* dispatcher) |
74 | + : dispatcher{dispatcher} {} |
75 | |
76 | - void device_added(std::shared_ptr<mi::Device> const&) override |
77 | + void device_added(std::shared_ptr<mi::Device> const& device) override |
78 | { |
79 | + if (device->name() == "mtk-tpd") |
80 | + { |
81 | + dispatcher->set_touch_button_device(device->id()); |
82 | + } |
83 | + |
84 | } |
85 | |
86 | void device_changed(std::shared_ptr<mi::Device> const&) override |
87 | @@ -50,13 +55,13 @@ |
88 | |
89 | void device_removed(std::shared_ptr<mi::Device> const& device) override |
90 | { |
91 | - on_removal(device->id()); |
92 | + dispatcher->remove_device(device->id()); |
93 | } |
94 | |
95 | void changes_complete() override |
96 | { |
97 | } |
98 | - std::function<void(MirInputDeviceId)> on_removal; |
99 | + mi::KeyRepeatDispatcher* dispatcher; |
100 | }; |
101 | |
102 | } |
103 | @@ -67,25 +72,35 @@ |
104 | std::shared_ptr<mir::cookie::Authority> const& cookie_authority, |
105 | bool repeat_enabled, |
106 | std::chrono::milliseconds repeat_timeout, |
107 | - std::chrono::milliseconds repeat_delay) |
108 | + std::chrono::milliseconds repeat_delay, |
109 | + bool disable_repeat_on_touchscreen) |
110 | : next_dispatcher(next_dispatcher), |
111 | alarm_factory(factory), |
112 | cookie_authority(cookie_authority), |
113 | repeat_enabled(repeat_enabled), |
114 | repeat_timeout(repeat_timeout), |
115 | - repeat_delay(repeat_delay) |
116 | + repeat_delay(repeat_delay), |
117 | + disable_repeat_on_touchscreen(disable_repeat_on_touchscreen) |
118 | { |
119 | } |
120 | |
121 | void mi::KeyRepeatDispatcher::set_input_device_hub(std::shared_ptr<InputDeviceHub> const& hub) |
122 | { |
123 | - hub->add_observer(std::make_shared<DeviceRemovalFilter>( |
124 | - [this](MirInputDeviceId id) |
125 | - { |
126 | - std::unique_lock<std::mutex> lock(repeat_state_mutex); |
127 | - repeat_state_by_device.erase(id); // destructor cancels alarms |
128 | - } |
129 | - )); |
130 | + hub->add_observer(std::make_shared<DeviceRemovalFilter>(this)); |
131 | +} |
132 | + |
133 | +void mi::KeyRepeatDispatcher::set_touch_button_device(MirInputDeviceId id) |
134 | +{ |
135 | + std::lock_guard<std::mutex> lock(repeat_state_mutex); |
136 | + touch_button_device = id; |
137 | +} |
138 | + |
139 | +void mi::KeyRepeatDispatcher::remove_device(MirInputDeviceId id) |
140 | +{ |
141 | + std::lock_guard<std::mutex> lock(repeat_state_mutex); |
142 | + repeat_state_by_device.erase(id); // destructor cancels alarms |
143 | + if (touch_button_device.is_set() && touch_button_device.value() == id) |
144 | + touch_button_device.consume(); |
145 | } |
146 | |
147 | mi::KeyRepeatDispatcher::KeyboardState& mi::KeyRepeatDispatcher::ensure_state_for_device_locked(std::lock_guard<std::mutex> const&, MirInputDeviceId id) |
148 | @@ -100,12 +115,16 @@ |
149 | { |
150 | return next_dispatcher->dispatch(event); |
151 | } |
152 | - |
153 | + |
154 | if (mir_event_get_type(&event) == mir_event_type_input) |
155 | { |
156 | auto iev = mir_event_get_input_event(&event); |
157 | if (mir_input_event_get_type(iev) != mir_input_event_type_key) |
158 | return next_dispatcher->dispatch(event); |
159 | + auto device_id = mir_input_event_get_device_id(iev); |
160 | + if (disable_repeat_on_touchscreen && touch_button_device.is_set() && device_id == touch_button_device.value()) |
161 | + return next_dispatcher->dispatch(event); |
162 | + |
163 | if (!handle_key_input(mir_input_event_get_device_id(iev), mir_input_event_get_keyboard_event(iev))) |
164 | return next_dispatcher->dispatch(event); |
165 | else |
166 | |
167 | === modified file 'src/server/input/key_repeat_dispatcher.h' |
168 | --- src/server/input/key_repeat_dispatcher.h 2016-03-23 06:39:56 +0000 |
169 | +++ src/server/input/key_repeat_dispatcher.h 2016-04-08 06:59:01 +0000 |
170 | @@ -21,6 +21,7 @@ |
171 | |
172 | #include "mir/input/input_dispatcher.h" |
173 | #include "mir/input/input_device_observer.h" |
174 | +#include "mir/optional_value.h" |
175 | |
176 | #include <memory> |
177 | #include <chrono> |
178 | @@ -49,7 +50,8 @@ |
179 | std::shared_ptr<cookie::Authority> const& cookie_authority, |
180 | bool repeat_enabled, |
181 | std::chrono::milliseconds repeat_timeout, /* timeout before sending first repeat */ |
182 | - std::chrono::milliseconds repeat_delay /* delay between repeated keys */); |
183 | + std::chrono::milliseconds repeat_delay, /* delay between repeated keys */ |
184 | + bool disable_repeat_on_touchscreen); |
185 | |
186 | // InputDispatcher |
187 | bool dispatch(MirEvent const& event) override; |
188 | @@ -58,6 +60,8 @@ |
189 | |
190 | void set_input_device_hub(std::shared_ptr<InputDeviceHub> const& hub); |
191 | |
192 | + void set_touch_button_device(MirInputDeviceId id); |
193 | + void remove_device(MirInputDeviceId id); |
194 | private: |
195 | std::mutex repeat_state_mutex; |
196 | |
197 | @@ -67,6 +71,8 @@ |
198 | bool const repeat_enabled; |
199 | std::chrono::milliseconds repeat_timeout; |
200 | std::chrono::milliseconds repeat_delay; |
201 | + bool const disable_repeat_on_touchscreen; |
202 | + optional_value<MirInputDeviceId> touch_button_device; |
203 | |
204 | struct KeyboardState |
205 | { |
206 | |
207 | === modified file 'tests/unit-tests/input/test_key_repeat_dispatcher.cpp' |
208 | --- tests/unit-tests/input/test_key_repeat_dispatcher.cpp 2016-04-04 00:07:12 +0000 |
209 | +++ tests/unit-tests/input/test_key_repeat_dispatcher.cpp 2016-04-08 06:59:01 +0000 |
210 | @@ -76,10 +76,18 @@ |
211 | struct StubDevice : public mi::Device |
212 | { |
213 | MirInputDeviceId device_id; |
214 | + std::string device_name; |
215 | + |
216 | StubDevice(MirInputDeviceId id) : device_id(id) {} |
217 | - MirInputDeviceId id() const { return device_id;} |
218 | + StubDevice(MirInputDeviceId id, std::string device_name) : device_id{id}, device_name{device_name} |
219 | + { |
220 | + } |
221 | + MirInputDeviceId id() const |
222 | + { |
223 | + return device_id; |
224 | + } |
225 | mi::DeviceCapabilities capabilities() const {return mi::DeviceCapability::keyboard;} |
226 | - std::string name() const {return {};} |
227 | + std::string name() const {return device_name;} |
228 | std::string unique_id() const {return {};} |
229 | |
230 | mir::optional_value<mi::PointerConfiguration> pointer_configuration() const {return {};} |
231 | @@ -90,8 +98,8 @@ |
232 | |
233 | struct KeyRepeatDispatcher : public testing::Test |
234 | { |
235 | - KeyRepeatDispatcher() |
236 | - : dispatcher(mock_next_dispatcher, mock_alarm_factory, cookie_authority, true, repeat_time, repeat_delay) |
237 | + KeyRepeatDispatcher(bool on_arale = false) |
238 | + : dispatcher(mock_next_dispatcher, mock_alarm_factory, cookie_authority, true, repeat_time, repeat_delay, on_arale) |
239 | { |
240 | ON_CALL(hub,add_observer(_)).WillByDefault(SaveArg<0>(&observer)); |
241 | dispatcher.set_input_device_hub(mt::fake_shared(hub)); |
242 | @@ -123,6 +131,25 @@ |
243 | 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); |
244 | } |
245 | }; |
246 | + |
247 | +struct KeyRepeatDispatcherOnArale : KeyRepeatDispatcher |
248 | +{ |
249 | + KeyRepeatDispatcherOnArale() : KeyRepeatDispatcher(true){}; |
250 | + MirInputDeviceId mtk_id = 32; |
251 | + void add_mtk_tpd() |
252 | + { |
253 | + StubDevice dev(mtk_id, "mtk-tpd"); |
254 | + observer->device_added(mt::fake_shared(dev)); |
255 | + observer->changes_complete(); |
256 | + } |
257 | + |
258 | + mir::EventUPtr mtk_key_down_event() |
259 | + { |
260 | + auto const home_button = 53; |
261 | + return mev::make_event(mtk_id, std::chrono::nanoseconds(0), std::vector<uint8_t>{}, mir_keyboard_action_down, 0, |
262 | + home_button, mir_input_event_modifier_none); |
263 | + } |
264 | +}; |
265 | } |
266 | |
267 | TEST_F(KeyRepeatDispatcher, forwards_start_stop) |
268 | @@ -182,3 +209,31 @@ |
269 | simulate_device_removal(); |
270 | EXPECT_THAT(alarm_canceled, Eq(true)); |
271 | } |
272 | + |
273 | +TEST_F(KeyRepeatDispatcherOnArale, no_repeat_alarm_on_mtk_tpd) |
274 | +{ |
275 | + EXPECT_CALL(*mock_alarm_factory, create_alarm_adapter(_)).Times(0); |
276 | + EXPECT_CALL(*mock_next_dispatcher, dispatch(mt::KeyDownEvent())).Times(1); |
277 | + EXPECT_CALL(*mock_next_dispatcher, dispatch(mt::KeyRepeatEvent())).Times(0); |
278 | + |
279 | + add_mtk_tpd(); |
280 | + dispatcher.dispatch(*mtk_key_down_event()); |
281 | +} |
282 | + |
283 | +TEST_F(KeyRepeatDispatcherOnArale, repeat_for_regular_keys) |
284 | +{ |
285 | + MockAlarm *mock_alarm = new MockAlarm; |
286 | + std::function<void()> alarm_function; |
287 | + |
288 | + EXPECT_CALL(*mock_alarm_factory, create_alarm_adapter(_)).Times(1). |
289 | + WillOnce(DoAll(SaveArg<0>(&alarm_function), Return(mock_alarm))); |
290 | + // Once for initial down and again when invoked |
291 | + EXPECT_CALL(*mock_alarm, reschedule_in(repeat_delay)).Times(1).WillOnce(Return(true)); |
292 | + EXPECT_CALL(*mock_alarm, reschedule_in(repeat_time)).Times(1).WillOnce(Return(true)); |
293 | + EXPECT_CALL(*mock_next_dispatcher, dispatch(mt::KeyDownEvent())).Times(1); |
294 | + EXPECT_CALL(*mock_next_dispatcher, dispatch(mt::KeyRepeatEvent())).Times(1); |
295 | + |
296 | + add_mtk_tpd(); |
297 | + dispatcher.dispatch(*a_key_down_event()); |
298 | + alarm_function(); |
299 | +} |
FAILED: Continuous integration, rev:3428 /mir-jenkins. ubuntu. com/job/ mir-ci/ 695/ /mir-jenkins. ubuntu. com/job/ build-mir/ 650/console /mir-jenkins. ubuntu. com/job/ build-0- fetch/687 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= vivid+overlay/ 679 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial/ 679 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= vivid+overlay/ 660/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial/ 660/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 660/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 660/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial/ 660/console
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild: /mir-jenkins. ubuntu. com/job/ mir-ci/ 695/rebuild
https:/