[gnome-settings-daemon/wip/is-switch-fixes: 3/5] keyboard: Introduce a SetInputSource DBus method
- From: Rui Matos <rtcm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-settings-daemon/wip/is-switch-fixes: 3/5] keyboard: Introduce a SetInputSource DBus method
- Date: Fri, 5 Apr 2013 16:17:56 +0000 (UTC)
commit 7f0a89d1f2aa4be7aece8c2005902c93f2d4ec68
Author: Rui Matos <tiagomatos gmail com>
Date: Mon Mar 25 04:03:59 2013 +0100
keyboard: Introduce a SetInputSource DBus method
The only way for external components to activate an input source is by
setting the gsettings key. That's not optimal since external
components then have no way of knowing when exactly the switch is
completed.
This commit introduces a DBus method to set an input source and we
make sure to only return the method after all the changes have been
made, i.e. the XKB keyboard description has been changed and the IBus
engine (if any) has been activated.
E.g. gnome-shell can use this method and freeze keyboard events in the
X server until it hears back from g-s-d to ensure that events won't be
misinterpreted after an input source switch.
https://bugzilla.gnome.org/show_bug.cgi?id=696996
plugins/keyboard/gsd-keyboard-manager.c | 92 ++++++++++++++++++++++++++++++-
1 files changed, 91 insertions(+), 1 deletions(-)
---
diff --git a/plugins/keyboard/gsd-keyboard-manager.c b/plugins/keyboard/gsd-keyboard-manager.c
index 5f97a61..48a8706 100644
--- a/plugins/keyboard/gsd-keyboard-manager.c
+++ b/plugins/keyboard/gsd-keyboard-manager.c
@@ -122,6 +122,9 @@ struct GsdKeyboardManagerPrivate
GDBusNodeInfo *dbus_introspection;
guint dbus_own_name_id;
guint dbus_register_object_id;
+
+ GDBusMethodInvocation *invocation;
+ guint pending_ops;
};
static void gsd_keyboard_manager_class_init (GsdKeyboardManagerClass *klass);
@@ -133,12 +136,17 @@ static gboolean apply_input_sources_settings (GSettings *setti
GsdKeyboardManager *manager);
static void set_gtk_im_module (GsdKeyboardManager *manager,
GVariant *sources);
+static void maybe_return_from_set_input_source (GsdKeyboardManager *manager);
+static void increment_set_input_source_ops (GsdKeyboardManager *manager);
G_DEFINE_TYPE (GsdKeyboardManager, gsd_keyboard_manager, G_TYPE_OBJECT)
static const gchar introspection_xml[] =
"<node>"
" <interface name='org.gnome.SettingsDaemon.Keyboard'>"
+ " <method name='SetInputSource'>"
+ " <arg type='u' name='idx' direction='in'/>"
+ " </method>"
" </interface>"
"</node>";
@@ -288,7 +296,10 @@ set_ibus_engine_finish (GObject *object,
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
g_warning ("Couldn't set IBus engine: %s", error->message);
g_error_free (error);
+ return;
}
+
+ maybe_return_from_set_input_source (manager);
}
static void
@@ -304,6 +315,8 @@ set_ibus_engine (GsdKeyboardManager *manager,
g_clear_object (&priv->ibus_cancellable);
priv->ibus_cancellable = g_cancellable_new ();
+ increment_set_input_source_ops (manager);
+
ibus_bus_set_global_engine_async (priv->ibus,
engine_id,
-1,
@@ -1042,6 +1055,7 @@ apply_input_sources_settings (GSettings *settings,
exit:
apply_xkb_settings (manager, layout, variant, options);
+ maybe_return_from_set_input_source (manager);
g_variant_unref (sources);
g_free (layout);
g_free (variant);
@@ -1531,6 +1545,81 @@ out:
}
static void
+set_input_source_return (GDBusMethodInvocation *invocation)
+{
+ g_dbus_method_invocation_return_value (invocation, NULL);
+}
+
+static void
+maybe_return_from_set_input_source (GsdKeyboardManager *manager)
+{
+ GsdKeyboardManagerPrivate *priv = manager->priv;
+
+ if (!priv->invocation)
+ return;
+
+ if (priv->pending_ops > 0) {
+ priv->pending_ops -= 1;
+ return;
+ }
+
+ g_clear_pointer (&priv->invocation, set_input_source_return);
+}
+
+static void
+increment_set_input_source_ops (GsdKeyboardManager *manager)
+{
+ GsdKeyboardManagerPrivate *priv = manager->priv;
+
+ if (!priv->invocation)
+ return;
+
+ priv->pending_ops += 1;
+}
+
+static void
+set_input_source (GsdKeyboardManager *manager)
+{
+ GsdKeyboardManagerPrivate *priv = manager->priv;
+ guint idx;
+
+ g_variant_get (g_dbus_method_invocation_get_parameters (priv->invocation), "(u)", &idx);
+
+ if (idx == g_settings_get_uint (priv->input_sources_settings, KEY_CURRENT_INPUT_SOURCE)) {
+ maybe_return_from_set_input_source (manager);
+ return;
+ }
+
+ g_settings_set_uint (priv->input_sources_settings, KEY_CURRENT_INPUT_SOURCE, idx);
+}
+
+static void
+handle_dbus_method_call (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ GsdKeyboardManager *manager)
+{
+ GsdKeyboardManagerPrivate *priv = manager->priv;
+
+ if (g_str_equal (method_name, "SetInputSource")) {
+ if (priv->invocation) {
+ /* This can only happen if there's an
+ * ibus_bus_set_global_engine_async() call
+ * going on. */
+ g_cancellable_cancel (priv->ibus_cancellable);
+ g_clear_pointer (&priv->invocation, set_input_source_return);
+ priv->pending_ops = 0;
+ }
+ priv->invocation = invocation;
+ set_input_source (manager);
+ }
+}
+
+static void
on_bus_name_lost (GDBusConnection *connection,
const gchar *name,
gpointer data)
@@ -1547,7 +1636,7 @@ got_session_bus (GObject *source,
GDBusConnection *connection;
GError *error = NULL;
GDBusInterfaceVTable vtable = {
- NULL,
+ (GDBusInterfaceMethodCallFunc) handle_dbus_method_call,
NULL,
NULL,
};
@@ -1711,6 +1800,7 @@ gsd_keyboard_manager_stop (GsdKeyboardManager *manager)
set_input_sources_switcher (manager, FALSE);
+ g_clear_pointer (&p->invocation, set_input_source_return);
g_clear_pointer (&p->dbus_introspection, g_dbus_node_info_unref);
g_clear_object (&p->dbus_connection);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]