# define CODESET "INVALID"
#endif
+static Eina_Prefix *_ecore_pfx = NULL;
+static Eina_Array *module_list = NULL;
+
+static void
+ecore_system_modules_load(void)
+{
+ char buf[PATH_MAX] = "";
+ char *path;
+
+ if (getenv("EFL_RUN_IN_TREE"))
+ {
+ struct stat st;
+ snprintf(buf, sizeof(buf), "%s/src/modules/ecore/system",
+ PACKAGE_BUILD_DIR);
+ if (stat(buf, &st) == 0)
+ {
+ const char *built_modules[] = {
+#ifdef HAVE_SYSTEMD
+ "systemd",
+#endif
+ NULL
+ };
+ const char **itr;
+ for (itr = built_modules; *itr != NULL; itr++)
+ {
+ snprintf(buf, sizeof(buf),
+ "%s/src/modules/ecore/system/%s/.libs",
+ PACKAGE_BUILD_DIR, *itr);
+ module_list = eina_module_list_get(module_list, buf,
+ EINA_FALSE, NULL, NULL);
+ }
+
+ if (module_list)
+ eina_module_list_load(module_list);
+ return;
+ }
+ }
+
+ path = eina_module_environment_path_get("ECORE_MODULES_DIR",
+ "/ecore/system");
+ if (path)
+ {
+ module_list = eina_module_arch_list_get(module_list, path, MODULE_ARCH);
+ free(path);
+ }
+
+ path = eina_module_environment_path_get("HOME", "/.ecore/system");
+ if (path)
+ {
+ module_list = eina_module_arch_list_get(module_list, path, MODULE_ARCH);
+ free(path);
+ }
+
+ snprintf(buf, sizeof(buf), "%s/ecore/system",
+ eina_prefix_lib_get(_ecore_pfx));
+ module_list = eina_module_arch_list_get(module_list, buf, MODULE_ARCH);
+
+ eina_module_list_load(module_list);
+}
+
+static void
+ecore_system_modules_unload(void)
+{
+ if (module_list)
+ {
+ eina_module_list_free(module_list);
+ eina_array_free(module_list);
+ module_list = NULL;
+ }
+}
+
/**
* @addtogroup Ecore_Init_Group
*
goto shutdown_log_dom;
}
+ _ecore_pfx = eina_prefix_new(NULL, ecore_init,
+ "ECORE", "ecore", "checkme",
+ PACKAGE_BIN_DIR, PACKAGE_LIB_DIR,
+ PACKAGE_DATA_DIR, PACKAGE_DATA_DIR);
+ if (!_ecore_pfx)
+ {
+ ERR("Could not get ecore installation prefix");
+ goto shutdown_log_dom;
+ }
+
eo_init();
if (getenv("ECORE_FPS_DEBUG")) _ecore_fps_debug = 1;
EINA_LOG_STATE_STOP,
EINA_LOG_STATE_INIT);
+
+ ecore_system_modules_load();
+
return _ecore_init_count;
shutdown_mempool:
if (--_ecore_init_count != 0)
goto unlock;
+ ecore_system_modules_unload();
+
eina_log_timing(_ecore_log_dom,
EINA_LOG_STATE_START,
EINA_LOG_STATE_SHUTDOWN);
ecore_mempool_shutdown();
eina_log_domain_unregister(_ecore_log_dom);
_ecore_log_dom = -1;
+
+ eina_prefix_free(_ecore_pfx);
+ _ecore_pfx = NULL;
+
eina_shutdown();
#ifdef HAVE_EVIL
evil_shutdown();
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <Eldbus.h>
+#include <Ecore.h>
+#include <locale.h>
+
+static int _log_dom = -1;
+static Eldbus_Connection *_conn = NULL;
+
+static Eina_List *_objs = NULL;
+static Eina_List *_proxies = NULL;
+
+#ifdef CRITICAL
+#undef CRITICAL
+#endif
+#define CRITICAL(...) EINA_LOG_DOM_CRIT(_log_dom, __VA_ARGS__)
+
+#ifdef ERR
+#undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(_log_dom, __VA_ARGS__)
+
+#ifdef WRN
+#undef WRN
+#endif
+#define WRN(...) EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__)
+
+#ifdef DBG
+#undef DBG
+#endif
+#define DBG(...) EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__)
+
+
+static void
+_props_changed_hostname(void *data EINA_UNUSED, const Eldbus_Message *msg)
+{
+ Eldbus_Message_Iter *changed, *entry, *invalidated;
+ const char *iface, *prop;
+
+ if (!eldbus_message_arguments_get(msg, "sa{sv}as",
+ &iface, &changed, &invalidated))
+ {
+ ERR("Error getting data from properties changed signal.");
+ return;
+ }
+
+ while (eldbus_message_iter_get_and_next(changed, 'e', &entry))
+ {
+ const void *key;
+ Eldbus_Message_Iter *var;
+ if (!eldbus_message_iter_arguments_get(entry, "sv", &key, &var))
+ continue;
+ if (strcmp(key, "Hostname") == 0)
+ goto changed_hostname;
+ }
+
+ while (eldbus_message_iter_get_and_next(invalidated, 's', &prop))
+ {
+ if (strcmp(prop, "Hostname") == 0)
+ goto changed_hostname;
+ }
+
+ return;
+
+ changed_hostname:
+ ecore_event_add(ECORE_EVENT_HOSTNAME_CHANGED, NULL, NULL, NULL);
+}
+
+static void
+_props_changed_timedate(void *data EINA_UNUSED, const Eldbus_Message *msg)
+{
+ Eldbus_Message_Iter *changed, *entry, *invalidated;
+ const char *iface, *prop;
+
+ if (!eldbus_message_arguments_get(msg, "sa{sv}as",
+ &iface, &changed, &invalidated))
+ {
+ ERR("Error getting data from properties changed signal.");
+ return;
+ }
+
+ while (eldbus_message_iter_get_and_next(changed, 'e', &entry))
+ {
+ const void *key;
+ Eldbus_Message_Iter *var;
+ if (!eldbus_message_iter_arguments_get(entry, "sv", &key, &var))
+ continue;
+ if (strcmp(key, "Timezone") == 0)
+ goto changed_timedate;
+ }
+
+ while (eldbus_message_iter_get_and_next(invalidated, 's', &prop))
+ {
+ if (strcmp(prop, "Timezone") == 0)
+ goto changed_timedate;
+ }
+
+ return;
+
+ changed_timedate:
+ ecore_event_add(ECORE_EVENT_SYSTEM_TIMEDATE_CHANGED, NULL, NULL, NULL);
+}
+
+struct locale_cat_desc {
+ int cat;
+ int namelen;
+ const char *name;
+};
+
+static const struct locale_cat_desc locale_cat_desc[] = {
+#define CAT(name) {name, sizeof(#name) - 1, #name}
+ CAT(LC_CTYPE),
+ CAT(LC_NUMERIC),
+ CAT(LC_TIME),
+ CAT(LC_COLLATE),
+ CAT(LC_MONETARY),
+ CAT(LC_MESSAGES),
+ CAT(LC_ALL),
+ CAT(LC_PAPER),
+ CAT(LC_NAME),
+ CAT(LC_ADDRESS),
+ CAT(LC_TELEPHONE),
+ CAT(LC_MEASUREMENT),
+ CAT(LC_IDENTIFICATION),
+#undef CAT
+ {-1, -1, NULL}
+};
+
+static int _locale_parse(const char *str, int *cat, const char **value)
+{
+ const struct locale_cat_desc *itr;
+ const char *p = strchr(str, '=');
+ int klen;
+
+ if (!p) goto end;
+
+ klen = p - str;
+ for (itr = locale_cat_desc; itr->name != NULL; itr++)
+ {
+ if ((klen == itr->namelen) && (memcmp(str, itr->name, klen) == 0))
+ {
+ *cat = itr->cat;
+ *value = str + itr->namelen + 1;
+ return itr - locale_cat_desc;
+ }
+ }
+
+ end:
+ *cat = -1;
+ *value = NULL;
+ return -1;
+}
+
+static void _locale_get(void *data EINA_UNUSED, const Eldbus_Message *msg,
+ Eldbus_Pending *pending EINA_UNUSED)
+{
+ Eldbus_Message_Iter *variant, *array;
+ const char *errname, *errmsg, *val;
+ Eina_Bool setlocs[EINA_C_ARRAY_LENGTH(locale_cat_desc)];
+ unsigned int i;
+
+ if (eldbus_message_error_get(msg, &errname, &errmsg))
+ {
+ ERR("Message error %s - %s", errname, errmsg);
+ goto end;
+ }
+ if (!eldbus_message_arguments_get(msg, "v", &variant))
+ {
+ ERR("Error getting arguments.");
+ goto end;
+ }
+
+ if (!eldbus_message_iter_get_and_next(variant, 'a', &array))
+ {
+ ERR("Error getting array.");
+ goto end;
+ }
+
+ memset(setlocs, 0, sizeof(setlocs));
+ while (eldbus_message_iter_get_and_next(array, 's', &val))
+ {
+ int cat, idx;
+ const char *value;
+ idx = _locale_parse(val, &cat, &value);
+ if (idx >= 0)
+ setlocs[idx] = EINA_TRUE;
+ setlocale(cat, value);
+ }
+
+ for (i = 0; i < EINA_C_ARRAY_LENGTH(locale_cat_desc); i++)
+ {
+ if ((!setlocs[i]) && (locale_cat_desc[i].cat != LC_ALL))
+ setlocale(locale_cat_desc[i].cat, "C");
+ }
+
+ end:
+ ecore_event_add(ECORE_EVENT_LOCALE_CHANGED, NULL, NULL, NULL);
+}
+
+static void
+_props_changed_locale(void *data, const Eldbus_Message *msg)
+{
+ Eldbus_Proxy *proxy = data;
+ Eldbus_Message_Iter *changed, *entry, *invalidated;
+ const char *iface, *prop;
+
+ if (!eldbus_message_arguments_get(msg, "sa{sv}as",
+ &iface, &changed, &invalidated))
+ {
+ ERR("Error getting data from properties changed signal.");
+ return;
+ }
+
+ while (eldbus_message_iter_get_and_next(changed, 'e', &entry))
+ {
+ const void *key;
+ Eldbus_Message_Iter *var;
+ if (!eldbus_message_iter_arguments_get(entry, "sv", &key, &var))
+ continue;
+ if (strcmp(key, "Locale") == 0)
+ goto changed_locale;
+ }
+
+ while (eldbus_message_iter_get_and_next(invalidated, 's', &prop))
+ {
+ if (strcmp(prop, "Locale") == 0)
+ goto changed_locale;
+ }
+
+ return;
+
+ changed_locale:
+ eldbus_proxy_property_get(proxy, "Locale", _locale_get, NULL);
+}
+
+static Eina_Bool
+_property_change_monitor(const char *name,
+ const char *path,
+ const char *iface,
+ Eldbus_Signal_Cb cb)
+{
+ Eldbus_Object *o;
+ Eldbus_Proxy *p;
+ Eldbus_Signal_Handler *s;
+
+ o = eldbus_object_get(_conn, name, path);
+ if (!o)
+ {
+ ERR("could not get object name=%s, path=%s", name, path);
+ return EINA_FALSE;
+ }
+
+ p = eldbus_proxy_get(o, iface);
+ if (!p)
+ {
+ ERR("could not get proxy interface=%s, name=%s, path=%s",
+ iface, name, path);
+ eldbus_object_unref(o);
+ return EINA_FALSE;
+ }
+
+ s = eldbus_proxy_properties_changed_callback_add(p, cb, p);
+ if (!s)
+ {
+ ERR("could not add signal handler for properties changed for proxy "
+ "interface=%s, name=%s, path=%s", iface, name, path);
+ eldbus_proxy_unref(p);
+ eldbus_object_unref(o);
+ return EINA_FALSE;
+ }
+
+ _objs = eina_list_append(_objs, o);
+ _proxies = eina_list_append(_proxies, p);
+ return EINA_TRUE;
+}
+
+static void _ecore_system_systemd_shutdown(void);
+
+static Eina_Bool
+_ecore_system_systemd_init(void)
+{
+ eldbus_init();
+
+ _log_dom = eina_log_domain_register("ecore_system_systemd", NULL);
+ if (_log_dom < 0)
+ {
+ EINA_LOG_ERR("Could not register log domain: ecore_system_systemd");
+ goto error;
+ }
+
+ _conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
+
+ if (!_property_change_monitor("org.freedesktop.hostname1",
+ "/org/freedesktop/hostname1",
+ "org.freedesktop.hostname1",
+ _props_changed_hostname))
+ goto error;
+
+ if (!_property_change_monitor("org.freedesktop.timedate1",
+ "/org/freedesktop/timedate1",
+ "org.freedesktop.timedate1",
+ _props_changed_timedate))
+ goto error;
+
+ if (!_property_change_monitor("org.freedesktop.locale1",
+ "/org/freedesktop/locale1",
+ "org.freedesktop.locale1",
+ _props_changed_locale))
+ goto error;
+
+ DBG("ecore system 'systemd' loaded");
+ return EINA_TRUE;
+
+ error:
+ _ecore_system_systemd_shutdown();
+ return EINA_FALSE;
+}
+
+static void
+_ecore_system_systemd_shutdown(void)
+{
+ DBG("ecore system 'systemd' unloaded");
+
+ while (_proxies)
+ {
+ eldbus_proxy_unref(_proxies->data);
+ _proxies = eina_list_remove_list(_proxies, _proxies);
+ }
+
+ while (_objs)
+ {
+ eldbus_object_unref(_objs->data);
+ _objs = eina_list_remove_list(_objs, _objs);
+ }
+
+ if (_conn)
+ {
+ eldbus_connection_unref(_conn);
+ _conn = NULL;
+ }
+
+ if (_log_dom > 0)
+ {
+ eina_log_domain_unregister(_log_dom);
+ _log_dom = -1;
+ }
+
+ eldbus_shutdown();
+}
+
+EINA_MODULE_INIT(_ecore_system_systemd_init);
+EINA_MODULE_SHUTDOWN(_ecore_system_systemd_shutdown);