2 check http://www.pvv.org/~mariusbu/proposal.html
3 for advances in cross toolkit settings */
7 #include <X11/Xmd.h> /* For CARD16 */
9 #define RETRY_TIMEOUT 2.0
11 #define SETTING_TYPE_INT 0
12 #define SETTING_TYPE_STRING 1
13 #define SETTING_TYPE_COLOR 2
15 #define OFFSET_ADD(n) ((n + 4 - 1) & (~(4 - 1)))
19 typedef struct _Settings_Manger Settings_Manager;
20 typedef struct _Setting Setting;
22 struct _Settings_Manger
25 Ecore_X_Window selection;
26 Ecore_Timer *timer_retry;
28 Ecore_X_Atom _atom_xsettings_screen;
37 struct { const char *value; } s;
38 struct { int value; } i;
39 struct { unsigned short red, green, blue, alpha; } c;
42 unsigned long last_change;
45 static void _e_xsettings_apply(Settings_Manager *sm);
47 static Ecore_X_Atom _atom_manager = 0;
48 static Ecore_X_Atom _atom_xsettings = 0;
49 static Eina_List *managers = NULL;
50 static Eina_List *handlers = NULL;
51 static Eina_List *settings = NULL;
52 static Eina_Bool running = EINA_FALSE;
53 static const char _setting_icon_theme_name[] = "Net/IconThemeName";
54 static const char _setting_theme_name[] = "Net/ThemeName";
55 static const char _setting_font_name[] = "Gtk/FontName";
56 static const char _setting_xft_dpi[] = "Xft/DPI";
59 _e_xsettings_atom_screen_get(int screen_num)
62 snprintf(buf, sizeof(buf), "_XSETTINGS_S%d", screen_num);
63 return ecore_x_atom_get(buf);
67 _e_xsettings_selection_owner_set(Settings_Manager *sm)
70 Ecore_X_Window cur_selection;
73 atom = _e_xsettings_atom_screen_get(sm->man->num);
74 ecore_x_selection_owner_set(sm->selection, atom, ecore_x_current_time_get());
76 cur_selection = ecore_x_selection_owner_get(atom);
78 ret = (cur_selection == sm->selection);
80 fprintf(stderr, "XSETTINGS: tried to set selection to %#x, but got %#x\n",
81 sm->selection, cur_selection);
87 _e_xsettings_deactivate(Settings_Manager *sm)
91 if (sm->selection == 0) return;
95 _e_xsettings_selection_owner_set(sm);
97 ecore_x_window_free(old);
101 _e_xsettings_activate(Settings_Manager *sm)
104 Ecore_X_Window old_win;
106 if (sm->selection != 0) return 1;
108 atom = _e_xsettings_atom_screen_get(sm->man->num);
109 old_win = ecore_x_selection_owner_get(atom);
110 if (old_win != 0) return 0;
112 sm->selection = ecore_x_window_input_new(0, 0, 0, 1, 1);
113 if (sm->selection == 0)
116 if (!_e_xsettings_selection_owner_set(sm))
118 ecore_x_window_free(sm->selection);
123 ecore_x_client_message32_send(e_manager_current_get()->root, _atom_manager,
124 ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
125 ecore_x_current_time_get(), atom,
126 sm->selection, 0, 0);
128 _e_xsettings_apply(sm);
134 _e_xsettings_activate_retry(void *data)
136 Settings_Manager *sm = data;
139 fputs("XSETTINGS: reactivate...\n", stderr);
140 ret = _e_xsettings_activate(sm);
142 fputs("XSETTINGS: activate success!\n", stderr);
144 fprintf(stderr, "XSETTINGS: activate failure! retrying in %0.1f seconds\n",
148 return ECORE_CALLBACK_RENEW;
150 sm->timer_retry = NULL;
151 return ECORE_CALLBACK_CANCEL;
155 _e_xsettings_retry(Settings_Manager *sm)
157 if (sm->timer_retry) return;
158 sm->timer_retry = ecore_timer_add
159 (RETRY_TIMEOUT, _e_xsettings_activate_retry, sm);
163 _e_xsettings_string_set(const char *name, const char *value)
169 name = eina_stringshare_add(name);
171 EINA_LIST_FOREACH(settings, l, s)
173 if (s->type != SETTING_TYPE_STRING) continue;
174 if (s->name == name) break;
179 DBG("remove %s\n", name);
180 eina_stringshare_del(name);
181 eina_stringshare_del(s->name);
182 eina_stringshare_del(s->s.value);
183 settings = eina_list_remove(settings, s);
189 DBG("update %s %s\n", name, value);
190 eina_stringshare_del(name);
191 eina_stringshare_replace(&s->s.value, value);
195 DBG("add %s %s\n", name, value);
196 s = E_NEW(Setting, 1);
197 s->type = SETTING_TYPE_STRING;
199 s->s.value = eina_stringshare_add(value);
200 settings = eina_list_append(settings, s);
203 /* type + pad + name-len + last-change-serial + str_len */
205 s->length += OFFSET_ADD(strlen(name));
206 s->length += OFFSET_ADD(strlen(value));
207 s->last_change = ecore_x_current_time_get();
212 _e_xsettings_int_set(const char *name, int value, Eina_Bool set)
218 name = eina_stringshare_add(name);
220 EINA_LIST_FOREACH(settings, l, s)
222 if (s->type != SETTING_TYPE_INT) continue;
223 if (s->name == name) break;
228 DBG("remove %s\n", name);
229 eina_stringshare_del(name);
230 eina_stringshare_del(s->name);
231 settings = eina_list_remove(settings, s);
237 DBG("update %s %d\n", name, value);
238 eina_stringshare_del(name);
243 DBG("add %s %d\n", name, value);
244 s = E_NEW(Setting, 1);
245 s->type = SETTING_TYPE_INT;
248 settings = eina_list_append(settings, s);
251 // type + pad + name-len + last-change-serial + value
253 s->length += OFFSET_ADD(strlen(name));
256 static unsigned char *
257 _e_xsettings_copy(unsigned char *buffer, Setting *s)
266 str_len = strlen(s->name);
267 *(CARD16 *)(buffer) = str_len;
270 memcpy(buffer, s->name, str_len);
273 len = OFFSET_ADD(str_len) - str_len;
274 memset(buffer, 0, len);
277 *(CARD32 *)(buffer) = s->last_change;
282 case SETTING_TYPE_INT:
283 *(CARD32 *)(buffer) = s->i.value;
287 case SETTING_TYPE_STRING:
288 str_len = strlen (s->s.value);
289 *(CARD32 *)(buffer) = str_len;
292 memcpy(buffer, s->s.value, str_len);
295 len = OFFSET_ADD(str_len) - str_len;
296 memset(buffer, 0, len);
300 case SETTING_TYPE_COLOR:
301 *(CARD16 *)(buffer) = s->c.red;
302 *(CARD16 *)(buffer + 2) = s->c.green;
303 *(CARD16 *)(buffer + 4) = s->c.blue;
304 *(CARD16 *)(buffer + 6) = s->c.alpha;
313 _e_xsettings_apply(Settings_Manager *sm)
321 EINA_LIST_FOREACH(settings, l, s)
324 pos = data = malloc(len);
327 #if __BYTE_ORDER == __LITTLE_ENDIAN
334 *(CARD32*)pos = sm->serial++;
336 *(CARD32*)pos = eina_list_count(settings);
339 EINA_LIST_FOREACH(settings, l, s)
340 pos = _e_xsettings_copy(pos, s);
342 ecore_x_window_prop_property_set(sm->selection,
350 _e_xsettings_update(void)
352 Settings_Manager *sm;
355 EINA_LIST_FOREACH(managers, l, sm)
356 if (sm->selection) _e_xsettings_apply(sm);
360 _cb_icon_theme_change(void *data __UNUSED__, int type __UNUSED__, void *event)
362 E_Event_Config_Icon_Theme *ev = event;
364 if (e_config->xsettings.match_e17_icon_theme)
366 _e_xsettings_string_set(_setting_icon_theme_name,
368 _e_xsettings_update();
371 return ECORE_CALLBACK_PASS_ON;
376 _e_xsettings_icon_theme_set(void)
378 if (e_config->xsettings.match_e17_icon_theme)
380 _e_xsettings_string_set(_setting_icon_theme_name,
381 e_config->icon_theme);
385 if (e_config->xsettings.net_icon_theme_name)
387 _e_xsettings_string_set(_setting_icon_theme_name,
388 e_config->xsettings.net_icon_theme_name);
392 _e_xsettings_string_set(_setting_icon_theme_name, NULL);
396 _e_xsettings_theme_set(void)
398 if (e_config->xsettings.match_e17_theme)
401 if ((ct = e_theme_config_get("theme")))
405 if ((theme = edje_file_data_get(ct->file, "gtk-theme")))
407 char buf[4096], *dir;
408 Eina_List *xdg_dirs, *l;
410 e_user_homedir_snprintf(buf, sizeof(buf), ".themes/%s", theme);
411 if (ecore_file_exists(buf))
413 _e_xsettings_string_set(_setting_theme_name, theme);
417 xdg_dirs = efreet_data_dirs_get();
418 EINA_LIST_FOREACH(xdg_dirs, l, dir)
420 snprintf(buf, sizeof(buf), "%s/themes/%s", dir, theme);
421 if (ecore_file_exists(buf))
423 _e_xsettings_string_set(_setting_theme_name, theme);
431 if (e_config->xsettings.net_theme_name)
433 _e_xsettings_string_set(_setting_theme_name,
434 e_config->xsettings.net_theme_name);
438 _e_xsettings_string_set(_setting_theme_name, NULL);
442 _e_xsettings_font_set(void)
445 E_Font_Properties *efp;
447 efd = e_font_default_get("application");
449 if (efd && efd->font)
451 efp = e_font_fontconfig_name_parse(efd->font);
454 int size = efd->size;
456 /* TODO better way to convert evas font sizes? */
457 if (size < 0) size /= -10;
458 if (size < 5) size = 5;
459 if (size > 25) size = 25;
461 snprintf(buf, sizeof(buf), "%s %d", efp->name, size);
462 _e_xsettings_string_set(_setting_font_name, buf);
463 e_font_properties_free(efp);
467 e_font_properties_free(efp);
470 _e_xsettings_string_set(_setting_font_name, NULL);
474 _e_xsettings_xft_set(void)
477 if (e_config->scale.use_dpi)
478 _e_xsettings_int_set(_setting_xft_dpi, e_config->scale.base_dpi, EINA_TRUE);
480 _e_xsettings_int_set(_setting_xft_dpi, 0, EINA_FALSE);
485 _e_xsettings_start(void)
492 _e_xsettings_theme_set();
493 _e_xsettings_icon_theme_set();
494 _e_xsettings_font_set();
496 EINA_LIST_FOREACH(e_manager_list(), l, man)
498 Settings_Manager *sm = E_NEW(Settings_Manager, 1);
501 if (!_e_xsettings_activate(sm))
502 _e_xsettings_retry(sm);
504 managers = eina_list_append(managers, sm);
507 handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_CONFIG_ICON_THEME,
508 _cb_icon_theme_change, NULL));
514 _e_xsettings_stop(void)
516 Settings_Manager *sm;
517 Ecore_Event_Handler *h;
520 if (!running) return;
522 EINA_LIST_FREE(managers, sm)
525 ecore_timer_del(sm->timer_retry);
527 _e_xsettings_deactivate(sm);
532 EINA_LIST_FREE(settings, s)
534 if (s->name) eina_stringshare_del(s->name);
535 if (s->s.value) eina_stringshare_del(s->s.value);
539 EINA_LIST_FREE(handlers, h)
540 ecore_event_handler_del(h);
542 running = EINA_FALSE;
546 e_xsettings_init(void)
548 _atom_manager = ecore_x_atom_get("MANAGER");
549 _atom_xsettings = ecore_x_atom_get("_XSETTINGS_SETTINGS");
551 if (e_config->xsettings.enabled)
552 _e_xsettings_start();
558 e_xsettings_shutdown(void)
566 e_xsettings_config_update(void)
568 if (!e_config->xsettings.enabled)
576 _e_xsettings_start();
580 _e_xsettings_theme_set();
581 _e_xsettings_icon_theme_set();
582 _e_xsettings_font_set();
583 _e_xsettings_update();