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
=== modified file 'debian/control'
--- debian/control 2017-09-13 04:15:28 +0000
+++ debian/control 2017-09-25 18:25:28 +0000
@@ -47,6 +47,7 @@
47 capnproto,47 capnproto,
48 libepoxy-dev,48 libepoxy-dev,
49 python3-pil:native,49 python3-pil:native,
50 linux-libc-dev,
50Standards-Version: 3.9.451Standards-Version: 3.9.4
51Homepage: https://launchpad.net/mir52Homepage: https://launchpad.net/mir
52# If you aren't a member of ~mir-team but need to upload packaging changes,53# If you aren't a member of ~mir-team but need to upload packaging changes,
5354
=== added file 'include/client/mir/client/event.h'
--- include/client/mir/client/event.h 1970-01-01 00:00:00 +0000
+++ include/client/mir/client/event.h 2017-09-25 18:25:28 +0000
@@ -0,0 +1,54 @@
1/*
2 * Copyright © 2017 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 2 or 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
17 */
18
19#ifndef MIR_CLIENT_EVENT_H_
20#define MIR_CLIENT_EVENT_H_
21
22#include "mir_toolkit/events/event.h"
23
24#include <memory>
25
26namespace mir
27{
28namespace client
29{
30/// Handle class for MirEvent - provides automatic reference counting.
31class Event
32{
33public:
34 Event() = default;
35 explicit Event(MirEvent const* event) : self{mir_event_ref(event), deleter}
36 {
37 }
38
39 operator MirEvent const*() const { return self.get(); }
40
41 void reset() { self.reset(); }
42
43private:
44 static void deleter(MirEvent const* event) { mir_event_unref(event); }
45 std::shared_ptr<MirEvent const> self;
46};
47
48// Provide a deleted overload to avoid double release "accidents".
49void mir_event_unref(Event const& event) = delete;
50}
51}
52
53#endif //MIR_CLIENT_EVENT_H_
54
055
=== modified file 'src/client/CMakeLists.txt'
--- src/client/CMakeLists.txt 2017-08-29 14:23:50 +0000
+++ src/client/CMakeLists.txt 2017-09-25 18:25:28 +0000
@@ -118,6 +118,7 @@
118 ${CMAKE_SOURCE_DIR}/include/client/mir/client/connection.h118 ${CMAKE_SOURCE_DIR}/include/client/mir/client/connection.h
119 ${CMAKE_SOURCE_DIR}/include/client/mir/client/display_config.h119 ${CMAKE_SOURCE_DIR}/include/client/mir/client/display_config.h
120 ${CMAKE_SOURCE_DIR}/include/client/mir/client/window.h120 ${CMAKE_SOURCE_DIR}/include/client/mir/client/window.h
121 ${CMAKE_SOURCE_DIR}/include/client/mir/client/event.h
121)122)
122123
123# Ensure protobuf C++ headers have been produced before124# Ensure protobuf C++ headers have been produced before
124125
=== modified file 'src/protocol/wrapper_generator.cpp'
--- src/protocol/wrapper_generator.cpp 2017-09-07 00:32:52 +0000
+++ src/protocol/wrapper_generator.cpp 2017-09-25 18:25:28 +0000
@@ -373,6 +373,16 @@
373373
374 if (!methods.empty())374 if (!methods.empty())
375 {375 {
376 if (!is_global)
377 {
378 emit_indented_lines(out, " ", {
379 {"static void resource_destroyed_thunk(wl_resource* us)"},
380 {"{"},
381 {" delete static_cast<", generated_name, "*>(wl_resource_get_user_data(us));"},
382 {"}"}
383 });
384 }
385
376 emit_indented_lines(out, " ", {386 emit_indented_lines(out, " ", {
377 { "static struct ", wl_name, "_interface const vtable;" }387 { "static struct ", wl_name, "_interface const vtable;" }
378 });388 });
@@ -427,7 +437,7 @@
427 if (has_vtable)437 if (has_vtable)
428 {438 {
429 emit_indented_lines(out, indent + " ",439 emit_indented_lines(out, indent + " ",
430 {{ "wl_resource_set_implementation(resource, &vtable, this, nullptr);" }});440 {{ "wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);" }});
431 }441 }
432 emit_indented_lines(out, indent, {442 emit_indented_lines(out, indent, {
433 { "}" }443 { "}" }
434444
=== modified file 'src/server/frontend/wayland/core_generated_interfaces.h'
--- src/server/frontend/wayland/core_generated_interfaces.h 2017-09-07 00:33:43 +0000
+++ src/server/frontend/wayland/core_generated_interfaces.h 2017-09-25 18:25:28 +0000
@@ -108,7 +108,7 @@
108 wl_resource_post_no_memory(parent);108 wl_resource_post_no_memory(parent);
109 BOOST_THROW_EXCEPTION((std::bad_alloc{}));109 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
110 }110 }
111 wl_resource_set_implementation(resource, &vtable, this, nullptr);111 wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
112 }112 }
113 virtual ~ShmPool() = default;113 virtual ~ShmPool() = default;
114114
@@ -138,6 +138,10 @@
138 me->resize(size);138 me->resize(size);
139 }139 }
140140
141 static void resource_destroyed_thunk(wl_resource* us)
142 {
143 delete static_cast<ShmPool*>(wl_resource_get_user_data(us));
144 }
141 static struct wl_shm_pool_interface const vtable;145 static struct wl_shm_pool_interface const vtable;
142};146};
143147
@@ -207,7 +211,7 @@
207 wl_resource_post_no_memory(parent);211 wl_resource_post_no_memory(parent);
208 BOOST_THROW_EXCEPTION((std::bad_alloc{}));212 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
209 }213 }
210 wl_resource_set_implementation(resource, &vtable, this, nullptr);214 wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
211 }215 }
212 virtual ~Buffer() = default;216 virtual ~Buffer() = default;
213217
@@ -223,6 +227,10 @@
223 me->destroy();227 me->destroy();
224 }228 }
225229
230 static void resource_destroyed_thunk(wl_resource* us)
231 {
232 delete static_cast<Buffer*>(wl_resource_get_user_data(us));
233 }
226 static struct wl_buffer_interface const vtable;234 static struct wl_buffer_interface const vtable;
227};235};
228236
@@ -243,7 +251,7 @@
243 wl_resource_post_no_memory(parent);251 wl_resource_post_no_memory(parent);
244 BOOST_THROW_EXCEPTION((std::bad_alloc{}));252 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
245 }253 }
246 wl_resource_set_implementation(resource, &vtable, this, nullptr);254 wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
247 }255 }
248 virtual ~DataOffer() = default;256 virtual ~DataOffer() = default;
249257
@@ -293,6 +301,10 @@
293 me->set_actions(dnd_actions, preferred_action);301 me->set_actions(dnd_actions, preferred_action);
294 }302 }
295303
304 static void resource_destroyed_thunk(wl_resource* us)
305 {
306 delete static_cast<DataOffer*>(wl_resource_get_user_data(us));
307 }
296 static struct wl_data_offer_interface const vtable;308 static struct wl_data_offer_interface const vtable;
297};309};
298310
@@ -317,7 +329,7 @@
317 wl_resource_post_no_memory(parent);329 wl_resource_post_no_memory(parent);
318 BOOST_THROW_EXCEPTION((std::bad_alloc{}));330 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
319 }331 }
320 wl_resource_set_implementation(resource, &vtable, this, nullptr);332 wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
321 }333 }
322 virtual ~DataSource() = default;334 virtual ~DataSource() = default;
323335
@@ -347,6 +359,10 @@
347 me->set_actions(dnd_actions);359 me->set_actions(dnd_actions);
348 }360 }
349361
362 static void resource_destroyed_thunk(wl_resource* us)
363 {
364 delete static_cast<DataSource*>(wl_resource_get_user_data(us));
365 }
350 static struct wl_data_source_interface const vtable;366 static struct wl_data_source_interface const vtable;
351};367};
352368
@@ -369,7 +385,7 @@
369 wl_resource_post_no_memory(parent);385 wl_resource_post_no_memory(parent);
370 BOOST_THROW_EXCEPTION((std::bad_alloc{}));386 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
371 }387 }
372 wl_resource_set_implementation(resource, &vtable, this, nullptr);388 wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
373 }389 }
374 virtual ~DataDevice() = default;390 virtual ~DataDevice() = default;
375391
@@ -414,6 +430,10 @@
414 me->release();430 me->release();
415 }431 }
416432
433 static void resource_destroyed_thunk(wl_resource* us)
434 {
435 delete static_cast<DataDevice*>(wl_resource_get_user_data(us));
436 }
417 static struct wl_data_device_interface const vtable;437 static struct wl_data_device_interface const vtable;
418};438};
419439
@@ -536,7 +556,7 @@
536 wl_resource_post_no_memory(parent);556 wl_resource_post_no_memory(parent);
537 BOOST_THROW_EXCEPTION((std::bad_alloc{}));557 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
538 }558 }
539 wl_resource_set_implementation(resource, &vtable, this, nullptr);559 wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
540 }560 }
541 virtual ~ShellSurface() = default;561 virtual ~ShellSurface() = default;
542562
@@ -625,6 +645,10 @@
625 me->set_class(class_);645 me->set_class(class_);
626 }646 }
627647
648 static void resource_destroyed_thunk(wl_resource* us)
649 {
650 delete static_cast<ShellSurface*>(wl_resource_get_user_data(us));
651 }
628 static struct wl_shell_surface_interface const vtable;652 static struct wl_shell_surface_interface const vtable;
629};653};
630654
@@ -654,7 +678,7 @@
654 wl_resource_post_no_memory(parent);678 wl_resource_post_no_memory(parent);
655 BOOST_THROW_EXCEPTION((std::bad_alloc{}));679 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
656 }680 }
657 wl_resource_set_implementation(resource, &vtable, this, nullptr);681 wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
658 }682 }
659 virtual ~Surface() = default;683 virtual ~Surface() = default;
660684
@@ -748,6 +772,10 @@
748 me->damage_buffer(x, y, width, height);772 me->damage_buffer(x, y, width, height);
749 }773 }
750774
775 static void resource_destroyed_thunk(wl_resource* us)
776 {
777 delete static_cast<Surface*>(wl_resource_get_user_data(us));
778 }
751 static struct wl_surface_interface const vtable;779 static struct wl_surface_interface const vtable;
752};780};
753781
@@ -847,7 +875,7 @@
847 wl_resource_post_no_memory(parent);875 wl_resource_post_no_memory(parent);
848 BOOST_THROW_EXCEPTION((std::bad_alloc{}));876 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
849 }877 }
850 wl_resource_set_implementation(resource, &vtable, this, nullptr);878 wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
851 }879 }
852 virtual ~Pointer() = default;880 virtual ~Pointer() = default;
853881
@@ -875,6 +903,10 @@
875 me->release();903 me->release();
876 }904 }
877905
906 static void resource_destroyed_thunk(wl_resource* us)
907 {
908 delete static_cast<Pointer*>(wl_resource_get_user_data(us));
909 }
878 static struct wl_pointer_interface const vtable;910 static struct wl_pointer_interface const vtable;
879};911};
880912
@@ -896,7 +928,7 @@
896 wl_resource_post_no_memory(parent);928 wl_resource_post_no_memory(parent);
897 BOOST_THROW_EXCEPTION((std::bad_alloc{}));929 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
898 }930 }
899 wl_resource_set_implementation(resource, &vtable, this, nullptr);931 wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
900 }932 }
901 virtual ~Keyboard() = default;933 virtual ~Keyboard() = default;
902934
@@ -912,6 +944,10 @@
912 me->release();944 me->release();
913 }945 }
914946
947 static void resource_destroyed_thunk(wl_resource* us)
948 {
949 delete static_cast<Keyboard*>(wl_resource_get_user_data(us));
950 }
915 static struct wl_keyboard_interface const vtable;951 static struct wl_keyboard_interface const vtable;
916};952};
917953
@@ -932,7 +968,7 @@
932 wl_resource_post_no_memory(parent);968 wl_resource_post_no_memory(parent);
933 BOOST_THROW_EXCEPTION((std::bad_alloc{}));969 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
934 }970 }
935 wl_resource_set_implementation(resource, &vtable, this, nullptr);971 wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
936 }972 }
937 virtual ~Touch() = default;973 virtual ~Touch() = default;
938974
@@ -948,6 +984,10 @@
948 me->release();984 me->release();
949 }985 }
950986
987 static void resource_destroyed_thunk(wl_resource* us)
988 {
989 delete static_cast<Touch*>(wl_resource_get_user_data(us));
990 }
951 static struct wl_touch_interface const vtable;991 static struct wl_touch_interface const vtable;
952};992};
953993
@@ -1014,7 +1054,7 @@
1014 wl_resource_post_no_memory(parent);1054 wl_resource_post_no_memory(parent);
1015 BOOST_THROW_EXCEPTION((std::bad_alloc{}));1055 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
1016 }1056 }
1017 wl_resource_set_implementation(resource, &vtable, this, nullptr);1057 wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
1018 }1058 }
1019 virtual ~Region() = default;1059 virtual ~Region() = default;
10201060
@@ -1044,6 +1084,10 @@
1044 me->subtract(x, y, width, height);1084 me->subtract(x, y, width, height);
1045 }1085 }
10461086
1087 static void resource_destroyed_thunk(wl_resource* us)
1088 {
1089 delete static_cast<Region*>(wl_resource_get_user_data(us));
1090 }
1047 static struct wl_region_interface const vtable;1091 static struct wl_region_interface const vtable;
1048};1092};
10491093
@@ -1120,7 +1164,7 @@
1120 wl_resource_post_no_memory(parent);1164 wl_resource_post_no_memory(parent);
1121 BOOST_THROW_EXCEPTION((std::bad_alloc{}));1165 BOOST_THROW_EXCEPTION((std::bad_alloc{}));
1122 }1166 }
1123 wl_resource_set_implementation(resource, &vtable, this, nullptr);1167 wl_resource_set_implementation(resource, &vtable, this, &resource_destroyed_thunk);
1124 }1168 }
1125 virtual ~Subsurface() = default;1169 virtual ~Subsurface() = default;
11261170
@@ -1171,6 +1215,10 @@
1171 me->set_desync();1215 me->set_desync();
1172 }1216 }
11731217
1218 static void resource_destroyed_thunk(wl_resource* us)
1219 {
1220 delete static_cast<Subsurface*>(wl_resource_get_user_data(us));
1221 }
1174 static struct wl_subsurface_interface const vtable;1222 static struct wl_subsurface_interface const vtable;
1175};1223};
11761224
11771225
=== modified file 'src/server/frontend/wayland/wayland_connector.cpp'
--- src/server/frontend/wayland/wayland_connector.cpp 2017-09-22 15:49:10 +0000
+++ src/server/frontend/wayland/wayland_connector.cpp 2017-09-25 18:25:28 +0000
@@ -41,6 +41,8 @@
4141
42#include "mir/executor.h"42#include "mir/executor.h"
4343
44#include "mir/client/event.h"
45
44#include <system_error>46#include <system_error>
45#include <sys/eventfd.h>47#include <sys/eventfd.h>
46#include <wayland-server-core.h>48#include <wayland-server-core.h>
@@ -51,6 +53,7 @@
51#include <functional>53#include <functional>
52#include <type_traits>54#include <type_traits>
5355
56#include <linux/input.h>
54#include <algorithm>57#include <algorithm>
55#include <iostream>58#include <iostream>
56#include <mir/log.h>59#include <mir/log.h>
@@ -69,6 +72,7 @@
69namespace mc = mir::compositor;72namespace mc = mir::compositor;
70namespace ms = mir::scene;73namespace ms = mir::scene;
71namespace geom = mir::geometry;74namespace geom = mir::geometry;
75namespace mcl = mir::client;
7276
73namespace mir77namespace mir
74{78{
@@ -559,7 +563,7 @@
559563
560void WlSurface::destroy()564void WlSurface::destroy()
561{565{
562 delete this;566 wl_resource_destroy(resource);
563}567}
564568
565void WlSurface::attach(std::experimental::optional<wl_resource*> const& buffer, int32_t x, int32_t y)569void WlSurface::attach(std::experimental::optional<wl_resource*> const& buffer, int32_t x, int32_t y)
@@ -741,6 +745,19 @@
741class WlPointer;745class WlPointer;
742class WlTouch;746class WlTouch;
743747
748template<typename Callable>
749auto run_unless(std::shared_ptr<bool> const& condition, Callable&& callable)
750{
751 return
752 [callable = std::move(callable), condition]()
753 {
754 if (*condition)
755 return;
756
757 callable();
758 };
759}
760
744class WlKeyboard : public wayland::Keyboard761class WlKeyboard : public wayland::Keyboard
745{762{
746public:763public:
@@ -748,16 +765,29 @@
748 wl_client* client,765 wl_client* client,
749 wl_resource* parent,766 wl_resource* parent,
750 uint32_t id,767 uint32_t id,
768 std::function<void(WlKeyboard*)> const& on_destroy,
751 std::shared_ptr<mir::Executor> const& executor)769 std::shared_ptr<mir::Executor> const& executor)
752 : Keyboard(client, parent, id),770 : Keyboard(client, parent, id),
753 executor{executor}771 executor{executor},
754 {772 on_destroy{on_destroy},
773 destroyed{std::make_shared<bool>(false)}
774 {
775 }
776
777 ~WlKeyboard()
778 {
779 on_destroy(this);
780 *destroyed = true;
755 }781 }
756782
757 void handle_event(MirInputEvent const* event, wl_resource* /*target*/)783 void handle_event(MirInputEvent const* event, wl_resource* /*target*/)
758 {784 {
759 executor->spawn(785 executor->spawn(run_unless(
760 [ev = mir_event_ref(mir_input_event_get_event(event)), this] ()786 destroyed,
787 [
788 ev = mcl::Event{mir_event_ref(mir_input_event_get_event(event))},
789 this
790 ] ()
761 {791 {
762 int const serial = wl_display_next_serial(wl_client_get_display(client));792 int const serial = wl_display_next_serial(wl_client_get_display(client));
763 auto event = mir_event_get_input_event(ev);793 auto event = mir_event_get_input_event(ev);
@@ -782,18 +812,22 @@
782 default:812 default:
783 break;813 break;
784 }814 }
785 mir_event_unref(ev);815 }));
786 });
787 }816 }
788817
789 void handle_event(MirWindowEvent const* event, wl_resource* target)818 void handle_event(MirWindowEvent const* event, wl_resource* target)
790 {819 {
791 if (mir_window_event_get_attribute(event) == mir_window_attrib_focus)820 if (mir_window_event_get_attribute(event) == mir_window_attrib_focus)
792 {821 {
793 executor->spawn(822 executor->spawn(run_unless(
794 [resource = resource, serial = wl_display_next_serial(wl_client_get_display(client)),823 destroyed,
795 target = target, focussed = mir_window_event_get_attribute_value(event)]()824 [
825 target = target,
826 focussed = mir_window_event_get_attribute_value(event),
827 this
828 ]()
796 {829 {
830 auto const serial = wl_display_next_serial(wl_client_get_display(client));
797 if (focussed)831 if (focussed)
798 {832 {
799 wl_array key_state;833 wl_array key_state;
@@ -805,18 +839,21 @@
805 {839 {
806 wl_keyboard_send_leave(resource, serial, target);840 wl_keyboard_send_leave(resource, serial, target);
807 }841 }
808 });842 }));
809 }843 }
810 }844 }
811845
812private:846private:
813 std::shared_ptr<mir::Executor> const executor;847 std::shared_ptr<mir::Executor> const executor;
848 std::function<void(WlKeyboard*)> on_destroy;
849 std::shared_ptr<bool> const destroyed;
814850
815 void release() override;851 void release() override;
816};852};
817853
818void WlKeyboard::release()854void WlKeyboard::release()
819{855{
856 wl_resource_destroy(resource);
820}857}
821858
822class WlPointer : public wayland::Pointer859class WlPointer : public wayland::Pointer
@@ -827,17 +864,27 @@
827 wl_client* client,864 wl_client* client,
828 wl_resource* parent,865 wl_resource* parent,
829 uint32_t id,866 uint32_t id,
867 std::function<void(WlPointer*)> const& on_destroy,
830 std::shared_ptr<mir::Executor> const& executor)868 std::shared_ptr<mir::Executor> const& executor)
831 : Pointer(client, parent, id),869 : Pointer(client, parent, id),
832 display{wl_client_get_display(client)},870 display{wl_client_get_display(client)},
833 executor{executor}871 executor{executor},
834 {872 on_destroy{on_destroy},
873 destroyed{std::make_shared<bool>(false)}
874 {
875 }
876
877 ~WlPointer()
878 {
879 on_destroy(this);
880 *destroyed = true;
835 }881 }
836882
837 void handle_event(MirInputEvent const* event, wl_resource* target)883 void handle_event(MirInputEvent const* event, wl_resource* target)
838 {884 {
839 executor->spawn(885 executor->spawn(run_unless(
840 [ev = mir_event_ref(mir_input_event_get_event(event)), target, this]()886 destroyed,
887 [ev = mcl::Event{mir_input_event_get_event(event)}, target, this]()
841 {888 {
842 auto const serial = wl_display_next_serial(display);889 auto const serial = wl_display_next_serial(display);
843 auto const event = mir_event_get_input_event(ev);890 auto const event = mir_event_get_input_event(ev);
@@ -851,25 +898,27 @@
851 auto const current_set = mir_pointer_event_buttons(pointer_event);898 auto const current_set = mir_pointer_event_buttons(pointer_event);
852 auto const current_time = mir_input_event_get_event_time(event) / 1000;899 auto const current_time = mir_input_event_get_event_time(event) / 1000;
853900
854 auto button = 272; // No, I have *no* idea why GTK expects 272 to be the primary button.901 std::unordered_map<MirPointerButton, int> const button_mappings = {
855 // NB button is incremented in the loop and the order mir_pointer_button_XXX matters902 {mir_pointer_button_primary, BTN_LEFT},
856 for (auto mir_button :903 {mir_pointer_button_secondary, BTN_RIGHT},
857 {mir_pointer_button_primary, // 272904 {mir_pointer_button_tertiary, BTN_MIDDLE},
858 mir_pointer_button_tertiary, // 273905 {mir_pointer_button_back, BTN_BACK},
859 mir_pointer_button_secondary, // 274906 {mir_pointer_button_forward, BTN_FORWARD},
860 mir_pointer_button_back, // 275907 {mir_pointer_button_side, BTN_SIDE},
861 mir_pointer_button_forward}) // 276908 {mir_pointer_button_task, BTN_TASK},
909 {mir_pointer_button_extra, BTN_EXTRA}
910 };
911
912 for (auto mapping : button_mappings)
862 {913 {
863 if (mir_button & (current_set ^ last_set))914 if (mapping.first & (current_set ^ last_set))
864 {915 {
865 auto const action = (mir_button & current_set) ?916 auto const action = (mapping.first & current_set) ?
866 WL_POINTER_BUTTON_STATE_PRESSED :917 WL_POINTER_BUTTON_STATE_PRESSED :
867 WL_POINTER_BUTTON_STATE_RELEASED;918 WL_POINTER_BUTTON_STATE_RELEASED;
868919
869 wl_pointer_send_button(resource, serial, current_time, button, action);920 wl_pointer_send_button(resource, serial, current_time, mapping.second, action);
870 }921 }
871
872 ++button;
873 }922 }
874923
875 last_set = current_set;924 last_set = current_set;
@@ -934,7 +983,7 @@
934 case mir_pointer_actions:983 case mir_pointer_actions:
935 break;984 break;
936 }985 }
937 });986 }));
938 }987 }
939988
940 // Pointer interface989 // Pointer interface
@@ -942,6 +991,9 @@
942 wl_display* const display;991 wl_display* const display;
943 std::shared_ptr<mir::Executor> const executor;992 std::shared_ptr<mir::Executor> const executor;
944993
994 std::function<void(WlPointer*)> on_destroy;
995 std::shared_ptr<bool> const destroyed;
996
945 MirPointerButtons last_set{0};997 MirPointerButtons last_set{0};
946 float last_x, last_y, last_vscroll, last_hscroll;998 float last_x, last_y, last_vscroll, last_hscroll;
947999
@@ -959,7 +1011,7 @@
9591011
960void WlPointer::release()1012void WlPointer::release()
961{1013{
962 delete this;1014 wl_resource_destroy(resource);
963}1015}
9641016
965class WlTouch : public wayland::Touch1017class WlTouch : public wayland::Touch
@@ -969,9 +1021,18 @@
969 wl_client* client,1021 wl_client* client,
970 wl_resource* parent,1022 wl_resource* parent,
971 uint32_t id,1023 uint32_t id,
972 std::shared_ptr<mir::Executor> const& /*executor*/)1024 std::function<void(WlTouch*)> const& on_destroy,
973 : Touch(client, parent, id)1025 std::shared_ptr<mir::Executor> const& executor)
974 {1026 : Touch(client, parent, id),
1027 executor{executor},
1028 on_destroy{on_destroy}
1029 {
1030 }
1031
1032 ~WlTouch()
1033 {
1034 on_destroy(this);
1035 *destroyed = true;
975 }1036 }
9761037
977 void handle_event(MirInputEvent const* /*event*/, wl_resource* /*target*/)1038 void handle_event(MirInputEvent const* /*event*/, wl_resource* /*target*/)
@@ -980,11 +1041,16 @@
9801041
981 // Touch interface1042 // Touch interface
982private:1043private:
1044 std::shared_ptr<mir::Executor> const executor;
1045 std::function<void(WlTouch*)> on_destroy;
1046 std::shared_ptr<bool> const destroyed;
1047
983 void release() override;1048 void release() override;
984};1049};
9851050
986void WlTouch::release()1051void WlTouch::release()
987{1052{
1053 wl_resource_destroy(resource);
988}1054}
9891055
990template<class InputInterface>1056template<class InputInterface>
@@ -997,25 +1063,27 @@
997 InputCtx(InputCtx const&) = delete;1063 InputCtx(InputCtx const&) = delete;
998 InputCtx& operator=(InputCtx const&) = delete;1064 InputCtx& operator=(InputCtx const&) = delete;
9991065
1000 void register_listener(std::shared_ptr<InputInterface> const& listener)1066 void register_listener(InputInterface* listener)
1001 {1067 {
1068 std::lock_guard<std::mutex> lock{mutex};
1002 listeners.push_back(listener);1069 listeners.push_back(listener);
1003 }1070 }
10041071
1005 void unregister_listener(InputInterface const* listener)1072 void unregister_listener(InputInterface const* listener)
1006 {1073 {
1007 std::remove_if(1074 std::lock_guard<std::mutex> lock{mutex};
1008 listeners.begin(),1075 listeners.erase(
1009 listeners.end(),1076 std::remove(
1010 [listener](auto candidate)1077 listeners.begin(),
1011 {1078 listeners.end(),
1012 return candidate.get() == listener;1079 listener),
1013 });1080 listeners.end());
1014 }1081 }
10151082
1016 void handle_event(MirInputEvent const* event, wl_resource* target) const1083 void handle_event(MirInputEvent const* event, wl_resource* target) const
1017 {1084 {
1018 for (auto& listener : listeners)1085 std::lock_guard<std::mutex> lock{mutex};
1086 for (auto listener : listeners)
1019 {1087 {
1020 listener->handle_event(event, target);1088 listener->handle_event(event, target);
1021 }1089 }
@@ -1023,6 +1091,7 @@
10231091
1024 void handle_event(MirWindowEvent const* event, wl_resource* target) const1092 void handle_event(MirWindowEvent const* event, wl_resource* target) const
1025 {1093 {
1094 std::lock_guard<std::mutex> lock{mutex};
1026 for (auto& listener : listeners)1095 for (auto& listener : listeners)
1027 {1096 {
1028 listener->handle_event(event, target);1097 listener->handle_event(event, target);
@@ -1030,7 +1099,8 @@
1030 }1099 }
10311100
1032private:1101private:
1033 std::vector<std::shared_ptr<InputInterface>> listeners;1102 std::mutex mutable mutex;
1103 std::vector<InputInterface*> listeners;
1034};1104};
10351105
1036class WlSeat1106class WlSeat
@@ -1100,32 +1170,49 @@
1100 static void get_pointer(wl_client* client, wl_resource* resource, uint32_t id)1170 static void get_pointer(wl_client* client, wl_resource* resource, uint32_t id)
1101 {1171 {
1102 auto me = reinterpret_cast<WlSeat*>(wl_resource_get_user_data(resource));1172 auto me = reinterpret_cast<WlSeat*>(wl_resource_get_user_data(resource));
1103 me->pointer[client].register_listener(1173 auto& input_ctx = me->pointer[client];
1104 std::make_shared<WlPointer>(1174 input_ctx.register_listener(
1175 new WlPointer{
1105 client,1176 client,
1106 resource,1177 resource,
1107 id,1178 id,
1108 me->executor));1179 [&input_ctx](WlPointer* listener)
1180 {
1181 input_ctx.unregister_listener(listener);
1182 },
1183 me->executor});
1109 }1184 }
1110 static void get_keyboard(wl_client* client, wl_resource* resource, uint32_t id)1185 static void get_keyboard(wl_client* client, wl_resource* resource, uint32_t id)
1111 {1186 {
1112 auto me = reinterpret_cast<WlSeat*>(wl_resource_get_user_data(resource));1187 auto me = reinterpret_cast<WlSeat*>(wl_resource_get_user_data(resource));
1113 me->keyboard[client].register_listener(1188 auto& input_ctx = me->keyboard[client];
1114 std::make_shared<WlKeyboard>(1189
1190 input_ctx.register_listener(
1191 new WlKeyboard{
1115 client,1192 client,
1116 resource,1193 resource,
1117 id,1194 id,
1118 me->executor));1195 [&input_ctx](WlKeyboard* listener)
1196 {
1197 input_ctx.unregister_listener(listener);
1198 },
1199 me->executor});
1119 }1200 }
1120 static void get_touch(wl_client* client, wl_resource* resource, uint32_t id)1201 static void get_touch(wl_client* client, wl_resource* resource, uint32_t id)
1121 {1202 {
1122 auto me = reinterpret_cast<WlSeat*>(wl_resource_get_user_data(resource));1203 auto me = reinterpret_cast<WlSeat*>(wl_resource_get_user_data(resource));
1123 me->touch[client].register_listener(1204 auto& input_ctx = me->touch[client];
1124 std::make_shared<WlTouch>(1205
1206 input_ctx.register_listener(
1207 new WlTouch{
1125 client,1208 client,
1126 resource,1209 resource,
1127 id,1210 id,
1128 me->executor));1211 [&input_ctx](WlTouch* listener)
1212 {
1213 input_ctx.unregister_listener(listener);
1214 },
1215 me->executor});
1129 }1216 }
1130 static void release(struct wl_client* /*client*/, struct wl_resource* /*resource*/) {}1217 static void release(struct wl_client* /*client*/, struct wl_resource* /*resource*/) {}
11311218

Subscribers

People subscribed via source and target branches