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