2 Simple DirectMedia Layer
3 Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
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.
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:
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.
22 #include "../../SDL_internal.h"
24 #if SDL_VIDEO_DRIVER_WAYLAND
31 #include <sys/types.h>
38 #include "../SDL_sysvideo.h"
40 #include "SDL_mouse.h"
41 #include "../../events/SDL_mouse_c.h"
42 #include "SDL_waylandvideo.h"
43 #include "SDL_waylandevents_c.h"
45 #include "SDL_waylanddyn.h"
46 #include "wayland-cursor.h"
48 #include "SDL_assert.h"
52 struct wl_buffer *buffer;
53 struct wl_surface *surface;
58 /* Either a preloaded cursor, or one we created ourselves */
59 struct wl_cursor *cursor;
64 wayland_create_tmp_file(off_t size)
66 static const char template[] = "/sdl-shared-XXXXXX";
68 char tmp_path[PATH_MAX];
71 xdg_path = SDL_getenv("XDG_RUNTIME_DIR");
77 SDL_strlcpy(tmp_path, xdg_path, PATH_MAX);
78 SDL_strlcat(tmp_path, template, PATH_MAX);
80 fd = mkostemp(tmp_path, O_CLOEXEC);
84 if (ftruncate(fd, size) < 0) {
93 mouse_buffer_release(void *data, struct wl_buffer *buffer)
97 static const struct wl_buffer_listener mouse_buffer_listener = {
102 create_buffer_from_shm(Wayland_CursorData *d,
107 SDL_VideoDevice *vd = SDL_GetVideoDevice();
108 SDL_VideoData *data = (SDL_VideoData *) vd->driverdata;
109 struct wl_shm_pool *shm_pool;
111 int stride = width * 4;
112 int size = stride * height;
116 shm_fd = wayland_create_tmp_file(size);
119 fprintf(stderr, "creating mouse cursor buffer failed!\n");
123 d->shm_data = mmap(NULL,
125 PROT_READ | PROT_WRITE,
129 if (d->shm_data == MAP_FAILED) {
131 fprintf (stderr, "mmap () failed\n");
135 shm_pool = wl_shm_create_pool(data->shm, shm_fd, size);
136 d->buffer = wl_shm_pool_create_buffer(shm_pool,
142 wl_buffer_add_listener(d->buffer,
143 &mouse_buffer_listener,
146 wl_shm_pool_destroy (shm_pool);
153 Wayland_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y)
157 cursor = calloc(1, sizeof (*cursor));
159 SDL_VideoDevice *vd = SDL_GetVideoDevice ();
160 SDL_VideoData *wd = (SDL_VideoData *) vd->driverdata;
161 Wayland_CursorData *data = calloc (1, sizeof (Wayland_CursorData));
162 cursor->driverdata = (void *) data;
164 /* Assume ARGB8888 */
165 SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888);
166 SDL_assert(surface->pitch == surface->w * 4);
168 /* Allocate shared memory buffer for this cursor */
169 if (create_buffer_from_shm (data,
172 WL_SHM_FORMAT_XRGB8888) < 0)
174 free (cursor->driverdata);
179 SDL_memcpy(data->shm_data,
181 surface->h * surface->pitch);
183 data->surface = wl_compositor_create_surface(wd->compositor);
184 wl_surface_set_user_data(data->surface, NULL);
188 data->w = surface->w;
189 data->h = surface->h;
196 CreateCursorFromWlCursor(SDL_VideoData *d, struct wl_cursor *wlcursor)
200 cursor = calloc(1, sizeof (*cursor));
202 Wayland_CursorData *data = calloc (1, sizeof (Wayland_CursorData));
203 cursor->driverdata = (void *) data;
205 data->buffer = WAYLAND_wl_cursor_image_get_buffer(wlcursor->images[0]);
206 data->surface = wl_compositor_create_surface(d->compositor);
207 wl_surface_set_user_data(data->surface, NULL);
208 data->hot_x = wlcursor->images[0]->hotspot_x;
209 data->hot_y = wlcursor->images[0]->hotspot_y;
210 data->w = wlcursor->images[0]->width;
211 data->h = wlcursor->images[0]->height;
212 data->cursor= wlcursor;
221 Wayland_CreateDefaultCursor()
223 SDL_VideoDevice *device = SDL_GetVideoDevice();
224 SDL_VideoData *data = device->driverdata;
226 return CreateCursorFromWlCursor (data,
227 WAYLAND_wl_cursor_theme_get_cursor(data->cursor_theme,
232 Wayland_CreateSystemCursor(SDL_SystemCursor id)
234 SDL_VideoDevice *vd = SDL_GetVideoDevice();
235 SDL_VideoData *d = vd->driverdata;
237 struct wl_cursor *cursor = NULL;
244 case SDL_SYSTEM_CURSOR_ARROW:
245 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "left_ptr");
247 case SDL_SYSTEM_CURSOR_IBEAM:
248 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "xterm");
250 case SDL_SYSTEM_CURSOR_WAIT:
251 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "watch");
253 case SDL_SYSTEM_CURSOR_CROSSHAIR:
254 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
256 case SDL_SYSTEM_CURSOR_WAITARROW:
257 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "watch");
259 case SDL_SYSTEM_CURSOR_SIZENWSE:
260 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
262 case SDL_SYSTEM_CURSOR_SIZENESW:
263 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
265 case SDL_SYSTEM_CURSOR_SIZEWE:
266 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
268 case SDL_SYSTEM_CURSOR_SIZENS:
269 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
271 case SDL_SYSTEM_CURSOR_SIZEALL:
272 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
274 case SDL_SYSTEM_CURSOR_NO:
275 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "xterm");
277 case SDL_SYSTEM_CURSOR_HAND:
278 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
282 return CreateCursorFromWlCursor(d, cursor);
286 Wayland_FreeCursor(SDL_Cursor *cursor)
288 Wayland_CursorData *d;
293 d = cursor->driverdata;
295 /* Probably not a cursor we own */
299 if (d->buffer && !d->cursor)
300 wl_buffer_destroy(d->buffer);
303 wl_surface_destroy(d->surface);
305 /* Not sure what's meant to happen to shm_data */
306 free (cursor->driverdata);
311 Wayland_ShowCursor(SDL_Cursor *cursor)
313 SDL_VideoDevice *vd = SDL_GetVideoDevice();
314 SDL_VideoData *d = vd->driverdata;
316 struct wl_pointer *pointer = d->pointer;
323 Wayland_CursorData *data = cursor->driverdata;
325 wl_surface_attach(data->surface, data->buffer, 0, 0);
326 wl_surface_damage(data->surface, 0, 0, data->w, data->h);
327 wl_surface_commit(data->surface);
328 wl_pointer_set_cursor (pointer, 0,
335 wl_pointer_set_cursor (pointer, 0,
345 Wayland_WarpMouse(SDL_Window *window, int x, int y)
351 Wayland_WarpMouseGlobal(int x, int y)
353 return SDL_Unsupported();
357 Wayland_SetRelativeMouseMode(SDL_bool enabled)
359 return SDL_Unsupported();
363 Wayland_InitMouse(void)
365 SDL_Mouse *mouse = SDL_GetMouse();
367 mouse->CreateCursor = Wayland_CreateCursor;
368 mouse->CreateSystemCursor = Wayland_CreateSystemCursor;
369 mouse->ShowCursor = Wayland_ShowCursor;
370 mouse->FreeCursor = Wayland_FreeCursor;
371 mouse->WarpMouse = Wayland_WarpMouse;
372 mouse->WarpMouseGlobal = Wayland_WarpMouseGlobal;
373 mouse->SetRelativeMouseMode = Wayland_SetRelativeMouseMode;
375 SDL_SetDefaultCursor(Wayland_CreateDefaultCursor());
379 Wayland_FiniMouse(void)
381 /* This effectively assumes that nobody else
382 * touches SDL_Mouse which is effectively
385 SDL_Mouse *mouse = SDL_GetMouse();
387 /* Free the current cursor if not the same pointer as
388 * the default cursor */
389 if (mouse->def_cursor != mouse->cur_cursor)
390 Wayland_FreeCursor (mouse->cur_cursor);
392 Wayland_FreeCursor (mouse->def_cursor);
393 mouse->def_cursor = NULL;
394 mouse->cur_cursor = NULL;
396 mouse->CreateCursor = NULL;
397 mouse->CreateSystemCursor = NULL;
398 mouse->ShowCursor = NULL;
399 mouse->FreeCursor = NULL;
400 mouse->WarpMouse = NULL;
401 mouse->SetRelativeMouseMode = NULL;
403 #endif /* SDL_VIDEO_DRIVER_WAYLAND */