| File: | ctk/ctkfilechoosernativeportal.c |
| Warning: | line 352, column 41 Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */ |
| 2 | /* CTK - The GIMP Toolkit |
| 3 | * ctkfilechoosernativeportal.c: Portal File selector dialog |
| 4 | * Copyright (C) 2015, Red Hat, Inc. |
| 5 | * |
| 6 | * This library is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU Lesser General Public |
| 8 | * License as published by the Free Software Foundation; either |
| 9 | * version 2 of the License, or (at your option) any later version. |
| 10 | * |
| 11 | * This library is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 | * Lesser General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU Lesser General Public |
| 17 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
| 18 | */ |
| 19 | |
| 20 | #include "config.h" |
| 21 | |
| 22 | #include "ctkfilechoosernativeprivate.h" |
| 23 | #include "ctknativedialogprivate.h" |
| 24 | |
| 25 | #include "ctkprivate.h" |
| 26 | #include "ctkfilechooserdialog.h" |
| 27 | #include "ctkfilechooserprivate.h" |
| 28 | #include "ctkfilechooserwidget.h" |
| 29 | #include "ctkfilechooserwidgetprivate.h" |
| 30 | #include "ctkfilechooserutils.h" |
| 31 | #include "ctkfilechooserembed.h" |
| 32 | #include "ctkfilesystem.h" |
| 33 | #include "ctksizerequest.h" |
| 34 | #include "ctktypebuiltins.h" |
| 35 | #include "ctkintl.h" |
| 36 | #include "ctksettings.h" |
| 37 | #include "ctktogglebutton.h" |
| 38 | #include "ctkstylecontext.h" |
| 39 | #include "ctkheaderbar.h" |
| 40 | #include "ctklabel.h" |
| 41 | #include "ctkmain.h" |
| 42 | #include "ctkinvisible.h" |
| 43 | #include "ctkfilechooserentry.h" |
| 44 | #include "ctkfilefilterprivate.h" |
| 45 | #include "ctkwindowprivate.h" |
| 46 | |
| 47 | typedef struct { |
| 48 | CtkFileChooserNative *self; |
| 49 | |
| 50 | CtkWidget *grab_widget; |
| 51 | |
| 52 | GDBusConnection *connection; |
| 53 | char *portal_handle; |
| 54 | guint portal_response_signal_id; |
| 55 | gboolean modal; |
| 56 | |
| 57 | gboolean hidden; |
| 58 | |
| 59 | const char *method_name; |
| 60 | |
| 61 | CtkWindow *exported_window; |
| 62 | } FilechooserPortalData; |
| 63 | |
| 64 | |
| 65 | static void |
| 66 | filechooser_portal_data_free (FilechooserPortalData *data) |
| 67 | { |
| 68 | if (data->portal_response_signal_id != 0) |
| 69 | g_dbus_connection_signal_unsubscribe (data->connection, |
| 70 | data->portal_response_signal_id); |
| 71 | |
| 72 | g_object_unref (data->connection); |
| 73 | |
| 74 | if (data->grab_widget) |
| 75 | { |
| 76 | ctk_grab_remove (data->grab_widget); |
| 77 | ctk_widget_destroy (data->grab_widget); |
| 78 | } |
| 79 | |
| 80 | g_clear_object (&data->self)do { _Static_assert (sizeof *((&data->self)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ ((( &data->self))) _pp = ((&data->self)); __typeof__ (*((&data->self))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr); } while (0); |
| 81 | |
| 82 | if (data->exported_window) |
| 83 | ctk_window_unexport_handle (data->exported_window); |
| 84 | |
| 85 | g_free (data->portal_handle); |
| 86 | |
| 87 | g_free (data); |
| 88 | } |
| 89 | |
| 90 | static void |
| 91 | response_cb (GDBusConnection *connection G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 92 | const gchar *sender_name G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 93 | const gchar *object_path G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 94 | const gchar *interface_name G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 95 | const gchar *signal_name G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 96 | GVariant *parameters, |
| 97 | gpointer user_data) |
| 98 | { |
| 99 | CtkFileChooserNative *self = user_data; |
| 100 | FilechooserPortalData *data = self->mode_data; |
| 101 | guint32 portal_response; |
| 102 | int ctk_response; |
| 103 | const char **uris; |
| 104 | int i; |
| 105 | GVariant *response_data; |
| 106 | GVariant *choices = NULL((void*)0); |
| 107 | GVariant *current_filter = NULL((void*)0); |
| 108 | |
| 109 | g_variant_get (parameters, "(u@a{sv})", &portal_response, &response_data); |
| 110 | g_variant_lookup (response_data, "uris", "^a&s", &uris); |
| 111 | |
| 112 | choices = g_variant_lookup_value (response_data, "choices", G_VARIANT_TYPE ("a(ss)")(g_variant_type_checked_ (("a(ss)")))); |
| 113 | if (choices) |
| 114 | { |
| 115 | for (i = 0; i < g_variant_n_children (choices); i++) |
| 116 | { |
| 117 | const char *id; |
| 118 | const char *selected; |
| 119 | g_variant_get_child (choices, i, "(&s&s)", &id, &selected); |
| 120 | ctk_file_chooser_set_choice (CTK_FILE_CHOOSER (self)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((self)), ((ctk_file_chooser_get_type ())))))), id, selected); |
| 121 | } |
| 122 | g_variant_unref (choices); |
| 123 | } |
| 124 | |
| 125 | current_filter = g_variant_lookup_value (response_data, "current_filter", G_VARIANT_TYPE ("(sa(us))")(g_variant_type_checked_ (("(sa(us))")))); |
| 126 | if (current_filter) |
| 127 | { |
| 128 | CtkFileFilter *filter = ctk_file_filter_new_from_gvariant (current_filter); |
| 129 | const gchar *current_filter_name = ctk_file_filter_get_name (filter); |
| 130 | |
| 131 | /* Try to find the given filter in the list of filters. |
| 132 | * Since filters are compared by pointer value, using the passed |
| 133 | * filter would otherwise not match in a comparison, even if |
| 134 | * a filter in the list of filters has been selected. |
| 135 | * We'll use the heuristic that if two filters have the same name, |
| 136 | * they must be the same. |
| 137 | * If there is no match, just set the filter as it was retrieved. |
| 138 | */ |
| 139 | CtkFileFilter *filter_to_select = filter; |
| 140 | GSList *filters = ctk_file_chooser_list_filters (CTK_FILE_CHOOSER (self)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((self)), ((ctk_file_chooser_get_type ()))))))); |
| 141 | GSList *l; |
| 142 | |
| 143 | for (l = filters; l; l = l->next) |
| 144 | { |
| 145 | CtkFileFilter *f = l->data; |
| 146 | if (g_strcmp0 (ctk_file_filter_get_name (f), current_filter_name) == 0) |
| 147 | { |
| 148 | filter_to_select = f; |
| 149 | break; |
| 150 | } |
| 151 | } |
| 152 | g_slist_free (filters); |
| 153 | ctk_file_chooser_set_filter (CTK_FILE_CHOOSER (self)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((self)), ((ctk_file_chooser_get_type ())))))), filter_to_select); |
| 154 | } |
| 155 | |
| 156 | g_slist_free_full (self->custom_files, g_object_unref); |
| 157 | self->custom_files = NULL((void*)0); |
| 158 | for (i = 0; uris[i]; i++) |
| 159 | self->custom_files = g_slist_prepend (self->custom_files, g_file_new_for_uri (uris[i])); |
| 160 | |
| 161 | switch (portal_response) |
| 162 | { |
| 163 | case 0: |
| 164 | ctk_response = CTK_RESPONSE_ACCEPT; |
| 165 | break; |
| 166 | case 1: |
| 167 | ctk_response = CTK_RESPONSE_CANCEL; |
| 168 | break; |
| 169 | case 2: |
| 170 | default: |
| 171 | ctk_response = CTK_RESPONSE_DELETE_EVENT; |
| 172 | break; |
| 173 | } |
| 174 | |
| 175 | filechooser_portal_data_free (data); |
| 176 | self->mode_data = NULL((void*)0); |
| 177 | |
| 178 | _ctk_native_dialog_emit_response (CTK_NATIVE_DIALOG (self), ctk_response); |
| 179 | } |
| 180 | |
| 181 | static void |
| 182 | send_close (FilechooserPortalData *data) |
| 183 | { |
| 184 | GDBusMessage *message; |
| 185 | GError *error = NULL((void*)0); |
| 186 | |
| 187 | message = g_dbus_message_new_method_call ("org.freedesktop.portal.Desktop", |
| 188 | "/org/freedesktop/portal/desktop", |
| 189 | "org.freedesktop.portal.FileChooser", |
| 190 | "Close"); |
| 191 | g_dbus_message_set_body (message, |
| 192 | g_variant_new ("(o)", data->portal_handle)); |
| 193 | |
| 194 | if (!g_dbus_connection_send_message (data->connection, |
| 195 | message, |
| 196 | G_DBUS_SEND_MESSAGE_FLAGS_NONE, |
| 197 | NULL((void*)0), &error)) |
| 198 | { |
| 199 | g_warning ("unable to send FileChooser Close message: %s", error->message); |
| 200 | g_error_free (error); |
| 201 | } |
| 202 | |
| 203 | g_object_unref (message); |
| 204 | } |
| 205 | |
| 206 | static void |
| 207 | open_file_msg_cb (GObject *source_object G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 208 | GAsyncResult *res, |
| 209 | gpointer user_data) |
| 210 | { |
| 211 | FilechooserPortalData *data = user_data; |
| 212 | CtkFileChooserNative *self = data->self; |
| 213 | GDBusMessage *reply; |
| 214 | GError *error = NULL((void*)0); |
| 215 | char *handle = NULL((void*)0); |
| 216 | |
| 217 | reply = g_dbus_connection_send_message_with_reply_finish (data->connection, res, &error); |
| 218 | |
| 219 | if (reply && g_dbus_message_to_gerror (reply, &error)) |
| 220 | g_clear_object (&reply)do { _Static_assert (sizeof *((&reply)) == sizeof (gpointer ), "Expression evaluates to false"); __typeof__ (((&reply ))) _pp = ((&reply)); __typeof__ (*((&reply))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr); } while (0); |
| 221 | |
| 222 | if (reply == NULL((void*)0)) |
| 223 | { |
| 224 | if (!data->hidden) |
| 225 | _ctk_native_dialog_emit_response (CTK_NATIVE_DIALOG (self), CTK_RESPONSE_DELETE_EVENT); |
| 226 | g_warning ("Can't open portal file chooser: %s", error->message); |
| 227 | g_error_free (error); |
| 228 | filechooser_portal_data_free (data); |
| 229 | self->mode_data = NULL((void*)0); |
| 230 | return; |
| 231 | } |
| 232 | |
| 233 | g_variant_get_child (g_dbus_message_get_body (reply), 0, "o", &handle); |
| 234 | |
| 235 | if (data->hidden) |
| 236 | { |
| 237 | /* The dialog was hidden before we got the handle, close it now */ |
| 238 | send_close (data); |
| 239 | filechooser_portal_data_free (data); |
| 240 | self->mode_data = NULL((void*)0); |
| 241 | } |
| 242 | else if (strcmp (handle, data->portal_handle) != 0) |
| 243 | { |
| 244 | g_free (data->portal_handle); |
| 245 | data->portal_handle = g_steal_pointer (&handle)((__typeof__ (*&handle)) (g_steal_pointer) (&handle)); |
| 246 | g_dbus_connection_signal_unsubscribe (data->connection, |
| 247 | data->portal_response_signal_id); |
| 248 | |
| 249 | data->portal_response_signal_id = |
| 250 | g_dbus_connection_signal_subscribe (data->connection, |
| 251 | "org.freedesktop.portal.Desktop", |
| 252 | "org.freedesktop.portal.Request", |
| 253 | "Response", |
| 254 | data->portal_handle, |
| 255 | NULL((void*)0), |
| 256 | G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE, |
| 257 | response_cb, |
| 258 | self, NULL((void*)0)); |
| 259 | } |
| 260 | |
| 261 | g_object_unref (reply); |
| 262 | g_free (handle); |
| 263 | } |
| 264 | |
| 265 | static GVariant * |
| 266 | get_filters (CtkFileChooser *self) |
| 267 | { |
| 268 | GSList *list, *l; |
| 269 | GVariantBuilder builder; |
| 270 | |
| 271 | g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sa(us))")(g_variant_type_checked_ (("a(sa(us))")))); |
| 272 | list = ctk_file_chooser_list_filters (self); |
| 273 | for (l = list; l; l = l->next) |
| 274 | { |
| 275 | CtkFileFilter *filter = l->data; |
| 276 | g_variant_builder_add (&builder, "@(sa(us))", ctk_file_filter_to_gvariant (filter)); |
| 277 | } |
| 278 | g_slist_free (list); |
| 279 | |
| 280 | return g_variant_builder_end (&builder); |
| 281 | } |
| 282 | |
| 283 | static GVariant * |
| 284 | ctk_file_chooser_native_choice_to_variant (CtkFileChooserNativeChoice *choice) |
| 285 | { |
| 286 | GVariantBuilder choices; |
| 287 | int i; |
| 288 | |
| 289 | g_variant_builder_init (&choices, G_VARIANT_TYPE ("a(ss)")(g_variant_type_checked_ (("a(ss)")))); |
| 290 | if (choice->options) |
| 291 | { |
| 292 | for (i = 0; choice->options[i]; i++) |
| 293 | g_variant_builder_add (&choices, "(&s&s)", choice->options[i], choice->option_labels[i]); |
| 294 | } |
| 295 | |
| 296 | return g_variant_new ("(&s&s@a(ss)&s)", |
| 297 | choice->id, |
| 298 | choice->label, |
| 299 | g_variant_builder_end (&choices), |
| 300 | choice->selected ? choice->selected : ""); |
| 301 | } |
| 302 | |
| 303 | static GVariant * |
| 304 | serialize_choices (CtkFileChooserNative *self) |
| 305 | { |
| 306 | GVariantBuilder builder; |
| 307 | GSList *l; |
| 308 | |
| 309 | g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ssa(ss)s)")(g_variant_type_checked_ (("a(ssa(ss)s)")))); |
| 310 | for (l = self->choices; l; l = l->next) |
| 311 | { |
| 312 | CtkFileChooserNativeChoice *choice = l->data; |
| 313 | |
| 314 | g_variant_builder_add (&builder, "@(ssa(ss)s)", |
| 315 | ctk_file_chooser_native_choice_to_variant (choice)); |
| 316 | } |
| 317 | |
| 318 | return g_variant_builder_end (&builder); |
| 319 | } |
| 320 | |
| 321 | static void |
| 322 | show_portal_file_chooser (CtkFileChooserNative *self, |
| 323 | const char *parent_window_str) |
| 324 | { |
| 325 | FilechooserPortalData *data = self->mode_data; |
| 326 | GDBusMessage *message; |
| 327 | GVariantBuilder opt_builder; |
| 328 | gboolean multiple; |
| 329 | gboolean directory; |
| 330 | const char *title; |
| 331 | char *token; |
| 332 | |
| 333 | message = g_dbus_message_new_method_call ("org.freedesktop.portal.Desktop", |
| 334 | "/org/freedesktop/portal/desktop", |
| 335 | "org.freedesktop.portal.FileChooser", |
| 336 | data->method_name); |
| 337 | |
| 338 | data->portal_handle = ctk_get_portal_request_path (data->connection, &token); |
| 339 | data->portal_response_signal_id = |
| 340 | g_dbus_connection_signal_subscribe (data->connection, |
| 341 | "org.freedesktop.portal.Desktop", |
| 342 | "org.freedesktop.portal.Request", |
| 343 | "Response", |
| 344 | data->portal_handle, |
| 345 | NULL((void*)0), |
| 346 | G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE, |
| 347 | response_cb, |
| 348 | self, NULL((void*)0)); |
| 349 | |
| 350 | multiple = ctk_file_chooser_get_select_multiple (CTK_FILE_CHOOSER (self)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((self)), ((ctk_file_chooser_get_type ()))))))); |
| 351 | directory = ctk_file_chooser_get_action (CTK_FILE_CHOOSER (self)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((self)), ((ctk_file_chooser_get_type ()))))))) == CTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; |
| 352 | g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT((const GVariantType *) "a{sv}")); |
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption | |
| 353 | |
| 354 | g_variant_builder_add (&opt_builder, "{sv}", "handle_token", |
| 355 | g_variant_new_string (token)); |
| 356 | g_free (token); |
| 357 | |
| 358 | g_variant_builder_add (&opt_builder, "{sv}", "multiple", |
| 359 | g_variant_new_boolean (multiple)); |
| 360 | g_variant_builder_add (&opt_builder, "{sv}", "directory", |
| 361 | g_variant_new_boolean (directory)); |
| 362 | if (self->accept_label) |
| 363 | g_variant_builder_add (&opt_builder, "{sv}", "accept_label", |
| 364 | g_variant_new_string (self->accept_label)); |
| 365 | if (self->cancel_label) |
| 366 | g_variant_builder_add (&opt_builder, "{sv}", "cancel_label", |
| 367 | g_variant_new_string (self->cancel_label)); |
| 368 | g_variant_builder_add (&opt_builder, "{sv}", "modal", |
| 369 | g_variant_new_boolean (data->modal)); |
| 370 | g_variant_builder_add (&opt_builder, "{sv}", "filters", get_filters (CTK_FILE_CHOOSER (self)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((self)), ((ctk_file_chooser_get_type ())))))))); |
| 371 | if (self->current_filter) |
| 372 | g_variant_builder_add (&opt_builder, "{sv}", "current_filter", |
| 373 | ctk_file_filter_to_gvariant (self->current_filter)); |
| 374 | if (self->current_name) |
| 375 | g_variant_builder_add (&opt_builder, "{sv}", "current_name", |
| 376 | g_variant_new_string (CTK_FILE_CHOOSER_NATIVE (self)->current_name)); |
| 377 | if (self->current_folder) |
| 378 | { |
| 379 | gchar *path; |
| 380 | |
| 381 | path = g_file_get_path (CTK_FILE_CHOOSER_NATIVE (self)->current_folder); |
| 382 | g_variant_builder_add (&opt_builder, "{sv}", "current_folder", |
| 383 | g_variant_new_bytestring (path)); |
| 384 | g_free (path); |
| 385 | } |
| 386 | if (self->current_file) |
| 387 | { |
| 388 | gchar *path; |
| 389 | |
| 390 | path = g_file_get_path (CTK_FILE_CHOOSER_NATIVE (self)->current_file); |
| 391 | g_variant_builder_add (&opt_builder, "{sv}", "current_file", |
| 392 | g_variant_new_bytestring (path)); |
| 393 | g_free (path); |
| 394 | } |
| 395 | |
| 396 | if (self->choices) |
| 397 | g_variant_builder_add (&opt_builder, "{sv}", "choices", |
| 398 | serialize_choices (CTK_FILE_CHOOSER_NATIVE (self))); |
| 399 | |
| 400 | title = ctk_native_dialog_get_title (CTK_NATIVE_DIALOG (self)); |
| 401 | |
| 402 | g_dbus_message_set_body (message, |
| 403 | g_variant_new ("(ss@a{sv})", |
| 404 | parent_window_str ? parent_window_str : "", |
| 405 | title ? title : "", |
| 406 | g_variant_builder_end (&opt_builder))); |
| 407 | |
| 408 | g_dbus_connection_send_message_with_reply (data->connection, |
| 409 | message, |
| 410 | G_DBUS_SEND_MESSAGE_FLAGS_NONE, |
| 411 | G_MAXINT2147483647, |
| 412 | NULL((void*)0), |
| 413 | NULL((void*)0), |
| 414 | open_file_msg_cb, |
| 415 | data); |
| 416 | |
| 417 | g_object_unref (message); |
| 418 | } |
| 419 | |
| 420 | static void |
| 421 | window_handle_exported (CtkWindow *window, |
| 422 | const char *handle_str, |
| 423 | gpointer user_data) |
| 424 | { |
| 425 | CtkFileChooserNative *self = user_data; |
| 426 | FilechooserPortalData *data = self->mode_data; |
| 427 | |
| 428 | if (data->modal) |
| 429 | { |
| 430 | CdkScreen *screen = ctk_widget_get_screen (CTK_WIDGET (window)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((window)), ((ctk_widget_get_type ()))))))); |
| 431 | |
| 432 | data->grab_widget = ctk_invisible_new_for_screen (screen); |
| 433 | ctk_grab_add (CTK_WIDGET (data->grab_widget)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((data->grab_widget)), ((ctk_widget_get_type ()))))))); |
| 434 | } |
| 435 | |
| 436 | show_portal_file_chooser (self, handle_str); |
| 437 | } |
| 438 | |
| 439 | gboolean |
| 440 | ctk_file_chooser_native_portal_show (CtkFileChooserNative *self) |
| 441 | { |
| 442 | FilechooserPortalData *data; |
| 443 | CtkWindow *transient_for; |
| 444 | GDBusConnection *connection; |
| 445 | CtkFileChooserAction action; |
| 446 | const char *method_name; |
| 447 | |
| 448 | if (!ctk_should_use_portal ()) |
| 449 | return FALSE(0); |
| 450 | |
| 451 | connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL((void*)0), NULL((void*)0)); |
| 452 | if (connection == NULL((void*)0)) |
| 453 | return FALSE(0); |
| 454 | |
| 455 | action = ctk_file_chooser_get_action (CTK_FILE_CHOOSER (self)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((self)), ((ctk_file_chooser_get_type ()))))))); |
| 456 | |
| 457 | if (action == CTK_FILE_CHOOSER_ACTION_OPEN) |
| 458 | method_name = "OpenFile"; |
| 459 | else if (action == CTK_FILE_CHOOSER_ACTION_SAVE) |
| 460 | method_name = "SaveFile"; |
| 461 | else if (action == CTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) |
| 462 | { |
| 463 | if (ctk_get_portal_interface_version (connection, "org.freedesktop.portal.FileChooser") < 3) |
| 464 | { |
| 465 | g_warning ("CTK_FILE_CHOOSER_ACTION_SELECT_FOLDER is not supported by CtkFileChooserNativePortal because portal is too old"); |
| 466 | return FALSE(0); |
| 467 | } |
| 468 | method_name = "OpenFile"; |
| 469 | } |
| 470 | else |
| 471 | { |
| 472 | g_warning ("CTK_FILE_CHOOSER_ACTION_CREATE_FOLDER is not supported by CtkFileChooserNativePortal"); |
| 473 | return FALSE(0); |
| 474 | } |
| 475 | |
| 476 | data = g_new0 (FilechooserPortalData, 1)((FilechooserPortalData *) g_malloc0_n ((1), sizeof (FilechooserPortalData ))); |
| 477 | data->self = g_object_ref (self)((__typeof__ (self)) (g_object_ref) (self)); |
| 478 | data->connection = connection; |
| 479 | |
| 480 | data->method_name = method_name; |
| 481 | |
| 482 | if (ctk_native_dialog_get_modal (CTK_NATIVE_DIALOG (self))) |
| 483 | data->modal = TRUE(!(0)); |
| 484 | |
| 485 | self->mode_data = data; |
| 486 | |
| 487 | transient_for = ctk_native_dialog_get_transient_for (CTK_NATIVE_DIALOG (self)); |
| 488 | if (transient_for != NULL((void*)0) && ctk_widget_is_visible (CTK_WIDGET (transient_for)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((transient_for)), ((ctk_widget_get_type ())))))))) |
| 489 | { |
| 490 | if (!ctk_window_export_handle (transient_for, |
| 491 | window_handle_exported, |
| 492 | self)) |
| 493 | { |
| 494 | g_warning ("Failed to export handle, could not set transient for"); |
| 495 | show_portal_file_chooser (self, NULL((void*)0)); |
| 496 | } |
| 497 | else |
| 498 | { |
| 499 | data->exported_window = transient_for; |
| 500 | } |
| 501 | } |
| 502 | else |
| 503 | { |
| 504 | show_portal_file_chooser (self, NULL((void*)0)); |
| 505 | } |
| 506 | |
| 507 | return TRUE(!(0)); |
| 508 | } |
| 509 | |
| 510 | void |
| 511 | ctk_file_chooser_native_portal_hide (CtkFileChooserNative *self) |
| 512 | { |
| 513 | FilechooserPortalData *data = self->mode_data; |
| 514 | |
| 515 | /* This is always set while dialog visible */ |
| 516 | g_assert (data != NULL)do { if (data != ((void*)0)) ; else g_assertion_message_expr ( "Ctk", "ctkfilechoosernativeportal.c", 516, ((const char*) (__func__ )), "data != NULL"); } while (0); |
| 517 | |
| 518 | data->hidden = TRUE(!(0)); |
| 519 | |
| 520 | if (data->portal_handle) |
| 521 | { |
| 522 | send_close (data); |
| 523 | filechooser_portal_data_free (data); |
| 524 | } |
| 525 | |
| 526 | self->mode_data = NULL((void*)0); |
| 527 | } |