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