1 /* GTK - The GIMP Toolkit
2 * Copyright 1998-2002 Tim Janik, Red Hat, Inc., and others.
3 * Copyright (C) 2003 Alex Graveley
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
25 #include "gtkmodules.h"
26 #include "gtksettings.h"
28 #include "gtkprivate.h" /* GTK_LIBDIR */
31 #include <pango/pango-utils.h> /* For pango_split_file_list */
33 typedef struct _GtkModuleInfo GtkModuleInfo;
38 GtkModuleInitFunc init_func;
39 GtkModuleDisplayInitFunc display_init_func;
43 static GSList *gtk_modules = NULL;
45 static gboolean default_display_opened = FALSE;
47 /* Saved argc, argv for delayed module initialization
49 static gint gtk_argc = 0;
50 static gchar **gtk_argv = NULL;
53 get_module_path (void)
55 const gchar *module_path_env;
56 const gchar *exe_prefix;
57 const gchar *home_dir;
58 gchar *home_gtk_dir = NULL;
61 static gchar **result = NULL;
66 home_dir = g_get_home_dir();
68 home_gtk_dir = g_build_filename (home_dir, ".gtk-2.0", NULL);
70 module_path_env = g_getenv ("GTK_PATH");
71 exe_prefix = g_getenv ("GTK_EXE_PREFIX");
74 default_dir = g_build_filename (exe_prefix, "lib", "gtk-2.0", NULL);
76 default_dir = g_build_filename (GTK_LIBDIR, "gtk-2.0", NULL);
78 if (module_path_env && home_gtk_dir)
79 module_path = g_build_path (G_SEARCHPATH_SEPARATOR_S,
80 module_path_env, home_gtk_dir, default_dir, NULL);
81 else if (module_path_env)
82 module_path = g_build_path (G_SEARCHPATH_SEPARATOR_S,
83 module_path_env, default_dir, NULL);
84 else if (home_gtk_dir)
85 module_path = g_build_path (G_SEARCHPATH_SEPARATOR_S,
86 home_gtk_dir, default_dir, NULL);
88 module_path = g_build_path (G_SEARCHPATH_SEPARATOR_S,
91 g_free (home_gtk_dir);
94 result = pango_split_file_list (module_path);
101 * _gtk_get_module_path:
102 * @type: the type of the module, for instance 'modules', 'engines', immodules'
104 * Determines the search path for a particular type of module.
106 * Return value: the search path for the module type. Free with g_strfreev().
109 _gtk_get_module_path (const gchar *type)
111 gchar **paths = get_module_path();
116 for (path = paths; *path; path++)
119 result = g_new (gchar *, count * 4 + 1);
122 for (path = get_module_path (); *path; path++)
124 gint use_version, use_host;
126 for (use_version = TRUE; use_version >= FALSE; use_version--)
127 for (use_host = TRUE; use_host >= FALSE; use_host--)
131 if (use_version && use_host)
132 tmp_dir = g_build_filename (*path, GTK_BINARY_VERSION, GTK_HOST, type, NULL);
133 else if (use_version)
134 tmp_dir = g_build_filename (*path, GTK_BINARY_VERSION, type, NULL);
136 tmp_dir = g_build_filename (*path, GTK_HOST, type, NULL);
138 tmp_dir = g_build_filename (*path, type, NULL);
140 result[count++] = tmp_dir;
144 result[count++] = NULL;
149 /* Like g_module_path, but use .la as the suffix
152 module_build_la_path (const gchar *directory,
153 const gchar *module_name)
158 if (strncmp (module_name, "lib", 3) == 0)
159 filename = (gchar *)module_name;
161 filename = g_strconcat ("lib", module_name, ".la", NULL);
163 if (directory && *directory)
164 result = g_build_filename (directory, filename, NULL);
166 result = g_strdup (filename);
168 if (filename != module_name)
176 * @name: the name of the module
177 * @type: the type of the module, for instance 'modules', 'engines', immodules'
179 * Looks for a dynamically module named @name of type @type in the standard GTK+
180 * module search path.
182 * Return value: the pathname to the found module, or %NULL if it wasn't found.
183 * Free with g_free().
186 _gtk_find_module (const gchar *name,
191 gchar *module_name = NULL;
193 if (g_path_is_absolute (name))
194 return g_strdup (name);
196 paths = _gtk_get_module_path (type);
197 for (path = paths; *path; path++)
201 tmp_name = g_module_build_path (*path, name);
202 if (g_file_test (tmp_name, G_FILE_TEST_EXISTS))
204 module_name = tmp_name;
209 tmp_name = module_build_la_path (*path, name);
210 if (g_file_test (tmp_name, G_FILE_TEST_EXISTS))
212 module_name = tmp_name;
224 find_module (const gchar *name)
229 module_name = _gtk_find_module (name, "modules");
232 /* As last resort, try loading without an absolute path (using system
235 module_name = g_module_build_path (NULL, name);
238 module = g_module_open (module_name, G_MODULE_BIND_LAZY);
245 cmp_module (GtkModuleInfo *info,
248 return info->module != module;
252 load_module (GSList *module_list,
255 GtkModuleInitFunc modinit_func;
256 GtkModuleInfo *info = NULL;
257 GModule *module = NULL;
259 gboolean success = FALSE;
261 if (g_module_supported ())
263 for (l = gtk_modules; l; l = l->next)
266 if (g_slist_find_custom (info->names, name,
267 (GCompareFunc)strcmp))
277 module = find_module (name);
281 if (!g_module_symbol (module, "gtk_module_init", (gpointer *) &modinit_func) ||
283 g_module_close (module);
287 info = (GtkModuleInfo *) g_slist_find_custom (gtk_modules, module,
288 (GCompareFunc)cmp_module);
291 info = g_new0 (GtkModuleInfo, 1);
293 info->names = g_slist_prepend (info->names, g_strdup (name));
294 info->module = module;
296 info->init_func = modinit_func;
297 g_module_symbol (module, "gtk_module_display_init",
298 (gpointer *) &info->display_init_func);
300 gtk_modules = g_slist_prepend (gtk_modules, info);
302 /* display_init == NULL indicates a non-multihead aware module.
303 * For these, we delay the call to init_func until first display is
304 * opened, see default_display_notify_cb().
305 * For multihead aware modules, we call init_func immediately,
306 * and also call display_init_func on all opened displays.
308 if (default_display_opened || info->display_init_func)
309 (* info->init_func) (>k_argc, >k_argv);
311 if (info->display_init_func)
313 GSList *displays, *iter;
314 displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
315 for (iter = displays; iter; iter = iter->next)
317 GdkDisplay *display = iter->data;
318 (* info->display_init_func) (display);
320 g_slist_free (displays);
325 GTK_NOTE (MODULES, g_print ("Module already loaded, ignoring: %s\n", name));
326 info->names = g_slist_prepend (info->names, g_strdup (name));
328 /* remove new reference count on module, we already have one */
329 g_module_close (module);
338 if (!g_slist_find (module_list, info))
340 module_list = g_slist_prepend (module_list, info);
344 g_message ("Failed to load module \"%s\": %s", name, g_module_error ());
351 gtk_module_info_unref (GtkModuleInfo *info)
357 if (info->ref_count == 0)
360 g_print ("Unloading module: %s", g_module_name (info->module)));
362 gtk_modules = g_slist_remove (gtk_modules, info);
363 g_module_close (info->module);
364 for (l = info->names; l; l = l->next)
366 g_slist_free (info->names);
372 load_modules (const char *module_str)
374 gchar **module_names;
375 GSList *module_list = NULL;
378 GTK_NOTE (MODULES, g_print ("Loading module list: %s", module_str));
380 module_names = pango_split_file_list (module_str);
381 for (i = 0; module_names[i]; i++)
382 module_list = load_module (module_list, module_names[i]);
384 module_list = g_slist_reverse (module_list);
385 g_strfreev (module_names);
391 default_display_notify_cb (GdkDisplayManager *display_manager)
395 /* Initialize non-multihead-aware modules when the
396 * default display is first set to a non-NULL value.
399 if (!gdk_display_get_default () || default_display_opened)
402 default_display_opened = TRUE;
404 for (slist = gtk_modules; slist; slist = slist->next)
408 GtkModuleInfo *info = slist->data;
410 if (!info->display_init_func)
411 (* info->init_func) (>k_argc, >k_argv);
417 display_closed_cb (GdkDisplay *display,
421 GtkSettings *settings;
424 for (i = 0; i < gdk_display_get_n_screens (display); i++)
426 screen = gdk_display_get_screen (display, i);
428 settings = gtk_settings_get_for_screen (screen);
430 g_object_set_data_full (G_OBJECT (settings),
438 display_opened_cb (GdkDisplayManager *display_manager,
443 GtkSettings *settings;
446 for (slist = gtk_modules; slist; slist = slist->next)
450 GtkModuleInfo *info = slist->data;
452 if (info->display_init_func)
453 (* info->display_init_func) (display);
457 for (i = 0; i < gdk_display_get_n_screens (display); i++)
459 GValue value = { 0, };
461 g_value_init (&value, G_TYPE_STRING);
463 screen = gdk_display_get_screen (display, i);
465 if (gdk_screen_get_setting (screen, "gtk-modules", &value))
467 settings = gtk_settings_get_for_screen (screen);
468 _gtk_modules_settings_changed (settings, g_value_get_string (&value));
469 g_value_unset (&value);
473 /* Since closing display doesn't actually release the resources yet,
474 * we have to connect to the ::closed signal.
476 g_signal_connect (display, "closed", G_CALLBACK (display_closed_cb), NULL);
480 _gtk_modules_init (gint *argc,
482 const gchar *gtk_modules_args)
484 GdkDisplayManager *display_manager;
487 g_assert (gtk_argv == NULL);
491 /* store argc and argv for later use in mod initialization */
493 gtk_argv = g_new (gchar *, *argc + 1);
494 for (i = 0; i < gtk_argc; i++)
495 gtk_argv [i] = g_strdup ((*argv) [i]);
496 gtk_argv [*argc] = NULL;
499 display_manager = gdk_display_manager_get ();
500 g_signal_connect (display_manager, "notify::default-display",
501 G_CALLBACK (default_display_notify_cb),
503 g_signal_connect (display_manager, "display-opened",
504 G_CALLBACK (display_opened_cb),
507 /* Modules specified in the GTK_MODULES environment variable
508 * or on the command line are always loaded, so we'll just leak
511 g_slist_free (load_modules (gtk_modules_args));
515 settings_destroy_notify (gpointer data)
517 GSList *iter, *modules = data;
519 for (iter = modules; iter; iter = iter->next)
521 GtkModuleInfo *info = iter->data;
522 gtk_module_info_unref (info);
524 g_slist_free (modules);
528 _gtk_modules_settings_changed (GtkSettings *settings,
529 const gchar *modules)
531 GSList *new_modules = NULL;
533 /* load/ref before unreffing existing */
534 if (modules && modules[0])
535 new_modules = load_modules (modules);
537 g_object_set_data_full (G_OBJECT (settings),
540 settings_destroy_notify);