Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
| Offline AI | ONNX Runtime with T5-based grammar-correction models (Offline build only) |
| Custom AI Keys | 10 toolbar keys with user-defined prompts and hashtag personas |
| Floating Keyboard | Detachable draggable overlay window |
| Two-thumb Typing | Nintype-style combining mode, tap-during-swipe, manual spacing, autospace grace |
| Two-thumb Typing | Nintype-style combining mode, manual spacing, autospace grace, point hinting |
| UI / UX | Squircle key backgrounds, Split toolbar, Incognito icon, Clipboard search & undo, Screenshot suggestion, Emoji search |
Comment thread
AsafMah marked this conversation as resolved.
| Build flavors | `standard` (AI + internet), `offline` (ONNX, no internet), `offlinelite` (no AI at all) |

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy
// ValueAnimator drives invalidations at ~60fps so the bar shrinks smoothly; on cancel
// / timer-expiry we set mCombiningModeActive=false and the bar disappears next frame.
private boolean mCombiningModeActive = false;
private boolean mCombiningCompositionActiveForDebug = false;
private long mCombiningStartTimeMs = 0L;
private int mCombiningGraceMs = 0;
@Nullable private ValueAnimator mCombiningAnimator;
Expand Down Expand Up @@ -325,13 +326,19 @@ public void setLanguageOnSpacebarAnimAlpha(final int alpha) {
* No-ops when the space key isn't on the current layout (numeric / symbol).
*/
public void setCombiningMode(final boolean active, final long startTimeMs, final int graceMs) {
setCombiningMode(active, startTimeMs, graceMs, active);
}

public void setCombiningMode(final boolean active, final long startTimeMs, final int graceMs,
final boolean compositionActiveForDebug) {
// Stop any in-flight animator before mutating state — guarantees we don't have an
// animator updating mCombiningModeActive=false's invalidation while we set true.
if (mCombiningAnimator != null) {
mCombiningAnimator.cancel();
mCombiningAnimator = null;
}
mCombiningModeActive = active && graceMs > 0;
mCombiningCompositionActiveForDebug = compositionActiveForDebug;
mCombiningStartTimeMs = startTimeMs;
mCombiningGraceMs = graceMs;
// Always invalidate the whole view once so the global tint overlay appears or
Expand Down Expand Up @@ -555,6 +562,16 @@ public void clearGestureDebugPoints() {
mGestureDebugPointsDrawingPreview.clear();
}

@Override
public boolean isCombiningModeActiveForDebug() {
return mCombiningCompositionActiveForDebug;
}
Comment thread
AsafMah marked this conversation as resolved.

@Override
public boolean hasGestureDebugPoints() {
return mGestureDebugPointsDrawingPreview.hasSnapshot();
}

@Override
public void setGestureCommitPending(final boolean pending) {
mGestureFloatingTextDrawingPreview.setCommitPending(pending);
Expand Down
51 changes: 25 additions & 26 deletions app/src/main/java/helium314/keyboard/keyboard/PointerTracker.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,6 @@ public static void switchTo(DrawingProxy drawingProxy) {

private boolean mIsDetectingGesture = false; // per PointerTracker.
private static boolean sInGesture = false;
// True for this pointer when its down-event happened while another pointer's batch gesture
// was already in progress (sInGesture==true) and the pref PREF_GESTURE_TAP_DURING_SWIPE is on.
// Used in onUpEventInternal to suppress an accidental tap-keystroke if the parent gesture
// committed between this pointer's down and up.
private boolean mIsTapDuringSwipe = false;

// ---- Combining-mode tap seeding ------------------------------------------------------
// When the user taps a letter and within the combining-grace window starts a swipe, the
// pure concat path ("s" + recognizer-of-"ilo") produces unreliable results because the
Expand Down Expand Up @@ -365,9 +359,24 @@ private static DualThumbHinter.Result applyDualThumbHinting(
private static void pushGestureDebugSnapshot(
final InputPointers raw, final InputPointers syntheticOnly) {
if (!Settings.getValues().mGestureDebugDrawPoints) return;
Log.d(TAG, "debug gesture fragment raw=" + raw.getPointerSize()
+ " synthetic=" + syntheticOnly.getPointerSize());
sDrawingProxy.setGestureDebugPoints(raw, syntheticOnly);
}

private static void pushTapDebugPoint(final int x, final int y, final int pointerId,
final long eventTime) {
final SettingsValues sv = Settings.getValues();
if (!sv.mGestureDebugDrawPoints
|| (sv.mCombiningGraceMs <= 0 && !sv.mGestureManualSpacing)) {
return;
}
final InputPointers tap = new InputPointers(1);
tap.addPointer(x, y, pointerId, 0);
Log.d(TAG, "debug tap fragment x=" + x + " y=" + y + " pointer=" + pointerId);
sDrawingProxy.setGestureDebugPoints(tap, new InputPointers(0));
}


public static void setKeyboardActionListener(final KeyboardActionListener listener) {
sListener = listener;
Expand Down Expand Up @@ -696,9 +705,15 @@ public void onStartBatchInput() {
if (DEBUG_LISTENER) {
Log.d(TAG, String.format(Locale.US, "[%d] onStartBatchInput", mPointerId));
}
// Two-thumb typing (#2.1): a fresh gesture starts — wipe the previous batch's debug
// overlay so it doesn't visually mix with the in-flight gesture.
sDrawingProxy.clearGestureDebugPoints();
// Two-thumb typing debug overlay: clear only when this is a new word. While combining
// mode is active, a fresh gesture is another fragment of the same word and should remain
// visible alongside earlier fragments.
final SettingsValues settingsValues = Settings.getValues();
if (!settingsValues.mGestureDebugAccumulateFragments
|| (!sDrawingProxy.isCombiningModeActiveForDebug()
&& !settingsValues.mGestureManualSpacing)) {
sDrawingProxy.clearGestureDebugPoints();
}
sListener.onStartBatchInput();
dismissAllPopupKeysPanels();
sTimerProxy.cancelLongPressTimersOf(this);
Expand Down Expand Up @@ -930,12 +945,6 @@ private void onDownEvent(final int x, final int y, final long eventTime,
sTypingTimeRecorder.getLastLetterTypingTime(), getActivePointerTrackerCount());
mGestureStrokeDrawingPoints.onDownEvent(
seedX, seedY, mBatchInputArbiter.getElapsedTimeSinceFirstDown(seedTime));
// Two-thumb typing: remember whether this pointer started while another pointer's
// batch gesture was already in progress. Used in onUpEventInternal to suppress a
// stray tap-keystroke if the parent gesture commits before this pointer lifts.
mIsTapDuringSwipe = sInGesture
&& sv.mGestureTapDuringSwipe
&& key != null && Character.isLetter(key.getCode());
}
}

Expand Down Expand Up @@ -1394,8 +1403,6 @@ private void onUpEventInternal(final int x, final int y, final long eventTime) {
sTimerProxy.cancelKeyTimersOf(this);
final boolean isInDraggingFinger = mIsInDraggingFinger;
final boolean isInSlidingKeyInput = mIsInSlidingKeyInput;
final boolean wasTapDuringSwipe = mIsTapDuringSwipe;
mIsTapDuringSwipe = false;
resetKeySelectionByDraggingFinger();
mIsDetectingGesture = false;
final Key currentKey = mCurrentKey;
Expand Down Expand Up @@ -1489,15 +1496,6 @@ eventTime, getActivePointerTrackerCount(), graceMs, this,
&& (currentKey.getCode() == currentRepeatingKeyCode) && !isInDraggingFinger) {
return;
}
// Two-thumb typing (#1.3): if this pointer went down as a child of an in-progress
// batch gesture but the parent gesture committed before our up-event, suppress the
// tap-keystroke so we don't append a stray letter to the just-committed word.
// Long-press taps (longer than PREF_GESTURE_TAP_AS_SWIPE_WINDOW_MS) fall through to
// normal behaviour so the user can still type characters after a gesture commits.
if (wasTapDuringSwipe && !sInGesture
&& eventTime - mDownTime <= Settings.getValues().mGestureTapAsSwipeWindowMs) {
return;
}
detectAndSendKey(currentKey, mKeyX, mKeyY, eventTime);
// Combining-mode seeding: remember the last letter tap so a follow-up gesture can
// seed its first pointer event with this position and time. Only letter taps qualify
Expand All @@ -1510,6 +1508,7 @@ eventTime, getActivePointerTrackerCount(), graceMs, this,
sLastLetterTapY = mKeyY;
sLastLetterTapTime = eventTime;
sLastLetterTapCodepoint = code;
pushTapDebugPoint(mKeyX, mKeyY, mPointerId, eventTime);
}
}
if (isInSlidingKeyInput) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ void setGestureDebugPoints(@NonNull helium314.keyboard.latin.common.InputPointer
/** Clear the debug-points overlay (e.g. on gesture start or cancel). */
void clearGestureDebugPoints();

/** Whether debug overlay fragments should be preserved across the next gesture start. */
boolean isCombiningModeActiveForDebug();

/** True when there are debug points currently visible on the overlay. */
boolean hasGestureDebugPoints();

/**
* Toggle a "commit pending" visual indicator on the gesture floating preview text
* (feature #1.2). Shown during the autospace grace window so the user has a visible cue
Expand Down
Loading
Loading