Emoji input: remove context-dependent unicode points from output of emoji palette.
Build and Test / build-linux (push) Has been cancelled
Build and Test / build-wayland (push) Has been cancelled
Build and Test / build-macos (push) Has been cancelled
Build and Test / build-windows (push) Has been cancelled

The character palette allowing to input emojis in text generates in some cases a series
of unicode points to represent a single emoji. These series contain various kinds of
unicode points with context-dependent meaning. This commit prevents such context-
dependent unicodepoints from being inserted in FLTK text because FLTK text edition
mechanism is not ready to handle properly context dependency in edited UTF-8 text.
This commit is contained in:
ManoloFLTK
2026-01-18 18:04:06 +01:00
parent 20157f7caa
commit f3cbce2e92
2 changed files with 28 additions and 5 deletions
+16 -1
View File
@@ -2954,8 +2954,23 @@ static FLTextInputContext* fltextinputcontext_instance = nil;
BOOL has_text_key = Fl::e_keysym <= '~' || Fl::e_keysym == FL_Iso_Key ||
(Fl::e_keysym >= FL_KP && Fl::e_keysym <= FL_KP_Last && Fl::e_keysym != FL_KP_Enter);
// insertText sent during handleEvent of a key without text cannot be processed in a single FL_KEYBOARD event.
// Occurs with deadkey followed by non-text key
// Occurs with deadkey followed by non-text key. Occurs also with emoji palette.
if (!in_key_event || !has_text_key) {
if (fl_utf_nb_char((const uchar*)Fl::e_text, Fl::e_length) > 1) {
// Some emojis are expressed by a series of Unicode points
const char *p = Fl::e_text, *end = Fl::e_text + Fl::e_length;
int len;
while (p < end) { // loop over all unicode points of the series
unsigned u = fl_utf8decode(p, end, &len); // extract one such unicode point
if ((u >= 0xFE00 && u <= 0xFE0F) // variation selectors
|| u == 0x200D // zero-width joiner
|| (u >= 0x1F3FB && u <= 0x1F3FF) // EMOJI MODIFIERS FITZPATRICK TYPE
) { // remove context-dependent unicode points
memmove((void*)p, p + len, (end - (p+len)) + 1);
Fl::e_length -= len; end -= len;
} else p += len; // keep other unicode points
}
}
Fl::handle(FL_KEYBOARD, target);
Fl::e_length = 0;
}
+12 -4
View File
@@ -1562,8 +1562,8 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
if (uMsg == WM_CHAR || uMsg == WM_SYSCHAR) {
wchar_t u = (wchar_t)wParam;
// Windows emoji palette triggered with Windows + dot sends 2 or more WM_CHAR messages:
// the 2 components of a surrogate pair, or variation selectors, or zero-width stuff,
// or extra Unicode points.
// the 2 components of a surrogate pair, or variation selectors, or zero-width joiner,
// or emoji modifiers FITZPATRICK or extra Unicode points.
if (u >= 0xD800 && u <= 0xDFFF) { // handle the 2 components of a surrogate pair
static wchar_t surrogate_pair[2];
if (IS_HIGH_SURROGATE(u)) {
@@ -1572,10 +1572,18 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
return 0; // and wait for next WM_CHAR message that will give the 2nd member
} else {
surrogate_pair[1] = u; // memorize the 2nd member of the pair
unsigned u32 = // convert surrogate pair to UTF-32
0x10000 + ((surrogate_pair[0] & 0x3ff) << 10) + (surrogate_pair[1] & 0x3ff);
if (u32 >= 0x1F3FB && u32 <= 0x1F3FF) { // emoji modifiers FITZPATRICK
Fl::e_length = 0; // skip them
return 0;
}
Fl::e_length = fl_utf8fromwc(buffer, 1024, surrogate_pair, 2); // transform to UTF-8
}
} else if ((u >= 0xFE00 && u <= 0xFE0F) || (u >= 0x200B && u <= 0x200D)) {
Fl::e_length = 0; // skip variation selectors and zero-width Unicode points
} else if ( (u >= 0xFE00 && u <= 0xFE0F) // variation selectors
|| u == 0x200D // zero-width joiner
) {
Fl::e_length = 0; // skip these context-dependent Unicode points
return 0;
} else {
Fl::e_length = fl_utf8fromwc(buffer, 1024, &u, 1); // process regular Unicode point