diff options
| author | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2026-01-19 16:34:50 +0100 |
|---|---|---|
| committer | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2026-01-19 16:34:50 +0100 |
| commit | 61e75e4a12f199368f28dd274d83fc4ecd9cfec3 (patch) | |
| tree | 94c71a1dffe9c6d9ac4a51dbec84561d38828b2c | |
| parent | 59d93554b3aff9614276fec99792807d77b24ee5 (diff) | |
All platforms use same code to remove context-dependent codepoints from text input.
This commit introduces function fl_utf8_remove_context_dependent() that removes
from an UTF-8 string its context-dependent codepoints. Platforms macOS, Wayland
and X11 call this function to process UTF-8 text received from a character palette
as input to FLTK text. This makes sure FLTK text-editing widgets process textual input
equally and consistently across platforms, especially emojis entered via a palette.
Platform Windows creates a series of separate system events to input an emoji
via the character palette. For this reason, function fl_utf8_remove_context_dependent()
is not used by this platform which does internally the same filtering of context-
dependent codepoints.
| -rw-r--r-- | src/Fl_cocoa.mm | 17 | ||||
| -rw-r--r-- | src/Fl_x.cxx | 4 | ||||
| -rw-r--r-- | src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx | 2 | ||||
| -rw-r--r-- | src/fl_utf8.cxx | 29 |
4 files changed, 35 insertions, 17 deletions
diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm index eeeedf425..fed978e1e 100644 --- a/src/Fl_cocoa.mm +++ b/src/Fl_cocoa.mm @@ -67,6 +67,7 @@ extern "C" { // external functions extern void fl_fix_focus(); extern int fl_send_system_handlers(void *e); +extern int fl_utf8_remove_context_dependent(char *text, int len); // forward definition of functions in this file // converting cr lf converter function @@ -2956,21 +2957,7 @@ static FLTextInputContext* fltextinputcontext_instance = nil; // 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 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::e_length = fl_utf8_remove_context_dependent(Fl::e_text, Fl::e_length); Fl::handle(FL_KEYBOARD, target); Fl::e_length = 0; } diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx index fa58c8076..150438755 100644 --- a/src/Fl_x.cxx +++ b/src/Fl_x.cxx @@ -1,7 +1,7 @@ // // X specific code for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2025 by Bill Spitzak and others. +// Copyright 1998-2026 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -101,6 +101,7 @@ extern Fl_Window *fl_xmousewin; static void open_display_i(Display *d); // open display (internal) extern int fl_send_system_handlers(void *e); +extern int fl_utf8_remove_context_dependent(char *text, int len); #if FLTK_CONSOLIDATE_MOTION static Fl_Window *send_motion; @@ -1833,6 +1834,7 @@ int fl_handle(const XEvent& thisevent) Status status; len = XUtf8LookupString(Fl_X11_Screen_Driver::xim_ic, (XKeyPressedEvent *)&xevent.xkey, kp_buffer, kp_buffer_len, &keysym, &status); + len = fl_utf8_remove_context_dependent(kp_buffer, len); while (status == XBufferOverflow && kp_buffer_len < 50000) { kp_buffer_len = kp_buffer_len * 5 + 1; diff --git a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx index c474867d5..3816dff2c 100644 --- a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx @@ -53,6 +53,7 @@ extern "C" { bool fl_is_surface_from_GTK_titlebar (struct wl_surface *surface, struct libdecor_frame *frame, bool *using_GTK); } +extern int fl_utf8_remove_context_dependent(char *text, int len); // set this to 1 for keyboard debug output, 0 for no debug output #define DEBUG_KEYBOARD 0 @@ -1017,6 +1018,7 @@ void text_input_commit_string(void *data, struct zwp_text_input_v3 *zwp_text_inp //printf("text_input_commit_string %s\n",text); free(pending_commit); pending_commit = text ? strdup(text) : NULL; + fl_utf8_remove_context_dependent(pending_commit, strlen(pending_commit)); } diff --git a/src/fl_utf8.cxx b/src/fl_utf8.cxx index 7cc53f13b..05e45ded3 100644 --- a/src/fl_utf8.cxx +++ b/src/fl_utf8.cxx @@ -3,7 +3,7 @@ // // Author: Jean-Marc Lienher ( http://oksid.ch ) // Copyright 2000-2010 by O'ksi'D. -// Copyright 2016-2022 by Bill Spitzak and others. +// Copyright 2016-2026 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -1630,3 +1630,30 @@ unsigned fl_utf8from_mb(char* dst, unsigned dstlen, const char* src, unsigned sr } /** @} */ + +#ifndef FL_DOXYGEN + +/* This function removes from an UTF-8 string its context-dependent codepoints + when there are any, and returns the length of the possibly shortened string. + */ +int fl_utf8_remove_context_dependent(char *text, int len) { + if (len > 1 && fl_utf_nb_char((const uchar*)text, len) > 1) { + // Some emojis are expressed by a series of Unicode points + char *p = text, *end = text + len; + while (p < end) { // loop over all unicode points of the series + int l_point; + unsigned u = fl_utf8decode(p, end, &l_point); // 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 + l_point, (end - (p+l_point)) + 1); + end -= l_point; + len -= l_point; + } else p += l_point; // keep other unicode points + } + } + return len; +} + +#endif // ! FL_DOXYGEN |
