Fixed nasty bugs with multitouch input and on-screen keyboard (bad, bad Java!)

This commit is contained in:
pelya
2010-10-06 14:42:17 +03:00
parent b292e52900
commit 586f659e48
3 changed files with 268 additions and 125 deletions

View File

@@ -170,7 +170,7 @@ static inline SDL_keysym *GetKeysym(SDLKey scancode, SDL_keysym *keysym)
enum MOUSE_ACTION { MOUSE_DOWN = 0, MOUSE_UP=1, MOUSE_MOVE=2 }; enum MOUSE_ACTION { MOUSE_DOWN = 0, MOUSE_UP=1, MOUSE_MOVE=2 };
enum { MAX_MULTITOUCH_POINTERS = 5 }; enum { MAX_MULTITOUCH_POINTERS = 16 };
extern int SDL_ANDROID_processTouchscreenKeyboard(int x, int y, int action, int pointerId); extern int SDL_ANDROID_processTouchscreenKeyboard(int x, int y, int action, int pointerId);
extern int SDL_ANDROID_isTouchscreenKeyboardUsed; extern int SDL_ANDROID_isTouchscreenKeyboardUsed;

View File

@@ -64,7 +64,7 @@ static int AutoFireButtonsNum = 0;
static int nbuttons = 4; static int nbuttons = 4;
static int buttonsize = 1; static int buttonsize = 1;
static SDL_Rect arrows, buttons[MAX_BUTTONS]; static SDL_Rect arrows, buttons[MAX_BUTTONS], buttonsAutoFireRect[MAX_BUTTONS_AUTOFIRE];
static SDLKey buttonKeysyms[MAX_BUTTONS] = { static SDLKey buttonKeysyms[MAX_BUTTONS] = {
SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_KEYCODE_0)), SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_KEYCODE_0)),
SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_KEYCODE_1)), SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_KEYCODE_1)),
@@ -83,7 +83,7 @@ static int ButtonAutoFireX[MAX_BUTTONS_AUTOFIRE*2] = {0, 0, 0, 0};
static int ButtonAutoFireRot[MAX_BUTTONS_AUTOFIRE] = {0, 0}; static int ButtonAutoFireRot[MAX_BUTTONS_AUTOFIRE] = {0, 0};
static int ButtonAutoFireDecay[MAX_BUTTONS_AUTOFIRE] = {0, 0}; static int ButtonAutoFireDecay[MAX_BUTTONS_AUTOFIRE] = {0, 0};
static SDL_Rect * OldCoords[MAX_MULTITOUCH_POINTERS] = { NULL }; static int pointerInButtonRect[MAX_BUTTONS + 1] = {0};
typedef struct typedef struct
{ {
@@ -371,173 +371,231 @@ int SDL_ANDROID_processTouchscreenKeyboard(int x, int y, int action, int pointer
{ {
int i; int i;
SDL_keysym keysym; SDL_keysym keysym;
int processed = 0;
if( !touchscreenKeyboardShown ) if( !touchscreenKeyboardShown )
return 0; return 0;
if( action == MOUSE_DOWN ) if( action == MOUSE_DOWN )
{ {
//__android_log_print(ANDROID_LOG_INFO, "libSDL", "touch %03dx%03d ptr %d action %d", x, y, pointerId, action);
if( InsideRect( &arrows, x, y ) ) if( InsideRect( &arrows, x, y ) )
{ {
OldCoords[pointerId] = &arrows; processed = 1;
i = ArrowKeysPressed(x, y); if( pointerInButtonRect[MAX_BUTTONS] == -1 )
if( i & ARROW_UP ) {
SDL_SendKeyboardKey( SDL_PRESSED, GetKeysym( SDL_KEY(UP), &keysym) ); pointerInButtonRect[MAX_BUTTONS] = pointerId;
if( i & ARROW_DOWN ) i = ArrowKeysPressed(x, y);
SDL_SendKeyboardKey( SDL_PRESSED, GetKeysym( SDL_KEY(DOWN), &keysym) ); if( i & ARROW_UP )
if( i & ARROW_LEFT ) SDL_SendKeyboardKey( SDL_PRESSED, GetKeysym( SDL_KEY(UP), &keysym) );
SDL_SendKeyboardKey( SDL_PRESSED, GetKeysym( SDL_KEY(LEFT), &keysym) ); if( i & ARROW_DOWN )
if( i & ARROW_RIGHT ) SDL_SendKeyboardKey( SDL_PRESSED, GetKeysym( SDL_KEY(DOWN), &keysym) );
SDL_SendKeyboardKey( SDL_PRESSED, GetKeysym( SDL_KEY(RIGHT), &keysym) ); if( i & ARROW_LEFT )
oldArrows = i; SDL_SendKeyboardKey( SDL_PRESSED, GetKeysym( SDL_KEY(LEFT), &keysym) );
return 1; if( i & ARROW_RIGHT )
SDL_SendKeyboardKey( SDL_PRESSED, GetKeysym( SDL_KEY(RIGHT), &keysym) );
oldArrows = i;
}
} }
for( i = 0; i < nbuttons; i++ ) for( i = 0; i < nbuttons; i++ )
{ {
if( InsideRect( &buttons[i], x, y) ) if( InsideRect( &buttons[i], x, y) )
{ {
OldCoords[pointerId] = &buttons[i]; processed = 1;
SDL_SendKeyboardKey( SDL_PRESSED, GetKeysym(buttonKeysyms[i], &keysym) ); if( pointerInButtonRect[i] == -1 )
if( i < AutoFireButtonsNum )
{ {
ButtonAutoFire[i] = 0; pointerInButtonRect[i] = pointerId;
if(touchscreenKeyboardTheme == 0) SDL_SendKeyboardKey( SDL_PRESSED, GetKeysym(buttonKeysyms[i], &keysym) );
if( i < AutoFireButtonsNum )
{ {
ButtonAutoFireX[i] = x; ButtonAutoFire[i] = 0;
ButtonAutoFireRot[i] = 0; if(touchscreenKeyboardTheme == 0)
} {
else ButtonAutoFireX[i] = x;
{ ButtonAutoFireRot[i] = 0;
ButtonAutoFireX[i*2] = 0; }
ButtonAutoFireX[i*2+1] = 0; else
ButtonAutoFireRot[i] = x; {
ButtonAutoFireDecay[i] = SDL_GetTicks(); ButtonAutoFireX[i*2] = 0;
ButtonAutoFireX[i*2+1] = 0;
ButtonAutoFireRot[i] = x;
ButtonAutoFireDecay[i] = SDL_GetTicks();
}
} }
} }
return 1;
} }
} }
} }
else else
if( action == MOUSE_UP ) if( action == MOUSE_UP )
{ {
if( OldCoords[pointerId] == &arrows ) //__android_log_print(ANDROID_LOG_INFO, "libSDL", "touch %03dx%03d ptr %d action %d", x, y, pointerId, action);
if( pointerInButtonRect[MAX_BUTTONS] == pointerId )
{ {
OldCoords[pointerId] = NULL; processed = 1;
pointerInButtonRect[MAX_BUTTONS] = -1;
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym( SDL_KEY(UP), &keysym) ); SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym( SDL_KEY(UP), &keysym) );
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym( SDL_KEY(DOWN), &keysym) ); SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym( SDL_KEY(DOWN), &keysym) );
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym( SDL_KEY(LEFT), &keysym) ); SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym( SDL_KEY(LEFT), &keysym) );
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym( SDL_KEY(RIGHT), &keysym) ); SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym( SDL_KEY(RIGHT), &keysym) );
oldArrows = 0; oldArrows = 0;
return 1;
} }
for( i = 0; i < nbuttons; i++ ) for( i = 0; i < nbuttons; i++ )
{ {
if( OldCoords[pointerId] == &buttons[i] ) if( pointerInButtonRect[i] == pointerId )
{ {
if( ! ( i < AutoFireButtonsNum && ButtonAutoFire[i] ) ) processed = 1;
{ pointerInButtonRect[i] = -1;
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym(buttonKeysyms[i] ,&keysym) ); if( i < AutoFireButtonsNum && ButtonAutoFire[i] )
}
else
{ {
ButtonAutoFire[i] = 2; ButtonAutoFire[i] = 2;
} }
OldCoords[pointerId] = NULL;
if(touchscreenKeyboardTheme == 0)
{
ButtonAutoFireX[i] = 0;
}
else else
{ {
ButtonAutoFireX[i*2] = 0; SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym(buttonKeysyms[i] ,&keysym) );
ButtonAutoFireX[i*2+1] = 0; }
if( i < AutoFireButtonsNum )
{
if(touchscreenKeyboardTheme == 0)
{
ButtonAutoFireX[i] = 0;
}
else
{
ButtonAutoFireX[i*2] = 0;
ButtonAutoFireX[i*2+1] = 0;
}
} }
return 1;
} }
} }
} }
else else
if( action == MOUSE_MOVE ) if( action == MOUSE_MOVE )
{ {
if( OldCoords[pointerId] && !InsideRect(OldCoords[pointerId], x, y) ) // Process cases when pointer enters button area (it won't send keypress twice if button already pressed)
processed = SDL_ANDROID_processTouchscreenKeyboard(x, y, MOUSE_DOWN, pointerId);
// Process cases when pointer leaves button area
// TODO: huge code size, split it or somehow make it more readable
if( pointerInButtonRect[MAX_BUTTONS] == pointerId )
{ {
SDL_ANDROID_processTouchscreenKeyboard(x, y, MOUSE_UP, pointerId); processed = 1;
return SDL_ANDROID_processTouchscreenKeyboard(x, y, MOUSE_DOWN, pointerId); if( ! InsideRect( &arrows, x, y ) )
}
else
if( OldCoords[pointerId] == &arrows )
{
i = ArrowKeysPressed(x, y);
if( i == oldArrows )
return 1;
if( oldArrows & ARROW_UP && ! (i & ARROW_UP) )
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym( SDL_KEY(UP), &keysym) );
if( oldArrows & ARROW_DOWN && ! (i & ARROW_DOWN) )
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym( SDL_KEY(DOWN), &keysym) );
if( oldArrows & ARROW_LEFT && ! (i & ARROW_LEFT) )
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym( SDL_KEY(LEFT), &keysym) );
if( oldArrows & ARROW_RIGHT && ! (i & ARROW_RIGHT) )
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym( SDL_KEY(RIGHT), &keysym) );
if( i & ARROW_UP )
SDL_SendKeyboardKey( SDL_PRESSED, GetKeysym( SDL_KEY(UP), &keysym) );
if( i & ARROW_DOWN )
SDL_SendKeyboardKey( SDL_PRESSED, GetKeysym( SDL_KEY(DOWN), &keysym) );
if( i & ARROW_LEFT )
SDL_SendKeyboardKey( SDL_PRESSED, GetKeysym( SDL_KEY(LEFT), &keysym) );
if( i & ARROW_RIGHT )
SDL_SendKeyboardKey( SDL_PRESSED, GetKeysym( SDL_KEY(RIGHT), &keysym) );
oldArrows = i;
}
else
{
for(i = 0; i < AutoFireButtonsNum; i++)
if( OldCoords[pointerId] == &buttons[i] )
{ {
if(touchscreenKeyboardTheme == 0) pointerInButtonRect[MAX_BUTTONS] = -1;
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym( SDL_KEY(UP), &keysym) );
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym( SDL_KEY(DOWN), &keysym) );
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym( SDL_KEY(LEFT), &keysym) );
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym( SDL_KEY(RIGHT), &keysym) );
oldArrows = 0;
}
else
{
i = ArrowKeysPressed(x, y);
if( i != oldArrows )
{ {
ButtonAutoFire[i] = abs(ButtonAutoFireX[i] - x) > buttons[i].w / 2; if( oldArrows & ARROW_UP && ! (i & ARROW_UP) )
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym( SDL_KEY(UP), &keysym) );
if( oldArrows & ARROW_DOWN && ! (i & ARROW_DOWN) )
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym( SDL_KEY(DOWN), &keysym) );
if( oldArrows & ARROW_LEFT && ! (i & ARROW_LEFT) )
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym( SDL_KEY(LEFT), &keysym) );
if( oldArrows & ARROW_RIGHT && ! (i & ARROW_RIGHT) )
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym( SDL_KEY(RIGHT), &keysym) );
if( i & ARROW_UP )
SDL_SendKeyboardKey( SDL_PRESSED, GetKeysym( SDL_KEY(UP), &keysym) );
if( i & ARROW_DOWN )
SDL_SendKeyboardKey( SDL_PRESSED, GetKeysym( SDL_KEY(DOWN), &keysym) );
if( i & ARROW_LEFT )
SDL_SendKeyboardKey( SDL_PRESSED, GetKeysym( SDL_KEY(LEFT), &keysym) );
if( i & ARROW_RIGHT )
SDL_SendKeyboardKey( SDL_PRESSED, GetKeysym( SDL_KEY(RIGHT), &keysym) );
}
oldArrows = i;
}
}
for( i = 0; i < AutoFireButtonsNum; i++ )
{
if( pointerInButtonRect[i] == pointerId )
{
processed = 1;
if( ! InsideRect( &buttonsAutoFireRect[i], x, y ) )
{
pointerInButtonRect[i] = -1;
if( !ButtonAutoFire[i] ) if( !ButtonAutoFire[i] )
ButtonAutoFireRot[i] = ButtonAutoFireX[i] - x; {
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym(buttonKeysyms[i] ,&keysym) );
}
else
{
ButtonAutoFire[i] = 2;
}
if(touchscreenKeyboardTheme == 0)
{
ButtonAutoFireX[i] = 0;
}
else
{
ButtonAutoFireX[i*2] = 0;
ButtonAutoFireX[i*2+1] = 0;
}
} }
else else
{ {
int coeff = (buttonAutoFireImages[i*2+1].w > buttons[i].w) ? buttonAutoFireImages[i*2+1].w / buttons[i].w + 1 : 1; if(touchscreenKeyboardTheme == 0)
if( ButtonAutoFireRot[i] < x )
ButtonAutoFireX[i*2+1] += (x - ButtonAutoFireRot[i]) * coeff;
if( ButtonAutoFireRot[i] > x )
ButtonAutoFireX[i*2] += (ButtonAutoFireRot[i] - x) * coeff;
ButtonAutoFireRot[i] = x;
if( ButtonAutoFireX[i*2] < 0 )
ButtonAutoFireX[i*2] = 0;
if( ButtonAutoFireX[i*2+1] < 0 )
ButtonAutoFireX[i*2+1] = 0;
if( ButtonAutoFireX[i*2] > buttonAutoFireImages[i*2+1].w / 2 )
ButtonAutoFireX[i*2] = buttonAutoFireImages[i*2+1].w / 2;
if( ButtonAutoFireX[i*2+1] > buttonAutoFireImages[i*2+1].w / 2 )
ButtonAutoFireX[i*2+1] = buttonAutoFireImages[i*2+1].w / 2;
if( ButtonAutoFireX[i*2] == buttonAutoFireImages[i*2+1].w / 2 &&
ButtonAutoFireX[i*2+1] == buttonAutoFireImages[i*2+1].w / 2 )
{ {
if( ! ButtonAutoFire[i] ) ButtonAutoFire[i] = abs(ButtonAutoFireX[i] - x) > buttons[i].w / 2;
ButtonAutoFireDecay[i] = SDL_GetTicks(); if( !ButtonAutoFire[i] )
ButtonAutoFire[i] = 1; ButtonAutoFireRot[i] = ButtonAutoFireX[i] - x;
}
else
{
int coeff = (buttonAutoFireImages[i*2+1].w > buttons[i].w) ? buttonAutoFireImages[i*2+1].w / buttons[i].w + 1 : 1;
if( ButtonAutoFireRot[i] < x )
ButtonAutoFireX[i*2+1] += (x - ButtonAutoFireRot[i]) * coeff;
if( ButtonAutoFireRot[i] > x )
ButtonAutoFireX[i*2] += (ButtonAutoFireRot[i] - x) * coeff;
ButtonAutoFireRot[i] = x;
if( ButtonAutoFireX[i*2] < 0 )
ButtonAutoFireX[i*2] = 0;
if( ButtonAutoFireX[i*2+1] < 0 )
ButtonAutoFireX[i*2+1] = 0;
if( ButtonAutoFireX[i*2] > buttonAutoFireImages[i*2+1].w / 2 )
ButtonAutoFireX[i*2] = buttonAutoFireImages[i*2+1].w / 2;
if( ButtonAutoFireX[i*2+1] > buttonAutoFireImages[i*2+1].w / 2 )
ButtonAutoFireX[i*2+1] = buttonAutoFireImages[i*2+1].w / 2;
if( ButtonAutoFireX[i*2] == buttonAutoFireImages[i*2+1].w / 2 &&
ButtonAutoFireX[i*2+1] == buttonAutoFireImages[i*2+1].w / 2 )
{
if( ! ButtonAutoFire[i] )
ButtonAutoFireDecay[i] = SDL_GetTicks();
ButtonAutoFire[i] = 1;
}
} }
} }
} }
} }
for( i = AutoFireButtonsNum; i < nbuttons; i++ )
if( OldCoords[pointerId] ) {
return 1; if( pointerInButtonRect[i] == pointerId )
{
return SDL_ANDROID_processTouchscreenKeyboard(x, y, MOUSE_DOWN, pointerId); processed = 1;
if( ! InsideRect( &buttons[i], x, y ) )
{
pointerInButtonRect[i] = -1;
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym(buttonKeysyms[i] ,&keysym) );
}
}
}
} }
return 0;
return processed;
}; };
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
@@ -633,6 +691,18 @@ JAVA_EXPORT_NAME(Settings_nativeSetupScreenKeyboard) ( JNIEnv* env, jobject thi
buttons[6].w = 30; buttons[6].w = 30;
buttons[6].h = 30; buttons[6].h = 30;
} }
for( i = 0; i < sizeof(pointerInButtonRect)/sizeof(pointerInButtonRect[0]); i++ )
{
pointerInButtonRect[i] = -1;
}
for( i = 0; i < nbuttonsAutoFire; i++ )
{
buttonsAutoFireRect[i].w = buttons[i].w * 2;
buttonsAutoFireRect[i].h = buttons[i].h * 2;
buttonsAutoFireRect[i].x = buttons[i].x - buttons[i].w / 2;
buttonsAutoFireRect[i].y = buttons[i].y - buttons[i].h / 2;
}
}; };

View File

@@ -56,28 +56,101 @@ abstract class DifferentTouchInput
} }
private static class MultiTouchInput extends DifferentTouchInput private static class MultiTouchInput extends DifferentTouchInput
{ {
private static final int touchEventMax = 16; // Max multitouch pointers
private class touchEvent
{
public boolean down = false;
public int x = 0;
public int y = 0;
public int pressure = 0;
public int size = 0;
}
private touchEvent touchEvents[];
MultiTouchInput()
{
touchEvents = new touchEvent[touchEventMax];
for( int i = 0; i < touchEventMax; i++ )
touchEvents[i] = new touchEvent();
}
private static class Holder private static class Holder
{ {
private static final MultiTouchInput sInstance = new MultiTouchInput(); private static final MultiTouchInput sInstance = new MultiTouchInput();
} }
public void process(final MotionEvent event) public void process(final MotionEvent event)
{ {
for( int i = 0; i < event.getPointerCount(); i++ ) int action = -1;
if( event.getAction() == MotionEvent.ACTION_UP )
{ {
int action = -1; action = 1;
if( event.getAction() == MotionEvent.ACTION_DOWN ) for( int i = 0; i < touchEventMax; i++ )
action = 0; {
if( event.getAction() == MotionEvent.ACTION_UP ) if( touchEvents[i].down )
action = 1; {
if( event.getAction() == MotionEvent.ACTION_MOVE ) touchEvents[i].down = false;
action = 2; DemoGLSurfaceView.nativeMouse( touchEvents[i].x, touchEvents[i].y, action, i, touchEvents[i].pressure, touchEvents[i].size );
if ( action >= 0 ) }
DemoGLSurfaceView.nativeMouse( (int)event.getX(i), }
(int)event.getY(i), }
action, if( event.getAction() == MotionEvent.ACTION_DOWN )
event.getPointerId(i), {
(int)(event.getPressure(i) * 1000.0), action = 0;
(int)(event.getSize(i) * 1000.0)); for( int i = 0; i < event.getPointerCount(); i++ )
{
int id = event.getPointerId(i);
if( id >= touchEventMax )
id = touchEventMax-1;
touchEvents[id].down = true;
touchEvents[id].x = (int)event.getX(i);
touchEvents[id].y = (int)event.getY(i);
touchEvents[id].pressure = (int)(event.getPressure(i) * 1000.0);
touchEvents[id].size = (int)(event.getSize(i) * 1000.0);
DemoGLSurfaceView.nativeMouse( touchEvents[i].x, touchEvents[i].y, action, id, touchEvents[i].pressure, touchEvents[i].size );
}
}
if( event.getAction() == MotionEvent.ACTION_MOVE )
{
for( int i = 0; i < touchEventMax; i++ )
{
int ii;
for( ii = 0; ii < event.getPointerCount(); ii++ )
{
if( i == event.getPointerId(ii) )
break;
}
if( ii >= event.getPointerCount() )
{
// Up event
if( touchEvents[i].down )
{
action = 1;
touchEvents[i].down = false;
DemoGLSurfaceView.nativeMouse( touchEvents[i].x, touchEvents[i].y, action, i, touchEvents[i].pressure, touchEvents[i].size );
}
}
else
{
int id = event.getPointerId(ii);
if( id >= touchEventMax )
id = touchEventMax-1;
if( touchEvents[id].down )
action = 2;
else
action = 0;
touchEvents[id].down = true;
touchEvents[id].x = (int)event.getX(i);
touchEvents[id].y = (int)event.getY(i);
touchEvents[id].pressure = (int)(event.getPressure(i) * 1000.0);
touchEvents[id].size = (int)(event.getSize(i) * 1000.0);
DemoGLSurfaceView.nativeMouse( touchEvents[i].x, touchEvents[i].y, action, id, touchEvents[i].pressure, touchEvents[i].size );
}
}
} }
} }
} }