Clear all input contexts associated with disconnected client.
This commit is contained in:
		@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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 */
 | 
			
		||||
 | 
			
		||||
@ -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,
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user