diff --git a/README.md b/README.md index 53687a01..d38b1898 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,13 @@ Running $ rootston $ cd ../build/ $ src/squeekboard -$ busctl call --user org.fedorahosted.Eekboard /org/fedorahosted/Eekboard org.fedorahosted.Eekboard ShowKeyboard -$ busctl call --user org.fedorahosted.Eekboard /org/fedorahosted/Eekboard org.fedorahosted.Eekboard HideKeyboard +``` + +### Testing + +``` +$ busctl call --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 SetVisible b true +$ busctl call --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 SetVisible b false +$ gsettings set org.gnome.desktop.input-sources sources "[('xkb', 'us'), ('xkb', 'ru')]" +$ gsettings set org.gnome.desktop.input-sources current 1 ``` diff --git a/data/meson.build b/data/meson.build index 8118b234..04e3aa3a 100644 --- a/data/meson.build +++ b/data/meson.build @@ -14,6 +14,10 @@ install_data( install_dir: pkgdatadir + '/keyboards/geometry/', ) +install_data('dbus/sm.puri.OSK0.xml', + install_dir: dbusdir +) + symbols = [ 'ar.xml', 'as-inscript.xml', diff --git a/eekboard/eekboard-service.c b/eekboard/eekboard-service.c index 2cf00bd4..9020f502 100644 --- a/eekboard/eekboard-service.c +++ b/eekboard/eekboard-service.c @@ -30,6 +30,8 @@ #include "eekboard/eekboard-service.h" +#include "sm.puri.OSK0.h" + #include enum { @@ -51,6 +53,7 @@ static guint signals[LAST_SIGNAL] = { 0, }; struct _EekboardServicePrivate { GDBusConnection *connection; + SmPuriOSK0 *dbus_interface; GDBusNodeInfo *introspection_data; guint registration_id; char *object_path; @@ -62,40 +65,6 @@ struct _EekboardServicePrivate { G_DEFINE_TYPE (EekboardService, eekboard_service, G_TYPE_OBJECT); -static const gchar introspection_xml[] = - "" - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - /* signals */ - " " - ""; - -static void handle_method_call (GDBusConnection *connection, - const gchar *sender, - const gchar *object_path, - const gchar *interface_name, - const gchar *method_name, - GVariant *parameters, - GDBusMethodInvocation *invocation, - gpointer user_data); - -static const GDBusInterfaceVTable interface_vtable = -{ - handle_method_call, - NULL, - NULL -}; - static void eekboard_service_set_property (GObject *object, guint prop_id, @@ -190,26 +159,46 @@ eekboard_service_finalize (GObject *object) G_OBJECT_CLASS (eekboard_service_parent_class)->finalize (object); } +static gboolean +handle_set_visible(SmPuriOSK0 *object, GDBusMethodInvocation *invocation, + gboolean arg_visible, gpointer user_data) { + EekboardService *service = user_data; + if (arg_visible) { + if (service->priv->context_stack) { + eekboard_context_service_show_keyboard (service->priv->context_stack->data); + } else { + service->priv->visible = TRUE; + } + } else { + if (service->priv->context_stack) { + eekboard_context_service_hide_keyboard (service->priv->context_stack->data); + } else { + service->priv->visible = FALSE; + } + } + sm_puri_osk0_complete_set_visible(object, invocation); + return TRUE; +} + static void eekboard_service_constructed (GObject *object) { EekboardService *service = EEKBOARD_SERVICE(object); + + service->priv->dbus_interface = sm_puri_osk0_skeleton_new(); + sm_puri_osk0_set_visible(service->priv->dbus_interface, FALSE); // TODO: use actual value + g_signal_connect(service->priv->dbus_interface, "handle-set-visible", + G_CALLBACK(handle_set_visible), service); + if (service->priv->connection && service->priv->object_path) { GError *error = NULL; - service->priv->registration_id = g_dbus_connection_register_object - (service->priv->connection, - service->priv->object_path, - service->priv->introspection_data->interfaces[0], - &interface_vtable, - object, - NULL, - &error); - - if (service->priv->registration_id == 0) { - g_warning ("failed to register context object: %s", - error->message); - g_error_free (error); + if (!g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(service->priv->dbus_interface), + service->priv->connection, + service->priv->object_path, + &error)) { + g_warning("Error registering dbus object: %s\n", error->message); + g_clear_error(&error); } } @@ -299,19 +288,8 @@ eekboard_service_class_init (EekboardServiceClass *klass) static void eekboard_service_init (EekboardService *self) { - GError *error; - self->priv = EEKBOARD_SERVICE_GET_PRIVATE(self); - error = NULL; - self->priv->introspection_data = - g_dbus_node_info_new_for_xml (introspection_xml, &error); - if (self->priv->introspection_data == NULL) { - g_warning ("failed to parse D-Bus XML: %s", error->message); - g_error_free (error); - g_assert_not_reached (); - } - self->priv->context_hash = g_hash_table_new_full (g_str_hash, g_str_equal, @@ -335,170 +313,6 @@ remove_context_from_stack (EekboardService *service, eekboard_context_service_enable (service->priv->context_stack->data); } -static void -service_name_vanished_callback (GDBusConnection *connection, - const gchar *name, - gpointer user_data) -{ - EekboardService *service = user_data; - GSList *head; - GHashTableIter iter; - gpointer k, v; - - g_hash_table_iter_init (&iter, service->priv->context_hash); - while (g_hash_table_iter_next (&iter, &k, &v)) { - const gchar *owner = g_object_get_data (G_OBJECT(v), "owner"); - if (g_strcmp0 (owner, name) == 0) - g_hash_table_iter_remove (&iter); - } - - for (head = service->priv->context_stack; head; ) { - const gchar *owner = g_object_get_data (G_OBJECT(head->data), "owner"); - GSList *next = g_slist_next (head); - - if (g_strcmp0 (owner, name) == 0) { - service->priv->context_stack = - g_slist_remove_link (service->priv->context_stack, head); - g_object_unref (head->data); - g_slist_free1 (head); - } - - head = next; - } - - if (service->priv->context_stack) - eekboard_context_service_enable (service->priv->context_stack->data); -} - -static void -context_destroyed_cb (EekboardContextService *context, EekboardService *service) -{ - gchar *object_path = NULL; - - remove_context_from_stack (service, context); - - g_object_get (G_OBJECT(context), "object-path", &object_path, NULL); - g_hash_table_remove (service->priv->context_hash, object_path); - g_free (object_path); -} - -static void -on_notify_visible (GObject *object, GParamSpec *spec, gpointer user_data) -{ - EekboardService *service = user_data; - - g_object_get (object, "visible", &service->priv->visible, NULL); -} - -static void -handle_method_call (GDBusConnection *connection, - const gchar *sender, - const gchar *object_path, - const gchar *interface_name, - const gchar *method_name, - GVariant *parameters, - GDBusMethodInvocation *invocation, - gpointer user_data) -{ - EekboardService *service = user_data; - EekboardServiceClass *klass = EEKBOARD_SERVICE_GET_CLASS(service); - - if (g_strcmp0 (method_name, "CreateContext") == 0) { - printf("Ignoring CreateContext call\n"); - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(s)", - "object_path")); - return; - } - - if (g_strcmp0 (method_name, "PushContext") == 0) { - const gchar *object_path; - EekboardContextService *context; - - g_variant_get (parameters, "(&s)", &object_path); - context = g_hash_table_lookup (service->priv->context_hash, object_path); - if (!context) { - g_dbus_method_invocation_return_error (invocation, - G_IO_ERROR, - G_IO_ERROR_FAILED_HANDLED, - "context not found"); - return; - } - if (service->priv->context_stack) - eekboard_context_service_disable (service->priv->context_stack->data); - service->priv->context_stack = g_slist_prepend (service->priv->context_stack, - g_object_ref (context)); - eekboard_context_service_enable (context); - g_signal_connect (context, "notify::visible", - G_CALLBACK(on_notify_visible), service); - if (service->priv->visible) - eekboard_context_service_show_keyboard (context); - - g_dbus_method_invocation_return_value (invocation, NULL); - return; - } - - if (g_strcmp0 (method_name, "PopContext") == 0) { - if (service->priv->context_stack) { - EekboardContextService *context = service->priv->context_stack->data; - gchar *object_path; - const gchar *owner; - - g_object_get (G_OBJECT(context), "object-path", &object_path, NULL); - owner = g_object_get_data (G_OBJECT(context), "owner"); - if (g_strcmp0 (owner, sender) != 0) { - g_dbus_method_invocation_return_error - (invocation, - G_IO_ERROR, - G_IO_ERROR_FAILED_HANDLED, - "context at %s not owned by %s", - object_path, sender); - return; - } - g_free (object_path); - - g_signal_handlers_disconnect_by_func (context, - G_CALLBACK(on_notify_visible), - service); - eekboard_context_service_disable (context); - service->priv->context_stack = g_slist_next (service->priv->context_stack); - if (service->priv->context_stack) - eekboard_context_service_enable (service->priv->context_stack->data); - } - - g_dbus_method_invocation_return_value (invocation, NULL); - return; - } - - if (g_strcmp0 (method_name, "ShowKeyboard") == 0) { - if (service->priv->context_stack) { - eekboard_context_service_show_keyboard (service->priv->context_stack->data); - } else { - service->priv->visible = TRUE; - } - g_dbus_method_invocation_return_value (invocation, NULL); - return; - } - - if (g_strcmp0 (method_name, "HideKeyboard") == 0) { - if (service->priv->context_stack) { - eekboard_context_service_hide_keyboard (service->priv->context_stack->data); - } else { - service->priv->visible = FALSE; - } - g_dbus_method_invocation_return_value (invocation, NULL); - return; - } - - if (g_strcmp0 (method_name, "Destroy") == 0) { - g_signal_emit (service, signals[DESTROYED], 0); - g_dbus_method_invocation_return_value (invocation, NULL); - return; - } - - g_return_if_reached (); -} - /** * eekboard_service_new: * @connection: a #GDBusConnection diff --git a/eekboard/eekboard-service.h b/eekboard/eekboard-service.h index 678b5b6c..5180a538 100644 --- a/eekboard/eekboard-service.h +++ b/eekboard/eekboard-service.h @@ -24,8 +24,8 @@ G_BEGIN_DECLS -#define EEKBOARD_SERVICE_PATH "/org/fedorahosted/Eekboard" -#define EEKBOARD_SERVICE_INTERFACE "org.fedorahosted.Eekboard" +#define EEKBOARD_SERVICE_PATH "/sm/puri/OSK0" +#define EEKBOARD_SERVICE_INTERFACE "sm.puri.OSK0" #define EEKBOARD_TYPE_SERVICE (eekboard_service_get_type()) #define EEKBOARD_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEKBOARD_TYPE_SERVICE, EekboardService)) diff --git a/meson.build b/meson.build index 2004b8f8..30a6ed2d 100644 --- a/meson.build +++ b/meson.build @@ -10,6 +10,7 @@ project( prefix = get_option('prefix') datadir = join_paths(prefix, get_option('datadir')) pkgdatadir = join_paths(datadir, meson.project_name()) +dbusdir = join_paths(datadir, 'dbus-1/interfaces') subdir('data') subdir('eek') diff --git a/src/meson.build b/src/meson.build index 56c5f8b3..bb0101dd 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,3 +1,9 @@ +gnome = import('gnome') +dbus_src = gnome.gdbus_codegen( + 'sm.puri.OSK0', + '../data/dbus/sm.puri.OSK0.xml' +) + sources = [ 'server-service.c', 'server-context-service.c', @@ -23,6 +29,7 @@ sources = [ '../eek/eek-theme-node.c', '../eek/eek-types.c', '../eek/eek-xml-layout.c', + dbus_src, enums, keysym_entries, marshalers,