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];
}
extern void SDL_ANDROID_MainThreadPushKeyboardKey(int pressed, SDL_scancode key, int unicode)
{
	SDL_keysym keysym;

	if( SDL_ANDROID_moveMouseWithArrowKeys && (
		key == SDL_KEY(UP) || key == SDL_KEY(DOWN) ||
		key == SDL_KEY(LEFT) || key == SDL_KEY(RIGHT) ) )
	{
		if( SDL_ANDROID_moveMouseWithKbX < 0 )
		{
			SDL_ANDROID_moveMouseWithKbX = SDL_ANDROID_currentMouseX;
			SDL_ANDROID_moveMouseWithKbY = SDL_ANDROID_currentMouseY;
		}

		if( pressed )
		{
			if( key == SDL_KEY(LEFT) )
			{
				if( SDL_ANDROID_moveMouseWithKbSpeedX > 0 )
					SDL_ANDROID_moveMouseWithKbSpeedX = 0;
				SDL_ANDROID_moveMouseWithKbSpeedX -= SDL_ANDROID_moveMouseWithKbSpeed;
				SDL_ANDROID_moveMouseWithKbAccelX = -SDL_ANDROID_moveMouseWithKbAccel;
				SDL_ANDROID_moveMouseWithKbAccelUpdateNeeded |= 1;
			}
			else if( key == SDL_KEY(RIGHT) )
			{
				if( SDL_ANDROID_moveMouseWithKbSpeedX < 0 )
					SDL_ANDROID_moveMouseWithKbSpeedX = 0;
				SDL_ANDROID_moveMouseWithKbSpeedX += SDL_ANDROID_moveMouseWithKbSpeed;
				SDL_ANDROID_moveMouseWithKbAccelX = SDL_ANDROID_moveMouseWithKbAccel;
				SDL_ANDROID_moveMouseWithKbAccelUpdateNeeded |= 1;
			}

			if( key == SDL_KEY(UP) )
			{
				if( SDL_ANDROID_moveMouseWithKbSpeedY > 0 )
					SDL_ANDROID_moveMouseWithKbSpeedY = 0;
				SDL_ANDROID_moveMouseWithKbSpeedY -= SDL_ANDROID_moveMouseWithKbSpeed;
				SDL_ANDROID_moveMouseWithKbAccelY = -SDL_ANDROID_moveMouseWithKbAccel;
				SDL_ANDROID_moveMouseWithKbAccelUpdateNeeded |= 2;
			}
			else if( key == SDL_KEY(DOWN) )
			{
				if( SDL_ANDROID_moveMouseWithKbSpeedY < 0 )
					SDL_ANDROID_moveMouseWithKbSpeedY = 0;
				SDL_ANDROID_moveMouseWithKbSpeedY += SDL_ANDROID_moveMouseWithKbSpeed;
				SDL_ANDROID_moveMouseWithKbAccelY = SDL_ANDROID_moveMouseWithKbAccel;
				SDL_ANDROID_moveMouseWithKbAccelUpdateNeeded |= 2;
			}
		}
		else
		{
			if( key == SDL_KEY(LEFT) || key == SDL_KEY(RIGHT) )
			{
				SDL_ANDROID_moveMouseWithKbSpeedX = 0;
				SDL_ANDROID_moveMouseWithKbAccelX = 0;
				SDL_ANDROID_moveMouseWithKbAccelUpdateNeeded &= ~1;
			}
			if( key == SDL_KEY(UP) || key == SDL_KEY(DOWN) )
			{
				SDL_ANDROID_moveMouseWithKbSpeedY = 0;
				SDL_ANDROID_moveMouseWithKbAccelY = 0;
				SDL_ANDROID_moveMouseWithKbAccelUpdateNeeded &= ~2;
			}
		}

		SDL_ANDROID_moveMouseWithKbX += SDL_ANDROID_moveMouseWithKbSpeedX;
		SDL_ANDROID_moveMouseWithKbY += SDL_ANDROID_moveMouseWithKbSpeedY;

		SDL_ANDROID_MainThreadPushMouseMotion(SDL_ANDROID_moveMouseWithKbX, SDL_ANDROID_moveMouseWithKbY);
		return;
	}

	if ( key >= SDLK_MOUSE_LEFT && key <= SDLK_MOUSE_X2 )
	{
		SDL_ANDROID_MainThreadPushMouseButton(pressed, key - SDLK_MOUSE_LEFT + SDL_BUTTON_LEFT);
		return;
	}

	keysym.scancode = key;
	if ( key < SDLK_LAST )
		keysym.scancode = SDL_android_keysym_to_scancode[key];
	keysym.sym = key;
	keysym.mod = KMOD_NONE;
	keysym.unicode = 0;
#if SDL_VERSION_ATLEAST(1,3,0)
#else
	if ( SDL_TranslateUNICODE )
#endif
		keysym.unicode = unicode;
	if( (keysym.unicode & 0xFF80) != 0 )
		keysym.sym = SDLK_WORLD_0;
	//else if( keysym.sym < 0x80 )
	//	keysym.unicode = keysym.sym;

	if( pressed == SDL_RELEASED )
		keysym.unicode = 0;

	//__android_log_print(ANDROID_LOG_INFO, "libSDL","SDL_SendKeyboardKey sym %d scancode %d unicode %d", keysym.sym, keysym.scancode, keysym.unicode);

	SDL_SendKeyboardKey( pressed, &keysym );
}
Example #3
0
void SDL_android_init_keymap(SDLKey *SDL_android_keymap)
{
  int i;
  SDLKey * keymap = SDL_android_keymap;

  for (i=0; i<SDL_arraysize(SDL_android_keymap); ++i)
    SDL_android_keymap[i] = SDL_KEY(UNKNOWN);

  keymap[KEYCODE_UNKNOWN] = SDL_KEY(UNKNOWN);

  keymap[KEYCODE_BACK] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_KEYCODE_5));

  keymap[KEYCODE_MENU] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_KEYCODE_4));

  keymap[KEYCODE_DPAD_CENTER] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_KEYCODE_1));
  keymap[KEYCODE_SEARCH] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_KEYCODE_7));

  keymap[KEYCODE_VOLUME_UP] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_KEYCODE_2));
  keymap[KEYCODE_VOLUME_DOWN] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_KEYCODE_3));
  
  keymap[KEYCODE_HOME] = SDL_KEY(HOME); // Cannot be used in application

  // On some devices pressing Camera key will generate Camera keyevent, but releasing it will generate Focus keyevent.
  keymap[KEYCODE_CAMERA] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_KEYCODE_6));
  keymap[KEYCODE_FOCUS] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_KEYCODE_6));

  keymap[KEYCODE_CALL] = SDL_KEY(TAB);

  keymap[KEYCODE_0] = SDL_KEY(0);
  keymap[KEYCODE_1] = SDL_KEY(1);
  keymap[KEYCODE_2] = SDL_KEY(2);
  keymap[KEYCODE_3] = SDL_KEY(3);
  keymap[KEYCODE_4] = SDL_KEY(4);
  keymap[KEYCODE_5] = SDL_KEY(5);
  keymap[KEYCODE_6] = SDL_KEY(6);
  keymap[KEYCODE_7] = SDL_KEY(7);
  keymap[KEYCODE_8] = SDL_KEY(8);
  keymap[KEYCODE_9] = SDL_KEY(9);
  keymap[KEYCODE_STAR] = SDL_KEY(KP_MULTIPLY);
  keymap[KEYCODE_POUND] = SDL_KEY(HASH);

  keymap[KEYCODE_DPAD_UP] = SDL_KEY(UP);
  keymap[KEYCODE_DPAD_DOWN] = SDL_KEY(DOWN);
  keymap[KEYCODE_DPAD_LEFT] = SDL_KEY(LEFT);
  keymap[KEYCODE_DPAD_RIGHT] = SDL_KEY(RIGHT);

  keymap[KEYCODE_SOFT_LEFT] = SDL_KEY(KP_4);
  keymap[KEYCODE_SOFT_RIGHT] = SDL_KEY(KP_6);
  keymap[KEYCODE_ENTER] = SDL_KEY(RETURN);


  keymap[KEYCODE_CLEAR] = SDL_KEY(CLEAR);
  keymap[KEYCODE_A] = SDL_KEY(A);
  keymap[KEYCODE_B] = SDL_KEY(B);
  keymap[KEYCODE_C] = SDL_KEY(C);
  keymap[KEYCODE_D] = SDL_KEY(D);
  keymap[KEYCODE_E] = SDL_KEY(E);
  keymap[KEYCODE_F] = SDL_KEY(F);
  keymap[KEYCODE_G] = SDL_KEY(G);
  keymap[KEYCODE_H] = SDL_KEY(H);
  keymap[KEYCODE_I] = SDL_KEY(I);
  keymap[KEYCODE_J] = SDL_KEY(J);
  keymap[KEYCODE_K] = SDL_KEY(K);
  keymap[KEYCODE_L] = SDL_KEY(L);
  keymap[KEYCODE_M] = SDL_KEY(M);
  keymap[KEYCODE_N] = SDL_KEY(N);
  keymap[KEYCODE_O] = SDL_KEY(O);
  keymap[KEYCODE_P] = SDL_KEY(P);
  keymap[KEYCODE_Q] = SDL_KEY(Q);
  keymap[KEYCODE_R] = SDL_KEY(R);
  keymap[KEYCODE_S] = SDL_KEY(S);
  keymap[KEYCODE_T] = SDL_KEY(T);
  keymap[KEYCODE_U] = SDL_KEY(U);
  keymap[KEYCODE_V] = SDL_KEY(V);
  keymap[KEYCODE_W] = SDL_KEY(W);
  keymap[KEYCODE_X] = SDL_KEY(X);
  keymap[KEYCODE_Y] = SDL_KEY(Y);
  keymap[KEYCODE_Z] = SDL_KEY(Z);
  keymap[KEYCODE_COMMA] = SDL_KEY(COMMA);
  keymap[KEYCODE_PERIOD] = SDL_KEY(PERIOD);
  keymap[KEYCODE_TAB] = SDL_KEY(TAB);
  keymap[KEYCODE_SPACE] = SDL_KEY(SPACE);
  keymap[KEYCODE_DEL] = SDL_KEY(BACKSPACE);
  keymap[KEYCODE_GRAVE] = SDL_KEY(GRAVE);
  keymap[KEYCODE_MINUS] = SDL_KEY(MINUS);
  keymap[KEYCODE_PLUS] = SDL_KEY(PLUS);
  keymap[KEYCODE_EQUALS] = SDL_KEY(EQUALS);
  keymap[KEYCODE_LEFT_BRACKET] = SDL_KEY(LEFTBRACKET);
  keymap[KEYCODE_RIGHT_BRACKET] = SDL_KEY(RIGHTBRACKET);
  keymap[KEYCODE_BACKSLASH] = SDL_KEY(BACKSLASH);
  keymap[KEYCODE_SEMICOLON] = SDL_KEY(SEMICOLON);
  keymap[KEYCODE_APOSTROPHE] = SDL_KEY(APOSTROPHE);
  keymap[KEYCODE_SLASH] = SDL_KEY(SLASH);
  keymap[KEYCODE_AT] = SDL_KEY(AT);

  keymap[KEYCODE_MEDIA_PLAY_PAUSE] = SDL_KEY(KP_2);
  keymap[KEYCODE_MEDIA_STOP] = SDL_KEY(HELP);
  keymap[KEYCODE_MEDIA_NEXT] = SDL_KEY(KP_8);
  keymap[KEYCODE_MEDIA_PREVIOUS] = SDL_KEY(KP_5);
  keymap[KEYCODE_MEDIA_REWIND] = SDL_KEY(KP_1);
  keymap[KEYCODE_MEDIA_FAST_FORWARD] = SDL_KEY(KP_3);
  keymap[KEYCODE_MUTE] = SDL_KEY(KP_0);

  keymap[KEYCODE_SYM] = SDL_KEY(LGUI);
  keymap[KEYCODE_NUM] = SDL_KEY(NUMLOCKCLEAR);

  keymap[KEYCODE_ALT_LEFT] = SDL_KEY(LALT);
  keymap[KEYCODE_ALT_RIGHT] = SDL_KEY(RALT);

  keymap[KEYCODE_SHIFT_LEFT] = SDL_KEY(LSHIFT);
  keymap[KEYCODE_SHIFT_RIGHT] = SDL_KEY(RSHIFT);

  keymap[KEYCODE_EXPLORER] = SDL_KEY(F3);
  keymap[KEYCODE_ENVELOPE] = SDL_KEY(F4);

  keymap[KEYCODE_HEADSETHOOK] = SDL_KEY(F5);
  keymap[KEYCODE_NOTIFICATION] = SDL_KEY(F6);

  // Cannot be received by application, OS internal
  keymap[KEYCODE_ENDCALL] = SDL_KEY(LSHIFT);
  keymap[KEYCODE_POWER] = SDL_KEY(RALT);

  keymap[KEYCODE_PAGE_UP] = SDL_KEY(PAGEUP);
  keymap[KEYCODE_PAGE_DOWN] = SDL_KEY(PAGEDOWN);
  keymap[KEYCODE_PICTSYMBOLS] = SDL_KEY(LSHIFT);
  keymap[KEYCODE_SWITCH_CHARSET] = SDL_KEY(LSHIFT);
  keymap[KEYCODE_BUTTON_A] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_SCREENKB_KEYCODE_0));
  keymap[KEYCODE_BUTTON_B] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_SCREENKB_KEYCODE_1));
  keymap[KEYCODE_BUTTON_C] = SDL_KEY(C);
  keymap[KEYCODE_BUTTON_X] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_SCREENKB_KEYCODE_2));
  keymap[KEYCODE_BUTTON_Y] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_SCREENKB_KEYCODE_3));
  keymap[KEYCODE_BUTTON_Z] = SDL_KEY(Z);
  keymap[KEYCODE_BUTTON_L1] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_SCREENKB_KEYCODE_5));
  keymap[KEYCODE_BUTTON_R1] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_SCREENKB_KEYCODE_4));
  keymap[KEYCODE_BUTTON_L2] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_KEYCODE_0));
  keymap[KEYCODE_BUTTON_R2] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_KEYCODE_6));
  keymap[KEYCODE_BUTTON_THUMBL] = SDL_KEY(SPACE);
  keymap[KEYCODE_BUTTON_THUMBR] = SDL_KEY(RETURN);
  keymap[KEYCODE_BUTTON_START] = SDL_KEY(RETURN);
  keymap[KEYCODE_BUTTON_SELECT] = SDL_KEY(ESCAPE);
  keymap[KEYCODE_BUTTON_MODE] = SDL_KEY(SPACE);
  keymap[KEYCODE_ESCAPE] = SDL_KEY(ESCAPE);
  keymap[KEYCODE_FORWARD_DEL] = SDL_KEY(DELETE);
  keymap[KEYCODE_CTRL_LEFT] = SDL_KEY(LCTRL);
  keymap[KEYCODE_CTRL_RIGHT] = SDL_KEY(RCTRL);
  keymap[KEYCODE_CAPS_LOCK] = SDL_KEY(CAPSLOCK);
  keymap[KEYCODE_SCROLL_LOCK] = SDL_KEY(SCROLLLOCK);
  keymap[KEYCODE_META_LEFT] = SDL_KEY(LEFT);
  keymap[KEYCODE_META_RIGHT] = SDL_KEY(RIGHT);
  keymap[KEYCODE_FUNCTION] = SDL_KEY(RGUI);
  keymap[KEYCODE_SYSRQ] = SDL_KEY(SYSREQ);
  keymap[KEYCODE_BREAK] = SDL_KEY(PAUSE);
  keymap[KEYCODE_MOVE_HOME] = SDL_KEY(HOME);
  keymap[KEYCODE_MOVE_END] = SDL_KEY(END);
  keymap[KEYCODE_INSERT] = SDL_KEY(INSERT);
  keymap[KEYCODE_FORWARD] = SDL_KEY(RIGHT);
  keymap[KEYCODE_MEDIA_PLAY] = SDL_KEY(F1);
  keymap[KEYCODE_MEDIA_PAUSE] = SDL_KEY(F2);
  keymap[KEYCODE_MEDIA_CLOSE] = SDL_KEY(F3);
  keymap[KEYCODE_MEDIA_EJECT] = SDL_KEY(F4);
  keymap[KEYCODE_MEDIA_RECORD] = SDL_KEY(F5);
  keymap[KEYCODE_F1] = SDL_KEY(F1);
  keymap[KEYCODE_F2] = SDL_KEY(F2);
  keymap[KEYCODE_F3] = SDL_KEY(F3);
  keymap[KEYCODE_F4] = SDL_KEY(F4);
  keymap[KEYCODE_F5] = SDL_KEY(F5);
  keymap[KEYCODE_F6] = SDL_KEY(F6);
  keymap[KEYCODE_F7] = SDL_KEY(F7);
  keymap[KEYCODE_F8] = SDL_KEY(F8);
  keymap[KEYCODE_F9] = SDL_KEY(F9);
  keymap[KEYCODE_F10] = SDL_KEY(F10);
  keymap[KEYCODE_F11] = SDL_KEY(F11);
  keymap[KEYCODE_F12] = SDL_KEY(F12);
  keymap[KEYCODE_NUM_LOCK] = SDL_KEY(NUMLOCKCLEAR);
  keymap[KEYCODE_NUMPAD_0] = SDL_KEY(KP_0);
  keymap[KEYCODE_NUMPAD_1] = SDL_KEY(KP_1);
  keymap[KEYCODE_NUMPAD_2] = SDL_KEY(KP_2);
  keymap[KEYCODE_NUMPAD_3] = SDL_KEY(KP_3);
  keymap[KEYCODE_NUMPAD_4] = SDL_KEY(KP_4);
  keymap[KEYCODE_NUMPAD_5] = SDL_KEY(KP_5);
  keymap[KEYCODE_NUMPAD_6] = SDL_KEY(KP_6);
  keymap[KEYCODE_NUMPAD_7] = SDL_KEY(KP_7);
  keymap[KEYCODE_NUMPAD_8] = SDL_KEY(KP_8);
  keymap[KEYCODE_NUMPAD_9] = SDL_KEY(KP_9);
  keymap[KEYCODE_NUMPAD_DIVIDE] = SDL_KEY(KP_DIVIDE);
  keymap[KEYCODE_NUMPAD_MULTIPLY] = SDL_KEY(KP_MULTIPLY);
  keymap[KEYCODE_NUMPAD_SUBTRACT] = SDL_KEY(KP_MINUS);
  keymap[KEYCODE_NUMPAD_ADD] = SDL_KEY(KP_PLUS);
  keymap[KEYCODE_NUMPAD_DOT] = SDL_KEY(KP_PERIOD);
  keymap[KEYCODE_NUMPAD_COMMA] = SDL_KEY(KP_PERIOD);
  keymap[KEYCODE_NUMPAD_ENTER] = SDL_KEY(KP_ENTER);
  keymap[KEYCODE_NUMPAD_EQUALS] = SDL_KEY(KP_EQUALS);
  keymap[KEYCODE_NUMPAD_LEFT_PAREN] = SDL_KEY(KP_DIVIDE);
  keymap[KEYCODE_NUMPAD_RIGHT_PAREN] = SDL_KEY(KP_MULTIPLY);
  keymap[KEYCODE_VOLUME_MUTE] = SDL_KEY(F13);
  keymap[KEYCODE_INFO] = SDL_KEY(F14);
  keymap[KEYCODE_CHANNEL_UP] = SDL_KEY(UP);
  keymap[KEYCODE_CHANNEL_DOWN] = SDL_KEY(DOWN);
  keymap[KEYCODE_ZOOM_IN] = SDL_KEY(PAGEUP);
  keymap[KEYCODE_ZOOM_OUT] = SDL_KEY(PAGEDOWN);
  keymap[KEYCODE_TV] = SDL_KEY(F15);
  keymap[KEYCODE_WINDOW] = SDL_KEY(F1);
  keymap[KEYCODE_GUIDE] = SDL_KEY(F2);
  keymap[KEYCODE_DVR] = SDL_KEY(F3);
  keymap[KEYCODE_BOOKMARK] = SDL_KEY(F4);
  keymap[KEYCODE_CAPTIONS] = SDL_KEY(F5);
  keymap[KEYCODE_SETTINGS] = SDL_KEY(F6);
  keymap[KEYCODE_TV_POWER] = SDL_KEY(F7);
  keymap[KEYCODE_TV_INPUT] = SDL_KEY(F8);
  keymap[KEYCODE_STB_POWER] = SDL_KEY(F9);
  keymap[KEYCODE_STB_INPUT] = SDL_KEY(F10);
  keymap[KEYCODE_AVR_POWER] = SDL_KEY(F11);
  keymap[KEYCODE_AVR_INPUT] = SDL_KEY(F12);
  keymap[KEYCODE_PROG_RED] = SDL_KEY(F13);
  keymap[KEYCODE_PROG_GREEN] = SDL_KEY(F14);
  keymap[KEYCODE_PROG_YELLOW] = SDL_KEY(F15);
  keymap[KEYCODE_PROG_BLUE] = SDL_KEY(F1);
  keymap[KEYCODE_APP_SWITCH] = SDL_KEY(F2);
  keymap[KEYCODE_BUTTON_1] = SDL_KEY(A);
  keymap[KEYCODE_BUTTON_2] = SDL_KEY(B);
  keymap[KEYCODE_BUTTON_3] = SDL_KEY(C);
  keymap[KEYCODE_BUTTON_4] = SDL_KEY(D);
  keymap[KEYCODE_BUTTON_5] = SDL_KEY(E);
  keymap[KEYCODE_BUTTON_6] = SDL_KEY(F);
  keymap[KEYCODE_BUTTON_7] = SDL_KEY(G);
  keymap[KEYCODE_BUTTON_8] = SDL_KEY(H);
  keymap[KEYCODE_BUTTON_9] = SDL_KEY(I);
  keymap[KEYCODE_BUTTON_10] = SDL_KEY(J);
  keymap[KEYCODE_BUTTON_11] = SDL_KEY(K);
  keymap[KEYCODE_BUTTON_12] = SDL_KEY(L);
  keymap[KEYCODE_BUTTON_13] = SDL_KEY(M);
  keymap[KEYCODE_BUTTON_14] = SDL_KEY(N);
  keymap[KEYCODE_BUTTON_15] = SDL_KEY(O);
  keymap[KEYCODE_BUTTON_16] = SDL_KEY(P);

}
extern void SDL_ANDROID_MainThreadPushKeyboardKey(int pressed, SDL_scancode key)
{
	SDL_keysym keysym;

	if( SDL_ANDROID_moveMouseWithArrowKeys && (
		key == SDL_KEY(UP) || key == SDL_KEY(DOWN) ||
		key == SDL_KEY(LEFT) || key == SDL_KEY(RIGHT) ) )
	{
		if( SDL_ANDROID_moveMouseWithKbX < 0 )
		{
			SDL_ANDROID_moveMouseWithKbX = SDL_ANDROID_currentMouseX;
			SDL_ANDROID_moveMouseWithKbY = SDL_ANDROID_currentMouseY;
		}

		if( pressed )
		{
			if( key == SDL_KEY(LEFT) )
			{
				if( SDL_ANDROID_moveMouseWithKbSpeedX > 0 )
					SDL_ANDROID_moveMouseWithKbSpeedX = 0;
				SDL_ANDROID_moveMouseWithKbSpeedX -= SDL_ANDROID_moveMouseWithKbSpeed;
				SDL_ANDROID_moveMouseWithKbAccelX = -SDL_ANDROID_moveMouseWithKbAccel;
				SDL_ANDROID_moveMouseWithKbAccelUpdateNeeded |= 1;
			}
			else if( key == SDL_KEY(RIGHT) )
			{
				if( SDL_ANDROID_moveMouseWithKbSpeedX < 0 )
					SDL_ANDROID_moveMouseWithKbSpeedX = 0;
				SDL_ANDROID_moveMouseWithKbSpeedX += SDL_ANDROID_moveMouseWithKbSpeed;
				SDL_ANDROID_moveMouseWithKbAccelX = SDL_ANDROID_moveMouseWithKbAccel;
				SDL_ANDROID_moveMouseWithKbAccelUpdateNeeded |= 1;
			}

			if( key == SDL_KEY(UP) )
			{
				if( SDL_ANDROID_moveMouseWithKbSpeedY > 0 )
					SDL_ANDROID_moveMouseWithKbSpeedY = 0;
				SDL_ANDROID_moveMouseWithKbSpeedY -= SDL_ANDROID_moveMouseWithKbSpeed;
				SDL_ANDROID_moveMouseWithKbAccelY = -SDL_ANDROID_moveMouseWithKbAccel;
				SDL_ANDROID_moveMouseWithKbAccelUpdateNeeded |= 2;
			}
			else if( key == SDL_KEY(DOWN) )
			{
				if( SDL_ANDROID_moveMouseWithKbSpeedY < 0 )
					SDL_ANDROID_moveMouseWithKbSpeedY = 0;
				SDL_ANDROID_moveMouseWithKbSpeedY += SDL_ANDROID_moveMouseWithKbSpeed;
				SDL_ANDROID_moveMouseWithKbAccelY = SDL_ANDROID_moveMouseWithKbAccel;
				SDL_ANDROID_moveMouseWithKbAccelUpdateNeeded |= 2;
			}
		}
		else
		{
			if( key == SDL_KEY(LEFT) || key == SDL_KEY(RIGHT) )
			{
				SDL_ANDROID_moveMouseWithKbSpeedX = 0;
				SDL_ANDROID_moveMouseWithKbAccelX = 0;
				SDL_ANDROID_moveMouseWithKbAccelUpdateNeeded &= ~1;
			}
			if( key == SDL_KEY(UP) || key == SDL_KEY(DOWN) )
			{
				SDL_ANDROID_moveMouseWithKbSpeedY = 0;
				SDL_ANDROID_moveMouseWithKbAccelY = 0;
				SDL_ANDROID_moveMouseWithKbAccelUpdateNeeded &= ~2;
			}
		}

		SDL_ANDROID_moveMouseWithKbX += SDL_ANDROID_moveMouseWithKbSpeedX;
		SDL_ANDROID_moveMouseWithKbY += SDL_ANDROID_moveMouseWithKbSpeedY;

		SDL_ANDROID_MainThreadPushMouseMotion(SDL_ANDROID_moveMouseWithKbX, SDL_ANDROID_moveMouseWithKbY);
		return;
	}

	keysym.scancode = key;
	keysym.sym = key;
	keysym.mod = KMOD_NONE;
	keysym.unicode = 0;
#if SDL_VERSION_ATLEAST(1,3,0)
#else
	if ( SDL_TranslateUNICODE )
#endif
		keysym.unicode = key;

	if( pressed == SDL_RELEASED )
		keysym.unicode = 0;

	SDL_SendKeyboardKey( pressed, &keysym );
}
int SDL_ANDROID_drawTouchscreenKeyboard()
{
	int i;
	if( !SDL_ANDROID_isTouchscreenKeyboardUsed || !touchscreenKeyboardShown )
		return 0;
	if( touchscreenKeyboardTheme == 0 )
	{
		beginDrawingWireframe();
		// Draw arrow keys
		drawCharWireframe( FONT_LEFT, arrows.x + arrows.w / 4, arrows.y + arrows.h / 2, 0, 
					255, 255, SDL_GetKeyboardState(NULL)[SDL_KEY(LEFT)] ? 255 : 0, 128 );
		drawCharWireframe( FONT_RIGHT, arrows.x + arrows.w / 4 * 3, arrows.y + arrows.h / 2, 0,
					255, 255, SDL_GetKeyboardState(NULL)[SDL_KEY(RIGHT)] ? 255 : 0, 128 );
		drawCharWireframe( FONT_UP, arrows.x + arrows.w / 2, arrows.y + arrows.h / 4, 0, 
					255, 255, SDL_GetKeyboardState(NULL)[SDL_KEY(UP)] ? 255 : 0, 128 );
		drawCharWireframe( FONT_DOWN, arrows.x + arrows.w / 2, arrows.y + arrows.h / 4 * 3, 0, 
					255, 255, SDL_GetKeyboardState(NULL)[SDL_KEY(DOWN)] ? 255 : 0, 128 );

		// Draw buttons
		for( i = 0; i < nbuttons; i++ )
		{
			drawCharWireframe( FONT_BTN1 + i, buttons[i].x + buttons[i].w / 2, buttons[i].y + buttons[i].h / 2, ( i < AutoFireButtonsNum ? ButtonAutoFireRot[i] * 0x10000 : 0 ),
						( i < AutoFireButtonsNum && ButtonAutoFire[i] ) ? 0 : 255, 255, SDL_GetKeyboardState(NULL)[buttonKeysyms[i]] ? 255 : 0, 128 );
		}
		endDrawingWireframe();
	}
	else
	{
		int blendFactor =	( SDL_GetKeyboardState(NULL)[SDL_KEY(LEFT)] ? 1 : 0 ) + 
							( SDL_GetKeyboardState(NULL)[SDL_KEY(RIGHT)] ? 1 : 0 ) +
							( SDL_GetKeyboardState(NULL)[SDL_KEY(UP)] ? 1 : 0 ) +
							( SDL_GetKeyboardState(NULL)[SDL_KEY(DOWN)] ? 1 : 0 );
		beginDrawingTex();
		if( blendFactor == 0 )
			drawCharTex( &arrowImages[0], NULL, &arrows, 255, 255, 255, 128 );
		else
		{
			if( SDL_GetKeyboardState(NULL)[SDL_KEY(LEFT)] )
				drawCharTex( &arrowImages[1], NULL, &arrows, 255, 255, 255, 128 / blendFactor );
			if( SDL_GetKeyboardState(NULL)[SDL_KEY(RIGHT)] )
				drawCharTex( &arrowImages[2], NULL, &arrows, 255, 255, 255, 128 / blendFactor );
			if( SDL_GetKeyboardState(NULL)[SDL_KEY(UP)] )
				drawCharTex( &arrowImages[3], NULL, &arrows, 255, 255, 255, 128 / blendFactor );
			if( SDL_GetKeyboardState(NULL)[SDL_KEY(DOWN)] )
				drawCharTex( &arrowImages[4], NULL, &arrows, 255, 255, 255, 128 / blendFactor );
		}

		for( i = 0; i < nbuttons; i++ )
		{
			if( i < AutoFireButtonsNum )
			{
				if( ButtonAutoFire[i] == 1 && SDL_GetTicks() - ButtonAutoFireDecay[i] > 1000 )
				{
					ButtonAutoFire[i] = 0;
				}
				if( ! ButtonAutoFire[i] && SDL_GetTicks() - ButtonAutoFireDecay[i] > 300 )
				{
					if( ButtonAutoFireX[i*2] > 0 )
						ButtonAutoFireX[i*2] --;
					if( ButtonAutoFireX[i*2+1] > 0 )
						ButtonAutoFireX[i*2+1] --;
					ButtonAutoFireDecay[i] = SDL_GetTicks();
				}
			}

			if( i < AutoFireButtonsNum && ! ButtonAutoFire[i] && 
				( ButtonAutoFireX[i*2] > 0 || ButtonAutoFireX[i*2+1] > 0 ) )
			{
				int pos1src = buttonImages[i*2+1].w / 2 - ButtonAutoFireX[i*2];
				int pos1dst = buttons[i].w * pos1src / buttonImages[i*2+1].w;
				int pos2src = buttonImages[i*2+1].w - ( buttonImages[i*2+1].w / 2 - ButtonAutoFireX[i*2+1] );
				int pos2dst = buttons[i].w * pos2src / buttonImages[i*2+1].w;
				
				SDL_Rect autoFireCrop = { 0, 0, pos1src, buttonImages[i*2+1].h };
				SDL_Rect autoFireDest = buttons[i];
				autoFireDest.w = pos1dst;
				
				drawCharTex( &buttonImages[i*2+1],
							&autoFireCrop, &autoFireDest, 255, 255, 255, 128 );

				autoFireCrop.x = pos2src;
				autoFireCrop.w = buttonImages[i*2+1].w - pos2src;
				autoFireDest.x = buttons[i].x + pos2dst;
				autoFireDest.w = buttons[i].w - pos2dst;

				drawCharTex( &buttonImages[i*2+1],
							&autoFireCrop, &autoFireDest, 255, 255, 255, 128 );
				
				autoFireCrop.x = pos1src;
				autoFireCrop.w = pos2src - pos1src;
				autoFireDest.x = buttons[i].x + pos1dst;
				autoFireDest.w = pos2dst - pos1dst;

				drawCharTex( &buttonAutoFireImages[i*2+1],
							&autoFireCrop, &autoFireDest, 255, 255, 255, 128 );
			}
			else
			{
				drawCharTex( ( i < AutoFireButtonsNum && ButtonAutoFire[i] ) ? &buttonAutoFireImages[i*2] :
							&buttonImages[ SDL_GetKeyboardState(NULL)[buttonKeysyms[i]] ? (i * 2 + 1) : (i * 2) ],
							NULL, &buttons[i], 255, 255, 255, 128 );
			}
		}
		endDrawingTex();
	}
	return 1;
};
int SDL_ANDROID_processTouchscreenKeyboard(int x, int y, int action, int pointerId)
{
	int i;
	SDL_keysym keysym;

	
	if( !touchscreenKeyboardShown )
		return 0;

	if( action == MOUSE_DOWN )
	{
		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;
		}

		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 )
				{
					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 )
		{
			OldCoords[pointerId] = NULL;
			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( ! ( i < AutoFireButtonsNum && ButtonAutoFire[i] ) )
				{
					SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym(buttonKeysyms[i] ,&keysym) );
				}
				else
				{
					ButtonAutoFire[i] = 2;
				}
				OldCoords[pointerId] = NULL;
				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) )
		{
			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] )
			{
				if(touchscreenKeyboardTheme == 0)
				{
					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);
	}
	return 0;
};
static GLshort fontGL[sizeof(font)/sizeof(font[0])][FONT_MAX_LINES_PER_CHAR * 4 + 1];
enum { FONT_CHAR_LINES_COUNT = FONT_MAX_LINES_PER_CHAR * 4 };

enum { MAX_BUTTONS = SDL_ANDRIOD_SCREENKEYBOARD_BUTTON_MAX, MAX_BUTTONS_AUTOFIRE = 2 } ; // Max amount of custom buttons

int SDL_ANDROID_isTouchscreenKeyboardUsed = 0;
static int touchscreenKeyboardTheme = 0;
static int touchscreenKeyboardShown = 1;
static int AutoFireButtonsNum = 0;
static int nbuttons = 4;
static int buttonsize = 1;

static SDL_Rect arrows, buttons[MAX_BUTTONS];
static SDLKey buttonKeysyms[MAX_BUTTONS] = { 
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_2)),
SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_KEYCODE_3)),
// 4 and 5 are MENU and BACK, always available as HW keys
SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_KEYCODE_6)),
SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_KEYCODE_7)),
SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_KEYCODE_8))
};

enum { ARROW_LEFT = 1, ARROW_RIGHT = 2, ARROW_UP = 4, ARROW_DOWN = 8 };
static int oldArrows = 0;
static int ButtonAutoFire[MAX_BUTTONS_AUTOFIRE] = {0, 0};
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};
JNIEXPORT void JNICALL 
JAVA_EXPORT_NAME(SDLSurfaceView_nativeMouse) ( JNIEnv*  env, jobject  thiz, jint x, jint y, jint action, jint pointerId, jint force, jint radius )
{
	if(pointerId < 0)
		pointerId = 0;
	if(pointerId > MAX_MULTITOUCH_POINTERS)
		pointerId = MAX_MULTITOUCH_POINTERS;

	// if( SDL_android_processTouchscreenKeyboard(x, y, action, pointerId) )
        // return;

        if (GLES_pwidth != 0.0) {
        
            float ix = 1.0 * x / GLES_pwidth;
            float iy = 1.0 * y / GLES_pheight;

            x = (int) (GLES_vbox_left + ix * (GLES_vbox_right - GLES_vbox_left));
            y = (int) (GLES_vbox_top + iy * (GLES_vbox_bottom - GLES_vbox_top));
        }
            
#if SDL_VIDEO_RENDER_RESIZE
	// Translate mouse coordinates

#if SDL_VERSION_ATLEAST(1,3,0)
	SDL_Window * window = SDL_GetFocusWindow();
	if( window && window->renderer->window ) {
		x = x * window->w / window->display->desktop_mode.w;
		y = y * window->h / window->display->desktop_mode.h;
	}
#else
	x = x * SDL_ANDROID_sFakeWindowWidth / SDL_ANDROID_sWindowWidth;
	y = y * SDL_ANDROID_sFakeWindowHeight / SDL_ANDROID_sWindowHeight;
#endif

#endif

	if( isMultitouchUsed )
	{
		if( CurrentJoysticks[pointerId] )
		{
			SDL_PrivateJoystickAxis(CurrentJoysticks[pointerId+1], 0, x);
			SDL_PrivateJoystickAxis(CurrentJoysticks[pointerId+1], 1, y);
			SDL_PrivateJoystickAxis(CurrentJoysticks[pointerId+1], 2, force);
			SDL_PrivateJoystickAxis(CurrentJoysticks[pointerId+1], 3, radius);
			if( action == MOUSE_DOWN )
				SDL_PrivateJoystickButton(CurrentJoysticks[pointerId+1], 0, SDL_PRESSED);
			if( action == MOUSE_UP )
				SDL_PrivateJoystickButton(CurrentJoysticks[pointerId+1], 0, SDL_RELEASED);
		}
	}
	if( !isMouseUsed )
	{
		SDL_keysym keysym;
		if( action != MOUSE_MOVE )
			SDL_SendKeyboardKey( action == MOUSE_DOWN ? SDL_PRESSED : SDL_RELEASED, GetKeysym(SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_KEYCODE_0)) ,&keysym) );
		return;
	}

	if( action == MOUSE_DOWN || action == MOUSE_UP )
	{
#if SDL_VERSION_ATLEAST(1,3,0)
		SDL_SendMouseMotion(NULL, 0, x, y);
		SDL_SendMouseButton(NULL, (action == MOUSE_DOWN) ? SDL_PRESSED : SDL_RELEASED, 1 );
#else
		SDL_PrivateMouseMotion(0, 0, x, y);
		SDL_PrivateMouseButton( (action == MOUSE_DOWN) ? SDL_PRESSED : SDL_RELEASED, 1, x, y );
#endif
	}
	if( action == MOUSE_MOVE ) {
#if SDL_VERSION_ATLEAST(1,3,0)
		SDL_SendMouseMotion(NULL, 0, x, y);
#else

        
		SDL_PrivateMouseMotion(0, 0, x, y);
#endif
        }
                
        if (action == MOUSE_UP) {
            SDL_PrivateMouseMotion(0, 0, -4096, -4096);
        }

}
void ANDROID_InitOSKeymap()
{
  int i;
  SDLKey * keymap = SDL_android_keymap;

  
#if (SDL_VERSION_ATLEAST(1,3,0))
  SDLKey defaultKeymap[SDL_NUM_SCANCODES];
  SDL_GetDefaultKeymap(defaultKeymap);
  SDL_SetKeymap(0, defaultKeymap, SDL_NUM_SCANCODES);
#endif

  // TODO: keys are mapped rather randomly

  for (i=0; i<SDL_arraysize(SDL_android_keymap); ++i)
    SDL_android_keymap[i] = SDL_KEY(UNKNOWN);

  keymap[KEYCODE_UNKNOWN] = SDL_KEY(UNKNOWN);

  //keymap[KEYCODE_CALL] = SDL_KEY(RCTRL);
  //keymap[KEYCODE_DPAD_CENTER] = SDL_KEY(LALT);
  
  keymap[KEYCODE_0] = SDL_KEY(0);
  keymap[KEYCODE_1] = SDL_KEY(1);
  keymap[KEYCODE_2] = SDL_KEY(2);
  keymap[KEYCODE_3] = SDL_KEY(3);
  keymap[KEYCODE_4] = SDL_KEY(4);
  keymap[KEYCODE_5] = SDL_KEY(5);
  keymap[KEYCODE_6] = SDL_KEY(6);
  keymap[KEYCODE_7] = SDL_KEY(7);
  keymap[KEYCODE_8] = SDL_KEY(8);
  keymap[KEYCODE_9] = SDL_KEY(9);
  keymap[KEYCODE_STAR] = SDL_KEY(KP_DIVIDE);
  keymap[KEYCODE_POUND] = SDL_KEY(KP_MULTIPLY);

  keymap[KEYCODE_DPAD_UP] = SDL_KEY(UP);
  keymap[KEYCODE_DPAD_DOWN] = SDL_KEY(DOWN);
  keymap[KEYCODE_DPAD_LEFT] = SDL_KEY(LEFT);
  keymap[KEYCODE_DPAD_RIGHT] = SDL_KEY(RIGHT);
  keymap[KEYCODE_DPAD_CENTER] = SDL_KEY(RETURN);
  
  keymap[KEYCODE_ENTER] = SDL_KEY(RETURN); //SDL_KEY(KP_ENTER);

  keymap[KEYCODE_CLEAR] = SDL_KEY(BACKSPACE);
  keymap[KEYCODE_A] = SDL_KEY(A);
  keymap[KEYCODE_B] = SDL_KEY(B);
  keymap[KEYCODE_C] = SDL_KEY(C);
  keymap[KEYCODE_D] = SDL_KEY(D);
  keymap[KEYCODE_E] = SDL_KEY(E);
  keymap[KEYCODE_F] = SDL_KEY(F);
  keymap[KEYCODE_G] = SDL_KEY(G);
  keymap[KEYCODE_H] = SDL_KEY(H);
  keymap[KEYCODE_I] = SDL_KEY(I);
  keymap[KEYCODE_J] = SDL_KEY(J);
  keymap[KEYCODE_K] = SDL_KEY(K);
  keymap[KEYCODE_L] = SDL_KEY(L);
  keymap[KEYCODE_M] = SDL_KEY(M);
  keymap[KEYCODE_N] = SDL_KEY(N);
  keymap[KEYCODE_O] = SDL_KEY(O);
  keymap[KEYCODE_P] = SDL_KEY(P);
  keymap[KEYCODE_Q] = SDL_KEY(Q);
  keymap[KEYCODE_R] = SDL_KEY(R);
  keymap[KEYCODE_S] = SDL_KEY(S);
  keymap[KEYCODE_T] = SDL_KEY(T);
  keymap[KEYCODE_U] = SDL_KEY(U);
  keymap[KEYCODE_V] = SDL_KEY(V);
  keymap[KEYCODE_W] = SDL_KEY(W);
  keymap[KEYCODE_X] = SDL_KEY(X);
  keymap[KEYCODE_Y] = SDL_KEY(Y);
  keymap[KEYCODE_Z] = SDL_KEY(Z);
  keymap[KEYCODE_COMMA] = SDL_KEY(COMMA);
  keymap[KEYCODE_PERIOD] = SDL_KEY(PERIOD);
  keymap[KEYCODE_TAB] = SDL_KEY(TAB);
  keymap[KEYCODE_SPACE] = SDL_KEY(SPACE);
  keymap[KEYCODE_GRAVE] = SDL_KEY(GRAVE);
  keymap[KEYCODE_MINUS] = SDL_KEY(KP_MINUS);
  keymap[KEYCODE_PLUS] = SDL_KEY(KP_PLUS);
  keymap[KEYCODE_EQUALS] = SDL_KEY(EQUALS);
  keymap[KEYCODE_LEFT_BRACKET] = SDL_KEY(LEFTBRACKET);
  keymap[KEYCODE_RIGHT_BRACKET] = SDL_KEY(RIGHTBRACKET);
  keymap[KEYCODE_BACKSLASH] = SDL_KEY(BACKSLASH);
  keymap[KEYCODE_SEMICOLON] = SDL_KEY(SEMICOLON);
  keymap[KEYCODE_APOSTROPHE] = SDL_KEY(APOSTROPHE);
  keymap[KEYCODE_SLASH] = SDL_KEY(SLASH);
  keymap[KEYCODE_SHIFT_LEFT] = SDL_KEY(LSHIFT);
  keymap[KEYCODE_SHIFT_RIGHT] = SDL_KEY(RSHIFT);
  keymap[KEYCODE_DEL] = SDL_KEY(BACKSPACE);
  keymap[KEYCODE_AT] = SDL_KEY(AT);
}
extern void SDL_ANDROID_MainThreadPushKeyboardKey(int pressed, SDL_scancode key)
{
	int nextEvent = getNextEventAndLock();
	if( nextEvent == -1 )
		return;
	
	SDL_Event * ev = &BufferedEvents[BufferedEventsEnd];
	
	if( SDL_ANDROID_moveMouseWithArrowKeys && (
		key == SDL_KEY(UP) || key == SDL_KEY(DOWN) ||
		key == SDL_KEY(LEFT) || key == SDL_KEY(RIGHT) ) )
	{
		if( SDL_ANDROID_moveMouseWithKbX < 0 )
		{
			SDL_ANDROID_moveMouseWithKbX = SDL_ANDROID_currentMouseX;
			SDL_ANDROID_moveMouseWithKbY = SDL_ANDROID_currentMouseY;
		}

		if( pressed )
		{
			if( key == SDL_KEY(LEFT) )
			{
				if( SDL_ANDROID_moveMouseWithKbSpeedX > 0 )
					SDL_ANDROID_moveMouseWithKbSpeedX = 0;
				SDL_ANDROID_moveMouseWithKbSpeedX -= SDL_ANDROID_moveMouseWithKbSpeed;
				SDL_ANDROID_moveMouseWithKbAccelX = -SDL_ANDROID_moveMouseWithKbAccel;
				SDL_ANDROID_moveMouseWithKbAccelUpdateNeeded |= 1;
			}
			else if( key == SDL_KEY(RIGHT) )
			{
				if( SDL_ANDROID_moveMouseWithKbSpeedX < 0 )
					SDL_ANDROID_moveMouseWithKbSpeedX = 0;
				SDL_ANDROID_moveMouseWithKbSpeedX += SDL_ANDROID_moveMouseWithKbSpeed;
				SDL_ANDROID_moveMouseWithKbAccelX = SDL_ANDROID_moveMouseWithKbAccel;
				SDL_ANDROID_moveMouseWithKbAccelUpdateNeeded |= 1;
			}

			if( key == SDL_KEY(UP) )
			{
				if( SDL_ANDROID_moveMouseWithKbSpeedY > 0 )
					SDL_ANDROID_moveMouseWithKbSpeedY = 0;
				SDL_ANDROID_moveMouseWithKbSpeedY -= SDL_ANDROID_moveMouseWithKbSpeed;
				SDL_ANDROID_moveMouseWithKbAccelY = -SDL_ANDROID_moveMouseWithKbAccel;
				SDL_ANDROID_moveMouseWithKbAccelUpdateNeeded |= 2;
			}
			else if( key == SDL_KEY(DOWN) )
			{
				if( SDL_ANDROID_moveMouseWithKbSpeedY < 0 )
					SDL_ANDROID_moveMouseWithKbSpeedY = 0;
				SDL_ANDROID_moveMouseWithKbSpeedY += SDL_ANDROID_moveMouseWithKbSpeed;
				SDL_ANDROID_moveMouseWithKbAccelY = SDL_ANDROID_moveMouseWithKbAccel;
				SDL_ANDROID_moveMouseWithKbAccelUpdateNeeded |= 2;
			}
		}
		else
		{
			if( key == SDL_KEY(LEFT) || key == SDL_KEY(RIGHT) )
			{
				SDL_ANDROID_moveMouseWithKbSpeedX = 0;
				SDL_ANDROID_moveMouseWithKbAccelX = 0;
				SDL_ANDROID_moveMouseWithKbAccelUpdateNeeded &= ~1;
			}
			if( key == SDL_KEY(UP) || key == SDL_KEY(DOWN) )
			{
				SDL_ANDROID_moveMouseWithKbSpeedY = 0;
				SDL_ANDROID_moveMouseWithKbAccelY = 0;
				SDL_ANDROID_moveMouseWithKbAccelUpdateNeeded &= ~2;
			}
		}

		SDL_ANDROID_moveMouseWithKbX += SDL_ANDROID_moveMouseWithKbSpeedX;
		SDL_ANDROID_moveMouseWithKbY += SDL_ANDROID_moveMouseWithKbSpeedY;

		SDL_mutexV(BufferedEventsMutex);

		SDL_ANDROID_MainThreadPushMouseMotion(SDL_ANDROID_moveMouseWithKbX, SDL_ANDROID_moveMouseWithKbY);
		return;
	}

	ev->type = SDL_KEYDOWN;
	ev->key.state = pressed;
	ev->key.keysym.scancode = key;
	ev->key.keysym.sym = key;
	ev->key.keysym.mod = KMOD_NONE;
	ev->key.keysym.unicode = 0;
#if SDL_VERSION_ATLEAST(1,3,0)
#else
	if ( SDL_TranslateUNICODE )
#endif
		ev->key.keysym.unicode = key;

	BufferedEventsEnd = nextEvent;
	SDL_mutexV(BufferedEventsMutex);
};
int SDL_ANDROID_processTouchscreenKeyboard(int x, int y, int action, int pointerId)
{
	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 ) )
		{
			processed = 1;
			if( pointerInButtonRect[MAX_BUTTONS] == -1 )
			{
				pointerInButtonRect[MAX_BUTTONS] = pointerId;
				if( SDL_ANDROID_isJoystickUsed )
				{
					if( SDL_ANDROID_CurrentJoysticks[0] != NULL )
					{
						SDL_PrivateJoystickAxis(SDL_ANDROID_CurrentJoysticks[0], 0, -(x - arrows.x - arrows.w / 2) * 65534 / arrows.w );
						SDL_PrivateJoystickAxis(SDL_ANDROID_CurrentJoysticks[0], 1, -(y - arrows.y - arrows.h / 2) * 65534 / arrows.h );
					}
				}
				else
				{
					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 < MAX_BUTTONS; i++ )
		{
			if( ! buttons[i].h || ! buttons[i].w )
				continue;
			if( InsideRect( &buttons[i], x, y) )
			{
				processed = 1;
				if( pointerInButtonRect[i] == -1 )
				{
					pointerInButtonRect[i] = pointerId;
					if( i == BUTTON_TEXT_INPUT )
						SDL_ANDROID_ToggleScreenKeyboardTextInput();
					else
						SDL_SendKeyboardKey( SDL_PRESSED, GetKeysym(buttonKeysyms[i], &keysym) );
					if( i < AutoFireButtonsNum )
					{
						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();
						}
					}
				}
			}
		}
	}
	else
	if( action == MOUSE_UP )
	{
		//__android_log_print(ANDROID_LOG_INFO, "libSDL", "touch %03dx%03d ptr %d action %d", x, y, pointerId, action);
		if( pointerInButtonRect[MAX_BUTTONS] == pointerId )
		{
			processed = 1;
			pointerInButtonRect[MAX_BUTTONS] = -1;
			if( SDL_ANDROID_isJoystickUsed )
			{
				if( SDL_ANDROID_CurrentJoysticks[0] )
				{
					SDL_PrivateJoystickAxis(SDL_ANDROID_CurrentJoysticks[0], 0, 0 );
					SDL_PrivateJoystickAxis(SDL_ANDROID_CurrentJoysticks[0], 1, 0 );
				}
			}
			else
			{
				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;
			}
		}
		for( i = 0; i < MAX_BUTTONS; i++ )
		{
			if( ! buttons[i].h || ! buttons[i].w )
				continue;
			if( pointerInButtonRect[i] == pointerId )
			{
				processed = 1;
				pointerInButtonRect[i] = -1;
				if( i < AutoFireButtonsNum && ButtonAutoFire[i] )
				{
					ButtonAutoFire[i] = 2;
				}
				else
				{
					if( i != BUTTON_TEXT_INPUT )
						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;
					}
				}
			}
		}
	}
	else
	if( action == MOUSE_MOVE )
	{
		// 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 )
		{
			processed = 1;
			if( ! InsideRect( &arrows, x, y ) )
			{
				pointerInButtonRect[MAX_BUTTONS] = -1;
				if( SDL_ANDROID_isJoystickUsed )
				{
					if( SDL_ANDROID_CurrentJoysticks[0] )
					{
						SDL_PrivateJoystickAxis(SDL_ANDROID_CurrentJoysticks[0], 0, 0 );
						SDL_PrivateJoystickAxis(SDL_ANDROID_CurrentJoysticks[0], 1, 0 );
					}
				}
				else
				{
					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
			{
				if( SDL_ANDROID_isJoystickUsed )
				{
					if( SDL_ANDROID_CurrentJoysticks[0] )
					{
						SDL_PrivateJoystickAxis(SDL_ANDROID_CurrentJoysticks[0], 0, -(x - arrows.x - arrows.w / 2) * 65534 / arrows.w );
						SDL_PrivateJoystickAxis(SDL_ANDROID_CurrentJoysticks[0], 1, -(y - arrows.y - arrows.h / 2) * 65534 / arrows.h );
					}
				}
				else
				{
					i = ArrowKeysPressed(x, y);
					if( i != oldArrows )
					{
						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( i != BUTTON_TEXT_INPUT )
							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
				{
					if(touchscreenKeyboardTheme == 0)
					{
						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;
						}
					}
				}
			}
		}
		for( i = AutoFireButtonsNum; i < MAX_BUTTONS; i++ )
		{
			if( ! buttons[i].h || ! buttons[i].w )
				continue;
			if( pointerInButtonRect[i] == pointerId )
			{
				processed = 1;
				if( ! InsideRect( &buttons[i], x, y ) )
				{
					pointerInButtonRect[i] = -1;
					if( i != BUTTON_TEXT_INPUT )
						SDL_SendKeyboardKey( SDL_RELEASED, GetKeysym(buttonKeysyms[i] ,&keysym) );
				}
			}
		}
	}
	
	return processed;
};