[gtk+] Add portal support to GtkPrintOperation



commit 25fed0342094686bae8a97981838235204b818c7
Author: Matthias Clasen <mclasen redhat com>
Date:   Tue Jul 5 01:36:56 2016 -0400

    Add portal support to GtkPrintOperation
    
    Make GtkPrintOperation talk to org.freedesktop.portal.Print when
    running in a sandbox.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=768499

 gtk/Makefile.am                |    8 +-
 gtk/gtkprintoperation-portal.c |  626 ++++++++++++++++++++++++++++++++++++++++
 gtk/gtkprintoperation-portal.h |   40 +++
 gtk/gtkprintoperation-unix.c   |  138 +++++++---
 4 files changed, 777 insertions(+), 35 deletions(-)
---
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 966a60b..81692ce 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -987,9 +987,12 @@ gtk_os_unix_c_sources =            \
        gtkprinteroptionwidget.c        \
        gtkprintjob.c                   \
        gtkprintoperation-unix.c        \
+       gtkprintoperation-portal.h      \
+       gtkprintoperation-portal.c      \
        gtkprintunixdialog.c            \
         gtkprintbackend.c              \
        gtksearchenginetracker.c
+
 if OS_UNIX
 gtk_private_h_sources += \
        gtkiconcachevalidator.h         \
@@ -999,6 +1002,7 @@ gtk_private_h_sources += \
        gtkprinteroptionset.h           \
        gtkprinteroptionwidget.h        \
        gtksearchenginetracker.h
+
 gtk_c_sources += $(gtk_os_unix_c_sources)
 endif
 
@@ -1143,6 +1147,7 @@ gtk_extra_sources =                               \
 MAINTAINERCLEANFILES = \
        $(gtk_built_sources)                    \
        $(gtk_dbus_built_sources)               \
+       $(print_portal_built_sources)           \
        $(stamp_files)
 
 DISTCLEANFILES =
@@ -1208,7 +1213,8 @@ CLEANFILES = $(gen_sources)
 
 BUILT_SOURCES = \
        $(gtk_built_sources) \
-       $(gtk_dbus_built_sources)
+       $(gtk_dbus_built_sources) \
+       $(print_portal_built_sources)
 
 # all autogenerated files need to be generated in the srcdir,
 # so old versions get remade and are not confused with newer
diff --git a/gtk/gtkprintoperation-portal.c b/gtk/gtkprintoperation-portal.c
new file mode 100644
index 0000000..20857cc
--- /dev/null
+++ b/gtk/gtkprintoperation-portal.c
@@ -0,0 +1,626 @@
+/* GTK - The GIMP Toolkit
+ * gtkprintoperation-portal.c: Print Operation Details for sandboxed apps
+ * Copyright (C) 2016, 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
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <cairo-pdf.h>
+#include <cairo-ps.h>
+
+#include <gio/gunixfdlist.h>
+
+#include "gtkprintoperation-private.h"
+#include "gtkprintoperation-portal.h"
+#include "gtkprintsettings.h"
+#include "gtkpagesetup.h"
+#include "gtkprintbackend.h"
+#include "gtkshow.h"
+#include "gtkintl.h"
+
+#ifdef GDK_WINDOWING_X11
+#include <gdk/gdkx.h>
+#endif
+
+typedef struct {
+  GtkPrintOperation *op;
+  GDBusProxy *proxy;
+  guint response_signal_id;
+  gboolean do_print;
+  GtkPrintOperationResult result;
+  GtkPrintOperationPrintFunc print_cb;
+  GtkWindow *parent;
+  GMainLoop *loop;
+  guint32 token;
+  GDestroyNotify destroy;
+} PortalData;
+
+static void
+portal_data_free (gpointer data)
+{
+  PortalData *portal = data;
+
+  g_object_unref (portal->op);
+  g_object_unref (portal->proxy);
+  if (portal->loop)
+    g_main_loop_unref (portal->loop);
+
+  g_free (portal);
+}
+
+typedef struct {
+  GDBusProxy *proxy;
+  GtkPrintJob *job;
+  guint32 token;
+  cairo_surface_t *surface;
+  GMainLoop *loop;
+  gboolean file_written;
+} GtkPrintOperationPortal;
+
+static void
+op_portal_free (GtkPrintOperationPortal *op_portal)
+{
+  g_clear_object (&op_portal->proxy);
+  g_clear_object (&op_portal->job);
+  if (op_portal->loop)
+    g_main_loop_unref (op_portal->loop);
+  g_free (op_portal);
+}
+
+static void
+portal_start_page (GtkPrintOperation *op,
+                   GtkPrintContext   *print_context,
+                   GtkPageSetup      *page_setup)
+{
+  GtkPrintOperationPortal *op_portal = op->priv->platform_data;
+  GtkPaperSize *paper_size;
+  cairo_surface_type_t type;
+  gdouble w, h;
+
+  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);
+
+  type = cairo_surface_get_type (op_portal->surface);
+
+  if ((op->priv->manual_number_up < 2) ||
+      (op->priv->page_position % op->priv->manual_number_up == 0))
+    {
+      if (type == CAIRO_SURFACE_TYPE_PS)
+        {
+          cairo_ps_surface_set_size (op_portal->surface, w, h);
+          cairo_ps_surface_dsc_begin_page_setup (op_portal->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_portal->surface, "%%PageOrientation: Portrait");
+                break;
+
+              case GTK_PAGE_ORIENTATION_LANDSCAPE:
+              case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
+                cairo_ps_surface_dsc_comment (op_portal->surface, "%%PageOrientation: Landscape");
+                break;
+            }
+         }
+      else if (type == CAIRO_SURFACE_TYPE_PDF)
+        {
+          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);
+            }
+          cairo_pdf_surface_set_size (op_portal->surface, w, h);
+        }
+    }
+}
+
+static void
+portal_end_page (GtkPrintOperation *op,
+                 GtkPrintContext   *print_context)
+{
+  cairo_t *cr;
+
+  cr = gtk_print_context_get_cairo_context (print_context);
+
+  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);
+}
+
+static void
+print_file_done (GObject *source,
+                 GAsyncResult *result,
+                 gpointer data)
+{
+  GtkPrintOperation *op = data;
+  GtkPrintOperationPortal *op_portal = op->priv->platform_data;
+  GError *error = NULL;
+  GVariant *ret;
+
+  ret = g_dbus_proxy_call_finish (op_portal->proxy,
+                                  result,
+                                  &error);
+  if (ret == NULL)
+    {
+      if (op->priv->error == NULL)
+        op->priv->error = g_error_copy (error);
+      g_warning ("Print file failed: %s", error->message);
+      g_error_free (error);
+    }
+  else
+    g_variant_unref (ret);
+
+  if (op_portal->loop)
+    g_main_loop_quit (op_portal->loop);
+
+  g_object_unref (op);
+}
+
+static void
+portal_job_complete (GtkPrintJob  *job,
+                     gpointer      data,
+                     const GError *error)
+{
+  GtkPrintOperation *op = data;
+  GtkPrintOperationPortal *op_portal = op->priv->platform_data;
+  GtkPrintSettings *settings;
+  const char *uri;
+  char *filename;
+  int fd, idx;
+  GVariantBuilder opt_builder;
+  GUnixFDList *fd_list;
+
+  if (error != NULL && op->priv->error == NULL)
+    {
+      g_warning ("Print job failed: %s", error->message);
+      op->priv->error = g_error_copy (error);
+      return;
+    }
+
+  op_portal->file_written = TRUE;
+
+  settings = gtk_print_job_get_settings (job);
+  uri = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_OUTPUT_URI);
+  filename = g_filename_from_uri (uri, NULL, NULL);
+
+  fd = open (filename, O_RDONLY|O_CLOEXEC);
+  fd_list = g_unix_fd_list_new ();
+  idx = g_unix_fd_list_append (fd_list, fd, NULL);
+  close (fd);
+
+  g_free (filename);
+
+  g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
+  g_variant_builder_add (&opt_builder, "{sv}",  "token", g_variant_new_uint32 (op_portal->token));
+
+  g_dbus_proxy_call_with_unix_fd_list (op_portal->proxy,
+                                       "Print",
+                                       g_variant_new ("(ssh@a{sv})",
+                                                      "", /* window */
+                                                      _("Print"), /* title */
+                                                      idx,
+                                                      g_variant_builder_end (&opt_builder)),
+                                       G_DBUS_CALL_FLAGS_NONE,
+                                       -1,
+                                       fd_list,
+                                       NULL,
+                                       print_file_done,
+                                       op);
+  g_object_unref (fd_list);
+}
+
+static void
+portal_end_run (GtkPrintOperation *op,
+                gboolean           wait,
+                gboolean           cancelled)
+{
+  GtkPrintOperationPortal *op_portal = op->priv->platform_data;
+
+  cairo_surface_finish (op_portal->surface);
+
+  if (cancelled)
+    return;
+
+  if (wait)
+    op_portal->loop = g_main_loop_new (NULL, FALSE);
+
+  /* TODO: Check for error */
+  if (op_portal->job != NULL)
+    {
+      g_object_ref (op);
+      gtk_print_job_send (op_portal->job, portal_job_complete, op, NULL);
+    }
+
+  if (wait)
+    {
+      g_object_ref (op);
+      if (!op_portal->file_written)
+        {
+          gdk_threads_leave ();
+          g_main_loop_run (op_portal->loop);
+          gdk_threads_enter ();
+        }
+      g_object_unref (op);
+    }
+}
+
+static void
+finish_print (PortalData        *portal,
+              GtkPrinter        *printer,
+              GtkPageSetup      *page_setup,
+              GtkPrintSettings  *settings)
+{
+  GtkPrintOperation *op = portal->op;
+  GtkPrintOperationPrivate *priv = op->priv;
+  GtkPrintJob *job;
+  GtkPrintOperationPortal *op_portal;
+  cairo_t *cr;
+
+  if (portal->do_print)
+    {
+      gtk_print_operation_set_print_settings (op, settings);
+      priv->print_context = _gtk_print_context_new (op);
+
+      _gtk_print_context_set_hard_margins (priv->print_context, 0, 0, 0, 0);
+
+      gtk_print_operation_set_default_page_setup (op, page_setup);
+      _gtk_print_context_set_page_setup (priv->print_context, page_setup);
+
+      op_portal = g_new0 (GtkPrintOperationPortal, 1);
+      priv->platform_data = op_portal;
+      priv->free_platform_data = (GDestroyNotify) op_portal_free;
+
+      priv->start_page = portal_start_page;
+      priv->end_page = portal_end_page;
+      priv->end_run = portal_end_run;
+
+      job = gtk_print_job_new (priv->job_name, printer, settings, page_setup);
+      op_portal->job = job;
+
+      op_portal->proxy = g_object_ref (portal->proxy);
+      op_portal->token = portal->token;
+
+      op_portal->surface = gtk_print_job_get_surface (job, &priv->error);
+      if (op_portal->surface == NULL)
+        {
+          portal->result = GTK_PRINT_OPERATION_RESULT_ERROR;
+          portal->do_print = FALSE;
+          goto out;
+        }
+
+      cr = cairo_create (op_portal->surface);
+      gtk_print_context_set_cairo_context (priv->print_context, cr, 72, 72);
+      cairo_destroy (cr);
+
+      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);
+    }
+
+out:
+  if (portal->print_cb)
+    portal->print_cb (op, portal->parent, portal->do_print, portal->result);
+
+  if (portal->destroy)
+    portal->destroy (portal);
+}
+
+static GtkPrinter *
+find_file_printer (void)
+{
+  GList *backends, *l, *printers;
+  GtkPrinter *printer;
+
+  printer = NULL;
+
+  backends = gtk_print_backend_load_modules ();
+  for (l = backends; l; l = l->next)
+    {
+      GtkPrintBackend *backend = l->data;
+      if (strcmp (G_OBJECT_TYPE_NAME (backend), "GtkPrintBackendFile") == 0)
+        {
+          printers = gtk_print_backend_get_printer_list (backend);
+          printer = printers->data;
+          g_list_free (printers);
+          break;
+        }
+    }
+  g_list_free (backends);
+
+  return printer;
+}
+
+static void
+prepare_print_response (GDBusConnection *connection,
+                        const char      *sender_name,
+                        const char      *object_path,
+                        const char      *interface_name,
+                        const char      *signal_name,
+                        GVariant        *parameters,
+                        gpointer         data)
+{
+  PortalData *portal = data;
+  guint32 response;
+  GVariant *options;
+
+  if (portal->response_signal_id != 0)
+    {
+      g_dbus_connection_signal_unsubscribe (connection,
+                                            portal->response_signal_id);
+      portal->response_signal_id = 0;
+    }
+
+  g_variant_get (parameters, "(u@a{sv})", &response, &options);
+
+  portal->do_print = (response == 0);
+
+  if (portal->do_print)
+    {
+      GVariant *v;
+      GtkPrintSettings *settings;
+      GtkPageSetup *page_setup;
+      GtkPrinter *printer;
+      char *filename;
+      char *uri;
+      int fd;
+
+      portal->result = GTK_PRINT_OPERATION_RESULT_APPLY;
+
+      v = g_variant_lookup_value (options, "settings", G_VARIANT_TYPE_VARDICT);
+      settings = gtk_print_settings_new_from_gvariant (v);
+      g_variant_unref (v);
+
+      v = g_variant_lookup_value (options, "page-setup", G_VARIANT_TYPE_VARDICT);
+      page_setup = gtk_page_setup_new_from_gvariant (v);
+      g_variant_unref (v);
+
+      g_variant_lookup (options, "token", "u", &portal->token);
+
+      printer = find_file_printer ();
+
+      fd = g_file_open_tmp ("gtkprintXXXXXX", &filename, NULL);
+      uri = g_filename_to_uri (filename, NULL, NULL);
+      gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_OUTPUT_URI, uri);
+      g_free (uri);
+      close (fd);
+
+      finish_print (portal, printer, page_setup, settings);
+      g_free (filename);
+    }
+  else
+    portal->result = GTK_PRINT_OPERATION_RESULT_CANCEL;
+
+  if (portal->loop)
+    g_main_loop_quit (portal->loop);
+}
+
+static void
+prepare_print_called (GObject      *source,
+                      GAsyncResult *result,
+                      gpointer      data)
+{
+  PortalData *portal = data;
+  GError *error = NULL;
+  const char *handle = NULL;
+  GVariant *ret;
+
+  ret = g_dbus_proxy_call_finish (portal->proxy, result, &error);
+  if (ret == NULL)
+    {
+      if (portal->op->priv->error == NULL)
+        portal->op->priv->error = g_error_copy (error);
+      g_error_free (error);
+      if (portal->loop)
+        g_main_loop_quit (portal->loop);
+      return;
+    }
+  else
+    g_variant_get (ret, "(&o)", &handle);
+
+  portal->response_signal_id =
+    g_dbus_connection_signal_subscribe (g_dbus_proxy_get_connection (G_DBUS_PROXY (portal->proxy)),
+                                        "org.freedesktop.portal.Desktop",
+                                        "org.freedesktop.portal.Request",
+                                        "Response",
+                                        handle,
+                                        NULL,
+                                        G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
+                                        prepare_print_response,
+                                        portal, NULL);
+
+  g_variant_unref (ret);
+}
+
+PortalData *
+create_portal_data (GtkPrintOperation          *op,
+                    GtkWindow                  *parent,
+                    GtkPrintOperationPrintFunc  print_cb)
+{
+  GDBusProxy *proxy;
+  PortalData *portal;
+  guint signal_id;
+  GError *error = NULL;
+
+  signal_id = g_signal_lookup ("create-custom-widget", GTK_TYPE_PRINT_OPERATION);
+  if (g_signal_has_handler_pending (op, signal_id, 0, TRUE))
+    g_warning ("GtkPrintOperation::create-custom-widget not supported with portal");
+
+  proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                         G_DBUS_PROXY_FLAGS_NONE,
+                                         NULL,
+                                         "org.freedesktop.portal.Desktop",
+                                         "/org/freedesktop/portal/desktop",
+                                         "org.freedesktop.portal.Print",
+                                         NULL,
+                                         &error);
+
+  if (proxy == NULL)
+    {
+      if (op->priv->error == NULL)
+        op->priv->error = g_error_copy (error);
+      g_error_free (error);
+      return NULL;
+    }
+
+  portal = g_new0 (PortalData, 1);
+  portal->proxy = proxy;
+  portal->op = g_object_ref (op);
+  portal->parent = parent;
+  portal->result = GTK_PRINT_OPERATION_RESULT_CANCEL;
+  portal->print_cb = print_cb;
+
+  if (print_cb) /* async case */
+    {
+      portal->loop = NULL;
+      portal->destroy = portal_data_free;
+    }
+  else
+    {
+      portal->loop = g_main_loop_new (NULL, FALSE);
+      portal->destroy = NULL;
+    }
+
+  return portal;
+}
+
+static void
+call_prepare_print (GtkPrintOperation *op,
+                    PortalData        *portal)
+{
+  GtkPrintOperationPrivate *priv = op->priv;
+  GVariant *settings;
+  GVariant *setup;
+  GVariantBuilder opt_builder;
+  GVariant *options;
+  char *parent_window_str = NULL;
+
+  g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
+  options = g_variant_builder_end (&opt_builder);
+
+  if (priv->print_settings)
+    settings = gtk_print_settings_to_gvariant (priv->print_settings);
+  else
+    {
+      GVariantBuilder builder;
+      g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
+      settings = g_variant_builder_end (&builder);
+    }
+
+  if (priv->default_page_setup)
+    setup = gtk_page_setup_to_gvariant (priv->default_page_setup);
+  else
+    {
+      GtkPageSetup *page_setup = gtk_page_setup_new ();
+      setup = gtk_page_setup_to_gvariant (page_setup);
+      g_object_unref (page_setup);
+    }
+
+  if (portal->parent != NULL && gtk_widget_is_visible (GTK_WIDGET (portal->parent)))
+    {
+      GdkWindow *window = gtk_widget_get_window (GTK_WIDGET (portal->parent));
+#ifdef GDK_WINDOWING_X11
+      if (GDK_IS_X11_WINDOW (window))
+        parent_window_str = g_strdup_printf ("x11:%x", (guint32)gdk_x11_window_get_xid (window));
+#endif
+    }
+
+  g_dbus_proxy_call (portal->proxy,
+                     "PreparePrint",
+                     g_variant_new ("(ss@a{sv}@a{sv}@a{sv})",
+                                    parent_window_str ? parent_window_str : "",
+                                    _("Print"), /* title */
+                                    settings,
+                                    setup,
+                                    options),
+                     G_DBUS_CALL_FLAGS_NONE,
+                     -1,
+                     NULL,
+                     prepare_print_called,
+                     portal);
+
+  g_free (parent_window_str);
+}
+
+GtkPrintOperationResult
+gtk_print_operation_portal_run_dialog (GtkPrintOperation *op,
+                                       gboolean           show_dialog,
+                                       GtkWindow         *parent,
+                                       gboolean          *do_print)
+{
+  PortalData *portal;
+  GtkPrintOperationResult result;
+
+  portal = create_portal_data (op, parent, NULL);
+  if (portal == NULL)
+    return GTK_PRINT_OPERATION_RESULT_ERROR;
+
+  call_prepare_print (op, portal);
+
+  gdk_threads_leave ();
+  g_main_loop_run (portal->loop);
+  gdk_threads_enter ();
+
+  *do_print = portal->do_print;
+  result = portal->result;
+
+  portal_data_free (portal);
+
+  return result;
+}
+
+void
+gtk_print_operation_portal_run_dialog_async (GtkPrintOperation          *op,
+                                             gboolean                    show_dialog,
+                                             GtkWindow                  *parent,
+                                             GtkPrintOperationPrintFunc  print_cb)
+{
+  PortalData *portal;
+
+  portal = create_portal_data (op, parent, print_cb);
+  if (portal == NULL)
+    return;
+
+  call_prepare_print (op, portal);
+}
+
+void
+gtk_print_operation_portal_launch_preview (GtkPrintOperation *op,
+                                           cairo_surface_t   *surface,
+                                           GtkWindow         *parent,
+                                           const char        *filename)
+{
+  char *uri;
+
+  uri = g_filename_to_uri (filename, NULL, NULL);
+  gtk_show_uri_on_window (parent, uri, GDK_CURRENT_TIME, NULL);
+  g_free (uri);
+}
diff --git a/gtk/gtkprintoperation-portal.h b/gtk/gtkprintoperation-portal.h
new file mode 100644
index 0000000..cc81b12
--- /dev/null
+++ b/gtk/gtkprintoperation-portal.h
@@ -0,0 +1,40 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2016, 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
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_PRINT_OPERATION_PORTAL_H__
+#define __GTK_PRINT_OPERATION_PORTAL_H__
+
+#include "gtkprintoperation.h"
+
+G_BEGIN_DECLS
+
+GtkPrintOperationResult gtk_print_operation_portal_run_dialog             (GtkPrintOperation           *op,
+                                                                           gboolean                     
show_dialog,
+                                                                           GtkWindow                   
*parent,
+                                                                           gboolean                    
*do_print);
+void                    gtk_print_operation_portal_run_dialog_async       (GtkPrintOperation           *op,
+                                                                           gboolean                     
show_dialog,
+                                                                           GtkWindow                   
*parent,
+                                                                           GtkPrintOperationPrintFunc   
print_cb);
+void                    gtk_print_operation_portal_launch_preview         (GtkPrintOperation           *op,
+                                                                           cairo_surface_t             
*surface,
+                                                                           GtkWindow                   
*parent,
+                                                                           const char                  
*filename);
+
+G_END_DECLS
+
+#endif /* __GTK_PRINT_OPERATION_PORTAL_H__ */
diff --git a/gtk/gtkprintoperation-unix.c b/gtk/gtkprintoperation-unix.c
index d62173e..3709f5f 100644
--- a/gtk/gtkprintoperation-unix.c
+++ b/gtk/gtkprintoperation-unix.c
@@ -30,6 +30,7 @@
 
 #include <glib/gstdio.h>
 #include "gtkprintoperation-private.h"
+#include "gtkprintoperation-portal.h"
 #include "gtkmessagedialog.h"
 
 #include <cairo-pdf.h>
@@ -199,11 +200,11 @@ shell_command_substitute_file (const gchar *cmd,
   return g_string_free (final, FALSE);
 }
 
-void
-_gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
-                                                     cairo_surface_t   *surface,
-                                                     GtkWindow         *parent,
-                                                     const gchar       *filename)
+static void
+gtk_print_operation_unix_launch_preview (GtkPrintOperation *op,
+                                         cairo_surface_t   *surface,
+                                         GtkWindow         *parent,
+                                         const gchar       *filename)
 {
   GAppInfo *appinfo;
   GdkAppLaunchContext *context;
@@ -703,11 +704,11 @@ found_printer (GtkPrinter        *printer,
     g_object_unref (page_setup);
 }
 
-void
-_gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation          *op,
-                                                       gboolean                    show_dialog,
-                                                        GtkWindow                  *parent,
-                                                       GtkPrintOperationPrintFunc  print_cb)
+static void
+gtk_print_operation_unix_run_dialog_async (GtkPrintOperation          *op,
+                                           gboolean                    show_dialog,
+                                           GtkWindow                  *parent,
+                                           GtkPrintOperationPrintFunc  print_cb)
 {
   GtkWidget *pd;
   PrintResponseData *rdata;
@@ -778,12 +779,12 @@ close_preview (void *data)
   close (fd);
 }
 
-cairo_surface_t *
-_gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation *op,
-                                                             GtkPageSetup      *page_setup,
-                                                             gdouble           *dpi_x,
-                                                             gdouble           *dpi_y,
-                                                             gchar            **target)
+static cairo_surface_t *
+gtk_print_operation_unix_create_preview_surface (GtkPrintOperation *op,
+                                                 GtkPageSetup      *page_setup,
+                                                 gdouble           *dpi_x,
+                                                 gdouble           *dpi_y,
+                                                 gchar            **target)
 {
   gchar *filename;
   gint fd;
@@ -815,25 +816,25 @@ _gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation
   return surface;
 }
 
-void
-_gtk_print_operation_platform_backend_preview_start_page (GtkPrintOperation *op,
-                                                         cairo_surface_t   *surface,
-                                                         cairo_t           *cr)
+static void
+gtk_print_operation_unix_preview_start_page (GtkPrintOperation *op,
+                                             cairo_surface_t   *surface,
+                                             cairo_t           *cr)
 {
 }
 
-void
-_gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op,
-                                                       cairo_surface_t   *surface,
-                                                       cairo_t           *cr)
+static void
+gtk_print_operation_unix_preview_end_page (GtkPrintOperation *op,
+                                           cairo_surface_t   *surface,
+                                           cairo_t           *cr)
 {
   cairo_show_page (cr);
 }
 
-void
-_gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation *op,
-                                                             GtkPageSetup      *page_setup,
-                                                             cairo_surface_t   *surface)
+static void
+gtk_print_operation_unix_resize_preview_surface (GtkPrintOperation *op,
+                                                 GtkPageSetup      *page_setup,
+                                                 cairo_surface_t   *surface)
 {
   gdouble w, h;
   
@@ -842,12 +843,11 @@ _gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation
   cairo_pdf_surface_set_size (surface, w, h);
 }
 
-
-GtkPrintOperationResult
-_gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
-                                                 gboolean           show_dialog,
-                                                 GtkWindow         *parent,
-                                                 gboolean          *do_print)
+static GtkPrintOperationResult
+gtk_print_operation_unix_run_dialog (GtkPrintOperation *op,
+                                     gboolean           show_dialog,
+                                     GtkWindow         *parent,
+                                     gboolean          *do_print)
  {
   GtkWidget *pd;
   PrintResponseData rdata;
@@ -1218,3 +1218,73 @@ find_printer (const gchar *printer,
   if (finder->backends == NULL && !finder->found_printer)
     g_idle_add (find_printer_idle, finder);
 }
+
+
+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);
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]