ime: fcitx: Retrieve cursor position and selection Also, if `SDL_HINT_IME_SUPPORT_EXTENDED_TEXT` is enabled, make use of `SDL_TEXTEDITING_EXT` by sending the full preedit string.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
diff --git a/src/core/linux/SDL_fcitx.c b/src/core/linux/SDL_fcitx.c
index bab5e88..b7a0cfa 100644
--- a/src/core/linux/SDL_fcitx.c
+++ b/src/core/linux/SDL_fcitx.c
@@ -85,14 +85,22 @@ GetAppName()
}
static size_t
-Fcitx_GetPreeditString(SDL_DBusContext *dbus, DBusMessage *msg, char **ret) {
+Fcitx_GetPreeditString(SDL_DBusContext *dbus,
+ DBusMessage *msg,
+ char **ret,
+ Sint32 *start_pos,
+ Sint32 *end_pos)
+{
char *text = NULL, *subtext;
size_t text_bytes = 0;
DBusMessageIter iter, array, sub;
+ Sint32 p_start_pos = -1;
+ Sint32 p_end_pos = -1;
dbus->message_iter_init(msg, &iter);
/* Message type is a(si)i, we only need string part */
if (dbus->message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY) {
+ size_t pos = 0;
/* First pass: calculate string length */
dbus->message_iter_recurse(&iter, &array);
while (dbus->message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
@@ -103,7 +111,29 @@ Fcitx_GetPreeditString(SDL_DBusContext *dbus, DBusMessage *msg, char **ret) {
text_bytes += SDL_strlen(subtext);
}
}
+ dbus->message_iter_next(&sub);
+ if (dbus->message_iter_get_arg_type(&sub) == DBUS_TYPE_INT32 && p_end_pos == -1) {
+ /* Type is a bit field defined as follows: */
+ /* bit 3: Underline, bit 4: HighLight, bit 5: DontCommit, */
+ /* bit 6: Bold, bit 7: Strike, bit 8: Italic */
+ Sint32 type;
+ dbus->message_iter_get_basic(&sub, &type);
+ /* We only consider highlight */
+ if (type & (1 << 4)) {
+ if (p_start_pos == -1) {
+ p_start_pos = pos;
+ }
+ } else if (p_start_pos != -1 && p_end_pos == -1) {
+ p_end_pos = pos;
+ }
+ }
dbus->message_iter_next(&array);
+ if (subtext && *subtext) {
+ pos += SDL_utf8strlen(subtext);
+ }
+ }
+ if (p_start_pos != -1 && p_end_pos == -1) {
+ p_end_pos = pos;
}
if (text_bytes) {
text = SDL_malloc(text_bytes + 1);
@@ -129,10 +159,32 @@ Fcitx_GetPreeditString(SDL_DBusContext *dbus, DBusMessage *msg, char **ret) {
text_bytes = 0;
}
}
- *ret= text;
+
+ *ret = text;
+ *start_pos = p_start_pos;
+ *end_pos = p_end_pos;
return text_bytes;
}
+static Sint32
+Fcitx_GetPreeditCursorByte(SDL_DBusContext *dbus, DBusMessage *msg)
+{
+ Sint32 byte = -1;
+ DBusMessageIter iter;
+
+ dbus->message_iter_init(msg, &iter);
+
+ dbus->message_iter_next(&iter);
+
+ if (dbus->message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32) {
+ return -1;
+ }
+
+ dbus->message_iter_get_basic(&iter, &byte);
+
+ return byte;
+}
+
static DBusHandlerResult
DBus_MessageFilter(DBusConnection *conn, DBusMessage *msg, void *data)
{
@@ -162,20 +214,28 @@ DBus_MessageFilter(DBusConnection *conn, DBusMessage *msg, void *data)
if (dbus->message_is_signal(msg, FCITX_IC_DBUS_INTERFACE, "UpdateFormattedPreedit")) {
char *text = NULL;
- size_t text_bytes = Fcitx_GetPreeditString(dbus, msg, &text);
+ Sint32 start_pos, end_pos;
+ size_t text_bytes = Fcitx_GetPreeditString(dbus, msg, &text, &start_pos, &end_pos);
if (text_bytes) {
- char buf[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
- size_t i = 0;
- size_t cursor = 0;
-
- while (i < text_bytes) {
- const size_t sz = SDL_utf8strlcpy(buf, text + i, sizeof(buf));
- const size_t chars = SDL_utf8strlen(buf);
-
- SDL_SendEditingText(buf, cursor, chars);
-
- i += sz;
- cursor += chars;
+ if (SDL_GetHintBoolean(SDL_HINT_IME_SUPPORT_EXTENDED_TEXT, SDL_FALSE)) {
+ if (start_pos == -1) {
+ Sint32 byte_pos = Fcitx_GetPreeditCursorByte(dbus, msg);
+ start_pos = byte_pos >= 0 ? SDL_utf8strnlen(text, byte_pos) : -1;
+ }
+ SDL_SendEditingText(text, start_pos, end_pos >= 0 ? end_pos - start_pos : -1);
+ } else {
+ char buf[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
+ size_t i = 0;
+ size_t cursor = 0;
+ while (i < text_bytes) {
+ const size_t sz = SDL_utf8strlcpy(buf, text + i, sizeof(buf));
+ const size_t chars = SDL_utf8strlen(buf);
+
+ SDL_SendEditingText(buf, cursor, chars);
+
+ i += sz;
+ cursor += chars;
+ }
}
SDL_free(text);
} else {