/** * Copyright 2008 - 2011 * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * * @project loon * @author cping * @email:javachenpeng@yahoo.com * @version 0.1 */ package loon; import loon.core.EmulatorButtons; import loon.core.event.ActionKey; import loon.utils.collection.IntArray; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.View.OnKeyListener; import android.view.View.OnTouchListener; public class AndroidInputFactory implements OnKeyListener, OnTouchListener { public static void setOnscreenKeyboardVisible(final boolean visible) { LSystem.getOSHandler().post(new Runnable() { public void run() { android.view.inputmethod.InputMethodManager manager = (android.view.inputmethod.InputMethodManager) LSystem .getActivity().getSystemService( android.content.Context.INPUT_METHOD_SERVICE); if (visible) { AndroidView gameview = LSystem.getActivity().gameView(); if (gameview != null) { View view = gameview.getView(); view.setFocusable(true); view.setFocusableInTouchMode(true); manager.showSoftInput(view, 0); } } else { AndroidView gameview = LSystem.getActivity().gameView(); if (gameview != null) { View view = gameview.getView(); view.setFocusable(true); view.setFocusableInTouchMode(true); manager.hideSoftInputFromWindow(view.getWindowToken(), 0); } } } }); } private static boolean useTouchCollection = false; public static void startTouchCollection() { useTouchCollection = true; } public static void stopTouchCollection() { useTouchCollection = false; } private static LTouchCollection touchCollection = new LTouchCollection(); public static LTouchCollection getTouchState() { LTouchCollection result = new LTouchCollection(touchCollection); touchCollection.update(); return result; } public static void resetTouch() { touchCollection.clear(); } final static IntArray keys = new IntArray(); private float offsetTouchX, offsetMoveX, offsetTouchY, offsetMoveY; private final LProcess handler; final static LTouch finalTouch = new LTouch(); final static LKey finalKey = new LKey(); private long keyTimeMillis; static boolean isDraging; private int halfWidth, halfHeight; public AndroidInputFactory(LProcess handler) { this.handler = handler; this.halfWidth = handler.getWidth() / 2; this.halfHeight = handler.getHeight() / 2; } final static ActionKey only_key = new ActionKey( ActionKey.DETECT_INITIAL_PRESS_ONLY); public static ActionKey getOnlyKey() { return only_key; } private void callKey(KeyEvent e) { try { LSystem.AUTO_REPAINT = false; char charCode = (char) e.getUnicodeChar(); if (e.getKeyCode() == 67) { charCode = '\b'; } switch (e.getAction()) { case android.view.KeyEvent.ACTION_DOWN: long curTime = System.currentTimeMillis(); // 让每次执行键盘事件,至少间隔1/5秒 if ((curTime - keyTimeMillis) > LSystem.SECOND / 5) { keyTimeMillis = curTime; finalKey.timer = e.getEventTime(); finalKey.keyChar = charCode; finalKey.keyCode = e.getKeyCode(); finalKey.type = Key.KEY_DOWN; if (finalKey.keyCode == android.view.KeyEvent.KEYCODE_BACK && e.isAltPressed()) { finalKey.keyCode = Key.BUTTON_CIRCLE; } only_key.press(); handler.keyDown(finalKey); keys.add(finalKey.keyCode); } break; case android.view.KeyEvent.ACTION_UP: finalKey.timer = e.getEventTime(); finalKey.keyChar = charCode; finalKey.keyCode = e.getKeyCode(); finalKey.type = Key.KEY_UP; if (finalKey.keyCode == android.view.KeyEvent.KEYCODE_BACK && e.isAltPressed()) { finalKey.keyCode = Key.BUTTON_CIRCLE; } only_key.release(); handler.keyUp(finalKey); keys.removeValue(finalKey.keyCode); break; default: only_key.reset(); keys.clear(); } } finally { LSystem.AUTO_REPAINT = true; } } private ActionKey _close_key = new ActionKey( ActionKey.DETECT_INITIAL_PRESS_ONLY); @Override public boolean onKey(View v, int keyCode, KeyEvent e) { if (keyCode == KeyEvent.KEYCODE_BACK) { if (!LSystem.isBackLocked) { if (android.view.KeyEvent.ACTION_UP == e.getAction() && _close_key.isPressed()) { _close_key.release(); } else if (android.view.KeyEvent.ACTION_DOWN == e.getAction() && !_close_key.isPressed()) { _close_key.press(); Runnable runnable = new Runnable() { @Override public void run() { LSystem.screenActivity .showAndroidYesOrNo( "Exit", "Do you want to Quit ? ", true, "Yes", "No", new android.content.DialogInterface.OnClickListener() { @Override public void onClick( android.content.DialogInterface dialog, int which) { LSystem.AUTO_REPAINT = false; LSystem.exit(); } }, new android.content.DialogInterface.OnClickListener() { @Override public void onClick( android.content.DialogInterface dialog, int which) { LSystem.AUTO_REPAINT = true; } }); } }; LSystem.runOnUiThread(runnable); } } callKey(e); return true; } else { _close_key.release(); } if (keyCode == KeyEvent.KEYCODE_MENU) { return false; } if (handler == null) { return true; } synchronized (this) { callKey(e); } return false; } public void callKeyboard(final boolean visible) { LSystem.runOnUiThread(new Runnable() { @Override public void run() { android.view.inputmethod.InputMethodManager manager = (android.view.inputmethod.InputMethodManager) LSystem .getActivity().getSystemService( android.content.Context.INPUT_METHOD_SERVICE); View view = LSystem.getActivity().gameView().getView(); if (visible) { view.setFocusable(true); view.setFocusableInTouchMode(true); manager.showSoftInput(view, 0); } else { manager.hideSoftInputFromWindow(view.getWindowToken(), 0); } } }); } private boolean requestFocus = true; public boolean onTouch(View v, MotionEvent e) { if (handler == null) { return true; } if (requestFocus && LSystem.getActivity() != null) { if (requestFocus && LSystem.getActivity().gameView() != null) { View view = LSystem.getActivity().gameView().getView(); view.requestFocus(); view.requestFocusFromTouch(); requestFocus = false; } } EmulatorButtons ebs = handler.emulatorButtons; if (ebs != null && ebs.isVisible()) { ebs.onEmulatorButtonEvent(e); } try { float touchX; float touchY; int code = e.getAction(); if (AndroidMultitouchUtils.isMultitouch()) { final int action = code & AndroidMultitouchUtils.ACTION_MASK; int pointerIndex = (code & AndroidMultitouchUtils.ACTION_POINTER_ID_MASK) >> AndroidMultitouchUtils.ACTION_POINTER_ID_SHIFT; int pointerId = AndroidMultitouchUtils.getPointId(e, pointerIndex); int pointerCount = AndroidMultitouchUtils.getPointerCount(e); touchX = (AndroidMultitouchUtils.getX(e, pointerId) - handler .getX()) / LSystem.scaleWidth; touchY = (AndroidMultitouchUtils.getY(e, pointerId) - handler .getY()) / LSystem.scaleHeight; finalTouch.x = touchX; finalTouch.y = touchY; finalTouch.pointer = pointerCount; finalTouch.id = pointerId; switch (action) { case AndroidMultitouchUtils.ACTION_DOWN: case AndroidMultitouchUtils.ACTION_POINTER_DOWN: if (useTouchCollection) { touchCollection.add(finalTouch.id, finalTouch.x, finalTouch.y); } offsetTouchX = touchX; offsetTouchY = touchY; if ((touchX < halfWidth) && (touchY < halfHeight)) { finalTouch.type = Touch.UPPER_LEFT; } else if ((touchX >= halfWidth) && (touchY < halfHeight)) { finalTouch.type = Touch.UPPER_RIGHT; } else if ((touchX < halfWidth) && (touchY >= halfHeight)) { finalTouch.type = Touch.LOWER_LEFT; } else { finalTouch.type = Touch.LOWER_RIGHT; } finalTouch.button = Touch.TOUCH_DOWN; handler.mousePressed(finalTouch); isDraging = false; break; case AndroidMultitouchUtils.ACTION_UP: case AndroidMultitouchUtils.ACTION_POINTER_UP: case AndroidMultitouchUtils.ACTION_OUTSIDE: case AndroidMultitouchUtils.ACTION_CANCEL: if (useTouchCollection) { touchCollection.update(finalTouch.id, LTouchLocationState.Released, finalTouch.x, finalTouch.y); } if (finalTouch.button == Touch.TOUCH_DOWN || finalTouch.button == Touch.TOUCH_MOVE) { finalTouch.button = Touch.TOUCH_UP; } handler.mouseReleased(finalTouch); isDraging = false; break; case AndroidMultitouchUtils.ACTION_MOVE: offsetMoveX = touchX; offsetMoveY = touchY; if (Math.abs(offsetTouchX - offsetMoveX) > 5 || Math.abs(offsetTouchY - offsetMoveY) > 5) { if (useTouchCollection) { touchCollection.update(finalTouch.id, LTouchLocationState.Dragged, finalTouch.x, finalTouch.y); } finalTouch.button = Touch.TOUCH_MOVE; handler.mouseMoved(finalTouch); isDraging = true; } break; default: if (useTouchCollection) { touchCollection.update(finalTouch.id, LTouchLocationState.Invalid, finalTouch.x, finalTouch.y); } break; } return true; } else { touchX = (e.getX() - handler.getX()) / LSystem.scaleWidth; touchY = (e.getY() - handler.getY()) / LSystem.scaleHeight; finalTouch.x = touchX; finalTouch.y = touchY; finalTouch.pointer = 1; finalTouch.id = 0; switch (code) { case MotionEvent.ACTION_DOWN: if (useTouchCollection) { touchCollection.add(finalTouch.id, finalTouch.x, finalTouch.y); } offsetTouchX = touchX; offsetTouchY = touchY; if ((touchX < halfWidth) && (touchY < halfHeight)) { finalTouch.type = Touch.UPPER_LEFT; } else if ((touchX >= halfWidth) && (touchY < halfHeight)) { finalTouch.type = Touch.UPPER_RIGHT; } else if ((touchX < halfWidth) && (touchY >= halfHeight)) { finalTouch.type = Touch.LOWER_LEFT; } else { finalTouch.type = Touch.LOWER_RIGHT; } finalTouch.button = Touch.TOUCH_DOWN; handler.mousePressed(finalTouch); isDraging = false; return true; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_OUTSIDE: case MotionEvent.ACTION_CANCEL: if (useTouchCollection) { touchCollection.update(finalTouch.id, LTouchLocationState.Released, finalTouch.x, finalTouch.y); } finalTouch.button = Touch.TOUCH_UP; handler.mouseReleased(finalTouch); isDraging = false; return true; case MotionEvent.ACTION_MOVE: offsetMoveX = touchX; offsetMoveY = touchY; if (Math.abs(offsetTouchX - offsetMoveX) > 5 || Math.abs(offsetTouchY - offsetMoveY) > 5) { if (useTouchCollection) { touchCollection.update(finalTouch.id, LTouchLocationState.Dragged, finalTouch.x, finalTouch.y); } finalTouch.button = Touch.TOUCH_MOVE; handler.mouseMoved(finalTouch); isDraging = true; return true; } break; default: if (useTouchCollection) { touchCollection.update(finalTouch.id, LTouchLocationState.Invalid, finalTouch.x, finalTouch.y); } break; } } } catch (Exception ex) { Log.d("on Touch !", ex.getMessage()); } finally { try { Thread.sleep(16); } catch (InterruptedException ei) { } } return false; } }