|
Packit |
3ff832 |
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
|
|
Packit |
3ff832 |
/* vim:set et sts=4: */
|
|
Packit |
3ff832 |
/* bus - The Input Bus
|
|
Packit |
3ff832 |
* Copyright (C) 2015 Peng Huang <shawn.p.huang@gmail.com>
|
|
Packit |
3ff832 |
* Copyright (C) 2015-2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
|
Packit |
3ff832 |
* Copyright (C) 2015 Red Hat, Inc.
|
|
Packit |
3ff832 |
*
|
|
Packit |
3ff832 |
* This library is free software; you can redistribute it and/or
|
|
Packit |
3ff832 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
3ff832 |
* License as published by the Free Software Foundation; either
|
|
Packit |
3ff832 |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
3ff832 |
*
|
|
Packit |
3ff832 |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
3ff832 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
3ff832 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
3ff832 |
* Lesser General Public License for more details.
|
|
Packit |
3ff832 |
*
|
|
Packit |
3ff832 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
3ff832 |
* License along with this library; if not, write to the Free Software
|
|
Packit |
3ff832 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
Packit |
3ff832 |
* USA
|
|
Packit |
3ff832 |
*/
|
|
Packit |
3ff832 |
#include <gio/gio.h>
|
|
Packit |
3ff832 |
#include <glib/gstdio.h>
|
|
Packit |
3ff832 |
#include <string.h>
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
#include "ibusinternal.h"
|
|
Packit |
3ff832 |
#include "ibusmarshalers.h"
|
|
Packit |
3ff832 |
#include "ibusregistry.h"
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
#define IBUS_CACHE_MAGIC 0x49425553 /* "IBUS" */
|
|
Packit |
3ff832 |
#define IBUS_CACHE_VERSION 0x00010512
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
enum {
|
|
Packit |
3ff832 |
CHANGED,
|
|
Packit |
3ff832 |
LAST_SIGNAL,
|
|
Packit |
3ff832 |
};
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static guint _signals[LAST_SIGNAL] = { 0 };
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
struct _IBusRegistryPrivate {
|
|
Packit |
3ff832 |
/* a list of IBusObservedPath objects. */
|
|
Packit |
3ff832 |
GList *observed_paths;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* a list of IBusComponent objects that are created from component XML
|
|
Packit |
3ff832 |
* files (or from the cache of them). */
|
|
Packit |
3ff832 |
GList *components;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
gboolean changed;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* a mapping from GFile to GFileMonitor. */
|
|
Packit |
3ff832 |
GHashTable *monitor_table;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
guint monitor_timeout_id;
|
|
Packit |
3ff832 |
};
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
#define IBUS_REGISTRY_GET_PRIVATE(o) \
|
|
Packit |
3ff832 |
(G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_REGISTRY, IBusRegistryPrivate))
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* functions prototype */
|
|
Packit |
3ff832 |
static void ibus_registry_destroy (IBusRegistry *registry);
|
|
Packit |
3ff832 |
static void ibus_registry_remove_all (IBusRegistry *registry);
|
|
Packit |
3ff832 |
static gboolean ibus_registry_serialize (IBusRegistry *registry,
|
|
Packit |
3ff832 |
GVariantBuilder *builder);
|
|
Packit |
3ff832 |
static gint ibus_registry_deserialize (IBusRegistry *registry,
|
|
Packit |
3ff832 |
GVariant *variant);
|
|
Packit |
3ff832 |
static gboolean ibus_registry_copy (IBusRegistry *dest,
|
|
Packit |
3ff832 |
const IBusRegistry *src);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
G_DEFINE_TYPE (IBusRegistry, ibus_registry, IBUS_TYPE_SERIALIZABLE)
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
ibus_registry_class_init (IBusRegistryClass *class)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
|
Packit |
3ff832 |
IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (class);
|
|
Packit |
3ff832 |
IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (class);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_registry_destroy;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
serializable_class->serialize =
|
|
Packit |
3ff832 |
(IBusSerializableSerializeFunc) ibus_registry_serialize;
|
|
Packit |
3ff832 |
serializable_class->deserialize =
|
|
Packit |
3ff832 |
(IBusSerializableDeserializeFunc) ibus_registry_deserialize;
|
|
Packit |
3ff832 |
serializable_class->copy = (IBusSerializableCopyFunc) ibus_registry_copy;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_type_class_add_private (class, sizeof (IBusRegistryPrivate));
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* install signals */
|
|
Packit |
3ff832 |
/**
|
|
Packit |
3ff832 |
* IBusRegistry::changed:
|
|
Packit |
3ff832 |
* @registry: An #IBusRegistry.
|
|
Packit |
3ff832 |
*
|
|
Packit |
3ff832 |
* Emitted when any observed paths are changed.
|
|
Packit |
3ff832 |
* A method is not associated in this class. the "changed"
|
|
Packit |
3ff832 |
* signal would be handled in other classes.
|
|
Packit |
3ff832 |
*
|
|
Packit |
3ff832 |
* See also: ibus_registry_start_monitor_changes().
|
|
Packit |
3ff832 |
*/
|
|
Packit |
3ff832 |
_signals[CHANGED] =
|
|
Packit |
3ff832 |
g_signal_new (I_("changed"),
|
|
Packit |
3ff832 |
G_TYPE_FROM_CLASS (gobject_class),
|
|
Packit |
3ff832 |
G_SIGNAL_RUN_LAST,
|
|
Packit |
3ff832 |
0,
|
|
Packit |
3ff832 |
NULL, NULL,
|
|
Packit |
3ff832 |
_ibus_marshal_VOID__VOID,
|
|
Packit |
3ff832 |
G_TYPE_NONE,
|
|
Packit |
3ff832 |
0);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
ibus_registry_init (IBusRegistry *registry)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
registry->priv = IBUS_REGISTRY_GET_PRIVATE (registry);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
registry->priv->observed_paths = NULL;
|
|
Packit |
3ff832 |
registry->priv->components = NULL;
|
|
Packit |
3ff832 |
registry->priv->changed = FALSE;
|
|
Packit |
3ff832 |
registry->priv->monitor_table =
|
|
Packit |
3ff832 |
g_hash_table_new_full (g_file_hash,
|
|
Packit |
3ff832 |
(GEqualFunc) g_file_equal,
|
|
Packit |
3ff832 |
(GDestroyNotify) g_object_unref,
|
|
Packit |
3ff832 |
(GDestroyNotify) g_object_unref);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
ibus_registry_destroy (IBusRegistry *registry)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
ibus_registry_remove_all (registry);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_hash_table_destroy (registry->priv->monitor_table);
|
|
Packit |
3ff832 |
registry->priv->monitor_table = NULL;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (registry->priv->monitor_timeout_id > 0) {
|
|
Packit |
3ff832 |
g_source_remove (registry->priv->monitor_timeout_id);
|
|
Packit |
3ff832 |
registry->priv->monitor_timeout_id = 0;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
IBUS_OBJECT_CLASS (ibus_registry_parent_class)->
|
|
Packit |
3ff832 |
destroy (IBUS_OBJECT (registry));
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static gboolean
|
|
Packit |
3ff832 |
ibus_registry_serialize (IBusRegistry *registry,
|
|
Packit |
3ff832 |
GVariantBuilder *builder)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
gboolean retval;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
retval = IBUS_SERIALIZABLE_CLASS (ibus_registry_parent_class)->
|
|
Packit |
3ff832 |
serialize ((IBusSerializable *)registry, builder);
|
|
Packit |
3ff832 |
g_return_val_if_fail (retval, FALSE);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
GList *p;
|
|
Packit |
3ff832 |
GVariantBuilder *array;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
array = g_variant_builder_new (G_VARIANT_TYPE ("av"));
|
|
Packit |
3ff832 |
for (p = registry->priv->observed_paths; p != NULL; p = p->next) {
|
|
Packit |
3ff832 |
IBusSerializable *serializable = (IBusSerializable *) p->data;
|
|
Packit |
3ff832 |
g_variant_builder_add (array,
|
|
Packit |
3ff832 |
"v",
|
|
Packit |
3ff832 |
ibus_serializable_serialize (serializable));
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
g_variant_builder_add (builder, "av", array);
|
|
Packit |
3ff832 |
g_variant_builder_unref (array);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
array = g_variant_builder_new (G_VARIANT_TYPE ("av"));
|
|
Packit |
3ff832 |
for (p = registry->priv->components; p != NULL; p = p->next) {
|
|
Packit |
3ff832 |
IBusSerializable *serializable = (IBusSerializable *) p->data;
|
|
Packit |
3ff832 |
g_variant_builder_add (array,
|
|
Packit |
3ff832 |
"v",
|
|
Packit |
3ff832 |
ibus_serializable_serialize (serializable));
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
g_variant_builder_add (builder, "av", array);
|
|
Packit |
3ff832 |
g_variant_builder_unref (array);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
return TRUE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static gint
|
|
Packit |
3ff832 |
ibus_registry_deserialize (IBusRegistry *registry,
|
|
Packit |
3ff832 |
GVariant *variant)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
GVariant *var;
|
|
Packit |
3ff832 |
GVariantIter *iter;
|
|
Packit |
3ff832 |
gint retval;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
retval = IBUS_SERIALIZABLE_CLASS (ibus_registry_parent_class)->
|
|
Packit |
3ff832 |
deserialize ((IBusSerializable *)registry, variant);
|
|
Packit |
3ff832 |
g_return_val_if_fail (retval, 0);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_variant_get_child (variant, retval++, "av", &iter);
|
|
Packit |
3ff832 |
while (g_variant_iter_loop (iter, "v", &var)) {
|
|
Packit |
3ff832 |
IBusSerializable *serializable = ibus_serializable_deserialize (var);
|
|
Packit |
3ff832 |
registry->priv->observed_paths =
|
|
Packit |
3ff832 |
g_list_append (registry->priv->observed_paths,
|
|
Packit |
3ff832 |
IBUS_OBSERVED_PATH (serializable));
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
g_variant_iter_free (iter);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_variant_get_child (variant, retval++, "av", &iter);
|
|
Packit |
3ff832 |
while (g_variant_iter_loop (iter, "v", &var)) {
|
|
Packit |
3ff832 |
IBusSerializable *serializable = ibus_serializable_deserialize (var);
|
|
Packit |
3ff832 |
registry->priv->components =
|
|
Packit |
3ff832 |
g_list_append (registry->priv->components,
|
|
Packit |
3ff832 |
IBUS_COMPONENT (serializable));
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
g_variant_iter_free (iter);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
return retval;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static gboolean
|
|
Packit |
3ff832 |
ibus_registry_copy (IBusRegistry *dest,
|
|
Packit |
3ff832 |
const IBusRegistry *src)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
gboolean retval;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
retval = IBUS_SERIALIZABLE_CLASS (ibus_registry_parent_class)->
|
|
Packit |
3ff832 |
copy ((IBusSerializable *)dest, (IBusSerializable *)src);
|
|
Packit |
3ff832 |
g_return_val_if_fail (retval, FALSE);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
dest->priv->components = g_list_copy (src->priv->components);
|
|
Packit |
3ff832 |
dest->priv->observed_paths = g_list_copy (src->priv->observed_paths);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
return TRUE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/**
|
|
Packit |
3ff832 |
* ibus_registry_remove_all:
|
|
Packit |
3ff832 |
*
|
|
Packit |
3ff832 |
* Remove the loaded registry.
|
|
Packit |
3ff832 |
*/
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
ibus_registry_remove_all (IBusRegistry *registry)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
g_assert (IBUS_IS_REGISTRY (registry));
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_list_free_full (registry->priv->observed_paths, g_object_unref);
|
|
Packit |
3ff832 |
registry->priv->observed_paths = NULL;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_list_free_full (registry->priv->components, g_object_unref);
|
|
Packit |
3ff832 |
registry->priv->components = NULL;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
void
|
|
Packit |
3ff832 |
ibus_registry_load (IBusRegistry *registry)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
const gchar *envstr;
|
|
Packit |
3ff832 |
GPtrArray *path;
|
|
Packit |
3ff832 |
gchar **d, **search_path;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_assert (IBUS_IS_REGISTRY (registry));
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
path = g_ptr_array_new();
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
envstr = g_getenv ("IBUS_COMPONENT_PATH");
|
|
Packit |
3ff832 |
if (envstr) {
|
|
Packit |
3ff832 |
gchar **dirs = g_strsplit (envstr, G_SEARCHPATH_SEPARATOR_S, 0);
|
|
Packit |
3ff832 |
for (d = dirs; *d != NULL; d++)
|
|
Packit |
3ff832 |
g_ptr_array_add (path, *d);
|
|
Packit |
3ff832 |
g_free (dirs);
|
|
Packit |
3ff832 |
} else {
|
|
Packit |
3ff832 |
gchar *dirname;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
dirname = g_build_filename (IBUS_DATA_DIR, "component", NULL);
|
|
Packit |
3ff832 |
g_ptr_array_add (path, dirname);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
#if 0
|
|
Packit |
3ff832 |
/* FIXME Should we support install some IME in user dir? */
|
|
Packit |
3ff832 |
dirname = g_build_filename (g_get_user_data_dir (),
|
|
Packit |
3ff832 |
"ibus", "component",
|
|
Packit |
3ff832 |
NULL);
|
|
Packit |
3ff832 |
g_ptr_array_add (path, dirname);
|
|
Packit |
3ff832 |
#endif
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_ptr_array_add (path, NULL);
|
|
Packit |
3ff832 |
search_path = (gchar **) g_ptr_array_free (path, FALSE);
|
|
Packit |
3ff832 |
for (d = search_path; *d != NULL; d++) {
|
|
Packit |
3ff832 |
ibus_registry_load_in_dir (registry, *d);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
g_strfreev (search_path);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
gboolean
|
|
Packit |
3ff832 |
ibus_registry_load_cache (IBusRegistry *registry,
|
|
Packit |
3ff832 |
gboolean is_user)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
gchar *filename;
|
|
Packit |
3ff832 |
gboolean retval;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_assert (IBUS_IS_REGISTRY (registry));
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (is_user) {
|
|
Packit |
3ff832 |
filename = g_build_filename (g_get_user_cache_dir (),
|
|
Packit |
3ff832 |
"ibus", "bus", "registry", NULL);
|
|
Packit |
3ff832 |
} else {
|
|
Packit |
3ff832 |
filename = g_build_filename (IBUS_CACHE_DIR,
|
|
Packit |
3ff832 |
"bus", "registry", NULL);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
retval = ibus_registry_load_cache_file (registry, filename);
|
|
Packit |
3ff832 |
g_free (filename);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
return retval;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
gboolean
|
|
Packit |
3ff832 |
ibus_registry_load_cache_file (IBusRegistry *registry,
|
|
Packit |
3ff832 |
const gchar *filename)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
gchar *contents, *p;
|
|
Packit |
3ff832 |
gsize length;
|
|
Packit |
3ff832 |
GVariant *variant;
|
|
Packit |
3ff832 |
GError *error;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_assert (IBUS_IS_REGISTRY (registry));
|
|
Packit |
3ff832 |
g_assert (filename != NULL);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (!g_file_test (filename, G_FILE_TEST_EXISTS))
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
error = NULL;
|
|
Packit |
3ff832 |
if (!g_file_get_contents (filename, &contents, &length, &error)) {
|
|
Packit |
3ff832 |
g_warning ("cannot read %s: %s", filename, error->message);
|
|
Packit |
3ff832 |
g_error_free (error);
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
p = contents;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* read file header including magic and version */
|
|
Packit |
3ff832 |
if (length < 8) {
|
|
Packit |
3ff832 |
g_free (contents);
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (GUINT32_FROM_BE (*(guint32 *) p) != IBUS_CACHE_MAGIC) {
|
|
Packit |
3ff832 |
g_free (contents);
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
p += 4;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (GUINT32_FROM_BE (*(guint32 *) p) != IBUS_CACHE_VERSION) {
|
|
Packit |
3ff832 |
g_free (contents);
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
p += 4;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* read serialized IBusRegistry */
|
|
Packit |
3ff832 |
variant = g_variant_new_from_data (G_VARIANT_TYPE ("(sa{sv}avav)"),
|
|
Packit |
3ff832 |
p,
|
|
Packit |
3ff832 |
length - (p - contents),
|
|
Packit |
3ff832 |
FALSE,
|
|
Packit |
3ff832 |
(GDestroyNotify) g_free,
|
|
Packit |
3ff832 |
NULL);
|
|
Packit |
3ff832 |
if (variant == NULL) {
|
|
Packit |
3ff832 |
g_free (contents);
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
ibus_registry_deserialize (registry, variant);
|
|
Packit |
3ff832 |
g_variant_unref (variant);
|
|
Packit |
3ff832 |
g_free (contents);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
return TRUE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
gboolean
|
|
Packit |
3ff832 |
ibus_registry_check_modification (IBusRegistry *registry)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
GList *p;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_assert (IBUS_IS_REGISTRY (registry));
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
for (p = registry->priv->observed_paths; p != NULL; p = p->next) {
|
|
Packit |
3ff832 |
if (!IBUS_IS_OBSERVED_PATH (p->data)) {
|
|
Packit |
3ff832 |
g_warning ("The registry cache of observed_paths might be " \
|
|
Packit |
3ff832 |
"broken and have to generate the cache again.");
|
|
Packit |
3ff832 |
g_list_free_full (registry->priv->observed_paths, g_object_unref);
|
|
Packit |
3ff832 |
registry->priv->observed_paths = NULL;
|
|
Packit |
3ff832 |
return TRUE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
if (ibus_observed_path_check_modification (
|
|
Packit |
3ff832 |
(IBusObservedPath *) p->data))
|
|
Packit |
3ff832 |
return TRUE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
for (p = registry->priv->components; p != NULL; p = p->next) {
|
|
Packit |
3ff832 |
if (!IBUS_IS_COMPONENT (p->data)) {
|
|
Packit |
3ff832 |
g_warning ("The registry cache of components might be " \
|
|
Packit |
3ff832 |
"broken and have to generate the cache again.");
|
|
Packit |
3ff832 |
g_list_free_full (registry->priv->components, g_object_unref);
|
|
Packit |
3ff832 |
registry->priv->components = NULL;
|
|
Packit |
3ff832 |
return TRUE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
if (ibus_component_check_modification ((IBusComponent *) p->data))
|
|
Packit |
3ff832 |
return TRUE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
gboolean
|
|
Packit |
3ff832 |
ibus_registry_save_cache (IBusRegistry *registry,
|
|
Packit |
3ff832 |
gboolean is_user)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
gchar *filename;
|
|
Packit |
3ff832 |
gboolean retval;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_assert (IBUS_IS_REGISTRY (registry));
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (is_user) {
|
|
Packit |
3ff832 |
filename = g_build_filename (g_get_user_cache_dir (),
|
|
Packit |
3ff832 |
"ibus", "bus", "registry", NULL);
|
|
Packit |
3ff832 |
} else {
|
|
Packit |
3ff832 |
filename = g_build_filename (IBUS_CACHE_DIR,
|
|
Packit |
3ff832 |
"bus", "registry", NULL);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
retval = ibus_registry_save_cache_file (registry, filename);
|
|
Packit |
3ff832 |
g_free (filename);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
return retval;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
gboolean
|
|
Packit |
3ff832 |
ibus_registry_save_cache_file (IBusRegistry *registry,
|
|
Packit |
3ff832 |
const gchar *filename)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
gchar *cachedir;
|
|
Packit |
3ff832 |
GVariant *variant;
|
|
Packit |
3ff832 |
gchar *contents, *p;
|
|
Packit |
3ff832 |
gsize length;
|
|
Packit |
3ff832 |
gboolean retval;
|
|
Packit |
3ff832 |
guint32 intval;
|
|
Packit |
3ff832 |
GError *error;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_assert (IBUS_IS_REGISTRY (registry));
|
|
Packit |
3ff832 |
g_assert (filename != NULL);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
cachedir = g_path_get_dirname (filename);
|
|
Packit |
3ff832 |
g_mkdir_with_parents (cachedir, 0775);
|
|
Packit |
3ff832 |
g_free (cachedir);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
variant = ibus_serializable_serialize (IBUS_SERIALIZABLE (registry));
|
|
Packit |
3ff832 |
length = 8 + g_variant_get_size (variant);
|
|
Packit |
3ff832 |
p = contents = g_slice_alloc (length);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* write file header */
|
|
Packit |
3ff832 |
intval = GUINT32_TO_BE (IBUS_CACHE_MAGIC);
|
|
Packit |
3ff832 |
memcpy (p, (gchar *) &intval, 4);
|
|
Packit |
3ff832 |
p += 4;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
intval = GUINT32_TO_BE (IBUS_CACHE_VERSION);
|
|
Packit |
3ff832 |
memcpy (p, (gchar *) &intval, 4);
|
|
Packit |
3ff832 |
p += 4;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* write serialized IBusRegistry */
|
|
Packit |
3ff832 |
g_variant_store (variant, p);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
error = NULL;
|
|
Packit |
3ff832 |
retval = g_file_set_contents (filename, contents, length, &error);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_variant_unref (variant);
|
|
Packit |
3ff832 |
g_slice_free1 (length, contents);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (!retval) {
|
|
Packit |
3ff832 |
g_warning ("cannot write %s: %s", filename, error->message);
|
|
Packit |
3ff832 |
g_error_free (error);
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (g_str_has_prefix (filename, g_get_user_cache_dir ())) {
|
|
Packit |
3ff832 |
g_warn_if_fail (!g_chmod (filename, 0644));
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
return TRUE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
#define g_string_append_indent(string, indent) \
|
|
Packit |
3ff832 |
{ \
|
|
Packit |
3ff832 |
gint i; \
|
|
Packit |
3ff832 |
for (i = 0; i < (indent); i++) { \
|
|
Packit |
3ff832 |
g_string_append (string, " "); \
|
|
Packit |
3ff832 |
} \
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
void
|
|
Packit |
3ff832 |
ibus_registry_output (IBusRegistry *registry,
|
|
Packit |
3ff832 |
GString *output,
|
|
Packit |
3ff832 |
int indent)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
GList *p;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_assert (IBUS_IS_REGISTRY (registry));
|
|
Packit |
3ff832 |
g_return_if_fail (output != NULL);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_string_append (output, "\n");
|
|
Packit |
3ff832 |
g_string_append (output, "<ibus-registry>\n");
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (registry->priv->observed_paths) {
|
|
Packit |
3ff832 |
g_string_append_indent (output, indent);
|
|
Packit |
3ff832 |
g_string_append (output, "<observed-paths>\n");
|
|
Packit |
3ff832 |
for (p = registry->priv->observed_paths; p != NULL; p = p->next) {
|
|
Packit |
3ff832 |
ibus_observed_path_output ((IBusObservedPath *) p->data,
|
|
Packit |
3ff832 |
output, indent * 2);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
g_string_append_indent (output, indent);
|
|
Packit |
3ff832 |
g_string_append (output, "</observed-paths>\n");
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (registry->priv->components) {
|
|
Packit |
3ff832 |
g_string_append_indent (output, indent);
|
|
Packit |
3ff832 |
g_string_append (output, "<components>\n");
|
|
Packit |
3ff832 |
for (p = registry->priv->components; p != NULL; p = p->next) {
|
|
Packit |
3ff832 |
ibus_component_output ((IBusComponent *) p->data,
|
|
Packit |
3ff832 |
output, indent * 2);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
g_string_append_indent (output, indent);
|
|
Packit |
3ff832 |
g_string_append (output, "</components>\n");
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_string_append (output, "</ibus-registry>\n");
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
void
|
|
Packit |
3ff832 |
ibus_registry_load_in_dir (IBusRegistry *registry,
|
|
Packit |
3ff832 |
const gchar *dirname)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
GError *error = NULL;
|
|
Packit |
3ff832 |
GDir *dir;
|
|
Packit |
3ff832 |
IBusObservedPath *observed_path = NULL;
|
|
Packit |
3ff832 |
const gchar *filename;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_assert (IBUS_IS_REGISTRY (registry));
|
|
Packit |
3ff832 |
g_assert (dirname);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
dir = g_dir_open (dirname, 0, &error);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (dir == NULL) {
|
|
Packit |
3ff832 |
g_warning ("Unable open directory %s : %s", dirname, error->message);
|
|
Packit |
3ff832 |
g_error_free (error);
|
|
Packit |
3ff832 |
return;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
observed_path = ibus_observed_path_new (dirname, TRUE);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
registry->priv->observed_paths =
|
|
Packit |
3ff832 |
g_list_append (registry->priv->observed_paths,
|
|
Packit |
3ff832 |
observed_path);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
while ((filename = g_dir_read_name (dir)) != NULL) {
|
|
Packit |
3ff832 |
glong size;
|
|
Packit |
3ff832 |
gchar *path;
|
|
Packit |
3ff832 |
IBusComponent *component;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
size = g_utf8_strlen (filename, -1);
|
|
Packit |
3ff832 |
if (g_strcmp0 (MAX (filename, filename + size - 4), ".xml") != 0)
|
|
Packit |
3ff832 |
continue;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
path = g_build_filename (dirname, filename, NULL);
|
|
Packit |
3ff832 |
component = ibus_component_new_from_file (path);
|
|
Packit |
3ff832 |
if (component != NULL) {
|
|
Packit |
3ff832 |
g_object_ref_sink (component);
|
|
Packit |
3ff832 |
registry->priv->components =
|
|
Packit |
3ff832 |
g_list_append (registry->priv->components, component);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_free (path);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_dir_close (dir);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
IBusRegistry *
|
|
Packit |
3ff832 |
ibus_registry_new (void)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IBusRegistry *registry;
|
|
Packit |
3ff832 |
registry = (IBusRegistry *) g_object_new (IBUS_TYPE_REGISTRY, NULL);
|
|
Packit |
3ff832 |
return registry;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
GList *
|
|
Packit |
3ff832 |
ibus_registry_get_components (IBusRegistry *registry)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
g_assert (IBUS_IS_REGISTRY (registry));
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
return g_list_copy (registry->priv->components);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
GList *
|
|
Packit |
3ff832 |
ibus_registry_get_observed_paths (IBusRegistry *registry)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
g_assert (IBUS_IS_REGISTRY (registry));
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
return g_list_copy (registry->priv->observed_paths);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static gboolean
|
|
Packit |
3ff832 |
_monitor_timeout_cb (IBusRegistry *registry)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
g_hash_table_remove_all (registry->priv->monitor_table);
|
|
Packit |
3ff832 |
registry->priv->changed = TRUE;
|
|
Packit |
3ff832 |
g_signal_emit (registry, _signals[CHANGED], 0);
|
|
Packit |
3ff832 |
registry->priv->monitor_timeout_id = 0;
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_monitor_changed_cb (GFileMonitor *monitor,
|
|
Packit |
3ff832 |
GFile *file,
|
|
Packit |
3ff832 |
GFile *other_file,
|
|
Packit |
3ff832 |
GFileMonitorEvent event_type,
|
|
Packit |
3ff832 |
IBusRegistry *registry)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
g_assert (IBUS_IS_REGISTRY (registry));
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (event_type != G_FILE_MONITOR_EVENT_CHANGED &&
|
|
Packit |
3ff832 |
event_type != G_FILE_MONITOR_EVENT_DELETED &&
|
|
Packit |
3ff832 |
event_type != G_FILE_MONITOR_EVENT_CREATED &&
|
|
Packit |
3ff832 |
event_type != G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED)
|
|
Packit |
3ff832 |
return;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* Merge successive file changes into one, with a low priority
|
|
Packit |
3ff832 |
timeout handler. */
|
|
Packit |
3ff832 |
if (registry->priv->monitor_timeout_id > 0)
|
|
Packit |
3ff832 |
return;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
registry->priv->monitor_timeout_id =
|
|
Packit |
3ff832 |
g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE,
|
|
Packit |
3ff832 |
5000,
|
|
Packit |
3ff832 |
(GSourceFunc) _monitor_timeout_cb,
|
|
Packit |
3ff832 |
g_object_ref (registry),
|
|
Packit |
3ff832 |
(GDestroyNotify) g_object_unref);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
void
|
|
Packit |
3ff832 |
ibus_registry_start_monitor_changes (IBusRegistry *registry)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
GList *observed_paths, *p;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_assert (IBUS_IS_REGISTRY (registry));
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_hash_table_remove_all (registry->priv->monitor_table);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
observed_paths = g_list_copy (registry->priv->observed_paths);
|
|
Packit |
3ff832 |
for (p = registry->priv->components; p != NULL; p = p->next) {
|
|
Packit |
3ff832 |
IBusComponent *component = (IBusComponent *) p->data;
|
|
Packit |
3ff832 |
GList *component_observed_paths =
|
|
Packit |
3ff832 |
ibus_component_get_observed_paths (component);
|
|
Packit |
3ff832 |
observed_paths = g_list_concat (observed_paths,
|
|
Packit |
3ff832 |
component_observed_paths);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
for (p = observed_paths; p != NULL; p = p->next) {
|
|
Packit |
3ff832 |
IBusObservedPath *path = (IBusObservedPath *) p->data;
|
|
Packit |
3ff832 |
GFile *file = g_file_new_for_path (path->path);
|
|
Packit |
3ff832 |
if (g_hash_table_lookup (registry->priv->monitor_table, file) == NULL) {
|
|
Packit |
3ff832 |
GFileMonitor *monitor;
|
|
Packit |
3ff832 |
GError *error;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
error = NULL;
|
|
Packit |
3ff832 |
monitor = g_file_monitor (file,
|
|
Packit |
3ff832 |
G_FILE_MONITOR_NONE,
|
|
Packit |
3ff832 |
NULL,
|
|
Packit |
3ff832 |
&error);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (monitor != NULL) {
|
|
Packit |
3ff832 |
g_signal_connect (monitor, "changed",
|
|
Packit |
3ff832 |
G_CALLBACK (_monitor_changed_cb),
|
|
Packit |
3ff832 |
registry);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_hash_table_replace (registry->priv->monitor_table,
|
|
Packit |
3ff832 |
g_object_ref (file),
|
|
Packit |
3ff832 |
monitor);
|
|
Packit |
3ff832 |
} else {
|
|
Packit |
3ff832 |
g_warning ("Can't monitor directory %s: %s",
|
|
Packit |
3ff832 |
path->path,
|
|
Packit |
3ff832 |
error->message);
|
|
Packit |
3ff832 |
g_error_free (error);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
g_object_unref (file);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
g_list_free (observed_paths);
|
|
Packit |
3ff832 |
}
|