GTK+ Printing backend HowTo
- From: Ghee Teo <Ghee Teo Sun COM>
- To: desktop-devel-list gnome org
- Cc: Norm Jacobs <Norm Jacobs Sun COM>
- Subject: GTK+ Printing backend HowTo
- Date: Sat, 09 Dec 2006 12:29:19 +0000
Hi,
As I have been prompted by some in the past in writing up a
HowTo write a GTK+ Printing backend. So this is attached, welcome
any comment and feedbacks [1], I hope to make that so that it can become
a useful document for someone who plans to write a one similar to the one
I have written for PAPI.
I also welcome suggestion as to where I can post this document once it
is completed :)
thanks,
-Ghee
[1] comments from Alex and Matthias included
Title: How to write a GTK+ Printing Backend
Author: Ghee Teo <ghee teo sun com>
Date: 6th Dec 2006
Version: 0.1 (Initial Draft)
0.2 (Feedbacks/comments from mclasen redhat com and alexl redhat com)
I. Background
The GTK+ Printing API is designed and implemented to replace and enhance
printing supports for developers. Given that GNOME applications have been
relied in the past on libgnomeprint/libgnomeprintui which is GNOME specific.
Since GTK+ have been developed and deployed not onlu on Linux/Unix but also
on Windows amd MacOS. It is therefore important that GTK+ printing must
support various backend implementations required on various platforms.
As I have just implemented the PAPI (Printing API) as defined by Free
Standards Group on Solaris. I would like to share briefly even the steps
required to implement a GTK+ Printing backend. The following steps have been
described in as generic terms as possible though it still heavily influenced
by GTK+ printing on Unix.
II. Steps to write a GTK+ Printing Backend
The GTK+ printing backend code should reside in a sub-directory under
gtk+/modules/printbackends.
1. CVS checkout the gtk+ module from HEAD
2. Create a subdir where the GTK+ Backend module to build
Create modules/printbackends/<backend>
3. Make GTK+ to recognise backend module to build
Modify modules/printbackends/Makefile.am to include the module to build
4. Create Makefile.am in the <backend> subdir and modify to work
Hints: Take a copy of these files from printbackends/lpr
5. Create the backend's backend class
Create a backend class named gtkprintbackend<backend>.[ch]
This backend class is dynamically loaded g_module.
5.1 Create the G_MODULE methods that the GtkPrintBackend requires
G_MODULE_EXPORT void pb_module_init (GTypeModule *module);
G_MODULE_EXPORT void pb_module_exit (void);
G_MODULE_EXPORT GtkPrintBackend *pb_module_create (void);
Hints: check out the lpr module for the bodies of the methods.
5.2 Register the backend backend printer type in pb_module_init ()
E.g. gtk_print_backend_<backend>_register_type (module);
gtk_printer_<backend>_register_type (module);
It is important to mention that the types need to be registered
dynamically, not statically, since we are in a dlopened module.
Ie, use g_type_module_register_type.
5.3 Create an new instance of backend type in pb_module_create ()
E.g. return gtk_print_backend_<backend>_new ();
5.4 Write the template code of the backend class
Hints: Use printbackends/[lpr|cups|papi] as reference points
6. Implement the GtkPrintBackend's methods
GtkPrintBackend defines a number of interfaces that the real backend
ought to implement to make the backend works. (see gtk/gtkprintbackend.h).
I have listed the essential 7 below.
6.1 Method 1: void (*request_printer_list) (GtkPrintBackend *backend);
When the backend is created, it must dislay the list of printers that it
knows about into the Print Dialog. So this is the first method that will be
run when a backend is created. The backend should emit the
'printer-list-done' signal when it has complete loaded its printers.
6.2 Method 2: void (*printer_request_details) (GtkPrinter *printer);
This method is invoked when a printer is selected as in GtkPrintUnixDialog
(registered as a callback to the "changed" signal of the scrolled list).
It is important to note that request_details is optional and only needed
when you need to asynchronously fill in printer details. The lpr backend has
no need for that, so it just always marks printers as "has_details".
When the details have been filled in, the backend must set the
has_details flag on the printer, and emit the details-acquired signal.
6.3 Method 3: GtkPrintCapabilities (*printer_get_capabilities) (GtkPrinter *)
This is a key design of the GTK+ printing, where applications *MUST* query
this value and to response accordingly in how to generate its data for
printing.
Examples are: GTK_PRINT_CAPABILITY_COPIES, GTK_PRINT_CAPABILITY_PAGE_SET,
GTK_PRINT_CAPABILITY_COLLATE, GTK_PRINT_CAPABILITY_REVERSE,
GTK_PRINT_CAPABILITY_SCALE
(Current list are in gtkprintjob.h, but this can be extended if requires)
NOTE: Applications only need to deal with this manually if the choose to use
the Unix printing api. The portable api is handling most of this
automatically.
6.4 Method 4: GtkPrinterOptionSet *(*printer_get_options) (GtkPrinter *,
GtkPrintSettings *,
GtkPageSetup *,
GtkPrintCapabilities);
These two methods are invoked by the GtkPrintUnixDialog on the signal of
"details-acquired". _gtk_printer_get_capabilities() simply return the values
that the backend printer set.
printer_get_options () is the real worker for getting all the options that
the particular backend printer capable of support and display them into the
GUI template of the GTK+ print dialog box. The backend should obtain what
ever it support from either its print server of printer description file if
applicable.
Based on the different options setting, different tab will be shown on
the GTK+ Print dialog. Much of these information are derived from the
PPD files for the printer.
NOTE: This is the most tedious of works mapping various bits and pieces of
the same thing but with different terminology amid the different backends.
6.5 Method 5: void (*printer_get_settings_from_options) (GtkPrinter *printer,
GtkPrinterOptionSet *,
GtkPrintSettings *);
This method is invoked when the Print button on the Print dialog is pressed.
The purpose of this method is to gather from the settings on the print
dialog that the user may have selected before the Print buttin is activated.
6.6 Method 6: void (*printer_prepare_for_print) (GtkPrinter *,
GtkPrintJob *,
GtkPrintSettings *,
GtkPageSetup *);
After the values of the various settings have been gathered, the backend
is now ready to set up the print-job object to be sent to the actual
printer.
6.7 Method 7: void (*print_stream) (GtkPrintBackend *backend,
GtkPrintJob *job,
GIOChannel *data_io,
GtkPrintJobCompleteFunc callback,
gpointer user_data,
GDestroyNotify dnotify);
This is the method that does the really print job submission. Print data
is sent over the GIOChannel.
The application generates the data for printing through the data_io
stream, the backend print system read the data from here. The backend
should call the callback function when it is done, call the dnotify on
user_data and finally update the status of the print job.
If the data is processed asynchronously, a ref top the print job should
be made so as to keep the ref it alive until the print system has completed
the processing.
7. Once you are happy with the code, compile them and install them.
8. The backend module should generate a share library in
modules/printbackends<backend>/.libs/<myprintbackend>.so
9. The backend module should be installed into
<prefix>/lib/gtk-2.0/2.10.x/printbackends
III. What still need to be done
Thre are a couple of still missing (wholely my faults)
o there is no mention how to handle the method
gboolean (*printer_mark_conflicts)(GtkPrinter *printer,
GtkPrinterOptionSet *options);
Alex has this first comment:
It doesn't mention conflict handling, but maybe CUPS/PPDs is the only
system that handle that.
My reply: This typically is the case when the user has selected a pagesize
that is not being supported by the printer according to its PPDs.
Alex has this further comments:
- That is a simple version of conflicts. But PPDs can specify much more
interesting conflicts. For instance, if you have installed an extension
to the printer or added more memory it can make more options availible.
And some features conflict, like the printer might not support stapling
when printing to some output bins, etc.
o Examples to explain more on details about options and groups and how
they work, and how the print dialog sorts options into tabs. The real
tricky bits is to map the inconsistent naming of the attributes among
cups, gtk+ printing, and that of PPDs.
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]