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