private void setContext(MotionEvent curr) { if (mCurrEvent != null) { mCurrEvent.recycle(); } mCurrEvent = MotionEvent.obtain(curr); mCurrLen = -1; mPrevLen = -1; mScaleFactor = -1; final MotionEvent prev = mPrevEvent; final float px0 = prev.getX(0); final float py0 = prev.getY(0); final float px1 = prev.getX(1); final float py1 = prev.getY(1); final float cx0 = curr.getX(0); final float cy0 = curr.getY(0); final float cx1 = curr.getX(1); final float cy1 = curr.getY(1); final float pvx = px1 - px0; final float pvy = py1 - py0; final float cvx = cx1 - cx0; final float cvy = cy1 - cy0; mPrevFingerDiffX = pvx; mPrevFingerDiffY = pvy; mCurrFingerDiffX = cvx; mCurrFingerDiffY = cvy; mTimeDelta = curr.getEventTime() - prev.getEventTime(); mCurrPressure = curr.getPressure(0) + curr.getPressure(1); mPrevPressure = prev.getPressure(0) + prev.getPressure(1); }
// Touch events @Override public boolean onTouch(View v, MotionEvent event) { final int touchDevId = event.getDeviceId(); final int pointerCount = event.getPointerCount(); // touchId, pointerId, action, x, y, pressure int actionPointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT; /* API 8: event.getActionIndex(); */ int pointerFingerId = event.getPointerId(actionPointerIndex); int action = (event.getAction() & MotionEvent.ACTION_MASK); /* API 8: event.getActionMasked(); */ float x = event.getX(actionPointerIndex) / mWidth; float y = event.getY(actionPointerIndex) / mHeight; float p = event.getPressure(actionPointerIndex); if (action == MotionEvent.ACTION_MOVE && pointerCount > 1) { // TODO send motion to every pointer if its position has // changed since prev event. for (int i = 0; i < pointerCount; i++) { pointerFingerId = event.getPointerId(i); x = event.getX(i) / mWidth; y = event.getY(i) / mHeight; p = event.getPressure(i); SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p); } } else { SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p); } return true; }
/** * Extracts the touch point data from a MotionEvent, converts each point into a marshallable * object and passes the set of points to the JNI layer to be transmitted to the remote host. * * @param event The event to send to the remote host for injection. NOTE: This object must be * updated to represent the remote machine's coordinate system before calling this function. */ public void sendTouchEvent(MotionEvent event) { int action = event.getActionMasked(); TouchEventData.EventType touchEventType = TouchEventData.EventType.fromMaskedAction(action); List<TouchEventData> touchEventList = new ArrayList<TouchEventData>(); if (action == MotionEvent.ACTION_MOVE) { // In order to process all of the events associated with an ACTION_MOVE event, we need // to walk the list of historical events in order and add each event to our list, then // retrieve the current move event data. int pointerCount = event.getPointerCount(); int historySize = event.getHistorySize(); for (int h = 0; h < historySize; ++h) { for (int p = 0; p < pointerCount; ++p) { touchEventList.add( new TouchEventData( event.getPointerId(p), event.getHistoricalX(p, h), event.getHistoricalY(p, h), event.getHistoricalSize(p, h), event.getHistoricalSize(p, h), event.getHistoricalOrientation(p, h), event.getHistoricalPressure(p, h))); } } for (int p = 0; p < pointerCount; p++) { touchEventList.add( new TouchEventData( event.getPointerId(p), event.getX(p), event.getY(p), event.getSize(p), event.getSize(p), event.getOrientation(p), event.getPressure(p))); } } else { // For all other events, we only want to grab the current/active pointer. The event // contains a list of every active pointer but passing all of of these to the host can // cause confusion on the remote OS side and result in broken touch gestures. int activePointerIndex = event.getActionIndex(); touchEventList.add( new TouchEventData( event.getPointerId(activePointerIndex), event.getX(activePointerIndex), event.getY(activePointerIndex), event.getSize(activePointerIndex), event.getSize(activePointerIndex), event.getOrientation(activePointerIndex), event.getPressure(activePointerIndex))); } if (!touchEventList.isEmpty()) { mInjector.sendTouchEvent(touchEventType, touchEventList.toArray(new TouchEventData[0])); } }
@Override public boolean onTouchEvent(MotionEvent event) { float mCurX; float mCurY; // API level 9 and above supports "Major" property on event which // gives // the size of the touch area at the point of contact // so for now we just hard code float TOUCH_AREA_SIZE = penWidth; int action = event.getAction(); if (action != MotionEvent.ACTION_UP && action != MotionEvent.ACTION_CANCEL) { int N = event.getHistorySize(); int P = event.getPointerCount(); for (int i = 0; i < N; i++) { for (int j = 0; j < P; j++) { mCurX = event.getHistoricalX(j, i); mCurY = event.getHistoricalY(j, i); drawPoint(mCurX, mCurY, event.getHistoricalPressure(j, i), TOUCH_AREA_SIZE); } } for (int j = 0; j < P; j++) { mCurX = event.getX(j); mCurY = event.getY(j); drawPoint(mCurX, mCurY, event.getPressure(j), TOUCH_AREA_SIZE); } } unsaved = true; return true; }
@Override public void onTouchEvent(MotionEvent e) { float x = e.getX(); float y = e.getY(); switch (e.getAction()) { case MotionEvent.ACTION_UP: x = x * .001f; y = y * .001f; for (int i = 0; i < _scene.numChildren(); i++) { Object3d obj = _scene.getChildAt(i); if (obj == _up || obj == _down || obj == _east || obj == _west) continue; // TODO: make pressure equal to distance from touch obj.velocity().z = -(e.getPressure() * 100); obj.velocity().z = -(e.getPressure() * 100); } break; case MotionEvent.ACTION_MOVE: float dx = x - mPreviousX; float dy = y - mPreviousY; for (int i = 0; i < _scene.numChildren(); i++) { Object3d obj = _scene.getChildAt(i); if (obj == _up || obj == _down || obj == _east || obj == _west) continue; obj.rotation().x += dx * Object3d.TOUCH_SCALE_FACTOR; obj.rotation().y += dy * Object3d.TOUCH_SCALE_FACTOR; } break; } mPreviousX = x; mPreviousY = y; }
// Touch events @Override public boolean onTouch(View v, MotionEvent event) { /* Ref: http://developer.android.com/training/gestures/multi.html */ final int touchDevId = event.getDeviceId(); final int pointerCount = event.getPointerCount(); int action = event.getActionMasked(); int pointerFingerId; int i = -1; float x, y, p; switch (action) { case MotionEvent.ACTION_MOVE: for (i = 0; i < pointerCount; i++) { pointerFingerId = event.getPointerId(i); x = event.getX(i) / mWidth; y = event.getY(i) / mHeight; p = event.getPressure(i); SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p); } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_DOWN: // Primary pointer up/down, the index is always zero i = 0; case MotionEvent.ACTION_POINTER_UP: case MotionEvent.ACTION_POINTER_DOWN: // Non primary pointer up/down if (i == -1) { i = event.getActionIndex(); } pointerFingerId = event.getPointerId(i); x = event.getX(i) / mWidth; y = event.getY(i) / mHeight; p = event.getPressure(i); SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p); break; default: break; } return true; }
// returns the WebTouchEvent::Type for the MotionEvent and -1 for failure public static int createTouchPoints(MotionEvent event, TouchPoint[] pts) { int type; int defaultState; switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: type = TOUCH_EVENT_TYPE_START; defaultState = TOUCH_POINT_STATE_PRESSED; break; case MotionEvent.ACTION_MOVE: type = TOUCH_EVENT_TYPE_MOVE; defaultState = TOUCH_POINT_STATE_MOVED; break; case MotionEvent.ACTION_UP: type = TOUCH_EVENT_TYPE_END; defaultState = TOUCH_POINT_STATE_RELEASED; break; case MotionEvent.ACTION_CANCEL: type = TOUCH_EVENT_TYPE_CANCEL; defaultState = TOUCH_POINT_STATE_CANCELLED; break; case MotionEvent.ACTION_POINTER_DOWN: // fall through. case MotionEvent.ACTION_POINTER_UP: type = TOUCH_EVENT_TYPE_MOVE; defaultState = TOUCH_POINT_STATE_STATIONARY; break; default: Log.e("Chromium", "Unknown motion event action: " + event.getActionMasked()); return CONVERSION_ERROR; } for (int i = 0; i < pts.length; ++i) { int state = defaultState; if (defaultState == TOUCH_POINT_STATE_STATIONARY && event.getActionIndex() == i) { // An additional pointer has started or ended. Map this pointer state as // required, and all other pointers as "stationary". state = event.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN ? TOUCH_POINT_STATE_PRESSED : TOUCH_POINT_STATE_RELEASED; } pts[i] = new TouchPoint( state, event.getPointerId(i), event.getX(i), event.getY(i), event.getSize(i), event.getPressure(i)); } return type; }
// Touch events public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); float x = event.getX(); float y = event.getY(); float p = event.getPressure(); // TODO: Anything else we need to pass? SDLActivity.onNativeTouch(action, x, y, p); return true; }
public boolean onTouch(View view, MotionEvent motionEvent) { int viewHeight = view.getHeight(); int viewWidth = view.getWidth(); Point currentPosition = new Point(viewWidth / 2, viewHeight / 2); if (pie == null || (pie != null && pie.getPosition().equals(currentPosition))) { pie = new PieTouchArea(150, 8, currentPosition, -22); } int area = pie.getArea(new Point(motionEvent.getX(), motionEvent.getY())); if (D) { Log.d( TAG, String.format("Touched in %s (%d, %d) at %s)", view, viewWidth, viewHeight, area)); } int speed = (int) (motionEvent.getPressure() * BlueCar.MAX_SPEED * 3); if (speed > BlueCar.MAX_SPEED) speed = BlueCar.MAX_SPEED; int command = 0; switch (area) { case 0: command = BlueCar.CMD_STRAIGHT_FORWARD; break; case 1: command = BlueCar.CMD_RIGHT_FORWARD; break; case 2: command = BlueCar.CMD_RIGHT_NO_DRIVE; break; case 3: command = BlueCar.CMD_RIGHT_BACKWARD; break; case 4: command = BlueCar.CMD_STRAIGHT_BACKWARD; break; case 5: command = BlueCar.CMD_LEFT_BACKWARD; break; case 6: command = BlueCar.CMD_LEFT_NO_DRIVE; break; case 7: command = BlueCar.CMD_LEFT_FORWARD; break; } command = command + speed; return sendCommand(command); }
public static void sendTouchEvent(MotionEvent event, int id) { // @!ANDROID-4 touchBegin(id); for (int i = 0; i < event.getPointerCount(); i++) touchAdd( id, event.getPointerId(i), getAction(i, event), i == 0, (int) event.getX(i), (int) event.getY(i), event.getSize(i), event.getPressure(i)); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: touchEnd(id, 0); break; case MotionEvent.ACTION_UP: touchEnd(id, 2); break; default: touchEnd(id, 1); } // @!ANDROID-4 switch (event.getAction()) { case MotionEvent.ACTION_UP: mouseUp(id, (int) event.getX(), (int) event.getY()); break; case MotionEvent.ACTION_DOWN: mouseDown(id, (int) event.getX(), (int) event.getY()); m_oldx = (int) event.getX(); m_oldy = (int) event.getY(); break; case MotionEvent.ACTION_MOVE: int dx = (int) (event.getX() - m_oldx); int dy = (int) (event.getY() - m_oldy); if (Math.abs(dx) > m_moveThreshold || Math.abs(dy) > m_moveThreshold) { mouseMove(id, (int) event.getX(), (int) event.getY()); m_oldx = (int) event.getX(); m_oldy = (int) event.getY(); } break; } }
public void addMotionPoint(int index, int eventIndex, MotionEvent event) { try { PointF geckoPoint = new PointF(event.getX(eventIndex), event.getY(eventIndex)); geckoPoint = GeckoApp.mAppContext.getLayerView().convertViewPointToLayerPoint(geckoPoint); mPoints[index] = new Point(Math.round(geckoPoint.x), Math.round(geckoPoint.y)); mPointIndicies[index] = event.getPointerId(eventIndex); // getToolMajor, getToolMinor and getOrientation are API Level 9 features if (Build.VERSION.SDK_INT >= 9) { double radians = event.getOrientation(eventIndex); mOrientations[index] = (float) Math.toDegrees(radians); // w3c touchevents spec does not allow orientations == 90 // this shifts it to -90, which will be shifted to zero below if (mOrientations[index] == 90) mOrientations[index] = -90; // w3c touchevent radius are given by an orientation between 0 and 90 // the radius is found by removing the orientation and measuring the x and y // radius of the resulting ellipse // for android orientations >= 0 and < 90, the major axis should correspond to // just reporting the y radius as the major one, and x as minor // however, for a radius < 0, we have to shift the orientation by adding 90, and // reverse which radius is major and minor if (mOrientations[index] < 0) { mOrientations[index] += 90; mPointRadii[index] = new Point( (int) event.getToolMajor(eventIndex) / 2, (int) event.getToolMinor(eventIndex) / 2); } else { mPointRadii[index] = new Point( (int) event.getToolMinor(eventIndex) / 2, (int) event.getToolMajor(eventIndex) / 2); } } else { float size = event.getSize(eventIndex); Resources resources = GeckoApp.mAppContext.getResources(); DisplayMetrics displaymetrics = resources.getDisplayMetrics(); size = size * Math.min(displaymetrics.heightPixels, displaymetrics.widthPixels); mPointRadii[index] = new Point((int) size, (int) size); mOrientations[index] = 0; } mPressures[index] = event.getPressure(eventIndex); } catch (Exception ex) { Log.e(LOGTAG, "Error creating motion point " + index, ex); mPointRadii[index] = new Point(0, 0); mPoints[index] = new Point(0, 0); } }
@Override public boolean onDoubleTap(MotionEvent event) { final int action = event.getAction(); final int pointerIndex = (action & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT; final int pointerId = event.getPointerId(pointerIndex); OFAndroid.onTouchDoubleTap( pointerId, event.getX(pointerIndex), event.getY(pointerIndex), event.getPressure(pointerIndex)); return true; // return super.onDoubleTap(e); }
private void addPointerForIndex(MotionEvent event, int pointerIndex, List<Pointer> result) { Integer pointerType = getPointerTypeForAction(event.getActionMasked()); if (pointerType == null) { return; } Pointer pointer = new Pointer(); pointer.timeStamp = event.getEventTime() * 1000; // Convert from milliseconds to microseconds. pointer.pointer = event.getPointerId(pointerIndex); pointer.type = pointerType; pointer.kind = PointerKind.TOUCH; pointer.x = event.getX(pointerIndex); pointer.y = event.getY(pointerIndex); pointer.buttons = 0; pointer.down = false; pointer.primary = false; pointer.obscured = false; // TODO(eseidel): Could get the calibrated range if necessary: // event.getDevice().getMotionRange(MotionEvent.AXIS_PRESSURE) pointer.pressure = event.getPressure(pointerIndex); pointer.pressureMin = 0.0f; pointer.pressureMax = 1.0f; pointer.distance = 0.0f; pointer.distanceMin = 0.0f; pointer.distanceMax = 0.0f; pointer.radiusMajor = 0.0f; pointer.radiusMinor = 0.0f; pointer.radiusMin = 0.0f; pointer.radiusMax = 0.0f; pointer.orientation = 0.0f; pointer.tilt = 0.0f; result.add(pointer); }
private boolean processMoveEvent(MotionEvent ev) { if (pointerId != INVALID_POINTER_ID) { final int pointerIndex = ev.findPointerIndex(pointerId); // Translate touch position to center of view float x = ev.getX(pointerIndex); touchX = x - cX - offsetX; float y = ev.getY(pointerIndex); touchY = y - cY - offsetY; // Log.d(TAG, String.format("ACTION_MOVE: (%03.0f, %03.0f) => (%03.0f, %03.0f)", x, y, // touchX, touchY)); reportOnMoved(); invalidate(); touchPressure = ev.getPressure(pointerIndex); reportOnPressure(); return true; } return false; }
/** * Strips the last pointer from a {@link MotionEvent} and returns the modified event. Does not * modify the original event. * * @param ev The MotionEvent to modify. * @return The modified MotionEvent. */ private MotionEvent stripLastPointer(MotionEvent ev) { ev.getPointerCount(); int removePointer = ev.getPointerCount() - 1; int removePointerId = ev.getPointerId(removePointer); long downTime = ev.getDownTime(); long eventTime = ev.getEventTime(); int action = ev.getAction(); int pointers = ev.getPointerCount() - 1; int[] pointerIds = new int[pointers]; int metaState = ev.getMetaState(); float xPrecision = ev.getXPrecision(); float yPrecision = ev.getYPrecision(); int deviceId = ev.getDeviceId(); int edgeFlags = ev.getEdgeFlags(); switch (ev.getActionMasked()) { case MotionEvent.ACTION_POINTER_DOWN: case MotionEvent.ACTION_POINTER_UP: action -= 0x100; if (pointers == 1) { action -= 0x5; } break; } MotionEvent event = null; if (mCompatibilityMode) { float x = ev.getX(); float y = ev.getY(); float pressure = ev.getPressure(); float size = ev.getSize(); event = MotionEvent.obtain( downTime, eventTime, action, pointers, x, y, pressure, size, metaState, xPrecision, yPrecision, deviceId, edgeFlags); } // XXX commented out to get this to compile ! /* else { PointerCoords[] pointerCoords = new PointerCoords[pointers]; int source = ev.getSource(); int flags = ev.getFlags(); for (int i = 0; i < pointers; i++) { pointerIds[i] = ev.getPointerId(i); pointerCoords[i] = new PointerCoords(); ev.getPointerCoords(i, pointerCoords[i]); } event = MotionEvent.obtain(downTime, eventTime, action, pointers, pointerIds, pointerCoords, metaState, xPrecision, yPrecision, deviceId, edgeFlags, source, flags); } */ return event; }
private void logMotionEvent(MotionEvent event, boolean gen) { String s = gen ? "GenericMotionEvent from " : "TouchEvent from "; s += printDevice(event.getDeviceId()) + " source " + printSource(event.getSource()); int pointerCount = event.getPointerCount(); String action; switch (event.getActionMasked()) { case MotionEvent.ACTION_CANCEL: action = "cancel"; break; case MotionEvent.ACTION_DOWN: action = "down"; break; case MotionEvent.ACTION_HOVER_ENTER: action = "hover_enter"; break; case MotionEvent.ACTION_HOVER_EXIT: action = "hover_exit"; break; case MotionEvent.ACTION_HOVER_MOVE: action = "hover_move"; break; case MotionEvent.ACTION_MOVE: action = "move"; break; case MotionEvent.ACTION_OUTSIDE: action = "outside"; break; case MotionEvent.ACTION_POINTER_DOWN: action = "pointer_down"; break; case MotionEvent.ACTION_POINTER_UP: action = "pointer_up"; break; case MotionEvent.ACTION_UP: action = "up"; break; case MotionEvent.ACTION_SCROLL: action = "scroll"; break; default: action = "" + event.getAction(); break; } s += ", action " + action + " pointer count " + pointerCount + " buttons " + event.getButtonState() + " RawX " + event.getRawX() + " RawY " + event.getRawY() + " MetaState " + event.getMetaState() + " Flags " + event.getFlags() + "\n"; for (int p = 0; p < pointerCount; p++) { int ptrId = event.getPointerId(p); s += "Pointer id " + ptrId + " X " + event.getX(p) + " Y " + event.getY(p) + " pressure " + event.getPressure(p) + " size " + event.getSize(p) + " orientation " + event.getOrientation(p) + // (float)Math.toDegrees(event.getOrientation(p)) + " TouchMajor " + event.getTouchMajor(p) + " TouchMinor " + event.getTouchMinor(p) + " ToolMajor " + event.getToolMajor(p) + " ToolMinor " + event.getToolMinor(p) + "\n"; for (int i = 0; i < 255; i++) { if (event.getAxisValue(i, p) != 0.0) { s += "Axis " + i + " " + event.axisToString(i) + ": " + event.getAxisValue(i, p); InputDevice device = InputDevice.getDevice(event.getDeviceId()); if (device != null) { InputDevice.MotionRange range = device.getMotionRange(i); if (range != null) s += " range " + range.getMin() + " to " + range.getMax(); } s += "\n"; } } } pushText(s); }
// BEGIN_INCLUDE(onTouchEvent) @Override public boolean onTouchEvent(MotionEvent event) { final int action = event.getAction(); /* * Switch on the action. The action is extracted from the event by * applying the MotionEvent.ACTION_MASK. Alternatively a call to * event.getActionMasked() would yield in the action as well. */ switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: { // first pressed gesture has started /* * Only one touch event is stored in the MotionEvent. Extract * the pointer identifier of this touch from the first index * within the MotionEvent object. */ int id = event.getPointerId(0); TouchHistory data = TouchHistory.obtain(event.getX(0), event.getY(0), event.getPressure(0)); data.label = x + event.getX(0); /* * Store the data under its pointer identifier. The pointer * number stays consistent for the duration of a gesture, * accounting for other pointers going up or down. */ mTouches.put(id, data); mHasTouch = true; break; } case MotionEvent.ACTION_POINTER_DOWN: { /* * A non-primary pointer has gone down, after an event for the * primary pointer (ACTION_DOWN) has already been received. */ /* * The MotionEvent object contains multiple pointers. Need to * extract the index at which the data for this particular event * is stored. */ int index = event.getActionIndex(); int id = event.getPointerId(index); TouchHistory data = TouchHistory.obtain(event.getX(index), event.getY(index), event.getPressure(index)); data.label = x + event.getX(0); /* * Store the data under its pointer identifier. The index of * this pointer can change over multiple events, but this * pointer is always identified by the same identifier for this * active gesture. */ mTouches.put(id, data); break; } case MotionEvent.ACTION_UP: { /* * Final pointer has gone up and has ended the last pressed * gesture. */ /* * Extract the pointer identifier for the only event stored in * the MotionEvent object and remove it from the list of active * touches. */ int id = event.getPointerId(0); TouchHistory data = mTouches.get(id); mTouches.remove(id); data.recycle(); mHasTouch = false; break; } case MotionEvent.ACTION_POINTER_UP: { /* * A non-primary pointer has gone up and other pointers are * still active. */ /* * The MotionEvent object contains multiple pointers. Need to * extract the index at which the data for this particular event * is stored. */ int index = event.getActionIndex(); int id = event.getPointerId(index); TouchHistory data = mTouches.get(id); mTouches.remove(id); data.recycle(); break; } case MotionEvent.ACTION_MOVE: { /* * A change event happened during a pressed gesture. (Between * ACTION_DOWN and ACTION_UP or ACTION_POINTER_DOWN and * ACTION_POINTER_UP) */ /* * Loop through all active pointers contained within this event. * Data for each pointer is stored in a MotionEvent at an index * (starting from 0 up to the number of active pointers). This * loop goes through each of these active pointers, extracts its * data (position and pressure) and updates its stored data. A * pointer is identified by its pointer number which stays * constant across touch events as long as it remains active. * This identifier is used to keep track of a pointer across * events. */ for (int index = 0; index < event.getPointerCount(); index++) { // get pointer id for data stored at this index int id = event.getPointerId(index); // get the data stored externally about this pointer. TouchHistory data = mTouches.get(id); // add previous position to history and add new values data.addHistory(data.x, data.y); data.setTouch(event.getX(index), event.getY(index), event.getPressure(index)); /* int index = event.getActionIndex(); int id = event.getPointerId(index); TouchHistory data = TouchHistory.obtain(event.getX(index), event.getY(index), event.getPressure(index)); data.label = "id: " + event.getX(0); */ data.label = x + event.getX(0); } break; } } // trigger redraw on UI thread this.postInvalidate(); return true; }
// Touch events @Override public boolean onTouch(View v, MotionEvent event) { /* Ref: http://developer.android.com/training/gestures/multi.html */ final int touchDevId = event.getDeviceId(); final int pointerCount = event.getPointerCount(); int action = event.getActionMasked(); int pointerFingerId; int mouseButton; int i = -1; float x, y, p; // !!! FIXME: dump this SDK check after 2.0.4 ships and require API14. if (event.getSource() == InputDevice.SOURCE_MOUSE && SDLActivity.mSeparateMouseAndTouch) { if (Build.VERSION.SDK_INT < 14) { mouseButton = 1; // For Android==12 all mouse buttons are the left button } else { try { mouseButton = (Integer) event.getClass().getMethod("getButtonState").invoke(event); } catch (Exception e) { mouseButton = 1; // oh well. } } SDLActivity.onNativeMouse(mouseButton, action, event.getX(0), event.getY(0)); } else { switch (action) { case MotionEvent.ACTION_MOVE: for (i = 0; i < pointerCount; i++) { pointerFingerId = event.getPointerId(i); x = event.getX(i) / mWidth; y = event.getY(i) / mHeight; p = event.getPressure(i); SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p); } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_DOWN: // Primary pointer up/down, the index is always zero i = 0; case MotionEvent.ACTION_POINTER_UP: case MotionEvent.ACTION_POINTER_DOWN: // Non primary pointer up/down if (i == -1) { i = event.getActionIndex(); } pointerFingerId = event.getPointerId(i); x = event.getX(i) / mWidth; y = event.getY(i) / mHeight; p = event.getPressure(i); SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p); break; case MotionEvent.ACTION_CANCEL: for (i = 0; i < pointerCount; i++) { pointerFingerId = event.getPointerId(i); x = event.getX(i) / mWidth; y = event.getY(i) / mHeight; p = event.getPressure(i); SDLActivity.onNativeTouch(touchDevId, pointerFingerId, MotionEvent.ACTION_UP, x, y, p); } break; default: break; } } return true; }
@Override public boolean onTouch(View view, MotionEvent me) { // No dragging during animation at the moment. // TODO: Stop animation on touch event and return to drag mode. if (mAnimate || mPageProvider == null) { return false; } // We need page rects quite extensively so get them for later use. RectF rightRect = mRenderer.getPageRect(CurlRenderer.PAGE_RIGHT); RectF leftRect = mRenderer.getPageRect(CurlRenderer.PAGE_LEFT); // Store pointer position. mPointerPos.mPos.set(me.getX(), me.getY()); mRenderer.translate(mPointerPos.mPos); if (mEnableTouchPressure) { mPointerPos.mPressure = me.getPressure(); } else { mPointerPos.mPressure = 0.8f; } switch (me.getAction()) { case MotionEvent.ACTION_DOWN: { // Once we receive pointer down event its position is mapped to // right or left edge of page and that'll be the position from where // user is holding the paper to make curl happen. mDragStartPos.set(mPointerPos.mPos); // First we make sure it's not over or below page. Pages are // supposed to be same height so it really doesn't matter do we use // left or right one. if (mDragStartPos.y > rightRect.top) { mDragStartPos.y = rightRect.top; } else if (mDragStartPos.y < rightRect.bottom) { mDragStartPos.y = rightRect.bottom; } // Then we have to make decisions for the user whether curl is going // to happen from left or right, and on which page. if (mViewMode == SHOW_TWO_PAGES) { // If we have an open book and pointer is on the left from right // page we'll mark drag position to left edge of left page. // Additionally checking mCurrentIndex is higher than zero tells // us there is a visible page at all. if (mDragStartPos.x < rightRect.left && mCurrentIndex > 0) { mDragStartPos.x = leftRect.left; startCurl(CURL_LEFT); } // Otherwise check pointer is on right page's side. else if (mDragStartPos.x >= rightRect.left && mCurrentIndex < mPageProvider.getPageCount()) { mDragStartPos.x = rightRect.right; if (!mAllowLastPageCurl && mCurrentIndex >= mPageProvider.getPageCount() - 1) { return false; } startCurl(CURL_RIGHT); } } else if (mViewMode == SHOW_ONE_PAGE) { float halfX = (rightRect.right + rightRect.left) / 2; if (mDragStartPos.x < halfX && mCurrentIndex > 0) { mDragStartPos.x = rightRect.left; startCurl(CURL_LEFT); } else if (mDragStartPos.x >= halfX && mCurrentIndex < mPageProvider.getPageCount()) { mDragStartPos.x = rightRect.right; if (!mAllowLastPageCurl && mCurrentIndex >= mPageProvider.getPageCount() - 1) { return false; } startCurl(CURL_RIGHT); } } // If we have are in curl state, let this case clause flow through // to next one. We have pointer position and drag position defined // and this will create first render request given these points. if (mCurlState == CURL_NONE) { return false; } } case MotionEvent.ACTION_MOVE: { updateCurlPos(mPointerPos); break; } case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: { if (mCurlState == CURL_LEFT || mCurlState == CURL_RIGHT) { // Animation source is the point from where animation starts. // Also it's handled in a way we actually simulate touch events // meaning the output is exactly the same as if user drags the // page to other side. While not producing the best looking // result (which is easier done by altering curl position and/or // direction directly), this is done in a hope it made code a // bit more readable and easier to maintain. mAnimationSource.set(mPointerPos.mPos); mAnimationStartTime = System.currentTimeMillis(); // Given the explanation, here we decide whether to simulate // drag to left or right end. if ((mViewMode == SHOW_ONE_PAGE && mPointerPos.mPos.x > (rightRect.left + rightRect.right) / 2) || mViewMode == SHOW_TWO_PAGES && mPointerPos.mPos.x > rightRect.left) { // On right side target is always right page's right border. mAnimationTarget.set(mDragStartPos); mAnimationTarget.x = mRenderer.getPageRect(CurlRenderer.PAGE_RIGHT).right; mAnimationTargetEvent = SET_CURL_TO_RIGHT; } else { // On left side target depends on visible pages. mAnimationTarget.set(mDragStartPos); if (mCurlState == CURL_RIGHT || mViewMode == SHOW_TWO_PAGES) { mAnimationTarget.x = leftRect.left; } else { mAnimationTarget.x = rightRect.left; } mAnimationTargetEvent = SET_CURL_TO_LEFT; } mAnimate = true; requestRender(); } break; } } return true; }
@Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); int actionType = action & MotionEvent.ACTION_MASK; // Log.i("ZgeAndroid", "Action: " + action + " actiontype: " + actionType); switch (actionType) { case MotionEvent.ACTION_DOWN: { int count = event.getPointerCount(); for (int i = 0; i < count; i++) { int pointerID = event.getPointerId(i); NativeTouch(pointerID, event.getX(i), event.getY(i), event.getPressure(i)); } break; } case MotionEvent.ACTION_UP: { int count = event.getPointerCount(); for (int i = 0; i < count; i++) { int pointerID = event.getPointerId(i); NativeTouch(pointerID, event.getX(i), event.getY(i), 0); } break; } case MotionEvent.ACTION_MOVE: { int count = event.getPointerCount(); for (int i = 0; i < count; i++) { int pointerID = event.getPointerId(i); NativeTouch(pointerID, event.getX(i), event.getY(i), event.getPressure(i)); } break; } case MotionEvent.ACTION_POINTER_DOWN: { int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; int pointerId = event.getPointerId(pointerIndex); NativeTouch( pointerId, event.getX(pointerIndex), event.getY(pointerIndex), event.getPressure(pointerIndex)); break; } case MotionEvent.ACTION_POINTER_UP: { int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; int pointerId = event.getPointerId(pointerIndex); NativeTouch(pointerId, event.getX(pointerIndex), event.getY(pointerIndex), 0); break; } } return true; }