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