1858 lines
64 KiB
C
1858 lines
64 KiB
C
/*
|
|
Simple DirectMedia Layer
|
|
Copyright (C) 2009-2014 Sergii Pylypenko
|
|
|
|
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.
|
|
*/
|
|
/*
|
|
This source code is distibuted under ZLIB license, however when compiling with SDL 1.2,
|
|
which is licensed under LGPL, the resulting library, and all it's source code,
|
|
falls under "stronger" LGPL terms, so is this file.
|
|
If you compile this code with SDL 1.3 or newer, or use in some other way, the license stays ZLIB.
|
|
*/
|
|
|
|
#include <jni.h>
|
|
#include <android/log.h>
|
|
#include <sys/time.h>
|
|
#include <time.h>
|
|
#include <stdint.h>
|
|
#include <math.h>
|
|
#include <string.h> // for memset()
|
|
#include <pthread.h>
|
|
#include <semaphore.h>
|
|
|
|
#include "SDL.h"
|
|
#include "SDL_config.h"
|
|
#include "SDL_syswm.h"
|
|
|
|
#include "SDL_version.h"
|
|
#include "SDL_mutex.h"
|
|
#include "SDL_events.h"
|
|
#if SDL_VERSION_ATLEAST(1,3,0)
|
|
#include "SDL_touch.h"
|
|
#include "../../events/SDL_touch_c.h"
|
|
#endif
|
|
|
|
#include "../SDL_sysvideo.h"
|
|
#include "SDL_androidvideo.h"
|
|
#include "SDL_androidinput.h"
|
|
#include "SDL_screenkeyboard.h"
|
|
#include "jniwrapperstuff.h"
|
|
#include "unicodestuff.h"
|
|
#include "atan2i.h"
|
|
|
|
SDLKey SDL_android_keymap[KEYCODE_LAST+1];
|
|
|
|
SDLKey SDL_android_gamepad_keymap[SDL_ANDROID_MAX_GAMEPADS][KEYCODE_LAST+1];
|
|
|
|
static inline SDL_scancode TranslateKey(int scancode)
|
|
{
|
|
if ( scancode >= KEYCODE_LAST + 1 )
|
|
scancode = KEYCODE_UNKNOWN;
|
|
return SDL_android_keymap[scancode];
|
|
}
|
|
|
|
static inline SDL_scancode TranslateKeyGamepad(int scancode, int gamepadId)
|
|
{
|
|
if ( scancode >= KEYCODE_LAST + 1 )
|
|
scancode = KEYCODE_UNKNOWN;
|
|
if (gamepadId < 0 || gamepadId > SDL_ANDROID_MAX_GAMEPADS)
|
|
gamepadId = 0;
|
|
return gamepadId ? SDL_android_gamepad_keymap[gamepadId - 1][scancode] : SDL_android_keymap[scancode];
|
|
}
|
|
|
|
int SDL_ANDROID_isMouseUsed = 0;
|
|
|
|
#define NORMALIZE_FLOAT_32767(X) (fminf(32767.0f, fmaxf(-32767.0f, (X) * 32767.0f)))
|
|
|
|
enum { RIGHT_CLICK_NONE = 0, RIGHT_CLICK_WITH_MULTITOUCH = 1, RIGHT_CLICK_WITH_PRESSURE = 2,
|
|
RIGHT_CLICK_WITH_KEY = 3, RIGHT_CLICK_WITH_TIMEOUT = 4 };
|
|
enum { LEFT_CLICK_NORMAL = 0, LEFT_CLICK_NEAR_CURSOR = 1, LEFT_CLICK_WITH_MULTITOUCH = 2, LEFT_CLICK_WITH_PRESSURE = 3,
|
|
LEFT_CLICK_WITH_KEY = 4, LEFT_CLICK_WITH_TIMEOUT = 5, LEFT_CLICK_WITH_TAP = 6, LEFT_CLICK_WITH_TAP_OR_TIMEOUT = 7 };
|
|
enum { JOY_TOUCHSCREEN = 0, JOY_ACCELGYRO = 1, JOY_GAMEPAD1 = 2, JOY_GAMEPAD2 = 3, JOY_GAMEPAD3 = 4, JOY_GAMEPAD4 = 5 };
|
|
static int leftClickMethod = LEFT_CLICK_NORMAL;
|
|
static int rightClickMethod = RIGHT_CLICK_NONE;
|
|
static int leftClickKey = KEYCODE_DPAD_CENTER;
|
|
static int rightClickKey = KEYCODE_MENU;
|
|
int SDL_ANDROID_ShowScreenUnderFinger = ZOOM_NONE;
|
|
SDL_Rect SDL_ANDROID_ShowScreenUnderFingerRect = {0, 0, 0, 0}, SDL_ANDROID_ShowScreenUnderFingerRectSrc = {0, 0, 0, 0};
|
|
static int clickMouseWithDpadCenter = 0;
|
|
int SDL_ANDROID_moveMouseWithArrowKeys = 0;
|
|
int SDL_ANDROID_moveMouseWithKbSpeed = 0;
|
|
int SDL_ANDROID_moveMouseWithKbAccel = 0;
|
|
int SDL_ANDROID_moveMouseWithKbActive = 0;
|
|
int SDL_ANDROID_moveMouseWithKbX = 0, SDL_ANDROID_moveMouseWithKbY = 0;
|
|
int SDL_ANDROID_moveMouseWithKbSpeedX = 0, SDL_ANDROID_moveMouseWithKbSpeedY = 0;
|
|
int SDL_ANDROID_moveMouseWithKbAccelX = 0, SDL_ANDROID_moveMouseWithKbAccelY = 0;
|
|
int SDL_ANDROID_moveMouseWithKbAccelUpdateNeeded = 0;
|
|
static int maxForce = 0;
|
|
static int maxRadius = 0;
|
|
int SDL_ANDROID_joysticksAmount = 0;
|
|
static int SDL_ANDROID_isAccelerometerUsed = 0;
|
|
static int isMultitouchUsed = 0;
|
|
SDL_Joystick *SDL_ANDROID_CurrentJoysticks[JOY_GAMEPAD4+1];
|
|
enum { TOUCH_PTR_UP = 0, TOUCH_PTR_MOUSE = 1, TOUCH_PTR_SCREENKB = 2 };
|
|
static int touchPointers[MAX_MULTITOUCH_POINTERS] = {0};
|
|
static int firstMousePointerId = -1, secondMousePointerId = -1;
|
|
enum { MAX_MULTITOUCH_GESTURES = 4 };
|
|
static int multitouchGestureKeycode[MAX_MULTITOUCH_GESTURES] = {
|
|
SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_SCREENKB_KEYCODE_6)),
|
|
SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_SCREENKB_KEYCODE_7)),
|
|
SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_SCREENKB_KEYCODE_8)),
|
|
SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_SCREENKB_KEYCODE_9))
|
|
};
|
|
static int multitouchGestureSensitivity = 0;
|
|
static int multitouchGestureDist = -1;
|
|
static int multitouchGestureAngle = 0;
|
|
static int multitouchGestureX = -1;
|
|
static int multitouchGestureY = -1;
|
|
static int multitouchGestureMiddleX = -1;
|
|
static int multitouchGestureMiddleY = -1;
|
|
static int multitouchGestureHappened = 0;
|
|
enum { MULTITOUCH_MOUSE_WHEEL_DIST = 20 };
|
|
int SDL_ANDROID_TouchscreenCalibrationWidth = 480;
|
|
int SDL_ANDROID_TouchscreenCalibrationHeight = 320;
|
|
int SDL_ANDROID_TouchscreenCalibrationX = 0;
|
|
int SDL_ANDROID_TouchscreenCalibrationY = 0;
|
|
static int leftClickTimeout = 0;
|
|
static int rightClickTimeout = 0;
|
|
static int mouseInitialX = -1;
|
|
static int mouseInitialY = -1;
|
|
static unsigned int mouseInitialTime = 0;
|
|
static int deferredMouseTap = 0;
|
|
static unsigned int leftButtonDownTime = 0;
|
|
static int relativeMovement = 0;
|
|
static int relativeMovementSpeed = 2;
|
|
static int relativeMovementAccel = 0;
|
|
static int relativeMovementX = 0;
|
|
static int relativeMovementY = 0;
|
|
static unsigned int relativeMovementTime = 0;
|
|
int SDL_ANDROID_currentMouseX = 0;
|
|
int SDL_ANDROID_currentMouseY = 0;
|
|
int SDL_ANDROID_currentMouseButtons = 0;
|
|
int screenFollowsMouse = 0;
|
|
int SDL_ANDROID_SystemBarAndKeyboardShown;
|
|
|
|
static int hardwareMouseDetected = 0;
|
|
enum { MOUSE_HW_BUTTON_LEFT = 1, MOUSE_HW_BUTTON_RIGHT = 2, MOUSE_HW_BUTTON_MIDDLE = 4, MOUSE_HW_BUTTON_BACK = 8, MOUSE_HW_BUTTON_FORWARD = 16, MOUSE_HW_BUTTON_MAX = MOUSE_HW_BUTTON_FORWARD };
|
|
enum { MOUSE_HW_INPUT_FINGER = 0, MOUSE_HW_INPUT_STYLUS = 1, MOUSE_HW_INPUT_MOUSE = 2 };
|
|
enum { DEADZONE_HOVER_FINGER = 50, DEADZONE_HOVER_STYLUS = 80, HOVER_FREEZE_TIME = 500, HOVER_DISTANCE_MAX = 1024, HOVER_REDRAW_SCREEN = 1024 * 10 };
|
|
static int hoverJitterFilter = 1;
|
|
static int hoverX, hoverY, hoverTime = 0, hoverMouseFreeze = 0, hoverDeadzone = 0;
|
|
static int rightMouseButtonLongPress = 1;
|
|
static int moveMouseWithGyroscope = 0;
|
|
static float moveMouseWithGyroscopeSpeed = 5.0f;
|
|
static int moveMouseWithGyroscopeX = 0;
|
|
static int moveMouseWithGyroscopeY = 0;
|
|
static int forceScreenUpdateMouseClick = 1;
|
|
|
|
static pthread_t mouseClickTimeoutThreadId = 0;
|
|
static sem_t mouseClickTimeoutSemaphore;
|
|
static void *mouseClickTimeoutThread (void *);
|
|
static int mouseClickTimeout = 100000;
|
|
static int mouseClickTimeoutInitialized = 0;
|
|
|
|
static inline int InsideRect( const SDL_Rect * r, int x, int y )
|
|
{
|
|
return ( x >= r->x && x <= r->x + r->w ) && ( y >= r->y && y <= r->y + r->h );
|
|
}
|
|
|
|
void UpdateScreenUnderFingerRect( int x, int y )
|
|
{
|
|
#if SDL_VERSION_ATLEAST(1,3,0)
|
|
return;
|
|
#else
|
|
int screenX = SDL_ANDROID_sFakeWindowWidth, screenY = SDL_ANDROID_sFakeWindowHeight;
|
|
if( SDL_ANDROID_ShowScreenUnderFinger == ZOOM_NONE )
|
|
return;
|
|
|
|
if( SDL_ANDROID_ShowScreenUnderFinger == ZOOM_MAGNIFIER )
|
|
{
|
|
SDL_ANDROID_ShowScreenUnderFingerRectSrc.w = screenX / 4;
|
|
SDL_ANDROID_ShowScreenUnderFingerRectSrc.h = screenY / 4;
|
|
SDL_ANDROID_ShowScreenUnderFingerRectSrc.x = x - SDL_ANDROID_ShowScreenUnderFingerRectSrc.w/2;
|
|
SDL_ANDROID_ShowScreenUnderFingerRectSrc.y = y - SDL_ANDROID_ShowScreenUnderFingerRectSrc.h/2;
|
|
if( SDL_ANDROID_ShowScreenUnderFingerRectSrc.x < 0 )
|
|
SDL_ANDROID_ShowScreenUnderFingerRectSrc.x = 0;
|
|
if( SDL_ANDROID_ShowScreenUnderFingerRectSrc.y < 0 )
|
|
SDL_ANDROID_ShowScreenUnderFingerRectSrc.y = 0;
|
|
|
|
if( SDL_ANDROID_ShowScreenUnderFingerRectSrc.x > screenX - SDL_ANDROID_ShowScreenUnderFingerRectSrc.w )
|
|
SDL_ANDROID_ShowScreenUnderFingerRectSrc.x = screenX - SDL_ANDROID_ShowScreenUnderFingerRectSrc.w;
|
|
if( SDL_ANDROID_ShowScreenUnderFingerRectSrc.y > screenY - SDL_ANDROID_ShowScreenUnderFingerRectSrc.h )
|
|
SDL_ANDROID_ShowScreenUnderFingerRectSrc.y = screenY - SDL_ANDROID_ShowScreenUnderFingerRectSrc.h;
|
|
|
|
SDL_ANDROID_ShowScreenUnderFingerRect.w = SDL_ANDROID_ShowScreenUnderFingerRectSrc.w * 3 / 2;
|
|
SDL_ANDROID_ShowScreenUnderFingerRect.h = SDL_ANDROID_ShowScreenUnderFingerRectSrc.h * 3 / 2;
|
|
SDL_ANDROID_ShowScreenUnderFingerRect.x = x + SDL_ANDROID_ShowScreenUnderFingerRect.w/10;
|
|
SDL_ANDROID_ShowScreenUnderFingerRect.y = y - SDL_ANDROID_ShowScreenUnderFingerRect.h*11/10;
|
|
if( SDL_ANDROID_ShowScreenUnderFingerRect.x < 0 )
|
|
SDL_ANDROID_ShowScreenUnderFingerRect.x = 0;
|
|
if( SDL_ANDROID_ShowScreenUnderFingerRect.y < 0 )
|
|
SDL_ANDROID_ShowScreenUnderFingerRect.y = 0;
|
|
if( SDL_ANDROID_ShowScreenUnderFingerRect.x + SDL_ANDROID_ShowScreenUnderFingerRect.w >= screenX )
|
|
SDL_ANDROID_ShowScreenUnderFingerRect.x = screenX - SDL_ANDROID_ShowScreenUnderFingerRect.w - 1;
|
|
if( SDL_ANDROID_ShowScreenUnderFingerRect.y + SDL_ANDROID_ShowScreenUnderFingerRect.h >= screenY )
|
|
SDL_ANDROID_ShowScreenUnderFingerRect.y = screenY - SDL_ANDROID_ShowScreenUnderFingerRect.h - 1;
|
|
if( InsideRect(&SDL_ANDROID_ShowScreenUnderFingerRect, x, y) )
|
|
SDL_ANDROID_ShowScreenUnderFingerRect.x = x - SDL_ANDROID_ShowScreenUnderFingerRect.w*11/10 - 1;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if SDL_VERSION_ATLEAST(1,3,0)
|
|
#define SDL_ANDROID_sFakeWindowWidth (SDL_GetFocusWindow() ? SDL_GetFocusWindow()->w : 100)
|
|
#define SDL_ANDROID_sFakeWindowHeight (SDL_GetFocusWindow() ? SDL_GetFocusWindow()->h : 100)
|
|
#endif
|
|
|
|
static int BumpPointerId( int pointerId )
|
|
{
|
|
if(pointerId < 0)
|
|
pointerId = 0;
|
|
if(pointerId >= MAX_MULTITOUCH_POINTERS)
|
|
pointerId = MAX_MULTITOUCH_POINTERS-1;
|
|
return pointerId;
|
|
}
|
|
|
|
static int ProcessTouchscreenKeyboard( int x, int y, int action, int pointerId )
|
|
{
|
|
// The touch is passed either to on-screen keyboard or as mouse event for all duration of touch between down and up,
|
|
// even if the finger is not anymore above screen kb button it will not acr as mouse event, and if it's initially
|
|
// touches the screen outside of screen kb it won't trigger button keypress -
|
|
// I think it's more logical this way
|
|
if( SDL_ANDROID_isTouchscreenKeyboardUsed && ( action == MOUSE_DOWN || touchPointers[pointerId] & TOUCH_PTR_SCREENKB ) )
|
|
{
|
|
unsigned processed = SDL_ANDROID_processTouchscreenKeyboard(x, y, action, pointerId);
|
|
//__android_log_print(ANDROID_LOG_INFO, "libSDL", "SDL_ANDROID_processTouchscreenKeyboard: ptr %d action %d ret 0x%08x", pointerId, action, processed);
|
|
if( processed && action == MOUSE_DOWN )
|
|
touchPointers[pointerId] |= TOUCH_PTR_SCREENKB;
|
|
if( touchPointers[pointerId] & TOUCH_PTR_SCREENKB )
|
|
{
|
|
if( action == MOUSE_UP )
|
|
touchPointers[pointerId] = TOUCH_PTR_UP;
|
|
if( !(processed & TOUCHSCREEN_KEYBOARD_PASS_EVENT_DOWN_TO_SDL) )
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void AssignNewTouchPointers( int action, int pointerId )
|
|
{
|
|
int i;
|
|
if( action == MOUSE_DOWN )
|
|
{
|
|
touchPointers[pointerId] |= TOUCH_PTR_MOUSE;
|
|
firstMousePointerId = -1;
|
|
secondMousePointerId = -1;
|
|
for( i = 0; i < MAX_MULTITOUCH_POINTERS; i++ )
|
|
{
|
|
if( touchPointers[i] & TOUCH_PTR_MOUSE )
|
|
{
|
|
if( firstMousePointerId == -1 )
|
|
firstMousePointerId = i;
|
|
else if( secondMousePointerId == -1 )
|
|
secondMousePointerId = i;
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void ClearOldTouchPointers( int action, int pointerId )
|
|
{
|
|
int i;
|
|
if( action == MOUSE_UP )
|
|
{
|
|
touchPointers[pointerId] = TOUCH_PTR_UP;
|
|
firstMousePointerId = -1;
|
|
secondMousePointerId = -1;
|
|
for( i = 0; i < MAX_MULTITOUCH_POINTERS; i++ )
|
|
{
|
|
if( touchPointers[i] != TOUCH_PTR_MOUSE )
|
|
{
|
|
if( firstMousePointerId == -1 )
|
|
firstMousePointerId = i;
|
|
else if( secondMousePointerId == -1 )
|
|
secondMousePointerId = i;
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void AdjustTouchScreenCalibration( jint *xx, jint *yy )
|
|
{
|
|
int x = *xx, y = *yy;
|
|
|
|
x -= SDL_ANDROID_TouchscreenCalibrationX;
|
|
y -= SDL_ANDROID_TouchscreenCalibrationY;
|
|
#if SDL_VIDEO_RENDER_RESIZE
|
|
// Translate mouse coordinates
|
|
|
|
x -= (SDL_ANDROID_sRealWindowWidth - SDL_ANDROID_sWindowWidth) / 2;
|
|
x = x * SDL_ANDROID_sFakeWindowWidth / SDL_ANDROID_TouchscreenCalibrationWidth;
|
|
y = y * SDL_ANDROID_sFakeWindowHeight / SDL_ANDROID_TouchscreenCalibrationHeight;
|
|
if( x < 0 )
|
|
x = 0;
|
|
if( x > SDL_ANDROID_sFakeWindowWidth )
|
|
x = SDL_ANDROID_sFakeWindowWidth;
|
|
if( y < 0 )
|
|
y = 0;
|
|
if( y > SDL_ANDROID_sFakeWindowHeight )
|
|
y = SDL_ANDROID_sFakeWindowHeight;
|
|
|
|
#else
|
|
x = x * SDL_ANDROID_sRealWindowWidth / SDL_ANDROID_TouchscreenCalibrationWidth;
|
|
y = y * SDL_ANDROID_sRealWindowHeight / SDL_ANDROID_TouchscreenCalibrationHeight;
|
|
#endif
|
|
|
|
*xx = x;
|
|
*yy = y;
|
|
}
|
|
|
|
static void ProcessMultitouchGesture( int x, int y, int action, int pointerId )
|
|
{
|
|
int i;
|
|
if( action == MOUSE_UP )
|
|
{
|
|
multitouchGestureX = -1;
|
|
multitouchGestureY = -1;
|
|
multitouchGestureDist = -1;
|
|
multitouchGestureMiddleX = -1;
|
|
multitouchGestureMiddleY = -1;
|
|
}
|
|
else if( !hardwareMouseDetected && !(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON_MMASK) )
|
|
{
|
|
if( firstMousePointerId != pointerId )
|
|
{
|
|
multitouchGestureX = x;
|
|
multitouchGestureY = y;
|
|
}
|
|
if( firstMousePointerId == pointerId && multitouchGestureX >= 0 )
|
|
{
|
|
int dist = abs( x - multitouchGestureX ) + abs( y - multitouchGestureY );
|
|
int angle = atan2i( y - multitouchGestureY, x - multitouchGestureX );
|
|
int middleX = (x + multitouchGestureX) / 2;
|
|
int middleY = (y + multitouchGestureY) / 2;
|
|
if( multitouchGestureDist < 0 )
|
|
{
|
|
multitouchGestureDist = dist;
|
|
multitouchGestureAngle = angle;
|
|
multitouchGestureMiddleX = middleX;
|
|
multitouchGestureMiddleY = middleY;
|
|
}
|
|
else
|
|
{
|
|
int distMaxDiff = SDL_ANDROID_sFakeWindowHeight / ( 2 + (1 + multitouchGestureSensitivity) * 3 );
|
|
int angleMaxDiff = atan2i_PI * 2 / 3 / ( 1 + (1 + multitouchGestureSensitivity) * 2 );
|
|
int wheelThreshold = SDL_ANDROID_sFakeWindowHeight / MULTITOUCH_MOUSE_WHEEL_DIST;
|
|
if( dist - multitouchGestureDist > distMaxDiff )
|
|
{
|
|
multitouchGestureHappened = 1;
|
|
multitouchGestureDist += distMaxDiff;
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_PRESSED, multitouchGestureKeycode[0], 0 );
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_RELEASED, multitouchGestureKeycode[0], 0 );
|
|
}
|
|
if( multitouchGestureDist - dist > distMaxDiff )
|
|
{
|
|
multitouchGestureHappened = 1;
|
|
multitouchGestureDist -= distMaxDiff;
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_PRESSED, multitouchGestureKeycode[1], 0 );
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_RELEASED, multitouchGestureKeycode[1], 0 );
|
|
}
|
|
|
|
int angleDiff = angle - multitouchGestureAngle;
|
|
|
|
while( angleDiff < atan2i_PI )
|
|
angleDiff += atan2i_PI * 2;
|
|
while( angleDiff > atan2i_PI )
|
|
angleDiff -= atan2i_PI * 2;
|
|
|
|
if( angleDiff < -angleMaxDiff )
|
|
{
|
|
multitouchGestureHappened = 1;
|
|
multitouchGestureAngle = angle;
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_PRESSED, multitouchGestureKeycode[2], 0 );
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_RELEASED, multitouchGestureKeycode[2], 0 );
|
|
}
|
|
if( angleDiff > angleMaxDiff )
|
|
{
|
|
multitouchGestureHappened = 1;
|
|
multitouchGestureAngle = angle;
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_PRESSED, multitouchGestureKeycode[3], 0 );
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_RELEASED, multitouchGestureKeycode[3], 0 );
|
|
}
|
|
|
|
if( rightMouseButtonLongPress )
|
|
return;
|
|
|
|
//__android_log_print(ANDROID_LOG_INFO, "libSDL", "middleY %d multitouchGestureMiddleY %d threshold %d", middleY, multitouchGestureMiddleY, wheelThreshold);
|
|
if( middleX - multitouchGestureMiddleX > wheelThreshold )
|
|
{
|
|
multitouchGestureHappened = 1;
|
|
multitouchGestureMiddleX += wheelThreshold;
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_PRESSED, SDL_BUTTON_X1 );
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_RELEASED, SDL_BUTTON_X1 );
|
|
}
|
|
if( multitouchGestureMiddleX - middleX > wheelThreshold )
|
|
{
|
|
multitouchGestureHappened = 1;
|
|
multitouchGestureMiddleX -= wheelThreshold;
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_PRESSED, SDL_BUTTON_X2 );
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_RELEASED, SDL_BUTTON_X2 );
|
|
}
|
|
if( middleY - multitouchGestureMiddleY > wheelThreshold )
|
|
{
|
|
multitouchGestureHappened = 1;
|
|
multitouchGestureMiddleY += wheelThreshold;
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_PRESSED, SDL_BUTTON_WHEELUP );
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_RELEASED, SDL_BUTTON_WHEELUP );
|
|
}
|
|
if( multitouchGestureMiddleY - middleY > wheelThreshold )
|
|
{
|
|
multitouchGestureHappened = 1;
|
|
multitouchGestureMiddleY -= wheelThreshold;
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_PRESSED, SDL_BUTTON_WHEELDOWN );
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_RELEASED, SDL_BUTTON_WHEELDOWN );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void SendMultitouchEvents( int x, int y, int action, int pointerId, int force, int radius )
|
|
{
|
|
if( isMultitouchUsed && (action == MOUSE_DOWN || action == MOUSE_UP || action == MOUSE_MOVE) ) // Ignore hover events
|
|
{
|
|
#if SDL_VERSION_ATLEAST(1,3,0)
|
|
// Use nifty SDL 1.3 multitouch API
|
|
if( action == MOUSE_MOVE )
|
|
SDL_ANDROID_MainThreadPushMultitouchMotion(pointerId, x, y, force + radius);
|
|
else
|
|
SDL_ANDROID_MainThreadPushMultitouchButton(pointerId, action == MOUSE_DOWN ? 1 : 0, x, y, force + radius);
|
|
#endif
|
|
|
|
if( action == MOUSE_DOWN )
|
|
SDL_ANDROID_MainThreadPushJoystickButton(JOY_TOUCHSCREEN, pointerId, SDL_PRESSED);
|
|
SDL_ANDROID_MainThreadPushJoystickAxis(JOY_TOUCHSCREEN, pointerId+4, force + radius); // Radius is more sensitive usually
|
|
SDL_ANDROID_MainThreadPushJoystickBall(JOY_TOUCHSCREEN, pointerId, x, y);
|
|
if( action == MOUSE_UP )
|
|
SDL_ANDROID_MainThreadPushJoystickButton(JOY_TOUCHSCREEN, pointerId, SDL_RELEASED);
|
|
}
|
|
|
|
if( !isMultitouchUsed && !SDL_ANDROID_isMouseUsed && !SDL_ANDROID_isTouchscreenKeyboardUsed )
|
|
{
|
|
SDL_keysym keysym;
|
|
if( action == MOUSE_DOWN || action == MOUSE_UP )
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( action == MOUSE_DOWN ? SDL_PRESSED : SDL_RELEASED, SDL_ANDROID_GetScreenKeyboardButtonKey(SDL_ANDROID_SCREENKEYBOARD_BUTTON_0), 0 );
|
|
return;
|
|
}
|
|
}
|
|
|
|
static void ProcessMouseRelativeMovement( jint *xx, jint *yy, int action )
|
|
{
|
|
int x = *xx, y = *yy;
|
|
|
|
if( !relativeMovement )
|
|
return;
|
|
|
|
if( action == MOUSE_DOWN )
|
|
{
|
|
relativeMovementX = SDL_ANDROID_currentMouseX - x;
|
|
relativeMovementY = SDL_ANDROID_currentMouseY - y;
|
|
}
|
|
x += relativeMovementX;
|
|
y += relativeMovementY;
|
|
|
|
int diffX = x - SDL_ANDROID_currentMouseX;
|
|
int diffY = y - SDL_ANDROID_currentMouseY;
|
|
int coeff = relativeMovementSpeed + 2;
|
|
if( relativeMovementSpeed > 2 )
|
|
coeff += relativeMovementSpeed - 2;
|
|
diffX = diffX * coeff / 4;
|
|
diffY = diffY * coeff / 4;
|
|
if( relativeMovementAccel > 0 )
|
|
{
|
|
unsigned int newTime = SDL_GetTicks();
|
|
if( newTime - relativeMovementTime > 0 )
|
|
{
|
|
diffX += diffX * ( relativeMovementAccel * 30 ) / (int)(newTime - relativeMovementTime);
|
|
diffY += diffY * ( relativeMovementAccel * 30 ) / (int)(newTime - relativeMovementTime);
|
|
}
|
|
relativeMovementTime = newTime;
|
|
}
|
|
diffX -= x - SDL_ANDROID_currentMouseX;
|
|
diffY -= y - SDL_ANDROID_currentMouseY;
|
|
x += diffX;
|
|
y += diffY;
|
|
relativeMovementX += diffX;
|
|
relativeMovementY += diffY;
|
|
|
|
diffX = x;
|
|
diffY = y;
|
|
if( x < 0 )
|
|
x = 0;
|
|
if( x > SDL_ANDROID_sFakeWindowWidth )
|
|
x = SDL_ANDROID_sFakeWindowWidth;
|
|
if( y < 0 )
|
|
y = 0;
|
|
if( y > SDL_ANDROID_sFakeWindowHeight )
|
|
y = SDL_ANDROID_sFakeWindowHeight;
|
|
relativeMovementX += x - diffX;
|
|
relativeMovementY += y - diffY;
|
|
|
|
*xx = x;
|
|
*yy = y;
|
|
}
|
|
|
|
static void ProcessMouseUp( int x, int y )
|
|
{
|
|
if( rightClickMethod != RIGHT_CLICK_WITH_KEY )
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_RELEASED, SDL_BUTTON_RIGHT );
|
|
|
|
if( mouseInitialX >= 0 && mouseInitialY >= 0 && (
|
|
leftClickMethod == LEFT_CLICK_WITH_TAP || leftClickMethod == LEFT_CLICK_WITH_TAP_OR_TIMEOUT ) &&
|
|
abs(mouseInitialX - x) < SDL_ANDROID_sFakeWindowHeight / 16 &&
|
|
abs(mouseInitialY - y) < SDL_ANDROID_sFakeWindowHeight / 16 &&
|
|
SDL_GetTicks() - mouseInitialTime < 700 )
|
|
{
|
|
SDL_ANDROID_MainThreadPushMouseMotion( mouseInitialX, mouseInitialY );
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_PRESSED, SDL_BUTTON_LEFT );
|
|
if( forceScreenUpdateMouseClick && mouseInitialX > 0 )
|
|
SDL_ANDROID_MainThreadPushMouseMotion( mouseInitialX - 1, mouseInitialY );
|
|
mouseInitialX = -1;
|
|
mouseInitialY = -1;
|
|
deferredMouseTap = 2;
|
|
mouseClickTimeout = 200;
|
|
if( mouseClickTimeoutInitialized )
|
|
sem_post(&mouseClickTimeoutSemaphore);
|
|
}
|
|
else
|
|
{
|
|
if( leftClickMethod != LEFT_CLICK_WITH_KEY )
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_RELEASED, SDL_BUTTON_LEFT );
|
|
}
|
|
|
|
SDL_ANDROID_ShowScreenUnderFingerRect.w = SDL_ANDROID_ShowScreenUnderFingerRect.h = 0;
|
|
SDL_ANDROID_ShowScreenUnderFingerRectSrc.w = SDL_ANDROID_ShowScreenUnderFingerRectSrc.h = 0;
|
|
if( SDL_ANDROID_ShowScreenUnderFinger == ZOOM_MAGNIFIER )
|
|
{
|
|
// Move mouse by 1 pixel so it will force screen update and mouse-under-finger window will be removed
|
|
if( SDL_ANDROID_moveMouseWithKbActive )
|
|
SDL_ANDROID_MainThreadPushMouseMotion(SDL_ANDROID_moveMouseWithKbX > 0 ? SDL_ANDROID_moveMouseWithKbX-1 : 0, SDL_ANDROID_moveMouseWithKbY);
|
|
else
|
|
SDL_ANDROID_MainThreadPushMouseMotion(x > 0 ? x-1 : 0, y);
|
|
}
|
|
SDL_ANDROID_moveMouseWithKbActive = 0;
|
|
SDL_ANDROID_moveMouseWithKbX = 0;
|
|
SDL_ANDROID_moveMouseWithKbY = 0;
|
|
SDL_ANDROID_moveMouseWithKbSpeedX = 0;
|
|
SDL_ANDROID_moveMouseWithKbSpeedY = 0;
|
|
if( !deferredMouseTap )
|
|
{
|
|
moveMouseWithGyroscopeX = 0;
|
|
moveMouseWithGyroscopeY = 0;
|
|
}
|
|
}
|
|
|
|
static int ProcessMouseDown( int x, int y )
|
|
{
|
|
int action = MOUSE_DOWN;
|
|
if( (SDL_ANDROID_moveMouseWithKbActive || leftClickMethod == LEFT_CLICK_NEAR_CURSOR) &&
|
|
abs(SDL_ANDROID_currentMouseX - x) < SDL_ANDROID_sFakeWindowWidth / 10 && abs(SDL_ANDROID_currentMouseY - y) < SDL_ANDROID_sFakeWindowHeight / 10 )
|
|
{
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_PRESSED, SDL_BUTTON_LEFT );
|
|
SDL_ANDROID_moveMouseWithKbX = SDL_ANDROID_currentMouseX;
|
|
SDL_ANDROID_moveMouseWithKbY = SDL_ANDROID_currentMouseY;
|
|
SDL_ANDROID_moveMouseWithKbSpeedX = 0;
|
|
SDL_ANDROID_moveMouseWithKbSpeedY = 0;
|
|
leftButtonDownTime = SDL_GetTicks();
|
|
action = MOUSE_MOVE;
|
|
}
|
|
else
|
|
if( leftClickMethod == LEFT_CLICK_NORMAL )
|
|
{
|
|
SDL_ANDROID_MainThreadPushMouseMotion(x, y);
|
|
if( !hardwareMouseDetected || SDL_ANDROID_currentMouseButtons == 0 )
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_PRESSED, SDL_BUTTON_LEFT );
|
|
}
|
|
else
|
|
{
|
|
SDL_ANDROID_MainThreadPushMouseMotion(x, y);
|
|
action == MOUSE_MOVE;
|
|
mouseInitialX = x;
|
|
mouseInitialY = y;
|
|
mouseInitialTime = SDL_GetTicks();
|
|
mouseClickTimeout = (rightClickMethod == RIGHT_CLICK_WITH_TIMEOUT) ? rightClickTimeout + 10 : leftClickTimeout + 10;
|
|
if( mouseClickTimeoutInitialized )
|
|
sem_post(&mouseClickTimeoutSemaphore);
|
|
}
|
|
if( SDL_ANDROID_ShowScreenUnderFinger == ZOOM_MAGNIFIER )
|
|
UpdateScreenUnderFingerRect(x, y);
|
|
return action;
|
|
}
|
|
|
|
static void ProcessMouseMove_Timeouts( int x, int y )
|
|
{
|
|
if( mouseInitialX >= 0 && mouseInitialY >= 0 && (
|
|
leftClickMethod == LEFT_CLICK_WITH_TIMEOUT || leftClickMethod == LEFT_CLICK_WITH_TAP ||
|
|
leftClickMethod == LEFT_CLICK_WITH_TAP_OR_TIMEOUT || rightClickMethod == RIGHT_CLICK_WITH_TIMEOUT ) )
|
|
{
|
|
if( abs(mouseInitialX - x) >= SDL_ANDROID_sFakeWindowHeight / 15 || abs(mouseInitialY - y) >= SDL_ANDROID_sFakeWindowHeight / 15 )
|
|
{
|
|
mouseInitialX = -1;
|
|
mouseInitialY = -1;
|
|
}
|
|
else
|
|
{
|
|
if( leftClickMethod == LEFT_CLICK_WITH_TIMEOUT || leftClickMethod == LEFT_CLICK_WITH_TAP_OR_TIMEOUT )
|
|
{
|
|
if( SDL_GetTicks() - mouseInitialTime > leftClickTimeout )
|
|
{
|
|
//SDL_ANDROID_MainThreadPushMouseMotion(mouseInitialX, mouseInitialY);
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_PRESSED, SDL_BUTTON_LEFT );
|
|
mouseInitialX = -1;
|
|
mouseInitialY = -1;
|
|
}
|
|
}
|
|
if( rightClickMethod == RIGHT_CLICK_WITH_TIMEOUT )
|
|
{
|
|
if( SDL_GetTicks() - mouseInitialTime > rightClickTimeout )
|
|
{
|
|
//SDL_ANDROID_MainThreadPushMouseMotion(mouseInitialX, mouseInitialY);
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_PRESSED, SDL_BUTTON_RIGHT );
|
|
mouseInitialX = -1;
|
|
mouseInitialY = -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if( SDL_ANDROID_ShowScreenUnderFinger == ZOOM_MAGNIFIER )
|
|
UpdateScreenUnderFingerRect(x, y);
|
|
}
|
|
|
|
static void ProcessMouseMove( int x, int y, int force, int radius )
|
|
{
|
|
if( SDL_ANDROID_moveMouseWithKbActive )
|
|
{
|
|
// Mouse lazily follows magnifying glass, not very intuitive for drag&drop
|
|
/*
|
|
if( abs(moveMouseWithKbX - x) > SDL_ANDROID_sFakeWindowWidth / 12 )
|
|
moveMouseWithKbSpeedX += moveMouseWithKbX > x ? -1 : 1;
|
|
else
|
|
moveMouseWithKbSpeedX = moveMouseWithKbSpeedX * 2 / 3;
|
|
if( abs(moveMouseWithKbY - y) > SDL_ANDROID_sFakeWindowHeight / 12 )
|
|
moveMouseWithKbSpeedY += moveMouseWithKbY > y ? -1 : 1;
|
|
else
|
|
moveMouseWithKbSpeedY = moveMouseWithKbSpeedY * 2 / 3;
|
|
|
|
moveMouseWithKbX += moveMouseWithKbSpeedX;
|
|
moveMouseWithKbY += moveMouseWithKbSpeedY;
|
|
*/
|
|
// Mouse follows touch instantly, when it's out of the snapping distance from mouse cursor
|
|
if( abs(SDL_ANDROID_moveMouseWithKbX - x) >= SDL_ANDROID_sFakeWindowWidth / 10 ||
|
|
abs(SDL_ANDROID_moveMouseWithKbY - y) >= SDL_ANDROID_sFakeWindowHeight / 10 ) // || SDL_GetTicks() - leftButtonDownTime > 600
|
|
{
|
|
SDL_ANDROID_moveMouseWithKbActive = 0;
|
|
SDL_ANDROID_moveMouseWithKbX = 0;
|
|
SDL_ANDROID_moveMouseWithKbY = 0;
|
|
SDL_ANDROID_moveMouseWithKbSpeedX = 0;
|
|
SDL_ANDROID_moveMouseWithKbSpeedY = 0;
|
|
SDL_ANDROID_MainThreadPushMouseMotion(x, y);
|
|
}
|
|
else
|
|
SDL_ANDROID_MainThreadPushMouseMotion(SDL_ANDROID_moveMouseWithKbX, SDL_ANDROID_moveMouseWithKbY);
|
|
}
|
|
else
|
|
{
|
|
SDL_ANDROID_MainThreadPushMouseMotion(x, y);
|
|
}
|
|
|
|
if( rightClickMethod == RIGHT_CLICK_WITH_PRESSURE || leftClickMethod == LEFT_CLICK_WITH_PRESSURE )
|
|
{
|
|
int button = (leftClickMethod == LEFT_CLICK_WITH_PRESSURE) ? SDL_BUTTON_LEFT : SDL_BUTTON_RIGHT;
|
|
int buttonState = ( force > maxForce || radius > maxRadius );
|
|
if( button == SDL_BUTTON_RIGHT )
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_RELEASED, SDL_BUTTON_LEFT );
|
|
SDL_ANDROID_MainThreadPushMouseButton( buttonState ? SDL_PRESSED : SDL_RELEASED, button );
|
|
}
|
|
ProcessMouseMove_Timeouts(x, y);
|
|
}
|
|
|
|
static void ProcessMouseMultitouch( int action, int pointerId )
|
|
{
|
|
if( pointerId == secondMousePointerId && (action == MOUSE_DOWN || action == MOUSE_UP) )
|
|
{
|
|
if( leftClickMethod == LEFT_CLICK_WITH_MULTITOUCH )
|
|
{
|
|
SDL_ANDROID_MainThreadPushMouseButton( (action == MOUSE_DOWN) ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_LEFT );
|
|
}
|
|
else if( rightClickMethod == RIGHT_CLICK_WITH_MULTITOUCH )
|
|
{
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_RELEASED, SDL_BUTTON_LEFT );
|
|
if( rightMouseButtonLongPress )
|
|
SDL_ANDROID_MainThreadPushMouseButton( (action == MOUSE_DOWN) ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_RIGHT );
|
|
else
|
|
{
|
|
if( action == MOUSE_UP )
|
|
{
|
|
if( !multitouchGestureHappened )
|
|
{
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_PRESSED, SDL_BUTTON_RIGHT );
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_RELEASED, SDL_BUTTON_RIGHT );
|
|
}
|
|
}
|
|
multitouchGestureHappened = 0;
|
|
}
|
|
}
|
|
}
|
|
if( pointerId != firstMousePointerId && pointerId != secondMousePointerId && (action == MOUSE_DOWN || action == MOUSE_UP) )
|
|
{
|
|
SDL_ANDROID_MainThreadPushMouseButton( (action == MOUSE_DOWN) ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_MIDDLE );
|
|
multitouchGestureHappened = 1; // Prevent firing left mouse button when lifting two fingers
|
|
}
|
|
}
|
|
|
|
static void ProcessMouseHover( jint *xx, jint *yy, int action, int distance )
|
|
{
|
|
int x = *xx, y = *yy;
|
|
|
|
if( relativeMovement )
|
|
return;
|
|
|
|
if( !hoverJitterFilter )
|
|
{
|
|
if( action == MOUSE_HOVER )
|
|
SDL_ANDROID_MainThreadPushMouseMotion(x, y);
|
|
}
|
|
else
|
|
{
|
|
if( action == MOUSE_HOVER )
|
|
{
|
|
if( hoverDeadzone )
|
|
{
|
|
if( abs(x - hoverX) < hoverDeadzone && abs(y - hoverY) < hoverDeadzone )
|
|
{
|
|
if( hoverTime == 0 )
|
|
hoverTime = SDL_GetTicks();
|
|
else if( !hoverMouseFreeze && SDL_GetTicks() > hoverTime + HOVER_FREEZE_TIME )
|
|
{
|
|
hoverMouseFreeze = 1;
|
|
hoverX = x;
|
|
hoverY = y;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hoverTime = 0;
|
|
hoverMouseFreeze = 0;
|
|
hoverX = x;
|
|
hoverY = y;
|
|
}
|
|
}
|
|
if( !hoverMouseFreeze )
|
|
SDL_ANDROID_MainThreadPushMouseMotion(x, y);
|
|
}
|
|
else if( hoverMouseFreeze && !(abs(x - hoverX) < hoverDeadzone && abs(y - hoverY) < hoverDeadzone) )
|
|
{
|
|
hoverMouseFreeze = 0;
|
|
hoverTime = 0;
|
|
}
|
|
|
|
if( hoverMouseFreeze )
|
|
{
|
|
*xx = hoverX;
|
|
*yy = hoverY;
|
|
}
|
|
}
|
|
|
|
if( action == MOUSE_HOVER && distance < HOVER_DISTANCE_MAX * 3 / 4 )
|
|
UpdateScreenUnderFingerRect(*xx, *yy);
|
|
else
|
|
SDL_ANDROID_ShowScreenUnderFingerRect.w = SDL_ANDROID_ShowScreenUnderFingerRect.h = 0; // This is reset later by ProcessMouseMove()
|
|
|
|
if( distance == HOVER_REDRAW_SCREEN && *xx > 0 ) // Force screen redraw, to remove magnifier window when hovering finger leaves the screen
|
|
{
|
|
(*xx)--;
|
|
SDL_ANDROID_MainThreadPushMouseMotion(*xx, *yy);
|
|
}
|
|
|
|
#ifdef VIDEO_DEBUG
|
|
SDL_ANDROID_VideoDebugRect.x = hoverX - hoverDeadzone;
|
|
SDL_ANDROID_VideoDebugRect.y = hoverY - hoverDeadzone;
|
|
SDL_ANDROID_VideoDebugRect.w = hoverDeadzone * 2;
|
|
SDL_ANDROID_VideoDebugRect.h = hoverDeadzone * 2;
|
|
memset(&SDL_ANDROID_VideoDebugRectColor, 0, sizeof(SDL_ANDROID_VideoDebugRectColor));
|
|
SDL_ANDROID_VideoDebugRectColor.g = hoverMouseFreeze * 255;
|
|
SDL_ANDROID_VideoDebugRectColor.r = SDL_ANDROID_VideoDebugRectColor.b = (SDL_GetTicks() - hoverTime) * 255 / HOVER_FREEZE_TIME;
|
|
#endif
|
|
}
|
|
|
|
static void AdjustMouseWithGyroscope( jint *xx, jint *yy )
|
|
{
|
|
if( !moveMouseWithGyroscope || relativeMovement ||
|
|
SDL_ANDROID_moveMouseWithKbActive || hardwareMouseDetected == MOUSE_HW_INPUT_MOUSE )
|
|
return;
|
|
|
|
static int oldX = 0, oldY = 0, count = 0;
|
|
count += abs(*xx - oldX) + abs(*yy - oldY);
|
|
oldX = *xx;
|
|
oldY = *yy;
|
|
|
|
*xx += moveMouseWithGyroscopeX;
|
|
*yy += moveMouseWithGyroscopeY;
|
|
|
|
// Decrease the adjustment values slowly, when we move mouse
|
|
int decrease = count / 10;
|
|
count %= 10;
|
|
|
|
#define SIGN(x) ((x > 0) - (x < 0)) // -1, 0, or 1, depending on the value sign
|
|
|
|
int signX = SIGN(moveMouseWithGyroscopeX);
|
|
moveMouseWithGyroscopeX -= signX * decrease;
|
|
if( signX != SIGN(moveMouseWithGyroscopeX) )
|
|
moveMouseWithGyroscopeX = 0;
|
|
|
|
int signY = SIGN(moveMouseWithGyroscopeY);
|
|
moveMouseWithGyroscopeY -= signY * decrease;
|
|
if( signY != SIGN(moveMouseWithGyroscopeY) )
|
|
moveMouseWithGyroscopeY = 0;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
JAVA_EXPORT_NAME(DemoGLSurfaceView_nativeMotionEvent) ( JNIEnv* env, jobject thiz, jint x, jint y, jint action, jint pointerId, jint force, jint radius )
|
|
{
|
|
int i;
|
|
#if SDL_VERSION_ATLEAST(1,3,0)
|
|
if( !SDL_GetFocusWindow() )
|
|
return;
|
|
#else
|
|
if( !SDL_CurrentVideoSurface )
|
|
return;
|
|
#endif
|
|
|
|
//__android_log_print(ANDROID_LOG_INFO, "libSDL", "Motion event: %4d %4d action %d ptr %d, force %d radius %d", x, y, action, pointerId, force, radius);
|
|
|
|
pointerId = BumpPointerId( pointerId );
|
|
|
|
if( ProcessTouchscreenKeyboard( x, y, action, pointerId ) )
|
|
return;
|
|
|
|
AssignNewTouchPointers( action, pointerId );
|
|
|
|
AdjustTouchScreenCalibration( &x, &y );
|
|
|
|
ProcessMultitouchGesture( x, y, action, pointerId );
|
|
|
|
SendMultitouchEvents( x, y, action, pointerId, force, radius );
|
|
|
|
if( !SDL_ANDROID_isMouseUsed )
|
|
return;
|
|
|
|
AdjustMouseWithGyroscope( &x, &y );
|
|
|
|
ProcessMouseHover( &x, &y, action, force );
|
|
|
|
if( pointerId == firstMousePointerId )
|
|
{
|
|
ProcessMouseRelativeMovement( &x, &y, action );
|
|
if( action == MOUSE_UP )
|
|
ProcessMouseUp( x, y );
|
|
if( action == MOUSE_DOWN )
|
|
action = ProcessMouseDown( x, y ); // May change action to MOUSE_MOVE
|
|
if( action == MOUSE_MOVE )
|
|
ProcessMouseMove( x, y, force, radius );
|
|
}
|
|
ProcessMouseMultitouch( action, pointerId );
|
|
|
|
ClearOldTouchPointers( action, pointerId );
|
|
}
|
|
|
|
static void ProcessDeferredMouseTap()
|
|
{
|
|
if( deferredMouseTap > 0 )
|
|
{
|
|
deferredMouseTap--;
|
|
if (deferredMouseTap > 0)
|
|
return;
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_RELEASED, SDL_BUTTON_LEFT );
|
|
if( forceScreenUpdateMouseClick && SDL_ANDROID_currentMouseX + 1 < SDL_ANDROID_sFakeWindowWidth )
|
|
SDL_ANDROID_MainThreadPushMouseMotion( SDL_ANDROID_currentMouseX + 1, SDL_ANDROID_currentMouseY );
|
|
moveMouseWithGyroscopeX = 0;
|
|
moveMouseWithGyroscopeY = 0;
|
|
}
|
|
}
|
|
|
|
static void ProcessMoveMouseWithGyroscope(float gx, float gy, float gz)
|
|
{
|
|
if( hardwareMouseDetected == MOUSE_HW_INPUT_MOUSE ) // We don't need all that stuff with a proper precise input device
|
|
return;
|
|
|
|
//gx += gz; // Ignore Z
|
|
gx *= moveMouseWithGyroscopeSpeed;
|
|
gy *= -moveMouseWithGyroscopeSpeed; // Screen has Y coordinate inverted
|
|
|
|
static float subpixelX = 0.0f, subpixelY = 0.0f;
|
|
|
|
gx += subpixelX;
|
|
gy += subpixelY;
|
|
float t = truncf(gx);
|
|
subpixelX = gx - t;
|
|
gx = t;
|
|
t = truncf(gy);
|
|
subpixelY = gy - t;
|
|
gy = t;
|
|
|
|
// TODO: mutex here?
|
|
// If race condition happens, mouse will jump at random across the screen. Nothing serious.
|
|
|
|
if( SDL_ANDROID_moveMouseWithKbActive )
|
|
{
|
|
SDL_ANDROID_moveMouseWithKbX += gx;
|
|
SDL_ANDROID_moveMouseWithKbY += gy;
|
|
if (SDL_ANDROID_moveMouseWithKbX < 0)
|
|
SDL_ANDROID_moveMouseWithKbX = 0;
|
|
if (SDL_ANDROID_moveMouseWithKbY < 0)
|
|
SDL_ANDROID_moveMouseWithKbY = 0;
|
|
if (SDL_ANDROID_moveMouseWithKbX >= SDL_ANDROID_sFakeWindowWidth)
|
|
SDL_ANDROID_moveMouseWithKbX = SDL_ANDROID_sFakeWindowWidth - 1;
|
|
if (SDL_ANDROID_moveMouseWithKbY >= SDL_ANDROID_sFakeWindowHeight)
|
|
SDL_ANDROID_moveMouseWithKbY = SDL_ANDROID_sFakeWindowHeight - 1;
|
|
SDL_ANDROID_MainThreadPushMouseMotion(SDL_ANDROID_moveMouseWithKbX, SDL_ANDROID_moveMouseWithKbY);
|
|
return;
|
|
}
|
|
|
|
if( relativeMovement )
|
|
{
|
|
SDL_ANDROID_MainThreadPushMouseMotion(SDL_ANDROID_currentMouseX + gx, SDL_ANDROID_currentMouseY + gy);
|
|
return;
|
|
}
|
|
|
|
// Mouse coords before gyroscope was applied
|
|
int actualTouchX = SDL_ANDROID_currentMouseX - moveMouseWithGyroscopeX;
|
|
int actualTouchY = SDL_ANDROID_currentMouseY - moveMouseWithGyroscopeY;
|
|
|
|
moveMouseWithGyroscopeX += gx;
|
|
moveMouseWithGyroscopeY += gy;
|
|
|
|
SDL_ANDROID_MainThreadPushMouseMotion(actualTouchX + moveMouseWithGyroscopeX, actualTouchY + moveMouseWithGyroscopeY);
|
|
}
|
|
|
|
void SDL_ANDROID_WarpMouse(int x, int y)
|
|
{
|
|
if(!relativeMovement)
|
|
{
|
|
//SDL_ANDROID_MainThreadPushMouseMotion(x, y);
|
|
}
|
|
else
|
|
{
|
|
//__android_log_print(ANDROID_LOG_INFO, "libSDL", "SDL_ANDROID_WarpMouse(): %dx%d rel %dx%d old %dx%d", x, y, relativeMovementX, relativeMovementY, SDL_ANDROID_currentMouseX, SDL_ANDROID_currentMouseY);
|
|
relativeMovementX -= SDL_ANDROID_currentMouseX-x;
|
|
relativeMovementY -= SDL_ANDROID_currentMouseY-y;
|
|
SDL_ANDROID_MainThreadPushMouseMotion(x, y);
|
|
}
|
|
};
|
|
|
|
JNIEXPORT jint JNICALL
|
|
JAVA_EXPORT_NAME(DemoGLSurfaceView_nativeKey) ( JNIEnv* env, jobject thiz, jint key, jint action, jint unicode, jint gamepadId )
|
|
{
|
|
SDL_scancode keycode;
|
|
int unshifted = unicode;
|
|
int shiftRequired = checkShiftRequired(&unshifted);
|
|
#if SDL_VERSION_ATLEAST(1,3,0)
|
|
#else
|
|
if( !SDL_CurrentVideoSurface )
|
|
return 1;
|
|
#endif
|
|
|
|
//__android_log_print(ANDROID_LOG_INFO, "libSDL", "%s: gamepadId %d", __FUNCTION__, gamepadId);
|
|
|
|
if( key == rightClickKey && rightClickMethod == RIGHT_CLICK_WITH_KEY )
|
|
{
|
|
SDL_ANDROID_MainThreadPushMouseButton( action ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_RIGHT );
|
|
return 1;
|
|
}
|
|
if( (key == leftClickKey && leftClickMethod == LEFT_CLICK_WITH_KEY) || (clickMouseWithDpadCenter && key == KEYCODE_DPAD_CENTER) )
|
|
{
|
|
SDL_ANDROID_MainThreadPushMouseButton( action ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_LEFT );
|
|
return 1;
|
|
}
|
|
|
|
keycode = TranslateKeyGamepad(key, gamepadId);
|
|
//__android_log_print(ANDROID_LOG_INFO, "libSDL","nativeKey %d action %d translated %d unicode %d", key, action, keycode, unicode);
|
|
|
|
if( (int)keycode == SDLK_NO_REMAP || (keycode == SDLK_UNKNOWN && unicode == 0) )
|
|
return 0;
|
|
|
|
if( keycode == SDLK_UNKNOWN || unicode != unshifted )
|
|
{
|
|
if ((unshifted & 0xFF80) == 0)
|
|
keycode = unshifted;
|
|
if (unicode != unshifted)
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( action ? SDL_PRESSED : SDL_RELEASED, SDLK_LSHIFT, 0 );
|
|
}
|
|
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( action ? SDL_PRESSED : SDL_RELEASED, keycode, unicode );
|
|
return 1;
|
|
}
|
|
|
|
static char * textInputBuffer = NULL;
|
|
int textInputBufferLen = 0;
|
|
int textInputBufferPos = 0;
|
|
|
|
void SDL_ANDROID_TextInputInit(char * buffer, int len)
|
|
{
|
|
textInputBuffer = buffer;
|
|
textInputBufferLen = len;
|
|
textInputBufferPos = 0;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
JAVA_EXPORT_NAME(DemoRenderer_nativeTextInput) ( JNIEnv* env, jobject thiz, jint ascii, jint unicode )
|
|
{
|
|
if( ascii == 10 )
|
|
ascii = SDLK_RETURN;
|
|
|
|
if( !textInputBuffer )
|
|
SDL_ANDROID_MainThreadPushText(ascii, unicode);
|
|
else
|
|
{
|
|
if( textInputBufferPos < textInputBufferLen + 4 && ascii != SDLK_RETURN && ascii != '\r' && ascii != '\n' )
|
|
{
|
|
textInputBufferPos += UnicodeToUtf8(unicode, textInputBuffer + textInputBufferPos);
|
|
}
|
|
}
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
JAVA_EXPORT_NAME(DemoRenderer_nativeTextInputFinished) ( JNIEnv* env, jobject thiz )
|
|
{
|
|
if (textInputBufferPos == 0 && textInputBuffer) // No text input - clear buffer
|
|
textInputBuffer[0] = 0;
|
|
textInputBuffer = NULL;
|
|
SDL_ANDROID_TextInputFinished = 1;
|
|
SDL_ANDROID_IsScreenKeyboardShownFlag = 0;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
JAVA_EXPORT_NAME(AccelerometerReader_nativeAccelerometer) ( JNIEnv* env, jobject thiz, jfloat accPosX, jfloat accPosY, jfloat accPosZ )
|
|
{
|
|
#if SDL_VERSION_ATLEAST(1,3,0)
|
|
#else
|
|
if( !SDL_CurrentVideoSurface )
|
|
return;
|
|
#endif
|
|
// Calculate two angles from three coordinates
|
|
float normal = sqrt(accPosX*accPosX+accPosY*accPosY+accPosZ*accPosZ);
|
|
if(normal <= 0.0000001f)
|
|
normal = 0.00001f;
|
|
|
|
SDL_ANDROID_MainThreadPushJoystickAxis(JOY_ACCELGYRO, 0, NORMALIZE_FLOAT_32767(accPosX/normal));
|
|
SDL_ANDROID_MainThreadPushJoystickAxis(JOY_ACCELGYRO, 1, NORMALIZE_FLOAT_32767(-accPosY/normal));
|
|
|
|
// Also send raw coordinates
|
|
SDL_ANDROID_MainThreadPushJoystickAxis(JOY_ACCELGYRO, 5, fminf(32767.0f, fmaxf(-32767.0f, accPosX*1000.0f))); // Do not consider wraparound case
|
|
SDL_ANDROID_MainThreadPushJoystickAxis(JOY_ACCELGYRO, 6, fminf(32767.0f, fmaxf(-32767.0f, accPosY*1000.0f)));
|
|
SDL_ANDROID_MainThreadPushJoystickAxis(JOY_ACCELGYRO, 7, fminf(32767.0f, fmaxf(-32767.0f, accPosZ*1000.0f)));
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
JAVA_EXPORT_NAME(AccelerometerReader_nativeGyroscope) ( JNIEnv* env, jobject thiz, jfloat X, jfloat Y, jfloat Z )
|
|
{
|
|
#if SDL_VERSION_ATLEAST(1,3,0)
|
|
#else
|
|
if( !SDL_CurrentVideoSurface )
|
|
return;
|
|
#endif
|
|
|
|
if( moveMouseWithGyroscope )
|
|
{
|
|
ProcessMoveMouseWithGyroscope(X, Y, Z);
|
|
return;
|
|
}
|
|
|
|
X *= 0.25f;
|
|
Y *= 0.25f;
|
|
Z *= 0.25f;
|
|
while ( X != 0.0f || Y != 0.0f || Z != 0.0f )
|
|
{
|
|
float dx = ( X > 1.0f ? 1.0f : ( X < -1.0f ? -1.0f : X ) );
|
|
float dy = ( Y > 1.0f ? 1.0f : ( Y < -1.0f ? -1.0f : Y ) );
|
|
float dz = ( Z > 1.0f ? 1.0f : ( Z < -1.0f ? -1.0f : Z ) );
|
|
|
|
X -= dx;
|
|
Y -= dy;
|
|
Z -= dz;
|
|
|
|
SDL_ANDROID_MainThreadPushJoystickAxis(JOY_ACCELGYRO, 2, NORMALIZE_FLOAT_32767(dx));
|
|
SDL_ANDROID_MainThreadPushJoystickAxis(JOY_ACCELGYRO, 3, NORMALIZE_FLOAT_32767(dy));
|
|
SDL_ANDROID_MainThreadPushJoystickAxis(JOY_ACCELGYRO, 4, NORMALIZE_FLOAT_32767(dz));
|
|
//if( fabs(dx) >= 1.0f || fabs(dy) >= 1.0f || fabs(dz) >= 1.0f ) __android_log_print(ANDROID_LOG_INFO, "libSDL", "nativeGyroscope(): sending several events, this eats CPU!");
|
|
}
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
JAVA_EXPORT_NAME(AccelerometerReader_nativeOrientation) ( JNIEnv* env, jobject thiz, jfloat X, jfloat Y, jfloat Z )
|
|
{
|
|
#if SDL_VERSION_ATLEAST(1,3,0)
|
|
#else
|
|
if( !SDL_CurrentVideoSurface )
|
|
return;
|
|
#endif
|
|
|
|
//__android_log_print(ANDROID_LOG_INFO, "libSDL", "Orientation %f %f %f", X, Y, Z);
|
|
|
|
SDL_ANDROID_MainThreadPushJoystickAxis(JOY_ACCELGYRO, 8, NORMALIZE_FLOAT_32767(X));
|
|
SDL_ANDROID_MainThreadPushJoystickAxis(JOY_ACCELGYRO, 9, NORMALIZE_FLOAT_32767(Y));
|
|
SDL_ANDROID_MainThreadPushJoystickAxis(JOY_ACCELGYRO, 10, NORMALIZE_FLOAT_32767(Z));
|
|
}
|
|
|
|
static int getClickTimeout(int v)
|
|
{
|
|
switch(v)
|
|
{
|
|
case 0: return 200;
|
|
case 1: return 300;
|
|
case 2: return 400;
|
|
case 3: return 700;
|
|
case 4: return 1000;
|
|
}
|
|
return 1000;
|
|
}
|
|
|
|
// Mwahaha overkill!
|
|
JNIEXPORT void JNICALL
|
|
JAVA_EXPORT_NAME(Settings_nativeSetMouseUsed) (JNIEnv* env, jobject thiz,
|
|
jint RightClickMethod, jint ShowScreenUnderFinger, jint LeftClickMethod,
|
|
jint MoveMouseWithJoystick, jint ClickMouseWithDpad,
|
|
jint MaxForce, jint MaxRadius,
|
|
jint MoveMouseWithJoystickSpeed, jint MoveMouseWithJoystickAccel,
|
|
jint LeftClickKeycode, jint RightClickKeycode,
|
|
jint LeftClickTimeout, jint RightClickTimeout,
|
|
jint RelativeMovement, jint RelativeMovementSpeed, jint RelativeMovementAccel,
|
|
jint ShowMouseCursor, jint HoverJitterFilter, jint RightMouseButtonLongPress,
|
|
jint MoveMouseWithGyroscope, jint MoveMouseWithGyroscopeSpeed,
|
|
jint ForceScreenUpdateMouseClick, jint ScreenFollowsMouse)
|
|
{
|
|
SDL_ANDROID_isMouseUsed = 1;
|
|
rightClickMethod = RightClickMethod;
|
|
SDL_ANDROID_ShowScreenUnderFinger = ShowScreenUnderFinger;
|
|
SDL_ANDROID_moveMouseWithArrowKeys = MoveMouseWithJoystick;
|
|
clickMouseWithDpadCenter = ClickMouseWithDpad;
|
|
leftClickMethod = LeftClickMethod;
|
|
maxForce = MaxForce;
|
|
maxRadius = MaxRadius;
|
|
SDL_ANDROID_moveMouseWithKbSpeed = MoveMouseWithJoystickSpeed + 1;
|
|
SDL_ANDROID_moveMouseWithKbAccel = MoveMouseWithJoystickAccel;
|
|
leftClickKey = LeftClickKeycode;
|
|
rightClickKey = RightClickKeycode;
|
|
leftClickTimeout = getClickTimeout(LeftClickTimeout);
|
|
rightClickTimeout = getClickTimeout(RightClickTimeout);
|
|
relativeMovement = RelativeMovement;
|
|
relativeMovementSpeed = RelativeMovementSpeed;
|
|
relativeMovementAccel = RelativeMovementAccel;
|
|
SDL_ANDROID_ShowMouseCursor = ShowMouseCursor;
|
|
hoverJitterFilter = HoverJitterFilter;
|
|
rightMouseButtonLongPress = RightMouseButtonLongPress;
|
|
moveMouseWithGyroscope = MoveMouseWithGyroscope;
|
|
moveMouseWithGyroscopeSpeed = 0.0625f * MoveMouseWithGyroscopeSpeed * MoveMouseWithGyroscopeSpeed + 0.125f * MoveMouseWithGyroscopeSpeed + 0.5f; // Scale value from 0.5 to 2, with 1 at the middle
|
|
moveMouseWithGyroscopeSpeed *= 5.0f;
|
|
forceScreenUpdateMouseClick = ForceScreenUpdateMouseClick;
|
|
screenFollowsMouse = ScreenFollowsMouse;
|
|
//__android_log_print(ANDROID_LOG_INFO, "libSDL", "moveMouseWithGyroscopeSpeed %d = %f", MoveMouseWithGyroscopeSpeed, moveMouseWithGyroscopeSpeed);
|
|
if( !mouseClickTimeoutInitialized && (
|
|
leftClickMethod == LEFT_CLICK_WITH_TAP ||
|
|
leftClickMethod == LEFT_CLICK_WITH_TIMEOUT ||
|
|
leftClickMethod == LEFT_CLICK_WITH_TAP_OR_TIMEOUT ||
|
|
rightClickMethod == RIGHT_CLICK_WITH_TIMEOUT ) )
|
|
{
|
|
mouseClickTimeoutInitialized = 1;
|
|
sem_init(&mouseClickTimeoutSemaphore, 0, 0);
|
|
pthread_attr_t attr;
|
|
pthread_attr_init(&attr);
|
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
|
pthread_create(&mouseClickTimeoutThreadId, &attr, mouseClickTimeoutThread, NULL);
|
|
pthread_attr_destroy(&attr);
|
|
}
|
|
}
|
|
|
|
void SDLCALL SDL_ANDROID_SetMouseEmulationMode(
|
|
int _relativeMovement, int _relativeMovementSpeed, int _relativeMovementAcceleration,
|
|
int _leftClickMode, SDLKey _leftClickKey, int _leftClickTimeout,
|
|
int _rightClickMode, SDLKey _rightClickKey, int _rightClickTimeout,
|
|
int _moveMouseWithJoystick, int _moveMouseWithJoystickSpeed, int _moveMouseWithJoystickAcceleration,
|
|
int _moveMouseWithGyroscope, int _moveMouseWithGyroscopeSpeed,
|
|
int _forceHardwareMouse, int _showScreenUnderFinger,
|
|
int _fingerHover, int _fingerHoverJitterFilter, int _generateSubframeTouchEvents
|
|
)
|
|
{
|
|
relativeMovement = _relativeMovement;
|
|
if (relativeMovement)
|
|
{
|
|
leftClickMethod = LEFT_CLICK_WITH_TAP_OR_TIMEOUT;
|
|
}
|
|
else
|
|
{
|
|
leftClickMethod = LEFT_CLICK_NORMAL;
|
|
}
|
|
}
|
|
|
|
int SDLCALL SDL_ANDROID_GetMouseEmulationMode() {
|
|
return relativeMovement;
|
|
}
|
|
|
|
typedef struct
|
|
{
|
|
int leftClickMethod;
|
|
int ShowScreenUnderFinger;
|
|
int leftClickTimeout;
|
|
int relativeMovement;
|
|
int ShowMouseCursor;
|
|
} MouseSettings_t;
|
|
|
|
static void saveMouseSettings(MouseSettings_t *cfg)
|
|
{
|
|
cfg->leftClickMethod = leftClickMethod;
|
|
cfg->ShowScreenUnderFinger = SDL_ANDROID_ShowScreenUnderFinger;
|
|
cfg->leftClickTimeout = leftClickTimeout;
|
|
cfg->relativeMovement = relativeMovement;
|
|
cfg->ShowMouseCursor = SDL_ANDROID_ShowMouseCursor;
|
|
}
|
|
|
|
static void restoreMouseSettings(MouseSettings_t *cfg)
|
|
{
|
|
leftClickMethod = cfg->leftClickMethod;
|
|
SDL_ANDROID_ShowScreenUnderFinger = cfg->ShowScreenUnderFinger;
|
|
leftClickTimeout = cfg->leftClickTimeout;
|
|
relativeMovement = cfg->relativeMovement;
|
|
SDL_ANDROID_ShowMouseCursor = cfg->ShowMouseCursor;
|
|
}
|
|
|
|
static void processHardwareMouseDetected (int detected, int ScreenSizeCallback)
|
|
{
|
|
static MouseSettings_t cfg;
|
|
static int initialized = 0;
|
|
|
|
if( !SDL_ANDROID_isMouseUsed )
|
|
return;
|
|
|
|
if( !initialized )
|
|
{
|
|
initialized = 1;
|
|
saveMouseSettings(&cfg);
|
|
}
|
|
|
|
if( hardwareMouseDetected != detected || ScreenSizeCallback )
|
|
{
|
|
if( !ScreenSizeCallback )
|
|
{
|
|
hardwareMouseDetected = detected;
|
|
if( SDL_ANDROID_SystemBarAndKeyboardShown )
|
|
return; // Do not enable hardware mouse mode when the keyboard is shown
|
|
}
|
|
|
|
if( detected )
|
|
{
|
|
saveMouseSettings(&cfg);
|
|
|
|
leftClickMethod = LEFT_CLICK_NORMAL;
|
|
SDL_ANDROID_ShowScreenUnderFinger = ZOOM_NONE;
|
|
leftClickTimeout = 0;
|
|
relativeMovement = 0;
|
|
SDL_ANDROID_ShowMouseCursor = 0;
|
|
}
|
|
else
|
|
restoreMouseSettings(&cfg);
|
|
}
|
|
SDL_ANDROID_SetHoverDeadzone();
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
JAVA_EXPORT_NAME(DemoGLSurfaceView_nativeHardwareMouseDetected) (JNIEnv* env, jobject thiz, int detected)
|
|
{
|
|
processHardwareMouseDetected(detected, 0);
|
|
}
|
|
|
|
void SDL_ANDROID_SetHoverDeadzone()
|
|
{
|
|
hoverDeadzone = (hardwareMouseDetected == MOUSE_HW_INPUT_STYLUS) ?
|
|
SDL_ANDROID_sFakeWindowHeight * (70 / (atoi(getenv("DISPLAY_HEIGHT_MM")) > 0 ? atoi(getenv("DISPLAY_HEIGHT_MM")) : 70)) / DEADZONE_HOVER_STYLUS :
|
|
(hardwareMouseDetected == MOUSE_HW_INPUT_FINGER) ?
|
|
SDL_ANDROID_sFakeWindowHeight * (70 / (atoi(getenv("DISPLAY_HEIGHT_MM")) > 0 ? atoi(getenv("DISPLAY_HEIGHT_MM")) : 70)) / DEADZONE_HOVER_FINGER : 0;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
JAVA_EXPORT_NAME(DemoGLSurfaceView_nativeMouseButtonsPressed) (JNIEnv* env, jobject thiz, jint buttonId, jint pressedState)
|
|
{
|
|
int btn = SDL_BUTTON_LEFT;
|
|
if( !SDL_ANDROID_isMouseUsed )
|
|
return;
|
|
|
|
switch(buttonId)
|
|
{
|
|
case MOUSE_HW_BUTTON_LEFT:
|
|
btn = SDL_BUTTON_LEFT;
|
|
break;
|
|
case MOUSE_HW_BUTTON_RIGHT:
|
|
btn = SDL_BUTTON_RIGHT;
|
|
break;
|
|
case MOUSE_HW_BUTTON_MIDDLE:
|
|
btn = SDL_BUTTON_MIDDLE;
|
|
break;
|
|
case MOUSE_HW_BUTTON_BACK:
|
|
btn = SDL_BUTTON_X1;
|
|
break;
|
|
case MOUSE_HW_BUTTON_FORWARD:
|
|
btn = SDL_BUTTON_X2;
|
|
break;
|
|
}
|
|
SDL_ANDROID_MainThreadPushMouseButton( pressedState ? SDL_PRESSED : SDL_RELEASED, btn );
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
JAVA_EXPORT_NAME(DemoGLSurfaceView_nativeMouseWheel) (JNIEnv* env, jobject thiz, jint scrollX, jint scrollY)
|
|
{
|
|
#if SDL_VERSION_ATLEAST(1,3,0)
|
|
SDL_ANDROID_MainThreadPushMouseWheel( scrollX, scrollY );
|
|
#else
|
|
// TODO: direction might get inverted
|
|
for( ; scrollX > 0; scrollX-- )
|
|
{
|
|
if( !SDL_ANDROID_isMouseUsed )
|
|
{
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_PRESSED, TranslateKey(KEYCODE_DPAD_RIGHT), 0 );
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_RELEASED, TranslateKey(KEYCODE_DPAD_RIGHT), 0 );
|
|
}
|
|
else
|
|
{
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_PRESSED, SDL_BUTTON_X2 );
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_RELEASED, SDL_BUTTON_X2 );
|
|
}
|
|
}
|
|
for( ; scrollX < 0; scrollX++ )
|
|
{
|
|
if( !SDL_ANDROID_isMouseUsed )
|
|
{
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_PRESSED, TranslateKey(KEYCODE_DPAD_LEFT), 0 );
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_RELEASED, TranslateKey(KEYCODE_DPAD_LEFT), 0 );
|
|
}
|
|
else
|
|
{
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_PRESSED, SDL_BUTTON_X1 );
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_RELEASED, SDL_BUTTON_X1 );
|
|
}
|
|
}
|
|
for( ; scrollY > 0; scrollY-- )
|
|
{
|
|
if( !SDL_ANDROID_isMouseUsed )
|
|
{
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_PRESSED, TranslateKey(KEYCODE_DPAD_UP), 0 );
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_RELEASED, TranslateKey(KEYCODE_DPAD_UP), 0 );
|
|
}
|
|
else
|
|
{
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_PRESSED, SDL_BUTTON_WHEELUP );
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_RELEASED, SDL_BUTTON_WHEELUP );
|
|
}
|
|
}
|
|
for( ; scrollY < 0; scrollY++ )
|
|
{
|
|
if( !SDL_ANDROID_isMouseUsed )
|
|
{
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_PRESSED, TranslateKey(KEYCODE_DPAD_DOWN), 0 );
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_RELEASED, TranslateKey(KEYCODE_DPAD_DOWN), 0 );
|
|
}
|
|
else
|
|
{
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_PRESSED, SDL_BUTTON_WHEELDOWN );
|
|
SDL_ANDROID_MainThreadPushMouseButton( SDL_RELEASED, SDL_BUTTON_WHEELDOWN );
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
JAVA_EXPORT_NAME(Settings_nativeSetJoystickUsed) (JNIEnv* env, jobject thiz, jint amount)
|
|
{
|
|
SDL_ANDROID_joysticksAmount = amount;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
JAVA_EXPORT_NAME(Settings_nativeSetAccelerometerUsed) (JNIEnv* env, jobject thiz)
|
|
{
|
|
SDL_ANDROID_isAccelerometerUsed = 1;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
JAVA_EXPORT_NAME(Settings_nativeSetMultitouchUsed) ( JNIEnv* env, jobject thiz)
|
|
{
|
|
isMultitouchUsed = 1;
|
|
}
|
|
|
|
|
|
static float dx = 0.04, dy = 0.1, dz = 0.1, joystickSensitivity = 400.0f; // For accelerometer
|
|
enum { ACCELEROMETER_CENTER_FLOATING, ACCELEROMETER_CENTER_FIXED_START, ACCELEROMETER_CENTER_FIXED_HORIZ };
|
|
static int accelerometerCenterPos = ACCELEROMETER_CENTER_FLOATING;
|
|
|
|
JNIEXPORT void JNICALL
|
|
JAVA_EXPORT_NAME(Settings_nativeSetAccelerometerSettings) ( JNIEnv* env, jobject thiz, jint sensitivity, jint centerPos)
|
|
{
|
|
dx = 0.04; dy = 0.08; dz = 0.08; joystickSensitivity = 32767.0f * 3.0f; // Fast sensitivity
|
|
if( sensitivity == 1 )
|
|
{
|
|
dx = 0.1; dy = 0.15; dz = 0.15; joystickSensitivity = 32767.0f * 2.0f; // Medium sensitivity
|
|
}
|
|
if( sensitivity == 2 )
|
|
{
|
|
dx = 0.2; dy = 0.25; dz = 0.25; joystickSensitivity = 32767.0f; // Slow sensitivity
|
|
}
|
|
accelerometerCenterPos = centerPos;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
JAVA_EXPORT_NAME(DemoGLSurfaceView_nativeGamepadAnalogJoystickInput) (JNIEnv* env, jobject thiz,
|
|
jfloat stick1x, jfloat stick1y, jfloat stick2x, jfloat stick2y, jfloat ltrigger, jfloat rtrigger,
|
|
jfloat dpadx, jfloat dpady, jint gamepadId)
|
|
{
|
|
//__android_log_print(ANDROID_LOG_INFO, "libSDL","%s: gamepadId %d", __FUNCTION__, gamepadId);
|
|
|
|
if (gamepadId > SDL_ANDROID_MAX_GAMEPADS || gamepadId <= 0)
|
|
gamepadId = 1;
|
|
|
|
gamepadId --;
|
|
|
|
if( SDL_ANDROID_CurrentJoysticks[JOY_GAMEPAD1 + gamepadId] )
|
|
{
|
|
SDL_ANDROID_MainThreadPushJoystickAxis(JOY_GAMEPAD1 + gamepadId, 0, NORMALIZE_FLOAT_32767(stick1x));
|
|
SDL_ANDROID_MainThreadPushJoystickAxis(JOY_GAMEPAD1 + gamepadId, 1, NORMALIZE_FLOAT_32767(stick1y));
|
|
SDL_ANDROID_MainThreadPushJoystickAxis(JOY_GAMEPAD1 + gamepadId, 2, NORMALIZE_FLOAT_32767(stick2x));
|
|
SDL_ANDROID_MainThreadPushJoystickAxis(JOY_GAMEPAD1 + gamepadId, 3, NORMALIZE_FLOAT_32767(stick2y));
|
|
SDL_ANDROID_MainThreadPushJoystickAxis(JOY_GAMEPAD1 + gamepadId, 4, NORMALIZE_FLOAT_32767(ltrigger));
|
|
SDL_ANDROID_MainThreadPushJoystickAxis(JOY_GAMEPAD1 + gamepadId, 5, NORMALIZE_FLOAT_32767(rtrigger));
|
|
}
|
|
else
|
|
{
|
|
if( fabsf(dpadx) < 0.01f && fabsf(dpady) < 0.01f )
|
|
{
|
|
dpadx = stick1x;
|
|
dpady = stick1y;
|
|
}
|
|
if( fabsf(stick2x) > 0.2f || fabsf(stick2y) > 0.2f )
|
|
{
|
|
// Move mouse with right stick
|
|
SDL_ANDROID_moveMouseWithKbAccelUpdateNeeded |= 4;
|
|
SDL_ANDROID_moveMouseWithKbSpeedX = stick2x * 3 * SDL_ANDROID_moveMouseWithKbSpeed;
|
|
SDL_ANDROID_moveMouseWithKbSpeedY = stick2y * 3 * SDL_ANDROID_moveMouseWithKbSpeed;
|
|
}
|
|
else
|
|
{
|
|
SDL_ANDROID_moveMouseWithKbAccelUpdateNeeded &= ~4;
|
|
}
|
|
}
|
|
// Translate to up/down/left/right
|
|
if( dpadx < -0.5f )
|
|
{
|
|
if( !SDL_GetKeyboardState(NULL)[SDL_android_gamepad_keymap[gamepadId][KEYCODE_DPAD_LEFT]] )
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_PRESSED, SDL_android_gamepad_keymap[gamepadId][KEYCODE_DPAD_LEFT], 0 );
|
|
}
|
|
else
|
|
{
|
|
if( SDL_GetKeyboardState(NULL)[SDL_android_gamepad_keymap[gamepadId][KEYCODE_DPAD_LEFT]] )
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_RELEASED, SDL_android_gamepad_keymap[gamepadId][KEYCODE_DPAD_LEFT], 0 );
|
|
}
|
|
if( dpadx > 0.5f )
|
|
{
|
|
if( !SDL_GetKeyboardState(NULL)[SDL_android_gamepad_keymap[gamepadId][KEYCODE_DPAD_RIGHT]] )
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_PRESSED, SDL_android_gamepad_keymap[gamepadId][KEYCODE_DPAD_RIGHT], 0 );
|
|
}
|
|
else
|
|
{
|
|
if( SDL_GetKeyboardState(NULL)[SDL_android_gamepad_keymap[gamepadId][KEYCODE_DPAD_RIGHT]] )
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_RELEASED, SDL_android_gamepad_keymap[gamepadId][KEYCODE_DPAD_RIGHT], 0 );
|
|
}
|
|
if( dpady < -0.5f )
|
|
{
|
|
if( !SDL_GetKeyboardState(NULL)[SDL_android_gamepad_keymap[gamepadId][KEYCODE_DPAD_UP]] )
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_PRESSED, SDL_android_gamepad_keymap[gamepadId][KEYCODE_DPAD_UP], 0 );
|
|
}
|
|
else
|
|
{
|
|
if( SDL_GetKeyboardState(NULL)[SDL_android_gamepad_keymap[gamepadId][KEYCODE_DPAD_UP]] )
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_RELEASED, SDL_android_gamepad_keymap[gamepadId][KEYCODE_DPAD_UP], 0 );
|
|
}
|
|
if( dpady > 0.5f )
|
|
{
|
|
if( !SDL_GetKeyboardState(NULL)[SDL_android_gamepad_keymap[gamepadId][KEYCODE_DPAD_DOWN]] )
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_PRESSED, SDL_android_gamepad_keymap[gamepadId][KEYCODE_DPAD_DOWN], 0 );
|
|
}
|
|
else
|
|
{
|
|
if( SDL_GetKeyboardState(NULL)[SDL_android_gamepad_keymap[gamepadId][KEYCODE_DPAD_DOWN]] )
|
|
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_RELEASED, SDL_android_gamepad_keymap[gamepadId][KEYCODE_DPAD_DOWN], 0 );
|
|
}
|
|
}
|
|
|
|
int SDL_SYS_JoystickInit(void)
|
|
{
|
|
SDL_numjoysticks = JOY_GAMEPAD4 + 1;
|
|
|
|
return(SDL_numjoysticks);
|
|
}
|
|
|
|
/* Function to get the device-dependent name of a joystick */
|
|
const char *SDL_SYS_JoystickName(int index)
|
|
{
|
|
if( index == JOY_TOUCHSCREEN )
|
|
return "Multitouch and on-screen joystick";
|
|
if( index == JOY_ACCELGYRO )
|
|
return "Accelerometer/gyroscope";
|
|
if( index == JOY_GAMEPAD1 )
|
|
return "Gamepad 1";
|
|
if( index == JOY_GAMEPAD2 )
|
|
return "Gamepad 2";
|
|
if( index == JOY_GAMEPAD3 )
|
|
return "Gamepad 3";
|
|
if( index == JOY_GAMEPAD4 )
|
|
return "Gamepad 4";
|
|
return "This joystick does not exist, check your code";
|
|
}
|
|
|
|
int SDL_SYS_JoystickOpen(SDL_Joystick *joystick)
|
|
{
|
|
joystick->naxes = 0;
|
|
joystick->nbuttons = 0;
|
|
joystick->nhats = 0;
|
|
joystick->nballs = 0;
|
|
if( joystick->index == JOY_TOUCHSCREEN )
|
|
{
|
|
joystick->naxes = 6 + MAX_MULTITOUCH_POINTERS; // Three joysticks plus touch pressure/size
|
|
joystick->nbuttons = MAX_MULTITOUCH_POINTERS;
|
|
joystick->nballs = MAX_MULTITOUCH_POINTERS;
|
|
}
|
|
if( joystick->index == JOY_ACCELGYRO )
|
|
{
|
|
joystick->naxes = 11; // Normalized accelerometer = axes 0-1, gyroscope = axes 2-4, raw accelerometer = axes 5-7, orientation = axes 8-10
|
|
if( !moveMouseWithGyroscope )
|
|
SDL_ANDROID_CallJavaStartAccelerometerGyroscope(1);
|
|
}
|
|
if( joystick->index >= JOY_GAMEPAD1 && joystick->index <= JOY_GAMEPAD4 )
|
|
{
|
|
joystick->naxes = 8; // Two analog stick + two trigger buttons + Ouya touchpad
|
|
}
|
|
SDL_ANDROID_CurrentJoysticks[joystick->index] = joystick;
|
|
//__android_log_print(ANDROID_LOG_INFO, "libSDL", "Opened joystick %d axes %d buttons %d balls %d", joystick->index, joystick->naxes, joystick->nbuttons, joystick->nballs);
|
|
return(0);
|
|
}
|
|
|
|
void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Function to close a joystick after use */
|
|
void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
|
|
{
|
|
SDL_ANDROID_CurrentJoysticks[joystick->index] = NULL;
|
|
if( joystick->index == JOY_ACCELGYRO && !moveMouseWithGyroscope )
|
|
SDL_ANDROID_CallJavaStartAccelerometerGyroscope(0);
|
|
return;
|
|
}
|
|
|
|
/* Function to perform any system-specific joystick related cleanup */
|
|
void SDL_SYS_JoystickQuit(void)
|
|
{
|
|
int i;
|
|
SDL_ANDROID_CurrentJoysticks[0] = NULL;
|
|
return;
|
|
}
|
|
|
|
Uint32 lastMoveMouseWithKeyboardUpdate = 0;
|
|
|
|
void SDL_ANDROID_processMoveMouseWithKeyboard()
|
|
{
|
|
if( ! SDL_ANDROID_moveMouseWithKbAccelUpdateNeeded )
|
|
return;
|
|
|
|
Uint32 ticks = SDL_GetTicks();
|
|
|
|
if( ticks - lastMoveMouseWithKeyboardUpdate < 20 ) // Update at 50 FPS max, or it will not work properlty on very fast devices
|
|
return;
|
|
|
|
lastMoveMouseWithKeyboardUpdate = ticks;
|
|
|
|
SDL_ANDROID_moveMouseWithKbSpeedX += SDL_ANDROID_moveMouseWithKbAccelX;
|
|
SDL_ANDROID_moveMouseWithKbSpeedY += SDL_ANDROID_moveMouseWithKbAccelY;
|
|
|
|
SDL_ANDROID_moveMouseWithKbX += SDL_ANDROID_moveMouseWithKbSpeedX;
|
|
SDL_ANDROID_moveMouseWithKbY += SDL_ANDROID_moveMouseWithKbSpeedY;
|
|
|
|
if (SDL_ANDROID_moveMouseWithKbX < 0)
|
|
SDL_ANDROID_moveMouseWithKbX = 0;
|
|
if (SDL_ANDROID_moveMouseWithKbY < 0)
|
|
SDL_ANDROID_moveMouseWithKbY = 0;
|
|
if (SDL_ANDROID_moveMouseWithKbX >= SDL_ANDROID_sFakeWindowWidth)
|
|
SDL_ANDROID_moveMouseWithKbX = SDL_ANDROID_sFakeWindowWidth - 1;
|
|
if (SDL_ANDROID_moveMouseWithKbY >= SDL_ANDROID_sFakeWindowHeight)
|
|
SDL_ANDROID_moveMouseWithKbY = SDL_ANDROID_sFakeWindowHeight - 1;
|
|
|
|
SDL_ANDROID_MainThreadPushMouseMotion(SDL_ANDROID_moveMouseWithKbX, SDL_ANDROID_moveMouseWithKbY);
|
|
};
|
|
|
|
extern void SDL_ANDROID_ProcessDeferredEvents()
|
|
{
|
|
SDL_ANDROID_DeferredTextInput();
|
|
ProcessDeferredMouseTap();
|
|
};
|
|
|
|
void ANDROID_InitOSKeymap()
|
|
{
|
|
#if (SDL_VERSION_ATLEAST(1,3,0))
|
|
SDLKey defaultKeymap[SDL_NUM_SCANCODES];
|
|
SDL_GetDefaultKeymap(defaultKeymap);
|
|
SDL_SetKeymap(0, defaultKeymap, SDL_NUM_SCANCODES);
|
|
|
|
SDL_Touch touch;
|
|
memset( &touch, 0, sizeof(touch) );
|
|
touch.x_min = touch.y_min = touch.pressure_min = 0.0f;
|
|
touch.pressure_max = 1000000;
|
|
touch.x_max = SDL_ANDROID_sWindowWidth;
|
|
touch.y_max = SDL_ANDROID_sWindowHeight;
|
|
|
|
// These constants are hardcoded inside SDL_touch.c, which makes no sense for me.
|
|
touch.xres = touch.yres = 32768;
|
|
touch.native_xres = touch.native_yres = 32768.0f;
|
|
|
|
touch.pressureres = 1;
|
|
touch.native_pressureres = 1.0f;
|
|
touch.id = 0;
|
|
|
|
SDL_AddTouch(&touch, "Android touch screen");
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL
|
|
JAVA_EXPORT_NAME(Settings_nativeGetKeymapKey) (JNIEnv* env, jobject thiz, jint code)
|
|
{
|
|
if( code < 0 || code > KEYCODE_LAST )
|
|
return SDL_KEY(UNKNOWN);
|
|
return SDL_android_keymap[code];
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
JAVA_EXPORT_NAME(Settings_nativeSetKeymapKey) (JNIEnv* env, jobject thiz, jint javakey, jint key)
|
|
{
|
|
if( javakey < 0 || javakey > KEYCODE_LAST )
|
|
return;
|
|
SDL_android_keymap[javakey] = key;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL
|
|
JAVA_EXPORT_NAME(Settings_nativeGetKeymapKeyMultitouchGesture) (JNIEnv* env, jobject thiz, jint keynum)
|
|
{
|
|
if( keynum < 0 || keynum >= MAX_MULTITOUCH_GESTURES )
|
|
return SDL_KEY(UNKNOWN);
|
|
return multitouchGestureKeycode[keynum];
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
JAVA_EXPORT_NAME(Settings_nativeSetKeymapKeyMultitouchGesture) (JNIEnv* env, jobject thiz, jint keynum, jint keycode)
|
|
{
|
|
if( keynum < 0 || keynum >= MAX_MULTITOUCH_GESTURES )
|
|
return;
|
|
multitouchGestureKeycode[keynum] = keycode;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
JAVA_EXPORT_NAME(Settings_nativeSetMultitouchGestureSensitivity) (JNIEnv* env, jobject thiz, jint sensitivity)
|
|
{
|
|
multitouchGestureSensitivity = sensitivity;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
JAVA_EXPORT_NAME(Settings_nativeSetTouchscreenCalibration) (JNIEnv* env, jobject thiz, jint x1, jint y1, jint x2, jint y2)
|
|
{
|
|
SDL_ANDROID_TouchscreenCalibrationX = x1;
|
|
SDL_ANDROID_TouchscreenCalibrationY = y1;
|
|
SDL_ANDROID_TouchscreenCalibrationWidth = x2 - x1;
|
|
SDL_ANDROID_TouchscreenCalibrationHeight = y2 - y1;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
JAVA_EXPORT_NAME(Settings_nativeInitKeymap) ( JNIEnv* env, jobject thiz )
|
|
{
|
|
SDL_android_init_keymap(SDL_android_keymap);
|
|
}
|
|
|
|
void SDL_ANDROID_SetIndividualGamepadKeymap(int GamepadId,
|
|
int A, int B, int X, int Y, int L1, int R1, int L2, int R2, int LThumb, int RThumb,
|
|
int Start, int Select, int Up, int Down, int Left, int Right)
|
|
{
|
|
/*
|
|
Arguments are SDL keycodes. Use the SDLK_ constants.
|
|
Pass zero to leave a button mapping untouched.
|
|
|
|
On OUYA:
|
|
O = A
|
|
U = X
|
|
Y = Y
|
|
A = B
|
|
C and Z do not exist, they also do not exist on any gamepad I've seen (PS3/XBox/SHIELD)
|
|
*/
|
|
|
|
if( GamepadId < 0 || GamepadId >= SDL_ANDROID_MAX_GAMEPADS )
|
|
return;
|
|
|
|
if (A) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_A] = A;
|
|
if (A) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_3] = A;
|
|
if (B) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_B] = B;
|
|
if (B) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_2] = B;
|
|
if (X) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_X] = X;
|
|
if (X) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_4] = X;
|
|
if (Y) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_Y] = Y;
|
|
if (Y) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_1] = Y;
|
|
if (L1) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_L1] = L1;
|
|
if (L1) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_5] = L1;
|
|
if (R1) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_R1] = R1;
|
|
if (R1) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_6] = R1;
|
|
if (L2) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_L2] = L2;
|
|
if (L2) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_7] = L2;
|
|
if (R2) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_R2] = R2;
|
|
if (R2) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_8] = R2;
|
|
if (LThumb) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_THUMBL] = LThumb;
|
|
if (LThumb) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_11] = LThumb;
|
|
if (RThumb) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_THUMBR] = RThumb;
|
|
if (RThumb) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_12] = RThumb;
|
|
if (Start) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_START] = Start;
|
|
if (Start) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_9] = Start;
|
|
if (Select) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_SELECT] = Select;
|
|
if (Select) SDL_android_gamepad_keymap[GamepadId][KEYCODE_BUTTON_10] = Select;
|
|
if (Up) SDL_android_gamepad_keymap[GamepadId][KEYCODE_DPAD_UP] = Up;
|
|
if (Down) SDL_android_gamepad_keymap[GamepadId][KEYCODE_DPAD_DOWN] = Down;
|
|
if (Left) SDL_android_gamepad_keymap[GamepadId][KEYCODE_DPAD_LEFT] = Left;
|
|
if (Right) SDL_android_gamepad_keymap[GamepadId][KEYCODE_DPAD_RIGHT] = Right;
|
|
|
|
if( GamepadId == 0 )
|
|
{
|
|
int i;
|
|
for( i = KEYCODE_BUTTON_A; i <= KEYCODE_BUTTON_SELECT; i++ )
|
|
{
|
|
SDL_android_keymap[i] = SDL_android_gamepad_keymap[GamepadId][i];
|
|
}
|
|
for( i = KEYCODE_BUTTON_1; i <= KEYCODE_BUTTON_12; i++ )
|
|
{
|
|
SDL_android_keymap[i] = SDL_android_gamepad_keymap[GamepadId][i];
|
|
}
|
|
}
|
|
}
|
|
|
|
void SDL_ANDROID_SetGamepadKeymap(int A, int B, int X, int Y, int L1, int R1, int L2, int R2, int LThumb, int RThumb)
|
|
{
|
|
int i;
|
|
for( i = 0; i < SDL_ANDROID_MAX_GAMEPADS; i++ )
|
|
{
|
|
SDL_ANDROID_SetIndividualGamepadKeymap(i, A, B, X, Y, L1, R1, L2, R2, LThumb, RThumb, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
}
|
|
|
|
void SDL_ANDROID_SetAndroidKeycode(int Android_Key, int Sdl_Key)
|
|
{
|
|
if (Android_Key < 0 || Android_Key >= KEYCODE_LAST)
|
|
return;
|
|
SDL_android_keymap[Android_Key] = Sdl_Key;
|
|
}
|
|
|
|
void *mouseClickTimeoutThread (void * unused)
|
|
{
|
|
struct timespec ts;
|
|
while( 1 )
|
|
{
|
|
clock_gettime(CLOCK_REALTIME, &ts);
|
|
ts.tv_sec += mouseClickTimeout / 1000;
|
|
ts.tv_nsec += (mouseClickTimeout % 1000) * 1000000;
|
|
if( ts.tv_nsec >= 1000000000 )
|
|
{
|
|
ts.tv_sec++;
|
|
ts.tv_nsec %= 1000000000;
|
|
}
|
|
mouseClickTimeout = 100000;
|
|
if( sem_timedwait(&mouseClickTimeoutSemaphore, &ts) != 0 ) // Only call when timeout occurs
|
|
{
|
|
//__android_log_print(ANDROID_LOG_INFO, "libSDL", "mouseClickTimeoutThread: move %d %d", SDL_ANDROID_currentMouseX, SDL_ANDROID_currentMouseY);
|
|
ProcessMouseMove_Timeouts(SDL_ANDROID_currentMouseX, SDL_ANDROID_currentMouseY);
|
|
ProcessDeferredMouseTap();
|
|
}
|
|
//__android_log_print(ANDROID_LOG_INFO, "libSDL", "mouseClickTimeoutThread: tick");
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
JAVA_EXPORT_NAME(DemoGLSurfaceView_nativeScreenVisibleRect) (JNIEnv* env, jobject thiz, jint x, jint y, jint w, jint h )
|
|
{
|
|
SDL_ANDROID_ScreenVisibleRect.x = x;
|
|
SDL_ANDROID_ScreenVisibleRect.y = y;
|
|
SDL_ANDROID_ScreenVisibleRect.w = w;
|
|
SDL_ANDROID_ScreenVisibleRect.h = h;
|
|
|
|
if( SDL_WasInit(SDL_INIT_VIDEO) )
|
|
{
|
|
// Move mouse by 1 pixel to force screen update
|
|
SDL_GetMouseState( &x, &y );
|
|
SDL_ANDROID_MainThreadPushMouseMotion(x > 0 ? x-1 : 0, y);
|
|
if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE )
|
|
{
|
|
struct SDL_SysWMmsg wmmsg;
|
|
SDL_VERSION(&wmmsg.version);
|
|
wmmsg.type = SDL_SYSWM_ANDROID_SCREEN_VISIBLE_RECT;
|
|
wmmsg.event.screenVisibleRect = (SDL_Rect) {x, y, w, h};
|
|
SDL_PrivateSysWMEvent(&wmmsg);
|
|
}
|
|
}
|
|
else
|
|
return;
|
|
|
|
if( screenFollowsMouse )
|
|
{
|
|
static MouseSettings_t cfg;
|
|
//int systemBarActive = SDL_ANDROID_ScreenVisibleRect.h < SDL_ANDROID_sRealWindowHeight;
|
|
int keyboardActive = SDL_ANDROID_ScreenVisibleRect.h < SDL_ANDROID_sRealWindowHeight * 9 / 10;
|
|
|
|
if( keyboardActive && !SDL_ANDROID_SystemBarAndKeyboardShown )
|
|
{
|
|
SDL_ANDROID_SystemBarAndKeyboardShown = 1;
|
|
processHardwareMouseDetected(0, 1); // Disable direct mouse input mode, set relative mouse mode
|
|
|
|
saveMouseSettings(&cfg);
|
|
|
|
leftClickMethod = LEFT_CLICK_WITH_TAP_OR_TIMEOUT;
|
|
SDL_ANDROID_ShowScreenUnderFinger = ZOOM_NONE;
|
|
leftClickTimeout = getClickTimeout(3);
|
|
relativeMovement = 1;
|
|
}
|
|
else if( !keyboardActive && SDL_ANDROID_SystemBarAndKeyboardShown )
|
|
{
|
|
SDL_ANDROID_SystemBarAndKeyboardShown = 0;
|
|
restoreMouseSettings(&cfg);
|
|
if( hardwareMouseDetected ) // Restore direct mouse input mode if needed
|
|
processHardwareMouseDetected(1, 1);
|
|
}
|
|
}
|
|
}
|