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