1 | /* |
2 | Simple DirectMedia Layer |
3 | Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org> |
4 | |
5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. |
8 | |
9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: |
12 | |
13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ |
21 | |
22 | /* Contributed by Thomas Perl <thomas.perl@jollamobile.com> */ |
23 | |
24 | #include "../../SDL_internal.h" |
25 | |
26 | #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH |
27 | |
28 | #include "SDL_mouse.h" |
29 | #include "SDL_keyboard.h" |
30 | #include "SDL_waylandtouch.h" |
31 | #include "../../events/SDL_touch_c.h" |
32 | |
33 | struct SDL_WaylandTouch { |
34 | struct qt_touch_extension *touch_extension; |
35 | }; |
36 | |
37 | |
38 | /** |
39 | * Qt TouchPointState |
40 | * adapted from qtbase/src/corelib/global/qnamespace.h |
41 | **/ |
42 | enum QtWaylandTouchPointState { |
43 | QtWaylandTouchPointPressed = 0x01, |
44 | QtWaylandTouchPointMoved = 0x02, |
45 | /* |
46 | Never sent by the server: |
47 | QtWaylandTouchPointStationary = 0x04, |
48 | */ |
49 | QtWaylandTouchPointReleased = 0x08, |
50 | }; |
51 | |
52 | static void |
53 | touch_handle_touch(void *data, |
54 | struct qt_touch_extension *qt_touch_extension, |
55 | uint32_t time, |
56 | uint32_t id, |
57 | uint32_t state, |
58 | int32_t x, |
59 | int32_t y, |
60 | int32_t normalized_x, |
61 | int32_t normalized_y, |
62 | int32_t width, |
63 | int32_t height, |
64 | uint32_t pressure, |
65 | int32_t velocity_x, |
66 | int32_t velocity_y, |
67 | uint32_t flags, |
68 | struct wl_array *rawdata) |
69 | { |
70 | /** |
71 | * Event is assembled in QtWayland in TouchExtensionGlobal::postTouchEvent |
72 | * (src/compositor/wayland_wrapper/qwltouch.cpp) |
73 | **/ |
74 | |
75 | float FIXED_TO_FLOAT = 1. / 10000.; |
76 | float xf = FIXED_TO_FLOAT * x; |
77 | float yf = FIXED_TO_FLOAT * y; |
78 | |
79 | float PRESSURE_TO_FLOAT = 1. / 255.; |
80 | float pressuref = PRESSURE_TO_FLOAT * pressure; |
81 | |
82 | uint32_t touchState = state & 0xFFFF; |
83 | /* |
84 | Other fields that are sent by the server (qwltouch.cpp), |
85 | but not used at the moment can be decoded in this way: |
86 | |
87 | uint32_t sentPointCount = state >> 16; |
88 | uint32_t touchFlags = flags & 0xFFFF; |
89 | uint32_t capabilities = flags >> 16; |
90 | */ |
91 | |
92 | SDL_Window* window = NULL; |
93 | |
94 | SDL_TouchID deviceId = 1; |
95 | if (SDL_AddTouch(deviceId, SDL_TOUCH_DEVICE_DIRECT, "qt_touch_extension" ) < 0) { |
96 | SDL_Log("error: can't add touch %s, %d" , __FILE__, __LINE__); |
97 | } |
98 | |
99 | /* FIXME: This should be the window the given wayland surface is associated |
100 | * with, but how do we get the wayland surface? */ |
101 | window = SDL_GetMouseFocus(); |
102 | if (window == NULL) { |
103 | window = SDL_GetKeyboardFocus(); |
104 | } |
105 | |
106 | switch (touchState) { |
107 | case QtWaylandTouchPointPressed: |
108 | case QtWaylandTouchPointReleased: |
109 | SDL_SendTouch(deviceId, (SDL_FingerID)id, window, |
110 | (touchState == QtWaylandTouchPointPressed) ? SDL_TRUE : SDL_FALSE, |
111 | xf, yf, pressuref); |
112 | break; |
113 | case QtWaylandTouchPointMoved: |
114 | SDL_SendTouchMotion(deviceId, (SDL_FingerID)id, window, xf, yf, pressuref); |
115 | break; |
116 | default: |
117 | /* Should not happen */ |
118 | break; |
119 | } |
120 | } |
121 | |
122 | static void |
123 | touch_handle_configure(void *data, |
124 | struct qt_touch_extension *qt_touch_extension, |
125 | uint32_t flags) |
126 | { |
127 | } |
128 | |
129 | |
130 | /* wayland-qt-touch-extension.c BEGINS */ |
131 | |
132 | static const struct qt_touch_extension_listener touch_listener = { |
133 | touch_handle_touch, |
134 | touch_handle_configure, |
135 | }; |
136 | |
137 | static const struct wl_interface *qt_touch_extension_types[] = { |
138 | NULL, |
139 | NULL, |
140 | NULL, |
141 | NULL, |
142 | NULL, |
143 | NULL, |
144 | NULL, |
145 | NULL, |
146 | NULL, |
147 | NULL, |
148 | NULL, |
149 | NULL, |
150 | NULL, |
151 | NULL, |
152 | }; |
153 | |
154 | static const struct wl_message qt_touch_extension_requests[] = { |
155 | { "dummy" , "" , qt_touch_extension_types + 0 }, |
156 | }; |
157 | |
158 | static const struct wl_message qt_touch_extension_events[] = { |
159 | { "touch" , "uuuiiiiiiuiiua" , qt_touch_extension_types + 0 }, |
160 | { "configure" , "u" , qt_touch_extension_types + 0 }, |
161 | }; |
162 | |
163 | const struct wl_interface qt_touch_extension_interface = { |
164 | "qt_touch_extension" , 1, |
165 | 1, qt_touch_extension_requests, |
166 | 2, qt_touch_extension_events, |
167 | }; |
168 | |
169 | /* wayland-qt-touch-extension.c ENDS */ |
170 | |
171 | /* wayland-qt-windowmanager.c BEGINS */ |
172 | static const struct wl_interface *qt_windowmanager_types[] = { |
173 | NULL, |
174 | NULL, |
175 | }; |
176 | |
177 | static const struct wl_message qt_windowmanager_requests[] = { |
178 | { "open_url" , "us" , qt_windowmanager_types + 0 }, |
179 | }; |
180 | |
181 | static const struct wl_message qt_windowmanager_events[] = { |
182 | { "hints" , "i" , qt_windowmanager_types + 0 }, |
183 | { "quit" , "" , qt_windowmanager_types + 0 }, |
184 | }; |
185 | |
186 | const struct wl_interface qt_windowmanager_interface = { |
187 | "qt_windowmanager" , 1, |
188 | 1, qt_windowmanager_requests, |
189 | 2, qt_windowmanager_events, |
190 | }; |
191 | /* wayland-qt-windowmanager.c ENDS */ |
192 | |
193 | /* wayland-qt-surface-extension.c BEGINS */ |
194 | #ifndef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC |
195 | extern const struct wl_interface wl_surface_interface; |
196 | #endif |
197 | |
198 | static const struct wl_interface *qt_surface_extension_types[] = { |
199 | NULL, |
200 | NULL, |
201 | &qt_extended_surface_interface, |
202 | #ifdef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC |
203 | /* FIXME: Set this dynamically to (*WAYLAND_wl_surface_interface) ? |
204 | * The value comes from auto generated code and does |
205 | * not appear to actually be used anywhere |
206 | */ |
207 | NULL, |
208 | #else |
209 | &wl_surface_interface, |
210 | #endif |
211 | }; |
212 | |
213 | static const struct wl_message qt_surface_extension_requests[] = { |
214 | { "get_extended_surface" , "no" , qt_surface_extension_types + 2 }, |
215 | }; |
216 | |
217 | const struct wl_interface qt_surface_extension_interface = { |
218 | "qt_surface_extension" , 1, |
219 | 1, qt_surface_extension_requests, |
220 | 0, NULL, |
221 | }; |
222 | |
223 | static const struct wl_message qt_extended_surface_requests[] = { |
224 | { "update_generic_property" , "sa" , qt_surface_extension_types + 0 }, |
225 | { "set_content_orientation" , "i" , qt_surface_extension_types + 0 }, |
226 | { "set_window_flags" , "i" , qt_surface_extension_types + 0 }, |
227 | }; |
228 | |
229 | static const struct wl_message qt_extended_surface_events[] = { |
230 | { "onscreen_visibility" , "i" , qt_surface_extension_types + 0 }, |
231 | { "set_generic_property" , "sa" , qt_surface_extension_types + 0 }, |
232 | { "close" , "" , qt_surface_extension_types + 0 }, |
233 | }; |
234 | |
235 | const struct wl_interface qt_extended_surface_interface = { |
236 | "qt_extended_surface" , 1, |
237 | 3, qt_extended_surface_requests, |
238 | 3, qt_extended_surface_events, |
239 | }; |
240 | |
241 | /* wayland-qt-surface-extension.c ENDS */ |
242 | |
243 | void |
244 | Wayland_touch_create(SDL_VideoData *data, uint32_t id) |
245 | { |
246 | struct SDL_WaylandTouch *touch; |
247 | |
248 | if (data->touch) { |
249 | Wayland_touch_destroy(data); |
250 | } |
251 | |
252 | /* !!! FIXME: check for failure, call SDL_OutOfMemory() */ |
253 | data->touch = SDL_malloc(sizeof(struct SDL_WaylandTouch)); |
254 | |
255 | touch = data->touch; |
256 | touch->touch_extension = wl_registry_bind(data->registry, id, &qt_touch_extension_interface, 1); |
257 | qt_touch_extension_add_listener(touch->touch_extension, &touch_listener, data); |
258 | } |
259 | |
260 | void |
261 | Wayland_touch_destroy(SDL_VideoData *data) |
262 | { |
263 | if (data->touch) { |
264 | struct SDL_WaylandTouch *touch = data->touch; |
265 | if (touch->touch_extension) { |
266 | qt_touch_extension_destroy(touch->touch_extension); |
267 | } |
268 | |
269 | SDL_free(data->touch); |
270 | data->touch = NULL; |
271 | } |
272 | } |
273 | |
274 | #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */ |
275 | |