Touchpad: two-finger scroll and pinch zoom, fix selection row offset; v0.1.1
This commit is contained in:
+2
-2
@@ -10,8 +10,8 @@ android {
|
|||||||
applicationId "xyz.whcself.whcshell"
|
applicationId "xyz.whcself.whcshell"
|
||||||
minSdk 26
|
minSdk 26
|
||||||
targetSdk 35
|
targetSdk 35
|
||||||
versionCode 1
|
versionCode 2
|
||||||
versionName "0.1.0"
|
versionName "0.1.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
|||||||
@@ -284,10 +284,15 @@ public final class TermView extends View {
|
|||||||
return Math.max(0, Math.min(cols - 1, c));
|
return Math.max(0, Math.min(cols - 1, c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Top of the first text row; the renderer starts rows below the padding by this offset. */
|
||||||
|
private int textTop() {
|
||||||
|
return getPaddingTop() + renderer.getFontLineSpacingAndAscent();
|
||||||
|
}
|
||||||
|
|
||||||
/** Visible row, 0-based. */
|
/** Visible row, 0-based. */
|
||||||
private int row(MotionEvent ev) {
|
private int row(MotionEvent ev) {
|
||||||
int rows = emulator().mRows;
|
int rows = emulator().mRows;
|
||||||
int r = (int) Math.floor((ev.getY() - getPaddingTop()) / renderer.getFontLineSpacing());
|
int r = (int) Math.floor((ev.getY() - textTop()) / renderer.getFontLineSpacing());
|
||||||
return Math.max(0, Math.min(rows - 1, r));
|
return Math.max(0, Math.min(rows - 1, r));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -448,6 +453,49 @@ public final class TermView extends View {
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float gestureY, pinchDist;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Touchpad gestures arrive as mouse-source events with a finger tool and no buttons: a fake
|
||||||
|
* finger classified as a two-finger swipe for scrolling (the gesture axes stay 0, so the finger's
|
||||||
|
* movement is the distance), two fake fingers for a pinch, and stray single-finger strokes around
|
||||||
|
* taps. None of them are button presses.
|
||||||
|
*/
|
||||||
|
private boolean onTouchpadGesture(MotionEvent ev) {
|
||||||
|
int action = ev.getActionMasked();
|
||||||
|
if (ev.getPointerCount() >= 2) {
|
||||||
|
float d = (float) Math.hypot(ev.getX(0) - ev.getX(1), ev.getY(0) - ev.getY(1));
|
||||||
|
if (action == MotionEvent.ACTION_POINTER_DOWN) {
|
||||||
|
pinchDist = d;
|
||||||
|
} else if (action == MotionEvent.ACTION_MOVE && pinchDist > 0 && actions != null) {
|
||||||
|
if (d > pinchDist * 1.25f) {
|
||||||
|
actions.zoom(1);
|
||||||
|
pinchDist = d;
|
||||||
|
} else if (d < pinchDist / 1.25f) {
|
||||||
|
actions.zoom(-1);
|
||||||
|
pinchDist = d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
pinchDist = 0;
|
||||||
|
boolean swipe = android.os.Build.VERSION.SDK_INT >= 34
|
||||||
|
&& ev.getClassification() == MotionEvent.CLASSIFICATION_TWO_FINGER_SWIPE;
|
||||||
|
if (action == MotionEvent.ACTION_DOWN) {
|
||||||
|
gestureY = ev.getY();
|
||||||
|
scrollAccum = 0;
|
||||||
|
} else if (action == MotionEvent.ACTION_MOVE && swipe) {
|
||||||
|
scrollAccum += (gestureY - ev.getY()) / renderer.getFontLineSpacing();
|
||||||
|
gestureY = ev.getY();
|
||||||
|
int lines = (int) scrollAccum;
|
||||||
|
if (lines != 0) {
|
||||||
|
scrollAccum -= lines;
|
||||||
|
scrollLines(lines, ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private static final int[][] BUTTONS = {
|
private static final int[][] BUTTONS = {
|
||||||
{MotionEvent.BUTTON_PRIMARY, TerminalEmulator.MOUSE_LEFT_BUTTON},
|
{MotionEvent.BUTTON_PRIMARY, TerminalEmulator.MOUSE_LEFT_BUTTON},
|
||||||
{MotionEvent.BUTTON_TERTIARY, 1},
|
{MotionEvent.BUTTON_TERTIARY, 1},
|
||||||
@@ -459,11 +507,12 @@ public final class TermView extends View {
|
|||||||
* button, so presses and releases are derived from changes in the button state.
|
* button, so presses and releases are derived from changes in the button state.
|
||||||
*/
|
*/
|
||||||
private boolean onMouse(MotionEvent ev) {
|
private boolean onMouse(MotionEvent ev) {
|
||||||
|
if (ev.getToolType(0) == MotionEvent.TOOL_TYPE_FINGER) return onTouchpadGesture(ev);
|
||||||
TerminalEmulator e = emulator();
|
TerminalEmulator e = emulator();
|
||||||
int action = ev.getActionMasked();
|
int action = ev.getActionMasked();
|
||||||
int state = ev.getButtonState()
|
int state = ev.getButtonState()
|
||||||
& (MotionEvent.BUTTON_PRIMARY | MotionEvent.BUTTON_SECONDARY | MotionEvent.BUTTON_TERTIARY);
|
& (MotionEvent.BUTTON_PRIMARY | MotionEvent.BUTTON_SECONDARY | MotionEvent.BUTTON_TERTIARY);
|
||||||
// Touchpad taps and injected events can come as DOWN/UP without any button state.
|
// Injected events (adb input mouse) come as DOWN/UP without any button state.
|
||||||
if (action == MotionEvent.ACTION_DOWN && state == 0) implicitPrimary = true;
|
if (action == MotionEvent.ACTION_DOWN && state == 0) implicitPrimary = true;
|
||||||
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) implicitPrimary = false;
|
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) implicitPrimary = false;
|
||||||
if (implicitPrimary) state |= MotionEvent.BUTTON_PRIMARY;
|
if (implicitPrimary) state |= MotionEvent.BUTTON_PRIMARY;
|
||||||
@@ -524,8 +573,8 @@ public final class TermView extends View {
|
|||||||
} else if (selDragging && (state & MotionEvent.BUTTON_PRIMARY) != 0
|
} else if (selDragging && (state & MotionEvent.BUTTON_PRIMARY) != 0
|
||||||
&& action == MotionEvent.ACTION_MOVE) {
|
&& action == MotionEvent.ACTION_MOVE) {
|
||||||
float y = ev.getY();
|
float y = ev.getY();
|
||||||
if (y < getPaddingTop()) scrollTranscript(-1);
|
if (y < textTop()) scrollTranscript(-1);
|
||||||
else if (y > getHeight() - getPaddingBottom()) scrollTranscript(1);
|
else if (y >= textTop() + emulator().mRows * renderer.getFontLineSpacing()) scrollTranscript(1);
|
||||||
extendSelection(col, row + topRow);
|
extendSelection(col, row + topRow);
|
||||||
}
|
}
|
||||||
if ((released & MotionEvent.BUTTON_PRIMARY) != 0 && selDragging) {
|
if ((released & MotionEvent.BUTTON_PRIMARY) != 0 && selDragging) {
|
||||||
|
|||||||
Reference in New Issue
Block a user