Merge lp:~andreas-pokorny/mir/fix-1536279 into lp:mir
- fix-1536279
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | Daniel van Vugt |
Approved revision: | no longer in the source branch. |
Merged at revision: | 4121 |
Proposed branch: | lp:~andreas-pokorny/mir/fix-1536279 |
Merge into: | lp:mir |
Prerequisite: | lp:~andreas-pokorny/mir/store-device-config |
Diff against target: |
716 lines (+254/-38) 15 files modified
src/client/buffer_vault.cpp (+1/-1) src/client/connection_surface_map.cpp (+7/-0) src/client/connection_surface_map.h (+2/-1) src/client/default_connection_configuration.cpp (+2/-2) src/client/input/input_devices.cpp (+39/-1) src/client/mir_surface.cpp (+5/-0) src/client/mir_surface.h (+1/-0) src/client/rpc/mir_protobuf_rpc_channel.cpp (+1/-1) src/include/client/mir/client/surface_map.h (+2/-1) src/include/client/mir/input/input_devices.h (+3/-1) tests/acceptance-tests/test_nested_input.cpp (+163/-17) tests/include/mir/test/test_protobuf_client.h (+6/-1) tests/mir_test_doubles/test_protobuf_client.cpp (+3/-2) tests/unit-tests/client/test_protobuf_rpc_channel.cpp (+15/-8) tests/unit-tests/frontend/stress_protobuf_communicator.cpp (+4/-2) |
To merge this branch: | bzr merge lp:~andreas-pokorny/mir/fix-1536279 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alan Griffiths | Abstain | ||
Cemil Azizoglu (community) | Approve | ||
Kevin DuBois (community) | Approve | ||
Mir CI Bot | continuous-integration | Approve | |
Andreas Pokorny (community) | Abstain | ||
Review via email: mp+319438@code.launchpad.net |
Commit message
Clear keystate and keymap on device removal (LP: #1536279)
A client window may have a "default" keymap configured. So a keystate will be tracked for each keyboard device individually. Switching away from the vt of the mirserver will trigger a removal of all devices, switching back to the server will make those devices reappear.
If the keystate is not cleared on removal any pressed key will be stuck during a vt switch.
Description of the change
This makes the keymapper in the client behave like the server on device removal.
The keystate gets cleared and when the device reappears and will be used again the default keymap will be used to create a clean keystate again.
Majority of the change is about constructing the test to have a mirserver with a nested server a focused window with a keymap configured followed by a vt switch and key presses..
Mir CI Bot (mir-ci-bot) wrote : | # |
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:4081
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:4082
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: 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:/
Andreas Pokorny (andreas-pokorny) wrote : | # |
^ the new test fails, the client does not receive the keymap in the time frame.
Andreas Pokorny (andreas-pokorny) wrote : | # |
should be fine now..
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:4083
https:/
Executed test runs:
SUCCESS: https:/
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:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Kevin DuBois (kdub) wrote : | # |
+ static void for_each_
could we use ConnectionSurfa
Alright by me otherwise.
Andreas Pokorny (andreas-pokorny) wrote : | # |
> + static void for_each_
> fun);
>
> could we use ConnectionSurfa
> good to remove the system of checking valid surfaces in favor of using the
> connection-saved map).
ok
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:4085
https:/
Executed test runs:
SUCCESS: https:/
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:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Alan Griffiths (alan-griffiths) wrote : | # |
SurfaceTracking
Andreas Pokorny (andreas-pokorny) wrote : | # |
> SurfaceTracking
I am not sure it can be classified as accidental. And only useful until we discover a general problem...
Alan Griffiths (alan-griffiths) wrote : | # |
> > SurfaceTracking
> accidental?
>
> I am not sure it can be classified as accidental. And only useful until we
> discover a general problem...
/shrug. But I will block a third copy.
Preview Diff
1 | === modified file 'src/client/buffer_vault.cpp' |
2 | --- src/client/buffer_vault.cpp 2017-01-30 08:13:20 +0000 |
3 | +++ src/client/buffer_vault.cpp 2017-03-23 16:39:46 +0000 |
4 | @@ -18,10 +18,10 @@ |
5 | |
6 | #include "mir/client_buffer_factory.h" |
7 | #include "mir/client_buffer.h" |
8 | +#include "mir/client/surface_map.h" |
9 | #include "buffer_vault.h" |
10 | #include "buffer.h" |
11 | #include "buffer_factory.h" |
12 | -#include "surface_map.h" |
13 | #include "mir_protobuf.pb.h" |
14 | #include "protobuf_to_native_buffer.h" |
15 | #include "connection_surface_map.h" |
16 | |
17 | === modified file 'src/client/connection_surface_map.cpp' |
18 | --- src/client/connection_surface_map.cpp 2017-03-14 04:41:33 +0000 |
19 | +++ src/client/connection_surface_map.cpp 2017-03-23 16:39:46 +0000 |
20 | @@ -136,3 +136,10 @@ |
21 | BOOST_THROW_EXCEPTION(std::runtime_error("could not find render surface")); |
22 | } |
23 | #pragma GCC diagnostic pop |
24 | + |
25 | +void mcl::ConnectionSurfaceMap::with_all_windows_do(std::function<void(MirWindow*)> const& fn) const |
26 | +{ |
27 | + std::shared_lock<decltype(stream_guard)> lk(guard); |
28 | + for(auto const& window : surfaces) |
29 | + fn(window.second.get()); |
30 | +} |
31 | |
32 | === modified file 'src/client/connection_surface_map.h' |
33 | --- src/client/connection_surface_map.h 2017-03-14 04:41:33 +0000 |
34 | +++ src/client/connection_surface_map.h 2017-03-23 16:39:46 +0000 |
35 | @@ -19,7 +19,7 @@ |
36 | #ifndef MIR_CLIENT_CONNECTION_SURFACE_MAP_H_ |
37 | #define MIR_CLIENT_CONNECTION_SURFACE_MAP_H_ |
38 | |
39 | -#include "surface_map.h" |
40 | +#include "mir/client/surface_map.h" |
41 | |
42 | #include <shared_mutex> |
43 | #include <unordered_map> |
44 | @@ -56,6 +56,7 @@ |
45 | void insert(void* render_surface_key, std::shared_ptr<MirRenderSurface> const& render_surface); |
46 | std::shared_ptr<MirRenderSurface> render_surface(void* render_surface_key) const; |
47 | #pragma GCC diagnostic pop |
48 | + void with_all_windows_do(std::function<void(MirWindow*)> const&) const override; |
49 | private: |
50 | std::shared_timed_mutex mutable guard; |
51 | std::unordered_map<frontend::SurfaceId, std::shared_ptr<MirWindow>> surfaces; |
52 | |
53 | === modified file 'src/client/default_connection_configuration.cpp' |
54 | --- src/client/default_connection_configuration.cpp 2017-02-15 14:45:41 +0000 |
55 | +++ src/client/default_connection_configuration.cpp 2017-03-23 16:39:46 +0000 |
56 | @@ -118,9 +118,9 @@ |
57 | mcl::DefaultConnectionConfiguration::the_input_devices() |
58 | { |
59 | return input_devices( |
60 | - [] |
61 | + [this] |
62 | { |
63 | - return std::make_shared<mir::input::InputDevices>(); |
64 | + return std::make_shared<mir::input::InputDevices>(the_surface_map()); |
65 | }); |
66 | } |
67 | |
68 | |
69 | === modified file 'src/client/input/input_devices.cpp' |
70 | --- src/client/input/input_devices.cpp 2017-01-18 02:29:37 +0000 |
71 | +++ src/client/input/input_devices.cpp 2017-03-23 16:39:46 +0000 |
72 | @@ -18,19 +18,57 @@ |
73 | |
74 | #include "mir/input/input_devices.h" |
75 | #include "mir/input/mir_input_config_serialization.h" |
76 | +#include "mir/input/mir_input_config_serialization.h" |
77 | +#include "mir/input/xkb_mapper.h" |
78 | +#include "../mir_surface.h" |
79 | + |
80 | +#include <unordered_set> |
81 | |
82 | namespace mi = mir::input; |
83 | |
84 | +namespace |
85 | +{ |
86 | +std::unordered_set<MirInputDeviceId> get_removed_devices(MirInputConfig const& old_config, MirInputConfig const& new_config) |
87 | +{ |
88 | + std::unordered_set<MirInputDeviceId> removed; |
89 | + old_config.for_each( |
90 | + [&new_config, &removed](MirInputDevice const& dev) |
91 | + { |
92 | + if (nullptr == new_config.get_device_config_by_id(dev.id())) |
93 | + removed.insert(dev.id()); |
94 | + }); |
95 | + return removed; |
96 | +} |
97 | +} |
98 | + |
99 | +mi::InputDevices::InputDevices(std::shared_ptr<client::SurfaceMap> const& windows) |
100 | + : windows{windows} |
101 | +{ |
102 | +} |
103 | + |
104 | void mi::InputDevices::update_devices(std::string const& config_buffer) |
105 | { |
106 | std::function<void()> stored_callback; |
107 | |
108 | + std::unordered_set<MirInputDeviceId> ids; |
109 | { |
110 | + auto new_configuration = mi::deserialize_input_config(config_buffer); |
111 | std::unique_lock<std::mutex> lock(devices_access); |
112 | - configuration = mi::deserialize_input_config(config_buffer); |
113 | + ids = get_removed_devices(new_configuration, configuration); |
114 | + configuration = new_configuration; |
115 | stored_callback = callback; |
116 | } |
117 | |
118 | + auto window_map = windows.lock(); |
119 | + if (window_map) |
120 | + window_map->with_all_windows_do( |
121 | + [&ids](MirWindow* window) |
122 | + { |
123 | + auto keymapper = window->get_keymapper(); |
124 | + for (auto const& id : ids) |
125 | + keymapper->clear_keymap_for_device(id); |
126 | + }); |
127 | + |
128 | if (stored_callback) |
129 | stored_callback(); |
130 | } |
131 | |
132 | === modified file 'src/client/mir_surface.cpp' |
133 | --- src/client/mir_surface.cpp 2017-03-17 15:32:15 +0000 |
134 | +++ src/client/mir_surface.cpp 2017-03-23 16:39:46 +0000 |
135 | @@ -838,4 +838,9 @@ |
136 | return frame_clock; |
137 | } |
138 | |
139 | +std::shared_ptr<mir::input::receiver::XKBMapper> MirSurface::get_keymapper() const |
140 | +{ |
141 | + return keymapper; |
142 | +} |
143 | + |
144 | #pragma GCC diagnostic pop |
145 | |
146 | === modified file 'src/client/mir_surface.h' |
147 | --- src/client/mir_surface.h 2017-03-17 15:32:15 +0000 |
148 | +++ src/client/mir_surface.h 2017-03-23 16:39:46 +0000 |
149 | @@ -221,6 +221,7 @@ |
150 | MirConnection* connection() const; |
151 | |
152 | std::shared_ptr<mir::client::FrameClock> get_frame_clock() const; |
153 | + std::shared_ptr<mir::input::receiver::XKBMapper> get_keymapper() const; |
154 | |
155 | private: |
156 | std::mutex mutable mutex; // Protects all members of *this |
157 | |
158 | === modified file 'src/client/rpc/mir_protobuf_rpc_channel.cpp' |
159 | --- src/client/rpc/mir_protobuf_rpc_channel.cpp 2017-03-17 17:20:09 +0000 |
160 | +++ src/client/rpc/mir_protobuf_rpc_channel.cpp 2017-03-23 16:39:46 +0000 |
161 | @@ -19,7 +19,7 @@ |
162 | #include "mir_protobuf_rpc_channel.h" |
163 | #include "rpc_report.h" |
164 | |
165 | -#include "../surface_map.h" |
166 | +#include "mir/client/surface_map.h" |
167 | #include "../buffer.h" |
168 | #include "../presentation_chain.h" |
169 | #include "../buffer_factory.h" |
170 | |
171 | === renamed file 'src/client/surface_map.h' => 'src/include/client/mir/client/surface_map.h' |
172 | --- src/client/surface_map.h 2017-01-18 04:43:15 +0000 |
173 | +++ src/include/client/mir/client/surface_map.h 2017-03-23 16:39:46 +0000 |
174 | @@ -43,7 +43,8 @@ |
175 | virtual void with_all_streams_do(std::function<void(MirBufferStream*)> const&) const = 0; |
176 | virtual std::shared_ptr<MirBuffer> buffer(int buffer_id) const = 0; |
177 | virtual void insert(int buffer_id, std::shared_ptr<MirBuffer> const& buffer) = 0; |
178 | - virtual void erase(int buffer_id) = 0; |
179 | + virtual void erase(int buffer_id) = 0; |
180 | + virtual void with_all_windows_do(std::function<void(MirWindow*)> const&) const = 0; |
181 | |
182 | protected: |
183 | virtual ~SurfaceMap() = default; |
184 | |
185 | === modified file 'src/include/client/mir/input/input_devices.h' |
186 | --- src/include/client/mir/input/input_devices.h 2017-01-18 02:29:37 +0000 |
187 | +++ src/include/client/mir/input/input_devices.h 2017-03-23 16:39:46 +0000 |
188 | @@ -20,6 +20,7 @@ |
189 | #define MIR_INPUT_INPUT_DEVICES_H_ |
190 | |
191 | #include "mir/input/mir_input_config.h" |
192 | +#include "mir/client/surface_map.h" |
193 | |
194 | #include <mutex> |
195 | #include <string> |
196 | @@ -32,11 +33,12 @@ |
197 | class InputDevices |
198 | { |
199 | public: |
200 | - InputDevices() = default; |
201 | + InputDevices(std::shared_ptr<client::SurfaceMap> const& windows); |
202 | void update_devices(std::string const& device_buffer); |
203 | MirInputConfig devices(); |
204 | void set_change_callback(std::function<void()> const& callback); |
205 | private: |
206 | + std::weak_ptr<client::SurfaceMap> const windows; |
207 | std::mutex devices_access; |
208 | MirInputConfig configuration; |
209 | std::function<void()> callback; |
210 | |
211 | === modified file 'tests/acceptance-tests/test_nested_input.cpp' |
212 | --- tests/acceptance-tests/test_nested_input.cpp 2017-03-23 16:39:46 +0000 |
213 | +++ tests/acceptance-tests/test_nested_input.cpp 2017-03-23 16:39:46 +0000 |
214 | @@ -22,6 +22,10 @@ |
215 | #include "mir/input/event_filter.h" |
216 | #include "mir/input/composite_event_filter.h" |
217 | #include "mir/input/mir_input_config.h" |
218 | +#include "mir/shell/shell_wrapper.h" |
219 | +#include "mir/scene/session.h" |
220 | +#include "mir/scene/surface.h" |
221 | +#include "mir/graphics/event_handler_register.h" |
222 | |
223 | #include "mir_test_framework/fake_input_device.h" |
224 | #include "mir_test_framework/stub_server_platform_factory.h" |
225 | @@ -30,6 +34,7 @@ |
226 | #include "mir_test_framework/any_surface.h" |
227 | #include "mir/test/doubles/nested_mock_egl.h" |
228 | #include "mir/test/doubles/mock_input_device_observer.h" |
229 | +#include "mir/test/doubles/fake_display.h" |
230 | #include "mir/test/event_factory.h" |
231 | #include "mir/test/event_matchers.h" |
232 | #include "mir/test/fake_shared.h" |
233 | @@ -48,6 +53,7 @@ |
234 | namespace mis = mi::synthesis; |
235 | |
236 | namespace mt = mir::test; |
237 | +namespace mg = mir::graphics; |
238 | namespace mtd = mt::doubles; |
239 | namespace mtf = mir_test_framework; |
240 | |
241 | @@ -56,6 +62,71 @@ |
242 | |
243 | namespace |
244 | { |
245 | + |
246 | +struct SurfaceTrackingShell : mir::shell::ShellWrapper |
247 | +{ |
248 | + SurfaceTrackingShell( |
249 | + std::shared_ptr<mir::shell::Shell> wrapped_shell) |
250 | + : ShellWrapper{wrapped_shell}, wrapped_shell{wrapped_shell} |
251 | + {} |
252 | + |
253 | + mir::frontend::SurfaceId create_surface( |
254 | + std::shared_ptr<mir::scene::Session> const& session, |
255 | + mir::scene::SurfaceCreationParameters const& params, |
256 | + std::shared_ptr<mir::frontend::EventSink> const& sink) override |
257 | + { |
258 | + auto surface_id = wrapped_shell->create_surface(session, params, sink); |
259 | + |
260 | + tracked_surfaces[session->name()] = TrackedSurface{session, surface_id}; |
261 | + |
262 | + return surface_id; |
263 | + } |
264 | + |
265 | + std::shared_ptr<mir::scene::Surface> get_surface(std::string const& session_name) |
266 | + { |
267 | + if (end(tracked_surfaces) == tracked_surfaces.find(session_name)) |
268 | + return nullptr; |
269 | + TrackedSurface & tracked_surface = tracked_surfaces[session_name]; |
270 | + auto session = tracked_surface.session.lock(); |
271 | + if (!session) |
272 | + return nullptr; |
273 | + return session->surface(tracked_surface.surface); |
274 | + } |
275 | + |
276 | + struct TrackedSurface |
277 | + { |
278 | + std::weak_ptr<mir::scene::Session> session; |
279 | + mir::frontend::SurfaceId surface; |
280 | + }; |
281 | + std::unordered_map<std::string, TrackedSurface> tracked_surfaces; |
282 | + std::shared_ptr<mir::shell::Shell> wrapped_shell; |
283 | +}; |
284 | + |
285 | +struct Display : mtd::FakeDisplay |
286 | +{ |
287 | + using mtd::FakeDisplay::FakeDisplay; |
288 | + |
289 | + void register_pause_resume_handlers( |
290 | + mg::EventHandlerRegister&, |
291 | + mg::DisplayPauseHandler const& pause_handler, |
292 | + mg::DisplayResumeHandler const& resume_handler) override |
293 | + { |
294 | + pause_function = pause_handler; |
295 | + resume_function = resume_handler; |
296 | + } |
297 | + |
298 | + void trigger_pause() |
299 | + { |
300 | + pause_function(); |
301 | + } |
302 | + void trigger_resume() |
303 | + { |
304 | + resume_function(); |
305 | + } |
306 | + std::function<bool()> pause_function{[](){return false;}}; |
307 | + std::function<bool()> resume_function{[](){return false;}}; |
308 | +}; |
309 | + |
310 | size_t get_index_of(MirInputConfig const* config, std::string const& id) |
311 | { |
312 | for (size_t i = 0, e = mir_input_config_device_count(config);i != e;++i) |
313 | @@ -75,11 +146,11 @@ |
314 | struct MockEventFilter : public mi::EventFilter |
315 | { |
316 | // Work around GMock wanting to know how to construct MirEvent |
317 | - MOCK_METHOD1(handle, bool(MirEvent const*)); |
318 | + MOCK_METHOD1(handle, void(MirEvent const*)); |
319 | bool handle(MirEvent const& ev) |
320 | { |
321 | handle(&ev); |
322 | - return true; |
323 | + return false; |
324 | } |
325 | }; |
326 | |
327 | @@ -94,7 +165,15 @@ |
328 | std::shared_ptr<MockEventFilter> const& event_filter) |
329 | : mtf::HeadlessNestedServerRunner(connection_string), mock_event_filter{event_filter} |
330 | { |
331 | - server.the_composite_event_filter()->append(mock_event_filter); |
332 | + server.the_composite_event_filter()->prepend(mock_event_filter); |
333 | + server.wrap_shell( |
334 | + [this](std::shared_ptr<mir::shell::Shell> const& wrapped) |
335 | + { |
336 | + surfaces = std::make_shared<SurfaceTrackingShell>(wrapped); |
337 | + return surfaces; |
338 | + }); |
339 | + |
340 | + |
341 | start_server(); |
342 | } |
343 | NestedServerWithMockEventFilter(std::string const& connection_string) |
344 | @@ -107,14 +186,24 @@ |
345 | stop_server(); |
346 | } |
347 | |
348 | + std::shared_ptr<mir::scene::Surface> get_surface(std::string const& name) |
349 | + { |
350 | + return surfaces->get_surface(name); |
351 | + } |
352 | + std::shared_ptr<SurfaceTrackingShell> surfaces; |
353 | std::shared_ptr<MockEventFilter> const mock_event_filter; |
354 | }; |
355 | |
356 | struct NestedInput : public mtf::HeadlessInProcessServer |
357 | { |
358 | + Display display{display_geometry}; |
359 | + NestedInput() |
360 | + { |
361 | + preset_display(mt::fake_shared(display)); |
362 | + } |
363 | + |
364 | void SetUp() |
365 | { |
366 | - initial_display_layout(display_geometry); |
367 | mtf::HeadlessInProcessServer::SetUp(); |
368 | } |
369 | |
370 | @@ -143,10 +232,10 @@ |
371 | { |
372 | public: |
373 | using UniqueInputConfig = std::unique_ptr<MirInputConfig , void(*)(MirInputConfig const*)>; |
374 | - ExposedSurface(std::string const& connect_string) |
375 | + ExposedSurface(std::string const& connect_string, std::string const& session_name = "ExposedSurface") |
376 | { |
377 | // Ensure the nested server posts a frame |
378 | - connection = mir_connect_sync(connect_string.c_str(), __PRETTY_FUNCTION__); |
379 | + connection = mir_connect_sync(connect_string.c_str(), session_name.c_str()); |
380 | |
381 | mir_connection_set_input_config_change_callback( |
382 | connection, |
383 | @@ -163,6 +252,8 @@ |
384 | } |
385 | |
386 | MOCK_METHOD1(handle_input, void(MirEvent const*)); |
387 | + MOCK_METHOD1(handle_device_state, void(MirEvent const*)); |
388 | + MOCK_METHOD0(handle_keymap, void()); |
389 | |
390 | void handle_window_event(MirWindowEvent const* event) |
391 | { |
392 | @@ -177,7 +268,12 @@ |
393 | mir_window_focus_state_focused == value) |
394 | focused = true; |
395 | |
396 | - if (exposed && focused) |
397 | + test_and_raise(); |
398 | + } |
399 | + |
400 | + void test_and_raise() |
401 | + { |
402 | + if (exposed && focused && input_device_state_received) |
403 | ready_to_accept_events.raise(); |
404 | } |
405 | |
406 | @@ -207,8 +303,17 @@ |
407 | client->handle_window_event(window_event); |
408 | |
409 | } |
410 | + if (type == mir_event_type_keymap) |
411 | + client->handle_keymap(); |
412 | if (type == mir_event_type_input) |
413 | client->handle_input(ev); |
414 | + if (type == mir_event_type_input_device_state) |
415 | + { |
416 | + client->input_device_state_received = true; |
417 | + client->test_and_raise(); |
418 | + client->handle_device_state(ev); |
419 | + } |
420 | + |
421 | } |
422 | |
423 | static void null_event_handler(MirWindow*, MirEvent const*, void*) {}; |
424 | @@ -229,6 +334,7 @@ |
425 | MirWindow *window; |
426 | bool exposed{false}; |
427 | bool focused{false}; |
428 | + bool input_device_state_received = false; |
429 | std::function<void(MirInputConfig const* confg)> input_config{[](MirInputConfig const*){}}; |
430 | }; |
431 | |
432 | @@ -243,15 +349,14 @@ |
433 | |
434 | InSequence seq; |
435 | EXPECT_CALL(nested_event_filter, handle(mt::InputDeviceStateEvent())) |
436 | - .WillOnce(DoAll(mt::WakeUp(&devices_ready), Return(true))); |
437 | + .WillOnce(mt::WakeUp(&devices_ready)); |
438 | EXPECT_CALL(nested_event_filter, handle(mt::KeyOfScanCode(KEY_A))). |
439 | Times(AtLeast(1)). |
440 | - WillRepeatedly(DoAll(InvokeWithoutArgs(increase_key_a_events), Return(true))); |
441 | + WillRepeatedly(InvokeWithoutArgs(increase_key_a_events)); |
442 | |
443 | EXPECT_CALL(nested_event_filter, handle(mt::KeyOfScanCode(KEY_RIGHTSHIFT))). |
444 | Times(2). |
445 | - WillOnce(Return(true)). |
446 | - WillOnce(DoAll(mt::WakeUp(&all_events_received), Return(true))); |
447 | + WillOnce(mt::WakeUp(&all_events_received)); |
448 | |
449 | NestedServerWithMockEventFilter nested_mir{new_connection(), mt::fake_shared(nested_event_filter)}; |
450 | ExposedSurface client(nested_mir.new_connection()); |
451 | @@ -348,7 +453,7 @@ |
452 | .WillOnce(mt::WakeUp(&client_to_host_event_received)); |
453 | EXPECT_CALL(nested_event_filter, |
454 | handle(mt::DeviceStateWithPressedKeys(std::vector<uint32_t>({KEY_LEFTALT, KEY_TAB})))) |
455 | - .WillOnce(DoAll(mt::WakeUp(&client_to_nested_event_received), Return(true))); |
456 | + .WillOnce(mt::WakeUp(&client_to_nested_event_received)); |
457 | |
458 | fake_keyboard->emit_event(mis::a_key_down_event().of_scancode(KEY_LEFTALT)); |
459 | fake_keyboard->emit_event(mis::a_key_down_event().of_scancode(KEY_TAB)); |
460 | @@ -367,12 +472,12 @@ |
461 | mt::Signal devices_ready; |
462 | mt::Signal event_received; |
463 | EXPECT_CALL(nested_event_filter, handle(mt::InputDeviceStateEvent())) |
464 | - .WillOnce(DoAll(mt::WakeUp(&devices_ready), Return(true))); |
465 | + .WillOnce(mt::WakeUp(&devices_ready)); |
466 | |
467 | EXPECT_CALL(nested_event_filter, |
468 | handle(AllOf(mt::PointerEventWithPosition(initial_movement_x, initial_movement_y), |
469 | mt::PointerEventWithDiff(initial_movement_x, initial_movement_y)))) |
470 | - .WillOnce(DoAll(mt::WakeUp(&event_received), Return(true))); |
471 | + .WillOnce(mt::WakeUp(&event_received)); |
472 | |
473 | NestedServerWithMockEventFilter nested_mir{new_connection(), mt::fake_shared(nested_event_filter)}; |
474 | ExposedSurface client_to_nested_mir(nested_mir.new_connection()); |
475 | @@ -388,7 +493,7 @@ |
476 | EXPECT_CALL(nested_event_filter, |
477 | handle(AllOf(mt::PointerEventWithPosition(initial_movement_x + second_movement_x, initial_movement_y + second_movement_y), |
478 | mt::PointerEventWithDiff(second_movement_x, second_movement_y)))) |
479 | - .WillOnce(DoAll(mt::WakeUp(&event_received), Return(true))); |
480 | + .WillOnce(mt::WakeUp(&event_received)); |
481 | |
482 | fake_mouse->emit_event(mis::a_pointer_event().with_movement(second_movement_x, second_movement_y)); |
483 | ASSERT_TRUE(event_received.wait_for(60s)); |
484 | @@ -410,11 +515,11 @@ |
485 | |
486 | EXPECT_CALL(nested_event_filter, handle( |
487 | mt::DeviceStateWithPosition(initial_x, initial_y))) |
488 | - .WillOnce(DoAll(mt::WakeUp(&devices_ready), Return(true))); |
489 | + .WillOnce(mt::WakeUp(&devices_ready)); |
490 | EXPECT_CALL(nested_event_filter, |
491 | handle(AllOf(mt::PointerEventWithPosition(final_x, final_y), |
492 | mt::PointerEventWithDiff(x[2], y[2])))) |
493 | - .WillOnce(DoAll(mt::WakeUp(&event_received), Return(true))); |
494 | + .WillOnce(mt::WakeUp(&event_received)); |
495 | |
496 | NestedServerWithMockEventFilter nested_mir{new_connection(), mt::fake_shared(nested_event_filter)}; |
497 | ExposedSurface client_to_nested_mir(nested_mir.new_connection()); |
498 | @@ -464,3 +569,44 @@ |
499 | EXPECT_THAT(mir_pointer_config_get_acceleration_bias(ptr_conf), acceleration_bias); |
500 | } |
501 | |
502 | +TEST_F(NestedInput, pressed_keys_on_vt_switch_are_forgotten) |
503 | +{ |
504 | + mt::Signal keymap_received; |
505 | + mt::Signal devices_ready; |
506 | + mt::Signal initial_keys_received; |
507 | + mt::Signal keys_without_modifier_received; |
508 | + NiceMock<MockEventFilter> nested_event_filter; |
509 | + ON_CALL(nested_event_filter, handle( |
510 | + mt::InputDeviceStateEvent())) |
511 | + .WillByDefault(mt::WakeUp(&devices_ready)); |
512 | + |
513 | + NestedServerWithMockEventFilter nested_mir{new_connection(), mt::fake_shared(nested_event_filter)}; |
514 | + ExposedSurface client_to_nested(nested_mir.new_connection(), "with_keymap"); |
515 | + |
516 | + ASSERT_TRUE(devices_ready.wait_for(10s)); |
517 | + EXPECT_CALL(client_to_nested, handle_keymap()) |
518 | + .WillOnce(mt::WakeUp(&keymap_received)); |
519 | + EXPECT_CALL(client_to_nested, handle_input(mt::KeyOfScanCode(KEY_RIGHTALT))); |
520 | + EXPECT_CALL(client_to_nested, handle_input(mt::KeyOfScanCode(KEY_RIGHTCTRL))) |
521 | + .WillOnce(mt::WakeUp(&initial_keys_received)); |
522 | + |
523 | + nested_mir.get_surface("with_keymap")->set_keymap(MirInputDeviceId{0}, "pc105", "de", "", ""); |
524 | + |
525 | + ASSERT_TRUE(client_to_nested.ready_to_accept_events.wait_for(10s)); |
526 | + EXPECT_TRUE(keymap_received.wait_for(10s)); |
527 | + |
528 | + fake_keyboard->emit_event(mis::a_key_down_event().of_scancode(KEY_RIGHTALT)); |
529 | + fake_keyboard->emit_event(mis::a_key_down_event().of_scancode(KEY_RIGHTCTRL)); |
530 | + |
531 | + EXPECT_TRUE(initial_keys_received.wait_for(10s)); |
532 | + |
533 | + display.trigger_pause(); |
534 | + display.trigger_resume(); |
535 | + |
536 | + EXPECT_CALL(client_to_nested, |
537 | + handle_input(AllOf(mt::KeyOfScanCode(KEY_A), mt::KeyWithModifiers(mir_input_event_modifier_none)))) |
538 | + .WillOnce(mt::WakeUp(&keys_without_modifier_received)); |
539 | + |
540 | + fake_keyboard->emit_event(mis::a_key_down_event().of_scancode(KEY_A)); |
541 | + EXPECT_TRUE(keys_without_modifier_received.wait_for(10s)); |
542 | +} |
543 | |
544 | === modified file 'tests/include/mir/test/test_protobuf_client.h' |
545 | --- tests/include/mir/test/test_protobuf_client.h 2017-01-18 02:29:37 +0000 |
546 | +++ tests/include/mir/test/test_protobuf_client.h 2017-03-23 16:39:46 +0000 |
547 | @@ -33,7 +33,11 @@ |
548 | |
549 | namespace mir |
550 | { |
551 | -namespace client { namespace rpc {class MirBasicRpcChannel;}} |
552 | +namespace client |
553 | +{ |
554 | +class SurfaceMap; |
555 | +namespace rpc {class MirBasicRpcChannel;} |
556 | +} |
557 | namespace dispatch |
558 | { |
559 | class ThreadedDispatcher; |
560 | @@ -49,6 +53,7 @@ |
561 | TestProtobufClient(std::string socket_file, int timeout_ms); |
562 | |
563 | std::shared_ptr<doubles::MockRpcReport> rpc_report; |
564 | + std::shared_ptr<mir::client::SurfaceMap> surface_map; |
565 | std::shared_ptr<mir::client::rpc::MirBasicRpcChannel> channel; |
566 | std::shared_ptr<dispatch::ThreadedDispatcher> eventloop; |
567 | mir::client::rpc::DisplayServer display_server; |
568 | |
569 | === modified file 'tests/mir_test_doubles/test_protobuf_client.cpp' |
570 | --- tests/mir_test_doubles/test_protobuf_client.cpp 2017-01-18 02:29:37 +0000 |
571 | +++ tests/mir_test_doubles/test_protobuf_client.cpp 2017-03-23 16:39:46 +0000 |
572 | @@ -42,12 +42,13 @@ |
573 | |
574 | mir::test::TestProtobufClient::TestProtobufClient(std::string socket_file, int timeout_ms) : |
575 | rpc_report(std::make_shared<testing::NiceMock<doubles::MockRpcReport>>()), |
576 | + surface_map{std::make_shared<mir::client::ConnectionSurfaceMap>()}, |
577 | channel(mclr::make_rpc_channel( |
578 | socket_file, |
579 | - std::make_shared<mir::client::ConnectionSurfaceMap>(), |
580 | + surface_map, |
581 | std::make_shared<mir::client::BufferFactory>(), |
582 | std::make_shared<mir::client::DisplayConfiguration>(), |
583 | - std::make_shared<mir::input::InputDevices>(), |
584 | + std::make_shared<mir::input::InputDevices>(surface_map), |
585 | rpc_report, |
586 | std::make_shared<mir::client::LifecycleControl>(), |
587 | std::make_shared<mir::client::AtomicCallback<int32_t>>(), |
588 | |
589 | === modified file 'tests/unit-tests/client/test_protobuf_rpc_channel.cpp' |
590 | --- tests/unit-tests/client/test_protobuf_rpc_channel.cpp 2017-03-10 19:47:57 +0000 |
591 | +++ tests/unit-tests/client/test_protobuf_rpc_channel.cpp 2017-03-23 16:39:46 +0000 |
592 | @@ -19,7 +19,6 @@ |
593 | #include "src/client/rpc/mir_protobuf_rpc_channel.h" |
594 | #include "src/client/rpc/stream_transport.h" |
595 | #include "src/client/rpc/mir_display_server.h" |
596 | -#include "src/client/surface_map.h" |
597 | #include "src/client/display_configuration.h" |
598 | #include "src/client/rpc/null_rpc_report.h" |
599 | #include "src/client/lifecycle_control.h" |
600 | @@ -29,6 +28,7 @@ |
601 | #include "mir/variable_length_array.h" |
602 | #include "mir_protobuf.pb.h" |
603 | #include "mir_protobuf_wire.pb.h" |
604 | +#include "mir/client/surface_map.h" |
605 | #include "mir/input/input_devices.h" |
606 | |
607 | #include "mir/test/doubles/null_client_event_sink.h" |
608 | @@ -67,7 +67,9 @@ |
609 | MOCK_METHOD2(insert, void(int, std::shared_ptr<mcl::MirBuffer> const&)); |
610 | MOCK_METHOD2(insert, void(mir::frontend::BufferStreamId, std::shared_ptr<MirPresentationChain> const&)); |
611 | MOCK_METHOD1(erase, void(int)); |
612 | -}; |
613 | + MOCK_CONST_METHOD1(with_all_windows_do, |
614 | + void(std::function<void(MirWindow*)> const&)); |
615 | +}; |
616 | |
617 | class StubSurfaceMap : public mcl::SurfaceMap |
618 | { |
619 | @@ -96,6 +98,9 @@ |
620 | void erase(int) override |
621 | { |
622 | } |
623 | + void with_all_windows_do(std::function<void(MirWindow*)> const&) const override |
624 | + { |
625 | + } |
626 | }; |
627 | |
628 | class MockStreamTransport : public mclr::StreamTransport |
629 | @@ -235,12 +240,13 @@ |
630 | MirProtobufRpcChannelTest() |
631 | : transport{new testing::NiceMock<MockStreamTransport>}, |
632 | lifecycle{std::make_shared<mcl::LifecycleControl>()}, |
633 | + surface_map{std::make_shared<StubSurfaceMap>()}, |
634 | channel{new mclr::MirProtobufRpcChannel{ |
635 | std::unique_ptr<MockStreamTransport>{transport}, |
636 | - std::make_shared<StubSurfaceMap>(), |
637 | + surface_map, |
638 | std::make_shared<mcl::BufferFactory>(), |
639 | std::make_shared<mcl::DisplayConfiguration>(), |
640 | - std::make_shared<mir::input::InputDevices>(), |
641 | + std::make_shared<mir::input::InputDevices>(surface_map), |
642 | std::make_shared<mclr::NullRpcReport>(), |
643 | lifecycle, |
644 | std::make_shared<mir::client::PingHandler>(), |
645 | @@ -251,6 +257,7 @@ |
646 | |
647 | MockStreamTransport* transport; |
648 | std::shared_ptr<mcl::LifecycleControl> lifecycle; |
649 | + std::shared_ptr<mcl::SurfaceMap> surface_map; |
650 | std::shared_ptr<mclr::MirProtobufRpcChannel> channel; |
651 | mtd::MockMirBufferStream stream; |
652 | }; |
653 | @@ -395,7 +402,7 @@ |
654 | stream_map, |
655 | std::make_shared<mcl::BufferFactory>(), |
656 | std::make_shared<mcl::DisplayConfiguration>(), |
657 | - std::make_shared<mir::input::InputDevices>(), |
658 | + std::make_shared<mir::input::InputDevices>(stream_map), |
659 | std::make_shared<mclr::NullRpcReport>(), |
660 | lifecycle, |
661 | std::make_shared<mir::client::PingHandler>(), |
662 | @@ -745,7 +752,7 @@ |
663 | stream_map, |
664 | mock_buffer_factory, |
665 | std::make_shared<mcl::DisplayConfiguration>(), |
666 | - std::make_shared<mir::input::InputDevices>(), |
667 | + std::make_shared<mir::input::InputDevices>(stream_map), |
668 | std::make_shared<mclr::NullRpcReport>(), |
669 | lifecycle, |
670 | std::make_shared<mir::client::PingHandler>(), |
671 | @@ -780,7 +787,7 @@ |
672 | stream_map, |
673 | mock_buffer_factory, |
674 | std::make_shared<mcl::DisplayConfiguration>(), |
675 | - std::make_shared<mir::input::InputDevices>(), |
676 | + std::make_shared<mir::input::InputDevices>(stream_map), |
677 | std::make_shared<mclr::NullRpcReport>(), |
678 | lifecycle, |
679 | std::make_shared<mir::client::PingHandler>(), |
680 | @@ -813,7 +820,7 @@ |
681 | stream_map, |
682 | mock_buffer_factory, |
683 | std::make_shared<mcl::DisplayConfiguration>(), |
684 | - std::make_shared<mir::input::InputDevices>(), |
685 | + std::make_shared<mir::input::InputDevices>(stream_map), |
686 | std::make_shared<mclr::NullRpcReport>(), |
687 | lifecycle, |
688 | std::make_shared<mir::client::PingHandler>(), |
689 | |
690 | === modified file 'tests/unit-tests/frontend/stress_protobuf_communicator.cpp' |
691 | --- tests/unit-tests/frontend/stress_protobuf_communicator.cpp 2017-03-20 12:08:08 +0000 |
692 | +++ tests/unit-tests/frontend/stress_protobuf_communicator.cpp 2017-03-23 16:39:46 +0000 |
693 | @@ -59,6 +59,7 @@ |
694 | StubProtobufClient(std::string socket_file, int timeout_ms); |
695 | |
696 | std::shared_ptr<mir::client::rpc::RpcReport> rpc_report; |
697 | + std::shared_ptr<mir::client::SurfaceMap> surface_map; |
698 | std::shared_ptr<mir::client::rpc::MirBasicRpcChannel> channel; |
699 | mir::client::rpc::DisplayServer display_server; |
700 | mir::protobuf::ConnectParameters connect_parameters; |
701 | @@ -162,12 +163,13 @@ |
702 | std::string socket_file, |
703 | int timeout_ms) : |
704 | rpc_report(std::make_shared<mir::client::rpc::NullRpcReport>()), |
705 | + surface_map(std::make_shared<mir::client::ConnectionSurfaceMap>()), |
706 | channel(mir::client::rpc::make_rpc_channel( |
707 | socket_file, |
708 | - std::make_shared<mir::client::ConnectionSurfaceMap>(), |
709 | + surface_map, |
710 | std::make_shared<mir::client::BufferFactory>(), |
711 | std::make_shared<mir::client::DisplayConfiguration>(), |
712 | - std::make_shared<mir::input::InputDevices>(), |
713 | + std::make_shared<mir::input::InputDevices>(surface_map), |
714 | rpc_report, |
715 | std::make_shared<mir::client::LifecycleControl>(), |
716 | std::make_shared<mir::client::PingHandler>(), |
FAILED: Continuous integration, rev:4080 /mir-jenkins. ubuntu. com/job/ mir-ci/ 3120/ /mir-jenkins. ubuntu. com/job/ build-mir/ 4188/console /mir-jenkins. ubuntu. com/job/ build-0- fetch/4275 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= vivid+overlay/ 4265 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial+ overlay/ 4265 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= zesty/4265 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= zesty/4215/ console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial+ overlay/ 4215 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial+ overlay/ 4215/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= zesty/4215 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= zesty/4215/ artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 4215 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 4215/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 4215 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 4215/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial+ overlay/ 4215/console
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: 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:/
FAILURE: https:/
Click here to trigger a rebuild: /mir-jenkins. ubuntu. com/job/ mir-ci/ 3120/rebuild
https:/