File: | ctk/ctkprintoperation-portal.c |
Warning: | line 582, 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 | /* CTK - The GIMP Toolkit |
2 | * ctkprintoperation-portal.c: Print Operation Details for sandboxed apps |
3 | * Copyright (C) 2016, Red Hat, Inc. |
4 | * |
5 | * This library is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU Lesser General Public |
7 | * License as published by the Free Software Foundation; either |
8 | * version 2 of the License, or (at your option) any later version. |
9 | * |
10 | * This library is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | * Lesser General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU Lesser General Public |
16 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
17 | */ |
18 | |
19 | #include "config.h" |
20 | |
21 | #include <string.h> |
22 | |
23 | #include <sys/types.h> |
24 | #include <sys/stat.h> |
25 | #include <fcntl.h> |
26 | |
27 | #include <cairo-pdf.h> |
28 | #include <cairo-ps.h> |
29 | |
30 | #include <gio/gunixfdlist.h> |
31 | |
32 | #include "ctkprintoperation-private.h" |
33 | #include "ctkprintoperation-portal.h" |
34 | #include "ctkprintsettings.h" |
35 | #include "ctkpagesetup.h" |
36 | #include "ctkprintbackend.h" |
37 | #include "ctkshow.h" |
38 | #include "ctkintl.h" |
39 | #include "ctkwindowprivate.h" |
40 | #include "ctkprivate.h" |
41 | |
42 | |
43 | typedef struct { |
44 | CtkPrintOperation *op; |
45 | GDBusProxy *proxy; |
46 | guint response_signal_id; |
47 | gboolean do_print; |
48 | CtkPrintOperationResult result; |
49 | CtkPrintOperationPrintFunc print_cb; |
50 | CtkWindow *parent; |
51 | GMainLoop *loop; |
52 | guint32 token; |
53 | GDestroyNotify destroy; |
54 | GVariant *settings; |
55 | GVariant *setup; |
56 | GVariant *options; |
57 | char *prepare_print_handle; |
58 | } PortalData; |
59 | |
60 | static void |
61 | portal_data_free (gpointer data) |
62 | { |
63 | PortalData *portal = data; |
64 | |
65 | g_object_unref (portal->op); |
66 | g_object_unref (portal->proxy); |
67 | if (portal->loop) |
68 | g_main_loop_unref (portal->loop); |
69 | if (portal->settings) |
70 | g_variant_unref (portal->settings); |
71 | if (portal->setup) |
72 | g_variant_unref (portal->setup); |
73 | if (portal->options) |
74 | g_variant_unref (portal->options); |
75 | g_free (portal->prepare_print_handle); |
76 | g_free (portal); |
77 | } |
78 | |
79 | typedef struct { |
80 | GDBusProxy *proxy; |
81 | CtkPrintJob *job; |
82 | guint32 token; |
83 | cairo_surface_t *surface; |
84 | GMainLoop *loop; |
85 | gboolean file_written; |
86 | } CtkPrintOperationPortal; |
87 | |
88 | static void |
89 | op_portal_free (CtkPrintOperationPortal *op_portal) |
90 | { |
91 | g_clear_object (&op_portal->proxy)do { _Static_assert (sizeof *((&op_portal->proxy)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ ((( &op_portal->proxy))) _pp = ((&op_portal->proxy) ); __typeof__ (*((&op_portal->proxy))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr); } while (0); |
92 | g_clear_object (&op_portal->job)do { _Static_assert (sizeof *((&op_portal->job)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ ((( &op_portal->job))) _pp = ((&op_portal->job)); __typeof__ (*((&op_portal->job))) _ptr = *_pp; *_pp = ((void*)0) ; if (_ptr) (g_object_unref) (_ptr); } while (0); |
93 | if (op_portal->loop) |
94 | g_main_loop_unref (op_portal->loop); |
95 | g_free (op_portal); |
96 | } |
97 | |
98 | static void |
99 | portal_start_page (CtkPrintOperation *op, |
100 | CtkPrintContext *print_context G_GNUC_UNUSED__attribute__ ((__unused__)), |
101 | CtkPageSetup *page_setup) |
102 | { |
103 | CtkPrintOperationPortal *op_portal = op->priv->platform_data; |
104 | CtkPaperSize *paper_size; |
105 | cairo_surface_type_t type; |
106 | gdouble w, h; |
107 | |
108 | paper_size = ctk_page_setup_get_paper_size (page_setup); |
109 | |
110 | w = ctk_paper_size_get_width (paper_size, CTK_UNIT_POINTS); |
111 | h = ctk_paper_size_get_height (paper_size, CTK_UNIT_POINTS); |
112 | |
113 | type = cairo_surface_get_type (op_portal->surface); |
114 | |
115 | if ((op->priv->manual_number_up < 2) || |
116 | (op->priv->page_position % op->priv->manual_number_up == 0)) |
117 | { |
118 | if (type == CAIRO_SURFACE_TYPE_PS) |
119 | { |
120 | cairo_ps_surface_set_size (op_portal->surface, w, h); |
121 | cairo_ps_surface_dsc_begin_page_setup (op_portal->surface); |
122 | switch (ctk_page_setup_get_orientation (page_setup)) |
123 | { |
124 | case CTK_PAGE_ORIENTATION_PORTRAIT: |
125 | case CTK_PAGE_ORIENTATION_REVERSE_PORTRAIT: |
126 | cairo_ps_surface_dsc_comment (op_portal->surface, "%%PageOrientation: Portrait"); |
127 | break; |
128 | |
129 | case CTK_PAGE_ORIENTATION_LANDSCAPE: |
130 | case CTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE: |
131 | cairo_ps_surface_dsc_comment (op_portal->surface, "%%PageOrientation: Landscape"); |
132 | break; |
133 | } |
134 | } |
135 | else if (type == CAIRO_SURFACE_TYPE_PDF) |
136 | { |
137 | if (!op->priv->manual_orientation) |
138 | { |
139 | w = ctk_page_setup_get_paper_width (page_setup, CTK_UNIT_POINTS); |
140 | h = ctk_page_setup_get_paper_height (page_setup, CTK_UNIT_POINTS); |
141 | } |
142 | cairo_pdf_surface_set_size (op_portal->surface, w, h); |
143 | } |
144 | } |
145 | } |
146 | |
147 | static void |
148 | portal_end_page (CtkPrintOperation *op, |
149 | CtkPrintContext *print_context) |
150 | { |
151 | cairo_t *cr; |
152 | |
153 | cr = ctk_print_context_get_cairo_context (print_context); |
154 | |
155 | if ((op->priv->manual_number_up < 2) || |
156 | ((op->priv->page_position + 1) % op->priv->manual_number_up == 0) || |
157 | (op->priv->page_position == op->priv->nr_of_pages_to_print - 1)) |
158 | cairo_show_page (cr); |
159 | } |
160 | |
161 | static void |
162 | print_file_done (GObject *source G_GNUC_UNUSED__attribute__ ((__unused__)), |
163 | GAsyncResult *result, |
164 | gpointer data) |
165 | { |
166 | CtkPrintOperation *op = data; |
167 | CtkPrintOperationPortal *op_portal = op->priv->platform_data; |
168 | GError *error = NULL((void*)0); |
169 | GVariant *ret; |
170 | |
171 | ret = g_dbus_proxy_call_finish (op_portal->proxy, |
172 | result, |
173 | &error); |
174 | if (ret == NULL((void*)0)) |
175 | { |
176 | if (op->priv->error == NULL((void*)0)) |
177 | op->priv->error = g_error_copy (error); |
178 | g_warning ("Print file failed: %s", error->message); |
179 | g_error_free (error); |
180 | } |
181 | else |
182 | g_variant_unref (ret); |
183 | |
184 | if (op_portal->loop) |
185 | g_main_loop_quit (op_portal->loop); |
186 | |
187 | g_object_unref (op); |
188 | } |
189 | |
190 | static void |
191 | portal_job_complete (CtkPrintJob *job, |
192 | gpointer data, |
193 | const GError *error) |
194 | { |
195 | CtkPrintOperation *op = data; |
196 | CtkPrintOperationPortal *op_portal = op->priv->platform_data; |
197 | CtkPrintSettings *settings; |
198 | const char *uri; |
199 | char *filename; |
200 | int fd, idx; |
201 | GVariantBuilder opt_builder; |
202 | GUnixFDList *fd_list; |
203 | |
204 | if (error != NULL((void*)0) && op->priv->error == NULL((void*)0)) |
205 | { |
206 | g_warning ("Print job failed: %s", error->message); |
207 | op->priv->error = g_error_copy (error); |
208 | return; |
209 | } |
210 | |
211 | op_portal->file_written = TRUE(!(0)); |
212 | |
213 | settings = ctk_print_job_get_settings (job); |
214 | uri = ctk_print_settings_get (settings, CTK_PRINT_SETTINGS_OUTPUT_URI"output-uri"); |
215 | filename = g_filename_from_uri (uri, NULL((void*)0), NULL((void*)0)); |
216 | |
217 | fd = open (filename, O_RDONLY00|O_CLOEXEC02000000); |
218 | fd_list = g_unix_fd_list_new (); |
219 | idx = g_unix_fd_list_append (fd_list, fd, NULL((void*)0)); |
220 | close (fd); |
221 | |
222 | g_free (filename); |
223 | |
224 | g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT((const GVariantType *) "a{sv}")); |
225 | g_variant_builder_add (&opt_builder, "{sv}", "token", g_variant_new_uint32 (op_portal->token)); |
226 | |
227 | g_dbus_proxy_call_with_unix_fd_list (op_portal->proxy, |
228 | "Print", |
229 | g_variant_new ("(ssh@a{sv})", |
230 | "", /* window */ |
231 | _("Print")((char *) g_dgettext ("ctk30", "Print")), /* title */ |
232 | idx, |
233 | g_variant_builder_end (&opt_builder)), |
234 | G_DBUS_CALL_FLAGS_NONE, |
235 | -1, |
236 | fd_list, |
237 | NULL((void*)0), |
238 | print_file_done, |
239 | op); |
240 | g_object_unref (fd_list); |
241 | } |
242 | |
243 | static void |
244 | portal_end_run (CtkPrintOperation *op, |
245 | gboolean wait, |
246 | gboolean cancelled) |
247 | { |
248 | CtkPrintOperationPortal *op_portal = op->priv->platform_data; |
249 | |
250 | cairo_surface_finish (op_portal->surface); |
251 | |
252 | if (cancelled) |
253 | return; |
254 | |
255 | if (wait) |
256 | op_portal->loop = g_main_loop_new (NULL((void*)0), FALSE(0)); |
257 | |
258 | /* TODO: Check for error */ |
259 | if (op_portal->job != NULL((void*)0)) |
260 | { |
261 | g_object_ref (op)((__typeof__ (op)) (g_object_ref) (op)); |
262 | ctk_print_job_send (op_portal->job, portal_job_complete, op, NULL((void*)0)); |
263 | } |
264 | |
265 | if (wait) |
266 | { |
267 | g_object_ref (op)((__typeof__ (op)) (g_object_ref) (op)); |
268 | if (!op_portal->file_written) |
269 | { |
270 | cdk_threads_leave (); |
271 | g_main_loop_run (op_portal->loop); |
272 | cdk_threads_enter (); |
273 | } |
274 | g_object_unref (op); |
275 | } |
276 | } |
277 | |
278 | static void |
279 | finish_print (PortalData *portal, |
280 | CtkPrinter *printer, |
281 | CtkPageSetup *page_setup, |
282 | CtkPrintSettings *settings) |
283 | { |
284 | CtkPrintOperation *op = portal->op; |
285 | CtkPrintOperationPrivate *priv = op->priv; |
286 | CtkPrintJob *job; |
287 | CtkPrintOperationPortal *op_portal; |
288 | cairo_t *cr; |
289 | |
290 | if (portal->do_print) |
291 | { |
292 | ctk_print_operation_set_print_settings (op, settings); |
293 | priv->print_context = _ctk_print_context_new (op); |
294 | |
295 | _ctk_print_context_set_hard_margins (priv->print_context, 0, 0, 0, 0); |
296 | |
297 | ctk_print_operation_set_default_page_setup (op, page_setup); |
298 | _ctk_print_context_set_page_setup (priv->print_context, page_setup); |
299 | |
300 | op_portal = g_new0 (CtkPrintOperationPortal, 1)((CtkPrintOperationPortal *) g_malloc0_n ((1), sizeof (CtkPrintOperationPortal ))); |
301 | priv->platform_data = op_portal; |
302 | priv->free_platform_data = (GDestroyNotify) op_portal_free; |
303 | |
304 | priv->start_page = portal_start_page; |
305 | priv->end_page = portal_end_page; |
306 | priv->end_run = portal_end_run; |
307 | |
308 | job = ctk_print_job_new (priv->job_name, printer, settings, page_setup); |
309 | op_portal->job = job; |
310 | |
311 | op_portal->proxy = g_object_ref (portal->proxy)((__typeof__ (portal->proxy)) (g_object_ref) (portal->proxy )); |
312 | op_portal->token = portal->token; |
313 | |
314 | op_portal->surface = ctk_print_job_get_surface (job, &priv->error); |
315 | if (op_portal->surface == NULL((void*)0)) |
316 | { |
317 | portal->result = CTK_PRINT_OPERATION_RESULT_ERROR; |
318 | portal->do_print = FALSE(0); |
319 | goto out; |
320 | } |
321 | |
322 | cr = cairo_create (op_portal->surface); |
323 | ctk_print_context_set_cairo_context (priv->print_context, cr, 72, 72); |
324 | cairo_destroy (cr); |
325 | |
326 | priv->print_pages = ctk_print_job_get_pages (job); |
327 | priv->page_ranges = ctk_print_job_get_page_ranges (job, &priv->num_page_ranges); |
328 | priv->manual_num_copies = ctk_print_job_get_num_copies (job); |
329 | priv->manual_collation = ctk_print_job_get_collate (job); |
330 | priv->manual_reverse = ctk_print_job_get_reverse (job); |
331 | priv->manual_page_set = ctk_print_job_get_page_set (job); |
332 | priv->manual_scale = ctk_print_job_get_scale (job); |
333 | priv->manual_orientation = ctk_print_job_get_rotate (job); |
334 | priv->manual_number_up = ctk_print_job_get_n_up (job); |
335 | priv->manual_number_up_layout = ctk_print_job_get_n_up_layout (job); |
336 | } |
337 | |
338 | out: |
339 | if (portal->print_cb) |
340 | portal->print_cb (op, portal->parent, portal->do_print, portal->result); |
341 | |
342 | if (portal->destroy) |
343 | portal->destroy (portal); |
344 | } |
345 | |
346 | static CtkPrinter * |
347 | find_file_printer (void) |
348 | { |
349 | GList *backends, *l, *printers; |
350 | CtkPrinter *printer; |
351 | |
352 | printer = NULL((void*)0); |
353 | |
354 | backends = ctk_print_backend_load_modules (); |
355 | for (l = backends; l; l = l->next) |
356 | { |
357 | CtkPrintBackend *backend = l->data; |
358 | if (strcmp (G_OBJECT_TYPE_NAME (backend)(g_type_name ((((((GTypeClass*) (((GTypeInstance*) (backend)) ->g_class))->g_type))))), "CtkPrintBackendFile") == 0) |
359 | { |
360 | printers = ctk_print_backend_get_printer_list (backend); |
361 | printer = printers->data; |
362 | g_list_free (printers); |
363 | break; |
364 | } |
365 | } |
366 | g_list_free (backends); |
367 | |
368 | return printer; |
369 | } |
370 | |
371 | static void |
372 | prepare_print_response (GDBusConnection *connection, |
373 | const char *sender_name G_GNUC_UNUSED__attribute__ ((__unused__)), |
374 | const char *object_path G_GNUC_UNUSED__attribute__ ((__unused__)), |
375 | const char *interface_name G_GNUC_UNUSED__attribute__ ((__unused__)), |
376 | const char *signal_name G_GNUC_UNUSED__attribute__ ((__unused__)), |
377 | GVariant *parameters, |
378 | gpointer data) |
379 | { |
380 | PortalData *portal = data; |
381 | guint32 response; |
382 | GVariant *options; |
383 | |
384 | if (portal->response_signal_id != 0) |
385 | { |
386 | g_dbus_connection_signal_unsubscribe (connection, |
387 | portal->response_signal_id); |
388 | portal->response_signal_id = 0; |
389 | } |
390 | |
391 | g_variant_get (parameters, "(u@a{sv})", &response, &options); |
392 | |
393 | portal->do_print = (response == 0); |
394 | |
395 | if (portal->do_print) |
396 | { |
397 | GVariant *v; |
398 | CtkPrintSettings *settings; |
399 | CtkPageSetup *page_setup; |
400 | CtkPrinter *printer; |
401 | char *filename; |
402 | char *uri; |
403 | int fd; |
404 | |
405 | portal->result = CTK_PRINT_OPERATION_RESULT_APPLY; |
406 | |
407 | v = g_variant_lookup_value (options, "settings", G_VARIANT_TYPE_VARDICT((const GVariantType *) "a{sv}")); |
408 | settings = ctk_print_settings_new_from_gvariant (v); |
409 | g_variant_unref (v); |
410 | |
411 | v = g_variant_lookup_value (options, "page-setup", G_VARIANT_TYPE_VARDICT((const GVariantType *) "a{sv}")); |
412 | page_setup = ctk_page_setup_new_from_gvariant (v); |
413 | g_variant_unref (v); |
414 | |
415 | g_variant_lookup (options, "token", "u", &portal->token); |
416 | |
417 | printer = find_file_printer (); |
418 | |
419 | fd = g_file_open_tmp ("ctkprintXXXXXX", &filename, NULL((void*)0)); |
420 | uri = g_filename_to_uri (filename, NULL((void*)0), NULL((void*)0)); |
421 | ctk_print_settings_set (settings, CTK_PRINT_SETTINGS_OUTPUT_URI"output-uri", uri); |
422 | g_free (uri); |
423 | close (fd); |
424 | |
425 | finish_print (portal, printer, page_setup, settings); |
426 | g_free (filename); |
427 | } |
428 | else |
429 | { |
430 | portal->result = CTK_PRINT_OPERATION_RESULT_CANCEL; |
431 | |
432 | if (portal->print_cb) |
433 | portal->print_cb (portal->op, portal->parent, portal->do_print, portal->result); |
434 | |
435 | if (portal->destroy) |
436 | portal->destroy (portal); |
437 | } |
438 | if (portal->loop) |
439 | g_main_loop_quit (portal->loop); |
440 | } |
441 | |
442 | static void |
443 | prepare_print_called (GObject *source G_GNUC_UNUSED__attribute__ ((__unused__)), |
444 | GAsyncResult *result, |
445 | gpointer data) |
446 | { |
447 | PortalData *portal = data; |
448 | GError *error = NULL((void*)0); |
449 | const char *handle = NULL((void*)0); |
450 | GVariant *ret; |
451 | |
452 | ret = g_dbus_proxy_call_finish (portal->proxy, result, &error); |
453 | if (ret == NULL((void*)0)) |
454 | { |
455 | if (portal->op->priv->error == NULL((void*)0)) |
456 | portal->op->priv->error = g_error_copy (error); |
457 | g_error_free (error); |
458 | if (portal->loop) |
459 | g_main_loop_quit (portal->loop); |
460 | return; |
461 | } |
462 | else |
463 | g_variant_get (ret, "(&o)", &handle); |
464 | |
465 | if (strcmp (portal->prepare_print_handle, handle) != 0) |
466 | { |
467 | g_free (portal->prepare_print_handle); |
468 | portal->prepare_print_handle = g_strdup (handle)g_strdup_inline (handle); |
469 | g_dbus_connection_signal_unsubscribe (g_dbus_proxy_get_connection (G_DBUS_PROXY (portal->proxy)((((GDBusProxy*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((portal->proxy)), ((g_dbus_proxy_get_type ()))))))), |
470 | portal->response_signal_id); |
471 | portal->response_signal_id = |
472 | g_dbus_connection_signal_subscribe (g_dbus_proxy_get_connection (G_DBUS_PROXY (portal->proxy)((((GDBusProxy*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((portal->proxy)), ((g_dbus_proxy_get_type ()))))))), |
473 | "org.freedesktop.portal.Desktop", |
474 | "org.freedesktop.portal.Request", |
475 | "Response", |
476 | handle, |
477 | NULL((void*)0), |
478 | G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE, |
479 | prepare_print_response, |
480 | portal, NULL((void*)0)); |
481 | } |
482 | |
483 | g_variant_unref (ret); |
484 | } |
485 | |
486 | PortalData * |
487 | create_portal_data (CtkPrintOperation *op, |
488 | CtkWindow *parent, |
489 | CtkPrintOperationPrintFunc print_cb) |
490 | { |
491 | GDBusProxy *proxy; |
492 | PortalData *portal; |
493 | guint signal_id; |
494 | GError *error = NULL((void*)0); |
495 | |
496 | signal_id = g_signal_lookup ("create-custom-widget", CTK_TYPE_PRINT_OPERATION(ctk_print_operation_get_type ())); |
497 | if (g_signal_has_handler_pending (op, signal_id, 0, TRUE(!(0)))) |
498 | g_warning ("CtkPrintOperation::create-custom-widget not supported with portal"); |
499 | |
500 | proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, |
501 | G_DBUS_PROXY_FLAGS_NONE, |
502 | NULL((void*)0), |
503 | "org.freedesktop.portal.Desktop", |
504 | "/org/freedesktop/portal/desktop", |
505 | "org.freedesktop.portal.Print", |
506 | NULL((void*)0), |
507 | &error); |
508 | |
509 | if (proxy == NULL((void*)0)) |
510 | { |
511 | if (op->priv->error == NULL((void*)0)) |
512 | op->priv->error = g_error_copy (error); |
513 | g_error_free (error); |
514 | return NULL((void*)0); |
515 | } |
516 | |
517 | portal = g_new0 (PortalData, 1)((PortalData *) g_malloc0_n ((1), sizeof (PortalData))); |
518 | portal->proxy = proxy; |
519 | portal->op = g_object_ref (op)((__typeof__ (op)) (g_object_ref) (op)); |
520 | portal->parent = parent; |
521 | portal->result = CTK_PRINT_OPERATION_RESULT_CANCEL; |
522 | portal->print_cb = print_cb; |
523 | |
524 | if (print_cb) /* async case */ |
525 | { |
526 | portal->loop = NULL((void*)0); |
527 | portal->destroy = portal_data_free; |
528 | } |
529 | else |
530 | { |
531 | portal->loop = g_main_loop_new (NULL((void*)0), FALSE(0)); |
532 | portal->destroy = NULL((void*)0); |
533 | } |
534 | |
535 | return portal; |
536 | } |
537 | |
538 | static void |
539 | window_handle_exported (CtkWindow *window G_GNUC_UNUSED__attribute__ ((__unused__)), |
540 | const char *handle_str, |
541 | gpointer user_data) |
542 | { |
543 | PortalData *portal = user_data; |
544 | |
545 | g_dbus_proxy_call (portal->proxy, |
546 | "PreparePrint", |
547 | g_variant_new ("(ss@a{sv}@a{sv}@a{sv})", |
548 | handle_str, |
549 | _("Print")((char *) g_dgettext ("ctk30", "Print")), /* title */ |
550 | portal->settings, |
551 | portal->setup, |
552 | portal->options), |
553 | G_DBUS_CALL_FLAGS_NONE, |
554 | -1, |
555 | NULL((void*)0), |
556 | prepare_print_called, |
557 | portal); |
558 | } |
559 | |
560 | static void |
561 | call_prepare_print (CtkPrintOperation *op, |
562 | PortalData *portal) |
563 | { |
564 | CtkPrintOperationPrivate *priv = op->priv; |
565 | GVariantBuilder opt_builder; |
566 | char *token; |
567 | |
568 | portal->prepare_print_handle = |
569 | ctk_get_portal_request_path (g_dbus_proxy_get_connection (portal->proxy), &token); |
570 | |
571 | portal->response_signal_id = |
572 | g_dbus_connection_signal_subscribe (g_dbus_proxy_get_connection (G_DBUS_PROXY (portal->proxy)((((GDBusProxy*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((portal->proxy)), ((g_dbus_proxy_get_type ()))))))), |
573 | "org.freedesktop.portal.Desktop", |
574 | "org.freedesktop.portal.Request", |
575 | "Response", |
576 | portal->prepare_print_handle, |
577 | NULL((void*)0), |
578 | G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE, |
579 | prepare_print_response, |
580 | portal, NULL((void*)0)); |
581 | |
582 | 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 | |
583 | g_variant_builder_add (&opt_builder, "{sv}", "handle_token", g_variant_new_string (token)); |
584 | g_free (token); |
585 | portal->options = g_variant_builder_end (&opt_builder); |
586 | |
587 | if (priv->print_settings) |
588 | portal->settings = ctk_print_settings_to_gvariant (priv->print_settings); |
589 | else |
590 | { |
591 | GVariantBuilder builder; |
592 | g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT((const GVariantType *) "a{sv}")); |
593 | portal->settings = g_variant_builder_end (&builder); |
594 | } |
595 | |
596 | if (priv->default_page_setup) |
597 | portal->setup = ctk_page_setup_to_gvariant (priv->default_page_setup); |
598 | else |
599 | { |
600 | CtkPageSetup *page_setup = ctk_page_setup_new (); |
601 | portal->setup = ctk_page_setup_to_gvariant (page_setup); |
602 | g_object_unref (page_setup); |
603 | } |
604 | |
605 | g_variant_ref_sink (portal->options); |
606 | g_variant_ref_sink (portal->settings); |
607 | g_variant_ref_sink (portal->setup); |
608 | |
609 | if (portal->parent != NULL((void*)0) && |
610 | ctk_widget_is_visible (CTK_WIDGET (portal->parent)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((portal->parent)), ((ctk_widget_get_type ()))))))) && |
611 | ctk_window_export_handle (portal->parent, window_handle_exported, portal)) |
612 | return; |
613 | |
614 | g_dbus_proxy_call (portal->proxy, |
615 | "PreparePrint", |
616 | g_variant_new ("(ss@a{sv}@a{sv}@a{sv})", |
617 | "", |
618 | _("Print")((char *) g_dgettext ("ctk30", "Print")), /* title */ |
619 | portal->settings, |
620 | portal->setup, |
621 | portal->options), |
622 | G_DBUS_CALL_FLAGS_NONE, |
623 | -1, |
624 | NULL((void*)0), |
625 | prepare_print_called, |
626 | portal); |
627 | } |
628 | |
629 | CtkPrintOperationResult |
630 | ctk_print_operation_portal_run_dialog (CtkPrintOperation *op, |
631 | gboolean show_dialog G_GNUC_UNUSED__attribute__ ((__unused__)), |
632 | CtkWindow *parent, |
633 | gboolean *do_print) |
634 | { |
635 | PortalData *portal; |
636 | CtkPrintOperationResult result; |
637 | |
638 | portal = create_portal_data (op, parent, NULL((void*)0)); |
639 | if (portal == NULL((void*)0)) |
640 | return CTK_PRINT_OPERATION_RESULT_ERROR; |
641 | |
642 | call_prepare_print (op, portal); |
643 | |
644 | cdk_threads_leave (); |
645 | g_main_loop_run (portal->loop); |
646 | cdk_threads_enter (); |
647 | |
648 | *do_print = portal->do_print; |
649 | result = portal->result; |
650 | |
651 | portal_data_free (portal); |
652 | |
653 | return result; |
654 | } |
655 | |
656 | void |
657 | ctk_print_operation_portal_run_dialog_async (CtkPrintOperation *op, |
658 | gboolean show_dialog G_GNUC_UNUSED__attribute__ ((__unused__)), |
659 | CtkWindow *parent, |
660 | CtkPrintOperationPrintFunc print_cb) |
661 | { |
662 | PortalData *portal; |
663 | |
664 | portal = create_portal_data (op, parent, print_cb); |
665 | if (portal == NULL((void*)0)) |
666 | return; |
667 | |
668 | call_prepare_print (op, portal); |
669 | } |
670 | |
671 | void |
672 | ctk_print_operation_portal_launch_preview (CtkPrintOperation *op G_GNUC_UNUSED__attribute__ ((__unused__)), |
673 | cairo_surface_t *surface G_GNUC_UNUSED__attribute__ ((__unused__)), |
674 | CtkWindow *parent, |
675 | const char *filename) |
676 | { |
677 | char *uri; |
678 | |
679 | uri = g_filename_to_uri (filename, NULL((void*)0), NULL((void*)0)); |
680 | ctk_show_uri_on_window (parent, uri, CDK_CURRENT_TIME0L, NULL((void*)0)); |
681 | g_free (uri); |
682 | } |