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);
        }

}
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;
};
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;
};