1 /* 2 * A800view.java - atari screen view 3 * 4 * Copyright (C) 2010 Kostas Nakos 5 * Copyright (C) 2010 Atari800 development team (see DOC/CREDITS) 6 * 7 * This file is part of the Atari800 emulator project which emulates 8 * the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers. 9 * 10 * Atari800 is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * Atari800 is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with Atari800; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 23 */ 24 25 package name.nick.jubanka.colleen; 26 27 import android.content.Context; 28 import android.opengl.GLSurfaceView; 29 import android.view.MotionEvent; 30 import android.view.KeyEvent; 31 import android.util.Log; 32 import android.view.KeyCharacterMap; 33 import android.os.Build; 34 import android.widget.Toast; 35 import android.view.View; 36 import android.util.SparseArray; 37 import android.os.Handler; 38 import android.os.Message; 39 import android.view.inputmethod.InputConnection; 40 import android.view.inputmethod.BaseInputConnection; 41 import android.view.inputmethod.EditorInfo; 42 import static android.view.KeyEvent.*; 43 44 45 public final class A800view extends GLSurfaceView 46 { 47 public static final int KEY_SHIFT = 256; 48 public static final int KEY_CONTROL = 257; 49 public static final int KEY_BACKSPACE = 255; 50 public static final int KEY_UP = 254; 51 public static final int KEY_DOWN = 253; 52 public static final int KEY_LEFT = 252; 53 public static final int KEY_RIGHT = 251; 54 public static final int KEY_FIRE = 250; 55 public static final int KEY_ENTER = 249; 56 public static final int KEY_ESCAPE = 248; 57 public static final int KEY_CENTER = 247; 58 public static final int KEY_BT_X = 246; 59 public static final int KEY_BT_Y = 245; 60 public static final int KEY_BT_L1 = 244; 61 public static final int KEY_BT_R1 = 243; 62 public static final int KEY_BREAK = 242; 63 // keycodes from newer sdks 64 public static final int KC_BUTTON_X = 307; 65 public static final int KC_BUTTON_Y = 308; 66 public static final int KC_BUTTON_L1 = 310; 67 public static final int KC_BUTTON_R1 = 311; 68 69 70 private static final String TAG = "A800View"; 71 private A800Renderer _renderer; 72 private KeyCharacterMap _keymap; 73 private int _key, _meta, _hit; 74 private TouchFactory _touchHandler = null; 75 private Toast _toastquit; 76 private Integer _xkey; 77 A800view(Context context)78 public A800view(Context context) { 79 super(context); 80 81 _renderer = new A800Renderer(); 82 setRenderer(_renderer); 83 _renderer.prepareToast(context); 84 _renderer.setHandler(new Handler() { 85 @Override 86 public void handleMessage(Message msg) { 87 ((MainActivity) getContext()).message(msg.what); 88 } 89 }); 90 91 setFocusable(true); 92 setFocusableInTouchMode(true); 93 requestFocus(); 94 95 _keymap = KeyCharacterMap.load(KeyCharacterMap.BUILT_IN_KEYBOARD); 96 97 if (Integer.parseInt(Build.VERSION.SDK) < Build.VERSION_CODES.ECLAIR) 98 _touchHandler = new SingleTouch(); 99 else 100 _touchHandler = new MultiTouch(); 101 102 _toastquit = Toast.makeText(context, R.string.pressback, Toast.LENGTH_SHORT); 103 } 104 pause(boolean p)105 public void pause(boolean p) { 106 setRenderMode(p ? GLSurfaceView.RENDERMODE_WHEN_DIRTY : 107 GLSurfaceView.RENDERMODE_CONTINUOUSLY); 108 } 109 110 // Touch input 111 @Override onTouchEvent(final MotionEvent ev)112 public boolean onTouchEvent(final MotionEvent ev) { 113 int ret = _touchHandler.onTouchEvent(ev); 114 115 if (Integer.parseInt(Build.VERSION.SDK) >= Build.VERSION_CODES.HONEYCOMB) { 116 MainActivity m = (MainActivity) getContext(); 117 if (ret == 2) 118 m._aBar.show(m); 119 else if (ret == 1) 120 m._aBar.hide(m); 121 } 122 return true; 123 } 124 125 abstract static class TouchFactory { onTouchEvent(MotionEvent ev)126 public abstract int onTouchEvent(MotionEvent ev); 127 }; 128 129 private static final class SingleTouch extends TouchFactory { 130 private int _x1, _y1, _s1; 131 private int _action, _actioncode; 132 133 134 @Override onTouchEvent(final MotionEvent ev)135 public int onTouchEvent(final MotionEvent ev) { 136 _action = ev.getAction(); 137 _actioncode = _action & MotionEvent.ACTION_MASK; 138 _x1 = (int) ev.getX(); 139 _y1 = (int) ev.getY(); 140 _s1 = 1; 141 if (_actioncode == MotionEvent.ACTION_UP) 142 _s1 = 0; 143 144 return NativeTouch(_x1, _y1, _s1, -1000, -1000, 0); 145 } 146 } 147 148 private static final class MultiTouch extends TouchFactory { 149 private int _x1, _y1, _s1, _x2, _y2, _s2; 150 private int _action, _actioncode, _ptrcnt; 151 152 @Override onTouchEvent(final MotionEvent ev)153 public int onTouchEvent(final MotionEvent ev) { 154 _action = ev.getAction(); 155 _actioncode = _action & MotionEvent.ACTION_MASK; 156 _ptrcnt = ev.getPointerCount(); 157 _x1 = (int) ev.getX(0); 158 _y1 = (int) ev.getY(0); 159 _s1 = 1; 160 if (_ptrcnt > 1) { 161 _x2 = (int) ev.getX(1); 162 _y2 = (int) ev.getY(1); 163 _s2 = 1; 164 } else { 165 _x2 = -1000; 166 _y2 = -1000; 167 _s2 = 0; 168 } 169 if (_actioncode == MotionEvent.ACTION_UP) { 170 _s1 = _s2 = 0; 171 } else if (_actioncode == MotionEvent.ACTION_POINTER_UP) { 172 if ( (_action >> MotionEvent.ACTION_POINTER_ID_SHIFT) == 0) 173 _s1 = 0; 174 else 175 _s2 = 0; 176 } 177 178 return NativeTouch(_x1, _y1, _s1, _x2, _y2, _s2); 179 } 180 } 181 182 // Key input 183 @Override onKeyDown(int kc, final KeyEvent ev)184 public boolean onKeyDown(int kc, final KeyEvent ev) { 185 return doKey(kc, ev); 186 } 187 188 @Override onKeyUp(int kc, final KeyEvent ev)189 public boolean onKeyUp(int kc, final KeyEvent ev) { 190 return doKey(kc, ev); 191 } 192 193 @Override onCheckIsTextEditor()194 public boolean onCheckIsTextEditor() { 195 return true; 196 } 197 198 @Override onCreateInputConnection(EditorInfo outAttrs)199 public InputConnection onCreateInputConnection (EditorInfo outAttrs) { 200 return new BaseInputConnection(this, false) { 201 @Override 202 public boolean deleteSurroundingText (int leftLength, int rightLength) { 203 //Log.d(TAG, "Synthetic del"); 204 this.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)); 205 this.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL)); 206 return true; 207 } 208 }; 209 } 210 211 private boolean doKey(int kc, final KeyEvent ev) { 212 _hit =(ev.getAction() == ACTION_DOWN) ? 1 : 0; 213 214 if (kc == KEYCODE_BACK && _hit == 1) { 215 MainActivity m = (MainActivity) getContext(); 216 if (_toastquit.getView().getWindowVisibility() == View.VISIBLE) { 217 _toastquit.cancel(); 218 m.finish(); 219 } else if (m._aBar.isShowing(m)) 220 m._aBar.hide(m); 221 else 222 _toastquit.show(); 223 return true; 224 } 225 226 _xkey = XLATKEYS.get(kc); 227 if (_xkey != null) 228 _key = _xkey.intValue(); 229 else { 230 _meta = ev.getMetaState(); 231 if ((_meta & KeyEvent.META_SHIFT_RIGHT_ON) == KeyEvent.META_SHIFT_RIGHT_ON) 232 _meta &= ~(KeyEvent.META_SHIFT_RIGHT_ON | KeyEvent.META_SHIFT_ON); 233 _key = _keymap.get(kc, _meta); 234 if (_key == 0) 235 return false; 236 } 237 238 //Log.d(TAG, String.format("key %d %d -> %d", ev.getAction(), kc, _key)); 239 240 NativeKey(_key, _hit); 241 242 return true; 243 } 244 245 private native static int NativeTouch(int x1, int y1, int s1, int x2, int y2, int s2); 246 private native void NativeKey(int keycode, int status); 247 248 public static final SparseArray<Integer> XLATKEYS = new SparseArray<Integer>(14); 249 static { 250 XLATKEYS.put(KEYCODE_DPAD_UP, KEY_UP); 251 XLATKEYS.put(KEYCODE_DPAD_DOWN, KEY_DOWN); 252 XLATKEYS.put(KEYCODE_DPAD_LEFT, KEY_LEFT); 253 XLATKEYS.put(KEYCODE_DPAD_RIGHT, KEY_RIGHT); 254 XLATKEYS.put(KEYCODE_DPAD_CENTER, KEY_BREAK); 255 XLATKEYS.put(KEYCODE_SEARCH, KEY_FIRE); 256 XLATKEYS.put(KEYCODE_SHIFT_LEFT, KEY_SHIFT); 257 XLATKEYS.put(KEYCODE_SHIFT_RIGHT, KEY_CONTROL); 258 XLATKEYS.put(KEYCODE_DEL, KEY_BACKSPACE); 259 XLATKEYS.put(KEYCODE_ENTER, KEY_ENTER); 260 XLATKEYS.put(KC_BUTTON_X, KEY_BT_X); 261 XLATKEYS.put(KC_BUTTON_Y, KEY_BT_Y); 262 XLATKEYS.put(KC_BUTTON_L1, KEY_BT_L1); 263 XLATKEYS.put(KC_BUTTON_R1, KEY_BT_R1); 264 } 265 } 266