# HG changeset patch # User Alex Baines # Date 1406677741 -3600 # Node ID 3cbcd2434f64f2571f8811a5760682321500a240 # Parent 65beae82fc0c5658043cd7044161ce54c5f40dc4 Add a SDL_IBUS_EDITING_EVENTS hint to let IBus handle text editing by default, and allow applications to opt in to rendering the editing text themselves by setting it to 1. Also improve handling of inotify and keeping the candidate list position up to date. diff -r 65beae82fc0c -r 3cbcd2434f64 include/SDL_hints.h --- a/include/SDL_hints.h Sun Jul 27 19:05:40 2014 +0100 +++ b/include/SDL_hints.h Wed Jul 30 00:49:01 2014 +0100 @@ -477,6 +477,20 @@ */ #define SDL_HINT_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION "SDL_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION" +/** + * \brief A variable to control whether SDL sends TEXTEDITING events from IBus. + * + * This hint only applies to Linux. + * + * The variable can be set to the following values: + * "0" - TEXTEDITING events are not sent, and text that is being + * composed by IBus will be rendered in its own UI. (Default) + * "1" - TEXTEDITING events are sent, and it is the application's + * responsibility to render the text from these events and + * differentiate it somehow from committed text. + * (This is often done by underlining the text being edited.) + */ +#define SDL_HINT_IBUS_EDITING_EVENTS "SDL_IBUS_EDITING_EVENTS" /** * \brief An enumeration of hint priorities diff -r 65beae82fc0c -r 3cbcd2434f64 src/core/linux/SDL_ibus.c --- a/src/core/linux/SDL_ibus.c Sun Jul 27 19:05:40 2014 +0100 +++ b/src/core/linux/SDL_ibus.c Wed Jul 30 00:49:01 2014 +0100 @@ -46,6 +46,7 @@ static DBusConnection *ibus_conn = NULL; static char *ibus_addr_file = NULL; int inotify_fd = -1; +int inotify_wd = -1; static Uint32 IBus_ModState(void) @@ -289,6 +290,40 @@ return SDL_strdup(file_path); } +static SDL_bool IBus_CheckConnection(SDL_DBusContext *dbus); + +static void +IBus_SetCapabilities(void *data, const char *name, const char *old_val, + const char *cap_preedit) +{ + SDL_DBusContext *dbus = SDL_DBus_GetContext(); + + if(IBus_CheckConnection(dbus)){ + + DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE, + input_ctx_path, + IBUS_INPUT_INTERFACE, + "SetCapabilities"); + if(msg){ + Uint32 caps = IBUS_CAP_FOCUS; + if(cap_preedit && *cap_preedit && *cap_preedit != '0'){ + caps |= IBUS_CAP_PREEDIT_TEXT; + } + + dbus->message_append_args(msg, + DBUS_TYPE_UINT32, &caps, + DBUS_TYPE_INVALID); + } + + if(msg){ + if(dbus->connection_send(ibus_conn, msg, NULL)){ + dbus->connection_flush(ibus_conn); + } + dbus->message_unref(msg); + } + } +} + static SDL_bool IBus_SetupConnection(SDL_DBusContext *dbus, const char* addr) { @@ -341,31 +376,12 @@ } if(result){ - DBusMessage *msg2 = dbus->message_new_method_call(IBUS_SERVICE, - input_ctx_path, - IBUS_INPUT_INTERFACE, - "SetCapabilities"); - if(msg2){ - Uint32 caps = IBUS_CAP_FOCUS | IBUS_CAP_PREEDIT_TEXT; - dbus->message_append_args(msg2, - DBUS_TYPE_UINT32, &caps, - DBUS_TYPE_INVALID); - } - - if(msg2){ - if(dbus->connection_send(ibus_conn, msg2, NULL)){ - dbus->connection_flush(ibus_conn); - } - dbus->message_unref(msg2); - } + SDL_AddHintCallback(SDL_HINT_IBUS_EDITING_EVENTS, &IBus_SetCapabilities, NULL); dbus->bus_add_match(ibus_conn, "type='signal',interface='org.freedesktop.IBus.InputContext'", NULL); dbus->connection_add_filter(ibus_conn, &IBus_MessageFilter, dbus, NULL); dbus->connection_flush(ibus_conn); } - - SDL_IBus_SetFocus(SDL_GetFocusWindow() != NULL); - SDL_IBus_UpdateTextRect(NULL); return result; } @@ -379,7 +395,7 @@ return SDL_TRUE; } - if(inotify_fd != -1){ + if(inotify_wd != -1){ char buf[1024]; ssize_t readsize = read(inotify_fd, buf, sizeof(buf)); if(readsize > 0){ @@ -432,15 +448,17 @@ char *addr = IBus_ReadAddressFromFile(addr_file); - inotify_fd = inotify_init(); - fcntl(inotify_fd, F_SETFL, O_NONBLOCK); + if(inotify_fd < 0){ + inotify_fd = inotify_init(); + fcntl(inotify_fd, F_SETFL, O_NONBLOCK); + } char *addr_file_dir = SDL_strrchr(addr_file, '/'); if(addr_file_dir){ *addr_file_dir = 0; } - inotify_add_watch(inotify_fd, addr_file, IN_CREATE | IN_MODIFY); + inotify_wd = inotify_add_watch(inotify_fd, addr_file, IN_CREATE | IN_MODIFY); SDL_free(addr_file); result = IBus_SetupConnection(dbus, addr); @@ -470,6 +488,13 @@ dbus->connection_unref(ibus_conn); } + if(inotify_fd > 0 && inotify_wd > 0){ + inotify_rm_watch(inotify_fd, inotify_wd); + inotify_wd = -1; + } + + SDL_DelHintCallback(SDL_HINT_IBUS_EDITING_EVENTS, &IBus_SetCapabilities, NULL); + SDL_memset(&ibus_cursor_rect, 0, sizeof(ibus_cursor_rect)); } @@ -542,6 +567,8 @@ } + SDL_IBus_UpdateTextRect(NULL); + return result; } @@ -582,7 +609,7 @@ x += ibus_cursor_rect.x; y += ibus_cursor_rect.y; - + SDL_DBusContext *dbus = SDL_DBus_GetContext(); if(IBus_CheckConnection(dbus)){