diff options
author | Matthias Clasen <mclasen@redhat.com> | 2004-09-01 20:30:24 +0000 |
---|---|---|
committer | Matthias Clasen <matthiasc@src.gnome.org> | 2004-09-01 20:30:24 +0000 |
commit | 8189921f446a585398d8df69d589b6003ccbffdb (patch) | |
tree | 92dcb32a0d29888b23f82d91b61615a21b2b5317 /gtk | |
parent | 0ac4f2837a6e8d57f79846f4cef65658122264b5 (diff) | |
download | gtk+-8189921f446a585398d8df69d589b6003ccbffdb.tar.gz |
Make it possible to specify additional modules to load via a setting.
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.
Diffstat (limited to 'gtk')
-rw-r--r-- | gtk/Makefile.am | 2 | ||||
-rw-r--r-- | gtk/gtk.h | 1 | ||||
-rw-r--r-- | gtk/gtkdebug.h | 3 | ||||
-rw-r--r-- | gtk/gtkmain.c | 368 | ||||
-rw-r--r-- | gtk/gtkmain.h | 7 | ||||
-rw-r--r-- | gtk/gtkmodules.c | 540 | ||||
-rw-r--r-- | gtk/gtkmodules.h | 50 | ||||
-rw-r--r-- | gtk/gtksettings.c | 30 |
8 files changed, 641 insertions, 360 deletions
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 \ @@ -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 (>k_argc, >k_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) (>k_argc, >k_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) (>k_argc, >k_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); +} |