Add a SDL_IM_INTERNAL_EDITING event to make IMs like iBus render editing text in its own UI instead of sending TEXTEDITING events.
authorAlex Baines <alex@abaines.me.uk>
Tue, 19 Aug 2014 23:31:50 +0100
changeset 909756d712662a82
parent 9096 6454f71d6f15
child 9098 064ea0b1275c
Add a SDL_IM_INTERNAL_EDITING event to make IMs like iBus render editing text in its own UI instead of sending TEXTEDITING events.
This is useful for applications that handle TEXTINPUT events but not TEXTEDITING events.
include/SDL_hints.h
src/core/linux/SDL_ibus.c
     1.1 --- a/include/SDL_hints.h	Tue Aug 19 23:17:28 2014 +0100
     1.2 +++ b/include/SDL_hints.h	Tue Aug 19 23:31:50 2014 +0100
     1.3 @@ -477,6 +477,18 @@
     1.4   */
     1.5  #define SDL_HINT_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION "SDL_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION"
     1.6  
     1.7 +/**
     1.8 + * \brief A variable to control whether certain IMs should handle text editing internally instead of sending TEXTEDITING events.
     1.9 + *
    1.10 + *
    1.11 + * The variable can be set to the following values:
    1.12 + *   "0"       - TEXTEDITING events are sent, and it is the application's
    1.13 + *               responsibility to render the text from these events and 
    1.14 + *               differentiate it somehow from committed text. (default)
    1.15 + *   "1"       - If supported by the IM then TEXTEDITING events are not sent, 
    1.16 + *               and text that is being composed will be rendered in its own UI.
    1.17 + */
    1.18 +#define SDL_HINT_IM_INTERNAL_EDITING "SDL_IM_INTERNAL_EDITING"
    1.19  
    1.20  /**
    1.21   *  \brief  An enumeration of hint priorities
     2.1 --- a/src/core/linux/SDL_ibus.c	Tue Aug 19 23:17:28 2014 +0100
     2.2 +++ b/src/core/linux/SDL_ibus.c	Tue Aug 19 23:31:50 2014 +0100
     2.3 @@ -288,6 +288,41 @@
     2.4      return SDL_strdup(file_path);
     2.5  }
     2.6  
     2.7 +static SDL_bool IBus_CheckConnection(SDL_DBusContext *dbus);
     2.8 +
     2.9 +static void
    2.10 +IBus_SetCapabilities(void *data, const char *name, const char *old_val,
    2.11 +                                                   const char *internal_editing)
    2.12 +{
    2.13 +    SDL_DBusContext *dbus = SDL_DBus_GetContext();
    2.14 +    
    2.15 +    if(IBus_CheckConnection(dbus)){
    2.16 +
    2.17 +        DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
    2.18 +                                                         input_ctx_path,
    2.19 +                                                         IBUS_INPUT_INTERFACE,
    2.20 +                                                         "SetCapabilities");
    2.21 +        if(msg){
    2.22 +            Uint32 caps = IBUS_CAP_FOCUS;
    2.23 +            if(!(internal_editing && *internal_editing == '1')){
    2.24 +                caps |= IBUS_CAP_PREEDIT_TEXT;
    2.25 +            }
    2.26 +            
    2.27 +            dbus->message_append_args(msg,
    2.28 +                                      DBUS_TYPE_UINT32, &caps,
    2.29 +                                      DBUS_TYPE_INVALID);
    2.30 +        }
    2.31 +        
    2.32 +        if(msg){
    2.33 +            if(dbus->connection_send(ibus_conn, msg, NULL)){
    2.34 +                dbus->connection_flush(ibus_conn);
    2.35 +            }
    2.36 +            dbus->message_unref(msg);
    2.37 +        }
    2.38 +    }
    2.39 +}
    2.40 +
    2.41 +
    2.42  static SDL_bool
    2.43  IBus_SetupConnection(SDL_DBusContext *dbus, const char* addr)
    2.44  {
    2.45 @@ -340,23 +375,7 @@
    2.46      }
    2.47  
    2.48      if(result){
    2.49 -        msg = dbus->message_new_method_call(IBUS_SERVICE,
    2.50 -                                            input_ctx_path,
    2.51 -                                            IBUS_INPUT_INTERFACE,
    2.52 -                                            "SetCapabilities");
    2.53 -        if(msg){
    2.54 -            Uint32 caps = IBUS_CAP_FOCUS | IBUS_CAP_PREEDIT_TEXT;
    2.55 -            dbus->message_append_args(msg,
    2.56 -                                      DBUS_TYPE_UINT32, &caps,
    2.57 -                                      DBUS_TYPE_INVALID);
    2.58 -        }
    2.59 -        
    2.60 -        if(msg){
    2.61 -            if(dbus->connection_send(ibus_conn, msg, NULL)){
    2.62 -                dbus->connection_flush(ibus_conn);
    2.63 -            }
    2.64 -            dbus->message_unref(msg);
    2.65 -        }
    2.66 +        SDL_AddHintCallback(SDL_HINT_IM_INTERNAL_EDITING, &IBus_SetCapabilities, NULL);
    2.67          
    2.68          dbus->bus_add_match(ibus_conn, "type='signal',interface='org.freedesktop.IBus.InputContext'", NULL);
    2.69          dbus->connection_add_filter(ibus_conn, &IBus_MessageFilter, dbus, NULL);
    2.70 @@ -476,6 +495,8 @@
    2.71          inotify_wd = -1;
    2.72      }
    2.73      
    2.74 +    SDL_DelHintCallback(SDL_HINT_IM_INTERNAL_EDITING, &IBus_SetCapabilities, NULL);
    2.75 +    
    2.76      SDL_memset(&ibus_cursor_rect, 0, sizeof(ibus_cursor_rect));
    2.77  }
    2.78  
    2.79 @@ -548,6 +569,8 @@
    2.80          
    2.81      }
    2.82      
    2.83 +    SDL_IBus_UpdateTextRect(NULL);
    2.84 +
    2.85      return result;
    2.86  }
    2.87