Merge branch 'dialog-fixes' into 'main'

filechooserwidget: Fixes

See merge request GNOME/gtk!5311
This commit is contained in:
Matthias Clasen 2022-12-09 16:22:00 +00:00
commit a07bf1a047
8 changed files with 263 additions and 149 deletions

View File

@ -29,6 +29,8 @@
#include "gopenuriportal.h"
#include "xdp-dbus.h"
#include "gtkwindowprivate.h"
#include "gtkprivate.h"
#include "gtkdialogerror.h"
#ifdef G_OS_UNIX
#include <gio/gunixfdlist.h>
@ -56,12 +58,12 @@ init_openuri_portal (void)
if (connection != NULL)
{
openuri = gxdp_open_uri_proxy_new_sync (connection, 0,
"org.freedesktop.portal.Desktop",
"/org/freedesktop/portal/desktop",
PORTAL_BUS_NAME,
PORTAL_OBJECT_PATH,
NULL, &error);
if (openuri == NULL)
{
g_warning ("Cannot create document portal proxy: %s", error->message);
g_warning ("Cannot create OpenURI portal proxy: %s", error->message);
g_error_free (error);
}
@ -69,7 +71,7 @@ init_openuri_portal (void)
}
else
{
g_warning ("Cannot connect to session bus when initializing document portal: %s",
g_warning ("Cannot connect to session bus when initializing OpenURI portal: %s",
error->message);
g_error_free (error);
}
@ -80,12 +82,55 @@ init_openuri_portal (void)
return openuri != NULL;
}
gboolean
g_openuri_portal_is_available (void)
{
return init_openuri_portal ();
}
enum {
XDG_DESKTOP_PORTAL_SUCCESS = 0,
XDG_DESKTOP_PORTAL_CANCELLED = 1,
XDG_DESKTOP_PORTAL_FAILED = 2
};
enum {
OPEN_URI = 0,
OPEN_FILE = 1,
OPEN_FOLDER = 2
};
typedef struct {
GtkWindow *parent;
GFile *file;
gboolean open_folder;
GDBusConnection *connection;
GCancellable *cancellable;
GTask *task;
char *handle;
guint signal_id;
glong cancel_handler;
int call;
} OpenUriData;
static void
open_uri_data_free (OpenUriData *data)
{
if (data->signal_id)
g_dbus_connection_signal_unsubscribe (data->connection, data->signal_id);
g_clear_object (&data->connection);
if (data->cancel_handler)
g_signal_handler_disconnect (data->cancellable, data->cancel_handler);
if (data->parent)
gtk_window_unexport_handle (data->parent);
g_clear_object (&data->parent);
g_clear_object (&data->file);
g_clear_object (&data->cancellable);
g_clear_object (&data->task);
g_free (data->handle);
g_free (data);
}
static void
response_received (GDBusConnection *connection,
const char *sender_name,
@ -97,10 +142,6 @@ response_received (GDBusConnection *connection,
{
GTask *task = user_data;
guint32 response;
guint signal_id;
signal_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (task), "signal-id"));
g_dbus_connection_signal_unsubscribe (connection, signal_id);
g_variant_get (parameters, "(u@a{sv})", &response, NULL);
@ -110,11 +151,11 @@ response_received (GDBusConnection *connection,
g_task_return_boolean (task, TRUE);
break;
case XDG_DESKTOP_PORTAL_CANCELLED:
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Launch cancelled");
g_task_return_new_error (task, GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_CANCELLED, "The portal dialog was closed");
break;
case XDG_DESKTOP_PORTAL_FAILED:
default:
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Launch failed");
g_task_return_new_error (task, GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_FAILED, "The application launch failed");
break;
}
@ -127,105 +168,145 @@ open_call_done (GObject *source,
gpointer user_data)
{
GXdpOpenURI *portal = GXDP_OPEN_URI (source);
GDBusConnection *connection;
GTask *task = user_data;
OpenUriData *data = g_task_get_task_data (task);
GError *error = NULL;
gboolean open_file;
gboolean res;
char *path = NULL;
const char *handle;
guint signal_id;
connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (portal));
open_file = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (task), "open-file"));
if (open_file)
res = gxdp_open_uri_call_open_file_finish (portal, &path, NULL, result, &error);
else
res = gxdp_open_uri_call_open_uri_finish (portal, &path, result, &error);
switch (data->call)
{
case OPEN_FILE:
res = gxdp_open_uri_call_open_file_finish (portal, &path, NULL, result, &error);
break;
case OPEN_FOLDER:
res = gxdp_open_uri_call_open_directory_finish (portal, &path, NULL, result, &error);
break;
case OPEN_URI:
res = gxdp_open_uri_call_open_uri_finish (portal, &path, result, &error);
break;
default:
g_assert_not_reached ();
break;
}
if (!res)
{
g_free (path);
g_task_return_error (task, error);
g_object_unref (task);
g_free (path);
return;
}
handle = (const char *)g_object_get_data (G_OBJECT (task), "handle");
if (g_strcmp0 (handle, path) != 0)
if (g_strcmp0 (data->handle, path) != 0)
{
signal_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (task), "signal-id"));
g_dbus_connection_signal_unsubscribe (connection, signal_id);
g_dbus_connection_signal_unsubscribe (data->connection, data->signal_id);
signal_id = g_dbus_connection_signal_subscribe (connection,
"org.freedesktop.portal.Desktop",
"org.freedesktop.portal.Request",
"Response",
path,
NULL,
G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
response_received,
task,
NULL);
g_object_set_data (G_OBJECT (task), "signal-id", GINT_TO_POINTER (signal_id));
data->signal_id = g_dbus_connection_signal_subscribe (data->connection,
PORTAL_BUS_NAME,
PORTAL_REQUEST_INTERFACE,
"Response",
path,
NULL,
G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
response_received,
task,
NULL);
g_free (data->handle);
data->handle = g_strdup (path);
}
g_free (path);
}
static void
send_close (OpenUriData *data)
{
GDBusMessage *message;
GError *error = NULL;
message = g_dbus_message_new_method_call (PORTAL_BUS_NAME,
PORTAL_OBJECT_PATH,
PORTAL_REQUEST_INTERFACE,
"Close");
g_dbus_message_set_body (message, g_variant_new ("(o)", data->handle));
if (!g_dbus_connection_send_message (data->connection,
message,
G_DBUS_SEND_MESSAGE_FLAGS_NONE,
NULL, &error))
{
g_warning ("unable to send Close message: %s", error->message);
g_error_free (error);
}
g_object_unref (message);
}
static void
canceled (GCancellable *cancellable,
GTask *task)
{
OpenUriData *data = g_task_get_task_data (task);
send_close (data);
g_task_return_new_error (task,
GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_ABORTED,
"The OpenURI portal call was cancelled programmatically");
g_object_unref (task);
}
static void
open_uri (GFile *file,
gboolean open_folder,
const char *parent_window,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
OpenUriData *data = user_data;
GTask *task;
GVariant *opts = NULL;
int i;
guint signal_id;
GDBusConnection *connection;
GVariantBuilder opt_builder;
char *token;
char *sender;
if (callback)
{
GDBusConnection *connection;
GVariantBuilder opt_builder;
char *token;
char *sender;
char *handle;
connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (openuri));
data->connection = g_object_ref (connection);
connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (openuri));
task = g_task_new (NULL, NULL, callback, user_data);
g_task_set_check_cancellable (task, FALSE);
g_task_set_task_data (task, user_data, NULL);
if (data->cancellable)
data->cancel_handler = g_signal_connect (data->cancellable, "cancelled", G_CALLBACK (canceled), task);
task = g_task_new (NULL, cancellable, callback, user_data);
token = g_strdup_printf ("gtk%d", g_random_int_range (0, G_MAXINT));
sender = g_strdup (g_dbus_connection_get_unique_name (connection) + 1);
for (i = 0; sender[i]; i++)
if (sender[i] == '.')
sender[i] = '_';
token = g_strdup_printf ("gtk%d", g_random_int_range (0, G_MAXINT));
sender = g_strdup (g_dbus_connection_get_unique_name (connection) + 1);
for (i = 0; sender[i]; i++)
if (sender[i] == '.')
sender[i] = '_';
data->handle = g_strdup_printf ("/org/freedesktop/portal/desktop/request/%s/%s", sender, token);
g_free (sender);
handle = g_strdup_printf ("/org/freedesktop/portal/desktop/request/%s/%s", sender, token);
g_object_set_data_full (G_OBJECT (task), "handle", handle, g_free);
g_free (sender);
data->signal_id = g_dbus_connection_signal_subscribe (connection,
PORTAL_BUS_NAME,
PORTAL_REQUEST_INTERFACE,
"Response",
data->handle,
NULL,
G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
response_received,
task,
NULL);
signal_id = g_dbus_connection_signal_subscribe (connection,
"org.freedesktop.portal.Desktop",
"org.freedesktop.portal.Request",
"Response",
handle,
NULL,
G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
response_received,
task,
NULL);
g_object_set_data (G_OBJECT (task), "signal-id", GINT_TO_POINTER (signal_id));
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
g_variant_builder_add (&opt_builder, "{sv}", "handle_token", g_variant_new_string (token));
g_free (token);
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
g_variant_builder_add (&opt_builder, "{sv}", "handle_token", g_variant_new_string (token));
g_free (token);
opts = g_variant_builder_end (&opt_builder);
}
else
task = NULL;
opts = g_variant_builder_end (&opt_builder);
if (g_file_is_native (file))
{
@ -233,17 +314,15 @@ open_uri (GFile *file,
GUnixFDList *fd_list = NULL;
int fd, fd_id, errsv;
if (task)
g_object_set_data (G_OBJECT (task), "open-file", GINT_TO_POINTER (TRUE));
path = g_file_peek_path (file);
fd = g_open (path, O_RDONLY | O_CLOEXEC);
errsv = errno;
if (fd == -1)
{
g_task_report_new_error (NULL, callback, user_data, NULL,
g_task_return_new_error (task,
G_IO_ERROR, g_io_error_from_errno (errsv),
"OpenURI portal is not available");
"Failed to open file");
g_object_unref (task);
return;
}
@ -254,49 +333,49 @@ open_uri (GFile *file,
fd = -1;
fd_id = 0;
gxdp_open_uri_call_open_file (openuri,
parent_window ? parent_window : "",
g_variant_new ("h", fd_id),
opts,
fd_list,
cancellable,
task ? open_call_done : NULL,
task);
if (open_folder)
{
data->call = OPEN_FOLDER;
gxdp_open_uri_call_open_directory (openuri,
parent_window ? parent_window : "",
g_variant_new ("h", fd_id),
opts,
fd_list,
NULL,
open_call_done,
task);
}
else
{
data->call = OPEN_FILE;
gxdp_open_uri_call_open_file (openuri,
parent_window ? parent_window : "",
g_variant_new ("h", fd_id),
opts,
fd_list,
NULL,
open_call_done,
task);
}
g_object_unref (fd_list);
}
else
{
char *uri = g_file_get_uri (file);
data->call = OPEN_URI;
gxdp_open_uri_call_open_uri (openuri,
parent_window ? parent_window : "",
uri,
opts,
cancellable,
task ? open_call_done : NULL,
NULL,
open_call_done,
task);
g_free (uri);
}
}
typedef struct {
GtkWindow *parent;
GFile *file;
GTask *task;
} OpenUriData;
static void
open_uri_data_free (OpenUriData *data)
{
if (data->parent)
gtk_window_unexport_handle (data->parent);
g_clear_object (&data->parent);
g_clear_object (&data->file);
g_clear_object (&data->task);
g_free (data);
}
static void
open_uri_done (GObject *source,
GAsyncResult *result,
@ -306,7 +385,17 @@ open_uri_done (GObject *source,
GError *error = NULL;
if (!g_task_propagate_boolean (G_TASK (result), &error))
g_task_return_error (data->task, error);
{
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
{
g_error_free (error);
g_task_return_new_error (data->task,
GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_ABORTED,
"The operation was aborted programmatically");
}
else
g_task_return_error (data->task, error);
}
else
g_task_return_boolean (data->task, TRUE);
@ -320,11 +409,12 @@ window_handle_exported (GtkWindow *window,
{
OpenUriData *data = user_data;
open_uri (data->file, handle, g_task_get_cancellable (data->task), open_uri_done, data);
open_uri (data->file, data->open_folder, handle, open_uri_done, data);
}
void
g_openuri_portal_open_async (GFile *file,
gboolean open_folder,
GtkWindow *parent,
GCancellable *cancellable,
GAsyncReadyCallback callback,
@ -335,15 +425,18 @@ g_openuri_portal_open_async (GFile *file,
if (!init_openuri_portal ())
{
g_task_report_new_error (NULL, callback, user_data, NULL,
G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED,
"OpenURI portal is not available");
GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_FAILED,
"The OpenURI portal is not available");
return;
}
data = g_new0 (OpenUriData, 1);
data->parent = parent ? g_object_ref (parent) : NULL;
data->file = g_object_ref (file);
data->open_folder = open_folder;
data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
data->task = g_task_new (parent, cancellable, callback, user_data);
g_task_set_check_cancellable (data->task, FALSE);
g_task_set_source_tag (data->task, g_openuri_portal_open_async);
if (!parent || !gtk_window_export_handle (parent, window_handle_exported, data))

View File

@ -26,14 +26,17 @@
G_BEGIN_DECLS
void g_openuri_portal_open_async (GFile *file,
GtkWindow *window,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean g_openuri_portal_is_available (void);
gboolean g_openuri_portal_open_finish (GAsyncResult *result,
GError **error);
void g_openuri_portal_open_async (GFile *file,
gboolean open_folder,
GtkWindow *window,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean g_openuri_portal_open_finish (GAsyncResult *result,
GError **error);
G_END_DECLS

View File

@ -458,6 +458,7 @@ gtk_color_dialog_choose_rgba (GtkColorDialog *self,
window = create_color_chooser (self, parent, initial_color);
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_check_cancellable (task, FALSE);
g_task_set_source_tag (task, gtk_color_dialog_choose_rgba);
g_task_set_task_data (task, window, (GDestroyNotify) gtk_window_destroy);
@ -472,7 +473,7 @@ gtk_color_dialog_choose_rgba (GtkColorDialog *self,
* gtk_color_dialog_choose_rgba_finish:
* @self: a `GtkColorDialog`
* @result: a `GAsyncResult`
* @error: return location for an error
* @error: return location for a [enum@Gtk.DialogError] error
*
* Finishes the [method@Gtk.ColorDialog.choose_rgba] call and
* returns the resulting color.

View File

@ -338,8 +338,9 @@ drag_prepare (GtkDragSource *source,
static void
update_button_sensitivity (GtkColorDialogButton *self)
{
gtk_widget_set_sensitive (self->button,
self->dialog != NULL && self->cancellable == NULL);
if (self->button)
gtk_widget_set_sensitive (self->button,
self->dialog != NULL && self->cancellable == NULL);
}
static void
@ -347,10 +348,11 @@ color_chosen (GObject *source,
GAsyncResult *result,
gpointer data)
{
GtkColorDialog *dialog = GTK_COLOR_DIALOG (source);
GtkColorDialogButton *self = data;
GdkRGBA *color;
color = gtk_color_dialog_choose_rgba_finish (self->dialog, result, NULL);
color = gtk_color_dialog_choose_rgba_finish (dialog, result, NULL);
if (color)
{
gtk_color_dialog_button_set_rgba (self, color);

View File

@ -1385,12 +1385,12 @@ open_folder_cb (GSimpleAction *action,
if (gdk_should_use_portal ())
{
g_openuri_portal_open_async (file, toplevel, NULL, NULL, NULL);
g_openuri_portal_open_async (file, TRUE, toplevel, NULL, NULL, NULL);
}
else
{
GDBusConnection *bus;
GVariantBuilder *uris_builder;
GVariantBuilder uris_builder;
GVariant *result;
GError *error = NULL;
@ -1398,20 +1398,20 @@ open_folder_cb (GSimpleAction *action,
bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
uris_builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
g_variant_builder_add (uris_builder, "s", uri);
g_variant_builder_init (&uris_builder, G_VARIANT_TYPE ("as"));
g_variant_builder_add (&uris_builder, "s", uri);
result = g_dbus_connection_call_sync (bus,
FILE_MANAGER_DBUS_NAME,
FILE_MANAGER_DBUS_PATH,
FILE_MANAGER_DBUS_IFACE,
"ShowFolders",
g_variant_new ("(ass)", uris_builder, ""),
NULL, /* ignore returned type */
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
FILE_MANAGER_DBUS_NAME,
FILE_MANAGER_DBUS_PATH,
FILE_MANAGER_DBUS_IFACE,
"ShowFolders",
g_variant_new ("(ass)", &uris_builder, ""),
NULL, /* ignore returned type */
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if (error)
{
if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER) ||

View File

@ -778,6 +778,7 @@ gtk_file_dialog_open (GtkFileDialog *self,
current_file, NULL, FALSE);
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_check_cancellable (task, FALSE);
g_task_set_source_tag (task, gtk_file_dialog_open);
g_task_set_task_data (task, chooser, (GDestroyNotify) gtk_native_dialog_destroy);
@ -854,6 +855,7 @@ gtk_file_dialog_select_folder (GtkFileDialog *self,
current_folder, NULL, FALSE);
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_check_cancellable (task, FALSE);
g_task_set_source_tag (task, gtk_file_dialog_select_folder);
g_task_set_task_data (task, chooser, (GDestroyNotify) gtk_native_dialog_destroy);
@ -935,6 +937,7 @@ gtk_file_dialog_save (GtkFileDialog *self,
current_file, current_name, FALSE);
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_check_cancellable (task, FALSE);
g_task_set_source_tag (task, gtk_file_dialog_save);
g_task_set_task_data (task, chooser, (GDestroyNotify) gtk_native_dialog_destroy);
@ -1008,6 +1011,7 @@ gtk_file_dialog_open_multiple (GtkFileDialog *self,
NULL, NULL, TRUE);
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_check_cancellable (task, FALSE);
g_task_set_source_tag (task, gtk_file_dialog_open_multiple);
g_task_set_task_data (task, chooser, (GDestroyNotify) gtk_native_dialog_destroy);
@ -1082,6 +1086,7 @@ gtk_file_dialog_select_multiple_folders (GtkFileDialog *self,
NULL, NULL, TRUE);
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_check_cancellable (task, FALSE);
g_task_set_source_tag (task, gtk_file_dialog_select_multiple_folders);
g_task_set_task_data (task, chooser, (GDestroyNotify) gtk_native_dialog_destroy);

View File

@ -596,6 +596,7 @@ create_font_chooser (GtkFontDialog *self,
window = gtk_font_chooser_dialog_new (title, parent);
gtk_font_chooser_set_level (GTK_FONT_CHOOSER (window), level);
gtk_window_set_modal (GTK_WINDOW (window), TRUE);
if (self->language)
gtk_font_chooser_set_language (GTK_FONT_CHOOSER (window),
pango_language_to_string (self->language));
@ -657,6 +658,7 @@ gtk_font_dialog_choose_family (GtkFontDialog *self,
g_clear_pointer (&desc, pango_font_description_free);
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_check_cancellable (task, FALSE);
g_task_set_source_tag (task, gtk_font_dialog_choose_family);
g_task_set_task_data (task, window, (GDestroyNotify) gtk_window_destroy);
@ -672,7 +674,7 @@ gtk_font_dialog_choose_family (GtkFontDialog *self,
* gtk_font_dialog_choose_family_finish:
* @self: a `GtkFontDialog`
* @result: a `GAsyncResult`
* @error: return location for an error
* @error: return location for a [enum@Gtk.DialogError] error
*
* Finishes the [method@Gtk.FontDialog.choose_family] call
* and returns the resulting family.
@ -740,6 +742,7 @@ gtk_font_dialog_choose_face (GtkFontDialog *self,
g_clear_pointer (&desc, pango_font_description_free);
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_check_cancellable (task, FALSE);
g_task_set_source_tag (task, gtk_font_dialog_choose_face);
g_task_set_task_data (task, window, (GDestroyNotify) gtk_window_destroy);
@ -755,7 +758,7 @@ gtk_font_dialog_choose_face (GtkFontDialog *self,
* gtk_font_dialog_choose_face_finish:
* @self: a `GtkFontDialog`
* @result: a `GAsyncResult`
* @error: return location for an error
* @error: return location for a [enum@Gtk.DialogError] error
*
* Finishes the [method@Gtk.FontDialog.choose_face] call
* and returns the resulting font face.
@ -773,7 +776,7 @@ gtk_font_dialog_choose_face_finish (GtkFontDialog *self,
g_return_val_if_fail (g_task_is_valid (result, self), NULL);
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gtk_font_dialog_choose_face, NULL);
return g_task_propagate_pointer (G_TASK (result), NULL);
return g_task_propagate_pointer (G_TASK (result), error);
}
/**
@ -817,6 +820,7 @@ gtk_font_dialog_choose_font (GtkFontDialog *self,
GTK_FONT_CHOOSER_LEVEL_VARIATIONS);
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_check_cancellable (task, FALSE);
g_task_set_source_tag (task, gtk_font_dialog_choose_font);
g_task_set_task_data (task, window, (GDestroyNotify) gtk_window_destroy);
@ -832,7 +836,7 @@ gtk_font_dialog_choose_font (GtkFontDialog *self,
* gtk_font_dialog_choose_font_finish:
* @self: a `GtkFontDialog`
* @result: a `GAsyncResult`
* @error: return location for an error
* @error: return location for a [enum@Gtk.DialogError] error
*
* Finishes the [method@Gtk.FontDialog.choose_font] call
* and returns the resulting font description.
@ -850,7 +854,7 @@ gtk_font_dialog_choose_font_finish (GtkFontDialog *self,
g_return_val_if_fail (g_task_is_valid (result, self), NULL);
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gtk_font_dialog_choose_font, NULL);
return g_task_propagate_pointer (G_TASK (result), NULL);
return g_task_propagate_pointer (G_TASK (result), error);
}
/**
@ -896,6 +900,7 @@ gtk_font_dialog_choose_font_and_features (GtkFontDialog *self,
GTK_FONT_CHOOSER_LEVEL_FEATURES);
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_check_cancellable (task, FALSE);
g_task_set_source_tag (task, gtk_font_dialog_choose_font_and_features);
g_task_set_task_data (task, window, (GDestroyNotify) gtk_window_destroy);
@ -914,7 +919,7 @@ gtk_font_dialog_choose_font_and_features (GtkFontDialog *self,
* @font_desc: (out caller-allocates): return location for font description
* @font_features: (out caller-allocates): return location for font features
* @language: (out caller-allocates): return location for the language
* @error: return location for an error
* @error: return location for a [enum@Gtk.DialogError] error
*
* Finishes the [method@Gtk.FontDialog.choose_font_and_features]
* call and returns the resulting font description and font features.

View File

@ -393,8 +393,9 @@ gtk_font_dialog_button_class_init (GtkFontDialogButtonClass *class)
static void
update_button_sensitivity (GtkFontDialogButton *self)
{
gtk_widget_set_sensitive (self->button,
self->dialog != NULL && self->cancellable == NULL);
if (self->button)
gtk_widget_set_sensitive (self->button,
self->dialog != NULL && self->cancellable == NULL);
}
static void
@ -402,10 +403,11 @@ family_chosen (GObject *source,
GAsyncResult *result,
gpointer data)
{
GtkFontDialog *dialog = GTK_FONT_DIALOG (source);
GtkFontDialogButton *self = data;
PangoFontFamily *family;
family = gtk_font_dialog_choose_family_finish (self->dialog, result, NULL);
family = gtk_font_dialog_choose_family_finish (dialog, result, NULL);
if (family)
{
PangoFontDescription *desc;
@ -428,10 +430,11 @@ face_chosen (GObject *source,
GAsyncResult *result,
gpointer data)
{
GtkFontDialog *dialog = GTK_FONT_DIALOG (source);
GtkFontDialogButton *self = data;
PangoFontFace *face;
face = gtk_font_dialog_choose_face_finish (self->dialog, result, NULL);
face = gtk_font_dialog_choose_face_finish (dialog, result, NULL);
if (face)
{
PangoFontDescription *desc;
@ -453,10 +456,11 @@ font_chosen (GObject *source,
GAsyncResult *result,
gpointer data)
{
GtkFontDialog *dialog = GTK_FONT_DIALOG (source);
GtkFontDialogButton *self = data;
PangoFontDescription *desc;
desc = gtk_font_dialog_choose_font_finish (self->dialog, result, NULL);
desc = gtk_font_dialog_choose_font_finish (dialog, result, NULL);
if (desc)
{
gtk_font_dialog_button_set_font_desc (self, desc);
@ -472,12 +476,13 @@ font_and_features_chosen (GObject *source,
GAsyncResult *result,
gpointer data)
{
GtkFontDialog *dialog = GTK_FONT_DIALOG (source);
GtkFontDialogButton *self = data;
PangoFontDescription *desc;
char *features;
PangoLanguage *language;
if (gtk_font_dialog_choose_font_and_features_finish (self->dialog, result,
if (gtk_font_dialog_choose_font_and_features_finish (dialog, result,
&desc, &features, &language,
NULL))
{