1 #include "e.h"
2
3 static void *_create_data(E_Config_Dialog *cfd);
4 static void _free_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
5 static int _basic_check_changed(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
6 static int _basic_apply(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
7 static Evas_Object *_basic_create(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata);
8 //static int _sort_widget_themes(const void *data1, const void *data2);
9 //static Evas_Object *_icon_new(Evas *evas, const char *theme, const char *icon, unsigned int size);
10
11 struct _E_Config_Dialog_Data
12 {
13 E_Config_Dialog *cfd;
14 Eina_List *widget_themes;
15 const char *widget_theme;
16 int enable_xsettings;
17 int match_e17_theme;
18 int match_e17_icon_theme;
19 Eina_List *icon_themes;
20 const char *icon_theme;
21 int icon_overrides;
22 //int enable_icon_theme; // We just need to check whether override or match icon theme is set.
23 int icon_populating;
24 struct
25 {
26 Evas_Object *widget_list;
27 Evas_Object *match_theme;
28 Evas_Object *icon_list;
29 Evas_Object *icon_preview[4]; /* same size as _icon_previews */
30 Evas_Object *icon_enable_apps;
31 Evas_Object *icon_enable_enlightenment;
32 } gui;
33 Ecore_Idler *fill_icon_themes_delayed;
34 };
35
36 static const char *_icon_previews[4] =
37 {
38 "system-run",
39 "system-file-manager",
40 "preferences-desktop-theme",
41 "text-x-generic"
42 };
43
44 #define PREVIEW_SIZE (48)
45
46 E_Config_Dialog *
e_int_config_xsettings(Evas_Object * parent EINA_UNUSED,const char * params EINA_UNUSED)47 e_int_config_xsettings(Evas_Object *parent EINA_UNUSED, const char *params EINA_UNUSED)
48 {
49 E_Config_Dialog *cfd;
50 E_Config_Dialog_View *v;
51
52 if (e_config_dialog_find("E", "appearance/xsettings")) return NULL;
53 v = E_NEW(E_Config_Dialog_View, 1);
54
55 v->create_cfdata = _create_data;
56 v->free_cfdata = _free_data;
57 v->basic.create_widgets = _basic_create;
58 v->basic.apply_cfdata = _basic_apply;
59 v->basic.check_changed = _basic_check_changed;
60
61 cfd = e_config_dialog_new(NULL, _("Application Theme Settings"),
62 "E", "appearance/xsettings",
63 "preferences-desktop-theme", 0, v, NULL);
64 return cfd;
65 }
66
67 static void *
_create_data(E_Config_Dialog * cfd)68 _create_data(E_Config_Dialog *cfd)
69 {
70 E_Config_Dialog_Data *cfdata;
71
72 cfdata = E_NEW(E_Config_Dialog_Data, 1);
73 cfdata->cfd = cfd;
74 cfdata->widget_theme = eina_stringshare_add(e_config->xsettings.net_theme_name);
75 cfdata->match_e17_icon_theme = e_config->xsettings.match_e17_icon_theme;
76 cfdata->match_e17_theme = e_config->xsettings.match_e17_theme;
77 cfdata->enable_xsettings = e_config->xsettings.enabled;
78 cfdata->icon_theme = eina_stringshare_add(e_config->icon_theme);
79 cfdata->icon_overrides = e_config->icon_theme_overrides;
80 //cfdata->enable_icon_theme = !!(e_config->icon_theme);
81 return cfdata;
82 }
83
84 static void
_free_data(E_Config_Dialog * cfd EINA_UNUSED,E_Config_Dialog_Data * cfdata)85 _free_data(E_Config_Dialog *cfd EINA_UNUSED, E_Config_Dialog_Data *cfdata)
86 {
87 if (cfdata->fill_icon_themes_delayed)
88 free(ecore_idler_del(cfdata->fill_icon_themes_delayed));
89
90 eina_list_free(cfdata->icon_themes);
91 eina_stringshare_del(cfdata->icon_theme);
92 eina_stringshare_del(cfdata->widget_theme);
93 E_FREE(cfdata);
94 }
95
96 static int
_basic_check_changed(E_Config_Dialog * cfd EINA_UNUSED,E_Config_Dialog_Data * cfdata)97 _basic_check_changed(E_Config_Dialog *cfd EINA_UNUSED, E_Config_Dialog_Data *cfdata)
98 {
99 if (cfdata->match_e17_icon_theme != e_config->xsettings.match_e17_icon_theme)
100 return 1;
101
102 if (cfdata->match_e17_theme != e_config->xsettings.match_e17_theme)
103 return 1;
104
105 if (cfdata->enable_xsettings != !!(e_config->xsettings.enabled))
106 return 1;
107
108 if ((!cfdata->widget_theme) && e_config->xsettings.net_theme_name)
109 return 1;
110
111 if (cfdata->widget_theme && (!e_config->xsettings.net_theme_name))
112 return 1;
113
114 if (cfdata->icon_overrides != e_config->icon_theme_overrides)
115 return 1;
116
117 /* if (cfdata->enable_icon_theme != !!(e_config->icon_theme))
118 * return 1; */
119
120 if ((!cfdata->icon_theme) && (e_config->icon_theme))
121 return 1;
122
123 if ((cfdata->icon_theme) && (!e_config->icon_theme))
124 return 1;
125
126 if ((cfdata->widget_theme && e_config->xsettings.net_theme_name) &&
127 (strcmp(cfdata->widget_theme, e_config->xsettings.net_theme_name) != 0))
128 return 1;
129
130 if ((cfdata->icon_theme && e_config->icon_theme) &&
131 (strcmp(cfdata->icon_theme, e_config->icon_theme) != 0))
132 return 1;
133
134 return 0;
135 }
136
137 static int
_basic_apply(E_Config_Dialog * cfd,E_Config_Dialog_Data * cfdata)138 _basic_apply(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata)
139 {
140 E_Event_Config_Icon_Theme *ev;
141
142 if (!_basic_check_changed(cfd, cfdata)) return 1;
143
144 e_widget_ilist_selected_label_get(cfdata->gui.widget_list);
145
146 eina_stringshare_replace(&e_config->xsettings.net_theme_name, cfdata->widget_theme);
147
148 // e_config->xsettings.match_e17_icon_theme = cfdata->match_e17_icon_theme;
149 e_config->xsettings.match_e17_theme = cfdata->match_e17_theme;
150 e_config->xsettings.enabled = cfdata->enable_xsettings;
151
152 eina_stringshare_del(e_config->icon_theme);
153 if (cfdata->icon_overrides || cfdata->match_e17_icon_theme)
154 e_config->icon_theme = eina_stringshare_ref(cfdata->icon_theme);
155 else
156 e_config->icon_theme = eina_stringshare_add("hicolor"); // FDO default
157
158 e_config->icon_theme_overrides = !!cfdata->icon_overrides;
159 e_config->xsettings.match_e17_icon_theme = cfdata->match_e17_icon_theme;
160 e_config_save_queue();
161
162 if (cfdata->match_e17_icon_theme &&
163 strcmp(e_config->icon_theme, elm_config_icon_theme_get()))
164 {
165 elm_config_icon_theme_set(e_config->icon_theme);
166 elm_config_all_flush();
167 elm_config_save();
168 }
169 e_util_env_set("E_ICON_THEME", e_config->icon_theme);
170
171 ev = E_NEW(E_Event_Config_Icon_Theme, 1);
172 if (ev)
173 {
174 ev->icon_theme = e_config->icon_theme;
175 ecore_event_add(E_EVENT_CONFIG_ICON_THEME, ev, NULL, NULL);
176 }
177
178 #ifndef HAVE_WAYLAND_ONLY
179 e_xsettings_config_update();
180 #endif
181
182 return 1;
183 }
184
185 static int
_sort_widget_themes(const void * data1,const void * data2)186 _sort_widget_themes(const void *data1, const void *data2)
187 {
188 const char *d1, *d2;
189
190 d1 = data1;
191 d2 = data2;
192 if (!d1) return 1;
193 if (!d2) return -1;
194
195 return strcmp(d1, d2);
196 }
197
198 static int
_sort_icon_themes(const void * data1,const void * data2)199 _sort_icon_themes(const void *data1, const void *data2)
200 {
201 const Efreet_Icon_Theme *m1, *m2;
202
203 if (!data2) return -1;
204
205 m1 = data1;
206 m2 = data2;
207
208 if (!m1->name.name) return 1;
209 if (!m2->name.name) return -1;
210
211 return strcmp(m1->name.name, m2->name.name);
212 }
213
214 static void
_ilist_files_add(E_Config_Dialog_Data * cfdata,const char * dir)215 _ilist_files_add(E_Config_Dialog_Data *cfdata, const char *dir)
216 {
217 Eina_Iterator *it;
218 const char *file;
219
220 it = eina_file_ls(dir);
221 if (!it) return;
222
223 EINA_ITERATOR_FOREACH(it, file)
224 {
225 if ((ecore_file_is_dir(file)) &&
226 (!eina_list_data_find(cfdata->widget_themes, file)))
227 {
228 cfdata->widget_themes = eina_list_append(cfdata->widget_themes, file);
229 }
230 else
231 eina_stringshare_del(file);
232 }
233
234 eina_iterator_free(it);
235 }
236
237 static Eina_Bool
_fill_files_ilist(void * data)238 _fill_files_ilist(void *data)
239 {
240 Evas *evas;
241 Evas_Object *o;
242 char theme_dir[4096];
243 E_Config_Dialog_Data *cfdata = data;
244 Eina_List *xdg_dirs, *l;
245 const char *dir;
246
247 if (!(o = cfdata->gui.widget_list))
248 return ECORE_CALLBACK_CANCEL;
249
250 e_user_homedir_concat_static(theme_dir, ".themes");
251 _ilist_files_add(cfdata, theme_dir);
252
253 xdg_dirs = efreet_data_dirs_get();
254 EINA_LIST_FOREACH(xdg_dirs, l, dir)
255 {
256 snprintf(theme_dir, sizeof(theme_dir), "%s/themes", dir);
257 _ilist_files_add(cfdata, theme_dir);
258 }
259
260 evas = evas_object_evas_get(o);
261 evas_event_freeze(evas);
262 edje_freeze();
263 e_widget_ilist_freeze(o);
264 e_widget_ilist_clear(o);
265
266 if (cfdata->widget_themes)
267 {
268 const char *theme;
269 int cnt = 0;
270
271 cfdata->widget_themes = eina_list_sort(cfdata->widget_themes, -1, _sort_widget_themes);
272
273 EINA_LIST_FREE(cfdata->widget_themes, theme)
274 {
275 const char *tmp;
276 char buf[PATH_MAX];
277 Eina_Bool gtk2 = EINA_FALSE;
278 Eina_Bool gtk3 = EINA_FALSE;
279 snprintf(buf, sizeof(buf), "%s/gtk-2.0", theme);
280 gtk2 = ecore_file_is_dir(buf);
281 snprintf(buf, sizeof(buf), "%s/gtk-3.0", theme);
282 gtk3 = ecore_file_is_dir(buf);
283 if ((!gtk2) && (!gtk3)) continue;
284
285 tmp = strrchr(theme, '/');
286 if (tmp)
287 {
288 char label[256];
289 const char *value;
290 ssize_t len = sizeof(label) - 1;
291
292 tmp += 1;
293 value = eina_stringshare_add(tmp);
294 label[0] = 0;
295 strncpy(label, value, len);
296 len -= strlen(label);
297 if (gtk2 && (len > 5))
298 {
299 strcat(label, " (v2)");
300 len -= 5;
301 }
302 if (gtk3 && (len > 5))
303 {
304 strcat(label, " (v3)");
305 len -= 5;
306 }
307
308 /* value pointer will exist as long as ilist item
309 so val remains valid */
310 e_widget_ilist_append(o, NULL, label, NULL, NULL, value);
311 if ((e_config->xsettings.net_theme_name_detected == value) || (cfdata->widget_theme == value))
312 e_widget_ilist_selected_set(cfdata->gui.widget_list, cnt);
313 eina_stringshare_del(value);
314 cnt++;
315 }
316
317 eina_stringshare_del(theme);
318 }
319 }
320
321 e_widget_ilist_go(o);
322 e_widget_ilist_thaw(o);
323 edje_thaw();
324 evas_event_thaw(evas);
325
326 return ECORE_CALLBACK_CANCEL;
327 }
328
329 static Evas_Object *
_icon_new(Evas * evas,const char * theme,const char * icon,unsigned int size)330 _icon_new(Evas *evas, const char *theme, const char *icon, unsigned int size)
331 {
332 Evas_Object *o;
333 const char *path;
334
335 if (!(path = efreet_icon_path_find(theme, icon, size))) return NULL;
336 o = e_icon_add(evas);
337 e_icon_file_set(o, path);
338 e_icon_fill_inside_set(o, EINA_TRUE);
339 return o;
340 }
341
342 static void
_populate_icon_preview(E_Config_Dialog_Data * cfdata)343 _populate_icon_preview(E_Config_Dialog_Data *cfdata)
344 {
345 const char *t = cfdata->icon_theme;
346 unsigned int i;
347
348 for (i = 0; i < sizeof(_icon_previews) / sizeof(_icon_previews[0]); i++)
349 {
350 const char *path;
351
352 if (!(path = efreet_icon_path_find(t, _icon_previews[i], PREVIEW_SIZE)))
353 continue;
354 e_icon_file_set(cfdata->gui.icon_preview[i], path);
355 e_icon_fill_inside_set(cfdata->gui.icon_preview[i], EINA_TRUE);
356 }
357 }
358
359 struct _fill_icon_themes_data
360 {
361 Eina_List *l;
362 int i;
363 Evas *evas;
364 E_Config_Dialog_Data *cfdata;
365 Eina_Bool themes_loaded;
366 };
367
368 static void
_fill_icon_data(E_Config_Dialog_Data * cfdata)369 _fill_icon_data(E_Config_Dialog_Data *cfdata)
370 {
371 cfdata->icon_themes = efreet_icon_theme_list_get();
372 cfdata->icon_themes = eina_list_sort(cfdata->icon_themes,
373 eina_list_count(cfdata->icon_themes),
374 _sort_icon_themes);
375 }
376
377 static Eina_Bool
_fill_icon_themes(void * data)378 _fill_icon_themes(void *data)
379 {
380 struct _fill_icon_themes_data *d = data;
381 Efreet_Icon_Theme *theme;
382 Evas_Object *oc = NULL;
383 const char **example_icon, *example_icons[] =
384 {
385 NULL,
386 "folder",
387 "user-home",
388 "text-x-generic",
389 "system-run",
390 "preferences-system",
391 NULL,
392 };
393
394 if (!d->themes_loaded)
395 {
396 d->cfdata->icon_themes = eina_list_free(d->cfdata->icon_themes);
397 _fill_icon_data(d->cfdata);
398 d->l = d->cfdata->icon_themes;
399 d->i = 0;
400 d->themes_loaded = 1;
401 return ECORE_CALLBACK_RENEW;
402 }
403
404 if (!d->l)
405 {
406 int mw, mh;
407
408 e_widget_ilist_go(d->cfdata->gui.icon_list);
409
410 e_widget_size_min_get(d->cfdata->gui.icon_list, &mw, &mh);
411 e_widget_size_min_set(d->cfdata->gui.icon_list, mw, 100);
412
413 d->cfdata->fill_icon_themes_delayed = NULL;
414 d->cfdata->icon_populating = EINA_FALSE;
415 _populate_icon_preview(d->cfdata);
416 free(d);
417 return ECORE_CALLBACK_CANCEL;
418 }
419
420 theme = d->l->data;
421 if (theme->example_icon)
422 {
423 example_icons[0] = theme->example_icon;
424 example_icon = example_icons;
425 }
426 else
427 example_icon = example_icons + 1;
428
429 for (; (*example_icon) && (!oc); example_icon++)
430 oc = _icon_new(d->evas, theme->name.internal, *example_icon, 24);
431
432 if (oc)
433 {
434 e_widget_ilist_append(d->cfdata->gui.icon_list, oc, theme->name.name,
435 NULL, NULL, theme->name.internal);
436 if ((d->cfdata->icon_theme) && (theme->name.internal) &&
437 (strcmp(d->cfdata->icon_theme, theme->name.internal) == 0))
438 e_widget_ilist_selected_set(d->cfdata->gui.icon_list, d->i);
439 }
440
441 d->i++;
442 d->l = d->l->next;
443 return ECORE_CALLBACK_RENEW;
444 }
445
446 static void
_icon_theme_changed(void * data,Evas_Object * o EINA_UNUSED)447 _icon_theme_changed(void *data, Evas_Object *o EINA_UNUSED)
448 {
449 E_Config_Dialog_Data *cfdata;
450
451 cfdata = data;
452 if (cfdata->icon_populating) return;
453 _populate_icon_preview(cfdata);
454 }
455
456 static Evas_Object *
_basic_create(E_Config_Dialog * cfd EINA_UNUSED,Evas * evas,E_Config_Dialog_Data * cfdata)457 _basic_create(E_Config_Dialog *cfd EINA_UNUSED, Evas *evas, E_Config_Dialog_Data *cfdata)
458 {
459 Evas_Object *otb, *ol, *ilist, *of, *ow, *oc;
460 struct _fill_icon_themes_data *d;
461 unsigned int i;
462
463 otb = e_widget_toolbook_add(evas, (24 * e_scale), (24 * e_scale));
464
465 ol = e_widget_list_add(evas, 0, 0);
466 ilist = e_widget_ilist_add(evas, 24, 24, &(cfdata->widget_theme));
467 cfdata->gui.widget_list = ilist;
468 e_widget_size_min_set(cfdata->gui.widget_list, 100, 100);
469
470 /* e_widget_on_change_hook_set(ilist, _icon_theme_changed, cfdata); */
471 e_widget_list_object_append(ol, ilist, 1, 1, 0.5);
472
473 /* ow = e_widget_check_add(evas, _("Use icon theme for applications"),
474 * &(cfdata->match_e17_icon_theme));
475 * e_widget_list_object_append(ol, ow, 0, 0, 0.0); */
476
477 cfdata->gui.match_theme = ow = e_widget_check_add(evas, _("Match Enlightenment theme if possible"),
478 &(cfdata->match_e17_theme));
479 e_widget_list_object_append(ol, ow, 0, 0, 0.0);
480
481 /* ow = e_widget_check_add(evas, _("Set application theme"),
482 * &(cfdata->enable_app_theme));
483 * e_widget_list_object_append(o, ow, 0, 0, 0.0); */
484
485 // >> advanced
486 #ifndef HAVE_WAYLAND_ONLY
487 oc = e_widget_check_add(evas, _("Enable X Application Settings"),
488 &(cfdata->enable_xsettings));
489 e_widget_list_object_append(ol, oc, 0, 0, 0.0);
490 #endif
491 e_widget_check_widget_disable_on_unchecked_add(oc, ilist);
492 e_widget_check_widget_disable_on_unchecked_add(oc, ow);
493 e_widget_toolbook_page_append(otb, NULL, _("GTK Applications"), ol,
494 1, 1, 1, 1, 0.5, 0.0);
495
496 ol = e_widget_list_add(evas, 0, 0);
497 ilist = e_widget_ilist_add(evas, 24, 24, &(cfdata->icon_theme));
498 cfdata->gui.icon_list = ilist;
499 e_widget_size_min_set(cfdata->gui.icon_list, 100, 100);
500
501 cfdata->icon_populating = EINA_TRUE;
502 e_widget_on_change_hook_set(ilist, _icon_theme_changed, cfdata);
503 e_widget_list_object_append(ol, ilist, 1, 1, 0.5);
504
505 of = e_widget_framelist_add(evas, _("Preview"), 1);
506
507 for (i = 0; i < sizeof(_icon_previews) / sizeof(_icon_previews[0]); i++)
508 {
509 cfdata->gui.icon_preview[i] = e_icon_add(evas);
510 e_icon_preload_set(cfdata->gui.icon_preview[i], EINA_TRUE);
511 e_icon_scale_size_set(cfdata->gui.icon_preview[i], PREVIEW_SIZE);
512 e_widget_framelist_object_append_full(of, cfdata->gui.icon_preview[i],
513 0, 0, 0, 0, 0.5, 0.5,
514 PREVIEW_SIZE, PREVIEW_SIZE,
515 PREVIEW_SIZE, PREVIEW_SIZE);
516 }
517 e_widget_list_object_append(ol, of, 0, 0, 0.5);
518
519 /* ow = e_widget_check_add(evas, _("Enable icon theme"),
520 * &(cfdata->enable_icon_theme));
521 * e_widget_on_change_hook_set(ow, _icon_theme_changed, cfdata);
522 * e_widget_list_object_append(ol, ow, 0, 0, 0.0); */
523
524 cfdata->gui.icon_enable_apps = ow = e_widget_check_add(evas, _("Enable icon theme for applications"),
525 &(cfdata->match_e17_icon_theme));
526 e_widget_check_widget_disable_on_unchecked_add(oc, ow);
527 e_widget_list_object_append(ol, ow, 0, 0, 0.0);
528
529 cfdata->gui.icon_enable_enlightenment = ow = e_widget_check_add(evas, _("Enable icon theme for Enlightenment"),
530 &(cfdata->icon_overrides));
531 e_widget_list_object_append(ol, ow, 0, 0, 0.0);
532
533 e_widget_toolbook_page_append(otb, NULL, _("Icons"), ol,
534 1, 1, 1, 1, 0.5, 0.0);
535
536 e_widget_toolbook_page_show(otb, 0);
537 e_dialog_resizable_set(cfd->dia, 1);
538
539 _fill_files_ilist(cfdata);
540
541 if (cfdata->fill_icon_themes_delayed)
542 free(ecore_idler_del(cfdata->fill_icon_themes_delayed));
543
544 d = malloc(sizeof(*d));
545 d->l = NULL;
546 d->cfdata = cfdata;
547 d->themes_loaded = 0;
548 d->evas = evas;
549 cfdata->fill_icon_themes_delayed = ecore_idler_add(_fill_icon_themes, d);
550
551 return otb;
552 }
553
554