summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog55
-rw-r--r--ChangeLog.pre-2-1055
-rw-r--r--gtk/gtk.symbols2
-rw-r--r--gtk/gtkpagesetupunixdialog.c30
-rw-r--r--gtk/gtkprintbackend.c307
-rw-r--r--gtk/gtkprintbackend.h88
-rw-r--r--gtk/gtkprinter.c67
-rw-r--r--gtk/gtkprinter.h2
-rw-r--r--gtk/gtkprintoperation-private.h6
-rw-r--r--gtk/gtkprintoperation-unix.c385
-rw-r--r--gtk/gtkprintoperation.c13
-rw-r--r--gtk/gtkprintunixdialog.c27
-rw-r--r--modules/printbackends/cups/gtkcupsutils.c20
-rw-r--r--modules/printbackends/cups/gtkcupsutils.h7
-rw-r--r--modules/printbackends/cups/gtkprintbackendcups.c467
-rw-r--r--modules/printbackends/cups/gtkprintercups.c3
-rw-r--r--modules/printbackends/lpr/gtkprintbackendlpr.c123
-rw-r--r--modules/printbackends/pdf/gtkprintbackendpdf.c123
-rw-r--r--tests/Makefile.am3
-rw-r--r--tests/testnouiprint.c107
20 files changed, 1278 insertions, 612 deletions
diff --git a/ChangeLog b/ChangeLog
index ef7b5f310e..d3df94cc3c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,58 @@
+2006-05-04 Alexander Larsson <alexl@redhat.com>
+
+ * gtk/gtk.symbols:
+ Added new symbols
+
+ * gtk/gtkpagesetupunixdialog.c:
+ * gtk/gtkprintunixdialog.c:
+ Destroy backends when finalizing dialogs.
+ Fix printer leak in selected_printer_changed.
+
+ * gtk/gtkprintbackend.[ch]:
+ Convert from interface to baseclass.
+ Move printer hashtable here so that the baseclass can handle
+ the slightly complicated ownership model.
+ Add gtk_print_backend_destroy which runs the dispose method,
+ causing the ref-cycles between the backend and its printers
+ to be broken.
+ Add gtk_print_backend_unref_at_idle().
+
+ * gtk/gtkprinter.[ch]:
+ GtkPrinter objects now ref their backend so that its always
+ availible, since its needed for the printer object to work.
+ This causes a reference-cycle that is broken using
+ gtk_print_backend_destroy.
+ Add gtk_printer_compare.
+
+ * gtk/gtkprintoperation-private.h:
+ * gtk/gtkprintoperation-unix.c:
+ * gtk/gtkprintoperation.c:
+ Implement !show_dialog for unix.
+ Make sure the print data is fully spooled before returning
+ from a sync run_dialog.
+
+
+ * modules/printbackends/cups/gtkcupsutils.[ch]:
+ Add gtk_cups_request_ipp_add_strings
+
+ * modules/printbackends/cups/gtkprintbackendcups.c:
+ * modules/printbackends/cups/gtkprintercups.c:
+ * modules/printbackends/lpr/gtkprintbackendlpr.c:
+ * modules/printbackends/pdf/gtkprintbackendpdf.c:
+ Convert backends to derive instead of implementing interface.
+ Move common code into baseclass.
+ CUPS:
+ Remove the printer polling in dispose, not finalize.
+ In the cups watch, remove the backend at idle instead of
+ immediately, since the unref can cause the module to be unloaded.
+ Limit the number of printer attributes requested
+ Get printer uri in initial printer listing so that we can use
+ the printer object immediately.
+
+ * tests/Makefile.am:
+ * tests/testnouiprint.c:
+ Add testcase for !show_dialog.
+
2006-05-04 Matthias Clasen <mclasen@redhat.com>
* gtk/gtk.symbols:
diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10
index ef7b5f310e..d3df94cc3c 100644
--- a/ChangeLog.pre-2-10
+++ b/ChangeLog.pre-2-10
@@ -1,3 +1,58 @@
+2006-05-04 Alexander Larsson <alexl@redhat.com>
+
+ * gtk/gtk.symbols:
+ Added new symbols
+
+ * gtk/gtkpagesetupunixdialog.c:
+ * gtk/gtkprintunixdialog.c:
+ Destroy backends when finalizing dialogs.
+ Fix printer leak in selected_printer_changed.
+
+ * gtk/gtkprintbackend.[ch]:
+ Convert from interface to baseclass.
+ Move printer hashtable here so that the baseclass can handle
+ the slightly complicated ownership model.
+ Add gtk_print_backend_destroy which runs the dispose method,
+ causing the ref-cycles between the backend and its printers
+ to be broken.
+ Add gtk_print_backend_unref_at_idle().
+
+ * gtk/gtkprinter.[ch]:
+ GtkPrinter objects now ref their backend so that its always
+ availible, since its needed for the printer object to work.
+ This causes a reference-cycle that is broken using
+ gtk_print_backend_destroy.
+ Add gtk_printer_compare.
+
+ * gtk/gtkprintoperation-private.h:
+ * gtk/gtkprintoperation-unix.c:
+ * gtk/gtkprintoperation.c:
+ Implement !show_dialog for unix.
+ Make sure the print data is fully spooled before returning
+ from a sync run_dialog.
+
+
+ * modules/printbackends/cups/gtkcupsutils.[ch]:
+ Add gtk_cups_request_ipp_add_strings
+
+ * modules/printbackends/cups/gtkprintbackendcups.c:
+ * modules/printbackends/cups/gtkprintercups.c:
+ * modules/printbackends/lpr/gtkprintbackendlpr.c:
+ * modules/printbackends/pdf/gtkprintbackendpdf.c:
+ Convert backends to derive instead of implementing interface.
+ Move common code into baseclass.
+ CUPS:
+ Remove the printer polling in dispose, not finalize.
+ In the cups watch, remove the backend at idle instead of
+ immediately, since the unref can cause the module to be unloaded.
+ Limit the number of printer attributes requested
+ Get printer uri in initial printer listing so that we can use
+ the printer object immediately.
+
+ * tests/Makefile.am:
+ * tests/testnouiprint.c:
+ Add testcase for !show_dialog.
+
2006-05-04 Matthias Clasen <mclasen@redhat.com>
* gtk/gtk.symbols:
diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols
index eb09e7da24..afcbe2c123 100644
--- a/gtk/gtk.symbols
+++ b/gtk/gtk.symbols
@@ -2550,9 +2550,11 @@ gtk_paper_size_get_default
gtk_print_backend_error_quark
gtk_print_backend_get_type G_GNUC_CONST
gtk_print_backend_get_printer_list
+gtk_print_backend_printer_list_is_done
gtk_print_backend_find_printer
gtk_print_backend_print_stream
gtk_print_backend_load_modules
+gtk_print_backend_unref_at_idle
#endif
#endif
#endif
diff --git a/gtk/gtkpagesetupunixdialog.c b/gtk/gtkpagesetupunixdialog.c
index 72a5cd074c..5daf854959 100644
--- a/gtk/gtkpagesetupunixdialog.c
+++ b/gtk/gtkpagesetupunixdialog.c
@@ -110,6 +110,17 @@ static void populate_dialog (GtkPageSetupUnixDialog *dialog
static void fill_paper_sizes_from_printer (GtkPageSetupUnixDialog *dialog,
GtkPrinter *printer);
static void run_custom_paper_dialog (GtkPageSetupUnixDialog *dialog);
+static void printer_added_cb (GtkPrintBackend *backend,
+ GtkPrinter *printer,
+ GtkPageSetupUnixDialog *dialog);
+static void printer_removed_cb (GtkPrintBackend *backend,
+ GtkPrinter *printer,
+ GtkPageSetupUnixDialog *dialog);
+static void printer_status_cb (GtkPrintBackend *backend,
+ GtkPrinter *printer,
+ GtkPageSetupUnixDialog *dialog);
+
+
static const char * const common_paper_sizes[] = {
"na_letter",
@@ -369,7 +380,9 @@ gtk_page_setup_unix_dialog_finalize (GObject *object)
{
GtkPageSetupUnixDialog *dialog = GTK_PAGE_SETUP_UNIX_DIALOG (object);
GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
-
+ GtkPrintBackend *backend;
+ GList *node;
+
if (priv->request_details_tag)
{
g_source_remove (priv->request_details_tag);
@@ -397,6 +410,21 @@ gtk_page_setup_unix_dialog_finalize (GObject *object)
g_free (priv->waiting_for_printer);
priv->waiting_for_printer = NULL;
+ for (node = priv->print_backends; node != NULL; node = node->next)
+ {
+ backend = GTK_PRINT_BACKEND (node->data);
+
+ g_signal_handlers_disconnect_by_func (backend, printer_added_cb, dialog);
+ g_signal_handlers_disconnect_by_func (backend, printer_removed_cb, dialog);
+ g_signal_handlers_disconnect_by_func (backend, printer_status_cb, dialog);
+
+ gtk_print_backend_destroy (backend);
+ g_object_unref (backend);
+ }
+
+ g_list_free (priv->print_backends);
+ priv->print_backends = NULL;
+
G_OBJECT_CLASS (gtk_page_setup_unix_dialog_parent_class)->finalize (object);
}
diff --git a/gtk/gtkprintbackend.c b/gtk/gtkprintbackend.c
index 32e6596d0a..272d2f3957 100644
--- a/gtk/gtkprintbackend.c
+++ b/gtk/gtkprintbackend.c
@@ -29,7 +29,30 @@
#include "gtkprintbackend.h"
#include "gtkalias.h"
-static void gtk_print_backend_base_init (gpointer g_class);
+#define GTK_PRINT_BACKEND_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_PRINT_BACKEND, GtkPrintBackendPrivate))
+
+static void gtk_print_backend_dispose (GObject *object);
+
+struct _GtkPrintBackendPrivate
+{
+ GHashTable *printers;
+ guint printer_list_requested : 1;
+ guint printer_list_done : 1;
+};
+
+enum {
+ PRINTER_LIST_CHANGED,
+ PRINTER_LIST_DONE,
+ PRINTER_ADDED,
+ PRINTER_REMOVED,
+ PRINTER_STATUS_CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static GObjectClass *backend_parent_class;
GQuark
gtk_print_backend_error_quark (void)
@@ -142,7 +165,7 @@ _gtk_print_backend_module_class_init (GtkPrintBackendModuleClass *class)
{
GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class);
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
-
+
module_class->load = gtk_print_backend_module_load;
module_class->unload = gtk_print_backend_module_unload;
@@ -272,107 +295,255 @@ gtk_print_backend_load_modules ()
/*****************************************
* GtkPrintBackend *
*****************************************/
-GType
-gtk_print_backend_get_type (void)
+
+G_DEFINE_TYPE (GtkPrintBackend, gtk_print_backend, G_TYPE_OBJECT);
+
+static void
+gtk_print_backend_class_init (GtkPrintBackendClass *class)
{
- static GType print_backend_type = 0;
+ GObjectClass *object_class;
+ object_class = (GObjectClass *) class;
- if (!print_backend_type)
+ backend_parent_class = g_type_class_peek_parent (class);
+
+ object_class->dispose = gtk_print_backend_dispose;
+
+ g_type_class_add_private (class, sizeof (GtkPrintBackendPrivate));
+
+
+ signals[PRINTER_LIST_CHANGED] =
+ g_signal_new ("printer-list-changed",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ signals[PRINTER_LIST_DONE] =
+ g_signal_new ("printer-list-done",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_done),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ signals[PRINTER_ADDED] =
+ g_signal_new ("printer-added",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkPrintBackendClass, printer_added),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
+ signals[PRINTER_REMOVED] =
+ g_signal_new ("printer-removed",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkPrintBackendClass, printer_removed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
+ signals[PRINTER_STATUS_CHANGED] =
+ g_signal_new ("printer-status-changed",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkPrintBackendClass, printer_status_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
+}
+
+static void
+gtk_print_backend_init (GtkPrintBackend *backend)
+{
+ GtkPrintBackendPrivate *priv;
+
+ priv = backend->priv = GTK_PRINT_BACKEND_GET_PRIVATE (backend);
+
+ priv->printers = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_object_unref);
+}
+
+static void
+gtk_print_backend_dispose (GObject *object)
+{
+ GtkPrintBackend *backend;
+ GtkPrintBackendPrivate *priv;
+
+ backend = GTK_PRINT_BACKEND (object);
+ priv = backend->priv;
+
+ /* We unref the printers in dispose, not in finalize so that
+ we can break refcount cycles with gtk_print_backend_destroy */
+ if (priv->printers)
{
- static const GTypeInfo print_backend_info =
- {
- sizeof (GtkPrintBackendIface), /* class_size */
- gtk_print_backend_base_init, /* base_init */
- NULL, /* base_finalize */
- };
-
- print_backend_type = g_type_register_static (G_TYPE_INTERFACE,
- "GtkPrintBackend",
- &print_backend_info, 0);
-
- g_type_interface_add_prerequisite (print_backend_type, G_TYPE_OBJECT);
+ g_hash_table_destroy (priv->printers);
+ priv->printers = NULL;
}
- return print_backend_type;
+ backend_parent_class->dispose (object);
}
+
static void
-gtk_print_backend_base_init (gpointer g_class)
+printer_hash_to_sorted_active_list (const gchar *key,
+ gpointer value,
+ GList **out_list)
{
- static gboolean initialized = FALSE;
+ GtkPrinter *printer;
+
+ printer = GTK_PRINTER (value);
+
+ if (gtk_printer_get_name (printer) == NULL)
+ return;
+
+ if (!gtk_printer_is_active (printer))
+ return;
+
+ *out_list = g_list_insert_sorted (*out_list, value, (GCompareFunc) gtk_printer_compare);
+}
+
+
+void
+gtk_print_backend_add_printer (GtkPrintBackend *backend,
+ GtkPrinter *printer)
+{
+ GtkPrintBackendPrivate *priv;
- if (!initialized)
- {
- GType iface_type = G_TYPE_FROM_INTERFACE (g_class);
+ g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
- g_signal_new ("printer-list-changed",
- iface_type,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkPrintBackendIface, printer_list_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
- g_signal_new ("printer-added",
- iface_type,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkPrintBackendIface, printer_added),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, G_TYPE_OBJECT);
- g_signal_new ("printer-removed",
- iface_type,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkPrintBackendIface, printer_removed),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, G_TYPE_OBJECT);
- g_signal_new ("printer-status-changed",
- iface_type,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkPrintBackendIface, printer_status_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, G_TYPE_OBJECT);
+ priv = backend->priv;
- initialized = TRUE;
+ if (!priv->printers)
+ return;
+
+ g_hash_table_insert (priv->printers,
+ g_strdup (gtk_printer_get_name (printer)),
+ g_object_ref (printer));
+}
+
+void
+gtk_print_backend_remove_printer (GtkPrintBackend *backend,
+ GtkPrinter *printer)
+{
+ GtkPrintBackendPrivate *priv;
+
+ g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
+ priv = backend->priv;
+
+ if (!priv->printers)
+ return;
+
+ g_hash_table_remove (priv->printers,
+ gtk_printer_get_name (printer));
+}
+
+void
+gtk_print_backend_set_list_done (GtkPrintBackend *backend)
+{
+ if (!backend->priv->printer_list_done)
+ {
+ backend->priv->printer_list_done = TRUE;
+ g_signal_emit (backend, signals[PRINTER_LIST_DONE], 0);
}
}
+
GList *
-gtk_print_backend_get_printer_list (GtkPrintBackend *print_backend)
+gtk_print_backend_get_printer_list (GtkPrintBackend *backend)
{
- g_return_val_if_fail (GTK_IS_PRINT_BACKEND (print_backend), NULL);
+ GtkPrintBackendPrivate *priv;
+ GList *result;
+
+ g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
+
+ priv = backend->priv;
+
+ result = NULL;
+ if (priv->printers != NULL)
+ g_hash_table_foreach (priv->printers,
+ (GHFunc) printer_hash_to_sorted_active_list,
+ &result);
+
+ if (!priv->printer_list_requested && priv->printers != NULL)
+ {
+ if (GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list)
+ GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list (backend);
+ priv->printer_list_requested = TRUE;
+ }
+
+ return result;;
+}
- return GTK_PRINT_BACKEND_GET_IFACE (print_backend)->get_printer_list (print_backend);
+gboolean
+gtk_print_backend_printer_list_is_done (GtkPrintBackend *print_backend)
+{
+ g_return_val_if_fail (GTK_IS_PRINT_BACKEND (print_backend), TRUE);
+ return print_backend->priv->printer_list_done;
}
GtkPrinter *
-gtk_print_backend_find_printer (GtkPrintBackend *print_backend,
+gtk_print_backend_find_printer (GtkPrintBackend *backend,
const gchar *printer_name)
{
- g_return_val_if_fail (GTK_IS_PRINT_BACKEND (print_backend), NULL);
+ GtkPrintBackendPrivate *priv;
+ GtkPrinter *printer;
+
+ g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
+
+ priv = backend->priv;
- return GTK_PRINT_BACKEND_GET_IFACE (print_backend)->find_printer (print_backend, printer_name);
+ if (priv->printers)
+ printer = g_hash_table_lookup (priv->printers, printer_name);
+ else
+ printer = NULL;
+ return printer;
}
void
-gtk_print_backend_print_stream (GtkPrintBackend *print_backend,
+gtk_print_backend_print_stream (GtkPrintBackend *backend,
GtkPrintJob *job,
gint data_fd,
GtkPrintJobCompleteFunc callback,
gpointer user_data,
GDestroyNotify dnotify)
{
- g_return_if_fail (GTK_IS_PRINT_BACKEND (print_backend));
-
- GTK_PRINT_BACKEND_GET_IFACE (print_backend)->print_stream (print_backend,
- job,
- data_fd,
- callback,
- user_data,
- dnotify);
+ g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
+
+ GTK_PRINT_BACKEND_GET_CLASS (backend)->print_stream (backend,
+ job,
+ data_fd,
+ callback,
+ user_data,
+ dnotify);
+}
+
+static gboolean
+unref_at_idle_cb (gpointer data)
+{
+ g_object_unref (data);
+ return FALSE;
+}
+
+void
+gtk_print_backend_unref_at_idle (GtkPrintBackend *print_backend)
+{
+ g_idle_add (unref_at_idle_cb, print_backend);
+}
+
+void
+gtk_print_backend_destroy (GtkPrintBackend *print_backend)
+{
+ /* The lifecycle of print backends and printers are tied, such that
+ the backend owns the printers, but the printers also ref the backend.
+ This is so that if the app has a reference to a printer its backend
+ will be around. However, this results in a cycle, which we break
+ with this call, which causes the print backend to release its printers.
+ */
+ g_object_run_dispose (G_OBJECT (print_backend));
}
#define __GTK_PRINT_BACKEND_C__
diff --git a/gtk/gtkprintbackend.h b/gtk/gtkprintbackend.h
index 4e2a05c4b3..fc48690ba3 100644
--- a/gtk/gtkprintbackend.h
+++ b/gtk/gtkprintbackend.h
@@ -39,7 +39,8 @@
G_BEGIN_DECLS
-typedef struct _GtkPrintBackendIface GtkPrintBackendIface;
+typedef struct _GtkPrintBackendClass GtkPrintBackendClass;
+typedef struct _GtkPrintBackendPrivate GtkPrintBackendPrivate;
#define GTK_PRINT_BACKEND_ERROR (gtk_print_backend_error_quark ())
@@ -51,22 +52,28 @@ typedef enum
GQuark gtk_print_backend_error_quark (void);
-#define GTK_TYPE_PRINT_BACKEND (gtk_print_backend_get_type ())
-#define GTK_PRINT_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINT_BACKEND, GtkPrintBackend))
-#define GTK_IS_PRINT_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINT_BACKEND))
-#define GTK_PRINT_BACKEND_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GTK_TYPE_PRINT_BACKEND, GtkPrintBackendIface))
+#define GTK_TYPE_PRINT_BACKEND (gtk_print_backend_get_type ())
+#define GTK_PRINT_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINT_BACKEND, GtkPrintBackend))
+#define GTK_PRINT_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINT_BACKEND, GtkPrintBackendClass))
+#define GTK_IS_PRINT_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINT_BACKEND))
+#define GTK_IS_PRINT_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINT_BACKEND))
+#define GTK_PRINT_BACKEND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINT_BACKEND, GtkPrintBackendClass))
-struct _GtkPrintBackendIface
+struct _GtkPrintBackend
{
- GTypeInterface base_iface;
+ GObject parent_instance;
- /* Global backend methods: */
- GList * (*get_printer_list) (GtkPrintBackend *printer_backend);
+ GtkPrintBackendPrivate *priv;
+};
- GtkPrinter * (*find_printer) (GtkPrintBackend *print_backend,
- const gchar *printer_name);
- void (*print_stream) (GtkPrintBackend *print_backend,
- GtkPrintJob *job,
+struct _GtkPrintBackendClass
+{
+ GObjectClass parent_class;
+
+ /* Global backend methods: */
+ void (*request_printer_list) (GtkPrintBackend *backend);
+ void (*print_stream) (GtkPrintBackend *backend,
+ GtkPrintJob *job,
gint data_fd,
GtkPrintJobCompleteFunc callback,
gpointer user_data,
@@ -97,26 +104,49 @@ struct _GtkPrintBackendIface
double *left,
double *right);
- /* Signals
- */
- void (*printer_list_changed) (void);
- void (*printer_added) (GtkPrinter *printer);
- void (*printer_removed) (GtkPrinter *printer);
- void (*printer_status_changed) (GtkPrinter *printer);
+ /* Signals */
+ void (*printer_list_changed) (GtkPrintBackend *backend);
+ void (*printer_list_done) (GtkPrintBackend *backend);
+ void (*printer_added) (GtkPrintBackend *backend,
+ GtkPrinter *printer);
+ void (*printer_removed) (GtkPrintBackend *backend,
+ GtkPrinter *printer);
+ void (*printer_status_changed) (GtkPrintBackend *backend,
+ GtkPrinter *printer);
+
+ /* Padding for future expansion */
+ void (*_gtk_reserved1) (void);
+ void (*_gtk_reserved2) (void);
+ void (*_gtk_reserved3) (void);
+ void (*_gtk_reserved4) (void);
+ void (*_gtk_reserved5) (void);
+ void (*_gtk_reserved6) (void);
+ void (*_gtk_reserved7) (void);
};
GType gtk_print_backend_get_type (void) G_GNUC_CONST;
-GList *gtk_print_backend_get_printer_list (GtkPrintBackend *print_backend);
-GtkPrinter *gtk_print_backend_find_printer (GtkPrintBackend *print_backend,
- const gchar *printer_name);
-void gtk_print_backend_print_stream (GtkPrintBackend *print_backend,
- GtkPrintJob *job,
- gint data_fd,
- GtkPrintJobCompleteFunc callback,
- gpointer user_data,
- GDestroyNotify dnotify);
-GList * gtk_print_backend_load_modules (void);
+GList *gtk_print_backend_get_printer_list (GtkPrintBackend *print_backend);
+gboolean gtk_print_backend_printer_list_is_done (GtkPrintBackend *print_backend);
+GtkPrinter *gtk_print_backend_find_printer (GtkPrintBackend *print_backend,
+ const gchar *printer_name);
+void gtk_print_backend_print_stream (GtkPrintBackend *print_backend,
+ GtkPrintJob *job,
+ gint data_fd,
+ GtkPrintJobCompleteFunc callback,
+ gpointer user_data,
+ GDestroyNotify dnotify);
+GList * gtk_print_backend_load_modules (void);
+void gtk_print_backend_unref_at_idle (GtkPrintBackend *print_backend);
+void gtk_print_backend_destroy (GtkPrintBackend *print_backend);
+
+/* Backend-only functions for GtkPrintBackend */
+
+void gtk_print_backend_add_printer (GtkPrintBackend *print_backend,
+ GtkPrinter *printer);
+void gtk_print_backend_remove_printer (GtkPrintBackend *print_backend,
+ GtkPrinter *printer);
+void gtk_print_backend_set_list_done (GtkPrintBackend *backend);
/* Backend-only functions for GtkPrinter */
diff --git a/gtk/gtkprinter.c b/gtk/gtkprinter.c
index 4ae748cec0..e9a197cb9c 100644
--- a/gtk/gtkprinter.c
+++ b/gtk/gtkprinter.c
@@ -52,7 +52,6 @@ struct _GtkPrinterPrivate
gchar *state_message;
gint job_count;
- /* Not ref:ed, backend owns printer. */
GtkPrintBackend *backend;
};
@@ -215,6 +214,9 @@ gtk_printer_finalize (GObject *object)
g_free (priv->state_message);
g_free (priv->icon_name);
+ if (priv->backend)
+ g_object_unref (priv->backend);
+
G_OBJECT_CLASS (gtk_printer_parent_class)->finalize (object);
}
@@ -234,7 +236,7 @@ gtk_printer_set_property (GObject *object,
break;
case PROP_BACKEND:
- priv->backend = GTK_PRINT_BACKEND (g_value_get_object (value));
+ priv->backend = GTK_PRINT_BACKEND (g_value_dup_object (value));
break;
case PROP_IS_VIRTUAL:
@@ -340,16 +342,6 @@ gtk_printer_get_backend (GtkPrinter *printer)
return printer->priv->backend;
}
-void
-gtk_printer_set_backend (GtkPrinter *printer,
- GtkPrintBackend *backend)
-{
- g_return_if_fail (GTK_IS_PRINTER (printer));
- g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
-
- printer->priv->backend = backend;
-}
-
/**
* gtk_printer_get_name:
* @printer: a #GtkPrinter
@@ -663,8 +655,8 @@ gtk_printer_set_is_default (GtkPrinter *printer,
void
_gtk_printer_request_details (GtkPrinter *printer)
{
- GtkPrintBackendIface *backend_iface = GTK_PRINT_BACKEND_GET_IFACE (printer->priv->backend);
- return backend_iface->printer_request_details (printer);
+ GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (printer->priv->backend);
+ return backend_class->printer_request_details (printer);
}
GtkPrinterOptionSet *
@@ -672,16 +664,16 @@ _gtk_printer_get_options (GtkPrinter *printer,
GtkPrintSettings *settings,
GtkPageSetup *page_setup)
{
- GtkPrintBackendIface *backend_iface = GTK_PRINT_BACKEND_GET_IFACE (printer->priv->backend);
- return backend_iface->printer_get_options (printer, settings, page_setup);
+ GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (printer->priv->backend);
+ return backend_class->printer_get_options (printer, settings, page_setup);
}
gboolean
_gtk_printer_mark_conflicts (GtkPrinter *printer,
GtkPrinterOptionSet *options)
{
- GtkPrintBackendIface *backend_iface = GTK_PRINT_BACKEND_GET_IFACE (printer->priv->backend);
- return backend_iface->printer_mark_conflicts (printer, options);
+ GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (printer->priv->backend);
+ return backend_class->printer_mark_conflicts (printer, options);
}
void
@@ -689,8 +681,8 @@ _gtk_printer_get_settings_from_options (GtkPrinter *printer,
GtkPrinterOptionSet *options,
GtkPrintSettings *settings)
{
- GtkPrintBackendIface *backend_iface = GTK_PRINT_BACKEND_GET_IFACE (printer->priv->backend);
- return backend_iface->printer_get_settings_from_options (printer, options, settings);
+ GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (printer->priv->backend);
+ return backend_class->printer_get_settings_from_options (printer, options, settings);
}
void
@@ -699,8 +691,8 @@ _gtk_printer_prepare_for_print (GtkPrinter *printer,
GtkPrintSettings *settings,
GtkPageSetup *page_setup)
{
- GtkPrintBackendIface *backend_iface = GTK_PRINT_BACKEND_GET_IFACE (printer->priv->backend);
- return backend_iface->printer_prepare_for_print (printer, print_job, settings, page_setup);
+ GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (printer->priv->backend);
+ return backend_class->printer_prepare_for_print (printer, print_job, settings, page_setup);
}
cairo_surface_t *
@@ -709,17 +701,17 @@ _gtk_printer_create_cairo_surface (GtkPrinter *printer,
gdouble height,
gint cache_fd)
{
- GtkPrintBackendIface *backend_iface = GTK_PRINT_BACKEND_GET_IFACE (printer->priv->backend);
+ GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (printer->priv->backend);
- return backend_iface->printer_create_cairo_surface (printer, width, height, cache_fd);
+ return backend_class->printer_create_cairo_surface (printer, width, height, cache_fd);
}
GList *
_gtk_printer_list_papers (GtkPrinter *printer)
{
- GtkPrintBackendIface *backend_iface = GTK_PRINT_BACKEND_GET_IFACE (printer->priv->backend);
+ GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (printer->priv->backend);
- return backend_iface->printer_list_papers (printer);
+ return backend_class->printer_list_papers (printer);
}
void
@@ -729,9 +721,28 @@ _gtk_printer_get_hard_margins (GtkPrinter *printer,
gdouble *left,
gdouble *right)
{
- GtkPrintBackendIface *backend_iface = GTK_PRINT_BACKEND_GET_IFACE (printer->priv->backend);
+ GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (printer->priv->backend);
- backend_iface->printer_get_hard_margins (printer, top, bottom, left, right);
+ backend_class->printer_get_hard_margins (printer, top, bottom, left, right);
+}
+
+gint
+gtk_printer_compare (GtkPrinter *a, GtkPrinter *b)
+{
+ const char *name_a, *name_b;
+
+ g_assert (GTK_IS_PRINTER (a) && GTK_IS_PRINTER (b));
+
+ name_a = gtk_printer_get_name (a);
+ name_b = gtk_printer_get_name (b);
+ if (name_a == NULL && name_b == NULL)
+ return 0;
+ else if (name_a == NULL)
+ return G_MAXINT;
+ else if (name_b == NULL)
+ return G_MININT;
+ else
+ return g_ascii_strcasecmp (name_a, name_b);
}
#define __GTK_PRINTER_C__
diff --git a/gtk/gtkprinter.h b/gtk/gtkprinter.h
index 90a0e6b0ae..6c9e056e15 100644
--- a/gtk/gtkprinter.h
+++ b/gtk/gtkprinter.h
@@ -78,6 +78,8 @@ gboolean gtk_printer_is_active (GtkPrinter *printer
gboolean gtk_printer_is_virtual (GtkPrinter *printer);
gboolean gtk_printer_is_default (GtkPrinter *printer);
+gint gtk_printer_compare (GtkPrinter *a,
+ GtkPrinter *b);
G_END_DECLS
diff --git a/gtk/gtkprintoperation-private.h b/gtk/gtkprintoperation-private.h
index cf38582dcc..2213967162 100644
--- a/gtk/gtkprintoperation-private.h
+++ b/gtk/gtkprintoperation-private.h
@@ -61,7 +61,8 @@ struct _GtkPrintOperationPrivate
GtkPageSetup *page_setup);
void (*end_page) (GtkPrintOperation *operation,
GtkPrintContext *print_context);
- void (*end_run) (GtkPrintOperation *operation);
+ void (*end_run) (GtkPrintOperation *operation,
+ gboolean wait);
GDestroyNotify free_platform_data;
};
@@ -70,7 +71,8 @@ GtkPrintOperationResult _gtk_print_operation_platform_backend_run_dialog (GtkPri
gboolean *do_print,
GError **error);
-typedef void (* GtkPrintOperationPrintFunc) (GtkPrintOperation *op);
+typedef void (* GtkPrintOperationPrintFunc) (GtkPrintOperation *op,
+ gboolean wait);
void _gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation *op,
GtkWindow *parent,
diff --git a/gtk/gtkprintoperation-unix.c b/gtk/gtkprintoperation-unix.c
index 4f74bf52ac..3b6f5561f5 100644
--- a/gtk/gtkprintoperation-unix.c
+++ b/gtk/gtkprintoperation-unix.c
@@ -42,8 +42,17 @@ typedef struct {
GtkPrintJob *job; /* the job we are sending to the printer */
gulong job_status_changed_tag;
GtkWindow *parent; /* just in case we need to throw error dialogs */
+ GMainLoop *loop;
+ gboolean data_sent;
} GtkPrintOperationUnix;
+typedef struct _PrinterFinder PrinterFinder;
+
+static void printer_finder_free (PrinterFinder *finder);
+static void find_printer (const char *printer,
+ GFunc func,
+ gpointer data);
+
static void
unix_start_page (GtkPrintOperation *op,
GtkPrintContext *print_context,
@@ -100,18 +109,37 @@ unix_finish_send (GtkPrintJob *job,
gtk_window_present (GTK_WINDOW (edialog));
}
+
+ op_unix->data_sent = TRUE;
+ if (op_unix->loop)
+ g_main_loop_quit (op_unix->loop);
}
static void
-unix_end_run (GtkPrintOperation *op)
+unix_end_run (GtkPrintOperation *op,
+ gboolean wait)
{
GtkPrintOperationUnix *op_unix = op->priv->platform_data;
-
+
+ if (wait)
+ op_unix->loop = g_main_loop_new (NULL, FALSE);
+
/* TODO: Check for error */
gtk_print_job_send (op_unix->job,
unix_finish_send,
op_unix, NULL,
NULL);
+
+ if (wait)
+ {
+ if (!op_unix->data_sent)
+ {
+ GDK_THREADS_LEAVE ();
+ g_main_loop_run (op_unix->loop);
+ GDK_THREADS_ENTER ();
+ }
+ g_main_loop_unref (op_unix->loop);
+ }
}
static void
@@ -154,6 +182,8 @@ typedef struct {
GtkPrintOperationResult result;
GtkPrintOperationPrintFunc print_cb;
GDestroyNotify destroy;
+ GtkWindow *parent;
+ GMainLoop *loop;
} PrintResponseData;
static void
@@ -166,41 +196,29 @@ print_response_data_free (gpointer data)
}
static void
-handle_print_response (GtkWidget *dialog,
- gint response,
- gpointer data)
+finish_print (PrintResponseData *rdata,
+ GtkPrinter *printer,
+ GtkPageSetup *page_setup,
+ GtkPrintSettings *settings)
{
- GtkPrintUnixDialog *pd = GTK_PRINT_UNIX_DIALOG (dialog);
- PrintResponseData *rdata = data;
GtkPrintOperation *op = rdata->op;
GtkPrintOperationPrivate *priv = op->priv;
- if (response == GTK_RESPONSE_OK)
+ priv->start_page = unix_start_page;
+ priv->end_page = unix_end_page;
+ priv->end_run = unix_end_run;
+
+ if (rdata->do_print)
{
GtkPrintOperationUnix *op_unix;
- GtkPrinter *printer;
- GtkPrintSettings *settings;
- GtkPageSetup *page_setup;
-
- rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
-
- printer = gtk_print_unix_dialog_get_selected_printer (GTK_PRINT_UNIX_DIALOG (pd));
- if (printer == NULL)
- goto out;
-
- rdata->do_print = TRUE;
-
- 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));
gtk_print_operation_set_print_settings (op, settings);
-
+
op_unix = g_new0 (GtkPrintOperationUnix, 1);
op_unix->job = gtk_print_job_new (priv->job_name,
printer,
settings,
page_setup);
- g_object_unref (settings);
rdata->op->priv->surface = gtk_print_job_get_surface (op_unix->job, rdata->error);
if (op->priv->surface == NULL)
@@ -216,7 +234,7 @@ handle_print_response (GtkWidget *dialog,
g_signal_connect (op_unix->job, "status_changed",
G_CALLBACK (job_status_changed_cb), op);
- op_unix->parent = gtk_window_get_transient_for (GTK_WINDOW (pd));
+ op_unix->parent = rdata->parent;
priv->dpi_x = 72;
priv->dpi_y = 72;
@@ -236,17 +254,11 @@ handle_print_response (GtkWidget *dialog,
priv->manual_orientation = op_unix->job->rotate_to_orientation;
}
- priv->start_page = unix_start_page;
- priv->end_page = unix_end_page;
- priv->end_run = unix_end_run;
-
out:
- gtk_widget_destroy (GTK_WIDGET (pd));
-
if (rdata->print_cb)
{
if (rdata->do_print)
- rdata->print_cb (op);
+ rdata->print_cb (op, FALSE);
else
_gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
}
@@ -255,6 +267,81 @@ handle_print_response (GtkWidget *dialog,
rdata->destroy (rdata);
}
+static void
+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;
+
+ if (response == GTK_RESPONSE_OK)
+ {
+ rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
+
+ printer = gtk_print_unix_dialog_get_selected_printer (GTK_PRINT_UNIX_DIALOG (pd));
+ if (printer == NULL)
+ goto out;
+
+ rdata->do_print = TRUE;
+
+ 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));
+ }
+
+ out:
+ finish_print (rdata, printer, page_setup, settings);
+
+ if (settings)
+ g_object_unref (settings);
+
+ gtk_widget_destroy (GTK_WIDGET (pd));
+}
+
+
+static void
+found_printer (GtkPrinter *printer,
+ 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);
+
+ if (printer != NULL) {
+ rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
+
+ 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 ();
+ }
+
+ finish_print (rdata, printer, page_setup, settings);
+
+ if (settings)
+ g_object_unref (settings);
+
+ if (page_setup)
+ g_object_unref (page_setup);
+}
+
void
_gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation *op,
GtkWindow *parent,
@@ -262,6 +349,7 @@ _gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation
{
GtkWidget *pd;
PrintResponseData *rdata;
+ const char *printer_name;
rdata = g_new (PrintResponseData, 1);
rdata->op = g_object_ref (op);
@@ -269,15 +357,29 @@ _gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation
rdata->result = GTK_PRINT_OPERATION_RESULT_CANCEL;
rdata->error = NULL;
rdata->print_cb = print_cb;
+ rdata->parent = parent;
+ rdata->loop = NULL;
rdata->destroy = print_response_data_free;
- pd = get_print_dialog (op, parent);
- gtk_window_set_modal (GTK_WINDOW (pd), TRUE);
-
- g_signal_connect (pd, "response",
- G_CALLBACK (handle_print_response), rdata);
+ if (op->priv->show_dialog)
+ {
+ pd = get_print_dialog (op, parent);
+ gtk_window_set_modal (GTK_WINDOW (pd), TRUE);
- gtk_window_present (GTK_WINDOW (pd));
+ 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);
+
+ find_printer (printer_name,
+ (GFunc) found_printer, rdata);
+ }
}
GtkPrintOperationResult
@@ -289,6 +391,7 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
GtkWidget *pd;
PrintResponseData rdata;
gint response;
+ const char *printer_name;
rdata.op = op;
rdata.do_print = FALSE;
@@ -296,14 +399,34 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
rdata.error = error;
rdata.print_cb = NULL;
rdata.destroy = NULL;
+ rdata.parent = parent;
+ rdata.loop = NULL;
- pd = get_print_dialog (op, parent);
+ if (op->priv->show_dialog)
+ {
+ pd = get_print_dialog (op, parent);
+ 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);
- response = gtk_dialog_run (GTK_DIALOG (pd));
- handle_print_response (pd, response, &rdata);
+ GDK_THREADS_LEAVE ();
+ g_main_loop_run (rdata.loop);
+ GDK_THREADS_ENTER ();
- *do_print = rdata.do_print;
+ g_main_loop_unref (rdata.loop);
+ }
+ *do_print = rdata.do_print;
+
return rdata.result;
}
@@ -448,6 +571,184 @@ gtk_print_run_page_setup_dialog_async (GtkWindow *parent,
gtk_window_present (GTK_WINDOW (dialog));
}
+struct _PrinterFinder {
+ gboolean found_printer;
+ GFunc func;
+ gpointer data;
+ char *printer_name;
+ 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);
+
+ return FALSE;
+}
+
+static void
+printer_added_cb (GtkPrintBackend *backend,
+ GtkPrinter *printer,
+ PrinterFinder *finder)
+{
+ if (gtk_printer_is_virtual (printer) ||
+ finder->found_printer)
+ 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
+find_printer_init (PrinterFinder *finder,
+ 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
+ {
+ g_signal_connect (backend,
+ "printer-added",
+ (GCallback) printer_added_cb,
+ finder);
+ g_signal_connect (backend,
+ "printer-list-done",
+ (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
+find_printer (const char *printer,
+ GFunc func,
+ gpointer data)
+{
+ 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);
+}
#define __GTK_PRINT_OPERATION_UNIX_C__
#include "gtkaliasdef.c"
diff --git a/gtk/gtkprintoperation.c b/gtk/gtkprintoperation.c
index cd52b8eb1f..998717d753 100644
--- a/gtk/gtkprintoperation.c
+++ b/gtk/gtkprintoperation.c
@@ -1115,7 +1115,8 @@ pdf_end_page (GtkPrintOperation *op,
}
static void
-pdf_end_run (GtkPrintOperation *op)
+pdf_end_run (GtkPrintOperation *op,
+ gboolean wait)
{
GtkPrintOperationPrivate *priv = op->priv;
@@ -1161,7 +1162,8 @@ run_pdf (GtkPrintOperation *op,
}
static void
-print_pages (GtkPrintOperation *op)
+print_pages (GtkPrintOperation *op,
+ gboolean wait)
{
GtkPrintOperationPrivate *priv = op->priv;
int page, range;
@@ -1289,8 +1291,7 @@ print_pages (GtkPrintOperation *op)
g_object_unref (initial_page_setup);
cairo_surface_finish (priv->surface);
- priv->end_run (op);
-
+ priv->end_run (op, wait);
}
/**
@@ -1343,7 +1344,7 @@ gtk_print_operation_run (GtkPrintOperation *op,
&do_print,
error);
if (do_print)
- print_pages (op);
+ print_pages (op, TRUE);
else
_gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
@@ -1384,7 +1385,7 @@ gtk_print_operation_run_async (GtkPrintOperation *op,
{
run_pdf (op, parent, &do_print, NULL);
if (do_print)
- print_pages (op);
+ print_pages (op, FALSE);
else
_gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
}
diff --git a/gtk/gtkprintunixdialog.c b/gtk/gtkprintunixdialog.c
index f2cdd8040a..59cf75321b 100644
--- a/gtk/gtkprintunixdialog.c
+++ b/gtk/gtkprintunixdialog.c
@@ -73,6 +73,15 @@ static void unschedule_idle_mark_conflicts (GtkPrintUnixDialog *dialog);
static void selected_printer_changed (GtkTreeSelection *selection,
GtkPrintUnixDialog *dialog);
static void clear_per_printer_ui (GtkPrintUnixDialog *dialog);
+static void printer_added_cb (GtkPrintBackend *backend,
+ GtkPrinter *printer,
+ GtkPrintUnixDialog *dialog);
+static void printer_removed_cb (GtkPrintBackend *backend,
+ GtkPrinter *printer,
+ GtkPrintUnixDialog *dialog);
+static void printer_status_cb (GtkPrintBackend *backend,
+ GtkPrinter *printer,
+ GtkPrintUnixDialog *dialog);
enum {
PROP_0,
@@ -281,6 +290,8 @@ gtk_print_unix_dialog_finalize (GObject *object)
{
GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
GtkPrintUnixDialogPrivate *priv = dialog->priv;
+ GtkPrintBackend *backend;
+ GList *node;
unschedule_idle_mark_conflicts (dialog);
@@ -339,6 +350,21 @@ gtk_print_unix_dialog_finalize (GObject *object)
g_free (priv->format_for_printer);
priv->format_for_printer = NULL;
+ for (node = priv->print_backends; node != NULL; node = node->next)
+ {
+ backend = GTK_PRINT_BACKEND (node->data);
+
+ g_signal_handlers_disconnect_by_func (backend, printer_added_cb, dialog);
+ g_signal_handlers_disconnect_by_func (backend, printer_removed_cb, dialog);
+ g_signal_handlers_disconnect_by_func (backend, printer_status_cb, dialog);
+
+ gtk_print_backend_destroy (backend);
+ g_object_unref (backend);
+ }
+
+ g_list_free (priv->print_backends);
+ priv->print_backends = NULL;
+
G_OBJECT_CLASS (gtk_print_unix_dialog_parent_class)->finalize (object);
}
@@ -1164,6 +1190,7 @@ selected_printer_changed (GtkTreeSelection *selection,
g_signal_connect (printer, "details-acquired",
G_CALLBACK (printer_details_acquired), dialog);
_gtk_printer_request_details (printer);
+ g_object_unref (printer);
return;
}
diff --git a/modules/printbackends/cups/gtkcupsutils.c b/modules/printbackends/cups/gtkcupsutils.c
index 458e1c4219..2ebf4a785f 100644
--- a/modules/printbackends/cups/gtkcupsutils.c
+++ b/modules/printbackends/cups/gtkcupsutils.c
@@ -242,6 +242,26 @@ gtk_cups_request_ipp_add_string (GtkCupsRequest *request,
value);
}
+void
+gtk_cups_request_ipp_add_strings (GtkCupsRequest *request,
+ ipp_tag_t group,
+ ipp_tag_t tag,
+ const char *name,
+ int num_values,
+ const char *charset,
+ const char * const *values)
+{
+ ippAddStrings (request->ipp_request,
+ group,
+ tag,
+ name,
+ num_values,
+ charset,
+ values);
+}
+
+
+
typedef struct
{
const char *name;
diff --git a/modules/printbackends/cups/gtkcupsutils.h b/modules/printbackends/cups/gtkcupsutils.h
index f49cd2e9bc..88fb8810f2 100644
--- a/modules/printbackends/cups/gtkcupsutils.h
+++ b/modules/printbackends/cups/gtkcupsutils.h
@@ -109,6 +109,13 @@ void gtk_cups_request_ipp_add_string (GtkCupsRequest *request,
const char *name,
const char *charset,
const char *value);
+void gtk_cups_request_ipp_add_strings (GtkCupsRequest *request,
+ ipp_tag_t group,
+ ipp_tag_t tag,
+ const char *name,
+ int num_values,
+ const char *charset,
+ const char * const *values);
gboolean gtk_cups_request_read_write (GtkCupsRequest *request);
GtkCupsPollState gtk_cups_request_get_poll_state (GtkCupsRequest *request);
void gtk_cups_request_free (GtkCupsRequest *request);
diff --git a/modules/printbackends/cups/gtkprintbackendcups.c b/modules/printbackends/cups/gtkprintbackendcups.c
index 0e10c275b0..13bdfdb0d4 100644
--- a/modules/printbackends/cups/gtkprintbackendcups.c
+++ b/modules/printbackends/cups/gtkprintbackendcups.c
@@ -89,14 +89,12 @@ typedef struct
struct _GtkPrintBackendCupsClass
{
- GObjectClass parent_class;
+ GtkPrintBackendClass parent_class;
};
struct _GtkPrintBackendCups
{
- GObject parent_instance;
-
- GHashTable *printers;
+ GtkPrintBackend parent_instance;
char *default_printer;
@@ -108,10 +106,10 @@ struct _GtkPrintBackendCups
static GObjectClass *backend_parent_class;
static void gtk_print_backend_cups_class_init (GtkPrintBackendCupsClass *class);
-static void gtk_print_backend_cups_iface_init (GtkPrintBackendIface *iface);
static void gtk_print_backend_cups_init (GtkPrintBackendCups *impl);
static void gtk_print_backend_cups_finalize (GObject *object);
-static GList * cups_get_printer_list (GtkPrintBackend *print_backend);
+static void gtk_print_backend_cups_dispose (GObject *object);
+static void cups_get_printer_list (GtkPrintBackend *print_backend);
static void cups_request_execute (GtkPrintBackendCups *print_backend,
GtkCupsRequest *request,
GtkPrintCupsResponseCallbackFunc callback,
@@ -145,6 +143,17 @@ static void cups_begin_polling_info (GtkPrintBack
GtkPrintJob *job,
int job_id);
static gboolean cups_job_info_poll_timeout (gpointer user_data);
+static void gtk_print_backend_cups_print_stream (GtkPrintBackend *backend,
+ GtkPrintJob *job,
+ gint data_fd,
+ GtkPrintJobCompleteFunc callback,
+ gpointer user_data,
+ GDestroyNotify dnotify);
+static cairo_surface_t * cups_printer_create_cairo_surface (GtkPrinter *printer,
+ gdouble width,
+ gdouble height,
+ gint cache_fd);
+
static void
gtk_print_backend_cups_register_type (GTypeModule *module)
@@ -164,21 +173,10 @@ gtk_print_backend_cups_register_type (GTypeModule *module)
(GInstanceInitFunc) gtk_print_backend_cups_init
};
- static const GInterfaceInfo print_backend_info =
- {
- (GInterfaceInitFunc) gtk_print_backend_cups_iface_init, /* interface_init */
- NULL, /* interface_finalize */
- NULL /* interface_data */
- };
-
print_backend_cups_type = g_type_module_register_type (module,
- G_TYPE_OBJECT,
+ GTK_TYPE_PRINT_BACKEND,
"GtkPrintBackendCups",
&print_backend_cups_info, 0);
- g_type_module_add_interface (module,
- print_backend_cups_type,
- GTK_TYPE_PRINT_BACKEND,
- &print_backend_info);
}
}
@@ -229,10 +227,23 @@ static void
gtk_print_backend_cups_class_init (GtkPrintBackendCupsClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+ GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_CLASS (class);
backend_parent_class = g_type_class_peek_parent (class);
gobject_class->finalize = gtk_print_backend_cups_finalize;
+ gobject_class->dispose = gtk_print_backend_cups_dispose;
+
+ backend_class->request_printer_list = cups_get_printer_list;
+ backend_class->print_stream = gtk_print_backend_cups_print_stream;
+ backend_class->printer_request_details = cups_printer_request_details;
+ backend_class->printer_create_cairo_surface = cups_printer_create_cairo_surface;
+ backend_class->printer_get_options = cups_printer_get_options;
+ backend_class->printer_mark_conflicts = cups_printer_mark_conflicts;
+ backend_class->printer_get_settings_from_options = cups_printer_get_settings_from_options;
+ backend_class->printer_prepare_for_print = cups_printer_prepare_for_print;
+ backend_class->printer_list_papers = cups_printer_list_papers;
+ backend_class->printer_get_hard_margins = cups_printer_get_hard_margins;
}
static cairo_status_t
@@ -272,18 +283,6 @@ cups_printer_create_cairo_surface (GtkPrinter *printer,
return surface;
}
-static GtkPrinter *
-gtk_print_backend_cups_find_printer (GtkPrintBackend *print_backend,
- const gchar *printer_name)
-{
- GtkPrintBackendCups *cups_print_backend;
-
- cups_print_backend = GTK_PRINT_BACKEND_CUPS (print_backend);
-
- return (GtkPrinter *) g_hash_table_lookup (cups_print_backend->printers,
- printer_name);
-}
-
typedef struct {
GtkPrintJobCompleteFunc callback;
GtkPrintJob *job;
@@ -417,30 +416,10 @@ gtk_print_backend_cups_print_stream (GtkPrintBackend *print_backend,
static void
-gtk_print_backend_cups_iface_init (GtkPrintBackendIface *iface)
-{
- iface->get_printer_list = cups_get_printer_list;
- iface->find_printer = gtk_print_backend_cups_find_printer;
- iface->print_stream = gtk_print_backend_cups_print_stream;
- iface->printer_request_details = cups_printer_request_details;
- iface->printer_create_cairo_surface = cups_printer_create_cairo_surface;
- iface->printer_get_options = cups_printer_get_options;
- iface->printer_mark_conflicts = cups_printer_mark_conflicts;
- iface->printer_get_settings_from_options = cups_printer_get_settings_from_options;
- iface->printer_prepare_for_print = cups_printer_prepare_for_print;
- iface->printer_list_papers = cups_printer_list_papers;
- iface->printer_get_hard_margins = cups_printer_get_hard_margins;
-}
-
-static void
gtk_print_backend_cups_init (GtkPrintBackendCups *backend_cups)
{
backend_cups->list_printers_poll = 0;
backend_cups->list_printers_pending = FALSE;
- backend_cups->printers = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- (GDestroyNotify) g_free,
- (GDestroyNotify) g_object_unref);
cups_request_default_printer (backend_cups);
}
@@ -452,18 +431,27 @@ gtk_print_backend_cups_finalize (GObject *object)
backend_cups = GTK_PRINT_BACKEND_CUPS (object);
- if (backend_cups->list_printers_poll > 0)
- g_source_remove (backend_cups->list_printers_poll);
-
- if (backend_cups->printers)
- g_hash_table_unref (backend_cups->printers);
-
g_free (backend_cups->default_printer);
backend_cups->default_printer = NULL;
backend_parent_class->finalize (object);
}
+static void
+gtk_print_backend_cups_dispose (GObject *object)
+{
+ GtkPrintBackendCups *backend_cups;
+
+ backend_cups = GTK_PRINT_BACKEND_CUPS (object);
+
+ if (backend_cups->list_printers_poll > 0)
+ g_source_remove (backend_cups->list_printers_poll);
+ backend_cups->list_printers_poll = 0;
+
+ backend_parent_class->dispose (object);
+}
+
+
static gboolean
cups_dispatch_watch_check (GSource *source)
{
@@ -514,13 +502,12 @@ cups_dispatch_watch_check (GSource *source)
static gboolean
cups_dispatch_watch_prepare (GSource *source,
- gint *timeout_)
+ gint *timeout_)
{
GtkPrintCupsDispatchWatch *dispatch;
dispatch = (GtkPrintCupsDispatchWatch *) source;
-
*timeout_ = -1;
return gtk_cups_request_read_write (dispatch->request);
@@ -528,8 +515,8 @@ cups_dispatch_watch_prepare (GSource *source,
static gboolean
cups_dispatch_watch_dispatch (GSource *source,
- GSourceFunc callback,
- gpointer user_data)
+ GSourceFunc callback,
+ gpointer user_data)
{
GtkPrintCupsDispatchWatch *dispatch;
GtkPrintCupsResponseCallbackFunc ep_callback;
@@ -548,7 +535,6 @@ cups_dispatch_watch_dispatch (GSource *source,
ep_callback (GTK_PRINT_BACKEND (dispatch->backend), result, user_data);
- g_source_unref (source);
return FALSE;
}
@@ -563,7 +549,11 @@ cups_dispatch_watch_finalize (GSource *source)
if (dispatch->backend)
{
- g_object_unref (dispatch->backend);
+ /* We need to unref this at idle time, because it might be the
+ last reference to this module causing the code to be
+ unloaded (including this particular function!)
+ */
+ gtk_print_backend_unref_at_idle (GTK_PRINT_BACKEND (dispatch->backend));
dispatch->backend = NULL;
}
@@ -588,7 +578,7 @@ cups_request_execute (GtkPrintBackendCups *print_backend,
GError **err)
{
GtkPrintCupsDispatchWatch *dispatch;
-
+
dispatch = (GtkPrintCupsDispatchWatch *) g_source_new (&_cups_dispatch_watch_funcs,
sizeof (GtkPrintCupsDispatchWatch));
@@ -599,10 +589,11 @@ cups_request_execute (GtkPrintBackendCups *print_backend,
g_source_set_callback ((GSource *) dispatch, (GSourceFunc) callback, user_data, notify);
g_source_attach ((GSource *) dispatch, NULL);
+ g_source_unref ((GSource *) dispatch);
}
static void
-cups_request_printer_info_cb (GtkPrintBackendCups *print_backend,
+cups_request_printer_info_cb (GtkPrintBackendCups *backend,
GtkCupsResult *result,
gpointer user_data)
{
@@ -611,40 +602,29 @@ cups_request_printer_info_cb (GtkPrintBackendCups *print_backend,
gchar *printer_name;
GtkPrinterCups *cups_printer;
GtkPrinter *printer;
- gchar *printer_uri;
- gchar *member_printer_uri;
gchar *loc;
gchar *desc;
gchar *state_msg;
int job_count;
-
- char uri[HTTP_MAX_URI], /* Printer URI */
- method[HTTP_MAX_URI], /* Method/scheme name */
- username[HTTP_MAX_URI], /* Username:password */
- hostname[HTTP_MAX_URI], /* Hostname */
- resource[HTTP_MAX_URI]; /* Resource name */
- int port; /* Port number */
gboolean status_changed;
- g_assert (GTK_IS_PRINT_BACKEND_CUPS (print_backend));
-
- printer_uri = NULL;
- member_printer_uri = NULL;
+ g_assert (GTK_IS_PRINT_BACKEND_CUPS (backend));
printer_name = (gchar *)user_data;
- cups_printer = (GtkPrinterCups *) g_hash_table_lookup (print_backend->printers, printer_name);
+ printer = gtk_print_backend_find_printer (GTK_PRINT_BACKEND (backend),
+ printer_name);
- if (!cups_printer)
+ if (!printer)
return;
- printer = GTK_PRINTER (cups_printer);
+ cups_printer = GTK_PRINTER_CUPS (printer);
if (gtk_cups_result_is_error (result))
{
if (gtk_printer_is_new (printer))
{
- g_hash_table_remove (print_backend->printers,
- printer_name);
+ gtk_print_backend_remove_printer (GTK_PRINT_BACKEND (backend),
+ printer);
return;
}
else
@@ -656,8 +636,6 @@ cups_request_printer_info_cb (GtkPrintBackendCups *print_backend,
/* TODO: determine printer type and use correct icon */
gtk_printer_set_icon_name (printer, "printer");
- cups_printer->device_uri = g_strdup_printf ("/printers/%s", printer_name);
-
state_msg = "";
loc = "";
desc = "";
@@ -670,8 +648,6 @@ cups_request_printer_info_cb (GtkPrintBackendCups *print_backend,
_CUPS_MAP_ATTR_STR (attr, loc, "printer-location");
_CUPS_MAP_ATTR_STR (attr, desc, "printer-info");
_CUPS_MAP_ATTR_STR (attr, state_msg, "printer-state-message");
- _CUPS_MAP_ATTR_STR (attr, printer_uri, "printer-uri-supported");
- _CUPS_MAP_ATTR_STR (attr, member_printer_uri, "member-uris");
_CUPS_MAP_ATTR_INT (attr, cups_printer->state, "printer-state");
_CUPS_MAP_ATTR_INT (attr, job_count, "queued-job-count");
}
@@ -679,53 +655,15 @@ cups_request_printer_info_cb (GtkPrintBackendCups *print_backend,
/* if we got a member_printer_uri then this printer is part of a class
so use member_printer_uri, else user printer_uri */
- if (cups_printer->printer_uri)
- g_free (cups_printer->printer_uri);
-
- if (member_printer_uri)
- {
- g_free (printer_uri);
- cups_printer->printer_uri = member_printer_uri;
- }
- else
- cups_printer->printer_uri = printer_uri;
-
status_changed = gtk_printer_set_job_count (printer, job_count);
status_changed |= gtk_printer_set_location (printer, loc);
status_changed |= gtk_printer_set_description (printer, desc);
status_changed |= gtk_printer_set_state_message (printer, state_msg);
-#if (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR >= 2) || CUPS_VERSION_MAJOR > 1
- httpSeparateURI (HTTP_URI_CODING_ALL, cups_printer->printer_uri,
- method, sizeof (method),
- username, sizeof (username),
- hostname, sizeof (hostname),
- &port,
- resource, sizeof (resource));
-
-#else
- httpSeparate (cups_printer->printer_uri,
- method,
- username,
- hostname,
- &port,
- resource);
-#endif
-
- gethostname(uri, sizeof(uri));
-
- if (strcasecmp(uri, hostname) == 0)
- strcpy(hostname, "localhost");
-
- if (cups_printer->hostname)
- g_free (cups_printer->hostname);
-
- cups_printer->hostname = g_strdup (hostname);
- cups_printer->port = port;
-
if (status_changed)
- g_signal_emit_by_name (GTK_PRINT_BACKEND (print_backend), "printer-status-changed", printer);
+ g_signal_emit_by_name (GTK_PRINT_BACKEND (backend),
+ "printer-status-changed", printer);
}
static void
@@ -735,6 +673,14 @@ cups_request_printer_info (GtkPrintBackendCups *print_backend,
GError *error;
GtkCupsRequest *request;
gchar *printer_uri;
+ static const char * const pattrs[] = /* Attributes we're interested in */
+ {
+ "printer-location",
+ "printer-info",
+ "printer-state-message",
+ "printer-state",
+ "queued-job-count"
+ };
error = NULL;
@@ -752,6 +698,10 @@ cups_request_printer_info (GtkPrintBackendCups *print_backend,
g_free (printer_uri);
+ gtk_cups_request_ipp_add_strings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", G_N_ELEMENTS (pattrs),
+ NULL, pattrs);
+
cups_request_execute (print_backend,
request,
(GtkPrintCupsResponseCallbackFunc) cups_request_printer_info_cb,
@@ -922,82 +872,22 @@ cups_begin_polling_info (GtkPrintBackendCups *print_backend,
cups_request_job_info (data);
}
-static gint
-printer_cmp (GtkPrinter *a, GtkPrinter *b)
-{
- const char *name_a, *name_b;
- g_assert (GTK_IS_PRINTER (a) && GTK_IS_PRINTER (b));
-
- name_a = gtk_printer_get_name (a);
- name_b = gtk_printer_get_name (b);
- if (name_a == NULL && name_b == NULL)
- return 0;
- else if (name_a == NULL)
- return G_MAXINT;
- else if (name_b == NULL)
- return G_MININT;
- else
- return g_ascii_strcasecmp (name_a, name_b);
-}
-
static void
-printer_hash_to_sorted_active_list (const gchar *key,
- gpointer value,
- GList **out_list)
+mark_printer_inactive (GtkPrinter *printer,
+ GtkPrintBackend *backend)
{
- GtkPrinter *printer;
-
- printer = GTK_PRINTER (value);
-
- if (gtk_printer_get_name (printer) == NULL)
- return;
-
- if (!gtk_printer_is_active (printer))
- return;
-
- *out_list = g_list_insert_sorted (*out_list, value, (GCompareFunc) printer_cmp);
+ gtk_printer_set_is_active (printer, FALSE);
+ g_signal_emit_by_name (backend,
+ "printer-removed", printer);
}
-static void
-printer_hash_to_sorted_active_name_list (const gchar *key,
- gpointer value,
- GList **out_list)
+static gint
+find_printer (GtkPrinter *printer, const char *find_name)
{
- GtkPrinter *printer;
-
- printer = GTK_PRINTER (value);
-
-
- if (gtk_printer_get_name (printer) == NULL)
- return;
-
- if (!gtk_printer_is_active (printer))
- return;
+ const char *printer_name;
- if (gtk_printer_is_active (printer))
- *out_list = g_list_insert_sorted (*out_list,
- (char *)gtk_printer_get_name (printer),
- g_str_equal);
-}
-
-static void
-mark_printer_inactive (const gchar *printer_name,
- GtkPrintBackendCups *cups_backend)
-{
- GtkPrinter *printer;
- GHashTable *printer_hash;
-
- printer_hash = cups_backend->printers;
-
- printer = (GtkPrinter *) g_hash_table_lookup (printer_hash,
- printer_name);
-
- if (printer == NULL)
- return;
-
- gtk_printer_set_is_active (printer, FALSE);
-
- g_signal_emit_by_name (GTK_PRINT_BACKEND (cups_backend), "printer-removed", printer);
+ printer_name = gtk_printer_get_name (printer);
+ return g_ascii_strcasecmp (printer_name, find_name);
}
static void
@@ -1021,51 +911,122 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
g_warning ("Error getting printer list: %s", gtk_cups_result_get_error_string (result));
return;
}
-
+
/* gether the names of the printers in the current queue
so we may check to see if they were removed */
- removed_printer_checklist = NULL;
- if (cups_backend->printers != NULL)
- g_hash_table_foreach (cups_backend->printers,
- (GHFunc) printer_hash_to_sorted_active_name_list,
- &removed_printer_checklist);
-
+ removed_printer_checklist = gtk_print_backend_get_printer_list (GTK_PRINT_BACKEND (cups_backend));
+
response = gtk_cups_result_get_response (result);
- attr = ippFindAttribute (response, "printer-name", IPP_TAG_NAME);
- while (attr)
+ for (attr = response->attrs; attr != NULL; attr = attr->next)
{
- GtkPrinterCups *cups_printer;
GtkPrinter *printer;
const gchar *printer_name;
+ const char *printer_uri;
+ const char *member_uris;
GList *node;
+
+ /*
+ * Skip leading attributes until we hit a printer...
+ */
+ while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
+ attr = attr->next;
+
+ if (attr == NULL)
+ break;
+
+ printer_name = NULL;
+ printer_uri = NULL;
+ member_uris = NULL;
+ while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
+ {
+ if (!strcmp(attr->name, "printer-name") &&
+ attr->value_tag == IPP_TAG_NAME)
+ printer_name = attr->values[0].string.text;
+ else if (!strcmp(attr->name, "printer-uri-supported") &&
+ attr->value_tag == IPP_TAG_URI)
+ printer_uri = attr->values[0].string.text;
+ else if (!strcmp(attr->name, "member-uris") &&
+ attr->value_tag == IPP_TAG_URI)
+ member_uris = attr->values[0].string.text;
+
+ attr = attr->next;
+ }
- printer_name = attr->values[0].string.text;
+ if (printer_name == NULL ||
+ (printer_uri == NULL && member_uris == NULL))
+ {
+ if (attr == NULL)
+ break;
+ else
+ continue;
+ }
+
/* remove name from checklist if it was found */
- node = g_list_find_custom (removed_printer_checklist, printer_name, (GCompareFunc) g_ascii_strcasecmp);
+ node = g_list_find_custom (removed_printer_checklist, printer_name, (GCompareFunc) find_printer);
removed_printer_checklist = g_list_delete_link (removed_printer_checklist, node);
- cups_printer = (GtkPrinterCups *) g_hash_table_lookup (cups_backend->printers,
- printer_name);
- printer = cups_printer ? GTK_PRINTER (cups_printer) : NULL;
-
- if (!cups_printer)
+ printer = gtk_print_backend_find_printer (GTK_PRINT_BACKEND (cups_backend), printer_name);
+ if (!printer)
{
+ GtkPrinterCups *cups_printer;
+ char uri[HTTP_MAX_URI], /* Printer URI */
+ method[HTTP_MAX_URI], /* Method/scheme name */
+ username[HTTP_MAX_URI], /* Username:password */
+ hostname[HTTP_MAX_URI], /* Hostname */
+ resource[HTTP_MAX_URI]; /* Resource name */
+ int port; /* Port number */
+
list_has_changed = TRUE;
- cups_printer = gtk_printer_cups_new (attr->values[0].string.text,
+ cups_printer = gtk_printer_cups_new (printer_name,
GTK_PRINT_BACKEND (cups_backend));
- printer = GTK_PRINTER (cups_printer);
+ cups_printer->device_uri = g_strdup_printf ("/printers/%s", printer_name);
+
+ if (member_uris)
+ {
+ cups_printer->printer_uri = g_strdup (member_uris);
+ }
+ else
+ cups_printer->printer_uri = g_strdup (printer_uri);
+
+#if (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR >= 2) || CUPS_VERSION_MAJOR > 1
+ httpSeparateURI (HTTP_URI_CODING_ALL, cups_printer->printer_uri,
+ method, sizeof (method),
+ username, sizeof (username),
+ hostname, sizeof (hostname),
+ &port,
+ resource, sizeof (resource));
+
+#else
+ httpSeparate (cups_printer->printer_uri,
+ method,
+ username,
+ hostname,
+ &port,
+ resource);
+#endif
+
+ gethostname(uri, sizeof(uri));
+ if (strcasecmp(uri, hostname) == 0)
+ strcpy(hostname, "localhost");
+
+ cups_printer->hostname = g_strdup (hostname);
+ cups_printer->port = port;
+
+ printer = GTK_PRINTER (cups_printer);
+
if (cups_backend->default_printer != NULL &&
strcmp (cups_backend->default_printer, gtk_printer_get_name (printer)) == 0)
gtk_printer_set_is_default (printer, TRUE);
- g_hash_table_insert (cups_backend->printers,
- g_strdup (gtk_printer_get_name (printer)),
- cups_printer);
+
+ gtk_print_backend_add_printer (GTK_PRINT_BACKEND (cups_backend), printer);
}
-
+ else
+ g_object_ref (printer);
+
if (!gtk_printer_is_active (printer))
{
gtk_printer_set_is_active (printer, TRUE);
@@ -1083,25 +1044,29 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
}
cups_request_printer_info (cups_backend, gtk_printer_get_name (printer));
-
- attr = ippFindNextAttribute (response,
- "printer-name",
- IPP_TAG_NAME);
- }
- /* look at the removed printers checklist and mark any printer
- as inactive if it is in the list, emitting a printer_removed signal */
+ /* The ref is held by GtkPrintBackend, in add_printer() */
+ g_object_unref (printer);
- if (removed_printer_checklist != NULL)
- {
- g_list_foreach (removed_printer_checklist, (GFunc) mark_printer_inactive, cups_backend);
- g_list_free (removed_printer_checklist);
- list_has_changed = TRUE;
- }
-
- if (list_has_changed)
- g_signal_emit_by_name (GTK_PRINT_BACKEND (cups_backend), "printer-list-changed");
+
+ if (attr == NULL)
+ break;
+ }
+ /* look at the removed printers checklist and mark any printer
+ as inactive if it is in the list, emitting a printer_removed signal */
+ if (removed_printer_checklist != NULL)
+ {
+ g_list_foreach (removed_printer_checklist, (GFunc) mark_printer_inactive,
+ GTK_PRINT_BACKEND (cups_backend));
+ g_list_free (removed_printer_checklist);
+ list_has_changed = TRUE;
+ }
+
+ if (list_has_changed)
+ g_signal_emit_by_name (GTK_PRINT_BACKEND (cups_backend), "printer-list-changed");
+
+ gtk_print_backend_set_list_done (GTK_PRINT_BACKEND (cups_backend));
}
static gboolean
@@ -1109,7 +1074,13 @@ cups_request_printer_list (GtkPrintBackendCups *cups_backend)
{
GError *error;
GtkCupsRequest *request;
-
+ static const char * const pattrs[] = /* Attributes we're interested in */
+ {
+ "printer-name",
+ "printer-uri-supported",
+ "member-uris"
+ };
+
if (cups_backend->list_printers_pending ||
!cups_backend->got_default_printer)
return TRUE;
@@ -1125,6 +1096,10 @@ cups_request_printer_list (GtkPrintBackendCups *cups_backend)
NULL,
NULL);
+ gtk_cups_request_ipp_add_strings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", G_N_ELEMENTS (pattrs),
+ NULL, pattrs);
+
cups_request_execute (cups_backend,
request,
(GtkPrintCupsResponseCallbackFunc) cups_request_printer_list_cb,
@@ -1136,29 +1111,19 @@ cups_request_printer_list (GtkPrintBackendCups *cups_backend)
return TRUE;
}
-static GList *
-cups_get_printer_list (GtkPrintBackend *print_backend)
+static void
+cups_get_printer_list (GtkPrintBackend *backend)
{
GtkPrintBackendCups *cups_backend;
- GList *result;
-
- cups_backend = GTK_PRINT_BACKEND_CUPS (print_backend);
-
- result = NULL;
- if (cups_backend->printers != NULL)
- g_hash_table_foreach (cups_backend->printers,
- (GHFunc) printer_hash_to_sorted_active_list,
- &result);
+ cups_backend = GTK_PRINT_BACKEND_CUPS (backend);
if (cups_backend->list_printers_poll == 0)
{
cups_request_printer_list (cups_backend);
- cups_backend->list_printers_poll = g_timeout_add (3000,
+ cups_backend->list_printers_poll = g_timeout_add (3000 * 100000,
(GSourceFunc) cups_request_printer_list,
- print_backend);
+ backend);
}
-
- return result;
}
typedef struct {
diff --git a/modules/printbackends/cups/gtkprintercups.c b/modules/printbackends/cups/gtkprintercups.c
index c36b8077e5..89713339e7 100644
--- a/modules/printbackends/cups/gtkprintercups.c
+++ b/modules/printbackends/cups/gtkprintercups.c
@@ -90,8 +90,7 @@ gtk_printer_cups_finalize (GObject *object)
if (printer->ppd_file)
ppdClose (printer->ppd_file);
- if (G_OBJECT_CLASS (gtk_printer_cups_parent_class)->finalize)
- G_OBJECT_CLASS (gtk_printer_cups_parent_class)->finalize (object);
+ G_OBJECT_CLASS (gtk_printer_cups_parent_class)->finalize (object);
}
/**
diff --git a/modules/printbackends/lpr/gtkprintbackendlpr.c b/modules/printbackends/lpr/gtkprintbackendlpr.c
index 4560c92a2f..daed2e589b 100644
--- a/modules/printbackends/lpr/gtkprintbackendlpr.c
+++ b/modules/printbackends/lpr/gtkprintbackendlpr.c
@@ -51,25 +51,18 @@ static GType print_backend_lpr_type = 0;
struct _GtkPrintBackendLprClass
{
- GObjectClass parent_class;
+ GtkPrintBackendClass parent_class;
};
struct _GtkPrintBackendLpr
{
- GObject parent_instance;
-
- GtkPrinter *printer;
-
- GHashTable *printers;
+ GtkPrintBackend parent_instance;
};
static GObjectClass *backend_parent_class;
static void gtk_print_backend_lpr_class_init (GtkPrintBackendLprClass *class);
-static void gtk_print_backend_lpr_iface_init (GtkPrintBackendIface *iface);
static void gtk_print_backend_lpr_init (GtkPrintBackendLpr *impl);
-static void gtk_print_backend_lpr_finalize (GObject *object);
-static GList * lpr_request_printer_list (GtkPrintBackend *print_backend);
static void lpr_printer_get_settings_from_options (GtkPrinter *printer,
GtkPrinterOptionSet *options,
GtkPrintSettings *settings);
@@ -89,6 +82,16 @@ static void lpr_printer_get_hard_margins (GtkPrinter
double *right);
static void lpr_printer_request_details (GtkPrinter *printer);
static GList * lpr_printer_list_papers (GtkPrinter *printer);
+static cairo_surface_t * lpr_printer_create_cairo_surface (GtkPrinter *printer,
+ gdouble width,
+ gdouble height,
+ gint cache_fd);
+static void gtk_print_backend_lpr_print_stream (GtkPrintBackend *print_backend,
+ GtkPrintJob *job,
+ gint data_fd,
+ GtkPrintJobCompleteFunc callback,
+ gpointer user_data,
+ GDestroyNotify dnotify);
static void
gtk_print_backend_lpr_register_type (GTypeModule *module)
@@ -108,24 +111,11 @@ gtk_print_backend_lpr_register_type (GTypeModule *module)
(GInstanceInitFunc) gtk_print_backend_lpr_init,
};
- static const GInterfaceInfo print_backend_info =
- {
- (GInterfaceInitFunc) gtk_print_backend_lpr_iface_init, /* interface_init */
- NULL, /* interface_finalize */
- NULL /* interface_data */
- };
-
print_backend_lpr_type = g_type_module_register_type (module,
- G_TYPE_OBJECT,
- "GtkPrintBackendLpr",
- &print_backend_lpr_info, 0);
- g_type_module_add_interface (module,
- print_backend_lpr_type,
- GTK_TYPE_PRINT_BACKEND,
- &print_backend_info);
+ GTK_TYPE_PRINT_BACKEND,
+ "GtkPrintBackendLpr",
+ &print_backend_lpr_info, 0);
}
-
-
}
G_MODULE_EXPORT void
@@ -173,11 +163,19 @@ gtk_print_backend_lpr_new (void)
static void
gtk_print_backend_lpr_class_init (GtkPrintBackendLprClass *class)
{
- GObjectClass *gobject_class = G_OBJECT_CLASS (class);
-
+ GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_CLASS (class);
+
backend_parent_class = g_type_class_peek_parent (class);
- gobject_class->finalize = gtk_print_backend_lpr_finalize;
+ backend_class->print_stream = gtk_print_backend_lpr_print_stream;
+ backend_class->printer_request_details = lpr_printer_request_details;
+ backend_class->printer_create_cairo_surface = lpr_printer_create_cairo_surface;
+ backend_class->printer_get_options = lpr_printer_get_options;
+ backend_class->printer_mark_conflicts = lpr_printer_mark_conflicts;
+ backend_class->printer_get_settings_from_options = lpr_printer_get_settings_from_options;
+ backend_class->printer_prepare_for_print = lpr_printer_prepare_for_print;
+ backend_class->printer_list_papers = lpr_printer_list_papers;
+ backend_class->printer_get_hard_margins = lpr_printer_get_hard_margins;
}
static cairo_status_t
@@ -215,22 +213,6 @@ lpr_printer_create_cairo_surface (GtkPrinter *printer,
return surface;
}
-static GtkPrinter *
-gtk_print_backend_lpr_find_printer (GtkPrintBackend *print_backend,
- const gchar *printer_name)
-{
- GtkPrintBackendLpr *lpr_print_backend;
- GtkPrinter *printer;
-
- lpr_print_backend = GTK_PRINT_BACKEND_LPR (print_backend);
-
- printer = NULL;
- if (strcmp (gtk_printer_get_name (lpr_print_backend->printer), printer_name) == 0)
- printer = lpr_print_backend->printer;
-
- return printer;
-}
-
typedef struct {
GtkPrintBackend *backend;
GtkPrintJobCompleteFunc callback;
@@ -398,64 +380,21 @@ gtk_print_backend_lpr_print_stream (GtkPrintBackend *print_backend,
g_strfreev (argv);
}
-
static void
-gtk_print_backend_lpr_iface_init (GtkPrintBackendIface *iface)
-{
- iface->get_printer_list = lpr_request_printer_list;
- iface->find_printer = gtk_print_backend_lpr_find_printer;
- iface->print_stream = gtk_print_backend_lpr_print_stream;
- iface->printer_request_details = lpr_printer_request_details;
- iface->printer_create_cairo_surface = lpr_printer_create_cairo_surface;
- iface->printer_get_options = lpr_printer_get_options;
- iface->printer_mark_conflicts = lpr_printer_mark_conflicts;
- iface->printer_get_settings_from_options = lpr_printer_get_settings_from_options;
- iface->printer_prepare_for_print = lpr_printer_prepare_for_print;
- iface->printer_list_papers = lpr_printer_list_papers;
- iface->printer_get_hard_margins = lpr_printer_get_hard_margins;
-}
-
-static GList *
-lpr_request_printer_list (GtkPrintBackend *backend)
-{
- GList *l;
- GtkPrintBackendLpr *lpr_backend;
-
- l = NULL;
-
- lpr_backend = GTK_PRINT_BACKEND_LPR (backend);
-
- if (lpr_backend->printer)
- l = g_list_append (l, lpr_backend->printer);
-
- return l;
-}
-
-static void
-gtk_print_backend_lpr_init (GtkPrintBackendLpr *backend_lpr)
+gtk_print_backend_lpr_init (GtkPrintBackendLpr *backend)
{
GtkPrinter *printer;
printer = gtk_printer_new (_("Print to LPR"),
- GTK_PRINT_BACKEND (backend_lpr),
+ GTK_PRINT_BACKEND (backend),
TRUE);
gtk_printer_set_has_details (printer, TRUE);
gtk_printer_set_icon_name (printer, "printer");
gtk_printer_set_is_active (printer, TRUE);
-
- backend_lpr->printer = printer;
-}
-
-static void
-gtk_print_backend_lpr_finalize (GObject *object)
-{
- GtkPrintBackendLpr *backend_lpr;
-
- backend_lpr = GTK_PRINT_BACKEND_LPR (object);
-
- g_object_unref (backend_lpr->printer);
+ gtk_printer_set_is_default (printer, TRUE);
- backend_parent_class->finalize (object);
+ gtk_print_backend_add_printer (GTK_PRINT_BACKEND (backend), printer);
+ g_object_unref (printer);
}
static void
diff --git a/modules/printbackends/pdf/gtkprintbackendpdf.c b/modules/printbackends/pdf/gtkprintbackendpdf.c
index e746f92d46..206b2c1a8e 100644
--- a/modules/printbackends/pdf/gtkprintbackendpdf.c
+++ b/modules/printbackends/pdf/gtkprintbackendpdf.c
@@ -52,25 +52,18 @@ static GType print_backend_pdf_type = 0;
struct _GtkPrintBackendPdfClass
{
- GObjectClass parent_class;
+ GtkPrintBackendClass parent_class;
};
struct _GtkPrintBackendPdf
{
- GObject parent_instance;
-
- GtkPrinter *printer;
-
- GHashTable *printers;
+ GtkPrintBackend parent_instance;
};
static GObjectClass *backend_parent_class;
static void gtk_print_backend_pdf_class_init (GtkPrintBackendPdfClass *class);
-static void gtk_print_backend_pdf_iface_init (GtkPrintBackendIface *iface);
static void gtk_print_backend_pdf_init (GtkPrintBackendPdf *impl);
-static void gtk_print_backend_pdf_finalize (GObject *object);
-static GList * pdf_request_printer_list (GtkPrintBackend *print_backend);
static void pdf_printer_get_settings_from_options (GtkPrinter *printer,
GtkPrinterOptionSet *options,
GtkPrintSettings *settings);
@@ -90,6 +83,16 @@ static void pdf_printer_get_hard_margins (GtkPrinter
double *right);
static void pdf_printer_request_details (GtkPrinter *printer);
static GList * pdf_printer_list_papers (GtkPrinter *printer);
+static void gtk_print_backend_pdf_print_stream (GtkPrintBackend *print_backend,
+ GtkPrintJob *job,
+ gint data_fd,
+ GtkPrintJobCompleteFunc callback,
+ gpointer user_data,
+ GDestroyNotify dnotify);
+static cairo_surface_t * pdf_printer_create_cairo_surface (GtkPrinter *printer,
+ gdouble width,
+ gdouble height,
+ gint cache_fd);
static void
gtk_print_backend_pdf_register_type (GTypeModule *module)
@@ -109,24 +112,11 @@ gtk_print_backend_pdf_register_type (GTypeModule *module)
(GInstanceInitFunc) gtk_print_backend_pdf_init,
};
- static const GInterfaceInfo print_backend_info =
- {
- (GInterfaceInitFunc) gtk_print_backend_pdf_iface_init, /* interface_init */
- NULL, /* interface_finalize */
- NULL /* interface_data */
- };
-
print_backend_pdf_type = g_type_module_register_type (module,
- G_TYPE_OBJECT,
- "GtkPrintBackendPdf",
- &print_backend_pdf_info, 0);
- g_type_module_add_interface (module,
- print_backend_pdf_type,
- GTK_TYPE_PRINT_BACKEND,
- &print_backend_info);
+ GTK_TYPE_PRINT_BACKEND,
+ "GtkPrintBackendPdf",
+ &print_backend_pdf_info, 0);
}
-
-
}
G_MODULE_EXPORT void
@@ -174,11 +164,19 @@ gtk_print_backend_pdf_new (void)
static void
gtk_print_backend_pdf_class_init (GtkPrintBackendPdfClass *class)
{
- GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+ GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_CLASS (class);
backend_parent_class = g_type_class_peek_parent (class);
- gobject_class->finalize = gtk_print_backend_pdf_finalize;
+ backend_class->print_stream = gtk_print_backend_pdf_print_stream;
+ backend_class->printer_request_details = pdf_printer_request_details;
+ backend_class->printer_create_cairo_surface = pdf_printer_create_cairo_surface;
+ backend_class->printer_get_options = pdf_printer_get_options;
+ backend_class->printer_mark_conflicts = pdf_printer_mark_conflicts;
+ backend_class->printer_get_settings_from_options = pdf_printer_get_settings_from_options;
+ backend_class->printer_prepare_for_print = pdf_printer_prepare_for_print;
+ backend_class->printer_list_papers = pdf_printer_list_papers;
+ backend_class->printer_get_hard_margins = pdf_printer_get_hard_margins;
}
static cairo_status_t
@@ -216,22 +214,6 @@ pdf_printer_create_cairo_surface (GtkPrinter *printer,
return surface;
}
-static GtkPrinter *
-gtk_print_backend_pdf_find_printer (GtkPrintBackend *print_backend,
- const gchar *printer_name)
-{
- GtkPrintBackendPdf *pdf_print_backend;
- GtkPrinter *printer;
-
- pdf_print_backend = GTK_PRINT_BACKEND_PDF (print_backend);
-
- printer = NULL;
- if (strcmp (gtk_printer_get_name (pdf_print_backend->printer), printer_name) == 0)
- printer = pdf_print_backend->printer;
-
- return printer;
-}
-
typedef struct {
GtkPrintBackend *backend;
GtkPrintJobCompleteFunc callback;
@@ -366,64 +348,23 @@ gtk_print_backend_pdf_print_stream (GtkPrintBackend *print_backend,
ps);
}
-
static void
-gtk_print_backend_pdf_iface_init (GtkPrintBackendIface *iface)
-{
- iface->get_printer_list = pdf_request_printer_list;
- iface->find_printer = gtk_print_backend_pdf_find_printer;
- iface->print_stream = gtk_print_backend_pdf_print_stream;
- iface->printer_request_details = pdf_printer_request_details;
- iface->printer_create_cairo_surface = pdf_printer_create_cairo_surface;
- iface->printer_get_options = pdf_printer_get_options;
- iface->printer_mark_conflicts = pdf_printer_mark_conflicts;
- iface->printer_get_settings_from_options = pdf_printer_get_settings_from_options;
- iface->printer_prepare_for_print = pdf_printer_prepare_for_print;
- iface->printer_list_papers = pdf_printer_list_papers;
- iface->printer_get_hard_margins = pdf_printer_get_hard_margins;
-}
-
-static GList *
-pdf_request_printer_list (GtkPrintBackend *backend)
-{
- GList *l;
- GtkPrintBackendPdf *pdf_backend;
-
- l = NULL;
-
- pdf_backend = GTK_PRINT_BACKEND_PDF (backend);
-
- if (pdf_backend->printer)
- l = g_list_append (l, pdf_backend->printer);
-
- return l;
-}
-
-static void
-gtk_print_backend_pdf_init (GtkPrintBackendPdf *backend_pdf)
+gtk_print_backend_pdf_init (GtkPrintBackendPdf *backend)
{
GtkPrinter *printer;
- backend_pdf->printer = gtk_printer_new (_("Print to PDF"),
- GTK_PRINT_BACKEND (backend_pdf),
- TRUE);
+ printer = gtk_printer_new (_("Print to PDF"),
+ GTK_PRINT_BACKEND (backend),
+ TRUE);
- printer = backend_pdf->printer;
gtk_printer_set_has_details (printer, TRUE);
gtk_printer_set_icon_name (printer, "floppy");
gtk_printer_set_is_active (printer, TRUE);
-}
-
-static void
-gtk_print_backend_pdf_finalize (GObject *object)
-{
- GtkPrintBackendPdf *backend_pdf;
-
- backend_pdf = GTK_PRINT_BACKEND_PDF (object);
- g_object_unref (backend_pdf->printer);
+ gtk_print_backend_add_printer (GTK_PRINT_BACKEND (backend), printer);
+ g_object_unref (printer);
- backend_parent_class->finalize (object);
+ gtk_print_backend_set_list_done (GTK_PRINT_BACKEND (backend));
}
static void
diff --git a/tests/Makefile.am b/tests/Makefile.am
index a900f8d5fb..c5d269ec42 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -53,6 +53,7 @@ noinst_PROGRAMS = \
testmultidisplay \
testmultiscreen \
testnotebookdnd \
+ testnouiprint \
testrgb \
testrecentchooser \
testselection \
@@ -107,6 +108,7 @@ testmenubars_DEPENDENCIES = $(TEST_DEPS)
testmultidisplay_DEPENDENCIES = $(TEST_DEPS)
testmultiscreen_DEPENDENCIES = $(TEST_DEPS)
testnotebookdnd_DEPENDENCIES = $(TEST_DEPS)
+testnouiprint_DEPENDENCIES = $(TEST_DEPS)
testrecentchooser_DEPENDENCIES = $(TEST_DEPS)
testrgb_DEPENDENCIES = $(TEST_DEPS)
testselection_DEPENDENCIES = $(TEST_DEPS)
@@ -155,6 +157,7 @@ testmenubars_LDADD = $(LDADDS)
testmultidisplay_LDADD = $(LDADDS)
testmultiscreen_LDADD = $(LDADDS)
testnotebookdnd_LDADD = $(LDADDS)
+testnouiprint_LDADD = $(LDADDS)
testrecentchooser_LDADD = $(LDADDS)
testrgb_LDADD = $(LDADDS)
testselection_LDADD = $(LDADDS)
diff --git a/tests/testnouiprint.c b/tests/testnouiprint.c
new file mode 100644
index 0000000000..3b0825b2ab
--- /dev/null
+++ b/tests/testnouiprint.c
@@ -0,0 +1,107 @@
+/* -*- Mode: C; c-basic-offset: 2; -*- */
+/* Gtk+ - non-ui printing
+ *
+ * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "gtk/gtkprintoperation.h"
+#include <math.h>
+
+static void
+draw_page (GtkPrintOperation *operation,
+ GtkPrintContext *context,
+ int page_nr)
+{
+ cairo_t *cr;
+ PangoLayout *layout;
+ PangoFontDescription *desc;
+
+ cr = gtk_print_context_get_cairo (context);
+
+ /* Draw a red rectangle, as wide as the paper (inside the margins) */
+ cairo_set_source_rgb (cr, 1.0, 0, 0);
+ cairo_rectangle (cr, 0, 0, gtk_print_context_get_width (context), 50);
+
+ cairo_fill (cr);
+
+ /* Draw some lines */
+ cairo_move_to (cr, 20, 10);
+ cairo_line_to (cr, 40, 20);
+ cairo_arc (cr, 60, 60, 20, 0, M_PI);
+ cairo_line_to (cr, 80, 20);
+
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_set_line_width (cr, 5);
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+ cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+
+ cairo_stroke (cr);
+
+ /* Draw some text */
+
+ layout = gtk_print_context_create_layout (context);
+ pango_layout_set_text (layout, "Hello World! Printing is easy", -1);
+ desc = pango_font_description_from_string ("sans 28");
+ pango_layout_set_font_description (layout, desc);
+ pango_font_description_free (desc);
+
+ cairo_move_to (cr, 30, 20);
+ pango_cairo_layout_path (cr, layout);
+
+ /* Font Outline */
+ cairo_set_source_rgb (cr, 0.93, 1.0, 0.47);
+ cairo_set_line_width (cr, 0.5);
+ cairo_stroke_preserve (cr);
+
+ /* Font Fill */
+ cairo_set_source_rgb (cr, 0, 0.0, 1.0);
+ cairo_fill (cr);
+
+ g_object_unref (layout);
+}
+
+
+int
+main (int argc, char **argv)
+{
+ GMainLoop *loop;
+ GtkPrintOperation *print;
+ GtkPrintOperationResult res;
+ GtkPrintSettings *settings;
+
+
+ /* Unfortunately we need a display for the XSettings to get the
+ list of backends... */
+ /* gtk_parse_args (&argc, &argv); */
+ gtk_init (&argc, &argv);
+
+ loop = g_main_loop_new (NULL, TRUE);
+
+ settings = gtk_print_settings_new ();
+ /* gtk_print_settings_set_printer (settings, "printer"); */
+
+ print = gtk_print_operation_new ();
+ gtk_print_operation_set_print_settings (print, settings);
+ gtk_print_operation_set_nr_of_pages (print, 1);
+ gtk_print_operation_set_unit (print, GTK_UNIT_MM);
+ gtk_print_operation_set_show_dialog (print, FALSE);
+ g_signal_connect (print, "draw_page", G_CALLBACK (draw_page), NULL);
+ res = gtk_print_operation_run (print, NULL, NULL);
+
+ return 0;
+}