]> Pileus Git - ~andy/gtk/blob - gtk/gtkmodules.c
gtk: move _gtk_modules_has_mixed_deps() to gtkmodlesprivate.h
[~andy/gtk] / gtk / gtkmodules.c
1 /* GTK - The GIMP Toolkit
2  * Copyright 1998-2002 Tim Janik, Red Hat, Inc., and others.
3  * Copyright (C) 2003 Alex Graveley
4  *
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.
9  *
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.
14  *
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.
19  */
20
21 #include "config.h"
22
23 #include <string.h>
24
25 #include "gtkmodules.h"
26 #include "gtkmodulesprivate.h"
27 #include "gtksettings.h"
28 #include "gtkdebug.h"
29 #include "gtkprivate.h"
30 #include "gtkmodulesprivate.h"
31 #include "gtkintl.h"
32
33 #include <gmodule.h>
34
35 typedef struct _GtkModuleInfo GtkModuleInfo;
36 struct _GtkModuleInfo
37 {
38   GModule                 *module;
39   gint                     ref_count;
40   GtkModuleInitFunc        init_func;
41   GtkModuleDisplayInitFunc display_init_func;
42   GSList                  *names;
43 };
44
45 static GSList *gtk_modules = NULL;
46
47 static gboolean default_display_opened = FALSE;
48
49 /* Saved argc, argv for delayed module initialization
50  */
51 static gint    gtk_argc = 0;
52 static gchar **gtk_argv = NULL;
53
54 static gchar **
55 get_module_path (void)
56 {
57   const gchar *module_path_env;
58   const gchar *exe_prefix;
59   const gchar *home_dir;
60   gchar *home_gtk_dir = NULL;
61   gchar *module_path;
62   gchar *default_dir;
63   static gchar **result = NULL;
64
65   if (result)
66     return result;
67
68   home_dir = g_get_home_dir();
69   if (home_dir)
70     home_gtk_dir = g_build_filename (home_dir, ".gtk-3.0", NULL);
71
72   module_path_env = g_getenv ("GTK_PATH");
73   exe_prefix = g_getenv ("GTK_EXE_PREFIX");
74
75   if (exe_prefix)
76     default_dir = g_build_filename (exe_prefix, "lib", "gtk-3.0", NULL);
77   else
78     default_dir = g_build_filename (_gtk_get_libdir (), "gtk-3.0", NULL);
79
80   if (module_path_env && home_gtk_dir)
81     module_path = g_build_path (G_SEARCHPATH_SEPARATOR_S,
82                                 module_path_env, home_gtk_dir, default_dir, NULL);
83   else if (module_path_env)
84     module_path = g_build_path (G_SEARCHPATH_SEPARATOR_S,
85                                 module_path_env, default_dir, NULL);
86   else if (home_gtk_dir)
87     module_path = g_build_path (G_SEARCHPATH_SEPARATOR_S,
88                                 home_gtk_dir, default_dir, NULL);
89   else
90     module_path = g_build_path (G_SEARCHPATH_SEPARATOR_S,
91                                 default_dir, NULL);
92
93   g_free (home_gtk_dir);
94   g_free (default_dir);
95
96   result = pango_split_file_list (module_path);
97   g_free (module_path);
98
99   return result;
100 }
101
102 /**
103  * _gtk_get_module_path:
104  * @type: the type of the module, for instance 'modules', 'engines', immodules'
105  * 
106  * Determines the search path for a particular type of module.
107  * 
108  * Return value: the search path for the module type. Free with g_strfreev().
109  **/
110 gchar **
111 _gtk_get_module_path (const gchar *type)
112 {
113   gchar **paths = get_module_path();
114   gchar **path;
115   gchar **result;
116   gint count = 0;
117
118   for (path = paths; *path; path++)
119     count++;
120
121   result = g_new (gchar *, count * 4 + 1);
122
123   count = 0;
124   for (path = get_module_path (); *path; path++)
125     {
126       gint use_version, use_host;
127       
128       for (use_version = TRUE; use_version >= FALSE; use_version--)
129         for (use_host = TRUE; use_host >= FALSE; use_host--)
130           {
131             gchar *tmp_dir;
132             
133             if (use_version && use_host)
134               tmp_dir = g_build_filename (*path, GTK_BINARY_VERSION, GTK_HOST, type, NULL);
135             else if (use_version)
136               tmp_dir = g_build_filename (*path, GTK_BINARY_VERSION, type, NULL);
137             else if (use_host)
138               tmp_dir = g_build_filename (*path, GTK_HOST, type, NULL);
139             else
140               tmp_dir = g_build_filename (*path, type, NULL);
141
142             result[count++] = tmp_dir;
143           }
144     }
145
146   result[count++] = NULL;
147
148   return result;
149 }
150
151 /* Like g_module_path, but use .la as the suffix
152  */
153 static gchar*
154 module_build_la_path (const gchar *directory,
155                       const gchar *module_name)
156 {
157   gchar *filename;
158   gchar *result;
159         
160   if (strncmp (module_name, "lib", 3) == 0)
161     filename = (gchar *)module_name;
162   else
163     filename =  g_strconcat ("lib", module_name, ".la", NULL);
164
165   if (directory && *directory)
166     result = g_build_filename (directory, filename, NULL);
167   else
168     result = g_strdup (filename);
169
170   if (filename != module_name)
171     g_free (filename);
172
173   return result;
174 }
175
176 /**
177  * _gtk_find_module:
178  * @name: the name of the module
179  * @type: the type of the module, for instance 'modules', 'engines', immodules'
180  * 
181  * Looks for a dynamically module named @name of type @type in the standard GTK+
182  *  module search path.
183  * 
184  * Return value: the pathname to the found module, or %NULL if it wasn't found.
185  *  Free with g_free().
186  **/
187 gchar *
188 _gtk_find_module (const gchar *name,
189                   const gchar *type)
190 {
191   gchar **paths;
192   gchar **path;
193   gchar *module_name = NULL;
194
195   if (g_path_is_absolute (name))
196     return g_strdup (name);
197
198   paths = _gtk_get_module_path (type);
199   for (path = paths; *path; path++)
200     {
201       gchar *tmp_name;
202
203       tmp_name = g_module_build_path (*path, name);
204       if (g_file_test (tmp_name, G_FILE_TEST_EXISTS))
205         {
206           module_name = tmp_name;
207           goto found;
208         }
209       g_free(tmp_name);
210
211       tmp_name = module_build_la_path (*path, name);
212       if (g_file_test (tmp_name, G_FILE_TEST_EXISTS))
213         {
214           module_name = tmp_name;
215           goto found;
216         }
217       g_free(tmp_name);
218     }
219
220  found:
221   g_strfreev (paths);
222   return module_name;
223 }
224
225 static GModule *
226 find_module (const gchar *name)
227 {
228   GModule *module;
229   gchar *module_name;
230
231   module_name = _gtk_find_module (name, "modules");
232   if (!module_name)
233     {
234       /* As last resort, try loading without an absolute path (using system
235        * library path)
236        */
237       module_name = g_module_build_path (NULL, name);
238     }
239
240   module = g_module_open (module_name, G_MODULE_BIND_LOCAL | G_MODULE_BIND_LAZY);
241
242   if (_gtk_module_has_mixed_deps (module))
243     {
244       g_warning ("GTK+ module %s cannot be loaded.\n"
245                  "GTK+ 2.x symbols detected. Using GTK+ 2.x and GTK+ 3 in the same process is not supported.", module_name);
246       g_module_close (module);
247       module = NULL;
248     }
249
250   g_free (module_name);
251
252   return module;
253 }
254
255 static gint
256 cmp_module (GtkModuleInfo *info,
257             GModule       *module)
258 {
259   return info->module != module;
260 }
261
262 static gboolean
263 module_is_blacklisted (const gchar *name,
264                        gboolean     verbose)
265 {
266   if (g_str_equal (name, "gail"))
267     {
268       if (verbose)
269         g_message ("Not loading module \"gail\": The functionality is provided by GTK natively. Please try to not load it.");
270
271       return TRUE;
272     }
273
274   return FALSE;
275 }
276
277 static GSList *
278 load_module (GSList      *module_list,
279              const gchar *name)
280 {
281   GtkModuleInitFunc modinit_func;
282   gpointer modinit_func_ptr;
283   GtkModuleInfo *info = NULL;
284   GModule *module = NULL;
285   GSList *l;
286   gboolean success = FALSE;
287   
288   if (g_module_supported ())
289     {
290       for (l = gtk_modules; l; l = l->next)
291         {
292           info = l->data;
293           if (g_slist_find_custom (info->names, name,
294                                    (GCompareFunc)strcmp))
295             {
296               info->ref_count++;
297               
298               success = TRUE;
299               break;
300             }
301           info = NULL;
302         }
303
304       if (!success)
305         {
306           module = find_module (name);
307
308           if (module)
309             {
310               /* Do the check this late so we only warn about existing modules,
311                * not old modules that are still in the modules path. */
312               if (module_is_blacklisted (name, TRUE))
313                 {
314                   modinit_func = NULL;
315                   success = TRUE;
316                 }
317               else if (g_module_symbol (module, "gtk_module_init", &modinit_func_ptr))
318                 modinit_func = modinit_func_ptr;
319               else
320                 modinit_func = NULL;
321
322               if (!modinit_func)
323                 g_module_close (module);
324               else
325                 {
326                   GSList *temp;
327
328                   success = TRUE;
329                   info = NULL;
330
331                   temp = g_slist_find_custom (gtk_modules, module,
332                         (GCompareFunc)cmp_module);
333                   if (temp != NULL)
334                         info = temp->data;
335
336                   if (!info)
337                     {
338                       info = g_new0 (GtkModuleInfo, 1);
339                       
340                       info->names = g_slist_prepend (info->names, g_strdup (name));
341                       info->module = module;
342                       info->ref_count = 1;
343                       info->init_func = modinit_func;
344                       g_module_symbol (module, "gtk_module_display_init",
345                                        (gpointer *) &info->display_init_func);
346                       
347                       gtk_modules = g_slist_append (gtk_modules, info);
348                       
349                       /* display_init == NULL indicates a non-multihead aware module.
350                        * For these, we delay the call to init_func until first display is
351                        * opened, see default_display_notify_cb().
352                        * For multihead aware modules, we call init_func immediately,
353                        * and also call display_init_func on all opened displays.
354                        */
355                       if (default_display_opened || info->display_init_func)
356                         (* info->init_func) (&gtk_argc, &gtk_argv);
357                       
358                       if (info->display_init_func) 
359                         {
360                           GSList *displays, *iter;                
361                           displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
362                           for (iter = displays; iter; iter = iter->next)
363                             {
364                               GdkDisplay *display = iter->data;
365                           (* info->display_init_func) (display);
366                             }
367                           g_slist_free (displays);
368                         }
369                     }
370                   else
371                     {
372                       GTK_NOTE (MODULES, g_print ("Module already loaded, ignoring: %s\n", name));
373                       info->names = g_slist_prepend (info->names, g_strdup (name));
374                       info->ref_count++;
375                       /* remove new reference count on module, we already have one */
376                       g_module_close (module);
377                     }
378                 }
379             }
380         }
381     }
382
383   if (success && info)
384     {
385       if (!g_slist_find (module_list, info))
386         {
387           module_list = g_slist_prepend (module_list, info);
388         }
389     }
390   else
391     {
392       if (!module_is_blacklisted (name, FALSE))
393         {
394           const gchar *error = g_module_error ();
395
396           g_message ("Failed to load module \"%s\"%s%s",
397                      name, error ? ": " : "", error ? error : "");
398         }
399     }
400
401   return module_list;
402 }
403
404
405 static void
406 gtk_module_info_unref (GtkModuleInfo *info)
407 {
408   GSList *l;
409
410   info->ref_count--;
411
412   if (info->ref_count == 0) 
413     {
414       GTK_NOTE (MODULES, 
415                 g_print ("Unloading module: %s\n", g_module_name (info->module)));
416
417       gtk_modules = g_slist_remove (gtk_modules, info);
418       g_module_close (info->module);
419       for (l = info->names; l; l = l->next)
420         g_free (l->data);
421       g_slist_free (info->names);
422       g_free (info);
423     }
424 }
425
426 static GSList *
427 load_modules (const char *module_str)
428 {
429   gchar **module_names;
430   GSList *module_list = NULL;
431   gint i;
432
433   GTK_NOTE (MODULES, g_print ("Loading module list: %s\n", module_str));
434
435   module_names = pango_split_file_list (module_str);
436   for (i = 0; module_names[i]; i++) 
437     module_list = load_module (module_list, module_names[i]);
438
439   module_list = g_slist_reverse (module_list);
440   g_strfreev (module_names);
441
442   return module_list;
443 }
444
445 static void
446 default_display_notify_cb (GdkDisplayManager *display_manager)
447 {
448   GSList *slist;
449
450   /* Initialize non-multihead-aware modules when the
451    * default display is first set to a non-NULL value.
452    */
453
454   if (!gdk_display_get_default () || default_display_opened)
455     return;
456
457   default_display_opened = TRUE;
458
459   for (slist = gtk_modules; slist; slist = slist->next)
460     {
461       if (slist->data)
462         {
463           GtkModuleInfo *info = slist->data;
464
465           if (!info->display_init_func)
466             (* info->init_func) (&gtk_argc, &gtk_argv);
467         }
468     }
469 }
470
471 static void
472 display_closed_cb (GdkDisplay *display,
473                    gboolean    is_error)
474 {
475   GdkScreen *screen;
476   GtkSettings *settings;
477   gint i;
478
479   for (i = 0; i < gdk_display_get_n_screens (display); i++)
480     {
481       screen = gdk_display_get_screen (display, i);
482
483       settings = gtk_settings_get_for_screen (screen);
484
485       g_object_set_data_full (G_OBJECT (settings),
486                               I_("gtk-modules"),
487                               NULL, NULL);
488     }  
489 }
490                    
491
492 static void
493 display_opened_cb (GdkDisplayManager *display_manager,
494                    GdkDisplay        *display)
495 {
496   GSList *slist;
497   GdkScreen *screen;
498   GtkSettings *settings;
499   gint i;
500
501   for (slist = gtk_modules; slist; slist = slist->next)
502     {
503       if (slist->data)
504         {
505           GtkModuleInfo *info = slist->data;
506
507           if (info->display_init_func)
508             (* info->display_init_func) (display);
509         }
510     }
511   
512   for (i = 0; i < gdk_display_get_n_screens (display); i++)
513     {
514       GValue value = G_VALUE_INIT;
515
516       g_value_init (&value, G_TYPE_STRING);
517
518       screen = gdk_display_get_screen (display, i);
519
520       if (gdk_screen_get_setting (screen, "gtk-modules", &value))
521         {
522           settings = gtk_settings_get_for_screen (screen);
523           _gtk_modules_settings_changed (settings, g_value_get_string (&value));
524           g_value_unset (&value);
525         }
526     }
527
528   /* Since closing display doesn't actually release the resources yet,
529    * we have to connect to the ::closed signal.
530    */
531   g_signal_connect (display, "closed", G_CALLBACK (display_closed_cb), NULL);
532 }
533
534 void
535 _gtk_modules_init (gint        *argc, 
536                    gchar     ***argv, 
537                    const gchar *gtk_modules_args)
538 {
539   GdkDisplayManager *display_manager;
540   gint i;
541
542   g_assert (gtk_argv == NULL);
543
544   if (argc && argv) 
545     {
546       /* store argc and argv for later use in mod initialization */
547       gtk_argc = *argc;
548       gtk_argv = g_new (gchar *, *argc + 1);
549       for (i = 0; i < gtk_argc; i++)
550         gtk_argv [i] = g_strdup ((*argv) [i]);
551       gtk_argv [*argc] = NULL;
552     }
553
554   display_manager = gdk_display_manager_get ();
555   default_display_opened = gdk_display_get_default () != NULL;
556   g_signal_connect (display_manager, "notify::default-display",
557                     G_CALLBACK (default_display_notify_cb), 
558                     NULL);
559   g_signal_connect (display_manager, "display-opened",
560                     G_CALLBACK (display_opened_cb), 
561                     NULL);
562
563   if (gtk_modules_args) {
564     /* Modules specified in the GTK_MODULES environment variable
565      * or on the command line are always loaded, so we'll just leak 
566      * the refcounts.
567      */
568     g_slist_free (load_modules (gtk_modules_args));
569   }
570 }
571
572 static void
573 settings_destroy_notify (gpointer data)
574 {
575   GSList *iter, *modules = data;
576
577   for (iter = modules; iter; iter = iter->next) 
578     {
579       GtkModuleInfo *info = iter->data;
580       gtk_module_info_unref (info);
581     }
582   g_slist_free (modules);
583 }
584
585 void
586 _gtk_modules_settings_changed (GtkSettings *settings, 
587                                const gchar *modules)
588 {
589   GSList *new_modules = NULL;
590
591   GTK_NOTE (MODULES, g_print ("gtk-modules setting changed to: %s\n", modules));
592
593   /* load/ref before unreffing existing */
594   if (modules && modules[0])
595     new_modules = load_modules (modules);
596
597   g_object_set_data_full (G_OBJECT (settings),
598                           I_("gtk-modules"),
599                           new_modules,
600                           settings_destroy_notify);
601 }
602
603 /* Return TRUE if module_to_check causes version conflicts.
604  * If module_to_check is NULL, check the main module.
605  */
606 gboolean
607 _gtk_module_has_mixed_deps (GModule *module_to_check)
608 {
609   GModule *module;
610   gpointer func;
611   gboolean result;
612
613   if (!module_to_check)
614     module = g_module_open (NULL, 0);
615   else
616     module = module_to_check;
617
618   if (g_module_symbol (module, "gtk_progress_get_type", &func))
619     result = TRUE;
620   else
621     result = FALSE;
622
623   if (!module_to_check)
624     g_module_close (module);
625
626   return result;
627 }