Mir

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

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
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/reconnects from crashing the server, which is good.

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

Subscribers

People subscribed via source and target branches