Merge branch 'dialog-portal-cherry-pick' into 'gtk-3-24'

[gtk3] Cherry-pick gtkfilechoosernativeportal fixes from gtk4

See merge request GNOME/gtk!6612
This commit is contained in:
Matthias Clasen
2023-12-19 01:13:40 +00:00

View File

@ -23,24 +23,16 @@
#include "gtknativedialogprivate.h" #include "gtknativedialogprivate.h"
#include "gtkprivate.h" #include "gtkprivate.h"
#include "gtkfilechooserdialog.h" #include "gtkdialog.h"
#include "gtkfilechooserprivate.h" #include "gtkfilechooserprivate.h"
#include "gtkfilechooserwidget.h" #include "gtkinvisible.h"
#include "gtkfilechooserwidgetprivate.h"
#include "gtkfilechooserutils.h"
#include "gtkfilechooserembed.h"
#include "gtkfilesystem.h"
#include "gtksizerequest.h" #include "gtksizerequest.h"
#include "gtktypebuiltins.h" #include "gtktypebuiltins.h"
#include "gtkintl.h"
#include "gtksettings.h" #include "gtksettings.h"
#include "gtktogglebutton.h" #include "gtktogglebutton.h"
#include "gtkstylecontext.h"
#include "gtkheaderbar.h" #include "gtkheaderbar.h"
#include "gtklabel.h" #include "gtklabel.h"
#include "gtkmain.h" #include "gtkmain.h"
#include "gtkinvisible.h"
#include "gtkfilechooserentry.h"
#include "gtkfilefilterprivate.h" #include "gtkfilefilterprivate.h"
#include "gtkwindowprivate.h" #include "gtkwindowprivate.h"
@ -63,36 +55,51 @@ typedef struct {
static void static void
filechooser_portal_data_free (FilechooserPortalData *data) filechooser_portal_data_clear (FilechooserPortalData *data)
{ {
if (data->portal_response_signal_id != 0) if (data->portal_response_signal_id != 0)
g_dbus_connection_signal_unsubscribe (data->connection, {
data->portal_response_signal_id); g_dbus_connection_signal_unsubscribe (data->connection,
data->portal_response_signal_id);
data->portal_response_signal_id = 0;
}
g_object_unref (data->connection); g_clear_object (&data->connection);
if (data->grab_widget) if (data->grab_widget)
{ {
gtk_grab_remove (data->grab_widget); gtk_grab_remove (data->grab_widget);
gtk_widget_destroy (data->grab_widget); gtk_widget_destroy (data->grab_widget);
data->grab_widget = NULL;
} }
g_clear_object (&data->self); g_clear_object (&data->self);
if (data->exported_window) if (data->exported_window)
gtk_window_unexport_handle (data->exported_window); {
gtk_window_unexport_handle (data->exported_window);
data->exported_window = NULL;
}
g_free (data->portal_handle); g_clear_pointer (&data->portal_handle, g_free);
}
g_free (data); static void
filechooser_portal_data_free (FilechooserPortalData *data)
{
if (data != NULL)
{
filechooser_portal_data_clear (data);
g_free (data);
}
} }
static void static void
response_cb (GDBusConnection *connection, response_cb (GDBusConnection *connection,
const gchar *sender_name, const char *sender_name,
const gchar *object_path, const char *object_path,
const gchar *interface_name, const char *interface_name,
const gchar *signal_name, const char *signal_name,
GVariant *parameters, GVariant *parameters,
gpointer user_data) gpointer user_data)
{ {
@ -126,7 +133,7 @@ response_cb (GDBusConnection *connection,
if (current_filter) if (current_filter)
{ {
GtkFileFilter *filter = gtk_file_filter_new_from_gvariant (current_filter); GtkFileFilter *filter = gtk_file_filter_new_from_gvariant (current_filter);
const gchar *current_filter_name = gtk_file_filter_get_name (filter); const char *current_filter_name = gtk_file_filter_get_name (filter);
/* Try to find the given filter in the list of filters. /* Try to find the given filter in the list of filters.
* Since filters are compared by pointer value, using the passed * Since filters are compared by pointer value, using the passed
@ -157,6 +164,10 @@ response_cb (GDBusConnection *connection,
self->custom_files = NULL; self->custom_files = NULL;
for (i = 0; uris[i]; i++) for (i = 0; uris[i]; i++)
self->custom_files = g_slist_prepend (self->custom_files, g_file_new_for_uri (uris[i])); self->custom_files = g_slist_prepend (self->custom_files, g_file_new_for_uri (uris[i]));
self->custom_files = g_slist_reverse (self->custom_files);
g_free (uris);
g_variant_unref (response_data);
switch (portal_response) switch (portal_response)
{ {
@ -172,10 +183,18 @@ response_cb (GDBusConnection *connection,
break; break;
} }
/* Keep a reference on the native dialog until we can emit the response
* signal; filechooser_portal_data_free() will drop a reference on the
* dialog as well
*/
g_object_ref (self);
filechooser_portal_data_free (data); filechooser_portal_data_free (data);
self->mode_data = NULL; self->mode_data = NULL;
_gtk_native_dialog_emit_response (GTK_NATIVE_DIALOG (self), gtk_response); _gtk_native_dialog_emit_response (GTK_NATIVE_DIALOG (self), gtk_response);
g_object_unref (self);
} }
static void static void
@ -220,11 +239,11 @@ open_file_msg_cb (GObject *source_object,
if (reply == NULL) if (reply == NULL)
{ {
if (!data->hidden) if (!data->hidden)
_gtk_native_dialog_emit_response (GTK_NATIVE_DIALOG (self), GTK_RESPONSE_DELETE_EVENT); {
g_warning ("Can't open portal file chooser: %s", error->message); filechooser_portal_data_free (data);
self->mode_data = NULL;
}
g_error_free (error); g_error_free (error);
filechooser_portal_data_free (data);
self->mode_data = NULL;
return; return;
} }
@ -233,7 +252,6 @@ open_file_msg_cb (GObject *source_object,
if (data->hidden) if (data->hidden)
{ {
/* The dialog was hidden before we got the handle, close it now */ /* The dialog was hidden before we got the handle, close it now */
send_close (data);
filechooser_portal_data_free (data); filechooser_portal_data_free (data);
self->mode_data = NULL; self->mode_data = NULL;
} }
@ -374,7 +392,7 @@ show_portal_file_chooser (GtkFileChooserNative *self,
g_variant_new_string (GTK_FILE_CHOOSER_NATIVE (self)->current_name)); g_variant_new_string (GTK_FILE_CHOOSER_NATIVE (self)->current_name));
if (self->current_folder) if (self->current_folder)
{ {
gchar *path; char *path;
path = g_file_get_path (GTK_FILE_CHOOSER_NATIVE (self)->current_folder); path = g_file_get_path (GTK_FILE_CHOOSER_NATIVE (self)->current_folder);
g_variant_builder_add (&opt_builder, "{sv}", "current_folder", g_variant_builder_add (&opt_builder, "{sv}", "current_folder",
@ -383,7 +401,7 @@ show_portal_file_chooser (GtkFileChooserNative *self,
} }
if (self->current_file) if (self->current_file)
{ {
gchar *path; char *path;
path = g_file_get_path (GTK_FILE_CHOOSER_NATIVE (self)->current_file); path = g_file_get_path (GTK_FILE_CHOOSER_NATIVE (self)->current_file);
g_variant_builder_add (&opt_builder, "{sv}", "current_file", g_variant_builder_add (&opt_builder, "{sv}", "current_file",
@ -516,10 +534,11 @@ gtk_file_chooser_native_portal_hide (GtkFileChooserNative *self)
data->hidden = TRUE; data->hidden = TRUE;
if (data->portal_handle) if (data->portal_handle)
{ send_close (data);
send_close (data);
filechooser_portal_data_free (data);
}
/* We clear the data because we might have in-flight async
* operations that can still access it
*/
filechooser_portal_data_clear (data);
self->mode_data = NULL; self->mode_data = NULL;
} }