package com.iiordanov.bVNC.input; import android.graphics.PointF; import android.os.SystemClock; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import com.iiordanov.android.bc.BCFactory; import com.iiordanov.bVNC.RemoteCanvas; import com.iiordanov.bVNC.RemoteCanvasActivity; import com.iiordanov.bVNC.*; import com.iiordanov.freebVNC.*; import com.iiordanov.aRDP.*; import com.iiordanov.freeaRDP.*; import com.iiordanov.aSPICE.*; import com.iiordanov.freeaSPICE.*; public class TouchMouseSwipePanInputHandler extends AbstractGestureInputHandler { static final String TAG = "TouchMouseSwipePanInputHandler"; public static final String TOUCH_ZOOM_MODE = "TOUCH_ZOOM_MODE"; /** * Divide stated fling velocity by this amount to get initial velocity * per pan interval */ static final float FLING_FACTOR = 8; /** * @param c */ public TouchMouseSwipePanInputHandler(RemoteCanvasActivity va, RemoteCanvas v, boolean slowScrolling) { super(va, v, slowScrolling); } /* * (non-Javadoc) * * @see com.iiordanov.bVNC.AbstractInputHandler#getHandlerDescription() */ @Override public CharSequence getHandlerDescription() { return canvas.getResources().getString(R.string.input_mode_touch_pan_description); } /* * (non-Javadoc) * * @see com.iiordanov.bVNC.AbstractInputHandler#getName() */ @Override public String getName() { return TOUCH_ZOOM_MODE; } /* * (non-Javadoc) * * @see com.iiordanov.bVNC.RemoteCanvasActivity.ZoomInputHandler#onKeyDown(int, * android.view.KeyEvent) */ @Override public boolean onKeyDown(int keyCode, KeyEvent evt) { return keyHandler.onKeyDown(keyCode, evt); } /* * (non-Javadoc) * * @see com.iiordanov.bVNC.RemoteCanvasActivity.ZoomInputHandler#onKeyUp(int, * android.view.KeyEvent) */ @Override public boolean onKeyUp(int keyCode, KeyEvent evt) { return keyHandler.onKeyUp(keyCode, evt); } /* * (non-Javadoc) * * @see com.iiordanov.bVNC.AbstractInputHandler#onTrackballEvent(android.view.MotionEvent) */ @Override public boolean onTrackballEvent(MotionEvent evt) { return trackballMouse(evt); } /* * (non-Javadoc) * * @see android.view.GestureDetector.SimpleOnGestureListener#onDown(android.view.MotionEvent) */ @Override public boolean onDown(MotionEvent e) { activity.stopPanner(); return true; } /* * (non-Javadoc) * * @see android.view.GestureDetector.SimpleOnGestureListener#onFling(android.view.MotionEvent, * android.view.MotionEvent, float, float) */ @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // TODO: Workaround for Android 4.2. boolean twoFingers = false; if (e1 != null) twoFingers = (e1.getPointerCount() > 1); if (e2 != null) twoFingers = twoFingers || (e2.getPointerCount() > 1); // onFling called while scaling/swiping gesture is in effect. We ignore the event and pretend it was // consumed. This prevents the mouse pointer from flailing around while we are scaling. // Also, if one releases one finger slightly earlier than the other when scaling, it causes Android // to stick a spiteful onFling with a MASSIVE delta here. // This would cause the mouse pointer to jump to another place suddenly. // Hence, we ignore onFling after scaling until we lift all pointers up. if (twoFingers||disregardNextOnFling||inSwiping||inScaling||scalingJustFinished) { return true; } activity.showZoomer(false); activity.getPanner().start(-(velocityX / FLING_FACTOR), -(velocityY / FLING_FACTOR), new Panner.VelocityUpdater() { /* * (non-Javadoc) * * @see com.iiordanov.bVNC.Panner.VelocityUpdater#updateVelocity(android.graphics.Point, * long) */ @Override public boolean updateVelocity(PointF p, long interval) { double scale = Math.pow(0.8, interval / 50.0); p.x *= scale; p.y *= scale; return (Math.abs(p.x) > 0.5 || Math.abs(p.y) > 0.5); } }); return true; } /* * (non-Javadoc) * * @see android.view.GestureDetector.SimpleOnGestureListener#onScroll(android.view.MotionEvent, * android.view.MotionEvent, float, float) */ @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // onScroll called while scaling/swiping gesture is in effect. We ignore the event and pretend it was // consumed. This prevents the mouse pointer from flailing around while we are scaling. // Also, if one releases one finger slightly earlier than the other when scaling, it causes Android // to stick a spiteful onScroll with a MASSIVE delta here. // This would cause the mouse pointer to jump to another place suddenly. // Hence, we ignore onScroll after scaling until we lift all pointers up. boolean twoFingers = false; if (e1 != null) twoFingers = (e1.getPointerCount() > 1); if (e2 != null) twoFingers = twoFingers || (e2.getPointerCount() > 1); if (twoFingers||inSwiping||inScaling||scalingJustFinished) return true; if (!inScrolling) { inScrolling = true; distanceX = sign(distanceX); distanceY = sign(distanceY); distXQueue.clear(); distYQueue.clear(); } distXQueue.add(distanceX); distYQueue.add(distanceY); // Only after the first two events have arrived do we start using distanceX and Y // In order to effectively discard the last two events (which are typically unreliable // because of the finger lifting off). if (distXQueue.size() > 2) { distanceX = distXQueue.poll(); distanceY = distYQueue.poll(); } else { return true; } float scale = canvas.getScale(); activity.showZoomer(false); return canvas.pan((int)(distanceX*scale), (int)(distanceY*scale)); } }