Browse Source

Android: Mouse Implementation

Implement mouse
Move touch to inputManager
Change to use android/input.h
thebestnom 4 years ago
parent
commit
191c84f952

+ 3 - 120
platform/android/android_keys_utils.h

@@ -31,128 +31,9 @@
 #ifndef ANDROID_KEYS_UTILS_H
 #define ANDROID_KEYS_UTILS_H
 
+#include <android/input.h>
 #include <core/os/keyboard.h>
 
-/*
- * Android Key codes.
- */
-enum {
-	AKEYCODE_UNKNOWN = 0,
-	AKEYCODE_SOFT_LEFT = 1,
-	AKEYCODE_SOFT_RIGHT = 2,
-	AKEYCODE_HOME = 3,
-	AKEYCODE_BACK = 4,
-	AKEYCODE_CALL = 5,
-	AKEYCODE_ENDCALL = 6,
-	AKEYCODE_0 = 7,
-	AKEYCODE_1 = 8,
-	AKEYCODE_2 = 9,
-	AKEYCODE_3 = 10,
-	AKEYCODE_4 = 11,
-	AKEYCODE_5 = 12,
-	AKEYCODE_6 = 13,
-	AKEYCODE_7 = 14,
-	AKEYCODE_8 = 15,
-	AKEYCODE_9 = 16,
-	AKEYCODE_STAR = 17,
-	AKEYCODE_POUND = 18,
-	AKEYCODE_DPAD_UP = 19,
-	AKEYCODE_DPAD_DOWN = 20,
-	AKEYCODE_DPAD_LEFT = 21,
-	AKEYCODE_DPAD_RIGHT = 22,
-	AKEYCODE_DPAD_CENTER = 23,
-	AKEYCODE_VOLUME_UP = 24,
-	AKEYCODE_VOLUME_DOWN = 25,
-	AKEYCODE_POWER = 26,
-	AKEYCODE_CAMERA = 27,
-	AKEYCODE_CLEAR = 28,
-	AKEYCODE_A = 29,
-	AKEYCODE_B = 30,
-	AKEYCODE_C = 31,
-	AKEYCODE_D = 32,
-	AKEYCODE_E = 33,
-	AKEYCODE_F = 34,
-	AKEYCODE_G = 35,
-	AKEYCODE_H = 36,
-	AKEYCODE_I = 37,
-	AKEYCODE_J = 38,
-	AKEYCODE_K = 39,
-	AKEYCODE_L = 40,
-	AKEYCODE_M = 41,
-	AKEYCODE_N = 42,
-	AKEYCODE_O = 43,
-	AKEYCODE_P = 44,
-	AKEYCODE_Q = 45,
-	AKEYCODE_R = 46,
-	AKEYCODE_S = 47,
-	AKEYCODE_T = 48,
-	AKEYCODE_U = 49,
-	AKEYCODE_V = 50,
-	AKEYCODE_W = 51,
-	AKEYCODE_X = 52,
-	AKEYCODE_Y = 53,
-	AKEYCODE_Z = 54,
-	AKEYCODE_COMMA = 55,
-	AKEYCODE_PERIOD = 56,
-	AKEYCODE_ALT_LEFT = 57,
-	AKEYCODE_ALT_RIGHT = 58,
-	AKEYCODE_SHIFT_LEFT = 59,
-	AKEYCODE_SHIFT_RIGHT = 60,
-	AKEYCODE_TAB = 61,
-	AKEYCODE_SPACE = 62,
-	AKEYCODE_SYM = 63,
-	AKEYCODE_EXPLORER = 64,
-	AKEYCODE_ENVELOPE = 65,
-	AKEYCODE_ENTER = 66,
-	AKEYCODE_DEL = 67,
-	AKEYCODE_GRAVE = 68,
-	AKEYCODE_MINUS = 69,
-	AKEYCODE_EQUALS = 70,
-	AKEYCODE_LEFT_BRACKET = 71,
-	AKEYCODE_RIGHT_BRACKET = 72,
-	AKEYCODE_BACKSLASH = 73,
-	AKEYCODE_SEMICOLON = 74,
-	AKEYCODE_APOSTROPHE = 75,
-	AKEYCODE_SLASH = 76,
-	AKEYCODE_AT = 77,
-	AKEYCODE_NUM = 78,
-	AKEYCODE_HEADSETHOOK = 79,
-	AKEYCODE_FOCUS = 80, // *Camera* focus
-	AKEYCODE_PLUS = 81,
-	AKEYCODE_MENU = 82,
-	AKEYCODE_NOTIFICATION = 83,
-	AKEYCODE_SEARCH = 84,
-	AKEYCODE_MEDIA_PLAY_PAUSE = 85,
-	AKEYCODE_MEDIA_STOP = 86,
-	AKEYCODE_MEDIA_NEXT = 87,
-	AKEYCODE_MEDIA_PREVIOUS = 88,
-	AKEYCODE_MEDIA_REWIND = 89,
-	AKEYCODE_MEDIA_FAST_FORWARD = 90,
-	AKEYCODE_MUTE = 91,
-	AKEYCODE_PAGE_UP = 92,
-	AKEYCODE_PAGE_DOWN = 93,
-	AKEYCODE_PICTSYMBOLS = 94,
-	AKEYCODE_SWITCH_CHARSET = 95,
-	AKEYCODE_BUTTON_A = 96,
-	AKEYCODE_BUTTON_B = 97,
-	AKEYCODE_BUTTON_C = 98,
-	AKEYCODE_BUTTON_X = 99,
-	AKEYCODE_BUTTON_Y = 100,
-	AKEYCODE_BUTTON_Z = 101,
-	AKEYCODE_BUTTON_L1 = 102,
-	AKEYCODE_BUTTON_R1 = 103,
-	AKEYCODE_BUTTON_L2 = 104,
-	AKEYCODE_BUTTON_R2 = 105,
-	AKEYCODE_BUTTON_THUMBL = 106,
-	AKEYCODE_BUTTON_THUMBR = 107,
-	AKEYCODE_BUTTON_START = 108,
-	AKEYCODE_BUTTON_SELECT = 109,
-	AKEYCODE_BUTTON_MODE = 110,
-
-	// NOTE: If you add a new keycode here you must also add it to several other files.
-	//       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
-};
-
 struct _WinTranslatePair {
 
 	unsigned int keysym;
@@ -247,6 +128,8 @@ static _WinTranslatePair _ak_to_keycode[] = {
 	{ KEY_BACKSLASH, AKEYCODE_BACKSLASH },
 	{ KEY_BRACKETLEFT, AKEYCODE_LEFT_BRACKET },
 	{ KEY_BRACKETRIGHT, AKEYCODE_RIGHT_BRACKET },
+	{ KEY_CONTROL, AKEYCODE_CTRL_LEFT },
+	{ KEY_CONTROL, AKEYCODE_CTRL_RIGHT },
 	{ KEY_UNKNOWN, 0 }
 };
 /*

+ 1 - 59
platform/android/java/lib/src/org/godotengine/godot/Godot.java

@@ -72,6 +72,7 @@ import android.os.VibrationEffect;
 import android.os.Vibrator;
 import android.provider.Settings.Secure;
 import android.view.Display;
+import android.view.InputDevice;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -989,65 +990,6 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
 		}
 	}
 
-	public boolean gotTouchEvent(final MotionEvent event) {
-
-		final int evcount = event.getPointerCount();
-		if (evcount == 0)
-			return true;
-
-		if (mView != null) {
-			final int[] arr = new int[event.getPointerCount() * 3];
-
-			for (int i = 0; i < event.getPointerCount(); i++) {
-
-				arr[i * 3 + 0] = (int)event.getPointerId(i);
-				arr[i * 3 + 1] = (int)event.getX(i);
-				arr[i * 3 + 2] = (int)event.getY(i);
-			}
-			final int pointer_idx = event.getPointerId(event.getActionIndex());
-
-			//System.out.printf("gaction: %d\n",event.getAction());
-			final int action = event.getAction() & MotionEvent.ACTION_MASK;
-			mView.queueEvent(new Runnable() {
-				@Override
-				public void run() {
-					switch (action) {
-						case MotionEvent.ACTION_DOWN: {
-							GodotLib.touch(0, 0, evcount, arr);
-							//System.out.printf("action down at: %f,%f\n", event.getX(),event.getY());
-						} break;
-						case MotionEvent.ACTION_MOVE: {
-							GodotLib.touch(1, 0, evcount, arr);
-							/*
-							for(int i=0;i<event.getPointerCount();i++) {
-								System.out.printf("%d - moved to: %f,%f\n",i, event.getX(i),event.getY(i));
-							}
-							*/
-						} break;
-						case MotionEvent.ACTION_POINTER_UP: {
-							GodotLib.touch(4, pointer_idx, evcount, arr);
-							//System.out.printf("%d - s.up at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
-						} break;
-						case MotionEvent.ACTION_POINTER_DOWN: {
-							GodotLib.touch(3, pointer_idx, evcount, arr);
-							//System.out.printf("%d - s.down at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
-						} break;
-						case MotionEvent.ACTION_CANCEL:
-						case MotionEvent.ACTION_UP: {
-							GodotLib.touch(2, 0, evcount, arr);
-							/*
-							for(int i=0;i<event.getPointerCount();i++) {
-								System.out.printf("%d - up! %f,%f\n",i, event.getX(i),event.getY(i));
-							}
-							*/
-						} break;
-					}
-				}
-			});
-		}
-		return true;
-	}
-
 	public boolean onKeyMultiple(final int inKeyCode, int repeatCount, KeyEvent event) {
 		String s = event.getCharacters();
 		if (s == null || s.length() == 0)

+ 5 - 3
platform/android/java/lib/src/org/godotengine/godot/GodotLib.java

@@ -93,17 +93,19 @@ public class GodotLib {
 	/**
 	 * Forward touch events from the main thread to the GL thread.
 	 */
-	public static native void touch(int what, int pointer, int howmany, int[] arr);
+	public static native void touch(int inputDevice, int event, int pointer, int pointerCount, float[] positions);
+	public static native void touch(int inputDevice, int event, int pointer, int pointerCount, float[] positions, int buttonsMask);
+	public static native void touch(int inputDevice, int event, int pointer, int pointerCount, float[] positions, int buttonsMask, float verticalFactor, float horizontalFactor);
 
 	/**
 	 * Forward hover events from the main thread to the GL thread.
 	 */
-	public static native void hover(int type, int x, int y);
+	public static native void hover(int type, float x, float y);
 
 	/**
 	 * Forward double_tap events from the main thread to the GL thread.
 	 */
-	public static native void doubletap(int x, int y);
+	public static native void doubleTap(int buttonMask, int x, int y);
 
 	/**
 	 * Forward scroll events from the main thread to the GL thread.

+ 1 - 1
platform/android/java/lib/src/org/godotengine/godot/GodotView.java

@@ -99,7 +99,7 @@ public class GodotView extends GLSurfaceView {
 	public boolean onTouchEvent(MotionEvent event) {
 		super.onTouchEvent(event);
 		this.detector.onTouchEvent(event);
-		return godot.gotTouchEvent(event);
+		return inputHandler.onTouchEvent(event);
 	}
 
 	@Override

+ 2 - 2
platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java

@@ -33,7 +33,6 @@ package org.godotengine.godot.input;
 import org.godotengine.godot.GodotLib;
 import org.godotengine.godot.GodotView;
 
-import android.util.Log;
 import android.view.GestureDetector;
 import android.view.MotionEvent;
 
@@ -76,10 +75,11 @@ public class GodotGestureHandler extends GestureDetector.SimpleOnGestureListener
 		//Log.i("GodotGesture", "onDoubleTap");
 		final int x = Math.round(event.getX());
 		final int y = Math.round(event.getY());
+		final int buttonMask = event.getButtonState();
 		queueEvent(new Runnable() {
 			@Override
 			public void run() {
-				GodotLib.doubletap(x, y);
+				GodotLib.doubleTap(buttonMask, x, y);
 			}
 		});
 		return true;

+ 103 - 2
platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java

@@ -36,6 +36,7 @@ import org.godotengine.godot.GodotLib;
 import org.godotengine.godot.GodotView;
 import org.godotengine.godot.input.InputManagerCompat.InputDeviceListener;
 
+import android.os.Build;
 import android.util.Log;
 import android.view.InputDevice;
 import android.view.InputDevice.MotionRange;
@@ -157,6 +158,53 @@ public class GodotInputHandler implements InputDeviceListener {
 		return true;
 	}
 
+	public boolean onTouchEvent(final MotionEvent event) {
+		// Mouse drag (mouse pressed and move) doesn't fire onGenericMotionEvent so this is needed
+		if (event.isFromSource(InputDevice.SOURCE_MOUSE)) {
+			if (event.getAction() != MotionEvent.ACTION_MOVE) {
+				// we return true because every time a mouse event is fired, the event is already handled
+				// in onGenericMotionEvent, so by touch event we can say that the event is also handled
+				return true;
+			}
+			return handleMouseEvent(event);
+		}
+
+		final int evcount = event.getPointerCount();
+		if (evcount == 0)
+			return true;
+
+		if (godotView != null) {
+			final float[] arr = new float[event.getPointerCount() * 3]; // pointerId1, x1, y1, pointerId2, etc...
+
+			for (int i = 0; i < event.getPointerCount(); i++) {
+				arr[i * 3 + 0] = event.getPointerId(i);
+				arr[i * 3 + 1] = event.getX(i);
+				arr[i * 3 + 2] = event.getY(i);
+			}
+			final int action = event.getActionMasked();
+
+			godotView.queueEvent(new Runnable() {
+				@Override
+				public void run() {
+					switch (action) {
+						case MotionEvent.ACTION_DOWN:
+						case MotionEvent.ACTION_CANCEL:
+						case MotionEvent.ACTION_UP:
+						case MotionEvent.ACTION_MOVE: {
+							GodotLib.touch(event.getSource(), action, 0, evcount, arr);
+						} break;
+						case MotionEvent.ACTION_POINTER_UP:
+						case MotionEvent.ACTION_POINTER_DOWN: {
+							int pointer_idx = event.getPointerId(event.getActionIndex());
+							GodotLib.touch(event.getSource(), action, pointer_idx, evcount, arr);
+						} break;
+					}
+				}
+			});
+		}
+		return true;
+	}
+
 	public boolean onGenericMotionEvent(MotionEvent event) {
 		if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK && event.getAction() == MotionEvent.ACTION_MOVE) {
 
@@ -191,8 +239,8 @@ public class GodotInputHandler implements InputDeviceListener {
 				return true;
 			}
 		} else if ((event.getSource() & InputDevice.SOURCE_STYLUS) == InputDevice.SOURCE_STYLUS) {
-			final int x = Math.round(event.getX());
-			final int y = Math.round(event.getY());
+			final float x = event.getX();
+			final float y = event.getY();
 			final int type = event.getAction();
 			queueEvent(new Runnable() {
 				@Override
@@ -201,6 +249,10 @@ public class GodotInputHandler implements InputDeviceListener {
 				}
 			});
 			return true;
+		} else if ((event.getSource() & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) {
+			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+				return handleMouseEvent(event);
+			}
 		}
 
 		return false;
@@ -368,4 +420,53 @@ public class GodotInputHandler implements InputDeviceListener {
 
 		return -1;
 	}
+
+	private boolean handleMouseEvent(final MotionEvent event) {
+		switch (event.getActionMasked()) {
+			case MotionEvent.ACTION_HOVER_ENTER:
+			case MotionEvent.ACTION_HOVER_MOVE:
+			case MotionEvent.ACTION_HOVER_EXIT: {
+				final float x = event.getX();
+				final float y = event.getY();
+				final int type = event.getAction();
+				queueEvent(new Runnable() {
+					@Override
+					public void run() {
+						GodotLib.hover(type, x, y);
+					}
+				});
+				return true;
+			}
+			case MotionEvent.ACTION_BUTTON_PRESS:
+			case MotionEvent.ACTION_BUTTON_RELEASE:
+			case MotionEvent.ACTION_MOVE: {
+				final float x = event.getX();
+				final float y = event.getY();
+				final int buttonsMask = event.getButtonState();
+				final int action = event.getAction();
+				queueEvent(new Runnable() {
+					@Override
+					public void run() {
+						GodotLib.touch(event.getSource(), action, 0, 1, new float[] { 0, x, y }, buttonsMask);
+					}
+				});
+				return true;
+			}
+			case MotionEvent.ACTION_SCROLL: {
+				final float x = event.getX();
+				final float y = event.getY();
+				final int buttonsMask = event.getButtonState();
+				final int action = event.getAction();
+				final float verticalFactor = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
+				final float horizontalFactor = event.getAxisValue(MotionEvent.AXIS_HSCROLL);
+				queueEvent(new Runnable() {
+					@Override
+					public void run() {
+						GodotLib.touch(event.getSource(), action, 0, 1, new float[] { 0, x, y }, buttonsMask, verticalFactor, horizontalFactor);
+					}
+				});
+			}
+		}
+		return false;
+	}
 }

+ 26 - 15
platform/android/java_godot_lib_jni.cpp

@@ -49,6 +49,8 @@
 #include "os_android.h"
 #include "string_android.h"
 #include "thread_jandroid.h"
+
+#include <android/input.h>
 #include <unistd.h>
 
 static JavaClassWrapper *java_class_wrapper = NULL;
@@ -272,42 +274,51 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jcl
 	}
 }
 
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch(JNIEnv *env, jclass clazz, jint ev, jint pointer, jint count, jintArray positions) {
-
+void touch_preprocessing(JNIEnv *env, jclass clazz, jint input_device, jint ev, jint pointer, jint pointer_count, jfloatArray positions, jint buttons_mask, jfloat vertical_factor, jfloat horizontal_factor) {
 	if (step == 0)
 		return;
 
 	Vector<OS_Android::TouchPos> points;
-	for (int i = 0; i < count; i++) {
-
-		jint p[3];
-		env->GetIntArrayRegion(positions, i * 3, 3, p);
+	for (int i = 0; i < pointer_count; i++) {
+		jfloat p[3];
+		env->GetFloatArrayRegion(positions, i * 3, 3, p);
 		OS_Android::TouchPos tp;
 		tp.pos = Point2(p[1], p[2]);
-		tp.id = p[0];
+		tp.id = (int)p[0];
 		points.push_back(tp);
 	}
 
-	os_android->process_touch(ev, pointer, points);
+	if ((input_device & AINPUT_SOURCE_MOUSE) == AINPUT_SOURCE_MOUSE) {
+		os_android->process_mouse_event(ev, buttons_mask, points[0].pos, vertical_factor, horizontal_factor);
+	} else {
+		os_android->process_touch(ev, pointer, points);
+	}
+}
 
-	/*
-	if (os_android)
-		os_android->process_touch(ev,pointer,points);
-	*/
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch__IIII_3F(JNIEnv *env, jclass clazz, jint input_device, jint ev, jint pointer, jint pointer_count, jfloatArray position) {
+	touch_preprocessing(env, clazz, input_device, ev, pointer, pointer_count, position);
+}
+
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch__IIII_3FI(JNIEnv *env, jclass clazz, jint input_device, jint ev, jint pointer, jint pointer_count, jfloatArray position, jint buttons_mask) {
+	touch_preprocessing(env, clazz, input_device, ev, pointer, pointer_count, position, buttons_mask);
+}
+
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch__IIII_3FIFF(JNIEnv *env, jclass clazz, jint input_device, jint ev, jint pointer, jint pointer_count, jfloatArray position, jint buttons_mask, jfloat vertical_factor, jfloat horizontal_factor) {
+	touch_preprocessing(env, clazz, input_device, ev, pointer, pointer_count, position, buttons_mask, vertical_factor, horizontal_factor);
 }
 
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hover(JNIEnv *env, jclass clazz, jint p_type, jint p_x, jint p_y) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hover(JNIEnv *env, jclass clazz, jint p_type, jfloat p_x, jfloat p_y) {
 	if (step == 0)
 		return;
 
 	os_android->process_hover(p_type, Point2(p_x, p_y));
 }
 
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_doubletap(JNIEnv *env, jclass clazz, jint p_x, jint p_y) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_doubleTap(JNIEnv *env, jclass clazz, jint p_button_mask, jint p_x, jint p_y) {
 	if (step == 0)
 		return;
 
-	os_android->process_double_tap(Point2(p_x, p_y));
+	os_android->process_double_tap(p_button_mask, Point2(p_x, p_y));
 }
 
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_scroll(JNIEnv *env, jclass clazz, jint p_x, jint p_y) {

+ 6 - 3
platform/android/java_godot_lib_jni.h

@@ -44,9 +44,12 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, j
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jclass clazz, jboolean p_32_bits);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jclass clazz);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, jclass clazz);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch(JNIEnv *env, jclass clazz, jint ev, jint pointer, jint count, jintArray positions);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hover(JNIEnv *env, jclass clazz, jint p_type, jint p_x, jint p_y);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_doubletap(JNIEnv *env, jclass clazz, jint p_x, jint p_y);
+void touch_preprocessing(JNIEnv *env, jclass clazz, jint input_device, jint ev, jint pointer, jint pointer_count, jfloatArray positions, jint buttons_mask = 0, jfloat vertical_factor = 0, jfloat horizontal_factor = 0);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch__IIII_3F(JNIEnv *env, jclass clazz, jint input_device, jint ev, jint pointer, jint pointer_count, jfloatArray positions);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch__IIII_3FI(JNIEnv *env, jclass clazz, jint input_device, jint ev, jint pointer, jint pointer_count, jfloatArray positions, jint buttons_mask);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch__IIII_3FIFF(JNIEnv *env, jclass clazz, jint input_device, jint ev, jint pointer, jint pointer_count, jfloatArray positions, jint buttons_mask, jfloat vertical_factor, jfloat horizontal_factor);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hover(JNIEnv *env, jclass clazz, jint p_type, jfloat p_x, jfloat p_y);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_doubleTap(JNIEnv *env, jclass clazz, jint p_button_mask, jint p_x, jint p_y);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_scroll(JNIEnv *env, jclass clazz, jint p_x, jint p_y);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jclass clazz, jint p_scancode, jint p_unicode_char, jboolean p_pressed);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env, jclass clazz, jint p_device, jint p_button, jboolean p_pressed);

+ 121 - 27
platform/android/os_android.cpp

@@ -45,6 +45,7 @@
 #include "file_access_jandroid.h"
 #include "net_socket_android.h"
 
+#include <android/input.h>
 #include <dlfcn.h>
 
 #include "java_godot_io_wrapper.h"
@@ -251,13 +252,11 @@ bool OS_Android::is_mouse_grab_enabled() const {
 }
 
 Point2 OS_Android::get_mouse_position() const {
-
-	return Point2();
+	return hover_prev_pos;
 }
 
 int OS_Android::get_mouse_button_state() const {
-
-	return 0;
+	return buttons_state;
 }
 
 void OS_Android::set_window_title(const String &p_title) {
@@ -370,15 +369,13 @@ void OS_Android::process_event(Ref<InputEvent> p_event) {
 	input->parse_input_event(p_event);
 }
 
-void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos> &p_points) {
-
-	switch (p_what) {
-		case 0: { //gesture begin
+void OS_Android::process_touch(int p_event, int p_pointer, const Vector<TouchPos> &p_points) {
 
+	switch (p_event) {
+		case AMOTION_EVENT_ACTION_DOWN: { //gesture begin
 			if (touch.size()) {
 				//end all if exist
 				for (int i = 0; i < touch.size(); i++) {
-
 					Ref<InputEventScreenTouch> ev;
 					ev.instance();
 					ev->set_index(touch[i].id);
@@ -396,7 +393,6 @@ void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos>
 
 			//send touch
 			for (int i = 0; i < touch.size(); i++) {
-
 				Ref<InputEventScreenTouch> ev;
 				ev.instance();
 				ev->set_index(touch[i].id);
@@ -406,15 +402,12 @@ void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos>
 			}
 
 		} break;
-		case 1: { //motion
-
+		case AMOTION_EVENT_ACTION_MOVE: { //motion
 			ERR_FAIL_COND(touch.size() != p_points.size());
 
 			for (int i = 0; i < touch.size(); i++) {
-
 				int idx = -1;
 				for (int j = 0; j < p_points.size(); j++) {
-
 					if (touch[i].id == p_points[j].id) {
 						idx = j;
 						break;
@@ -436,12 +429,11 @@ void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos>
 			}
 
 		} break;
-		case 2: { //release
-
+		case AMOTION_EVENT_ACTION_CANCEL:
+		case AMOTION_EVENT_ACTION_UP: { //release
 			if (touch.size()) {
 				//end all if exist
 				for (int i = 0; i < touch.size(); i++) {
-
 					Ref<InputEventScreenTouch> ev;
 					ev.instance();
 					ev->set_index(touch[i].id);
@@ -452,8 +444,7 @@ void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos>
 				touch.clear();
 			}
 		} break;
-		case 3: { // add touch
-
+		case AMOTION_EVENT_ACTION_POINTER_DOWN: { // add touch
 			for (int i = 0; i < p_points.size(); i++) {
 				if (p_points[i].id == p_pointer) {
 					TouchPos tp = p_points[i];
@@ -471,11 +462,9 @@ void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos>
 				}
 			}
 		} break;
-		case 4: { // remove touch
-
+		case AMOTION_EVENT_ACTION_POINTER_UP: { // remove touch
 			for (int i = 0; i < touch.size(); i++) {
 				if (touch[i].id == p_pointer) {
-
 					Ref<InputEventScreenTouch> ev;
 					ev.instance();
 					ev->set_index(touch[i].id);
@@ -494,9 +483,9 @@ void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos>
 void OS_Android::process_hover(int p_type, Point2 p_pos) {
 	// https://developer.android.com/reference/android/view/MotionEvent.html#ACTION_HOVER_ENTER
 	switch (p_type) {
-		case 7: // hover move
-		case 9: // hover enter
-		case 10: { // hover exit
+		case AMOTION_EVENT_ACTION_HOVER_MOVE: // hover move
+		case AMOTION_EVENT_ACTION_HOVER_ENTER: // hover enter
+		case AMOTION_EVENT_ACTION_HOVER_EXIT: { // hover exit
 			Ref<InputEventMouseMotion> ev;
 			ev.instance();
 			ev->set_position(p_pos);
@@ -508,12 +497,78 @@ void OS_Android::process_hover(int p_type, Point2 p_pos) {
 	}
 }
 
-void OS_Android::process_double_tap(Point2 p_pos) {
+void OS_Android::process_mouse_event(int event_action, int event_android_buttons_mask, Point2 event_pos, float event_vertical_factor, float event_horizontal_factor) {
+	int event_buttons_mask = _android_button_mask_to_godot_button_mask(event_android_buttons_mask);
+	switch (event_action) {
+		case AMOTION_EVENT_ACTION_BUTTON_PRESS:
+		case AMOTION_EVENT_ACTION_BUTTON_RELEASE: {
+			Ref<InputEventMouseButton> ev;
+			ev.instance();
+			ev->set_position(event_pos);
+			ev->set_global_position(event_pos);
+			ev->set_pressed(event_action == AMOTION_EVENT_ACTION_BUTTON_PRESS);
+			int changed_button_mask = buttons_state ^ event_buttons_mask;
+
+			buttons_state = event_buttons_mask;
+
+			ev->set_button_index(_button_index_from_mask(changed_button_mask));
+			ev->set_button_mask(event_buttons_mask);
+			input->parse_input_event(ev);
+		} break;
+
+		case AMOTION_EVENT_ACTION_MOVE: {
+			Ref<InputEventMouseMotion> ev;
+			ev.instance();
+			ev->set_position(event_pos);
+			ev->set_global_position(event_pos);
+			ev->set_relative(event_pos - hover_prev_pos);
+			ev->set_button_mask(event_buttons_mask);
+			input->parse_input_event(ev);
+			hover_prev_pos = event_pos;
+		} break;
+		case AMOTION_EVENT_ACTION_SCROLL: {
+			Ref<InputEventMouseButton> ev;
+			ev.instance();
+			ev->set_position(event_pos);
+			ev->set_global_position(event_pos);
+			ev->set_pressed(true);
+			buttons_state = event_buttons_mask;
+			if (event_vertical_factor > 0) {
+				_wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_UP, event_vertical_factor);
+			} else if (event_vertical_factor < 0) {
+				_wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_DOWN, -event_vertical_factor);
+			}
+
+			if (event_horizontal_factor > 0) {
+				_wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_RIGHT, event_horizontal_factor);
+			} else if (event_horizontal_factor < 0) {
+				_wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_LEFT, -event_horizontal_factor);
+			}
+		} break;
+	}
+}
+
+void OS_Android::_wheel_button_click(int event_buttons_mask, const Ref<InputEventMouseButton> &ev, int wheel_button, float factor) {
+	Ref<InputEventMouseButton> evd = ev->duplicate();
+	evd->set_button_index(wheel_button);
+	evd->set_button_mask(event_buttons_mask ^ (1 << (wheel_button - 1)));
+	evd->set_factor(factor);
+	input->parse_input_event(evd);
+	Ref<InputEventMouseButton> evdd = evd->duplicate();
+	evdd->set_pressed(false);
+	evdd->set_button_mask(event_buttons_mask);
+	input->parse_input_event(evdd);
+}
+
+void OS_Android::process_double_tap(int event_android_button_mask, Point2 p_pos) {
+	int event_button_mask = _android_button_mask_to_godot_button_mask(event_android_button_mask);
 	Ref<InputEventMouseButton> ev;
 	ev.instance();
 	ev->set_position(p_pos);
 	ev->set_global_position(p_pos);
-	ev->set_pressed(false);
+	ev->set_pressed(event_button_mask != 0);
+	ev->set_button_index(_button_index_from_mask(event_button_mask));
+	ev->set_button_mask(event_button_mask);
 	ev->set_doubleclick(true);
 	input->parse_input_event(ev);
 }
@@ -527,6 +582,44 @@ void OS_Android::process_scroll(Point2 p_pos) {
 	scroll_prev_pos = p_pos;
 }
 
+int OS_Android::_button_index_from_mask(int button_mask) {
+	switch (button_mask) {
+		case BUTTON_MASK_LEFT:
+			return BUTTON_LEFT;
+		case BUTTON_MASK_RIGHT:
+			return BUTTON_RIGHT;
+		case BUTTON_MASK_MIDDLE:
+			return BUTTON_MIDDLE;
+		case BUTTON_MASK_XBUTTON1:
+			return BUTTON_XBUTTON1;
+		case BUTTON_MASK_XBUTTON2:
+			return BUTTON_XBUTTON2;
+		default:
+			return 0;
+	}
+}
+
+int OS_Android::_android_button_mask_to_godot_button_mask(int android_button_mask) {
+	int godot_button_mask = 0;
+	if (android_button_mask & AMOTION_EVENT_BUTTON_PRIMARY) {
+		godot_button_mask |= BUTTON_MASK_LEFT;
+	}
+	if (android_button_mask & AMOTION_EVENT_BUTTON_SECONDARY) {
+		godot_button_mask |= BUTTON_MASK_RIGHT;
+	}
+	if (android_button_mask & AMOTION_EVENT_BUTTON_TERTIARY) {
+		godot_button_mask |= BUTTON_MASK_MIDDLE;
+	}
+	if (android_button_mask & AMOTION_EVENT_BUTTON_BACK) {
+		godot_button_mask |= BUTTON_MASK_XBUTTON1;
+	}
+	if (android_button_mask & AMOTION_EVENT_BUTTON_SECONDARY) {
+		godot_button_mask |= BUTTON_MASK_XBUTTON2;
+	}
+
+	return godot_button_mask;
+}
+
 void OS_Android::process_accelerometer(const Vector3 &p_accelerometer) {
 
 	input->set_accelerometer(p_accelerometer);
@@ -782,6 +875,7 @@ OS_Android::OS_Android(GodotJavaWrapper *p_godot_java, GodotIOJavaWrapper *p_god
 	default_videomode.height = 600;
 	default_videomode.fullscreen = true;
 	default_videomode.resizable = false;
+	buttons_state = 0;
 
 	main_loop = NULL;
 	gl_extensions = NULL;

+ 11 - 2
platform/android/os_android.h

@@ -97,6 +97,14 @@ private:
 
 	int video_driver_index;
 
+	int buttons_state;
+
+	static int _button_index_from_mask(int button_mask);
+
+	static int _android_button_mask_to_godot_button_mask(int android_button_mask);
+
+	void _wheel_button_click(int event_buttons_mask, const Ref<InputEventMouseButton> &ev, int wheel_button, float factor);
+
 public:
 	// functions used by main to initialize/deinitialize the OS
 	virtual int get_video_driver_count() const;
@@ -187,9 +195,10 @@ public:
 	void process_gravity(const Vector3 &p_gravity);
 	void process_magnetometer(const Vector3 &p_magnetometer);
 	void process_gyroscope(const Vector3 &p_gyroscope);
-	void process_touch(int p_what, int p_pointer, const Vector<TouchPos> &p_points);
+	void process_touch(int p_event, int p_pointer, const Vector<TouchPos> &p_points);
 	void process_hover(int p_type, Point2 p_pos);
-	void process_double_tap(Point2 p_pos);
+	void process_mouse_event(int event_action, int event_android_buttons_mask, Point2 event_pos, float event_vertical_factor = 0, float event_horizontal_factor = 0);
+	void process_double_tap(int event_android_button_mask, Point2 p_pos);
 	void process_scroll(Point2 p_pos);
 	void process_joy_event(JoypadEvent p_event);
 	void process_event(Ref<InputEvent> p_event);