From 5aedeaf8a9b6548de2891cecc38f7ae1932f9d27 Mon Sep 17 00:00:00 2001 From: Koki Ryu Date: Thu, 20 Oct 2022 15:04:53 +0900 Subject: [PATCH] Handle emojis with emoji-modifier and zwj properly on backspace Since Unicode 12, emoji modifier sequences (such as human + light skin tone) can be combined with zwj. However, current backspace state machine ignores that and stops when one emoji modifier sequence is found. This CL make the state machine continue exploration as long as a zwj is found before an emoji modifier sequence. BYPASS_INCLUSIVE_LANGUAGE_REASON="man" is the name of the emoji Bug: 171495034 Test: Do the following: - Enter an emoji from the "family" subgroup with different skin tones combined such as 1F468 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F468 "kiss: man, man, medium-dark skin tone, light skin tone" - Press the backspace key and confirm that the entire emoji is deleted. Change-Id: I260f509832cb24486665019d68a25db0ad089d7e --- core/java/android/text/method/BaseKeyListener.java | 2 ++ .../coretests/src/android/text/method/BackspaceTest.java | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/core/java/android/text/method/BaseKeyListener.java b/core/java/android/text/method/BaseKeyListener.java index d4bcd12abd965..01989d54b871c 100644 --- a/core/java/android/text/method/BaseKeyListener.java +++ b/core/java/android/text/method/BaseKeyListener.java @@ -229,6 +229,8 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener break; } else if (Emoji.isEmojiModifierBase(codePoint)) { deleteCharCount += Character.charCount(codePoint); + state = STATE_BEFORE_EMOJI; + break; } state = STATE_FINISHED; break; diff --git a/core/tests/coretests/src/android/text/method/BackspaceTest.java b/core/tests/coretests/src/android/text/method/BackspaceTest.java index ddae652cec059..19c2c61535580 100644 --- a/core/tests/coretests/src/android/text/method/BackspaceTest.java +++ b/core/tests/coretests/src/android/text/method/BackspaceTest.java @@ -193,11 +193,15 @@ public class BackspaceTest { backspace(state, 0); state.assertEquals("|"); - // Emoji modifier can be appended to the first emoji. + // Emoji modifier can be appended to each emoji. state.setByString("U+1F469 U+1F3FB U+200D U+1F4BC |"); backspace(state, 0); state.assertEquals("|"); + state.setByString("U+1F468 U+1F3FF U+200D U+2764 U+FE0F U+200D U+1F468 U+1F3FB |"); + backspace(state, 0); + state.assertEquals("|"); + // End with ZERO WIDTH JOINER state.setByString("U+1F441 U+200D |"); backspace(state, 0);