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