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