Merge lp:~andreas-pokorny/mir/nested-input-platform into lp:mir
- nested-input-platform
- Merge into development-branch
Status: | Superseded |
---|---|
Proposed branch: | lp:~andreas-pokorny/mir/nested-input-platform |
Merge into: | lp:mir |
Prerequisite: | lp:~andreas-pokorny/mir/fix-accumulation-of-relative-axis-when-resampling |
Diff against target: |
1295 lines (+622/-301) 18 files modified
src/include/server/mir/default_server_configuration.h (+1/-0) src/server/graphics/default_configuration.cpp (+2/-6) src/server/graphics/nested/CMakeLists.txt (+1/-0) src/server/graphics/nested/display.cpp (+3/-9) src/server/graphics/nested/display.h (+1/-10) src/server/graphics/nested/display_buffer.cpp (+5/-37) src/server/graphics/nested/display_buffer.h (+4/-9) src/server/graphics/nested/host_connection.h (+7/-0) src/server/graphics/nested/input_platform.cpp (+269/-0) src/server/graphics/nested/input_platform.h (+71/-0) src/server/graphics/nested/mir_client_host_connection.cpp (+22/-167) src/server/graphics/nested/mir_client_host_connection.h (+8/-17) src/server/input/default_configuration.cpp (+31/-43) src/server/input/seat_input_device_tracker.cpp (+3/-1) tests/include/mir/test/doubles/stub_host_connection.h (+10/-0) tests/unit-tests/graphics/nested/test_nested_display.cpp (+1/-2) tests/unit-tests/input/CMakeLists.txt (+1/-0) tests/unit-tests/input/test_nested_input_platform.cpp (+182/-0) |
To merge this branch: | bzr merge lp:~andreas-pokorny/mir/nested-input-platform |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alan Griffiths | Needs Information | ||
Chris Halse Rogers | Approve | ||
Mir CI Bot | continuous-integration | Needs Fixing | |
Review via email:
|
This proposal has been superseded by a proposal from 2016-05-20.
Commit message
Nested Input Platform
Convert the input setup code for a nested server into a platform. The platform is not dynamically loaded. Still part of the server, but only uses the HostConnection interface and the APIs use by other input platforms. As a result there is now the same InputDeviceRegistry and the same input::Seat like on the host server.
Description of the change
A nested input platform built into the server.
This change adds input state tracking to nested servers.
The MP has two unrelated prerequisite branches
* lp:~andreas-pokorny/mir/mediate-nested-cursor-configuration-on-construction
* lp:~andreas-pokorny/mir/fix-accumulation-of-relative-axis-when-resampling
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Mir CI Bot (mir-ci-bot) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Alan Griffiths (alan-griffiths) wrote : | # |
Unrelated failure: (lp:1570698)
22:06:59 11: Expected: to be called between 50 and 150 times
22:06:59 11: Actual: called 167 times - over-saturated and active
22:06:59 11: /��BUILDDIR�
22:06:59 11: Value of: client_
22:06:59 11: Expected: is < 1.5
22:06:59 11: Actual: 1.5 (of type float)
22:06:59 11: [2016-05-04 22:06:58.560725] mirserver: Stopping
22:06:59 11: [ FAILED ] TestClientInput
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3496
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3498
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Chris Halse Rogers (raof) wrote : | # |
Seems sensible on a first pass. Does our discussion regarding the intricacies of per-surface keymaps and modifier state require any alteration?
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Andreas Pokorny (andreas-pokorny) wrote : | # |
> Seems sensible on a first pass. Does our discussion regarding the intricacies
> of per-surface keymaps and modifier state require any alteration?
Not really - instead this helps with the per device keymaps, and helps with figuring out the actual modifiers according to the keymap configured. The alteration necessary is inside the mir::input::Seat implementation details. It needs to keep track of key states, instead of modifier states. Additionally to allow servers to properly implement key bindings I will add the per device keymapping to a related class there..
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Chris Halse Rogers (raof) wrote : | # |
I'm happy with this.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Alan Griffiths (alan-griffiths) wrote : | # |
One of the prerequisite branches appears to have been rejected. Is this still relevant?
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Andreas Pokorny (andreas-pokorny) wrote : | # |
> One of the prerequisite branches appears to have been rejected. Is this still
> relevant?
the issue is very relevant - but I had to recject the MP. CI successfully merged the branch but then failed to remove the MP itself.
Preview Diff
1 | === modified file 'src/include/server/mir/default_server_configuration.h' |
2 | --- src/include/server/mir/default_server_configuration.h 2016-05-10 05:13:30 +0000 |
3 | +++ src/include/server/mir/default_server_configuration.h 2016-05-20 13:09:42 +0000 |
4 | @@ -335,6 +335,7 @@ |
5 | protected: |
6 | std::shared_ptr<options::Option> the_options() const; |
7 | std::shared_ptr<graphics::nested::MirClientHostConnection> the_mir_client_host_connection(); |
8 | + std::shared_ptr<input::DefaultInputDeviceHub> the_default_input_device_hub(); |
9 | |
10 | virtual std::shared_ptr<input::InputChannelFactory> the_input_channel_factory(); |
11 | virtual std::shared_ptr<scene::MediatingDisplayChanger> the_mediating_display_changer(); |
12 | |
13 | === modified file 'src/server/graphics/default_configuration.cpp' |
14 | --- src/server/graphics/default_configuration.cpp 2016-03-29 07:30:50 +0000 |
15 | +++ src/server/graphics/default_configuration.cpp 2016-05-20 13:09:42 +0000 |
16 | @@ -162,11 +162,9 @@ |
17 | return std::make_shared<mgn::Display>( |
18 | the_graphics_platform(), |
19 | the_host_connection(), |
20 | - the_input_dispatcher(), |
21 | the_display_report(), |
22 | the_display_configuration_policy(), |
23 | - the_gl_config(), |
24 | - the_cursor_listener()); |
25 | + the_gl_config()); |
26 | } |
27 | { |
28 | return the_graphics_platform()->create_display( |
29 | @@ -254,9 +252,7 @@ |
30 | return std::make_shared<graphics::nested::MirClientHostConnection>( |
31 | host_socket, |
32 | my_name, |
33 | - the_host_lifecycle_event_listener(), |
34 | - the_global_event_sink(), |
35 | - the_main_loop() |
36 | + the_host_lifecycle_event_listener() |
37 | ); |
38 | }); |
39 | } |
40 | |
41 | === modified file 'src/server/graphics/nested/CMakeLists.txt' |
42 | --- src/server/graphics/nested/CMakeLists.txt 2016-01-29 08:18:22 +0000 |
43 | +++ src/server/graphics/nested/CMakeLists.txt 2016-05-20 13:09:42 +0000 |
44 | @@ -6,6 +6,7 @@ |
45 | mirnestedgraphics OBJECT |
46 | |
47 | display.cpp |
48 | + input_platform.cpp |
49 | nested_display_configuration.cpp |
50 | display_buffer.cpp |
51 | mir_client_host_connection.cpp |
52 | |
53 | === modified file 'src/server/graphics/nested/display.cpp' |
54 | --- src/server/graphics/nested/display.cpp 2016-05-13 07:15:29 +0000 |
55 | +++ src/server/graphics/nested/display.cpp 2016-05-20 13:09:42 +0000 |
56 | @@ -37,7 +37,6 @@ |
57 | #include <stdexcept> |
58 | #include <sstream> |
59 | |
60 | -namespace mi = mir::input; |
61 | namespace mg = mir::graphics; |
62 | namespace mgn = mir::graphics::nested; |
63 | namespace geom = mir::geometry; |
64 | @@ -179,17 +178,13 @@ |
65 | mgn::Display::Display( |
66 | std::shared_ptr<mg::Platform> const& platform, |
67 | std::shared_ptr<HostConnection> const& connection, |
68 | - std::shared_ptr<input::InputDispatcher> const& dispatcher, |
69 | std::shared_ptr<mg::DisplayReport> const& display_report, |
70 | std::shared_ptr<mg::DisplayConfigurationPolicy> const& initial_conf_policy, |
71 | - std::shared_ptr<mg::GLConfig> const& gl_config, |
72 | - std::shared_ptr<mi::CursorListener> const& cursor_listener) : |
73 | + std::shared_ptr<mg::GLConfig> const& gl_config) : |
74 | platform{platform}, |
75 | connection{connection}, |
76 | - dispatcher{dispatcher}, |
77 | display_report{display_report}, |
78 | egl_display{connection->egl_native_display(), gl_config}, |
79 | - cursor_listener{cursor_listener}, |
80 | outputs{}, |
81 | current_configuration(std::make_unique<NestedDisplayConfiguration>(connection->create_display_config())) |
82 | { |
83 | @@ -321,9 +316,8 @@ |
84 | egl_display, |
85 | host_surface, |
86 | extents, |
87 | - dispatcher, |
88 | - cursor_listener, |
89 | - best_output.current_format)); |
90 | + best_output.current_format, |
91 | + connection)); |
92 | } |
93 | }); |
94 | |
95 | |
96 | === modified file 'src/server/graphics/nested/display.h' |
97 | --- src/server/graphics/nested/display.h 2016-05-12 08:01:23 +0000 |
98 | +++ src/server/graphics/nested/display.h 2016-05-20 13:09:42 +0000 |
99 | @@ -33,11 +33,6 @@ |
100 | |
101 | namespace mir |
102 | { |
103 | -namespace input |
104 | -{ |
105 | -class InputDispatcher; |
106 | -class CursorListener; |
107 | -} |
108 | namespace geometry |
109 | { |
110 | struct Rectangle; |
111 | @@ -120,11 +115,9 @@ |
112 | Display( |
113 | std::shared_ptr<Platform> const& platform, |
114 | std::shared_ptr<HostConnection> const& connection, |
115 | - std::shared_ptr<input::InputDispatcher> const& dispatcher, |
116 | std::shared_ptr<DisplayReport> const& display_report, |
117 | std::shared_ptr<DisplayConfigurationPolicy> const& conf_policy, |
118 | - std::shared_ptr<GLConfig> const& gl_config, |
119 | - std::shared_ptr<input::CursorListener> const& cursor_listener); |
120 | + std::shared_ptr<GLConfig> const& gl_config); |
121 | |
122 | ~Display() noexcept; |
123 | |
124 | @@ -152,10 +145,8 @@ |
125 | private: |
126 | std::shared_ptr<Platform> const platform; |
127 | std::shared_ptr<HostConnection> const connection; |
128 | - std::shared_ptr<input::InputDispatcher> const dispatcher; |
129 | std::shared_ptr<DisplayReport> const display_report; |
130 | detail::EGLDisplayHandle egl_display; |
131 | - std::shared_ptr<input::CursorListener> const cursor_listener; |
132 | |
133 | std::mutex outputs_mutex; |
134 | std::unordered_map<DisplayConfigurationOutputId, std::shared_ptr<detail::DisplaySyncGroup>> outputs; |
135 | |
136 | === modified file 'src/server/graphics/nested/display_buffer.cpp' |
137 | --- src/server/graphics/nested/display_buffer.cpp 2016-05-12 08:01:23 +0000 |
138 | +++ src/server/graphics/nested/display_buffer.cpp 2016-05-20 13:09:42 +0000 |
139 | @@ -19,16 +19,13 @@ |
140 | #include "display_buffer.h" |
141 | |
142 | #include "host_connection.h" |
143 | -#include "mir/input/input_dispatcher.h" |
144 | #include "mir/graphics/pixel_format_utils.h" |
145 | -#include "mir/input/cursor_listener.h" |
146 | #include "mir/graphics/egl_error.h" |
147 | #include "mir/events/event_private.h" |
148 | |
149 | #include <boost/throw_exception.hpp> |
150 | #include <stdexcept> |
151 | |
152 | -namespace mi = mir::input; |
153 | namespace mg = mir::graphics; |
154 | namespace mgn = mir::graphics::nested; |
155 | namespace geom = mir::geometry; |
156 | @@ -37,16 +34,15 @@ |
157 | EGLDisplayHandle const& egl_display, |
158 | std::shared_ptr<HostSurface> const& host_surface, |
159 | geometry::Rectangle const& area, |
160 | - std::shared_ptr<input::InputDispatcher> const& dispatcher, |
161 | - std::shared_ptr<mi::CursorListener> const& cursor_listener, |
162 | - MirPixelFormat preferred_format) : |
163 | + MirPixelFormat preferred_format, |
164 | + std::shared_ptr<HostConnection> const& host_connection |
165 | + ) : |
166 | egl_display(egl_display), |
167 | host_surface{host_surface}, |
168 | + host_connection{host_connection}, |
169 | egl_config{egl_display.choose_windowed_config(preferred_format)}, |
170 | egl_context{egl_display, eglCreateContext(egl_display, egl_config, egl_display.egl_context(), nested_egl_context_attribs)}, |
171 | area{area.top_left, area.size}, |
172 | - dispatcher{dispatcher}, |
173 | - cursor_listener{cursor_listener}, |
174 | egl_surface{egl_display, host_surface->egl_native_window(), egl_config} |
175 | { |
176 | host_surface->set_event_handler(event_thunk, this); |
177 | @@ -118,35 +114,7 @@ |
178 | if (mir_event_get_type(&event) != mir_event_type_input) |
179 | return; |
180 | |
181 | - if (event.type() == mir_event_type_motion) |
182 | - { |
183 | - MirMotionEvent my_event = *event.to_input()->to_motion(); |
184 | - auto iev = mir_event_get_input_event(&my_event); |
185 | - |
186 | - if (mir_input_event_get_type(iev) == mir_input_event_type_pointer) |
187 | - { |
188 | - auto motion = my_event.to_input()->to_motion(); |
189 | - |
190 | - for (size_t i = 0; i != motion->pointer_count(); ++i) |
191 | - { |
192 | - auto x = motion->x(i); |
193 | - auto y = motion->y(i); |
194 | - motion->set_x(i, x + area.top_left.x.as_float()); |
195 | - motion->set_y(i, y + area.top_left.y.as_float()); |
196 | - } |
197 | - |
198 | - auto pev = mir_input_event_get_pointer_event(iev); |
199 | - auto x = mir_pointer_event_axis_value(pev, mir_pointer_axis_x); |
200 | - auto y = mir_pointer_event_axis_value(pev, mir_pointer_axis_y); |
201 | - cursor_listener->cursor_moved_to(x, y); |
202 | - } |
203 | - |
204 | - dispatcher->dispatch(my_event); |
205 | - } |
206 | - else |
207 | - { |
208 | - dispatcher->dispatch(event); |
209 | - } |
210 | + host_connection->emit_input_event(event, area); |
211 | } |
212 | |
213 | mg::NativeDisplayBuffer* mgn::detail::DisplayBuffer::native_display_buffer() |
214 | |
215 | === modified file 'src/server/graphics/nested/display_buffer.h' |
216 | --- src/server/graphics/nested/display_buffer.h 2016-05-03 04:36:33 +0000 |
217 | +++ src/server/graphics/nested/display_buffer.h 2016-05-20 13:09:42 +0000 |
218 | @@ -28,10 +28,6 @@ |
219 | |
220 | namespace mir |
221 | { |
222 | -namespace input |
223 | -{ |
224 | -class CursorListener; |
225 | -} |
226 | namespace graphics |
227 | { |
228 | namespace nested |
229 | @@ -50,9 +46,9 @@ |
230 | EGLDisplayHandle const& egl_display, |
231 | std::shared_ptr<HostSurface> const& host_surface, |
232 | geometry::Rectangle const& area, |
233 | - std::shared_ptr<input::InputDispatcher> const& input_dispatcher, |
234 | - std::shared_ptr<input::CursorListener> const& cursor, |
235 | - MirPixelFormat preferred_format); |
236 | + MirPixelFormat preferred_format, |
237 | + std::shared_ptr<HostConnection> const& host_connection |
238 | + ); |
239 | |
240 | ~DisplayBuffer() noexcept; |
241 | |
242 | @@ -73,11 +69,10 @@ |
243 | private: |
244 | EGLDisplayHandle const& egl_display; |
245 | std::shared_ptr<HostSurface> const host_surface; |
246 | + std::shared_ptr<HostConnection> const host_connection; |
247 | EGLConfig const egl_config; |
248 | EGLContextStore const egl_context; |
249 | geometry::Rectangle const area; |
250 | - std::shared_ptr<input::InputDispatcher> const dispatcher; |
251 | - std::shared_ptr<input::CursorListener> const cursor_listener; |
252 | EGLSurfaceHandle const egl_surface; |
253 | |
254 | static void event_thunk(MirSurface* surface, MirEvent const* event, void* context); |
255 | |
256 | === modified file 'src/server/graphics/nested/host_connection.h' |
257 | --- src/server/graphics/nested/host_connection.h 2016-03-29 07:30:50 +0000 |
258 | +++ src/server/graphics/nested/host_connection.h 2016-05-20 13:09:42 +0000 |
259 | @@ -21,6 +21,7 @@ |
260 | |
261 | #include "mir_toolkit/client_types.h" |
262 | #include "mir/graphics/nested_context.h" |
263 | +#include "mir/geometry/rectangle.h" |
264 | |
265 | #include <memory> |
266 | #include <vector> |
267 | @@ -36,6 +37,8 @@ |
268 | |
269 | namespace nested |
270 | { |
271 | +using UniqueInputConfig = std::unique_ptr<MirInputConfig, void(*)(MirInputConfig const*)>; |
272 | + |
273 | class HostSurface; |
274 | class HostConnection : public NestedContext |
275 | { |
276 | @@ -54,6 +57,10 @@ |
277 | virtual void hide_cursor() = 0; |
278 | virtual auto graphics_platform_library() -> std::string = 0; |
279 | |
280 | + virtual void set_input_device_change_callback(std::function<void(UniqueInputConfig)> const& cb) = 0; |
281 | + virtual void set_input_event_callback(std::function<void(MirEvent const&, mir::geometry::Rectangle const&)> const& cb) = 0; |
282 | + virtual void emit_input_event(MirEvent const& event, mir::geometry::Rectangle const& source_frame) = 0; |
283 | + |
284 | protected: |
285 | HostConnection() = default; |
286 | HostConnection(HostConnection const&) = delete; |
287 | |
288 | === added file 'src/server/graphics/nested/input_platform.cpp' |
289 | --- src/server/graphics/nested/input_platform.cpp 1970-01-01 00:00:00 +0000 |
290 | +++ src/server/graphics/nested/input_platform.cpp 2016-05-20 13:09:42 +0000 |
291 | @@ -0,0 +1,269 @@ |
292 | +/* |
293 | + * Copyright © 2016 Canonical Ltd. |
294 | + * |
295 | + * This program is free software: you can redistribute it and/or modify it |
296 | + * under the terms of the GNU General Public License version 3, |
297 | + * as published by the Free Software Foundation. |
298 | + * |
299 | + * This program is distributed in the hope that it will be useful, |
300 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
301 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
302 | + * GNU General Public License for more details. |
303 | + * |
304 | + * You should have received a copy of the GNU General Public License |
305 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
306 | + * |
307 | + * Authored by: |
308 | + * Andreas Pokorny <andreas.pokorny@canonical.com> |
309 | + */ |
310 | + |
311 | +#include "input_platform.h" |
312 | +#include "host_connection.h" |
313 | + |
314 | +#include "mir/input/input_device_registry.h" |
315 | +#include "mir/input/input_device_info.h" |
316 | +#include "mir/input/input_device.h" |
317 | +#include "mir/input/input_sink.h" |
318 | +#include "mir/input/event_builder.h" |
319 | +#include "mir/input/pointer_settings.h" |
320 | +#include "mir/input/touchpad_settings.h" |
321 | +#include "mir/input/device_capability.h" |
322 | +#include "mir/dispatch/action_queue.h" |
323 | +#include "mir/events/event_builders.h" |
324 | +#include "mir/events/event_private.h" |
325 | + |
326 | +#include <chrono> |
327 | + |
328 | +namespace mi = mir::input; |
329 | +namespace mgn = mir::graphics::nested; |
330 | + |
331 | +namespace |
332 | +{ |
333 | + |
334 | +mgn::UniqueInputConfig make_empty_config() |
335 | +{ |
336 | + return mgn::UniqueInputConfig(nullptr, [](MirInputConfig const*){}); |
337 | +} |
338 | + |
339 | +} |
340 | + |
341 | +struct mgn::InputPlatform::InputDevice : mi::InputDevice |
342 | +{ |
343 | +public: |
344 | + InputDevice(MirInputDevice const* dev) |
345 | + { |
346 | + update(dev); |
347 | + } |
348 | + |
349 | + MirInputDeviceId id() const |
350 | + { |
351 | + return device_id; |
352 | + } |
353 | + |
354 | + void update(MirInputDevice const* dev) |
355 | + { |
356 | + device_id = mir_input_device_get_id(dev); |
357 | + device_info.name = mir_input_device_get_name(dev); |
358 | + device_info.unique_id = mir_input_device_get_unique_id(dev); |
359 | + device_info.capabilities = mi::DeviceCapabilities(mir_input_device_get_capabilities(dev)); |
360 | + } |
361 | + |
362 | + void start(mi::InputSink* destination, mi::EventBuilder* builder) override |
363 | + { |
364 | + this->destination = destination; |
365 | + this->builder = builder; |
366 | + } |
367 | + |
368 | + void emit_event(MirInputEvent const* event, mir::geometry::Rectangle const& frame) |
369 | + { |
370 | + auto const type = mir_input_event_get_type(event); |
371 | + auto const event_time = std::chrono::nanoseconds{mir_input_event_get_event_time(event)}; |
372 | + |
373 | + // TODO move the coordinate transformation over here |
374 | + switch(type) |
375 | + { |
376 | + case mir_input_event_type_touch: |
377 | + { |
378 | + auto const* touch_event = mir_input_event_get_touch_event(event); |
379 | + auto new_event = builder->touch_event(event_time); |
380 | + |
381 | + for (int i = 0, point_count = mir_touch_event_point_count(touch_event); i != point_count; ++i) |
382 | + { |
383 | + builder->add_touch( |
384 | + *new_event, |
385 | + mir_touch_event_id(touch_event, i), |
386 | + mir_touch_event_action(touch_event, i), |
387 | + mir_touch_event_tooltype(touch_event, i), |
388 | + mir_touch_event_axis_value(touch_event, i, mir_touch_axis_x), |
389 | + mir_touch_event_axis_value(touch_event, i, mir_touch_axis_y), |
390 | + mir_touch_event_axis_value(touch_event, i, mir_touch_axis_pressure), |
391 | + mir_touch_event_axis_value(touch_event, i, mir_touch_axis_touch_major), |
392 | + mir_touch_event_axis_value(touch_event, i, mir_touch_axis_touch_minor), |
393 | + mir_touch_event_axis_value(touch_event, i, mir_touch_axis_size)); |
394 | + } |
395 | + destination->handle_input(*new_event); |
396 | + break; |
397 | + } |
398 | + case mir_input_event_type_key: |
399 | + { |
400 | + auto const* key_event = mir_input_event_get_keyboard_event(event); |
401 | + destination->handle_input(*builder->key_event( |
402 | + event_time, |
403 | + mir_keyboard_event_action(key_event), |
404 | + mir_keyboard_event_key_code(key_event), |
405 | + mir_keyboard_event_scan_code(key_event) |
406 | + )); |
407 | + |
408 | + break; |
409 | + } |
410 | + case mir_input_event_type_pointer: |
411 | + { |
412 | + auto const* pointer_event = mir_input_event_get_pointer_event(event); |
413 | + auto new_event = builder->pointer_event( |
414 | + event_time, |
415 | + mir_pointer_event_action(pointer_event), |
416 | + mir_pointer_event_buttons(pointer_event), |
417 | + mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_hscroll), |
418 | + mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll), |
419 | + mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_relative_x), |
420 | + mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_relative_y) |
421 | + ); |
422 | + |
423 | + auto x = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_x); |
424 | + auto y = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_y); |
425 | + new_event->to_input()->to_motion()->set_x(0, x + frame.top_left.x.as_float()); |
426 | + new_event->to_input()->to_motion()->set_y(0, y + frame.top_left.y.as_float()); |
427 | + destination->handle_input(*new_event); |
428 | + break; |
429 | + } |
430 | + default: |
431 | + break; |
432 | + } |
433 | + } |
434 | + |
435 | + void stop() override |
436 | + { |
437 | + this->destination = nullptr; |
438 | + this->builder = nullptr; |
439 | + } |
440 | + |
441 | + mi::InputDeviceInfo get_device_info() override |
442 | + { |
443 | + return device_info; |
444 | + } |
445 | + |
446 | + mir::optional_value<mi::PointerSettings> get_pointer_settings() const override |
447 | + { |
448 | + return pointer_settings; |
449 | + } |
450 | + |
451 | + void apply_settings(mi::PointerSettings const&) override |
452 | + { |
453 | + // TODO no C API for that |
454 | + } |
455 | + |
456 | + mir::optional_value<mi::TouchpadSettings> get_touchpad_settings() const override |
457 | + { |
458 | + return touchpad_settings; |
459 | + } |
460 | + |
461 | + void apply_settings(mi::TouchpadSettings const&) override |
462 | + { |
463 | + // no c api for that |
464 | + } |
465 | + |
466 | + MirInputDeviceId device_id; |
467 | + mi::InputSink* destination{nullptr}; |
468 | + mi::EventBuilder* builder{nullptr}; |
469 | + mi::InputDeviceInfo device_info; |
470 | + mir::optional_value<mi::PointerSettings> pointer_settings; |
471 | + mir::optional_value<mi::TouchpadSettings> touchpad_settings; |
472 | +}; |
473 | + |
474 | + |
475 | +mgn::InputPlatform::InputPlatform(std::shared_ptr<HostConnection> const& connection, |
476 | + std::shared_ptr<input::InputDeviceRegistry> const& input_device_registry, |
477 | + std::shared_ptr<input::InputReport> const& report) |
478 | + : connection{connection}, input_device_registry{input_device_registry}, report{report}, action_queue{std::make_shared<dispatch::ActionQueue>()}, input_config{make_empty_config()} |
479 | +{ |
480 | +} |
481 | + |
482 | +std::shared_ptr<mir::dispatch::Dispatchable> mgn::InputPlatform::dispatchable() |
483 | +{ |
484 | + return action_queue; |
485 | +} |
486 | + |
487 | +void mgn::InputPlatform::start() |
488 | +{ |
489 | + connection->set_input_device_change_callback( |
490 | + [this](mgn::UniqueInputConfig new_config) |
491 | + { |
492 | + std::lock_guard<std::mutex> lock(devices_guard); |
493 | + input_config = std::move(new_config); |
494 | + update_devices_locked(); |
495 | + }); |
496 | + |
497 | + connection->set_input_device_change_callback( |
498 | + [this](mgn::UniqueInputConfig new_config) |
499 | + { |
500 | + std::lock_guard<std::mutex> lock(devices_guard); |
501 | + input_config = std::move(new_config); |
502 | + action_queue->enqueue([this]{update_devices();}); |
503 | + }); |
504 | + |
505 | + connection->set_input_event_callback( |
506 | + [this](MirEvent const& event, mir::geometry::Rectangle const& area) |
507 | + { |
508 | + auto const* input_ev = mir_event_get_input_event(&event); |
509 | + auto const id = mir_input_event_get_device_id(input_ev); |
510 | + auto it = devices.find(id); |
511 | + if (it != end(devices)) |
512 | + it->second->emit_event(input_ev, area); |
513 | + }); |
514 | +} |
515 | + |
516 | +void mgn::InputPlatform::stop() |
517 | +{ |
518 | + std::function<void(mgn::UniqueInputConfig)> reset; |
519 | + connection->set_input_device_change_callback(reset); |
520 | + |
521 | + for(auto const& device : devices) |
522 | + input_device_registry->remove_device(device.second); |
523 | + |
524 | + devices.clear(); |
525 | +} |
526 | + |
527 | +void mgn::InputPlatform::update_devices() |
528 | +{ |
529 | + std::lock_guard<std::mutex> lock(devices_guard); |
530 | + update_devices_locked(); |
531 | +} |
532 | + |
533 | +void mgn::InputPlatform::update_devices_locked() |
534 | +{ |
535 | + auto deleted = std::move(devices); |
536 | + std::vector<std::shared_ptr<mgn::InputPlatform::InputDevice>> new_devs; |
537 | + auto config_ptr = input_config.get(); |
538 | + for (size_t i = 0, e = mir_input_config_device_count(config_ptr); i!=e; ++i) |
539 | + { |
540 | + auto dev = mir_input_config_get_device(config_ptr, i); |
541 | + auto const id = mir_input_device_get_id(dev); |
542 | + auto it = deleted.find(id); |
543 | + if (it != end(deleted)) |
544 | + { |
545 | + it->second->update(dev); |
546 | + devices[id] = it->second; |
547 | + deleted.erase(it); |
548 | + } |
549 | + else |
550 | + { |
551 | + new_devs.push_back(std::make_shared<InputDevice>(dev)); |
552 | + devices[id] = new_devs.back(); |
553 | + } |
554 | + } |
555 | + |
556 | + for (auto const& deleted_dev : deleted) |
557 | + input_device_registry->remove_device(deleted_dev.second); |
558 | + for (auto new_dev : new_devs) |
559 | + input_device_registry->add_device(new_dev); |
560 | +} |
561 | |
562 | === added file 'src/server/graphics/nested/input_platform.h' |
563 | --- src/server/graphics/nested/input_platform.h 1970-01-01 00:00:00 +0000 |
564 | +++ src/server/graphics/nested/input_platform.h 2016-05-20 13:09:42 +0000 |
565 | @@ -0,0 +1,71 @@ |
566 | +/* |
567 | + * Copyright © 2016 Canonical Ltd. |
568 | + * |
569 | + * This program is free software: you can redistribute it and/or modify it |
570 | + * under the terms of the GNU General Public License version 3, |
571 | + * as published by the Free Software Foundation. |
572 | + * |
573 | + * This program is distributed in the hope that it will be useful, |
574 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
575 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
576 | + * GNU General Public License for more details. |
577 | + * |
578 | + * You should have received a copy of the GNU General Public License |
579 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
580 | + * |
581 | + * Authored by: |
582 | + * Andreas Pokorny <andreas.pokorny@canonical.com> |
583 | + */ |
584 | + |
585 | +#ifndef MIR_GRAPHICS_NESTED_INPUT_PLATFORM_H_ |
586 | +#define MIR_GRAPHICS_NESTED_INPUT_PLATFORM_H_ |
587 | + |
588 | +#include "host_connection.h" |
589 | +#include "mir/input/platform.h" |
590 | +#include "mir/dispatch/dispatchable.h" |
591 | +#include "mir/dispatch/action_queue.h" |
592 | + |
593 | +#include <memory> |
594 | +#include <unordered_map> |
595 | +#include <mutex> |
596 | + |
597 | +namespace mir |
598 | +{ |
599 | +namespace input |
600 | +{ |
601 | +class InputDevice; |
602 | +class InputDeviceRegistry; |
603 | +class InputReport; |
604 | +} |
605 | +namespace graphics |
606 | +{ |
607 | +namespace nested |
608 | +{ |
609 | +class HostConnection; |
610 | +class InputPlatform : public input::Platform |
611 | +{ |
612 | +public: |
613 | + InputPlatform(std::shared_ptr<HostConnection> const& connection, |
614 | + std::shared_ptr<input::InputDeviceRegistry> const& input_device_registry, |
615 | + std::shared_ptr<input::InputReport> const& report); |
616 | + std::shared_ptr<mir::dispatch::Dispatchable> dispatchable() override; |
617 | + void start() override; |
618 | + void stop() override; |
619 | + |
620 | +private: |
621 | + void update_devices(); |
622 | + void update_devices_locked(); |
623 | + struct InputDevice; |
624 | + std::shared_ptr<HostConnection> const connection; |
625 | + std::shared_ptr<input::InputDeviceRegistry> const input_device_registry; |
626 | + std::shared_ptr<input::InputReport> const report; |
627 | + std::shared_ptr<dispatch::ActionQueue> const action_queue; |
628 | + std::mutex devices_guard; |
629 | + UniqueInputConfig input_config; |
630 | + std::unordered_map<MirInputDeviceId, std::shared_ptr<InputDevice>> devices; |
631 | +}; |
632 | +} |
633 | +} |
634 | +} |
635 | + |
636 | +#endif |
637 | |
638 | === modified file 'src/server/graphics/nested/mir_client_host_connection.cpp' |
639 | --- src/server/graphics/nested/mir_client_host_connection.cpp 2016-05-20 11:11:28 +0000 |
640 | +++ src/server/graphics/nested/mir_client_host_connection.cpp 2016-05-20 13:09:42 +0000 |
641 | @@ -19,6 +19,7 @@ |
642 | #include "mir_client_host_connection.h" |
643 | #include "host_surface.h" |
644 | #include "mir_toolkit/mir_client_library.h" |
645 | + |
646 | #include "mir/raii.h" |
647 | #include "mir/graphics/platform_operation_message.h" |
648 | #include "mir/graphics/cursor_image.h" |
649 | @@ -45,79 +46,11 @@ |
650 | |
651 | namespace |
652 | { |
653 | - |
654 | -mgn::UniqueInputConfig make_empty_config() |
655 | -{ |
656 | - return mgn::UniqueInputConfig(nullptr, [](MirInputConfig const*){}); |
657 | -} |
658 | - |
659 | mgn::UniqueInputConfig make_input_config(MirConnection* con) |
660 | { |
661 | return mgn::UniqueInputConfig(mir_connection_create_input_config(con), mir_input_config_destroy); |
662 | } |
663 | |
664 | -class NestedDevice : public mi::Device |
665 | -{ |
666 | -public: |
667 | - NestedDevice(MirInputDevice const* dev) |
668 | - { |
669 | - update(dev); |
670 | - } |
671 | - |
672 | - void update(MirInputDevice const* dev) |
673 | - { |
674 | - device_id = mir_input_device_get_id(dev); |
675 | - device_name = mir_input_device_get_name(dev); |
676 | - unique_device_id = mir_input_device_get_unique_id(dev); |
677 | - caps = mi::DeviceCapabilities(mir_input_device_get_capabilities(dev)); |
678 | - } |
679 | - |
680 | - MirInputDeviceId id() const |
681 | - { |
682 | - return device_id; |
683 | - } |
684 | - |
685 | - mi::DeviceCapabilities capabilities() const |
686 | - { |
687 | - return caps; |
688 | - } |
689 | - |
690 | - std::string name() const |
691 | - { |
692 | - return device_name; |
693 | - } |
694 | - std::string unique_id() const |
695 | - { |
696 | - return unique_device_id; |
697 | - } |
698 | - |
699 | - mir::optional_value<mi::PointerConfiguration> pointer_configuration() const |
700 | - { |
701 | - return pointer_conf; |
702 | - } |
703 | - void apply_pointer_configuration(mi::PointerConfiguration const&) |
704 | - { |
705 | - // TODO requires c api support |
706 | - } |
707 | - |
708 | - mir::optional_value<mi::TouchpadConfiguration> touchpad_configuration() const |
709 | - { |
710 | - return touchpad_conf; |
711 | - } |
712 | - void apply_touchpad_configuration(mi::TouchpadConfiguration const&) |
713 | - { |
714 | - // TODO requires c api support |
715 | - } |
716 | -private: |
717 | - MirInputDeviceId device_id; |
718 | - std::string device_name; |
719 | - std::string unique_device_id; |
720 | - mi::DeviceCapabilities caps; |
721 | - mir::optional_value<mi::PointerConfiguration> pointer_conf; |
722 | - mir::optional_value<mi::TouchpadConfiguration> touchpad_conf; |
723 | -}; |
724 | - |
725 | - |
726 | void display_config_callback_thunk(MirConnection* /*connection*/, void* context) |
727 | { |
728 | (*static_cast<std::function<void()>*>(context))(); |
729 | @@ -292,15 +225,10 @@ |
730 | mgn::MirClientHostConnection::MirClientHostConnection( |
731 | std::string const& host_socket, |
732 | std::string const& name, |
733 | - std::shared_ptr<msh::HostLifecycleEventListener> const& host_lifecycle_event_listener, |
734 | - std::shared_ptr<mf::EventSink> const& sink, |
735 | - std::shared_ptr<mir::ServerActionQueue> const& input_observer_queue) |
736 | + std::shared_ptr<msh::HostLifecycleEventListener> const& host_lifecycle_event_listener) |
737 | : mir_connection{mir_connect_sync(host_socket.c_str(), name.c_str())}, |
738 | conf_change_callback{[]{}}, |
739 | - host_lifecycle_event_listener{host_lifecycle_event_listener}, |
740 | - sink{sink}, |
741 | - observer_queue{input_observer_queue}, |
742 | - config{make_empty_config()} |
743 | + host_lifecycle_event_listener{host_lifecycle_event_listener} |
744 | { |
745 | if (!mir_connection_is_valid(mir_connection)) |
746 | { |
747 | @@ -318,14 +246,13 @@ |
748 | |
749 | mir_connection_set_input_config_change_callback( |
750 | mir_connection, |
751 | - [](MirConnection*, void* context) |
752 | + [](MirConnection* connection, void* context) |
753 | { |
754 | auto obj = static_cast<MirClientHostConnection*>(context); |
755 | - obj->update_input_devices(); |
756 | + if (obj->input_config_callback) |
757 | + obj->input_config_callback(make_input_config(connection)); |
758 | }, |
759 | this); |
760 | - |
761 | - update_input_devices(); |
762 | } |
763 | |
764 | mgn::MirClientHostConnection::~MirClientHostConnection() |
765 | @@ -466,92 +393,20 @@ |
766 | return properties.filename; |
767 | } |
768 | |
769 | -void mgn::MirClientHostConnection::update_input_devices() |
770 | -{ |
771 | - std::lock_guard<std::mutex> lock(devices_guard); |
772 | - config = make_input_config(mir_connection); |
773 | - |
774 | - auto deleted = std::move(devices); |
775 | - std::vector<std::shared_ptr<mi::Device>> new_devs; |
776 | - auto config_ptr = config.get(); |
777 | - for (size_t i = 0, e = mir_input_config_device_count(config_ptr); i!=e; ++i) |
778 | - { |
779 | - auto dev = mir_input_config_get_device(config_ptr, i); |
780 | - auto it = std::find_if( |
781 | - begin(deleted), |
782 | - end(deleted), |
783 | - [id = mir_input_device_get_id(dev)](auto const& dev) |
784 | - { |
785 | - return id == dev->id(); |
786 | - }); |
787 | - if (it != end(deleted)) |
788 | - { |
789 | - std::static_pointer_cast<NestedDevice>(*it)->update(dev); |
790 | - devices.push_back(*it); |
791 | - deleted.erase(it); |
792 | - } |
793 | - else |
794 | - { |
795 | - devices.push_back(std::make_shared<NestedDevice>(dev)); |
796 | - new_devs.push_back(devices.back()); |
797 | - } |
798 | - } |
799 | - |
800 | - sink->handle_input_device_change(devices); |
801 | - |
802 | - if ((deleted.empty() && new_devs.empty()) || observers.empty()) |
803 | - return; |
804 | - |
805 | - observer_queue->enqueue( |
806 | - this, |
807 | - [this, new_devs = std::move(new_devs), deleted = std::move(deleted)] |
808 | - { |
809 | - std::lock_guard<std::mutex> lock(devices_guard); |
810 | - for (auto const observer : observers) |
811 | - { |
812 | - for (auto const& item : new_devs) |
813 | - observer->device_added(item); |
814 | - for (auto const& item : deleted) |
815 | - observer->device_removed(item); |
816 | - observer->changes_complete(); |
817 | - } |
818 | - }); |
819 | -} |
820 | - |
821 | -void mgn::MirClientHostConnection::add_observer(std::shared_ptr<mi::InputDeviceObserver> const& observer) |
822 | -{ |
823 | - observer_queue->enqueue( |
824 | - this, |
825 | - [observer,this] |
826 | - { |
827 | - std::lock_guard<std::mutex> lock(devices_guard); |
828 | - observers.push_back(observer); |
829 | - for (auto const& item : devices) |
830 | - { |
831 | - observer->device_added(item); |
832 | - } |
833 | - observer->changes_complete(); |
834 | - } |
835 | - ); |
836 | -} |
837 | - |
838 | -void mgn::MirClientHostConnection::remove_observer(std::weak_ptr<mi::InputDeviceObserver> const& element) |
839 | -{ |
840 | - auto observer = element.lock(); |
841 | - |
842 | - observer_queue->enqueue(this, |
843 | - [observer, this] |
844 | - { |
845 | - observers.erase(remove(begin(observers), end(observers), observer), end(observers)); |
846 | - }); |
847 | -} |
848 | - |
849 | -void mgn::MirClientHostConnection::for_each_input_device(std::function<void(mi::Device const& device)> const& callback) |
850 | -{ |
851 | - std::lock_guard<std::mutex> lock(devices_guard); |
852 | - for (auto const& item : devices) |
853 | - { |
854 | - callback(*item); |
855 | - } |
856 | - |
857 | +void mgn::MirClientHostConnection::set_input_device_change_callback(std::function<void(UniqueInputConfig)> const& cb) |
858 | +{ |
859 | + input_config_callback = cb; |
860 | + if (input_config_callback) |
861 | + input_config_callback(make_input_config(mir_connection)); |
862 | +} |
863 | + |
864 | +void mgn::MirClientHostConnection::set_input_event_callback(std::function<void(MirEvent const&, mir::geometry::Rectangle const&)> const& cb) |
865 | +{ |
866 | + event_callback = cb; |
867 | +} |
868 | + |
869 | +void mgn::MirClientHostConnection::emit_input_event(MirEvent const& event, mir::geometry::Rectangle const& source_frame) |
870 | +{ |
871 | + if (event_callback) |
872 | + event_callback(event, source_frame); |
873 | } |
874 | |
875 | === modified file 'src/server/graphics/nested/mir_client_host_connection.h' |
876 | --- src/server/graphics/nested/mir_client_host_connection.h 2016-05-20 11:11:28 +0000 |
877 | +++ src/server/graphics/nested/mir_client_host_connection.h 2016-05-20 13:09:42 +0000 |
878 | @@ -51,16 +51,12 @@ |
879 | namespace nested |
880 | { |
881 | |
882 | -using UniqueInputConfig = std::unique_ptr<MirInputConfig, void(*)(MirInputConfig const*)>; |
883 | - |
884 | -class MirClientHostConnection : public HostConnection, public input::InputDeviceHub |
885 | +class MirClientHostConnection : public HostConnection |
886 | { |
887 | public: |
888 | MirClientHostConnection(std::string const& host_socket, |
889 | std::string const& name, |
890 | - std::shared_ptr<msh::HostLifecycleEventListener> const& host_lifecycle_event_listener, |
891 | - std::shared_ptr<frontend::EventSink> const& sink, |
892 | - std::shared_ptr<ServerActionQueue> const& observer_queue); |
893 | + std::shared_ptr<msh::HostLifecycleEventListener> const& host_lifecycle_event_listener); |
894 | ~MirClientHostConnection(); |
895 | |
896 | std::vector<int> platform_fd_items() override; |
897 | @@ -79,13 +75,12 @@ |
898 | virtual PlatformOperationMessage platform_operation( |
899 | unsigned int op, PlatformOperationMessage const& request) override; |
900 | |
901 | - // InputDeviceHub |
902 | - void add_observer(std::shared_ptr<input::InputDeviceObserver> const&) override; |
903 | - void remove_observer(std::weak_ptr<input::InputDeviceObserver> const&) override; |
904 | - void for_each_input_device(std::function<void(input::Device const& device)> const& callback) override; |
905 | + void set_input_device_change_callback(std::function<void(UniqueInputConfig)> const& cb) override; |
906 | + void set_input_event_callback(std::function<void(MirEvent const&, mir::geometry::Rectangle const&)> const& cb) override; |
907 | + void emit_input_event(MirEvent const& cb, mir::geometry::Rectangle const& source_frame) override; |
908 | |
909 | private: |
910 | - void update_input_devices(); |
911 | + void update_input_config(UniqueInputConfig input_config); |
912 | std::mutex surfaces_mutex; |
913 | |
914 | MirConnection* const mir_connection; |
915 | @@ -94,12 +89,8 @@ |
916 | |
917 | std::vector<HostSurface*> surfaces; |
918 | |
919 | - std::shared_ptr<frontend::EventSink> const sink; |
920 | - std::shared_ptr<mir::ServerActionQueue> const observer_queue; |
921 | - std::vector<std::shared_ptr<input::InputDeviceObserver>> observers; |
922 | - std::mutex devices_guard; |
923 | - std::vector<std::shared_ptr<input::Device>> devices; |
924 | - UniqueInputConfig config; |
925 | + std::function<void(UniqueInputConfig)> input_config_callback; |
926 | + std::function<void(MirEvent const&, mir::geometry::Rectangle const&)> event_callback; |
927 | |
928 | struct NestedCursorImage : graphics::CursorImage |
929 | { |
930 | |
931 | === modified file 'src/server/input/default_configuration.cpp' |
932 | --- src/server/input/default_configuration.cpp 2016-05-03 04:36:33 +0000 |
933 | +++ src/server/input/default_configuration.cpp 2016-05-20 13:09:42 +0000 |
934 | @@ -34,7 +34,7 @@ |
935 | #include "default_input_manager.h" |
936 | #include "surface_input_dispatcher.h" |
937 | #include "basic_seat.h" |
938 | -#include "../graphics/nested/mir_client_host_connection.h" |
939 | +#include "../graphics/nested/input_platform.h" |
940 | |
941 | #include "mir/input/touch_visualizer.h" |
942 | #include "mir/input/input_probe.h" |
943 | @@ -58,6 +58,7 @@ |
944 | namespace mr = mir::report; |
945 | namespace ms = mir::scene; |
946 | namespace mg = mir::graphics; |
947 | +namespace mgn = mg::nested; |
948 | namespace msh = mir::shell; |
949 | namespace md = mir::dispatch; |
950 | |
951 | @@ -277,8 +278,13 @@ |
952 | } |
953 | else if (options->is_set(options::host_socket_opt)) |
954 | { |
955 | - // TODO nested input handling (== host_socket) should fold into a platform |
956 | - return std::make_shared<mi::NullInputManager>(); |
957 | + auto const device_registry = the_input_device_registry(); |
958 | + auto const input_report = the_input_report(); |
959 | + |
960 | + // TODO: move this into a nested graphics platform |
961 | + auto platform = std::make_shared<mgn::InputPlatform>(the_host_connection(), device_registry, input_report); |
962 | + |
963 | + return std::make_shared<mi::DefaultInputManager>(the_input_reading_multiplexer(), std::move(platform)); |
964 | } |
965 | else |
966 | { |
967 | @@ -330,48 +336,30 @@ |
968 | |
969 | std::shared_ptr<mi::InputDeviceRegistry> mir::DefaultServerConfiguration::the_input_device_registry() |
970 | { |
971 | - return default_input_device_hub( |
972 | - [this]() |
973 | - { |
974 | - auto input_dispatcher = the_input_dispatcher(); |
975 | - auto key_repeater = std::dynamic_pointer_cast<mi::KeyRepeatDispatcher>(input_dispatcher); |
976 | - auto hub = std::make_shared<mi::DefaultInputDeviceHub>( |
977 | - the_global_event_sink(), |
978 | - the_seat(), |
979 | - the_input_reading_multiplexer(), |
980 | - the_main_loop(), |
981 | - the_cookie_authority()); |
982 | - |
983 | - if (key_repeater) |
984 | - key_repeater->set_input_device_hub(hub); |
985 | - return hub; |
986 | - }); |
987 | + return the_default_input_device_hub(); |
988 | } |
989 | |
990 | std::shared_ptr<mi::InputDeviceHub> mir::DefaultServerConfiguration::the_input_device_hub() |
991 | { |
992 | - auto options = the_options(); |
993 | - if (options->is_set(options::host_socket_opt)) |
994 | - { |
995 | - return the_mir_client_host_connection(); |
996 | - } |
997 | - else |
998 | - { |
999 | - return default_input_device_hub( |
1000 | - [this]() |
1001 | - { |
1002 | - auto input_dispatcher = the_input_dispatcher(); |
1003 | - auto key_repeater = std::dynamic_pointer_cast<mi::KeyRepeatDispatcher>(input_dispatcher); |
1004 | - auto hub = std::make_shared<mi::DefaultInputDeviceHub>( |
1005 | - the_global_event_sink(), |
1006 | - the_seat(), |
1007 | - the_input_reading_multiplexer(), |
1008 | - the_main_loop(), |
1009 | - the_cookie_authority()); |
1010 | - |
1011 | - if (key_repeater) |
1012 | - key_repeater->set_input_device_hub(hub); |
1013 | - return hub; |
1014 | - }); |
1015 | - } |
1016 | + return the_default_input_device_hub(); |
1017 | +} |
1018 | + |
1019 | +std::shared_ptr<mi::DefaultInputDeviceHub> mir::DefaultServerConfiguration::the_default_input_device_hub() |
1020 | +{ |
1021 | + return default_input_device_hub( |
1022 | + [this]() |
1023 | + { |
1024 | + auto input_dispatcher = the_input_dispatcher(); |
1025 | + auto key_repeater = std::dynamic_pointer_cast<mi::KeyRepeatDispatcher>(input_dispatcher); |
1026 | + auto hub = std::make_shared<mi::DefaultInputDeviceHub>( |
1027 | + the_global_event_sink(), |
1028 | + the_seat(), |
1029 | + the_input_reading_multiplexer(), |
1030 | + the_main_loop(), |
1031 | + the_cookie_authority()); |
1032 | + |
1033 | + if (key_repeater && !the_options()->is_set(options::host_socket_opt)) |
1034 | + key_repeater->set_input_device_hub(hub); |
1035 | + return hub; |
1036 | + }); |
1037 | } |
1038 | |
1039 | === modified file 'src/server/input/seat_input_device_tracker.cpp' |
1040 | --- src/server/input/seat_input_device_tracker.cpp 2016-05-03 04:36:33 +0000 |
1041 | +++ src/server/input/seat_input_device_tracker.cpp 2016-05-20 13:09:42 +0000 |
1042 | @@ -24,6 +24,7 @@ |
1043 | #include "mir/input/input_dispatcher.h" |
1044 | #include "mir/geometry/displacement.h" |
1045 | #include "mir/events/event_builders.h" |
1046 | +#include "mir/events/event_private.h" |
1047 | |
1048 | #include "input_modifier_utils.h" |
1049 | |
1050 | @@ -82,7 +83,8 @@ |
1051 | |
1052 | if (mir_input_event_type_pointer == mir_input_event_get_type(input_event)) |
1053 | { |
1054 | - mev::set_cursor_position(event, cursor_position()); |
1055 | + event.to_input()->to_motion()->set_x(0, cursor_x); |
1056 | + event.to_input()->to_motion()->set_y(0, cursor_y); |
1057 | mev::set_button_state(event, button_state()); |
1058 | } |
1059 | |
1060 | |
1061 | === modified file 'tests/include/mir/test/doubles/stub_host_connection.h' |
1062 | --- tests/include/mir/test/doubles/stub_host_connection.h 2016-03-29 07:30:50 +0000 |
1063 | +++ tests/include/mir/test/doubles/stub_host_connection.h 2016-05-20 13:09:42 +0000 |
1064 | @@ -78,6 +78,16 @@ |
1065 | } |
1066 | |
1067 | auto graphics_platform_library() -> std::string { return {}; } |
1068 | + |
1069 | + void set_input_device_change_callback(std::function<void(graphics::nested::UniqueInputConfig)> const&) override |
1070 | + { |
1071 | + } |
1072 | + void set_input_event_callback(std::function<void(MirEvent const&, mir::geometry::Rectangle const&)> const&) override |
1073 | + { |
1074 | + } |
1075 | + void emit_input_event(MirEvent const&, mir::geometry::Rectangle const&) override |
1076 | + { |
1077 | + } |
1078 | }; |
1079 | |
1080 | |
1081 | |
1082 | === modified file 'tests/unit-tests/graphics/nested/test_nested_display.cpp' |
1083 | --- tests/unit-tests/graphics/nested/test_nested_display.cpp 2016-01-28 22:27:36 +0000 |
1084 | +++ tests/unit-tests/graphics/nested/test_nested_display.cpp 2016-05-20 13:09:42 +0000 |
1085 | @@ -68,10 +68,9 @@ |
1086 | auto nested_display_raw = new mgn::Display{ |
1087 | platform, |
1088 | std::make_shared<SingleDisplayHostConnection>(), |
1089 | - mt::fake_shared(null_input_dispatcher), |
1090 | mt::fake_shared(null_display_report), |
1091 | mt::fake_shared(default_conf_policy), |
1092 | - gl_config, std::make_shared<mtd::StubCursorListener>()}; |
1093 | + gl_config}; |
1094 | |
1095 | return std::unique_ptr<mgn::Display>{nested_display_raw}; |
1096 | } |
1097 | |
1098 | === modified file 'tests/unit-tests/input/CMakeLists.txt' |
1099 | --- tests/unit-tests/input/CMakeLists.txt 2016-05-03 04:36:33 +0000 |
1100 | +++ tests/unit-tests/input/CMakeLists.txt 2016-05-20 13:09:42 +0000 |
1101 | @@ -17,6 +17,7 @@ |
1102 | ${CMAKE_CURRENT_SOURCE_DIR}/test_seat_input_device_tracker.cpp |
1103 | ${CMAKE_CURRENT_SOURCE_DIR}/test_key_repeat_dispatcher.cpp |
1104 | ${CMAKE_CURRENT_SOURCE_DIR}/test_validator.cpp |
1105 | + ${CMAKE_CURRENT_SOURCE_DIR}/test_nested_input_platform.cpp |
1106 | ) |
1107 | |
1108 | list(APPEND UMOCK_UNIT_TEST_SOURCES |
1109 | |
1110 | === added file 'tests/unit-tests/input/test_nested_input_platform.cpp' |
1111 | --- tests/unit-tests/input/test_nested_input_platform.cpp 1970-01-01 00:00:00 +0000 |
1112 | +++ tests/unit-tests/input/test_nested_input_platform.cpp 2016-05-20 13:09:42 +0000 |
1113 | @@ -0,0 +1,182 @@ |
1114 | +/* |
1115 | + * Copyright © 2016 Canonical Ltd. |
1116 | + * |
1117 | + * This program is free software: you can redistribute it and/or modify |
1118 | + * it under the terms of the GNU General Public License version 3 as |
1119 | + * published by the Free Software Foundation. |
1120 | + * |
1121 | + * This program is distributed in the hope that it will be useful, |
1122 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1123 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1124 | + * GNU General Public License for more details. |
1125 | + * |
1126 | + * You should have received a copy of the GNU General Public License |
1127 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1128 | + * |
1129 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
1130 | + */ |
1131 | + |
1132 | +#include "src/server/graphics/nested/input_platform.h" |
1133 | +#include "src/server/report/null_report_factory.h" |
1134 | +#include "src/include/client/mir/input/input_devices.h" |
1135 | +#include "src/server/input/default_event_builder.h" |
1136 | + |
1137 | +#include "mir/cookie/authority.h" |
1138 | +#include "mir/input/device_capability.h" |
1139 | +#include "mir/input/input_device.h" |
1140 | +#include "mir/input/input_device_info.h" |
1141 | +#include "mir/input/input_report.h" |
1142 | +#include "mir/events/event_builders.h" |
1143 | +#include "mir_toolkit/mir_connection.h" |
1144 | + |
1145 | +#include "mir/test/doubles/mock_input_device_registry.h" |
1146 | +#include "mir/test/doubles/mock_input_sink.h" |
1147 | +#include "mir/test/doubles/stub_host_connection.h" |
1148 | +#include "mir/test/fake_shared.h" |
1149 | +#include "mir/test/event_matchers.h" |
1150 | + |
1151 | + |
1152 | +namespace mi = mir::input; |
1153 | +namespace mt = mir::test; |
1154 | +namespace mr = mir::report; |
1155 | +namespace mev = mir::events; |
1156 | +namespace mtd = mir::test::doubles; |
1157 | +namespace mgn = mir::graphics::nested; |
1158 | +using namespace std::chrono_literals; |
1159 | +using namespace testing; |
1160 | +namespace |
1161 | +{ |
1162 | + |
1163 | +struct MockHostConnection : mtd::StubHostConnection |
1164 | +{ |
1165 | + MOCK_METHOD1(set_input_device_change_callback, void (std::function<void(mgn::UniqueInputConfig)> const&)); |
1166 | + MOCK_METHOD1(set_input_event_callback, void (std::function<void(MirEvent const&, mir::geometry::Rectangle const&)> const&)); |
1167 | + void emit_input_event(MirEvent const& event, mir::geometry::Rectangle const& source_frame) |
1168 | + { |
1169 | + if (event_callback) |
1170 | + event_callback(event, source_frame); |
1171 | + } |
1172 | + |
1173 | + MockHostConnection() |
1174 | + { |
1175 | + ON_CALL(*this, set_input_device_change_callback(_)) |
1176 | + .WillByDefault(SaveArg<0>(&device_change_callback)); |
1177 | + ON_CALL(*this, set_input_event_callback(_)) |
1178 | + .WillByDefault(SaveArg<0>(&event_callback)); |
1179 | + } |
1180 | + |
1181 | + std::function<void(mgn::UniqueInputConfig)> device_change_callback; |
1182 | + std::function<void(MirEvent const&, mir::geometry::Rectangle const&)> event_callback; |
1183 | +}; |
1184 | + |
1185 | +struct TestNestedInputPlatform : Test |
1186 | +{ |
1187 | + NiceMock<mtd::MockInputDeviceRegistry> mock_input_device_registry; |
1188 | + NiceMock<MockHostConnection> mock_host_connection; |
1189 | + mgn::InputPlatform platform{mt::fake_shared(mock_host_connection), mt::fake_shared(mock_input_device_registry), |
1190 | + mr::null_input_report()}; |
1191 | + mi::DeviceData a_keyboard{1, mir_input_device_capability_keyboard, "keys" , "keys-evdev2"}; |
1192 | + mi::DeviceData a_mouse{0, mir_input_device_capability_pointer, "rodent", "rodent-evdev1"}; |
1193 | + const mir::geometry::Rectangle source_surface{{0, 0}, {100, 100}}; |
1194 | + |
1195 | + |
1196 | + auto capture_input_device(mi::DeviceData& dev) |
1197 | + { |
1198 | + std::shared_ptr<mi::InputDevice> input_dev; |
1199 | + ON_CALL(mock_input_device_registry, add_device(_)) |
1200 | + .WillByDefault(SaveArg<0>(&input_dev)); |
1201 | + platform.start(); |
1202 | + mgn::UniqueInputConfig input_config( |
1203 | + reinterpret_cast<MirInputConfig*>( |
1204 | + new std::vector<mir::input::DeviceData>{dev}), |
1205 | + mir_input_config_destroy); |
1206 | + mock_host_connection.device_change_callback(std::move(input_config)); |
1207 | + |
1208 | + platform.dispatchable()->dispatch(mir::dispatch::readable); |
1209 | + |
1210 | + return input_dev; |
1211 | + } |
1212 | +}; |
1213 | + |
1214 | +} |
1215 | + |
1216 | +TEST_F(TestNestedInputPlatform, registers_to_host_connection) |
1217 | +{ |
1218 | + EXPECT_CALL(mock_host_connection, set_input_device_change_callback(_)).Times(2); |
1219 | + EXPECT_CALL(mock_host_connection, set_input_event_callback(_)); |
1220 | + |
1221 | + platform.start(); |
1222 | +} |
1223 | + |
1224 | +MATCHER_P(MatchesDeviceData, device_data, "") |
1225 | +{ |
1226 | + mi::InputDevice& dev = *arg; |
1227 | + auto dev_info = dev.get_device_info(); |
1228 | + |
1229 | + if (dev_info.name != device_data.name) |
1230 | + return false; |
1231 | + if (dev_info.unique_id != device_data.unique_id) |
1232 | + return false; |
1233 | + if (dev_info.capabilities.value() != device_data.caps) |
1234 | + return false; |
1235 | + |
1236 | + return true; |
1237 | +} |
1238 | + |
1239 | +TEST_F(TestNestedInputPlatform, registers_devices) |
1240 | +{ |
1241 | + EXPECT_CALL(mock_input_device_registry, add_device(MatchesDeviceData(a_keyboard))); |
1242 | + EXPECT_CALL(mock_input_device_registry, add_device(MatchesDeviceData(a_mouse))); |
1243 | + |
1244 | + platform.start(); |
1245 | + mi::InputDevices devices; |
1246 | + mgn::UniqueInputConfig input_config( |
1247 | + reinterpret_cast<MirInputConfig*>( |
1248 | + new std::vector<mir::input::DeviceData>{a_keyboard, a_mouse}), |
1249 | + mir_input_config_destroy); |
1250 | + mock_host_connection.device_change_callback(std::move(input_config)); |
1251 | + |
1252 | + platform.dispatchable()->dispatch(mir::dispatch::readable); |
1253 | +} |
1254 | + |
1255 | +TEST_F(TestNestedInputPlatform, devices_forward_input_events) |
1256 | +{ |
1257 | + auto nested_input_device = capture_input_device(a_mouse); |
1258 | + NiceMock<mtd::MockInputSink> event_sink; |
1259 | + mi::DefaultEventBuilder builder(MirInputDeviceId{12}, mir::cookie::Authority::create()); |
1260 | + |
1261 | + ASSERT_THAT(nested_input_device, Ne(nullptr)); |
1262 | + nested_input_device->start(&event_sink, &builder); |
1263 | + |
1264 | + EXPECT_CALL(event_sink, handle_input( |
1265 | + AllOf(mt::PointerAxisChange(mir_pointer_axis_relative_x, 12), |
1266 | + mt::PointerAxisChange(mir_pointer_axis_relative_y, 10), |
1267 | + mt::InputDeviceIdMatches(MirInputDeviceId{12}) |
1268 | + )) |
1269 | + ); |
1270 | + |
1271 | + std::vector<uint8_t> cookie; |
1272 | + |
1273 | + mock_host_connection.event_callback(*mev::make_event(a_mouse.id, 12ns, cookie, mir_input_event_modifier_none, |
1274 | + mir_pointer_action_motion, mir_pointer_button_primary, 23, 42, |
1275 | + 0, 0, 12, 10), source_surface); |
1276 | +} |
1277 | + |
1278 | +TEST_F(TestNestedInputPlatform, devices_forward_key_events) |
1279 | +{ |
1280 | + auto nested_input_device = capture_input_device(a_keyboard); |
1281 | + auto const scan_code = 45; |
1282 | + NiceMock<mtd::MockInputSink> event_sink; |
1283 | + mi::DefaultEventBuilder builder(MirInputDeviceId{18}, mir::cookie::Authority::create()); |
1284 | + |
1285 | + ASSERT_THAT(nested_input_device, Ne(nullptr)); |
1286 | + nested_input_device->start(&event_sink, &builder); |
1287 | + |
1288 | + EXPECT_CALL(event_sink, |
1289 | + handle_input(AllOf( |
1290 | + mt::KeyDownEvent(), mt::KeyOfScanCode(scan_code), mt::InputDeviceIdMatches(MirInputDeviceId{18})))); |
1291 | + std::vector<uint8_t> cookie; |
1292 | + |
1293 | + mock_host_connection.event_callback(*mev::make_event(a_keyboard.id, 141ns, cookie, mir_keyboard_action_down, 0, |
1294 | + scan_code, mir_input_event_modifier_none), source_surface); |
1295 | +} |
FAILED: Continuous integration, rev:3496 /mir-jenkins. ubuntu. com/job/ mir-ci/ 943/ /mir-jenkins. ubuntu. com/job/ build-mir/ 1005/console /mir-jenkins. ubuntu. com/job/ build-0- fetch/1051 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= vivid+overlay/ 1042 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial/ 1042 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= vivid+overlay/ 1015 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= vivid+overlay/ 1015/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial/ 1015/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 1015 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 1015/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 1015 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 1015/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial/ 1015/console
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:/
FAILURE: https:/
Click here to trigger a rebuild: /mir-jenkins. ubuntu. com/job/ mir-ci/ 943/rebuild
https:/