From 21093175646b8d359e8108b93e28898ed9695457 Mon Sep 17 00:00:00 2001 From: Lauri Härsilä Date: Sun, 7 Oct 2012 04:53:52 +0300 Subject: ANDROID: Mouse and stylus support From pull request #285. --- backends/platform/android/android.h | 2 +- backends/platform/android/android.mk | 21 +- backends/platform/android/events.cpp | 78 +++++++- .../android/org/scummvm/scummvm/MouseHelper.java | 214 +++++++++++++++++++++ .../org/scummvm/scummvm/ScummVMActivity.java | 21 +- .../android/org/scummvm/scummvm/ScummVMEvents.java | 51 ++++- 6 files changed, 365 insertions(+), 22 deletions(-) create mode 100644 backends/platform/android/org/scummvm/scummvm/MouseHelper.java (limited to 'backends/platform/android') diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h index 4b13ca4b0f..5f2f40b726 100644 --- a/backends/platform/android/android.h +++ b/backends/platform/android/android.h @@ -234,7 +234,7 @@ private: int _fingersDown; void clipMouse(Common::Point &p); - void scaleMouse(Common::Point &p, int x, int y, bool deductDrawRect = true); + void scaleMouse(Common::Point &p, int x, int y, bool deductDrawRect = true, bool touchpadMode = false); void updateEventScale(); void disableCursorPalette(); diff --git a/backends/platform/android/android.mk b/backends/platform/android/android.mk index 9292a16595..0651fc796e 100644 --- a/backends/platform/android/android.mk +++ b/backends/platform/android/android.mk @@ -10,6 +10,7 @@ JAVA_FILES = \ ScummVMApplication.java \ ScummVMActivity.java \ EditableSurfaceView.java \ + MouseHelper.java \ Unpacker.java JAVA_FILES_PLUGIN = \ @@ -47,13 +48,7 @@ APKBUILDER = $(ANDROID_SDK)/tools/apkbuilder JAVAC ?= javac JAVACFLAGS = -source 1.5 -target 1.5 -# This is a bit silly. I want to compile against the 1.6 android.jar, -# to make the compiler check that I don't use something that requires -# a newer Android. However, in order to use android:installLocation, -# we need to give aapt a version >=8 android.jar - even though the -# result will work ok on 1.5+. -ANDROID_JAR = $(ANDROID_SDK)/platforms/android-4/android.jar -ANDROID_JAR8 = $(ANDROID_SDK)/platforms/android-8/android.jar +ANDROID_JAR = $(ANDROID_SDK)/platforms/android-14/android.jar PATH_BUILD = build.tmp PATH_BUILD_ASSETS = $(PATH_BUILD)/assets @@ -92,9 +87,9 @@ $(FILE_MANIFEST): $(FILE_MANIFEST_SRC) @$(MKDIR) -p $(@D) sed "s/@ANDROID_VERSIONCODE@/$(ANDROID_VERSIONCODE)/" < $< > $@ -$(SRC_GEN): $(FILE_MANIFEST) $(filter %.xml,$(RESOURCES)) $(ANDROID_JAR8) +$(SRC_GEN): $(FILE_MANIFEST) $(filter %.xml,$(RESOURCES)) $(ANDROID_JAR) @$(MKDIR) -p $(PATH_GEN_TOP) - $(AAPT) package -m -J $(PATH_GEN_TOP) -M $< -S $(PATH_RESOURCES) -I $(ANDROID_JAR8) + $(AAPT) package -m -J $(PATH_GEN_TOP) -M $< -S $(PATH_RESOURCES) -I $(ANDROID_JAR) $(PATH_CLASSES_MAIN)/%.class: $(PATH_GEN)/%.java $(SRC_GEN) @$(MKDIR) -p $(@D) @@ -127,7 +122,7 @@ $(PATH_STAGE_PREFIX).%/res/drawable/scummvm.png: $(PATH_RESOURCES)/drawable/scum @$(MKDIR) -p $(@D) $(CP) $< $@ -$(FILE_RESOURCES_MAIN): $(FILE_MANIFEST) $(RESOURCES) $(ANDROID_JAR8) $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) +$(FILE_RESOURCES_MAIN): $(FILE_MANIFEST) $(RESOURCES) $(ANDROID_JAR) $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(INSTALL) -d $(PATH_BUILD_ASSETS) $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(PATH_BUILD_ASSETS)/ work_dir=`pwd`; \ @@ -141,10 +136,10 @@ $(FILE_RESOURCES_MAIN): $(FILE_MANIFEST) $(RESOURCES) $(ANDROID_JAR8) $(DIST_FIL zip -r ../`basename $$i` *; \ done @$(RM) -rf $(PATH_BUILD_ASSETS)/tmp - $(AAPT) package -f -0 zip -M $< -S $(PATH_RESOURCES) -A $(PATH_BUILD_ASSETS) -I $(ANDROID_JAR8) -F $@ + $(AAPT) package -f -0 zip -M $< -S $(PATH_RESOURCES) -A $(PATH_BUILD_ASSETS) -I $(ANDROID_JAR) -F $@ -$(PATH_BUILD)/%/$(FILE_RESOURCES): $(PATH_BUILD)/%/AndroidManifest.xml $(PATH_STAGE_PREFIX).%/res/values/strings.xml $(PATH_STAGE_PREFIX).%/res/drawable/scummvm.png plugins/lib%.so $(ANDROID_JAR8) - $(AAPT) package -f -M $< -S $(PATH_STAGE_PREFIX).$*/res -I $(ANDROID_JAR8) -F $@ +$(PATH_BUILD)/%/$(FILE_RESOURCES): $(PATH_BUILD)/%/AndroidManifest.xml $(PATH_STAGE_PREFIX).%/res/values/strings.xml $(PATH_STAGE_PREFIX).%/res/drawable/scummvm.png plugins/lib%.so $(ANDROID_JAR) + $(AAPT) package -f -M $< -S $(PATH_STAGE_PREFIX).$*/res -I $(ANDROID_JAR) -F $@ # Package installer won't delete old libscummvm.so on upgrade so # replace it with a zero size file diff --git a/backends/platform/android/events.cpp b/backends/platform/android/events.cpp index 21d2344fa7..db1261e432 100644 --- a/backends/platform/android/events.cpp +++ b/backends/platform/android/events.cpp @@ -59,6 +59,11 @@ enum { JE_DOUBLE_TAP = 6, JE_MULTI = 7, JE_BALL = 8, + JE_LMB_DOWN = 9, + JE_LMB_UP = 10, + JE_RMB_DOWN = 11, + JE_RMB_UP = 12, + JE_MOUSE_MOVE = 13, JE_QUIT = 0x1000 }; @@ -272,7 +277,7 @@ void OSystem_Android::clipMouse(Common::Point &p) { } void OSystem_Android::scaleMouse(Common::Point &p, int x, int y, - bool deductDrawRect) { + bool deductDrawRect, bool touchpadMode) { const GLESBaseTexture *tex; if (_show_overlay) @@ -282,7 +287,7 @@ void OSystem_Android::scaleMouse(Common::Point &p, int x, int y, const Common::Rect &r = tex->getDrawRect(); - if (_touchpad_mode) { + if (touchpadMode) { x = x * 100 / _touchpad_scale; y = y * 100 / _touchpad_scale; } @@ -327,11 +332,16 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3, } switch (arg2) { + + // special case. we'll only get it's up event case JKEYCODE_BACK: e.kbd.keycode = Common::KEYCODE_ESCAPE; e.kbd.ascii = Common::ASCII_ESCAPE; lockMutex(_event_queue_lock); + e.type = Common::EVENT_KEYDOWN; + _event_queue.push(e); + e.type = Common::EVENT_KEYUP; _event_queue.push(e); unlockMutex(_event_queue_lock); @@ -554,7 +564,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3, } scaleMouse(e.mouse, arg3 - _touch_pt_scroll.x, - arg4 - _touch_pt_scroll.y, false); + arg4 - _touch_pt_scroll.y, false, true); e.mouse += _touch_pt_down; clipMouse(e.mouse); } else { @@ -652,7 +662,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3, if (_touchpad_mode) { scaleMouse(e.mouse, arg1 - _touch_pt_dt.x, - arg2 - _touch_pt_dt.y, false); + arg2 - _touch_pt_dt.y, false, true); e.mouse += _touch_pt_down; clipMouse(e.mouse); @@ -757,6 +767,66 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3, return; + case JE_MOUSE_MOVE: + e.type = Common::EVENT_MOUSEMOVE; + + scaleMouse(e.mouse, arg1, arg2); + clipMouse(e.mouse); + + lockMutex(_event_queue_lock); + _event_queue.push(e); + unlockMutex(_event_queue_lock); + + return; + + case JE_LMB_DOWN: + e.type = Common::EVENT_LBUTTONDOWN; + + scaleMouse(e.mouse, arg1, arg2); + clipMouse(e.mouse); + + lockMutex(_event_queue_lock); + _event_queue.push(e); + unlockMutex(_event_queue_lock); + + return; + + case JE_LMB_UP: + e.type = Common::EVENT_LBUTTONUP; + + scaleMouse(e.mouse, arg1, arg2); + clipMouse(e.mouse); + + lockMutex(_event_queue_lock); + _event_queue.push(e); + unlockMutex(_event_queue_lock); + + return; + + case JE_RMB_DOWN: + e.type = Common::EVENT_RBUTTONDOWN; + + scaleMouse(e.mouse, arg1, arg2); + clipMouse(e.mouse); + + lockMutex(_event_queue_lock); + _event_queue.push(e); + unlockMutex(_event_queue_lock); + + return; + + case JE_RMB_UP: + e.type = Common::EVENT_RBUTTONUP; + + scaleMouse(e.mouse, arg1, arg2); + clipMouse(e.mouse); + + lockMutex(_event_queue_lock); + _event_queue.push(e); + unlockMutex(_event_queue_lock); + + return; + case JE_QUIT: e.type = Common::EVENT_QUIT; diff --git a/backends/platform/android/org/scummvm/scummvm/MouseHelper.java b/backends/platform/android/org/scummvm/scummvm/MouseHelper.java new file mode 100644 index 0000000000..ae30bcd1da --- /dev/null +++ b/backends/platform/android/org/scummvm/scummvm/MouseHelper.java @@ -0,0 +1,214 @@ +package org.scummvm.scummvm; + +import android.view.InputDevice; +import android.view.MotionEvent; +import android.view.SurfaceView; +import android.view.View; + +/** + * Contains helper methods for mouse/hover events that were introduced in Android 4.0. + * + * Mouse (hover) events seem to be a bit arbitrary, so here's couple of scenarios: + * + * + * 1. Galaxy Note 2 (4.1) + stylus: + * Tool type: TOOL_TYPE_STYLUS + * + * Key: 238 ACTION_DOWN (once) + * Key: 238 ACTION_UP (once) + * Hover: ACTION_HOVER_ENTER (once) + * Hover: ACTION_HOVER_MOVE (multiple, while hovering) + * + * touch screen with the pen: + * Hover: ACTION_HOVER_EXIT, ButtonState: 0 (once) + * Touch: ACTION_DOWN, ButtonState: 0 (once) + * Touch: ACTION_MOVE, ButtonState: 0 (multiple, while pressing) + * Touch: ACTION_UP, ButtonState: 0 (once) + * Hover: ACTION_HOVER_ENTER (once) + * + * press the stylus button while hovering: + * Hover: ACTION_HOVER_MOVE, ButtonState: 2 (multiple, while pressing button) + * Hover: ACTION_HOVER_MOVE, ButtonState: 0 (multiple, after release) + * + * + * 2. Galaxy Note 2 (4.1) + mouse (usb): + * Tool type: TOOL_TYPE_MOUSE + * + * Hover: ACTION_HOVER_ENTER (once) + * Hover: ACTION_HOVER_MOVE (multiple, while hovering) + * + * press left button: + * Hover: ACTION_HOVER_EXIT, ButtonState: 1 (once) + * Touch: ACTION_DOWN, ButtonState: 1 (once) + * Touch: ACTION_MOVE, ButtonState: 1 (multiple, while pressing) + * Touch: ACTION_UP, ButtonState: 0 (once) + * Hover: ACTION_HOVER_ENTER, ButtonState: 0 (once) + * + * press right button: + * Key: KEYCODE_BACK, ACTION_DOWN + * Hover: ACTION_HOVER_MOVE, ButtonState: 2 (multiple, while pressing button) + * Hover: ACTION_HOVER_MOVE, ButtonState: 0 (once) + * Key: KEYCODE_BACK, ACTION_UP + * + * + * 3. Asus eeePad Transformer Prime running CyanogenMod 10 (Android 4.1) + mouse (usb): + * Tool type: TOOL_TYPE_MOUSE + * + * Hover: ACTION_HOVER_ENTER (once) + * Hover: ACTION_HOVER_MOVE (multiple, while hovering) + * + * press left button: + * Hover: ACTION_HOVER_EXIT, ButtonState: 1 (once) + * Touch: ACTION_DOWN, ButtonState: 1 (once) + * Touch: ACTION_MOVE, ButtonState: 1 (multiple, while pressing) + * Touch: ACTION_UP, ButtonState: 0 (once) + * Hover: ACTION_HOVER_ENTER, ButtonState: 0 (once) + * + * press right button: + * Hover: ACTION_HOVER_EXIT, ButtonState: 2 (once) + * Touch: ACTION_DOWN, ButtonState: 2 (once) + * Touch: ACTION_MOVE, ButtonState: 2 (multiple, while pressing) + * Touch: ACTION_UP, ButtonState: 0 (once) + * Hover: ACTION_HOVER_ENTER, ButtonState: 0 (once) + * + * + * 4. Asus eeePad Transformer Prime running CyanogenMod 10 (Android 4.1) + touchpad: + * Tool type: TOOL_TYPE_FINGER + * + * Hover: ACTION_HOVER_ENTER (once) + * Hover: ACTION_HOVER_MOVE (multiple, while hovering) + * + * press left button: + * Hover: ACTION_HOVER_EXIT, ButtonState: 1 (once) + * Touch: ACTION_DOWN, ButtonState: 1 (once) + * Touch: ACTION_MOVE, ButtonState: 1 (multiple, while pressing) + * Touch: ACTION_UP, ButtonState: 0 (once) + * Hover: ACTION_HOVER_ENTER, ButtonState: 0 (once) + * + * press right button: + * Hover: ACTION_HOVER_EXIT, ButtonState: 2 (once) + * Touch: ACTION_DOWN, ButtonState: 2 (once) + * Touch: ACTION_MOVE, ButtonState: 2 (multiple, while pressing) + * Touch: ACTION_UP, ButtonState: 0 (once) + * Hover: ACTION_HOVER_ENTER, ButtonState: 0 (once) + * + */ +public class MouseHelper { + private View.OnHoverListener _listener; + private ScummVM _scummvm; + private long _rmbGuardTime; + private boolean _rmbPressed; + private boolean _lmbPressed; + + /** + * Class initialization fails when this throws an exception. + * Checking hover availability is done on static class initialization for Android 1.6 compatibility. + */ + static { + try { + Class.forName("android.view.View$OnHoverListener"); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + /** + * Calling this forces class initialization + */ + public static void checkHoverAvailable() {} + + public MouseHelper(ScummVM scummvm) { + _scummvm = scummvm; + _listener = createListener(); + } + + private View.OnHoverListener createListener() { + return new View.OnHoverListener() { + @Override + public boolean onHover(View view, MotionEvent e) { + return onTouch(e, true); + } + }; + } + + public void attach(SurfaceView main_surface) { + main_surface.setOnHoverListener(_listener); + } + + public static boolean isMouse(MotionEvent e) { + if (e == null) { + return false; + } + + InputDevice device = e.getDevice(); + + if (device == null) { + return false; + } + + int sources = device.getSources(); + + return ((sources & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) || + ((sources & InputDevice.SOURCE_STYLUS) == InputDevice.SOURCE_STYLUS) || + ((sources & InputDevice.SOURCE_TOUCHPAD) == InputDevice.SOURCE_TOUCHPAD); + } + + public boolean onTouch(MotionEvent e, boolean hover) { + _scummvm.pushEvent(ScummVMEvents.JE_MOUSE_MOVE, (int)e.getX(), (int)e.getY(), 0, 0, 0); + + int buttonState = e.getButtonState(); + + boolean lmbDown = (buttonState & MotionEvent.BUTTON_PRIMARY) == MotionEvent.BUTTON_PRIMARY; + + if (e.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS) { + // when using stylus, ButtonState is 0 + lmbDown = !hover; + } + + if (lmbDown) { + if (!_lmbPressed) { + // left mouse button was pressed just now + _scummvm.pushEvent(ScummVMEvents.JE_LMB_DOWN, (int)e.getX(), (int)e.getY(), e.getButtonState(), 0, 0); + } + + _lmbPressed = true; + } else { + if (_lmbPressed) { + // left mouse button was released just now + _scummvm.pushEvent(ScummVMEvents.JE_LMB_UP, (int)e.getX(), (int)e.getY(), e.getButtonState(), 0, 0); + } + + _lmbPressed = false; + } + + boolean rmbDown = (buttonState & MotionEvent.BUTTON_SECONDARY) == MotionEvent.BUTTON_SECONDARY; + if (rmbDown) { + if (!_rmbPressed) { + // right mouse button was pressed just now + _scummvm.pushEvent(ScummVMEvents.JE_RMB_DOWN, (int)e.getX(), (int)e.getY(), e.getButtonState(), 0, 0); + } + + _rmbPressed = true; + } else { + if (_rmbPressed) { + // right mouse button was released just now + _scummvm.pushEvent(ScummVMEvents.JE_RMB_UP, (int)e.getX(), (int)e.getY(), e.getButtonState(), 0, 0); + _rmbGuardTime = System.currentTimeMillis(); + } + + _rmbPressed = false; + } + + return true; + } + + /** + * Checks whether right mouse button is pressed or was pressed just previously. This is used to prevent sending + * extra back key on right mouse click which is the default behaviour in some platforms. + * + * @return true if right mouse button is (or was in the last 200ms) pressed + */ + public boolean getRmbGuard() { + return _rmbPressed || _rmbGuardTime + 200 > System.currentTimeMillis(); + } +} diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java index fbd6513761..34c6df3a3a 100644 --- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java +++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java @@ -18,6 +18,18 @@ import java.io.File; public class ScummVMActivity extends Activity { + /* Establish whether the hover events are available */ + private static boolean _hoverAvailable; + + static { + try { + MouseHelper.checkHoverAvailable(); // this throws exception if we're on too old version + _hoverAvailable = true; + } catch (Throwable t) { + _hoverAvailable = false; + } + } + private class MyScummVM extends ScummVM { private boolean usingSmallScreen() { // Multiple screen sizes came in with Android 1.6. Have @@ -94,6 +106,7 @@ public class ScummVMActivity extends Activity { private MyScummVM _scummvm; private ScummVMEvents _events; + private MouseHelper _mouseHelper; private Thread _scummvm_thread; @Override @@ -151,7 +164,13 @@ public class ScummVMActivity extends Activity { "--savepath=" + savePath }); - _events = new ScummVMEvents(this, _scummvm); + Log.d(ScummVM.LOG_TAG, "Hover available: " + _hoverAvailable); + if (_hoverAvailable) { + _mouseHelper = new MouseHelper(_scummvm); + _mouseHelper.attach(main_surface); + } + + _events = new ScummVMEvents(this, _scummvm, _mouseHelper); main_surface.setOnKeyListener(_events); main_surface.setOnTouchListener(_events); diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java b/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java index 86227b9352..45c1f8bcb5 100644 --- a/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java +++ b/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java @@ -2,7 +2,6 @@ package org.scummvm.scummvm; import android.os.Handler; import android.os.Message; -import android.util.Log; import android.content.Context; import android.view.KeyEvent; import android.view.KeyCharacterMap; @@ -27,16 +26,23 @@ public class ScummVMEvents implements public static final int JE_DOUBLE_TAP = 6; public static final int JE_MULTI = 7; public static final int JE_BALL = 8; + public static final int JE_LMB_DOWN = 9; + public static final int JE_LMB_UP = 10; + public static final int JE_RMB_DOWN = 11; + public static final int JE_RMB_UP = 12; + public static final int JE_MOUSE_MOVE = 13; public static final int JE_QUIT = 0x1000; final protected Context _context; final protected ScummVM _scummvm; final protected GestureDetector _gd; final protected int _longPress; + final protected MouseHelper _mouseHelper; - public ScummVMEvents(Context context, ScummVM scummvm) { + public ScummVMEvents(Context context, ScummVM scummvm, MouseHelper mouseHelper) { _context = context; _scummvm = scummvm; + _mouseHelper = mouseHelper; _gd = new GestureDetector(context, this); _gd.setOnDoubleTapListener(this); @@ -64,7 +70,7 @@ public class ScummVMEvents implements public void handleMessage(Message msg) { if (msg.what == MSG_MENU_LONG_PRESS) { InputMethodManager imm = (InputMethodManager) - _context.getSystemService(_context.INPUT_METHOD_SERVICE); + _context.getSystemService(Context.INPUT_METHOD_SERVICE); if (imm != null) imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); @@ -73,9 +79,30 @@ public class ScummVMEvents implements }; // OnKeyListener + @Override final public boolean onKey(View v, int keyCode, KeyEvent e) { final int action = e.getAction(); + if (keyCode == 238) { + // this (undocumented) event is sent when ACTION_HOVER_ENTER or ACTION_HOVER_EXIT occurs + return false; + } + + if (keyCode == KeyEvent.KEYCODE_BACK) { + if (action != KeyEvent.ACTION_UP) { + // only send event from back button on up event, since down event is sent on right mouse click and + // cannot be caught (thus rmb click would send escape key first) + return true; + } + + if (_mouseHelper != null) { + if (_mouseHelper.getRmbGuard()) { + // right mouse button was just clicked which sends an extra back button press + return true; + } + } + } + if (e.isSystem()) { // filter what we handle switch (keyCode) { @@ -160,7 +187,16 @@ public class ScummVMEvents implements } // OnTouchListener + @Override final public boolean onTouch(View v, MotionEvent e) { + if (_mouseHelper != null) { + boolean isMouse = MouseHelper.isMouse(e); + if (isMouse) { + // mouse button is pressed + return _mouseHelper.onTouch(e, false); + } + } + final int action = e.getAction(); // constants from APIv5: @@ -177,11 +213,13 @@ public class ScummVMEvents implements } // OnGestureListener + @Override final public boolean onDown(MotionEvent e) { _scummvm.pushEvent(JE_DOWN, (int)e.getX(), (int)e.getY(), 0, 0, 0); return true; } + @Override final public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { //Log.d(ScummVM.LOG_TAG, String.format("onFling: %s -> %s (%.3f %.3f)", @@ -191,10 +229,12 @@ public class ScummVMEvents implements return true; } + @Override final public void onLongPress(MotionEvent e) { // disabled, interferes with drag&drop } + @Override final public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { _scummvm.pushEvent(JE_SCROLL, (int)e1.getX(), (int)e1.getY(), @@ -203,9 +243,11 @@ public class ScummVMEvents implements return true; } + @Override final public void onShowPress(MotionEvent e) { } + @Override final public boolean onSingleTapUp(MotionEvent e) { _scummvm.pushEvent(JE_TAP, (int)e.getX(), (int)e.getY(), (int)(e.getEventTime() - e.getDownTime()), 0, 0); @@ -214,10 +256,12 @@ public class ScummVMEvents implements } // OnDoubleTapListener + @Override final public boolean onDoubleTap(MotionEvent e) { return true; } + @Override final public boolean onDoubleTapEvent(MotionEvent e) { _scummvm.pushEvent(JE_DOUBLE_TAP, (int)e.getX(), (int)e.getY(), e.getAction(), 0, 0); @@ -225,6 +269,7 @@ public class ScummVMEvents implements return true; } + @Override final public boolean onSingleTapConfirmed(MotionEvent e) { return true; } -- cgit v1.2.3 From fc15e1c207c64e64eda6eb9e0e1b3a6e0f462c1d Mon Sep 17 00:00:00 2001 From: Lauri Härsilä Date: Sun, 21 Oct 2012 06:29:36 +0300 Subject: ANDROID: Fixed tapping touchpad not sending left clicks --- .../android/org/scummvm/scummvm/MouseHelper.java | 95 ++-------------------- .../android/org/scummvm/scummvm/ScummVMEvents.java | 2 +- 2 files changed, 6 insertions(+), 91 deletions(-) (limited to 'backends/platform/android') diff --git a/backends/platform/android/org/scummvm/scummvm/MouseHelper.java b/backends/platform/android/org/scummvm/scummvm/MouseHelper.java index ae30bcd1da..999815593f 100644 --- a/backends/platform/android/org/scummvm/scummvm/MouseHelper.java +++ b/backends/platform/android/org/scummvm/scummvm/MouseHelper.java @@ -7,91 +7,6 @@ import android.view.View; /** * Contains helper methods for mouse/hover events that were introduced in Android 4.0. - * - * Mouse (hover) events seem to be a bit arbitrary, so here's couple of scenarios: - * - * - * 1. Galaxy Note 2 (4.1) + stylus: - * Tool type: TOOL_TYPE_STYLUS - * - * Key: 238 ACTION_DOWN (once) - * Key: 238 ACTION_UP (once) - * Hover: ACTION_HOVER_ENTER (once) - * Hover: ACTION_HOVER_MOVE (multiple, while hovering) - * - * touch screen with the pen: - * Hover: ACTION_HOVER_EXIT, ButtonState: 0 (once) - * Touch: ACTION_DOWN, ButtonState: 0 (once) - * Touch: ACTION_MOVE, ButtonState: 0 (multiple, while pressing) - * Touch: ACTION_UP, ButtonState: 0 (once) - * Hover: ACTION_HOVER_ENTER (once) - * - * press the stylus button while hovering: - * Hover: ACTION_HOVER_MOVE, ButtonState: 2 (multiple, while pressing button) - * Hover: ACTION_HOVER_MOVE, ButtonState: 0 (multiple, after release) - * - * - * 2. Galaxy Note 2 (4.1) + mouse (usb): - * Tool type: TOOL_TYPE_MOUSE - * - * Hover: ACTION_HOVER_ENTER (once) - * Hover: ACTION_HOVER_MOVE (multiple, while hovering) - * - * press left button: - * Hover: ACTION_HOVER_EXIT, ButtonState: 1 (once) - * Touch: ACTION_DOWN, ButtonState: 1 (once) - * Touch: ACTION_MOVE, ButtonState: 1 (multiple, while pressing) - * Touch: ACTION_UP, ButtonState: 0 (once) - * Hover: ACTION_HOVER_ENTER, ButtonState: 0 (once) - * - * press right button: - * Key: KEYCODE_BACK, ACTION_DOWN - * Hover: ACTION_HOVER_MOVE, ButtonState: 2 (multiple, while pressing button) - * Hover: ACTION_HOVER_MOVE, ButtonState: 0 (once) - * Key: KEYCODE_BACK, ACTION_UP - * - * - * 3. Asus eeePad Transformer Prime running CyanogenMod 10 (Android 4.1) + mouse (usb): - * Tool type: TOOL_TYPE_MOUSE - * - * Hover: ACTION_HOVER_ENTER (once) - * Hover: ACTION_HOVER_MOVE (multiple, while hovering) - * - * press left button: - * Hover: ACTION_HOVER_EXIT, ButtonState: 1 (once) - * Touch: ACTION_DOWN, ButtonState: 1 (once) - * Touch: ACTION_MOVE, ButtonState: 1 (multiple, while pressing) - * Touch: ACTION_UP, ButtonState: 0 (once) - * Hover: ACTION_HOVER_ENTER, ButtonState: 0 (once) - * - * press right button: - * Hover: ACTION_HOVER_EXIT, ButtonState: 2 (once) - * Touch: ACTION_DOWN, ButtonState: 2 (once) - * Touch: ACTION_MOVE, ButtonState: 2 (multiple, while pressing) - * Touch: ACTION_UP, ButtonState: 0 (once) - * Hover: ACTION_HOVER_ENTER, ButtonState: 0 (once) - * - * - * 4. Asus eeePad Transformer Prime running CyanogenMod 10 (Android 4.1) + touchpad: - * Tool type: TOOL_TYPE_FINGER - * - * Hover: ACTION_HOVER_ENTER (once) - * Hover: ACTION_HOVER_MOVE (multiple, while hovering) - * - * press left button: - * Hover: ACTION_HOVER_EXIT, ButtonState: 1 (once) - * Touch: ACTION_DOWN, ButtonState: 1 (once) - * Touch: ACTION_MOVE, ButtonState: 1 (multiple, while pressing) - * Touch: ACTION_UP, ButtonState: 0 (once) - * Hover: ACTION_HOVER_ENTER, ButtonState: 0 (once) - * - * press right button: - * Hover: ACTION_HOVER_EXIT, ButtonState: 2 (once) - * Touch: ACTION_DOWN, ButtonState: 2 (once) - * Touch: ACTION_MOVE, ButtonState: 2 (multiple, while pressing) - * Touch: ACTION_UP, ButtonState: 0 (once) - * Hover: ACTION_HOVER_ENTER, ButtonState: 0 (once) - * */ public class MouseHelper { private View.OnHoverListener _listener; @@ -126,7 +41,7 @@ public class MouseHelper { return new View.OnHoverListener() { @Override public boolean onHover(View view, MotionEvent e) { - return onTouch(e, true); + return onMouseEvent(e, true); } }; } @@ -153,16 +68,16 @@ public class MouseHelper { ((sources & InputDevice.SOURCE_TOUCHPAD) == InputDevice.SOURCE_TOUCHPAD); } - public boolean onTouch(MotionEvent e, boolean hover) { + public boolean onMouseEvent(MotionEvent e, boolean hover) { _scummvm.pushEvent(ScummVMEvents.JE_MOUSE_MOVE, (int)e.getX(), (int)e.getY(), 0, 0, 0); int buttonState = e.getButtonState(); boolean lmbDown = (buttonState & MotionEvent.BUTTON_PRIMARY) == MotionEvent.BUTTON_PRIMARY; - if (e.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS) { - // when using stylus, ButtonState is 0 - lmbDown = !hover; + if (!hover && e.getAction() != MotionEvent.ACTION_UP && buttonState == 0) { + // On some device types, ButtonState is 0 even when tapping on the touchpad or using the stylus on the screen etc. + lmbDown = true; } if (lmbDown) { diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java b/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java index 45c1f8bcb5..5f51ffac6c 100644 --- a/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java +++ b/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java @@ -193,7 +193,7 @@ public class ScummVMEvents implements boolean isMouse = MouseHelper.isMouse(e); if (isMouse) { // mouse button is pressed - return _mouseHelper.onTouch(e, false); + return _mouseHelper.onMouseEvent(e, false); } } -- cgit v1.2.3 From 0e5bfb66f03551f998405ce6674f3e6eab4a0150 Mon Sep 17 00:00:00 2001 From: D G Turner Date: Mon, 24 Dec 2012 16:45:49 +0000 Subject: ANDROID: Remove parameter forcing use of Modern theme. This parameter overrides any user choice in the GUI or config file, which is not good UX design (and is making it hard to debug loading issues associated with theme files). If we want to set this to default to Modern, we should do this in a different way i.e. do this by ConfMan.loadDefaultConfigFile() This is probably related to the Android issue with the backend init running before main() is called, rather than after... --- backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java | 1 - 1 file changed, 1 deletion(-) (limited to 'backends/platform/android') diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java index 34c6df3a3a..829a948435 100644 --- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java +++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java @@ -160,7 +160,6 @@ public class ScummVMActivity extends Activity { "ScummVM", "--config=" + getFileStreamPath("scummvmrc").getPath(), "--path=" + Environment.getExternalStorageDirectory().getPath(), - "--gui-theme=scummmodern", "--savepath=" + savePath }); -- cgit v1.2.3 From 21ea60f604b586da7337e2794fb4b4f25e63701b Mon Sep 17 00:00:00 2001 From: D G Turner Date: Fri, 28 Dec 2012 00:54:00 +0000 Subject: ANDROID: Minor fixes to build-specific makefile. This fixes two minor issues when trying to cross-compile to Android on Win32 using the Win32 Android SDK/NDK and MinGW shell. However, this is still no working as DX and APKBUILDER are batch files in the Win32 SDK (which then call the real Java tools) and these fail to run in shell. However, using "cmd /C" also fails as the paths in the parameters have unix, rather than native separators. Unsure how to fix. --- backends/platform/android/android.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'backends/platform/android') diff --git a/backends/platform/android/android.mk b/backends/platform/android/android.mk index 0651fc796e..f498c671de 100644 --- a/backends/platform/android/android.mk +++ b/backends/platform/android/android.mk @@ -50,7 +50,7 @@ JAVACFLAGS = -source 1.5 -target 1.5 ANDROID_JAR = $(ANDROID_SDK)/platforms/android-14/android.jar -PATH_BUILD = build.tmp +PATH_BUILD = ./build.tmp PATH_BUILD_ASSETS = $(PATH_BUILD)/assets PATH_BUILD_CLASSES_MAIN_TOP = $(PATH_BUILD)/classes.main PATH_BUILD_CLASSES_PLUGIN_TOP = $(PATH_BUILD)/classes.plugin @@ -128,7 +128,7 @@ $(FILE_RESOURCES_MAIN): $(FILE_MANIFEST) $(RESOURCES) $(ANDROID_JAR) $(DIST_FILE work_dir=`pwd`; \ for i in $(PATH_BUILD_ASSETS)/*.zip; do \ echo "recompress $$i"; \ - cd $$work_dir; \ + cd "$$work_dir"; \ $(RM) -rf $(PATH_BUILD_ASSETS)/tmp; \ $(MKDIR) $(PATH_BUILD_ASSETS)/tmp; \ unzip -q $$i -d $(PATH_BUILD_ASSETS)/tmp; \ -- cgit v1.2.3 From 89d9a624d9f0b4f5ba07259d5f90f7f85f15a0df Mon Sep 17 00:00:00 2001 From: Alyssa Milburn Date: Thu, 16 May 2013 12:55:06 +0200 Subject: ANDROID: Delete local JNI references to asset data/classes. --- backends/platform/android/asset-archive.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'backends/platform/android') diff --git a/backends/platform/android/asset-archive.cpp b/backends/platform/android/asset-archive.cpp index 14840de996..f1decfb7fa 100644 --- a/backends/platform/android/asset-archive.cpp +++ b/backends/platform/android/asset-archive.cpp @@ -97,7 +97,9 @@ JavaInputStream::JavaInputStream(JNIEnv *env, jobject is) : { _input_stream = env->NewGlobalRef(is); _buflen = 8192; - _buf = (jbyteArray)env->NewGlobalRef(env->NewByteArray(_buflen)); + jobject buf = env->NewByteArray(_buflen); + _buf = (jbyteArray)env->NewGlobalRef(buf); + env->DeleteLocalRef(buf); jclass cls = env->GetObjectClass(_input_stream); MID_mark = env->GetMethodID(cls, "mark", "(I)V"); @@ -112,6 +114,7 @@ JavaInputStream::JavaInputStream(JNIEnv *env, jobject is) : assert(MID_reset); MID_skip = env->GetMethodID(cls, "skip", "(J)J"); assert(MID_skip); + env->DeleteLocalRef(cls); // Mark start of stream, so we can reset back to it. // readlimit is set to something bigger than anything we might @@ -142,7 +145,9 @@ uint32 JavaInputStream::read(void *dataPtr, uint32 dataSize) { _buflen = dataSize; env->DeleteGlobalRef(_buf); - _buf = static_cast(env->NewGlobalRef(env->NewByteArray(_buflen))); + jobject buf = env->NewByteArray(_buflen); + _buf = static_cast(env->NewGlobalRef(buf)); + env->DeleteLocalRef(buf); } jint ret = env->CallIntMethod(_input_stream, MID_read, _buf, 0, dataSize); @@ -290,6 +295,7 @@ AssetFdReadStream::AssetFdReadStream(JNIEnv *env, jobject assetfd) : jclass cls = env->GetObjectClass(_assetfd); MID_close = env->GetMethodID(cls, "close", "()V"); assert(MID_close); + env->DeleteLocalRef(cls); jmethodID MID_getStartOffset = env->GetMethodID(cls, "getStartOffset", "()J"); @@ -311,8 +317,10 @@ AssetFdReadStream::AssetFdReadStream(JNIEnv *env, jobject assetfd) : jclass fd_cls = env->GetObjectClass(javafd); jfieldID FID_descriptor = env->GetFieldID(fd_cls, "descriptor", "I"); assert(FID_descriptor); + env->DeleteLocalRef(fd_cls); _fd = env->GetIntField(javafd, FID_descriptor); + env->DeleteLocalRef(javafd); } AssetFdReadStream::~AssetFdReadStream() { @@ -382,6 +390,7 @@ AndroidAssetArchive::AndroidAssetArchive(jobject am) { MID_list = env->GetMethodID(cls, "list", "(Ljava/lang/String;)[Ljava/lang/String;"); assert(MID_list); + env->DeleteLocalRef(cls); } AndroidAssetArchive::~AndroidAssetArchive() { @@ -481,8 +490,10 @@ Common::SeekableReadStream *AndroidAssetArchive::createReadStreamForMember(const env->ExceptionClear(); else if (afd != 0) { // success :) + Common::SeekableReadStream *stream = new AssetFdReadStream(env, afd); env->DeleteLocalRef(jpath); - return new AssetFdReadStream(env, afd); + env->DeleteLocalRef(afd); + return stream; } // ... and fallback to normal open() if that doesn't work @@ -498,7 +509,10 @@ Common::SeekableReadStream *AndroidAssetArchive::createReadStreamForMember(const return 0; } - return new JavaInputStream(env, is); + Common::SeekableReadStream *stream = new JavaInputStream(env, is); + env->DeleteLocalRef(jpath); + env->DeleteLocalRef(is); + return stream; } #endif -- cgit v1.2.3 From c96b75e1f7c3ca7c46aafc51d7d1fd841417c15c Mon Sep 17 00:00:00 2001 From: Alyssa Milburn Date: Thu, 16 May 2013 12:56:41 +0200 Subject: ANDROID: Ignore subdirectories of asset archives. --- backends/platform/android/asset-archive.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'backends/platform/android') diff --git a/backends/platform/android/asset-archive.cpp b/backends/platform/android/asset-archive.cpp index f1decfb7fa..da378fb082 100644 --- a/backends/platform/android/asset-archive.cpp +++ b/backends/platform/android/asset-archive.cpp @@ -461,7 +461,9 @@ int AndroidAssetArchive::listMembers(Common::ArchiveMemberList &member_list) con member_list.push_back(getMember(thispath)); ++count; } else { - dirlist.push_back(thispath); + // AssetManager is ridiculously slow and we don't care + // about subdirectories at the moment, so ignore them. + // dirlist.push_back(thispath); } } -- cgit v1.2.3 From 8d488f9f70171fa33ff7013efb7cc476e15f8bda Mon Sep 17 00:00:00 2001 From: Alyssa Milburn Date: Thu, 16 May 2013 12:57:21 +0200 Subject: ANDROID: Force htc_fail for all Android devices, for now. --- backends/platform/android/android.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'backends/platform/android') diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp index 0b31ee717c..f06e4be19e 100644 --- a/backends/platform/android/android.cpp +++ b/backends/platform/android/android.cpp @@ -116,7 +116,7 @@ OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) : _screen_changeid(0), _egl_surface_width(0), _egl_surface_height(0), - _htc_fail(false), + _htc_fail(true), _force_redraw(false), _game_texture(0), _overlay_texture(0), @@ -162,10 +162,10 @@ OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) : getSystemProperty("ro.product.cpu.abi").c_str()); mf.toLowercase(); - _htc_fail = mf.contains("htc"); + /*_htc_fail = mf.contains("htc"); if (_htc_fail) - LOGI("Enabling HTC workaround"); + LOGI("Enabling HTC workaround");*/ } OSystem_Android::~OSystem_Android() { -- cgit v1.2.3 From 400763390e20c6b2b9d5b29de9cfdafc93d227e2 Mon Sep 17 00:00:00 2001 From: Alyssa Milburn Date: Thu, 16 May 2013 13:01:32 +0200 Subject: ANDROID: Disable parachute slot 0 saves. --- backends/platform/android/jni.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'backends/platform/android') diff --git a/backends/platform/android/jni.cpp b/backends/platform/android/jni.cpp index a7ebb87651..2b738dd63f 100644 --- a/backends/platform/android/jni.cpp +++ b/backends/platform/android/jni.cpp @@ -603,10 +603,10 @@ void JNI::setPause(JNIEnv *env, jobject self, jboolean value) { g_engine->pauseEngine(value); - if (value && + /*if (value && g_engine->hasFeature(Engine::kSupportsSavingDuringRuntime) && g_engine->canSaveGameStateCurrently()) - g_engine->saveGameState(0, "Android parachute"); + g_engine->saveGameState(0, "Android parachute");*/ } pause = value; -- cgit v1.2.3