Mir

Merge lp:~raof/mir/wayland-input-fixes into lp:mir

Proposed by Chris Halse Rogers on 2017-09-25
Status: Merged
Merge reported by: Alan Griffiths
Merged at revision: not available
Proposed branch: lp:~raof/mir/wayland-input-fixes
Merge into: lp:mir
Prerequisite: lp:~raof/mir/add-mirclientcpp-event
Diff against target: 680 lines (+210/-65)
4 files modified
debian/control (+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 (+138/-52)
To merge this branch: bzr merge lp:~raof/mir/wayland-input-fixes
Reviewer Review Type Date Requested Status
Mir CI Bot continuous-integration 2017-09-25 Needs Fixing on 2017-09-26
Alan Griffiths 2017-09-25 Approve on 2017-09-26
Review via email: mp+331282@code.launchpad.net

Commit message

Wayland: Fix lifetimes of wrapper objects.

This prevents client disconnects/reconnects from crashing the server, which is good.

Fixes: https://bugs.launchpad.net/mir/+bug/1718677

To post a comment you must log in.
Alan Griffiths (alan-griffiths) wrote :

It would be nice to call Shell::close_session() when the client disconnects.

Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:4276
https://mir-jenkins.ubuntu.com/job/mir-ci/3687/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/5055/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/5291
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/5279
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/5279
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/5279
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/5099
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/5099/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/5099
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/5099/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/5099
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/5099/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/5099/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/5099
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/5099/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/5099
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/5099/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/5099
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/5099/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/5099/console

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/3687/rebuild

review: Needs Fixing (continuous-integration)
Alan Griffiths (alan-griffiths) wrote :

Works, a few comments inline.

review: Approve
Alan Griffiths (alan-griffiths) wrote :

> > + std::initializer_list<std::pair<MirPointerButton, int>> const button_mappings = {
>
> static std::pair<MirPointerButton, int> const button_mappings[] = {

Or, for clarity:

   static struct { MirPointerButton mir_button; int wl_button; } const button_mappings[] = {

etc

Mir CI Bot (mir-ci-bot) wrote :

PASSED: Continuous integration, rev:4277
https://mir-jenkins.ubuntu.com/job/mir-ci/3690/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/5059
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/5295
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/5283
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/5283
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/5283
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/5103
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/5103/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/5103
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/5103/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/5103
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/5103/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/5103
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/5103/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/5103
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/5103/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/5103
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/5103/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/5103
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/5103/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/5103
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/5103/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/3690/rebuild

review: Approve (continuous-integration)
Alan Griffiths (alan-griffiths) wrote :

Thanks

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-26 14:05:33 +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=== modified file 'src/protocol/wrapper_generator.cpp'
14--- src/protocol/wrapper_generator.cpp 2017-09-07 00:32:52 +0000
15+++ src/protocol/wrapper_generator.cpp 2017-09-26 14:05:33 +0000
16@@ -373,6 +373,16 @@
17
18 if (!methods.empty())
19 {
20+ if (!is_global)
21+ {
22+ emit_indented_lines(out, " ", {
23+ {"static void resource_destroyed_thunk(wl_resource* us)"},
24+ {"{"},
25+ {" delete static_cast<", generated_name, "*>(wl_resource_get_user_data(us));"},
26+ {"}"}
27+ });
28+ }
29+
30 emit_indented_lines(out, " ", {
31 { "static struct ", wl_name, "_interface const vtable;" }
32 });
33@@ -427,7 +437,7 @@
34 if (has_vtable)
35 {
36 emit_indented_lines(out, indent + " ",
37- {{ "wl_resource_set_implementation(resource, &vtable, this, nullptr);" }});
38+ {{ "wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);" }});
39 }
40 emit_indented_lines(out, indent, {
41 { "}" }
42
43=== modified file 'src/server/frontend/wayland/core_generated_interfaces.h'
44--- src/server/frontend/wayland/core_generated_interfaces.h 2017-09-07 00:33:43 +0000
45+++ src/server/frontend/wayland/core_generated_interfaces.h 2017-09-26 14:05:33 +0000
46@@ -108,7 +108,7 @@
47 wl_resource_post_no_memory(parent);
48 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
49 }
50- wl_resource_set_implementation(resource, &vtable, this, nullptr);
51+ wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
52 }
53 virtual ~ShmPool() = default;
54
55@@ -138,6 +138,10 @@
56 me->resize(size);
57 }
58
59+ static void resource_destroyed_thunk(wl_resource* us)
60+ {
61+ delete static_cast<ShmPool*>(wl_resource_get_user_data(us));
62+ }
63 static struct wl_shm_pool_interface const vtable;
64 };
65
66@@ -207,7 +211,7 @@
67 wl_resource_post_no_memory(parent);
68 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
69 }
70- wl_resource_set_implementation(resource, &vtable, this, nullptr);
71+ wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
72 }
73 virtual ~Buffer() = default;
74
75@@ -223,6 +227,10 @@
76 me->destroy();
77 }
78
79+ static void resource_destroyed_thunk(wl_resource* us)
80+ {
81+ delete static_cast<Buffer*>(wl_resource_get_user_data(us));
82+ }
83 static struct wl_buffer_interface const vtable;
84 };
85
86@@ -243,7 +251,7 @@
87 wl_resource_post_no_memory(parent);
88 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
89 }
90- wl_resource_set_implementation(resource, &vtable, this, nullptr);
91+ wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
92 }
93 virtual ~DataOffer() = default;
94
95@@ -293,6 +301,10 @@
96 me->set_actions(dnd_actions, preferred_action);
97 }
98
99+ static void resource_destroyed_thunk(wl_resource* us)
100+ {
101+ delete static_cast<DataOffer*>(wl_resource_get_user_data(us));
102+ }
103 static struct wl_data_offer_interface const vtable;
104 };
105
106@@ -317,7 +329,7 @@
107 wl_resource_post_no_memory(parent);
108 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
109 }
110- wl_resource_set_implementation(resource, &vtable, this, nullptr);
111+ wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
112 }
113 virtual ~DataSource() = default;
114
115@@ -347,6 +359,10 @@
116 me->set_actions(dnd_actions);
117 }
118
119+ static void resource_destroyed_thunk(wl_resource* us)
120+ {
121+ delete static_cast<DataSource*>(wl_resource_get_user_data(us));
122+ }
123 static struct wl_data_source_interface const vtable;
124 };
125
126@@ -369,7 +385,7 @@
127 wl_resource_post_no_memory(parent);
128 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
129 }
130- wl_resource_set_implementation(resource, &vtable, this, nullptr);
131+ wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
132 }
133 virtual ~DataDevice() = default;
134
135@@ -414,6 +430,10 @@
136 me->release();
137 }
138
139+ static void resource_destroyed_thunk(wl_resource* us)
140+ {
141+ delete static_cast<DataDevice*>(wl_resource_get_user_data(us));
142+ }
143 static struct wl_data_device_interface const vtable;
144 };
145
146@@ -536,7 +556,7 @@
147 wl_resource_post_no_memory(parent);
148 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
149 }
150- wl_resource_set_implementation(resource, &vtable, this, nullptr);
151+ wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
152 }
153 virtual ~ShellSurface() = default;
154
155@@ -625,6 +645,10 @@
156 me->set_class(class_);
157 }
158
159+ static void resource_destroyed_thunk(wl_resource* us)
160+ {
161+ delete static_cast<ShellSurface*>(wl_resource_get_user_data(us));
162+ }
163 static struct wl_shell_surface_interface const vtable;
164 };
165
166@@ -654,7 +678,7 @@
167 wl_resource_post_no_memory(parent);
168 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
169 }
170- wl_resource_set_implementation(resource, &vtable, this, nullptr);
171+ wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
172 }
173 virtual ~Surface() = default;
174
175@@ -748,6 +772,10 @@
176 me->damage_buffer(x, y, width, height);
177 }
178
179+ static void resource_destroyed_thunk(wl_resource* us)
180+ {
181+ delete static_cast<Surface*>(wl_resource_get_user_data(us));
182+ }
183 static struct wl_surface_interface const vtable;
184 };
185
186@@ -847,7 +875,7 @@
187 wl_resource_post_no_memory(parent);
188 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
189 }
190- wl_resource_set_implementation(resource, &vtable, this, nullptr);
191+ wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
192 }
193 virtual ~Pointer() = default;
194
195@@ -875,6 +903,10 @@
196 me->release();
197 }
198
199+ static void resource_destroyed_thunk(wl_resource* us)
200+ {
201+ delete static_cast<Pointer*>(wl_resource_get_user_data(us));
202+ }
203 static struct wl_pointer_interface const vtable;
204 };
205
206@@ -896,7 +928,7 @@
207 wl_resource_post_no_memory(parent);
208 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
209 }
210- wl_resource_set_implementation(resource, &vtable, this, nullptr);
211+ wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
212 }
213 virtual ~Keyboard() = default;
214
215@@ -912,6 +944,10 @@
216 me->release();
217 }
218
219+ static void resource_destroyed_thunk(wl_resource* us)
220+ {
221+ delete static_cast<Keyboard*>(wl_resource_get_user_data(us));
222+ }
223 static struct wl_keyboard_interface const vtable;
224 };
225
226@@ -932,7 +968,7 @@
227 wl_resource_post_no_memory(parent);
228 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
229 }
230- wl_resource_set_implementation(resource, &vtable, this, nullptr);
231+ wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
232 }
233 virtual ~Touch() = default;
234
235@@ -948,6 +984,10 @@
236 me->release();
237 }
238
239+ static void resource_destroyed_thunk(wl_resource* us)
240+ {
241+ delete static_cast<Touch*>(wl_resource_get_user_data(us));
242+ }
243 static struct wl_touch_interface const vtable;
244 };
245
246@@ -1014,7 +1054,7 @@
247 wl_resource_post_no_memory(parent);
248 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
249 }
250- wl_resource_set_implementation(resource, &vtable, this, nullptr);
251+ wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
252 }
253 virtual ~Region() = default;
254
255@@ -1044,6 +1084,10 @@
256 me->subtract(x, y, width, height);
257 }
258
259+ static void resource_destroyed_thunk(wl_resource* us)
260+ {
261+ delete static_cast<Region*>(wl_resource_get_user_data(us));
262+ }
263 static struct wl_region_interface const vtable;
264 };
265
266@@ -1120,7 +1164,7 @@
267 wl_resource_post_no_memory(parent);
268 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
269 }
270- wl_resource_set_implementation(resource, &vtable, this, nullptr);
271+ wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
272 }
273 virtual ~Subsurface() = default;
274
275@@ -1171,6 +1215,10 @@
276 me->set_desync();
277 }
278
279+ static void resource_destroyed_thunk(wl_resource* us)
280+ {
281+ delete static_cast<Subsurface*>(wl_resource_get_user_data(us));
282+ }
283 static struct wl_subsurface_interface const vtable;
284 };
285
286
287=== modified file 'src/server/frontend/wayland/wayland_connector.cpp'
288--- src/server/frontend/wayland/wayland_connector.cpp 2017-09-22 15:49:10 +0000
289+++ src/server/frontend/wayland/wayland_connector.cpp 2017-09-26 14:05:33 +0000
290@@ -41,6 +41,8 @@
291
292 #include "mir/executor.h"
293
294+#include "mir/client/event.h"
295+
296 #include <system_error>
297 #include <sys/eventfd.h>
298 #include <wayland-server-core.h>
299@@ -51,6 +53,7 @@
300 #include <functional>
301 #include <type_traits>
302
303+#include <linux/input.h>
304 #include <algorithm>
305 #include <iostream>
306 #include <mir/log.h>
307@@ -69,6 +72,7 @@
308 namespace mc = mir::compositor;
309 namespace ms = mir::scene;
310 namespace geom = mir::geometry;
311+namespace mcl = mir::client;
312
313 namespace mir
314 {
315@@ -559,7 +563,7 @@
316
317 void WlSurface::destroy()
318 {
319- delete this;
320+ wl_resource_destroy(resource);
321 }
322
323 void WlSurface::attach(std::experimental::optional<wl_resource*> const& buffer, int32_t x, int32_t y)
324@@ -741,6 +745,19 @@
325 class WlPointer;
326 class WlTouch;
327
328+template<typename Callable>
329+auto run_unless(std::shared_ptr<bool> const& condition, Callable&& callable)
330+{
331+ return
332+ [callable = std::move(callable), condition]()
333+ {
334+ if (*condition)
335+ return;
336+
337+ callable();
338+ };
339+}
340+
341 class WlKeyboard : public wayland::Keyboard
342 {
343 public:
344@@ -748,16 +765,29 @@
345 wl_client* client,
346 wl_resource* parent,
347 uint32_t id,
348+ std::function<void(WlKeyboard*)> const& on_destroy,
349 std::shared_ptr<mir::Executor> const& executor)
350 : Keyboard(client, parent, id),
351- executor{executor}
352- {
353+ executor{executor},
354+ on_destroy{on_destroy},
355+ destroyed{std::make_shared<bool>(false)}
356+ {
357+ }
358+
359+ ~WlKeyboard()
360+ {
361+ on_destroy(this);
362+ *destroyed = true;
363 }
364
365 void handle_event(MirInputEvent const* event, wl_resource* /*target*/)
366 {
367- executor->spawn(
368- [ev = mir_event_ref(mir_input_event_get_event(event)), this] ()
369+ executor->spawn(run_unless(
370+ destroyed,
371+ [
372+ ev = mcl::Event{mir_event_ref(mir_input_event_get_event(event))},
373+ this
374+ ] ()
375 {
376 int const serial = wl_display_next_serial(wl_client_get_display(client));
377 auto event = mir_event_get_input_event(ev);
378@@ -782,18 +812,22 @@
379 default:
380 break;
381 }
382- mir_event_unref(ev);
383- });
384+ }));
385 }
386
387 void handle_event(MirWindowEvent const* event, wl_resource* target)
388 {
389 if (mir_window_event_get_attribute(event) == mir_window_attrib_focus)
390 {
391- executor->spawn(
392- [resource = resource, serial = wl_display_next_serial(wl_client_get_display(client)),
393- target = target, focussed = mir_window_event_get_attribute_value(event)]()
394+ executor->spawn(run_unless(
395+ destroyed,
396+ [
397+ target = target,
398+ focussed = mir_window_event_get_attribute_value(event),
399+ this
400+ ]()
401 {
402+ auto const serial = wl_display_next_serial(wl_client_get_display(client));
403 if (focussed)
404 {
405 wl_array key_state;
406@@ -805,18 +839,21 @@
407 {
408 wl_keyboard_send_leave(resource, serial, target);
409 }
410- });
411+ }));
412 }
413 }
414
415 private:
416 std::shared_ptr<mir::Executor> const executor;
417+ std::function<void(WlKeyboard*)> on_destroy;
418+ std::shared_ptr<bool> const destroyed;
419
420 void release() override;
421 };
422
423 void WlKeyboard::release()
424 {
425+ wl_resource_destroy(resource);
426 }
427
428 class WlPointer : public wayland::Pointer
429@@ -827,17 +864,27 @@
430 wl_client* client,
431 wl_resource* parent,
432 uint32_t id,
433+ std::function<void(WlPointer*)> const& on_destroy,
434 std::shared_ptr<mir::Executor> const& executor)
435 : Pointer(client, parent, id),
436 display{wl_client_get_display(client)},
437- executor{executor}
438- {
439+ executor{executor},
440+ on_destroy{on_destroy},
441+ destroyed{std::make_shared<bool>(false)}
442+ {
443+ }
444+
445+ ~WlPointer()
446+ {
447+ on_destroy(this);
448+ *destroyed = true;
449 }
450
451 void handle_event(MirInputEvent const* event, wl_resource* target)
452 {
453- executor->spawn(
454- [ev = mir_event_ref(mir_input_event_get_event(event)), target, this]()
455+ executor->spawn(run_unless(
456+ destroyed,
457+ [ev = mcl::Event{mir_input_event_get_event(event)}, target, this]()
458 {
459 auto const serial = wl_display_next_serial(display);
460 auto const event = mir_event_get_input_event(ev);
461@@ -851,25 +898,26 @@
462 auto const current_set = mir_pointer_event_buttons(pointer_event);
463 auto const current_time = mir_input_event_get_event_time(event) / 1000;
464
465- auto button = 272; // No, I have *no* idea why GTK expects 272 to be the primary button.
466- // NB button is incremented in the loop and the order mir_pointer_button_XXX matters
467- for (auto mir_button :
468- {mir_pointer_button_primary, // 272
469- mir_pointer_button_tertiary, // 273
470- mir_pointer_button_secondary, // 274
471- mir_pointer_button_back, // 275
472- mir_pointer_button_forward}) // 276
473+ for (auto const& mapping :
474+ {
475+ std::make_pair(mir_pointer_button_primary, BTN_LEFT),
476+ std::make_pair(mir_pointer_button_secondary, BTN_RIGHT),
477+ std::make_pair(mir_pointer_button_tertiary, BTN_MIDDLE),
478+ std::make_pair(mir_pointer_button_back, BTN_BACK),
479+ std::make_pair(mir_pointer_button_forward, BTN_FORWARD),
480+ std::make_pair(mir_pointer_button_side, BTN_SIDE),
481+ std::make_pair(mir_pointer_button_task, BTN_TASK),
482+ std::make_pair(mir_pointer_button_extra, BTN_EXTRA)
483+ })
484 {
485- if (mir_button & (current_set ^ last_set))
486+ if (mapping.first & (current_set ^ last_set))
487 {
488- auto const action = (mir_button & current_set) ?
489+ auto const action = (mapping.first & current_set) ?
490 WL_POINTER_BUTTON_STATE_PRESSED :
491 WL_POINTER_BUTTON_STATE_RELEASED;
492
493- wl_pointer_send_button(resource, serial, current_time, button, action);
494+ wl_pointer_send_button(resource, serial, current_time, mapping.second, action);
495 }
496-
497- ++button;
498 }
499
500 last_set = current_set;
501@@ -934,7 +982,7 @@
502 case mir_pointer_actions:
503 break;
504 }
505- });
506+ }));
507 }
508
509 // Pointer interface
510@@ -942,6 +990,9 @@
511 wl_display* const display;
512 std::shared_ptr<mir::Executor> const executor;
513
514+ std::function<void(WlPointer*)> on_destroy;
515+ std::shared_ptr<bool> const destroyed;
516+
517 MirPointerButtons last_set{0};
518 float last_x, last_y, last_vscroll, last_hscroll;
519
520@@ -959,7 +1010,7 @@
521
522 void WlPointer::release()
523 {
524- delete this;
525+ wl_resource_destroy(resource);
526 }
527
528 class WlTouch : public wayland::Touch
529@@ -969,9 +1020,18 @@
530 wl_client* client,
531 wl_resource* parent,
532 uint32_t id,
533- std::shared_ptr<mir::Executor> const& /*executor*/)
534- : Touch(client, parent, id)
535- {
536+ std::function<void(WlTouch*)> const& on_destroy,
537+ std::shared_ptr<mir::Executor> const& executor)
538+ : Touch(client, parent, id),
539+ executor{executor},
540+ on_destroy{on_destroy}
541+ {
542+ }
543+
544+ ~WlTouch()
545+ {
546+ on_destroy(this);
547+ *destroyed = true;
548 }
549
550 void handle_event(MirInputEvent const* /*event*/, wl_resource* /*target*/)
551@@ -980,11 +1040,16 @@
552
553 // Touch interface
554 private:
555+ std::shared_ptr<mir::Executor> const executor;
556+ std::function<void(WlTouch*)> on_destroy;
557+ std::shared_ptr<bool> const destroyed;
558+
559 void release() override;
560 };
561
562 void WlTouch::release()
563 {
564+ wl_resource_destroy(resource);
565 }
566
567 template<class InputInterface>
568@@ -997,25 +1062,27 @@
569 InputCtx(InputCtx const&) = delete;
570 InputCtx& operator=(InputCtx const&) = delete;
571
572- void register_listener(std::shared_ptr<InputInterface> const& listener)
573+ void register_listener(InputInterface* listener)
574 {
575+ std::lock_guard<std::mutex> lock{mutex};
576 listeners.push_back(listener);
577 }
578
579 void unregister_listener(InputInterface const* listener)
580 {
581- std::remove_if(
582- listeners.begin(),
583- listeners.end(),
584- [listener](auto candidate)
585- {
586- return candidate.get() == listener;
587- });
588+ std::lock_guard<std::mutex> lock{mutex};
589+ listeners.erase(
590+ std::remove(
591+ listeners.begin(),
592+ listeners.end(),
593+ listener),
594+ listeners.end());
595 }
596
597 void handle_event(MirInputEvent const* event, wl_resource* target) const
598 {
599- for (auto& listener : listeners)
600+ std::lock_guard<std::mutex> lock{mutex};
601+ for (auto listener : listeners)
602 {
603 listener->handle_event(event, target);
604 }
605@@ -1023,6 +1090,7 @@
606
607 void handle_event(MirWindowEvent const* event, wl_resource* target) const
608 {
609+ std::lock_guard<std::mutex> lock{mutex};
610 for (auto& listener : listeners)
611 {
612 listener->handle_event(event, target);
613@@ -1030,7 +1098,8 @@
614 }
615
616 private:
617- std::vector<std::shared_ptr<InputInterface>> listeners;
618+ std::mutex mutable mutex;
619+ std::vector<InputInterface*> listeners;
620 };
621
622 class WlSeat
623@@ -1100,32 +1169,49 @@
624 static void get_pointer(wl_client* client, wl_resource* resource, uint32_t id)
625 {
626 auto me = reinterpret_cast<WlSeat*>(wl_resource_get_user_data(resource));
627- me->pointer[client].register_listener(
628- std::make_shared<WlPointer>(
629+ auto& input_ctx = me->pointer[client];
630+ input_ctx.register_listener(
631+ new WlPointer{
632 client,
633 resource,
634 id,
635- me->executor));
636+ [&input_ctx](WlPointer* listener)
637+ {
638+ input_ctx.unregister_listener(listener);
639+ },
640+ me->executor});
641 }
642 static void get_keyboard(wl_client* client, wl_resource* resource, uint32_t id)
643 {
644 auto me = reinterpret_cast<WlSeat*>(wl_resource_get_user_data(resource));
645- me->keyboard[client].register_listener(
646- std::make_shared<WlKeyboard>(
647+ auto& input_ctx = me->keyboard[client];
648+
649+ input_ctx.register_listener(
650+ new WlKeyboard{
651 client,
652 resource,
653 id,
654- me->executor));
655+ [&input_ctx](WlKeyboard* listener)
656+ {
657+ input_ctx.unregister_listener(listener);
658+ },
659+ me->executor});
660 }
661 static void get_touch(wl_client* client, wl_resource* resource, uint32_t id)
662 {
663 auto me = reinterpret_cast<WlSeat*>(wl_resource_get_user_data(resource));
664- me->touch[client].register_listener(
665- std::make_shared<WlTouch>(
666+ auto& input_ctx = me->touch[client];
667+
668+ input_ctx.register_listener(
669+ new WlTouch{
670 client,
671 resource,
672 id,
673- me->executor));
674+ [&input_ctx](WlTouch* listener)
675+ {
676+ input_ctx.unregister_listener(listener);
677+ },
678+ me->executor});
679 }
680 static void release(struct wl_client* /*client*/, struct wl_resource* /*resource*/) {}
681

Subscribers

People subscribed via source and target branches