pwu / rpms / ibus

Forked from rpms/ibus 5 years ago
Clone
Blob Blame History Raw
From c72e8177099fb9079e2f295c0bb2118b998cb0e8 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@unixuser.org>
Date: Wed, 13 Apr 2011 16:26:54 +0900
Subject: [PATCH] Backport caps feature from the Fedora internal patch.

---
 client/gtk2/ibusimcontext.c |   34 ++++++++++-
 src/ibusenginedesc.c        |  132 +++++++++++++++++++++++++++++++++++++++++++
 src/ibusenginedesc.h        |   11 ++++
 3 files changed, 173 insertions(+), 4 deletions(-)

diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c
index dc3640e..0ac1b70 100644
--- a/client/gtk2/ibusimcontext.c
+++ b/client/gtk2/ibusimcontext.c
@@ -61,6 +61,7 @@ struct _IBusIMContext {
     gboolean         has_focus;
 
     guint32          time;
+    guint            supported_caps;
     gint             caps;
 
     /* cancellable */
@@ -150,6 +151,7 @@ static gboolean _slave_delete_surrounding_cb
 static void     _request_surrounding_text   (IBusIMContext      *context,
                                              gboolean            force);
 static void     _create_fake_input_context  (void);
+static void     _negotiate_capabilities     (IBusIMContext      *context);
 
 
 
@@ -580,10 +582,11 @@ ibus_im_context_init (GObject *obj)
     ibusimcontext->has_focus = FALSE;
     ibusimcontext->time = GDK_CURRENT_TIME;
 #ifdef ENABLE_SURROUNDING
-    ibusimcontext->caps = IBUS_CAP_PREEDIT_TEXT | IBUS_CAP_FOCUS | IBUS_CAP_SURROUNDING_TEXT;
+    ibusimcontext->supported_caps = IBUS_CAP_PREEDIT_TEXT | IBUS_CAP_FOCUS | IBUS_CAP_SURROUNDING_TEXT;
 #else
-    ibusimcontext->caps = IBUS_CAP_PREEDIT_TEXT | IBUS_CAP_FOCUS;
+    ibusimcontext->supported_caps = IBUS_CAP_PREEDIT_TEXT | IBUS_CAP_FOCUS;
 #endif
+    ibusimcontext->caps = ibusimcontext->supported_caps;
 
 
     // Create slave im context
@@ -930,6 +933,27 @@ ibus_im_context_set_cursor_location (GtkIMContext *context, GdkRectangle *area)
 }
 
 static void
+_negotiate_capabilities (IBusIMContext *context)
+{
+    if (context->enable) {
+        IBusEngineDesc *engine =
+            ibus_input_context_get_engine (context->ibuscontext);
+
+        if (engine) {
+            context->caps = context->supported_caps &
+                ibus_engine_desc_get_requires (engine);
+            ibus_input_context_set_capabilities (context->ibuscontext,
+                                                 context->caps);
+        IDEBUG ("engine %s: supported caps = %u, engine wants = %u, caps = %u",
+                ibus_engine_desc_get_name (engine),
+                context->supported_caps,
+                ibus_engine_desc_get_requires (engine),
+                context->caps);
+        }
+    }
+}
+
+static void
 ibus_im_context_set_use_preedit (GtkIMContext *context, gboolean use_preedit)
 {
     IDEBUG ("%s", __FUNCTION__);
@@ -938,11 +962,12 @@ ibus_im_context_set_use_preedit (GtkIMContext *context, gboolean use_preedit)
 
     if(ibusimcontext->ibuscontext) {
         if (use_preedit) {
-            ibusimcontext->caps |= IBUS_CAP_PREEDIT_TEXT;
+            ibusimcontext->supported_caps |= IBUS_CAP_PREEDIT_TEXT;
         }
         else {
-            ibusimcontext->caps &= ~IBUS_CAP_PREEDIT_TEXT;
+            ibusimcontext->supported_caps &= ~IBUS_CAP_PREEDIT_TEXT;
         }
+        _negotiate_capabilities (ibusimcontext);
     }
     gtk_im_context_set_use_preedit (ibusimcontext->slave, use_preedit);
 }
@@ -1320,6 +1345,7 @@ _ibus_context_enabled_cb (IBusInputContext *ibuscontext,
     IDEBUG ("%s", __FUNCTION__);
 
     ibusimcontext->enable = TRUE;
+    _negotiate_capabilities (ibusimcontext);
 
     /* retrieve the initial surrounding-text (regardless of whether
      * the current IBus engine needs surrounding-text) */
diff --git a/src/ibusenginedesc.c b/src/ibusenginedesc.c
index ca5ef60..956ce73 100644
--- a/src/ibusenginedesc.c
+++ b/src/ibusenginedesc.c
@@ -22,6 +22,7 @@
 #include <stdlib.h>
 #include "ibusenginedesc.h"
 #include "ibusxml.h"
+#include "ibusenumtypes.h"
 
 enum {
     LAST_SIGNAL,
@@ -39,6 +40,7 @@ enum {
     PROP_LAYOUT,
     PROP_RANK,
     PROP_HOTKEYS,
+    PROP_REQUIRES,
 };
 
 
@@ -54,6 +56,7 @@ struct _IBusEngineDescPrivate {
     gchar      *layout;
     guint       rank;
     gchar      *hotkeys;
+    guint       requires;
 };
 
 #define IBUS_ENGINE_DESC_GET_PRIVATE(o)  \
@@ -79,9 +82,20 @@ static gboolean     ibus_engine_desc_copy           (IBusEngineDesc         *des
                                                      const IBusEngineDesc   *src);
 static gboolean     ibus_engine_desc_parse_xml_node (IBusEngineDesc         *desc,
                                                      XMLNode                *node);
+static void         ibus_engine_desc_output_capabilities
+                                                    (guint                   caps,
+                                                     GString                *output,
+                                                     gint                    indent);
+static guint        ibus_engine_desc_parse_capabilities
+                                                    (XMLNode                *node);
 
 G_DEFINE_TYPE (IBusEngineDesc, ibus_engine_desc, IBUS_TYPE_SERIALIZABLE)
 
+#define DEFAULT_REQUIRES (IBUS_CAP_PREEDIT_TEXT |   \
+                          IBUS_CAP_AUXILIARY_TEXT | \
+                          IBUS_CAP_LOOKUP_TABLE |   \
+                          IBUS_CAP_FOCUS |          \
+                          IBUS_CAP_PROPERTY)
 
 static void
 ibus_engine_desc_class_init (IBusEngineDescClass *class)
@@ -232,6 +246,21 @@ ibus_engine_desc_class_init (IBusEngineDescClass *class)
                         "The hotkeys of engine description",
                         "",
                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+    /**
+     * IBusEngineDesc:requires:
+     *
+     * The required capabilities of engine description
+     */
+    g_object_class_install_property (gobject_class,
+                    PROP_REQUIRES,
+                    g_param_spec_uint ("requires",
+                        "description requires",
+                        "The required capabilities of engine description",
+                        0,
+                        G_MAXUINT,
+                        DEFAULT_REQUIRES,
+                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 }
 
 static void
@@ -249,6 +278,7 @@ ibus_engine_desc_init (IBusEngineDesc *desc)
     desc->priv->layout = NULL;
     desc->priv->rank = 0;
     desc->priv->hotkeys = NULL;
+    desc->priv->requires = DEFAULT_REQUIRES;
 }
 
 static void
@@ -313,6 +343,9 @@ ibus_engine_desc_set_property (IBusEngineDesc *desc,
         g_assert (desc->priv->hotkeys == NULL);
         desc->priv->hotkeys = g_value_dup_string (value);
         break;
+    case PROP_REQUIRES:
+        desc->priv->requires = g_value_get_uint (value);
+        break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (desc, prop_id, pspec);
     }
@@ -355,6 +388,9 @@ ibus_engine_desc_get_property (IBusEngineDesc *desc,
     case PROP_HOTKEYS:
         g_value_set_string (value, ibus_engine_desc_get_hotkeys (desc));
         break;
+    case PROP_REQUIRES:
+        g_value_set_uint (value, ibus_engine_desc_get_requires (desc));
+        break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (desc, prop_id, pspec);
     }
@@ -382,9 +418,28 @@ ibus_engine_desc_serialize (IBusEngineDesc  *desc,
     g_variant_builder_add (builder, "u", desc->priv->rank);
     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->hotkeys));
 #undef NOTNULL
+
+    /* append extra properties */
+    GVariantBuilder array;
+    g_variant_builder_init (&array, G_VARIANT_TYPE ("a{sv}"));
+    g_variant_builder_add (&array, "{sv}", "requires", g_variant_new_uint32 (desc->priv->requires));
+    g_variant_builder_add (builder, "v", g_variant_builder_end (&array));
+
     return TRUE;
 }
 
+static gboolean
+ibus_engine_desc_deserialize_property (IBusEngineDesc *desc,
+                                       const gchar    *name,
+                                       GVariant       *variant)
+{
+    if (g_strcmp0 (name, "requires") == 0) {
+        g_variant_get (variant, "u", &desc->priv->requires);
+        return TRUE;
+    }
+    return FALSE;
+}
+
 static gint
 ibus_engine_desc_deserialize (IBusEngineDesc *desc,
                               GVariant       *variant)
@@ -405,6 +460,23 @@ ibus_engine_desc_deserialize (IBusEngineDesc *desc,
     g_variant_get_child (variant, retval++, "u", &desc->priv->rank);
     g_variant_get_child (variant, retval++, "s", &desc->priv->hotkeys);
 
+    /* extract extra properties */
+    GVariantIter iter;
+    GVariant *child, *array;
+
+    g_variant_get_child (variant, retval++, "v", &array);
+    g_variant_iter_init (&iter, array);
+    while ((child = g_variant_iter_next_value (&iter))) {
+        gchar *name;
+        GVariant *value;
+        g_variant_get (child, "{sv}", &name, &value);
+        if (ibus_engine_desc_deserialize_property (desc, name, value))
+            retval++;
+        g_free (name);
+        g_variant_unref (value);
+        g_variant_unref (child);
+    }
+
     return retval;
 }
 
@@ -428,6 +500,7 @@ ibus_engine_desc_copy (IBusEngineDesc       *dest,
     dest->priv->layout           = g_strdup (src->priv->layout);
     dest->priv->rank             = src->priv->rank;
     dest->priv->hotkeys          = g_strdup (src->priv->hotkeys);
+    dest->priv->requires         = src->priv->requires;
     return TRUE;
 }
 
@@ -439,6 +512,52 @@ ibus_engine_desc_copy (IBusEngineDesc       *dest,
         }                                       \
     }
 
+static void
+ibus_engine_desc_output_capabilities (guint    caps,
+                                      GString *output,
+                                      gint     indent)
+{
+    GFlagsClass *flags_class;
+    gint i;
+
+    flags_class = g_type_class_ref (IBUS_TYPE_CAPABILITE);
+    g_return_if_fail (G_TYPE_IS_FLAGS (IBUS_TYPE_CAPABILITE));
+    for (i = 0; i < flags_class->n_values; i++) {
+        GFlagsValue *flags_value = &flags_class->values[i];
+        if (caps & flags_value->value) {
+            g_string_append_indent (output, indent + 1);
+            g_string_append_printf (output, "<capability>%s</capability>\n",
+                                    flags_value->value_nick);
+        }
+    }
+    g_type_class_unref (flags_class);
+}
+
+static guint
+ibus_engine_desc_parse_capabilities (XMLNode *node)
+{
+    GFlagsClass *flags_class;
+    guint caps = 0;
+    GList *p;
+
+    flags_class = g_type_class_ref (IBUS_TYPE_CAPABILITE);
+    for (p = node->sub_nodes; p != NULL; p = p->next) {
+        XMLNode *sub_node = (XMLNode *) p->data;
+
+        if (g_strcmp0 (sub_node->name, "capability") == 0) {
+            gint i;
+            for (i = 0; i < flags_class->n_values; i++) {
+                GFlagsValue *flags_value = &flags_class->values[i];
+                if (g_strcmp0 (flags_value->value_nick, sub_node->text) == 0)
+                    caps |= flags_value->value;
+            }
+        }
+    }
+    g_type_class_unref (flags_class);
+
+    return caps;
+}
+
 void
 ibus_engine_desc_output (IBusEngineDesc *desc,
                          GString        *output,
@@ -467,6 +586,13 @@ ibus_engine_desc_output (IBusEngineDesc *desc,
     OUTPUT_ENTRY_1(hotkeys);
     g_string_append_indent (output, indent + 1);
     g_string_append_printf (output, "<rank>%u</rank>\n", desc->priv->rank);
+
+    g_string_append_indent (output, indent + 1);
+    g_string_append (output, "<requires>\n");
+    ibus_engine_desc_output_capabilities (desc->priv->requires, output,
+                                          indent + 2);
+    g_string_append_indent (output, indent + 1);
+    g_string_append (output, "</requires>\n");
 #undef OUTPUT_ENTRY
 #undef OUTPUT_ENTRY_1
     g_string_append_indent (output, indent);
@@ -504,6 +630,11 @@ ibus_engine_desc_parse_xml_node (IBusEngineDesc *desc,
             desc->priv->rank = atoi (sub_node->text);
             continue;
         }
+        if (g_strcmp0 (sub_node->name , "requires") == 0) {
+            desc->priv->requires =
+                ibus_engine_desc_parse_capabilities (sub_node);
+            continue;
+        }
         g_warning ("<engines> element contains invalidate element <%s>", sub_node->name);
     }
     return TRUE;
@@ -526,6 +657,7 @@ IBUS_ENGINE_DESC_GET_PROPERTY (icon, const gchar *)
 IBUS_ENGINE_DESC_GET_PROPERTY (layout, const gchar *)
 IBUS_ENGINE_DESC_GET_PROPERTY (rank, guint)
 IBUS_ENGINE_DESC_GET_PROPERTY (hotkeys, const gchar *)
+IBUS_ENGINE_DESC_GET_PROPERTY (requires, guint)
 #undef IBUS_ENGINE_DESC_GET_PROPERTY
 
 IBusEngineDesc *
diff --git a/src/ibusenginedesc.h b/src/ibusenginedesc.h
index 9718b15..209d460 100644
--- a/src/ibusenginedesc.h
+++ b/src/ibusenginedesc.h
@@ -90,6 +90,8 @@ typedef struct _IBusEngineDescClass IBusEngineDescClass;
  * the front.
  * hotkeys: One or more hotkeys for switching to this engine, separated by
  *  semi-colon.
+ * requires: Capabilities this engine will utilize.  The value is the
+ * union of the IBusCapability flags.
  */
 struct _IBusEngineDesc {
     IBusSerializable parent;
@@ -249,6 +251,15 @@ guint            ibus_engine_desc_get_rank      (IBusEngineDesc *info);
 const gchar     *ibus_engine_desc_get_hotkeys   (IBusEngineDesc *info);
 
 /**
+ * ibus_engine_desc_get_requires:
+ * @info: An IBusEngineDesc
+ * @returns: request capabilites property in IBusEngineDesc
+ *
+ * Return the capabilites property in IBusEngineDesc.
+ */
+guint            ibus_engine_desc_get_requires  (IBusEngineDesc *info);
+
+/**
  * ibus_engine_desc_output:
  * @info: An IBusEngineDesc
  * @output: XML-formatted Input method engine description.
-- 
1.7.4.2