src/video/android/SDL_androidmouse.c
author Sylvain Becker <sylvain.becker@gmail.com>
Thu, 03 Jan 2019 13:14:16 +0100
changeset 12494 6053ab61996a
parent 12462 b57435750c5b
child 12503 806492103856
permissions -rw-r--r--
Android: preparation bug 4142, reduce usage of global variable Android_Window
joseba@9438
     1
/*
joseba@9438
     2
  Simple DirectMedia Layer
slouken@11811
     3
  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
joseba@9438
     4
joseba@9438
     5
  This software is provided 'as-is', without any express or implied
joseba@9438
     6
  warranty.  In no event will the authors be held liable for any damages
joseba@9438
     7
  arising from the use of this software.
joseba@9438
     8
joseba@9438
     9
  Permission is granted to anyone to use this software for any purpose,
joseba@9438
    10
  including commercial applications, and to alter it and redistribute it
joseba@9438
    11
  freely, subject to the following restrictions:
joseba@9438
    12
joseba@9438
    13
  1. The origin of this software must not be misrepresented; you must not
joseba@9438
    14
     claim that you wrote the original software. If you use this software
joseba@9438
    15
     in a product, an acknowledgment in the product documentation would be
joseba@9438
    16
     appreciated but is not required.
joseba@9438
    17
  2. Altered source versions must be plainly marked as such, and must not be
joseba@9438
    18
     misrepresented as being the original software.
joseba@9438
    19
  3. This notice may not be removed or altered from any source distribution.
joseba@9438
    20
*/
joseba@9438
    21
joseba@9438
    22
#include "../../SDL_internal.h"
joseba@9438
    23
joseba@9438
    24
#if SDL_VIDEO_DRIVER_ANDROID
joseba@9438
    25
joseba@9438
    26
#include "SDL_androidmouse.h"
joseba@9438
    27
joseba@9438
    28
#include "SDL_events.h"
joseba@9438
    29
#include "../../events/SDL_mouse_c.h"
joseba@9438
    30
joseba@9438
    31
#include "../../core/android/SDL_android.h"
joseba@9438
    32
slouken@11237
    33
/* See Android's MotionEvent class for constants */
joseba@9438
    34
#define ACTION_DOWN 0
joseba@9438
    35
#define ACTION_UP 1
philipp@10295
    36
#define ACTION_MOVE 2
joseba@9438
    37
#define ACTION_HOVER_MOVE 7
joseba@9438
    38
#define ACTION_SCROLL 8
joseba@9438
    39
#define BUTTON_PRIMARY 1
joseba@9438
    40
#define BUTTON_SECONDARY 2
joseba@9438
    41
#define BUTTON_TERTIARY 4
philipp@10049
    42
#define BUTTON_BACK 8
philipp@10049
    43
#define BUTTON_FORWARD 16
joseba@9438
    44
slouken@11931
    45
typedef struct
slouken@11931
    46
{
slouken@11931
    47
    int custom_cursor;
slouken@11931
    48
    int system_cursor;
slouken@11931
    49
slouken@11931
    50
} SDL_AndroidCursorData;
slouken@11931
    51
slouken@11237
    52
/* Last known Android mouse button state (includes all buttons) */
slouken@11237
    53
static int last_state;
philipp@10051
    54
slouken@12025
    55
/* Blank cursor */
slouken@12025
    56
static SDL_Cursor *empty_cursor;
slouken@11931
    57
slouken@11931
    58
static SDL_Cursor *
slouken@11931
    59
Android_WrapCursor(int custom_cursor, int system_cursor)
slouken@11931
    60
{
slouken@11931
    61
    SDL_Cursor *cursor;
slouken@11931
    62
slouken@11931
    63
    cursor = SDL_calloc(1, sizeof(*cursor));
slouken@11931
    64
    if (cursor) {
sylvain@12494
    65
        SDL_AndroidCursorData *data = (SDL_AndroidCursorData *)SDL_calloc(1, sizeof(*data));
slouken@11931
    66
        if (data) {
slouken@11931
    67
            data->custom_cursor = custom_cursor;
slouken@11931
    68
            data->system_cursor = system_cursor;
slouken@11931
    69
            cursor->driverdata = data;
slouken@11931
    70
        } else {
slouken@11931
    71
            SDL_free(cursor);
slouken@11931
    72
            cursor = NULL;
slouken@11931
    73
            SDL_OutOfMemory();
slouken@11931
    74
        }
slouken@11931
    75
    } else {
slouken@11931
    76
        SDL_OutOfMemory();
slouken@11931
    77
    }
slouken@11931
    78
slouken@11931
    79
    return cursor;
slouken@11931
    80
}
slouken@11931
    81
slouken@11931
    82
static SDL_Cursor *
slouken@11931
    83
Android_CreateDefaultCursor()
slouken@11931
    84
{
slouken@11931
    85
    return Android_WrapCursor(0, SDL_SYSTEM_CURSOR_ARROW);
slouken@11931
    86
}
slouken@11931
    87
slouken@11931
    88
static SDL_Cursor *
slouken@11931
    89
Android_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
slouken@11931
    90
{
slouken@11931
    91
    int custom_cursor;
slouken@11931
    92
    SDL_Surface *converted;
slouken@11931
    93
slouken@11931
    94
    converted = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888, 0);
slouken@11931
    95
    if (!converted) {
slouken@11931
    96
        return NULL;
slouken@11931
    97
    }
slouken@11931
    98
    custom_cursor = Android_JNI_CreateCustomCursor(converted, hot_x, hot_y);
slouken@11931
    99
    SDL_FreeSurface(converted);
slouken@11931
   100
    if (!custom_cursor) {
slouken@11931
   101
        SDL_Unsupported();
slouken@11931
   102
        return NULL;
slouken@11931
   103
    }
slouken@11931
   104
    return Android_WrapCursor(custom_cursor, 0);
slouken@11931
   105
}
slouken@11931
   106
slouken@11931
   107
static SDL_Cursor *
slouken@11931
   108
Android_CreateSystemCursor(SDL_SystemCursor id)
slouken@11931
   109
{
slouken@11931
   110
    return Android_WrapCursor(0, id);
slouken@11931
   111
}
slouken@11931
   112
slouken@11931
   113
static void
slouken@11931
   114
Android_FreeCursor(SDL_Cursor * cursor)
slouken@11931
   115
{
slouken@11931
   116
    SDL_free(cursor->driverdata);
slouken@11931
   117
    SDL_free(cursor);
slouken@11931
   118
}
slouken@11931
   119
slouken@12025
   120
static SDL_Cursor *
slouken@12025
   121
Android_CreateEmptyCursor()
slouken@12025
   122
{
slouken@12025
   123
    if (!empty_cursor) {
slouken@12025
   124
        SDL_Surface *empty_surface = SDL_CreateRGBSurfaceWithFormat(0, 1, 1, 32, SDL_PIXELFORMAT_ARGB8888);
slouken@12025
   125
        if (empty_surface) {
slouken@12025
   126
            SDL_memset(empty_surface->pixels, 0, empty_surface->h * empty_surface->pitch);
slouken@12025
   127
            empty_cursor = Android_CreateCursor(empty_surface, 0, 0);
slouken@12025
   128
            SDL_FreeSurface(empty_surface);
slouken@12025
   129
        }
slouken@12025
   130
    }
slouken@12025
   131
    return empty_cursor;
slouken@12025
   132
}
slouken@12025
   133
slouken@12025
   134
static void
slouken@12025
   135
Android_DestroyEmptyCursor()
slouken@12025
   136
{
slouken@12025
   137
    if (empty_cursor) {
slouken@12025
   138
        Android_FreeCursor(empty_cursor);
slouken@12025
   139
        empty_cursor = NULL;
slouken@12025
   140
    }
slouken@12025
   141
}
slouken@12025
   142
slouken@11931
   143
static int
sylvain@12494
   144
Android_ShowCursor(SDL_Cursor *cursor)
slouken@11931
   145
{
slouken@12025
   146
    if (!cursor) {
slouken@12025
   147
        cursor = Android_CreateEmptyCursor();
slouken@12025
   148
    }
slouken@11931
   149
    if (cursor) {
sylvain@12494
   150
        SDL_AndroidCursorData *data = (SDL_AndroidCursorData *)cursor->driverdata;
slouken@11931
   151
        if (data->custom_cursor) {
slouken@11932
   152
            if (!Android_JNI_SetCustomCursor(data->custom_cursor)) {
slouken@11932
   153
                return SDL_Unsupported();
slouken@11932
   154
            }
slouken@11931
   155
        } else {
slouken@11932
   156
            if (!Android_JNI_SetSystemCursor(data->system_cursor)) {
slouken@11932
   157
                return SDL_Unsupported();
slouken@11932
   158
            }
slouken@11931
   159
        }
slouken@12025
   160
        return 0;
slouken@11931
   161
    } else {
slouken@12025
   162
        /* SDL error set inside Android_CreateEmptyCursor() */
slouken@12025
   163
        return -1;
slouken@11931
   164
    }
slouken@11931
   165
}
slouken@11931
   166
slouken@12007
   167
static int
slouken@12007
   168
Android_SetRelativeMouseMode(SDL_bool enabled)
slouken@12007
   169
{
slouken@12007
   170
    if (!Android_JNI_SupportsRelativeMouse()) {
slouken@12007
   171
        return SDL_Unsupported();
slouken@12007
   172
    }
slouken@12007
   173
slouken@12007
   174
    if (!Android_JNI_SetRelativeMouseEnabled(enabled)) {
slouken@12007
   175
        return SDL_Unsupported();
slouken@12007
   176
    }
slouken@12007
   177
slouken@12007
   178
    return 0;
slouken@12007
   179
}
slouken@12007
   180
philipp@10051
   181
void
philipp@10051
   182
Android_InitMouse(void)
philipp@10051
   183
{
slouken@11931
   184
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@11931
   185
slouken@11931
   186
    mouse->CreateCursor = Android_CreateCursor;
slouken@11931
   187
    mouse->CreateSystemCursor = Android_CreateSystemCursor;
slouken@11931
   188
    mouse->ShowCursor = Android_ShowCursor;
slouken@11931
   189
    mouse->FreeCursor = Android_FreeCursor;
slouken@12007
   190
    mouse->SetRelativeMouseMode = Android_SetRelativeMouseMode;
slouken@11931
   191
slouken@11931
   192
    SDL_SetDefaultCursor(Android_CreateDefaultCursor());
slouken@11931
   193
slouken@11237
   194
    last_state = 0;
philipp@10051
   195
}
philipp@10051
   196
slouken@12025
   197
void
slouken@12025
   198
Android_QuitMouse(void)
slouken@12025
   199
{
slouken@12025
   200
    Android_DestroyEmptyCursor();
slouken@12025
   201
}
slouken@12025
   202
slouken@11237
   203
/* Translate Android mouse button state to SDL mouse button */
slouken@11237
   204
static Uint8
slouken@11237
   205
TranslateButton(int state)
slouken@11237
   206
{
slouken@11237
   207
    if (state & BUTTON_PRIMARY) {
slouken@11237
   208
        return SDL_BUTTON_LEFT;
slouken@11237
   209
    } else if (state & BUTTON_SECONDARY) {
slouken@11237
   210
        return SDL_BUTTON_RIGHT;
slouken@11237
   211
    } else if (state & BUTTON_TERTIARY) {
slouken@11237
   212
        return SDL_BUTTON_MIDDLE;
slouken@11237
   213
    } else if (state & BUTTON_FORWARD) {
slouken@11237
   214
        return SDL_BUTTON_X1;
slouken@11237
   215
    } else if (state & BUTTON_BACK) {
slouken@11237
   216
        return SDL_BUTTON_X2;
slouken@11237
   217
    } else {
slouken@11237
   218
        return 0;
slouken@11237
   219
    }
slouken@11237
   220
}
slouken@11237
   221
slouken@11237
   222
void
sylvain@12494
   223
Android_OnMouse(SDL_Window *window, int state, int action, float x, float y, SDL_bool relative)
slouken@11237
   224
{
slouken@11237
   225
    int changes;
slouken@11237
   226
    Uint8 button;
slouken@11237
   227
sylvain@12494
   228
    if (!window) {
joseba@9438
   229
        return;
joseba@9438
   230
    }
joseba@9438
   231
joseba@9438
   232
    switch(action) {
joseba@9438
   233
        case ACTION_DOWN:
slouken@11237
   234
            changes = state & ~last_state;
slouken@11237
   235
            button = TranslateButton(changes);
slouken@11237
   236
            last_state = state;
sylvain@12494
   237
            SDL_SendMouseMotion(window, 0, relative, (int)x, (int)y);
sylvain@12494
   238
            SDL_SendMouseButton(window, 0, SDL_PRESSED, button);
joseba@9438
   239
            break;
joseba@9438
   240
joseba@9438
   241
        case ACTION_UP:
slouken@11237
   242
            changes = last_state & ~state;
slouken@11237
   243
            button = TranslateButton(changes);
slouken@11237
   244
            last_state = state;
sylvain@12494
   245
            SDL_SendMouseMotion(window, 0, relative, (int)x, (int)y);
sylvain@12494
   246
            SDL_SendMouseButton(window, 0, SDL_RELEASED, button);
joseba@9438
   247
            break;
joseba@9438
   248
philipp@10295
   249
        case ACTION_MOVE:
joseba@9438
   250
        case ACTION_HOVER_MOVE:
sylvain@12494
   251
            SDL_SendMouseMotion(window, 0, relative, (int)x, (int)y);
joseba@9438
   252
            break;
joseba@9438
   253
joseba@9438
   254
        case ACTION_SCROLL:
sylvain@12494
   255
            SDL_SendMouseWheel(window, 0, x, y, SDL_MOUSEWHEEL_NORMAL);
joseba@9438
   256
            break;
joseba@9438
   257
joseba@9438
   258
        default:
joseba@9438
   259
            break;
joseba@9438
   260
    }
joseba@9438
   261
}
joseba@9438
   262
joseba@9438
   263
#endif /* SDL_VIDEO_DRIVER_ANDROID */
joseba@9438
   264
joseba@9438
   265
/* vi: set ts=4 sw=4 expandtab: */
joseba@9438
   266