summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog25
-rw-r--r--ChangeLog.pre-2-1025
-rw-r--r--ChangeLog.pre-2-625
-rw-r--r--ChangeLog.pre-2-825
-rw-r--r--gdk/x11/gdkevents-x11.c1
-rw-r--r--gtk/Makefile.am2
-rw-r--r--gtk/gtk.h1
-rw-r--r--gtk/gtkdebug.h3
-rw-r--r--gtk/gtkmain.c368
-rw-r--r--gtk/gtkmain.h7
-rw-r--r--gtk/gtkmodules.c540
-rw-r--r--gtk/gtkmodules.h50
-rw-r--r--gtk/gtksettings.c30
13 files changed, 742 insertions, 360 deletions
diff --git a/ChangeLog b/ChangeLog
index 878d74c522..d25d433d9b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2004-09-01 Matthias Clasen <mclasen@redhat.com>
+
+ Make it possible to specify additional modules to load
+ via a setting. (#117236, Alex Graveley)
+
+ * gtk/gtkmodules.h:
+ * gtk/gtkmodules.c: New files which contain the module
+ handling code which was previously in gtkmain.[hc].
+ Additionally, the code now looks for the gtk-modules
+ setting, which can specify additional modules to load.
+
+ * gtk/gtkmain.c:
+ * gtk/gtkmain.h: Remove all the module handling code.
+
+ * gtk/gtkdebug.h: Add a debug flag for modules.
+
+ * gtk/gtk.h: Include gtkmodules.h
+
+ * gtk/Makefile.am (gtk_public_h_sources): Add gtkmodules.h
+ (gtk_c_sources): Add gtkmodules.c
+
+ * gtk/gtksettings.c: Add the gtk-modules setting.
+
+ * gdk/x11/gdkevents-x11.c: Add the Gtk/Modules XSetting.
+
Wed Sep 1 19:11:44 2004 Søren Sandmann <sandmann@redhat.com>
* gtk/gtktoolbar.c (gtk_toolbar_size_allocate): Make sure
diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10
index 878d74c522..d25d433d9b 100644
--- a/ChangeLog.pre-2-10
+++ b/ChangeLog.pre-2-10
@@ -1,3 +1,28 @@
+2004-09-01 Matthias Clasen <mclasen@redhat.com>
+
+ Make it possible to specify additional modules to load
+ via a setting. (#117236, Alex Graveley)
+
+ * gtk/gtkmodules.h:
+ * gtk/gtkmodules.c: New files which contain the module
+ handling code which was previously in gtkmain.[hc].
+ Additionally, the code now looks for the gtk-modules
+ setting, which can specify additional modules to load.
+
+ * gtk/gtkmain.c:
+ * gtk/gtkmain.h: Remove all the module handling code.
+
+ * gtk/gtkdebug.h: Add a debug flag for modules.
+
+ * gtk/gtk.h: Include gtkmodules.h
+
+ * gtk/Makefile.am (gtk_public_h_sources): Add gtkmodules.h
+ (gtk_c_sources): Add gtkmodules.c
+
+ * gtk/gtksettings.c: Add the gtk-modules setting.
+
+ * gdk/x11/gdkevents-x11.c: Add the Gtk/Modules XSetting.
+
Wed Sep 1 19:11:44 2004 Søren Sandmann <sandmann@redhat.com>
* gtk/gtktoolbar.c (gtk_toolbar_size_allocate): Make sure
diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6
index 878d74c522..d25d433d9b 100644
--- a/ChangeLog.pre-2-6
+++ b/ChangeLog.pre-2-6
@@ -1,3 +1,28 @@
+2004-09-01 Matthias Clasen <mclasen@redhat.com>
+
+ Make it possible to specify additional modules to load
+ via a setting. (#117236, Alex Graveley)
+
+ * gtk/gtkmodules.h:
+ * gtk/gtkmodules.c: New files which contain the module
+ handling code which was previously in gtkmain.[hc].
+ Additionally, the code now looks for the gtk-modules
+ setting, which can specify additional modules to load.
+
+ * gtk/gtkmain.c:
+ * gtk/gtkmain.h: Remove all the module handling code.
+
+ * gtk/gtkdebug.h: Add a debug flag for modules.
+
+ * gtk/gtk.h: Include gtkmodules.h
+
+ * gtk/Makefile.am (gtk_public_h_sources): Add gtkmodules.h
+ (gtk_c_sources): Add gtkmodules.c
+
+ * gtk/gtksettings.c: Add the gtk-modules setting.
+
+ * gdk/x11/gdkevents-x11.c: Add the Gtk/Modules XSetting.
+
Wed Sep 1 19:11:44 2004 Søren Sandmann <sandmann@redhat.com>
* gtk/gtktoolbar.c (gtk_toolbar_size_allocate): Make sure
diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8
index 878d74c522..d25d433d9b 100644
--- a/ChangeLog.pre-2-8
+++ b/ChangeLog.pre-2-8
@@ -1,3 +1,28 @@
+2004-09-01 Matthias Clasen <mclasen@redhat.com>
+
+ Make it possible to specify additional modules to load
+ via a setting. (#117236, Alex Graveley)
+
+ * gtk/gtkmodules.h:
+ * gtk/gtkmodules.c: New files which contain the module
+ handling code which was previously in gtkmain.[hc].
+ Additionally, the code now looks for the gtk-modules
+ setting, which can specify additional modules to load.
+
+ * gtk/gtkmain.c:
+ * gtk/gtkmain.h: Remove all the module handling code.
+
+ * gtk/gtkdebug.h: Add a debug flag for modules.
+
+ * gtk/gtk.h: Include gtkmodules.h
+
+ * gtk/Makefile.am (gtk_public_h_sources): Add gtkmodules.h
+ (gtk_c_sources): Add gtkmodules.c
+
+ * gtk/gtksettings.c: Add the gtk-modules setting.
+
+ * gdk/x11/gdkevents-x11.c: Add the Gtk/Modules XSetting.
+
Wed Sep 1 19:11:44 2004 Søren Sandmann <sandmann@redhat.com>
* gtk/gtktoolbar.c (gtk_toolbar_size_allocate): Make sure
diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c
index 733fd56845..bb121dc22d 100644
--- a/gdk/x11/gdkevents-x11.c
+++ b/gdk/x11/gdkevents-x11.c
@@ -2710,6 +2710,7 @@ static struct
{ "Gtk/ToolbarIconSize", "gtk-toolbar-icon-size" },
{ "Gtk/IMPreeditStyle", "gtk-im-preedit-style" },
{ "Gtk/IMStatusStyle", "gtk-im-status-style" },
+ { "Gtk/Modules", "gtk-modules" },
{ "Gtk/FileChooserBackend", "gtk-file-chooser-backend" },
{ "Gtk/ButtonImages", "gtk-button-images" },
{ "Gtk/MenuImages", "gtk-menu-images" },
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index dce2321113..4ebb8c993d 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -203,6 +203,7 @@ gtk_public_h_sources = \
gtkmenushell.h \
gtkmessagedialog.h \
gtkmisc.h \
+ gtkmodules.h \
gtknotebook.h \
gtkobject.h \
gtkoldeditable.h \
@@ -422,6 +423,7 @@ gtk_c_sources = \
gtkmenushell.c \
gtkmessagedialog.c \
gtkmisc.c \
+ gtkmodules.c \
gtknotebook.c \
gtkobject.c \
gtkoldeditable.c \
diff --git a/gtk/gtk.h b/gtk/gtk.h
index cce4ef82b6..c5a982e6a5 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -118,6 +118,7 @@
#include <gtk/gtkmenushell.h>
#include <gtk/gtkmessagedialog.h>
#include <gtk/gtkmisc.h>
+#include <gtk/gtkmodules.h>
#include <gtk/gtknotebook.h>
#include <gtk/gtkobject.h>
#include <gtk/gtkoldeditable.h>
diff --git a/gtk/gtkdebug.h b/gtk/gtkdebug.h
index 5a5a1ec230..6febf849a9 100644
--- a/gtk/gtkdebug.h
+++ b/gtk/gtkdebug.h
@@ -38,7 +38,8 @@ typedef enum {
GTK_DEBUG_TREE = 1 << 3,
GTK_DEBUG_UPDATES = 1 << 4,
GTK_DEBUG_KEYBINDINGS = 1 << 5,
- GTK_DEBUG_MULTIHEAD = 1 << 6
+ GTK_DEBUG_MULTIHEAD = 1 << 6,
+ GTK_DEBUG_MODULES = 1 << 7
} GtkDebugFlag;
#ifdef G_ENABLE_DEBUG
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index 55df71e992..7ded976440 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -37,18 +37,18 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <gmodule.h>
-#ifdef G_OS_UNIX
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#include <sys/types.h> /* For uid_t, gid_t */
#endif
+#include <sys/types.h> /* For uid_t, gid_t */
+
#ifdef G_OS_WIN32
#define STRICT
#include <windows.h>
#undef STRICT
#endif
-#include <pango/pango-utils.h> /* For pango_split_file_list */
+#include <pango/pango-types.h> /* For pango_language_from_string */
#include "gtkalias.h"
#include "gtkintl.h"
@@ -59,6 +59,7 @@
#include "gtkdnd.h"
#include "gtkversion.h"
#include "gtkmain.h"
+#include "gtkmodules.h"
#include "gtkrc.h"
#include "gtkselection.h"
#include "gtksettings.h"
@@ -73,7 +74,6 @@ typedef struct _GtkInitFunction GtkInitFunction;
typedef struct _GtkQuitFunction GtkQuitFunction;
typedef struct _GtkClosure GtkClosure;
typedef struct _GtkKeySnooperData GtkKeySnooperData;
-typedef struct _GtkModuleInfo GtkModuleInfo;
struct _GtkInitFunction
{
@@ -105,12 +105,6 @@ struct _GtkKeySnooperData
guint id;
};
-struct _GtkModuleInfo
-{
- GtkModuleInitFunc init_func;
- GtkModuleDisplayInitFunc display_init_func;
-};
-
static gint gtk_quit_invoke_function (GtkQuitFunction *quitf);
static void gtk_quit_destroy (GtkQuitFunction *quitf);
static gint gtk_invoke_key_snoopers (GtkWidget *grab_widget,
@@ -137,13 +131,6 @@ const guint gtk_micro_version = GTK_MICRO_VERSION;
const guint gtk_binary_age = GTK_BINARY_AGE;
const guint gtk_interface_age = GTK_INTERFACE_AGE;
-static GSList *gtk_modules;
-
-/* Saved argc,argv for delayed module initialization
- */
-static gint gtk_argc = 0;
-static gchar **gtk_argv = NULL;
-
static guint gtk_main_loop_level = 0;
static gint gtk_initialized = FALSE;
static GList *current_events = NULL;
@@ -168,7 +155,8 @@ static const GDebugKey gtk_debug_keys[] = {
{"tree", GTK_DEBUG_TREE},
{"updates", GTK_DEBUG_UPDATES},
{"keybindings", GTK_DEBUG_KEYBINDINGS},
- {"multihead", GTK_DEBUG_MULTIHEAD}
+ {"multihead", GTK_DEBUG_MULTIHEAD},
+ {"modules", GTK_DEBUG_MODULES}
};
static const guint gtk_ndebug_keys = sizeof (gtk_debug_keys) / sizeof (GDebugKey);
@@ -334,260 +322,6 @@ _gtk_get_data_prefix (void)
#endif /* G_OS_WIN32 */
-static gchar **
-get_module_path (void)
-{
- const gchar *module_path_env;
- const gchar *exe_prefix;
- const gchar *home_dir;
- gchar *home_gtk_dir = NULL;
- gchar *module_path;
- gchar *default_dir;
- static gchar **result = NULL;
-
- if (result)
- return result;
-
- home_dir = g_get_home_dir();
- if (home_dir)
- home_gtk_dir = g_build_filename (home_dir, ".gtk-2.0", NULL);
-
- module_path_env = g_getenv ("GTK_PATH");
- exe_prefix = g_getenv ("GTK_EXE_PREFIX");
-
- if (exe_prefix)
- default_dir = g_build_filename (exe_prefix, "lib", "gtk-2.0", NULL);
- else
- default_dir = g_build_filename (GTK_LIBDIR, "gtk-2.0", NULL);
-
- if (module_path_env && home_gtk_dir)
- module_path = g_build_path (G_SEARCHPATH_SEPARATOR_S,
- module_path_env, home_gtk_dir, default_dir, NULL);
- else if (module_path_env)
- module_path = g_build_path (G_SEARCHPATH_SEPARATOR_S,
- module_path_env, default_dir, NULL);
- else if (home_gtk_dir)
- module_path = g_build_path (G_SEARCHPATH_SEPARATOR_S,
- home_gtk_dir, default_dir, NULL);
- else
- module_path = g_build_path (G_SEARCHPATH_SEPARATOR_S,
- default_dir, NULL);
-
- g_free (home_gtk_dir);
- g_free (default_dir);
-
- result = pango_split_file_list (module_path);
- g_free (module_path);
-
- return result;
-}
-
-/**
- * _gtk_get_module_path:
- * @type: the type of the module, for instance 'modules', 'engines', immodules'
- *
- * Determines the search path for a particular type of module.
- *
- * Return value: the search path for the module type. Free with g_strfreev().
- **/
-gchar **
-_gtk_get_module_path (const gchar *type)
-{
- gchar **paths = get_module_path();
- gchar **path;
- gchar **result;
- gint count = 0;
-
- for (path = paths; *path; path++)
- count++;
-
- result = g_new (gchar *, count * 4 + 1);
-
- count = 0;
- for (path = get_module_path (); *path; path++)
- {
- gint use_version, use_host;
-
- for (use_version = TRUE; use_version >= FALSE; use_version--)
- for (use_host = TRUE; use_host >= FALSE; use_host--)
- {
- gchar *tmp_dir;
-
- if (use_version && use_host)
- tmp_dir = g_build_filename (*path, GTK_BINARY_VERSION, GTK_HOST, type, NULL);
- else if (use_version)
- tmp_dir = g_build_filename (*path, GTK_BINARY_VERSION, type, NULL);
- else if (use_host)
- tmp_dir = g_build_filename (*path, GTK_HOST, type, NULL);
- else
- tmp_dir = g_build_filename (*path, type, NULL);
-
- result[count++] = tmp_dir;
- }
- }
-
- result[count++] = NULL;
-
- return result;
-}
-
-/* Like g_module_path, but use .la as the suffix
- */
-static gchar*
-module_build_la_path (const gchar *directory,
- const gchar *module_name)
-{
- gchar *filename;
- gchar *result;
-
- if (strncmp (module_name, "lib", 3) == 0)
- filename = (gchar *)module_name;
- else
- filename = g_strconcat ("lib", module_name, ".la", NULL);
-
- if (directory && *directory)
- result = g_build_filename (directory, filename, NULL);
- else
- result = g_strdup (filename);
-
- if (filename != module_name)
- g_free (filename);
-
- return result;
-}
-
-/**
- * _gtk_find_module:
- * @name: the name of the module
- * @type: the type of the module, for instance 'modules', 'engines', immodules'
- *
- * Looks for a dynamically loadable module named @name of type @type in the
- * standard GTK+ module search path.
- *
- * Return value: the pathname to the found module, or %NULL if it wasn't found.
- * Free with g_free().
- **/
-gchar *
-_gtk_find_module (const gchar *name,
- const gchar *type)
-{
- gchar **paths;
- gchar **path;
- gchar *module_name = NULL;
-
- if (g_path_is_absolute (name))
- return g_strdup (name);
-
- paths = _gtk_get_module_path (type);
- for (path = paths; *path; path++)
- {
- gchar *tmp_name;
-
- tmp_name = g_module_build_path (*path, name);
- if (g_file_test (tmp_name, G_FILE_TEST_EXISTS))
- {
- module_name = tmp_name;
- goto found;
- }
- g_free(tmp_name);
-
- tmp_name = module_build_la_path (*path, name);
- if (g_file_test (tmp_name, G_FILE_TEST_EXISTS))
- {
- module_name = tmp_name;
- goto found;
- }
- g_free(tmp_name);
- }
-
- found:
- g_strfreev (paths);
- return module_name;
-}
-
-static GModule *
-find_module (const gchar *name)
-{
- GModule *module;
- gchar *module_name;
-
- module_name = _gtk_find_module (name, "modules");
- if (!module_name)
- {
- /* As last resort, try loading without an absolute path (using system
- * library path)
- */
- module_name = g_module_build_path (NULL, name);
- }
-
- module = g_module_open (module_name, G_MODULE_BIND_LAZY);
- g_free(module_name);
-
- return module;
-}
-
-static GSList *
-load_module (GSList *module_list,
- const gchar *name)
-{
- GtkModuleInitFunc modinit_func = NULL;
- GtkModuleInfo *info;
- GModule *module = NULL;
-
- if (g_module_supported ())
- {
- module = find_module (name);
- if (module &&
- g_module_symbol (module, "gtk_module_init", (gpointer *) &modinit_func) &&
- modinit_func)
- {
- if (!g_slist_find (module_list, (gconstpointer) modinit_func))
- {
- g_module_make_resident (module);
- info = g_new (GtkModuleInfo, 1);
-
- info->init_func = modinit_func;
- g_module_symbol (module, "gtk_module_display_init",
- (gpointer *) &info->display_init_func);
-
- module_list = g_slist_prepend (module_list, info);
- }
- else
- {
- g_module_close (module);
- module = NULL;
- }
- }
- }
- if (!modinit_func)
- {
- g_message ("Failed to load module \"%s\": %s",
- module ? g_module_name (module) : name,
- g_module_error ());
- if (module)
- g_module_close (module);
- }
-
- return module_list;
-}
-
-static GSList *
-load_modules (const char *module_str)
-{
- gchar **module_names = pango_split_file_list (module_str);
- GSList *module_list = NULL;
- gint i;
-
- for (i = 0; module_names[i]; i++)
- module_list = load_module (module_list, module_names[i]);
-
- module_list = g_slist_reverse (module_list);
-
- g_strfreev (module_names);
-
- return module_list;
-}
-
static gboolean do_setlocale = TRUE;
/**
@@ -614,51 +348,6 @@ gtk_disable_setlocale (void)
#undef gtk_init_check
#endif
-static void
-default_display_notify_cb (GdkDisplayManager *display_manager)
-{
- GSList *slist;
-
- /* Initialize non-multihead-aware modules when the
- * default display is first set to a non-NULL value.
- */
- static gboolean initialized = FALSE;
-
- if (!gdk_display_get_default () || initialized)
- return;
-
- initialized = TRUE;
-
- for (slist = gtk_modules; slist; slist = slist->next)
- {
- if (slist->data)
- {
- GtkModuleInfo *info = slist->data;
-
- if (!info->display_init_func)
- info->init_func (&gtk_argc, &gtk_argv);
- }
- }
-}
-
-static void
-display_opened_cb (GdkDisplayManager *display_manager,
- GdkDisplay *display)
-{
- GSList *slist;
-
- for (slist = gtk_modules; slist; slist = slist->next)
- {
- if (slist->data)
- {
- GtkModuleInfo *info = slist->data;
-
- if (info->display_init_func)
- info->display_init_func (display);
- }
- }
-}
-
/**
* gtk_parse_args:
* @argc: a pointer to the number of command line arguments.
@@ -681,8 +370,6 @@ gtk_parse_args (int *argc,
char ***argv)
{
GString *gtk_modules_string = NULL;
- GSList *slist;
- GdkDisplayManager *display_manager;
const gchar *env_string;
if (gtk_initialized)
@@ -747,8 +434,8 @@ gtk_parse_args (int *argc,
{
if (gtk_modules_string)
g_string_append_c (gtk_modules_string, G_SEARCHPATH_SEPARATOR);
- else
- gtk_modules_string = g_string_new (NULL);
+ else
+ gtk_modules_string = g_string_new (NULL);
g_string_append (gtk_modules_string, module_name);
}
@@ -823,23 +510,11 @@ gtk_parse_args (int *argc,
*argc -= k;
}
}
-
- gtk_argv = g_malloc ((gtk_argc + 1) * sizeof (char*));
- for (i = 0; i < gtk_argc; i++)
- gtk_argv[i] = g_strdup ((*argv)[i]);
- gtk_argv[gtk_argc] = NULL;
}
if (gtk_debug_flags & GTK_DEBUG_UPDATES)
gdk_window_set_debug_updates (TRUE);
- /* load gtk modules */
- if (gtk_modules_string)
- {
- gtk_modules = load_modules (gtk_modules_string->str);
- g_string_free (gtk_modules_string, TRUE);
- }
-
#ifdef ENABLE_NLS
bindtextdomain (GETTEXT_PACKAGE, GTK_LOCALEDIR);
bindtextdomain (GETTEXT_PACKAGE "-properties", GTK_LOCALEDIR);
@@ -866,30 +541,19 @@ gtk_parse_args (int *argc,
gtk_type_init (0);
_gtk_accel_map_init ();
_gtk_rc_init ();
-
+
/* Set the 'initialized' flag.
*/
gtk_initialized = TRUE;
- display_manager = gdk_display_manager_get ();
- g_signal_connect (display_manager, "notify::default-display",
- G_CALLBACK (default_display_notify_cb), NULL);
- g_signal_connect (display_manager, "display-opened",
- G_CALLBACK (display_opened_cb), NULL);
-
- /* initialize multhead aware gtk modules; for other modules,
- * we wait until we have a display open;
- */
- for (slist = gtk_modules; slist; slist = slist->next)
+ /* load gtk modules */
+ if (gtk_modules_string)
{
- if (slist->data)
- {
- GtkModuleInfo *info = slist->data;
-
- if (info->display_init_func)
- info->init_func (argc, argv);
- }
+ _gtk_modules_init (argc, argv, gtk_modules_string->str);
+ g_string_free (gtk_modules_string, TRUE);
}
+ else
+ _gtk_modules_init (argc, argv, "");
return TRUE;
}
diff --git a/gtk/gtkmain.h b/gtk/gtkmain.h
index 06d15f76db..03d0bf38b7 100644
--- a/gtk/gtkmain.h
+++ b/gtk/gtkmain.h
@@ -57,9 +57,6 @@ extern "C" {
#endif /* GTK_DISABLE_DEPRECATED */
-typedef void (*GtkModuleInitFunc) (gint *argc,
- gchar ***argv);
-typedef void (*GtkModuleDisplayInitFunc) (GdkDisplay *display);
typedef gint (*GtkKeySnoopFunc) (GtkWidget *grab_widget,
GdkEventKey *event,
gpointer func_data);
@@ -214,10 +211,6 @@ gboolean _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
const GValue *handler_return,
gpointer dummy);
-gchar * _gtk_find_module (const gchar *name,
- const gchar *type);
-gchar **_gtk_get_module_path (const gchar *type);
-
gchar *_gtk_get_lc_ctype (void);
#ifdef __cplusplus
diff --git a/gtk/gtkmodules.c b/gtk/gtkmodules.c
new file mode 100644
index 0000000000..51718c8e58
--- /dev/null
+++ b/gtk/gtkmodules.c
@@ -0,0 +1,540 @@
+/* GTK - The GIMP Toolkit
+ * Copyright 1998-2002 Tim Janik, Red Hat, Inc., and others.
+ * Copyright (C) 2003 Alex Graveley
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include "gtkmodules.h"
+#include "gtksettings.h"
+#include "gtkdebug.h"
+
+#include <gmodule.h>
+#include <pango/pango-utils.h> /* For pango_split_file_list */
+
+typedef struct _GtkModuleInfo GtkModuleInfo;
+struct _GtkModuleInfo
+{
+ GModule *module;
+ gint ref_count;
+ GtkModuleInitFunc init_func;
+ GtkModuleDisplayInitFunc display_init_func;
+ GSList *names;
+};
+
+static GSList *gtk_modules = NULL;
+
+static gboolean default_display_opened = FALSE;
+
+/* Saved argc, argv for delayed module initialization
+ */
+static gint gtk_argc = 0;
+static gchar **gtk_argv = NULL;
+
+static gchar **
+get_module_path (void)
+{
+ const gchar *module_path_env;
+ const gchar *exe_prefix;
+ const gchar *home_dir;
+ gchar *home_gtk_dir = NULL;
+ gchar *module_path;
+ gchar *default_dir;
+ static gchar **result = NULL;
+
+ if (result)
+ return result;
+
+ home_dir = g_get_home_dir();
+ if (home_dir)
+ home_gtk_dir = g_build_filename (home_dir, ".gtk-2.0", NULL);
+
+ module_path_env = g_getenv ("GTK_PATH");
+ exe_prefix = g_getenv ("GTK_EXE_PREFIX");
+
+ if (exe_prefix)
+ default_dir = g_build_filename (exe_prefix, "lib", "gtk-2.0", NULL);
+ else
+ default_dir = g_build_filename (GTK_LIBDIR, "gtk-2.0", NULL);
+
+ if (module_path_env && home_gtk_dir)
+ module_path = g_build_path (G_SEARCHPATH_SEPARATOR_S,
+ module_path_env, home_gtk_dir, default_dir, NULL);
+ else if (module_path_env)
+ module_path = g_build_path (G_SEARCHPATH_SEPARATOR_S,
+ module_path_env, default_dir, NULL);
+ else if (home_gtk_dir)
+ module_path = g_build_path (G_SEARCHPATH_SEPARATOR_S,
+ home_gtk_dir, default_dir, NULL);
+ else
+ module_path = g_build_path (G_SEARCHPATH_SEPARATOR_S,
+ default_dir, NULL);
+
+ g_free (home_gtk_dir);
+ g_free (default_dir);
+
+ result = pango_split_file_list (module_path);
+ g_free (module_path);
+
+ return result;
+}
+
+/**
+ * _gtk_get_module_path:
+ * @type: the type of the module, for instance 'modules', 'engines', immodules'
+ *
+ * Determines the search path for a particular type of module.
+ *
+ * Return value: the search path for the module type. Free with g_strfreev().
+ **/
+gchar **
+_gtk_get_module_path (const gchar *type)
+{
+ gchar **paths = get_module_path();
+ gchar **path;
+ gchar **result;
+ gint count = 0;
+
+ for (path = paths; *path; path++)
+ count++;
+
+ result = g_new (gchar *, count * 4 + 1);
+
+ count = 0;
+ for (path = get_module_path (); *path; path++)
+ {
+ gint use_version, use_host;
+
+ for (use_version = TRUE; use_version >= FALSE; use_version--)
+ for (use_host = TRUE; use_host >= FALSE; use_host--)
+ {
+ gchar *tmp_dir;
+
+ if (use_version && use_host)
+ tmp_dir = g_build_filename (*path, GTK_BINARY_VERSION, GTK_HOST, type, NULL);
+ else if (use_version)
+ tmp_dir = g_build_filename (*path, GTK_BINARY_VERSION, type, NULL);
+ else if (use_host)
+ tmp_dir = g_build_filename (*path, GTK_HOST, type, NULL);
+ else
+ tmp_dir = g_build_filename (*path, type, NULL);
+
+ result[count++] = tmp_dir;
+ }
+ }
+
+ result[count++] = NULL;
+
+ return result;
+}
+
+/* Like g_module_path, but use .la as the suffix
+ */
+static gchar*
+module_build_la_path (const gchar *directory,
+ const gchar *module_name)
+{
+ gchar *filename;
+ gchar *result;
+
+ if (strncmp (module_name, "lib", 3) == 0)
+ filename = (gchar *)module_name;
+ else
+ filename = g_strconcat ("lib", module_name, ".la", NULL);
+
+ if (directory && *directory)
+ result = g_build_filename (directory, filename, NULL);
+ else
+ result = g_strdup (filename);
+
+ if (filename != module_name)
+ g_free (filename);
+
+ return result;
+}
+
+/**
+ * _gtk_find_module:
+ * @name: the name of the module
+ * @type: the type of the module, for instance 'modules', 'engines', immodules'
+ *
+ * Looks for a dynamically module named @name of type @type in the standard GTK+
+ * module search path.
+ *
+ * Return value: the pathname to the found module, or %NULL if it wasn't found.
+ * Free with g_free().
+ **/
+gchar *
+_gtk_find_module (const gchar *name,
+ const gchar *type)
+{
+ gchar **paths;
+ gchar **path;
+ gchar *module_name = NULL;
+
+ if (g_path_is_absolute (name))
+ return g_strdup (name);
+
+ paths = _gtk_get_module_path (type);
+ for (path = paths; *path; path++)
+ {
+ gchar *tmp_name;
+
+ tmp_name = g_module_build_path (*path, name);
+ if (g_file_test (tmp_name, G_FILE_TEST_EXISTS))
+ {
+ module_name = tmp_name;
+ goto found;
+ }
+ g_free(tmp_name);
+
+ tmp_name = module_build_la_path (*path, name);
+ if (g_file_test (tmp_name, G_FILE_TEST_EXISTS))
+ {
+ module_name = tmp_name;
+ goto found;
+ }
+ g_free(tmp_name);
+ }
+
+ found:
+ g_strfreev (paths);
+ return module_name;
+}
+
+static GModule *
+find_module (const gchar *name)
+{
+ GModule *module;
+ gchar *module_name;
+
+ module_name = _gtk_find_module (name, "modules");
+ if (!module_name)
+ {
+ /* As last resort, try loading without an absolute path (using system
+ * library path)
+ */
+ module_name = g_module_build_path (NULL, name);
+ }
+
+ module = g_module_open (module_name, G_MODULE_BIND_LAZY);
+ g_free(module_name);
+
+ return module;
+}
+
+static gint
+cmp_module (GtkModuleInfo *info,
+ GModule *module)
+{
+ return info->module != module;
+}
+
+static GSList *
+load_module (GSList *module_list,
+ const gchar *name)
+{
+ GtkModuleInitFunc modinit_func;
+ GtkModuleInfo *info = NULL;
+ GModule *module = NULL;
+ GSList *l;
+ gboolean success = FALSE;
+
+ if (g_module_supported ())
+ {
+ for (l = gtk_modules; l; l = l->next)
+ {
+ info = l->data;
+ if (g_slist_find_custom (info->names, name,
+ (GCompareFunc)strcmp))
+ {
+ info->ref_count++;
+
+ success = TRUE;
+ }
+ }
+
+ if (!success)
+ {
+ module = find_module (name);
+
+ if (module)
+ {
+ if (!g_module_symbol (module, "gtk_module_init", (gpointer *) &modinit_func) ||
+ !modinit_func)
+ g_module_close (module);
+ else
+ {
+ success = TRUE;
+ info = (GtkModuleInfo *) g_slist_find_custom (gtk_modules, module,
+ (GCompareFunc)cmp_module);
+ if (!info)
+ {
+ info = g_new0 (GtkModuleInfo, 1);
+
+ info->names = g_slist_prepend (info->names, g_strdup (name));
+ info->module = module;
+ info->ref_count = 1;
+ info->init_func = modinit_func;
+ g_module_symbol (module, "gtk_module_display_init",
+ (gpointer *) &info->display_init_func);
+
+ gtk_modules = g_slist_prepend (gtk_modules, info);
+
+ /* display_init == NULL indicates a non-multihead aware module.
+ * For these, we delay the call to init_func until first display is
+ * opened, see default_display_notify_cb().
+ * For multihead aware modules, we call init_func immediately,
+ * and also call display_init_func on all opened displays.
+ */
+ if (default_display_opened || info->display_init_func)
+ (* info->init_func) (&gtk_argc, &gtk_argv);
+
+ if (info->display_init_func)
+ {
+ GSList *displays, *iter;
+ displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
+ for (iter = displays; iter; iter = iter->next)
+ {
+ GdkDisplay *display = iter->data;
+ (* info->display_init_func) (display);
+ }
+ g_slist_free (displays);
+ }
+ }
+ else
+ {
+ GTK_NOTE (MODULES, g_print ("Module already loaded, ignoring: %s\n", name));
+ info->names = g_slist_prepend (info->names, g_strdup (name));
+ info->ref_count++;
+ /* remove new reference count on module, we already have one */
+ g_module_close (module);
+ }
+ }
+ }
+ }
+ }
+
+ if (success)
+ {
+ if (!g_slist_find (module_list, info))
+ {
+ module_list = g_slist_prepend (module_list, info);
+ }
+ }
+ else
+ g_message ("Failed to load module \"%s\": %s", name, g_module_error ());
+
+ return module_list;
+}
+
+
+static void
+gtk_module_info_unref (GtkModuleInfo *info)
+{
+ GSList *l;
+
+ info->ref_count--;
+
+ if (info->ref_count == 0)
+ {
+ GTK_NOTE (MODULES,
+ g_print ("Unloading module: %s", g_module_name (info->module)));
+
+ gtk_modules = g_slist_remove (gtk_modules, info);
+ g_module_close (info->module);
+ for (l = info->names; l; l = l->next)
+ g_free (l->data);
+ g_slist_free (info->names);
+ g_free (info);
+ }
+}
+
+static GSList *
+load_modules (const char *module_str)
+{
+ gchar **module_names;
+ GSList *module_list = NULL;
+ gint i;
+
+ GTK_NOTE (MODULES, g_print ("Loading module list: %s", module_str));
+
+ module_names = pango_split_file_list (module_str);
+ for (i = 0; module_names[i]; i++)
+ module_list = load_module (module_list, module_names[i]);
+
+ module_list = g_slist_reverse (module_list);
+ g_strfreev (module_names);
+
+ return module_list;
+}
+
+static void
+default_display_notify_cb (GdkDisplayManager *display_manager)
+{
+ GSList *slist;
+
+ /* Initialize non-multihead-aware modules when the
+ * default display is first set to a non-NULL value.
+ */
+
+ if (!gdk_display_get_default () || default_display_opened)
+ return;
+
+ default_display_opened = TRUE;
+
+ for (slist = gtk_modules; slist; slist = slist->next)
+ {
+ if (slist->data)
+ {
+ GtkModuleInfo *info = slist->data;
+
+ if (!info->display_init_func)
+ (* info->init_func) (&gtk_argc, &gtk_argv);
+ }
+ }
+}
+
+static void
+display_closed_cb (GdkDisplay *display,
+ gboolean is_error)
+{
+ GdkScreen *screen;
+ GtkSettings *settings;
+ gint i;
+
+ for (i = 0; i < gdk_display_get_n_screens (display); i++)
+ {
+ screen = gdk_display_get_screen (display, i);
+
+ settings = gtk_settings_get_for_screen (screen);
+
+ g_object_set_data_full (G_OBJECT (settings),
+ "gtk-modules",
+ NULL, NULL);
+ }
+}
+
+
+static void
+display_opened_cb (GdkDisplayManager *display_manager,
+ GdkDisplay *display)
+{
+ GSList *slist;
+ GdkScreen *screen;
+ GtkSettings *settings;
+ gint i;
+
+ for (slist = gtk_modules; slist; slist = slist->next)
+ {
+ if (slist->data)
+ {
+ GtkModuleInfo *info = slist->data;
+
+ if (info->display_init_func)
+ (* info->display_init_func) (display);
+ }
+ }
+
+ for (i = 0; i < gdk_display_get_n_screens (display); i++)
+ {
+ GValue value = { 0, };
+
+ g_value_init (&value, G_TYPE_STRING);
+
+ screen = gdk_display_get_screen (display, i);
+
+ if (gdk_screen_get_setting (screen, "gtk-modules", &value))
+ {
+ settings = gtk_settings_get_for_screen (screen);
+ _gtk_modules_settings_changed (settings, g_value_get_string (&value));
+ g_value_unset (&value);
+ }
+ }
+
+ /* Since closing display doesn't actually release the resources yet,
+ * we have to connect to the ::closed signal.
+ */
+ g_signal_connect (display, "closed", G_CALLBACK (display_closed_cb), NULL);
+}
+
+void
+_gtk_modules_init (gint *argc,
+ gchar ***argv,
+ const gchar *gtk_modules_args)
+{
+ GdkDisplayManager *display_manager;
+ gint i;
+
+ g_assert (gtk_argv == NULL);
+
+ if (argc && argv)
+ {
+ /* store argc and argv for later use in mod initialization */
+ gtk_argc = *argc;
+ gtk_argv = g_new (gchar *, *argc + 1);
+ for (i = 0; i < gtk_argc; i++)
+ gtk_argv [i] = g_strdup ((*argv) [i]);
+ gtk_argv [*argc] = NULL;
+ }
+
+ display_manager = gdk_display_manager_get ();
+ g_signal_connect (display_manager, "notify::default-display",
+ G_CALLBACK (default_display_notify_cb),
+ NULL);
+ g_signal_connect (display_manager, "display-opened",
+ G_CALLBACK (display_opened_cb),
+ NULL);
+
+ /* Modules specified in the GTK_MODULES environment variable
+ * or on the command line are always loaded, so we'll just leak
+ * the refcounts.
+ */
+ g_slist_free (load_modules (gtk_modules_args));
+}
+
+static void
+settings_destroy_notify (gpointer data)
+{
+ GSList *iter, *modules = data;
+
+ for (iter = modules; iter; iter = iter->next)
+ {
+ GtkModuleInfo *info = iter->data;
+ gtk_module_info_unref (info);
+ }
+ g_slist_free (modules);
+}
+
+void
+_gtk_modules_settings_changed (GtkSettings *settings,
+ const gchar *modules)
+{
+ GSList *new_modules = NULL;
+
+ /* load/ref before unreffing existing */
+ if (modules && modules[0])
+ new_modules = load_modules (modules);
+
+ g_object_set_data_full (G_OBJECT (settings),
+ "gtk-modules",
+ new_modules,
+ settings_destroy_notify);
+}
diff --git a/gtk/gtkmodules.h b/gtk/gtkmodules.h
new file mode 100644
index 0000000000..c7ebd395a7
--- /dev/null
+++ b/gtk/gtkmodules.h
@@ -0,0 +1,50 @@
+/* GTK - The GIMP Toolkit
+ * Copyright 1998-2002 Tim Janik, Red Hat, Inc., and others.
+ * Copyright (C) 2003 Alex Graveley
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_MODULES_H__
+#define __GTK_MODULES_H__
+
+#include <gtk/gtksettings.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Functions for use within GTK+
+ */
+gchar * _gtk_find_module (const gchar *name,
+ const gchar *type);
+gchar **_gtk_get_module_path (const gchar *type);
+
+void _gtk_modules_init (gint *argc,
+ gchar ***argv,
+ const gchar *gtk_modules_args);
+void _gtk_modules_settings_changed (GtkSettings *settings,
+ const gchar *modules);
+
+typedef void (*GtkModuleInitFunc) (gint *argc,
+ gchar ***argv);
+typedef void (*GtkModuleDisplayInitFunc) (GdkDisplay *display);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GTK_MODULES_H__ */
diff --git a/gtk/gtksettings.c b/gtk/gtksettings.c
index cf4a7772f3..0767b35e24 100644
--- a/gtk/gtksettings.c
+++ b/gtk/gtksettings.c
@@ -63,6 +63,7 @@ enum {
PROP_DND_DRAG_THRESHOLD,
PROP_FONT_NAME,
PROP_ICON_SIZES,
+ PROP_MODULES,
PROP_XFT_ANTIALIAS,
PROP_XFT_HINTING,
PROP_XFT_HINTSTYLE,
@@ -89,6 +90,8 @@ static guint settings_install_property_parser (GtkSettingsClass *class,
GParamSpec *pspec,
GtkRcPropertyParser parser);
static void settings_update_double_click (GtkSettings *settings);
+static void settings_update_modules (GtkSettings *settings);
+
/* --- variables --- */
@@ -360,6 +363,15 @@ gtk_settings_class_init (GtkSettingsClass *class)
NULL);
g_assert (result == PROP_ICON_SIZES);
+ result = settings_install_property_parser (class,
+ g_param_spec_string ("gtk-modules",
+ P_("GTK Modules"),
+ P_("List of currently active GTK modules"),
+ NULL,
+ G_PARAM_READWRITE),
+ NULL);
+ g_assert (result == PROP_MODULES);
+
#ifdef GDK_WINDOWING_X11
result = settings_install_property_parser (class,
g_param_spec_int ("gtk-xft-antialias",
@@ -584,6 +596,9 @@ gtk_settings_notify (GObject *object,
switch (property_id)
{
+ case PROP_MODULES:
+ settings_update_modules (settings);
+ break;
case PROP_DOUBLE_CLICK_TIME:
case PROP_DOUBLE_CLICK_DISTANCE:
settings_update_double_click (settings);
@@ -1363,3 +1378,18 @@ settings_update_double_click (GtkSettings *settings)
gdk_display_set_double_click_distance (display, double_click_distance);
}
}
+
+static void
+settings_update_modules (GtkSettings *settings)
+{
+ GdkDisplay *display = gdk_screen_get_display (settings->screen);
+ gchar *modules;
+
+ g_object_get (settings,
+ "gtk-modules", &modules,
+ NULL);
+
+ _gtk_modules_settings_changed (settings, modules);
+
+ g_free (modules);
+}