* Improve mouse support in Android. These changes require Android API v12 to compile

main
Joseba Garc?a Etxebarria 2015-03-24 20:45:29 +01:00
parent 87ef19c44a
commit 387fa5dcfb
6 changed files with 249 additions and 51 deletions

View File

@ -401,6 +401,7 @@ public class SDLActivity extends Activity {
public static native void onNativeKeyDown(int keycode); public static native void onNativeKeyDown(int keycode);
public static native void onNativeKeyUp(int keycode); public static native void onNativeKeyUp(int keycode);
public static native void onNativeKeyboardFocusLost(); public static native void onNativeKeyboardFocusLost();
public static native void onNativeMouse(int button, int action, float x, float y);
public static native void onNativeTouch(int touchDevId, int pointerFingerId, public static native void onNativeTouch(int touchDevId, int pointerFingerId,
int action, float x, int action, float x,
float y, float p); float y, float p);
@ -1088,7 +1089,7 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
// Some SOURCE_DPAD or SOURCE_GAMEPAD are also SOURCE_KEYBOARD // Some SOURCE_DPAD or SOURCE_GAMEPAD are also SOURCE_KEYBOARD
// So, we try to process them as DPAD or GAMEPAD events first, if that fails we try them as KEYBOARD // So, we try to process them as DPAD or GAMEPAD events first, if that fails we try them as KEYBOARD
if ( (event.getSource() & 0x00000401) != 0 || /* API 12: SOURCE_GAMEPAD */ if ( (event.getSource() & InputDevice.SOURCE_GAMEPAD) != 0 ||
(event.getSource() & InputDevice.SOURCE_DPAD) != 0 ) { (event.getSource() & InputDevice.SOURCE_DPAD) != 0 ) {
if (event.getAction() == KeyEvent.ACTION_DOWN) { if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (SDLActivity.onNativePadDown(event.getDeviceId(), keyCode) == 0) { if (SDLActivity.onNativePadDown(event.getDeviceId(), keyCode) == 0) {
@ -1125,50 +1126,58 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
final int pointerCount = event.getPointerCount(); final int pointerCount = event.getPointerCount();
int action = event.getActionMasked(); int action = event.getActionMasked();
int pointerFingerId; int pointerFingerId;
int mouseButton;
int i = -1; int i = -1;
float x,y,p; float x,y,p;
switch(action) { if (event.getSource() == InputDevice.SOURCE_MOUSE &&
case MotionEvent.ACTION_MOVE: SDLActivity.nativeGetHint("SDL_ANDROID_SEPARATE_MOUSE_AND_TOUCH").equals("1")) {
for (i = 0; i < pointerCount; i++) { mouseButton = 1; // For Android==12 all mouse buttons are the left button
SDLActivity.onNativeMouse(mouseButton, action, event.getX(0), event.getY(0));
} else {
switch(action) {
case MotionEvent.ACTION_MOVE:
for (i = 0; i < pointerCount; i++) {
pointerFingerId = event.getPointerId(i);
x = event.getX(i) / mWidth;
y = event.getY(i) / mHeight;
p = event.getPressure(i);
SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_DOWN:
// Primary pointer up/down, the index is always zero
i = 0;
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_POINTER_DOWN:
// Non primary pointer up/down
if (i == -1) {
i = event.getActionIndex();
}
pointerFingerId = event.getPointerId(i); pointerFingerId = event.getPointerId(i);
x = event.getX(i) / mWidth; x = event.getX(i) / mWidth;
y = event.getY(i) / mHeight; y = event.getY(i) / mHeight;
p = event.getPressure(i); p = event.getPressure(i);
SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p); SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
} break;
break;
case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_DOWN: for (i = 0; i < pointerCount; i++) {
// Primary pointer up/down, the index is always zero pointerFingerId = event.getPointerId(i);
i = 0; x = event.getX(i) / mWidth;
case MotionEvent.ACTION_POINTER_UP: y = event.getY(i) / mHeight;
case MotionEvent.ACTION_POINTER_DOWN: p = event.getPressure(i);
// Non primary pointer up/down SDLActivity.onNativeTouch(touchDevId, pointerFingerId, MotionEvent.ACTION_UP, x, y, p);
if (i == -1) { }
i = event.getActionIndex(); break;
}
pointerFingerId = event.getPointerId(i); default:
x = event.getX(i) / mWidth; break;
y = event.getY(i) / mHeight; }
p = event.getPressure(i);
SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
break;
case MotionEvent.ACTION_CANCEL:
for (i = 0; i < pointerCount; i++) {
pointerFingerId = event.getPointerId(i);
x = event.getX(i) / mWidth;
y = event.getY(i) / mHeight;
p = event.getPressure(i);
SDLActivity.onNativeTouch(touchDevId, pointerFingerId, MotionEvent.ACTION_UP, x, y, p);
}
break;
default:
break;
} }
return true; return true;
@ -1497,11 +1506,47 @@ class SDLJoystickHandler_API12 extends SDLJoystickHandler {
} }
} }
class SDLGenericMotionListener_API12 implements View.OnGenericMotionListener { class SDLGenericMotionListener implements View.OnGenericMotionListener {
// Generic Motion (mouse hover, joystick...) events go here // Generic Motion (mouse hover, joystick...) events go here
// We only have joysticks yet // We only have joysticks yet
@Override @Override
public boolean onGenericMotion(View v, MotionEvent event) { public boolean onGenericMotion(View v, MotionEvent event) {
return SDLActivity.handleJoystickMotionEvent(event); float x, y;
int mouseButton;
int action;
switch ( event.getSource() ) {
case InputDevice.SOURCE_JOYSTICK:
case InputDevice.SOURCE_GAMEPAD:
case InputDevice.SOURCE_DPAD:
SDLActivity.handleJoystickMotionEvent(event);
return true;
case InputDevice.SOURCE_MOUSE:
action = event.getActionMasked();
switch(event.getActionMasked()) {
case MotionEvent.ACTION_SCROLL:
x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0);
y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0);
SDLActivity.onNativeMouse(0, action, x, y);
return true;
case MotionEvent.ACTION_HOVER_MOVE:
x = event.getX(0);
y = event.getY(0);
SDLActivity.onNativeMouse(0, action, x, y);
return true;
default:
break;
}
default:
break;
}
// Event was not managed
return false;
} }
} }

View File

@ -532,6 +532,18 @@ extern "C" {
*/ */
#define SDL_HINT_IME_INTERNAL_EDITING "SDL_IME_INTERNAL_EDITING" #define SDL_HINT_IME_INTERNAL_EDITING "SDL_IME_INTERNAL_EDITING"
/**
* \brief A variable to control whether mouse and touch events are to be treated together or separately
*
* The variable can be set to the following values:
* "0" - Mouse events will be handled as touch events, and touch will raise fake mouse
* events. This is the behaviour of SDL <= 2.0.3. (default)
* "1" - Mouse events will be handled separately from pure touch events.
*
* The value of this hint is used at runtime, so it can be changed at any time.
*/
#define SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH "SDL_ANDROID_SEPARATE_MOUSE_AND_TOUCH"
/** /**
* \brief override the binding element for keyboard inputs for Emscripten builds * \brief override the binding element for keyboard inputs for Emscripten builds
* *

View File

@ -32,6 +32,7 @@
#include "../../events/SDL_events_c.h" #include "../../events/SDL_events_c.h"
#include "../../video/android/SDL_androidkeyboard.h" #include "../../video/android/SDL_androidkeyboard.h"
#include "../../video/android/SDL_androidmouse.h"
#include "../../video/android/SDL_androidtouch.h" #include "../../video/android/SDL_androidtouch.h"
#include "../../video/android/SDL_androidvideo.h" #include "../../video/android/SDL_androidvideo.h"
#include "../../video/android/SDL_androidwindow.h" #include "../../video/android/SDL_androidwindow.h"
@ -293,6 +294,22 @@ JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeTouch(
Android_OnTouch(touch_device_id_in, pointer_finger_id_in, action, x, y, p); Android_OnTouch(touch_device_id_in, pointer_finger_id_in, action, x, y, p);
} }
/* Mouse */
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeMouse(
JNIEnv* env, jclass jcls,
jint button, jint action, jfloat x, jfloat y)
{
Android_OnMouse(button, action, x, y);
}
/* Mouse */
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeMouse(
JNIEnv* env, jclass jcls,
jint button, jint action, jfloat x, jfloat y)
{
Android_OnMouse(button, action, x, y);
}
/* Accelerometer */ /* Accelerometer */
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeAccel( JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeAccel(
JNIEnv* env, jclass jcls, JNIEnv* env, jclass jcls,

View File

@ -0,0 +1,85 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_ANDROID
#include "SDL_androidmouse.h"
#include "SDL_Log.h"
#include "SDL_events.h"
#include "../../events/SDL_mouse_c.h"
#include "../../core/android/SDL_android.h"
#define ACTION_DOWN 0
#define ACTION_UP 1
#define ACTION_HOVER_MOVE 7
#define ACTION_SCROLL 8
#define BUTTON_PRIMARY 1
#define BUTTON_SECONDARY 2
#define BUTTON_TERTIARY 4
void Android_OnMouse( int androidButton, int action, float x, float y) {
static Uint8 SDLButton;
if (!Android_Window) {
return;
}
switch(action) {
case ACTION_DOWN:
// Determine which button originated the event, and store it for ACTION_UP
SDLButton = SDL_BUTTON_LEFT;
if (androidButton == BUTTON_SECONDARY) {
SDLButton = SDL_BUTTON_RIGHT;
} else if (androidButton == BUTTON_TERTIARY) {
SDLButton = SDL_BUTTON_MIDDLE;
}
SDL_SendMouseMotion(Android_Window, 0, 0, x, y);
SDL_SendMouseButton(Android_Window, 0, SDL_PRESSED, SDLButton);
break;
case ACTION_UP:
// Android won't give us the button that originated the ACTION_DOWN event, so we'll
// assume it's the one we stored
SDL_SendMouseMotion(Android_Window, 0, 0, x, y);
SDL_SendMouseButton(Android_Window, 0, SDL_RELEASED, SDLButton);
break;
case ACTION_HOVER_MOVE:
SDL_SendMouseMotion(Android_Window, 0, 0, x, y);
break;
case ACTION_SCROLL:
SDL_SendMouseWheel(Android_Window, 0, x, y);
break;
default:
break;
}
}
#endif /* SDL_VIDEO_DRIVER_ANDROID */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -0,0 +1,31 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef _SDL_androidmouse_h
#define _SDL_androidmouse_h
#include "SDL_androidvideo.h"
extern void Android_OnMouse( int button, int action, float x, float y);
#endif /* _SDL_androidmouse_h */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -69,6 +69,7 @@ void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int actio
SDL_TouchID touchDeviceId = 0; SDL_TouchID touchDeviceId = 0;
SDL_FingerID fingerId = 0; SDL_FingerID fingerId = 0;
int window_x, window_y; int window_x, window_y;
char * hint;
static SDL_FingerID pointerFingerID = 0; static SDL_FingerID pointerFingerID = 0;
if (!Android_Window) { if (!Android_Window) {
@ -81,14 +82,17 @@ void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int actio
} }
fingerId = (SDL_FingerID)pointer_finger_id_in; fingerId = (SDL_FingerID)pointer_finger_id_in;
hint = SDL_GetHint("SDL_ANDROID_SEPARATE_MOUSE_AND_TOUCH");
switch (action) { switch (action) {
case ACTION_DOWN: case ACTION_DOWN:
/* Primary pointer down */ /* Primary pointer down */
Android_GetWindowCoordinates(x, y, &window_x, &window_y); Android_GetWindowCoordinates(x, y, &window_x, &window_y);
/* send moved event */ if ((!hint) || (hint && SDL_strcmp(hint, "1") != 0)) {
SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y); /* send moved event */
/* send mouse down event */ SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y);
SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT); /* send mouse down event */
SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
}
pointerFingerID = fingerId; pointerFingerID = fingerId;
case ACTION_POINTER_DOWN: case ACTION_POINTER_DOWN:
/* Non primary pointer down */ /* Non primary pointer down */
@ -99,17 +103,21 @@ void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int actio
if (!pointerFingerID) { if (!pointerFingerID) {
Android_GetWindowCoordinates(x, y, &window_x, &window_y); Android_GetWindowCoordinates(x, y, &window_x, &window_y);
/* send moved event */ if ((!hint) || (hint && SDL_strcmp(hint, "1") != 0)) {
SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y); /* send moved event */
SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y);
}
} }
SDL_SendTouchMotion(touchDeviceId, fingerId, x, y, p); SDL_SendTouchMotion(touchDeviceId, fingerId, x, y, p);
break; break;
case ACTION_UP: case ACTION_UP:
/* Primary pointer up */ /* Primary pointer up */
/* send mouse up */ if ((!hint) || (hint && SDL_strcmp(hint, "1") != 0)) {
pointerFingerID = (SDL_FingerID) 0; /* send mouse up */
SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT); pointerFingerID = (SDL_FingerID) 0;
SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
}
case ACTION_POINTER_UP: case ACTION_POINTER_UP:
/* Non primary pointer up */ /* Non primary pointer up */
SDL_SendTouch(touchDeviceId, fingerId, SDL_FALSE, x, y, p); SDL_SendTouch(touchDeviceId, fingerId, SDL_FALSE, x, y, p);