Atlas - SDL_waylandmouse.c

Home / ext / SDL2 / src / video / wayland Lines: 1 | Size: 10924 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2018 Sam Lantinga <[email protected]> 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, 99 uint32_t format) 100{ 101 SDL_VideoDevice *vd = SDL_GetVideoDevice(); 102 SDL_VideoData *data = (SDL_VideoData *) vd->driverdata; 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); 135 wl_buffer_add_listener(d->buffer, 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{ 148 SDL_Cursor *cursor; 149 150 cursor = calloc(1, sizeof (*cursor)); 151 if (cursor) { 152 SDL_VideoDevice *vd = SDL_GetVideoDevice (); 153 SDL_VideoData *wd = (SDL_VideoData *) vd->driverdata; 154 Wayland_CursorData *data = calloc (1, sizeof (Wayland_CursorData)); 155 if (!data) { 156 SDL_OutOfMemory(); 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, 170 WL_SHM_FORMAT_ARGB8888) < 0) 171 { 172 free (cursor->driverdata); 173 free (cursor); 174 return NULL; 175 } 176 177 SDL_memcpy(data->shm_data, 178 surface->pixels, 179 surface->h * surface->pitch); 180 181 data->surface = wl_compositor_create_surface(wd->compositor); 182 wl_surface_set_user_data(data->surface, NULL); 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 { 189 SDL_OutOfMemory(); 190 } 191 192 return cursor; 193} 194 195static SDL_Cursor * 196CreateCursorFromWlCursor(SDL_VideoData *d, struct wl_cursor *wlcursor) 197{ 198 SDL_Cursor *cursor; 199 200 cursor = calloc(1, sizeof (*cursor)); 201 if (cursor) { 202 Wayland_CursorData *data = calloc (1, sizeof (Wayland_CursorData)); 203 if (!data) { 204 SDL_OutOfMemory(); 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); 212 wl_surface_set_user_data(data->surface, NULL); 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 { 219 SDL_OutOfMemory (); 220 } 221 222 return cursor; 223} 224 225static SDL_Cursor * 226Wayland_CreateDefaultCursor() 227{ 228 SDL_VideoDevice *device = SDL_GetVideoDevice(); 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{ 239 SDL_VideoDevice *vd = SDL_GetVideoDevice(); 240 SDL_VideoData *d = vd->driverdata; 241 242 struct wl_cursor *cursor = NULL; 243 244 switch(id) 245 { 246 default: 247 SDL_assert(0); 248 return NULL; 249 case SDL_SYSTEM_CURSOR_ARROW: 250 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "left_ptr"); 251 break; 252 case SDL_SYSTEM_CURSOR_IBEAM: 253 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "xterm"); 254 break; 255 case SDL_SYSTEM_CURSOR_WAIT: 256 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "watch"); 257 break; 258 case SDL_SYSTEM_CURSOR_CROSSHAIR: 259 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1"); 260 break; 261 case SDL_SYSTEM_CURSOR_WAITARROW: 262 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "watch"); 263 break; 264 case SDL_SYSTEM_CURSOR_SIZENWSE: 265 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1"); 266 break; 267 case SDL_SYSTEM_CURSOR_SIZENESW: 268 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1"); 269 break; 270 case SDL_SYSTEM_CURSOR_SIZEWE: 271 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1"); 272 break; 273 case SDL_SYSTEM_CURSOR_SIZENS: 274 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1"); 275 break; 276 case SDL_SYSTEM_CURSOR_SIZEALL: 277 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1"); 278 break; 279 case SDL_SYSTEM_CURSOR_NO: 280 cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "xterm"); 281 break; 282 case SDL_SYSTEM_CURSOR_HAND: 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 298 d = cursor->driverdata; 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 */ 311 free (cursor->driverdata); 312 SDL_free(cursor); 313} 314 315static int 316Wayland_ShowCursor(SDL_Cursor *cursor) 317{ 318 SDL_VideoDevice *vd = SDL_GetVideoDevice(); 319 SDL_VideoData *d = vd->driverdata; 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 330 wl_pointer_set_cursor (pointer, 0, 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 { 340 wl_pointer_set_cursor (pointer, 0, 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{ 352 SDL_Unsupported(); 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{ 364 SDL_VideoDevice *vd = SDL_GetVideoDevice(); 365 SDL_VideoData *data = (SDL_VideoData *) vd->driverdata; 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 */ 397
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.