summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2019-09-15 15:57:29 +0200
committerManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2019-09-15 15:57:29 +0200
commitc549b7acbd65674019b731c6648a9e8eb22f70dd (patch)
tree7e6b8745573d2b8c1f9a61a7393b1e7c2b0d8f69
parent000807cc1d1a1c2f00274763f3e8e24145f1af00 (diff)
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.
-rw-r--r--FL/Fl.H4
-rw-r--r--fluid/alignment_panel.cxx44
-rw-r--r--fluid/alignment_panel.fl50
-rw-r--r--fluid/alignment_panel.h2
-rw-r--r--src/Fl.cxx8
-rw-r--r--src/Fl_Native_File_Chooser_GTK.cxx72
-rw-r--r--src/drivers/Posix/Fl_Posix_Printer_Driver.cxx180
-rw-r--r--src/drivers/X11/Fl_X11_System_Driver.H4
-rw-r--r--src/drivers/X11/Fl_X11_System_Driver.cxx57
9 files changed, 352 insertions, 69 deletions
diff --git a/FL/Fl.H b/FL/Fl.H
index 88fe801c6..0c3eab377 100644
--- a/FL/Fl.H
+++ b/FL/Fl.H
@@ -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.
diff --git a/fluid/alignment_panel.cxx b/fluid/alignment_panel.cxx
index 6444ce462..5b2335443 100644
--- a/fluid/alignment_panel.cxx
+++ b/fluid/alignment_panel.cxx
@@ -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();
diff --git a/fluid/alignment_panel.fl b/fluid/alignment_panel.fl
index e2445970a..c3e1c049a 100644
--- a/fluid/alignment_panel.fl
+++ b/fluid/alignment_panel.fl
@@ -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();
diff --git a/fluid/alignment_panel.h b/fluid/alignment_panel.h
index 1e02a5c37..5e8035bf4 100644
--- a/fluid/alignment_panel.h
+++ b/fluid/alignment_panel.h
@@ -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
diff --git a/src/Fl.cxx b/src/Fl.cxx
index 1327509e8..0a4e22ee9 100644
--- a/src/Fl.cxx
+++ b/src/Fl.cxx
@@ -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;
}
diff --git a/src/Fl_Native_File_Chooser_GTK.cxx b/src/Fl_Native_File_Chooser_GTK.cxx
index 2d6b819f9..575ab4c70 100644
--- a/src/Fl_Native_File_Chooser_GTK.cxx
+++ b/src/Fl_Native_File_Chooser_GTK.cxx
@@ -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);
diff --git a/src/drivers/Posix/Fl_Posix_Printer_Driver.cxx b/src/drivers/Posix/Fl_Posix_Printer_Driver.cxx
index 835529be1..926f1b3d6 100644
--- a/src/drivers/Posix/Fl_Posix_Printer_Driver.cxx
+++ b/src/drivers/Posix/Fl_Posix_Printer_Driver.cxx
@@ -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();
}
diff --git a/src/drivers/X11/Fl_X11_System_Driver.H b/src/drivers/X11/Fl_X11_System_Driver.H
index b7d6e9ff7..138959d75 100644
--- a/src/drivers/X11/Fl_X11_System_Driver.H
+++ b/src/drivers/X11/Fl_X11_System_Driver.H
@@ -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 */
diff --git a/src/drivers/X11/Fl_X11_System_Driver.cxx b/src/drivers/X11/Fl_X11_System_Driver.cxx
index 42d403299..f406dce02 100644
--- a/src/drivers/X11/Fl_X11_System_Driver.cxx
+++ b/src/drivers/X11/Fl_X11_System_Driver.cxx
@@ -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)