summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2018-09-03 18:36:56 -0400
committerMatthias Clasen <mclasen@redhat.com>2018-09-05 17:56:33 -0400
commitbba183ee0c96b6124358447a4a9747dc38a5c8a0 (patch)
treeb7ecdc0071c178bc9503c7c195d86a0da51de1d7
parent2bb97bc136620ba4cd5d9e7283f9fa94e8042989 (diff)
downloadgtk+-bba183ee0c96b6124358447a4a9747dc38a5c8a0.tar.gz
clipboard: file transfer portal supportfile-transfer-portal
Implement file-list <-> application/vnd.flatpak.file-list serialization by talking to the file transfer portal.
-rw-r--r--gdk/gdkclipboard.c3
-rw-r--r--gdk/gdkcontentdeserializer.c98
-rw-r--r--gdk/gdkcontentserializer.c67
-rw-r--r--gdk/gfiletransferportal.c323
-rw-r--r--gdk/gfiletransferportal.h15
-rw-r--r--gdk/meson.build1
-rw-r--r--tests/simple.c67
-rw-r--r--tests/testclipboard2.c19
8 files changed, 581 insertions, 12 deletions
diff --git a/gdk/gdkclipboard.c b/gdk/gdkclipboard.c
index d165b0fd79..6ceb7b4b29 100644
--- a/gdk/gdkclipboard.c
+++ b/gdk/gdkclipboard.c
@@ -1054,6 +1054,7 @@ gdk_clipboard_write_serialize_done (GObject *content,
g_object_unref (task);
}
+
void
gdk_clipboard_write_async (GdkClipboard *clipboard,
const char *mime_type,
@@ -1076,6 +1077,7 @@ gdk_clipboard_write_async (GdkClipboard *clipboard,
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
g_return_if_fail (callback != NULL);
+g_print ("clipboard write in %s\n", mime_type);
task = g_task_new (clipboard, cancellable, callback, user_data);
g_task_set_priority (task, io_priority);
g_task_set_source_tag (task, gdk_clipboard_write_async);
@@ -1232,6 +1234,7 @@ gdk_clipboard_set_content (GdkClipboard *clipboard,
formats = gdk_content_formats_new (NULL, 0);
}
+g_print ("claiming clipboard for %s\n", gdk_content_formats_to_string (formats));
result = gdk_clipboard_claim (clipboard, formats, TRUE, provider);
gdk_content_formats_unref (formats);
diff --git a/gdk/gdkcontentdeserializer.c b/gdk/gdkcontentdeserializer.c
index 93564e2002..ea3c7ad003 100644
--- a/gdk/gdkcontentdeserializer.c
+++ b/gdk/gdkcontentdeserializer.c
@@ -22,6 +22,7 @@
#include "gdkcontentdeserializer.h"
#include "gdkcontentformats.h"
+#include "gfiletransferportal.h"
#include "gdktexture.h"
#include <gdk-pixbuf/gdk-pixbuf.h>
@@ -691,6 +692,93 @@ string_deserializer (GdkContentDeserializer *deserializer)
}
static void
+portal_finish (GObject *object,
+ GAsyncResult *result,
+ gpointer deserializer)
+{
+ char **files = NULL;
+ GError *error = NULL;
+ GValue *value;
+
+ if (!file_transfer_portal_retrieve_files_finish (result, &files, &error))
+ {
+ gdk_content_deserializer_return_error (deserializer, error);
+ return;
+ }
+
+ value = gdk_content_deserializer_get_value (deserializer);
+ if (G_VALUE_HOLDS (value, G_TYPE_FILE))
+ {
+ if (files[0] != NULL)
+ g_value_take_object (value, g_file_new_for_path (files[0]));
+ }
+ else
+ {
+ GSList *l = NULL;
+ gsize i;
+
+ for (i = 0; files[i] != NULL; i++)
+ l = g_slist_prepend (l, g_file_new_for_path (files[i]));
+ g_value_take_boxed (value, g_slist_reverse (l));
+ }
+ g_strfreev (files);
+
+ gdk_content_deserializer_return_success (deserializer);
+}
+
+static void
+portal_file_deserializer_finish (GObject *source,
+ GAsyncResult *result,
+ gpointer deserializer)
+{
+ GOutputStream *stream = G_OUTPUT_STREAM (source);
+ GError *error = NULL;
+ gssize written;
+ char *key;
+
+ written = g_output_stream_splice_finish (stream, result, &error);
+ if (written < 0)
+ {
+ gdk_content_deserializer_return_error (deserializer, error);
+ return;
+ }
+
+ /* write terminating NULL */
+ if (!g_output_stream_write (stream, "", 1, NULL, &error))
+ {
+ gdk_content_deserializer_return_error (deserializer, error);
+ return;
+ }
+
+ key = g_memory_output_stream_steal_data (G_MEMORY_OUTPUT_STREAM (stream));
+ if (key == NULL)
+ {
+ deserialize_not_found (deserializer);
+ return;
+ }
+
+ file_transfer_portal_retrieve_files (key, portal_finish, deserializer);
+ gdk_content_deserializer_set_task_data (deserializer, key, g_free);
+}
+
+static void
+portal_file_deserializer (GdkContentDeserializer *deserializer)
+{
+ GOutputStream *output;
+
+ output = g_memory_output_stream_new_resizable ();
+
+ g_output_stream_splice_async (output,
+ gdk_content_deserializer_get_input_stream (deserializer),
+ G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
+ gdk_content_deserializer_get_priority (deserializer),
+ gdk_content_deserializer_get_cancellable (deserializer),
+ portal_file_deserializer_finish,
+ deserializer);
+ g_object_unref (output);
+}
+
+static void
file_uri_deserializer_finish (GObject *source,
GAsyncResult *result,
gpointer deserializer)
@@ -816,11 +904,21 @@ init (void)
g_slist_free (formats);
+ gdk_content_register_deserializer ("application/vnd.portal.filetransfer",
+ GDK_TYPE_FILE_LIST,
+ portal_file_deserializer,
+ NULL,
+ NULL);
gdk_content_register_deserializer ("text/uri-list",
GDK_TYPE_FILE_LIST,
file_uri_deserializer,
NULL,
NULL);
+ gdk_content_register_deserializer ("application/vnd.portal.filetransfer",
+ G_TYPE_FILE,
+ portal_file_deserializer,
+ NULL,
+ NULL);
gdk_content_register_deserializer ("text/uri-list",
G_TYPE_FILE,
file_uri_deserializer,
diff --git a/gdk/gdkcontentserializer.c b/gdk/gdkcontentserializer.c
index 7b99690224..bbe66824f1 100644
--- a/gdk/gdkcontentserializer.c
+++ b/gdk/gdkcontentserializer.c
@@ -23,6 +23,7 @@
#include "gdkcontentformats.h"
#include "gdkpixbuf.h"
+#include "gfiletransferportal.h"
#include "gdktextureprivate.h"
#include <gdk-pixbuf/gdk-pixbuf.h>
@@ -702,6 +703,62 @@ file_serializer_finish (GObject *source,
}
static void
+portal_ready (GObject *object,
+ GAsyncResult *result,
+ gpointer serializer)
+{
+ GError *error = NULL;
+ char *key;
+
+ if (!file_transfer_portal_register_files_finish (result, &key, &error))
+ {
+ gdk_content_serializer_return_error (serializer, error);
+ return;
+ }
+
+ g_output_stream_write_all_async (gdk_content_serializer_get_output_stream (serializer),
+ key,
+ strlen (key) + 1,
+ gdk_content_serializer_get_priority (serializer),
+ gdk_content_serializer_get_cancellable (serializer),
+ file_serializer_finish,
+ serializer);
+ gdk_content_serializer_set_task_data (serializer, key, g_free);
+}
+
+static void
+portal_file_serializer (GdkContentSerializer *serializer)
+{
+ GFile *file;
+ const GValue *value;
+ GPtrArray *files;
+
+ files = g_ptr_array_new_with_free_func (g_free);
+
+ value = gdk_content_serializer_get_value (serializer);
+
+ if (G_VALUE_HOLDS (value, G_TYPE_FILE))
+ {
+ file = g_value_get_object (gdk_content_serializer_get_value (serializer));
+ if (file)
+ g_ptr_array_add (files, g_file_get_path (file));
+ g_ptr_array_add (files, NULL);
+ }
+ else if (G_VALUE_HOLDS (value, GDK_TYPE_FILE_LIST))
+ {
+ GSList *l;
+
+ for (l = g_value_get_boxed (value); l; l = l->next)
+ g_ptr_array_add (files, g_file_get_path (l->data));
+
+ g_ptr_array_add (files, NULL);
+ }
+
+ file_transfer_portal_register_files ((const char **)files->pdata, TRUE, portal_ready, serializer);
+ gdk_content_serializer_set_task_data (serializer, files, (GDestroyNotify)g_ptr_array_unref);
+}
+
+static void
file_uri_serializer (GdkContentSerializer *serializer)
{
GFile *file;
@@ -864,6 +921,11 @@ init (void)
g_slist_free (formats);
gdk_content_register_serializer (G_TYPE_FILE,
+ "application/vnd.portal.filetransfer",
+ portal_file_serializer,
+ NULL,
+ NULL);
+ gdk_content_register_serializer (G_TYPE_FILE,
"text/uri-list",
file_uri_serializer,
NULL,
@@ -874,6 +936,11 @@ init (void)
NULL,
NULL);
gdk_content_register_serializer (GDK_TYPE_FILE_LIST,
+ "application/vnd.portal.filetransfer",
+ portal_file_serializer,
+ NULL,
+ NULL);
+ gdk_content_register_serializer (GDK_TYPE_FILE_LIST,
"text/uri-list",
file_uri_serializer,
NULL,
diff --git a/gdk/gfiletransferportal.c b/gdk/gfiletransferportal.c
new file mode 100644
index 0000000000..2ebb865452
--- /dev/null
+++ b/gdk/gfiletransferportal.c
@@ -0,0 +1,323 @@
+#include "config.h"
+
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <gio/gio.h>
+#include <gio/gunixfdlist.h>
+
+#include "gfiletransferportal.h"
+
+static GDBusProxy *
+ensure_file_transfer_portal (void)
+{
+ static GDBusProxy *proxy = NULL;
+
+ if (proxy == NULL)
+ {
+ GError *error = NULL;
+
+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
+ | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS
+ | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+ NULL,
+ "org.freedesktop.portal.Documents",
+ "/org/freedesktop/portal/documents",
+ "org.freedesktop.portal.FileTransfer",
+ NULL, &error);
+
+ if (error)
+ {
+ g_warning ("Failed to get proxy: %s", error->message);
+ g_error_free (error);
+ }
+ }
+
+ if (proxy)
+ {
+ char *owner = g_dbus_proxy_get_name_owner (proxy);
+
+ if (owner)
+ {
+ g_free (owner);
+ return proxy;
+ }
+ }
+
+ return NULL;
+}
+
+typedef struct {
+ GTask *task;
+ const char **files;
+ int len;
+ int start;
+} AddFileData;
+
+static void add_files (GDBusProxy *proxy,
+ AddFileData *afd);
+
+static void
+add_files_done (GObject *object,
+ GAsyncResult *result,
+ gpointer data)
+{
+ GDBusProxy *proxy = G_DBUS_PROXY (object);
+ AddFileData *afd = data;
+ GError *error = NULL;
+ GVariant *ret;
+
+ ret = g_dbus_proxy_call_with_unix_fd_list_finish (proxy, NULL, result, &error);
+ if (ret == NULL)
+ {
+ g_task_return_error (afd->task, error);
+ g_object_unref (afd->task);
+ g_free (afd);
+ return;
+ }
+
+ g_variant_unref (ret);
+
+ if (afd->start >= afd->len)
+ {
+ g_task_return_boolean (afd->task, TRUE);
+ g_object_unref (afd->task);
+ g_free (afd);
+ return;
+ }
+
+ add_files (proxy, afd);
+}
+
+/* We call AddFiles in chunks of 16 to avoid running into
+ * the per-message fd limit of the bus.
+ */
+static void
+add_files (GDBusProxy *proxy,
+ AddFileData *afd)
+{
+ GUnixFDList *fd_list;
+ GVariantBuilder fds;
+ int i;
+ char *key;
+ GVariantBuilder options;
+
+ g_variant_builder_init (&fds, G_VARIANT_TYPE ("ah"));
+ fd_list = g_unix_fd_list_new ();
+
+ for (i = 0; afd->files[afd->start + i]; i++)
+ {
+ int fd;
+ int fd_in;
+ GError *error = NULL;
+
+ if (i == 16)
+ break;
+
+ fd = open (afd->files[afd->start + i], O_PATH | O_CLOEXEC);
+ if (fd == -1)
+ {
+ g_task_return_new_error (afd->task, G_IO_ERROR, g_io_error_from_errno (errno),
+ "Failed to open %s", afd->files[afd->start + i]);
+ g_object_unref (afd->task);
+ g_free (afd);
+ g_object_unref (fd_list);
+ return;
+ }
+ fd_in = g_unix_fd_list_append (fd_list, fd, &error);
+ close (fd);
+
+ if (fd_in == -1)
+ {
+ g_task_return_error (afd->task, error);
+ g_object_unref (afd->task);
+ g_free (afd);
+ g_object_unref (fd_list);
+ return;
+ }
+
+ g_variant_builder_add (&fds, "h", fd_in);
+ }
+
+ afd->start += 16;
+
+ key = (char *)g_object_get_data (G_OBJECT (afd->task), "key");
+
+ g_variant_builder_init (&options, G_VARIANT_TYPE_VARDICT);
+ g_dbus_proxy_call_with_unix_fd_list (proxy,
+ "AddFiles",
+ g_variant_new ("(saha{sv})", key, &fds, &options),
+ 0, -1,
+ fd_list,
+ NULL,
+ add_files_done, afd);
+
+ g_object_unref (fd_list);
+}
+
+static void
+start_session_done (GObject *object,
+ GAsyncResult *result,
+ gpointer data)
+{
+ GDBusProxy *proxy = G_DBUS_PROXY (object);
+ AddFileData *afd = data;
+ GError *error = NULL;
+ GVariant *ret;
+ const char *key;
+
+ ret = g_dbus_proxy_call_finish (proxy, result, &error);
+ if (ret == NULL)
+ {
+ g_task_return_error (afd->task, error);
+ g_object_unref (afd->task);
+ g_free (afd);
+ return;
+ }
+
+ g_variant_get (ret, "(&s)", &key);
+
+ g_object_set_data_full (G_OBJECT (afd->task), "key", g_strdup (key), g_free);
+
+ g_variant_unref (ret);
+
+ add_files (proxy, afd);
+}
+
+void
+file_transfer_portal_register_files (const char **files,
+ gboolean writable,
+ GAsyncReadyCallback callback,
+ gpointer data)
+{
+ GTask *task;
+ GDBusProxy *proxy;
+ AddFileData *afd;
+ GVariantBuilder options;
+
+ task = g_task_new (NULL, NULL, callback, data);
+
+ proxy = ensure_file_transfer_portal ();
+
+ if (proxy == NULL)
+ {
+ g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ "No portal found");
+ g_object_unref (task);
+ return;
+ }
+
+ afd = g_new (AddFileData, 1);
+ afd->task = task;
+ afd->files = files;
+ afd->len = g_strv_length ((char **)files);
+ afd->start = 0;
+
+ g_variant_builder_init (&options, G_VARIANT_TYPE_VARDICT);
+ g_variant_builder_add (&options, "{sv}", "writable", g_variant_new_boolean (writable));
+ g_variant_builder_add (&options, "{sv}", "autostop", g_variant_new_boolean (TRUE));
+
+ g_dbus_proxy_call (proxy, "StartTransfer",
+ g_variant_new ("(a{sv})", &options),
+ 0, -1, NULL, start_session_done, afd);
+}
+
+gboolean
+file_transfer_portal_register_files_finish (GAsyncResult *result,
+ char **out_key,
+ GError **error)
+{
+ char *key;
+ GDBusProxy *proxy;
+
+ key = g_object_get_data (G_OBJECT (result), "key");
+
+ if (g_task_propagate_boolean (G_TASK (result), error))
+ {
+ *out_key = g_strdup (key);
+ return TRUE;
+ }
+
+ proxy = ensure_file_transfer_portal ();
+
+ g_dbus_proxy_call (proxy, "StopTransfer",
+ g_variant_new ("(s)", key),
+ 0, -1, NULL, NULL, NULL);
+
+ return FALSE;
+}
+
+static void
+retrieve_files_done (GObject *object,
+ GAsyncResult *result,
+ gpointer data)
+{
+ GDBusProxy *proxy = G_DBUS_PROXY (object);
+ GTask *task = data;
+ GError *error = NULL;
+ GVariant *ret;
+ char **files;
+
+ ret = g_dbus_proxy_call_finish (proxy, result, &error);
+ if (ret == NULL)
+ {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ g_variant_get (ret, "(^a&s)", &files);
+
+ g_object_set_data_full (G_OBJECT (task), "files", g_strdupv (files), (GDestroyNotify)g_strfreev);
+
+ g_variant_unref (ret);
+
+ g_task_return_boolean (task, TRUE);
+}
+
+void
+file_transfer_portal_retrieve_files (const char *key,
+ GAsyncReadyCallback callback,
+ gpointer data)
+{
+ GDBusProxy *proxy;
+ GTask *task;
+ GVariantBuilder options;
+
+ task = g_task_new (NULL, NULL, callback, data);
+
+ proxy = ensure_file_transfer_portal ();
+
+ if (proxy == NULL)
+ {
+ g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ "No portal found");
+ g_object_unref (task);
+ return;
+ }
+
+ g_variant_builder_init (&options, G_VARIANT_TYPE_VARDICT);
+ g_dbus_proxy_call (proxy,
+ "RetrieveFiles",
+ g_variant_new ("(sa{sv})", key, &options),
+ 0, -1, NULL,
+ retrieve_files_done, task);
+}
+
+gboolean
+file_transfer_portal_retrieve_files_finish (GAsyncResult *result,
+ char ***files,
+ GError **error)
+{
+ if (g_task_propagate_boolean (G_TASK (result), error))
+ {
+ *files = g_strdupv (g_object_get_data (G_OBJECT (result), "files"));
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/gdk/gfiletransferportal.h b/gdk/gfiletransferportal.h
new file mode 100644
index 0000000000..0203b4d94b
--- /dev/null
+++ b/gdk/gfiletransferportal.h
@@ -0,0 +1,15 @@
+
+void file_transfer_portal_register_files (const char **files,
+ gboolean writable,
+ GAsyncReadyCallback callback,
+ gpointer data);
+gboolean file_transfer_portal_register_files_finish (GAsyncResult *result,
+ char **key,
+ GError **error);
+
+void file_transfer_portal_retrieve_files (const char *key,
+ GAsyncReadyCallback callback,
+ gpointer data);
+gboolean file_transfer_portal_retrieve_files_finish (GAsyncResult *result,
+ char ***files,
+ GError **error);
diff --git a/gdk/meson.build b/gdk/meson.build
index d68307392b..88d8a8a363 100644
--- a/gdk/meson.build
+++ b/gdk/meson.build
@@ -19,6 +19,7 @@ gdk_public_sources = files([
'gdkdrawcontext.c',
'gdkdrop.c',
'gdkevents.c',
+ 'gfiletransferportal.c',
'gdkframeclock.c',
'gdkframeclockidle.c',
'gdkframetimings.c',
diff --git a/tests/simple.c b/tests/simple.c
index 63ae18f2f6..17991b3465 100644
--- a/tests/simple.c
+++ b/tests/simple.c
@@ -20,15 +20,59 @@
void
-hello (void)
+copy (void)
{
- g_print ("hello world\n");
+ GdkClipboard *clipboard = gdk_display_get_clipboard (gdk_display_get_default ());
+ GFile *file = g_file_new_for_path ("/home/mclasen/faw-sig");
+
+ gdk_clipboard_set (clipboard, G_TYPE_FILE, file);
+
+ g_object_unref (file);
+}
+
+static void
+value_received (GObject *object,
+ GAsyncResult *result,
+ gpointer data)
+{
+ const GValue *value;
+ GError *error = NULL;
+ GSList *l;
+
+ value = gdk_clipboard_read_value_finish (GDK_CLIPBOARD (object), result, &error);
+ if (value == NULL)
+ {
+ g_print ("Failed to read: %s\n", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ for (l = g_value_get_boxed (value); l; l = l->next)
+ g_print ("%s\n", g_file_get_path (l->data));
+}
+
+void
+paste (void)
+{
+ GdkClipboard *clipboard = gdk_display_get_clipboard (gdk_display_get_default ());
+
+ gdk_clipboard_read_value_async (clipboard, GDK_TYPE_FILE_LIST, 0, NULL, value_received, NULL);
+
+}
+
+static void
+clipboard_changed (GdkClipboard *clipboard)
+{
+ GdkContentFormats *formats = gdk_clipboard_get_formats (clipboard);
+ g_autofree char *s = gdk_content_formats_to_string (formats);
+ g_print ("clipboard contents now: %s, local: %d\n", s, gdk_clipboard_is_local (clipboard));
}
int
main (int argc, char *argv[])
{
- GtkWidget *window, *button;
+ GtkWidget *window, *button, *box;
+ GdkClipboard *clipboard;
gtk_init ();
@@ -37,11 +81,22 @@ main (int argc, char *argv[])
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
button = gtk_button_new ();
- gtk_button_set_label (GTK_BUTTON (button), "hello world");
- g_signal_connect (button, "clicked", G_CALLBACK (hello), NULL);
+ gtk_button_set_label (GTK_BUTTON (button), "copy");
+ g_signal_connect (button, "clicked", G_CALLBACK (copy), NULL);
+ gtk_container_add (GTK_CONTAINER (box), button);
+
+ button = gtk_button_new ();
+ gtk_button_set_label (GTK_BUTTON (button), "paste");
+ g_signal_connect (button, "clicked", G_CALLBACK (paste), NULL);
+ gtk_container_add (GTK_CONTAINER (box), button);
+
+ gtk_container_add (GTK_CONTAINER (window), box);
- gtk_container_add (GTK_CONTAINER (window), button);
+ clipboard = gdk_display_get_clipboard (gdk_display_get_default ());
+ g_signal_connect (clipboard, "changed", G_CALLBACK (clipboard_changed), NULL);
gtk_widget_show (window);
diff --git a/tests/testclipboard2.c b/tests/testclipboard2.c
index 86c0e5dc3f..e539c14d3e 100644
--- a/tests/testclipboard2.c
+++ b/tests/testclipboard2.c
@@ -103,23 +103,30 @@ visible_child_changed_cb (GtkWidget *stack,
}
}
-static GList *
+static GSList *
get_file_list (const char *dir)
{
GFileEnumerator *enumerator;
GFile *file;
- GList *list = NULL;
+ GFileInfo *info;
+ GSList *list = NULL;
file = g_file_new_for_path (dir);
- enumerator = g_file_enumerate_children (file, "standard::name", 0, NULL, NULL);
+ enumerator = g_file_enumerate_children (file, "standard::name,standard::type", 0, NULL, NULL);
g_object_unref (file);
if (enumerator == NULL)
return NULL;
- while (g_file_enumerator_iterate (enumerator, NULL, &file, NULL, NULL) && file != NULL)
- list = g_list_prepend (list, g_object_ref (file));
+ while (g_file_enumerator_iterate (enumerator, &info, &file, NULL, NULL) && file != NULL)
+ {
+ /* the portal can't handle directories */
+ if (g_file_info_get_file_type (info) != G_FILE_TYPE_REGULAR)
+ continue;
+
+ list = g_slist_prepend (list, g_object_ref (file));
+ }
- return g_list_reverse (list);
+ return g_slist_reverse (list);
}
static void