这是indexloc提供的服务,不要输入任何密码
Skip to content
106 changes: 91 additions & 15 deletions app/src/main/java/com/termux/x11/input/TouchInputHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.PointF;
import android.hardware.display.DisplayManager;
import android.hardware.input.InputManager;
import android.os.Handler;
import android.os.Build;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.GestureDetector;
import android.view.InputDevice;
import android.view.KeyEvent;
Expand Down Expand Up @@ -63,13 +65,15 @@ public class TouchInputHandler {
int TOUCH = 3;
}

@IntDef({CapturedPointerTransformation.NONE, CapturedPointerTransformation.CLOCKWISE, CapturedPointerTransformation.COUNTER_CLOCKWISE, CapturedPointerTransformation.UPSIDE_DOWN})
@IntDef({CapturedPointerTransformation.AUTO, CapturedPointerTransformation.NONE, CapturedPointerTransformation.COUNTER_CLOCKWISE, CapturedPointerTransformation.UPSIDE_DOWN, CapturedPointerTransformation.CLOCKWISE})
@Retention(RetentionPolicy.SOURCE)
public @interface CapturedPointerTransformation {
// values correspond to transformation needed given getRotation(), e.g. getRotation() = 1 requires counter-clockwise transformation
int AUTO = -1;
int NONE = 0;
int CLOCKWISE = 1;
int COUNTER_CLOCKWISE = 2;
int UPSIDE_DOWN = 3;
int COUNTER_CLOCKWISE = 1;
int UPSIDE_DOWN = 2;
int CLOCKWISE = 3;
}

private final RenderData mRenderData;
Expand Down Expand Up @@ -128,8 +132,40 @@ public class TouchInputHandler {
* is performing a drag operation.
*/
private boolean mIsDragging;
private static DisplayManager mDisplayManager;
private static int mDisplayRotation;
private static final DisplayManager.DisplayListener mDisplayListener = new DisplayManager.DisplayListener() {
@Override
public void onDisplayAdded(int displayId) {
mDisplayRotation = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY).getRotation() % 4;
}

@CapturedPointerTransformation int capturedPointerTransformation = CapturedPointerTransformation.NONE;
@Override
public void onDisplayRemoved(int displayId) {
mDisplayRotation = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY).getRotation() % 4;
}

@Override
public void onDisplayChanged(int displayId) {
mDisplayRotation = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY).getRotation() % 4;
}
};

@CapturedPointerTransformation static int capturedPointerTransformation = CapturedPointerTransformation.NONE;
private final int[][] buttons = {
{MotionEvent.BUTTON_PRIMARY, InputStub.BUTTON_LEFT},
{MotionEvent.BUTTON_TERTIARY, InputStub.BUTTON_MIDDLE},
{MotionEvent.BUTTON_SECONDARY, InputStub.BUTTON_RIGHT}
};
private int savedBS = 0;
private int currentBS = 0;
boolean isMouseButtonChanged(int mask) {
return (savedBS & mask) != (currentBS & mask);
}

boolean mouseButtonDown(int mask) {
return ((currentBS & mask) != 0);
}

private TouchInputHandler(MainActivity activity, RenderData renderData,
final InputEventSender injector, boolean isTouchpad) {
Expand All @@ -139,6 +175,11 @@ private TouchInputHandler(MainActivity activity, RenderData renderData,
mRenderData = renderData != null ? renderData :new RenderData();
mInjector = injector;
mActivity = activity;
if (mDisplayManager == null) {
mDisplayManager = (DisplayManager) mActivity.getSystemService(Context.DISPLAY_SERVICE);
mDisplayRotation = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY).getRotation() % 4;
mDisplayManager.registerDisplayListener(mDisplayListener, null);
}

GestureListener listener = new GestureListener();
mScroller = new GestureDetector(/*desktop*/ activity, listener, null, false);
Expand Down Expand Up @@ -227,6 +268,13 @@ boolean isDexEvent(MotionEvent event) {
}

public boolean handleTouchEvent(View view0, View view, MotionEvent event) {
// Regular touchpads and Dex touchpad (in captured mode) send events as finger too,
// but they should be handled as touchscreens with trackpad mode.
if (event.getToolType(event.getActionIndex()) == MotionEvent.TOOL_TYPE_FINGER &&
mTouchpadHandler != null && (event.getSource() & InputDevice.SOURCE_TOUCHPAD) == InputDevice.SOURCE_TOUCHPAD) {
return mTouchpadHandler.handleTouchEvent(view0, view, event);
}

if (view0 != view) {
int[] view0Location = new int[2];
int[] viewLocation = new int[2];
Expand All @@ -252,21 +300,14 @@ public boolean handleTouchEvent(View view0, View view, MotionEvent event) {

if (!isDexEvent(event) && (event.getToolType(event.getActionIndex()) == MotionEvent.TOOL_TYPE_MOUSE
|| (event.getSource() & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE)
|| (event.getSource() & InputDevice.SOURCE_MOUSE_RELATIVE) == InputDevice.SOURCE_MOUSE_RELATIVE
|| (event.getPointerCount() == 1 && mTouchpadHandler == null
&& (event.getSource() & InputDevice.SOURCE_TOUCHPAD) == InputDevice.SOURCE_TOUCHPAD))
|| (event.getSource() & InputDevice.SOURCE_MOUSE_RELATIVE) == InputDevice.SOURCE_MOUSE_RELATIVE)
return mHMListener.onTouch(view, event);

if (event.getToolType(event.getActionIndex()) == MotionEvent.TOOL_TYPE_FINGER) {
// Dex touchpad sends events as finger, but it should be considered as a mouse.
// Dex touchpad (in non-captured mode) sends events as finger, but it should be considered as a mouse.
if (isDexEvent(event) && mDexListener.onTouch(view, event))
return true;

// Regular touchpads and Dex touchpad send events as finger too,
// but they should be handled as touchscreens with trackpad mode.
if (mTouchpadHandler != null && (event.getSource() & InputDevice.SOURCE_TOUCHPAD) == InputDevice.SOURCE_TOUCHPAD)
return mTouchpadHandler.handleTouchEvent(view, view, event);

// Give the underlying input strategy a chance to observe the current motion event before
// passing it to the gesture detectors. This allows the input strategy to react to the
// event or save the payload for use in recreating the gesture remotely.
Expand All @@ -281,6 +322,14 @@ public boolean handleTouchEvent(View view0, View view, MotionEvent event) {
mTapDetector.onTouchEvent(event);
mSwipePinchDetector.onTouchEvent(event);

// For hardware touchpad in DeX (captured mode), handle physical click buttons
if ((event.getSource() & InputDevice.SOURCE_TOUCHPAD) == InputDevice.SOURCE_TOUCHPAD) {
currentBS = event.getButtonState();
for (int[] button: buttons)
if (isMouseButtonChanged(button[0]))
mInjector.sendMouseEvent(null, button[1], mouseButtonDown(button[0]), true);
savedBS = currentBS;
}
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
mSuppressCursorMovement = false;
Expand Down Expand Up @@ -339,7 +388,9 @@ public void handleHostSizeChanged(int w, int h) {
}

public void setInputMode(@InputMode int inputMode) {
if (inputMode == InputMode.TOUCH)
if (mTouchpadHandler == null)
mInputStrategy = new InputStrategyInterface.TrackpadInputStrategy(mInjector);
else if (inputMode == InputMode.TOUCH)
mInputStrategy = new InputStrategyInterface.NullInputStrategy();
else if (inputMode == InputMode.SIMULATED_TOUCH)
mInputStrategy = new InputStrategyInterface.SimulatedTouchInputStrategy(mRenderData, mInjector, mActivity);
Expand Down Expand Up @@ -396,6 +447,9 @@ public void reloadPreferences(Prefs p) {
case "ud":
capturedPointerTransformation = CapturedPointerTransformation.UPSIDE_DOWN;
break;
case "at":
capturedPointerTransformation = CapturedPointerTransformation.AUTO;
break;
default:
capturedPointerTransformation = CapturedPointerTransformation.NONE;
}
Expand Down Expand Up @@ -490,6 +544,28 @@ private class GestureListener extends GestureDetector.SimpleOnGestureListener
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
int pointerCount = e2.getPointerCount();

// For captured touchpad pointer:
// Automatic (for touchpad) mode is needed because touchpads ignore screen orientation and report physical X and Y
if ((e2.getSource() & InputDevice.SOURCE_TOUCHPAD) == InputDevice.SOURCE_TOUCHPAD
&& mInputStrategy instanceof InputStrategyInterface.TrackpadInputStrategy) {
float temp;
int transform = capturedPointerTransformation == CapturedPointerTransformation.AUTO ?
mDisplayRotation : capturedPointerTransformation;
switch (transform) {
case CapturedPointerTransformation.NONE:
break;
case CapturedPointerTransformation.CLOCKWISE:
temp = distanceX; distanceX = -distanceY; distanceY = temp; break;
case CapturedPointerTransformation.COUNTER_CLOCKWISE:
temp = distanceX; distanceX = distanceY; distanceY = -temp; break;
case CapturedPointerTransformation.UPSIDE_DOWN:
distanceX = -distanceX; distanceY = -distanceY; break;
}
distanceX *= mInjector.capturedPointerSpeedFactor;
distanceY *= mInjector.capturedPointerSpeedFactor;
}


if (pointerCount >= 3 && !mSwipeCompleted) {
// Note that distance values are reversed. For example, dragging a finger in the
// direction of increasing Y coordinate (downwards) results in distanceY being
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/arrays.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
<item>Clockwise</item>
<item>Counter clockwise</item>
<item>Upside down</item>
<item>Automatic (for touchpad)</item>
</string-array>
<string-array name="transformCapturedPointerValues">
<item>no</item>
<item>c</item>
<item>cc</item>
<item>ud</item>
<item>at</item>
</string-array>
<string-array name="displayResolutionVariants">
<item>native</item>
Expand Down