File: | capplets/common/cafe-theme-info.c |
Warning: | line 1235, column 12 Potential leak of memory pointed to by 'tuple' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* cafe-theme-info.c - CAFE Theme information | |||
2 | * | |||
3 | * Copyright (C) 2002 Jonathan Blandford <jrb@gnome.org> | |||
4 | * Copyright (C) 2011 Perberos | |||
5 | * All rights reserved. | |||
6 | * | |||
7 | * This file is part of the Cafe Library. | |||
8 | * | |||
9 | * The Cafe Library is free software; you can redistribute it and/or | |||
10 | * modify it under the terms of the GNU Library General Public License as | |||
11 | * published by the Free Software Foundation; either version 2 of the | |||
12 | * License, or (at your option) any later version. | |||
13 | * | |||
14 | * The Cafe Library is distributed in the hope that it will be useful, | |||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
17 | * Library General Public License for more details. | |||
18 | * | |||
19 | * You should have received a copy of the GNU Library General Public | |||
20 | * License along with the Cafe Library; see the file COPYING.LIB. If not, | |||
21 | * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, | |||
22 | * Boston, MA 02110-1301, USA. | |||
23 | */ | |||
24 | ||||
25 | #ifdef HAVE_CONFIG_H1 | |||
26 | #include <config.h> | |||
27 | #endif | |||
28 | ||||
29 | #include <sys/types.h> | |||
30 | #include <sys/stat.h> | |||
31 | #include <dirent.h> | |||
32 | #include <glib/gi18n.h> | |||
33 | #include <gmodule.h> | |||
34 | #include <ctk/ctk.h> | |||
35 | #include <cdk/cdkx.h> | |||
36 | #include <gio/gio.h> | |||
37 | #include <string.h> | |||
38 | #include <libcafe-desktop/cafe-desktop-item.h> | |||
39 | #include "cafe-theme-info.h" | |||
40 | #include "ctkrc-utils.h" | |||
41 | ||||
42 | #include <X11/Xcursor/Xcursor.h> | |||
43 | ||||
44 | #define THEME_NAME"X-GNOME-Metatheme/Name" "X-GNOME-Metatheme/Name" | |||
45 | #define THEME_COMMENT"X-GNOME-Metatheme/Comment" "X-GNOME-Metatheme/Comment" | |||
46 | #define CTK_THEME_KEY"X-GNOME-Metatheme/CtkTheme" "X-GNOME-Metatheme/CtkTheme" | |||
47 | #define CTK_COLOR_SCHEME_KEY"X-GNOME-Metatheme/CtkColorScheme" "X-GNOME-Metatheme/CtkColorScheme" | |||
48 | #define CROMA_THEME_KEY"X-GNOME-Metatheme/MetacityTheme" "X-GNOME-Metatheme/MetacityTheme" | |||
49 | #define ICON_THEME_KEY"X-GNOME-Metatheme/IconTheme" "X-GNOME-Metatheme/IconTheme" | |||
50 | #define CURSOR_THEME_KEY"X-GNOME-Metatheme/CursorTheme" "X-GNOME-Metatheme/CursorTheme" | |||
51 | #define NOTIFICATION_THEME_KEY"X-GNOME-Metatheme/NotificationTheme" "X-GNOME-Metatheme/NotificationTheme" | |||
52 | #define CURSOR_SIZE_KEY"X-GNOME-Metatheme/CursorSize" "X-GNOME-Metatheme/CursorSize" | |||
53 | #define SOUND_THEME_KEY"X-GNOME-Metatheme/SoundTheme" "X-GNOME-Metatheme/SoundTheme" | |||
54 | #define APPLICATION_FONT_KEY"X-GNOME-Metatheme/ApplicationFont" "X-GNOME-Metatheme/ApplicationFont" | |||
55 | #define DOCUMENTS_FONT_KEY"X-GNOME-Metatheme/DocumentsFont" "X-GNOME-Metatheme/DocumentsFont" | |||
56 | #define DESKTOP_FONT_KEY"X-GNOME-Metatheme/DesktopFont" "X-GNOME-Metatheme/DesktopFont" | |||
57 | #define WINDOWTITLE_FONT_KEY"X-GNOME-Metatheme/WindowTitleFont" "X-GNOME-Metatheme/WindowTitleFont" | |||
58 | #define MONOSPACE_FONT_KEY"X-GNOME-Metatheme/MonospaceFont" "X-GNOME-Metatheme/MonospaceFont" | |||
59 | #define BACKGROUND_IMAGE_KEY"X-GNOME-Metatheme/BackgroundImage" "X-GNOME-Metatheme/BackgroundImage" | |||
60 | #define HIDDEN_KEY"X-GNOME-Metatheme/Hidden" "X-GNOME-Metatheme/Hidden" | |||
61 | ||||
62 | /* Terminology used in this lib: | |||
63 | * | |||
64 | * /usr/share/themes, ~/.themes -- top_theme_dir | |||
65 | * top_theme_dir/theme_name/ -- common_theme_dir | |||
66 | * /usr/share/icons, ~/.icons -- top_icon_theme_dir | |||
67 | * top_icon_theme_dir/theme_name/ -- icon_common_theme_dir | |||
68 | * | |||
69 | */ | |||
70 | ||||
71 | typedef struct _ThemeCallbackData { | |||
72 | ThemeChangedCallback func; | |||
73 | gpointer data; | |||
74 | } ThemeCallbackData; | |||
75 | ||||
76 | typedef struct { | |||
77 | GFileMonitor* common_theme_dir_handle; | |||
78 | GFileMonitor* ctk2_dir_handle; | |||
79 | GFileMonitor* keybinding_dir_handle; | |||
80 | GFileMonitor* croma_dir_handle; | |||
81 | gint priority; | |||
82 | } CommonThemeDirMonitorData; | |||
83 | ||||
84 | typedef struct { | |||
85 | GFileMonitor* common_icon_theme_dir_handle; | |||
86 | gint priority; | |||
87 | } CommonIconThemeDirMonitorData; | |||
88 | ||||
89 | typedef struct { | |||
90 | GHashTable* handle_hash; | |||
91 | gint priority; | |||
92 | } CallbackTuple; | |||
93 | ||||
94 | ||||
95 | /* Hash tables */ | |||
96 | ||||
97 | /* The hashes_by_dir are indexed by an escaped uri of the common_theme_dir that | |||
98 | * that particular theme is part of. The data pointed to by them is a | |||
99 | * CafeTheme{Meta,Icon,}Info struct. Note that the uri is of the form | |||
100 | * "file:///home/username/.themes/foo", and not "/home/username/.themes/foo" | |||
101 | */ | |||
102 | ||||
103 | /* The hashes_by_name are hashed by the index of the theme. The data pointed to | |||
104 | * by them is a GList whose data elements are CafeTheme{Meta,Icon,}Info | |||
105 | * structs. This is because a theme can be found both in the users ~/.theme as | |||
106 | * well as globally in $prefix. All access to them must be done via helper | |||
107 | * functions. | |||
108 | */ | |||
109 | static GList* callbacks = NULL((void*)0); | |||
110 | ||||
111 | static GHashTable* meta_theme_hash_by_uri; | |||
112 | static GHashTable* meta_theme_hash_by_name; | |||
113 | static GHashTable* icon_theme_hash_by_uri; | |||
114 | static GHashTable* icon_theme_hash_by_name; | |||
115 | static GHashTable* cursor_theme_hash_by_uri; | |||
116 | static GHashTable* cursor_theme_hash_by_name; | |||
117 | static GHashTable* theme_hash_by_uri; | |||
118 | static GHashTable* theme_hash_by_name; | |||
119 | static gboolean initting = FALSE(0); | |||
120 | ||||
121 | /* private functions */ | |||
122 | static gint safe_strcmp(const gchar* a_str, const gchar* b_str) | |||
123 | { | |||
124 | if (a_str && b_str) | |||
125 | { | |||
126 | return strcmp(a_str, b_str); | |||
127 | } | |||
128 | else | |||
129 | { | |||
130 | return a_str - b_str; | |||
131 | } | |||
132 | } | |||
133 | ||||
134 | static GFileType | |||
135 | get_file_type (GFile *file) | |||
136 | { | |||
137 | GFileType file_type = G_FILE_TYPE_UNKNOWN; | |||
138 | GFileInfo *file_info; | |||
139 | ||||
140 | file_info = g_file_query_info (file, | |||
141 | G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type", | |||
142 | G_FILE_QUERY_INFO_NONE, | |||
143 | NULL((void*)0), NULL((void*)0)); | |||
144 | if (file_info != NULL((void*)0)) { | |||
145 | file_type = g_file_info_get_file_type (file_info); | |||
146 | g_object_unref (file_info); | |||
147 | } | |||
148 | ||||
149 | return file_type; | |||
150 | } | |||
151 | ||||
152 | static void | |||
153 | add_theme_to_hash_by_name (GHashTable *hash_table, | |||
154 | gpointer data) | |||
155 | { | |||
156 | CafeThemeCommonInfo *info = data; | |||
157 | GList *list; | |||
158 | ||||
159 | list = g_hash_table_lookup (hash_table, info->name); | |||
160 | if (list == NULL((void*)0)) { | |||
161 | list = g_list_append (list, info); | |||
162 | } else { | |||
163 | GList *list_ptr = list; | |||
164 | gboolean added = FALSE(0); | |||
165 | ||||
166 | while (list_ptr) { | |||
167 | gint theme_priority; | |||
168 | ||||
169 | theme_priority = ((CafeThemeCommonInfo *) list_ptr->data)->priority; | |||
170 | ||||
171 | if (theme_priority == info->priority) { | |||
172 | /* Swap it in */ | |||
173 | list_ptr->data = info; | |||
174 | added = TRUE(!(0)); | |||
175 | break; | |||
176 | } else if (theme_priority > info->priority) { | |||
177 | list = g_list_insert_before (list, list_ptr, info); | |||
178 | added = TRUE(!(0)); | |||
179 | break; | |||
180 | } | |||
181 | list_ptr = list_ptr->next; | |||
182 | } | |||
183 | if (!added) | |||
184 | list = g_list_append (list, info); | |||
185 | } | |||
186 | g_hash_table_insert (hash_table, g_strdup (info->name)g_strdup_inline (info->name), list); | |||
187 | } | |||
188 | ||||
189 | static void | |||
190 | remove_theme_from_hash_by_name (GHashTable *hash_table, | |||
191 | gpointer data) | |||
192 | { | |||
193 | CafeThemeCommonInfo *info = data; | |||
194 | GList *list; | |||
195 | ||||
196 | list = g_hash_table_lookup (hash_table, info->name); | |||
197 | ||||
198 | list = g_list_remove (list, info); | |||
199 | if (list == NULL((void*)0)) | |||
200 | g_hash_table_remove (hash_table, info->name); | |||
201 | else | |||
202 | g_hash_table_insert (hash_table, g_strdup (info->name)g_strdup_inline (info->name), list); | |||
203 | } | |||
204 | ||||
205 | static CafeThemeCommonInfo * | |||
206 | get_theme_from_hash_by_name (GHashTable *hash_table, | |||
207 | const gchar *name, | |||
208 | gint priority) | |||
209 | { | |||
210 | GList *list; | |||
211 | ||||
212 | list = g_hash_table_lookup (hash_table, name); | |||
213 | ||||
214 | /* -1 implies return the first one */ | |||
215 | if (priority == -1) { | |||
216 | return list ? list->data : NULL((void*)0); | |||
217 | } | |||
218 | ||||
219 | while (list) { | |||
220 | CafeThemeCommonInfo *info = (CafeThemeCommonInfo *) list->data; | |||
221 | ||||
222 | if (info->priority == priority) | |||
223 | return info; | |||
224 | ||||
225 | list = list->next; | |||
226 | } | |||
227 | return NULL((void*)0); | |||
228 | } | |||
229 | ||||
230 | static gint | |||
231 | theme_compare (CafeThemeCommonInfo *a, | |||
232 | CafeThemeCommonInfo *b) | |||
233 | { | |||
234 | gint cmp; | |||
235 | ||||
236 | g_return_val_if_fail (a->type == b->type, a->type - b->type)do { if ((a->type == b->type)) { } else { g_return_if_fail_warning ("capplet-common", ((const char*) (__func__)), "a->type == b->type" ); return (a->type - b->type); } } while (0); | |||
237 | ||||
238 | switch (a->type) { | |||
239 | case CAFE_THEME_TYPE_METATHEME: | |||
240 | cmp = cafe_theme_meta_info_compare ( | |||
241 | (CafeThemeMetaInfo *) a, (CafeThemeMetaInfo *) b); | |||
242 | break; | |||
243 | case CAFE_THEME_TYPE_ICON: | |||
244 | cmp = cafe_theme_icon_info_compare ( | |||
245 | (CafeThemeIconInfo *) a, (CafeThemeIconInfo *) b); | |||
246 | break; | |||
247 | case CAFE_THEME_TYPE_CURSOR: | |||
248 | cmp = cafe_theme_cursor_info_compare ( | |||
249 | (CafeThemeCursorInfo *) a, (CafeThemeCursorInfo *) b); | |||
250 | break; | |||
251 | default: | |||
252 | /* not supported at this time */ | |||
253 | g_assert_not_reached ()do { g_assertion_message_expr ("capplet-common", "cafe-theme-info.c" , 253, ((const char*) (__func__)), ((void*)0)); } while (0); | |||
254 | } | |||
255 | ||||
256 | return cmp; | |||
257 | } | |||
258 | ||||
259 | static void | |||
260 | theme_free (CafeThemeCommonInfo *info) | |||
261 | { | |||
262 | switch (info->type) { | |||
263 | case CAFE_THEME_TYPE_METATHEME: | |||
264 | cafe_theme_meta_info_free ((CafeThemeMetaInfo *) info); | |||
265 | break; | |||
266 | case CAFE_THEME_TYPE_ICON: | |||
267 | cafe_theme_icon_info_free ((CafeThemeIconInfo *) info); | |||
268 | break; | |||
269 | case CAFE_THEME_TYPE_REGULAR: | |||
270 | cafe_theme_info_free ((CafeThemeInfo *) info); | |||
271 | break; | |||
272 | case CAFE_THEME_TYPE_CURSOR: | |||
273 | cafe_theme_cursor_info_free ((CafeThemeCursorInfo *) info); | |||
274 | break; | |||
275 | default: | |||
276 | g_assert_not_reached ()do { g_assertion_message_expr ("capplet-common", "cafe-theme-info.c" , 276, ((const char*) (__func__)), ((void*)0)); } while (0); | |||
277 | } | |||
278 | } | |||
279 | ||||
280 | GQuark cafe_theme_info_error_quark(void) | |||
281 | { | |||
282 | return g_quark_from_static_string("cafe-theme-info-error-quark"); | |||
283 | } | |||
284 | ||||
285 | CafeThemeMetaInfo* cafe_theme_read_meta_theme(GFile* meta_theme_uri) | |||
286 | { | |||
287 | CafeThemeMetaInfo* meta_theme_info; | |||
288 | GFile* common_theme_dir_uri; | |||
289 | CafeDesktopItem* meta_theme_ditem; | |||
290 | gchar* meta_theme_file; | |||
291 | const gchar* str; | |||
292 | gchar* scheme; | |||
293 | ||||
294 | meta_theme_file = g_file_get_uri(meta_theme_uri); | |||
295 | meta_theme_ditem = cafe_desktop_item_new_from_uri(meta_theme_file, 0, NULL((void*)0)); | |||
296 | g_free(meta_theme_file); | |||
297 | ||||
298 | if (meta_theme_ditem == NULL((void*)0)) | |||
299 | return NULL((void*)0); | |||
300 | ||||
301 | common_theme_dir_uri = g_file_get_parent(meta_theme_uri); | |||
302 | meta_theme_info = cafe_theme_meta_info_new(); | |||
303 | meta_theme_info->path = g_file_get_path(meta_theme_uri); | |||
304 | meta_theme_info->name = g_file_get_basename(common_theme_dir_uri); | |||
305 | g_object_unref(common_theme_dir_uri); | |||
306 | ||||
307 | str = cafe_desktop_item_get_localestring(meta_theme_ditem, THEME_NAME"X-GNOME-Metatheme/Name"); | |||
308 | ||||
309 | if (!str) | |||
310 | { | |||
311 | str = cafe_desktop_item_get_localestring(meta_theme_ditem, CAFE_DESKTOP_ITEM_NAME"Name"); | |||
312 | if (!str) | |||
313 | { /* shouldn't reach */ | |||
314 | cafe_theme_meta_info_free(meta_theme_info); | |||
315 | return NULL((void*)0); | |||
316 | } | |||
317 | } | |||
318 | ||||
319 | meta_theme_info->readable_name = g_strdup(str)g_strdup_inline (str); | |||
320 | ||||
321 | str = cafe_desktop_item_get_localestring(meta_theme_ditem, THEME_COMMENT"X-GNOME-Metatheme/Comment"); | |||
322 | ||||
323 | if (str == NULL((void*)0)) | |||
324 | str = cafe_desktop_item_get_localestring(meta_theme_ditem, CAFE_DESKTOP_ITEM_COMMENT"Comment"); | |||
325 | ||||
326 | if (str != NULL((void*)0)) | |||
327 | meta_theme_info->comment = g_strdup(str)g_strdup_inline (str); | |||
328 | ||||
329 | str = cafe_desktop_item_get_string(meta_theme_ditem, CAFE_DESKTOP_ITEM_ICON"Icon"); | |||
330 | ||||
331 | if (str != NULL((void*)0)) | |||
332 | meta_theme_info->icon_file = g_strdup(str)g_strdup_inline (str); | |||
333 | ||||
334 | str = cafe_desktop_item_get_string(meta_theme_ditem, CTK_THEME_KEY"X-GNOME-Metatheme/CtkTheme"); | |||
335 | ||||
336 | if (str == NULL((void*)0)) | |||
337 | { | |||
338 | cafe_theme_meta_info_free(meta_theme_info); | |||
339 | return NULL((void*)0); | |||
340 | } | |||
341 | meta_theme_info->ctk_theme_name = g_strdup(str)g_strdup_inline (str); | |||
342 | ||||
343 | str = cafe_desktop_item_get_string(meta_theme_ditem, CTK_COLOR_SCHEME_KEY"X-GNOME-Metatheme/CtkColorScheme"); | |||
344 | ||||
345 | if (str == NULL((void*)0) || str[0] == '\0') | |||
346 | scheme = ctkrc_get_color_scheme_for_theme(meta_theme_info->ctk_theme_name); | |||
347 | else | |||
348 | scheme = g_strdup(str)g_strdup_inline (str); | |||
349 | ||||
350 | if (scheme != NULL((void*)0)) | |||
351 | { | |||
352 | meta_theme_info->ctk_color_scheme = scheme; | |||
353 | ||||
354 | for (; *scheme != '\0'; scheme++) | |||
355 | if (*scheme == ',') | |||
356 | *scheme = '\n'; | |||
357 | } | |||
358 | ||||
359 | str = cafe_desktop_item_get_string (meta_theme_ditem, CROMA_THEME_KEY"X-GNOME-Metatheme/MetacityTheme"); | |||
360 | ||||
361 | if (str == NULL((void*)0)) | |||
362 | { | |||
363 | cafe_theme_meta_info_free (meta_theme_info); | |||
364 | return NULL((void*)0); | |||
365 | } | |||
366 | ||||
367 | meta_theme_info->croma_theme_name = g_strdup (str)g_strdup_inline (str); | |||
368 | ||||
369 | str = cafe_desktop_item_get_string(meta_theme_ditem, ICON_THEME_KEY"X-GNOME-Metatheme/IconTheme"); | |||
370 | ||||
371 | if (str == NULL((void*)0)) | |||
372 | { | |||
373 | cafe_theme_meta_info_free(meta_theme_info); | |||
374 | return NULL((void*)0); | |||
375 | } | |||
376 | ||||
377 | meta_theme_info->icon_theme_name = g_strdup(str)g_strdup_inline (str); | |||
378 | ||||
379 | str = cafe_desktop_item_get_string(meta_theme_ditem, NOTIFICATION_THEME_KEY"X-GNOME-Metatheme/NotificationTheme"); | |||
380 | ||||
381 | if (str != NULL((void*)0)) | |||
382 | meta_theme_info->notification_theme_name = g_strdup(str)g_strdup_inline (str); | |||
383 | ||||
384 | str = cafe_desktop_item_get_string(meta_theme_ditem, CURSOR_THEME_KEY"X-GNOME-Metatheme/CursorTheme"); | |||
385 | ||||
386 | if (str != NULL((void*)0)) | |||
387 | { | |||
388 | meta_theme_info->cursor_theme_name = g_strdup(str)g_strdup_inline (str); | |||
389 | ||||
390 | str = cafe_desktop_item_get_string(meta_theme_ditem, CURSOR_SIZE_KEY"X-GNOME-Metatheme/CursorSize"); | |||
391 | ||||
392 | if (str) | |||
393 | meta_theme_info->cursor_size = (int) g_ascii_strtoll(str, NULL((void*)0), 10); | |||
394 | else | |||
395 | meta_theme_info->cursor_size = 24; | |||
396 | } | |||
397 | else | |||
398 | { | |||
399 | meta_theme_info->cursor_theme_name = g_strdup("default")g_strdup_inline ("default"); | |||
400 | meta_theme_info->cursor_size = 24; | |||
401 | } | |||
402 | ||||
403 | str = cafe_desktop_item_get_string(meta_theme_ditem, APPLICATION_FONT_KEY"X-GNOME-Metatheme/ApplicationFont"); | |||
404 | ||||
405 | if (str != NULL((void*)0)) | |||
406 | meta_theme_info->application_font = g_strdup(str)g_strdup_inline (str); | |||
407 | ||||
408 | str = cafe_desktop_item_get_string(meta_theme_ditem, DOCUMENTS_FONT_KEY"X-GNOME-Metatheme/DocumentsFont"); | |||
409 | ||||
410 | if (str != NULL((void*)0)) | |||
411 | meta_theme_info->documents_font = g_strdup(str)g_strdup_inline (str); | |||
412 | ||||
413 | str = cafe_desktop_item_get_string(meta_theme_ditem, DESKTOP_FONT_KEY"X-GNOME-Metatheme/DesktopFont"); | |||
414 | ||||
415 | if (str != NULL((void*)0)) | |||
416 | meta_theme_info->desktop_font = g_strdup(str)g_strdup_inline (str); | |||
417 | ||||
418 | str = cafe_desktop_item_get_string(meta_theme_ditem, WINDOWTITLE_FONT_KEY"X-GNOME-Metatheme/WindowTitleFont"); | |||
419 | ||||
420 | if (str != NULL((void*)0)) | |||
421 | meta_theme_info->windowtitle_font = g_strdup(str)g_strdup_inline (str); | |||
422 | ||||
423 | str = cafe_desktop_item_get_string(meta_theme_ditem, MONOSPACE_FONT_KEY"X-GNOME-Metatheme/MonospaceFont"); | |||
424 | ||||
425 | if (str != NULL((void*)0)) | |||
426 | meta_theme_info->monospace_font = g_strdup(str)g_strdup_inline (str); | |||
427 | ||||
428 | str = cafe_desktop_item_get_string(meta_theme_ditem, BACKGROUND_IMAGE_KEY"X-GNOME-Metatheme/BackgroundImage"); | |||
429 | ||||
430 | if (str != NULL((void*)0)) | |||
431 | meta_theme_info->background_image = g_strdup(str)g_strdup_inline (str); | |||
432 | ||||
433 | meta_theme_info->hidden = cafe_desktop_item_get_boolean(meta_theme_ditem, HIDDEN_KEY"X-GNOME-Metatheme/Hidden"); | |||
434 | ||||
435 | cafe_desktop_item_unref(meta_theme_ditem); | |||
436 | ||||
437 | return meta_theme_info; | |||
438 | } | |||
439 | ||||
440 | static CafeThemeIconInfo * | |||
441 | read_icon_theme (GFile *icon_theme_uri) | |||
442 | { | |||
443 | CafeThemeIconInfo *icon_theme_info; | |||
444 | CafeDesktopItem *icon_theme_ditem; | |||
445 | gchar *icon_theme_file; | |||
446 | gchar *dir_name; | |||
447 | const gchar *name; | |||
448 | const gchar *directories; | |||
449 | ||||
450 | icon_theme_file = g_file_get_uri (icon_theme_uri); | |||
451 | icon_theme_ditem = cafe_desktop_item_new_from_uri (icon_theme_file, 0, NULL((void*)0)); | |||
452 | g_free (icon_theme_file); | |||
453 | ||||
454 | if (icon_theme_ditem == NULL((void*)0)) | |||
455 | return NULL((void*)0); | |||
456 | ||||
457 | name = cafe_desktop_item_get_localestring (icon_theme_ditem, "Icon Theme/Name"); | |||
458 | if (!name) { | |||
459 | name = cafe_desktop_item_get_localestring (icon_theme_ditem, CAFE_DESKTOP_ITEM_NAME"Name"); | |||
460 | if (!name) { | |||
461 | cafe_desktop_item_unref (icon_theme_ditem); | |||
462 | return NULL((void*)0); | |||
463 | } | |||
464 | } | |||
465 | ||||
466 | /* If index.theme has no Directories entry, it is only a cursor theme */ | |||
467 | directories = cafe_desktop_item_get_string (icon_theme_ditem, "Icon Theme/Directories"); | |||
468 | if (directories == NULL((void*)0)) { | |||
469 | cafe_desktop_item_unref (icon_theme_ditem); | |||
470 | return NULL((void*)0); | |||
471 | } | |||
472 | ||||
473 | icon_theme_info = cafe_theme_icon_info_new (); | |||
474 | icon_theme_info->readable_name = g_strdup (name)g_strdup_inline (name); | |||
475 | icon_theme_info->path = g_file_get_path (icon_theme_uri); | |||
476 | icon_theme_info->hidden = cafe_desktop_item_get_boolean (icon_theme_ditem, "Icon Theme/Hidden"); | |||
477 | dir_name = g_path_get_dirname (icon_theme_info->path); | |||
478 | icon_theme_info->name = g_path_get_basename (dir_name); | |||
479 | g_free (dir_name); | |||
480 | ||||
481 | cafe_desktop_item_unref (icon_theme_ditem); | |||
482 | ||||
483 | return icon_theme_info; | |||
484 | } | |||
485 | ||||
486 | static void | |||
487 | add_default_cursor_theme () | |||
488 | { | |||
489 | CafeThemeCursorInfo *theme_info; | |||
490 | ||||
491 | theme_info = cafe_theme_cursor_info_new (); | |||
492 | theme_info->path = g_strdup ("builtin")g_strdup_inline ("builtin"); | |||
493 | theme_info->name = g_strdup ("default")g_strdup_inline ("default"); | |||
494 | theme_info->readable_name = g_strdup (_("Default Pointer"))g_strdup_inline (gettext ("Default Pointer")); | |||
495 | theme_info->sizes = g_array_sized_new (FALSE(0), FALSE(0), sizeof (gint), 0); | |||
496 | ||||
497 | g_hash_table_insert (cursor_theme_hash_by_uri, theme_info->path, theme_info); | |||
498 | add_theme_to_hash_by_name (cursor_theme_hash_by_name, theme_info); | |||
499 | } | |||
500 | ||||
501 | static GdkPixbuf * | |||
502 | gdk_pixbuf_from_xcursor_image (XcursorImage *cursor) | |||
503 | { | |||
504 | GdkPixbuf *pixbuf; | |||
505 | #define BUF_SIZEsizeof(guint32) * cursor->width * cursor->height sizeof(guint32) * cursor->width * cursor->height | |||
506 | guchar *buf = g_malloc0 (BUF_SIZEsizeof(guint32) * cursor->width * cursor->height); | |||
507 | guchar *it; | |||
508 | ||||
509 | for (it = buf; it < (buf + BUF_SIZEsizeof(guint32) * cursor->width * cursor->height); it += 4) { | |||
510 | #if G_BYTE_ORDER1234 == G_LITTLE_ENDIAN1234 | |||
511 | /* on little endianess it's BGRA to RGBA */ | |||
512 | it[0] = ((guchar *) (cursor->pixels))[it - buf + 2]; | |||
513 | it[1] = ((guchar *) (cursor->pixels))[it - buf + 1]; | |||
514 | it[2] = ((guchar *) (cursor->pixels))[it - buf + 0]; | |||
515 | it[3] = ((guchar *) (cursor->pixels))[it - buf + 3]; | |||
516 | #else | |||
517 | /* on big endianess it's ARGB to RGBA */ | |||
518 | it[0] = ((guchar *) cursor->pixels)[it - buf + 1]; | |||
519 | it[1] = ((guchar *) cursor->pixels)[it - buf + 2]; | |||
520 | it[2] = ((guchar *) cursor->pixels)[it - buf + 3]; | |||
521 | it[3] = ((guchar *) cursor->pixels)[it - buf + 0]; | |||
522 | #endif | |||
523 | } | |||
524 | ||||
525 | pixbuf = gdk_pixbuf_new_from_data ((const guchar *) buf, | |||
526 | GDK_COLORSPACE_RGB, TRUE(!(0)), 8, | |||
527 | cursor->width, cursor->height, | |||
528 | cursor->width * 4, | |||
529 | (GdkPixbufDestroyNotify) g_free, | |||
530 | NULL((void*)0)); | |||
531 | ||||
532 | if (!pixbuf) | |||
533 | g_free (buf); | |||
534 | ||||
535 | return pixbuf; | |||
536 | } | |||
537 | ||||
538 | static CafeThemeCursorInfo * | |||
539 | read_cursor_theme (GFile *cursor_theme_uri) | |||
540 | { | |||
541 | CafeThemeCursorInfo *cursor_theme_info = NULL((void*)0); | |||
542 | GFile *parent_uri, *cursors_uri; | |||
543 | ||||
544 | const gint filter_sizes[] = { 12, 16, 18, 24, 32, 36, 40, 48, 64, 96, 128 }; | |||
545 | const gint num_sizes = G_N_ELEMENTS (filter_sizes)(sizeof (filter_sizes) / sizeof ((filter_sizes)[0])); | |||
546 | ||||
547 | parent_uri = g_file_get_parent (cursor_theme_uri); | |||
548 | cursors_uri = g_file_get_child (parent_uri, "cursors"); | |||
549 | ||||
550 | if (get_file_type (cursors_uri) == G_FILE_TYPE_DIRECTORY) { | |||
551 | GArray *sizes; | |||
552 | XcursorImage *cursor; | |||
553 | GdkPixbuf *thumbnail = NULL((void*)0); | |||
554 | gchar *name; | |||
555 | gint i; | |||
556 | ||||
557 | name = g_file_get_basename (parent_uri); | |||
558 | ||||
559 | sizes = g_array_sized_new (FALSE(0), FALSE(0), sizeof (gint), num_sizes); | |||
560 | ||||
561 | for (i = 0; i < num_sizes; ++i) { | |||
562 | cursor = XcursorLibraryLoadImage ("left_ptr", name, filter_sizes[i]); | |||
563 | ||||
564 | if (cursor) { | |||
565 | if (cursor->size == filter_sizes[i]) { | |||
566 | g_array_append_val (sizes, filter_sizes[i])g_array_append_vals (sizes, &(filter_sizes[i]), 1); | |||
567 | ||||
568 | if (thumbnail == NULL((void*)0) && i >= 1) | |||
569 | thumbnail = gdk_pixbuf_from_xcursor_image (cursor); | |||
570 | } | |||
571 | ||||
572 | XcursorImageDestroy (cursor); | |||
573 | } | |||
574 | } | |||
575 | ||||
576 | if (sizes->len == 0) { | |||
577 | g_array_free (sizes, TRUE(!(0))); | |||
578 | g_free (name); | |||
579 | } else { | |||
580 | CafeDesktopItem *cursor_theme_ditem; | |||
581 | gchar *cursor_theme_file; | |||
582 | ||||
583 | if (!thumbnail) { | |||
584 | cursor = XcursorLibraryLoadImage ("left_ptr", name, | |||
585 | g_array_index (sizes, gint, 0)(((gint*) (void *) (sizes)->data) [(0)])); | |||
586 | if (cursor) { | |||
587 | thumbnail = gdk_pixbuf_from_xcursor_image (cursor); | |||
588 | XcursorImageDestroy (cursor); | |||
589 | } | |||
590 | } | |||
591 | ||||
592 | cursor_theme_info = cafe_theme_cursor_info_new (); | |||
593 | cursor_theme_info->path = g_file_get_path (parent_uri); | |||
594 | cursor_theme_info->name = name; | |||
595 | cursor_theme_info->sizes = sizes; | |||
596 | cursor_theme_info->thumbnail = thumbnail; | |||
597 | ||||
598 | cursor_theme_file = g_file_get_path (cursor_theme_uri); | |||
599 | cursor_theme_ditem = cafe_desktop_item_new_from_file (cursor_theme_file, 0, NULL((void*)0)); | |||
600 | g_free (cursor_theme_file); | |||
601 | ||||
602 | if (cursor_theme_ditem != NULL((void*)0)) { | |||
603 | const gchar *readable_name; | |||
604 | ||||
605 | readable_name = cafe_desktop_item_get_string (cursor_theme_ditem, | |||
606 | "Icon Theme/Name"); | |||
607 | if (readable_name) | |||
608 | cursor_theme_info->readable_name = g_strdup (readable_name)g_strdup_inline (readable_name); | |||
609 | else | |||
610 | cursor_theme_info->readable_name = g_strdup (name)g_strdup_inline (name); | |||
611 | ||||
612 | cursor_theme_info->hidden = cafe_desktop_item_get_boolean (cursor_theme_ditem, | |||
613 | "Icon Theme/Hidden"); | |||
614 | ||||
615 | cafe_desktop_item_unref (cursor_theme_ditem); | |||
616 | } else { | |||
617 | cursor_theme_info->readable_name = g_strdup (name)g_strdup_inline (name); | |||
618 | } | |||
619 | } | |||
620 | } | |||
621 | ||||
622 | g_object_unref (cursors_uri); | |||
623 | g_object_unref (parent_uri); | |||
624 | ||||
625 | return cursor_theme_info; | |||
626 | } | |||
627 | ||||
628 | static void | |||
629 | handle_change_signal (gpointer data, | |||
630 | CafeThemeChangeType change_type, | |||
631 | CafeThemeElement element_type) | |||
632 | { | |||
633 | #ifdef DEBUG | |||
634 | gchar *type_str = NULL((void*)0); | |||
635 | gchar *change_str = NULL((void*)0); | |||
636 | gchar *element_str = NULL((void*)0); | |||
637 | #endif | |||
638 | CafeThemeCommonInfo *theme = data; | |||
639 | GList *list; | |||
640 | ||||
641 | if (initting) | |||
642 | return; | |||
643 | ||||
644 | for (list = callbacks; list; list = list->next) { | |||
645 | ThemeCallbackData *callback_data = list->data; | |||
646 | (* callback_data->func) (theme, change_type, element_type, callback_data->data); | |||
647 | } | |||
648 | ||||
649 | #ifdef DEBUG | |||
650 | if (theme->type == CAFE_THEME_TYPE_METATHEME) | |||
651 | type_str = "meta"; | |||
652 | else if (theme->type == CAFE_THEME_TYPE_ICON) | |||
653 | type_str = "icon"; | |||
654 | else if (theme->type == CAFE_THEME_TYPE_CURSOR) | |||
655 | type_str = "cursor"; | |||
656 | else if (theme->type == CAFE_THEME_TYPE_REGULAR) { | |||
657 | if (element_type & CAFE_THEME_CTK_2) | |||
658 | element_str = "ctk-2"; | |||
659 | else if (element_type & CAFE_THEME_CTK_2_KEYBINDING) | |||
660 | element_str = "keybinding"; | |||
661 | else if (element_type & CAFE_THEME_CROMA) | |||
662 | element_str = "croma"; | |||
663 | } | |||
664 | ||||
665 | if (change_type == CAFE_THEME_CHANGE_CREATED) | |||
666 | change_str = "created"; | |||
667 | else if (change_type == CAFE_THEME_CHANGE_CHANGED) | |||
668 | change_str = "changed"; | |||
669 | else if (change_type == CAFE_THEME_CHANGE_DELETED) | |||
670 | change_str = "deleted"; | |||
671 | ||||
672 | if (type == CAFE_THEME_TYPE_REGULAR) { | |||
673 | g_print ("theme \"%s\" has a theme of type %s (priority %d) has been %s\n", | |||
674 | theme->name, | |||
675 | element_str, | |||
676 | theme->priority, | |||
677 | type_str); | |||
678 | } else if (type_str != NULL((void*)0)) { | |||
679 | g_print ("%s theme \"%s\" (priority %d) has been %s\n", | |||
680 | type_str, | |||
681 | theme->name, | |||
682 | theme->priority, | |||
683 | type_str); | |||
684 | } | |||
685 | #endif | |||
686 | } | |||
687 | ||||
688 | /* index_uri should point to the ctkrc file that was modified */ | |||
689 | static void | |||
690 | update_theme_index (GFile *index_uri, | |||
691 | CafeThemeElement key_element, | |||
692 | gint priority) | |||
693 | { | |||
694 | gboolean theme_exists; | |||
695 | CafeThemeInfo *theme_info; | |||
696 | GFile *parent; | |||
697 | GFile *common_theme_dir_uri; | |||
698 | gchar *common_theme_dir; | |||
699 | ||||
700 | /* First, we determine the new state of the file. We do no more | |||
701 | * sophisticated a test than "files exists and is a file" */ | |||
702 | theme_exists = (get_file_type (index_uri) == G_FILE_TYPE_REGULAR); | |||
703 | ||||
704 | /* Next, we see what currently exists */ | |||
705 | parent = g_file_get_parent (index_uri); | |||
706 | common_theme_dir_uri = g_file_get_parent (parent); | |||
707 | common_theme_dir = g_file_get_path (common_theme_dir_uri); | |||
708 | ||||
709 | theme_info = g_hash_table_lookup (theme_hash_by_uri, common_theme_dir); | |||
710 | if (theme_info == NULL((void*)0)) { | |||
711 | if (theme_exists) { | |||
712 | theme_info = cafe_theme_info_new (); | |||
713 | theme_info->path = g_strdup (common_theme_dir)g_strdup_inline (common_theme_dir); | |||
714 | theme_info->name = g_file_get_basename (common_theme_dir_uri); | |||
715 | theme_info->readable_name = g_strdup (theme_info->name)g_strdup_inline (theme_info->name); | |||
716 | theme_info->priority = priority; | |||
717 | if (key_element & CAFE_THEME_CTK_2) | |||
718 | theme_info->has_ctk = TRUE(!(0)); | |||
719 | else if (key_element & CAFE_THEME_CTK_2_KEYBINDING) | |||
720 | theme_info->has_keybinding = TRUE(!(0)); | |||
721 | else if (key_element & CAFE_THEME_CROMA) | |||
722 | theme_info->has_croma = TRUE(!(0)); | |||
723 | ||||
724 | g_hash_table_insert (theme_hash_by_uri, g_strdup (common_theme_dir)g_strdup_inline (common_theme_dir), theme_info); | |||
725 | add_theme_to_hash_by_name (theme_hash_by_name, theme_info); | |||
726 | handle_change_signal (theme_info, CAFE_THEME_CHANGE_CREATED, key_element); | |||
727 | } | |||
728 | } else { | |||
729 | gboolean theme_used_to_exist = FALSE(0); | |||
730 | ||||
731 | if (key_element & CAFE_THEME_CTK_2) { | |||
732 | theme_used_to_exist = theme_info->has_ctk; | |||
733 | theme_info->has_ctk = theme_exists; | |||
734 | } else if (key_element & CAFE_THEME_CTK_2_KEYBINDING) { | |||
735 | theme_used_to_exist = theme_info->has_keybinding; | |||
736 | theme_info->has_keybinding = theme_exists; | |||
737 | } else if (key_element & CAFE_THEME_CROMA) { | |||
738 | theme_used_to_exist = theme_info->has_croma; | |||
739 | theme_info->has_croma = theme_exists; | |||
740 | } | |||
741 | ||||
742 | if (!theme_info->has_croma && !theme_info->has_keybinding && !theme_info->has_ctk) { | |||
743 | g_hash_table_remove (theme_hash_by_uri, common_theme_dir); | |||
744 | remove_theme_from_hash_by_name (theme_hash_by_name, theme_info); | |||
745 | } | |||
746 | ||||
747 | if (theme_exists && theme_used_to_exist) { | |||
748 | handle_change_signal (theme_info, CAFE_THEME_CHANGE_CHANGED, key_element); | |||
749 | } else if (theme_exists && !theme_used_to_exist) { | |||
750 | handle_change_signal (theme_info, CAFE_THEME_CHANGE_CREATED, key_element); | |||
751 | } else if (!theme_exists && theme_used_to_exist) { | |||
752 | handle_change_signal (theme_info, CAFE_THEME_CHANGE_DELETED, key_element); | |||
753 | } | |||
754 | ||||
755 | if (!theme_info->has_croma && !theme_info->has_keybinding && !theme_info->has_ctk) { | |||
756 | cafe_theme_info_free (theme_info); | |||
757 | } | |||
758 | } | |||
759 | ||||
760 | g_free (common_theme_dir); | |||
761 | g_object_unref (parent); | |||
762 | g_object_unref (common_theme_dir_uri); | |||
763 | } | |||
764 | ||||
765 | static void | |||
766 | update_ctk2_index (GFile *ctk2_index_uri, | |||
767 | gint priority) | |||
768 | { | |||
769 | update_theme_index (ctk2_index_uri, CAFE_THEME_CTK_2, priority); | |||
770 | } | |||
771 | ||||
772 | static void | |||
773 | update_keybinding_index (GFile *keybinding_index_uri, | |||
774 | gint priority) | |||
775 | { | |||
776 | update_theme_index (keybinding_index_uri, CAFE_THEME_CTK_2_KEYBINDING, priority); | |||
777 | } | |||
778 | ||||
779 | static void | |||
780 | update_croma_index (GFile *croma_index_uri, | |||
781 | gint priority) | |||
782 | { | |||
783 | update_theme_index (croma_index_uri, CAFE_THEME_CROMA, priority); | |||
784 | } | |||
785 | ||||
786 | static void | |||
787 | update_common_theme_dir_index (GFile *theme_index_uri, | |||
788 | CafeThemeType type, | |||
789 | gint priority) | |||
790 | { | |||
791 | gboolean theme_exists; | |||
792 | CafeThemeCommonInfo *theme_info = NULL((void*)0); | |||
793 | CafeThemeCommonInfo *old_theme_info; | |||
794 | GFile *common_theme_dir_uri; | |||
795 | gchar *common_theme_dir; | |||
796 | GHashTable *hash_by_uri; | |||
797 | GHashTable *hash_by_name; | |||
798 | ||||
799 | if (type == CAFE_THEME_TYPE_ICON) { | |||
800 | hash_by_uri = icon_theme_hash_by_uri; | |||
801 | hash_by_name = icon_theme_hash_by_name; | |||
802 | } else if (type == CAFE_THEME_TYPE_CURSOR) { | |||
803 | hash_by_uri = cursor_theme_hash_by_uri; | |||
804 | hash_by_name = cursor_theme_hash_by_name; | |||
805 | } else { | |||
806 | hash_by_uri = meta_theme_hash_by_uri; | |||
807 | hash_by_name = meta_theme_hash_by_name; | |||
808 | } | |||
809 | ||||
810 | if (type != CAFE_THEME_TYPE_CURSOR) { | |||
811 | /* First, we determine the new state of the file. */ | |||
812 | if (get_file_type (theme_index_uri) == G_FILE_TYPE_REGULAR) { | |||
813 | /* It's an interesting file. Let's try to load it. */ | |||
814 | if (type == CAFE_THEME_TYPE_ICON) | |||
815 | theme_info = (CafeThemeCommonInfo *) read_icon_theme (theme_index_uri); | |||
816 | else | |||
817 | theme_info = (CafeThemeCommonInfo *) cafe_theme_read_meta_theme (theme_index_uri); | |||
818 | } else { | |||
819 | theme_info = NULL((void*)0); | |||
820 | } | |||
821 | ||||
822 | } | |||
823 | /* cursor themes don't necessarily have an index file, so try those in any case */ | |||
824 | else { | |||
825 | theme_info = (CafeThemeCommonInfo *) read_cursor_theme (theme_index_uri); | |||
826 | } | |||
827 | ||||
828 | if (theme_info) { | |||
829 | theme_info->priority = priority; | |||
830 | theme_exists = TRUE(!(0)); | |||
831 | } else { | |||
832 | theme_exists = FALSE(0); | |||
833 | } | |||
834 | ||||
835 | /* Next, we see what currently exists */ | |||
836 | common_theme_dir_uri = g_file_get_parent (theme_index_uri); | |||
837 | common_theme_dir = g_file_get_path (common_theme_dir_uri); | |||
838 | g_object_unref (common_theme_dir_uri); | |||
839 | ||||
840 | old_theme_info = (CafeThemeCommonInfo *) g_hash_table_lookup (hash_by_uri, common_theme_dir); | |||
841 | ||||
842 | if (old_theme_info == NULL((void*)0)) { | |||
843 | if (theme_exists) { | |||
844 | g_hash_table_insert (hash_by_uri, g_strdup (common_theme_dir)g_strdup_inline (common_theme_dir), theme_info); | |||
845 | add_theme_to_hash_by_name (hash_by_name, theme_info); | |||
846 | handle_change_signal (theme_info, CAFE_THEME_CHANGE_CREATED, 0); | |||
847 | } | |||
848 | } else { | |||
849 | if (theme_exists) { | |||
850 | if (theme_compare (theme_info, old_theme_info) != 0) { | |||
851 | /* Remove old theme */ | |||
852 | g_hash_table_remove (hash_by_uri, common_theme_dir); | |||
853 | remove_theme_from_hash_by_name (hash_by_name, old_theme_info); | |||
854 | g_hash_table_insert (hash_by_uri, g_strdup (common_theme_dir)g_strdup_inline (common_theme_dir), theme_info); | |||
855 | add_theme_to_hash_by_name (hash_by_name, theme_info); | |||
856 | handle_change_signal (theme_info, CAFE_THEME_CHANGE_CHANGED, 0); | |||
857 | theme_free (old_theme_info); | |||
858 | } else { | |||
859 | theme_free (theme_info); | |||
860 | } | |||
861 | } else { | |||
862 | g_hash_table_remove (hash_by_uri, common_theme_dir); | |||
863 | remove_theme_from_hash_by_name (hash_by_name, old_theme_info); | |||
864 | ||||
865 | handle_change_signal (old_theme_info, CAFE_THEME_CHANGE_DELETED, 0); | |||
866 | theme_free (old_theme_info); | |||
867 | } | |||
868 | } | |||
869 | ||||
870 | g_free (common_theme_dir); | |||
871 | } | |||
872 | ||||
873 | static void | |||
874 | update_meta_theme_index (GFile *meta_theme_index_uri, | |||
875 | gint priority) | |||
876 | { | |||
877 | update_common_theme_dir_index (meta_theme_index_uri, CAFE_THEME_TYPE_METATHEME, priority); | |||
878 | } | |||
879 | ||||
880 | static void | |||
881 | update_icon_theme_index (GFile *icon_theme_index_uri, | |||
882 | gint priority) | |||
883 | { | |||
884 | update_common_theme_dir_index (icon_theme_index_uri, CAFE_THEME_TYPE_ICON, priority); | |||
885 | } | |||
886 | ||||
887 | static void | |||
888 | update_cursor_theme_index (GFile *cursor_theme_index_uri, | |||
889 | gint priority) | |||
890 | { | |||
891 | update_common_theme_dir_index (cursor_theme_index_uri, CAFE_THEME_TYPE_CURSOR, priority); | |||
892 | } | |||
893 | ||||
894 | static void | |||
895 | ctk2_dir_changed (GFileMonitor *monitor, | |||
896 | GFile *file, | |||
897 | GFile *other_file, | |||
898 | GFileMonitorEvent event_type, | |||
899 | CommonThemeDirMonitorData *monitor_data) | |||
900 | { | |||
901 | gchar *affected_file; | |||
902 | ||||
903 | affected_file = g_file_get_basename (file); | |||
904 | ||||
905 | /* The only file we care about is ctkrc */ | |||
906 | if (!strcmp (affected_file, "ctkrc")) { | |||
907 | update_ctk2_index (file, monitor_data->priority); | |||
908 | } | |||
909 | ||||
910 | g_free (affected_file); | |||
911 | } | |||
912 | ||||
913 | static void | |||
914 | keybinding_dir_changed (GFileMonitor *monitor, | |||
915 | GFile *file, | |||
916 | GFile *other_file, | |||
917 | GFileMonitorEvent event_type, | |||
918 | CommonThemeDirMonitorData *monitor_data) | |||
919 | { | |||
920 | gchar *affected_file; | |||
921 | ||||
922 | affected_file = g_file_get_basename (file); | |||
923 | ||||
924 | /* The only file we care about is ctkrc */ | |||
925 | if (!strcmp (affected_file, "ctkrc")) { | |||
926 | update_keybinding_index (file, monitor_data->priority); | |||
927 | } | |||
928 | ||||
929 | g_free (affected_file); | |||
930 | } | |||
931 | ||||
932 | static void | |||
933 | croma_dir_changed (GFileMonitor *monitor, | |||
934 | GFile *file, | |||
935 | GFile *other_file, | |||
936 | GFileMonitorEvent event_type, | |||
937 | CommonThemeDirMonitorData *monitor_data) | |||
938 | { | |||
939 | gchar *affected_file; | |||
940 | ||||
941 | affected_file = g_file_get_basename (file); | |||
942 | ||||
943 | /* The only file we care about is metacity-theme-(1|2).xml */ | |||
944 | if (!strcmp (affected_file, "metacity-theme-1.xml") || !strcmp (affected_file, "metacity-theme-2.xml")) { | |||
945 | update_croma_index (file, monitor_data->priority); | |||
946 | } | |||
947 | ||||
948 | g_free (affected_file); | |||
949 | } | |||
950 | ||||
951 | static void | |||
952 | common_theme_dir_changed (GFileMonitor *monitor, | |||
953 | GFile *file, | |||
954 | GFile *other_file, | |||
955 | GFileMonitorEvent event_type, | |||
956 | CommonThemeDirMonitorData *monitor_data) | |||
957 | { | |||
958 | gchar *affected_file; | |||
959 | ||||
960 | affected_file = g_file_get_basename (file); | |||
961 | ||||
962 | /* The only file we care about is index.theme */ | |||
963 | if (!strcmp (affected_file, "index.theme")) { | |||
964 | update_meta_theme_index (file, monitor_data->priority); | |||
965 | } | |||
966 | ||||
967 | g_free (affected_file); | |||
968 | } | |||
969 | ||||
970 | static void | |||
971 | common_icon_theme_dir_changed (GFileMonitor *monitor, | |||
972 | GFile *file, | |||
973 | GFile *other_file, | |||
974 | GFileMonitorEvent event_type, | |||
975 | CommonIconThemeDirMonitorData *monitor_data) | |||
976 | { | |||
977 | gchar *affected_file; | |||
978 | ||||
979 | affected_file = g_file_get_basename (file); | |||
980 | ||||
981 | /* The only file we care about is index.theme */ | |||
982 | if (!strcmp (affected_file, "index.theme")) { | |||
983 | update_icon_theme_index (file, monitor_data->priority); | |||
984 | update_cursor_theme_index (file, monitor_data->priority); | |||
985 | } | |||
986 | /* and the cursors subdir for cursor themes */ | |||
987 | else if (!strcmp (affected_file, "cursors")) { | |||
988 | /* always call update_cursor_theme_index with the index.theme URI */ | |||
989 | GFile *parent, *index; | |||
990 | ||||
991 | parent = g_file_get_parent (file); | |||
992 | index = g_file_get_child (parent, "index.theme"); | |||
993 | g_object_unref (parent); | |||
994 | ||||
995 | update_cursor_theme_index (index, monitor_data->priority); | |||
996 | ||||
997 | g_object_unref (index); | |||
998 | } | |||
999 | ||||
1000 | g_free (affected_file); | |||
1001 | } | |||
1002 | ||||
1003 | /* Add a monitor to a common_theme_dir. */ | |||
1004 | static gboolean | |||
1005 | add_common_theme_dir_monitor (GFile *theme_dir_uri, | |||
1006 | CommonThemeDirMonitorData *monitor_data, | |||
1007 | GError **error) | |||
1008 | { | |||
1009 | GFile *uri, *subdir; | |||
1010 | GFileMonitor *monitor; | |||
1011 | ||||
1012 | uri = g_file_get_child (theme_dir_uri, "index.theme"); | |||
1013 | update_meta_theme_index (uri, monitor_data->priority); | |||
1014 | g_object_unref (uri); | |||
1015 | ||||
1016 | /* Add the handle for this directory */ | |||
1017 | monitor = g_file_monitor_file (theme_dir_uri, G_FILE_MONITOR_NONE, NULL((void*)0), NULL((void*)0)); | |||
1018 | if (monitor == NULL((void*)0)) | |||
1019 | return FALSE(0); | |||
1020 | ||||
1021 | g_signal_connect (monitor, "changed",g_signal_connect_data ((monitor), ("changed"), ((GCallback) common_theme_dir_changed ), (monitor_data), ((void*)0), (GConnectFlags) 0) | |||
1022 | (GCallback) common_theme_dir_changed, monitor_data)g_signal_connect_data ((monitor), ("changed"), ((GCallback) common_theme_dir_changed ), (monitor_data), ((void*)0), (GConnectFlags) 0); | |||
1023 | ||||
1024 | monitor_data->common_theme_dir_handle = monitor; | |||
1025 | ||||
1026 | ||||
1027 | /* ctk-2 theme subdir */ | |||
1028 | subdir = g_file_get_child (theme_dir_uri, "ctk-2.0"); | |||
1029 | uri = g_file_get_child (subdir, "ctkrc"); | |||
1030 | if (g_file_query_exists (uri, NULL((void*)0))) { | |||
1031 | update_ctk2_index (uri, monitor_data->priority); | |||
1032 | } | |||
1033 | g_object_unref (uri); | |||
1034 | ||||
1035 | monitor = g_file_monitor_directory (subdir, G_FILE_MONITOR_NONE, NULL((void*)0), NULL((void*)0)); | |||
1036 | if (monitor != NULL((void*)0)) { | |||
1037 | g_signal_connect (monitor, "changed",g_signal_connect_data ((monitor), ("changed"), ((GCallback) ctk2_dir_changed ), (monitor_data), ((void*)0), (GConnectFlags) 0) | |||
1038 | (GCallback) ctk2_dir_changed, monitor_data)g_signal_connect_data ((monitor), ("changed"), ((GCallback) ctk2_dir_changed ), (monitor_data), ((void*)0), (GConnectFlags) 0); | |||
1039 | } | |||
1040 | monitor_data->ctk2_dir_handle = monitor; | |||
1041 | g_object_unref (subdir); | |||
1042 | ||||
1043 | /* keybinding theme subdir */ | |||
1044 | subdir = g_file_get_child (theme_dir_uri, "ctk-2.0-key"); | |||
1045 | uri = g_file_get_child (subdir, "ctkrc"); | |||
1046 | if (g_file_query_exists (uri, NULL((void*)0))) { | |||
1047 | update_keybinding_index (uri, monitor_data->priority); | |||
1048 | } | |||
1049 | g_object_unref (uri); | |||
1050 | ||||
1051 | monitor = g_file_monitor_directory (subdir, G_FILE_MONITOR_NONE, NULL((void*)0), NULL((void*)0)); | |||
1052 | if (monitor != NULL((void*)0)) { | |||
1053 | g_signal_connect (monitor, "changed",g_signal_connect_data ((monitor), ("changed"), ((GCallback) keybinding_dir_changed ), (monitor_data), ((void*)0), (GConnectFlags) 0) | |||
1054 | (GCallback) keybinding_dir_changed, monitor_data)g_signal_connect_data ((monitor), ("changed"), ((GCallback) keybinding_dir_changed ), (monitor_data), ((void*)0), (GConnectFlags) 0); | |||
1055 | } | |||
1056 | monitor_data->keybinding_dir_handle = monitor; | |||
1057 | g_object_unref (subdir); | |||
1058 | ||||
1059 | /* croma theme subdir */ | |||
1060 | subdir = g_file_get_child (theme_dir_uri, "metacity-1"); | |||
1061 | uri = g_file_get_child (subdir, "metacity-theme-2.xml"); | |||
1062 | if (g_file_query_exists (uri, NULL((void*)0))) { | |||
1063 | update_croma_index (uri, monitor_data->priority); | |||
1064 | } | |||
1065 | else { | |||
1066 | g_object_unref (uri); | |||
1067 | uri = g_file_get_child (subdir, "metacity-theme-1.xml"); | |||
1068 | if (g_file_query_exists (uri, NULL((void*)0))) { | |||
1069 | update_croma_index (uri, monitor_data->priority); | |||
1070 | } | |||
1071 | } | |||
1072 | g_object_unref (uri); | |||
1073 | ||||
1074 | monitor = g_file_monitor_directory (subdir, G_FILE_MONITOR_NONE, NULL((void*)0), NULL((void*)0)); | |||
1075 | if (monitor != NULL((void*)0)) { | |||
1076 | g_signal_connect (monitor, "changed",g_signal_connect_data ((monitor), ("changed"), ((GCallback) croma_dir_changed ), (monitor_data), ((void*)0), (GConnectFlags) 0) | |||
1077 | (GCallback) croma_dir_changed, monitor_data)g_signal_connect_data ((monitor), ("changed"), ((GCallback) croma_dir_changed ), (monitor_data), ((void*)0), (GConnectFlags) 0); | |||
1078 | } | |||
1079 | monitor_data->croma_dir_handle = monitor; | |||
1080 | g_object_unref (subdir); | |||
1081 | ||||
1082 | return TRUE(!(0)); | |||
1083 | } | |||
1084 | ||||
1085 | static gboolean | |||
1086 | add_common_icon_theme_dir_monitor (GFile *theme_dir_uri, | |||
1087 | CommonIconThemeDirMonitorData *monitor_data, | |||
1088 | GError **error) | |||
1089 | { | |||
1090 | GFile *index_uri; | |||
1091 | GFileMonitor *monitor; | |||
1092 | ||||
1093 | /* Add the handle for this directory */ | |||
1094 | index_uri = g_file_get_child (theme_dir_uri, "index.theme"); | |||
1095 | update_icon_theme_index (index_uri, monitor_data->priority); | |||
1096 | update_cursor_theme_index (index_uri, monitor_data->priority); | |||
1097 | g_object_unref (index_uri); | |||
1098 | ||||
1099 | monitor = g_file_monitor_file (theme_dir_uri, G_FILE_MONITOR_NONE, NULL((void*)0), NULL((void*)0)); | |||
1100 | if (monitor == NULL((void*)0)) | |||
1101 | return FALSE(0); | |||
1102 | ||||
1103 | g_signal_connect (monitor, "changed",g_signal_connect_data ((monitor), ("changed"), ((GCallback) common_icon_theme_dir_changed ), (monitor_data), ((void*)0), (GConnectFlags) 0) | |||
1104 | (GCallback) common_icon_theme_dir_changed, monitor_data)g_signal_connect_data ((monitor), ("changed"), ((GCallback) common_icon_theme_dir_changed ), (monitor_data), ((void*)0), (GConnectFlags) 0); | |||
1105 | ||||
1106 | monitor_data->common_icon_theme_dir_handle = monitor; | |||
1107 | return TRUE(!(0)); | |||
1108 | } | |||
1109 | ||||
1110 | static void | |||
1111 | remove_common_theme_dir_monitor (CommonThemeDirMonitorData *monitor_data) | |||
1112 | { | |||
1113 | g_file_monitor_cancel (monitor_data->common_theme_dir_handle); | |||
1114 | g_file_monitor_cancel (monitor_data->ctk2_dir_handle); | |||
1115 | g_file_monitor_cancel (monitor_data->keybinding_dir_handle); | |||
1116 | g_file_monitor_cancel (monitor_data->croma_dir_handle); | |||
1117 | } | |||
1118 | ||||
1119 | static void | |||
1120 | remove_common_icon_theme_dir_monitor (CommonIconThemeDirMonitorData *monitor_data) | |||
1121 | { | |||
1122 | g_file_monitor_cancel (monitor_data->common_icon_theme_dir_handle); | |||
1123 | } | |||
1124 | ||||
1125 | static void | |||
1126 | top_theme_dir_changed (GFileMonitor *monitor, | |||
1127 | GFile *file, | |||
1128 | GFile *other_file, | |||
1129 | GFileMonitorEvent event_type, | |||
1130 | CallbackTuple *tuple) | |||
1131 | { | |||
1132 | GHashTable *handle_hash; | |||
1133 | CommonThemeDirMonitorData *monitor_data; | |||
1134 | gint priority; | |||
1135 | ||||
1136 | handle_hash = tuple->handle_hash; | |||
1137 | priority = tuple->priority; | |||
1138 | ||||
1139 | if (event_type == G_FILE_MONITOR_EVENT_CREATED) { | |||
1140 | if (get_file_type (file) == G_FILE_TYPE_DIRECTORY) { | |||
1141 | monitor_data = g_new0 (CommonThemeDirMonitorData, 1)((CommonThemeDirMonitorData *) g_malloc0_n ((1), sizeof (CommonThemeDirMonitorData ))); | |||
1142 | monitor_data->priority = priority; | |||
1143 | add_common_theme_dir_monitor (file, monitor_data, NULL((void*)0)); | |||
1144 | g_hash_table_insert (handle_hash, g_file_get_basename (file), monitor_data); | |||
1145 | } | |||
1146 | ||||
1147 | } else if (event_type == G_FILE_MONITOR_EVENT_DELETED) { | |||
1148 | gchar *name; | |||
1149 | ||||
1150 | name = g_file_get_basename (file); | |||
1151 | monitor_data = g_hash_table_lookup (handle_hash, name); | |||
1152 | if (monitor_data != NULL((void*)0)) { | |||
1153 | remove_common_theme_dir_monitor (monitor_data); | |||
1154 | g_hash_table_remove (handle_hash, name); | |||
1155 | } | |||
1156 | g_free (name); | |||
1157 | } | |||
1158 | } | |||
1159 | ||||
1160 | static void | |||
1161 | top_icon_theme_dir_changed (GFileMonitor *monitor, | |||
1162 | GFile *file, | |||
1163 | GFile *other_file, | |||
1164 | GFileMonitorEvent event_type, | |||
1165 | CallbackTuple *tuple) | |||
1166 | { | |||
1167 | GHashTable *handle_hash; | |||
1168 | CommonIconThemeDirMonitorData *monitor_data; | |||
1169 | gint priority; | |||
1170 | ||||
1171 | handle_hash = tuple->handle_hash; | |||
1172 | priority = tuple->priority; | |||
1173 | ||||
1174 | if (event_type == G_FILE_MONITOR_EVENT_CREATED) { | |||
1175 | if (get_file_type (file) == G_FILE_TYPE_DIRECTORY) { | |||
1176 | monitor_data = g_new0 (CommonIconThemeDirMonitorData, 1)((CommonIconThemeDirMonitorData *) g_malloc0_n ((1), sizeof ( CommonIconThemeDirMonitorData))); | |||
1177 | monitor_data->priority = priority; | |||
1178 | add_common_icon_theme_dir_monitor (file, monitor_data, NULL((void*)0)); | |||
1179 | g_hash_table_insert (handle_hash, g_file_get_basename (file), monitor_data); | |||
1180 | } | |||
1181 | ||||
1182 | } else if (event_type == G_FILE_MONITOR_EVENT_DELETED) { | |||
1183 | gchar *name; | |||
1184 | ||||
1185 | name = g_file_get_basename (file); | |||
1186 | monitor_data = g_hash_table_lookup (handle_hash, name); | |||
1187 | if (monitor_data != NULL((void*)0)) { | |||
1188 | remove_common_icon_theme_dir_monitor (monitor_data); | |||
1189 | g_hash_table_remove (handle_hash, name); | |||
1190 | } | |||
1191 | g_free (name); | |||
1192 | } | |||
1193 | } | |||
1194 | ||||
1195 | /* Add a monitor to a top dir. These monitors persist for the duration of the | |||
1196 | * lib. | |||
1197 | */ | |||
1198 | static gboolean | |||
1199 | real_add_top_theme_dir_monitor (GFile *uri, | |||
1200 | gint priority, | |||
1201 | gboolean icon_theme, | |||
1202 | GError **error) | |||
1203 | { | |||
1204 | GFileInfo *file_info; | |||
1205 | GFileMonitor *monitor; | |||
1206 | GFileEnumerator *enumerator; | |||
1207 | CallbackTuple *tuple; | |||
1208 | ||||
1209 | /* Check the URI */ | |||
1210 | if (get_file_type (uri) != G_FILE_TYPE_DIRECTORY) | |||
1211 | return FALSE(0); | |||
1212 | ||||
1213 | /* handle_hash is a hash of common_theme_dir names to their monitor_data. We | |||
1214 | * use it to remove the monitor handles when a dir is removed. | |||
1215 | */ | |||
1216 | tuple = g_new (CallbackTuple, 1)((CallbackTuple *) g_malloc_n ((1), sizeof (CallbackTuple))); | |||
1217 | tuple->handle_hash = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, (GDestroyNotify) g_free); | |||
1218 | tuple->priority = priority; | |||
1219 | ||||
1220 | /* Monitor the top directory */ | |||
1221 | monitor = g_file_monitor_directory (uri, G_FILE_MONITOR_NONE, NULL((void*)0), NULL((void*)0)); | |||
1222 | if (monitor != NULL((void*)0)) { | |||
1223 | g_signal_connect (monitor, "changed",g_signal_connect_data ((monitor), ("changed"), ((GCallback) ( icon_theme ? top_icon_theme_dir_changed : top_theme_dir_changed )), (tuple), ((void*)0), (GConnectFlags) 0) | |||
1224 | (GCallback) (icon_theme ? top_icon_theme_dir_changed : top_theme_dir_changed),g_signal_connect_data ((monitor), ("changed"), ((GCallback) ( icon_theme ? top_icon_theme_dir_changed : top_theme_dir_changed )), (tuple), ((void*)0), (GConnectFlags) 0) | |||
1225 | tuple)g_signal_connect_data ((monitor), ("changed"), ((GCallback) ( icon_theme ? top_icon_theme_dir_changed : top_theme_dir_changed )), (tuple), ((void*)0), (GConnectFlags) 0); | |||
1226 | } | |||
1227 | ||||
1228 | /* Go through the directory to add monitoring */ | |||
1229 | enumerator = g_file_enumerate_children (uri, | |||
1230 | G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type" "," | |||
1231 | G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name", | |||
1232 | G_FILE_QUERY_INFO_NONE, | |||
1233 | NULL((void*)0), NULL((void*)0)); | |||
1234 | if (enumerator == NULL((void*)0)) | |||
1235 | return FALSE(0); | |||
| ||||
1236 | ||||
1237 | while ((file_info = g_file_enumerator_next_file (enumerator, NULL((void*)0), NULL((void*)0)))) { | |||
1238 | GFileType type = g_file_info_get_file_type (file_info); | |||
1239 | ||||
1240 | if (type == G_FILE_TYPE_DIRECTORY || type == G_FILE_TYPE_SYMBOLIC_LINK) { | |||
1241 | GFile *child; | |||
1242 | const gchar *name; | |||
1243 | gpointer data; | |||
1244 | ||||
1245 | /* Add the directory */ | |||
1246 | name = g_file_info_get_name (file_info); | |||
1247 | child = g_file_get_child (uri, name); | |||
1248 | ||||
1249 | if (icon_theme) { | |||
1250 | CommonIconThemeDirMonitorData *monitor_data; | |||
1251 | monitor_data = g_new0 (CommonIconThemeDirMonitorData, 1)((CommonIconThemeDirMonitorData *) g_malloc0_n ((1), sizeof ( CommonIconThemeDirMonitorData))); | |||
1252 | monitor_data->priority = priority; | |||
1253 | add_common_icon_theme_dir_monitor (child, monitor_data, error); | |||
1254 | data = monitor_data; | |||
1255 | } else { | |||
1256 | CommonThemeDirMonitorData *monitor_data; | |||
1257 | monitor_data = g_new0 (CommonThemeDirMonitorData, 1)((CommonThemeDirMonitorData *) g_malloc0_n ((1), sizeof (CommonThemeDirMonitorData ))); | |||
1258 | monitor_data->priority = priority; | |||
1259 | add_common_theme_dir_monitor (child, monitor_data, error); | |||
1260 | data = monitor_data; | |||
1261 | } | |||
1262 | g_object_unref (child); | |||
1263 | ||||
1264 | g_hash_table_insert (tuple->handle_hash, g_strdup (name)g_strdup_inline (name), data); | |||
1265 | } | |||
1266 | g_object_unref (file_info); | |||
1267 | } | |||
1268 | g_file_enumerator_close (enumerator, NULL((void*)0), NULL((void*)0)); | |||
1269 | ||||
1270 | return TRUE(!(0)); | |||
1271 | } | |||
1272 | ||||
1273 | static gboolean | |||
1274 | add_top_theme_dir_monitor (GFile *uri, | |||
1275 | gint priority, | |||
1276 | GError **error) | |||
1277 | { | |||
1278 | return real_add_top_theme_dir_monitor (uri, priority, FALSE(0), error); | |||
1279 | } | |||
1280 | ||||
1281 | static gboolean | |||
1282 | add_top_icon_theme_dir_monitor (GFile *uri, | |||
1283 | gint priority, | |||
1284 | GError **error) | |||
1285 | { | |||
1286 | return real_add_top_theme_dir_monitor (uri, priority, TRUE(!(0)), error); | |||
1287 | } | |||
1288 | ||||
1289 | /* Public functions */ | |||
1290 | ||||
1291 | /* CTK/Croma/keybinding Themes */ | |||
1292 | CafeThemeInfo * | |||
1293 | cafe_theme_info_new (void) | |||
1294 | { | |||
1295 | CafeThemeInfo *theme_info; | |||
1296 | ||||
1297 | theme_info = g_new0 (CafeThemeInfo, 1)((CafeThemeInfo *) g_malloc0_n ((1), sizeof (CafeThemeInfo))); | |||
1298 | theme_info->type = CAFE_THEME_TYPE_REGULAR; | |||
1299 | ||||
1300 | return theme_info; | |||
1301 | } | |||
1302 | ||||
1303 | void | |||
1304 | cafe_theme_info_free (CafeThemeInfo *theme_info) | |||
1305 | { | |||
1306 | g_free (theme_info->path); | |||
1307 | g_free (theme_info->name); | |||
1308 | g_free (theme_info->readable_name); | |||
1309 | g_free (theme_info); | |||
1310 | } | |||
1311 | ||||
1312 | CafeThemeInfo * | |||
1313 | cafe_theme_info_find (const gchar *theme_name) | |||
1314 | { | |||
1315 | return (CafeThemeInfo *) | |||
1316 | get_theme_from_hash_by_name (theme_hash_by_name, theme_name, -1); | |||
1317 | } | |||
1318 | ||||
1319 | struct CafeThemeInfoHashData | |||
1320 | { | |||
1321 | gconstpointer user_data; | |||
1322 | GList *list; | |||
1323 | }; | |||
1324 | ||||
1325 | static void | |||
1326 | cafe_theme_info_find_by_type_helper (gpointer key, | |||
1327 | GList *list, | |||
1328 | struct CafeThemeInfoHashData *hash_data) | |||
1329 | { | |||
1330 | guint elements = GPOINTER_TO_INT (hash_data->user_data)((gint) (glong) (hash_data->user_data)); | |||
1331 | ||||
1332 | do { | |||
1333 | CafeThemeInfo *theme_info = list->data; | |||
1334 | ||||
1335 | if ((elements & CAFE_THEME_CROMA && theme_info->has_croma) || | |||
1336 | (elements & CAFE_THEME_CTK_2 && theme_info->has_ctk) || | |||
1337 | (elements & CAFE_THEME_CTK_2_KEYBINDING && theme_info->has_keybinding)) { | |||
1338 | hash_data->list = g_list_prepend (hash_data->list, theme_info); | |||
1339 | return; | |||
1340 | } | |||
1341 | ||||
1342 | list = list->next; | |||
1343 | } while (list); | |||
1344 | } | |||
1345 | ||||
1346 | GList * | |||
1347 | cafe_theme_info_find_by_type (guint elements) | |||
1348 | { | |||
1349 | struct CafeThemeInfoHashData data; | |||
1350 | data.user_data = GINT_TO_POINTER (elements)((gpointer) (glong) (elements)); | |||
1351 | data.list = NULL((void*)0); | |||
1352 | ||||
1353 | g_hash_table_foreach (theme_hash_by_name, | |||
1354 | (GHFunc) cafe_theme_info_find_by_type_helper, | |||
1355 | &data); | |||
1356 | ||||
1357 | return data.list; | |||
1358 | } | |||
1359 | ||||
1360 | static void cafe_theme_info_find_all_helper(const gchar* key, GList* list, GList** themes) | |||
1361 | { | |||
1362 | /* only return visible themes */ | |||
1363 | if (!((CafeThemeCommonInfo*) list->data)->hidden) | |||
1364 | { | |||
1365 | *themes = g_list_prepend(*themes, list->data); | |||
1366 | } | |||
1367 | } | |||
1368 | ||||
1369 | gchar* ctk_theme_info_missing_engine(const gchar* ctk_theme, gboolean name_only) | |||
1370 | { | |||
1371 | gchar* engine = NULL((void*)0); | |||
1372 | gchar* ctkrc; | |||
1373 | ||||
1374 | ctkrc = ctkrc_find_named(ctk_theme); | |||
1375 | ||||
1376 | if (ctkrc) | |||
1377 | { | |||
1378 | GSList* engines = NULL((void*)0); | |||
1379 | GSList* l; | |||
1380 | ||||
1381 | ctkrc_get_details(ctkrc, &engines, NULL((void*)0)); | |||
1382 | ||||
1383 | g_free(ctkrc); | |||
1384 | ||||
1385 | for (l = engines; l; l = l->next) | |||
1386 | { | |||
1387 | /* This code do not work on distros with more of one ctk theme | |||
1388 | * engine path. Like debian. But yes on others like Archlinux. | |||
1389 | * Example, debian use: | |||
1390 | * /usr/lib/i386-linux-gnu/2.10.0/engines/ | |||
1391 | * and /usr/lib/2.10.0/engines/ | |||
1392 | * | |||
1393 | * some links | |||
1394 | * http://forums.linuxmint.com/viewtopic.php?f=190&t=85015 | |||
1395 | */ | |||
1396 | gchar* full = g_module_build_path(CTK_ENGINE_DIR"/usr/lib/x86_64-linux-gnu/ctk-3.0/3.0.0/theming-engines", l->data); | |||
1397 | ||||
1398 | gboolean found = g_file_test(full, G_FILE_TEST_EXISTS); | |||
1399 | ||||
1400 | if (!found) | |||
1401 | { | |||
1402 | if (name_only) | |||
1403 | { | |||
1404 | engine = g_strdup(l->data)g_strdup_inline (l->data); | |||
1405 | g_free(full); | |||
1406 | } | |||
1407 | else | |||
1408 | { | |||
1409 | engine = full; | |||
1410 | } | |||
1411 | ||||
1412 | break; | |||
1413 | } | |||
1414 | ||||
1415 | g_free(full); | |||
1416 | } | |||
1417 | ||||
1418 | g_slist_foreach(engines, (GFunc) g_free, NULL((void*)0)); | |||
1419 | g_slist_free(engines); | |||
1420 | } | |||
1421 | ||||
1422 | return engine; | |||
1423 | } | |||
1424 | ||||
1425 | /* Icon themes */ | |||
1426 | CafeThemeIconInfo * | |||
1427 | cafe_theme_icon_info_new (void) | |||
1428 | { | |||
1429 | CafeThemeIconInfo *icon_theme_info; | |||
1430 | ||||
1431 | icon_theme_info = g_new0 (CafeThemeIconInfo, 1)((CafeThemeIconInfo *) g_malloc0_n ((1), sizeof (CafeThemeIconInfo ))); | |||
1432 | icon_theme_info->type = CAFE_THEME_TYPE_ICON; | |||
1433 | ||||
1434 | return icon_theme_info; | |||
1435 | } | |||
1436 | ||||
1437 | void | |||
1438 | cafe_theme_icon_info_free (CafeThemeIconInfo *icon_theme_info) | |||
1439 | { | |||
1440 | g_free (icon_theme_info->name); | |||
1441 | g_free (icon_theme_info->readable_name); | |||
1442 | g_free (icon_theme_info->path); | |||
1443 | g_free (icon_theme_info); | |||
1444 | } | |||
1445 | ||||
1446 | CafeThemeIconInfo * | |||
1447 | cafe_theme_icon_info_find (const gchar *icon_theme_name) | |||
1448 | { | |||
1449 | g_return_val_if_fail (icon_theme_name != NULL, NULL)do { if ((icon_theme_name != ((void*)0))) { } else { g_return_if_fail_warning ("capplet-common", ((const char*) (__func__)), "icon_theme_name != NULL" ); return (((void*)0)); } } while (0); | |||
1450 | ||||
1451 | return (CafeThemeIconInfo *) | |||
1452 | get_theme_from_hash_by_name (icon_theme_hash_by_name, icon_theme_name, -1); | |||
1453 | } | |||
1454 | ||||
1455 | GList * | |||
1456 | cafe_theme_icon_info_find_all (void) | |||
1457 | { | |||
1458 | GList *list = NULL((void*)0); | |||
1459 | ||||
1460 | g_hash_table_foreach (icon_theme_hash_by_name, | |||
1461 | (GHFunc) cafe_theme_info_find_all_helper, | |||
1462 | &list); | |||
1463 | ||||
1464 | return list; | |||
1465 | } | |||
1466 | ||||
1467 | gint | |||
1468 | cafe_theme_icon_info_compare (CafeThemeIconInfo *a, | |||
1469 | CafeThemeIconInfo *b) | |||
1470 | { | |||
1471 | gint cmp; | |||
1472 | ||||
1473 | cmp = safe_strcmp (a->path, b->path); | |||
1474 | if (cmp != 0) return cmp; | |||
1475 | ||||
1476 | return safe_strcmp (a->name, b->name); | |||
1477 | } | |||
1478 | ||||
1479 | /* Cursor themes */ | |||
1480 | CafeThemeCursorInfo * | |||
1481 | cafe_theme_cursor_info_new (void) | |||
1482 | { | |||
1483 | CafeThemeCursorInfo *theme_info; | |||
1484 | ||||
1485 | theme_info = g_new0 (CafeThemeCursorInfo, 1)((CafeThemeCursorInfo *) g_malloc0_n ((1), sizeof (CafeThemeCursorInfo ))); | |||
1486 | theme_info->type = CAFE_THEME_TYPE_CURSOR; | |||
1487 | ||||
1488 | return theme_info; | |||
1489 | } | |||
1490 | ||||
1491 | void | |||
1492 | cafe_theme_cursor_info_free (CafeThemeCursorInfo *cursor_theme_info) | |||
1493 | { | |||
1494 | g_free (cursor_theme_info->name); | |||
1495 | g_free (cursor_theme_info->readable_name); | |||
1496 | g_free (cursor_theme_info->path); | |||
1497 | g_array_free (cursor_theme_info->sizes, TRUE(!(0))); | |||
1498 | if (cursor_theme_info->thumbnail != NULL((void*)0)) | |||
1499 | g_object_unref (cursor_theme_info->thumbnail); | |||
1500 | g_free (cursor_theme_info); | |||
1501 | } | |||
1502 | ||||
1503 | CafeThemeCursorInfo * | |||
1504 | cafe_theme_cursor_info_find (const gchar *cursor_theme_name) | |||
1505 | { | |||
1506 | g_return_val_if_fail (cursor_theme_name != NULL, NULL)do { if ((cursor_theme_name != ((void*)0))) { } else { g_return_if_fail_warning ("capplet-common", ((const char*) (__func__)), "cursor_theme_name != NULL" ); return (((void*)0)); } } while (0); | |||
1507 | ||||
1508 | return (CafeThemeCursorInfo *) | |||
1509 | get_theme_from_hash_by_name (cursor_theme_hash_by_name, cursor_theme_name, -1); | |||
1510 | } | |||
1511 | ||||
1512 | GList * | |||
1513 | cafe_theme_cursor_info_find_all (void) | |||
1514 | { | |||
1515 | GList *list = NULL((void*)0); | |||
1516 | ||||
1517 | g_hash_table_foreach (cursor_theme_hash_by_name, | |||
1518 | (GHFunc) cafe_theme_info_find_all_helper, | |||
1519 | &list); | |||
1520 | ||||
1521 | return list; | |||
1522 | } | |||
1523 | ||||
1524 | gint | |||
1525 | cafe_theme_cursor_info_compare (CafeThemeCursorInfo *a, | |||
1526 | CafeThemeCursorInfo *b) | |||
1527 | { | |||
1528 | gint cmp; | |||
1529 | ||||
1530 | cmp = safe_strcmp (a->path, b->path); | |||
1531 | if (cmp != 0) return cmp; | |||
1532 | ||||
1533 | return safe_strcmp (a->name, b->name); | |||
1534 | } | |||
1535 | ||||
1536 | /* Meta themes */ | |||
1537 | CafeThemeMetaInfo* cafe_theme_meta_info_new(void) | |||
1538 | { | |||
1539 | CafeThemeMetaInfo* theme_info; | |||
1540 | ||||
1541 | theme_info = g_new0(CafeThemeMetaInfo, 1)((CafeThemeMetaInfo *) g_malloc0_n ((1), sizeof (CafeThemeMetaInfo ))); | |||
1542 | theme_info->type = CAFE_THEME_TYPE_METATHEME; | |||
1543 | ||||
1544 | return theme_info; | |||
1545 | } | |||
1546 | ||||
1547 | void cafe_theme_meta_info_free(CafeThemeMetaInfo* meta_theme_info) | |||
1548 | { | |||
1549 | g_free (meta_theme_info->application_font); | |||
1550 | g_free (meta_theme_info->background_image); | |||
1551 | g_free (meta_theme_info->comment); | |||
1552 | g_free (meta_theme_info->cursor_theme_name); | |||
1553 | g_free (meta_theme_info->desktop_font); | |||
1554 | g_free (meta_theme_info->documents_font); | |||
1555 | g_free (meta_theme_info->ctk_color_scheme); | |||
1556 | g_free (meta_theme_info->ctk_theme_name); | |||
1557 | g_free (meta_theme_info->icon_file); | |||
1558 | g_free (meta_theme_info->icon_theme_name); | |||
1559 | g_free (meta_theme_info->croma_theme_name); | |||
1560 | g_free (meta_theme_info->monospace_font); | |||
1561 | g_free (meta_theme_info->name); | |||
1562 | g_free (meta_theme_info->notification_theme_name); | |||
1563 | g_free (meta_theme_info->path); | |||
1564 | g_free (meta_theme_info->sound_theme_name); | |||
1565 | g_free (meta_theme_info->windowtitle_font); | |||
1566 | g_free (meta_theme_info); | |||
1567 | } | |||
1568 | ||||
1569 | gboolean cafe_theme_meta_info_validate(const CafeThemeMetaInfo* info, GError** error) | |||
1570 | { | |||
1571 | CafeThemeInfo* theme; | |||
1572 | ||||
1573 | g_return_val_if_fail (error == NULL || *error == NULL, FALSE)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else { g_return_if_fail_warning ("capplet-common", ((const char*) (__func__)), "error == NULL || *error == NULL"); return ((0) ); } } while (0); | |||
1574 | ||||
1575 | theme = cafe_theme_info_find (info->ctk_theme_name); | |||
1576 | ||||
1577 | if (!theme || !theme->has_ctk) | |||
1578 | { | |||
1579 | g_set_error (error, CAFE_THEME_ERRORcafe_theme_info_error_quark(), CAFE_THEME_ERROR_CTK_THEME_NOT_AVAILABLE, | |||
1580 | _("This theme will not look as intended because the required CTK+ theme '%s' is not installed.")gettext ("This theme will not look as intended because the required CTK+ theme '%s' is not installed." ), | |||
1581 | info->ctk_theme_name); | |||
1582 | return FALSE(0); | |||
1583 | } | |||
1584 | ||||
1585 | theme = cafe_theme_info_find (info->croma_theme_name); | |||
1586 | ||||
1587 | if (!theme || !theme->has_croma) | |||
1588 | { | |||
1589 | g_set_error (error, CAFE_THEME_ERRORcafe_theme_info_error_quark(), CAFE_THEME_ERROR_WM_THEME_NOT_AVAILABLE, | |||
1590 | _("This theme will not look as intended because the required window manager theme '%s' is not installed.")gettext ("This theme will not look as intended because the required window manager theme '%s' is not installed." ), | |||
1591 | info->croma_theme_name); | |||
1592 | return FALSE(0); | |||
1593 | } | |||
1594 | ||||
1595 | if (!cafe_theme_icon_info_find (info->icon_theme_name)) | |||
1596 | { | |||
1597 | g_set_error (error, CAFE_THEME_ERRORcafe_theme_info_error_quark(), CAFE_THEME_ERROR_ICON_THEME_NOT_AVAILABLE, | |||
1598 | _("This theme will not look as intended because the required icon theme '%s' is not installed.")gettext ("This theme will not look as intended because the required icon theme '%s' is not installed." ), | |||
1599 | info->icon_theme_name); | |||
1600 | return FALSE(0); | |||
1601 | } | |||
1602 | ||||
1603 | return TRUE(!(0)); | |||
1604 | } | |||
1605 | ||||
1606 | CafeThemeMetaInfo* cafe_theme_meta_info_find(const char* meta_theme_name) | |||
1607 | { | |||
1608 | g_return_val_if_fail(meta_theme_name != NULL, NULL)do { if ((meta_theme_name != ((void*)0))) { } else { g_return_if_fail_warning ("capplet-common", ((const char*) (__func__)), "meta_theme_name != NULL" ); return (((void*)0)); } } while (0); | |||
1609 | ||||
1610 | return (CafeThemeMetaInfo*) get_theme_from_hash_by_name (meta_theme_hash_by_name, meta_theme_name, -1); | |||
1611 | } | |||
1612 | ||||
1613 | GList* cafe_theme_meta_info_find_all(void) | |||
1614 | { | |||
1615 | GList* list = NULL((void*)0); | |||
1616 | ||||
1617 | g_hash_table_foreach (meta_theme_hash_by_name, (GHFunc) cafe_theme_info_find_all_helper, &list); | |||
1618 | ||||
1619 | return list; | |||
1620 | } | |||
1621 | ||||
1622 | gint | |||
1623 | cafe_theme_meta_info_compare (CafeThemeMetaInfo *a, | |||
1624 | CafeThemeMetaInfo *b) | |||
1625 | { | |||
1626 | gint cmp; | |||
1627 | ||||
1628 | cmp = safe_strcmp (a->path, b->path); | |||
1629 | if (cmp != 0) return cmp; | |||
1630 | ||||
1631 | cmp = safe_strcmp (a->readable_name, b->readable_name); | |||
1632 | if (cmp != 0) return cmp; | |||
1633 | ||||
1634 | cmp = safe_strcmp (a->name, b->name); | |||
1635 | if (cmp != 0) return cmp; | |||
1636 | ||||
1637 | cmp = safe_strcmp (a->comment, b->comment); | |||
1638 | if (cmp != 0) return cmp; | |||
1639 | ||||
1640 | cmp = safe_strcmp (a->icon_file, b->icon_file); | |||
1641 | if (cmp != 0) return cmp; | |||
1642 | ||||
1643 | cmp = safe_strcmp (a->ctk_theme_name, b->ctk_theme_name); | |||
1644 | if (cmp != 0) return cmp; | |||
1645 | ||||
1646 | cmp = safe_strcmp (a->ctk_color_scheme, b->ctk_color_scheme); | |||
1647 | if (cmp != 0) return cmp; | |||
1648 | ||||
1649 | cmp = safe_strcmp (a->croma_theme_name, b->croma_theme_name); | |||
1650 | if (cmp != 0) return cmp; | |||
1651 | ||||
1652 | cmp = safe_strcmp (a->icon_theme_name, b->icon_theme_name); | |||
1653 | if (cmp != 0) return cmp; | |||
1654 | ||||
1655 | cmp = safe_strcmp (a->notification_theme_name, b->notification_theme_name); | |||
1656 | if (cmp != 0) return cmp; | |||
1657 | ||||
1658 | cmp = safe_strcmp (a->sound_theme_name, b->sound_theme_name); | |||
1659 | if (cmp != 0) return cmp; | |||
1660 | ||||
1661 | cmp = safe_strcmp (a->application_font, b->application_font); | |||
1662 | if (cmp != 0) return cmp; | |||
1663 | ||||
1664 | cmp = safe_strcmp (a->documents_font, b->documents_font); | |||
1665 | if (cmp != 0) return cmp; | |||
1666 | ||||
1667 | cmp = safe_strcmp (a->desktop_font, b->desktop_font); | |||
1668 | if (cmp != 0) return cmp; | |||
1669 | ||||
1670 | cmp = safe_strcmp (a->windowtitle_font, b->windowtitle_font); | |||
1671 | if (cmp != 0) return cmp; | |||
1672 | ||||
1673 | cmp = safe_strcmp (a->monospace_font, b->monospace_font); | |||
1674 | if (cmp != 0) return cmp; | |||
1675 | ||||
1676 | return safe_strcmp (a->background_image, b->background_image); | |||
1677 | } | |||
1678 | ||||
1679 | void | |||
1680 | cafe_theme_info_register_theme_change (ThemeChangedCallback func, | |||
1681 | gpointer data) | |||
1682 | { | |||
1683 | ThemeCallbackData *callback_data; | |||
1684 | ||||
1685 | g_return_if_fail (func != NULL)do { if ((func != ((void*)0))) { } else { g_return_if_fail_warning ("capplet-common", ((const char*) (__func__)), "func != NULL" ); return; } } while (0); | |||
1686 | ||||
1687 | callback_data = g_new (ThemeCallbackData, 1)((ThemeCallbackData *) g_malloc_n ((1), sizeof (ThemeCallbackData ))); | |||
1688 | callback_data->func = func; | |||
1689 | callback_data->data = data; | |||
1690 | ||||
1691 | callbacks = g_list_prepend (callbacks, callback_data); | |||
1692 | } | |||
1693 | ||||
1694 | gboolean | |||
1695 | cafe_theme_color_scheme_parse (const gchar *scheme, CdkRGBA *colors) | |||
1696 | { | |||
1697 | gchar **color_scheme_strings, **color_scheme_pair, *current_string; | |||
1698 | gint i; | |||
1699 | ||||
1700 | if (!scheme || !strcmp (scheme, "")) | |||
1701 | return FALSE(0); | |||
1702 | ||||
1703 | /* initialise the array */ | |||
1704 | for (i = 0; i < NUM_SYMBOLIC_COLORS; i++) | |||
1705 | colors[i].red = colors[i].green = colors[i].blue = 0; | |||
1706 | ||||
1707 | /* The color scheme string consists of name:color pairs, separated by | |||
1708 | * newlines, so first we split the string up by new line */ | |||
1709 | ||||
1710 | color_scheme_strings = g_strsplit (scheme, "\n", 0); | |||
1711 | ||||
1712 | /* loop through the name:color pairs, and save the color if we recognise the name */ | |||
1713 | i = 0; | |||
1714 | while ((current_string = color_scheme_strings[i++])) { | |||
1715 | color_scheme_pair = g_strsplit (current_string, ":", 0); | |||
1716 | ||||
1717 | if (color_scheme_pair[0] != NULL((void*)0) && color_scheme_pair[1] != NULL((void*)0)) { | |||
1718 | g_strstrip (color_scheme_pair[0])g_strchomp (g_strchug (color_scheme_pair[0])); | |||
1719 | g_strstrip (color_scheme_pair[1])g_strchomp (g_strchug (color_scheme_pair[1])); | |||
1720 | ||||
1721 | if (!strcmp ("fg_color", color_scheme_pair[0])) | |||
1722 | cdk_rgba_parse (&colors[COLOR_FG], color_scheme_pair[1]); | |||
1723 | else if (!strcmp ("bg_color", color_scheme_pair[0])) | |||
1724 | cdk_rgba_parse (&colors[COLOR_BG], color_scheme_pair[1]); | |||
1725 | else if (!strcmp ("text_color", color_scheme_pair[0])) | |||
1726 | cdk_rgba_parse (&colors[COLOR_TEXT], color_scheme_pair[1]); | |||
1727 | else if (!strcmp ("base_color", color_scheme_pair[0])) | |||
1728 | cdk_rgba_parse (&colors[COLOR_BASE], color_scheme_pair[1]); | |||
1729 | else if (!strcmp ("selected_fg_color", color_scheme_pair[0])) | |||
1730 | cdk_rgba_parse (&colors[COLOR_SELECTED_FG], color_scheme_pair[1]); | |||
1731 | else if (!strcmp ("selected_bg_color", color_scheme_pair[0])) | |||
1732 | cdk_rgba_parse ( &colors[COLOR_SELECTED_BG], color_scheme_pair[1]); | |||
1733 | else if (!strcmp ("tooltip_fg_color", color_scheme_pair[0])) | |||
1734 | cdk_rgba_parse (&colors[COLOR_TOOLTIP_FG], color_scheme_pair[1]); | |||
1735 | else if (!strcmp ("tooltip_bg_color", color_scheme_pair[0])) | |||
1736 | cdk_rgba_parse (&colors[COLOR_TOOLTIP_BG], color_scheme_pair[1]); | |||
1737 | } | |||
1738 | ||||
1739 | g_strfreev (color_scheme_pair); | |||
1740 | } | |||
1741 | ||||
1742 | g_strfreev (color_scheme_strings); | |||
1743 | ||||
1744 | return TRUE(!(0)); | |||
1745 | } | |||
1746 | ||||
1747 | gboolean | |||
1748 | cafe_theme_color_scheme_equal (const gchar *s1, const gchar *s2) | |||
1749 | { | |||
1750 | CdkRGBA c1[NUM_SYMBOLIC_COLORS], c2[NUM_SYMBOLIC_COLORS]; | |||
1751 | int i; | |||
1752 | ||||
1753 | if (!cafe_theme_color_scheme_parse (s1, c1) || | |||
1754 | !cafe_theme_color_scheme_parse (s2, c2)) | |||
1755 | return FALSE(0); | |||
1756 | ||||
1757 | for (i = 0; i < NUM_SYMBOLIC_COLORS; ++i) { | |||
1758 | if (!cdk_rgba_equal (&c1[i], &c2[i])) | |||
1759 | return FALSE(0); | |||
1760 | } | |||
1761 | ||||
1762 | return TRUE(!(0)); | |||
1763 | } | |||
1764 | ||||
1765 | void | |||
1766 | cafe_theme_init () | |||
1767 | { | |||
1768 | const gchar * const * dirs; | |||
1769 | GFile *top_theme_dir; | |||
1770 | gchar *top_theme_dir_string; | |||
1771 | static gboolean initted = FALSE(0); | |||
1772 | gchar **search_path; | |||
1773 | gint i, n; | |||
1774 | ||||
1775 | if (initted
| |||
| ||||
1776 | return; | |||
1777 | ||||
1778 | initting = TRUE(!(0)); | |||
1779 | ||||
1780 | meta_theme_hash_by_uri = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL((void*)0)); | |||
1781 | meta_theme_hash_by_name = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL((void*)0)); | |||
1782 | icon_theme_hash_by_uri = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL((void*)0)); | |||
1783 | icon_theme_hash_by_name = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL((void*)0)); | |||
1784 | cursor_theme_hash_by_uri = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL((void*)0)); | |||
1785 | cursor_theme_hash_by_name = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL((void*)0)); | |||
1786 | theme_hash_by_uri = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL((void*)0)); | |||
1787 | theme_hash_by_name = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL((void*)0)); | |||
1788 | ||||
1789 | /* Add all the toplevel theme dirs following the XDG Base Directory Specification */ | |||
1790 | dirs = g_get_system_data_dirs (); | |||
1791 | if (dirs != NULL((void*)0)) | |||
1792 | for (; *dirs != NULL((void*)0); ++dirs) { | |||
1793 | top_theme_dir_string = g_build_filename (*dirs, "themes", NULL((void*)0)); | |||
1794 | top_theme_dir = g_file_new_for_path (top_theme_dir_string); | |||
1795 | g_free (top_theme_dir_string); | |||
1796 | add_top_theme_dir_monitor (top_theme_dir, 1, NULL((void*)0)); | |||
1797 | g_object_unref (top_theme_dir); | |||
1798 | } | |||
1799 | ||||
1800 | /* ~/.themes */ | |||
1801 | top_theme_dir_string = g_build_filename (g_get_home_dir (), ".themes", NULL((void*)0)); | |||
1802 | top_theme_dir = g_file_new_for_path (top_theme_dir_string); | |||
1803 | g_free (top_theme_dir_string); | |||
1804 | if (!g_file_query_exists (top_theme_dir, NULL((void*)0))) | |||
1805 | g_file_make_directory (top_theme_dir, NULL((void*)0), NULL((void*)0)); | |||
1806 | add_top_theme_dir_monitor (top_theme_dir, 0, NULL((void*)0)); | |||
1807 | g_object_unref (top_theme_dir); | |||
1808 | ||||
1809 | /* ~/.icons */ | |||
1810 | top_theme_dir_string = g_build_filename (g_get_home_dir (), ".icons", NULL((void*)0)); | |||
1811 | top_theme_dir = g_file_new_for_path (top_theme_dir_string); | |||
1812 | g_free (top_theme_dir_string); | |||
1813 | if (!g_file_query_exists (top_theme_dir, NULL((void*)0))) | |||
1814 | g_file_make_directory (top_theme_dir, NULL((void*)0), NULL((void*)0)); | |||
1815 | g_object_unref (top_theme_dir); | |||
1816 | ||||
1817 | /* icon theme search path */ | |||
1818 | ctk_icon_theme_get_search_path (ctk_icon_theme_get_default (), &search_path, &n); | |||
1819 | for (i = 0; i < n; ++i) { | |||
1820 | top_theme_dir = g_file_new_for_path (search_path[i]); | |||
1821 | add_top_icon_theme_dir_monitor (top_theme_dir, i, NULL((void*)0)); | |||
1822 | g_object_unref (top_theme_dir); | |||
1823 | } | |||
1824 | g_strfreev (search_path); | |||
1825 | ||||
1826 | /* if there's a separate xcursors dir, add that as well */ | |||
1827 | if (strcmp (XCURSOR_ICONDIR"/usr/share/icons", "/usr/share/icons")) { | |||
1828 | top_theme_dir = g_file_new_for_path (XCURSOR_ICONDIR"/usr/share/icons"); | |||
1829 | add_top_icon_theme_dir_monitor (top_theme_dir, 1, NULL((void*)0)); | |||
1830 | g_object_unref (top_theme_dir); | |||
1831 | } | |||
1832 | ||||
1833 | /* make sure we have the default theme */ | |||
1834 | if (!cafe_theme_cursor_info_find ("default")) | |||
1835 | add_default_cursor_theme (); | |||
1836 | ||||
1837 | /* done */ | |||
1838 | initted = TRUE(!(0)); | |||
1839 | initting = FALSE(0); | |||
1840 | } |