summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilippe Rouquier <bonfire-app@wanadoo.fr>2023-01-23 21:04:51 +0900
committerfujiwarat <takao.fujiwara1@gmail.com>2023-01-23 21:04:51 +0900
commitbd24be4582f67e278fc85e843d39b81629bf7d9b (patch)
tree0ec1599c95e853df7863ca0b5a59db592c3f5007
parentd190bc32fe0fe780b66100e5461326973ac7a804 (diff)
downloadibus-bd24be4582f67e278fc85e843d39b81629bf7d9b.tar.gz
Add active-surrounding-text property to IBusEngine
When this property is set to TRUE, ibus daemon will update surrounding text on every focus(in/out) event which makes ibus_engine_get_surrounding_text() calls from an engine code unnecessary. This property must be set at construct time. BUG=https://github.com/ibus/ibus/pull/2447
-rw-r--r--bus/engineproxy.c114
-rw-r--r--bus/ibusimpl.c16
-rw-r--r--bus/ibusimpl.h9
-rw-r--r--src/ibusengine.c47
4 files changed, 167 insertions, 19 deletions
diff --git a/bus/engineproxy.c b/bus/engineproxy.c
index fd1f34fb..b3e16066 100644
--- a/bus/engineproxy.c
+++ b/bus/engineproxy.c
@@ -60,6 +60,7 @@ struct _BusEngineProxy {
/* cached properties */
IBusPropList *prop_list;
gboolean has_focus_id;
+ gboolean has_active_surrounding_text;
};
struct _BusEngineProxyClass {
@@ -130,6 +131,8 @@ static void bus_engine_proxy_initable_iface_init
*initable_iface);
static void bus_engine_proxy_get_has_focus_id
(BusEngineProxy *engine);
+static void bus_engine_proxy_get_active_surrounding_text
+ (BusEngineProxy *engine);
G_DEFINE_TYPE_WITH_CODE (BusEngineProxy, bus_engine_proxy, IBUS_TYPE_PROXY,
G_IMPLEMENT_INTERFACE (
@@ -699,7 +702,6 @@ bus_engine_proxy_new_internal (const gchar *path,
BusEngineProxy *engine;
BusIBusImpl *ibus = BUS_DEFAULT_IBUS;
GHashTable *hash_table = NULL;
- EngineFocusCategory category = ENGINE_FOCUS_CATEGORY_NONE;
g_assert (path);
g_assert (IBUS_IS_ENGINE_DESC (desc));
@@ -721,9 +723,12 @@ bus_engine_proxy_new_internal (const gchar *path,
if (layout != NULL && layout[0] != '\0') {
engine->keymap = ibus_keymap_get (layout);
}
- if (ibus)
- hash_table = bus_ibus_impl_get_engine_focus_id_table (ibus);
+
+ g_return_val_if_fail (ibus, engine);
+
+ hash_table = bus_ibus_impl_get_engine_focus_id_table (ibus);
if (hash_table) {
+ EngineFocusCategory category;
category = (EngineFocusCategory)GPOINTER_TO_INT (
g_hash_table_lookup (hash_table,
ibus_engine_desc_get_name (desc)));
@@ -734,6 +739,21 @@ bus_engine_proxy_new_internal (const gchar *path,
else
bus_engine_proxy_get_has_focus_id (engine);
}
+
+ hash_table = bus_ibus_impl_get_engine_active_surrounding_text_table (ibus);
+ if (hash_table) {
+ EngineSurroundingTextCategory category;
+ category = (EngineSurroundingTextCategory)GPOINTER_TO_INT (
+ g_hash_table_lookup (hash_table,
+ ibus_engine_desc_get_name (desc)));
+ if (category == ENGINE_SURROUNDING_TEXT_CATEGORY_HAS_ACTIVE)
+ engine->has_active_surrounding_text = TRUE;
+ else if (category == ENGINE_SURROUNDING_TEXT_CATEGORY_NOT_ACTIVE)
+ engine->has_active_surrounding_text = FALSE;
+ else
+ bus_engine_proxy_get_active_surrounding_text (engine);
+ }
+
return engine;
}
@@ -1264,6 +1284,26 @@ bus_engine_proxy_set_content_type (BusEngineProxy *engine,
}
static void
+bus_engine_proxy_get_engine_property (BusEngineProxy *engine,
+ const gchar *prop_name,
+ GAsyncReadyCallback callback,
+ GHashTable *hash_table)
+{
+ g_assert (BUS_IS_ENGINE_PROXY (engine));
+ g_assert (hash_table);
+ g_dbus_proxy_call ((GDBusProxy *) engine,
+ "org.freedesktop.DBus.Properties.Get",
+ g_variant_new ("(ss)",
+ IBUS_INTERFACE_ENGINE,
+ prop_name),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ callback,
+ g_hash_table_ref (hash_table));
+}
+
+static void
_get_has_focus_id_cb (GObject *object,
GAsyncResult *res,
gpointer user_data)
@@ -1299,23 +1339,57 @@ static void
bus_engine_proxy_get_has_focus_id (BusEngineProxy *engine)
{
BusIBusImpl *ibus = BUS_DEFAULT_IBUS;
- GHashTable *hash_table;
-
- g_assert (BUS_IS_ENGINE_PROXY (engine));
g_assert (ibus);
+ bus_engine_proxy_get_engine_property (
+ engine,
+ "FocusId",
+ _get_has_focus_id_cb,
+ bus_ibus_impl_get_engine_focus_id_table (ibus));
+}
- hash_table = bus_ibus_impl_get_engine_focus_id_table (ibus);
- g_assert (hash_table);
- g_dbus_proxy_call ((GDBusProxy *) engine,
- "org.freedesktop.DBus.Properties.Get",
- g_variant_new ("(ss)",
- IBUS_INTERFACE_ENGINE,
- "FocusId"),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- _get_has_focus_id_cb,
- g_hash_table_ref (hash_table));
+static void
+_get_active_surrounding_text_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GHashTable *hash_table = (GHashTable*)user_data;
+ BusEngineProxy *engine;
+ GError *error = NULL;
+ GVariant *result;
+
+ g_return_if_fail (BUS_IS_ENGINE_PROXY (object));
+ engine = BUS_ENGINE_PROXY (object);
+ result = g_dbus_proxy_call_finish (G_DBUS_PROXY (object), res, &error);
+
+ if (result != NULL) {
+ GVariant *variant = NULL;
+ gpointer value;
+ g_variant_get (result, "(v)", &variant);
+ engine->has_active_surrounding_text = g_variant_get_boolean (variant);
+ g_variant_unref (variant);
+ g_variant_unref (result);
+ value = GINT_TO_POINTER (
+ engine->has_active_surrounding_text
+ ? ENGINE_SURROUNDING_TEXT_CATEGORY_HAS_ACTIVE
+ : ENGINE_SURROUNDING_TEXT_CATEGORY_NOT_ACTIVE);
+ g_hash_table_replace (
+ hash_table,
+ (gpointer)ibus_engine_desc_get_name (engine->desc),
+ value);
+ }
+ g_hash_table_unref (hash_table);
+}
+
+static void
+bus_engine_proxy_get_active_surrounding_text (BusEngineProxy *engine)
+{
+ BusIBusImpl *ibus = BUS_DEFAULT_IBUS;
+ g_assert (ibus);
+ bus_engine_proxy_get_engine_property (
+ engine,
+ "ActiveSurroundingText",
+ _get_active_surrounding_text_cb,
+ bus_ibus_impl_get_engine_active_surrounding_text_table (ibus));
}
/* a macro to generate a function to call a nullary D-Bus method. */
@@ -1348,6 +1422,8 @@ bus_engine_proxy_focus_in (BusEngineProxy *engine,
if (engine->has_focus)
return;
engine->has_focus = TRUE;
+ if (engine->has_active_surrounding_text)
+ g_signal_emit (engine, engine_signals[REQUIRE_SURROUNDING_TEXT], 0);
if (engine->has_focus_id) {
g_dbus_proxy_call ((GDBusProxy *)engine,
"FocusInId",
@@ -1404,6 +1480,8 @@ bus_engine_proxy_enable (BusEngineProxy *engine)
g_assert (BUS_IS_ENGINE_PROXY (engine));
if (!engine->enabled) {
engine->enabled = TRUE;
+ if (engine->has_active_surrounding_text)
+ g_signal_emit (engine, engine_signals[REQUIRE_SURROUNDING_TEXT], 0);
g_dbus_proxy_call ((GDBusProxy *)engine,
"Enable",
NULL,
diff --git a/bus/ibusimpl.c b/bus/ibusimpl.c
index 8a443545..6df86c3f 100644
--- a/bus/ibusimpl.c
+++ b/bus/ibusimpl.c
@@ -73,6 +73,7 @@ struct _BusIBusImpl {
GHashTable *engine_table;
GHashTable *engine_focus_id_table;
+ GHashTable *engine_active_surrounding_text_table;
BusInputContext *focused_context;
BusPanelProxy *panel;
@@ -599,6 +600,8 @@ bus_ibus_impl_init (BusIBusImpl *ibus)
ibus->global_engine_name = NULL;
ibus->global_previous_engine_name = NULL;
ibus->engine_focus_id_table = g_hash_table_new (g_str_hash, g_str_equal);
+ ibus->engine_active_surrounding_text_table = g_hash_table_new (g_str_hash,
+ g_str_equal);
/* focus the fake_context, if use_global_engine is enabled. */
if (ibus->use_global_engine)
@@ -681,6 +684,11 @@ bus_ibus_impl_destroy (BusIBusImpl *ibus)
bus_ibus_impl_registry_destroy (ibus);
+ if (ibus->engine_active_surrounding_text_table != NULL) {
+ g_hash_table_destroy (ibus->engine_active_surrounding_text_table);
+ ibus->engine_active_surrounding_text_table = NULL;
+ }
+
IBUS_OBJECT_CLASS (bus_ibus_impl_parent_class)->destroy (IBUS_OBJECT (ibus));
}
@@ -2397,3 +2405,11 @@ bus_ibus_impl_get_engine_focus_id_table (BusIBusImpl *ibus)
return ibus->engine_focus_id_table;
}
+GHashTable *
+bus_ibus_impl_get_engine_active_surrounding_text_table (BusIBusImpl *ibus)
+{
+
+ g_assert (BUS_IS_IBUS_IMPL (ibus));
+
+ return ibus->engine_active_surrounding_text_table;
+}
diff --git a/bus/ibusimpl.h b/bus/ibusimpl.h
index cbe6856d..93a854de 100644
--- a/bus/ibusimpl.h
+++ b/bus/ibusimpl.h
@@ -66,6 +66,13 @@ typedef enum
ENGINE_FOCUS_CATEGORY_HAS_ID
} EngineFocusCategory;
+typedef enum
+{
+ ENGINE_SURROUNDING_TEXT_CATEGORY_NONE = 0,
+ ENGINE_SURROUNDING_TEXT_CATEGORY_NOT_ACTIVE,
+ ENGINE_SURROUNDING_TEXT_CATEGORY_HAS_ACTIVE
+} EngineSurroundingTextCategory;
+
GType bus_ibus_impl_get_type (void);
/**
@@ -91,5 +98,7 @@ BusInputContext *bus_ibus_impl_get_focused_input_context
(BusIBusImpl *ibus);
GHashTable *bus_ibus_impl_get_engine_focus_id_table
(BusIBusImpl *ibus);
+GHashTable *bus_ibus_impl_get_engine_active_surrounding_text_table
+ (BusIBusImpl *ibus);
G_END_DECLS
#endif
diff --git a/src/ibusengine.c b/src/ibusengine.c
index 7c797103..cc12ac5a 100644
--- a/src/ibusengine.c
+++ b/src/ibusengine.c
@@ -64,6 +64,7 @@ enum {
PROP_0,
PROP_ENGINE_NAME,
PROP_HAS_FOCUS_ID,
+ PROP_ACTIVE_SURROUNDING_TEXT,
};
@@ -86,6 +87,7 @@ struct _IBusEnginePrivate {
gboolean enable_extension;
gchar *current_extension_name;
gboolean has_focus_id;
+ gboolean has_active_surrounding_text;
};
@@ -303,6 +305,7 @@ static const gchar introspection_xml[] =
/* FIXME properties */
" <property name='ContentType' type='(uu)' access='write' />"
" <property name='FocusId' type='(b)' access='read' />"
+ " <property name='ActiveSurroundingText' type='(b)' access='read' />"
" </interface>"
"</node>";
@@ -391,6 +394,23 @@ ibus_engine_class_init (IBusEngineClass *class)
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
+ /**
+ * IBusEngine:active-surrounding-text:
+ *
+ * When this property is set to %TRUE, "RequireSurroundingText" D-Bus
+ * signal will be called by ibus-daemon on every focus-in/out event, with
+ * no need for the engine to call ibus_engine_get_surrounding_text().
+ * This property can only be set at construct time.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_ACTIVE_SURROUNDING_TEXT,
+ g_param_spec_boolean ("active-surrounding-text",
+ "enable surrounding text update by focus event",
+ "Enable surrounding text update by focus event",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+
/* install signals */
/**
* IBusEngine::process-key-event:
@@ -988,6 +1008,9 @@ ibus_engine_set_property (IBusEngine *engine,
case PROP_HAS_FOCUS_ID:
engine->priv->has_focus_id = g_value_get_boolean (value);
break;
+ case PROP_ACTIVE_SURROUNDING_TEXT:
+ engine->priv->has_active_surrounding_text = g_value_get_boolean (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (engine, prop_id, pspec);
}
@@ -1006,6 +1029,9 @@ ibus_engine_get_property (IBusEngine *engine,
case PROP_HAS_FOCUS_ID:
g_value_set_boolean (value, engine->priv->has_focus_id);
break;
+ case PROP_ACTIVE_SURROUNDING_TEXT:
+ g_value_set_boolean (value, engine->priv->has_active_surrounding_text);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (engine, prop_id, pspec);
}
@@ -1446,6 +1472,24 @@ ibus_engine_service_method_call (IBusService *service,
}
/**
+ * _ibus_engine_get_active_surrounding_text:
+ *
+ * Implement the "ActiveSurroundingText" method call of the
+ * org.freedesktop.IBus interface.
+ */
+static GVariant *
+_ibus_engine_get_active_surrounding_text (IBusEngine *engine,
+ GDBusConnection *connection,
+ GError **error)
+{
+ if (error) {
+ *error = NULL;
+ }
+
+ return g_variant_new_boolean (engine->priv->has_active_surrounding_text);
+}
+
+/**
* _ibus_engine_has_focus_id:
*
* Implement the "FocusId" method call of the org.freedesktop.IBus interface.
@@ -1478,7 +1522,8 @@ ibus_engine_service_get_property (IBusService *service,
GDBusConnection *,
GError **);
} methods [] = {
- { "FocusId", _ibus_engine_has_focus_id },
+ { "FocusId", _ibus_engine_has_focus_id },
+ { "ActiveSurroundingText", _ibus_engine_get_active_surrounding_text },
};
if (g_strcmp0 (interface_name, IBUS_INTERFACE_ENGINE) != 0) {