src/video/mir/SDL_mirmouse.c
author Philipp Wiesemann
Sat, 04 Mar 2017 23:05:32 +0100
changeset 10929 3a44f7762496
parent 10921 f426dbef4aa0
child 10990 b3c950a6fb09
permissions -rw-r--r--
Mir: Fixed crash if creating default cursor failed.

Found by Cppcheck.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2017 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 /*
    23   Contributed by Brandon Schaefer, <brandon.schaefer@canonical.com>
    24 */
    25 
    26 #include "../../SDL_internal.h"
    27 
    28 #if SDL_VIDEO_DRIVER_MIR
    29 
    30 #include "../../events/SDL_mouse_c.h"
    31 #include "../SDL_sysvideo.h"
    32 #include "SDL_assert.h"
    33 
    34 #include "SDL_mirdyn.h"
    35 
    36 #include "SDL_mirvideo.h"
    37 #include "SDL_mirmouse.h"
    38 #include "SDL_mirwindow.h"
    39 
    40 typedef struct
    41 {
    42     MirCursorConfiguration* conf;
    43     MirBufferStream*        stream;
    44     char const*             name;
    45 } MIR_Cursor;
    46 
    47 static SDL_Cursor*
    48 MIR_CreateDefaultCursor()
    49 {
    50     SDL_Cursor* cursor;
    51 
    52     cursor = SDL_calloc(1, sizeof(SDL_Cursor));
    53     if (cursor) {
    54 
    55         MIR_Cursor* mir_cursor = SDL_calloc(1, sizeof(MIR_Cursor));
    56         if (mir_cursor) {
    57             mir_cursor->conf   = NULL;
    58             mir_cursor->stream = NULL;
    59             mir_cursor->name   = NULL;
    60             cursor->driverdata = mir_cursor;
    61         }
    62         else {
    63             SDL_OutOfMemory();
    64             SDL_free(cursor);
    65             cursor = NULL;
    66         }
    67     }
    68     else {
    69         SDL_OutOfMemory();
    70     }
    71 
    72     return cursor;
    73 }
    74 
    75 static void
    76 CopySurfacePixelsToMirStream(SDL_Surface* surface, MirBufferStream* stream)
    77 {
    78     char* dest, *pixels;
    79     int i, s_w, s_h, r_stride, p_stride, bytes_per_pixel, bytes_per_row;
    80 
    81     MirGraphicsRegion region;
    82     MIR_mir_buffer_stream_get_graphics_region(stream, &region);
    83 
    84     s_w = surface->w;
    85     s_h = surface->h;
    86 
    87     bytes_per_pixel = surface->format->BytesPerPixel;
    88     bytes_per_row   = bytes_per_pixel * s_w;
    89 
    90     dest = region.vaddr;
    91     pixels = (char*)surface->pixels;
    92 
    93     r_stride = region.stride;
    94     p_stride = surface->pitch;
    95 
    96     for (i = 0; i < s_h; i++)
    97     {
    98         SDL_memcpy(dest, pixels, bytes_per_row);
    99         dest   += r_stride;
   100         pixels += p_stride;
   101     }
   102 }
   103 
   104 static SDL_Cursor*
   105 MIR_CreateCursor(SDL_Surface* surface, int hot_x, int hot_y)
   106 {
   107     MirCursorConfiguration* conf;
   108     MirBufferStream*        stream;
   109 
   110     int s_w = surface->w;
   111     int s_h = surface->h;
   112 
   113     MIR_Data* mir_data     = (MIR_Data*)SDL_GetVideoDevice()->driverdata;
   114     SDL_Cursor* cursor     = MIR_CreateDefaultCursor();
   115     MIR_Cursor* mir_cursor;
   116 
   117     if (!cursor) {
   118         return NULL;
   119     }
   120 
   121     mir_cursor = (MIR_Cursor*)cursor->driverdata;
   122 
   123     stream = MIR_mir_connection_create_buffer_stream_sync(mir_data->connection,
   124                                                           s_w, s_h, mir_data->pixel_format,
   125                                                           mir_buffer_usage_software);
   126 
   127     conf = MIR_mir_cursor_configuration_from_buffer_stream(stream, hot_x, hot_y);
   128 
   129     CopySurfacePixelsToMirStream(surface, stream);
   130     MIR_mir_buffer_stream_swap_buffers_sync(stream);
   131 
   132     mir_cursor->conf   = conf;
   133     mir_cursor->stream = stream;
   134 
   135     return cursor;
   136 }
   137 
   138 static SDL_Cursor*
   139 MIR_CreateSystemCursor(SDL_SystemCursor id)
   140 {
   141     char const* cursor_name = NULL;
   142     SDL_Cursor* cursor      = MIR_CreateDefaultCursor();
   143     MIR_Cursor* mir_cursor;
   144 
   145     if (!cursor) {
   146         return NULL;
   147     }
   148 
   149     mir_cursor = (MIR_Cursor*)cursor->driverdata;
   150 
   151     switch(id) {
   152         case SDL_SYSTEM_CURSOR_ARROW:
   153             cursor_name = MIR_mir_arrow_cursor_name;
   154             break;
   155         case SDL_SYSTEM_CURSOR_IBEAM:
   156             cursor_name = MIR_mir_caret_cursor_name;
   157             break;
   158         case SDL_SYSTEM_CURSOR_WAIT:
   159             cursor_name = MIR_mir_busy_cursor_name;
   160             break;
   161         case SDL_SYSTEM_CURSOR_CROSSHAIR:
   162             /* Unsupported */
   163             cursor_name = MIR_mir_arrow_cursor_name;
   164             break;
   165         case SDL_SYSTEM_CURSOR_WAITARROW:
   166             cursor_name = MIR_mir_busy_cursor_name;
   167             break;
   168         case SDL_SYSTEM_CURSOR_SIZENWSE:
   169             cursor_name = MIR_mir_omnidirectional_resize_cursor_name;
   170             break;
   171         case SDL_SYSTEM_CURSOR_SIZENESW:
   172             cursor_name = MIR_mir_omnidirectional_resize_cursor_name;
   173             break;
   174         case SDL_SYSTEM_CURSOR_SIZEWE:
   175             cursor_name = MIR_mir_horizontal_resize_cursor_name;
   176             break;
   177         case SDL_SYSTEM_CURSOR_SIZENS:
   178             cursor_name = MIR_mir_vertical_resize_cursor_name;
   179             break;
   180         case SDL_SYSTEM_CURSOR_SIZEALL:
   181             cursor_name = MIR_mir_omnidirectional_resize_cursor_name;
   182             break;
   183         case SDL_SYSTEM_CURSOR_NO:
   184             /* Unsupported */
   185             cursor_name = MIR_mir_closed_hand_cursor_name;
   186             break;
   187         case SDL_SYSTEM_CURSOR_HAND:
   188             cursor_name = MIR_mir_open_hand_cursor_name;
   189             break;
   190         default:
   191             SDL_assert(0);
   192             return NULL;
   193     }
   194 
   195     mir_cursor->name = cursor_name;
   196 
   197     return cursor;
   198 }
   199 
   200 static void
   201 MIR_FreeCursor(SDL_Cursor* cursor)
   202 {
   203     if (cursor) {
   204 
   205         if (cursor->driverdata) {
   206             MIR_Cursor* mir_cursor = (MIR_Cursor*)cursor->driverdata;
   207 
   208             if (mir_cursor->conf)
   209                 MIR_mir_cursor_configuration_destroy(mir_cursor->conf);
   210             if (mir_cursor->stream)
   211                 MIR_mir_buffer_stream_release_sync(mir_cursor->stream);
   212 
   213             SDL_free(mir_cursor);
   214         }
   215 
   216         SDL_free(cursor);
   217     }
   218 }
   219 
   220 static int
   221 MIR_ShowCursor(SDL_Cursor* cursor)
   222 {
   223     MIR_Data* mir_data      = (MIR_Data*)SDL_GetVideoDevice()->driverdata;
   224     MIR_Window* mir_window  = mir_data->current_window;
   225 
   226     if (cursor && cursor->driverdata) {
   227         if (mir_window && MIR_mir_window_is_valid(mir_window->window)) {
   228             MIR_Cursor* mir_cursor = (MIR_Cursor*)cursor->driverdata;
   229 
   230             if (mir_cursor->name != NULL) {
   231                 MirWindowSpec* spec = MIR_mir_create_window_spec(mir_data->connection);
   232                 MIR_mir_window_spec_set_cursor_name(spec, mir_cursor->name);
   233                 MIR_mir_window_apply_spec(mir_window->window, spec);
   234                 MIR_mir_window_spec_release(spec);
   235             }
   236 
   237             if (mir_cursor->conf) {
   238                 MIR_mir_window_configure_cursor(mir_window->window, mir_cursor->conf);
   239             }
   240         }
   241     }
   242     else if(mir_window && MIR_mir_window_is_valid(mir_window->window)) {
   243         MIR_mir_window_configure_cursor(mir_window->window, NULL);
   244     }
   245 
   246     return 0;
   247 }
   248 
   249 static void
   250 MIR_WarpMouse(SDL_Window* window, int x, int y)
   251 {
   252     SDL_Unsupported();
   253 }
   254 
   255 static int
   256 MIR_WarpMouseGlobal(int x, int y)
   257 {
   258     return SDL_Unsupported();
   259 }
   260 
   261 static int
   262 MIR_SetRelativeMouseMode(SDL_bool enabled)
   263 {
   264     return 0;
   265 }
   266 
   267 /* TODO Actually implement the cursor, need to wait for mir support */
   268 void
   269 MIR_InitMouse()
   270 {
   271     SDL_Mouse* mouse = SDL_GetMouse();
   272 
   273     mouse->CreateCursor         = MIR_CreateCursor;
   274     mouse->ShowCursor           = MIR_ShowCursor;
   275     mouse->FreeCursor           = MIR_FreeCursor;
   276     mouse->WarpMouse            = MIR_WarpMouse;
   277     mouse->WarpMouseGlobal      = MIR_WarpMouseGlobal;
   278     mouse->CreateSystemCursor   = MIR_CreateSystemCursor;
   279     mouse->SetRelativeMouseMode = MIR_SetRelativeMouseMode;
   280 
   281     SDL_SetDefaultCursor(MIR_CreateDefaultCursor());
   282 }
   283 
   284 void
   285 MIR_FiniMouse()
   286 {
   287     SDL_Mouse* mouse = SDL_GetMouse();
   288 
   289     MIR_FreeCursor(mouse->def_cursor);
   290     mouse->def_cursor = NULL;
   291 
   292     mouse->CreateCursor         = NULL;
   293     mouse->ShowCursor           = NULL;
   294     mouse->FreeCursor           = NULL;
   295     mouse->WarpMouse            = NULL;
   296     mouse->CreateSystemCursor   = NULL;
   297     mouse->SetRelativeMouseMode = NULL;
   298 }
   299 
   300 #endif /* SDL_VIDEO_DRIVER_MIR */
   301 
   302 /* vi: set ts=4 sw=4 expandtab: */
   303