Blame gio/gdelayedsettingsbackend.c

Packit ae235b
/*
Packit ae235b
 * Copyright © 2009, 2010 Codethink Limited
Packit ae235b
 *
Packit ae235b
 * This library is free software; you can redistribute it and/or
Packit ae235b
 * modify it under the terms of the GNU Lesser General Public
Packit ae235b
 * License as published by the Free Software Foundation; either
Packit ae235b
 * version 2.1 of the License, or (at your option) any later version.
Packit ae235b
 *
Packit ae235b
 * This library is distributed in the hope that it will be useful,
Packit ae235b
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit ae235b
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit ae235b
 * Lesser General Public License for more details.
Packit ae235b
 *
Packit ae235b
 * You should have received a copy of the GNU Lesser General Public
Packit ae235b
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
Packit ae235b
 *
Packit ae235b
 * Author: Ryan Lortie <desrt@desrt.ca>
Packit ae235b
 */
Packit ae235b
Packit ae235b
#include "config.h"
Packit ae235b
Packit ae235b
#include "gdelayedsettingsbackend.h"
Packit ae235b
#include "gsettingsbackendinternal.h"
Packit ae235b
Packit ae235b
#include <string.h>
Packit ae235b
Packit ae235b
Packit ae235b
struct _GDelayedSettingsBackendPrivate
Packit ae235b
{
Packit ae235b
  GSettingsBackend *backend;
Packit ae235b
  GMutex lock;
Packit ae235b
  GTree *delayed;
Packit ae235b
Packit ae235b
  GMainContext *owner_context;
Packit ae235b
  gpointer owner;
Packit ae235b
};
Packit ae235b
Packit ae235b
G_DEFINE_TYPE_WITH_PRIVATE (GDelayedSettingsBackend,
Packit ae235b
                            g_delayed_settings_backend,
Packit ae235b
                            G_TYPE_SETTINGS_BACKEND)
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
invoke_notify_unapplied (gpointer data)
Packit ae235b
{
Packit ae235b
  g_object_notify (data, "has-unapplied");
Packit ae235b
  g_object_unref (data);
Packit ae235b
Packit ae235b
  return FALSE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_delayed_settings_backend_notify_unapplied (GDelayedSettingsBackend *delayed)
Packit ae235b
{
Packit ae235b
  GMainContext *target_context;
Packit ae235b
  GObject *target;
Packit ae235b
Packit ae235b
  g_mutex_lock (&delayed->priv->lock);
Packit ae235b
  if (delayed->priv->owner)
Packit ae235b
    {
Packit ae235b
      target_context = delayed->priv->owner_context;
Packit ae235b
      target = g_object_ref (delayed->priv->owner);
Packit ae235b
    }
Packit ae235b
  else
Packit ae235b
    {
Packit ae235b
      target_context = NULL;
Packit ae235b
      target = NULL;
Packit ae235b
    }
Packit ae235b
  g_mutex_unlock (&delayed->priv->lock);
Packit ae235b
Packit ae235b
  if (target != NULL)
Packit ae235b
    g_main_context_invoke (target_context, invoke_notify_unapplied, target);
Packit ae235b
}
Packit ae235b
Packit ae235b
Packit ae235b
static GVariant *
Packit ae235b
g_delayed_settings_backend_read (GSettingsBackend   *backend,
Packit ae235b
                                 const gchar        *key,
Packit ae235b
                                 const GVariantType *expected_type,
Packit ae235b
                                 gboolean            default_value)
Packit ae235b
{
Packit ae235b
  GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (backend);
Packit ae235b
  gpointer result = NULL;
Packit ae235b
Packit ae235b
  if (!default_value)
Packit ae235b
    {
Packit ae235b
      g_mutex_lock (&delayed->priv->lock);
Packit ae235b
      if (g_tree_lookup_extended (delayed->priv->delayed, key, NULL, &result))
Packit ae235b
        {
Packit ae235b
          /* NULL in the tree means we should consult the default value */
Packit ae235b
          if (result != NULL)
Packit ae235b
            g_variant_ref (result);
Packit ae235b
          else
Packit ae235b
            default_value = TRUE;
Packit ae235b
        }
Packit ae235b
      g_mutex_unlock (&delayed->priv->lock);
Packit ae235b
    }
Packit ae235b
Packit ae235b
  if (result == NULL)
Packit ae235b
    result = g_settings_backend_read (delayed->priv->backend, key,
Packit ae235b
                                      expected_type, default_value);
Packit ae235b
Packit ae235b
  return result;
Packit ae235b
}
Packit ae235b
Packit ae235b
static GVariant *
Packit ae235b
g_delayed_settings_backend_read_user_value (GSettingsBackend   *backend,
Packit ae235b
                                            const gchar        *key,
Packit ae235b
                                            const GVariantType *expected_type)
Packit ae235b
{
Packit ae235b
  GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (backend);
Packit ae235b
  gboolean value_found = FALSE;
Packit ae235b
  gpointer result = NULL;
Packit ae235b
Packit ae235b
  /* If we find an explicit NULL in our changeset then we want to return
Packit ae235b
   * NULL (because the user value has been reset).
Packit ae235b
   *
Packit ae235b
   * Otherwise, chain up.
Packit ae235b
   */
Packit ae235b
  g_mutex_lock (&delayed->priv->lock);
Packit ae235b
  value_found = g_tree_lookup_extended (delayed->priv->delayed, key, NULL, &result);
Packit ae235b
  if (result)
Packit ae235b
    g_variant_ref (result);
Packit ae235b
  g_mutex_unlock (&delayed->priv->lock);
Packit ae235b
Packit ae235b
  if (value_found)
Packit ae235b
    return result;
Packit ae235b
Packit ae235b
  return g_settings_backend_read_user_value (delayed->priv->backend, key, expected_type);
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
g_delayed_settings_backend_write (GSettingsBackend *backend,
Packit ae235b
                                  const gchar      *key,
Packit ae235b
                                  GVariant         *value,
Packit ae235b
                                  gpointer          origin_tag)
Packit ae235b
{
Packit ae235b
  GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (backend);
Packit ae235b
  gboolean was_empty;
Packit ae235b
Packit ae235b
  g_mutex_lock (&delayed->priv->lock);
Packit ae235b
  was_empty = g_tree_nnodes (delayed->priv->delayed) == 0;
Packit ae235b
  g_tree_insert (delayed->priv->delayed, g_strdup (key),
Packit ae235b
                 g_variant_ref_sink (value));
Packit ae235b
  g_mutex_unlock (&delayed->priv->lock);
Packit ae235b
Packit ae235b
  g_settings_backend_changed (backend, key, origin_tag);
Packit ae235b
Packit ae235b
  if (was_empty)
Packit ae235b
    g_delayed_settings_backend_notify_unapplied (delayed);
Packit ae235b
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
add_to_tree (gpointer key,
Packit ae235b
             gpointer value,
Packit ae235b
             gpointer user_data)
Packit ae235b
{
Packit ae235b
  g_tree_insert (user_data, g_strdup (key), g_variant_ref (value));
Packit ae235b
  return FALSE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
g_delayed_settings_backend_write_tree (GSettingsBackend *backend,
Packit ae235b
                                       GTree            *tree,
Packit ae235b
                                       gpointer          origin_tag)
Packit ae235b
{
Packit ae235b
  GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (backend);
Packit ae235b
  gboolean was_empty;
Packit ae235b
Packit ae235b
  g_mutex_lock (&delayed->priv->lock);
Packit ae235b
  was_empty = g_tree_nnodes (delayed->priv->delayed) == 0;
Packit ae235b
Packit ae235b
  g_tree_foreach (tree, add_to_tree, delayed->priv->delayed);
Packit ae235b
  g_mutex_unlock (&delayed->priv->lock);
Packit ae235b
Packit ae235b
  g_settings_backend_changed_tree (backend, tree, origin_tag);
Packit ae235b
Packit ae235b
  if (was_empty)
Packit ae235b
    g_delayed_settings_backend_notify_unapplied (delayed);
Packit ae235b
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
g_delayed_settings_backend_get_writable (GSettingsBackend *backend,
Packit ae235b
                                         const gchar      *name)
Packit ae235b
{
Packit ae235b
  GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (backend);
Packit ae235b
Packit ae235b
  return g_settings_backend_get_writable (delayed->priv->backend, name);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_delayed_settings_backend_reset (GSettingsBackend *backend,
Packit ae235b
                                  const gchar      *key,
Packit ae235b
                                  gpointer          origin_tag)
Packit ae235b
{
Packit ae235b
  GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (backend);
Packit ae235b
  gboolean was_empty;
Packit ae235b
Packit ae235b
  g_mutex_lock (&delayed->priv->lock);
Packit ae235b
  was_empty = g_tree_nnodes (delayed->priv->delayed) == 0;
Packit ae235b
  g_tree_insert (delayed->priv->delayed, g_strdup (key), NULL);
Packit ae235b
  g_mutex_unlock (&delayed->priv->lock);
Packit ae235b
Packit ae235b
  if (was_empty)
Packit ae235b
    g_delayed_settings_backend_notify_unapplied (delayed);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_delayed_settings_backend_subscribe (GSettingsBackend *backend,
Packit ae235b
                                      const char       *name)
Packit ae235b
{
Packit ae235b
  GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (backend);
Packit ae235b
Packit ae235b
  g_settings_backend_subscribe (delayed->priv->backend, name);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_delayed_settings_backend_unsubscribe (GSettingsBackend *backend,
Packit ae235b
                                        const char       *name)
Packit ae235b
{
Packit ae235b
  GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (backend);
Packit ae235b
Packit ae235b
  g_settings_backend_unsubscribe (delayed->priv->backend, name);
Packit ae235b
}
Packit ae235b
Packit ae235b
static GPermission *
Packit ae235b
g_delayed_settings_backend_get_permission (GSettingsBackend *backend,
Packit ae235b
                                           const gchar      *path)
Packit ae235b
{
Packit ae235b
  GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (backend);
Packit ae235b
Packit ae235b
  return g_settings_backend_get_permission (delayed->priv->backend, path);
Packit ae235b
}
Packit ae235b
Packit ae235b
Packit ae235b
/* method calls */
Packit ae235b
gboolean
Packit ae235b
g_delayed_settings_backend_get_has_unapplied (GDelayedSettingsBackend *delayed)
Packit ae235b
{
Packit ae235b
  /* we don't need to lock for this... */
Packit ae235b
Packit ae235b
  return g_tree_nnodes (delayed->priv->delayed) > 0;
Packit ae235b
}
Packit ae235b
Packit ae235b
void
Packit ae235b
g_delayed_settings_backend_apply (GDelayedSettingsBackend *delayed)
Packit ae235b
{
Packit ae235b
  if (g_tree_nnodes (delayed->priv->delayed) > 0)
Packit ae235b
    {
Packit ae235b
      gboolean success;
Packit ae235b
      GTree *tmp;
Packit ae235b
Packit ae235b
      g_mutex_lock (&delayed->priv->lock);
Packit ae235b
      tmp = delayed->priv->delayed;
Packit ae235b
      delayed->priv->delayed = g_settings_backend_create_tree ();
Packit ae235b
      success = g_settings_backend_write_tree (delayed->priv->backend,
Packit ae235b
                                               tmp, delayed->priv);
Packit ae235b
      g_mutex_unlock (&delayed->priv->lock);
Packit ae235b
Packit ae235b
      if (!success)
Packit ae235b
        g_settings_backend_changed_tree (G_SETTINGS_BACKEND (delayed),
Packit ae235b
                                         tmp, NULL);
Packit ae235b
Packit ae235b
      g_tree_unref (tmp);
Packit ae235b
Packit ae235b
      g_delayed_settings_backend_notify_unapplied (delayed);
Packit ae235b
    }
Packit ae235b
}
Packit ae235b
Packit ae235b
void
Packit ae235b
g_delayed_settings_backend_revert (GDelayedSettingsBackend *delayed)
Packit ae235b
{
Packit ae235b
  if (g_tree_nnodes (delayed->priv->delayed) > 0)
Packit ae235b
    {
Packit ae235b
      GTree *tmp;
Packit ae235b
Packit ae235b
      g_mutex_lock (&delayed->priv->lock);
Packit ae235b
      tmp = delayed->priv->delayed;
Packit ae235b
      delayed->priv->delayed = g_settings_backend_create_tree ();
Packit ae235b
      g_mutex_unlock (&delayed->priv->lock);
Packit ae235b
      g_settings_backend_changed_tree (G_SETTINGS_BACKEND (delayed), tmp, NULL);
Packit ae235b
      g_tree_unref (tmp);
Packit ae235b
Packit ae235b
      g_delayed_settings_backend_notify_unapplied (delayed);
Packit ae235b
    }
Packit ae235b
}
Packit ae235b
Packit ae235b
/* change notification */
Packit ae235b
static void
Packit ae235b
delayed_backend_changed (GObject          *target,
Packit ae235b
                         GSettingsBackend *backend,
Packit ae235b
                         const gchar      *key,
Packit ae235b
                         gpointer          origin_tag)
Packit ae235b
{
Packit ae235b
  GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (target);
Packit ae235b
Packit ae235b
  if (origin_tag != delayed->priv)
Packit ae235b
    g_settings_backend_changed (G_SETTINGS_BACKEND (delayed),
Packit ae235b
                                key, origin_tag);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
delayed_backend_keys_changed (GObject             *target,
Packit ae235b
                              GSettingsBackend    *backend,
Packit ae235b
                              const gchar         *path,
Packit ae235b
                              gpointer             origin_tag,
Packit ae235b
                              const gchar * const *items)
Packit ae235b
{
Packit ae235b
  GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (target);
Packit ae235b
Packit ae235b
  if (origin_tag != delayed->priv)
Packit ae235b
    g_settings_backend_keys_changed (G_SETTINGS_BACKEND (delayed),
Packit ae235b
                                     path, items, origin_tag);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
delayed_backend_path_changed (GObject          *target,
Packit ae235b
                              GSettingsBackend *backend,
Packit ae235b
                              const gchar      *path,
Packit ae235b
                              gpointer          origin_tag)
Packit ae235b
{
Packit ae235b
  GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (target);
Packit ae235b
Packit ae235b
  if (origin_tag != delayed->priv)
Packit ae235b
    g_settings_backend_path_changed (G_SETTINGS_BACKEND (delayed),
Packit ae235b
                                     path, origin_tag);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
delayed_backend_writable_changed (GObject          *target,
Packit ae235b
                                  GSettingsBackend *backend,
Packit ae235b
                                  const gchar      *key)
Packit ae235b
{
Packit ae235b
  GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (target);
Packit ae235b
  gboolean last_one = FALSE;
Packit ae235b
Packit ae235b
  g_mutex_lock (&delayed->priv->lock);
Packit ae235b
Packit ae235b
  if (g_tree_lookup (delayed->priv->delayed, key) != NULL &&
Packit ae235b
      !g_settings_backend_get_writable (delayed->priv->backend, key))
Packit ae235b
    {
Packit ae235b
      /* drop the key from our changeset if it just became read-only.
Packit ae235b
       * no need to signal since the writable change below implies it.
Packit ae235b
       *
Packit ae235b
       * note that the item in the tree may very well be set to NULL in
Packit ae235b
       * the case that the user stored a reset.  we intentionally don't
Packit ae235b
       * drop the key in this case since a reset will always succeed
Packit ae235b
       * (even against a non-writable key).
Packit ae235b
       */
Packit ae235b
      g_tree_remove (delayed->priv->delayed, key);
Packit ae235b
Packit ae235b
      /* if that was the only key... */
Packit ae235b
      last_one = g_tree_nnodes (delayed->priv->delayed) == 0;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  g_mutex_unlock (&delayed->priv->lock);
Packit ae235b
Packit ae235b
  if (last_one)
Packit ae235b
    g_delayed_settings_backend_notify_unapplied (delayed);
Packit ae235b
Packit ae235b
  g_settings_backend_writable_changed (G_SETTINGS_BACKEND (delayed), key);
Packit ae235b
}
Packit ae235b
Packit ae235b
/* slow method until we get foreach-with-remove in GTree
Packit ae235b
 */
Packit ae235b
typedef struct
Packit ae235b
{
Packit ae235b
  const gchar *path;
Packit ae235b
  const gchar **keys;
Packit ae235b
  gsize index;
Packit ae235b
} CheckPrefixState;
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
check_prefix (gpointer key,
Packit ae235b
              gpointer value,
Packit ae235b
              gpointer data)
Packit ae235b
{
Packit ae235b
  CheckPrefixState *state = data;
Packit ae235b
Packit ae235b
  if (g_str_has_prefix (key, state->path))
Packit ae235b
    state->keys[state->index++] = key;
Packit ae235b
Packit ae235b
  return FALSE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
delayed_backend_path_writable_changed (GObject          *target,
Packit ae235b
                                       GSettingsBackend *backend,
Packit ae235b
                                       const gchar      *path)
Packit ae235b
{
Packit ae235b
  GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (target);
Packit ae235b
  gboolean last_one = FALSE;
Packit ae235b
  gsize n_keys;
Packit ae235b
Packit ae235b
  g_mutex_lock (&delayed->priv->lock);
Packit ae235b
Packit ae235b
  n_keys = g_tree_nnodes (delayed->priv->delayed);
Packit ae235b
Packit ae235b
  if (n_keys > 0)
Packit ae235b
    {
Packit ae235b
      CheckPrefixState state = { path, g_new (const gchar *, n_keys) };
Packit ae235b
      gsize i;
Packit ae235b
Packit ae235b
      /* collect a list of possibly-affected keys (ie: matching the path) */
Packit ae235b
      g_tree_foreach (delayed->priv->delayed, check_prefix, &state);
Packit ae235b
Packit ae235b
      /* drop the keys that have been affected.
Packit ae235b
       *
Packit ae235b
       * don't drop 'reset' keys (see above) */
Packit ae235b
      for (i = 0; i < state.index; i++)
Packit ae235b
        if (g_tree_lookup (delayed->priv->delayed, state.keys[i]) != NULL &&
Packit ae235b
            !g_settings_backend_get_writable (delayed->priv->backend,
Packit ae235b
                                              state.keys[i]))
Packit ae235b
          g_tree_remove (delayed->priv->delayed, state.keys[i]);
Packit ae235b
Packit ae235b
      g_free (state.keys);
Packit ae235b
Packit ae235b
      last_one = g_tree_nnodes (delayed->priv->delayed) == 0;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  g_mutex_unlock (&delayed->priv->lock);
Packit ae235b
Packit ae235b
  if (last_one)
Packit ae235b
    g_delayed_settings_backend_notify_unapplied (delayed);
Packit ae235b
Packit ae235b
  g_settings_backend_path_writable_changed (G_SETTINGS_BACKEND (delayed),
Packit ae235b
                                            path);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_delayed_settings_backend_finalize (GObject *object)
Packit ae235b
{
Packit ae235b
  GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (object);
Packit ae235b
Packit ae235b
  g_mutex_clear (&delayed->priv->lock);
Packit ae235b
  g_object_unref (delayed->priv->backend);
Packit ae235b
  g_tree_unref (delayed->priv->delayed);
Packit ae235b
Packit ae235b
  /* if our owner is still alive, why are we finalizing? */
Packit ae235b
  g_assert (delayed->priv->owner == NULL);
Packit ae235b
Packit ae235b
  G_OBJECT_CLASS (g_delayed_settings_backend_parent_class)
Packit ae235b
    ->finalize (object);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_delayed_settings_backend_class_init (GDelayedSettingsBackendClass *class)
Packit ae235b
{
Packit ae235b
  GSettingsBackendClass *backend_class = G_SETTINGS_BACKEND_CLASS (class);
Packit ae235b
  GObjectClass *object_class = G_OBJECT_CLASS (class);
Packit ae235b
Packit ae235b
  backend_class->read = g_delayed_settings_backend_read;
Packit ae235b
  backend_class->read_user_value = g_delayed_settings_backend_read_user_value;
Packit ae235b
  backend_class->write = g_delayed_settings_backend_write;
Packit ae235b
  backend_class->write_tree = g_delayed_settings_backend_write_tree;
Packit ae235b
  backend_class->reset = g_delayed_settings_backend_reset;
Packit ae235b
  backend_class->get_writable = g_delayed_settings_backend_get_writable;
Packit ae235b
  backend_class->subscribe = g_delayed_settings_backend_subscribe;
Packit ae235b
  backend_class->unsubscribe = g_delayed_settings_backend_unsubscribe;
Packit ae235b
  backend_class->get_permission = g_delayed_settings_backend_get_permission;
Packit ae235b
Packit ae235b
  object_class->finalize = g_delayed_settings_backend_finalize;
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_delayed_settings_backend_init (GDelayedSettingsBackend *delayed)
Packit ae235b
{
Packit ae235b
  delayed->priv = g_delayed_settings_backend_get_instance_private (delayed);
Packit ae235b
  delayed->priv->delayed = g_settings_backend_create_tree ();
Packit ae235b
  g_mutex_init (&delayed->priv->lock);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_delayed_settings_backend_disown (gpointer  data,
Packit ae235b
                                   GObject  *where_the_object_was)
Packit ae235b
{
Packit ae235b
  GDelayedSettingsBackend *delayed = data;
Packit ae235b
Packit ae235b
  g_mutex_lock (&delayed->priv->lock);
Packit ae235b
  delayed->priv->owner_context = NULL;
Packit ae235b
  delayed->priv->owner = NULL;
Packit ae235b
  g_mutex_unlock (&delayed->priv->lock);
Packit ae235b
}
Packit ae235b
Packit ae235b
GDelayedSettingsBackend *
Packit ae235b
g_delayed_settings_backend_new (GSettingsBackend *backend,
Packit ae235b
                                gpointer          owner,
Packit ae235b
                                GMainContext     *owner_context)
Packit ae235b
{
Packit ae235b
  static GSettingsListenerVTable vtable = {
Packit ae235b
    delayed_backend_changed,
Packit ae235b
    delayed_backend_path_changed,
Packit ae235b
    delayed_backend_keys_changed,
Packit ae235b
    delayed_backend_writable_changed,
Packit ae235b
    delayed_backend_path_writable_changed
Packit ae235b
  };
Packit ae235b
  GDelayedSettingsBackend *delayed;
Packit ae235b
Packit ae235b
  delayed = g_object_new (G_TYPE_DELAYED_SETTINGS_BACKEND, NULL);
Packit ae235b
  delayed->priv->backend = g_object_ref (backend);
Packit ae235b
  delayed->priv->owner_context = owner_context;
Packit ae235b
  delayed->priv->owner = owner;
Packit ae235b
Packit ae235b
  g_object_weak_ref (owner, g_delayed_settings_backend_disown, delayed);
Packit ae235b
Packit ae235b
  g_settings_backend_watch (delayed->priv->backend,
Packit ae235b
                            &vtable, G_OBJECT (delayed), NULL);
Packit ae235b
Packit ae235b
  return delayed;
Packit ae235b
}