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.main
parent
dd7bed9ebc
commit
e5a3acd6bd
|
@ -85,14 +85,22 @@ GetAppName()
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t
|
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;
|
char *text = NULL, *subtext;
|
||||||
size_t text_bytes = 0;
|
size_t text_bytes = 0;
|
||||||
DBusMessageIter iter, array, sub;
|
DBusMessageIter iter, array, sub;
|
||||||
|
Sint32 p_start_pos = -1;
|
||||||
|
Sint32 p_end_pos = -1;
|
||||||
|
|
||||||
dbus->message_iter_init(msg, &iter);
|
dbus->message_iter_init(msg, &iter);
|
||||||
/* Message type is a(si)i, we only need string part */
|
/* Message type is a(si)i, we only need string part */
|
||||||
if (dbus->message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY) {
|
if (dbus->message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY) {
|
||||||
|
size_t pos = 0;
|
||||||
/* First pass: calculate string length */
|
/* First pass: calculate string length */
|
||||||
dbus->message_iter_recurse(&iter, &array);
|
dbus->message_iter_recurse(&iter, &array);
|
||||||
while (dbus->message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
|
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);
|
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);
|
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) {
|
if (text_bytes) {
|
||||||
text = SDL_malloc(text_bytes + 1);
|
text = SDL_malloc(text_bytes + 1);
|
||||||
|
@ -129,10 +159,32 @@ Fcitx_GetPreeditString(SDL_DBusContext *dbus, DBusMessage *msg, char **ret) {
|
||||||
text_bytes = 0;
|
text_bytes = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*ret= text;
|
|
||||||
|
*ret = text;
|
||||||
|
*start_pos = p_start_pos;
|
||||||
|
*end_pos = p_end_pos;
|
||||||
return text_bytes;
|
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
|
static DBusHandlerResult
|
||||||
DBus_MessageFilter(DBusConnection *conn, DBusMessage *msg, void *data)
|
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")) {
|
if (dbus->message_is_signal(msg, FCITX_IC_DBUS_INTERFACE, "UpdateFormattedPreedit")) {
|
||||||
char *text = NULL;
|
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) {
|
if (text_bytes) {
|
||||||
char buf[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
|
if (SDL_GetHintBoolean(SDL_HINT_IME_SUPPORT_EXTENDED_TEXT, SDL_FALSE)) {
|
||||||
size_t i = 0;
|
if (start_pos == -1) {
|
||||||
size_t cursor = 0;
|
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);
|
||||||
|
|
||||||
while (i < text_bytes) {
|
SDL_SendEditingText(buf, cursor, chars);
|
||||||
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;
|
||||||
i += sz;
|
}
|
||||||
cursor += chars;
|
|
||||||
}
|
}
|
||||||
SDL_free(text);
|
SDL_free(text);
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue