forked from AuroraMiddleware/gtk
43c212ac28
This patch makes that work using 1 of 2 options: 1. Add all missing enums to the switch statement or 2. Cast the switch argument to a uint to avoid having to do that (mostly for GdkEventType). I even found a bug while doing that: clearing a GtkImage with a surface did not notify thae surface property. The reason for enabling this flag even though it is tedious at times is that it is very useful when adding values to an enum, because it makes GTK immediately warn about all the switch statements where this enum is relevant. And I expect changes to enums to be frequent during the GTK4 development cycle.
686 lines
21 KiB
C
686 lines
21 KiB
C
/* 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"
|
|
#include "gtkwindowprivate.h"
|
|
|
|
|
|
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;
|
|
GVariant *settings;
|
|
GVariant *setup;
|
|
GVariant *options;
|
|
char *prepare_print_handle;
|
|
} 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);
|
|
if (portal->settings)
|
|
g_variant_unref (portal->settings);
|
|
if (portal->setup)
|
|
g_variant_unref (portal->setup);
|
|
if (portal->options)
|
|
g_variant_unref (portal->options);
|
|
g_free (portal->prepare_print_handle);
|
|
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;
|
|
|
|
default:
|
|
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);
|
|
|
|
if (strcmp (portal->prepare_print_handle, handle) != 0)
|
|
{
|
|
g_free (portal->prepare_print_handle);
|
|
portal->prepare_print_handle = g_strdup (handle);
|
|
g_dbus_connection_signal_unsubscribe (g_dbus_proxy_get_connection (G_DBUS_PROXY (portal->proxy)),
|
|
portal->response_signal_id);
|
|
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);
|
|
}
|
|
|
|
static 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
|
|
window_handle_exported (GtkWindow *window,
|
|
const char *handle_str,
|
|
gpointer user_data)
|
|
{
|
|
PortalData *portal = user_data;
|
|
|
|
g_dbus_proxy_call (portal->proxy,
|
|
"PreparePrint",
|
|
g_variant_new ("(ss@a{sv}@a{sv}@a{sv})",
|
|
handle_str,
|
|
_("Print"), /* title */
|
|
portal->settings,
|
|
portal->setup,
|
|
portal->options),
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
-1,
|
|
NULL,
|
|
prepare_print_called,
|
|
portal);
|
|
}
|
|
|
|
static void
|
|
call_prepare_print (GtkPrintOperation *op,
|
|
PortalData *portal)
|
|
{
|
|
GtkPrintOperationPrivate *priv = op->priv;
|
|
GVariantBuilder opt_builder;
|
|
char *token;
|
|
char *sender;
|
|
int i;
|
|
|
|
token = g_strdup_printf ("gtk%d", g_random_int_range (0, G_MAXINT));
|
|
sender = g_strdup (g_dbus_connection_get_unique_name (g_dbus_proxy_get_connection (portal->proxy)) + 1);
|
|
for (i = 0; sender[i]; i++)
|
|
if (sender[i] == '.')
|
|
sender[i] = '_';
|
|
|
|
portal->prepare_print_handle = g_strdup_printf ("/org/fredesktop/portal/desktop/request/%s/%s", sender, token);
|
|
g_free (sender);
|
|
|
|
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",
|
|
portal->prepare_print_handle,
|
|
NULL,
|
|
G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
|
|
prepare_print_response,
|
|
portal, NULL);
|
|
|
|
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
|
|
g_variant_builder_add (&opt_builder, "{sv}", "handle_token", g_variant_new_string (token));
|
|
g_free (token);
|
|
portal->options = g_variant_builder_end (&opt_builder);
|
|
|
|
if (priv->print_settings)
|
|
portal->settings = gtk_print_settings_to_gvariant (priv->print_settings);
|
|
else
|
|
{
|
|
GVariantBuilder builder;
|
|
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
|
|
portal->settings = g_variant_builder_end (&builder);
|
|
}
|
|
|
|
if (priv->default_page_setup)
|
|
portal->setup = gtk_page_setup_to_gvariant (priv->default_page_setup);
|
|
else
|
|
{
|
|
GtkPageSetup *page_setup = gtk_page_setup_new ();
|
|
portal->setup = gtk_page_setup_to_gvariant (page_setup);
|
|
g_object_unref (page_setup);
|
|
}
|
|
|
|
g_variant_ref_sink (portal->options);
|
|
g_variant_ref_sink (portal->settings);
|
|
g_variant_ref_sink (portal->setup);
|
|
|
|
if (portal->parent != NULL &&
|
|
gtk_widget_is_visible (GTK_WIDGET (portal->parent)) &&
|
|
gtk_window_export_handle (portal->parent, window_handle_exported, portal))
|
|
return;
|
|
|
|
g_dbus_proxy_call (portal->proxy,
|
|
"PreparePrint",
|
|
g_variant_new ("(ss@a{sv}@a{sv}@a{sv})",
|
|
"",
|
|
_("Print"), /* title */
|
|
portal->settings,
|
|
portal->setup,
|
|
portal->options),
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
-1,
|
|
NULL,
|
|
prepare_print_called,
|
|
portal);
|
|
}
|
|
|
|
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);
|
|
}
|