SDL  2.0
SDL_waylandmouse.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2020 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 
44 
45 typedef struct {
46  struct wl_buffer *buffer;
47  struct wl_surface *surface;
48 
49  int hot_x, hot_y;
50  int w, h;
51 
52  /* Either a preloaded cursor, or one we created ourselves */
53  struct wl_cursor *cursor;
54  void *shm_data;
55 } Wayland_CursorData;
56 
57 static int
58 wayland_create_tmp_file(off_t size)
59 {
60  static const char template[] = "/sdl-shared-XXXXXX";
61  char *xdg_path;
62  char tmp_path[PATH_MAX];
63  int fd;
64 
65  xdg_path = SDL_getenv("XDG_RUNTIME_DIR");
66  if (!xdg_path) {
67  return -1;
68  }
69 
70  SDL_strlcpy(tmp_path, xdg_path, PATH_MAX);
71  SDL_strlcat(tmp_path, template, PATH_MAX);
72 
73  fd = mkostemp(tmp_path, O_CLOEXEC);
74  if (fd < 0)
75  return -1;
76 
77  if (ftruncate(fd, size) < 0) {
78  close(fd);
79  return -1;
80  }
81 
82  return fd;
83 }
84 
85 static void
86 mouse_buffer_release(void *data, struct wl_buffer *buffer)
87 {
88 }
89 
90 static const struct wl_buffer_listener mouse_buffer_listener = {
91  mouse_buffer_release
92 };
93 
94 static int
95 create_buffer_from_shm(Wayland_CursorData *d,
96  int width,
97  int height,
99 {
102  struct wl_shm_pool *shm_pool;
103 
104  int stride = width * 4;
105  int size = stride * height;
106 
107  int shm_fd;
108 
109  shm_fd = wayland_create_tmp_file(size);
110  if (shm_fd < 0)
111  {
112  return SDL_SetError("Creating mouse cursor buffer failed.");
113  }
114 
115  d->shm_data = mmap(NULL,
116  size,
117  PROT_READ | PROT_WRITE,
118  MAP_SHARED,
119  shm_fd,
120  0);
121  if (d->shm_data == MAP_FAILED) {
122  d->shm_data = NULL;
123  close (shm_fd);
124  return SDL_SetError("mmap() failed.");
125  }
126 
127  SDL_assert(d->shm_data != NULL);
128 
129  shm_pool = wl_shm_create_pool(data->shm, shm_fd, size);
130  d->buffer = wl_shm_pool_create_buffer(shm_pool,
131  0,
132  width,
133  height,
134  stride,
135  format);
136  wl_buffer_add_listener(d->buffer,
137  &mouse_buffer_listener,
138  d);
139 
140  wl_shm_pool_destroy (shm_pool);
141  close (shm_fd);
142 
143  return 0;
144 }
145 
146 static SDL_Cursor *
147 Wayland_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y)
148 {
150 
151  cursor = calloc(1, sizeof (*cursor));
152  if (cursor) {
154  SDL_VideoData *wd = (SDL_VideoData *) vd->driverdata;
155  Wayland_CursorData *data = calloc (1, sizeof (Wayland_CursorData));
156  if (!data) {
157  SDL_OutOfMemory();
158  free(cursor);
159  return NULL;
160  }
161  cursor->driverdata = (void *) data;
162 
163  /* Assume ARGB8888 */
164  SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888);
165  SDL_assert(surface->pitch == surface->w * 4);
166 
167  /* Allocate shared memory buffer for this cursor */
168  if (create_buffer_from_shm (data,
169  surface->w,
170  surface->h,
172  {
174  free (cursor);
175  return NULL;
176  }
177 
178  SDL_memcpy(data->shm_data,
179  surface->pixels,
180  surface->h * surface->pitch);
181 
184 
185  data->hot_x = hot_x;
186  data->hot_y = hot_y;
187  data->w = surface->w;
188  data->h = surface->h;
189  } else {
190  SDL_OutOfMemory();
191  }
192 
193  return cursor;
194 }
195 
196 static SDL_Cursor *
197 CreateCursorFromWlCursor(SDL_VideoData *d, struct wl_cursor *wlcursor)
198 {
200 
201  cursor = calloc(1, sizeof (*cursor));
202  if (cursor) {
203  Wayland_CursorData *data = calloc (1, sizeof (Wayland_CursorData));
204  if (!data) {
205  SDL_OutOfMemory();
206  free(cursor);
207  return NULL;
208  }
209  cursor->driverdata = (void *) data;
210 
211  data->buffer = WAYLAND_wl_cursor_image_get_buffer(wlcursor->images[0]);
212  data->surface = wl_compositor_create_surface(d->compositor);
214  data->hot_x = wlcursor->images[0]->hotspot_x;
215  data->hot_y = wlcursor->images[0]->hotspot_y;
216  data->w = wlcursor->images[0]->width;
217  data->h = wlcursor->images[0]->height;
218  data->cursor= wlcursor;
219  } else {
220  SDL_OutOfMemory ();
221  }
222 
223  return cursor;
224 }
225 
226 static SDL_Cursor *
227 Wayland_CreateDefaultCursor()
228 {
230  SDL_VideoData *data = device->driverdata;
231 
232  return CreateCursorFromWlCursor (data,
233  WAYLAND_wl_cursor_theme_get_cursor(data->cursor_theme,
234  "left_ptr"));
235 }
236 
237 static SDL_Cursor *
238 Wayland_CreateSystemCursor(SDL_SystemCursor id)
239 {
241  SDL_VideoData *d = vd->driverdata;
242 
243  struct wl_cursor *cursor = NULL;
244 
245  switch(id)
246  {
247  default:
248  SDL_assert(0);
249  return NULL;
251  cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "left_ptr");
252  break;
254  cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "xterm");
255  break;
257  cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "watch");
258  break;
260  cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
261  break;
263  cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "watch");
264  break;
266  cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
267  break;
269  cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
270  break;
272  cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
273  break;
275  cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
276  break;
278  cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
279  break;
281  cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "xterm");
282  break;
284  cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
285  break;
286  }
287 
288  return CreateCursorFromWlCursor(d, cursor);
289 }
290 
291 static void
292 Wayland_FreeCursor(SDL_Cursor *cursor)
293 {
294  Wayland_CursorData *d;
295 
296  if (!cursor)
297  return;
298 
299  d = cursor->driverdata;
300 
301  /* Probably not a cursor we own */
302  if (!d)
303  return;
304 
305  if (d->buffer && !d->cursor)
306  wl_buffer_destroy(d->buffer);
307 
308  if (d->surface)
309  wl_surface_destroy(d->surface);
310 
311  /* Not sure what's meant to happen to shm_data */
313  SDL_free(cursor);
314 }
315 
316 static int
317 Wayland_ShowCursor(SDL_Cursor *cursor)
318 {
320  SDL_VideoData *d = vd->driverdata;
321 
322  struct wl_pointer *pointer = d->pointer;
323 
324  if (!pointer)
325  return -1;
326 
327  if (cursor)
328  {
329  Wayland_CursorData *data = cursor->driverdata;
330 
332  data->surface,
333  data->hot_x,
334  data->hot_y);
335  wl_surface_attach(data->surface, data->buffer, 0, 0);
336  wl_surface_damage(data->surface, 0, 0, data->w, data->h);
337  wl_surface_commit(data->surface);
338  }
339  else
340  {
342  NULL,
343  0,
344  0);
345  }
346 
347  return 0;
348 }
349 
350 static void
351 Wayland_WarpMouse(SDL_Window *window, int x, int y)
352 {
353  SDL_Unsupported();
354 }
355 
356 static int
357 Wayland_WarpMouseGlobal(int x, int y)
358 {
359  return SDL_Unsupported();
360 }
361 
362 static int
363 Wayland_SetRelativeMouseMode(SDL_bool enabled)
364 {
367 
368  if (enabled)
369  return Wayland_input_lock_pointer(data->input);
370  else
371  return Wayland_input_unlock_pointer(data->input);
372 }
373 
374 void
375 Wayland_InitMouse(void)
376 {
377  SDL_Mouse *mouse = SDL_GetMouse();
378 
379  mouse->CreateCursor = Wayland_CreateCursor;
380  mouse->CreateSystemCursor = Wayland_CreateSystemCursor;
381  mouse->ShowCursor = Wayland_ShowCursor;
382  mouse->FreeCursor = Wayland_FreeCursor;
383  mouse->WarpMouse = Wayland_WarpMouse;
384  mouse->WarpMouseGlobal = Wayland_WarpMouseGlobal;
385  mouse->SetRelativeMouseMode = Wayland_SetRelativeMouseMode;
386 
387  SDL_SetDefaultCursor(Wayland_CreateDefaultCursor());
388 }
389 
390 void
391 Wayland_FiniMouse(void)
392 {
393  /* This effectively assumes that nobody else
394  * touches SDL_Mouse which is effectively
395  * a singleton */
396 }
397 #endif /* SDL_VIDEO_DRIVER_WAYLAND */
#define SDL_assert(condition)
Definition: SDL_assert.h:171
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:88
#define SDL_Unsupported()
Definition: SDL_error.h:89
SDL_EventEntry * free
Definition: SDL_events.c:89
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
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:175
void SDL_SetDefaultCursor(SDL_Cursor *cursor)
Definition: SDL_mouse.c:164
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:257
SDL_bool
Definition: SDL_stdinc.h:168
SDL_VideoDevice * SDL_GetVideoDevice(void)
Definition: SDL_video.c:587
int Wayland_input_lock_pointer(struct SDL_WaylandInput *input)
int Wayland_input_unlock_pointer(struct SDL_WaylandInput *input)
#define NULL
Definition: begin_code.h:163
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 void wl_shm_pool_destroy(struct wl_shm_pool *wl_shm_pool)
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 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
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
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
SDL_Cursor *(* CreateCursor)(SDL_Surface *surface, int hot_x, int hot_y)
Definition: SDL_mouse_c.h:46
void(* FreeCursor)(SDL_Cursor *cursor)
Definition: SDL_mouse_c.h:58
int(* ShowCursor)(SDL_Cursor *cursor)
Definition: SDL_mouse_c.h:52
int(* WarpMouseGlobal)(int x, int y)
Definition: SDL_mouse_c.h:64
SDL_Cursor *(* CreateSystemCursor)(SDL_SystemCursor id)
Definition: SDL_mouse_c.h:49
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:75
SDL_Cursor * cursor
Definition: testwm2.c:40