SDL 2.0
SDL_waylandmouse.c
Go to the documentation of this file.
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2019 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#include "../../SDL_internal.h"
23
24#if SDL_VIDEO_DRIVER_WAYLAND
25
26#include <sys/types.h>
27#include <sys/mman.h>
28#include <fcntl.h>
29#include <unistd.h>
30#include <stdlib.h>
31#include <limits.h>
32
33#include "../SDL_sysvideo.h"
34
35#include "SDL_mouse.h"
36#include "../../events/SDL_mouse_c.h"
37#include "SDL_waylandvideo.h"
38#include "SDL_waylandevents_c.h"
39
40#include "SDL_waylanddyn.h"
41#include "wayland-cursor.h"
42
43#include "SDL_assert.h"
44
45
46typedef struct {
47 struct wl_buffer *buffer;
48 struct wl_surface *surface;
49
50 int hot_x, hot_y;
51 int w, h;
52
53 /* Either a preloaded cursor, or one we created ourselves */
54 struct wl_cursor *cursor;
55 void *shm_data;
56} Wayland_CursorData;
57
58static int
59wayland_create_tmp_file(off_t size)
60{
61 static const char template[] = "/sdl-shared-XXXXXX";
62 char *xdg_path;
63 char tmp_path[PATH_MAX];
64 int fd;
65
66 xdg_path = SDL_getenv("XDG_RUNTIME_DIR");
67 if (!xdg_path) {
68 return -1;
69 }
70
71 SDL_strlcpy(tmp_path, xdg_path, PATH_MAX);
72 SDL_strlcat(tmp_path, template, PATH_MAX);
73
74 fd = mkostemp(tmp_path, O_CLOEXEC);
75 if (fd < 0)
76 return -1;
77
78 if (ftruncate(fd, size) < 0) {
79 close(fd);
80 return -1;
81 }
82
83 return fd;
84}
85
86static void
87mouse_buffer_release(void *data, struct wl_buffer *buffer)
88{
89}
90
91static const struct wl_buffer_listener mouse_buffer_listener = {
92 mouse_buffer_release
93};
94
95static int
96create_buffer_from_shm(Wayland_CursorData *d,
97 int width,
98 int height,
100{
103 struct wl_shm_pool *shm_pool;
104
105 int stride = width * 4;
106 int size = stride * height;
107
108 int shm_fd;
109
110 shm_fd = wayland_create_tmp_file(size);
111 if (shm_fd < 0)
112 {
113 return SDL_SetError("Creating mouse cursor buffer failed.");
114 }
115
116 d->shm_data = mmap(NULL,
117 size,
118 PROT_READ | PROT_WRITE,
119 MAP_SHARED,
120 shm_fd,
121 0);
122 if (d->shm_data == MAP_FAILED) {
123 d->shm_data = NULL;
124 close (shm_fd);
125 return SDL_SetError("mmap() failed.");
126 }
127
128 shm_pool = wl_shm_create_pool(data->shm, shm_fd, size);
129 d->buffer = wl_shm_pool_create_buffer(shm_pool,
130 0,
131 width,
132 height,
133 stride,
134 format);
136 &mouse_buffer_listener,
137 d);
138
139 wl_shm_pool_destroy (shm_pool);
140 close (shm_fd);
141
142 return 0;
143}
144
145static SDL_Cursor *
146Wayland_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y)
147{
149
150 cursor = calloc(1, sizeof (*cursor));
151 if (cursor) {
154 Wayland_CursorData *data = calloc (1, sizeof (Wayland_CursorData));
155 if (!data) {
157 free(cursor);
158 return NULL;
159 }
160 cursor->driverdata = (void *) data;
161
162 /* Assume ARGB8888 */
163 SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888);
164 SDL_assert(surface->pitch == surface->w * 4);
165
166 /* Allocate shared memory buffer for this cursor */
167 if (create_buffer_from_shm (data,
168 surface->w,
169 surface->h,
171 {
173 free (cursor);
174 return NULL;
175 }
176
177 SDL_memcpy(data->shm_data,
178 surface->pixels,
179 surface->h * surface->pitch);
180
183
184 data->hot_x = hot_x;
185 data->hot_y = hot_y;
186 data->w = surface->w;
187 data->h = surface->h;
188 } else {
190 }
191
192 return cursor;
193}
194
195static SDL_Cursor *
196CreateCursorFromWlCursor(SDL_VideoData *d, struct wl_cursor *wlcursor)
197{
199
200 cursor = calloc(1, sizeof (*cursor));
201 if (cursor) {
202 Wayland_CursorData *data = calloc (1, sizeof (Wayland_CursorData));
203 if (!data) {
205 free(cursor);
206 return NULL;
207 }
208 cursor->driverdata = (void *) data;
209
210 data->buffer = WAYLAND_wl_cursor_image_get_buffer(wlcursor->images[0]);
211 data->surface = wl_compositor_create_surface(d->compositor);
213 data->hot_x = wlcursor->images[0]->hotspot_x;
214 data->hot_y = wlcursor->images[0]->hotspot_y;
215 data->w = wlcursor->images[0]->width;
216 data->h = wlcursor->images[0]->height;
217 data->cursor= wlcursor;
218 } else {
220 }
221
222 return cursor;
223}
224
225static SDL_Cursor *
226Wayland_CreateDefaultCursor()
227{
229 SDL_VideoData *data = device->driverdata;
230
231 return CreateCursorFromWlCursor (data,
232 WAYLAND_wl_cursor_theme_get_cursor(data->cursor_theme,
233 "left_ptr"));
234}
235
236static SDL_Cursor *
237Wayland_CreateSystemCursor(SDL_SystemCursor id)
238{
241
242 struct wl_cursor *cursor = NULL;
243
244 switch(id)
245 {
246 default:
247 SDL_assert(0);
248 return NULL;
250 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "left_ptr");
251 break;
253 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "xterm");
254 break;
256 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "watch");
257 break;
259 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
260 break;
262 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "watch");
263 break;
265 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
266 break;
268 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
269 break;
271 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
272 break;
274 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
275 break;
277 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
278 break;
280 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "xterm");
281 break;
283 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
284 break;
285 }
286
287 return CreateCursorFromWlCursor(d, cursor);
288}
289
290static void
291Wayland_FreeCursor(SDL_Cursor *cursor)
292{
293 Wayland_CursorData *d;
294
295 if (!cursor)
296 return;
297
299
300 /* Probably not a cursor we own */
301 if (!d)
302 return;
303
304 if (d->buffer && !d->cursor)
305 wl_buffer_destroy(d->buffer);
306
307 if (d->surface)
308 wl_surface_destroy(d->surface);
309
310 /* Not sure what's meant to happen to shm_data */
313}
314
315static int
316Wayland_ShowCursor(SDL_Cursor *cursor)
317{
320
321 struct wl_pointer *pointer = d->pointer;
322
323 if (!pointer)
324 return -1;
325
326 if (cursor)
327 {
328 Wayland_CursorData *data = cursor->driverdata;
329
331 data->surface,
332 data->hot_x,
333 data->hot_y);
334 wl_surface_attach(data->surface, data->buffer, 0, 0);
335 wl_surface_damage(data->surface, 0, 0, data->w, data->h);
336 wl_surface_commit(data->surface);
337 }
338 else
339 {
341 NULL,
342 0,
343 0);
344 }
345
346 return 0;
347}
348
349static void
350Wayland_WarpMouse(SDL_Window *window, int x, int y)
351{
353}
354
355static int
356Wayland_WarpMouseGlobal(int x, int y)
357{
358 return SDL_Unsupported();
359}
360
361static int
362Wayland_SetRelativeMouseMode(SDL_bool enabled)
363{
366
367 if (enabled)
368 return Wayland_input_lock_pointer(data->input);
369 else
370 return Wayland_input_unlock_pointer(data->input);
371}
372
373void
374Wayland_InitMouse(void)
375{
376 SDL_Mouse *mouse = SDL_GetMouse();
377
378 mouse->CreateCursor = Wayland_CreateCursor;
379 mouse->CreateSystemCursor = Wayland_CreateSystemCursor;
380 mouse->ShowCursor = Wayland_ShowCursor;
381 mouse->FreeCursor = Wayland_FreeCursor;
382 mouse->WarpMouse = Wayland_WarpMouse;
383 mouse->WarpMouseGlobal = Wayland_WarpMouseGlobal;
384 mouse->SetRelativeMouseMode = Wayland_SetRelativeMouseMode;
385
386 SDL_SetDefaultCursor(Wayland_CreateDefaultCursor());
387}
388
389void
390Wayland_FiniMouse(void)
391{
392 /* This effectively assumes that nobody else
393 * touches SDL_Mouse which is effectively
394 * a singleton */
395}
396#endif /* SDL_VIDEO_DRIVER_WAYLAND */
#define SDL_assert(condition)
Definition: SDL_assert.h:169
unsigned int uint32_t
#define SDL_SetError
#define SDL_strlcat
#define SDL_getenv
#define SDL_strlcpy
#define SDL_free
#define SDL_memcpy
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 SDL_AssertionHandler void SDL_SpinLock SDL_atomic_t int int return SDL_atomic_t return void void void return void return int return SDL_AudioSpec SDL_AudioSpec return int int return return int SDL_RWops int SDL_AudioSpec Uint8 ** d
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
#define SDL_Unsupported()
Definition: SDL_error.h:53
SDL_EventEntry * free
Definition: SDL_events.c:82
int uint32_t uint32_t uint32_t uint32_t uint32_t int drmModeModeInfoPtr mode int uint32_t uint32_t uint32_t uint32_t int32_t hot_x
Definition: SDL_kmsdrmsym.h:57
void SDL_SetDefaultCursor(SDL_Cursor *cursor)
Definition: SDL_mouse.c:167
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:178
SDL_SystemCursor
Cursor types for SDL_CreateSystemCursor().
Definition: SDL_mouse.h:47
@ SDL_SYSTEM_CURSOR_SIZENS
Definition: SDL_mouse.h:56
@ SDL_SYSTEM_CURSOR_HAND
Definition: SDL_mouse.h:59
@ SDL_SYSTEM_CURSOR_ARROW
Definition: SDL_mouse.h:48
@ SDL_SYSTEM_CURSOR_SIZENWSE
Definition: SDL_mouse.h:53
@ SDL_SYSTEM_CURSOR_SIZENESW
Definition: SDL_mouse.h:54
@ SDL_SYSTEM_CURSOR_IBEAM
Definition: SDL_mouse.h:49
@ SDL_SYSTEM_CURSOR_NO
Definition: SDL_mouse.h:58
@ SDL_SYSTEM_CURSOR_WAITARROW
Definition: SDL_mouse.h:52
@ SDL_SYSTEM_CURSOR_SIZEALL
Definition: SDL_mouse.h:57
@ SDL_SYSTEM_CURSOR_WAIT
Definition: SDL_mouse.h:50
@ SDL_SYSTEM_CURSOR_SIZEWE
Definition: SDL_mouse.h:55
@ SDL_SYSTEM_CURSOR_CROSSHAIR
Definition: SDL_mouse.h:51
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
GLint GLint GLsizei width
Definition: SDL_opengl.h:1572
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
GLint GLint GLsizei GLsizei height
Definition: SDL_opengl.h:1572
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLsizei stride
GLsizei const void * pointer
GLuint buffer
GLsizeiptr size
GLfloat GLfloat GLfloat GLfloat h
GLubyte GLubyte GLubyte GLubyte w
@ SDL_PIXELFORMAT_ARGB8888
Definition: SDL_pixels.h:248
SDL_bool
Definition: SDL_stdinc.h:162
SDL_VideoDevice * SDL_GetVideoDevice(void)
Definition: SDL_video.c:583
int Wayland_input_lock_pointer(struct SDL_WaylandInput *input)
int Wayland_input_unlock_pointer(struct SDL_WaylandInput *input)
#define NULL
Definition: begin_code.h:167
EGLSurface surface
Definition: eglext.h:248
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
GLuint64 GLenum GLint fd
Definition: gl2ext.h:1508
static void wl_buffer_destroy(struct wl_buffer *wl_buffer)
static int wl_buffer_add_listener(struct wl_buffer *wl_buffer, const struct wl_buffer_listener *listener, void *data)
static struct wl_surface * wl_compositor_create_surface(struct wl_compositor *wl_compositor)
static void wl_pointer_set_cursor(struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, int32_t hotspot_x, int32_t hotspot_y)
static struct wl_buffer * wl_shm_pool_create_buffer(struct wl_shm_pool *wl_shm_pool, int32_t offset, int32_t width, int32_t height, int32_t stride, uint32_t format)
static void wl_shm_pool_destroy(struct wl_shm_pool *wl_shm_pool)
static struct wl_shm_pool * wl_shm_create_pool(struct wl_shm *wl_shm, int32_t fd, int32_t size)
@ WL_SHM_FORMAT_ARGB8888
static void wl_surface_set_user_data(struct wl_surface *wl_surface, void *user_data)
static void wl_surface_attach(struct wl_surface *wl_surface, struct wl_buffer *buffer, int32_t x, int32_t y)
static void wl_surface_damage(struct wl_surface *wl_surface, int32_t x, int32_t y, int32_t width, int32_t height)
static void wl_surface_destroy(struct wl_surface *wl_surface)
static void wl_surface_commit(struct wl_surface *wl_surface)
static SDL_AudioDeviceID device
Definition: loopwave.c:37
void * driverdata
Definition: SDL_mouse_c.h:33
int(* SetRelativeMouseMode)(SDL_bool enabled)
Definition: SDL_mouse_c.h:67
void(* WarpMouse)(SDL_Window *window, int x, int y)
Definition: SDL_mouse_c.h:61
void(* FreeCursor)(SDL_Cursor *cursor)
Definition: SDL_mouse_c.h:58
int(* ShowCursor)(SDL_Cursor *cursor)
Definition: SDL_mouse_c.h:52
SDL_Cursor *(* CreateSystemCursor)(SDL_SystemCursor id)
Definition: SDL_mouse_c.h:49
int(* WarpMouseGlobal)(int x, int y)
Definition: SDL_mouse_c.h:64
SDL_Cursor *(* CreateCursor)(SDL_Surface *surface, int hot_x, int hot_y)
Definition: SDL_mouse_c.h:46
A collection of pixels used in software blitting.
Definition: SDL_surface.h:71
struct wl_compositor * compositor
The type used to identify a window.
Definition: SDL_sysvideo.h:74
SDL_Cursor * cursor
Definition: testwm2.c:40