1 | /* GTK - The GIMP Toolkit |
2 | * gtkprintoperation-unix.c: Print Operation Details for Unix |
3 | * and Unix-like platforms |
4 | * Copyright (C) 2006, 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 | #ifdef HAVE_UNISTD_H |
22 | #include <unistd.h> |
23 | #endif |
24 | #include <sys/types.h> |
25 | #include <sys/stat.h> |
26 | #include <string.h> |
27 | #include <errno.h> |
28 | #include <stdlib.h> |
29 | #include <fcntl.h> |
30 | |
31 | #include <glib/gstdio.h> |
32 | #include "gtkprintoperation-private.h" |
33 | #include "gtkprintoperation-portal.h" |
34 | #include "gtkmessagedialog.h" |
35 | |
36 | #include <cairo-pdf.h> |
37 | #include <cairo-ps.h> |
38 | #include "gtkprivate.h" |
39 | #include "gtkprintunixdialog.h" |
40 | #include "gtkpagesetupunixdialog.h" |
41 | #include "gtkprintbackendprivate.h" |
42 | #include "gtkprinter.h" |
43 | #include "gtkprintjob.h" |
44 | #include "gtklabel.h" |
45 | #include "gtkintl.h" |
46 | |
47 | |
48 | typedef struct |
49 | { |
50 | GtkWindow *parent; /* just in case we need to throw error dialogs */ |
51 | GMainLoop *loop; |
52 | gboolean data_sent; |
53 | |
54 | /* Real printing (not preview) */ |
55 | GtkPrintJob *job; /* the job we are sending to the printer */ |
56 | cairo_surface_t *surface; |
57 | gulong job_status_changed_tag; |
58 | |
59 | |
60 | } GtkPrintOperationUnix; |
61 | |
62 | typedef struct _PrinterFinder PrinterFinder; |
63 | |
64 | static void printer_finder_free (PrinterFinder *finder); |
65 | static void find_printer (const char *printer, |
66 | GFunc func, |
67 | gpointer data); |
68 | |
69 | static void |
70 | unix_start_page (GtkPrintOperation *op, |
71 | GtkPrintContext *print_context, |
72 | GtkPageSetup *page_setup) |
73 | { |
74 | GtkPrintOperationUnix *op_unix; |
75 | GtkPaperSize *paper_size; |
76 | cairo_surface_type_t type; |
77 | double w, h; |
78 | |
79 | op_unix = op->priv->platform_data; |
80 | |
81 | paper_size = gtk_page_setup_get_paper_size (setup: page_setup); |
82 | |
83 | w = gtk_paper_size_get_width (size: paper_size, unit: GTK_UNIT_POINTS); |
84 | h = gtk_paper_size_get_height (size: paper_size, unit: GTK_UNIT_POINTS); |
85 | |
86 | type = cairo_surface_get_type (surface: op_unix->surface); |
87 | |
88 | if ((op->priv->manual_number_up < 2) || |
89 | (op->priv->page_position % op->priv->manual_number_up == 0)) |
90 | { |
91 | if (type == CAIRO_SURFACE_TYPE_PS) |
92 | { |
93 | cairo_ps_surface_set_size (surface: op_unix->surface, width_in_points: w, height_in_points: h); |
94 | cairo_ps_surface_dsc_begin_page_setup (surface: op_unix->surface); |
95 | switch (gtk_page_setup_get_orientation (setup: page_setup)) |
96 | { |
97 | case GTK_PAGE_ORIENTATION_PORTRAIT: |
98 | case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT: |
99 | cairo_ps_surface_dsc_comment (surface: op_unix->surface, comment: "%%PageOrientation: Portrait" ); |
100 | break; |
101 | |
102 | case GTK_PAGE_ORIENTATION_LANDSCAPE: |
103 | case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE: |
104 | cairo_ps_surface_dsc_comment (surface: op_unix->surface, comment: "%%PageOrientation: Landscape" ); |
105 | break; |
106 | default: |
107 | break; |
108 | } |
109 | } |
110 | else if (type == CAIRO_SURFACE_TYPE_PDF) |
111 | { |
112 | if (!op->priv->manual_orientation) |
113 | { |
114 | w = gtk_page_setup_get_paper_width (setup: page_setup, unit: GTK_UNIT_POINTS); |
115 | h = gtk_page_setup_get_paper_height (setup: page_setup, unit: GTK_UNIT_POINTS); |
116 | } |
117 | cairo_pdf_surface_set_size (surface: op_unix->surface, width_in_points: w, height_in_points: h); |
118 | } |
119 | } |
120 | } |
121 | |
122 | static void |
123 | unix_end_page (GtkPrintOperation *op, |
124 | GtkPrintContext *print_context) |
125 | { |
126 | cairo_t *cr; |
127 | |
128 | cr = gtk_print_context_get_cairo_context (context: print_context); |
129 | |
130 | if ((op->priv->manual_number_up < 2) || |
131 | ((op->priv->page_position + 1) % op->priv->manual_number_up == 0) || |
132 | (op->priv->page_position == op->priv->nr_of_pages_to_print - 1)) |
133 | cairo_show_page (cr); |
134 | } |
135 | |
136 | static void |
137 | op_unix_free (GtkPrintOperationUnix *op_unix) |
138 | { |
139 | if (op_unix->job) |
140 | { |
141 | if (op_unix->job_status_changed_tag > 0) |
142 | g_signal_handler_disconnect (instance: op_unix->job, |
143 | handler_id: op_unix->job_status_changed_tag); |
144 | g_object_unref (object: op_unix->job); |
145 | } |
146 | |
147 | g_free (mem: op_unix); |
148 | } |
149 | |
150 | static char * |
151 | shell_command_substitute_file (const char *cmd, |
152 | const char *pdf_filename, |
153 | const char *settings_filename, |
154 | gboolean *pdf_filename_replaced, |
155 | gboolean *settings_filename_replaced) |
156 | { |
157 | const char *inptr, *start; |
158 | GString *final; |
159 | |
160 | g_return_val_if_fail (cmd != NULL, NULL); |
161 | g_return_val_if_fail (pdf_filename != NULL, NULL); |
162 | g_return_val_if_fail (settings_filename != NULL, NULL); |
163 | |
164 | final = g_string_new (NULL); |
165 | |
166 | *pdf_filename_replaced = FALSE; |
167 | *settings_filename_replaced = FALSE; |
168 | |
169 | start = inptr = cmd; |
170 | while ((inptr = strchr (s: inptr, c: '%')) != NULL) |
171 | { |
172 | g_string_append_len (string: final, val: start, len: inptr - start); |
173 | inptr++; |
174 | switch (*inptr) |
175 | { |
176 | case 'f': |
177 | g_string_append (string: final, val: pdf_filename); |
178 | *pdf_filename_replaced = TRUE; |
179 | break; |
180 | |
181 | case 's': |
182 | g_string_append (string: final, val: settings_filename); |
183 | *settings_filename_replaced = TRUE; |
184 | break; |
185 | |
186 | case '%': |
187 | g_string_append_c (final, '%'); |
188 | break; |
189 | |
190 | default: |
191 | g_string_append_c (final, '%'); |
192 | if (*inptr) |
193 | g_string_append_c (final, *inptr); |
194 | break; |
195 | } |
196 | if (*inptr) |
197 | inptr++; |
198 | start = inptr; |
199 | } |
200 | g_string_append (string: final, val: start); |
201 | |
202 | return g_string_free (string: final, FALSE); |
203 | } |
204 | |
205 | static void |
206 | gtk_print_operation_unix_launch_preview (GtkPrintOperation *op, |
207 | cairo_surface_t *surface, |
208 | GtkWindow *parent, |
209 | const char *filename) |
210 | { |
211 | GAppInfo *appinfo; |
212 | GdkAppLaunchContext *context; |
213 | char *cmd; |
214 | char *preview_cmd; |
215 | GtkSettings *settings; |
216 | GtkPrintSettings *print_settings = NULL; |
217 | GtkPageSetup *page_setup; |
218 | GKeyFile *key_file = NULL; |
219 | char *data = NULL; |
220 | gsize data_len; |
221 | char *settings_filename = NULL; |
222 | char *quoted_filename; |
223 | char *quoted_settings_filename; |
224 | gboolean filename_used = FALSE; |
225 | gboolean settings_used = FALSE; |
226 | GdkDisplay *display; |
227 | GError *error = NULL; |
228 | int fd; |
229 | gboolean retval; |
230 | |
231 | cairo_surface_destroy (surface); |
232 | |
233 | if (parent) |
234 | display = gtk_widget_get_display (GTK_WIDGET (parent)); |
235 | else |
236 | display = gdk_display_get_default (); |
237 | |
238 | fd = g_file_open_tmp (tmpl: "settingsXXXXXX.ini" , name_used: &settings_filename, error: &error); |
239 | if (fd < 0) |
240 | goto out; |
241 | |
242 | key_file = g_key_file_new (); |
243 | |
244 | print_settings = gtk_print_settings_copy (other: gtk_print_operation_get_print_settings (op)); |
245 | |
246 | if (print_settings != NULL) |
247 | { |
248 | gtk_print_settings_set_reverse (settings: print_settings, FALSE); |
249 | gtk_print_settings_set_page_set (settings: print_settings, page_set: GTK_PAGE_SET_ALL); |
250 | gtk_print_settings_set_scale (settings: print_settings, scale: 1.0); |
251 | gtk_print_settings_set_number_up (settings: print_settings, number_up: 1); |
252 | gtk_print_settings_set_number_up_layout (settings: print_settings, number_up_layout: GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM); |
253 | |
254 | /* These removals are necessary because cups-* settings have higher priority |
255 | * than normal settings. |
256 | */ |
257 | gtk_print_settings_unset (settings: print_settings, key: "cups-reverse" ); |
258 | gtk_print_settings_unset (settings: print_settings, key: "cups-page-set" ); |
259 | gtk_print_settings_unset (settings: print_settings, key: "cups-scale" ); |
260 | gtk_print_settings_unset (settings: print_settings, key: "cups-number-up" ); |
261 | gtk_print_settings_unset (settings: print_settings, key: "cups-number-up-layout" ); |
262 | |
263 | gtk_print_settings_to_key_file (settings: print_settings, key_file, NULL); |
264 | g_object_unref (object: print_settings); |
265 | } |
266 | |
267 | page_setup = gtk_print_context_get_page_setup (context: op->priv->print_context); |
268 | gtk_page_setup_to_key_file (setup: page_setup, key_file, NULL); |
269 | |
270 | g_key_file_set_string (key_file, group_name: "Print Job" , key: "title" , string: op->priv->job_name); |
271 | |
272 | data = g_key_file_to_data (key_file, length: &data_len, error: &error); |
273 | if (!data) |
274 | goto out; |
275 | |
276 | retval = g_file_set_contents (filename: settings_filename, contents: data, length: data_len, error: &error); |
277 | if (!retval) |
278 | goto out; |
279 | |
280 | settings = gtk_settings_get_for_display (display); |
281 | g_object_get (object: settings, first_property_name: "gtk-print-preview-command" , &preview_cmd, NULL); |
282 | |
283 | quoted_filename = g_shell_quote (unquoted_string: filename); |
284 | quoted_settings_filename = g_shell_quote (unquoted_string: settings_filename); |
285 | cmd = shell_command_substitute_file (cmd: preview_cmd, pdf_filename: quoted_filename, settings_filename: quoted_settings_filename, pdf_filename_replaced: &filename_used, settings_filename_replaced: &settings_used); |
286 | |
287 | appinfo = g_app_info_create_from_commandline (commandline: cmd, |
288 | application_name: "Print Preview" , |
289 | flags: G_APP_INFO_CREATE_NONE, |
290 | error: &error); |
291 | |
292 | g_free (mem: preview_cmd); |
293 | g_free (mem: quoted_filename); |
294 | g_free (mem: quoted_settings_filename); |
295 | g_free (mem: cmd); |
296 | |
297 | if (error != NULL) |
298 | goto out; |
299 | |
300 | context = gdk_display_get_app_launch_context (display); |
301 | g_app_info_launch (appinfo, NULL, G_APP_LAUNCH_CONTEXT (context), error: &error); |
302 | |
303 | g_object_unref (object: context); |
304 | g_object_unref (object: appinfo); |
305 | |
306 | if (error != NULL) |
307 | { |
308 | char * uri; |
309 | |
310 | g_warning ("Error launching preview: %s" , error->message); |
311 | |
312 | g_error_free (error); |
313 | error = NULL; |
314 | uri = g_filename_to_uri (filename, NULL, NULL); |
315 | gtk_show_uri (parent, uri, GDK_CURRENT_TIME); |
316 | g_free (mem: uri); |
317 | } |
318 | |
319 | out: |
320 | if (error != NULL) |
321 | { |
322 | if (op->priv->error == NULL) |
323 | op->priv->error = error; |
324 | else |
325 | g_error_free (error); |
326 | |
327 | filename_used = FALSE; |
328 | settings_used = FALSE; |
329 | } |
330 | |
331 | if (!filename_used) |
332 | g_unlink (filename); |
333 | |
334 | if (!settings_used) |
335 | g_unlink (filename: settings_filename); |
336 | |
337 | if (fd > 0) |
338 | close (fd: fd); |
339 | |
340 | if (key_file) |
341 | g_key_file_free (key_file); |
342 | g_free (mem: data); |
343 | g_free (mem: settings_filename); |
344 | } |
345 | |
346 | static void |
347 | unix_finish_send (GtkPrintJob *job, |
348 | gpointer user_data, |
349 | const GError *error) |
350 | { |
351 | GtkPrintOperation *op = (GtkPrintOperation *) user_data; |
352 | GtkPrintOperationUnix *op_unix = op->priv->platform_data; |
353 | |
354 | if (error != NULL && op->priv->error == NULL) |
355 | op->priv->error = g_error_copy (error); |
356 | |
357 | op_unix->data_sent = TRUE; |
358 | |
359 | if (op_unix->loop) |
360 | g_main_loop_quit (loop: op_unix->loop); |
361 | |
362 | g_object_unref (object: op); |
363 | } |
364 | |
365 | static void |
366 | unix_end_run (GtkPrintOperation *op, |
367 | gboolean wait, |
368 | gboolean cancelled) |
369 | { |
370 | GtkPrintOperationUnix *op_unix = op->priv->platform_data; |
371 | |
372 | cairo_surface_finish (surface: op_unix->surface); |
373 | |
374 | if (cancelled) |
375 | return; |
376 | |
377 | if (wait) |
378 | op_unix->loop = g_main_loop_new (NULL, FALSE); |
379 | |
380 | /* TODO: Check for error */ |
381 | if (op_unix->job != NULL) |
382 | { |
383 | g_object_ref (op); |
384 | gtk_print_job_send (job: op_unix->job, |
385 | callback: unix_finish_send, |
386 | user_data: op, NULL); |
387 | } |
388 | |
389 | if (wait) |
390 | { |
391 | g_object_ref (op); |
392 | if (!op_unix->data_sent) |
393 | g_main_loop_run (loop: op_unix->loop); |
394 | g_main_loop_unref (loop: op_unix->loop); |
395 | op_unix->loop = NULL; |
396 | g_object_unref (object: op); |
397 | } |
398 | } |
399 | |
400 | static void |
401 | job_status_changed_cb (GtkPrintJob *job, |
402 | GtkPrintOperation *op) |
403 | { |
404 | _gtk_print_operation_set_status (op, status: gtk_print_job_get_status (job), NULL); |
405 | } |
406 | |
407 | |
408 | static void |
409 | print_setup_changed_cb (GtkPrintUnixDialog *print_dialog, |
410 | GParamSpec *pspec, |
411 | gpointer user_data) |
412 | { |
413 | GtkPageSetup *page_setup; |
414 | GtkPrintSettings *print_settings; |
415 | GtkPrintOperation *op = user_data; |
416 | GtkPrintOperationPrivate *priv = op->priv; |
417 | |
418 | page_setup = gtk_print_unix_dialog_get_page_setup (dialog: print_dialog); |
419 | print_settings = gtk_print_unix_dialog_get_settings (dialog: print_dialog); |
420 | |
421 | g_signal_emit_by_name (instance: op, |
422 | detailed_signal: "update-custom-widget" , |
423 | priv->custom_widget, |
424 | page_setup, |
425 | print_settings); |
426 | } |
427 | |
428 | static GtkWidget * |
429 | get_print_dialog (GtkPrintOperation *op, |
430 | GtkWindow *parent) |
431 | { |
432 | GtkPrintOperationPrivate *priv = op->priv; |
433 | GtkWidget *pd, *label; |
434 | const char *custom_tab_label; |
435 | |
436 | pd = gtk_print_unix_dialog_new (NULL, parent); |
437 | |
438 | gtk_print_unix_dialog_set_manual_capabilities (GTK_PRINT_UNIX_DIALOG (pd), |
439 | capabilities: GTK_PRINT_CAPABILITY_PAGE_SET | |
440 | GTK_PRINT_CAPABILITY_COPIES | |
441 | GTK_PRINT_CAPABILITY_COLLATE | |
442 | GTK_PRINT_CAPABILITY_REVERSE | |
443 | GTK_PRINT_CAPABILITY_SCALE | |
444 | GTK_PRINT_CAPABILITY_PREVIEW | |
445 | GTK_PRINT_CAPABILITY_NUMBER_UP | |
446 | GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT); |
447 | |
448 | if (priv->print_settings) |
449 | gtk_print_unix_dialog_set_settings (GTK_PRINT_UNIX_DIALOG (pd), |
450 | settings: priv->print_settings); |
451 | |
452 | if (priv->default_page_setup) |
453 | gtk_print_unix_dialog_set_page_setup (GTK_PRINT_UNIX_DIALOG (pd), |
454 | page_setup: priv->default_page_setup); |
455 | |
456 | gtk_print_unix_dialog_set_embed_page_setup (GTK_PRINT_UNIX_DIALOG (pd), |
457 | embed: priv->embed_page_setup); |
458 | |
459 | gtk_print_unix_dialog_set_current_page (GTK_PRINT_UNIX_DIALOG (pd), |
460 | current_page: priv->current_page); |
461 | |
462 | gtk_print_unix_dialog_set_support_selection (GTK_PRINT_UNIX_DIALOG (pd), |
463 | support_selection: priv->support_selection); |
464 | |
465 | gtk_print_unix_dialog_set_has_selection (GTK_PRINT_UNIX_DIALOG (pd), |
466 | has_selection: priv->has_selection); |
467 | |
468 | g_signal_emit_by_name (instance: op, detailed_signal: "create-custom-widget" , |
469 | &priv->custom_widget); |
470 | |
471 | if (priv->custom_widget) |
472 | { |
473 | custom_tab_label = priv->custom_tab_label; |
474 | |
475 | if (custom_tab_label == NULL) |
476 | { |
477 | custom_tab_label = g_get_application_name (); |
478 | if (custom_tab_label == NULL) |
479 | custom_tab_label = _("Application" ); |
480 | } |
481 | |
482 | label = gtk_label_new (str: custom_tab_label); |
483 | |
484 | gtk_print_unix_dialog_add_custom_tab (GTK_PRINT_UNIX_DIALOG (pd), |
485 | child: priv->custom_widget, tab_label: label); |
486 | |
487 | g_signal_connect (pd, "notify::selected-printer" , (GCallback) print_setup_changed_cb, op); |
488 | g_signal_connect (pd, "notify::page-setup" , (GCallback) print_setup_changed_cb, op); |
489 | } |
490 | |
491 | return pd; |
492 | } |
493 | |
494 | typedef struct |
495 | { |
496 | GtkPrintOperation *op; |
497 | gboolean do_print; |
498 | gboolean do_preview; |
499 | GtkPrintOperationResult result; |
500 | GtkPrintOperationPrintFunc print_cb; |
501 | GDestroyNotify destroy; |
502 | GtkWindow *parent; |
503 | GMainLoop *loop; |
504 | } PrintResponseData; |
505 | |
506 | static void |
507 | print_response_data_free (gpointer data) |
508 | { |
509 | PrintResponseData *rdata = data; |
510 | |
511 | g_object_unref (object: rdata->op); |
512 | g_free (mem: rdata); |
513 | } |
514 | |
515 | static void |
516 | finish_print (PrintResponseData *rdata, |
517 | GtkPrinter *printer, |
518 | GtkPageSetup *page_setup, |
519 | GtkPrintSettings *settings, |
520 | gboolean page_setup_set) |
521 | { |
522 | GtkPrintOperation *op = rdata->op; |
523 | GtkPrintOperationPrivate *priv = op->priv; |
524 | GtkPrintJob *job; |
525 | double top, bottom, left, right; |
526 | |
527 | if (rdata->do_print) |
528 | { |
529 | gtk_print_operation_set_print_settings (op, print_settings: settings); |
530 | priv->print_context = _gtk_print_context_new (op); |
531 | |
532 | if (gtk_print_settings_get_number_up (settings) < 2) |
533 | { |
534 | if (printer && (gtk_printer_get_hard_margins_for_paper_size (printer, paper_size: gtk_page_setup_get_paper_size (setup: page_setup), top: &top, bottom: &bottom, left: &left, right: &right) || |
535 | gtk_printer_get_hard_margins (printer, top: &top, bottom: &bottom, left: &left, right: &right))) |
536 | _gtk_print_context_set_hard_margins (context: priv->print_context, top, bottom, left, right); |
537 | } |
538 | else |
539 | { |
540 | /* Pages do not have any unprintable area when printing n-up as each page on the |
541 | * sheet has been scaled down and translated to a position within the printable |
542 | * area of the sheet. |
543 | */ |
544 | _gtk_print_context_set_hard_margins (context: priv->print_context, top: 0, bottom: 0, left: 0, right: 0); |
545 | } |
546 | |
547 | if (page_setup != NULL && |
548 | (gtk_print_operation_get_default_page_setup (op) == NULL || |
549 | page_setup_set)) |
550 | gtk_print_operation_set_default_page_setup (op, default_page_setup: page_setup); |
551 | |
552 | _gtk_print_context_set_page_setup (context: priv->print_context, page_setup); |
553 | |
554 | if (!rdata->do_preview) |
555 | { |
556 | GtkPrintOperationUnix *op_unix; |
557 | cairo_t *cr; |
558 | |
559 | op_unix = g_new0 (GtkPrintOperationUnix, 1); |
560 | priv->platform_data = op_unix; |
561 | priv->free_platform_data = (GDestroyNotify) op_unix_free; |
562 | op_unix->parent = rdata->parent; |
563 | |
564 | priv->start_page = unix_start_page; |
565 | priv->end_page = unix_end_page; |
566 | priv->end_run = unix_end_run; |
567 | |
568 | job = gtk_print_job_new (title: priv->job_name, printer, settings, page_setup); |
569 | op_unix->job = job; |
570 | gtk_print_job_set_track_print_status (job, track_status: priv->track_print_status); |
571 | |
572 | op_unix->surface = gtk_print_job_get_surface (job, error: &priv->error); |
573 | if (op_unix->surface == NULL) |
574 | { |
575 | rdata->result = GTK_PRINT_OPERATION_RESULT_ERROR; |
576 | rdata->do_print = FALSE; |
577 | goto out; |
578 | } |
579 | |
580 | cr = cairo_create (target: op_unix->surface); |
581 | gtk_print_context_set_cairo_context (context: priv->print_context, cr, dpi_x: 72, dpi_y: 72); |
582 | cairo_destroy (cr); |
583 | |
584 | _gtk_print_operation_set_status (op, status: gtk_print_job_get_status (job), NULL); |
585 | |
586 | op_unix->job_status_changed_tag = |
587 | g_signal_connect (job, "status-changed" , |
588 | G_CALLBACK (job_status_changed_cb), op); |
589 | |
590 | priv->print_pages = gtk_print_job_get_pages (job); |
591 | priv->page_ranges = gtk_print_job_get_page_ranges (job, n_ranges: &priv->num_page_ranges); |
592 | priv->manual_num_copies = gtk_print_job_get_num_copies (job); |
593 | priv->manual_collation = gtk_print_job_get_collate (job); |
594 | priv->manual_reverse = gtk_print_job_get_reverse (job); |
595 | priv->manual_page_set = gtk_print_job_get_page_set (job); |
596 | priv->manual_scale = gtk_print_job_get_scale (job); |
597 | priv->manual_orientation = gtk_print_job_get_rotate (job); |
598 | priv->manual_number_up = gtk_print_job_get_n_up (job); |
599 | priv->manual_number_up_layout = gtk_print_job_get_n_up_layout (job); |
600 | } |
601 | } |
602 | out: |
603 | if (rdata->print_cb) |
604 | rdata->print_cb (op, rdata->parent, rdata->do_print, rdata->result); |
605 | |
606 | if (rdata->destroy) |
607 | rdata->destroy (rdata); |
608 | } |
609 | |
610 | static void |
611 | handle_print_response (GtkWidget *dialog, |
612 | int response, |
613 | gpointer data) |
614 | { |
615 | GtkPrintUnixDialog *pd = GTK_PRINT_UNIX_DIALOG (dialog); |
616 | PrintResponseData *rdata = data; |
617 | GtkPrintSettings *settings = NULL; |
618 | GtkPageSetup *page_setup = NULL; |
619 | GtkPrinter *printer = NULL; |
620 | gboolean page_setup_set = FALSE; |
621 | |
622 | if (response == GTK_RESPONSE_OK) |
623 | { |
624 | printer = gtk_print_unix_dialog_get_selected_printer (GTK_PRINT_UNIX_DIALOG (pd)); |
625 | |
626 | rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY; |
627 | rdata->do_preview = FALSE; |
628 | if (printer != NULL) |
629 | rdata->do_print = TRUE; |
630 | } |
631 | else if (response == GTK_RESPONSE_APPLY) |
632 | { |
633 | /* print preview */ |
634 | rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY; |
635 | rdata->do_preview = TRUE; |
636 | rdata->do_print = TRUE; |
637 | |
638 | rdata->op->priv->action = GTK_PRINT_OPERATION_ACTION_PREVIEW; |
639 | } |
640 | |
641 | if (rdata->do_print) |
642 | { |
643 | settings = gtk_print_unix_dialog_get_settings (GTK_PRINT_UNIX_DIALOG (pd)); |
644 | page_setup = gtk_print_unix_dialog_get_page_setup (GTK_PRINT_UNIX_DIALOG (pd)); |
645 | page_setup_set = gtk_print_unix_dialog_get_page_setup_set (GTK_PRINT_UNIX_DIALOG (pd)); |
646 | |
647 | /* Set new print settings now so that custom-widget options |
648 | * can be added to the settings in the callback |
649 | */ |
650 | gtk_print_operation_set_print_settings (op: rdata->op, print_settings: settings); |
651 | g_signal_emit_by_name (instance: rdata->op, detailed_signal: "custom-widget-apply" , rdata->op->priv->custom_widget); |
652 | } |
653 | |
654 | if (rdata->loop) |
655 | g_main_loop_quit (loop: rdata->loop); |
656 | |
657 | finish_print (rdata, printer, page_setup, settings, page_setup_set); |
658 | |
659 | if (settings) |
660 | g_object_unref (object: settings); |
661 | |
662 | gtk_window_destroy (GTK_WINDOW (pd)); |
663 | } |
664 | |
665 | |
666 | static void |
667 | found_printer (GtkPrinter *printer, |
668 | PrintResponseData *rdata) |
669 | { |
670 | GtkPrintOperation *op = rdata->op; |
671 | GtkPrintOperationPrivate *priv = op->priv; |
672 | GtkPrintSettings *settings = NULL; |
673 | GtkPageSetup *page_setup = NULL; |
674 | |
675 | if (rdata->loop) |
676 | g_main_loop_quit (loop: rdata->loop); |
677 | |
678 | if (printer != NULL) |
679 | { |
680 | rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY; |
681 | |
682 | rdata->do_print = TRUE; |
683 | |
684 | if (priv->print_settings) |
685 | settings = gtk_print_settings_copy (other: priv->print_settings); |
686 | else |
687 | settings = gtk_print_settings_new (); |
688 | |
689 | gtk_print_settings_set_printer (settings, |
690 | printer: gtk_printer_get_name (printer)); |
691 | |
692 | if (priv->default_page_setup) |
693 | page_setup = gtk_page_setup_copy (other: priv->default_page_setup); |
694 | else |
695 | page_setup = gtk_page_setup_new (); |
696 | } |
697 | |
698 | finish_print (rdata, printer, page_setup, settings, FALSE); |
699 | |
700 | if (settings) |
701 | g_object_unref (object: settings); |
702 | |
703 | if (page_setup) |
704 | g_object_unref (object: page_setup); |
705 | } |
706 | |
707 | static void |
708 | gtk_print_operation_unix_run_dialog_async (GtkPrintOperation *op, |
709 | gboolean show_dialog, |
710 | GtkWindow *parent, |
711 | GtkPrintOperationPrintFunc print_cb) |
712 | { |
713 | GtkWidget *pd; |
714 | PrintResponseData *rdata; |
715 | const char *printer_name; |
716 | |
717 | rdata = g_new (PrintResponseData, 1); |
718 | rdata->op = g_object_ref (op); |
719 | rdata->do_print = FALSE; |
720 | rdata->do_preview = FALSE; |
721 | rdata->result = GTK_PRINT_OPERATION_RESULT_CANCEL; |
722 | rdata->print_cb = print_cb; |
723 | rdata->parent = parent; |
724 | rdata->loop = NULL; |
725 | rdata->destroy = print_response_data_free; |
726 | |
727 | if (show_dialog) |
728 | { |
729 | pd = get_print_dialog (op, parent); |
730 | gtk_window_set_modal (GTK_WINDOW (pd), TRUE); |
731 | |
732 | g_signal_connect (pd, "response" , |
733 | G_CALLBACK (handle_print_response), rdata); |
734 | |
735 | gtk_window_present (GTK_WINDOW (pd)); |
736 | } |
737 | else |
738 | { |
739 | printer_name = NULL; |
740 | if (op->priv->print_settings) |
741 | printer_name = gtk_print_settings_get_printer (settings: op->priv->print_settings); |
742 | |
743 | find_printer (printer: printer_name, func: (GFunc) found_printer, data: rdata); |
744 | } |
745 | } |
746 | |
747 | static cairo_status_t |
748 | write_preview (void *closure, |
749 | const unsigned char *data, |
750 | unsigned int length) |
751 | { |
752 | int fd = GPOINTER_TO_INT (closure); |
753 | gssize written; |
754 | |
755 | while (length > 0) |
756 | { |
757 | written = write (fd: fd, buf: data, n: length); |
758 | |
759 | if (written == -1) |
760 | { |
761 | if (errno == EAGAIN || errno == EINTR) |
762 | continue; |
763 | |
764 | return CAIRO_STATUS_WRITE_ERROR; |
765 | } |
766 | |
767 | data += written; |
768 | length -= written; |
769 | } |
770 | |
771 | return CAIRO_STATUS_SUCCESS; |
772 | } |
773 | |
774 | static void |
775 | close_preview (void *data) |
776 | { |
777 | int fd = GPOINTER_TO_INT (data); |
778 | |
779 | close (fd: fd); |
780 | } |
781 | |
782 | static cairo_surface_t * |
783 | gtk_print_operation_unix_create_preview_surface (GtkPrintOperation *op, |
784 | GtkPageSetup *page_setup, |
785 | double *dpi_x, |
786 | double *dpi_y, |
787 | char **target) |
788 | { |
789 | char *filename; |
790 | int fd; |
791 | GtkPaperSize *paper_size; |
792 | double w, h; |
793 | cairo_surface_t *surface; |
794 | static cairo_user_data_key_t key; |
795 | |
796 | filename = g_build_filename (first_element: g_get_tmp_dir (), "previewXXXXXX.pdf" , NULL); |
797 | fd = g_mkstemp (tmpl: filename); |
798 | |
799 | if (fd < 0) |
800 | { |
801 | g_free (mem: filename); |
802 | return NULL; |
803 | } |
804 | |
805 | *target = filename; |
806 | |
807 | paper_size = gtk_page_setup_get_paper_size (setup: page_setup); |
808 | w = gtk_paper_size_get_width (size: paper_size, unit: GTK_UNIT_POINTS); |
809 | h = gtk_paper_size_get_height (size: paper_size, unit: GTK_UNIT_POINTS); |
810 | |
811 | *dpi_x = *dpi_y = 72; |
812 | surface = cairo_pdf_surface_create_for_stream (write_func: write_preview, GINT_TO_POINTER (fd), width_in_points: w, height_in_points: h); |
813 | |
814 | cairo_surface_set_user_data (surface, key: &key, GINT_TO_POINTER (fd), destroy: close_preview); |
815 | |
816 | return surface; |
817 | } |
818 | |
819 | static void |
820 | gtk_print_operation_unix_preview_start_page (GtkPrintOperation *op, |
821 | cairo_surface_t *surface, |
822 | cairo_t *cr) |
823 | { |
824 | } |
825 | |
826 | static void |
827 | gtk_print_operation_unix_preview_end_page (GtkPrintOperation *op, |
828 | cairo_surface_t *surface, |
829 | cairo_t *cr) |
830 | { |
831 | cairo_show_page (cr); |
832 | } |
833 | |
834 | static void |
835 | gtk_print_operation_unix_resize_preview_surface (GtkPrintOperation *op, |
836 | GtkPageSetup *page_setup, |
837 | cairo_surface_t *surface) |
838 | { |
839 | double w, h; |
840 | |
841 | w = gtk_page_setup_get_paper_width (setup: page_setup, unit: GTK_UNIT_POINTS); |
842 | h = gtk_page_setup_get_paper_height (setup: page_setup, unit: GTK_UNIT_POINTS); |
843 | cairo_pdf_surface_set_size (surface, width_in_points: w, height_in_points: h); |
844 | } |
845 | |
846 | static GtkPrintOperationResult |
847 | gtk_print_operation_unix_run_dialog (GtkPrintOperation *op, |
848 | gboolean show_dialog, |
849 | GtkWindow *parent, |
850 | gboolean *do_print) |
851 | { |
852 | GtkWidget *pd; |
853 | PrintResponseData rdata; |
854 | const char *printer_name; |
855 | |
856 | rdata.op = op; |
857 | rdata.do_print = FALSE; |
858 | rdata.do_preview = FALSE; |
859 | rdata.result = GTK_PRINT_OPERATION_RESULT_CANCEL; |
860 | rdata.print_cb = NULL; |
861 | rdata.destroy = NULL; |
862 | rdata.parent = parent; |
863 | rdata.loop = NULL; |
864 | |
865 | if (show_dialog) |
866 | { |
867 | pd = get_print_dialog (op, parent); |
868 | gtk_window_set_modal (GTK_WINDOW (pd), TRUE); |
869 | |
870 | g_signal_connect (pd, "response" , |
871 | G_CALLBACK (handle_print_response), &rdata); |
872 | |
873 | gtk_window_present (GTK_WINDOW (pd)); |
874 | |
875 | rdata.loop = g_main_loop_new (NULL, FALSE); |
876 | g_main_loop_run (loop: rdata.loop); |
877 | g_main_loop_unref (loop: rdata.loop); |
878 | rdata.loop = NULL; |
879 | } |
880 | else |
881 | { |
882 | printer_name = NULL; |
883 | if (op->priv->print_settings) |
884 | printer_name = gtk_print_settings_get_printer (settings: op->priv->print_settings); |
885 | |
886 | rdata.loop = g_main_loop_new (NULL, FALSE); |
887 | find_printer (printer: printer_name, |
888 | func: (GFunc) found_printer, data: &rdata); |
889 | |
890 | g_main_loop_run (loop: rdata.loop); |
891 | g_main_loop_unref (loop: rdata.loop); |
892 | rdata.loop = NULL; |
893 | } |
894 | |
895 | *do_print = rdata.do_print; |
896 | |
897 | return rdata.result; |
898 | } |
899 | |
900 | |
901 | typedef struct |
902 | { |
903 | GtkPageSetup *page_setup; |
904 | GtkPageSetupDoneFunc done_cb; |
905 | gpointer data; |
906 | GDestroyNotify destroy; |
907 | GMainLoop *loop; |
908 | } PageSetupResponseData; |
909 | |
910 | static void |
911 | page_setup_data_free (gpointer data) |
912 | { |
913 | PageSetupResponseData *rdata = data; |
914 | |
915 | if (rdata->page_setup) |
916 | g_object_unref (object: rdata->page_setup); |
917 | |
918 | g_free (mem: rdata); |
919 | } |
920 | |
921 | static void |
922 | handle_page_setup_response (GtkWidget *dialog, |
923 | int response, |
924 | gpointer data) |
925 | { |
926 | GtkPageSetupUnixDialog *psd; |
927 | PageSetupResponseData *rdata = data; |
928 | |
929 | if (rdata->loop) |
930 | g_main_loop_quit (loop: rdata->loop); |
931 | |
932 | psd = GTK_PAGE_SETUP_UNIX_DIALOG (dialog); |
933 | if (response == GTK_RESPONSE_OK) |
934 | rdata->page_setup = gtk_page_setup_unix_dialog_get_page_setup (dialog: psd); |
935 | |
936 | gtk_window_destroy (GTK_WINDOW (dialog)); |
937 | |
938 | if (rdata->done_cb) |
939 | rdata->done_cb (rdata->page_setup, rdata->data); |
940 | |
941 | if (rdata->destroy) |
942 | rdata->destroy (rdata); |
943 | } |
944 | |
945 | static GtkWidget * |
946 | get_page_setup_dialog (GtkWindow *parent, |
947 | GtkPageSetup *page_setup, |
948 | GtkPrintSettings *settings) |
949 | { |
950 | GtkWidget *dialog; |
951 | |
952 | dialog = gtk_page_setup_unix_dialog_new (NULL, parent); |
953 | if (page_setup) |
954 | gtk_page_setup_unix_dialog_set_page_setup (GTK_PAGE_SETUP_UNIX_DIALOG (dialog), |
955 | page_setup); |
956 | gtk_page_setup_unix_dialog_set_print_settings (GTK_PAGE_SETUP_UNIX_DIALOG (dialog), |
957 | print_settings: settings); |
958 | |
959 | return dialog; |
960 | } |
961 | |
962 | /** |
963 | * gtk_print_run_page_setup_dialog: |
964 | * @parent: (nullable): transient parent |
965 | * @page_setup: (nullable): an existing `GtkPageSetup` |
966 | * @settings: a `GtkPrintSettings` |
967 | * |
968 | * Runs a page setup dialog, letting the user modify the values from |
969 | * @page_setup. If the user cancels the dialog, the returned `GtkPageSetup` |
970 | * is identical to the passed in @page_setup, otherwise it contains the |
971 | * modifications done in the dialog. |
972 | * |
973 | * Note that this function may use a recursive mainloop to show the page |
974 | * setup dialog. See gtk_print_run_page_setup_dialog_async() if this is |
975 | * a problem. |
976 | * |
977 | * Returns: (transfer full): a new `GtkPageSetup` |
978 | */ |
979 | GtkPageSetup * |
980 | gtk_print_run_page_setup_dialog (GtkWindow *parent, |
981 | GtkPageSetup *page_setup, |
982 | GtkPrintSettings *settings) |
983 | { |
984 | GtkWidget *dialog; |
985 | PageSetupResponseData rdata; |
986 | |
987 | rdata.page_setup = NULL; |
988 | rdata.done_cb = NULL; |
989 | rdata.data = NULL; |
990 | rdata.destroy = NULL; |
991 | rdata.loop = g_main_loop_new (NULL, FALSE); |
992 | |
993 | dialog = get_page_setup_dialog (parent, page_setup, settings); |
994 | |
995 | g_signal_connect (dialog, "response" , |
996 | G_CALLBACK (handle_page_setup_response), |
997 | &rdata); |
998 | |
999 | gtk_window_present (GTK_WINDOW (dialog)); |
1000 | |
1001 | g_main_loop_run (loop: rdata.loop); |
1002 | g_main_loop_unref (loop: rdata.loop); |
1003 | rdata.loop = NULL; |
1004 | |
1005 | if (rdata.page_setup) |
1006 | return rdata.page_setup; |
1007 | else if (page_setup) |
1008 | return gtk_page_setup_copy (other: page_setup); |
1009 | else |
1010 | return gtk_page_setup_new (); |
1011 | } |
1012 | |
1013 | /** |
1014 | * gtk_print_run_page_setup_dialog_async: |
1015 | * @parent: (nullable): transient parent |
1016 | * @page_setup: (nullable): an existing `GtkPageSetup` |
1017 | * @settings: a `GtkPrintSettings` |
1018 | * @done_cb: (scope async): a function to call when the user saves |
1019 | * the modified page setup |
1020 | * @data: user data to pass to @done_cb |
1021 | * |
1022 | * Runs a page setup dialog, letting the user modify the values from @page_setup. |
1023 | * |
1024 | * In contrast to gtk_print_run_page_setup_dialog(), this function returns after |
1025 | * showing the page setup dialog on platforms that support this, and calls @done_cb |
1026 | * from a signal handler for the ::response signal of the dialog. |
1027 | */ |
1028 | void |
1029 | gtk_print_run_page_setup_dialog_async (GtkWindow *parent, |
1030 | GtkPageSetup *page_setup, |
1031 | GtkPrintSettings *settings, |
1032 | GtkPageSetupDoneFunc done_cb, |
1033 | gpointer data) |
1034 | { |
1035 | GtkWidget *dialog; |
1036 | PageSetupResponseData *rdata; |
1037 | |
1038 | dialog = get_page_setup_dialog (parent, page_setup, settings); |
1039 | gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); |
1040 | |
1041 | rdata = g_new (PageSetupResponseData, 1); |
1042 | rdata->page_setup = NULL; |
1043 | rdata->done_cb = done_cb; |
1044 | rdata->data = data; |
1045 | rdata->destroy = page_setup_data_free; |
1046 | rdata->loop = NULL; |
1047 | |
1048 | g_signal_connect (dialog, "response" , |
1049 | G_CALLBACK (handle_page_setup_response), rdata); |
1050 | |
1051 | gtk_window_present (GTK_WINDOW (dialog)); |
1052 | } |
1053 | |
1054 | struct _PrinterFinder |
1055 | { |
1056 | gboolean found_printer; |
1057 | GFunc func; |
1058 | gpointer data; |
1059 | char *printer_name; |
1060 | GList *backends; |
1061 | guint timeout_tag; |
1062 | GtkPrinter *printer; |
1063 | GtkPrinter *default_printer; |
1064 | GtkPrinter *first_printer; |
1065 | }; |
1066 | |
1067 | static gboolean |
1068 | find_printer_idle (gpointer data) |
1069 | { |
1070 | PrinterFinder *finder = data; |
1071 | GtkPrinter *printer; |
1072 | |
1073 | if (finder->printer != NULL) |
1074 | printer = finder->printer; |
1075 | else if (finder->default_printer != NULL) |
1076 | printer = finder->default_printer; |
1077 | else if (finder->first_printer != NULL) |
1078 | printer = finder->first_printer; |
1079 | else |
1080 | printer = NULL; |
1081 | |
1082 | finder->func (printer, finder->data); |
1083 | |
1084 | printer_finder_free (finder); |
1085 | |
1086 | return G_SOURCE_REMOVE; |
1087 | } |
1088 | |
1089 | static void |
1090 | printer_added_cb (GtkPrintBackend *backend, |
1091 | GtkPrinter *printer, |
1092 | PrinterFinder *finder) |
1093 | { |
1094 | if (finder->found_printer) |
1095 | return; |
1096 | |
1097 | /* FIXME this skips "Print to PDF" - is this intentional ? */ |
1098 | if (gtk_printer_is_virtual (printer)) |
1099 | return; |
1100 | |
1101 | if (finder->printer_name != NULL && |
1102 | strcmp (s1: gtk_printer_get_name (printer), s2: finder->printer_name) == 0) |
1103 | { |
1104 | finder->printer = g_object_ref (printer); |
1105 | finder->found_printer = TRUE; |
1106 | } |
1107 | else if (finder->default_printer == NULL && |
1108 | gtk_printer_is_default (printer)) |
1109 | { |
1110 | finder->default_printer = g_object_ref (printer); |
1111 | if (finder->printer_name == NULL) |
1112 | finder->found_printer = TRUE; |
1113 | } |
1114 | else |
1115 | { |
1116 | if (finder->first_printer == NULL) |
1117 | finder->first_printer = g_object_ref (printer); |
1118 | } |
1119 | |
1120 | if (finder->found_printer) |
1121 | g_idle_add (function: find_printer_idle, data: finder); |
1122 | } |
1123 | |
1124 | static void |
1125 | printer_list_done_cb (GtkPrintBackend *backend, |
1126 | PrinterFinder *finder) |
1127 | { |
1128 | finder->backends = g_list_remove (list: finder->backends, data: backend); |
1129 | |
1130 | g_signal_handlers_disconnect_by_func (backend, printer_added_cb, finder); |
1131 | g_signal_handlers_disconnect_by_func (backend, printer_list_done_cb, finder); |
1132 | |
1133 | gtk_print_backend_destroy (print_backend: backend); |
1134 | g_object_unref (object: backend); |
1135 | |
1136 | if (finder->backends == NULL) |
1137 | g_idle_add (function: find_printer_idle, data: finder); |
1138 | } |
1139 | |
1140 | static void |
1141 | find_printer_init (PrinterFinder *finder, |
1142 | GtkPrintBackend *backend) |
1143 | { |
1144 | GList *list; |
1145 | GList *node; |
1146 | |
1147 | list = gtk_print_backend_get_printer_list (print_backend: backend); |
1148 | |
1149 | node = list; |
1150 | while (node != NULL) |
1151 | { |
1152 | printer_added_cb (backend, printer: node->data, finder); |
1153 | node = node->next; |
1154 | |
1155 | if (finder->found_printer) |
1156 | break; |
1157 | } |
1158 | |
1159 | g_list_free (list); |
1160 | |
1161 | if (gtk_print_backend_printer_list_is_done (print_backend: backend)) |
1162 | { |
1163 | finder->backends = g_list_remove (list: finder->backends, data: backend); |
1164 | gtk_print_backend_destroy (print_backend: backend); |
1165 | g_object_unref (object: backend); |
1166 | } |
1167 | else |
1168 | { |
1169 | g_signal_connect (backend, "printer-added" , |
1170 | (GCallback) printer_added_cb, |
1171 | finder); |
1172 | g_signal_connect (backend, "printer-list-done" , |
1173 | (GCallback) printer_list_done_cb, |
1174 | finder); |
1175 | } |
1176 | |
1177 | } |
1178 | |
1179 | static void |
1180 | printer_finder_free (PrinterFinder *finder) |
1181 | { |
1182 | GList *l; |
1183 | |
1184 | g_free (mem: finder->printer_name); |
1185 | |
1186 | if (finder->printer) |
1187 | g_object_unref (object: finder->printer); |
1188 | |
1189 | if (finder->default_printer) |
1190 | g_object_unref (object: finder->default_printer); |
1191 | |
1192 | if (finder->first_printer) |
1193 | g_object_unref (object: finder->first_printer); |
1194 | |
1195 | for (l = finder->backends; l != NULL; l = l->next) |
1196 | { |
1197 | GtkPrintBackend *backend = l->data; |
1198 | g_signal_handlers_disconnect_by_func (backend, printer_added_cb, finder); |
1199 | g_signal_handlers_disconnect_by_func (backend, printer_list_done_cb, finder); |
1200 | gtk_print_backend_destroy (print_backend: backend); |
1201 | g_object_unref (object: backend); |
1202 | } |
1203 | |
1204 | g_list_free (list: finder->backends); |
1205 | |
1206 | g_free (mem: finder); |
1207 | } |
1208 | |
1209 | static void |
1210 | find_printer (const char *printer, |
1211 | GFunc func, |
1212 | gpointer data) |
1213 | { |
1214 | GList *node, *next; |
1215 | PrinterFinder *finder; |
1216 | |
1217 | finder = g_new0 (PrinterFinder, 1); |
1218 | |
1219 | finder->printer_name = g_strdup (str: printer); |
1220 | finder->func = func; |
1221 | finder->data = data; |
1222 | |
1223 | finder->backends = NULL; |
1224 | if (g_module_supported ()) |
1225 | finder->backends = gtk_print_backend_load_modules (); |
1226 | |
1227 | for (node = finder->backends; !finder->found_printer && node != NULL; node = next) |
1228 | { |
1229 | next = node->next; |
1230 | find_printer_init (finder, GTK_PRINT_BACKEND (node->data)); |
1231 | } |
1232 | |
1233 | if (finder->backends == NULL) |
1234 | g_idle_add (function: find_printer_idle, data: finder); |
1235 | } |
1236 | |
1237 | |
1238 | GtkPrintOperationResult |
1239 | _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op, |
1240 | gboolean show_dialog, |
1241 | GtkWindow *parent, |
1242 | gboolean *do_print) |
1243 | { |
1244 | if (gdk_should_use_portal ()) |
1245 | return gtk_print_operation_portal_run_dialog (op, show_dialog, parent, do_print); |
1246 | else |
1247 | return gtk_print_operation_unix_run_dialog (op, show_dialog, parent, do_print); |
1248 | } |
1249 | void |
1250 | _gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation *op, |
1251 | gboolean show_dialog, |
1252 | GtkWindow *parent, |
1253 | GtkPrintOperationPrintFunc print_cb) |
1254 | { |
1255 | if (gdk_should_use_portal ()) |
1256 | gtk_print_operation_portal_run_dialog_async (op, show_dialog, parent, print_cb); |
1257 | else |
1258 | gtk_print_operation_unix_run_dialog_async (op, show_dialog, parent, print_cb); |
1259 | } |
1260 | |
1261 | void |
1262 | _gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op, |
1263 | cairo_surface_t *surface, |
1264 | GtkWindow *parent, |
1265 | const char *filename) |
1266 | { |
1267 | if (gdk_should_use_portal ()) |
1268 | gtk_print_operation_portal_launch_preview (op, surface, parent, filename); |
1269 | else |
1270 | gtk_print_operation_unix_launch_preview (op, surface, parent, filename); |
1271 | } |
1272 | |
1273 | cairo_surface_t * |
1274 | _gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation *op, |
1275 | GtkPageSetup *page_setup, |
1276 | double *dpi_x, |
1277 | double *dpi_y, |
1278 | char **target) |
1279 | { |
1280 | return gtk_print_operation_unix_create_preview_surface (op, page_setup, dpi_x, dpi_y, target); |
1281 | } |
1282 | |
1283 | void |
1284 | _gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation *op, |
1285 | GtkPageSetup *page_setup, |
1286 | cairo_surface_t *surface) |
1287 | { |
1288 | gtk_print_operation_unix_resize_preview_surface (op, page_setup, surface); |
1289 | } |
1290 | |
1291 | void |
1292 | _gtk_print_operation_platform_backend_preview_start_page (GtkPrintOperation *op, |
1293 | cairo_surface_t *surface, |
1294 | cairo_t *cr) |
1295 | { |
1296 | gtk_print_operation_unix_preview_start_page (op, surface, cr); |
1297 | } |
1298 | |
1299 | void |
1300 | _gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op, |
1301 | cairo_surface_t *surface, |
1302 | cairo_t *cr) |
1303 | { |
1304 | gtk_print_operation_unix_preview_end_page (op, surface, cr); |
1305 | } |
1306 | |