* the names must begin with a lowercase character, must not end
* with a '-', and must not contain consecutive dashes.
*
+ * GSettings supports change notification. The primary mechanism to
+ * watch for changes is to connect to the "changed" signal. You can
+ * optionally watch for changes on only a single key by using a signal
+ * detail. Signals are only guaranteed to be emitted for a given key
+ * after you have read the value of that key while a signal handler was
+ * connected for that key. Signals may or may not be emitted in the
+ * case that the key "changed" to the value that you had previously
+ * read. Signals may be reported in additional cases as well and the
+ * "changed" signal should really be treated as "may have changed".
+ *
* Similar to GConf, the default values in GSettings schemas can be
* localized, but the localized values are stored in gettext catalogs
* and looked up with the domain that is specified in the
GSettingsSchema *schema;
gchar *path;
+ gboolean is_subscribed;
+
GDelayedSettingsBackend *delayed;
};
return FALSE;
}
+static gboolean
+g_settings_has_signal_handlers (GSettings *settings,
+ const gchar *key)
+{
+ GSettingsClass *class = G_SETTINGS_GET_CLASS (settings);
+ GQuark keyq;
+
+ if (class->change_event != g_settings_real_change_event ||
+ class->writable_change_event != g_settings_real_writable_change_event)
+ return TRUE;
+
+ keyq = g_quark_from_string (key);
+
+ if (g_signal_has_handler_pending (settings, g_settings_signals[SIGNAL_WRITABLE_CHANGE_EVENT], 0, TRUE) ||
+ g_signal_has_handler_pending (settings, g_settings_signals[SIGNAL_WRITABLE_CHANGED], 0, TRUE) ||
+ g_signal_has_handler_pending (settings, g_settings_signals[SIGNAL_WRITABLE_CHANGED], keyq, TRUE) ||
+ g_signal_has_handler_pending (settings, g_settings_signals[SIGNAL_CHANGE_EVENT], 0, TRUE) ||
+ g_signal_has_handler_pending (settings, g_settings_signals[SIGNAL_CHANGED], 0, TRUE) ||
+ g_signal_has_handler_pending (settings, g_settings_signals[SIGNAL_CHANGED], keyq, TRUE))
+ return TRUE;
+
+ /* None of that? Then surely nobody is watching.... */
+ return FALSE;
+}
+
+
static void
settings_backend_changed (GObject *target,
GSettingsBackend *backend,
settings_backend_keys_changed (GObject *target,
GSettingsBackend *backend,
const gchar *path,
- const gchar * const *items,
- gpointer origin_tag)
+ gpointer origin_tag,
+ const gchar * const *items)
{
GSettings *settings = G_SETTINGS (target);
gboolean ignore_this;
g_settings_backend_watch (settings->priv->backend,
&listener_vtable, G_OBJECT (settings),
settings->priv->main_context);
- g_settings_backend_subscribe (settings->priv->backend,
- settings->priv->path);
}
static void
{
GSettings *settings = G_SETTINGS (object);
- g_settings_backend_unsubscribe (settings->priv->backend,
- settings->priv->path);
+ if (settings->priv->is_subscribed)
+ g_settings_backend_unsubscribe (settings->priv->backend,
+ settings->priv->path);
+
g_main_context_unref (settings->priv->main_context);
g_object_unref (settings->priv->backend);
g_settings_schema_unref (settings->priv->schema);
GVariant *fixup;
gchar *path;
+ /* If we are not yet watching for changes, consider doing it now... */
+ if (!settings->priv->is_subscribed && g_settings_has_signal_handlers (settings, key->name))
+ {
+ g_settings_backend_subscribe (settings->priv->backend, settings->priv->path);
+ settings->priv->is_subscribed = TRUE;
+ }
+
path = g_strconcat (settings->priv->path, key->name, NULL);
if (user_value_only)
value = g_settings_backend_read_user_value (settings->priv->backend, path, key->type);