e_desk: make e_desk's smart object be configuable.
[platform/upstream/enlightenment.git] / src / bin / e_config.c
1 #include "e.h"
2
3 E_API E_Config *e_config = NULL;
4
5 /* local subsystem functions */
6 static void      _e_config_save_cb(void *data);
7 static void      _e_config_free(E_Config *cfg);
8 static Eina_Bool _e_config_cb_timer(void *data);
9 static int       _e_config_eet_close_handle(Eet_File *ef, char *file);
10
11 /* local subsystem globals */
12 static int _e_config_save_block = 0;
13 static const char *_e_config_profile = NULL;
14
15 static E_Config_DD *_e_config_edd = NULL;
16 static E_Config_DD *_e_config_module_edd = NULL;
17 static E_Config_DD *_e_config_theme_edd = NULL;
18 static E_Config_DD *_e_config_desktop_bg_edd = NULL;
19 static E_Config_DD *_e_config_desklock_bg_edd = NULL;
20 static E_Config_DD *_e_config_desktop_name_edd = NULL;
21 static E_Config_DD *_e_config_desktop_window_profile_edd = NULL;
22 static E_Config_DD *_e_config_env_var_edd = NULL;
23 static E_Config_DD *_e_config_client_type_edd = NULL;
24 static E_Config_DD *_e_config_policy_desk_edd = NULL;
25 static E_Config_DD *_e_config_socket_access_edd = NULL;
26 static E_Config_DD *_e_config_aux_hint_supported_edd = NULL;
27
28 E_API int E_EVENT_CONFIG_MODE_CHANGED = 0;
29
30 #if 0
31 static E_Dialog *_e_config_error_dialog = NULL;
32
33 static void
34 _e_config_error_dialog_cb_delete(void *dia)
35 {
36    if (dia == _e_config_error_dialog)
37      _e_config_error_dialog = NULL;
38 }
39 #endif
40
41 static void
42 _e_config_edd_shutdown(void)
43 {
44    E_CONFIG_DD_FREE(_e_config_edd);
45    E_CONFIG_DD_FREE(_e_config_module_edd);
46    E_CONFIG_DD_FREE(_e_config_theme_edd);
47    E_CONFIG_DD_FREE(_e_config_desktop_bg_edd);
48    E_CONFIG_DD_FREE(_e_config_desklock_bg_edd);
49    E_CONFIG_DD_FREE(_e_config_desktop_name_edd);
50    E_CONFIG_DD_FREE(_e_config_desktop_window_profile_edd);
51    E_CONFIG_DD_FREE(_e_config_env_var_edd);
52    E_CONFIG_DD_FREE(_e_config_client_type_edd);
53    E_CONFIG_DD_FREE(_e_config_policy_desk_edd);
54    E_CONFIG_DD_FREE(_e_config_socket_access_edd);
55    E_CONFIG_DD_FREE(_e_config_aux_hint_supported_edd);
56 }
57
58 static void
59 _e_config_edd_init(Eina_Bool old)
60 {
61    _e_config_desktop_bg_edd = E_CONFIG_DD_NEW("E_Config_Desktop_Background", E_Config_Desktop_Background);
62 #undef T
63 #undef D
64 #define T E_Config_Desktop_Background
65 #define D _e_config_desktop_bg_edd
66    E_CONFIG_VAL(D, T, zone, INT);
67    E_CONFIG_VAL(D, T, desk_x, INT);
68    E_CONFIG_VAL(D, T, desk_y, INT);
69    E_CONFIG_VAL(D, T, file, STR);
70
71    _e_config_desktop_name_edd = E_CONFIG_DD_NEW("E_Config_Desktop_Name", E_Config_Desktop_Name);
72 #undef T
73 #undef D
74 #define T E_Config_Desktop_Name
75 #define D _e_config_desktop_name_edd
76    E_CONFIG_VAL(D, T, zone, INT);
77    E_CONFIG_VAL(D, T, desk_x, INT);
78    E_CONFIG_VAL(D, T, desk_y, INT);
79    E_CONFIG_VAL(D, T, name, STR);
80
81    _e_config_desktop_window_profile_edd = E_CONFIG_DD_NEW("E_Config_Desktop_Window_Profile", E_Config_Desktop_Window_Profile);
82 #undef T
83 #undef D
84 #define T E_Config_Desktop_Window_Profile
85 #define D _e_config_desktop_window_profile_edd
86    E_CONFIG_VAL(D, T, zone, INT);
87    E_CONFIG_VAL(D, T, desk_x, INT);
88    E_CONFIG_VAL(D, T, desk_y, INT);
89    E_CONFIG_VAL(D, T, profile, STR);
90
91    _e_config_module_edd = E_CONFIG_DD_NEW("E_Config_Module", E_Config_Module);
92 #undef T
93 #undef D
94 #define T E_Config_Module
95 #define D _e_config_module_edd
96    E_CONFIG_VAL(D, T, name, STR);
97    E_CONFIG_VAL(D, T, enabled, UCHAR);
98    E_CONFIG_VAL(D, T, delayed, UCHAR);
99    E_CONFIG_VAL(D, T, priority, INT);
100
101    _e_config_env_var_edd = E_CONFIG_DD_NEW("E_Config_Env_Var", E_Config_Env_Var);
102 #undef T
103 #undef D
104 #define T E_Config_Env_Var
105 #define D _e_config_env_var_edd
106    E_CONFIG_VAL(D, T, var, STR);
107    E_CONFIG_VAL(D, T, val, STR);
108    E_CONFIG_VAL(D, T, unset, UCHAR);
109
110    _e_config_client_type_edd = E_CONFIG_DD_NEW("E_Config_Client_Type", E_Config_Client_Type);
111 #undef T
112 #undef D
113 #define T E_Config_Client_Type
114 #define D _e_config_client_type_edd
115    E_CONFIG_VAL(D, T, name, STR);
116    E_CONFIG_VAL(D, T, clas, STR);
117    E_CONFIG_VAL(D, T, window_type, INT);
118    E_CONFIG_VAL(D, T, client_type, INT);
119
120    _e_config_policy_desk_edd = E_CONFIG_DD_NEW("E_Config_Policy_Desk", E_Config_Policy_Desk);
121 #undef T
122 #undef D
123 #define T E_Config_Policy_Desk
124 #define D _e_config_policy_desk_edd
125    E_CONFIG_VAL(D, T, zone_num, UINT);
126    E_CONFIG_VAL(D, T, x, INT);
127    E_CONFIG_VAL(D, T, y, INT);
128    E_CONFIG_VAL(D, T, enable, INT);
129
130    _e_config_socket_access_edd = E_CONFIG_DD_NEW("E_Config_Socket_Access", E_Config_Socket_Access);
131 #undef T
132 #undef D
133 #define T E_Config_Socket_Access
134 #define D _e_config_socket_access_edd
135    E_CONFIG_VAL(D, T, sock_access.use, UCHAR);
136    E_CONFIG_VAL(D, T, sock_access.name, STR);
137    E_CONFIG_VAL(D, T, sock_access.owner, STR);
138    E_CONFIG_VAL(D, T, sock_access.group, STR);
139    E_CONFIG_VAL(D, T, sock_access.permissions, INT);
140    E_CONFIG_VAL(D, T, sock_access.smack.use, UCHAR);
141    E_CONFIG_VAL(D, T, sock_access.smack.name, STR);
142    E_CONFIG_VAL(D, T, sock_access.smack.value, STR);
143    E_CONFIG_VAL(D, T, sock_access.smack.flags, INT);
144    E_CONFIG_VAL(D, T, sock_symlink_access.use, UCHAR);
145    E_CONFIG_VAL(D, T, sock_symlink_access.link_name, STR);
146    E_CONFIG_VAL(D, T, sock_symlink_access.owner, STR);
147    E_CONFIG_VAL(D, T, sock_symlink_access.group, STR);
148    E_CONFIG_VAL(D, T, sock_symlink_access.smack.name, STR);
149    E_CONFIG_VAL(D, T, sock_symlink_access.smack.value, STR);
150    E_CONFIG_VAL(D, T, sock_symlink_access.smack.flags, INT);
151
152    _e_config_aux_hint_supported_edd = E_CONFIG_DD_NEW("E_Config_Aux_Hint_Supported", E_Config_Aux_Hint_Supported);
153 #undef T
154 #undef D
155 #define T E_Config_Aux_Hint_Supported
156 #define D _e_config_aux_hint_supported_edd
157    E_CONFIG_VAL(D, T, name, STR);
158
159    _e_config_edd = E_CONFIG_DD_NEW("E_Config", E_Config);
160 #undef T
161 #undef D
162 #define T E_Config
163 #define D _e_config_edd
164    /**/ /* == already configurable via ipc */
165    E_CONFIG_VAL(D, T, config_version, INT);
166    E_CONFIG_VAL(D, T, desktop_default_background, STR);
167    E_CONFIG_VAL(D, T, desktop_default_name, STR);
168    E_CONFIG_VAL(D, T, desktop_default_window_profile, STR);
169    E_CONFIG_LIST(D, T, desktop_backgrounds, _e_config_desktop_bg_edd);
170    E_CONFIG_LIST(D, T, desktop_names, _e_config_desktop_name_edd);
171    E_CONFIG_LIST(D, T, desktop_window_profiles, _e_config_desktop_window_profile_edd);
172    E_CONFIG_VAL(D, T, framerate, DOUBLE);
173    E_CONFIG_VAL(D, T, priority, INT);
174    E_CONFIG_VAL(D, T, zone_desks_x_count, INT);
175    E_CONFIG_VAL(D, T, zone_desks_y_count, INT);
176    E_CONFIG_LIST(D, T, modules, _e_config_module_edd);
177    E_CONFIG_VAL(D, T, window_placement_policy, INT);
178    E_CONFIG_VAL(D, T, use_e_policy, INT);
179    E_CONFIG_VAL(D, T, launcher.title, STR);
180    E_CONFIG_VAL(D, T, launcher.clas, STR);
181    E_CONFIG_VAL(D, T, launcher.type, UINT);
182    E_CONFIG_LIST(D, T, policy_desks, _e_config_policy_desk_edd);
183    E_CONFIG_VAL(D, T, use_softkey, INT);
184    E_CONFIG_VAL(D, T, softkey_size, INT);
185    E_CONFIG_VAL(D, T, focus_policy, INT);
186    E_CONFIG_VAL(D, T, focus_policy_ext, INT);
187    E_CONFIG_VAL(D, T, focus_setting, INT);
188    E_CONFIG_VAL(D, T, always_click_to_raise, INT);
189    E_CONFIG_VAL(D, T, always_click_to_focus, INT);
190    E_CONFIG_VAL(D, T, use_auto_raise, INT);
191    E_CONFIG_VAL(D, T, maximize_policy, INT);
192    E_CONFIG_VAL(D, T, allow_manip, INT);
193    E_CONFIG_VAL(D, T, kill_if_close_not_possible, INT);
194    E_CONFIG_VAL(D, T, kill_process, INT);
195    E_CONFIG_VAL(D, T, kill_timer_wait, DOUBLE);
196    E_CONFIG_VAL(D, T, ping_clients, INT);
197    E_CONFIG_VAL(D, T, use_e_cursor, INT);
198    E_CONFIG_VAL(D, T, cursor_size, INT);
199    E_CONFIG_VAL(D, T, transient.move, INT);
200    E_CONFIG_VAL(D, T, transient.resize, INT);
201    E_CONFIG_VAL(D, T, transient.raise, INT);
202    E_CONFIG_VAL(D, T, transient.lower, INT);
203    E_CONFIG_VAL(D, T, transient.layer, INT);
204    E_CONFIG_VAL(D, T, transient.desktop, INT);
205    E_CONFIG_VAL(D, T, transient.iconify, INT);
206    E_CONFIG_VAL(D, T, fullscreen_policy, INT);
207    E_CONFIG_VAL(D, T, dpms_enable, INT);
208    E_CONFIG_VAL(D, T, dpms_standby_enable, INT);
209    E_CONFIG_VAL(D, T, dpms_suspend_enable, INT);
210    E_CONFIG_VAL(D, T, dpms_off_enable, INT);
211    E_CONFIG_VAL(D, T, dpms_standby_timeout, INT);
212    E_CONFIG_VAL(D, T, dpms_suspend_timeout, INT);
213    E_CONFIG_VAL(D, T, dpms_off_timeout, INT);
214    E_CONFIG_VAL(D, T, no_dpms_on_fullscreen, UCHAR);
215    E_CONFIG_VAL(D, T, mouse_hand, INT);
216    E_CONFIG_VAL(D, T, border_raise_on_mouse_action, INT);
217    E_CONFIG_VAL(D, T, border_raise_on_focus, INT);
218    E_CONFIG_VAL(D, T, raise_on_revert_focus, INT);
219    E_CONFIG_VAL(D, T, theme_default_border_style, STR);
220    E_CONFIG_VAL(D, T, screen_limits, INT);
221    E_CONFIG_VAL(D, T, ping_clients_interval, INT);
222    E_CONFIG_VAL(D, T, border_keyboard.timeout, DOUBLE);
223    E_CONFIG_VAL(D, T, border_keyboard.move.dx, UCHAR);
224    E_CONFIG_VAL(D, T, border_keyboard.move.dy, UCHAR);
225    E_CONFIG_VAL(D, T, border_keyboard.resize.dx, UCHAR);
226    E_CONFIG_VAL(D, T, border_keyboard.resize.dy, UCHAR);
227    E_CONFIG_VAL(D, T, scale.min, DOUBLE);
228    E_CONFIG_VAL(D, T, scale.max, DOUBLE);
229    E_CONFIG_VAL(D, T, scale.factor, DOUBLE);
230    E_CONFIG_VAL(D, T, scale.base_dpi, INT);
231    E_CONFIG_VAL(D, T, scale.use_dpi, UCHAR);
232    E_CONFIG_VAL(D, T, scale.use_custom, UCHAR);
233    E_CONFIG_VAL(D, T, show_cursor, UCHAR);
234    E_CONFIG_VAL(D, T, idle_cursor, UCHAR);
235    E_CONFIG_LIST(D, T, env_vars, _e_config_env_var_edd);
236    E_CONFIG_VAL(D, T, xkb.only_label, INT);
237    E_CONFIG_VAL(D, T, xkb.default_model, STR);
238    E_CONFIG_VAL(D, T, xkb.dont_touch_my_damn_keyboard, UCHAR);
239    E_CONFIG_VAL(D, T, xkb.use_cache, UCHAR);
240    E_CONFIG_VAL(D, T, xkb.delay_held_key_input_to_focus, UINT);
241    E_CONFIG_VAL(D, T, xkb.default_rmlvo.rules, STR);
242    E_CONFIG_VAL(D, T, xkb.default_rmlvo.model, STR);
243    E_CONFIG_VAL(D, T, xkb.default_rmlvo.layout, STR);
244    E_CONFIG_VAL(D, T, xkb.default_rmlvo.variant, STR);
245    E_CONFIG_VAL(D, T, xkb.default_rmlvo.options, STR);
246    E_CONFIG_VAL(D, T, keyboard.repeat_delay, INT);
247    E_CONFIG_VAL(D, T, keyboard.repeat_rate, INT);
248    E_CONFIG_VAL(D, T, use_desktop_window_profile, INT);
249 #ifdef _F_ZONE_WINDOW_ROTATION_
250    E_CONFIG_VAL(D, T, wm_win_rotation, UCHAR);
251 #endif
252    E_CONFIG_VAL(D, T, use_cursor_timer, INT);
253    E_CONFIG_VAL(D, T, cursor_timer_interval, INT);
254    E_CONFIG_LIST(D, T, client_types, _e_config_client_type_edd);
255    E_CONFIG_VAL(D, T, comp_shadow_file, STR);
256    E_CONFIG_VAL(D, T, sleep_for_dri, INT);
257    E_CONFIG_VAL(D, T, create_wm_ready, INT);
258    E_CONFIG_VAL(D, T, create_wm_start, INT);
259    E_CONFIG_VAL(D, T, comp_canvas_bg.r, UCHAR);
260    E_CONFIG_VAL(D, T, comp_canvas_bg.g, UCHAR);
261    E_CONFIG_VAL(D, T, comp_canvas_bg.b, UCHAR);
262    E_CONFIG_VAL(D, T, comp_canvas_bg.a, UCHAR);
263    E_CONFIG_VAL(D, T, comp_canvas_bg.opmode, INT);
264    E_CONFIG_VAL(D, T, delayed_load_idle_count, INT);
265    E_CONFIG_VAL(D, T, use_buffer_flush, UCHAR);
266    E_CONFIG_VAL(D, T, use_desk_smart_obj, UCHAR);
267    E_CONFIG_LIST(D, T, sock_accesses, _e_config_socket_access_edd);
268    E_CONFIG_LIST(D, T, aux_hint_supported, _e_config_aux_hint_supported_edd);
269    E_CONFIG_VAL(D, T, use_module_srv.qp, UCHAR);
270    E_CONFIG_VAL(D, T, launchscreen_timeout, DOUBLE);
271 }
272
273 /* externally accessible functions */
274 EINTERN int
275 e_config_init(void)
276 {
277    E_EVENT_CONFIG_MODE_CHANGED = ecore_event_type_new();
278
279    /* TIZEN_ONLY: We don't save e.cfg file.
280     * Sometimes e.cfg file was broken after writing.
281     */
282    e_config_save_block_set(1);
283
284    /* if environment var set - use this profile name */
285    _e_config_profile = eina_stringshare_add(getenv("E_CONF_PROFILE"));
286
287    _e_config_edd_init(EINA_FALSE);
288
289    e_config_load();
290    EINA_SAFETY_ON_NULL_RETURN_VAL(e_config, 0);
291
292    e_config_save_queue();
293    return 1;
294 }
295
296 EINTERN int
297 e_config_shutdown(void)
298 {
299    eina_stringshare_del(_e_config_profile);
300
301    _e_config_edd_shutdown();
302
303    return 1;
304 }
305
306 E_API void
307 e_config_load(void)
308 {
309    int reload = 0;
310
311    e_config = e_config_domain_load("e", _e_config_edd);
312    if (e_config)
313      {
314         /* major version change - that means wipe and restart */
315         if ((e_config->config_version) < E_CONFIG_FILE_EPOCH * 1000000)
316           {
317              /* your config is too old - need new defaults */
318              _e_config_free(e_config);
319              e_config = NULL;
320              reload = 1;
321              ecore_timer_add(1.0, _e_config_cb_timer,
322                              _("Settings data needed upgrading. Your old settings have<br>"
323                                "been wiped and a new set of defaults initialized. This<br>"
324                                "will happen regularly during development, so don't report a<br>"
325                                "bug. This simply means Enlightenment needs new settings<br>"
326                                "data by default for usable functionality that your old<br>"
327                                "settings simply lack. This new set of defaults will fix<br>"
328                                "that by adding it in. You can re-configure things now to your<br>"
329                                "liking. Sorry for the hiccup in your settings.<br>"));
330           }
331         /* config is too new? odd! suspect corruption? */
332         else if (e_config->config_version > E_CONFIG_FILE_VERSION)
333           {
334              /* your config is too new - what the fuck??? */
335              _e_config_free(e_config);
336              e_config = NULL;
337              reload = 1;
338              ecore_timer_add(1.0, _e_config_cb_timer,
339                              _("Your settings are NEWER than Enlightenment. This is very<br>"
340                                "strange. This should not happen unless you downgraded<br>"
341                                "Enlightenment or copied the settings from a place where<br>"
342                                "a newer version of Enlightenment was running. This is bad and<br>"
343                                "as a precaution your settings have been now restored to<br>"
344                                "defaults. Sorry for the inconvenience.<br>"));
345           }
346         if (reload)
347           {
348              e_config_profile_del(e_config_profile_get());
349              e_config_profile_set("default");
350              e_config = e_config_domain_load("e", _e_config_edd);
351           }
352      }
353    while (!e_config)
354      {
355         _e_config_edd_shutdown();
356         _e_config_edd_init(EINA_TRUE);
357         e_config = e_config_domain_load("e", _e_config_edd);
358         /* I made a c&p error here and fucked the world, so this ugliness
359          * will be my public mark of shame until E :/
360          * -zmike, 2013
361          */
362         if (e_config)
363           {
364              /* this is essentially CONFIG_VERSION_CHECK(7) */
365              INF("Performing config upgrade to %d.%d", 1, 7);
366              _e_config_edd_shutdown();
367              _e_config_edd_init(EINA_FALSE);
368              break;
369           }
370 #undef T
371 #undef D
372         e_config_profile_set("default");
373         if (!reload) e_config_profile_del(e_config_profile_get());
374         e_config_save_block_set(1);
375         e_error_message_show(_("Could not load e.cfg"));
376         return;
377      }
378
379 #define CONFIG_VERSION_CHECK(VERSION) \
380   if (e_config->config_version - (E_CONFIG_FILE_EPOCH * 1000000) < (VERSION))
381
382 #define CONFIG_VERSION_UPDATE_INFO(VERSION) \
383   INF("Performing config upgrade for %d.%d", E_CONFIG_FILE_EPOCH, VERSION);
384
385    if (e_config->config_version < E_CONFIG_FILE_VERSION)
386      {
387         CONFIG_VERSION_CHECK(18)
388           {
389              ;
390           }
391         CONFIG_VERSION_CHECK(19)
392           {
393              CONFIG_VERSION_UPDATE_INFO(19);
394
395              /* set (400, 25) as the default values of repeat delay, rate */
396              e_config->keyboard.repeat_delay = 400;
397              e_config->keyboard.repeat_rate = 25;
398           }
399      }
400
401    e_config->config_version = E_CONFIG_FILE_VERSION;
402
403    /* limit values so they are sane */
404    E_CONFIG_LIMIT(e_config->framerate, 1.0, 200.0);
405    E_CONFIG_LIMIT(e_config->priority, 0, 19);
406    E_CONFIG_LIMIT(e_config->zone_desks_x_count, 1, 64);
407    E_CONFIG_LIMIT(e_config->zone_desks_y_count, 1, 64);
408    E_CONFIG_LIMIT(e_config->use_e_policy, 0, 1);
409    E_CONFIG_LIMIT(e_config->use_softkey, 0, 1);
410    E_CONFIG_LIMIT(e_config->softkey_size, 0, 42);
411    E_CONFIG_LIMIT(e_config->window_placement_policy, E_WINDOW_PLACEMENT_SMART, E_WINDOW_PLACEMENT_MANUAL);
412    E_CONFIG_LIMIT(e_config->focus_policy, 0, 2);
413    E_CONFIG_LIMIT(e_config->focus_policy_ext, 0, 1);
414    E_CONFIG_LIMIT(e_config->focus_setting, 0, 3);
415    E_CONFIG_LIMIT(e_config->always_click_to_raise, 0, 1);
416    E_CONFIG_LIMIT(e_config->always_click_to_focus, 0, 1);
417    E_CONFIG_LIMIT(e_config->use_auto_raise, 0, 1);
418    E_CONFIG_LIMIT(e_config->maximize_policy, E_MAXIMIZE_FULLSCREEN, E_MAXIMIZE_DIRECTION);
419    E_CONFIG_LIMIT(e_config->allow_manip, 0, 1);
420    E_CONFIG_LIMIT(e_config->kill_if_close_not_possible, 0, 1);
421    E_CONFIG_LIMIT(e_config->kill_process, 0, 1);
422    E_CONFIG_LIMIT(e_config->kill_timer_wait, 0.0, 120.0);
423    E_CONFIG_LIMIT(e_config->ping_clients, 0, 1);
424    E_CONFIG_LIMIT(e_config->use_e_cursor, 0, 1);
425    E_CONFIG_LIMIT(e_config->cursor_size, 0, 1024);
426    E_CONFIG_LIMIT(e_config->dpms_enable, 0, 1);
427    E_CONFIG_LIMIT(e_config->dpms_standby_enable, 0, 1);
428    E_CONFIG_LIMIT(e_config->dpms_suspend_enable, 0, 1);
429    E_CONFIG_LIMIT(e_config->dpms_off_enable, 0, 1);
430    E_CONFIG_LIMIT(e_config->dpms_standby_timeout, 30, 5400);
431    E_CONFIG_LIMIT(e_config->dpms_suspend_timeout, 30, 5400);
432    E_CONFIG_LIMIT(e_config->dpms_off_timeout, 30, 5400);
433    E_CONFIG_LIMIT(e_config->mouse_hand, 0, 1);
434    E_CONFIG_LIMIT(e_config->border_raise_on_mouse_action, 0, 1);
435    E_CONFIG_LIMIT(e_config->border_raise_on_focus, 0, 1);
436    E_CONFIG_LIMIT(e_config->raise_on_revert_focus, 0, 1);
437    E_CONFIG_LIMIT(e_config->screen_limits, 0, 2);
438    E_CONFIG_LIMIT(e_config->ping_clients_interval, 16, 1024);
439    E_CONFIG_LIMIT(e_config->border_keyboard.move.dx, 1, 255);
440    E_CONFIG_LIMIT(e_config->border_keyboard.move.dy, 1, 255);
441    E_CONFIG_LIMIT(e_config->border_keyboard.resize.dx, 1, 255);
442    E_CONFIG_LIMIT(e_config->border_keyboard.resize.dy, 1, 255);
443    E_CONFIG_LIMIT(e_config->show_cursor, 0, 1);
444    E_CONFIG_LIMIT(e_config->xkb.delay_held_key_input_to_focus, 0,5000); // 5000(ms) == 5(s)
445    E_CONFIG_LIMIT(e_config->keyboard.repeat_delay, -1, 1000); // 1 second
446    E_CONFIG_LIMIT(e_config->keyboard.repeat_rate, -1, 1000); // 1 second
447    E_CONFIG_LIMIT(e_config->use_cursor_timer, 0, 1);
448    E_CONFIG_LIMIT(e_config->sleep_for_dri, 0, 1);
449    E_CONFIG_LIMIT(e_config->create_wm_ready, 0, 1);
450    E_CONFIG_LIMIT(e_config->create_wm_start, 0, 1);
451    E_CONFIG_LIMIT(e_config->comp_canvas_bg.r, 0, 255);
452    E_CONFIG_LIMIT(e_config->comp_canvas_bg.g, 0, 255);
453    E_CONFIG_LIMIT(e_config->comp_canvas_bg.b, 0, 255);
454    E_CONFIG_LIMIT(e_config->comp_canvas_bg.a, 0, 255);
455    E_CONFIG_LIMIT(e_config->comp_canvas_bg.opmode, 0, 11);
456    E_CONFIG_LIMIT(e_config->delayed_load_idle_count, 0, 100);
457    E_CONFIG_LIMIT(e_config->use_buffer_flush, 0, 1);
458    E_CONFIG_LIMIT(e_config->use_desk_smart_obj, 0, 1);
459    E_CONFIG_LIMIT(e_config->use_module_srv.qp, 0, 1);
460    E_CONFIG_LIMIT(e_config->launchscreen_timeout, 7.0, 100.0);
461 }
462
463 E_API int
464 e_config_save(void)
465 {
466    _e_config_save_cb(NULL);
467    return e_config_domain_save("e", _e_config_edd, e_config);
468 }
469
470 E_API void
471 e_config_save_queue(void)
472 {
473    // TODO: add ecore_timer_add and call _e_config_save_cb
474    _e_config_save_cb(NULL);
475 }
476
477 E_API const char *
478 e_config_profile_get(void)
479 {
480    return _e_config_profile;
481 }
482
483 E_API void
484 e_config_profile_set(const char *prof)
485 {
486    eina_stringshare_replace(&_e_config_profile, prof);
487    e_util_env_set("E_CONF_PROFILE", _e_config_profile);
488 }
489
490 E_API char *
491 e_config_profile_dir_get(const char *prof)
492 {
493    char buf[PATH_MAX];
494
495    e_user_dir_snprintf(buf, sizeof(buf), "config/%s", prof);
496    if (ecore_file_is_dir(buf)) return strdup(buf);
497    e_prefix_data_snprintf(buf, sizeof(buf), "data/config/%s", prof);
498    if (ecore_file_is_dir(buf)) return strdup(buf);
499    return NULL;
500 }
501
502 static int
503 _cb_sort_files(char *f1, char *f2)
504 {
505    return strcmp(f1, f2);
506 }
507
508 E_API Eina_List *
509 e_config_profile_list(void)
510 {
511    Eina_List *files;
512    char buf[PATH_MAX], *p;
513    Eina_List *flist = NULL;
514    size_t len;
515
516    len = e_user_dir_concat_static(buf, "config");
517    if (len + 1 >= (int)sizeof(buf))
518      return NULL;
519
520    files = ecore_file_ls(buf);
521
522    buf[len] = '/';
523    len++;
524
525    p = buf + len;
526    len = sizeof(buf) - len;
527    if (files)
528      {
529         char *file;
530
531         files = eina_list_sort(files, 0, (Eina_Compare_Cb)_cb_sort_files);
532         EINA_LIST_FREE(files, file)
533           {
534              if (eina_strlcpy(p, file, len) >= len)
535                {
536                   free(file);
537                   continue;
538                }
539              if (ecore_file_is_dir(buf))
540                flist = eina_list_append(flist, file);
541              else
542                free(file);
543           }
544      }
545    len = e_prefix_data_concat_static(buf, "data/config");
546    if (len + 1 >= sizeof(buf))
547      return NULL;
548
549    files = ecore_file_ls(buf);
550
551    buf[len] = '/';
552    len++;
553
554    p = buf + len;
555    len = sizeof(buf) - len;
556    if (files)
557      {
558         char *file;
559         files = eina_list_sort(files, 0, (Eina_Compare_Cb)_cb_sort_files);
560         EINA_LIST_FREE(files, file)
561           {
562              if (eina_strlcpy(p, file, len) >= len)
563                {
564                   free(file);
565                   continue;
566                }
567              if (ecore_file_is_dir(buf))
568                {
569                   const Eina_List *l;
570                   const char *tmp;
571                   EINA_LIST_FOREACH(flist, l, tmp)
572                     if (!strcmp(file, tmp)) break;
573
574                   if (!l) flist = eina_list_append(flist, file);
575                   else free(file);
576                }
577              else
578                free(file);
579           }
580      }
581    return flist;
582 }
583
584 E_API void
585 e_config_profile_add(const char *prof)
586 {
587    char buf[4096];
588    if (e_user_dir_snprintf(buf, sizeof(buf), "config/%s", prof) >= sizeof(buf))
589      return;
590    ecore_file_mkdir(buf);
591 }
592
593 E_API void
594 e_config_profile_del(const char *prof)
595 {
596    char buf[4096];
597    if (e_user_dir_snprintf(buf, sizeof(buf), "config/%s", prof) >= sizeof(buf))
598      return;
599    ecore_file_recursive_rm(buf);
600 }
601
602 E_API void
603 e_config_save_block_set(int block)
604 {
605    _e_config_save_block = block;
606 }
607
608 E_API int
609 e_config_save_block_get(void)
610 {
611    return _e_config_save_block;
612 }
613
614 /**
615  * Loads configurations from file located in the working profile
616  * The configurations are stored in a struct declated by the
617  * macros E_CONFIG_DD_NEW and E_CONFIG_<b>TYPE</b>
618  *
619  * @param domain of the configuration file.
620  * @param edd to struct definition
621  * @return returns allocated struct on success, if unable to find config returns null
622  */
623 E_API void *
624 e_config_domain_load(const char *domain, E_Config_DD *edd)
625 {
626    Eet_File *ef;
627    char buf[4096];
628    void *data = NULL;
629
630    e_user_dir_snprintf(buf, sizeof(buf), "config/%s/%s.cfg",
631                        _e_config_profile, domain);
632    ef = eet_open(buf, EET_FILE_MODE_READ);
633    if (ef)
634      {
635         data = eet_data_read(ef, edd, "config");
636         _e_config_eet_close_handle(ef, buf);
637         if (data)
638           {
639              ELOGF("CFG", "Loaded %s", NULL, NULL, buf);
640              return data;
641           }
642      }
643    else
644      {
645         ELOGF("CFG", "Could not load %s", NULL, NULL, buf);
646      }
647
648    return e_config_domain_system_load(domain, edd);
649 }
650
651 E_API void *
652 e_config_domain_system_load(const char *domain, E_Config_DD *edd)
653 {
654    Eet_File *ef;
655    char buf[4096];
656    void *data = NULL;
657
658    e_prefix_data_snprintf(buf, sizeof(buf), "data/config/%s/%s.cfg",
659                           _e_config_profile, domain);
660    ef = eet_open(buf, EET_FILE_MODE_READ);
661    if (ef)
662      {
663         data = eet_data_read(ef, edd, "config");
664         _e_config_eet_close_handle(ef, buf);
665         if (data)
666           {
667              ELOGF("CFG", "Loaded %s", NULL, NULL, buf);
668              return data;
669           }
670
671         ELOGF("CFG", "Could not read data %s", NULL, NULL, buf);
672      }
673
674    ELOGF("CFG", "Could not load %s", NULL, NULL, buf);
675
676    return data;
677 }
678
679 #if 0
680 static void
681 _e_config_mv_error(const char *from, const char *to)
682 {
683    E_Dialog *dia;
684    char buf[8192];
685
686    if (_e_config_error_dialog) return;
687
688    dia = e_dialog_new(NULL, "E", "_sys_error_logout_slow");
689    EINA_SAFETY_ON_NULL_RETURN(dia);
690
691    e_dialog_title_set(dia, _("Enlightenment Settings Write Problems"));
692    e_dialog_icon_set(dia, "dialog-error", 64);
693    snprintf(buf, sizeof(buf),
694             _("Enlightenment has had an error while moving config files<br>"
695               "from:<br>"
696               "%s<br>"
697               "<br>"
698               "to:<br>"
699               "%s<br>"
700               "<br>"
701               "The rest of the write has been aborted for safety.<br>"),
702             from, to);
703    e_dialog_text_set(dia, buf);
704    e_dialog_button_add(dia, _("OK"), NULL, NULL, NULL);
705    e_dialog_button_focus_num(dia, 0);
706    //elm_win_center(dia->win, 1, 1);
707    e_object_del_attach_func_set(E_OBJECT(dia),
708                                 _e_config_error_dialog_cb_delete);
709    e_dialog_show(dia);
710    _e_config_error_dialog = dia;
711 }
712 #endif
713
714 E_API int
715 e_config_profile_save(void)
716 {
717 #if 0
718    Eet_File *ef;
719    char buf[4096], buf2[4096];
720    int ok = 0;
721
722    /* FIXME: check for other sessions fo E running */
723    e_user_dir_concat_static(buf, "config/profile.cfg");
724    e_user_dir_concat_static(buf2, "config/profile.cfg.tmp");
725
726    ef = eet_open(buf2, EET_FILE_MODE_WRITE);
727    if (ef)
728      {
729         ok = eet_write(ef, "config", _e_config_profile,
730                        strlen(_e_config_profile), 0);
731         if (_e_config_eet_close_handle(ef, buf2))
732           {
733              Eina_Bool ret = EINA_TRUE;
734
735              if (_e_config_revisions > 0)
736                {
737                   int i;
738                   char bsrc[4096], bdst[4096];
739
740                   for (i = _e_config_revisions; i > 1; i--)
741                     {
742                        e_user_dir_snprintf(bsrc, sizeof(bsrc), "config/profile.%i.cfg", i - 1);
743                        e_user_dir_snprintf(bdst, sizeof(bdst), "config/profile.%i.cfg", i);
744                        if ((ecore_file_exists(bsrc)) &&
745                            (ecore_file_size(bsrc)))
746                          {
747                             ret = ecore_file_mv(bsrc, bdst);
748                             if (!ret)
749                               {
750                                  _e_config_mv_error(bsrc, bdst);
751                                  break;
752                               }
753                          }
754                     }
755                   if (ret)
756                     {
757                        e_user_dir_snprintf(bsrc, sizeof(bsrc), "config/profile.cfg");
758                        e_user_dir_snprintf(bdst, sizeof(bdst), "config/profile.1.cfg");
759                        ret = ecore_file_mv(bsrc, bdst);
760 //                       if (!ret)
761 //                          _e_config_mv_error(bsrc, bdst);
762                     }
763                }
764              ret = ecore_file_mv(buf2, buf);
765              if (!ret) _e_config_mv_error(buf2, buf);
766           }
767         ecore_file_unlink(buf2);
768      }
769    return ok;
770 #else
771    return 1;
772 #endif
773 }
774
775 /**
776  * Saves configurations to file located in the working profile
777  * The configurations are read from a struct declated by the
778  * macros E_CONFIG_DD_NEW and E_CONFIG_<b>TYPE</b>
779  *
780  * @param domain  name of the configuration file.
781  * @param edd pointer to struct definition
782  * @param data struct to save as configuration file
783  * @return 1 if save success, 0 on failure
784  */
785 E_API int
786 e_config_domain_save(const char *domain, E_Config_DD *edd, const void *data)
787 {
788    Eet_File *ef;
789    char buf[4096], buf2[4096];
790    int ok = 0, ret;
791    size_t len, len2;
792
793    if (_e_config_save_block) return 0;
794    /* FIXME: check for other sessions fo E running */
795    len = e_user_dir_snprintf(buf, sizeof(buf), "config/%s", _e_config_profile);
796    if (len + 1 >= sizeof(buf)) return 0;
797
798    ecore_file_mkdir(buf);
799
800    buf[len] = '/';
801    len++;
802
803    len2 = eina_strlcpy(buf + len, domain, sizeof(buf) - len);
804    if (len2 + sizeof(".cfg") >= sizeof(buf) - len) return 0;
805
806    len += len2;
807
808    memcpy(buf + len, ".cfg", sizeof(".cfg"));
809    len += sizeof(".cfg") - 1;
810
811    if (len + sizeof(".tmp") >= sizeof(buf)) return 0;
812    memcpy(buf2, buf, len);
813    memcpy(buf2 + len, ".tmp", sizeof(".tmp"));
814
815    ef = eet_open(buf2, EET_FILE_MODE_WRITE);
816    if (ef)
817      {
818         ok = eet_data_write(ef, edd, "config", data, 1);
819         if (_e_config_eet_close_handle(ef, buf2))
820           {
821              ret = ecore_file_mv(buf2, buf);
822              if (!ret)
823                ERR("*** Error saving config. ***");
824           }
825         ecore_file_unlink(buf2);
826      }
827    return ok;
828 }
829
830 E_API void
831 e_config_mode_changed(void)
832 {
833    ecore_event_add(E_EVENT_CONFIG_MODE_CHANGED, NULL, NULL, NULL);
834 }
835
836 /* local subsystem functions */
837 static void
838 _e_config_save_cb(void *data EINA_UNUSED)
839 {
840    e_config_profile_save();
841    e_module_save_all();
842    e_config_domain_save("e", _e_config_edd, e_config);
843 }
844
845 static void
846 _e_config_free(E_Config *ecf)
847 {
848    E_Config_Module *em;
849    E_Config_Env_Var *evr;
850    E_Config_Desktop_Window_Profile *wp;
851    E_Config_Policy_Desk *pd;
852    E_Config_Socket_Access *sa;
853    E_Config_Aux_Hint_Supported *auxhint;
854
855    if (!ecf) return;
856
857    EINA_LIST_FREE(ecf->desktop_window_profiles, wp)
858      {
859         eina_stringshare_del(wp->profile);
860         E_FREE(wp);
861      }
862
863    eina_stringshare_del(ecf->xkb.default_model);
864    eina_stringshare_del(ecf->xkb.default_rmlvo.rules);
865    eina_stringshare_del(ecf->xkb.default_rmlvo.model);
866    eina_stringshare_del(ecf->xkb.default_rmlvo.layout);
867    eina_stringshare_del(ecf->xkb.default_rmlvo.variant);
868    eina_stringshare_del(ecf->xkb.default_rmlvo.options);
869
870    EINA_LIST_FREE(ecf->modules, em)
871      {
872         if (em->name) eina_stringshare_del(em->name);
873         E_FREE(em);
874      }
875    if (ecf->comp_shadow_file) eina_stringshare_del(ecf->comp_shadow_file);
876    if (ecf->desktop_default_background) eina_stringshare_del(ecf->desktop_default_background);
877    if (ecf->desktop_default_name) eina_stringshare_del(ecf->desktop_default_name);
878    if (ecf->desktop_default_window_profile) eina_stringshare_del(ecf->desktop_default_window_profile);
879    if (ecf->theme_default_border_style) eina_stringshare_del(ecf->theme_default_border_style);
880    EINA_LIST_FREE(ecf->env_vars, evr)
881      {
882         if (evr->var) eina_stringshare_del(evr->var);
883         if (evr->val) eina_stringshare_del(evr->val);
884         E_FREE(evr);
885      }
886
887    EINA_LIST_FREE(ecf->policy_desks, pd)
888       E_FREE(pd);
889
890    eina_stringshare_del(ecf->launcher.title);
891    eina_stringshare_del(ecf->launcher.clas);
892
893    EINA_LIST_FREE(ecf->sock_accesses, sa)
894      {
895         eina_stringshare_del(sa->sock_access.name);
896         eina_stringshare_del(sa->sock_access.owner);
897         eina_stringshare_del(sa->sock_access.group);
898         eina_stringshare_del(sa->sock_access.smack.name);
899         eina_stringshare_del(sa->sock_access.smack.value);
900         eina_stringshare_del(sa->sock_symlink_access.link_name);
901         eina_stringshare_del(sa->sock_symlink_access.owner);
902         eina_stringshare_del(sa->sock_symlink_access.group);
903         eina_stringshare_del(sa->sock_symlink_access.smack.name);
904         eina_stringshare_del(sa->sock_symlink_access.smack.value);
905         E_FREE(sa);
906      }
907
908    EINA_LIST_FREE(ecf->aux_hint_supported, auxhint)
909      {
910         eina_stringshare_del(auxhint->name);
911         E_FREE(auxhint);
912      }
913
914    E_FREE(ecf);
915 }
916
917 static Eina_Bool
918 _e_config_cb_timer(void *data)
919 {
920    e_util_dialog_show(_("Settings Upgraded"), "%s", (char *)data);
921    return 0;
922 }
923
924 static int
925 _e_config_eet_close_handle(Eet_File *ef, char *file)
926 {
927    Eet_Error err;
928    char *erstr = NULL;
929
930    err = eet_close(ef);
931    switch (err)
932      {
933       case EET_ERROR_NONE:
934         /* all good - no error */
935         break;
936
937       case EET_ERROR_BAD_OBJECT:
938         erstr = _("The EET file handle is bad.");
939         break;
940
941       case EET_ERROR_EMPTY:
942         erstr = _("The file data is empty.");
943         break;
944
945       case EET_ERROR_NOT_WRITABLE:
946         erstr = _("The file is not writable. Perhaps the disk is read-only<br>or you lost permissions to your files.");
947         break;
948
949       case EET_ERROR_OUT_OF_MEMORY:
950         erstr = _("Memory ran out while preparing the write.<br>Please free up memory.");
951         break;
952
953       case EET_ERROR_WRITE_ERROR:
954         erstr = _("This is a generic error.");
955         break;
956
957       case EET_ERROR_WRITE_ERROR_FILE_TOO_BIG:
958         erstr = _("The settings file is too large.<br>It should be very small (a few hundred KB at most).");
959         break;
960
961       case EET_ERROR_WRITE_ERROR_IO_ERROR:
962         erstr = _("You have I/O errors on the disk.<br>Maybe it needs replacing?");
963         break;
964
965       case EET_ERROR_WRITE_ERROR_OUT_OF_SPACE:
966         erstr = _("You ran out of space while writing the file.");
967         break;
968
969       case EET_ERROR_WRITE_ERROR_FILE_CLOSED:
970         erstr = _("The file was closed while writing.");
971         break;
972
973       case EET_ERROR_MMAP_FAILED:
974         erstr = _("Memory-mapping (mmap) of the file failed.");
975         break;
976
977       case EET_ERROR_X509_ENCODING_FAILED:
978         erstr = _("X509 Encoding failed.");
979         break;
980
981       case EET_ERROR_SIGNATURE_FAILED:
982         erstr = _("Signature failed.");
983         break;
984
985       case EET_ERROR_INVALID_SIGNATURE:
986         erstr = _("The signature was invalid.");
987         break;
988
989       case EET_ERROR_NOT_SIGNED:
990         erstr = _("Not signed.");
991         break;
992
993       case EET_ERROR_NOT_IMPLEMENTED:
994         erstr = _("Feature not implemented.");
995         break;
996
997       case EET_ERROR_PRNG_NOT_SEEDED:
998         erstr = _("PRNG was not seeded.");
999         break;
1000
1001       case EET_ERROR_ENCRYPT_FAILED:
1002         erstr = _("Encryption failed.");
1003         break;
1004
1005       case EET_ERROR_DECRYPT_FAILED:
1006         erstr = _("Decryption failed.");
1007         break;
1008
1009       default: /* if we get here eet added errors we don't know */
1010         erstr = _("The error is unknown to Enlightenment.");
1011         break;
1012      }
1013    if (erstr)
1014      {
1015         // TODO - yigl
1016 #if 0
1017         /* delete any partially-written file */
1018         ecore_file_unlink(file);
1019         /* only show dialog for first error - further ones are likely */
1020         /* more of the same error */
1021         if (!_e_config_error_dialog)
1022           {
1023              E_Dialog *dia;
1024
1025              dia = e_dialog_new(NULL, "E", "_sys_error_logout_slow");
1026              if (dia)
1027                {
1028                   char buf[8192];
1029
1030                   e_dialog_title_set(dia, _("Enlightenment Settings Write Problems"));
1031                   e_dialog_icon_set(dia, "dialog-error", 64);
1032                   snprintf(buf, sizeof(buf),
1033                            _("Enlightenment has had an error while writing<br>"
1034                              "its config file.<br>"
1035                              "%s<br>"
1036                              "<br>"
1037                              "The file where the error occurred was:<br>"
1038                              "%s<br>"
1039                              "<br>"
1040                              "This file has been deleted to avoid corrupt data.<br>"),
1041                            erstr, file);
1042                   e_dialog_text_set(dia, buf);
1043                   e_dialog_button_add(dia, _("OK"), NULL, NULL, NULL);
1044                   e_dialog_button_focus_num(dia, 0);
1045                   //elm_win_center(dia->win, 1, 1);
1046                   e_object_del_attach_func_set(E_OBJECT(dia),
1047                                                _e_config_error_dialog_cb_delete);
1048                   e_dialog_show(dia);
1049                   _e_config_error_dialog = dia;
1050                }
1051           }
1052         return 0;
1053 #else
1054         ELOGF("CFG", "EET ERROR %s", NULL, NULL, erstr);
1055         return 0;
1056 #endif
1057      }
1058    return 1;
1059 }