X11 platform: use Gnome printer dialog when the GTK library is available at run-time

The code to determine whether the GTK library is available is now in Fl_X11_System_Driver::probe_for_GTK()
called both by Fl_Printer::begin_job() and Fl_Native_File_Chooser.
New Fl::option OPTION_PRINTER_USES_GTK allows to deactivate use of
the Gnome print dialog.

Minor change in Fl_Native_File_Chooser: GTK version 3 is searched before version 2,
whereas the search order was the opposite before.
This commit is contained in:
ManoloFLTK 2019-09-15 15:57:29 +02:00
parent 000807cc1d
commit c549b7acbd
9 changed files with 352 additions and 69 deletions

View File

@ -252,6 +252,10 @@ public:
/// if the GTK library is available on the platform (linux/unix only).
/// When switched off, GTK file dialogs aren't used even if the GTK library is available.
OPTION_FNFC_USES_GTK,
/// When switched on (default), Fl_Printer runs the GTK printer dialog
/// if the GTK library is available on the platform (linux/unix only).
/// When switched off, the GTK printer dialog isn't used even if the GTK library is available.
OPTION_PRINTER_USES_GTK,
/// When switched on (default), the library shows in a transient yellow window the zoom factor
/// value.
/// When switched off, no such window gets displayed.

View File

@ -555,6 +555,7 @@ static void refreshUI() {
wShowTooltips->value(opt[Fl::OPTION_SHOW_TOOLTIPS][mode]);
wDNDText->value(opt[Fl::OPTION_DND_TEXT][mode]);
wGTKText->value(opt[Fl::OPTION_FNFC_USES_GTK][mode]);
wPrintGTKText->value(opt[Fl::OPTION_PRINTER_USES_GTK][mode]);
}
/**
@ -570,6 +571,7 @@ static void readPrefs() {
opt_prefs.get("DNDText", opt[Fl::OPTION_DND_TEXT][1], 2);
opt_prefs.get("ShowTooltips", opt[Fl::OPTION_SHOW_TOOLTIPS][1], 2);
opt_prefs.get("FNFCUsesGTK", opt[Fl::OPTION_FNFC_USES_GTK ][1], 2);
opt_prefs.get("PrintUsesGTK", opt[Fl::OPTION_PRINTER_USES_GTK ][1], 2);
}
{
Fl_Preferences prefs(Fl_Preferences::USER, "fltk.org", "fltk");
@ -579,6 +581,7 @@ static void readPrefs() {
opt_prefs.get("DNDText", opt[Fl::OPTION_DND_TEXT][0], 2);
opt_prefs.get("ShowTooltips", opt[Fl::OPTION_SHOW_TOOLTIPS][0], 2);
opt_prefs.get("FNFCUsesGTK", opt[Fl::OPTION_FNFC_USES_GTK ][0], 2);
opt_prefs.get("PrintUsesGTK", opt[Fl::OPTION_PRINTER_USES_GTK ][0], 2);
}
refreshUI();
}
@ -601,6 +604,8 @@ static void writePrefs() {
else opt_prefs.set("ShowTooltips", opt[Fl::OPTION_SHOW_TOOLTIPS][1]);
if (opt[Fl::OPTION_FNFC_USES_GTK][1]==2) opt_prefs.deleteEntry("FNFCUsesGTK");
else opt_prefs.set("FNFCUsesGTK", opt[Fl::OPTION_FNFC_USES_GTK][1]);
if (opt[Fl::OPTION_PRINTER_USES_GTK][1]==2) opt_prefs.deleteEntry("PrintUsesGTK");
else opt_prefs.set("PrintUsesGTK", opt[Fl::OPTION_PRINTER_USES_GTK][1]);
}
{
Fl_Preferences prefs(Fl_Preferences::USER, "fltk.org", "fltk");
@ -615,6 +620,8 @@ static void writePrefs() {
else opt_prefs.set("ShowTooltips", opt[Fl::OPTION_SHOW_TOOLTIPS][0]);
if (opt[Fl::OPTION_FNFC_USES_GTK][0]==2) opt_prefs.deleteEntry("FNFCUsesGTK");
else opt_prefs.set("FNFCUsesGTK", opt[Fl::OPTION_FNFC_USES_GTK][0]);
if (opt[Fl::OPTION_PRINTER_USES_GTK][0]==2) opt_prefs.deleteEntry("PrintUsesGTK");
else opt_prefs.set("PrintUsesGTK", opt[Fl::OPTION_PRINTER_USES_GTK][0]);
}
}
@ -705,6 +712,20 @@ Fl_Menu_Item menu_wGTKText[] = {
{0,0,0,0,0,0,0,0,0}
};
Fl_Choice *wPrintGTKText=(Fl_Choice *)0;
static void cb_wPrintGTKText(Fl_Choice*, void*) {
int mode = wUserOrSystem->value();
opt[Fl::OPTION_PRINTER_USES_GTK ][mode] = wPrintGTKText->value();
}
Fl_Menu_Item menu_wPrintGTKText[] = {
{"off", 0, 0, (void*)(0), 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0},
{"on", 0, 0, (void*)(1), 128, (uchar)FL_NORMAL_LABEL, 0, 14, 0},
{"default", 0, 0, (void*)(2), 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0},
{0,0,0,0,0,0,0,0,0}
};
Fl_Choice *wUserOrSystem=(Fl_Choice *)0;
static void cb_wUserOrSystem(Fl_Choice*, void*) {
@ -727,7 +748,7 @@ global_settings_window->hide();
}
Fl_Double_Window* make_global_settings_window() {
{ global_settings_window = new Fl_Double_Window(400, 378, "FLTK Preferences");
{ global_settings_window = new Fl_Double_Window(400, 455, "FLTK Preferences");
global_settings_window->color(FL_LIGHT1);
{ Fl_Group* o = new Fl_Group(10, 10, 380, 100, "Keyboard Focus Options");
o->box(FL_GTK_DOWN_BOX);
@ -798,7 +819,22 @@ s available.\n\nDefault is on.");
} // Fl_Choice* wGTKText
o->end();
} // Fl_Group* o
{ wUserOrSystem = new Fl_Choice(10, 345, 141, 25);
{ Fl_Group* o = new Fl_Group(10, 345, 380, 66, "Print dialog Options");
o->box(FL_GTK_DOWN_BOX);
o->labelfont(2);
o->align(Fl_Align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE));
{ wPrintGTKText = new Fl_Choice(245, 366, 100, 25, "Print dialog uses GTK:");
wPrintGTKText->tooltip("OPTION_PRINTER_USES_GTK\n\nIf \'Print dialog uses GTK\' is enabled, the Fl_Pr\
inter class\ncalls the GTK print dialog when it\'s available on the platfom. I\
f disabled, the Fl_Printer class\nalways uses FLTK\'s own print dialog even if\
GTK is available.\n\nDefault is on.");
wPrintGTKText->down_box(FL_BORDER_BOX);
wPrintGTKText->callback((Fl_Callback*)cb_wPrintGTKText);
wPrintGTKText->menu(menu_wPrintGTKText);
} // Fl_Choice* wPrintGTKText
o->end();
} // Fl_Group* o
{ wUserOrSystem = new Fl_Choice(10, 420, 141, 25);
wUserOrSystem->tooltip("Change settings for the current user, or default values for all users of this\
computer. Individual users can override system options, if they set their opt\
ions to specific values (not \'default\').");
@ -806,10 +842,10 @@ ions to specific values (not \'default\').");
wUserOrSystem->callback((Fl_Callback*)cb_wUserOrSystem);
wUserOrSystem->menu(menu_wUserOrSystem);
} // Fl_Choice* wUserOrSystem
{ Fl_Button* o = new Fl_Button(230, 345, 75, 25, "Cancel");
{ Fl_Button* o = new Fl_Button(230, 420, 75, 25, "Cancel");
o->callback((Fl_Callback*)cb_Cancel1);
} // Fl_Button* o
{ Fl_Button* o = new Fl_Button(315, 345, 75, 25, "OK");
{ Fl_Button* o = new Fl_Button(315, 420, 75, 25, "OK");
o->callback((Fl_Callback*)cb_OK);
} // Fl_Button* o
global_settings_window->end();

View File

@ -484,7 +484,8 @@ wVisibleFocus->value(opt[Fl::OPTION_VISIBLE_FOCUS][mode]);
wArrowFocus->value(opt[Fl::OPTION_ARROW_FOCUS][mode]);
wShowTooltips->value(opt[Fl::OPTION_SHOW_TOOLTIPS][mode]);
wDNDText->value(opt[Fl::OPTION_DND_TEXT][mode]);
wGTKText->value(opt[Fl::OPTION_FNFC_USES_GTK][mode]);} {}
wGTKText->value(opt[Fl::OPTION_FNFC_USES_GTK][mode]);
wPrintGTKText->value(opt[Fl::OPTION_PRINTER_USES_GTK][mode]);} {}
}
Function {readPrefs()} {
@ -499,6 +500,7 @@ Function {readPrefs()} {
opt_prefs.get("DNDText", opt[Fl::OPTION_DND_TEXT][1], 2);
opt_prefs.get("ShowTooltips", opt[Fl::OPTION_SHOW_TOOLTIPS][1], 2);
opt_prefs.get("FNFCUsesGTK", opt[Fl::OPTION_FNFC_USES_GTK ][1], 2);
opt_prefs.get("PrintUsesGTK", opt[Fl::OPTION_PRINTER_USES_GTK ][1], 2);
}
{
Fl_Preferences prefs(Fl_Preferences::USER, "fltk.org", "fltk");
@ -508,6 +510,7 @@ Function {readPrefs()} {
opt_prefs.get("DNDText", opt[Fl::OPTION_DND_TEXT][0], 2);
opt_prefs.get("ShowTooltips", opt[Fl::OPTION_SHOW_TOOLTIPS][0], 2);
opt_prefs.get("FNFCUsesGTK", opt[Fl::OPTION_FNFC_USES_GTK ][0], 2);
opt_prefs.get("PrintUsesGTK", opt[Fl::OPTION_PRINTER_USES_GTK ][0], 2);
}
refreshUI();} {}
}
@ -529,6 +532,8 @@ Function {writePrefs()} {
else opt_prefs.set("ShowTooltips", opt[Fl::OPTION_SHOW_TOOLTIPS][1]);
if (opt[Fl::OPTION_FNFC_USES_GTK][1]==2) opt_prefs.deleteEntry("FNFCUsesGTK");
else opt_prefs.set("FNFCUsesGTK", opt[Fl::OPTION_FNFC_USES_GTK][1]);
if (opt[Fl::OPTION_PRINTER_USES_GTK][1]==2) opt_prefs.deleteEntry("PrintUsesGTK");
else opt_prefs.set("PrintUsesGTK", opt[Fl::OPTION_PRINTER_USES_GTK][1]);
}
{
Fl_Preferences prefs(Fl_Preferences::USER, "fltk.org", "fltk");
@ -543,6 +548,8 @@ Function {writePrefs()} {
else opt_prefs.set("ShowTooltips", opt[Fl::OPTION_SHOW_TOOLTIPS][0]);
if (opt[Fl::OPTION_FNFC_USES_GTK][0]==2) opt_prefs.deleteEntry("FNFCUsesGTK");
else opt_prefs.set("FNFCUsesGTK", opt[Fl::OPTION_FNFC_USES_GTK][0]);
if (opt[Fl::OPTION_PRINTER_USES_GTK][0]==2) opt_prefs.deleteEntry("PrintUsesGTK");
else opt_prefs.set("PrintUsesGTK", opt[Fl::OPTION_PRINTER_USES_GTK][0]);
}} {}
}
@ -565,7 +572,7 @@ global_settings_window->show();} {}
Function {make_global_settings_window()} {} {
Fl_Window global_settings_window {
label {FLTK Preferences} open
xywh {1147 190 400 378} type Double color 50 hide
xywh {715 96 400 455} type Double color 50 hide
} {
Fl_Group {} {
label {Keyboard Focus Options} open
@ -719,9 +726,42 @@ Default is on.} xywh {245 300 100 25} down_box BORDER_BOX
}
}
}
Fl_Group {} {
label {Print dialog Options} open
xywh {10 345 380 66} box GTK_DOWN_BOX labelfont 2 align 21
} {
Fl_Choice wPrintGTKText {
label {Print dialog uses GTK:}
callback {int mode = wUserOrSystem->value();
opt[Fl::OPTION_PRINTER_USES_GTK ][mode] = wPrintGTKText->value();} open
tooltip {OPTION_PRINTER_USES_GTK
If 'Print dialog uses GTK' is enabled, the Fl_Printer class
calls the GTK print dialog when it's available on the platfom. If disabled, the Fl_Printer class
always uses FLTK's own print dialog even if GTK is available.
Default is on.} xywh {245 366 100 25} down_box BORDER_BOX
} {
MenuItem {} {
label off
user_data 0 user_data_type long selected
xywh {30 30 31 20}
}
MenuItem {} {
label on
user_data 1 user_data_type long
xywh {30 30 31 20} divider
}
MenuItem {} {
label default
user_data 2 user_data_type long
xywh {30 30 31 20}
}
}
}
Fl_Choice wUserOrSystem {
callback {refreshUI();} open
tooltip {Change settings for the current user, or default values for all users of this computer. Individual users can override system options, if they set their options to specific values (not 'default').} xywh {10 345 141 25} down_box BORDER_BOX
tooltip {Change settings for the current user, or default values for all users of this computer. Individual users can override system options, if they set their options to specific values (not 'default').} xywh {10 420 141 25} down_box BORDER_BOX
} {
MenuItem {} {
label {User Settings}
@ -737,13 +777,13 @@ Default is on.} xywh {245 300 100 25} down_box BORDER_BOX
Fl_Button {} {
label Cancel
callback {global_settings_window->hide();}
xywh {230 345 75 25}
xywh {230 420 75 25}
}
Fl_Button {} {
label OK
callback {writePrefs();
global_settings_window->hide();}
xywh {315 345 75 25}
xywh {315 420 75 25}
}
}
code {readPrefs();

View File

@ -108,6 +108,7 @@ extern Fl_Choice *wArrowFocus;
extern Fl_Choice *wShowTooltips;
extern Fl_Choice *wDNDText;
extern Fl_Choice *wGTKText;
extern Fl_Choice *wPrintGTKText;
extern Fl_Choice *wUserOrSystem;
Fl_Double_Window* make_global_settings_window();
extern Fl_Menu_Item menu_wVisibleFocus[];
@ -115,6 +116,7 @@ extern Fl_Menu_Item menu_wArrowFocus[];
extern Fl_Menu_Item menu_wShowTooltips[];
extern Fl_Menu_Item menu_wDNDText[];
extern Fl_Menu_Item menu_wGTKText[];
extern Fl_Menu_Item menu_wPrintGTKText[];
extern Fl_Menu_Item menu_wUserOrSystem[];
#endif

View File

@ -1866,7 +1866,9 @@ bool Fl::option(Fl_Option opt)
options_[OPTION_SHOW_TOOLTIPS] = tmp;
opt_prefs.get("FNFCUsesGTK", tmp, 1); // default: on
options_[OPTION_FNFC_USES_GTK] = tmp;
opt_prefs.get("PrintUsesGTK", tmp, 1); // default: on
options_[OPTION_PRINTER_USES_GTK] = tmp;
opt_prefs.get("ShowZoomFactor", tmp, 1); // default: on
options_[OPTION_SHOW_SCALING] = tmp;
}
@ -1888,7 +1890,9 @@ bool Fl::option(Fl_Option opt)
if (tmp >= 0) options_[OPTION_SHOW_TOOLTIPS] = tmp;
opt_prefs.get("FNFCUsesGTK", tmp, -1);
if (tmp >= 0) options_[OPTION_FNFC_USES_GTK] = tmp;
opt_prefs.get("PrintUsesGTK", tmp, -1);
if (tmp >= 0) options_[OPTION_PRINTER_USES_GTK] = tmp;
opt_prefs.get("ShowZoomFactor", tmp, -1);
if (tmp >= 0) options_[OPTION_SHOW_SCALING] = tmp;
}

View File

@ -24,6 +24,7 @@
#if HAVE_DLSYM && HAVE_DLFCN_H
#include <dlfcn.h> // for dlopen et al
#include "drivers/X11/Fl_X11_System_Driver.H"
#endif
#include <locale.h> // for setlocale
@ -159,10 +160,6 @@ static XX_g_slist_length fl_g_slist_length = NULL;
typedef void (*XX_g_slist_free) (GSList *);
static XX_g_slist_free fl_g_slist_free = NULL;
// gboolean gtk_init_check (int *argc, char ***argv);
typedef gboolean (*XX_gtk_init_check)(int *, char ***);
static XX_gtk_init_check fl_gtk_init_check = NULL;
// void gtk_widget_destroy (GtkWidget *widget);
typedef void (*XX_gtk_widget_destroy) (GtkWidget *);
static XX_gtk_widget_destroy fl_gtk_widget_destroy = NULL;
@ -262,9 +259,9 @@ static XX_gtk_widget_show_now fl_gtk_widget_show_now = NULL;
typedef GdkWindow* (*XX_gtk_widget_get_window)(GtkWidget *);
static XX_gtk_widget_get_window fl_gtk_widget_get_window = NULL;
// Window gdk_x11_drawable_get_xid(GdkWindow *);
typedef Window (*XX_gdk_x11_drawable_get_xid)(GdkWindow *);
static XX_gdk_x11_drawable_get_xid fl_gdk_x11_drawable_get_xid = NULL;
// Window gdk_x11_drawable_get_xid(GdkWindow *); or gdk_x11_window_get_xid
typedef Window (*gdk_to_X11_t)(GdkWindow*);
static gdk_to_X11_t fl_gdk_to_X11 = NULL;
// GtkWidget *gtk_check_button_new_with_label(const gchar *);
typedef GtkWidget* (*XX_gtk_check_button_new_with_label)(const gchar *);
@ -492,15 +489,8 @@ static void run_response_handler(GtkDialog *dialog, gint response_id, gpointer d
int Fl_GTK_Native_File_Chooser_Driver::fl_gtk_chooser_wrapper()
{
int result = 1;
static int have_gtk_init = 0;
char *p;
if(!have_gtk_init) {
have_gtk_init = -1;
int ac = 0;
fl_gtk_init_check(&ac, NULL);
}
if(gtkw_ptr) { // discard the previous dialog widget
fl_gtk_widget_destroy (gtkw_ptr);
gtkw_ptr = NULL;
@ -611,7 +601,7 @@ int Fl_GTK_Native_File_Chooser_Driver::fl_gtk_chooser_wrapper()
fl_gtk_widget_show_now(gtkw_ptr); // map the GTK window on screen
if (firstw) {
GdkWindow* gdkw = fl_gtk_widget_get_window(gtkw_ptr);
Window xw = fl_gdk_x11_drawable_get_xid(gdkw); // get the X11 ref of the GTK window
Window xw = fl_gdk_to_X11(gdkw); // get the X11 ref of the GTK window
XSetTransientForHint(fl_display, xw, fl_xid(firstw)); // set the GTK window transient for the last FLTK win
}
gboolean state = fl_gtk_file_chooser_get_show_hidden((GtkFileChooser *)gtkw_ptr);
@ -701,57 +691,22 @@ fprintf(stderr, "%s\n", pc_dl_error); \
did_find_GTK_libs = 0; \
return; }
static void* fl_dlopen(const char *filename1, const char *filename2)
{
void *ptr = dlopen(filename1, RTLD_LAZY | RTLD_GLOBAL);
if (!ptr) ptr = dlopen(filename2, RTLD_LAZY | RTLD_GLOBAL);
return ptr;
}
#endif // HAVE_DLSYM && HAVE_DLFCN_H
/*
/*
* Use dlopen to see if we can load the gtk dynamic libraries that
* will allow us to create a GtkFileChooserDialog() on the fly,
* without linking to the GTK libs at compile time.
*/
void Fl_GTK_Native_File_Chooser_Driver::probe_for_GTK_libs(void) {
#if HAVE_DLSYM && HAVE_DLFCN_H
void *ptr_glib = NULL;
void *ptr_gtk = NULL;
# ifdef __APPLE_CC__ // allows testing on Darwin + X11
ptr_glib = dlopen("/sw/lib/libglib-2.0.dylib", RTLD_LAZY | RTLD_GLOBAL);
# else
ptr_glib = fl_dlopen("libglib-2.0.so", "libglib-2.0.so.0");
# endif
// Try first with GTK2
# ifdef __APPLE_CC__ // allows testing on Darwin + X11
ptr_gtk = dlopen("/sw/lib/libgtk-x11-2.0.dylib", RTLD_LAZY | RTLD_GLOBAL);
#else
ptr_gtk = fl_dlopen("libgtk-x11-2.0.so", "libgtk-x11-2.0.so.0");
#endif
if (ptr_gtk && ptr_glib) {
#ifdef DEBUG
puts("selected GTK-2\n");
#endif
}
else {// Try then with GTK3
ptr_gtk = fl_dlopen("libgtk-3.so", "libgtk-3.so.0");
#ifdef DEBUG
if (ptr_gtk && ptr_glib) {
puts("selected GTK-3\n");
}
#endif
}
if((!ptr_glib) || (!ptr_gtk)) {
#ifdef DEBUG
puts("Failure to load libglib or libgtk");
#endif
void *ptr_gtk;
if ( !Fl_X11_System_Driver::probe_for_GTK(2, 4, &ptr_gtk)) {
did_find_GTK_libs = 0;
return;
}
void *ptr_glib = ptr_gtk;
char *pc_dl_error; // used to report errors by the GET_SYM macro...
// items we need from GLib
GET_SYM(g_free, ptr_glib);
@ -759,7 +714,6 @@ void Fl_GTK_Native_File_Chooser_Driver::probe_for_GTK_libs(void) {
GET_SYM(g_slist_length, ptr_glib);
GET_SYM(g_slist_free, ptr_glib);
// items we need from GTK
GET_SYM(gtk_init_check, ptr_gtk);
GET_SYM(gtk_widget_destroy, ptr_gtk);
GET_SYM(gtk_file_chooser_set_select_multiple, ptr_gtk);
GET_SYM(gtk_file_chooser_set_do_overwrite_confirmation, ptr_gtk);
@ -784,7 +738,9 @@ void Fl_GTK_Native_File_Chooser_Driver::probe_for_GTK_libs(void) {
GET_SYM(gtk_file_chooser_set_extra_widget, ptr_gtk);
GET_SYM(gtk_widget_show_now, ptr_gtk);
GET_SYM(gtk_widget_get_window, ptr_gtk);
GET_SYM(gdk_x11_drawable_get_xid, ptr_gtk);
fl_gdk_to_X11 = (gdk_to_X11_t)dlsym(ptr_gtk, "gdk_x11_drawable_get_xid");
if (!fl_gdk_to_X11) fl_gdk_to_X11 = (gdk_to_X11_t)dlsym(ptr_gtk, "gdk_x11_window_get_xid");
if (!fl_gdk_to_X11) { did_find_GTK_libs = 0; return; }
GET_SYM(gtk_check_button_new_with_label, ptr_gtk);
GET_SYM(g_signal_connect_data, ptr_gtk);
GET_SYM(gtk_toggle_button_get_active, ptr_gtk);

View File

@ -31,8 +31,188 @@ class Fl_Posix_Printer_Driver : public Fl_PostScript_File_Device {
virtual int begin_job(int pagecount, int *frompage = NULL, int *topage = NULL);
};
#if HAVE_DLSYM && HAVE_DLFCN_H
// GTK types
#include <dlfcn.h> // for dlopen et al
#include <unistd.h> // for mkstemp
#include <FL/filename.H>
#include "../X11/Fl_X11_System_Driver.H"
#define GTK_PAPER_NAME_LETTER "na_letter"
#define GTK_RESPONSE_NONE 0
#define GTK_RESPONSE_OK -5
#define GTK_PRINT_PAGES_RANGES 2
class Fl_GTK_Printer_Driver : public Fl_PostScript_File_Device {
public:
typedef int gboolean;
typedef struct _GtkPrintUnixDialog GtkPrintUnixDialog;
typedef struct _GtkDialog GtkDialog;
typedef struct _GtkPrintSettings GtkPrintSettings;
typedef struct _GtkPageSetup GtkPageSetup;
enum GtkPageOrientation {GTK_PAGE_ORIENTATION_PORTRAIT, GTK_PAGE_ORIENTATION_LANDSCAPE};
typedef struct _GtkPaperSize GtkPaperSize;
typedef struct _GtkPrinter GtkPrinter;
typedef struct _GtkPrintJob GtkPrintJob;
typedef struct _GtkWidget GtkWidget;
struct GError;
GtkPrintJob *pjob; // data shared between begin_job() and end_job()
char tmpfilename[50]; // name of temporary PostScript file containing to-be-printed data
virtual int begin_job(int pagecount, int *frompage = NULL, int *topage = NULL);
virtual void end_job();
static bool probe_for_GTK();
static void *ptr_gtk; // points to the GTK dynamic lib or NULL
typedef GtkPrintUnixDialog* (*gtk_print_unix_dialog_new_t)(const char*, void*);
typedef int (*gtk_dialog_run_t)(GtkDialog*);
typedef GtkPrintSettings *(*gtk_print_unix_dialog_get_settings_t)(GtkPrintUnixDialog*);
typedef void (*gtk_print_unix_dialog_set_settings_t)(GtkPrintUnixDialog*, GtkPrintSettings*);
typedef GtkPageSetup *(*gtk_print_unix_dialog_get_page_setup_t)(GtkPrintUnixDialog*);
typedef GtkPageOrientation (*gtk_page_setup_get_orientation_t)(GtkPageSetup*);
typedef GtkPaperSize* (*gtk_page_setup_get_paper_size_t)(GtkPageSetup*);
typedef const char * (*gtk_paper_size_get_name_t)(GtkPaperSize*);
typedef GtkPrinter * (*gtk_print_unix_dialog_get_selected_printer_t)(GtkPrintUnixDialog*);
typedef int (*gtk_printer_accepts_ps_t)(GtkPrinter*);
typedef int (*gtk_printer_is_active_t)(GtkPrinter*);
typedef GtkPrintJob *(*gtk_print_job_new_t)(const char *, GtkPrinter *, GtkPrintSettings *, GtkPageSetup *);
typedef void (*gtk_widget_hide_t)(GtkWidget*);
typedef void (*gtk_widget_destroy_t)(GtkWidget*);
typedef gboolean (*gtk_events_pending_t)(void);
typedef void (*gtk_main_iteration_t)(void);
typedef int (*gtk_print_job_set_source_file_t)(GtkPrintJob *job, const char *filename, GError **error);
typedef void (*gtk_print_job_send_t)(GtkPrintJob *, void* , gboolean* , void* );
typedef void (*gtk_print_settings_set_t) (GtkPrintSettings *settings, const char *key, const char *value);
typedef const char * (*gtk_print_settings_get_t) (GtkPrintSettings *settings, const char *key );
typedef int (*gtk_print_settings_get_print_pages_t)(GtkPrintSettings*);
struct GtkPageRange { int start, end; };
typedef GtkPageRange* (*gtk_print_settings_get_page_ranges_t)(GtkPrintSettings*, int*);
typedef void (*g_object_unref_t)(void* object);
};
// the CALL_GTK macro produces the source code to call a GTK function given its name
// or to get a pointer to this function :
// CALL_GTK(gtk_my_function) produces ((gtk_my_function_t)dlsym(ptr_gtk, "gtk_my_function"))
#define CALL_GTK(NAME) ((NAME##_t)dlsym(ptr_gtk, #NAME))
void *Fl_GTK_Printer_Driver::ptr_gtk = NULL;
// test wether GTK is available at run-time
bool Fl_GTK_Printer_Driver::probe_for_GTK() {
return Fl_X11_System_Driver::probe_for_GTK(2, 10, &ptr_gtk);
}
int Fl_GTK_Printer_Driver::begin_job(int pagecount, int *firstpage, int *lastpage) {
enum Fl_Paged_Device::Page_Format format = Fl_Paged_Device::A4;
enum Fl_Paged_Device::Page_Layout layout = Fl_Paged_Device::PORTRAIT ;
GtkPrintUnixDialog *pdialog = CALL_GTK(gtk_print_unix_dialog_new)(Fl_Printer::dialog_title, NULL); //2.10
GtkPrintSettings *psettings = CALL_GTK(gtk_print_unix_dialog_get_settings)(pdialog); //2.10
CALL_GTK(gtk_print_settings_set)(psettings, "output-file-format", "ps"); //2.10
char line[FL_PATH_MAX + 20], cwd[FL_PATH_MAX];
sprintf(line, "file://%s/FLTK.ps", fl_getcwd(cwd, FL_PATH_MAX));
CALL_GTK(gtk_print_settings_set)(psettings, "output-uri", line); //2.10
CALL_GTK(gtk_print_unix_dialog_set_settings)(pdialog, psettings); //2.10
CALL_GTK(g_object_unref)(psettings);
int response_id = CALL_GTK(gtk_dialog_run)((GtkDialog*)pdialog);
if (response_id == GTK_RESPONSE_OK) {
GtkPageSetup *psetup = CALL_GTK(gtk_print_unix_dialog_get_page_setup)(pdialog); //2.10
GtkPageOrientation orient = CALL_GTK(gtk_page_setup_get_orientation)(psetup); //2.10
if (orient == GTK_PAGE_ORIENTATION_LANDSCAPE) layout = Fl_Paged_Device::LANDSCAPE;
GtkPaperSize* psize = CALL_GTK(gtk_page_setup_get_paper_size)(psetup); //2.10
const char *pname = CALL_GTK(gtk_paper_size_get_name)(psize); //2.10
if (strcmp(pname, GTK_PAPER_NAME_LETTER) == 0) format = Fl_Paged_Device::LETTER;
GtkPrinter *gprinter = CALL_GTK(gtk_print_unix_dialog_get_selected_printer)(pdialog); //2.10
psettings = CALL_GTK(gtk_print_unix_dialog_get_settings)(pdialog); //2.10
const char* p = CALL_GTK(gtk_print_settings_get)(psettings, "output-uri"); //2.10
bool printing_to_file = (p != NULL);
if (printing_to_file) {
p += 6; // skip "file://" prefix
strcpy(line, p);
int l = strlen(p);
if (strcmp(p+l-4, "/.ps") == 0) {
line[l-3] = 0;
strcat(line, "FLTK.ps");
}
}
if (firstpage && lastpage) {
*firstpage = 1; *lastpage = pagecount;
if (CALL_GTK(gtk_print_settings_get_print_pages)(psettings) == GTK_PRINT_PAGES_RANGES) { // 2.10
int num_ranges;
GtkPageRange *ranges = CALL_GTK(gtk_print_settings_get_page_ranges)(psettings, &num_ranges); //2.10
if (num_ranges > 0) {
*firstpage = ranges[0].start + 1;
*lastpage = ranges[0].end + 1;
free(ranges);
}
}
}
response_id = GTK_RESPONSE_NONE;
if (printing_to_file) {
pjob = NULL;
FILE *output = fopen(line, "w");
if (output) {
Fl_PostScript_File_Device::begin_job(output, 0, format, layout);
response_id = GTK_RESPONSE_OK;
}
} else if ( CALL_GTK(gtk_printer_accepts_ps)(gprinter) && //2.10
CALL_GTK(gtk_printer_is_active)(gprinter) ) { // 2.10
strcpy(tmpfilename, "/tmp/FLTKprintjobXXXXXX");
int fd = mkstemp(tmpfilename);
if (fd >= 0) {
FILE *output = fdopen(fd, "w");
Fl_PostScript_File_Device::begin_job(output, 0, format, layout);
pjob = CALL_GTK(gtk_print_job_new)("FLTK print job", gprinter, psettings, psetup); //2.10
response_id = GTK_RESPONSE_OK;
}
}
CALL_GTK(g_object_unref)(psettings);
}
CALL_GTK(gtk_widget_hide)((GtkWidget*)pdialog);
gtk_events_pending_t fl_gtk_events_pending = CALL_GTK(gtk_events_pending);
gtk_main_iteration_t fl_gtk_main_iteration = CALL_GTK(gtk_main_iteration);
while (fl_gtk_events_pending()) fl_gtk_main_iteration();
CALL_GTK(gtk_widget_destroy)((GtkWidget*)pdialog);
Fl_Window *first = Fl::first_window();
if (first) {
Fl_Surface_Device::push_current(Fl_Display_Device::display_device());
first->show();
while (Fl::ready()) Fl::check();
Fl_Surface_Device::pop_current();
}
return (response_id == GTK_RESPONSE_OK ? 0 : 1);
}
static void pJobCompleteFunc(Fl_GTK_Printer_Driver::GtkPrintJob *print_job, Fl_GTK_Printer_Driver::gboolean *user_data, const Fl_GTK_Printer_Driver::GError *error) {
*user_data = true;
}
static void pDestroyNotify(void* data) {}
void Fl_GTK_Printer_Driver::end_job() {
Fl_PostScript_File_Device::end_job();
Fl_PostScript_Graphics_Driver *psgd = driver();
fclose(psgd->output);
if (!pjob) return;
GError *gerr;
gboolean gb = CALL_GTK(gtk_print_job_set_source_file)(pjob, tmpfilename, &gerr); //2.10
if (gb) {
gb = false;
CALL_GTK(gtk_print_job_send)(pjob, (void*)pJobCompleteFunc, &gb, (void*)pDestroyNotify); //2.10
gtk_main_iteration_t fl_gtk_main_iteration = CALL_GTK(gtk_main_iteration);
while (!gb) {
fl_gtk_main_iteration();
}
}
fl_unlink(tmpfilename);
}
#endif // HAVE_DLSYM && HAVE_DLFCN_H
Fl_Paged_Device* Fl_Printer::newPrinterDriver(void)
{
#if HAVE_DLSYM && HAVE_DLFCN_H
static bool gtk = ( Fl::option(Fl::OPTION_PRINTER_USES_GTK) ? Fl_GTK_Printer_Driver::probe_for_GTK() : false);
if (gtk) return new Fl_GTK_Printer_Driver();
#endif
return new Fl_Posix_Printer_Driver();
}

View File

@ -20,6 +20,7 @@
#ifndef FL_X11_SYSTEM_DRIVER_H
#define FL_X11_SYSTEM_DRIVER_H
#include "../../config_lib.h"
#include "../Posix/Fl_Posix_System_Driver.H"
class Fl_X11_System_Driver : public Fl_Posix_System_Driver {
@ -63,6 +64,9 @@ public:
virtual void add_fd(int fd, Fl_FD_Handler cb, void* = 0);
virtual void remove_fd(int, int when);
virtual void remove_fd(int);
#if HAVE_DLSYM && HAVE_DLFCN_H
static bool probe_for_GTK(int major, int minor, void **ptr_gtk);
#endif
};
#endif /* FL_X11_SYSTEM_DRIVER_H */

View File

@ -517,6 +517,63 @@ int Fl_X11_System_Driver::utf8locale() {
return ret;
}
#if HAVE_DLSYM && HAVE_DLFCN_H
#include <dlfcn.h> // for dlopen et al
static void* fl_dlopen(const char *filename1, const char *filename2)
{
void *ptr = dlopen(filename1, RTLD_LAZY | RTLD_GLOBAL);
if (!ptr) ptr = dlopen(filename2, RTLD_LAZY | RTLD_GLOBAL);
return ptr;
}
bool Fl_X11_System_Driver::probe_for_GTK(int major, int minor, void **ptr_gtk) {
typedef void (*init_t)(int*, void*);
*ptr_gtk = NULL;
// was GTK previously loaded?
init_t init_f = (init_t)dlsym(RTLD_DEFAULT, "gtk_init_check");
if (init_f) { // yes it was.
*ptr_gtk = RTLD_DEFAULT; // Caution: NULL under linux, not-NULL under Darwin
} else {
// Try first with GTK3
*ptr_gtk = fl_dlopen("libgtk-3.so", "libgtk-3.so.0");
if (*ptr_gtk) {
#ifdef DEBUG
puts("selected GTK-3\n");
#endif
} else {
// Try then with GTK2
# ifdef __APPLE_CC__ // allows testing on Darwin + X11
*ptr_gtk = ::dlopen("/sw/lib/libgtk-x11-2.0.dylib", RTLD_LAZY | RTLD_GLOBAL);
#else
*ptr_gtk = fl_dlopen("libgtk-x11-2.0.so", "libgtk-x11-2.0.so.0");
#endif
}
if (*ptr_gtk) {
#ifdef DEBUG
puts("selected GTK-2\n");
#endif
} else {
#ifdef DEBUG
puts("Failure to load libgtk");
#endif
return false;
}
init_f = (init_t)dlsym(*ptr_gtk, "gtk_init_check");
if (!init_f) return false;
}
int ac = 0;
init_f(&ac, NULL);
// now check if running version is high enough
if (dlsym(*ptr_gtk, "gtk_get_major_version") == NULL) { // YES indicates V 3
typedef const char* (*check_t)(int, int, int);
check_t check_f = (check_t)dlsym(*ptr_gtk, "gtk_check_version");
if (!check_f || check_f(major, minor, 0) ) return false;
}
return true;
}
#endif // HAVE_DLSYM && HAVE_DLFCN_H
#if !defined(FL_DOXYGEN)
const char *Fl_X11_System_Driver::shortcut_add_key_name(unsigned key, char *p, char *buf, const char **eom)