gtkprintoperation-unix.c 36.4 KB
Newer Older
Cody Russell's avatar
Cody Russell committed
1
/* GTK - The GIMP Toolkit
2 3
 * gtkprintoperation-unix.c: Print Operation Details for Unix 
 *                           and Unix-like platforms
4 5 6 7 8 9 10 11 12 13 14 15 16
 * Copyright (C) 2006, Red Hat, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
Javier Jardon's avatar
Javier Jardon committed
17
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18 19 20 21 22 23 24 25 26
 */

#include "config.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
27 28 29
#include <errno.h>
#include <stdlib.h>       
#include <fcntl.h>
30

31
#include <glib/gstdio.h>
32
#include "gtkprintoperation-private.h"
33
#include "gtkprintoperation-portal.h"
34 35
#include "gtkmessagedialog.h"

36 37
#include <cairo-pdf.h>
#include <cairo-ps.h>
38
#include "gtkprivate.h"
39 40 41 42 43
#include "gtkprintunixdialog.h"
#include "gtkpagesetupunixdialog.h"
#include "gtkprintbackend.h"
#include "gtkprinter.h"
#include "gtkprintjob.h"
44
#include "gtklabel.h"
45
#include "gtkintl.h"
46

47

Matthias Clasen's avatar
Matthias Clasen committed
48 49
typedef struct 
{
Matthias Clasen's avatar
Matthias Clasen committed
50
  GtkWindow *parent;        /* just in case we need to throw error dialogs */
Alexander Larsson's avatar
Alexander Larsson committed
51 52
  GMainLoop *loop;
  gboolean data_sent;
53

54
  /* Real printing (not preview) */
55 56 57 58 59
  GtkPrintJob *job;         /* the job we are sending to the printer */
  cairo_surface_t *surface;
  gulong job_status_changed_tag;

  
60 61
} GtkPrintOperationUnix;

Alexander Larsson's avatar
Alexander Larsson committed
62 63 64
typedef struct _PrinterFinder PrinterFinder;

static void printer_finder_free (PrinterFinder *finder);
Matthias Clasen's avatar
Matthias Clasen committed
65
static void find_printer        (const gchar   *printer,
Alexander Larsson's avatar
Alexander Larsson committed
66 67 68
				 GFunc          func,
				 gpointer       data);

69 70
static void
unix_start_page (GtkPrintOperation *op,
Matthias Clasen's avatar
Matthias Clasen committed
71 72
		 GtkPrintContext   *print_context,
		 GtkPageSetup      *page_setup)
73
{
74
  GtkPrintOperationUnix *op_unix;  
75 76
  GtkPaperSize *paper_size;
  cairo_surface_type_t type;
Matthias Clasen's avatar
Matthias Clasen committed
77
  gdouble w, h;
78

79 80
  op_unix = op->priv->platform_data;
  
81 82 83 84 85
  paper_size = gtk_page_setup_get_paper_size (page_setup);

  w = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
  h = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
  
86
  type = cairo_surface_get_type (op_unix->surface);
87

88 89 90 91
  if ((op->priv->manual_number_up < 2) ||
      (op->priv->page_position % op->priv->manual_number_up == 0))
    {
      if (type == CAIRO_SURFACE_TYPE_PS)
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
        {
          cairo_ps_surface_set_size (op_unix->surface, w, h);
          cairo_ps_surface_dsc_begin_page_setup (op_unix->surface);
          switch (gtk_page_setup_get_orientation (page_setup))
            {
              case GTK_PAGE_ORIENTATION_PORTRAIT:
              case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
                cairo_ps_surface_dsc_comment (op_unix->surface, "%%PageOrientation: Portrait");
                break;

              case GTK_PAGE_ORIENTATION_LANDSCAPE:
              case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
                cairo_ps_surface_dsc_comment (op_unix->surface, "%%PageOrientation: Landscape");
                break;
            }
         }
108
      else if (type == CAIRO_SURFACE_TYPE_PDF)
109
        {
110 111 112 113 114
          if (!op->priv->manual_orientation)
            {
              w = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
              h = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
            }
115 116
          cairo_pdf_surface_set_size (op_unix->surface, w, h);
        }
117
    }
118 119 120 121
}

static void
unix_end_page (GtkPrintOperation *op,
Matthias Clasen's avatar
Matthias Clasen committed
122
	       GtkPrintContext   *print_context)
123 124 125
{
  cairo_t *cr;

126
  cr = gtk_print_context_get_cairo_context (print_context);
127 128 129 130 131

  if ((op->priv->manual_number_up < 2) ||
      ((op->priv->page_position + 1) % op->priv->manual_number_up == 0) ||
      (op->priv->page_position == op->priv->nr_of_pages_to_print - 1))
    cairo_show_page (cr);
132 133 134 135 136 137 138
}

static void
op_unix_free (GtkPrintOperationUnix *op_unix)
{
  if (op_unix->job)
    {
139 140 141
      if (op_unix->job_status_changed_tag > 0)
        g_signal_handler_disconnect (op_unix->job,
				     op_unix->job_status_changed_tag);
142 143 144 145 146 147
      g_object_unref (op_unix->job);
    }

  g_free (op_unix);
}

Matthias Clasen's avatar
Matthias Clasen committed
148
static gchar *
149
shell_command_substitute_file (const gchar *cmd,
150 151 152 153
			       const gchar *pdf_filename,
			       const gchar *settings_filename,
                               gboolean    *pdf_filename_replaced,
                               gboolean    *settings_filename_replaced)
154
{
Matthias Clasen's avatar
Matthias Clasen committed
155
  const gchar *inptr, *start;
156 157 158
  GString *final;

  g_return_val_if_fail (cmd != NULL, NULL);
159 160
  g_return_val_if_fail (pdf_filename != NULL, NULL);
  g_return_val_if_fail (settings_filename != NULL, NULL);
161 162 163

  final = g_string_new (NULL);

164 165
  *pdf_filename_replaced = FALSE;
  *settings_filename_replaced = FALSE;
166

167
  start = inptr = cmd;
168 169 170 171 172 173 174
  while ((inptr = strchr (inptr, '%')) != NULL) 
    {
      g_string_append_len (final, start, inptr - start);
      inptr++;
      switch (*inptr) 
        {
          case 'f':
175 176 177 178 179 180 181
            g_string_append (final, pdf_filename);
            *pdf_filename_replaced = TRUE;
            break;

          case 's':
            g_string_append (final, settings_filename);
            *settings_filename_replaced = TRUE;
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
            break;

          case '%':
            g_string_append_c (final, '%');
            break;

          default:
            g_string_append_c (final, '%');
            if (*inptr)
              g_string_append_c (final, *inptr);
            break;
        }
      if (*inptr)
        inptr++;
      start = inptr;
    }
  g_string_append (final, start);

200
  return g_string_free (final, FALSE);
201 202
}

203
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
204 205 206 207 208
static void
gtk_print_operation_unix_launch_preview (GtkPrintOperation *op,
                                         cairo_surface_t   *surface,
                                         GtkWindow         *parent,
                                         const gchar       *filename)
209
{
Matthias Clasen's avatar
Matthias Clasen committed
210
  GAppInfo *appinfo;
211
  GdkAppLaunchContext *context;
212 213 214
  gchar *cmd;
  gchar *preview_cmd;
  GtkSettings *settings;
Marek Kasik's avatar
Marek Kasik committed
215
  GtkPrintSettings *print_settings = NULL;
216 217 218 219
  GtkPageSetup *page_setup;
  GKeyFile *key_file = NULL;
  gchar *data = NULL;
  gsize data_len;
220
  gchar *settings_filename = NULL;
221
  gchar *quoted_filename;
222
  gchar *quoted_settings_filename;
223 224
  gboolean filename_used = FALSE;
  gboolean settings_used = FALSE;
225 226
  GdkScreen *screen;
  GError *error = NULL;
227
  gint fd;
228
  gboolean retval;
229

230
  cairo_surface_destroy (surface);
231
 
232 233 234 235 236
  if (parent)
    screen = gtk_window_get_screen (parent);
  else
    screen = gdk_screen_get_default ();

237 238 239
  fd = g_file_open_tmp ("settingsXXXXXX.ini", &settings_filename, &error);
  if (fd < 0) 
    goto out;
240

241 242
  key_file = g_key_file_new ();
  
Marek Kasik's avatar
Marek Kasik committed
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
  print_settings = gtk_print_settings_copy (gtk_print_operation_get_print_settings (op));

  if (print_settings != NULL)
    {
      gtk_print_settings_set_reverse (print_settings, FALSE);
      gtk_print_settings_set_page_set (print_settings, GTK_PAGE_SET_ALL);
      gtk_print_settings_set_scale (print_settings, 1.0);
      gtk_print_settings_set_number_up (print_settings, 1);
      gtk_print_settings_set_number_up_layout (print_settings, GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM);

      /*  These removals are neccessary because cups-* settings have higher priority
       *  than normal settings.
       */
      gtk_print_settings_unset (print_settings, "cups-reverse");
      gtk_print_settings_unset (print_settings, "cups-page-set");
      gtk_print_settings_unset (print_settings, "cups-scale");
      gtk_print_settings_unset (print_settings, "cups-number-up");
      gtk_print_settings_unset (print_settings, "cups-number-up-layout");

      gtk_print_settings_to_key_file (print_settings, key_file, NULL);
      g_object_unref (print_settings);
    }
265 266 267

  page_setup = gtk_print_context_get_page_setup (op->priv->print_context);
  gtk_page_setup_to_key_file (page_setup, key_file, NULL);
268

269 270
  g_key_file_set_string (key_file, "Print Job", "title", op->priv->job_name);

271 272 273 274 275
  data = g_key_file_to_data (key_file, &data_len, &error);
  if (!data)
    goto out;

  retval = g_file_set_contents (settings_filename, data, data_len, &error);
276
  if (!retval)
277 278 279
    goto out;

  settings = gtk_settings_get_for_screen (screen);
280 281 282
  g_object_get (settings, "gtk-print-preview-command", &preview_cmd, NULL);

  quoted_filename = g_shell_quote (filename);
283 284
  quoted_settings_filename = g_shell_quote (settings_filename);
  cmd = shell_command_substitute_file (preview_cmd, quoted_filename, quoted_settings_filename, &filename_used, &settings_used);
Matthias Clasen's avatar
Matthias Clasen committed
285 286 287 288 289

  appinfo = g_app_info_create_from_commandline (cmd,
                                                "Print Preview",
                                                G_APP_INFO_CREATE_NONE,
                                                &error);
290

291 292 293 294 295
  g_free (preview_cmd);
  g_free (quoted_filename);
  g_free (quoted_settings_filename);
  g_free (cmd);

Matthias Clasen's avatar
Matthias Clasen committed
296
  if (error != NULL)
297 298
    goto out;

Matthias Clasen's avatar
Matthias Clasen committed
299
  context = gdk_display_get_app_launch_context (gdk_screen_get_display (screen));
300 301
  gdk_app_launch_context_set_screen (context, screen);
  g_app_info_launch (appinfo, NULL, G_APP_LAUNCH_CONTEXT (context), &error);
302

Matthias Clasen's avatar
Matthias Clasen committed
303 304
  g_object_unref (context);
  g_object_unref (appinfo);
305

306 307 308 309
  if (error != NULL)
    {
      gchar* uri;

310
      g_warning ("Error launching preview: %s", error->message);
311 312 313 314 315 316 317 318

      g_error_free (error);
      error = NULL;
      uri = g_filename_to_uri (filename, NULL, NULL);
      gtk_show_uri (screen, uri, GDK_CURRENT_TIME, &error);
      g_free (uri);
    }

319 320 321
 out:
  if (error != NULL)
    {
322 323 324 325
      if (op->priv->error == NULL)
        op->priv->error = error;
      else
        g_error_free (error);
326

Matthias Clasen's avatar
Matthias Clasen committed
327
      filename_used = FALSE;
328
      settings_used = FALSE;
Matthias Clasen's avatar
Matthias Clasen committed
329
   }
330

331 332 333 334 335 336
  if (!filename_used)
    g_unlink (filename);

  if (!settings_used)
    g_unlink (settings_filename);

337 338
  if (fd > 0)
    close (fd);
Matthias Clasen's avatar
Matthias Clasen committed
339

340 341 342
  if (key_file)
    g_key_file_free (key_file);
  g_free (data);
343
  g_free (settings_filename);
344
}
345
G_GNUC_END_IGNORE_DEPRECATIONS
346

347
static void
348 349 350
unix_finish_send  (GtkPrintJob  *job,
                   gpointer      user_data, 
                   const GError *error)
351
{
352 353
  GtkPrintOperation *op = (GtkPrintOperation *) user_data;
  GtkPrintOperationUnix *op_unix = op->priv->platform_data;
354

355 356
  if (error != NULL && op->priv->error == NULL)
    op->priv->error = g_error_copy (error);
Alexander Larsson's avatar
Alexander Larsson committed
357 358

  op_unix->data_sent = TRUE;
359

Alexander Larsson's avatar
Alexander Larsson committed
360 361
  if (op_unix->loop)
    g_main_loop_quit (op_unix->loop);
362 363

  g_object_unref (op);
364 365 366
}

static void
Alexander Larsson's avatar
Alexander Larsson committed
367
unix_end_run (GtkPrintOperation *op,
368 369
	      gboolean           wait,
	      gboolean           cancelled)
370 371
{
  GtkPrintOperationUnix *op_unix = op->priv->platform_data;
Alexander Larsson's avatar
Alexander Larsson committed
372

373 374
  cairo_surface_finish (op_unix->surface);
  
375 376 377
  if (cancelled)
    return;

Alexander Larsson's avatar
Alexander Larsson committed
378 379 380
  if (wait)
    op_unix->loop = g_main_loop_new (NULL, FALSE);
  
381
  /* TODO: Check for error */
382
  if (op_unix->job != NULL)
383 384 385 386 387 388
    {
      g_object_ref (op);
      gtk_print_job_send (op_unix->job,
                          unix_finish_send, 
                          op, NULL);
    }
Alexander Larsson's avatar
Alexander Larsson committed
389 390 391

  if (wait)
    {
392
      g_object_ref (op);
Alexander Larsson's avatar
Alexander Larsson committed
393 394
      if (!op_unix->data_sent)
	{
395
	  gdk_threads_leave ();  
Alexander Larsson's avatar
Alexander Larsson committed
396
	  g_main_loop_run (op_unix->loop);
397
	  gdk_threads_enter ();  
Alexander Larsson's avatar
Alexander Larsson committed
398 399
	}
      g_main_loop_unref (op_unix->loop);
400 401
      op_unix->loop = NULL;
      g_object_unref (op);
Alexander Larsson's avatar
Alexander Larsson committed
402
    }
403 404 405
}

static void
Matthias Clasen's avatar
Matthias Clasen committed
406 407
job_status_changed_cb (GtkPrintJob       *job, 
		       GtkPrintOperation *op)
408 409 410 411
{
  _gtk_print_operation_set_status (op, gtk_print_job_get_status (job), NULL);
}

412

413
static void
414 415 416
print_setup_changed_cb (GtkPrintUnixDialog *print_dialog, 
                        GParamSpec         *pspec,
                        gpointer            user_data)
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432
{
  GtkPageSetup             *page_setup;
  GtkPrintSettings         *print_settings;
  GtkPrintOperation        *op = user_data;
  GtkPrintOperationPrivate *priv = op->priv;

  page_setup = gtk_print_unix_dialog_get_page_setup (print_dialog);
  print_settings = gtk_print_unix_dialog_get_settings (print_dialog);

  g_signal_emit_by_name (op,
                         "update-custom-widget",
                         priv->custom_widget,
                         page_setup,
                         print_settings);
}

433 434 435
static GtkWidget *
get_print_dialog (GtkPrintOperation *op,
                  GtkWindow         *parent)
436
{
437
  GtkPrintOperationPrivate *priv = op->priv;
438
  GtkWidget *pd, *label;
Matthias Clasen's avatar
Matthias Clasen committed
439
  const gchar *custom_tab_label;
440 441 442

  pd = gtk_print_unix_dialog_new (NULL, parent);

443 444 445 446 447
  gtk_print_unix_dialog_set_manual_capabilities (GTK_PRINT_UNIX_DIALOG (pd),
						 GTK_PRINT_CAPABILITY_PAGE_SET |
						 GTK_PRINT_CAPABILITY_COPIES |
						 GTK_PRINT_CAPABILITY_COLLATE |
						 GTK_PRINT_CAPABILITY_REVERSE |
448
						 GTK_PRINT_CAPABILITY_SCALE |
449 450 451
						 GTK_PRINT_CAPABILITY_PREVIEW |
						 GTK_PRINT_CAPABILITY_NUMBER_UP |
						 GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT);
452

453
  if (priv->print_settings)
454
    gtk_print_unix_dialog_set_settings (GTK_PRINT_UNIX_DIALOG (pd),
455
					priv->print_settings);
456

457
  if (priv->default_page_setup)
458 459
    gtk_print_unix_dialog_set_page_setup (GTK_PRINT_UNIX_DIALOG (pd), 
                                          priv->default_page_setup);
460

461 462 463
  gtk_print_unix_dialog_set_embed_page_setup (GTK_PRINT_UNIX_DIALOG (pd),
                                              priv->embed_page_setup);

464 465 466
  gtk_print_unix_dialog_set_current_page (GTK_PRINT_UNIX_DIALOG (pd), 
                                          priv->current_page);

467 468 469 470 471 472
  gtk_print_unix_dialog_set_support_selection (GTK_PRINT_UNIX_DIALOG (pd),
                                               priv->support_selection);

  gtk_print_unix_dialog_set_has_selection (GTK_PRINT_UNIX_DIALOG (pd),
                                           priv->has_selection);

473
  g_signal_emit_by_name (op, "create-custom-widget",
Matthias Clasen's avatar
Matthias Clasen committed
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
			 &priv->custom_widget);

  if (priv->custom_widget) 
    {
      custom_tab_label = priv->custom_tab_label;
      
      if (custom_tab_label == NULL)
	{
	  custom_tab_label = g_get_application_name ();
	  if (custom_tab_label == NULL)
	    custom_tab_label = _("Application");
	}

      label = gtk_label_new (custom_tab_label);
      
      gtk_print_unix_dialog_add_custom_tab (GTK_PRINT_UNIX_DIALOG (pd),
Matthias Clasen's avatar
Matthias Clasen committed
490
					    priv->custom_widget, label);
491

492 493
      g_signal_connect (pd, "notify::selected-printer", (GCallback) print_setup_changed_cb, op);
      g_signal_connect (pd, "notify::page-setup", (GCallback) print_setup_changed_cb, op);
Matthias Clasen's avatar
Matthias Clasen committed
494
    }
495
  
496 497
  return pd;
}
498
  
Matthias Clasen's avatar
Matthias Clasen committed
499 500
typedef struct 
{
501 502
  GtkPrintOperation           *op;
  gboolean                     do_print;
503
  gboolean                     do_preview;
504 505 506
  GtkPrintOperationResult      result;
  GtkPrintOperationPrintFunc   print_cb;
  GDestroyNotify               destroy;
Alexander Larsson's avatar
Alexander Larsson committed
507 508
  GtkWindow                   *parent;
  GMainLoop                   *loop;
509 510 511 512 513 514 515 516 517 518 519 520
} PrintResponseData;

static void
print_response_data_free (gpointer data)
{
  PrintResponseData *rdata = data;

  g_object_unref (rdata->op);
  g_free (rdata);
}

static void
Alexander Larsson's avatar
Alexander Larsson committed
521
finish_print (PrintResponseData *rdata,
Matthias Clasen's avatar
Matthias Clasen committed
522 523
	      GtkPrinter        *printer,
	      GtkPageSetup      *page_setup,
524 525
	      GtkPrintSettings  *settings,
	      gboolean           page_setup_set)
526 527
{
  GtkPrintOperation *op = rdata->op;
528
  GtkPrintOperationPrivate *priv = op->priv;
Matthias Clasen's avatar
Matthias Clasen committed
529
  GtkPrintJob *job;
530
  gdouble top, bottom, left, right;
Alexander Larsson's avatar
Alexander Larsson committed
531 532
  
  if (rdata->do_print)
533 534
    {
      gtk_print_operation_set_print_settings (op, settings);
535
      priv->print_context = _gtk_print_context_new (op);
536

537 538
      if (gtk_print_settings_get_number_up (settings) < 2)
        {
539
	  if (printer && gtk_printer_get_hard_margins (printer, &top, &bottom, &left, &right))
540 541 542 543 544 545 546 547 548 549
	    _gtk_print_context_set_hard_margins (priv->print_context, top, bottom, left, right);
	}
      else
        {
	  /* Pages do not have any unprintable area when printing n-up as each page on the
	   * sheet has been scaled down and translated to a position within the printable
	   * area of the sheet.
	   */
	  _gtk_print_context_set_hard_margins (priv->print_context, 0, 0, 0, 0);
	}
550

551 552 553
      if (page_setup != NULL &&
          (gtk_print_operation_get_default_page_setup (op) == NULL ||
           page_setup_set))
554 555
        gtk_print_operation_set_default_page_setup (op, page_setup);

556
      _gtk_print_context_set_page_setup (priv->print_context, page_setup);
557

558
      if (!rdata->do_preview)
559
        {
560 561 562
	  GtkPrintOperationUnix *op_unix;
	  cairo_t *cr;
	  
563
	  op_unix = g_new0 (GtkPrintOperationUnix, 1);
564 565 566 567 568 569 570 571
	  priv->platform_data = op_unix;
	  priv->free_platform_data = (GDestroyNotify) op_unix_free;
	  op_unix->parent = rdata->parent;
	  
	  priv->start_page = unix_start_page;
	  priv->end_page = unix_end_page;
	  priv->end_run = unix_end_run;
	  
Matthias Clasen's avatar
Matthias Clasen committed
572 573 574
	  job = gtk_print_job_new (priv->job_name, printer, settings, page_setup);
          op_unix->job = job;
          gtk_print_job_set_track_print_status (job, priv->track_print_status);
575
	  
576
	  op_unix->surface = gtk_print_job_get_surface (job, &priv->error);
Matthias Clasen's avatar
Matthias Clasen committed
577 578
	  if (op_unix->surface == NULL) 
            {
579
	      rdata->result = GTK_PRINT_OPERATION_RESULT_ERROR;
Matthias Clasen's avatar
Matthias Clasen committed
580 581 582
	      rdata->do_print = FALSE;
	      goto out;
            }
583 584
	  
	  cr = cairo_create (op_unix->surface);
Matthias Clasen's avatar
Matthias Clasen committed
585
	  gtk_print_context_set_cairo_context (priv->print_context, cr, 72, 72);
586 587
	  cairo_destroy (cr);

Matthias Clasen's avatar
Matthias Clasen committed
588
          _gtk_print_operation_set_status (op, gtk_print_job_get_status (job), NULL);
589 590
	  
          op_unix->job_status_changed_tag =
Matthias Clasen's avatar
Matthias Clasen committed
591
	    g_signal_connect (job, "status-changed",
592 593
			      G_CALLBACK (job_status_changed_cb), op);
	  
594 595 596 597 598 599 600 601 602 603
          priv->print_pages = gtk_print_job_get_pages (job);
          priv->page_ranges = gtk_print_job_get_page_ranges (job, &priv->num_page_ranges);
          priv->manual_num_copies = gtk_print_job_get_num_copies (job);
          priv->manual_collation = gtk_print_job_get_collate (job);
          priv->manual_reverse = gtk_print_job_get_reverse (job);
          priv->manual_page_set = gtk_print_job_get_page_set (job);
          priv->manual_scale = gtk_print_job_get_scale (job);
          priv->manual_orientation = gtk_print_job_get_rotate (job);
          priv->manual_number_up = gtk_print_job_get_n_up (job);
          priv->manual_number_up_layout = gtk_print_job_get_n_up_layout (job);
604
        }
605
    } 
606
 out:
607
  if (rdata->print_cb)
608
    rdata->print_cb (op, rdata->parent, rdata->do_print, rdata->result); 
609 610 611 612 613

  if (rdata->destroy)
    rdata->destroy (rdata);
}

614
static void 
Alexander Larsson's avatar
Alexander Larsson committed
615 616 617 618 619 620 621 622 623
handle_print_response (GtkWidget *dialog,
		       gint       response,
		       gpointer   data)
{
  GtkPrintUnixDialog *pd = GTK_PRINT_UNIX_DIALOG (dialog);
  PrintResponseData *rdata = data;
  GtkPrintSettings *settings = NULL;
  GtkPageSetup *page_setup = NULL;
  GtkPrinter *printer = NULL;
624
  gboolean page_setup_set = FALSE;
Alexander Larsson's avatar
Alexander Larsson committed
625 626 627 628

  if (response == GTK_RESPONSE_OK)
    {
      printer = gtk_print_unix_dialog_get_selected_printer (GTK_PRINT_UNIX_DIALOG (pd));
629 630 631

      rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
      rdata->do_preview = FALSE;
632 633 634 635 636 637
      if (printer != NULL)
	rdata->do_print = TRUE;
    } 
  else if (response == GTK_RESPONSE_APPLY)
    {
      /* print preview */
638 639
      rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
      rdata->do_preview = TRUE;
Alexander Larsson's avatar
Alexander Larsson committed
640
      rdata->do_print = TRUE;
641 642

      rdata->op->priv->action = GTK_PRINT_OPERATION_ACTION_PREVIEW;
643
    }
Alexander Larsson's avatar
Alexander Larsson committed
644

645 646
  if (rdata->do_print)
    {
Alexander Larsson's avatar
Alexander Larsson committed
647 648
      settings = gtk_print_unix_dialog_get_settings (GTK_PRINT_UNIX_DIALOG (pd));
      page_setup = gtk_print_unix_dialog_get_page_setup (GTK_PRINT_UNIX_DIALOG (pd));
649
      page_setup_set = gtk_print_unix_dialog_get_page_setup_set (GTK_PRINT_UNIX_DIALOG (pd));
650 651 652 653 654

      /* Set new print settings now so that custom-widget options
       * can be added to the settings in the callback
       */
      gtk_print_operation_set_print_settings (rdata->op, settings);
655
      g_signal_emit_by_name (rdata->op, "custom-widget-apply", rdata->op->priv->custom_widget);
656 657
    }
  
658
  finish_print (rdata, printer, page_setup, settings, page_setup_set);
Alexander Larsson's avatar
Alexander Larsson committed
659 660 661

  if (settings)
    g_object_unref (settings);
662
    
Alexander Larsson's avatar
Alexander Larsson committed
663
  gtk_widget_destroy (GTK_WIDGET (pd));
664
 
Alexander Larsson's avatar
Alexander Larsson committed
665 666 667 668
}


static void
Matthias Clasen's avatar
Matthias Clasen committed
669
found_printer (GtkPrinter        *printer,
Alexander Larsson's avatar
Alexander Larsson committed
670 671 672 673 674 675 676 677 678 679
	       PrintResponseData *rdata)
{
  GtkPrintOperation *op = rdata->op;
  GtkPrintOperationPrivate *priv = op->priv;
  GtkPrintSettings *settings = NULL;
  GtkPageSetup *page_setup = NULL;
  
  if (rdata->loop)
    g_main_loop_quit (rdata->loop);

Matthias Clasen's avatar
Matthias Clasen committed
680 681
  if (printer != NULL) 
    {
682
      rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
Alexander Larsson's avatar
Alexander Larsson committed
683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699

      rdata->do_print = TRUE;

      if (priv->print_settings)
	settings = gtk_print_settings_copy (priv->print_settings);
      else
	settings = gtk_print_settings_new ();

      gtk_print_settings_set_printer (settings,
				      gtk_printer_get_name (printer));
      
      if (priv->default_page_setup)
	page_setup = gtk_page_setup_copy (priv->default_page_setup);
      else
	page_setup = gtk_page_setup_new ();
  }
  
700
  finish_print (rdata, printer, page_setup, settings, FALSE);
Alexander Larsson's avatar
Alexander Larsson committed
701 702 703 704 705 706 707 708

  if (settings)
    g_object_unref (settings);
  
  if (page_setup)
    g_object_unref (page_setup);
}

709 710 711 712 713
static void
gtk_print_operation_unix_run_dialog_async (GtkPrintOperation          *op,
                                           gboolean                    show_dialog,
                                           GtkWindow                  *parent,
                                           GtkPrintOperationPrintFunc  print_cb)
714 715 716
{
  GtkWidget *pd;
  PrintResponseData *rdata;
Matthias Clasen's avatar
Matthias Clasen committed
717
  const gchar *printer_name;
718 719 720 721

  rdata = g_new (PrintResponseData, 1);
  rdata->op = g_object_ref (op);
  rdata->do_print = FALSE;
722
  rdata->do_preview = FALSE;
723 724
  rdata->result = GTK_PRINT_OPERATION_RESULT_CANCEL;
  rdata->print_cb = print_cb;
Alexander Larsson's avatar
Alexander Larsson committed
725 726
  rdata->parent = parent;
  rdata->loop = NULL;
727
  rdata->destroy = print_response_data_free;
728
  
729
  if (show_dialog)
Alexander Larsson's avatar
Alexander Larsson committed
730 731 732
    {
      pd = get_print_dialog (op, parent);
      gtk_window_set_modal (GTK_WINDOW (pd), TRUE);
733

Alexander Larsson's avatar
Alexander Larsson committed
734 735 736 737 738 739 740 741 742 743 744
      g_signal_connect (pd, "response", 
			G_CALLBACK (handle_print_response), rdata);
      
      gtk_window_present (GTK_WINDOW (pd));
    }
  else
    {
      printer_name = NULL;
      if (op->priv->print_settings)
	printer_name = gtk_print_settings_get_printer (op->priv->print_settings);
      
Matthias Clasen's avatar
Matthias Clasen committed
745
      find_printer (printer_name, (GFunc) found_printer, rdata);
Alexander Larsson's avatar
Alexander Larsson committed
746
    }
747 748
}

Matthias Clasen's avatar
Matthias Clasen committed
749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783
static cairo_status_t
write_preview (void                *closure,
               const unsigned char *data,
               unsigned int         length)
{
  gint fd = GPOINTER_TO_INT (closure);
  gssize written;
  
  while (length > 0) 
    {
      written = write (fd, data, length);

      if (written == -1)
	{
	  if (errno == EAGAIN || errno == EINTR)
	    continue;
	  
	  return CAIRO_STATUS_WRITE_ERROR;
	}    

      data += written;
      length -= written;
    }

  return CAIRO_STATUS_SUCCESS;
}

static void
close_preview (void *data)
{
  gint fd = GPOINTER_TO_INT (data);

  close (fd);
}

784 785 786 787 788 789
static cairo_surface_t *
gtk_print_operation_unix_create_preview_surface (GtkPrintOperation *op,
                                                 GtkPageSetup      *page_setup,
                                                 gdouble           *dpi_x,
                                                 gdouble           *dpi_y,
                                                 gchar            **target)
790
{
Matthias Clasen's avatar
Matthias Clasen committed
791 792
  gchar *filename;
  gint fd;
793
  GtkPaperSize *paper_size;
Matthias Clasen's avatar
Matthias Clasen committed
794
  gdouble w, h;
Matthias Clasen's avatar
Matthias Clasen committed
795 796
  cairo_surface_t *surface;
  static cairo_user_data_key_t key;
797
  
Matthias Clasen's avatar
Matthias Clasen committed
798 799
  filename = g_build_filename (g_get_tmp_dir (), "previewXXXXXX.pdf", NULL);
  fd = g_mkstemp (filename);
800 801 802 803 804 805 806

  if (fd < 0)
    {
      g_free (filename);
      return NULL;
    }

Matthias Clasen's avatar
Matthias Clasen committed
807
  *target = filename;
808
  
809 810 811 812 813
  paper_size = gtk_page_setup_get_paper_size (page_setup);
  w = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
  h = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
    
  *dpi_x = *dpi_y = 72;
814
  surface = cairo_pdf_surface_create_for_stream (write_preview, GINT_TO_POINTER (fd), w, h);
Matthias Clasen's avatar
Matthias Clasen committed
815 816 817 818
 
  cairo_surface_set_user_data (surface, &key, GINT_TO_POINTER (fd), close_preview);

  return surface;
819 820
}

821 822 823 824
static void
gtk_print_operation_unix_preview_start_page (GtkPrintOperation *op,
                                             cairo_surface_t   *surface,
                                             cairo_t           *cr)
825 826 827
{
}

828 829 830 831
static void
gtk_print_operation_unix_preview_end_page (GtkPrintOperation *op,
                                           cairo_surface_t   *surface,
                                           cairo_t           *cr)
832 833
{
  cairo_show_page (cr);
834 835
}

836 837 838 839
static void
gtk_print_operation_unix_resize_preview_surface (GtkPrintOperation *op,
                                                 GtkPageSetup      *page_setup,
                                                 cairo_surface_t   *surface)
840
{
Matthias Clasen's avatar
Matthias Clasen committed
841
  gdouble w, h;
842
  
843 844
  w = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
  h = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
845 846 847
  cairo_pdf_surface_set_size (surface, w, h);
}

848 849 850 851 852
static GtkPrintOperationResult
gtk_print_operation_unix_run_dialog (GtkPrintOperation *op,
                                     gboolean           show_dialog,
                                     GtkWindow         *parent,
                                     gboolean          *do_print)
853 854 855 856
 {
  GtkWidget *pd;
  PrintResponseData rdata;
  gint response;  
Matthias Clasen's avatar
Matthias Clasen committed
857
  const gchar *printer_name;
858 859 860
   
  rdata.op = op;
  rdata.do_print = FALSE;
861
  rdata.do_preview = FALSE;
862 863 864
  rdata.result = GTK_PRINT_OPERATION_RESULT_CANCEL;
  rdata.print_cb = NULL;
  rdata.destroy = NULL;
Alexander Larsson's avatar
Alexander Larsson committed
865 866
  rdata.parent = parent;
  rdata.loop = NULL;
867

868
  if (show_dialog)
Alexander Larsson's avatar
Alexander Larsson committed
869 870
    {
      pd = get_print_dialog (op, parent);
871

Alexander Larsson's avatar
Alexander Larsson committed
872 873 874 875 876 877 878 879 880 881 882 883
      response = gtk_dialog_run (GTK_DIALOG (pd));
      handle_print_response (pd, response, &rdata);
    }
  else
    {
      printer_name = NULL;
      if (op->priv->print_settings)
	printer_name = gtk_print_settings_get_printer (op->priv->print_settings);
      
      rdata.loop = g_main_loop_new (NULL, FALSE);
      find_printer (printer_name,
		    (GFunc) found_printer, &rdata);
884

885
      gdk_threads_leave ();  
Alexander Larsson's avatar
Alexander Larsson committed
886
      g_main_loop_run (rdata.loop);
887
      gdk_threads_enter ();  
888

Alexander Larsson's avatar
Alexander Larsson committed
889
      g_main_loop_unref (rdata.loop);
890
      rdata.loop = NULL;
Alexander Larsson's avatar
Alexander Larsson committed
891
    }
892

Alexander Larsson's avatar
Alexander Larsson committed
893 894
  *do_print = rdata.do_print;
  
895 896 897 898
  return rdata.result;
}


Matthias Clasen's avatar
Matthias Clasen committed
899 900
typedef struct 
{
901 902 903 904
  GtkPageSetup         *page_setup;
  GtkPageSetupDoneFunc  done_cb;
  gpointer              data;
  GDestroyNotify        destroy;
905 906 907 908 909 910 911
} PageSetupResponseData;

static void
page_setup_data_free (gpointer data)
{
  PageSetupResponseData *rdata = data;

Matthias Clasen's avatar
Matthias Clasen committed
912 913 914
  if (rdata->page_setup)
    g_object_unref (rdata->page_setup);

915 916 917 918 919 920 921 922 923 924
  g_free (rdata);
}

static void
handle_page_setup_response (GtkWidget *dialog,
			    gint       response,
			    gpointer   data)
{
  GtkPageSetupUnixDialog *psd;
  PageSetupResponseData *rdata = data;
925

926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953
  psd = GTK_PAGE_SETUP_UNIX_DIALOG (dialog);
  if (response == GTK_RESPONSE_OK)
    rdata->page_setup = gtk_page_setup_unix_dialog_get_page_setup (psd);

  gtk_widget_destroy (dialog);

  if (rdata->done_cb)
    rdata->done_cb (rdata->page_setup, rdata->data);

  if (rdata->destroy)
    rdata->destroy (rdata);
}

static GtkWidget *
get_page_setup_dialog (GtkWindow        *parent,
		       GtkPageSetup     *page_setup,
		       GtkPrintSettings *settings)
{
  GtkWidget *dialog;

  dialog = gtk_page_setup_unix_dialog_new (NULL, parent);
  if (page_setup)
    gtk_page_setup_unix_dialog_set_page_setup (GTK_PAGE_SETUP_UNIX_DIALOG (dialog),
					       page_setup);
  gtk_page_setup_unix_dialog_set_print_settings (GTK_PAGE_SETUP_UNIX_DIALOG (dialog),
						 settings);

  return dialog;
954 955
}

956 957
/**
 * gtk_print_run_page_setup_dialog:
958 959
 * @parent: (allow-none): transient parent
 * @page_setup: (allow-none): an existing #GtkPageSetup
960
 * @settings: a #GtkPrintSettings
961 962 963
 *
 * Runs a page setup dialog, letting the user modify the values from
 * @page_setup. If the user cancels the dialog, the returned #GtkPageSetup
964 965 966 967 968 969
 * is identical to the passed in @page_setup, otherwise it contains the 
 * modifications done in the dialog.
 *
 * Note that this function may use a recursive mainloop to show the page
 * setup dialog. See gtk_print_run_page_setup_dialog_async() if this is 
 * a problem.
970
 * 
971
 * Returns: (transfer full): a new #GtkPageSetup
972 973 974
 *
 * Since: 2.10
 */
975 976 977 978 979 980
GtkPageSetup *
gtk_print_run_page_setup_dialog (GtkWindow        *parent,
				 GtkPageSetup     *page_setup,
				 GtkPrintSettings *settings)
{
  GtkWidget *dialog;
981 982
  gint response;
  PageSetupResponseData rdata;  
983
  
984 985 986 987 988 989 990 991 992 993 994 995 996 997 998
  rdata.page_setup = NULL;
  rdata.done_cb = NULL;
  rdata.data = NULL;
  rdata.destroy = NULL;

  dialog = get_page_setup_dialog (parent, page_setup, settings);
  response = gtk_dialog_run (GTK_DIALOG (dialog));
  handle_page_setup_response (dialog, response, &rdata);
 
  if (rdata.page_setup)
    return rdata.page_setup;
  else if (page_setup)
    return gtk_page_setup_copy (page_setup);
  else
    return gtk_page_setup_new ();
999 1000
}

1001 1002
/**
 * gtk_print_run_page_setup_dialog_async:
1003 1004
 * @parent: (allow-none): transient parent, or %NULL
 * @page_setup: (allow-none): an existing #GtkPageSetup, or %NULL
1005
 * @settings: a #GtkPrintSettings
1006 1007
 * @done_cb: (scope async): a function to call when the user saves
 *           the modified page setup
1008 1009
 * @data: user data to pass to @done_cb
 * 
Matthias Clasen's avatar
Matthias Clasen committed
1010
 * Runs a page setup dialog, letting the user modify the values from @page_setup. 
1011
 *
Matthias Clasen's avatar
Matthias Clasen committed
1012 1013 1014
 * In contrast to gtk_print_run_page_setup_dialog(), this function  returns after 
 * showing the page setup dialog on platforms that support this, and calls @done_cb 
 * from a signal handler for the ::response signal of the dialog.
1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042
 *
 * Since: 2.10
 */
void
gtk_print_run_page_setup_dialog_async (GtkWindow            *parent,
				       GtkPageSetup         *page_setup,
				       GtkPrintSettings     *settings,
				       GtkPageSetupDoneFunc  done_cb,
				       gpointer              data)
{
  GtkWidget *dialog;
  PageSetupResponseData *rdata;
  
  dialog = get_page_setup_dialog (parent, page_setup, settings);
  gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
  
  rdata = g_new (PageSetupResponseData, 1);
  rdata->page_setup = NULL;
  rdata->done_cb = done_cb;
  rdata->data = data;
  rdata->destroy = page_setup_data_free;

  g_signal_connect (dialog, "response",
		    G_CALLBACK (handle_page_setup_response), rdata);
 
  gtk_window_present (GTK_WINDOW (dialog));
 }

Matthias Clasen's avatar
Matthias Clasen committed
1043 1044
struct _PrinterFinder 
{
Alexander Larsson's avatar
Alexander Larsson committed
1045 1046 1047
  gboolean found_printer;
  GFunc func;
  gpointer data;
Matthias Clasen's avatar
Matthias Clasen committed
1048
  gchar *printer_name;
Alexander Larsson's avatar
Alexander Larsson committed
1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074
  GList *backends;
  guint timeout_tag;
  GtkPrinter *printer;
  GtkPrinter *default_printer;
  GtkPrinter *first_printer;
};

static gboolean
find_printer_idle (gpointer data)
{
  PrinterFinder *finder = data;
  GtkPrinter *printer;

  if (finder->printer != NULL)
    printer = finder->printer;
  else if (finder->default_printer != NULL)
    printer = finder->default_printer;
  else if (finder->first_printer != NULL)
    printer = finder->first_printer;
  else
    printer = NULL;

  finder->func (printer, finder->data);
  
  printer_finder_free (finder);

1075
  return G_SOURCE_REMOVE;
Alexander Larsson's avatar
Alexander Larsson committed
1076 1077 1078 1079 1080 1081 1082
}

static void
printer_added_cb (GtkPrintBackend *backend, 
                  GtkPrinter      *printer, 
		  PrinterFinder   *finder)
{
1083 1084 1085 1086 1087
  if (finder->found_printer)
    return;

  /* FIXME this skips "Print to PDF" - is this intentional ? */
  if (gtk_printer_is_virtual (printer))
Alexander Larsson's avatar
Alexander Larsson committed
1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127
    return;

  if (finder->printer_name != NULL &&
      strcmp (gtk_printer_get_name (printer), finder->printer_name) == 0)
    {
      finder->printer = g_object_ref (printer);
      finder->found_printer = TRUE;
    }
  else if (finder->default_printer == NULL &&
	   gtk_printer_is_default (printer))
    {
      finder->default_printer = g_object_ref (printer);
      if (finder->printer_name == NULL)
	finder->found_printer = TRUE;
    }
  else
    if (finder->first_printer == NULL)
      finder->first_printer = g_object_ref (printer);
  
  if (finder->found_printer)
    g_idle_add (find_printer_idle, finder);
}

static void
printer_list_done_cb (GtkPrintBackend *backend, 
		      PrinterFinder   *finder)
{
  finder->backends = g_list_remove (finder->backends, backend);
  
  g_signal_handlers_disconnect_by_func (backend, printer_added_cb, finder);
  g_signal_handlers_disconnect_by_func (backend, printer_list_done_cb, finder);
  
  gtk_print_backend_destroy (backend);
  g_object_unref (backend);

  if (finder->backends == NULL && !finder->found_printer)
    g_idle_add (find_printer_idle, finder);
}

static void
Matthias Clasen's avatar
Matthias Clasen committed
1128
find_printer_init (PrinterFinder   *finder,
Alexander Larsson's avatar
Alexander Larsson committed
1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155
		   GtkPrintBackend *backend)
{
  GList *list;
  GList *node;

  list = gtk_print_backend_get_printer_list (backend);

  node = list;
  while (node != NULL)
    {
      printer_added_cb (backend, node->data, finder);
      node = node->next;

      if (finder->found_printer)
	break;
    }

  g_list_free (list);

  if (gtk_print_backend_printer_list_is_done (backend))
    {
      finder->backends = g_list_remove (finder->backends, backend);
      gtk_print_backend_destroy (backend);
      g_object_unref (backend);
    }
  else
    {
Matthias Clasen's avatar
Matthias Clasen committed
1156
      g_signal_connect (backend, "printer-added", 
Alexander Larsson's avatar
Alexander Larsson committed
1157 1158
			(GCallback) printer_added_cb, 
			finder);
Matthias Clasen's avatar
Matthias Clasen committed
1159
      g_signal_connect (backend, "printer-list-done", 
Alexander Larsson's avatar
Alexander Larsson committed
1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196
			(GCallback) printer_list_done_cb, 
			finder);
    }

}

static void
printer_finder_free (PrinterFinder *finder)
{
  GList *l;
  
  g_free (finder->printer_name);
  
  if (finder->printer)
    g_object_unref (finder->printer);
  
  if (finder->default_printer)
    g_object_unref (finder->default_printer);
  
  if (finder->first_printer)
    g_object_unref (finder->first_printer);

  for (l = finder->backends; l != NULL; l = l->next)
    {
      GtkPrintBackend *backend = l->data;
      g_signal_handlers_disconnect_by_func (backend, printer_added_cb, finder);
      g_signal_handlers_disconnect_by_func (backend, printer_list_done_cb, finder);
      gtk_print_backend_destroy (backend);
      g_object_unref (backend);
    }
  
  g_list_free (finder->backends);
  
  g_free (finder);
}

static void 
Matthias Clasen's avatar
Matthias Clasen committed
1197 1198 1199
find_printer (const gchar *printer,
	      GFunc        func,
	      gpointer     data)
Alexander Larsson's avatar
Alexander Larsson committed
1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222
{
  GList *node, *next;
  PrinterFinder *finder;

  finder = g_new0 (PrinterFinder, 1);

  finder->printer_name = g_strdup (printer);
  finder->func = func;
  finder->data = data;
  
  finder->backends = NULL;
  if (g_module_supported ())
    finder->backends = gtk_print_backend_load_modules ();

  for (node = finder->backends; !finder->found_printer && node != NULL; node = next)
    {
      next = node->next;
      find_printer_init (finder, GTK_PRINT_BACKEND (node->data));
    }

  if (finder->backends == NULL && !finder->found_printer)
    g_idle_add (find_printer_idle, finder);
}
1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292


GtkPrintOperationResult
_gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
						  gboolean           show_dialog,
						  GtkWindow         *parent,
						  gboolean          *do_print)
{
  if (gtk_should_use_portal ())
    return gtk_print_operation_portal_run_dialog (op, show_dialog, parent, do_print);
  else
    return gtk_print_operation_unix_run_dialog (op, show_dialog, parent, do_print);
}
void
_gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation          *op,
							gboolean                    show_dialog,
                                                        GtkWindow                  *parent,
							GtkPrintOperationPrintFunc  print_cb)
{
  if (gtk_should_use_portal ())
    gtk_print_operation_portal_run_dialog_async (op, show_dialog, parent, print_cb);
  else
    gtk_print_operation_unix_run_dialog_async (op, show_dialog, parent, print_cb);
}

void
_gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
                                                      cairo_surface_t   *surface,
                                                      GtkWindow         *parent,
                                                      const gchar       *filename)
{
  if (gtk_should_use_portal ())
    gtk_print_operation_portal_launch_preview (op, surface, parent, filename);
  else
    gtk_print_operation_unix_launch_preview (op, surface, parent, filename);
}

cairo_surface_t *
_gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation *op,
							      GtkPageSetup      *page_setup,
							      gdouble           *dpi_x,
							      gdouble           *dpi_y,
							      gchar            **target)
{
  return gtk_print_operation_unix_create_preview_surface (op, page_setup, dpi_x, dpi_y, target);
}

void
_gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation *op,
							      GtkPageSetup      *page_setup,
							      cairo_surface_t   *surface)
{
  gtk_print_operation_unix_resize_preview_surface (op, page_setup, surface);
}

void
_gtk_print_operation_platform_backend_preview_start_page (GtkPrintOperation *op,
							  cairo_surface_t   *surface,
							  cairo_t           *cr)
{
  gtk_print_operation_unix_preview_start_page (op, surface, cr);
}

void
_gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op,
							cairo_surface_t   *surface,
							cairo_t           *cr)
{
  gtk_print_operation_unix_preview_end_page (op, surface, cr);
}