src/video/android/SDL_androidmouse.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 05 Jun 2018 12:46:11 -0700
changeset 12007 ecfb6a793c30
parent 11932 a05a909eeddb
child 12025 39a92b19f99e
permissions -rw-r--r--
Add Android support for relative mouse mode to SDL.
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@11931
    55
slouken@11931
    56
static SDL_Cursor *
slouken@11931
    57
Android_WrapCursor(int custom_cursor, int system_cursor)
slouken@11931
    58
{
slouken@11931
    59
    SDL_Cursor *cursor;
slouken@11931
    60
slouken@11931
    61
    cursor = SDL_calloc(1, sizeof(*cursor));
slouken@11931
    62
    if (cursor) {
slouken@11931
    63
        SDL_AndroidCursorData *data = (SDL_AndroidCursorData*)SDL_calloc(1, sizeof(*data));
slouken@11931
    64
        if (data) {
slouken@11931
    65
            data->custom_cursor = custom_cursor;
slouken@11931
    66
            data->system_cursor = system_cursor;
slouken@11931
    67
            cursor->driverdata = data;
slouken@11931
    68
        } else {
slouken@11931
    69
            SDL_free(cursor);
slouken@11931
    70
            cursor = NULL;
slouken@11931
    71
            SDL_OutOfMemory();
slouken@11931
    72
        }
slouken@11931
    73
    } else {
slouken@11931
    74
        SDL_OutOfMemory();
slouken@11931
    75
    }
slouken@11931
    76
slouken@11931
    77
    return cursor;
slouken@11931
    78
}
slouken@11931
    79
slouken@11931
    80
static SDL_Cursor *
slouken@11931
    81
Android_CreateDefaultCursor()
slouken@11931
    82
{
slouken@11931
    83
    return Android_WrapCursor(0, SDL_SYSTEM_CURSOR_ARROW);
slouken@11931
    84
}
slouken@11931
    85
slouken@11931
    86
static SDL_Cursor *
slouken@11931
    87
Android_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
slouken@11931
    88
{
slouken@11931
    89
    int custom_cursor;
slouken@11931
    90
    SDL_Surface *converted;
slouken@11931
    91
slouken@11931
    92
    converted = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888, 0);
slouken@11931
    93
    if (!converted) {
slouken@11931
    94
        return NULL;
slouken@11931
    95
    }
slouken@11931
    96
    custom_cursor = Android_JNI_CreateCustomCursor(converted, hot_x, hot_y);
slouken@11931
    97
    SDL_FreeSurface(converted);
slouken@11931
    98
    if (!custom_cursor) {
slouken@11931
    99
        SDL_Unsupported();
slouken@11931
   100
        return NULL;
slouken@11931
   101
    }
slouken@11931
   102
    return Android_WrapCursor(custom_cursor, 0);
slouken@11931
   103
}
slouken@11931
   104
slouken@11931
   105
static SDL_Cursor *
slouken@11931
   106
Android_CreateSystemCursor(SDL_SystemCursor id)
slouken@11931
   107
{
slouken@11931
   108
    return Android_WrapCursor(0, id);
slouken@11931
   109
}
slouken@11931
   110
slouken@11931
   111
static void
slouken@11931
   112
Android_FreeCursor(SDL_Cursor * cursor)
slouken@11931
   113
{
slouken@11931
   114
    SDL_free(cursor->driverdata);
slouken@11931
   115
    SDL_free(cursor);
slouken@11931
   116
}
slouken@11931
   117
slouken@11931
   118
static int
slouken@11931
   119
Android_ShowCursor(SDL_Cursor * cursor)
slouken@11931
   120
{
slouken@11931
   121
    if (cursor) {
slouken@11931
   122
        SDL_AndroidCursorData *data = (SDL_AndroidCursorData*)cursor->driverdata;
slouken@11931
   123
        if (data->custom_cursor) {
slouken@11932
   124
            if (!Android_JNI_SetCustomCursor(data->custom_cursor)) {
slouken@11932
   125
                return SDL_Unsupported();
slouken@11932
   126
            }
slouken@11931
   127
        } else {
slouken@11932
   128
            if (!Android_JNI_SetSystemCursor(data->system_cursor)) {
slouken@11932
   129
                return SDL_Unsupported();
slouken@11932
   130
            }
slouken@11931
   131
        }
slouken@11931
   132
    } else {
slouken@11932
   133
        if (!Android_JNI_SetSystemCursor(-1)) {
slouken@11932
   134
            return SDL_Unsupported();
slouken@11932
   135
        }
slouken@11931
   136
    }
slouken@11931
   137
    return 0;
slouken@11931
   138
}
slouken@11931
   139
slouken@12007
   140
static int
slouken@12007
   141
Android_SetRelativeMouseMode(SDL_bool enabled)
slouken@12007
   142
{
slouken@12007
   143
    if (!Android_JNI_SupportsRelativeMouse()) {
slouken@12007
   144
        return SDL_Unsupported();
slouken@12007
   145
    }
slouken@12007
   146
slouken@12007
   147
    if (!Android_JNI_SetRelativeMouseEnabled(enabled)) {
slouken@12007
   148
        return SDL_Unsupported();
slouken@12007
   149
    }
slouken@12007
   150
slouken@12007
   151
    return 0;
slouken@12007
   152
}
slouken@12007
   153
philipp@10051
   154
void
philipp@10051
   155
Android_InitMouse(void)
philipp@10051
   156
{
slouken@11931
   157
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@11931
   158
slouken@11931
   159
    mouse->CreateCursor = Android_CreateCursor;
slouken@11931
   160
    mouse->CreateSystemCursor = Android_CreateSystemCursor;
slouken@11931
   161
    mouse->ShowCursor = Android_ShowCursor;
slouken@11931
   162
    mouse->FreeCursor = Android_FreeCursor;
slouken@12007
   163
    mouse->SetRelativeMouseMode = Android_SetRelativeMouseMode;
slouken@11931
   164
slouken@11931
   165
    SDL_SetDefaultCursor(Android_CreateDefaultCursor());
slouken@11931
   166
slouken@11237
   167
    last_state = 0;
philipp@10051
   168
}
philipp@10051
   169
slouken@11237
   170
/* Translate Android mouse button state to SDL mouse button */
slouken@11237
   171
static Uint8
slouken@11237
   172
TranslateButton(int state)
slouken@11237
   173
{
slouken@11237
   174
    if (state & BUTTON_PRIMARY) {
slouken@11237
   175
        return SDL_BUTTON_LEFT;
slouken@11237
   176
    } else if (state & BUTTON_SECONDARY) {
slouken@11237
   177
        return SDL_BUTTON_RIGHT;
slouken@11237
   178
    } else if (state & BUTTON_TERTIARY) {
slouken@11237
   179
        return SDL_BUTTON_MIDDLE;
slouken@11237
   180
    } else if (state & BUTTON_FORWARD) {
slouken@11237
   181
        return SDL_BUTTON_X1;
slouken@11237
   182
    } else if (state & BUTTON_BACK) {
slouken@11237
   183
        return SDL_BUTTON_X2;
slouken@11237
   184
    } else {
slouken@11237
   185
        return 0;
slouken@11237
   186
    }
slouken@11237
   187
}
slouken@11237
   188
slouken@11237
   189
void
slouken@12007
   190
Android_OnMouse(int state, int action, float x, float y, SDL_bool relative)
slouken@11237
   191
{
slouken@11237
   192
    int changes;
slouken@11237
   193
    Uint8 button;
slouken@11237
   194
joseba@9438
   195
    if (!Android_Window) {
joseba@9438
   196
        return;
joseba@9438
   197
    }
joseba@9438
   198
joseba@9438
   199
    switch(action) {
joseba@9438
   200
        case ACTION_DOWN:
slouken@11237
   201
            changes = state & ~last_state;
slouken@11237
   202
            button = TranslateButton(changes);
slouken@11237
   203
            last_state = state;
slouken@12007
   204
            SDL_SendMouseMotion(Android_Window, 0, relative, x, y);
slouken@11237
   205
            SDL_SendMouseButton(Android_Window, 0, SDL_PRESSED, button);
joseba@9438
   206
            break;
joseba@9438
   207
joseba@9438
   208
        case ACTION_UP:
slouken@11237
   209
            changes = last_state & ~state;
slouken@11237
   210
            button = TranslateButton(changes);
slouken@11237
   211
            last_state = state;
slouken@12007
   212
            SDL_SendMouseMotion(Android_Window, 0, relative, x, y);
slouken@11237
   213
            SDL_SendMouseButton(Android_Window, 0, SDL_RELEASED, button);
joseba@9438
   214
            break;
joseba@9438
   215
philipp@10295
   216
        case ACTION_MOVE:
joseba@9438
   217
        case ACTION_HOVER_MOVE:
slouken@12007
   218
            SDL_SendMouseMotion(Android_Window, 0, relative, x, y);
joseba@9438
   219
            break;
joseba@9438
   220
joseba@9438
   221
        case ACTION_SCROLL:
joseba@9439
   222
            SDL_SendMouseWheel(Android_Window, 0, x, y, SDL_MOUSEWHEEL_NORMAL);
joseba@9438
   223
            break;
joseba@9438
   224
joseba@9438
   225
        default:
joseba@9438
   226
            break;
joseba@9438
   227
    }
joseba@9438
   228
}
joseba@9438
   229
joseba@9438
   230
#endif /* SDL_VIDEO_DRIVER_ANDROID */
joseba@9438
   231
joseba@9438
   232
/* vi: set ts=4 sw=4 expandtab: */
joseba@9438
   233