From c72e8177099fb9079e2f295c0bb2118b998cb0e8 Mon Sep 17 00:00:00 2001 From: Daiki Ueno 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 #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, "%s\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, "%u\n", desc->priv->rank); + + g_string_append_indent (output, indent + 1); + g_string_append (output, "\n"); + ibus_engine_desc_output_capabilities (desc->priv->requires, output, + indent + 2); + g_string_append_indent (output, indent + 1); + g_string_append (output, "\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 (" 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