src/video/android/SDL_androidtouch.c
author Ryan C. Gordon <icculus@icculus.org>
Wed, 01 Apr 2015 12:14:56 -0400
changeset 9449 a65088766e35
parent 9441 fc7522030729
child 9450 bcb16ffce95b
permissions -rw-r--r--
Android: more separate-mouse-and-touch work.

This avoids a hint lookup for each mouse event we get by setting a static Java
variable from native code during our hint watcher callback.

Also attempts to do the right thing with mouse buttons if you happen to be
on an API14 (Ice Cream Sandwich, Android 4.0) or later device. We still
target API12 (Honeycomb MR1, Android 3.1) for SDL 2.0.4 though.

This isn't tested, so I'm pushing to see what the Android buildbot says. Stand
back, I'm a professional!
slouken@5001
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@8149
     3
  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
slouken@5001
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@5001
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@5001
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@5001
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
slouken@5001
    22
slouken@6044
    23
#if SDL_VIDEO_DRIVER_ANDROID
slouken@6044
    24
slouken@5001
    25
#include <android/log.h>
slouken@5001
    26
joseba@9439
    27
#include "SDL_hints.h"
slouken@5001
    28
#include "SDL_events.h"
joseba@9439
    29
#include "SDL_log.h"
joseba@9439
    30
#include "SDL_androidtouch.h"
slouken@5001
    31
#include "../../events/SDL_mouse_c.h"
icculus@5982
    32
#include "../../events/SDL_touch_c.h"
philipp@7786
    33
#include "../../core/android/SDL_android.h"
slouken@5001
    34
slouken@5001
    35
#define ACTION_DOWN 0
slouken@5001
    36
#define ACTION_UP 1
slouken@5001
    37
#define ACTION_MOVE 2
slouken@5001
    38
#define ACTION_CANCEL 3
slouken@5001
    39
#define ACTION_OUTSIDE 4
gabomdq@8030
    40
#define ACTION_POINTER_DOWN 5
gabomdq@8030
    41
#define ACTION_POINTER_UP 6
slouken@6651
    42
slouken@6651
    43
static void Android_GetWindowCoordinates(float x, float y,
slouken@6651
    44
                                         int *window_x, int *window_y)
slouken@6651
    45
{
slouken@6651
    46
    int window_w, window_h;
slouken@6651
    47
slouken@6651
    48
    SDL_GetWindowSize(Android_Window, &window_w, &window_h);
slouken@6651
    49
    *window_x = (int)(x * window_w);
slouken@6651
    50
    *window_y = (int)(y * window_h);
slouken@6651
    51
}
slouken@6651
    52
icculus@9441
    53
static volatile SDL_bool separate_mouse_and_touch = SDL_FALSE;
icculus@9441
    54
icculus@9441
    55
static void
icculus@9441
    56
SeparateEventsHintWatcher(void *userdata, const char *name,
icculus@9441
    57
                          const char *oldValue, const char *newValue)
icculus@9441
    58
{
icculus@9441
    59
    separate_mouse_and_touch = (newValue && (SDL_strcmp(newValue, "1") == 0));
icculus@9449
    60
    JNIEnv *env = Android_JNI_GetEnv();
icculus@9449
    61
    jfieldID fid = (*env)->GetStaticFieldID(env, mActivityClass, "mSeparateMouseAndTouch", "Z");
icculus@9449
    62
    (*env)->SetStaticBooleanField(env, mActivityClass, fid, separate_mouse_and_touch ? JNI_TRUE : JNI_FALSE);
icculus@9441
    63
}
icculus@9441
    64
philipp@7786
    65
void Android_InitTouch(void)
philipp@7786
    66
{
philipp@7786
    67
    int i;
philipp@7786
    68
    int* ids;
icculus@9441
    69
    const int number = Android_JNI_GetTouchDeviceIds(&ids);
icculus@9441
    70
icculus@9441
    71
    SDL_AddHintCallback(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH,
icculus@9441
    72
                        SeparateEventsHintWatcher, NULL);
icculus@9441
    73
philipp@7786
    74
    if (0 < number) {
philipp@7786
    75
        for (i = 0; i < number; ++i) {
philipp@7786
    76
            SDL_AddTouch((SDL_TouchID) ids[i], ""); /* no error handling */
philipp@7786
    77
        }
philipp@7786
    78
        SDL_free(ids);
philipp@7786
    79
    }
philipp@7786
    80
}
philipp@7786
    81
icculus@9441
    82
void Android_QuitTouch(void)
icculus@9441
    83
{
icculus@9441
    84
    SDL_DelHintCallback(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH,
icculus@9441
    85
                        SeparateEventsHintWatcher, NULL);
icculus@9441
    86
    separate_mouse_and_touch = SDL_FALSE;
icculus@9441
    87
}
icculus@9441
    88
slouken@7191
    89
void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int action, float x, float y, float p)
slouken@5001
    90
{
icculus@5982
    91
    SDL_TouchID touchDeviceId = 0;
icculus@5982
    92
    SDL_FingerID fingerId = 0;
slouken@6651
    93
    int window_x, window_y;
gabomdq@8030
    94
    static SDL_FingerID pointerFingerID = 0;
slouken@6651
    95
slouken@5001
    96
    if (!Android_Window) {
slouken@5001
    97
        return;
slouken@5001
    98
    }
slouken@6651
    99
icculus@5982
   100
    touchDeviceId = (SDL_TouchID)touch_device_id_in;
slouken@7043
   101
    if (SDL_AddTouch(touchDeviceId, "") < 0) {
slouken@7043
   102
        SDL_Log("error: can't add touch %s, %d", __FILE__, __LINE__);
icculus@5982
   103
    }
slouken@5001
   104
icculus@5982
   105
    fingerId = (SDL_FingerID)pointer_finger_id_in;
icculus@5982
   106
    switch (action) {
slouken@5001
   107
        case ACTION_DOWN:
gabomdq@8030
   108
            /* Primary pointer down */
gabomdq@8030
   109
            Android_GetWindowCoordinates(x, y, &window_x, &window_y);
icculus@9441
   110
            if (!separate_mouse_and_touch) {
joseba@9438
   111
                /* send moved event */
joseba@9438
   112
                SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y);
joseba@9438
   113
                /* send mouse down event */
joseba@9438
   114
                SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
joseba@9438
   115
            }
gabomdq@8030
   116
            pointerFingerID = fingerId;
gabomdq@8030
   117
        case ACTION_POINTER_DOWN:
gabomdq@8030
   118
            /* Non primary pointer down */
slouken@6951
   119
            SDL_SendTouch(touchDeviceId, fingerId, SDL_TRUE, x, y, p);
icculus@5982
   120
            break;
joseba@9438
   121
icculus@5982
   122
        case ACTION_MOVE:
gabomdq@8030
   123
            if (!pointerFingerID) {
slouken@6651
   124
                Android_GetWindowCoordinates(x, y, &window_x, &window_y);
icculus@9441
   125
                if (!separate_mouse_and_touch) {
joseba@9438
   126
                    /* send moved event */
joseba@9438
   127
                    SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y);
joseba@9438
   128
                }
slouken@6651
   129
            }
slouken@6951
   130
            SDL_SendTouchMotion(touchDeviceId, fingerId, x, y, p);
slouken@5001
   131
            break;
joseba@9438
   132
slouken@5001
   133
        case ACTION_UP:
gabomdq@8030
   134
            /* Primary pointer up */
icculus@9441
   135
            if (!separate_mouse_and_touch) {
joseba@9438
   136
                /* send mouse up */
joseba@9438
   137
                pointerFingerID = (SDL_FingerID) 0;
joseba@9438
   138
                SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
joseba@9438
   139
            }
gabomdq@8030
   140
        case ACTION_POINTER_UP:
gabomdq@8030
   141
            /* Non primary pointer up */
slouken@6951
   142
            SDL_SendTouch(touchDeviceId, fingerId, SDL_FALSE, x, y, p);
slouken@5001
   143
            break;
joseba@9438
   144
icculus@5982
   145
        default:
icculus@5982
   146
            break;
slouken@7191
   147
    }
slouken@5001
   148
}
slouken@5001
   149
slouken@6044
   150
#endif /* SDL_VIDEO_DRIVER_ANDROID */
slouken@6044
   151
slouken@5001
   152
/* vi: set ts=4 sw=4 expandtab: */