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 { 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_isTouchscreenKeyboardUsed;

View File

@@ -64,7 +64,7 @@ static int AutoFireButtonsNum = 0;
static int nbuttons = 4;
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] = {
SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_KEYCODE_0)),
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 ButtonAutoFireDecay[MAX_BUTTONS_AUTOFIRE] = {0, 0};
static SDL_Rect * OldCoords[MAX_MULTITOUCH_POINTERS] = { NULL };
static int pointerInButtonRect[MAX_BUTTONS + 1] = {0};
typedef struct
{
@@ -371,173 +371,231 @@ int SDL_ANDROID_processTouchscreenKeyboard(int x, int y, int action, int pointer
{
int i;
SDL_keysym keysym;
int processed = 0;
if( !touchscreenKeyboardShown )
return 0;
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 ) )
{
OldCoords[pointerId] = &arrows;
i = ArrowKeysPressed(x, y);
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;
return 1;
processed = 1;
if( pointerInButtonRect[MAX_BUTTONS] == -1 )
{
pointerInButtonRect[MAX_BUTTONS] = pointerId;
i = ArrowKeysPressed(x, y);
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 < nbuttons; i++ )
{
if( InsideRect( &buttons[i], x, y) )
{
OldCoords[pointerId] = &buttons[i];
SDL_SendKeyboardKey( SDL_PRESSED, GetKeysym(buttonKeysyms[i], &keysym) );
if( i < AutoFireButtonsNum )
processed = 1;
if( pointerInButtonRect[i] == -1 )
{
ButtonAutoFire[i] = 0;
if(touchscreenKeyboardTheme == 0)
pointerInButtonRect[i] = pointerId;
SDL_SendKeyboardKey( SDL_PRESSED, GetKeysym(buttonKeysyms[i], &keysym) );
if( i < AutoFireButtonsNum )
{
ButtonAutoFireX[i] = x;
ButtonAutoFireRot[i] = 0;
}
else
{
ButtonAutoFireX[i*2] = 0;
ButtonAutoFireX[i*2+1] = 0;
ButtonAutoFireRot[i] = x;
ButtonAutoFireDecay[i] = SDL_GetTicks();
ButtonAutoFire[i] = 0;
if(touchscreenKeyboardTheme == 0)
{
ButtonAutoFireX[i] = x;
ButtonAutoFireRot[i] = 0;
}
else
{
ButtonAutoFireX[i*2] = 0;
ButtonAutoFireX[i*2+1] = 0;
ButtonAutoFireRot[i] = x;
ButtonAutoFireDecay[i] = SDL_GetTicks();
}
}
}
return 1;
}
}
}
else
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(DOWN), &keysym) );
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym( SDL_KEY(LEFT), &keysym) );
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym( SDL_KEY(RIGHT), &keysym) );
oldArrows = 0;
return 1;
}
for( i = 0; i < nbuttons; i++ )
{
if( OldCoords[pointerId] == &buttons[i] )
if( pointerInButtonRect[i] == pointerId )
{
if( ! ( i < AutoFireButtonsNum && ButtonAutoFire[i] ) )
{
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym(buttonKeysyms[i] ,&keysym) );
}
else
processed = 1;
pointerInButtonRect[i] = -1;
if( i < AutoFireButtonsNum && ButtonAutoFire[i] )
{
ButtonAutoFire[i] = 2;
}
OldCoords[pointerId] = NULL;
if(touchscreenKeyboardTheme == 0)
{
ButtonAutoFireX[i] = 0;
}
else
{
ButtonAutoFireX[i*2] = 0;
ButtonAutoFireX[i*2+1] = 0;
SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym(buttonKeysyms[i] ,&keysym) );
}
if( i < AutoFireButtonsNum )
{
if(touchscreenKeyboardTheme == 0)
{
ButtonAutoFireX[i] = 0;
}
else
{
ButtonAutoFireX[i*2] = 0;
ButtonAutoFireX[i*2+1] = 0;
}
}
return 1;
}
}
}
else
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);
return SDL_ANDROID_processTouchscreenKeyboard(x, y, MOUSE_DOWN, pointerId);
}
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] )
processed = 1;
if( ! InsideRect( &arrows, x, y ) )
{
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] )
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
{
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(touchscreenKeyboardTheme == 0)
{
if( ! ButtonAutoFire[i] )
ButtonAutoFireDecay[i] = SDL_GetTicks();
ButtonAutoFire[i] = 1;
ButtonAutoFire[i] = abs(ButtonAutoFireX[i] - x) > buttons[i].w / 2;
if( !ButtonAutoFire[i] )
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;
}
}
}
}
}
if( OldCoords[pointerId] )
return 1;
return SDL_ANDROID_processTouchscreenKeyboard(x, y, MOUSE_DOWN, pointerId);
for( i = AutoFireButtonsNum; i < nbuttons; i++ )
{
if( pointerInButtonRect[i] == 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
@@ -633,6 +691,18 @@ JAVA_EXPORT_NAME(Settings_nativeSetupScreenKeyboard) ( JNIEnv* env, jobject thi
buttons[6].w = 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 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 final MultiTouchInput sInstance = new MultiTouchInput();
}
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;
if( event.getAction() == MotionEvent.ACTION_DOWN )
action = 0;
if( event.getAction() == MotionEvent.ACTION_UP )
action = 1;
if( event.getAction() == MotionEvent.ACTION_MOVE )
action = 2;
if ( action >= 0 )
DemoGLSurfaceView.nativeMouse( (int)event.getX(i),
(int)event.getY(i),
action,
event.getPointerId(i),
(int)(event.getPressure(i) * 1000.0),
(int)(event.getSize(i) * 1000.0));
action = 1;
for( int i = 0; i < touchEventMax; i++ )
{
if( touchEvents[i].down )
{
touchEvents[i].down = false;
DemoGLSurfaceView.nativeMouse( touchEvents[i].x, touchEvents[i].y, action, i, touchEvents[i].pressure, touchEvents[i].size );
}
}
}
if( event.getAction() == MotionEvent.ACTION_DOWN )
{
action = 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 );
}
}
}
}
}