Mir

Merge lp:~andreas-pokorny/mir/contact-info-as-extension into lp:mir

Proposed by Andreas Pokorny on 2017-04-28
Status: Merged
Approved by: Daniel van Vugt on 2017-05-02
Approved revision: 4160
Merged at revision: 4159
Proposed branch: lp:~andreas-pokorny/mir/contact-info-as-extension
Merge into: lp:mir
Diff against target: 153 lines (+74/-10)
3 files modified
src/platforms/evdev/libinput_device.cpp (+65/-4)
src/platforms/evdev/libinput_device.h (+3/-0)
tests/mir_test_doubles/mock_libinput.cpp (+6/-6)
To merge this branch: bzr merge lp:~andreas-pokorny/mir/contact-info-as-extension
Reviewer Review Type Date Requested Status
Mir CI Bot continuous-integration Approve on 2017-05-02
Daniel van Vugt 2017-04-28 Approve on 2017-05-02
Review via email: mp+323410@code.launchpad.net

Commit message

Allow the evdev platform to run on non-Ubuntu systems.

The Ubuntu version of libinput provides additional symbols, allowing to
access touch information. This is an intermediate solution until the
patch to libinput gets accepted upstream.

Description of the change

This loads the touch contact functions via dlsym - so evdev platform will compile and run on fedora or debian.

This is only meant as an intermediate step until the change in libinput gets upstreamed.

To post a comment you must log in.
Daniel van Vugt (vanvugt) wrote :

Sounds like a plan...

(1) This is a bit weird though:
  dladdr(dlsym(nullptr, "main"), &exec_info);
Why not use dlsym(RTLD_DEFAULT, "libinput_event_touch_get_major_transformed") to search the current process instead? You shouldn't need the Dl_info either... Just search for the functions using RTLD_DEFAULT.
  Alternatively, just provide a raw implementation of the relevant functions, and check to see if there is a (second) system-provided version to use by searching RTLD_NEXT.

(2) Why would the fallback touch_major and touch_minor functions return different values?

review: Needs Fixing
4159. By Andreas Pokorny on 2017-05-01

Missing error handling and removal of test code

Andreas Pokorny (andreas-pokorny) wrote :

> Sounds like a plan...
>
> (1) This is a bit weird though:
> dladdr(dlsym(nullptr, "main"), &exec_info);
> Why not use dlsym(RTLD_DEFAULT, "libinput_event_touch_get_major_transformed")
> to search the current process instead? You shouldn't need the Dl_info
> either... Just search for the functions using RTLD_DEFAULT.
> Alternatively, just provide a raw implementation of the relevant functions,
> and check to see if there is a (second) system-provided version to use by
> searching RTLD_NEXT.

Hmm ok I have not thought about that. I think the latter would fail because of mock_libinput.cpp. Will try the former now..

> (2) Why would the fallback touch_major and touch_minor functions return
> different values?

Usually the larger diameter is returned via major and the small diameter with touch minor.

4160. By Andreas Pokorny on 2017-05-01

much simpler

Daniel van Vugt (vanvugt) wrote :

OK, thanks.

I don't think the template function is necessary but it's not so important. I would have just made a lookup table:

typedef void (*FunPtr)();
static const struct
{
    char const* name;
    FunPtr* ptr;
} fun[] =
{
    {"libinput_event_touch_get_major_transformed", (FunPtr*)&get_touch_major},
    ...
};

And then loop through the array, indirectly filling out the pointed-to function pointers.

review: Approve
Mir CI Bot (mir-ci-bot) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/platforms/evdev/libinput_device.cpp'
2--- src/platforms/evdev/libinput_device.cpp 2017-03-14 02:26:28 +0000
3+++ src/platforms/evdev/libinput_device.cpp 2017-05-01 16:20:55 +0000
4@@ -38,6 +38,7 @@
5
6 #include <libinput.h>
7 #include <linux/input.h> // only used to get constants for input reports
8+#include <dlfcn.h>
9
10 #include <boost/exception/diagnostic_information.hpp>
11 #include <cstring>
12@@ -50,8 +51,68 @@
13 namespace mie = mi::evdev;
14 using namespace std::literals::chrono_literals;
15
16+namespace
17+{
18+double touch_major(libinput_event_touch*, uint32_t, uint32_t)
19+{
20+ return 8;
21+}
22+double touch_minor(libinput_event_touch*, uint32_t, uint32_t)
23+{
24+ return 6;
25+}
26+double pressure(libinput_event_touch*)
27+{
28+ return 0.8;
29+}
30+double orientation(libinput_event_touch*)
31+{
32+ return 0;
33+}
34+
35+template<typename T> auto load_function(char const* sym)
36+{
37+ T result{};
38+ dlerror();
39+ (void*&)result = dlsym(RTLD_DEFAULT, sym);
40+ char const *error = dlerror();
41+
42+ if (error)
43+ throw std::runtime_error(error);
44+ if (!result)
45+ throw std::runtime_error("no valid function address");
46+
47+ return result;
48+}
49+}
50+
51+struct mie::LibInputDevice::ContactExtension
52+{
53+ ContactExtension()
54+ {
55+ constexpr const char touch_major_sym[] = "libinput_event_touch_get_major_transformed";
56+ constexpr const char touch_minor_sym[] = "libinput_event_touch_get_minor_transformed";
57+ constexpr const char orientation_sym[] = "libinput_event_touch_get_orientation";
58+ constexpr const char pressure_sym[] = "libinput_event_touch_get_pressure";
59+
60+ try
61+ {
62+ get_touch_major = load_function<decltype(&touch_major)>(touch_major_sym);
63+ get_touch_minor = load_function<decltype(&touch_minor)>(touch_minor_sym);
64+ get_orientation = load_function<decltype(&orientation)>(orientation_sym);
65+ get_pressure = load_function<decltype(&pressure)>(pressure_sym);
66+ }
67+ catch(...) {}
68+ }
69+
70+ decltype(&touch_major) get_touch_major{&touch_major};
71+ decltype(&touch_minor) get_touch_minor{&touch_minor};
72+ decltype(&pressure) get_pressure{&pressure};
73+ decltype(&orientation) get_orientation{&orientation};
74+};
75+
76 mie::LibInputDevice::LibInputDevice(std::shared_ptr<mi::InputReport> const& report, LibInputDevicePtr dev)
77- : report{report}, pointer_pos{0, 0}, button_state{0}
78+ : contact_extension{std::make_unique<ContactExtension>()}, report{report}, pointer_pos{0, 0}, button_state{0}
79 {
80 add_device_of_group(std::move(dev));
81 }
82@@ -300,11 +361,11 @@
83 uint32_t height = info.output_size.height.as_int();
84
85 data.action = action;
86- data.pressure = libinput_event_touch_get_pressure(touch);
87 data.x = libinput_event_touch_get_x_transformed(touch, width);
88 data.y = libinput_event_touch_get_y_transformed(touch, height);
89- data.major = libinput_event_touch_get_major_transformed(touch, width, height);
90- data.minor = libinput_event_touch_get_minor_transformed(touch, width, height);
91+ data.major = contact_extension->get_touch_major(touch, width, height);
92+ data.minor = contact_extension->get_touch_minor(touch, width, height);
93+ data.pressure = contact_extension->get_pressure(touch);
94
95 info.transform_to_scene(data.x, data.y);
96 }
97
98=== modified file 'src/platforms/evdev/libinput_device.h'
99--- src/platforms/evdev/libinput_device.h 2017-03-20 11:46:27 +0000
100+++ src/platforms/evdev/libinput_device.h 2017-05-01 16:20:55 +0000
101@@ -81,6 +81,9 @@
102 bool is_output_active() const;
103 OutputInfo get_output_info() const;
104
105+ struct ContactExtension;
106+ std::unique_ptr<ContactExtension> contact_extension;
107+
108 std::shared_ptr<InputReport> report;
109 std::vector<LibInputDevicePtr> devices;
110
111
112=== modified file 'tests/mir_test_doubles/mock_libinput.cpp'
113--- tests/mir_test_doubles/mock_libinput.cpp 2017-03-14 02:26:28 +0000
114+++ tests/mir_test_doubles/mock_libinput.cpp 2017-05-01 16:20:55 +0000
115@@ -278,32 +278,32 @@
116 return global_libinput->libinput_event_touch_get_y_transformed(event, height);
117 }
118
119-double libinput_event_touch_get_major(libinput_event_touch* event)
120+extern "C" double libinput_event_touch_get_major(libinput_event_touch* event)
121 {
122 return global_libinput->libinput_event_touch_get_major(event);
123 }
124
125-double libinput_event_touch_get_minor(libinput_event_touch* event)
126+extern "C" double libinput_event_touch_get_minor(libinput_event_touch* event)
127 {
128 return global_libinput->libinput_event_touch_get_minor(event);
129 }
130
131-double libinput_event_touch_get_major_transformed(libinput_event_touch* event, uint32_t width, uint32_t height)
132+extern "C" double libinput_event_touch_get_major_transformed(libinput_event_touch* event, uint32_t width, uint32_t height)
133 {
134 return global_libinput->libinput_event_touch_get_major_transformed(event, width, height);
135 }
136
137-double libinput_event_touch_get_minor_transformed(libinput_event_touch* event, uint32_t width, uint32_t height)
138+extern "C" double libinput_event_touch_get_minor_transformed(libinput_event_touch* event, uint32_t width, uint32_t height)
139 {
140 return global_libinput->libinput_event_touch_get_minor_transformed(event, width, height);
141 }
142
143-double libinput_event_touch_get_pressure(libinput_event_touch* event)
144+extern "C" double libinput_event_touch_get_pressure(libinput_event_touch* event)
145 {
146 return global_libinput->libinput_event_touch_get_pressure(event);
147 }
148
149-double libinput_event_touch_get_orientation(libinput_event_touch* event)
150+extern "C" double libinput_event_touch_get_orientation(libinput_event_touch* event)
151 {
152 return global_libinput->libinput_event_touch_get_orientation(event);
153 }

Subscribers

People subscribed via source and target branches