src/video/wayland/SDL_waylandmouse.c
author Sam Lantinga
Tue, 20 Oct 2020 11:51:23 -0700
changeset 14181 5e54294cae9e
parent 13867 cf1e807e68e2
permissions -rw-r--r--
Fixed bug 5323 - SDL_SetWindowMaximumSize fails if Width or Height is equal to minimum Height or Width

batyastudios

Basicly there is problem and somewhat a solution: https://discourse.libsdl.org/t/setwindowmaximumsize-bug/28267

If you SDL_SetWindowMaximumSize() after SDL_SetWindowMinimumSize() with one of axes have the same value, function will have no effect.

This: (line 2144@SDL_video.c)
if (max_w <= window->min_w || max_h <= window->min_h) {
SDL_SetError("SDL_SetWindowMaximumSize(): Tried to set maximum size smaller than minimum size");
return;
}

May be changed to this:
if (max_w < window->min_w || max_h < window->min_h) {
SDL_SetError("SDL_SetWindowMaximumSize(): Tried to set maximum size smaller than minimum size");
return;
}
     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 #include "SDL_assert.h"
    44 
    45 
    46 typedef 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 
    58 static int
    59 wayland_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 
    86 static void
    87 mouse_buffer_release(void *data, struct wl_buffer *buffer)
    88 {
    89 }
    90 
    91 static const struct wl_buffer_listener mouse_buffer_listener = {
    92     mouse_buffer_release
    93 };
    94 
    95 static int
    96 create_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     SDL_assert(d->shm_data != NULL);
   129 
   130     shm_pool = wl_shm_create_pool(data->shm, shm_fd, size);
   131     d->buffer = wl_shm_pool_create_buffer(shm_pool,
   132                                           0,
   133                                           width,
   134                                           height,
   135                                           stride,
   136                                           format);
   137     wl_buffer_add_listener(d->buffer,
   138                            &mouse_buffer_listener,
   139                            d);
   140 
   141     wl_shm_pool_destroy (shm_pool);
   142     close (shm_fd);
   143 
   144     return 0;
   145 }
   146 
   147 static SDL_Cursor *
   148 Wayland_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y)
   149 {
   150     SDL_Cursor *cursor;
   151 
   152     cursor = calloc(1, sizeof (*cursor));
   153     if (cursor) {
   154         SDL_VideoDevice *vd = SDL_GetVideoDevice ();
   155         SDL_VideoData *wd = (SDL_VideoData *) vd->driverdata;
   156         Wayland_CursorData *data = calloc (1, sizeof (Wayland_CursorData));
   157         if (!data) {
   158             SDL_OutOfMemory();
   159             free(cursor);
   160             return NULL;
   161         }
   162         cursor->driverdata = (void *) data;
   163 
   164         /* Assume ARGB8888 */
   165         SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888);
   166         SDL_assert(surface->pitch == surface->w * 4);
   167 
   168         /* Allocate shared memory buffer for this cursor */
   169         if (create_buffer_from_shm (data,
   170                                     surface->w,
   171                                     surface->h,
   172                                     WL_SHM_FORMAT_ARGB8888) < 0)
   173         {
   174             free (cursor->driverdata);
   175             free (cursor);
   176             return NULL;
   177         }
   178 
   179         SDL_memcpy(data->shm_data,
   180                    surface->pixels,
   181                    surface->h * surface->pitch);
   182 
   183         data->surface = wl_compositor_create_surface(wd->compositor);
   184         wl_surface_set_user_data(data->surface, NULL);
   185 
   186         data->hot_x = hot_x;
   187         data->hot_y = hot_y;
   188         data->w = surface->w;
   189         data->h = surface->h;
   190     } else {
   191         SDL_OutOfMemory();
   192     }
   193 
   194     return cursor;
   195 }
   196 
   197 static SDL_Cursor *
   198 CreateCursorFromWlCursor(SDL_VideoData *d, struct wl_cursor *wlcursor)
   199 {
   200     SDL_Cursor *cursor;
   201 
   202     cursor = calloc(1, sizeof (*cursor));
   203     if (cursor) {
   204         Wayland_CursorData *data = calloc (1, sizeof (Wayland_CursorData));
   205         if (!data) {
   206             SDL_OutOfMemory();
   207             free(cursor);
   208             return NULL;
   209         }
   210         cursor->driverdata = (void *) data;
   211 
   212         data->buffer = WAYLAND_wl_cursor_image_get_buffer(wlcursor->images[0]);
   213         data->surface = wl_compositor_create_surface(d->compositor);
   214         wl_surface_set_user_data(data->surface, NULL);
   215         data->hot_x = wlcursor->images[0]->hotspot_x;
   216         data->hot_y = wlcursor->images[0]->hotspot_y;
   217         data->w = wlcursor->images[0]->width;
   218         data->h = wlcursor->images[0]->height;
   219         data->cursor= wlcursor;
   220     } else {
   221         SDL_OutOfMemory ();
   222     }
   223 
   224     return cursor;
   225 }
   226 
   227 static SDL_Cursor *
   228 Wayland_CreateDefaultCursor()
   229 {
   230     SDL_VideoDevice *device = SDL_GetVideoDevice();
   231     SDL_VideoData *data = device->driverdata;
   232 
   233     return CreateCursorFromWlCursor (data,
   234                                      WAYLAND_wl_cursor_theme_get_cursor(data->cursor_theme,
   235                                                                 "left_ptr"));
   236 }
   237 
   238 static SDL_Cursor *
   239 Wayland_CreateSystemCursor(SDL_SystemCursor id)
   240 {
   241     SDL_VideoDevice *vd = SDL_GetVideoDevice();
   242     SDL_VideoData *d = vd->driverdata;
   243 
   244     struct wl_cursor *cursor = NULL;
   245 
   246     switch(id)
   247     {
   248     default:
   249         SDL_assert(0);
   250         return NULL;
   251     case SDL_SYSTEM_CURSOR_ARROW:
   252         cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "left_ptr");
   253         break;
   254     case SDL_SYSTEM_CURSOR_IBEAM:
   255         cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "xterm");
   256         break;
   257     case SDL_SYSTEM_CURSOR_WAIT:
   258         cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "watch");
   259         break;
   260     case SDL_SYSTEM_CURSOR_CROSSHAIR:
   261         cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
   262         break;
   263     case SDL_SYSTEM_CURSOR_WAITARROW:
   264         cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "watch");
   265         break;
   266     case SDL_SYSTEM_CURSOR_SIZENWSE:
   267         cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
   268         break;
   269     case SDL_SYSTEM_CURSOR_SIZENESW:
   270         cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
   271         break;
   272     case SDL_SYSTEM_CURSOR_SIZEWE:
   273         cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
   274         break;
   275     case SDL_SYSTEM_CURSOR_SIZENS:
   276         cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
   277         break;
   278     case SDL_SYSTEM_CURSOR_SIZEALL:
   279         cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
   280         break;
   281     case SDL_SYSTEM_CURSOR_NO:
   282         cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "xterm");
   283         break;
   284     case SDL_SYSTEM_CURSOR_HAND:
   285         cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
   286         break;
   287     }
   288 
   289     return CreateCursorFromWlCursor(d, cursor);
   290 }
   291 
   292 static void
   293 Wayland_FreeCursor(SDL_Cursor *cursor)
   294 {
   295     Wayland_CursorData *d;
   296 
   297     if (!cursor)
   298         return;
   299 
   300     d = cursor->driverdata;
   301 
   302     /* Probably not a cursor we own */
   303     if (!d)
   304         return;
   305 
   306     if (d->buffer && !d->cursor)
   307         wl_buffer_destroy(d->buffer);
   308 
   309     if (d->surface)
   310         wl_surface_destroy(d->surface);
   311 
   312     /* Not sure what's meant to happen to shm_data */
   313     free (cursor->driverdata);
   314     SDL_free(cursor);
   315 }
   316 
   317 static int
   318 Wayland_ShowCursor(SDL_Cursor *cursor)
   319 {
   320     SDL_VideoDevice *vd = SDL_GetVideoDevice();
   321     SDL_VideoData *d = vd->driverdata;
   322 
   323     struct wl_pointer *pointer = d->pointer;
   324 
   325     if (!pointer)
   326         return -1;
   327 
   328     if (cursor)
   329     {
   330         Wayland_CursorData *data = cursor->driverdata;
   331 
   332         wl_pointer_set_cursor (pointer, 0,
   333                                data->surface,
   334                                data->hot_x,
   335                                data->hot_y);
   336         wl_surface_attach(data->surface, data->buffer, 0, 0);
   337         wl_surface_damage(data->surface, 0, 0, data->w, data->h);
   338         wl_surface_commit(data->surface);
   339     }
   340     else
   341     {
   342         wl_pointer_set_cursor (pointer, 0,
   343                                NULL,
   344                                0,
   345                                0);
   346     }
   347     
   348     return 0;
   349 }
   350 
   351 static void
   352 Wayland_WarpMouse(SDL_Window *window, int x, int y)
   353 {
   354     SDL_Unsupported();
   355 }
   356 
   357 static int
   358 Wayland_WarpMouseGlobal(int x, int y)
   359 {
   360     return SDL_Unsupported();
   361 }
   362 
   363 static int
   364 Wayland_SetRelativeMouseMode(SDL_bool enabled)
   365 {
   366     SDL_VideoDevice *vd = SDL_GetVideoDevice();
   367     SDL_VideoData *data = (SDL_VideoData *) vd->driverdata;
   368 
   369     if (enabled)
   370         return Wayland_input_lock_pointer(data->input);
   371     else
   372         return Wayland_input_unlock_pointer(data->input);
   373 }
   374 
   375 void
   376 Wayland_InitMouse(void)
   377 {
   378     SDL_Mouse *mouse = SDL_GetMouse();
   379 
   380     mouse->CreateCursor = Wayland_CreateCursor;
   381     mouse->CreateSystemCursor = Wayland_CreateSystemCursor;
   382     mouse->ShowCursor = Wayland_ShowCursor;
   383     mouse->FreeCursor = Wayland_FreeCursor;
   384     mouse->WarpMouse = Wayland_WarpMouse;
   385     mouse->WarpMouseGlobal = Wayland_WarpMouseGlobal;
   386     mouse->SetRelativeMouseMode = Wayland_SetRelativeMouseMode;
   387 
   388     SDL_SetDefaultCursor(Wayland_CreateDefaultCursor());
   389 }
   390 
   391 void
   392 Wayland_FiniMouse(void)
   393 {
   394     /* This effectively assumes that nobody else
   395      * touches SDL_Mouse which is effectively
   396      * a singleton */
   397 }
   398 #endif  /* SDL_VIDEO_DRIVER_WAYLAND */