Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Accelerated backspace measures the wrong code point and can split an emoji

Open Beginner friendly
#423 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
65/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
android, java
Domain
mobile

Research direction

Read app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java around lines 2019–2026, starting with the accelerated backspace logic and how it reads the code point before the cursor. Check the deletion length for both a plain character followed by an emoji and an emoji followed by a plain character; done means the second deletion uses the re-read code point and does not split an emoji or over-delete a plain character.

Written by the indexing model from the issue text.

Description

Summary

In InputLogic.handleBackspaceEvent, the accelerated (held-backspace) second deletion measures its length from the first code point instead of the one it is actually about to delete. When the second character back is a multi-code-point emoji, this deletes the wrong number of chars and can split the emoji, leaving an orphaned surrogate or a stray variation selector / ZWJ.

Present at tag v4.1.2 (f0ff166ae).

Location

app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java, around lines 2019–2026:

final int codePointBeforeCursorToDeleteAgain = mConnection.getCodePointBeforeCursor();
if (codePointBeforeCursorToDeleteAgain != Constants.NOT_A_CODE) {
    final int lengthToDeleteAgain = codePointBeforeCursor > 0xFE00          // <-- first code point
            || StringUtils.mightBeEmoji(codePointBeforeCursor)              // <-- first code point
                    ? mConnection.getCharCountToDeleteBeforeCursor()
                    : 1;
    mConnection.deleteTextBeforeCursor(lengthToDeleteAgain);
    totalDeletedLength += lengthToDeleteAgain;
}

The guard correctly re-reads the cursor into codePointBeforeCursorToDeleteAgain, but the ternary that decides the delete length still tests codePointBeforeCursor — the value from before the first deletion.

Consequences

Both directions are wrong:

  • First char plain, second an emoji → the branch evaluates false, so lengthToDeleteAgain is 1. A single char is removed from a multi-char emoji, splitting it.
  • First char an emoji, second plain → the branch evaluates true, so getCharCountToDeleteBeforeCursor() is used against a plain character and may remove more than intended.

Only reachable once mDeleteCount > Constants.DELETE_ACCELERATE_AT, i.e. while holding backspace, which is probably why it has gone unnoticed.

Suggested fix

Use the re-read value in the condition, so it describes the character actually being deleted:

final int lengthToDeleteAgain = codePointBeforeCursorToDeleteAgain > 0xFE00
        || StringUtils.mightBeEmoji(codePointBeforeCursorToDeleteAgain)
                ? mConnection.getCharCountToDeleteBeforeCursor()
                : 1;

Notes

Found while merging v4.1.2 into a downstream fork. This almost certainly predates LeanType — the surrounding accelerated-delete code comes from the HeliBoard/AOSP lineage — so it may be worth forwarding to Helium314/HeliBoard as well.

I have no reproduction on a physical device; this is from reading the code, so please sanity-check the emoji-splitting claim against real input before acting on it.

Dominant language
Kotlin
Stars
1k
Forks
59
Avg merge
14h 37m
Merged PRs (30d)
54

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from LeanBitLab/LeanType

All issues in LeanBitLab/LeanType

Similar issues

More Kotlin issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.