wip: print op implementation

This does not work well
This commit is contained in:
Matthias Clasen 2023-02-06 23:09:45 +01:00
parent 87a6033476
commit 2e95b13be5
5 changed files with 242 additions and 45 deletions

View File

@ -25,6 +25,9 @@
#include "gtkdialogerror.h"
#include "gtkprivate.h"
#include "gtkprintoperation.h"
#include "gtkprintoperation-private.h"
#include <glib/gi18n-lib.h>
#include <gio/gfiledescriptorbased.h>
#include <gio/gunixfdlist.h>
@ -52,17 +55,18 @@ struct _GtkPrintDialog
GtkPrintSettings *print_settings;
GtkPageSetup *default_page_setup;
GDBusProxy *portal;
GtkWindow *exported_window;
char *title;
unsigned int modal : 1;
/* portal implementation */
GDBusProxy *portal;
char *portal_handle;
unsigned int token;
unsigned int response_signal_id;
char *title;
unsigned int modal : 1;
/* print operation implementation */
GtkPrintOperation *op;
};
enum
@ -97,6 +101,8 @@ gtk_print_dialog_finalize (GObject *object)
g_clear_object (&self->default_page_setup);
g_free (self->title);
g_clear_object (&self->op);
G_OBJECT_CLASS (gtk_print_dialog_parent_class)->finalize (object);
}
@ -378,7 +384,7 @@ gtk_print_dialog_set_title (GtkPrintDialog *self,
}
/* }}} */
/* {{{ Async implementation */
/* {{{ Async implementation, portal */
static void
send_close (GTask *task)
@ -409,9 +415,11 @@ send_close (GTask *task)
}
static gboolean
ensure_portal_proxy (GtkPrintDialog *self,
GError **error)
ensure_portal_proxy (GtkPrintDialog *self)
{
if (gdk_display_get_debug_flags (NULL) & GDK_DEBUG_NO_PORTALS)
return FALSE;
if (!self->portal)
self->portal = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_NONE,
@ -420,7 +428,7 @@ ensure_portal_proxy (GtkPrintDialog *self,
PORTAL_OBJECT_PATH,
PORTAL_PRINT_INTERFACE,
NULL,
error);
NULL);
return self->portal != NULL;
}
@ -793,6 +801,54 @@ print_window_handle_exported (GtkWindow *window,
g_free (token);
}
/* }}} */
/* {{{ Async implementation, op */
static void
ensure_print_op (GtkPrintDialog *self)
{
if (!self->op)
{
self->op = gtk_print_operation_new ();
gtk_print_operation_set_allow_async (self->op, TRUE);
}
}
static void
print_pages (GtkPrintOperation *op,
GtkWindow *parent,
gboolean do_print,
GtkPrintOperationResult result)
{
GtkPrintOperationPrivate *priv = op->priv;
GTask *task = g_object_get_data (G_OBJECT (op), "task");
GtkPrintDialog *self = GTK_PRINT_DIALOG (g_task_get_source_object (task));
g_print ("print_pages do_print == %d, result %d\n", do_print, result);
g_print ("op refcount %d\n", G_OBJECT (self->op)->ref_count);
if (!do_print)
{
if (priv->error)
g_task_return_error (task, g_error_copy (priv->error));
else if (priv->cancelled)
g_task_return_new_error (task, GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_DISMISSED, "Dismissed by user");
else
{
gtk_print_dialog_set_print_settings (self, gtk_print_operation_get_print_settings (op));
gtk_print_dialog_set_default_page_setup (self, gtk_print_operation_get_default_page_setup (op));
g_task_return_boolean (task, TRUE);
}
}
else
{
gtk_print_dialog_set_print_settings (self, gtk_print_operation_get_print_settings (op));
gtk_print_dialog_set_default_page_setup (self, gtk_print_operation_get_default_page_setup (op));
g_task_return_boolean (task, TRUE);
}
g_object_unref (task);
}
/* }}} */
/* {{{ Async API */
@ -822,7 +878,6 @@ gtk_print_dialog_prepare_print (GtkPrintDialog *self,
gpointer user_data)
{
GTask *task;
GError *error = NULL;
g_return_if_fail (GTK_IS_PRINT_DIALOG (self));
g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
@ -833,10 +888,16 @@ gtk_print_dialog_prepare_print (GtkPrintDialog *self,
g_task_set_check_cancellable (task, FALSE);
g_task_set_source_tag (task, gtk_print_dialog_prepare_print);
if (!ensure_portal_proxy (self, &error))
if (!ensure_portal_proxy (self))
{
g_task_return_error (task, error);
g_object_unref (task);
ensure_print_op (self);
g_object_set_data_full (G_OBJECT (self->op), "task", task, g_object_unref);
g_print ("op refcount %d\n", G_OBJECT (self->op)->ref_count);
_gtk_print_operation_platform_backend_run_dialog_async (self->op,
TRUE,
parent,
print_pages);
return;
}
@ -906,7 +967,6 @@ gtk_print_dialog_print_stream (GtkPrintDialog *self,
gpointer user_data)
{
GTask *task;
GError *error = NULL;
g_return_if_fail (GTK_IS_PRINT_DIALOG (self));
g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
@ -919,10 +979,33 @@ gtk_print_dialog_print_stream (GtkPrintDialog *self,
g_task_set_source_tag (task, gtk_print_dialog_print_stream);
g_task_set_task_data (task, g_object_ref (content), g_object_unref);
if (!ensure_portal_proxy (self, &error))
if (!ensure_portal_proxy (self))
{
GError *error = NULL;
int fd;
ensure_print_op (self);
fd = get_content_fd (G_OBJECT (content), &error);
if (fd == -1)
{
g_task_return_error (task, error);
g_object_unref (task);
}
else if (self->print_settings == NULL)
{
g_object_set_data (G_OBJECT (task), "fd", GINT_TO_POINTER (fd));
g_object_set_data_full (G_OBJECT (self->op), "task", task, g_object_unref);
_gtk_print_operation_platform_backend_run_dialog_async (self->op,
TRUE,
parent,
print_pages);
}
else
{
gtk_print_operation_platform_backend_print_file (self->op, "", self->title, fd, task);
g_object_unref (task);
}
return;
}
@ -1013,10 +1096,35 @@ gtk_print_dialog_print_file (GtkPrintDialog *self,
g_task_set_task_data (task, content, g_object_unref);
if (!ensure_portal_proxy (self, &error))
if (!ensure_portal_proxy (self))
{
int fd;
ensure_print_op (self);
fd = get_content_fd (G_OBJECT (content), &error);
g_print ("print file, op, fd == %d\n", fd);
if (fd == -1)
{
g_task_return_error (task, error);
g_object_unref (task);
}
else if (self->print_settings == NULL)
{
g_print ("show dialog first\n");
g_print ("op refcount %d\n", G_OBJECT (self->op)->ref_count);
g_object_set_data (G_OBJECT (task), "fd", GINT_TO_POINTER (fd));
g_object_set_data_full (G_OBJECT (self->op), "task", task, g_object_unref);
_gtk_print_operation_platform_backend_run_dialog_async (self->op,
TRUE,
parent,
print_pages);
}
else
{
gtk_print_operation_platform_backend_print_file (self->op, "", self->title, fd, task);
g_object_unref (task);
}
return;
}

View File

@ -172,36 +172,52 @@ print_file_done (GObject *source,
GtkPrintOperationPortal *op_portal = op->priv->platform_data;
GError *error = NULL;
GVariant *ret;
GTask *task;
task = g_object_get_data (G_OBJECT (op), "task");
ret = g_dbus_proxy_call_finish (op_portal->proxy,
result,
&error);
if (ret == NULL)
{
if (op->priv->error == NULL)
if (task)
g_task_return_error (task, g_error_copy (error));
else 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
{
if (task)
g_task_return_boolean (task, TRUE);
g_variant_unref (ret);
}
if (op_portal->loop)
g_main_loop_quit (op_portal->loop);
g_object_set_data (G_OBJECT (op), "task", NULL);
g_object_unref (op);
}
void
gtk_print_operation_portal_print_file (GtkPrintOperation *op,
GtkWindow *parent,
int fd)
const char *window_handle,
const char *title,
int fd,
GTask *task)
{
GtkPrintOperationPortal *op_portal = op->priv->platform_data;
int idx;
GVariantBuilder opt_builder;
GUnixFDList *fd_list;
if (task)
g_object_set_data_full (G_OBJECT (op), "task", g_object_ref (task), g_object_unref);
fd_list = g_unix_fd_list_new ();
idx = g_unix_fd_list_append (fd_list, fd, NULL);
@ -211,8 +227,8 @@ gtk_print_operation_portal_print_file (GtkPrintOperation *op,
g_dbus_proxy_call_with_unix_fd_list (op_portal->proxy,
"Print",
g_variant_new ("(ssh@a{sv})",
"", /* window */
_("Print"), /* title */
window_handle,
title,
idx,
g_variant_builder_end (&opt_builder)),
G_DBUS_CALL_FLAGS_NONE,
@ -252,7 +268,7 @@ portal_job_complete (GtkPrintJob *job,
fd = open (filename, O_RDONLY|O_CLOEXEC);
g_free (filename);
gtk_print_operation_portal_print_file (op, NULL, fd);
gtk_print_operation_portal_print_file (op, "", _("Print"), fd, NULL);
}
static void

View File

@ -36,8 +36,10 @@ void gtk_print_operation_portal_launch_preview (GtkPr
const char *filename);
void gtk_print_operation_portal_print_file (GtkPrintOperation *op,
GtkWindow *parent,
int fd);
const char *window_handle,
const char *title,
int fd,
GTask *task);
G_END_DECLS

View File

@ -128,8 +128,10 @@ void _gtk_print_operation_platform_backend_preview_end_page
cairo_t *cr);
void gtk_print_operation_platform_backend_print_file (GtkPrintOperation *op,
GtkWindow *parent,
int fd);
const char *window_handle,
const char *title,
int fd,
GTask *task);
void _gtk_print_operation_set_status (GtkPrintOperation *op,
GtkPrintStatus status,

View File

@ -510,6 +510,7 @@ print_response_data_free (gpointer data)
{
PrintResponseData *rdata = data;
g_print ("free rdata: op refcount %d\n", G_OBJECT (rdata->op)->ref_count);
g_object_unref (rdata->op);
g_free (rdata);
}
@ -526,6 +527,7 @@ finish_print (PrintResponseData *rdata,
GtkPrintJob *job;
double top, bottom, left, right;
g_print ("finish_print: op refcount %d\n", G_OBJECT (rdata->op)->ref_count);
if (rdata->do_print)
{
gtk_print_operation_set_print_settings (op, settings);
@ -899,23 +901,88 @@ gtk_print_operation_unix_run_dialog (GtkPrintOperation *op,
return rdata.result;
}
typedef struct {
GtkPrintOperation *op;
int fd;
GTask *task;
} PrintFileData;
static void
free_print_file_data (gpointer data)
{
PrintFileData *f = data;
g_object_unref (f->op);
g_clear_object (&f->task);
g_free (f);
}
static void
complete_func (GtkPrintJob *job,
gpointer data,
const GError *error)
{
PrintFileData *f = data;
GtkPrintOperationPrivate *priv = f->op->priv;
if (error)
{
if (f->task)
g_task_return_error (f->task, g_error_copy (error));
else if (priv->error == NULL)
priv->error = g_error_copy (error);
}
else if (f->task)
g_task_return_boolean (f->task, TRUE);
free_print_file_data (data);
}
static void
print_file (GtkPrinter *printer,
gpointer data)
{
PrintFileData *f = data;
GtkPrintOperationPrivate *priv = f->op->priv;
GtkPrintSettings *print_settings;
GtkPageSetup *default_page_setup;
GtkPrintJob *job;
if (priv->print_settings)
print_settings = g_object_ref (priv->print_settings);
else
print_settings = gtk_print_settings_new ();
if (priv->default_page_setup)
default_page_setup = g_object_ref (priv->default_page_setup);
else
default_page_setup = gtk_page_setup_new ();
job = gtk_print_job_new ("printjob", printer, print_settings, default_page_setup);
gtk_print_job_set_source_fd (job, f->fd, NULL);
gtk_print_job_send (job, complete_func, data, free_print_file_data);
g_object_unref (print_settings);
g_object_unref (default_page_setup);
}
static void
gtk_print_operation_unix_print_file (GtkPrintOperation *op,
GtkWindow *parent,
int fd)
int fd,
GTask *task)
{
#if 0
PrintFileData *data;
const char *printer_name = NULL;
data = g_new (PrintFileData, 1);
data->op = g_object_ref (op);
data->fd = fd;
data->task = task ? g_object_ref (task) : NULL;
if (op->priv->print_settings)
printer_name = gtk_print_settings_get_printer (op->priv->print_settings);
find_printer (printer_name, (GFunc) found_printer, rdata);
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);
#endif
find_printer (printer_name, (GFunc) print_file, data);
}
typedef struct
@ -1291,13 +1358,15 @@ _gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
void
gtk_print_operation_platform_backend_print_file (GtkPrintOperation *op,
GtkWindow *parent,
int fd)
const char *window_handle,
const char *title,
int fd,
GTask *task)
{
if (gdk_should_use_portal ())
gtk_print_operation_portal_print_file (op, parent, fd);
if (gdk_display_get_debug_flags (NULL) & GDK_DEBUG_PORTALS)
gtk_print_operation_portal_print_file (op, window_handle, title, fd, task);
else
gtk_print_operation_unix_print_file (op, parent, fd);
gtk_print_operation_unix_print_file (op, fd, task);
}
cairo_surface_t *