diff --git a/app/src/main/java/com/limelight/Game.java b/app/src/main/java/com/limelight/Game.java index 5dcfe1ca..91a1f9f1 100644 --- a/app/src/main/java/com/limelight/Game.java +++ b/app/src/main/java/com/limelight/Game.java @@ -59,7 +59,6 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; -import android.os.SystemClock; import android.util.Rational; import android.view.Display; import android.view.InputDevice; @@ -1432,14 +1431,14 @@ public class Game extends Activity implements SurfaceHolder.Callback, if (event.getPointerCount() == 1 && event.getActionIndex() == 0) { if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { if (event.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS) { - lastAbsTouchDownTime = SystemClock.uptimeMillis(); + lastAbsTouchDownTime = event.getEventTime(); lastAbsTouchDownX = event.getX(0); lastAbsTouchDownY = event.getY(0); // Stylus is left click conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_LEFT); } else if (event.getToolType(0) == MotionEvent.TOOL_TYPE_ERASER) { - lastAbsTouchDownTime = SystemClock.uptimeMillis(); + lastAbsTouchDownTime = event.getEventTime(); lastAbsTouchDownX = event.getX(0); lastAbsTouchDownY = event.getY(0); @@ -1449,14 +1448,14 @@ public class Game extends Activity implements SurfaceHolder.Callback, } else if (event.getActionMasked() == MotionEvent.ACTION_UP || event.getActionMasked() == MotionEvent.ACTION_CANCEL) { if (event.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS) { - lastAbsTouchUpTime = SystemClock.uptimeMillis(); + lastAbsTouchUpTime = event.getEventTime(); lastAbsTouchUpX = event.getX(0); lastAbsTouchUpY = event.getY(0); // Stylus is left click conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_LEFT); } else if (event.getToolType(0) == MotionEvent.TOOL_TYPE_ERASER) { - lastAbsTouchUpTime = SystemClock.uptimeMillis(); + lastAbsTouchUpTime = event.getEventTime(); lastAbsTouchUpX = event.getX(0); lastAbsTouchUpY = event.getY(0); @@ -1492,7 +1491,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, if (event.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN && event.getPointerCount() == 3) { // Three fingers down - threeFingerDownTime = SystemClock.uptimeMillis(); + threeFingerDownTime = event.getEventTime(); // Cancel the first and second touches to avoid // erroneous events @@ -1515,14 +1514,14 @@ public class Game extends Activity implements SurfaceHolder.Callback, for (TouchContext touchContext : touchContextMap) { touchContext.setPointerCount(event.getPointerCount()); } - context.touchDownEvent(eventX, eventY, true); + context.touchDownEvent(eventX, eventY, event.getEventTime(), true); break; case MotionEvent.ACTION_POINTER_UP: case MotionEvent.ACTION_UP: if (event.getPointerCount() == 1 && (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU || (event.getFlags() & MotionEvent.FLAG_CANCELED) == 0)) { // All fingers up - if (SystemClock.uptimeMillis() - threeFingerDownTime < THREE_FINGER_TAP_THRESHOLD) { + if (event.getEventTime() - threeFingerDownTime < THREE_FINGER_TAP_THRESHOLD) { // This is a 3 finger tap to bring up the keyboard toggleKeyboard(); return true; @@ -1533,7 +1532,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, context.cancelTouch(); } else { - context.touchUpEvent(eventX, eventY); + context.touchUpEvent(eventX, eventY, event.getEventTime()); } for (TouchContext touchContext : touchContextMap) { @@ -1541,7 +1540,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, } if (actionIndex == 0 && event.getPointerCount() > 1 && !context.isCancelled()) { // The original secondary touch now becomes primary - context.touchDownEvent((int)event.getX(1), (int)event.getY(1), false); + context.touchDownEvent((int)event.getX(1), (int)event.getY(1), event.getEventTime(), false); } break; case MotionEvent.ACTION_MOVE: @@ -1555,7 +1554,8 @@ public class Game extends Activity implements SurfaceHolder.Callback, { aTouchContextMap.touchMoveEvent( (int)event.getHistoricalX(aTouchContextMap.getActionIndex(), i), - (int)event.getHistoricalY(aTouchContextMap.getActionIndex(), i)); + (int)event.getHistoricalY(aTouchContextMap.getActionIndex(), i), + event.getHistoricalEventTime(i)); } } } @@ -1566,7 +1566,8 @@ public class Game extends Activity implements SurfaceHolder.Callback, { aTouchContextMap.touchMoveEvent( (int)event.getX(aTouchContextMap.getActionIndex()), - (int)event.getY(aTouchContextMap.getActionIndex())); + (int)event.getY(aTouchContextMap.getActionIndex()), + event.getEventTime()); } } break; @@ -1615,7 +1616,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, case MotionEvent.ACTION_HOVER_ENTER: case MotionEvent.ACTION_HOVER_EXIT: case MotionEvent.ACTION_HOVER_MOVE: - if (SystemClock.uptimeMillis() - lastAbsTouchUpTime <= STYLUS_UP_DEAD_ZONE_DELAY && + if (event.getEventTime() - lastAbsTouchUpTime <= STYLUS_UP_DEAD_ZONE_DELAY && Math.sqrt(Math.pow(eventX - lastAbsTouchUpX, 2) + Math.pow(eventY - lastAbsTouchUpY, 2)) <= STYLUS_UP_DEAD_ZONE_RADIUS) { // Enforce a small deadzone between touch up and hover or touch down to allow more precise double-clicking return; @@ -1624,7 +1625,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_UP: - if (SystemClock.uptimeMillis() - lastAbsTouchDownTime <= STYLUS_DOWN_DEAD_ZONE_DELAY && + if (event.getEventTime() - lastAbsTouchDownTime <= STYLUS_DOWN_DEAD_ZONE_DELAY && Math.sqrt(Math.pow(eventX - lastAbsTouchDownX, 2) + Math.pow(eventY - lastAbsTouchDownY, 2)) <= STYLUS_DOWN_DEAD_ZONE_RADIUS) { // Enforce a small deadzone between touch down and move or touch up to allow more precise double-clicking return; diff --git a/app/src/main/java/com/limelight/binding/input/ControllerHandler.java b/app/src/main/java/com/limelight/binding/input/ControllerHandler.java index 13e22bb5..53e63fed 100644 --- a/app/src/main/java/com/limelight/binding/input/ControllerHandler.java +++ b/app/src/main/java/com/limelight/binding/input/ControllerHandler.java @@ -9,7 +9,6 @@ import android.hardware.usb.UsbManager; import android.media.AudioAttributes; import android.os.Build; import android.os.CombinedVibration; -import android.os.SystemClock; import android.os.VibrationAttributes; import android.os.VibrationEffect; import android.os.Vibrator; @@ -1506,7 +1505,8 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD // If the button hasn't been down long enough, sleep for a bit before sending the up event // This allows "instant" button presses (like OUYA's virtual menu button) to work. This // path should not be triggered during normal usage. - if (SystemClock.uptimeMillis() - event.getDownTime() < ControllerHandler.MINIMUM_BUTTON_DOWN_TIME_MS) + int buttonDownTime = (int)(event.getEventTime() - event.getDownTime()); + if (buttonDownTime < ControllerHandler.MINIMUM_BUTTON_DOWN_TIME_MS) { // Since our sleep time is so short (10 ms), it shouldn't cause a problem doing this in the // UI thread. @@ -1532,7 +1532,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD // Make sure it's real by checking that the key is actually down before taking // any action. if ((context.inputMap & ControllerPacket.PLAY_FLAG) != 0 && - SystemClock.uptimeMillis() - context.startDownTime > ControllerHandler.START_DOWN_TIME_MOUSE_MODE_MS && + event.getEventTime() - context.startDownTime > ControllerHandler.START_DOWN_TIME_MOUSE_MODE_MS && prefConfig.mouseEmulation) { toggleMouseEmulation(context); } @@ -1585,11 +1585,11 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD break; case KeyEvent.KEYCODE_BUTTON_L1: context.inputMap &= ~ControllerPacket.LB_FLAG; - context.lastLbUpTime = SystemClock.uptimeMillis(); + context.lastLbUpTime = event.getEventTime(); break; case KeyEvent.KEYCODE_BUTTON_R1: context.inputMap &= ~ControllerPacket.RB_FLAG; - context.lastRbUpTime = SystemClock.uptimeMillis(); + context.lastRbUpTime = event.getEventTime(); break; case KeyEvent.KEYCODE_BUTTON_THUMBL: context.inputMap &= ~ControllerPacket.LS_CLK_FLAG; @@ -1698,7 +1698,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD case KeyEvent.KEYCODE_BUTTON_START: case KeyEvent.KEYCODE_MENU: if (event.getRepeatCount() == 0) { - context.startDownTime = SystemClock.uptimeMillis(); + context.startDownTime = event.getEventTime(); } context.inputMap |= ControllerPacket.PLAY_FLAG; break; @@ -1789,7 +1789,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD if (!context.hasSelect) { if (context.inputMap == (ControllerPacket.PLAY_FLAG | ControllerPacket.LB_FLAG) || (context.inputMap == ControllerPacket.PLAY_FLAG && - SystemClock.uptimeMillis() - context.lastLbUpTime <= MAXIMUM_BUMPER_UP_DELAY_MS)) + event.getEventTime() - context.lastLbUpTime <= MAXIMUM_BUMPER_UP_DELAY_MS)) { context.inputMap &= ~(ControllerPacket.PLAY_FLAG | ControllerPacket.LB_FLAG); context.inputMap |= ControllerPacket.BACK_FLAG; @@ -1812,7 +1812,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD else { if (context.inputMap == (ControllerPacket.PLAY_FLAG | ControllerPacket.RB_FLAG) || (context.inputMap == ControllerPacket.PLAY_FLAG && - SystemClock.uptimeMillis() - context.lastRbUpTime <= MAXIMUM_BUMPER_UP_DELAY_MS)) + event.getEventTime() - context.lastRbUpTime <= MAXIMUM_BUMPER_UP_DELAY_MS)) { context.inputMap &= ~(ControllerPacket.PLAY_FLAG | ControllerPacket.RB_FLAG); context.inputMap |= ControllerPacket.SPECIAL_BUTTON_FLAG; diff --git a/app/src/main/java/com/limelight/binding/input/touch/AbsoluteTouchContext.java b/app/src/main/java/com/limelight/binding/input/touch/AbsoluteTouchContext.java index 1f365a51..f185f004 100644 --- a/app/src/main/java/com/limelight/binding/input/touch/AbsoluteTouchContext.java +++ b/app/src/main/java/com/limelight/binding/input/touch/AbsoluteTouchContext.java @@ -1,6 +1,5 @@ package com.limelight.binding.input.touch; -import android.os.SystemClock; import android.view.View; import com.limelight.nvstream.NvConnection; @@ -53,7 +52,7 @@ public class AbsoluteTouchContext implements TouchContext { } @Override - public boolean touchDownEvent(int eventX, int eventY, boolean isNewFinger) + public boolean touchDownEvent(int eventX, int eventY, long eventTime, boolean isNewFinger) { if (!isNewFinger) { // We don't handle finger transitions for absolute mode @@ -62,7 +61,7 @@ public class AbsoluteTouchContext implements TouchContext { lastTouchLocationX = lastTouchDownX = eventX; lastTouchLocationY = lastTouchDownY = eventY; - lastTouchDownTime = SystemClock.uptimeMillis(); + lastTouchDownTime = eventTime; cancelled = confirmedTap = confirmedLongPress = false; if (actionIndex == 0) { @@ -90,7 +89,7 @@ public class AbsoluteTouchContext implements TouchContext { } @Override - public void touchUpEvent(int eventX, int eventY) + public void touchUpEvent(int eventX, int eventY, long eventTime) { if (cancelled) { return; @@ -130,7 +129,7 @@ public class AbsoluteTouchContext implements TouchContext { lastTouchLocationX = lastTouchUpX = eventX; lastTouchLocationY = lastTouchUpY = eventY; - lastTouchUpTime = SystemClock.uptimeMillis(); + lastTouchUpTime = eventTime; } private synchronized void startLongPressTimer() { @@ -214,7 +213,7 @@ public class AbsoluteTouchContext implements TouchContext { } @Override - public boolean touchMoveEvent(int eventX, int eventY) + public boolean touchMoveEvent(int eventX, int eventY, long eventTime) { if (cancelled) { return true; diff --git a/app/src/main/java/com/limelight/binding/input/touch/RelativeTouchContext.java b/app/src/main/java/com/limelight/binding/input/touch/RelativeTouchContext.java index ff0af071..c354cb4b 100644 --- a/app/src/main/java/com/limelight/binding/input/touch/RelativeTouchContext.java +++ b/app/src/main/java/com/limelight/binding/input/touch/RelativeTouchContext.java @@ -1,6 +1,5 @@ package com.limelight.binding.input.touch; -import android.os.SystemClock; import android.view.View; import com.limelight.nvstream.NvConnection; @@ -66,7 +65,7 @@ public class RelativeTouchContext implements TouchContext { yDelta <= TAP_MOVEMENT_THRESHOLD; } - private boolean isTap() + private boolean isTap(long eventTime) { if (confirmedDrag || confirmedMove || confirmedScroll) { return false; @@ -79,7 +78,7 @@ public class RelativeTouchContext implements TouchContext { return false; } - long timeDelta = SystemClock.uptimeMillis() - originalTouchTime; + long timeDelta = eventTime - originalTouchTime; return isWithinTapBounds(lastTouchX, lastTouchY) && timeDelta <= TAP_TIME_THRESHOLD; } @@ -94,7 +93,7 @@ public class RelativeTouchContext implements TouchContext { } @Override - public boolean touchDownEvent(int eventX, int eventY, boolean isNewFinger) + public boolean touchDownEvent(int eventX, int eventY, long eventTime, boolean isNewFinger) { // Get the view dimensions to scale inputs on this touch xFactor = referenceWidth / (double)targetView.getWidth(); @@ -105,7 +104,7 @@ public class RelativeTouchContext implements TouchContext { if (isNewFinger) { maxPointerCountInGesture = pointerCount; - originalTouchTime = SystemClock.uptimeMillis(); + originalTouchTime = eventTime; cancelled = confirmedDrag = confirmedMove = confirmedScroll = false; distanceMoved = 0; @@ -119,7 +118,7 @@ public class RelativeTouchContext implements TouchContext { } @Override - public void touchUpEvent(int eventX, int eventY) + public void touchUpEvent(int eventX, int eventY, long eventTime) { if (cancelled) { return; @@ -134,7 +133,7 @@ public class RelativeTouchContext implements TouchContext { // Raise the button after a drag conn.sendMouseButtonUp(buttonIndex); } - else if (isTap()) + else if (isTap(eventTime)) { // Lower the mouse button conn.sendMouseButtonDown(buttonIndex); @@ -229,7 +228,7 @@ public class RelativeTouchContext implements TouchContext { } @Override - public boolean touchMoveEvent(int eventX, int eventY) + public boolean touchMoveEvent(int eventX, int eventY, long eventTime) { if (cancelled) { return true; diff --git a/app/src/main/java/com/limelight/binding/input/touch/TouchContext.java b/app/src/main/java/com/limelight/binding/input/touch/TouchContext.java index d08ab3c6..a04388fd 100644 --- a/app/src/main/java/com/limelight/binding/input/touch/TouchContext.java +++ b/app/src/main/java/com/limelight/binding/input/touch/TouchContext.java @@ -3,9 +3,9 @@ package com.limelight.binding.input.touch; public interface TouchContext { int getActionIndex(); void setPointerCount(int pointerCount); - boolean touchDownEvent(int eventX, int eventY, boolean isNewFinger); - boolean touchMoveEvent(int eventX, int eventY); - void touchUpEvent(int eventX, int eventY); + boolean touchDownEvent(int eventX, int eventY, long eventTime, boolean isNewFinger); + boolean touchMoveEvent(int eventX, int eventY, long eventTime); + void touchUpEvent(int eventX, int eventY, long eventTime); void cancelTouch(); boolean isCancelled(); } diff --git a/app/src/main/java/com/limelight/binding/input/virtual_controller/AnalogStick.java b/app/src/main/java/com/limelight/binding/input/virtual_controller/AnalogStick.java index a54c4b1f..9362d401 100644 --- a/app/src/main/java/com/limelight/binding/input/virtual_controller/AnalogStick.java +++ b/app/src/main/java/com/limelight/binding/input/virtual_controller/AnalogStick.java @@ -8,7 +8,6 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; -import android.os.SystemClock; import android.view.MotionEvent; import java.util.ArrayList; @@ -254,7 +253,7 @@ public class AnalogStick extends VirtualControllerElement { } } - private void updatePosition() { + private void updatePosition(long eventTime) { // get 100% way float complete = radius_complete - radius_analog_stick; @@ -271,7 +270,7 @@ public class AnalogStick extends VirtualControllerElement { // We also release the deadzone if the user keeps the stick pressed for a bit to allow // them to make precise movements. stick_state = (stick_state == STICK_STATE.MOVED_ACTIVE || - SystemClock.uptimeMillis() - timeLastClick > timeoutDeadzone || + eventTime - timeLastClick > timeoutDeadzone || movement_radius > radius_dead_zone) ? STICK_STATE.MOVED_ACTIVE : STICK_STATE.MOVED_IN_DEAD_ZONE; @@ -312,7 +311,7 @@ public class AnalogStick extends VirtualControllerElement { stick_state = STICK_STATE.MOVED_IN_DEAD_ZONE; // check for double click if (lastClickState == CLICK_STATE.SINGLE && - timeLastClick + timeoutDoubleClick > SystemClock.uptimeMillis()) { + event.getEventTime() - timeLastClick <= timeoutDoubleClick) { click_state = CLICK_STATE.DOUBLE; notifyOnDoubleClick(); } else { @@ -320,7 +319,7 @@ public class AnalogStick extends VirtualControllerElement { notifyOnClick(); } // reset last click timestamp - timeLastClick = SystemClock.uptimeMillis(); + timeLastClick = event.getEventTime(); // set item pressed and update setPressed(true); break; @@ -335,7 +334,7 @@ public class AnalogStick extends VirtualControllerElement { if (isPressed()) { // when is pressed calculate new positions (will trigger movement if necessary) - updatePosition(); + updatePosition(event.getEventTime()); } else { stick_state = STICK_STATE.NO_MOVEMENT; notifyOnRevoke();