diff --git a/Android/.idea/misc.xml b/Android/.idea/misc.xml index 8b7ac1cd..cd0c3b68 100644 --- a/Android/.idea/misc.xml +++ b/Android/.idea/misc.xml @@ -6,25 +6,6 @@ - - - - - - - - - Spelling - - - - - Spelling - - - - - 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 6e9cf793..effd5d98 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Activity.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Activity.java @@ -14,12 +14,12 @@ package org.deadc0de.apple2ix; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; -import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; +import android.view.MotionEvent; import java.io.File; import java.io.InputStream; @@ -35,15 +35,17 @@ public class Apple2Activity extends Activity { private final static String PREFS_CONFIGURED = "prefs_configured"; private Apple2View mView = null; + private int mWidth = 0; + private int mHeight = 0; static { System.loadLibrary("apple2ix"); } private native void nativeOnCreate(String dataDir); - private native void nativeOnResume(); - private native void nativeOnPause(); - public native void nativeGraphicsInitialized(int width, int height); + public native void nativeOnResume(); + public native void nativeOnPause(); + private native void nativeGraphicsInitialized(int width, int height); public native void nativeRender(); private native void nativeOnKeyDown(int keyCode, int metaState); private native void nativeOnKeyUp(int keyCode, int metaState); @@ -87,7 +89,7 @@ public class Apple2Activity extends Activity { Log.d(TAG, "Saving default preferences"); SharedPreferences.Editor editor = settings.edit(); editor.putBoolean(PREFS_CONFIGURED, true); - editor.commit(); + editor.apply(); return dataDir; } @@ -100,16 +102,9 @@ public class Apple2Activity extends Activity { new File(outputPath).mkdirs(); InputStream is = getAssets().open(subdir+File.separator+assetName); - if (is == null) { - Log.e(TAG, "inputstream is null"); - } File file = new File(outputPath+File.separator+assetName); file.setWritable(true); - FileOutputStream os = new FileOutputStream(file); - if (os == null) { - Log.e(TAG, "outputstream is null"); - } byte[] buf = new byte[BUF_SZ]; while (true) { @@ -161,4 +156,23 @@ public class Apple2Activity extends Activity { return true; } + @Override + public boolean onTouchEvent(MotionEvent event) { + Log.d(TAG, "onTouchEvent..."); + return true; + } + + public void graphicsInitialized(int width, int height) { + mWidth = width; + mHeight = height; + nativeGraphicsInitialized(width, height); + } + + public int getWidth() { + return mWidth; + } + + public int getHeight() { + return mHeight; + } } diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2MainMenu.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2MainMenu.java new file mode 100644 index 00000000..396a4b37 --- /dev/null +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2MainMenu.java @@ -0,0 +1,128 @@ +/* + * Apple // emulator for *nix + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +package org.deadc0de.apple2ix; + +import android.content.Context; +import android.util.Log; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.PopupWindow; + +public class Apple2MainMenu { + + public final static int MENU_INSET = 20; + + private final static String TAG = "Apple2MainMenu"; + + private Apple2Activity mActivity = null; + private Apple2View mParentView = null; + private PopupWindow mMainMenuPopup = null; + + public Apple2MainMenu(Apple2Activity activity, Apple2View parent) { + mActivity = activity; + mParentView = parent; + init(); + } + + private void init() { + + LayoutInflater inflater = (LayoutInflater)mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View listLayout=inflater.inflate(R.layout.activity_main_menu, null, false); + ListView mainMenuView = (ListView)listLayout.findViewById(R.id.main_popup_menu); + mainMenuView.setEnabled(true); + LinearLayout mainPopupContainer = (LinearLayout)listLayout.findViewById(R.id.main_popup_container); + String[] values = new String[] { + "Emulation Settings...", + "Load Disk Image...", + "Resume...", + }; + + ArrayAdapter adapter = new ArrayAdapter(mActivity, android.R.layout.simple_list_item_1, android.R.id.text1, values); + mainMenuView.setAdapter(adapter); + mainMenuView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + switch (position) { + case 0: + Apple2MainMenu.this.showSettings(); + break; + case 1: + Apple2MainMenu.this.showDisksMenu(); + break; + default: + Apple2MainMenu.this.dismiss(); + break; + } + } + }); + + // WTF ... is there an easier way to dynamically calculate these dimensions? + int totalHeight = 0; + int maxWidth = 0; + for (int i=0; i maxWidth) { + maxWidth = width; + } + } + + mMainMenuPopup = new PopupWindow(mainPopupContainer, maxWidth+MENU_INSET, totalHeight+MENU_INSET, true); + } + + public void showDisksMenu() { + Log.d(TAG, "showDisksMenu..."); + } + + public void showSettings() { + Log.d(TAG, "showSettings..."); + } + + public void quitEmulator() { + + } + + public void show() { + if (mMainMenuPopup.isShowing()) { + return; + } + + mActivity.nativeOnPause(); + + int x = (mActivity.getWidth()-mMainMenuPopup.getWidth())/2; + int y = (mActivity.getHeight()-mMainMenuPopup.getHeight())/2; + + mMainMenuPopup.showAtLocation(mParentView, Gravity.NO_GRAVITY, x, y); + } + + public void dismiss() { + if (mMainMenuPopup.isShowing()) { + mActivity.nativeOnResume(); + mMainMenuPopup.dismiss(); + } + } + + public void androidBackButton() { + dismiss(); + } + + public boolean isShowing() { + return mMainMenuPopup.isShowing(); + } +} 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 a2f8751e..8dd15d9f 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2View.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2View.java @@ -15,12 +15,9 @@ package org.deadc0de.apple2ix; -import android.content.Context; import android.graphics.PixelFormat; import android.opengl.GLSurfaceView; -import android.util.AttributeSet; import android.util.Log; -import android.view.KeyEvent; import android.view.MotionEvent; import javax.microedition.khronos.egl.EGL10; @@ -50,8 +47,17 @@ 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 ... @@ -96,6 +102,84 @@ 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) { + showMultiTapMenu(); + } + 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) { + mMainMenu.show(); + } + } + + public void showMultiTapMenu() { + Log.d(TAG, "showMultiTapMenu..."); + } + private static class ContextFactory implements GLSurfaceView.EGLContextFactory { private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098; public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) { @@ -310,7 +394,8 @@ class Apple2View extends GLSurfaceView { } public void onSurfaceChanged(GL10 gl, int width, int height) { - Apple2View.this.mActivity.nativeGraphicsInitialized(width, height); + Apple2View.this.mActivity.graphicsInitialized(width, height); + Apple2View.this.mMainMenu = new Apple2MainMenu(Apple2View.this.mActivity, Apple2View.this); } public void onSurfaceCreated(GL10 gl, EGLConfig config) { diff --git a/Android/app/src/main/res/layout/activity_main_menu.xml b/Android/app/src/main/res/layout/activity_main_menu.xml new file mode 100644 index 00000000..d3f1ac28 --- /dev/null +++ b/Android/app/src/main/res/layout/activity_main_menu.xml @@ -0,0 +1,14 @@ + + + + diff --git a/Android/app/src/main/res/values/strings.xml b/Android/app/src/main/res/values/strings.xml index 23ac1524..a7bf5b49 100644 --- a/Android/app/src/main/res/values/strings.xml +++ b/Android/app/src/main/res/values/strings.xml @@ -1,3 +1,4 @@ Apple2ix + #000000 diff --git a/Android/jni/jnihooks.c b/Android/jni/jnihooks.c index 5222c7cd..fe4297cc 100644 --- a/Android/jni/jnihooks.c +++ b/Android/jni/jnihooks.c @@ -56,10 +56,12 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeGraphicsInitialized(JNIEnv void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnResume(JNIEnv *env, jobject obj) { LOG("%s", "native onResume..."); + pthread_mutex_unlock(&interface_mutex); } void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnPause(JNIEnv *env, jobject obj) { LOG("%s", "native onPause..."); + pthread_mutex_lock(&interface_mutex); } void Java_org_deadc0de_apple2ix_Apple2Activity_nativeRender(JNIEnv *env, jobject obj) {