Merge lp:~raof/mir/wayland-input-fixes into lp:mir
- wayland-input-fixes
- Merge into development-branch
Proposed by
Chris Halse Rogers
Status: | Superseded | ||||
---|---|---|---|---|---|
Proposed branch: | lp:~raof/mir/wayland-input-fixes | ||||
Merge into: | lp:mir | ||||
Diff against target: |
752 lines (+266/-65) 6 files modified
debian/control (+1/-0) include/client/mir/client/event.h (+54/-0) src/client/CMakeLists.txt (+1/-0) src/protocol/wrapper_generator.cpp (+11/-1) src/server/frontend/wayland/core_generated_interfaces.h (+60/-12) src/server/frontend/wayland/wayland_connector.cpp (+139/-52) |
||||
To merge this branch: | bzr merge lp:~raof/mir/wayland-input-fixes | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir CI Bot | continuous-integration | Needs Fixing | |
Mir development team | Pending | ||
Review via email: mp+331281@code.launchpad.net |
Commit message
Wayland: Fix lifetimes of wrapper objects.
This prevents client disconnects/
Description of the change
To post a comment you must log in.
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote : | # |
review:
Needs Fixing
(continuous-integration)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'debian/control' |
2 | --- debian/control 2017-09-13 04:15:28 +0000 |
3 | +++ debian/control 2017-09-25 18:25:28 +0000 |
4 | @@ -47,6 +47,7 @@ |
5 | capnproto, |
6 | libepoxy-dev, |
7 | python3-pil:native, |
8 | + linux-libc-dev, |
9 | Standards-Version: 3.9.4 |
10 | Homepage: https://launchpad.net/mir |
11 | # If you aren't a member of ~mir-team but need to upload packaging changes, |
12 | |
13 | === added file 'include/client/mir/client/event.h' |
14 | --- include/client/mir/client/event.h 1970-01-01 00:00:00 +0000 |
15 | +++ include/client/mir/client/event.h 2017-09-25 18:25:28 +0000 |
16 | @@ -0,0 +1,54 @@ |
17 | +/* |
18 | + * Copyright © 2017 Canonical Ltd. |
19 | + * |
20 | + * This program is free software: you can redistribute it and/or modify |
21 | + * it under the terms of the GNU Lesser General Public License version 2 or 3 as |
22 | + * published by the Free Software Foundation. |
23 | + * |
24 | + * This program is distributed in the hope that it will be useful, |
25 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
26 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
27 | + * GNU General Public License for more details. |
28 | + * |
29 | + * You should have received a copy of the GNU General Public License |
30 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
31 | + * |
32 | + * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com> |
33 | + */ |
34 | + |
35 | +#ifndef MIR_CLIENT_EVENT_H_ |
36 | +#define MIR_CLIENT_EVENT_H_ |
37 | + |
38 | +#include "mir_toolkit/events/event.h" |
39 | + |
40 | +#include <memory> |
41 | + |
42 | +namespace mir |
43 | +{ |
44 | +namespace client |
45 | +{ |
46 | +/// Handle class for MirEvent - provides automatic reference counting. |
47 | +class Event |
48 | +{ |
49 | +public: |
50 | + Event() = default; |
51 | + explicit Event(MirEvent const* event) : self{mir_event_ref(event), deleter} |
52 | + { |
53 | + } |
54 | + |
55 | + operator MirEvent const*() const { return self.get(); } |
56 | + |
57 | + void reset() { self.reset(); } |
58 | + |
59 | +private: |
60 | + static void deleter(MirEvent const* event) { mir_event_unref(event); } |
61 | + std::shared_ptr<MirEvent const> self; |
62 | +}; |
63 | + |
64 | +// Provide a deleted overload to avoid double release "accidents". |
65 | +void mir_event_unref(Event const& event) = delete; |
66 | +} |
67 | +} |
68 | + |
69 | +#endif //MIR_CLIENT_EVENT_H_ |
70 | + |
71 | |
72 | === modified file 'src/client/CMakeLists.txt' |
73 | --- src/client/CMakeLists.txt 2017-08-29 14:23:50 +0000 |
74 | +++ src/client/CMakeLists.txt 2017-09-25 18:25:28 +0000 |
75 | @@ -118,6 +118,7 @@ |
76 | ${CMAKE_SOURCE_DIR}/include/client/mir/client/connection.h |
77 | ${CMAKE_SOURCE_DIR}/include/client/mir/client/display_config.h |
78 | ${CMAKE_SOURCE_DIR}/include/client/mir/client/window.h |
79 | + ${CMAKE_SOURCE_DIR}/include/client/mir/client/event.h |
80 | ) |
81 | |
82 | # Ensure protobuf C++ headers have been produced before |
83 | |
84 | === modified file 'src/protocol/wrapper_generator.cpp' |
85 | --- src/protocol/wrapper_generator.cpp 2017-09-07 00:32:52 +0000 |
86 | +++ src/protocol/wrapper_generator.cpp 2017-09-25 18:25:28 +0000 |
87 | @@ -373,6 +373,16 @@ |
88 | |
89 | if (!methods.empty()) |
90 | { |
91 | + if (!is_global) |
92 | + { |
93 | + emit_indented_lines(out, " ", { |
94 | + {"static void resource_destroyed_thunk(wl_resource* us)"}, |
95 | + {"{"}, |
96 | + {" delete static_cast<", generated_name, "*>(wl_resource_get_user_data(us));"}, |
97 | + {"}"} |
98 | + }); |
99 | + } |
100 | + |
101 | emit_indented_lines(out, " ", { |
102 | { "static struct ", wl_name, "_interface const vtable;" } |
103 | }); |
104 | @@ -427,7 +437,7 @@ |
105 | if (has_vtable) |
106 | { |
107 | emit_indented_lines(out, indent + " ", |
108 | - {{ "wl_resource_set_implementation(resource, &vtable, this, nullptr);" }}); |
109 | + {{ "wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);" }}); |
110 | } |
111 | emit_indented_lines(out, indent, { |
112 | { "}" } |
113 | |
114 | === modified file 'src/server/frontend/wayland/core_generated_interfaces.h' |
115 | --- src/server/frontend/wayland/core_generated_interfaces.h 2017-09-07 00:33:43 +0000 |
116 | +++ src/server/frontend/wayland/core_generated_interfaces.h 2017-09-25 18:25:28 +0000 |
117 | @@ -108,7 +108,7 @@ |
118 | wl_resource_post_no_memory(parent); |
119 | BOOST_THROW_EXCEPTION((std::bad_alloc{})); |
120 | } |
121 | - wl_resource_set_implementation(resource, &vtable, this, nullptr); |
122 | + wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk); |
123 | } |
124 | virtual ~ShmPool() = default; |
125 | |
126 | @@ -138,6 +138,10 @@ |
127 | me->resize(size); |
128 | } |
129 | |
130 | + static void resource_destroyed_thunk(wl_resource* us) |
131 | + { |
132 | + delete static_cast<ShmPool*>(wl_resource_get_user_data(us)); |
133 | + } |
134 | static struct wl_shm_pool_interface const vtable; |
135 | }; |
136 | |
137 | @@ -207,7 +211,7 @@ |
138 | wl_resource_post_no_memory(parent); |
139 | BOOST_THROW_EXCEPTION((std::bad_alloc{})); |
140 | } |
141 | - wl_resource_set_implementation(resource, &vtable, this, nullptr); |
142 | + wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk); |
143 | } |
144 | virtual ~Buffer() = default; |
145 | |
146 | @@ -223,6 +227,10 @@ |
147 | me->destroy(); |
148 | } |
149 | |
150 | + static void resource_destroyed_thunk(wl_resource* us) |
151 | + { |
152 | + delete static_cast<Buffer*>(wl_resource_get_user_data(us)); |
153 | + } |
154 | static struct wl_buffer_interface const vtable; |
155 | }; |
156 | |
157 | @@ -243,7 +251,7 @@ |
158 | wl_resource_post_no_memory(parent); |
159 | BOOST_THROW_EXCEPTION((std::bad_alloc{})); |
160 | } |
161 | - wl_resource_set_implementation(resource, &vtable, this, nullptr); |
162 | + wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk); |
163 | } |
164 | virtual ~DataOffer() = default; |
165 | |
166 | @@ -293,6 +301,10 @@ |
167 | me->set_actions(dnd_actions, preferred_action); |
168 | } |
169 | |
170 | + static void resource_destroyed_thunk(wl_resource* us) |
171 | + { |
172 | + delete static_cast<DataOffer*>(wl_resource_get_user_data(us)); |
173 | + } |
174 | static struct wl_data_offer_interface const vtable; |
175 | }; |
176 | |
177 | @@ -317,7 +329,7 @@ |
178 | wl_resource_post_no_memory(parent); |
179 | BOOST_THROW_EXCEPTION((std::bad_alloc{})); |
180 | } |
181 | - wl_resource_set_implementation(resource, &vtable, this, nullptr); |
182 | + wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk); |
183 | } |
184 | virtual ~DataSource() = default; |
185 | |
186 | @@ -347,6 +359,10 @@ |
187 | me->set_actions(dnd_actions); |
188 | } |
189 | |
190 | + static void resource_destroyed_thunk(wl_resource* us) |
191 | + { |
192 | + delete static_cast<DataSource*>(wl_resource_get_user_data(us)); |
193 | + } |
194 | static struct wl_data_source_interface const vtable; |
195 | }; |
196 | |
197 | @@ -369,7 +385,7 @@ |
198 | wl_resource_post_no_memory(parent); |
199 | BOOST_THROW_EXCEPTION((std::bad_alloc{})); |
200 | } |
201 | - wl_resource_set_implementation(resource, &vtable, this, nullptr); |
202 | + wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk); |
203 | } |
204 | virtual ~DataDevice() = default; |
205 | |
206 | @@ -414,6 +430,10 @@ |
207 | me->release(); |
208 | } |
209 | |
210 | + static void resource_destroyed_thunk(wl_resource* us) |
211 | + { |
212 | + delete static_cast<DataDevice*>(wl_resource_get_user_data(us)); |
213 | + } |
214 | static struct wl_data_device_interface const vtable; |
215 | }; |
216 | |
217 | @@ -536,7 +556,7 @@ |
218 | wl_resource_post_no_memory(parent); |
219 | BOOST_THROW_EXCEPTION((std::bad_alloc{})); |
220 | } |
221 | - wl_resource_set_implementation(resource, &vtable, this, nullptr); |
222 | + wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk); |
223 | } |
224 | virtual ~ShellSurface() = default; |
225 | |
226 | @@ -625,6 +645,10 @@ |
227 | me->set_class(class_); |
228 | } |
229 | |
230 | + static void resource_destroyed_thunk(wl_resource* us) |
231 | + { |
232 | + delete static_cast<ShellSurface*>(wl_resource_get_user_data(us)); |
233 | + } |
234 | static struct wl_shell_surface_interface const vtable; |
235 | }; |
236 | |
237 | @@ -654,7 +678,7 @@ |
238 | wl_resource_post_no_memory(parent); |
239 | BOOST_THROW_EXCEPTION((std::bad_alloc{})); |
240 | } |
241 | - wl_resource_set_implementation(resource, &vtable, this, nullptr); |
242 | + wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk); |
243 | } |
244 | virtual ~Surface() = default; |
245 | |
246 | @@ -748,6 +772,10 @@ |
247 | me->damage_buffer(x, y, width, height); |
248 | } |
249 | |
250 | + static void resource_destroyed_thunk(wl_resource* us) |
251 | + { |
252 | + delete static_cast<Surface*>(wl_resource_get_user_data(us)); |
253 | + } |
254 | static struct wl_surface_interface const vtable; |
255 | }; |
256 | |
257 | @@ -847,7 +875,7 @@ |
258 | wl_resource_post_no_memory(parent); |
259 | BOOST_THROW_EXCEPTION((std::bad_alloc{})); |
260 | } |
261 | - wl_resource_set_implementation(resource, &vtable, this, nullptr); |
262 | + wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk); |
263 | } |
264 | virtual ~Pointer() = default; |
265 | |
266 | @@ -875,6 +903,10 @@ |
267 | me->release(); |
268 | } |
269 | |
270 | + static void resource_destroyed_thunk(wl_resource* us) |
271 | + { |
272 | + delete static_cast<Pointer*>(wl_resource_get_user_data(us)); |
273 | + } |
274 | static struct wl_pointer_interface const vtable; |
275 | }; |
276 | |
277 | @@ -896,7 +928,7 @@ |
278 | wl_resource_post_no_memory(parent); |
279 | BOOST_THROW_EXCEPTION((std::bad_alloc{})); |
280 | } |
281 | - wl_resource_set_implementation(resource, &vtable, this, nullptr); |
282 | + wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk); |
283 | } |
284 | virtual ~Keyboard() = default; |
285 | |
286 | @@ -912,6 +944,10 @@ |
287 | me->release(); |
288 | } |
289 | |
290 | + static void resource_destroyed_thunk(wl_resource* us) |
291 | + { |
292 | + delete static_cast<Keyboard*>(wl_resource_get_user_data(us)); |
293 | + } |
294 | static struct wl_keyboard_interface const vtable; |
295 | }; |
296 | |
297 | @@ -932,7 +968,7 @@ |
298 | wl_resource_post_no_memory(parent); |
299 | BOOST_THROW_EXCEPTION((std::bad_alloc{})); |
300 | } |
301 | - wl_resource_set_implementation(resource, &vtable, this, nullptr); |
302 | + wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk); |
303 | } |
304 | virtual ~Touch() = default; |
305 | |
306 | @@ -948,6 +984,10 @@ |
307 | me->release(); |
308 | } |
309 | |
310 | + static void resource_destroyed_thunk(wl_resource* us) |
311 | + { |
312 | + delete static_cast<Touch*>(wl_resource_get_user_data(us)); |
313 | + } |
314 | static struct wl_touch_interface const vtable; |
315 | }; |
316 | |
317 | @@ -1014,7 +1054,7 @@ |
318 | wl_resource_post_no_memory(parent); |
319 | BOOST_THROW_EXCEPTION((std::bad_alloc{})); |
320 | } |
321 | - wl_resource_set_implementation(resource, &vtable, this, nullptr); |
322 | + wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk); |
323 | } |
324 | virtual ~Region() = default; |
325 | |
326 | @@ -1044,6 +1084,10 @@ |
327 | me->subtract(x, y, width, height); |
328 | } |
329 | |
330 | + static void resource_destroyed_thunk(wl_resource* us) |
331 | + { |
332 | + delete static_cast<Region*>(wl_resource_get_user_data(us)); |
333 | + } |
334 | static struct wl_region_interface const vtable; |
335 | }; |
336 | |
337 | @@ -1120,7 +1164,7 @@ |
338 | wl_resource_post_no_memory(parent); |
339 | BOOST_THROW_EXCEPTION((std::bad_alloc{})); |
340 | } |
341 | - wl_resource_set_implementation(resource, &vtable, this, nullptr); |
342 | + wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk); |
343 | } |
344 | virtual ~Subsurface() = default; |
345 | |
346 | @@ -1171,6 +1215,10 @@ |
347 | me->set_desync(); |
348 | } |
349 | |
350 | + static void resource_destroyed_thunk(wl_resource* us) |
351 | + { |
352 | + delete static_cast<Subsurface*>(wl_resource_get_user_data(us)); |
353 | + } |
354 | static struct wl_subsurface_interface const vtable; |
355 | }; |
356 | |
357 | |
358 | === modified file 'src/server/frontend/wayland/wayland_connector.cpp' |
359 | --- src/server/frontend/wayland/wayland_connector.cpp 2017-09-22 15:49:10 +0000 |
360 | +++ src/server/frontend/wayland/wayland_connector.cpp 2017-09-25 18:25:28 +0000 |
361 | @@ -41,6 +41,8 @@ |
362 | |
363 | #include "mir/executor.h" |
364 | |
365 | +#include "mir/client/event.h" |
366 | + |
367 | #include <system_error> |
368 | #include <sys/eventfd.h> |
369 | #include <wayland-server-core.h> |
370 | @@ -51,6 +53,7 @@ |
371 | #include <functional> |
372 | #include <type_traits> |
373 | |
374 | +#include <linux/input.h> |
375 | #include <algorithm> |
376 | #include <iostream> |
377 | #include <mir/log.h> |
378 | @@ -69,6 +72,7 @@ |
379 | namespace mc = mir::compositor; |
380 | namespace ms = mir::scene; |
381 | namespace geom = mir::geometry; |
382 | +namespace mcl = mir::client; |
383 | |
384 | namespace mir |
385 | { |
386 | @@ -559,7 +563,7 @@ |
387 | |
388 | void WlSurface::destroy() |
389 | { |
390 | - delete this; |
391 | + wl_resource_destroy(resource); |
392 | } |
393 | |
394 | void WlSurface::attach(std::experimental::optional<wl_resource*> const& buffer, int32_t x, int32_t y) |
395 | @@ -741,6 +745,19 @@ |
396 | class WlPointer; |
397 | class WlTouch; |
398 | |
399 | +template<typename Callable> |
400 | +auto run_unless(std::shared_ptr<bool> const& condition, Callable&& callable) |
401 | +{ |
402 | + return |
403 | + [callable = std::move(callable), condition]() |
404 | + { |
405 | + if (*condition) |
406 | + return; |
407 | + |
408 | + callable(); |
409 | + }; |
410 | +} |
411 | + |
412 | class WlKeyboard : public wayland::Keyboard |
413 | { |
414 | public: |
415 | @@ -748,16 +765,29 @@ |
416 | wl_client* client, |
417 | wl_resource* parent, |
418 | uint32_t id, |
419 | + std::function<void(WlKeyboard*)> const& on_destroy, |
420 | std::shared_ptr<mir::Executor> const& executor) |
421 | : Keyboard(client, parent, id), |
422 | - executor{executor} |
423 | - { |
424 | + executor{executor}, |
425 | + on_destroy{on_destroy}, |
426 | + destroyed{std::make_shared<bool>(false)} |
427 | + { |
428 | + } |
429 | + |
430 | + ~WlKeyboard() |
431 | + { |
432 | + on_destroy(this); |
433 | + *destroyed = true; |
434 | } |
435 | |
436 | void handle_event(MirInputEvent const* event, wl_resource* /*target*/) |
437 | { |
438 | - executor->spawn( |
439 | - [ev = mir_event_ref(mir_input_event_get_event(event)), this] () |
440 | + executor->spawn(run_unless( |
441 | + destroyed, |
442 | + [ |
443 | + ev = mcl::Event{mir_event_ref(mir_input_event_get_event(event))}, |
444 | + this |
445 | + ] () |
446 | { |
447 | int const serial = wl_display_next_serial(wl_client_get_display(client)); |
448 | auto event = mir_event_get_input_event(ev); |
449 | @@ -782,18 +812,22 @@ |
450 | default: |
451 | break; |
452 | } |
453 | - mir_event_unref(ev); |
454 | - }); |
455 | + })); |
456 | } |
457 | |
458 | void handle_event(MirWindowEvent const* event, wl_resource* target) |
459 | { |
460 | if (mir_window_event_get_attribute(event) == mir_window_attrib_focus) |
461 | { |
462 | - executor->spawn( |
463 | - [resource = resource, serial = wl_display_next_serial(wl_client_get_display(client)), |
464 | - target = target, focussed = mir_window_event_get_attribute_value(event)]() |
465 | + executor->spawn(run_unless( |
466 | + destroyed, |
467 | + [ |
468 | + target = target, |
469 | + focussed = mir_window_event_get_attribute_value(event), |
470 | + this |
471 | + ]() |
472 | { |
473 | + auto const serial = wl_display_next_serial(wl_client_get_display(client)); |
474 | if (focussed) |
475 | { |
476 | wl_array key_state; |
477 | @@ -805,18 +839,21 @@ |
478 | { |
479 | wl_keyboard_send_leave(resource, serial, target); |
480 | } |
481 | - }); |
482 | + })); |
483 | } |
484 | } |
485 | |
486 | private: |
487 | std::shared_ptr<mir::Executor> const executor; |
488 | + std::function<void(WlKeyboard*)> on_destroy; |
489 | + std::shared_ptr<bool> const destroyed; |
490 | |
491 | void release() override; |
492 | }; |
493 | |
494 | void WlKeyboard::release() |
495 | { |
496 | + wl_resource_destroy(resource); |
497 | } |
498 | |
499 | class WlPointer : public wayland::Pointer |
500 | @@ -827,17 +864,27 @@ |
501 | wl_client* client, |
502 | wl_resource* parent, |
503 | uint32_t id, |
504 | + std::function<void(WlPointer*)> const& on_destroy, |
505 | std::shared_ptr<mir::Executor> const& executor) |
506 | : Pointer(client, parent, id), |
507 | display{wl_client_get_display(client)}, |
508 | - executor{executor} |
509 | - { |
510 | + executor{executor}, |
511 | + on_destroy{on_destroy}, |
512 | + destroyed{std::make_shared<bool>(false)} |
513 | + { |
514 | + } |
515 | + |
516 | + ~WlPointer() |
517 | + { |
518 | + on_destroy(this); |
519 | + *destroyed = true; |
520 | } |
521 | |
522 | void handle_event(MirInputEvent const* event, wl_resource* target) |
523 | { |
524 | - executor->spawn( |
525 | - [ev = mir_event_ref(mir_input_event_get_event(event)), target, this]() |
526 | + executor->spawn(run_unless( |
527 | + destroyed, |
528 | + [ev = mcl::Event{mir_input_event_get_event(event)}, target, this]() |
529 | { |
530 | auto const serial = wl_display_next_serial(display); |
531 | auto const event = mir_event_get_input_event(ev); |
532 | @@ -851,25 +898,27 @@ |
533 | auto const current_set = mir_pointer_event_buttons(pointer_event); |
534 | auto const current_time = mir_input_event_get_event_time(event) / 1000; |
535 | |
536 | - auto button = 272; // No, I have *no* idea why GTK expects 272 to be the primary button. |
537 | - // NB button is incremented in the loop and the order mir_pointer_button_XXX matters |
538 | - for (auto mir_button : |
539 | - {mir_pointer_button_primary, // 272 |
540 | - mir_pointer_button_tertiary, // 273 |
541 | - mir_pointer_button_secondary, // 274 |
542 | - mir_pointer_button_back, // 275 |
543 | - mir_pointer_button_forward}) // 276 |
544 | + std::unordered_map<MirPointerButton, int> const button_mappings = { |
545 | + {mir_pointer_button_primary, BTN_LEFT}, |
546 | + {mir_pointer_button_secondary, BTN_RIGHT}, |
547 | + {mir_pointer_button_tertiary, BTN_MIDDLE}, |
548 | + {mir_pointer_button_back, BTN_BACK}, |
549 | + {mir_pointer_button_forward, BTN_FORWARD}, |
550 | + {mir_pointer_button_side, BTN_SIDE}, |
551 | + {mir_pointer_button_task, BTN_TASK}, |
552 | + {mir_pointer_button_extra, BTN_EXTRA} |
553 | + }; |
554 | + |
555 | + for (auto mapping : button_mappings) |
556 | { |
557 | - if (mir_button & (current_set ^ last_set)) |
558 | + if (mapping.first & (current_set ^ last_set)) |
559 | { |
560 | - auto const action = (mir_button & current_set) ? |
561 | + auto const action = (mapping.first & current_set) ? |
562 | WL_POINTER_BUTTON_STATE_PRESSED : |
563 | WL_POINTER_BUTTON_STATE_RELEASED; |
564 | |
565 | - wl_pointer_send_button(resource, serial, current_time, button, action); |
566 | + wl_pointer_send_button(resource, serial, current_time, mapping.second, action); |
567 | } |
568 | - |
569 | - ++button; |
570 | } |
571 | |
572 | last_set = current_set; |
573 | @@ -934,7 +983,7 @@ |
574 | case mir_pointer_actions: |
575 | break; |
576 | } |
577 | - }); |
578 | + })); |
579 | } |
580 | |
581 | // Pointer interface |
582 | @@ -942,6 +991,9 @@ |
583 | wl_display* const display; |
584 | std::shared_ptr<mir::Executor> const executor; |
585 | |
586 | + std::function<void(WlPointer*)> on_destroy; |
587 | + std::shared_ptr<bool> const destroyed; |
588 | + |
589 | MirPointerButtons last_set{0}; |
590 | float last_x, last_y, last_vscroll, last_hscroll; |
591 | |
592 | @@ -959,7 +1011,7 @@ |
593 | |
594 | void WlPointer::release() |
595 | { |
596 | - delete this; |
597 | + wl_resource_destroy(resource); |
598 | } |
599 | |
600 | class WlTouch : public wayland::Touch |
601 | @@ -969,9 +1021,18 @@ |
602 | wl_client* client, |
603 | wl_resource* parent, |
604 | uint32_t id, |
605 | - std::shared_ptr<mir::Executor> const& /*executor*/) |
606 | - : Touch(client, parent, id) |
607 | - { |
608 | + std::function<void(WlTouch*)> const& on_destroy, |
609 | + std::shared_ptr<mir::Executor> const& executor) |
610 | + : Touch(client, parent, id), |
611 | + executor{executor}, |
612 | + on_destroy{on_destroy} |
613 | + { |
614 | + } |
615 | + |
616 | + ~WlTouch() |
617 | + { |
618 | + on_destroy(this); |
619 | + *destroyed = true; |
620 | } |
621 | |
622 | void handle_event(MirInputEvent const* /*event*/, wl_resource* /*target*/) |
623 | @@ -980,11 +1041,16 @@ |
624 | |
625 | // Touch interface |
626 | private: |
627 | + std::shared_ptr<mir::Executor> const executor; |
628 | + std::function<void(WlTouch*)> on_destroy; |
629 | + std::shared_ptr<bool> const destroyed; |
630 | + |
631 | void release() override; |
632 | }; |
633 | |
634 | void WlTouch::release() |
635 | { |
636 | + wl_resource_destroy(resource); |
637 | } |
638 | |
639 | template<class InputInterface> |
640 | @@ -997,25 +1063,27 @@ |
641 | InputCtx(InputCtx const&) = delete; |
642 | InputCtx& operator=(InputCtx const&) = delete; |
643 | |
644 | - void register_listener(std::shared_ptr<InputInterface> const& listener) |
645 | + void register_listener(InputInterface* listener) |
646 | { |
647 | + std::lock_guard<std::mutex> lock{mutex}; |
648 | listeners.push_back(listener); |
649 | } |
650 | |
651 | void unregister_listener(InputInterface const* listener) |
652 | { |
653 | - std::remove_if( |
654 | - listeners.begin(), |
655 | - listeners.end(), |
656 | - [listener](auto candidate) |
657 | - { |
658 | - return candidate.get() == listener; |
659 | - }); |
660 | + std::lock_guard<std::mutex> lock{mutex}; |
661 | + listeners.erase( |
662 | + std::remove( |
663 | + listeners.begin(), |
664 | + listeners.end(), |
665 | + listener), |
666 | + listeners.end()); |
667 | } |
668 | |
669 | void handle_event(MirInputEvent const* event, wl_resource* target) const |
670 | { |
671 | - for (auto& listener : listeners) |
672 | + std::lock_guard<std::mutex> lock{mutex}; |
673 | + for (auto listener : listeners) |
674 | { |
675 | listener->handle_event(event, target); |
676 | } |
677 | @@ -1023,6 +1091,7 @@ |
678 | |
679 | void handle_event(MirWindowEvent const* event, wl_resource* target) const |
680 | { |
681 | + std::lock_guard<std::mutex> lock{mutex}; |
682 | for (auto& listener : listeners) |
683 | { |
684 | listener->handle_event(event, target); |
685 | @@ -1030,7 +1099,8 @@ |
686 | } |
687 | |
688 | private: |
689 | - std::vector<std::shared_ptr<InputInterface>> listeners; |
690 | + std::mutex mutable mutex; |
691 | + std::vector<InputInterface*> listeners; |
692 | }; |
693 | |
694 | class WlSeat |
695 | @@ -1100,32 +1170,49 @@ |
696 | static void get_pointer(wl_client* client, wl_resource* resource, uint32_t id) |
697 | { |
698 | auto me = reinterpret_cast<WlSeat*>(wl_resource_get_user_data(resource)); |
699 | - me->pointer[client].register_listener( |
700 | - std::make_shared<WlPointer>( |
701 | + auto& input_ctx = me->pointer[client]; |
702 | + input_ctx.register_listener( |
703 | + new WlPointer{ |
704 | client, |
705 | resource, |
706 | id, |
707 | - me->executor)); |
708 | + [&input_ctx](WlPointer* listener) |
709 | + { |
710 | + input_ctx.unregister_listener(listener); |
711 | + }, |
712 | + me->executor}); |
713 | } |
714 | static void get_keyboard(wl_client* client, wl_resource* resource, uint32_t id) |
715 | { |
716 | auto me = reinterpret_cast<WlSeat*>(wl_resource_get_user_data(resource)); |
717 | - me->keyboard[client].register_listener( |
718 | - std::make_shared<WlKeyboard>( |
719 | + auto& input_ctx = me->keyboard[client]; |
720 | + |
721 | + input_ctx.register_listener( |
722 | + new WlKeyboard{ |
723 | client, |
724 | resource, |
725 | id, |
726 | - me->executor)); |
727 | + [&input_ctx](WlKeyboard* listener) |
728 | + { |
729 | + input_ctx.unregister_listener(listener); |
730 | + }, |
731 | + me->executor}); |
732 | } |
733 | static void get_touch(wl_client* client, wl_resource* resource, uint32_t id) |
734 | { |
735 | auto me = reinterpret_cast<WlSeat*>(wl_resource_get_user_data(resource)); |
736 | - me->touch[client].register_listener( |
737 | - std::make_shared<WlTouch>( |
738 | + auto& input_ctx = me->touch[client]; |
739 | + |
740 | + input_ctx.register_listener( |
741 | + new WlTouch{ |
742 | client, |
743 | resource, |
744 | id, |
745 | - me->executor)); |
746 | + [&input_ctx](WlTouch* listener) |
747 | + { |
748 | + input_ctx.unregister_listener(listener); |
749 | + }, |
750 | + me->executor}); |
751 | } |
752 | static void release(struct wl_client* /*client*/, struct wl_resource* /*resource*/) {} |
753 |
FAILED: Continuous integration, rev:4276 /mir-jenkins. ubuntu. com/job/ mir-ci/ 3685/ /mir-jenkins. ubuntu. com/job/ build-mir/ 5052/console /mir-jenkins. ubuntu. com/job/ build-0- fetch/5288 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= artful/ 5276 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial/ 5276 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= zesty/5276 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= artful/ 5096/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= zesty/5096/ console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= mesa,release= artful/ 5096/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial/ 5096/console
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
ABORTED: https:/
ABORTED: https:/
ABORTED: https:/
FAILURE: https:/
Click here to trigger a rebuild: /mir-jenkins. ubuntu. com/job/ mir-ci/ 3685/rebuild
https:/