/** * 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(final MotionEvent ev) { final MainView me = this; final int action = ev.getAction(); int type = -1; switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: type = etTouchBegin; break; case MotionEvent.ACTION_POINTER_DOWN: type = etTouchBegin; break; case MotionEvent.ACTION_MOVE: type = etTouchMove; break; case MotionEvent.ACTION_UP: type = etTouchEnd; break; case MotionEvent.ACTION_POINTER_UP: type = etTouchEnd; break; case MotionEvent.ACTION_CANCEL: type = etTouchEnd; break; } // Log.e("VIEW","Actions : " + action ); // This is actually index, not id.... int idx = (action & MotionEvent.ACTION_POINTER_ID_MASK) >> (MotionEvent.ACTION_POINTER_ID_SHIFT); final int t = type; // if (type!=etTouchMove) // Log.e("VIEW","onTouchEvent " + ev.toString() ); for (int i = 0; i < ev.getPointerCount(); i++) { // Log.e("VIEW","onTouchEvent " + type + " x " + ev.getPointerCount() ); final int id = ev.getPointerId(i); final float x = ev.getX(i); final float y = ev.getY(i); final float sizeX = ev.getSize(i); final float sizeY = ev.getSize(i); // if (type!=etTouchMove) // Log.e("VIEW"," " + i + "] type=" + t + " id="+ id + " idx="+ idx +" " + x + ", "+ y + "," // + sizeX + "," + sizeY); if (type == etTouchMove || i == idx) { queueEvent( new Runnable() { public void run() { me.HandleResult(NME.onTouch(t, x, y, id, sizeX, sizeY)); } }); } } 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; }
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); } }
/** * 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); }