[gtk/matthiasc/for-master: 39/40] filechooser: Create volume monitor in a thread
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/matthiasc/for-master: 39/40] filechooser: Create volume monitor in a thread
- Date: Wed, 5 Feb 2020 12:00:49 +0000 (UTC)
commit 2c2d69ad2e1e7505ed5c98d846e3f5fdeb8d5d52
Author: Matthias Clasen <mclasen redhat com>
Date: Tue Feb 4 13:18:46 2020 +0100
filechooser: Create volume monitor in a thread
The placessidebar, placesview and filesystem code
all create a volume monitor. No need to block on this,
we need to handle volumes appearing and disappearing anyway.
gtk/gtkfilesystem.c | 55 ++++++++++++++++++++++++++++-------
gtk/gtkplacessidebar.c | 57 ++++++++++++++++++++++++++++++------
gtk/gtkplacesview.c | 79 ++++++++++++++++++++++++++++++++------------------
gtk/gtkvolumemonitor.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++
gtk/gtkvolumemonitor.h | 33 +++++++++++++++++++++
gtk/meson.build | 1 +
6 files changed, 251 insertions(+), 48 deletions(-)
---
diff --git a/gtk/gtkfilesystem.c b/gtk/gtkfilesystem.c
index 55cf55b1fc..d30996a87a 100644
--- a/gtk/gtkfilesystem.c
+++ b/gtk/gtkfilesystem.c
@@ -31,6 +31,7 @@
#include "gtkintl.h"
#include "gtkprivate.h"
#include "gtkstylecontextprivate.h"
+#include "gtkvolumemonitor.h"
/* #define DEBUG_MODE */
#ifdef DEBUG_MODE
@@ -78,6 +79,8 @@ struct GtkFileSystemPrivate
{
GVolumeMonitor *volume_monitor;
+ GCancellable *init_cancellable;
+
/* This list contains elements that can be
* of type GDrive, GVolume and GMount
*/
@@ -129,6 +132,11 @@ gtk_file_system_dispose (GObject *object)
priv->volume_monitor = NULL;
}
+ if (priv->init_cancellable)
+ g_cancellable_cancel (priv->init_cancellable);
+
+ g_clear_object (&priv->init_cancellable);
+
G_OBJECT_CLASS (_gtk_file_system_parent_class)->dispose (object);
}
@@ -201,7 +209,10 @@ get_volumes_list (GtkFileSystem *file_system)
}
/* first go through all connected drives */
- drives = g_volume_monitor_get_connected_drives (priv->volume_monitor);
+ if (priv->volume_monitor)
+ drives = g_volume_monitor_get_connected_drives (priv->volume_monitor);
+ else
+ drives = NULL;
for (l = drives; l != NULL; l = l->next)
{
@@ -259,7 +270,10 @@ get_volumes_list (GtkFileSystem *file_system)
g_list_free (drives);
/* add all volumes that is not associated with a drive */
- volumes = g_volume_monitor_get_volumes (priv->volume_monitor);
+ if (priv->volume_monitor)
+ volumes = g_volume_monitor_get_volumes (priv->volume_monitor);
+ else
+ volumes = NULL;
for (l = volumes; l != NULL; l = l->next)
{
@@ -290,7 +304,10 @@ get_volumes_list (GtkFileSystem *file_system)
}
/* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */
- mounts = g_volume_monitor_get_mounts (priv->volume_monitor);
+ if (priv->volume_monitor)
+ mounts = g_volume_monitor_get_mounts (priv->volume_monitor);
+ else
+ mounts = NULL;
for (l = mounts; l != NULL; l = l->next)
{
@@ -323,16 +340,19 @@ get_volumes_list (GtkFileSystem *file_system)
}
static void
-_gtk_file_system_init (GtkFileSystem *file_system)
+got_volume_monitor (GObject *source,
+ GAsyncResult *result,
+ gpointer data)
{
- GtkFileSystemPrivate *priv;
-
- DEBUG ("init");
+ GtkFileSystem *file_system = GTK_FILE_SYSTEM (data);
+ GtkFileSystemPrivate *priv = file_system->priv;
+ GTask *task = G_TASK (result);
- file_system->priv = priv = _gtk_file_system_get_instance_private (file_system);
+ priv->volume_monitor = g_task_propagate_pointer (task, NULL);
+ if (!priv->volume_monitor)
+ return;
- /* Volumes */
- priv->volume_monitor = g_volume_monitor_get ();
+ g_object_ref (priv->volume_monitor);
g_signal_connect (priv->volume_monitor, "mount-added",
G_CALLBACK (volumes_changed), file_system);
@@ -354,6 +374,21 @@ _gtk_file_system_init (GtkFileSystem *file_system)
G_CALLBACK (volumes_changed), file_system);
}
+static void
+_gtk_file_system_init (GtkFileSystem *file_system)
+{
+ GtkFileSystemPrivate *priv;
+
+ DEBUG ("init");
+
+ file_system->priv = priv = _gtk_file_system_get_instance_private (file_system);
+
+ /* Volumes */
+ priv->init_cancellable = g_cancellable_new ();
+
+ gtk_volume_monitor_get (got_volume_monitor, file_system, priv->init_cancellable);
+}
+
/* GtkFileSystem public methods */
GtkFileSystem *
_gtk_file_system_new (void)
diff --git a/gtk/gtkplacessidebar.c b/gtk/gtkplacessidebar.c
index 4b9a94d375..0f2071b937 100644
--- a/gtk/gtkplacessidebar.c
+++ b/gtk/gtkplacessidebar.c
@@ -67,6 +67,7 @@
#include "gtkwidgetpaintable.h"
#include "gtkselectionprivate.h"
#include "gtkstylecontext.h"
+#include "gtkvolumemonitor.h"
/*< private >
* SECTION:gtkplacessidebar
@@ -166,6 +167,7 @@ struct _GtkPlacesSidebar {
/* volume mounting - delayed open process */
GtkPlacesOpenFlags go_to_after_mount_open_flags;
GCancellable *cancellable;
+ GCancellable *init_cancellable;
GtkWidget *popover;
GtkSidebarRow *context_row;
@@ -1162,7 +1164,10 @@ update_places (GtkPlacesSidebar *sidebar)
#endif
/* go through all connected drives */
- drives = g_volume_monitor_get_connected_drives (sidebar->volume_monitor);
+ if (sidebar->volume_monitor)
+ drives = g_volume_monitor_get_connected_drives (sidebar->volume_monitor);
+ else
+ drives = NULL;
for (l = drives; l != NULL; l = l->next)
{
@@ -1270,7 +1275,11 @@ update_places (GtkPlacesSidebar *sidebar)
/* add all network volumes that are not associated with a drive, and
* loop devices
*/
- volumes = g_volume_monitor_get_volumes (sidebar->volume_monitor);
+ if (sidebar->volume_monitor)
+ volumes = g_volume_monitor_get_volumes (sidebar->volume_monitor);
+ else
+ volumes = NULL;
+
for (l = volumes; l != NULL; l = l->next)
{
gboolean is_loop = FALSE;
@@ -1353,7 +1362,10 @@ update_places (GtkPlacesSidebar *sidebar)
}
/* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */
- mounts = g_volume_monitor_get_mounts (sidebar->volume_monitor);
+ if (sidebar->volume_monitor)
+ mounts = g_volume_monitor_get_mounts (sidebar->volume_monitor);
+ else
+ mounts = NULL;
for (l = mounts; l != NULL; l = l->next)
{
@@ -3968,11 +3980,18 @@ hostname_proxy_new_cb (GObject *source_object,
}
static void
-create_volume_monitor (GtkPlacesSidebar *sidebar)
+got_volume_monitor (GObject *source,
+ GAsyncResult *result,
+ gpointer data)
{
- g_assert (sidebar->volume_monitor == NULL);
+ GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (data);
+ GTask *task = G_TASK (result);
- sidebar->volume_monitor = g_volume_monitor_get ();
+ sidebar->volume_monitor = g_task_propagate_pointer (task, NULL);
+ if (!sidebar->volume_monitor)
+ return;
+
+ g_object_ref (sidebar->volume_monitor);
g_signal_connect_object (sidebar->volume_monitor, "volume_added",
G_CALLBACK (update_places), sidebar, G_CONNECT_SWAPPED);
@@ -3992,6 +4011,20 @@ create_volume_monitor (GtkPlacesSidebar *sidebar)
G_CALLBACK (update_places), sidebar, G_CONNECT_SWAPPED);
g_signal_connect_object (sidebar->volume_monitor, "drive_changed",
G_CALLBACK (update_places), sidebar, G_CONNECT_SWAPPED);
+
+ update_places (sidebar);
+}
+
+static void
+create_volume_monitor (GtkPlacesSidebar *sidebar)
+{
+ GTask *task;
+
+ g_assert (sidebar->volume_monitor == NULL);
+
+ sidebar->init_cancellable = g_cancellable_new ();
+
+ gtk_volume_monitor_get (got_volume_monitor, sidebar, sidebar->init_cancellable);
}
static void
@@ -4137,10 +4170,9 @@ gtk_places_sidebar_init (GtkPlacesSidebar *sidebar)
sidebar);
#endif
- /* populate the sidebar */
- update_places (sidebar);
-
add_actions (sidebar);
+
+ /* we'll populate the sidebar when gtk_volume_manager_get returns in an idle */
}
static void
@@ -4264,6 +4296,13 @@ gtk_places_sidebar_dispose (GObject *object)
sidebar->cancellable = NULL;
}
+ if (sidebar->init_cancellable)
+ {
+ g_cancellable_cancel (sidebar->init_cancellable);
+ g_object_unref (sidebar->init_cancellable);
+ sidebar->init_cancellable = NULL;
+ }
+
free_drag_data (sidebar);
if (sidebar->bookmarks_manager != NULL)
diff --git a/gtk/gtkplacesview.c b/gtk/gtkplacesview.c
index c6915d1d55..2d303c344f 100644
--- a/gtk/gtkplacesview.c
+++ b/gtk/gtkplacesview.c
@@ -30,6 +30,7 @@
#include "gtktypebuiltins.h"
#include "gtkeventcontrollerkey.h"
#include "gtkpopovermenu.h"
+#include "gtkvolumemonitor.h"
/*
* SECTION:gtkplacesview
@@ -86,6 +87,7 @@ struct _GtkPlacesViewPrivate
GtkListStore *completion_store;
GCancellable *networks_fetching_cancellable;
+ GCancellable *init_cancellable;
GtkPlacesViewRow *row_for_action;
@@ -390,7 +392,8 @@ gtk_places_view_destroy (GtkWidget *widget)
priv->destroyed = 1;
- g_signal_handlers_disconnect_by_func (priv->volume_monitor, update_places, widget);
+ if (priv->volume_monitor)
+ g_signal_handlers_disconnect_by_func (priv->volume_monitor, update_places, widget);
if (priv->network_monitor)
g_signal_handlers_disconnect_by_func (priv->network_monitor, update_places, widget);
@@ -400,6 +403,7 @@ gtk_places_view_destroy (GtkWidget *widget)
g_cancellable_cancel (priv->cancellable);
g_cancellable_cancel (priv->networks_fetching_cancellable);
+ g_cancellable_cancel (priv->init_cancellable);
g_clear_pointer (&priv->server_adresses_popover, gtk_widget_unparent);
@@ -424,6 +428,7 @@ gtk_places_view_finalize (GObject *object)
g_clear_object (&priv->networks_fetching_cancellable);
g_clear_object (&priv->path_size_group);
g_clear_object (&priv->space_size_group);
+ g_clear_object (&priv->init_cancellable);
G_OBJECT_CLASS (gtk_places_view_parent_class)->finalize (object);
}
@@ -1127,7 +1132,10 @@ update_places (GtkPlacesView *view)
g_clear_object (&icon);
/* Add currently connected drives */
- drives = g_volume_monitor_get_connected_drives (priv->volume_monitor);
+ if ( priv->volume_monitor)
+ drives = g_volume_monitor_get_connected_drives (priv->volume_monitor);
+ else
+ drives = NULL;
for (l = drives; l != NULL; l = l->next)
add_drive (view, l->data);
@@ -1139,7 +1147,10 @@ update_places (GtkPlacesView *view)
* add_drive before, add all volumes that aren't associated with a
* drive.
*/
- volumes = g_volume_monitor_get_volumes (priv->volume_monitor);
+ if (priv->volume_monitor)
+ volumes = g_volume_monitor_get_volumes (priv->volume_monitor);
+ else
+ volumes = NULL;
for (l = volumes; l != NULL; l = l->next)
{
@@ -1164,7 +1175,10 @@ update_places (GtkPlacesView *view)
* Now that all necessary drives and volumes were already added, add mounts
* that have no volume, such as /etc/mtab mounts, ftp, sftp, etc.
*/
- mounts = g_volume_monitor_get_mounts (priv->volume_monitor);
+ if (priv->volume_monitor)
+ mounts = g_volume_monitor_get_mounts (priv->volume_monitor);
+ else
+ mounts = NULL;
for (l = mounts; l != NULL; l = l->next)
{
@@ -2199,30 +2213,6 @@ gtk_places_view_constructed (GObject *object)
/* load drives */
update_places (GTK_PLACES_VIEW (object));
- g_signal_connect_swapped (priv->volume_monitor,
- "mount-added",
- G_CALLBACK (update_places),
- object);
- g_signal_connect_swapped (priv->volume_monitor,
- "mount-changed",
- G_CALLBACK (update_places),
- object);
- g_signal_connect_swapped (priv->volume_monitor,
- "mount-removed",
- G_CALLBACK (update_places),
- object);
- g_signal_connect_swapped (priv->volume_monitor,
- "volume-added",
- G_CALLBACK (update_places),
- object);
- g_signal_connect_swapped (priv->volume_monitor,
- "volume-changed",
- G_CALLBACK (update_places),
- object);
- g_signal_connect_swapped (priv->volume_monitor,
- "volume-removed",
- G_CALLBACK (update_places),
- object);
}
static void
@@ -2364,6 +2354,35 @@ gtk_places_view_class_init (GtkPlacesViewClass *klass)
gtk_widget_class_set_css_name (widget_class, I_("placesview"));
}
+static void
+got_volume_monitor (GObject *source,
+ GAsyncResult *result,
+ gpointer data)
+{
+ GtkPlacesView *self = GTK_PLACES_VIEW (data);
+ GtkPlacesViewPrivate *priv = gtk_places_view_get_instance_private (self);
+ GTask *task = G_TASK (result);
+
+ priv->volume_monitor = g_task_propagate_pointer (task, NULL);
+ if (!priv->volume_monitor)
+ return;
+
+ g_object_ref (priv->volume_monitor);
+
+ g_signal_connect_swapped (priv->volume_monitor, "mount-added",
+ G_CALLBACK (update_places), self);
+ g_signal_connect_swapped (priv->volume_monitor, "mount-changed",
+ G_CALLBACK (update_places), self);
+ g_signal_connect_swapped (priv->volume_monitor, "mount-removed",
+ G_CALLBACK (update_places), self);
+ g_signal_connect_swapped (priv->volume_monitor, "volume-added",
+ G_CALLBACK (update_places), self);
+ g_signal_connect_swapped (priv->volume_monitor, "volume-changed",
+ G_CALLBACK (update_places), self);
+ g_signal_connect_swapped (priv->volume_monitor, "volume-removed",
+ G_CALLBACK (update_places), self);
+}
+
static void
gtk_places_view_init (GtkPlacesView *self)
{
@@ -2372,7 +2391,9 @@ gtk_places_view_init (GtkPlacesView *self)
priv = gtk_places_view_get_instance_private (self);
- priv->volume_monitor = g_volume_monitor_get ();
+ priv->init_cancellable = g_cancellable_new ();
+ gtk_volume_monitor_get (got_volume_monitor, self, priv->init_cancellable);
+
priv->open_flags = GTK_PLACES_OPEN_NORMAL;
priv->path_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
priv->space_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
diff --git a/gtk/gtkvolumemonitor.c b/gtk/gtkvolumemonitor.c
new file mode 100644
index 0000000000..b51b3f7f2d
--- /dev/null
+++ b/gtk/gtkvolumemonitor.c
@@ -0,0 +1,74 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2020 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Matthias Clasen
+ */
+
+#include "config.h"
+
+#include "gtkvolumemonitor.h"
+
+static GVolumeMonitor *the_volume_monitor;
+static GList *pending_tasks;
+
+static void
+get_volume_monitor_thread (GTask *running_task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ GList *l;
+
+ the_volume_monitor = g_volume_monitor_get ();
+
+ g_object_add_weak_pointer (G_OBJECT (the_volume_monitor), (gpointer *)&the_volume_monitor);
+
+ for (l = pending_tasks; l; l = l->next)
+ {
+ GTask *task = l->data;
+
+ if (!g_task_return_error_if_cancelled (task))
+ g_task_return_pointer (task, g_object_ref (the_volume_monitor), g_object_unref);
+ }
+
+ g_list_free_full (pending_tasks, g_object_unref);
+ pending_tasks = NULL;
+
+ g_object_unref (the_volume_monitor);
+}
+
+void
+gtk_volume_monitor_get (GAsyncReadyCallback callback,
+ gpointer data,
+ GCancellable *cancellable)
+{
+ GTask *task;
+
+ task = g_task_new (NULL, cancellable, callback, data);
+ g_task_set_return_on_cancel (task, TRUE);
+
+ if (the_volume_monitor)
+ {
+ g_task_return_pointer (task, g_object_ref (the_volume_monitor), g_object_unref);
+ g_object_unref (task);
+ }
+ else
+ {
+ pending_tasks = g_list_prepend (pending_tasks, task);
+ if (pending_tasks->next == NULL)
+ g_task_run_in_thread (task, get_volume_monitor_thread);
+ }
+}
diff --git a/gtk/gtkvolumemonitor.h b/gtk/gtkvolumemonitor.h
new file mode 100644
index 0000000000..06ef3fd6ec
--- /dev/null
+++ b/gtk/gtkvolumemonitor.h
@@ -0,0 +1,33 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2020 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Matthias Clasen
+ */
+
+#ifndef __GTK_VOLUME_MONITOR_H__
+#define __GTK_VOLUME_MONITOR_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+void gtk_volume_monitor_get (GAsyncReadyCallback callback,
+ gpointer data,
+ GCancellable *cancellable);
+
+G_END_DECLS
+
+#endif /* __GTK_VOLUME_MONITOR_H__ */
diff --git a/gtk/meson.build b/gtk/meson.build
index 17156b001a..8bde15bd5d 100644
--- a/gtk/meson.build
+++ b/gtk/meson.build
@@ -392,6 +392,7 @@ gtk_public_sources = files([
'gtkvideo.c',
'gtkviewport.c',
'gtkvolumebutton.c',
+ 'gtkvolumemonitor.c',
'gtkwidget.c',
'gtkwidgetfocus.c',
'gtkwidgetpaintable.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]