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.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2018 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 #include "../../SDL_internal.h"
    23 
    24 #if SDL_VIDEO_DRIVER_ANDROID
    25 
    26 #include "SDL_androidmouse.h"
    27 
    28 #include "SDL_events.h"
    29 #include "../../events/SDL_mouse_c.h"
    30 
    31 #include "../../core/android/SDL_android.h"
    32 
    33 /* See Android's MotionEvent class for constants */
    34 #define ACTION_DOWN 0
    35 #define ACTION_UP 1
    36 #define ACTION_MOVE 2
    37 #define ACTION_HOVER_MOVE 7
    38 #define ACTION_SCROLL 8
    39 #define BUTTON_PRIMARY 1
    40 #define BUTTON_SECONDARY 2
    41 #define BUTTON_TERTIARY 4
    42 #define BUTTON_BACK 8
    43 #define BUTTON_FORWARD 16
    44 
    45 typedef struct
    46 {
    47     int custom_cursor;
    48     int system_cursor;
    49 
    50 } SDL_AndroidCursorData;
    51 
    52 /* Last known Android mouse button state (includes all buttons) */
    53 static int last_state;
    54 
    55 
    56 static SDL_Cursor *
    57 Android_WrapCursor(int custom_cursor, int system_cursor)
    58 {
    59     SDL_Cursor *cursor;
    60 
    61     cursor = SDL_calloc(1, sizeof(*cursor));
    62     if (cursor) {
    63         SDL_AndroidCursorData *data = (SDL_AndroidCursorData*)SDL_calloc(1, sizeof(*data));
    64         if (data) {
    65             data->custom_cursor = custom_cursor;
    66             data->system_cursor = system_cursor;
    67             cursor->driverdata = data;
    68         } else {
    69             SDL_free(cursor);
    70             cursor = NULL;
    71             SDL_OutOfMemory();
    72         }
    73     } else {
    74         SDL_OutOfMemory();
    75     }
    76 
    77     return cursor;
    78 }
    79 
    80 static SDL_Cursor *
    81 Android_CreateDefaultCursor()
    82 {
    83     return Android_WrapCursor(0, SDL_SYSTEM_CURSOR_ARROW);
    84 }
    85 
    86 static SDL_Cursor *
    87 Android_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
    88 {
    89     int custom_cursor;
    90     SDL_Surface *converted;
    91 
    92     converted = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888, 0);
    93     if (!converted) {
    94         return NULL;
    95     }
    96     custom_cursor = Android_JNI_CreateCustomCursor(converted, hot_x, hot_y);
    97     SDL_FreeSurface(converted);
    98     if (!custom_cursor) {
    99         SDL_Unsupported();
   100         return NULL;
   101     }
   102     return Android_WrapCursor(custom_cursor, 0);
   103 }
   104 
   105 static SDL_Cursor *
   106 Android_CreateSystemCursor(SDL_SystemCursor id)
   107 {
   108     return Android_WrapCursor(0, id);
   109 }
   110 
   111 static void
   112 Android_FreeCursor(SDL_Cursor * cursor)
   113 {
   114     SDL_free(cursor->driverdata);
   115     SDL_free(cursor);
   116 }
   117 
   118 static int
   119 Android_ShowCursor(SDL_Cursor * cursor)
   120 {
   121     if (cursor) {
   122         SDL_AndroidCursorData *data = (SDL_AndroidCursorData*)cursor->driverdata;
   123         if (data->custom_cursor) {
   124             if (!Android_JNI_SetCustomCursor(data->custom_cursor)) {
   125                 return SDL_Unsupported();
   126             }
   127         } else {
   128             if (!Android_JNI_SetSystemCursor(data->system_cursor)) {
   129                 return SDL_Unsupported();
   130             }
   131         }
   132     } else {
   133         if (!Android_JNI_SetSystemCursor(-1)) {
   134             return SDL_Unsupported();
   135         }
   136     }
   137     return 0;
   138 }
   139 
   140 static int
   141 Android_SetRelativeMouseMode(SDL_bool enabled)
   142 {
   143     if (!Android_JNI_SupportsRelativeMouse()) {
   144         return SDL_Unsupported();
   145     }
   146 
   147     if (!Android_JNI_SetRelativeMouseEnabled(enabled)) {
   148         return SDL_Unsupported();
   149     }
   150 
   151     return 0;
   152 }
   153 
   154 void
   155 Android_InitMouse(void)
   156 {
   157     SDL_Mouse *mouse = SDL_GetMouse();
   158 
   159     mouse->CreateCursor = Android_CreateCursor;
   160     mouse->CreateSystemCursor = Android_CreateSystemCursor;
   161     mouse->ShowCursor = Android_ShowCursor;
   162     mouse->FreeCursor = Android_FreeCursor;
   163     mouse->SetRelativeMouseMode = Android_SetRelativeMouseMode;
   164 
   165     SDL_SetDefaultCursor(Android_CreateDefaultCursor());
   166 
   167     last_state = 0;
   168 }
   169 
   170 /* Translate Android mouse button state to SDL mouse button */
   171 static Uint8
   172 TranslateButton(int state)
   173 {
   174     if (state & BUTTON_PRIMARY) {
   175         return SDL_BUTTON_LEFT;
   176     } else if (state & BUTTON_SECONDARY) {
   177         return SDL_BUTTON_RIGHT;
   178     } else if (state & BUTTON_TERTIARY) {
   179         return SDL_BUTTON_MIDDLE;
   180     } else if (state & BUTTON_FORWARD) {
   181         return SDL_BUTTON_X1;
   182     } else if (state & BUTTON_BACK) {
   183         return SDL_BUTTON_X2;
   184     } else {
   185         return 0;
   186     }
   187 }
   188 
   189 void
   190 Android_OnMouse(int state, int action, float x, float y, SDL_bool relative)
   191 {
   192     int changes;
   193     Uint8 button;
   194 
   195     if (!Android_Window) {
   196         return;
   197     }
   198 
   199     switch(action) {
   200         case ACTION_DOWN:
   201             changes = state & ~last_state;
   202             button = TranslateButton(changes);
   203             last_state = state;
   204             SDL_SendMouseMotion(Android_Window, 0, relative, x, y);
   205             SDL_SendMouseButton(Android_Window, 0, SDL_PRESSED, button);
   206             break;
   207 
   208         case ACTION_UP:
   209             changes = last_state & ~state;
   210             button = TranslateButton(changes);
   211             last_state = state;
   212             SDL_SendMouseMotion(Android_Window, 0, relative, x, y);
   213             SDL_SendMouseButton(Android_Window, 0, SDL_RELEASED, button);
   214             break;
   215 
   216         case ACTION_MOVE:
   217         case ACTION_HOVER_MOVE:
   218             SDL_SendMouseMotion(Android_Window, 0, relative, x, y);
   219             break;
   220 
   221         case ACTION_SCROLL:
   222             SDL_SendMouseWheel(Android_Window, 0, x, y, SDL_MOUSEWHEEL_NORMAL);
   223             break;
   224 
   225         default:
   226             break;
   227     }
   228 }
   229 
   230 #endif /* SDL_VIDEO_DRIVER_ANDROID */
   231 
   232 /* vi: set ts=4 sw=4 expandtab: */
   233