* 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.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <config.h>
+#include "config.h"
#include <string.h>
#include "gtkmodules.h"
#include "gtksettings.h"
#include "gtkdebug.h"
-#include "gtkprivate.h" /* GTK_LIBDIR */
-#include "gtkintl.h"
+#include "gtkprivate.h"
+#include "gtkmodulesprivate.h"
+#include "gtkintl.h"
#include <gmodule.h>
-#include <pango/pango-utils.h> /* For pango_split_file_list */
typedef struct _GtkModuleInfo GtkModuleInfo;
struct _GtkModuleInfo
{
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);
+ default_dir = g_build_filename (exe_prefix, "lib", "gtk-3.0", NULL);
else
- default_dir = g_build_filename (GTK_LIBDIR, "gtk-2.0", NULL);
+ default_dir = g_build_filename (_gtk_get_libdir (), "gtk-3.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)
+ 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);
module_name = g_module_build_path (NULL, name);
}
- module = g_module_open (module_name, G_MODULE_BIND_LAZY);
- g_free(module_name);
+ module = g_module_open (module_name, G_MODULE_BIND_LOCAL | G_MODULE_BIND_LAZY);
+
+ if (_gtk_module_has_mixed_deps (module))
+ {
+ g_warning ("GTK+ module %s cannot be loaded.\n"
+ "GTK+ 2.x symbols detected. Using GTK+ 2.x and GTK+ 3 in the same process is not supported.", module_name);
+ g_module_close (module);
+ module = NULL;
+ }
+
+ g_free (module_name);
return module;
}
return info->module != module;
}
+static gboolean
+module_is_blacklisted (const gchar *name,
+ gboolean verbose)
+{
+ if (g_str_equal (name, "gail") ||
+ g_str_equal (name, "atk-bridge"))
+ {
+ if (verbose)
+ g_message ("Not loading module \"%s\": The functionality is provided by GTK natively. Please try to not load it.", name);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static GSList *
load_module (GSList *module_list,
const gchar *name)
{
GtkModuleInitFunc modinit_func;
+ gpointer modinit_func_ptr;
GtkModuleInfo *info = NULL;
GModule *module = NULL;
GSList *l;
for (l = gtk_modules; l; l = l->next)
{
info = l->data;
- if (g_slist_find_custom (info->names, name,
+ if (g_slist_find_custom (info->names, name,
(GCompareFunc)strcmp))
{
info->ref_count++;
success = TRUE;
+ break;
}
+ info = NULL;
}
- if (!success)
+ if (!success)
{
module = find_module (name);
if (module)
{
- if (!g_module_symbol (module, "gtk_module_init", (gpointer *) &modinit_func) ||
- !modinit_func)
+ /* Do the check this late so we only warn about existing modules,
+ * not old modules that are still in the modules path. */
+ if (module_is_blacklisted (name, TRUE))
+ {
+ modinit_func = NULL;
+ success = TRUE;
+ }
+ else if (g_module_symbol (module, "gtk_module_init", &modinit_func_ptr))
+ modinit_func = modinit_func_ptr;
+ else
+ modinit_func = NULL;
+
+ if (!modinit_func)
g_module_close (module);
else
{
+ GSList *temp;
+
success = TRUE;
- info = (GtkModuleInfo *) g_slist_find_custom (gtk_modules, module,
- (GCompareFunc)cmp_module);
+ info = NULL;
+
+ temp = g_slist_find_custom (gtk_modules, module,
+ (GCompareFunc)cmp_module);
+ if (temp != NULL)
+ info = temp->data;
+
if (!info)
{
info = g_new0 (GtkModuleInfo, 1);
gtk_modules = g_slist_append (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
+ * 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 (success)
+ if (success && info)
{
if (!g_slist_find (module_list, info))
{
}
}
else
- g_message ("Failed to load module \"%s\": %s", name, g_module_error ());
-
+ {
+ if (!module_is_blacklisted (name, FALSE))
+ {
+ const gchar *error = g_module_error ();
+
+ g_message ("Failed to load module \"%s\"%s%s",
+ name, error ? ": " : "", error ? error : "");
+ }
+ }
+
return module_list;
}
if (info->ref_count == 0)
{
GTK_NOTE (MODULES,
- g_print ("Unloading module: %s", g_module_name (info->module)));
+ g_print ("Unloading module: %s\n", g_module_name (info->module)));
gtk_modules = g_slist_remove (gtk_modules, info);
g_module_close (info->module);
GSList *module_list = NULL;
gint i;
- GTK_NOTE (MODULES, g_print ("Loading module list: %s", module_str));
+ GTK_NOTE (MODULES, g_print ("Loading module list: %s\n", module_str));
module_names = pango_split_file_list (module_str);
for (i = 0; module_names[i]; i++)
for (i = 0; i < gdk_display_get_n_screens (display); i++)
{
- GValue value = { 0, };
+ GValue value = G_VALUE_INIT;
g_value_init (&value, G_TYPE_STRING);
}
display_manager = gdk_display_manager_get ();
+ default_display_opened = gdk_display_get_default () != NULL;
g_signal_connect (display_manager, "notify::default-display",
G_CALLBACK (default_display_notify_cb),
NULL);
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));
+ if (gtk_modules_args) {
+ /* 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
{
GSList *new_modules = NULL;
+ GTK_NOTE (MODULES, g_print ("gtk-modules setting changed to: %s\n", modules));
+
/* load/ref before unreffing existing */
if (modules && modules[0])
new_modules = load_modules (modules);
new_modules,
settings_destroy_notify);
}
+
+/* Return TRUE if module_to_check causes version conflicts.
+ * If module_to_check is NULL, check the main module.
+ */
+gboolean
+_gtk_module_has_mixed_deps (GModule *module_to_check)
+{
+ GModule *module;
+ gpointer func;
+ gboolean result;
+
+ if (!module_to_check)
+ module = g_module_open (NULL, 0);
+ else
+ module = module_to_check;
+
+ if (g_module_symbol (module, "gtk_progress_get_type", &func))
+ result = TRUE;
+ else
+ result = FALSE;
+
+ if (!module_to_check)
+ g_module_close (module);
+
+ return result;
+}