Add a "Preview" switch to the GTK native file chooser.

The button state is recorded in a preference so is recovered the next
time the GTK file chooser runs.
This commit is contained in:
ManoloFLTK 2020-01-31 08:07:57 +01:00
parent b9ea732d02
commit d1afac2150
2 changed files with 254 additions and 31 deletions

View File

@ -106,6 +106,7 @@ class Fl_Native_File_Chooser_Driver;
- Under X windows, and if Fl::OPTION_FNFC_USES_GTK has not been switched off, - Under X windows, and if Fl::OPTION_FNFC_USES_GTK has not been switched off,
the widget attempts to use standard GTK file chooser dialogs if they are the widget attempts to use standard GTK file chooser dialogs if they are
available at run-time on the platform, and falls back to use FLTK's Fl_File_Chooser if they are not. available at run-time on the platform, and falls back to use FLTK's Fl_File_Chooser if they are not.
In the first case, calling fl_register_images() adds a "Preview" button to the GTK chooser dialog.
In the latter case, it's best if you call Fl_File_Icon::load_system_icons() In the latter case, it's best if you call Fl_File_Icon::load_system_icons()
at the start of main(), to enable the nicer looking file browser widgets. at the start of main(), to enable the nicer looking file browser widgets.
Use the static public attributes of class Fl_File_Chooser to localize Use the static public attributes of class Fl_File_Chooser to localize

View File

@ -19,14 +19,15 @@
#include "config_lib.h" #include "config_lib.h"
#ifdef FL_CFG_WIN_X11 #ifdef FL_CFG_WIN_X11
#include <FL/platform.H>
#include <FL/Fl_Native_File_Chooser.H> #include <FL/Fl_Native_File_Chooser.H>
#if HAVE_DLSYM && HAVE_DLFCN_H #if HAVE_DLSYM && HAVE_DLFCN_H
#include <FL/platform.H>
#include <FL/Fl_Shared_Image.H>
#include <FL/Fl_Image_Surface.H>
#include <FL/fl_draw.H>
#include <dlfcn.h> // for dlopen et al #include <dlfcn.h> // for dlopen et al
#include "drivers/X11/Fl_X11_System_Driver.H" #include "drivers/X11/Fl_X11_System_Driver.H"
#endif
#include <locale.h> // for setlocale
/* --------------------- Type definitions from GLIB and GTK --------------------- */ /* --------------------- Type definitions from GLIB and GTK --------------------- */
/* all of this is from the public gnome API, so unlikely to change */ /* all of this is from the public gnome API, so unlikely to change */
@ -56,6 +57,9 @@ typedef struct _GtkWindow GtkWindow;
typedef struct _GdkDrawable GdkWindow; typedef struct _GdkDrawable GdkWindow;
typedef struct _GtkFileFilter GtkFileFilter; typedef struct _GtkFileFilter GtkFileFilter;
typedef struct _GtkToggleButton GtkToggleButton; typedef struct _GtkToggleButton GtkToggleButton;
typedef struct _GdkPixbuf GdkPixbuf;
typedef struct _GtkImage GtkImage;
typedef struct _GtkTable GtkTable;
typedef enum { typedef enum {
GTK_FILE_FILTER_FILENAME = 1 << 0, GTK_FILE_FILTER_FILENAME = 1 << 0,
GTK_FILE_FILTER_URI = 1 << 1, GTK_FILE_FILTER_URI = 1 << 1,
@ -101,7 +105,6 @@ class FL_EXPORT Fl_GTK_Native_File_Chooser_Driver : public Fl_Native_File_Choose
friend class Fl_Native_File_Chooser; friend class Fl_Native_File_Chooser;
private: private:
static int have_looked_for_GTK_libs; static int have_looked_for_GTK_libs;
typedef struct _GtkWidget GtkWidget;
typedef struct _GtkFileFilterInfo GtkFileFilterInfo; typedef struct _GtkFileFilterInfo GtkFileFilterInfo;
struct pair { struct pair {
Fl_GTK_Native_File_Chooser_Driver* running; // the running Fl_GTK_File_Chooser Fl_GTK_Native_File_Chooser_Driver* running; // the running Fl_GTK_File_Chooser
@ -137,8 +140,12 @@ private:
static int custom_gtk_filter_function(const GtkFileFilterInfo*, Fl_GTK_Native_File_Chooser_Driver::pair*); static int custom_gtk_filter_function(const GtkFileFilterInfo*, Fl_GTK_Native_File_Chooser_Driver::pair*);
static void free_pair(pair *p); static void free_pair(pair *p);
Fl_Preferences gtk_chooser_prefs;
public:
static gboolean want_preview; // state of "Preview" button
}; };
gboolean Fl_GTK_Native_File_Chooser_Driver::want_preview = false;
int Fl_GTK_Native_File_Chooser_Driver::did_find_GTK_libs = 0; int Fl_GTK_Native_File_Chooser_Driver::did_find_GTK_libs = 0;
@ -287,27 +294,66 @@ static XX_gtk_file_chooser_get_show_hidden fl_gtk_file_chooser_get_show_hidden =
typedef void (*XX_gtk_toggle_button_set_active)(GtkToggleButton *, gboolean); typedef void (*XX_gtk_toggle_button_set_active)(GtkToggleButton *, gboolean);
static XX_gtk_toggle_button_set_active fl_gtk_toggle_button_set_active = NULL; static XX_gtk_toggle_button_set_active fl_gtk_toggle_button_set_active = NULL;
// GtkWidget *gtk_check_button_new_with_label(const gchar *);
typedef GtkWidget* (*XX_gtk_file_chooser_set_preview_widget_active)(GtkFileChooser*, gboolean);
static XX_gtk_file_chooser_set_preview_widget_active fl_gtk_file_chooser_set_preview_widget_active = NULL;
// GdkPixbuf* gtk_file_chooser_set_preview_widget(GtkFileChooser *, GtkWidget *);
typedef GdkPixbuf* (*XX_gtk_file_chooser_set_preview_widget) (GtkFileChooser *gtkw_ptr, GtkWidget *preview);
static XX_gtk_file_chooser_set_preview_widget fl_gtk_file_chooser_set_preview_widget = NULL;
// char *gtk_file_chooser_get_preview_filename(GtkFileChooser*); // 2.4
typedef char* (*XX_gtk_file_chooser_get_preview_filename) (GtkFileChooser*);
static XX_gtk_file_chooser_get_preview_filename fl_gtk_file_chooser_get_preview_filename = NULL;
// GdkPixbuf *gdk_pixbuf_new_from_data(const uchar *,GdkColorspace, gboolean, int, int, int, int, void*, void*);
typedef GdkPixbuf* (*XX_gdk_pixbuf_new_from_data)(const uchar *, int/*GdkColorspace*/, gboolean, int, int, int, int, void*, void*);
static XX_gdk_pixbuf_new_from_data fl_gdk_pixbuf_new_from_data = NULL;
// void gtk_image_set_from_pixbuf(GtkImage*, GdkPixbuf*);
typedef GdkPixbuf* (*XX_gtk_image_set_from_pixbuf) (GtkImage*, GdkPixbuf*);
static XX_gtk_image_set_from_pixbuf fl_gtk_image_set_from_pixbuf = NULL;
// GtkWidget *gtk_image_new();
typedef GtkWidget* (*XX_gtk_image_new)(void);
static XX_gtk_image_new fl_gtk_image_new = NULL;
// GtkWidget *gtk_table_new();
typedef GtkTable* (*XX_gtk_table_new)(int, int, gboolean);
static XX_gtk_table_new fl_gtk_table_new = NULL;
// GtkWidget *gtk_table_new();
typedef void (*XX_gtk_widget_show_all)(GtkWidget*);
static XX_gtk_widget_show_all fl_gtk_widget_show_all = NULL;
// void gtk_table_attach_defaults()
typedef void (*XX_gtk_table_attach_defaults)(GtkTable *, GtkWidget *, guint left_attach, guint right_attach,
guint top_attach, guint bottom_attach);
static XX_gtk_table_attach_defaults fl_gtk_table_attach_defaults = NULL;
// GtkImage *gtk_file_chooser_get_preview_widget(GtkFileChooser*);
typedef GtkImage*(*XX_gtk_file_chooser_get_preview_widget)(GtkFileChooser*);
static XX_gtk_file_chooser_get_preview_widget fl_gtk_file_chooser_get_preview_widget = NULL;
typedef void (*XX_gtk_widget_set_sensitive)(GtkWidget *, gboolean);
static XX_gtk_widget_set_sensitive fl_gtk_widget_set_sensitive = NULL;
typedef GtkWidget *(*XX_gtk_button_new_with_label)(const char*);
XX_gtk_button_new_with_label fl_gtk_button_new_with_label = NULL;
typedef GtkWidget *(*XX_gtk_widget_get_toplevel)(GtkWidget *);
static XX_gtk_widget_get_toplevel fl_gtk_widget_get_toplevel = NULL;
// void g_object_unref(gpointer);
typedef void (*XX_g_object_unref)(void*);
static XX_g_object_unref fl_g_object_unref = NULL;
int Fl_GTK_Native_File_Chooser_Driver::have_looked_for_GTK_libs = 0; int Fl_GTK_Native_File_Chooser_Driver::have_looked_for_GTK_libs = 0;
Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) { Fl_GTK_Native_File_Chooser_Driver::Fl_GTK_Native_File_Chooser_Driver(int val) : Fl_Native_File_Chooser_FLTK_Driver(-1),
if (Fl_GTK_Native_File_Chooser_Driver::have_looked_for_GTK_libs == 0) { gtk_chooser_prefs(Fl_Preferences::USER, "fltk.org", "fltk/GTK-file-chooser")
// First Time here, try to find the GTK libs if they are installed
#if HAVE_DLSYM && HAVE_DLFCN_H
if (Fl::option(Fl::OPTION_FNFC_USES_GTK)) {
Fl_GTK_Native_File_Chooser_Driver::probe_for_GTK_libs();
}
#endif
Fl_GTK_Native_File_Chooser_Driver::have_looked_for_GTK_libs = -1;
}
// if we found all the GTK functions we need, we will use the GtkFileChooserDialog
if (Fl_GTK_Native_File_Chooser_Driver::did_find_GTK_libs) platform_fnfc = new Fl_GTK_Native_File_Chooser_Driver(val);
else platform_fnfc = new Fl_Native_File_Chooser_FLTK_Driver(val);
}
Fl_GTK_Native_File_Chooser_Driver::Fl_GTK_Native_File_Chooser_Driver(int val) : Fl_Native_File_Chooser_FLTK_Driver(-1)
{ {
gtkw_ptr = NULL; // used to hold a GtkWidget* gtkw_ptr = NULL; // used to hold a GtkWidget*
gtkw_slist = NULL; // will hold the returned file names in a multi-selection... gtkw_slist = NULL; // will hold the returned file names in a multi-selection...
@ -316,6 +362,7 @@ Fl_GTK_Native_File_Chooser_Driver::Fl_GTK_Native_File_Chooser_Driver(int val) :
gtkw_title = NULL; // dialog title gtkw_title = NULL; // dialog title
_btype = val; _btype = val;
previous_filter = NULL; previous_filter = NULL;
gtk_chooser_prefs.get("Preview", want_preview, 0);
} }
Fl_GTK_Native_File_Chooser_Driver::~Fl_GTK_Native_File_Chooser_Driver() Fl_GTK_Native_File_Chooser_Driver::~Fl_GTK_Native_File_Chooser_Driver()
@ -340,6 +387,7 @@ Fl_GTK_Native_File_Chooser_Driver::~Fl_GTK_Native_File_Chooser_Driver()
} }
gtkw_count = 0; // assume we have no files selected now gtkw_count = 0; // assume we have no files selected now
gtkw_title = strfree(gtkw_title); gtkw_title = strfree(gtkw_title);
gtk_chooser_prefs.set("Preview", want_preview);
} }
void Fl_GTK_Native_File_Chooser_Driver::type(int val) { void Fl_GTK_Native_File_Chooser_Driver::type(int val) {
@ -459,6 +507,129 @@ static void run_response_handler(GtkDialog *dialog, gint response_id, gpointer d
*ri = response_id; *ri = response_id;
} }
// checks whether the file begins with up to 1000 UTF-8-encoded unicode characters
// if yes, those characters are returned as a UTF-8 string (to be delete[]'d after use)
// if no, NULL is returned
static char *text_file_preview(const char *fname) {
if (!strcmp(fl_filename_ext(fname), ".svg")) return NULL;
if (!strcmp(fl_filename_ext(fname), ".xpm")) return NULL;
FILE *in = fl_fopen(fname, "r");
if (!in) return NULL;
char *text = new char[4011];
int len = fread(text, 1, 4010, in);
fclose(in);
text[len] = 0;
if (strlen(text) < len) text[0] = 0; // presence of null byte in file --> not text
char *p = text;
int count = 0;
const char *end = text + strlen(text);
while (p < end && count < 1000) {
if (*p & 0x80) { // what should be a multibyte encoding
fl_utf8decode(p, end, &len);
if (len < 2) { // That's not genuine UTF-8
delete[] text;
return NULL;
}
} else {
len = 1;
}
p += len;
count++;
}
*p = 0;
if (text[0]==0) {delete[] text; text = NULL;}
return text;
}
static void delete_rgb_image(uchar *pixels, Fl_RGB_Image *rgb) {
delete rgb;
}
// Draws to an Fl_RGB_Image a preview of text and image files,
// and uses it to fill the "preview" part of the GTK file chooser
//static int preview_width = 175;
static float preview_zoom = 1.;
static GtkWidget *plus_button, *minus_button;
static void update_preview_cb(GtkFileChooser *file_chooser, GtkImage* gtkimg)
{
gboolean have_preview = false;
Fl_Shared_Image *img = NULL;
char *preview_text = NULL;
char *filename = NULL;
fl_gtk_widget_set_sensitive(plus_button, false);
fl_gtk_widget_set_sensitive(minus_button, false);
if (Fl_GTK_Native_File_Chooser_Driver::want_preview) filename = fl_gtk_file_chooser_get_preview_filename(file_chooser); // 2.4
if (filename) {
if (!fl_filename_isdir(filename)) {
preview_text = text_file_preview(filename);
if (!preview_text) {
img = Fl_Shared_Image::get(filename);
}
}
free(filename);
}
if (preview_text || (img && !img->fail())) {
int width = preview_zoom * 175, height = preview_zoom * 225; // same size as Fl_File_Chooser's preview box
if (preview_text) height = 225;
if (img) {
img->scale(width, height);
width = img->w(), height = img->h();
}
Fl_Image_Surface *surf = new Fl_Image_Surface(width, height, 1);
Fl_Surface_Device::push_current(surf);
fl_color(FL_WHITE);
fl_rectf(0, 0, width, height);
if (img) img->draw(0, 0);
else {
fl_color(FL_BLACK);
fl_font(FL_COURIER, FL_NORMAL_SIZE - 1);
fl_draw(preview_text, 0, 0, width, height, FL_ALIGN_TOP|FL_ALIGN_LEFT, NULL, false);
delete[] preview_text;
}
Fl_RGB_Image *rgb = surf->image();
Fl_Surface_Device::pop_current();
delete surf;
GdkPixbuf *pixbuf = fl_gdk_pixbuf_new_from_data(rgb->array, 0/*GDK_COLORSPACE_RGB*/, rgb->d() == 4,
8, rgb->data_w(), rgb->data_h(), rgb->ld() ? rgb->ld() : rgb->data_w() * rgb->d(),
(void*)&delete_rgb_image, rgb);
if (pixbuf) {
fl_gtk_image_set_from_pixbuf(gtkimg, pixbuf);
fl_g_object_unref(pixbuf);
if (preview_zoom < 4) fl_gtk_widget_set_sensitive(plus_button, true);
if (preview_zoom > 1) fl_gtk_widget_set_sensitive(minus_button, true);
have_preview = true;
}
}
if (img) img->release();
fl_gtk_file_chooser_set_preview_widget_active(file_chooser, have_preview); //2.4
}
static void preview_cb(GtkToggleButton *togglebutton, GtkFileChooser *chooser)
{
Fl_GTK_Native_File_Chooser_Driver::want_preview = fl_gtk_toggle_button_get_active(togglebutton);
GtkImage *preview = fl_gtk_file_chooser_get_preview_widget(chooser);
update_preview_cb(chooser, preview);
}
static void plus_cb(GtkWidget *togglebutton, GtkImage *preview) {
preview_zoom *= 1.5;
if (preview_zoom > 4) {
preview_zoom = 4;
}
update_preview_cb((GtkFileChooser*)fl_gtk_widget_get_toplevel(togglebutton), preview);
}
static void minus_cb(GtkWidget *togglebutton, GtkImage *preview) {
preview_zoom /= 1.5;
if (preview_zoom < 1) {
preview_zoom = 1;
}
update_preview_cb((GtkFileChooser*)fl_gtk_widget_get_toplevel(togglebutton), preview);
}
int Fl_GTK_Native_File_Chooser_Driver::fl_gtk_chooser_wrapper() int Fl_GTK_Native_File_Chooser_Driver::fl_gtk_chooser_wrapper()
{ {
@ -568,9 +739,33 @@ int Fl_GTK_Native_File_Chooser_Driver::fl_gtk_chooser_wrapper()
} }
} }
GtkWidget *toggle = fl_gtk_check_button_new_with_label(Fl_File_Chooser::hidden_label); // extra buttons "Show hidden" [+ "Preview" before it if fl_register_images() was called]
fl_gtk_file_chooser_set_extra_widget((GtkFileChooser *)gtkw_ptr, toggle); GtkWidget *show_hidden_button = fl_gtk_check_button_new_with_label(Fl_File_Chooser::hidden_label);
fl_g_signal_connect_data(toggle, "toggled", G_CALLBACK(hidden_files_cb), gtkw_ptr, NULL, (GConnectFlags) 0); fl_g_signal_connect_data(show_hidden_button, "toggled", G_CALLBACK(hidden_files_cb), gtkw_ptr, NULL, (GConnectFlags) 0);
GtkWidget *extra = show_hidden_button;
if (Fl_Image::register_images_done) {
GtkTable *table = fl_gtk_table_new(1, 4, true);
GtkWidget *preview = fl_gtk_image_new();
fl_gtk_file_chooser_set_preview_widget((GtkFileChooser *)gtkw_ptr, preview); //2.4
fl_g_signal_connect_data((GtkFileChooser *)gtkw_ptr, "update-preview", G_CALLBACK(update_preview_cb), preview,
NULL, (GConnectFlags)0);
GtkWidget *preview_button = fl_gtk_check_button_new_with_label(Fl_File_Chooser::preview_label);
fl_g_signal_connect_data(preview_button, "toggled", G_CALLBACK(preview_cb), gtkw_ptr, NULL, (GConnectFlags) 0);
fl_gtk_toggle_button_set_active((GtkToggleButton *)preview_button, want_preview);
fl_gtk_table_attach_defaults(table, preview_button, 0, 1, 0, 1);
plus_button = fl_gtk_button_new_with_label("<--->");
fl_g_signal_connect_data(plus_button, "clicked", G_CALLBACK(plus_cb), preview, NULL, (GConnectFlags) 0);
fl_gtk_table_attach_defaults(table, plus_button, 1,2, 0, 1);
minus_button = fl_gtk_button_new_with_label(">---<");
fl_g_signal_connect_data(minus_button, "clicked", G_CALLBACK(minus_cb), preview, NULL, (GConnectFlags) 0);
fl_gtk_table_attach_defaults(table, minus_button, 2,3, 0, 1);
fl_gtk_table_attach_defaults(table, show_hidden_button, 3, 4, 0, 1);
extra = (GtkWidget*)table;
}
fl_gtk_file_chooser_set_extra_widget((GtkFileChooser *)gtkw_ptr, extra);
fl_gtk_widget_show_all(extra);
Fl_Window* firstw = Fl::first_window(); Fl_Window* firstw = Fl::first_window();
fl_gtk_widget_show_now(gtkw_ptr); // map the GTK window on screen fl_gtk_widget_show_now(gtkw_ptr); // map the GTK window on screen
if (firstw) { if (firstw) {
@ -579,7 +774,7 @@ int Fl_GTK_Native_File_Chooser_Driver::fl_gtk_chooser_wrapper()
XSetTransientForHint(fl_display, xw, fl_xid(firstw)); // set the GTK window transient for the last FLTK win 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); gboolean state = fl_gtk_file_chooser_get_show_hidden((GtkFileChooser *)gtkw_ptr);
fl_gtk_toggle_button_set_active((GtkToggleButton *)toggle, state); fl_gtk_toggle_button_set_active((GtkToggleButton *)show_hidden_button, state);
gint response_id = GTK_RESPONSE_NONE; gint response_id = GTK_RESPONSE_NONE;
fl_g_signal_connect_data(gtkw_ptr, "response", G_CALLBACK(run_response_handler), &response_id, NULL, (GConnectFlags) 0); fl_g_signal_connect_data(gtkw_ptr, "response", G_CALLBACK(run_response_handler), &response_id, NULL, (GConnectFlags) 0);
@ -592,7 +787,7 @@ int Fl_GTK_Native_File_Chooser_Driver::fl_gtk_chooser_wrapper()
if (xevent.type == ConfigureNotify) xid = xevent.xmaprequest.window; if (xevent.type == ConfigureNotify) xid = xevent.xmaprequest.window;
if (!fl_find(xid)) continue; // skip events to non-FLTK windows if (!fl_find(xid)) continue; // skip events to non-FLTK windows
// process Expose and ConfigureNotify events // process Expose and ConfigureNotify events
if ( xevent.type == Expose || xevent.type == ConfigureNotify ) fl_handle(xevent); if ( xevent.type == Expose || xevent.type == ConfigureNotify ) fl_handle(xevent);
} }
Fl::flush(); // do the drawings needed after Expose events Fl::flush(); // do the drawings needed after Expose events
} }
@ -655,7 +850,6 @@ int Fl_GTK_Native_File_Chooser_Driver::fl_gtk_chooser_wrapper()
return result; return result;
} // fl_gtk_chooser_wrapper } // fl_gtk_chooser_wrapper
#if HAVE_DLSYM && HAVE_DLFCN_H
// macro to help with the symbol loading boilerplate... // macro to help with the symbol loading boilerplate...
# define GET_SYM(SSS, LLL) \ # define GET_SYM(SSS, LLL) \
dlerror(); /* Clear any existing error */ \ dlerror(); /* Clear any existing error */ \
@ -666,15 +860,12 @@ did_find_GTK_libs = 0; \
return; } return; }
#endif // HAVE_DLSYM && HAVE_DLFCN_H
/* /*
* Use dlopen to see if we can load the gtk dynamic libraries that * Use dlopen to see if we can load the gtk dynamic libraries that
* will allow us to create a GtkFileChooserDialog() on the fly, * will allow us to create a GtkFileChooserDialog() on the fly,
* without linking to the GTK libs at compile time. * without linking to the GTK libs at compile time.
*/ */
void Fl_GTK_Native_File_Chooser_Driver::probe_for_GTK_libs(void) { void Fl_GTK_Native_File_Chooser_Driver::probe_for_GTK_libs(void) {
#if HAVE_DLSYM && HAVE_DLFCN_H
void *ptr_gtk; void *ptr_gtk;
if ( !Fl_X11_System_Driver::probe_for_GTK(2, 4, &ptr_gtk)) { if ( !Fl_X11_System_Driver::probe_for_GTK(2, 4, &ptr_gtk)) {
did_find_GTK_libs = 0; did_find_GTK_libs = 0;
@ -712,6 +903,20 @@ 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_file_chooser_set_extra_widget, ptr_gtk);
GET_SYM(gtk_widget_show_now, ptr_gtk); GET_SYM(gtk_widget_show_now, ptr_gtk);
GET_SYM(gtk_widget_get_window, ptr_gtk); GET_SYM(gtk_widget_get_window, ptr_gtk);
GET_SYM(gtk_file_chooser_set_preview_widget_active, ptr_gtk);
GET_SYM(gtk_file_chooser_set_preview_widget, ptr_gtk);
GET_SYM(gtk_file_chooser_get_preview_widget, ptr_gtk);
GET_SYM(gtk_widget_set_sensitive, ptr_gtk);
GET_SYM(gtk_button_new_with_label, ptr_gtk);
GET_SYM(gtk_widget_get_toplevel, ptr_gtk);
GET_SYM(gtk_file_chooser_get_preview_filename, ptr_gtk);
GET_SYM(gdk_pixbuf_new_from_data, ptr_gtk);
GET_SYM(gtk_image_set_from_pixbuf, ptr_gtk);
GET_SYM(gtk_image_new, ptr_gtk);
GET_SYM(gtk_table_new, ptr_gtk);
GET_SYM(gtk_widget_show_all, ptr_gtk);
GET_SYM(gtk_table_attach_defaults, ptr_gtk);
GET_SYM(g_object_unref, ptr_gtk);
fl_gdk_to_X11 = (gdk_to_X11_t)dlsym(ptr_gtk, "gdk_x11_drawable_get_xid"); 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) 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; } if (!fl_gdk_to_X11) { did_find_GTK_libs = 0; return; }
@ -723,9 +928,26 @@ void Fl_GTK_Native_File_Chooser_Driver::probe_for_GTK_libs(void) {
GET_SYM(gtk_toggle_button_set_active, ptr_gtk); GET_SYM(gtk_toggle_button_set_active, ptr_gtk);
did_find_GTK_libs = 1; did_find_GTK_libs = 1;
#endif // HAVE_DLSYM && HAVE_DLFCN_H
} // probe_for_GTK_libs } // probe_for_GTK_libs
#endif // HAVE_DLSYM && HAVE_DLFCN_H
Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) {
#if HAVE_DLSYM && HAVE_DLFCN_H
if (Fl_GTK_Native_File_Chooser_Driver::have_looked_for_GTK_libs == 0) {
// First Time here, try to find the GTK libs if they are installed
if (Fl::option(Fl::OPTION_FNFC_USES_GTK)) {
Fl_GTK_Native_File_Chooser_Driver::probe_for_GTK_libs();
}
Fl_GTK_Native_File_Chooser_Driver::have_looked_for_GTK_libs = -1;
}
// if we found all the GTK functions we need, we will use the GtkFileChooserDialog
if (Fl_GTK_Native_File_Chooser_Driver::did_find_GTK_libs) platform_fnfc = new Fl_GTK_Native_File_Chooser_Driver(val);
else
#endif // HAVE_DLSYM && HAVE_DLFCN_H
platform_fnfc = new Fl_Native_File_Chooser_FLTK_Driver(val);
}
#endif // FL_CFG_WIN_X11 #endif // FL_CFG_WIN_X11
// //