From 3f7562809ec4980eb18bb816d9da0d82d34c97e6 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 23 Feb 2011 13:15:39 +0900 Subject: [PATCH] Clear all input contexts associated with disconnected client. --- src/server-context.c | 27 +++++++++++++++++++++++++- src/server-context.h | 5 +++++ src/server-server.c | 45 ++++++++++++++++++++++---------------------- 3 files changed, 53 insertions(+), 24 deletions(-) diff --git a/src/server-context.c b/src/server-context.c index 473cf238..d4b1073c 100644 --- a/src/server-context.c +++ b/src/server-context.c @@ -82,6 +82,7 @@ struct _ServerContext { GDBusNodeInfo *introspection_data; guint registration_id; char *object_path; + char *client_connection; gboolean enabled; gboolean last_keyboard_visible; @@ -213,7 +214,7 @@ update_widget (ServerContext *context) gtk_widget_set_can_focus (context->window, FALSE); g_object_set (G_OBJECT(context->window), "accept_focus", FALSE, NULL); gtk_window_set_title (GTK_WINDOW(context->window), "Keyboard"); - gtk_window_set_icon_name (GTK_WINDOW(context->window), "input-keyboard"); + gtk_window_set_icon_name (GTK_WINDOW(context->window), "eekboard"); gtk_window_set_keep_above (GTK_WINDOW(context->window), TRUE); screen = gdk_screen_get_default (); @@ -289,6 +290,16 @@ server_context_dispose (GObject *object) G_OBJECT_CLASS (server_context_parent_class)->dispose (object); } +static void +server_context_finalize (GObject *object) +{ + ServerContext *context = SERVER_CONTEXT(object); + + g_free (context->client_connection); + + G_OBJECT_CLASS (server_context_parent_class)->finalize (object); +} + static void server_context_constructed (GObject *object) { @@ -316,6 +327,7 @@ server_context_class_init (ServerContextClass *klass) gobject_class->constructed = server_context_constructed; gobject_class->set_property = server_context_set_property; gobject_class->dispose = server_context_dispose; + gobject_class->finalize = server_context_finalize; pspec = g_param_spec_string ("object-path", "Object-path", @@ -614,3 +626,16 @@ server_context_set_enabled (ServerContext *context, gboolean enabled) } context->enabled = enabled; } + +void +server_context_set_client_connection (ServerContext *context, + const gchar *client_connection) +{ + context->client_connection = g_strdup (client_connection); +} + +const gchar * +server_context_get_client_connection (ServerContext *context) +{ + return context->client_connection; +} diff --git a/src/server-context.h b/src/server-context.h index c08f0a27..f5515805 100644 --- a/src/server-context.h +++ b/src/server-context.h @@ -38,6 +38,11 @@ ServerContext *server_context_new (const gchar *object_path, GDBusConnection *connection); void server_context_set_enabled (ServerContext *context, gboolean enabled); +void server_context_set_client_connection + (ServerContext *context, + const gchar *client_connection); +const gchar *server_context_get_client_connection + (ServerContext *context); G_END_DECLS #endif /* SERVER_CONTEXT_H */ diff --git a/src/server-server.c b/src/server-server.c index ff0c9037..d2e072b2 100644 --- a/src/server-server.c +++ b/src/server-server.c @@ -58,7 +58,6 @@ struct _ServerServer { GHashTable *context_hash; GSList *context_stack; - GHashTable *sender_object_path_hash; }; struct _ServerServerClass { @@ -123,11 +122,6 @@ server_server_dispose (GObject *object) server->context_hash = NULL; } - if (server->sender_object_path_hash) { - g_hash_table_destroy (server->sender_object_path_hash); - server->sender_object_path_hash = NULL; - } - for (head = server->context_stack; head; head = server->context_stack) { g_object_unref (head->data); server->context_stack = g_slist_next (head); @@ -218,11 +212,6 @@ server_server_init (ServerServer *server) (GDestroyNotify)g_free, (GDestroyNotify)g_object_unref); server->context_stack = NULL; - server->sender_object_path_hash = - g_hash_table_new_full (g_str_hash, - g_str_equal, - (GDestroyNotify)g_free, - NULL); } static void @@ -234,8 +223,8 @@ remove_context_from_stack (ServerServer *server, ServerContext *context) if (head) { server->context_stack = g_slist_remove_link (server->context_stack, head); + g_object_unref (head->data); g_slist_free1 (head); - g_object_unref (context); } if (server->context_stack) server_context_set_enabled (server->context_stack->data, TRUE); @@ -247,18 +236,30 @@ server_name_vanished_callback (GDBusConnection *connection, gpointer user_data) { ServerServer *server = user_data; - const gchar *object_path; + GSList *head; + GHashTableIter iter; + gpointer k, v; - object_path = g_hash_table_lookup (server->sender_object_path_hash, name); - if (object_path) { - ServerContext *context; + g_hash_table_iter_init (&iter, server->context_hash); + while (g_hash_table_iter_next (&iter, &k, &v)) { + const gchar *client_connection = + server_context_get_client_connection (v); + if (g_strcmp0 (client_connection, name) == 0) + g_hash_table_iter_remove (&iter); + } - context = g_hash_table_lookup (server->context_hash, object_path); - if (context) { - remove_context_from_stack (server, context); - g_hash_table_remove (server->context_hash, object_path); + for (head = server->context_stack; head; head = server->context_stack) { + const gchar *client_connection = + server_context_get_client_connection (head->data); + if (g_strcmp0 (client_connection, name) == 0) { + server->context_stack = g_slist_remove_link (server->context_stack, + head); + g_object_unref (head->data); + g_slist_free1 (head); } } + if (server->context_stack) + server_context_set_enabled (server->context_stack->data, TRUE); } static void @@ -282,12 +283,10 @@ handle_method_call (GDBusConnection *connection, g_variant_get (parameters, "(&s)", &client_name); object_path = g_strdup_printf (SERVER_CONTEXT_PATH, context_id++); context = server_context_new (object_path, server->connection); + server_context_set_client_connection (context, sender); g_hash_table_insert (server->context_hash, object_path, context); - g_hash_table_insert (server->sender_object_path_hash, - g_strdup (sender), - object_path); g_bus_watch_name_on_connection (server->connection, sender, G_BUS_NAME_WATCHER_FLAGS_NONE,