Skip to content

Commit

Permalink
* Improve mouse support in Android. These changes require Android API…
Browse files Browse the repository at this point in the history
… v12 to compile
  • Loading branch information
josebagar committed Mar 24, 2015
1 parent 87ef19c commit 387fa5d
Show file tree
Hide file tree
Showing 6 changed files with 249 additions and 51 deletions.
123 changes: 84 additions & 39 deletions android-project/src/org/libsdl/app/SDLActivity.java
Expand Up @@ -401,6 +401,7 @@ public static native void onNativeHat(int device_id, int hat_id,
public static native void onNativeKeyDown(int keycode);
public static native void onNativeKeyUp(int keycode);
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,
int action, float x,
float y, float p);
Expand Down Expand Up @@ -1087,8 +1088,8 @@ public boolean onKey(View v, int keyCode, KeyEvent event) {
// Dispatch the different events depending on where they come from
// 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
if ( (event.getSource() & 0x00000401) != 0 || /* API 12: SOURCE_GAMEPAD */

if ( (event.getSource() & InputDevice.SOURCE_GAMEPAD) != 0 ||
(event.getSource() & InputDevice.SOURCE_DPAD) != 0 ) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (SDLActivity.onNativePadDown(event.getDeviceId(), keyCode) == 0) {
Expand Down Expand Up @@ -1125,50 +1126,58 @@ public boolean onTouch(View v, MotionEvent event) {
final int pointerCount = event.getPointerCount();
int action = event.getActionMasked();
int pointerFingerId;
int mouseButton;
int i = -1;
float x,y,p;

switch(action) {
case MotionEvent.ACTION_MOVE:
for (i = 0; i < pointerCount; i++) {

if (event.getSource() == InputDevice.SOURCE_MOUSE &&
SDLActivity.nativeGetHint("SDL_ANDROID_SEPARATE_MOUSE_AND_TOUCH").equals("1")) {
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);
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();
}
break;

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_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;
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;
default:
break;
}
}

return true;
Expand Down Expand Up @@ -1497,11 +1506,47 @@ public boolean handleMotionEvent(MotionEvent event) {
}
}

class SDLGenericMotionListener_API12 implements View.OnGenericMotionListener {
class SDLGenericMotionListener implements View.OnGenericMotionListener {
// Generic Motion (mouse hover, joystick...) events go here
// We only have joysticks yet
@Override
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;
}
}
12 changes: 12 additions & 0 deletions include/SDL_hints.h
Expand Up @@ -532,6 +532,18 @@ extern "C" {
*/
#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
*
Expand Down
17 changes: 17 additions & 0 deletions src/core/android/SDL_android.c
Expand Up @@ -32,6 +32,7 @@

#include "../../events/SDL_events_c.h"
#include "../../video/android/SDL_androidkeyboard.h"
#include "../../video/android/SDL_androidmouse.h"
#include "../../video/android/SDL_androidtouch.h"
#include "../../video/android/SDL_androidvideo.h"
#include "../../video/android/SDL_androidwindow.h"
Expand Down Expand Up @@ -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);
}

/* 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 */
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeAccel(
JNIEnv* env, jclass jcls,
Expand Down
85 changes: 85 additions & 0 deletions src/video/android/SDL_androidmouse.c
@@ -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: */

31 changes: 31 additions & 0 deletions src/video/android/SDL_androidmouse.h
@@ -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: */
32 changes: 20 additions & 12 deletions src/video/android/SDL_androidtouch.c
Expand Up @@ -69,6 +69,7 @@ void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int actio
SDL_TouchID touchDeviceId = 0;
SDL_FingerID fingerId = 0;
int window_x, window_y;
char * hint;
static SDL_FingerID pointerFingerID = 0;

if (!Android_Window) {
Expand All @@ -81,40 +82,47 @@ void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int actio
}

fingerId = (SDL_FingerID)pointer_finger_id_in;
hint = SDL_GetHint("SDL_ANDROID_SEPARATE_MOUSE_AND_TOUCH");
switch (action) {
case ACTION_DOWN:
/* Primary pointer down */
Android_GetWindowCoordinates(x, y, &window_x, &window_y);
/* send moved event */
SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y);
/* send mouse down event */
SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
if ((!hint) || (hint && SDL_strcmp(hint, "1") != 0)) {
/* send moved event */
SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y);
/* send mouse down event */
SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
}
pointerFingerID = fingerId;
case ACTION_POINTER_DOWN:
/* Non primary pointer down */
SDL_SendTouch(touchDeviceId, fingerId, SDL_TRUE, x, y, p);
break;

case ACTION_MOVE:
if (!pointerFingerID) {
Android_GetWindowCoordinates(x, y, &window_x, &window_y);

/* send moved event */
SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y);
if ((!hint) || (hint && SDL_strcmp(hint, "1") != 0)) {
/* send moved event */
SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y);
}
}
SDL_SendTouchMotion(touchDeviceId, fingerId, x, y, p);
break;

case ACTION_UP:
/* Primary pointer up */
/* send mouse up */
pointerFingerID = (SDL_FingerID) 0;
SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
if ((!hint) || (hint && SDL_strcmp(hint, "1") != 0)) {
/* send mouse up */
pointerFingerID = (SDL_FingerID) 0;
SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
}
case ACTION_POINTER_UP:
/* Non primary pointer up */
SDL_SendTouch(touchDeviceId, fingerId, SDL_FALSE, x, y, p);
break;

default:
break;
}
Expand Down

0 comments on commit 387fa5d

Please sign in to comment.