From 51617fa620d4c53611b9bb8bc955a6a926bbc1ec Mon Sep 17 00:00:00 2001 From: Aaron Culliney Date: Sat, 14 Mar 2015 15:42:02 -0700 Subject: [PATCH] Android : use GestureDetector instead of raw touch handling - Also simplifies general settings (now you can swipe to change emulation speed) --- .../org/deadc0de/apple2ix/Apple2Activity.java | 109 ++++++++++++++++-- .../deadc0de/apple2ix/Apple2SettingsMenu.java | 37 ++++-- .../org/deadc0de/apple2ix/Apple2View.java | 90 +-------------- .../src/main/res/layout/general_settings.xml | 101 +--------------- Android/app/src/main/res/values/strings.xml | 4 +- Android/jni/jnihooks.c | 106 ++++++++++++----- 6 files changed, 213 insertions(+), 234 deletions(-) diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Activity.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Activity.java index 60844d6e..76843831 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Activity.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Activity.java @@ -21,6 +21,7 @@ import android.content.pm.PackageManager; import android.graphics.Rect; import android.os.Bundle; import android.util.Log; +import android.view.GestureDetector; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.ViewTreeObserver; @@ -39,6 +40,10 @@ public class Apple2Activity extends Activity { private Apple2View mView = null; private AlertDialog mQuitDialog = null; + private GestureDetector mDetector = null; + private boolean mSwipeTogglesSpeed = true; + private boolean mDoubleTapShowsKeyboard = true; + private int mWidth = 0; private int mHeight = 0; private boolean mSoftKeyboardShowing = false; @@ -48,15 +53,19 @@ public class Apple2Activity extends Activity { } private native void nativeOnCreate(String dataDir); + private native void nativeGraphicsInitialized(int width, int height); + private native void nativeGraphicsChanged(int width, int height); + private native void nativeOnKeyDown(int keyCode, int metaState); + private native void nativeOnKeyUp(int keyCode, int metaState); + private native void nativeIncreaseCPUSpeed(); + private native void nativeDecreaseCPUSpeed(); + public native void nativeOnResume(); public native void nativeOnPause(); public native void nativeOnQuit(); + public native boolean nativeOnTouch(int action, float x, float y); public native void nativeReboot(); - private native void nativeGraphicsInitialized(int width, int height); - private native void nativeGraphicsChanged(int width, int height); public native void nativeRender(); - private native void nativeOnKeyDown(int keyCode, int metaState); - private native void nativeOnKeyUp(int keyCode, int metaState); // HACK NOTE 2015/02/22 : Apparently native code cannot easily access stuff in the APK ... so copy various resources // out of the APK and into the /data/data/... for ease of access. Because this is FOSS software we don't care about @@ -146,11 +155,14 @@ public class Apple2Activity extends Activity { Log.d(TAG, "Soft keyboard appears to be occupying screen real estate ..."); Apple2Activity.this.mSoftKeyboardShowing = true; } else { + Log.d(TAG, "Soft keyboard appears to be gone ..."); Apple2Activity.this.mSoftKeyboardShowing = false; } nativeGraphicsChanged(rect.width(), h); } }); + + mDetector = new GestureDetector(this, new Apple2GestureListener()); } @Override @@ -219,7 +231,7 @@ public class Apple2Activity extends Activity { mView.showMainMenu(); return true; } else if ((keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) || (keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) || (keyCode == KeyEvent.KEYCODE_VOLUME_UP)) { - return false; + return super.onKeyUp(keyCode, event); } else { nativeOnKeyUp(keyCode, event.getMetaState()); return true; @@ -228,8 +240,83 @@ public class Apple2Activity extends Activity { @Override public boolean onTouchEvent(MotionEvent event) { - Log.d(TAG, "onTouchEvent..."); - return true; + do { + Apple2MainMenu mainMenu = mView.getMainMenu(); + if (mainMenu == null) { + break; + } + + Apple2SettingsMenu settingsMenu = mainMenu.getSettingsMenu(); + if (settingsMenu != null && settingsMenu.isShowing()) { + break; + } + + int action = event.getActionMasked(); + float x = event.getX(); + float y = event.getY(); + + boolean nativeHandled = nativeOnTouch(action, x, y); + if (nativeHandled) { + break; + } + + this.mDetector.onTouchEvent(event); + } while (false); + + return super.onTouchEvent(event); + } + + private class Apple2GestureListener extends GestureDetector.SimpleOnGestureListener { + private static final String TAG = "Gestures"; + + @Override + public boolean onDown(MotionEvent event) { + Log.d(TAG,"onDown: " + event.toString()); + return true; + } + + @Override + public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) { + if (mSwipeTogglesSpeed) { + float ev1X = event1.getX(); + float ev2X = event2.getX(); + if (ev1X < ev2X) { + nativeIncreaseCPUSpeed(); + } else { + nativeDecreaseCPUSpeed(); + } + } + return true; + } + + @Override + public boolean onSingleTapConfirmed(MotionEvent event) { + Log.d(TAG, "onSingleTapConfirmed: " + event.toString()); + Apple2MainMenu mainMenu = Apple2Activity.this.mView.getMainMenu(); + if (mainMenu.isShowing()) { + Log.d(TAG, "dismissing main menu"); + mainMenu.dismiss(); + } else if (Apple2Activity.this.isSoftKeyboardShowing()) { + Log.d(TAG, "hiding keyboard"); + Apple2Activity.this.mView.toggleKeyboard(); + } else { + Log.d(TAG, "showing main menu"); + Apple2Activity.this.mView.showMainMenu(); + } + return true; + } + + @Override + public boolean onDoubleTap(MotionEvent event) { + if (mDoubleTapShowsKeyboard) { + Log.d(TAG, "onDoubleTap: " + event.toString()); + if (!Apple2Activity.this.isSoftKeyboardShowing()) { + Log.d(TAG, "showing keyboard"); + Apple2Activity.this.mView.toggleKeyboard(); + } + } + return true; + } } public void graphicsInitialized(int width, int height) { @@ -274,4 +361,12 @@ public class Apple2Activity extends Activity { } mQuitDialog.show(); } + + public void setSwipeTogglesSpeed(boolean swipeTogglesSpeed) { + mSwipeTogglesSpeed = swipeTogglesSpeed; + } + + public void setDoubleTapShowsKeyboard(boolean doubleTapShowsKeyboard) { + mDoubleTapShowsKeyboard = doubleTapShowsKeyboard; + } } diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2SettingsMenu.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2SettingsMenu.java index 4fc44b6f..f6788623 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2SettingsMenu.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2SettingsMenu.java @@ -18,7 +18,8 @@ import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; -import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; import android.widget.FrameLayout; import android.widget.ListView; import android.widget.TabHost; @@ -41,12 +42,31 @@ public class Apple2SettingsMenu { LayoutInflater inflater = (LayoutInflater)mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mSettingsView = inflater.inflate(R.layout.activity_settings, null, false); - ListView settingsMenuView = (ListView)mSettingsView.findViewById(R.id.joystick_settings_listview); + // General Settings + + final CheckBox swipeToChangeSpeeds = (CheckBox)mSettingsView.findViewById(R.id.checkBox_speedswipe); + swipeToChangeSpeeds.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + Apple2SettingsMenu.this.mActivity.setSwipeTogglesSpeed(isChecked); + } + }); + + final CheckBox doubleTapShowsKeyboard = (CheckBox)mSettingsView.findViewById(R.id.checkBox_doubletapkeyboard); + doubleTapShowsKeyboard.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + Apple2SettingsMenu.this.mActivity.setDoubleTapShowsKeyboard(isChecked); + } + }); + + // Joystick Settings + + ListView settingsMenuView = (ListView)mSettingsView.findViewById(R.id.joystick_settings_listview); String[] values = new String[] { mActivity.getResources().getString(R.string.joystick_configure), }; - ArrayAdapter adapter = new ArrayAdapter(mActivity, android.R.layout.simple_list_item_1, android.R.id.text1, values); settingsMenuView.setAdapter(adapter); settingsMenuView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @@ -62,6 +82,8 @@ public class Apple2SettingsMenu { } }); + // Tab management + TabHost tabHost = (TabHost)mSettingsView.findViewById(R.id.tabHost_settings); tabHost.setup(); TabHost.TabSpec spec = tabHost.newTabSpec("tab_general"); @@ -73,15 +95,6 @@ public class Apple2SettingsMenu { spec.setIndicator(mActivity.getResources().getString(R.string.tab_joystick), mActivity.getResources().getDrawable(android.R.drawable.ic_menu_compass)); spec.setContent(R.id.tab_joystick); tabHost.addTab(spec); - - Button rebootButton = (Button)mSettingsView.findViewById(R.id.reboot_button); - rebootButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - Apple2SettingsMenu.this.mActivity.nativeReboot(); - Apple2SettingsMenu.this.dismiss(); - } - }); } public void showJoystickConfiguration() { diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2View.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2View.java index 620e5d66..3db6f57a 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2View.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2View.java @@ -19,7 +19,6 @@ import android.content.Context; import android.graphics.PixelFormat; import android.opengl.GLSurfaceView; import android.util.Log; -import android.view.MotionEvent; import android.view.inputmethod.InputMethodManager; import javax.microedition.khronos.egl.EGL10; @@ -49,33 +48,20 @@ import javax.microedition.khronos.opengles.GL10; class Apple2View extends GLSurfaceView { private final static String TAG = "Apple2View"; private final static boolean DEBUG = false; - private final static int MENU_CANCEL_MOVE_THRESHOLD = 20; private Apple2Activity mActivity = null; private Apple2MainMenu mMainMenu = null; - private boolean mUltiTapEventBegin = false; - private boolean mTapEventBegin = false; - private float mSingleX = 0; - private float mSingleY = 0; - private float mUltiX = 0; - private float mUltiY = 0; private boolean inefficient8888 = true; // HACK FIXME TODO : rewrite GL code to accommodate 565 rendering ... public Apple2View(Apple2Activity activity) { super(activity.getApplication()); mActivity = activity; - init(inefficient8888, 0, 0); + setup(inefficient8888, 0, 0); } - public Apple2View(Apple2Activity activity, boolean translucent, int depth, int stencil) { - super(activity.getApplication()); - mActivity = activity; - init(translucent, depth, stencil); - } - - private void init(boolean translucent, int depth, int stencil) { + private void setup(boolean translucent, int depth, int stencil) { /* By default, GLSurfaceView() creates a RGB_565 opaque surface. * If we want a translucent one, we should change the surface's @@ -104,82 +90,10 @@ class Apple2View extends GLSurfaceView { setRenderer(new Renderer()); } - @Override - public boolean onTouchEvent(MotionEvent event) { - if (mMainMenu == null) { - return false; - } - - Log.d(TAG, "VIEW onTouchEvent : " + event.toString()); - - int action = event.getActionMasked(); - - if (mMainMenu.isShowing()) { - mMainMenu.dismiss(); - return true; - } - - // TODO : native GL touch joystick ... - - switch (action) { - case (MotionEvent.ACTION_DOWN): - mSingleX = event.getX(); - mSingleY = event.getY(); - mTapEventBegin = true; - mUltiTapEventBegin = false; - return true; - - case (MotionEvent.ACTION_MOVE): - if (mTapEventBegin) { - float thresholdX = Math.abs(event.getX() - mSingleX); - float thresholdY = Math.abs(event.getY() - mSingleY); - if (thresholdX > MENU_CANCEL_MOVE_THRESHOLD || thresholdY > MENU_CANCEL_MOVE_THRESHOLD) { - mTapEventBegin = false; - } - } else if (mUltiTapEventBegin) { - float thresholdX = Math.abs(event.getX() - mUltiX); - float thresholdY = Math.abs(event.getY() - mUltiY); - if (thresholdX > MENU_CANCEL_MOVE_THRESHOLD || thresholdY > MENU_CANCEL_MOVE_THRESHOLD) { - mUltiTapEventBegin = false; - } - } - return true; - - case (MotionEvent.ACTION_POINTER_DOWN): - mUltiX = event.getX(); - mUltiY = event.getY(); - mTapEventBegin = false; - mUltiTapEventBegin = true; - return true; - - case (MotionEvent.ACTION_POINTER_UP): - if (mUltiTapEventBegin) { - Log.d(TAG, "Toggling keyboard..."); - toggleKeyboard(); - } - mTapEventBegin = false; - mUltiTapEventBegin = false; - return true; - - case (MotionEvent.ACTION_UP): - if (mTapEventBegin) { - showMainMenu(); - } - mTapEventBegin = false; - mUltiTapEventBegin = false; - return true; - } - - return super.onTouchEvent(event); - } - public void showMainMenu() { if (mMainMenu != null) { Apple2SettingsMenu settingsMenu = mMainMenu.getSettingsMenu(); if (!settingsMenu.isShowing()) { - if (mActivity.isSoftKeyboardShowing()) { - toggleKeyboard(); - } mMainMenu.show(); } } diff --git a/Android/app/src/main/res/layout/general_settings.xml b/Android/app/src/main/res/layout/general_settings.xml index d39b9989..1bc0c143 100644 --- a/Android/app/src/main/res/layout/general_settings.xml +++ b/Android/app/src/main/res/layout/general_settings.xml @@ -5,100 +5,17 @@ android:layout_height="fill_parent" android:orientation="vertical" > - - - - - - - - - - - - - - - - - - - - - - - @@ -117,18 +34,4 @@ android:checked="true" android:textSize="14sp" /> - - - -