mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2026-04-22 08:20:12 +00:00
Fix mishandling ACTION_MOVE events for native pen/touch events
This commit is contained in:
@@ -1509,9 +1509,9 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private float[] getStreamViewRelativeNormalizedXY(View view, MotionEvent event) {
|
private float[] getStreamViewRelativeNormalizedXY(View view, MotionEvent event, int pointerIndex) {
|
||||||
float normalizedX = event.getX(event.getActionIndex());
|
float normalizedX = event.getX(pointerIndex);
|
||||||
float normalizedY = event.getY(event.getActionIndex());
|
float normalizedY = event.getY(pointerIndex);
|
||||||
|
|
||||||
// For the containing background view, we must subtract the origin
|
// For the containing background view, we must subtract the origin
|
||||||
// of the StreamView to get video-relative coordinates.
|
// of the StreamView to get video-relative coordinates.
|
||||||
@@ -1536,7 +1536,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
return (value - range.getMin()) / range.getRange();
|
return (value - range.getMin()) / range.getRange();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float getPressureOrDistance(MotionEvent event) {
|
private static float getPressureOrDistance(MotionEvent event, int pointerIndex) {
|
||||||
InputDevice dev = event.getDevice();
|
InputDevice dev = event.getDevice();
|
||||||
switch (event.getActionMasked()) {
|
switch (event.getActionMasked()) {
|
||||||
case MotionEvent.ACTION_HOVER_ENTER:
|
case MotionEvent.ACTION_HOVER_ENTER:
|
||||||
@@ -1546,22 +1546,22 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
if (dev != null) {
|
if (dev != null) {
|
||||||
InputDevice.MotionRange distanceRange = dev.getMotionRange(MotionEvent.AXIS_DISTANCE, event.getSource());
|
InputDevice.MotionRange distanceRange = dev.getMotionRange(MotionEvent.AXIS_DISTANCE, event.getSource());
|
||||||
if (distanceRange != null) {
|
if (distanceRange != null) {
|
||||||
return normalizeValueInRange(event.getAxisValue(MotionEvent.AXIS_DISTANCE, event.getActionIndex()), distanceRange);
|
return normalizeValueInRange(event.getAxisValue(MotionEvent.AXIS_DISTANCE, pointerIndex), distanceRange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Other events report pressure
|
// Other events report pressure
|
||||||
return event.getPressure(event.getActionIndex());
|
return event.getPressure(pointerIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static short getRotationDegrees(MotionEvent event) {
|
private static short getRotationDegrees(MotionEvent event, int pointerIndex) {
|
||||||
InputDevice dev = event.getDevice();
|
InputDevice dev = event.getDevice();
|
||||||
if (dev != null) {
|
if (dev != null) {
|
||||||
if (dev.getMotionRange(MotionEvent.AXIS_ORIENTATION, event.getSource()) != null) {
|
if (dev.getMotionRange(MotionEvent.AXIS_ORIENTATION, event.getSource()) != null) {
|
||||||
short rotationDegrees = (short) Math.toDegrees(event.getOrientation(event.getActionIndex()));
|
short rotationDegrees = (short) Math.toDegrees(event.getOrientation(pointerIndex));
|
||||||
if (rotationDegrees < 0) {
|
if (rotationDegrees < 0) {
|
||||||
rotationDegrees += 360;
|
rotationDegrees += 360;
|
||||||
}
|
}
|
||||||
@@ -1579,7 +1579,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
return (float)Math.sqrt(Math.pow(point[0], 2) + Math.pow(point[1], 2));
|
return (float)Math.sqrt(Math.pow(point[0], 2) + Math.pow(point[1], 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
private float[] getStreamViewNormalizedContactArea(MotionEvent event) {
|
private float[] getStreamViewNormalizedContactArea(MotionEvent event, int pointerIndex) {
|
||||||
float orientation;
|
float orientation;
|
||||||
|
|
||||||
// If the orientation is unknown, we'll just assume it's at a 45 degree angle and scale it by
|
// If the orientation is unknown, we'll just assume it's at a 45 degree angle and scale it by
|
||||||
@@ -1588,7 +1588,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
orientation = (float)(Math.PI / 4);
|
orientation = (float)(Math.PI / 4);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
orientation = event.getOrientation(event.getActionIndex());
|
orientation = event.getOrientation(pointerIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
float contactAreaMajor, contactAreaMinor;
|
float contactAreaMajor, contactAreaMinor;
|
||||||
@@ -1597,14 +1597,14 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
case MotionEvent.ACTION_HOVER_ENTER:
|
case MotionEvent.ACTION_HOVER_ENTER:
|
||||||
case MotionEvent.ACTION_HOVER_MOVE:
|
case MotionEvent.ACTION_HOVER_MOVE:
|
||||||
case MotionEvent.ACTION_HOVER_EXIT:
|
case MotionEvent.ACTION_HOVER_EXIT:
|
||||||
contactAreaMajor = event.getToolMajor(event.getActionIndex());
|
contactAreaMajor = event.getToolMajor(pointerIndex);
|
||||||
contactAreaMinor = event.getToolMinor(event.getActionIndex());
|
contactAreaMinor = event.getToolMinor(pointerIndex);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Other events report contact area
|
// Other events report contact area
|
||||||
default:
|
default:
|
||||||
contactAreaMajor = event.getTouchMajor(event.getActionIndex());
|
contactAreaMajor = event.getTouchMajor(pointerIndex);
|
||||||
contactAreaMinor = event.getTouchMinor(event.getActionIndex());
|
contactAreaMinor = event.getTouchMinor(pointerIndex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1626,24 +1626,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
return new float[] { cartesianToR(contactAreaMajorCartesian), cartesianToR(contactAreaMinorCartesian) };
|
return new float[] { cartesianToR(contactAreaMajorCartesian), cartesianToR(contactAreaMinorCartesian) };
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean trySendPenEvent(View view, MotionEvent event) {
|
private boolean sendPenEventForPointer(View view, MotionEvent event, byte eventType, byte toolType, int pointerIndex) {
|
||||||
byte eventType = getLiTouchTypeFromEvent(event);
|
|
||||||
if (eventType < 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte toolType;
|
|
||||||
switch (event.getToolType(event.getActionIndex())) {
|
|
||||||
case MotionEvent.TOOL_TYPE_ERASER:
|
|
||||||
toolType = MoonBridge.LI_TOOL_TYPE_ERASER;
|
|
||||||
break;
|
|
||||||
case MotionEvent.TOOL_TYPE_STYLUS:
|
|
||||||
toolType = MoonBridge.LI_TOOL_TYPE_PEN;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte penButtons = 0;
|
byte penButtons = 0;
|
||||||
if ((event.getButtonState() & MotionEvent.BUTTON_STYLUS_PRIMARY) != 0) {
|
if ((event.getButtonState() & MotionEvent.BUTTON_STYLUS_PRIMARY) != 0) {
|
||||||
penButtons |= MoonBridge.LI_PEN_BUTTON_PRIMARY;
|
penButtons |= MoonBridge.LI_PEN_BUTTON_PRIMARY;
|
||||||
@@ -1656,17 +1639,76 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
InputDevice dev = event.getDevice();
|
InputDevice dev = event.getDevice();
|
||||||
if (dev != null) {
|
if (dev != null) {
|
||||||
if (dev.getMotionRange(MotionEvent.AXIS_TILT, event.getSource()) != null) {
|
if (dev.getMotionRange(MotionEvent.AXIS_TILT, event.getSource()) != null) {
|
||||||
tiltDegrees = (byte)Math.toDegrees(event.getAxisValue(MotionEvent.AXIS_TILT, event.getActionIndex()));
|
tiltDegrees = (byte)Math.toDegrees(event.getAxisValue(MotionEvent.AXIS_TILT, pointerIndex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float[] normalizedCoords = getStreamViewRelativeNormalizedXY(view, event);
|
float[] normalizedCoords = getStreamViewRelativeNormalizedXY(view, event, pointerIndex);
|
||||||
float[] normalizedContactArea = getStreamViewNormalizedContactArea(event);
|
float[] normalizedContactArea = getStreamViewNormalizedContactArea(event, pointerIndex);
|
||||||
return conn.sendPenEvent(eventType, toolType, penButtons,
|
return conn.sendPenEvent(eventType, toolType, penButtons,
|
||||||
normalizedCoords[0], normalizedCoords[1],
|
normalizedCoords[0], normalizedCoords[1],
|
||||||
getPressureOrDistance(event),
|
getPressureOrDistance(event, pointerIndex),
|
||||||
normalizedContactArea[0], normalizedContactArea[1],
|
normalizedContactArea[0], normalizedContactArea[1],
|
||||||
getRotationDegrees(event), tiltDegrees) != MoonBridge.LI_ERR_UNSUPPORTED;
|
getRotationDegrees(event, pointerIndex), tiltDegrees) != MoonBridge.LI_ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte convertToolTypeToStylusToolType(MotionEvent event, int pointerIndex) {
|
||||||
|
switch (event.getToolType(pointerIndex)) {
|
||||||
|
case MotionEvent.TOOL_TYPE_ERASER:
|
||||||
|
return MoonBridge.LI_TOOL_TYPE_ERASER;
|
||||||
|
case MotionEvent.TOOL_TYPE_STYLUS:
|
||||||
|
return MoonBridge.LI_TOOL_TYPE_PEN;
|
||||||
|
default:
|
||||||
|
return MoonBridge.LI_TOOL_TYPE_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean trySendPenEvent(View view, MotionEvent event) {
|
||||||
|
byte eventType = getLiTouchTypeFromEvent(event);
|
||||||
|
if (eventType < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.getActionMasked() == MotionEvent.ACTION_MOVE) {
|
||||||
|
// Move events may impact all active pointers
|
||||||
|
boolean handledStylusEvent = false;
|
||||||
|
for (int i = 0; i < event.getPointerCount(); i++) {
|
||||||
|
byte toolType = convertToolTypeToStylusToolType(event, i);
|
||||||
|
if (toolType == MoonBridge.LI_TOOL_TYPE_UNKNOWN) {
|
||||||
|
// Not a stylus pointer, so skip it
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// This pointer is a stylus, so we'll report that we handled this event
|
||||||
|
handledStylusEvent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sendPenEventForPointer(view, event, eventType, toolType, i)) {
|
||||||
|
// Pen events aren't supported by the host
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return handledStylusEvent;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Up, Down, Hover, and Cancel events are specific to the action index
|
||||||
|
byte toolType = convertToolTypeToStylusToolType(event, event.getActionIndex());
|
||||||
|
if (toolType == MoonBridge.LI_TOOL_TYPE_UNKNOWN) {
|
||||||
|
// Not a stylus event
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return sendPenEventForPointer(view, event, eventType, toolType, event.getActionIndex());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean sendTouchEventForPointer(View view, MotionEvent event, byte eventType, int pointerIndex) {
|
||||||
|
float[] normalizedCoords = getStreamViewRelativeNormalizedXY(view, event, pointerIndex);
|
||||||
|
float[] normalizedContactArea = getStreamViewNormalizedContactArea(event, pointerIndex);
|
||||||
|
return conn.sendTouchEvent(eventType, event.getPointerId(pointerIndex),
|
||||||
|
normalizedCoords[0], normalizedCoords[1],
|
||||||
|
getPressureOrDistance(event, pointerIndex),
|
||||||
|
normalizedContactArea[0], normalizedContactArea[1],
|
||||||
|
getRotationDegrees(event, pointerIndex)) != MoonBridge.LI_ERR_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean trySendTouchEvent(View view, MotionEvent event) {
|
private boolean trySendTouchEvent(View view, MotionEvent event) {
|
||||||
@@ -1675,13 +1717,19 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
float[] normalizedCoords = getStreamViewRelativeNormalizedXY(view, event);
|
if (event.getActionMasked() == MotionEvent.ACTION_MOVE) {
|
||||||
float[] normalizedContactArea = getStreamViewNormalizedContactArea(event);
|
// Move events may impact all active pointers
|
||||||
return conn.sendTouchEvent(eventType, event.getPointerId(event.getActionIndex()),
|
for (int i = 0; i < event.getPointerCount(); i++) {
|
||||||
normalizedCoords[0], normalizedCoords[1],
|
if (!sendTouchEventForPointer(view, event, eventType, i)) {
|
||||||
getPressureOrDistance(event),
|
return false;
|
||||||
normalizedContactArea[0], normalizedContactArea[1],
|
}
|
||||||
getRotationDegrees(event)) != MoonBridge.LI_ERR_UNSUPPORTED;
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Up, Down, Hover, and Cancel events are specific to the action index
|
||||||
|
return sendTouchEventForPointer(view, event, eventType, event.getActionIndex());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the event was consumed
|
// Returns true if the event was consumed
|
||||||
|
|||||||
@@ -1502,6 +1502,18 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
|||||||
return value / range.getRange();
|
return value / range.getRange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean sendTouchpadEventForPointer(InputDeviceContext context, MotionEvent event, byte touchType, int pointerIndex) {
|
||||||
|
float normalizedX = normalizeRawValueWithRange(event.getX(pointerIndex), context.touchpadXRange);
|
||||||
|
float normalizedY = normalizeRawValueWithRange(event.getY(pointerIndex), context.touchpadYRange);
|
||||||
|
float normalizedPressure = context.touchpadPressureRange != null ?
|
||||||
|
normalizeRawValueWithRange(event.getPressure(pointerIndex), context.touchpadPressureRange)
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
return conn.sendControllerTouchEvent((byte)context.controllerNumber, touchType,
|
||||||
|
event.getPointerId(pointerIndex),
|
||||||
|
normalizedX, normalizedY, normalizedPressure) != MoonBridge.LI_ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean tryHandleTouchpadEvent(MotionEvent event) {
|
public boolean tryHandleTouchpadEvent(MotionEvent event) {
|
||||||
// Bail if this is not a touchpad event
|
// Bail if this is not a touchpad event
|
||||||
if (event.getSource() != InputDevice.SOURCE_TOUCHPAD) {
|
if (event.getSource() != InputDevice.SOURCE_TOUCHPAD) {
|
||||||
@@ -1573,15 +1585,20 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
float normalizedX = normalizeRawValueWithRange(event.getX(event.getActionIndex()), context.touchpadXRange);
|
if (event.getActionMasked() == MotionEvent.ACTION_MOVE) {
|
||||||
float normalizedY = normalizeRawValueWithRange(event.getY(event.getActionIndex()), context.touchpadYRange);
|
// Move events may impact all active pointers
|
||||||
float normalizedPressure = context.touchpadPressureRange != null ?
|
for (int i = 0; i < event.getPointerCount(); i++) {
|
||||||
normalizeRawValueWithRange(event.getPressure(event.getActionIndex()), context.touchpadPressureRange)
|
if (!sendTouchpadEventForPointer(context, event, touchType, i)) {
|
||||||
: 0;
|
// Controller touch events are not supported by the host
|
||||||
|
return false;
|
||||||
return conn.sendControllerTouchEvent((byte)context.controllerNumber, touchType,
|
}
|
||||||
event.getPointerId(event.getActionIndex()),
|
}
|
||||||
normalizedX, normalizedY, normalizedPressure) != MoonBridge.LI_ERR_UNSUPPORTED;
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Down and Up events impact the action index pointer
|
||||||
|
return sendTouchpadEventForPointer(context, event, touchType, event.getActionIndex());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean handleMotionEvent(MotionEvent event) {
|
public boolean handleMotionEvent(MotionEvent event) {
|
||||||
|
|||||||
Reference in New Issue
Block a user