Added proxy calls to IBusInputContext service
authorEduardo Lima (Etrunko) <eduardo.lima@intel.com>
Mon, 21 Oct 2013 18:03:45 +0000 (16:03 -0200)
committerEduardo Lima (Etrunko) <eduardo.lima@intel.com>
Mon, 21 Oct 2013 21:36:27 +0000 (19:36 -0200)
Change-Id: Id94424f6f58e2706c2e827f3f2c5e56a3000672b
Signed-off-by: Eduardo Lima (Etrunko) <eduardo.lima@intel.com>
src/wkb-ibus-defs.h
src/wkb-ibus.c
src/wkb-ibus.h

index 37995d5f93b026d4badcd9712f732e65142c5217..3d08d8c21aabd30c32aa48a191e1d2b430e418ce 100644 (file)
@@ -33,6 +33,7 @@ extern "C" {
 #define IBUS_INTERFACE_IBUS     "org.freedesktop.IBus"
 #define IBUS_INTERFACE_PANEL    "org.freedesktop.IBus.Panel"
 #define IBUS_INTERFACE_CONFIG   "org.freedesktop.IBus.Config"
+#define IBUS_INTERFACE_INPUT_CONTEXT "org.freedesktop.IBus.InputContext"
 
 /* from ibustypes.h/ibuserror.c */
 #define IBUS_ERROR_NO_ENGINE    "org.freedesktop.IBus.Error.NoEngine"
index f2fd95a9f0cc4f075f6c201377257f6b204b194c..bd47f2097ef89b8ea19a5a1b76d34417a7f18507 100644 (file)
 
 #include "wkb-ibus.h"
 #include "wkb-ibus-defs.h"
+#include "wkb-ibus-helper.h"
 #include "wkb-log.h"
+#include "wkb-ibus-config-eet.h"
+
+#include "input-method-client-protocol.h"
 
 #define _check_message_errors(_msg) \
    do \
@@ -46,6 +50,22 @@ static const char *IBUS_ADDRESS_ENV = "IBUS_ADDRESS";
 static const char *IBUS_ADDRESS_CMD = "ibus address";
 static const char *IBUS_DAEMON_CMD = "ibus-daemon -s";
 
+/* From ibustypes.h */
+static const unsigned int IBUS_CAP_PREEDIT_TEXT     = 1 << 0;
+static const unsigned int IBUS_CAP_AUXILIARY_TEXT   = 1 << 1;
+static const unsigned int IBUS_CAP_LOOKUP_TABLE     = 1 << 2;
+static const unsigned int IBUS_CAP_FOCUS            = 1 << 3;
+static const unsigned int IBUS_CAP_PROPERTY         = 1 << 4;
+static const unsigned int IBUS_CAP_SURROUNDING_TEXT = 1 << 5;
+
+struct wkb_ibus_input_context
+{
+   Eldbus_Pending *pending;
+   Eldbus_Proxy *ibus_ctx;
+   struct wl_input_method_context *wl_ctx;
+   unsigned int serial;
+};
+
 struct _wkb_ibus_context
 {
    char *address;
@@ -59,6 +79,9 @@ struct _wkb_ibus_context
    Eldbus_Service_Interface *panel;
    Eldbus_Signal_Handler *name_acquired;
    Eldbus_Signal_Handler *name_lost;
+   Eldbus_Proxy *ibus;
+
+   struct wkb_ibus_input_context *input_ctx;
 
    int refcount;
 
@@ -337,6 +360,8 @@ _wkb_ibus_disconnected_cb(void *data, Eldbus_Connection *conn, void *event_data)
 Eina_Bool
 wkb_ibus_connect(void)
 {
+   Eldbus_Object *obj;
+
    if (wkb_ibus->conn)
      {
         INF("Already connected to IBus");
@@ -413,6 +438,9 @@ wkb_ibus_connect(void)
                        ELDBUS_NAME_REQUEST_FLAG_REPLACE_EXISTING | ELDBUS_NAME_REQUEST_FLAG_DO_NOT_QUEUE,
                        _wkb_name_request_cb, wkb_ibus);
 
+   obj = eldbus_object_get(wkb_ibus->conn, IBUS_SERVICE_IBUS, IBUS_PATH_IBUS);
+   wkb_ibus->ibus = eldbus_proxy_get(obj, IBUS_INTERFACE_IBUS);
+
    ecore_event_add(WKB_IBUS_CONNECTED, NULL, NULL, NULL);
 
    return EINA_TRUE;
@@ -545,6 +573,16 @@ wkb_ibus_disconnect(void)
    eldbus_signal_handler_del(wkb_ibus->name_acquired);
    eldbus_signal_handler_del(wkb_ibus->name_lost);
 
+   /* IBus InputContext proxy */
+   wkb_ibus_input_context_destroy();
+
+   /* IBus proxy */
+   if (wkb_ibus->ibus)
+     {
+        eldbus_proxy_unref(wkb_ibus->ibus);
+        wkb_ibus->ibus = NULL;
+     }
+
    if (wkb_ibus->panel)
      {
         eldbus_name_release(wkb_ibus->conn, IBUS_SERVICE_PANEL, _wkb_name_release_cb, wkb_ibus);
@@ -571,3 +609,160 @@ wkb_ibus_is_connected(void)
 {
    return wkb_ibus->conn != NULL;
 }
+
+static void
+_ibus_input_ctx_commit_text(void *data, const Eldbus_Message *msg)
+{
+   Eldbus_Message_Iter *iter = NULL;
+   struct wkb_ibus_text *txt;
+
+   _check_message_errors(msg);
+
+   if (!eldbus_message_arguments_get(msg, "v", &iter))
+     {
+        ERR("Error reading message arguments");
+        return;
+     }
+
+   txt = wkb_ibus_text_from_message_iter(iter);
+   DBG("Commit text: '%s'", txt->text);
+   wl_input_method_context_commit_string(wkb_ibus->input_ctx->wl_ctx, wkb_ibus->input_ctx->serial, txt->text);
+   wkb_ibus_text_free(txt);
+}
+
+static void
+_ibus_input_ctx_forward_key_event(void *data, const Eldbus_Message *msg)
+{
+   _check_message_errors(msg);
+}
+
+static void
+_ibus_input_ctx_update_preedit_text(void *data, const Eldbus_Message *msg)
+{
+   _check_message_errors(msg);
+}
+
+static void
+_ibus_input_ctx_show_preedit_text(void *data, const Eldbus_Message *msg)
+{
+   _check_message_errors(msg);
+}
+
+static void
+_ibus_input_ctx_hide_input_text(void *data, const Eldbus_Message *msg)
+{
+   _check_message_errors(msg);
+}
+
+static void
+_ibus_input_ctx_create(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
+{
+   const char *obj_path;
+   Eldbus_Object *obj;
+   unsigned int capabilities = IBUS_CAP_FOCUS | IBUS_CAP_PREEDIT_TEXT | IBUS_CAP_SURROUNDING_TEXT;
+
+   _check_message_errors(msg);
+
+   if (!eldbus_message_arguments_get(msg, "o", &obj_path))
+     {
+        ERR("Error reading message arguments");
+        goto end;
+     }
+
+   DBG("Got new IBus input context: '%s'", obj_path);
+
+   obj = eldbus_object_get(wkb_ibus->conn, IBUS_SERVICE_IBUS, obj_path);
+   wkb_ibus->input_ctx->ibus_ctx = eldbus_proxy_get(obj, IBUS_INTERFACE_INPUT_CONTEXT);
+
+   eldbus_proxy_signal_handler_add(wkb_ibus->input_ctx->ibus_ctx, "CommitText", _ibus_input_ctx_commit_text, NULL);
+   eldbus_proxy_signal_handler_add(wkb_ibus->input_ctx->ibus_ctx, "ForwardKeyEvent", _ibus_input_ctx_forward_key_event, NULL);
+   eldbus_proxy_signal_handler_add(wkb_ibus->input_ctx->ibus_ctx, "UpdatePreeditText", _ibus_input_ctx_update_preedit_text, NULL);
+   eldbus_proxy_signal_handler_add(wkb_ibus->input_ctx->ibus_ctx, "ShowPreeditText", _ibus_input_ctx_show_preedit_text, NULL);
+   eldbus_proxy_signal_handler_add(wkb_ibus->input_ctx->ibus_ctx, "HidePreeditText", _ibus_input_ctx_hide_input_text, NULL);
+
+   eldbus_proxy_call(wkb_ibus->input_ctx->ibus_ctx, "FocusIn", NULL, NULL, -1, "");
+   eldbus_proxy_call(wkb_ibus->input_ctx->ibus_ctx, "SetCapabilities", NULL, NULL, -1, "u", capabilities);
+
+end:
+   wkb_ibus->input_ctx->pending = NULL;
+}
+
+void
+wkb_ibus_input_context_create(struct wl_input_method_context *wl_ctx)
+{
+   const char *ctx_name = "wayland";
+
+   if (!wkb_ibus)
+       return;
+
+   if (wkb_ibus->input_ctx)
+     {
+        WRN("Input context already exists");
+        wkb_ibus_input_context_destroy();
+     }
+
+   wkb_ibus->input_ctx = calloc(1, sizeof(*(wkb_ibus->input_ctx)));
+   wkb_ibus->input_ctx->wl_ctx = wl_ctx;
+
+   if (!wkb_ibus->conn)
+     {
+        ERR("Not connected");
+        return;
+     }
+
+   if (!wkb_ibus->ibus)
+     {
+        ERR("No IBus proxy");
+        return;
+     }
+
+   wkb_ibus->input_ctx->pending = eldbus_proxy_call(wkb_ibus->ibus, "CreateInputContext", _ibus_input_ctx_create, NULL, -1, "s", ctx_name);
+}
+
+void
+wkb_ibus_input_context_destroy(void)
+{
+   if (!wkb_ibus || !wkb_ibus->input_ctx)
+      return;
+
+   if (wkb_ibus->input_ctx->pending)
+      eldbus_pending_cancel(wkb_ibus->input_ctx->pending);
+
+   if (wkb_ibus->input_ctx->ibus_ctx)
+     {
+        eldbus_proxy_call(wkb_ibus->input_ctx->ibus_ctx, "FocusOut", NULL, NULL, -1, "");
+        eldbus_proxy_unref(wkb_ibus->input_ctx->ibus_ctx);
+     }
+
+end:
+   free(wkb_ibus->input_ctx);
+   wkb_ibus->input_ctx = NULL;
+}
+
+void
+wkb_ibus_input_context_process_key_event(void)
+{
+}
+
+void
+wkb_ibus_input_context_set_surrounding_text(void)
+{
+}
+
+unsigned int
+wkb_ibus_input_context_serial(void)
+{
+   if (!wkb_ibus || !wkb_ibus->input_ctx)
+      return 0;
+
+   return wkb_ibus->input_ctx->serial;
+}
+
+void
+wkb_ibus_input_context_set_serial(unsigned int serial)
+{
+   if (!wkb_ibus || !wkb_ibus->input_ctx)
+      return;
+
+   wkb_ibus->input_ctx->serial = serial;
+}
index 8e3cc70b85b6612252ff8d7268e3ec10170d0694..63c1d3939b89a14b5e416e873ce56e46b2914b77 100644 (file)
@@ -24,6 +24,9 @@
 extern "C" {
 #endif
 
+struct wl_input_method_context;
+
+/* Events */
 extern int WKB_IBUS_CONNECTED;
 extern int WKB_IBUS_DISCONNECTED;
 
@@ -35,10 +38,18 @@ void wkb_ibus_disconnect(void);
 
 Eina_Bool wkb_ibus_is_connected(void);
 
-/* Panel */
+/* IBus Input Context */
+void wkb_ibus_input_context_create(struct wl_input_method_context *wl_ctx);
+void wkb_ibus_input_context_destroy(void);
+void wkb_ibus_input_context_process_key_event(void);
+void wkb_ibus_input_context_set_surrounding_text(void);
+unsigned int wkb_ibus_input_context_serial(void);
+void wkb_ibus_input_context_set_serial(unsigned int serial);
+
+/* IBus Panel */
 Eldbus_Service_Interface * wkb_ibus_panel_register(Eldbus_Connection *conn);
 
-/* Config */
+/* IBus Config */
 Eldbus_Service_Interface * wkb_ibus_config_register(Eldbus_Connection *conn, const char *path);
 void wkb_ibus_config_unregister(void);