[gtk/ebassi/expression-type: 2/2] Turn GtkExpression into a GTypeInstance



commit ebaa96c0fadf4081fc772a01b76b3821b138eee4
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Mon Jun 1 21:07:53 2020 +0100

    Turn GtkExpression into a GTypeInstance
    
    Since it's a type with sub-classes, we need to use GTypeInstance (at the
    very least), otherwise we won't be able to address each sub-class as
    such.
    
    This is similar to how GskRenderNode and GdkEvent are handled, with the
    added difficulty that GtkExpression is meant to be used in properties,
    in order to be deserialised by GtkBuilder. This requires adding a
    GParamSpec sub-class that we can match on from within GtkBuilder,
    alongside some convenience API for storing a GtkExpression inside a
    GValue.

 gtk/gtkbuilder.c       |   6 +-
 gtk/gtkdropdown.c      |  15 +-
 gtk/gtkexpression.c    | 738 ++++++++++++++++++++++++++++++++++++++++++-------
 gtk/gtkexpression.h    |  74 ++++-
 gtk/gtknumericsorter.c |  29 +-
 gtk/gtkstringfilter.c  |  17 +-
 gtk/gtkstringsorter.c  |  17 +-
 7 files changed, 753 insertions(+), 143 deletions(-)
---
diff --git a/gtk/gtkbuilder.c b/gtk/gtkbuilder.c
index 385b78db65..187d95720d 100644
--- a/gtk/gtkbuilder.c
+++ b/gtk/gtkbuilder.c
@@ -534,11 +534,9 @@ gtk_builder_get_parameters (GtkBuilder         *builder,
           g_value_init (&property_value, G_PARAM_SPEC_VALUE_TYPE (prop->pspec));
 
           if (G_PARAM_SPEC_VALUE_TYPE (prop->pspec) == GTK_TYPE_EXPRESSION)
-            g_value_set_boxed (&property_value, prop->value);
+            gtk_value_set_expression (&property_value, prop->value);
           else
-            {
-              g_assert_not_reached();
-            }
+            g_assert_not_reached ();
         }
       else if (prop->bound && (!prop->text || prop->text->len == 0))
         {
diff --git a/gtk/gtkdropdown.c b/gtk/gtkdropdown.c
index 4759186a49..c4f3e37f19 100644
--- a/gtk/gtkdropdown.c
+++ b/gtk/gtkdropdown.c
@@ -315,7 +315,7 @@ gtk_drop_down_get_property (GObject    *object,
       break;
 
     case PROP_EXPRESSION:
-      g_value_set_boxed (value, self->expression);
+      gtk_value_set_expression (value, self->expression);
       break;
 
     default:
@@ -355,7 +355,7 @@ gtk_drop_down_set_property (GObject      *object,
       break;
 
     case PROP_EXPRESSION:
-      gtk_drop_down_set_expression (self, g_value_get_boxed (value));
+      gtk_drop_down_set_expression (self, gtk_value_get_expression (value));
       break;
 
     default:
@@ -497,7 +497,7 @@ gtk_drop_down_class_init (GtkDropDownClass *klass)
                          G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
 
   /**
-   * GtkDropDown:expression:
+   * GtkDropDown:expression: (type GtkExpression)
    *
    * An expression to evaluate to obtain strings to match against the search
    * term (see #GtkDropDown:enable-search). If #GtkDropDown:factory is not set,
@@ -505,11 +505,10 @@ gtk_drop_down_class_init (GtkDropDownClass *klass)
    * default factory.
    */
   properties[PROP_EXPRESSION] =
-    g_param_spec_boxed ("expression",
-                        P_("Expression"),
-                        P_("Expression to determine strings to search for"),
-                        GTK_TYPE_EXPRESSION,
-                        G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+    gtk_param_spec_expression ("expression",
+                               P_("Expression"),
+                               P_("Expression to determine strings to search for"),
+                               G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
 
   g_object_class_install_properties (gobject_class, N_PROPS, properties);
 
diff --git a/gtk/gtkexpression.c b/gtk/gtkexpression.c
index 394bdd42e9..2fcf29c83b 100644
--- a/gtk/gtkexpression.c
+++ b/gtk/gtkexpression.c
@@ -30,7 +30,7 @@
  *
  * GtkExpression provides a way to describe references to #GValues.
  *
- * An expression needs to be `evaluated` to obtain the value that it currently refers
+ * An expression needs to be "evaluated" to obtain the value that it currently refers
  * to. An evaluation always happens in the context of a current object called `this`
  * (it mirrors the behavior of object-oriented languages), which may or may not
  * influence the result of the evaluation. Use gtk_expression_evaluate() for
@@ -43,7 +43,7 @@
  *
  * By default, expressions are not paying attention to changes and evaluation is
  * just a snapshot of the current state at a given time. To get informed about
- * changes, an expression needs to be `watched` via a #GtkExpressionWatch, which
+ * changes, an expression needs to be "watched" via a #GtkExpressionWatch, which
  * will cause a callback to be called whenever the value of the expression may
  * have changed. gtk_expression_watch() starts watching an expression, and
  * gtk_expression_watch_unwatch() stops.
@@ -89,33 +89,54 @@
  *   </closure>
  * ]|
  */
+
+
+/**
+ * GtkExpression: (ref-func gtk_expression_ref) (unref-func gtk_expression_unref) (set-value-func 
gtk_value_set_expression) (get-value-func gtk_value_get_expression)
+ *
+ * The `GtkExpression` structure contains only private data.
+ */
+
 typedef struct _GtkExpressionClass GtkExpressionClass;
+typedef struct _GtkExpressionSubWatch GtkExpressionSubWatch;
+typedef struct _GtkExpressionTypeInfo GtkExpressionTypeInfo;
 
 struct _GtkExpression
 {
-  const GtkExpressionClass *expression_class;
+  GTypeInstance parent_instance;
+
+  gatomicrefcount ref_count;
+
   GType value_type;
 
   GtkExpression *owner;
 };
 
-typedef struct _GtkExpressionSubWatch GtkExpressionSubWatch;
-
-struct _GtkExpressionWatch
+struct _GtkExpressionClass
 {
-  GtkExpression         *expression;
-  GObject               *this;
-  GDestroyNotify         user_destroy;
-  GtkExpressionNotify    notify;
-  gpointer               user_data;
-  guchar                 sub[0];
+  GTypeClass parent_class;
+
+  void                  (* finalize)            (GtkExpression          *expr);
+  gboolean              (* is_static)           (GtkExpression          *expr);
+  gboolean              (* evaluate)            (GtkExpression          *expr,
+                                                 gpointer                this,
+                                                 GValue                 *value);
+
+  gsize                 (* watch_size)          (GtkExpression          *expr);
+  void                  (* watch)               (GtkExpression          *self,
+                                                 GtkExpressionSubWatch  *watch,
+                                                 gpointer                this_,
+                                                 GtkExpressionNotify     notify,
+                                                 gpointer                user_data);
+  void                  (* unwatch)             (GtkExpression          *self,
+                                                 GtkExpressionSubWatch  *watch);
 };
 
-struct _GtkExpressionClass
+struct _GtkExpressionTypeInfo
 {
-  gsize struct_size;
-  const char *type_name;
+  gsize instance_size;
 
+  void                  (* instance_init)       (GtkExpression          *expr);
   void                  (* finalize)            (GtkExpression          *expr);
   gboolean              (* is_static)           (GtkExpression          *expr);
   gboolean              (* evaluate)            (GtkExpression          *expr,
@@ -132,64 +153,500 @@ struct _GtkExpressionClass
                                                  GtkExpressionSubWatch  *watch);
 };
 
+struct _GtkExpressionWatch
+{
+  GtkExpression         *expression;
+  GObject               *this;
+  GDestroyNotify         user_destroy;
+  GtkExpressionNotify    notify;
+  gpointer               user_data;
+  guchar                 sub[0];
+};
+
+#define GTK_EXPRESSION_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_EXPRESSION, 
GtkExpressionClass))
+
+/*< private >
+ * GTK_DEFINE_EXPRESSION_TYPE:
+ * @TypeName: the type name, in camel case
+ * @type_name: the type name, in snake case
+ * @type_info: the address of the #GtkExpressionTypeInfo for the expression type
+ *
+ * Registers a new #GtkExpression subclass with the given @TypeName and @type_info.
+ *
+ * Similarly to %G_DEFINE_TYPE, this macro will generate a `get_type()`
+ * function that registers the event type.
+ *
+ * You can specify code to be run after the type registration; the #GType of
+ * the event is available in the `gtk_define_expression_type_id` variable.
+ */
+#define GTK_DEFINE_EXPRESSION_TYPE(TypeName, type_name, type_info) \
+GType \
+type_name ## _get_type (void) \
+{ \
+  static volatile gsize gtk_define_expression_type_id__volatile; \
+  if (g_once_init_enter (&gtk_define_expression_type_id__volatile)) \
+    { \
+      GType gtk_define_expression_type_id = \
+        gtk_expression_type_register_static (g_intern_static_string (#TypeName), type_info); \
+      g_once_init_leave (&gtk_define_expression_type_id__volatile, gtk_define_expression_type_id); \
+    } \
+  return gtk_define_expression_type_id__volatile; \
+}
+
+#define GTK_EXPRESSION_SUPER(expr) \
+  ((GtkExpressionClass *) g_type_class_peek (g_type_parent (G_TYPE_FROM_INSTANCE (expr))))
+
+/* {{{ GtkExpression internals */
+
+static void
+value_expression_init (GValue *value)
+{
+  value->data[0].v_pointer = NULL;
+}
+
+static void
+value_expression_free_value (GValue *value)
+{
+  if (value->data[0].v_pointer != NULL)
+    gtk_expression_unref (value->data[0].v_pointer);
+}
+
+static void
+value_expression_copy_value (const GValue *src,
+                             GValue       *dst)
+{
+  if (src->data[0].v_pointer != NULL)
+    dst->data[0].v_pointer = gtk_expression_ref (src->data[0].v_pointer);
+  else
+    dst->data[0].v_pointer = NULL;
+}
+
+static gpointer
+value_expression_peek_pointer (const GValue *value)
+{
+  return value->data[0].v_pointer;
+}
+
+static char *
+value_expression_collect_value (GValue      *value,
+                                guint        n_collect_values,
+                                GTypeCValue *collect_values,
+                                guint        collect_flags)
+{
+  GtkExpression *expression = collect_values[0].v_pointer;
+
+  if (expression == NULL)
+    {
+      value->data[0].v_pointer = NULL;
+      return NULL;
+    }
+
+  if (expression->parent_instance.g_class == NULL)
+    return g_strconcat ("invalid unclassed GtkExpression pointer for "
+                        "value type '",
+                        G_VALUE_TYPE_NAME (value),
+                        "'",
+                        NULL);
+
+  value->data[0].v_pointer = gtk_expression_ref (expression);
+
+  return NULL;
+}
+
+static gchar *
+value_expression_lcopy_value (const GValue *value,
+                              guint         n_collect_values,
+                              GTypeCValue  *collect_values,
+                              guint         collect_flags)
+{
+  GtkExpression **expression_p = collect_values[0].v_pointer;
+
+  if (expression_p == NULL)
+    return g_strconcat ("value location for '",
+                        G_VALUE_TYPE_NAME (value),
+                        "' passed as NULL",
+                        NULL);
+
+  if (value->data[0].v_pointer == NULL)
+    *expression_p = NULL;
+  else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
+    *expression_p = value->data[0].v_pointer;
+  else
+    *expression_p = gtk_expression_ref (value->data[0].v_pointer);
+
+  return NULL;
+}
+
 /**
- * GtkExpression: (ref-func gtk_expression_ref) (unref-func gtk_expression_unref)
+ * gtk_value_set_expression:
+ * @value: a #GValue initialized with type %GTK_TYPE_EXPRESSION
+ * @expression: a #GtkExpression
  *
- * The `GtkExpression` structure contains only private data.
+ * Stores the given #GtkExpression inside @value.
+ *
+ * The #GValue will acquire a reference to the @expression.
  */
+void
+gtk_value_set_expression (GValue        *value,
+                          GtkExpression *expression)
+{
+  g_return_if_fail (G_VALUE_HOLDS (value, GTK_TYPE_EXPRESSION));
 
-G_DEFINE_BOXED_TYPE (GtkExpression, gtk_expression,
-                     gtk_expression_ref,
-                     gtk_expression_unref)
+  GtkExpression *old_expression = value->data[0].v_pointer;
 
-/*< private >
- * gtk_expression_alloc:
- * @expression_class: class structure for this expression
- * @value_type: the type of the value returned by this expression
+  if (expression != NULL)
+    {
+      g_return_if_fail (GTK_IS_EXPRESSION (expression));
+
+      value->data[0].v_pointer = gtk_expression_ref (expression);
+    }
+  else
+    {
+      value->data[0].v_pointer = NULL;
+    }
+
+  if (old_expression != NULL)
+    gtk_expression_unref (old_expression);
+}
+
+/**
+ * gtk_value_take_expression:
+ * @value: a #GValue initialized with type %GTK_TYPE_EXPRESSION
+ * @expression: (transfer full) (nullable): a #GtkExpression
  *
- * Returns: (transfer full): the newly created #GtkExpression
+ * Stores the given #GtkExpression inside @value.
+ *
+ * This function transfers the ownership of the @expression to the #GValue.
  */
-static gpointer
-gtk_expression_alloc (const GtkExpressionClass *expression_class,
-                      GType                     value_type)
+void
+gtk_value_take_expression (GValue        *value,
+                           GtkExpression *expression)
 {
-  GtkExpression *self;
+  g_return_if_fail (G_VALUE_HOLDS (value, GTK_TYPE_EXPRESSION));
 
-  g_return_val_if_fail (expression_class != NULL, NULL);
+  GtkExpression *old_expression = value->data[0].v_pointer;
 
-  self = g_atomic_rc_box_alloc0 (expression_class->struct_size);
+  if (expression != NULL)
+    {
+      g_return_if_fail (GTK_IS_EXPRESSION (expression));
 
-  self->expression_class = expression_class;
-  self->value_type = value_type;
+      value->data[0].v_pointer = expression;
+    }
+  else
+    {
+      value->data[0].v_pointer = NULL;
+    }
 
-  return self;
+  if (old_expression != NULL)
+    gtk_expression_unref (old_expression);
+}
+
+/**
+ * gtk_value_get_expression:
+ * @value: a #GValue initialized with type %GTK_TYPE_EXPRESSION
+ *
+ * Retrieves the #GtkExpression stored inside the given @value.
+ *
+ * Returns: (transfer none) (nullable): a #GtkExpression
+ */
+GtkExpression *
+gtk_value_get_expression (const GValue *value)
+{
+  g_return_val_if_fail (G_VALUE_HOLDS (value, GTK_TYPE_EXPRESSION), NULL);
+
+  return value->data[0].v_pointer;
+}
+
+/**
+ * gtk_value_dup_expression:
+ * @value: a #GValue initialized with type %GTK_TYPE_EXPRESSION
+ *
+ * Retrieves the #GtkExpression stored inside the given @value, and acquires
+ * a reference to it.
+ *
+ * Returns: (transfer full) (nullable): a #GtkExpression
+ */
+GtkExpression *
+gtk_value_dup_expression (const GValue *value)
+{
+  g_return_val_if_fail (G_VALUE_HOLDS (value, GTK_TYPE_EXPRESSION), NULL);
+
+  if (value->data[0].v_pointer == NULL)
+    return NULL;
+
+  GtkExpression *expression = value->data[0].v_pointer;
+
+  return gtk_expression_ref (expression);
+}
+
+static void
+param_expression_init (GParamSpec *pspec)
+{
+}
+
+static void
+param_expression_set_default (GParamSpec *pspec,
+                              GValue     *value)
+{
+  value->data[0].v_pointer = NULL;
+}
+
+static gboolean
+param_expression_validate (GParamSpec *pspec,
+                           GValue     *value)
+{
+  GtkParamSpecExpression *espec = GTK_PARAM_SPEC_EXPRESSION (pspec);
+  GtkExpression *expr = value->data[0].v_pointer;
+  guint changed = 0;
+
+  if (expr != NULL &&
+      !g_value_type_compatible (G_TYPE_FROM_INSTANCE (expr), G_PARAM_SPEC_VALUE_TYPE (espec)))
+    {
+      gtk_expression_unref (expr);
+      value->data[0].v_pointer = NULL;
+      changed++;
+    }
+
+  return changed;
+}
+
+static gint
+param_expression_values_cmp (GParamSpec   *pspec,
+                             const GValue *value1,
+                             const GValue *value2)
+{
+  guint8 *p1 = value1->data[0].v_pointer;
+  guint8 *p2 = value2->data[0].v_pointer;
+
+  return p1 < p2 ? -1 : p1 > p2;
+}
+
+GType
+gtk_param_expression_get_type (void)
+{
+  static volatile gsize param_expression_type__volatile;
+
+  if (g_once_init_enter (&param_expression_type__volatile))
+    {
+      const GParamSpecTypeInfo pspec_info = {
+        sizeof (GtkParamSpecExpression),
+        16,
+        param_expression_init,
+        GTK_TYPE_EXPRESSION,
+        NULL,
+        param_expression_set_default,
+        param_expression_validate,
+        param_expression_values_cmp,
+      };
+
+      GType param_expression_type =
+        g_param_type_register_static (g_intern_static_string ("GtkParamSpecExpression"),
+                                      &pspec_info);
+
+      g_once_init_leave (&param_expression_type__volatile, param_expression_type);
+    }
+
+  return param_expression_type__volatile;
+}
+
+/**
+ * gtk_param_spec_expression:
+ * @name: canonical name of the property
+ * @nick: a user-readable name for the property
+ * @blurb: a user-readable description of the property
+ * @flags: flags for the property
+ *
+ * Creates a new #GParamSpec instance for a property holding a #GtkExpression.
+ *
+ * See g_param_spec_internal() for details on the property strings.
+ *
+ * Returns: (transfer full): a newly created property specification
+ */
+GParamSpec *
+gtk_param_spec_expression (const char  *name,
+                           const char  *nick,
+                           const char  *blurb,
+                           GParamFlags  flags)
+{
+  GParamSpec *pspec = g_param_spec_internal (GTK_TYPE_PARAM_SPEC_EXPRESSION,
+                                             name, nick, blurb,
+                                             flags);
+
+  pspec->value_type = GTK_TYPE_EXPRESSION;
+
+  return pspec;
+}
+
+/* }}} */
+
+/* {{{ GtkExpression internals */
+
+static void
+gtk_expression_real_finalize (GtkExpression *self)
+{
+  g_type_free_instance ((GTypeInstance *) self);
 }
 
 static gsize
-gtk_expression_watch_size_static (GtkExpression *self)
+gtk_expression_real_watch_size (GtkExpression *self)
 {
   return 0;
 }
 
 static void
-gtk_expression_watch_static (GtkExpression         *self,
-                             GtkExpressionSubWatch *watch,
-                             gpointer               this_,
-                             GtkExpressionNotify    notify,
-                             gpointer               user_data)
+gtk_expression_real_watch (GtkExpression         *self,
+                           GtkExpressionSubWatch *watch,
+                           gpointer               this_,
+                           GtkExpressionNotify    notify,
+                           gpointer               user_data)
 {
 }
 
 static void
-gtk_expression_unwatch_static (GtkExpression         *self,
-                               GtkExpressionSubWatch *watch)
+gtk_expression_real_unwatch (GtkExpression         *self,
+                             GtkExpressionSubWatch *watch)
 {
 }
 
 static gsize
 gtk_expression_watch_size (GtkExpression *self)
 {
-  return self->expression_class->watch_size (self);
+  return GTK_EXPRESSION_GET_CLASS (self)->watch_size (self);
+}
+
+static void
+gtk_expression_class_init (GtkExpressionClass *klass)
+{
+  klass->finalize = gtk_expression_real_finalize;
+  klass->watch_size = gtk_expression_real_watch_size;
+  klass->watch = gtk_expression_real_watch;
+  klass->unwatch = gtk_expression_real_unwatch;
+}
+
+static void
+gtk_expression_init (GtkExpression *self)
+{
+  g_atomic_ref_count_init (&self->ref_count);
+}
+
+GType
+gtk_expression_get_type (void)
+{
+  static volatile gsize expression_type__volatile;
+
+  if (g_once_init_enter (&expression_type__volatile))
+    {
+      static const GTypeFundamentalInfo finfo = {
+        (G_TYPE_FLAG_CLASSED |
+         G_TYPE_FLAG_INSTANTIATABLE |
+         G_TYPE_FLAG_DERIVABLE |
+         G_TYPE_FLAG_DEEP_DERIVABLE),
+      };
+
+      static const GTypeValueTable value_table = {
+        value_expression_init,
+        value_expression_free_value,
+        value_expression_copy_value,
+        value_expression_peek_pointer,
+        "p",
+        value_expression_collect_value,
+        "p",
+        value_expression_lcopy_value,
+      };
+
+      const GTypeInfo event_info = {
+        /* Class */
+        sizeof (GtkExpressionClass),
+        (GBaseInitFunc) NULL,
+        (GBaseFinalizeFunc) NULL,
+        (GClassInitFunc) gtk_expression_class_init,
+        (GClassFinalizeFunc) NULL,
+        NULL,
+
+        /* Instance */
+        sizeof (GtkExpression),
+        0,
+        (GInstanceInitFunc) gtk_expression_init,
+
+        /* GValue */
+        &value_table,
+      };
+
+      GType expression_type =
+        g_type_register_fundamental (g_type_fundamental_next (),
+                                     g_intern_static_string ("GtkExpression"),
+                                     &event_info, &finfo,
+                                     G_TYPE_FLAG_ABSTRACT);
+
+      g_once_init_leave (&expression_type__volatile, expression_type);
+    }
+
+  return expression_type__volatile;
+}
+
+static void
+gtk_expression_generic_class_init (gpointer g_class,
+                                   gpointer class_data)
+{
+  GtkExpressionTypeInfo *info = class_data;
+  GtkExpressionClass *expression_class = g_class;
+
+  /* Mandatory */
+  expression_class->is_static = info->is_static;
+  expression_class->evaluate = info->evaluate;
+
+  /* Optional */
+  if (info->finalize != NULL)
+    expression_class->finalize = info->finalize;
+  if (info->watch_size != NULL)
+    expression_class->watch_size = info->watch_size;
+  if (info->watch != NULL)
+    expression_class->watch = info->watch;
+  if (info->unwatch != NULL)
+    expression_class->unwatch = info->unwatch;
+
+  g_free (info);
+}
+
+static GType
+gtk_expression_type_register_static (const char                  *type_name,
+                                     const GtkExpressionTypeInfo *type_info)
+{
+  GTypeInfo info;
+
+  info.class_size = sizeof (GtkExpressionClass);
+  info.base_init = NULL;
+  info.base_finalize = NULL;
+  info.class_init = gtk_expression_generic_class_init;
+  info.class_finalize = NULL;
+  info.class_data = g_memdup (type_info, sizeof (GtkExpressionTypeInfo));
+
+  info.instance_size = type_info->instance_size;
+  info.n_preallocs = 0;
+  info.instance_init = (GInstanceInitFunc) type_info->instance_init;
+  info.value_table = NULL;
+
+  return g_type_register_static (GTK_TYPE_EXPRESSION, type_name, &info, 0);
+}
+
+/*< private >
+ * gtk_expression_alloc:
+ * @expression_type: the type of expression to create
+ * @value_type: the type of the value returned by this expression
+ *
+ * Returns: (transfer full): the newly created #GtkExpression
+ */
+static gpointer
+gtk_expression_alloc (GType expression_type,
+                      GType value_type)
+{
+  GtkExpression *self;
+
+  self = (GtkExpression *) g_type_create_instance (expression_type);
+
+  self->value_type = value_type;
+
+  return self;
 }
 
 static void
@@ -199,17 +656,19 @@ gtk_expression_subwatch_init (GtkExpression         *self,
                               GtkExpressionNotify    notify,
                               gpointer               user_data)
 {
-  self->expression_class->watch (self, watch, this, notify, user_data);
+  GTK_EXPRESSION_GET_CLASS (self)->watch (self, watch, this, notify, user_data);
 }
 
 static void
 gtk_expression_subwatch_finish (GtkExpression         *self,
                                 GtkExpressionSubWatch *watch)
 {
-  self->expression_class->unwatch (self, watch);
+  GTK_EXPRESSION_GET_CLASS (self)->unwatch (self, watch);
 }
 
-/*** CONSTANT ***/
+/* }}} */
+
+/* {{{ GtkConstantExpression */
 
 typedef struct _GtkConstantExpression GtkConstantExpression;
 
@@ -226,6 +685,8 @@ gtk_constant_expression_finalize (GtkExpression *expr)
   GtkConstantExpression *self = (GtkConstantExpression *) expr;
 
   g_value_unset (&self->value);
+
+  GTK_EXPRESSION_SUPER (expr)->finalize (expr);
 }
 
 static gboolean
@@ -246,18 +707,22 @@ gtk_constant_expression_evaluate (GtkExpression *expr,
   return TRUE;
 }
 
-static const GtkExpressionClass GTK_CONSTANT_EXPRESSION_CLASS =
+static const GtkExpressionTypeInfo gtk_constant_expression_info =
 {
   sizeof (GtkConstantExpression),
-  "GtkConstantExpression",
+  NULL,
   gtk_constant_expression_finalize,
   gtk_constant_expression_is_static,
   gtk_constant_expression_evaluate,
-  gtk_expression_watch_size_static,
-  gtk_expression_watch_static,
-  gtk_expression_unwatch_static
+  NULL,
+  NULL,
+  NULL,
 };
 
+GTK_DEFINE_EXPRESSION_TYPE (GtkConstantExpression,
+                            gtk_constant_expression,
+                            &gtk_constant_expression_info)
+
 /**
  * gtk_constant_expression_new:
  * @value_type: The type of the object
@@ -310,19 +775,23 @@ gtk_constant_expression_new (GType value_type,
 GtkExpression *
 gtk_constant_expression_new_for_value (const GValue *value)
 {
-  GtkConstantExpression *result;
+  GtkExpression *result;
+  GtkConstantExpression *self;
 
   g_return_val_if_fail (G_IS_VALUE (value), NULL);
 
-  result = gtk_expression_alloc (&GTK_CONSTANT_EXPRESSION_CLASS, G_VALUE_TYPE (value));
+  result = gtk_expression_alloc (GTK_TYPE_CONSTANT_EXPRESSION, G_VALUE_TYPE (value));
+  self = (GtkConstantExpression *) result;
 
-  g_value_init (&result->value, G_VALUE_TYPE (value));
-  g_value_copy (value, &result->value);
+  g_value_init (&self->value, G_VALUE_TYPE (value));
+  g_value_copy (value, &self->value);
 
-  return (GtkExpression *) result;
+  return result;
 }
 
-/*** OBJECT ***/
+/* }}} */
+
+/* {{{ GtkObjectExpression */
 
 typedef struct _GtkObjectExpression GtkObjectExpression;
 typedef struct _GtkObjectExpressionWatch GtkObjectExpressionWatch;
@@ -367,6 +836,8 @@ gtk_object_expression_finalize (GtkExpression *expr)
     g_object_weak_unref (self->object, gtk_object_expression_weak_ref_cb, self);
 
   g_assert (self->watches == NULL);
+
+  GTK_EXPRESSION_SUPER (expr)->finalize (expr);
 }
 
 static gboolean
@@ -420,10 +891,10 @@ gtk_object_expression_unwatch (GtkExpression         *expr,
   self->watches = g_slist_remove (self->watches, watch);
 }
 
-static const GtkExpressionClass GTK_OBJECT_EXPRESSION_CLASS =
+static const GtkExpressionTypeInfo gtk_object_expression_info =
 {
   sizeof (GtkObjectExpression),
-  "GtkObjectExpression",
+  NULL,
   gtk_object_expression_finalize,
   gtk_object_expression_is_static,
   gtk_object_expression_evaluate,
@@ -432,6 +903,10 @@ static const GtkExpressionClass GTK_OBJECT_EXPRESSION_CLASS =
   gtk_object_expression_unwatch
 };
 
+GTK_DEFINE_EXPRESSION_TYPE (GtkObjectExpression,
+                            gtk_object_expression,
+                            &gtk_object_expression_info)
+
 /**
  * gtk_object_expression_new:
  * @object: (transfer none): object to watch
@@ -447,19 +922,23 @@ static const GtkExpressionClass GTK_OBJECT_EXPRESSION_CLASS =
 GtkExpression *
 gtk_object_expression_new (GObject *object)
 {
-  GtkObjectExpression *result;
+  GtkExpression *result;
+  GtkObjectExpression *self;
 
   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
 
-  result = gtk_expression_alloc (&GTK_OBJECT_EXPRESSION_CLASS, G_OBJECT_TYPE (object));
+  result = gtk_expression_alloc (GTK_TYPE_OBJECT_EXPRESSION, G_OBJECT_TYPE (object));
+  self = (GtkObjectExpression *) result;
 
-  result->object = object;
-  g_object_weak_ref (object, gtk_object_expression_weak_ref_cb, result);
+  self->object = object;
+  g_object_weak_ref (object, gtk_object_expression_weak_ref_cb, self);
 
-  return (GtkExpression *) result;
+  return result;
 }
 
-/*** PROPERTY ***/
+/* }}} */
+
+/* {{{ GtkPropertyExpression */
 
 typedef struct _GtkPropertyExpression GtkPropertyExpression;
 
@@ -478,6 +957,8 @@ gtk_property_expression_finalize (GtkExpression *expr)
   GtkPropertyExpression *self = (GtkPropertyExpression *) expr;
 
   g_clear_pointer (&self->expr, gtk_expression_unref);
+
+  GTK_EXPRESSION_SUPER (expr)->finalize (expr);
 }
 
 static gboolean
@@ -657,10 +1138,10 @@ gtk_property_expression_unwatch (GtkExpression         *expr,
     gtk_expression_subwatch_finish (self->expr, (GtkExpressionSubWatch *) pwatch->sub);
 }
 
-static const GtkExpressionClass GTK_PROPERTY_EXPRESSION_CLASS =
+static const GtkExpressionTypeInfo gtk_property_expression_info =
 {
   sizeof (GtkPropertyExpression),
-  "GtkPropertyExpression",
+  NULL,
   gtk_property_expression_finalize,
   gtk_property_expression_is_static,
   gtk_property_expression_evaluate,
@@ -669,6 +1150,10 @@ static const GtkExpressionClass GTK_PROPERTY_EXPRESSION_CLASS =
   gtk_property_expression_unwatch
 };
 
+GTK_DEFINE_EXPRESSION_TYPE (GtkPropertyExpression,
+                            gtk_property_expression,
+                            &gtk_property_expression_info)
+
 /**
  * gtk_property_expression_new:
  * @this_type: The type to expect for the this type
@@ -744,17 +1229,21 @@ GtkExpression *
 gtk_property_expression_new_for_pspec (GtkExpression *expression,
                                        GParamSpec    *pspec)
 {
-  GtkPropertyExpression *result;
+  GtkExpression *result;
+  GtkPropertyExpression *self;
 
-  result = gtk_expression_alloc (&GTK_PROPERTY_EXPRESSION_CLASS, pspec->value_type);
+  result = gtk_expression_alloc (GTK_TYPE_PROPERTY_EXPRESSION, pspec->value_type);
+  self = (GtkPropertyExpression *) result;
 
-  result->pspec = pspec;
-  result->expr = expression;
+  self->pspec = pspec;
+  self->expr = expression;
 
-  return (GtkExpression *) result;
+  return result;
 }
 
-/*** CLOSURE ***/
+/* }}} */
+
+/* {{{ GtkClosureExpression */
 
 typedef struct _GtkClosureExpression GtkClosureExpression;
 
@@ -780,6 +1269,8 @@ gtk_closure_expression_finalize (GtkExpression *expr)
   g_free (self->params);
 
   g_closure_unref (self->closure);
+
+  GTK_EXPRESSION_SUPER (expr)->finalize (expr);
 }
 
 static gboolean
@@ -925,10 +1416,10 @@ gtk_closure_expression_unwatch (GtkExpression         *expr,
     }
 }
 
-static const GtkExpressionClass GTK_CLOSURE_EXPRESSION_CLASS =
+static const GtkExpressionTypeInfo gtk_closure_expression_info =
 {
   sizeof (GtkClosureExpression),
-  "GtkClosureExpression",
+  NULL,
   gtk_closure_expression_finalize,
   gtk_closure_expression_is_static,
   gtk_closure_expression_evaluate,
@@ -937,6 +1428,10 @@ static const GtkExpressionClass GTK_CLOSURE_EXPRESSION_CLASS =
   gtk_closure_expression_unwatch
 };
 
+GTK_DEFINE_EXPRESSION_TYPE (GtkClosureExpression,
+                            gtk_closure_expression,
+                            &gtk_closure_expression_info)
+
 /**
  * gtk_closure_expression_new:
  * @value_type: the type of the value that this expression evaluates to
@@ -956,27 +1451,56 @@ gtk_closure_expression_new (GType                value_type,
                             guint                n_params,
                             GtkExpression      **params)
 {
-  GtkClosureExpression *result;
+  GtkExpression *result;
+  GtkClosureExpression *self;
   guint i;
 
   g_return_val_if_fail (closure != NULL, NULL);
   g_return_val_if_fail (n_params == 0 || params != NULL, NULL);
 
-  result = gtk_expression_alloc (&GTK_CLOSURE_EXPRESSION_CLASS, value_type);
+  result = gtk_expression_alloc (GTK_TYPE_CLOSURE_EXPRESSION, value_type);
+  self = (GtkClosureExpression *) result;
 
-  result->closure = g_closure_ref (closure);
+  self->closure = g_closure_ref (closure);
   g_closure_sink (closure);
   if (G_CLOSURE_NEEDS_MARSHAL (closure))
     g_closure_set_marshal (closure, g_cclosure_marshal_generic);
 
-  result->n_params = n_params;
-  result->params = g_new (GtkExpression *, n_params);
+  self->n_params = n_params;
+  self->params = g_new (GtkExpression *, n_params);
   for (i = 0; i < n_params; i++)
-    result->params[i] = params[i];
+    self->params[i] = params[i];
 
-  return (GtkExpression *) result;
+  return result;
 }
 
+/* }}} */
+
+/* {{{ GtkCClosureExpression */
+
+typedef struct _GtkCClosureExpression GtkCClosureExpression;
+
+struct _GtkCClosureExpression
+{
+  GtkClosureExpression parent;
+};
+
+static const GtkExpressionTypeInfo gtk_cclosure_expression_info =
+{
+  sizeof (GtkClosureExpression),
+  NULL,
+  gtk_closure_expression_finalize,
+  gtk_closure_expression_is_static,
+  gtk_closure_expression_evaluate,
+  gtk_closure_expression_watch_size,
+  gtk_closure_expression_watch,
+  gtk_closure_expression_unwatch
+};
+
+GTK_DEFINE_EXPRESSION_TYPE (GtkCClosureExpression,
+                            gtk_cclosure_expression,
+                            &gtk_cclosure_expression_info)
+
 /**
  * gtk_cclosure_expression_new:
  * @value_type: the type of the value that this expression evaluates to
@@ -1002,23 +1526,38 @@ gtk_cclosure_expression_new (GType                value_type,
                              gpointer             user_data,
                              GClosureNotify       user_destroy)
 {
+  GtkExpression *result;
+  GtkClosureExpression *self;
   GClosure *closure;
+  guint i;
+
+  g_return_val_if_fail (callback_func != NULL, NULL);
+  g_return_val_if_fail (n_params == 0 || params != NULL, NULL);
+
+  result = gtk_expression_alloc (GTK_TYPE_CCLOSURE_EXPRESSION, value_type);
+  self = (GtkClosureExpression *) result;
 
   closure = g_cclosure_new (callback_func, user_data, user_destroy);
   if (marshal)
     g_closure_set_marshal (closure, marshal);
 
-  return gtk_closure_expression_new (value_type, closure, n_params, params);
-}
+  self->closure = g_closure_ref (closure);
+  g_closure_sink (closure);
+  if (G_CLOSURE_NEEDS_MARSHAL (closure))
+    g_closure_set_marshal (closure, g_cclosure_marshal_generic);
 
-/*** PUBLIC API ***/
+  self->n_params = n_params;
+  self->params = g_new (GtkExpression *, n_params);
+  for (i = 0; i < n_params; i++)
+    self->params[i] = params[i];
 
-static void
-gtk_expression_finalize (GtkExpression *self)
-{
-  self->expression_class->finalize (self);
+  return result;
 }
 
+/* }}} */
+
+/* {{{ GtkExpression public API */
+
 /**
  * gtk_expression_ref:
  * @self: (allow-none): a #GtkExpression
@@ -1030,7 +1569,11 @@ gtk_expression_finalize (GtkExpression *self)
 GtkExpression *
 gtk_expression_ref (GtkExpression *self)
 {
-  return g_atomic_rc_box_acquire (self);
+  g_return_val_if_fail (GTK_IS_EXPRESSION (self), NULL);
+
+  g_atomic_ref_count_inc (&self->ref_count);
+
+  return self;
 }
 
 /**
@@ -1045,7 +1588,10 @@ gtk_expression_ref (GtkExpression *self)
 void
 gtk_expression_unref (GtkExpression *self)
 {
-  g_atomic_rc_box_release_full (self, (GDestroyNotify) gtk_expression_finalize);
+  g_return_if_fail (GTK_IS_EXPRESSION (self));
+
+  if (g_atomic_ref_count_dec (&self->ref_count))
+    GTK_EXPRESSION_GET_CLASS (self)->finalize (self);
 }
 
 /**
@@ -1091,7 +1637,7 @@ gtk_expression_evaluate (GtkExpression *self,
   g_return_val_if_fail (this_ == NULL || G_IS_OBJECT (this_), FALSE);
   g_return_val_if_fail (value != NULL, FALSE);
 
-  return self->expression_class->evaluate (self, this_, value);
+  return GTK_EXPRESSION_GET_CLASS (self)->evaluate (self, this_, value);
 }
 
 /**
@@ -1111,7 +1657,9 @@ gtk_expression_evaluate (GtkExpression *self,
 gboolean
 gtk_expression_is_static (GtkExpression *self)
 {
-  return self->expression_class->is_static (self);
+  g_return_val_if_fail (GTK_IS_EXPRESSION (self), FALSE);
+
+  return GTK_EXPRESSION_GET_CLASS (self)->is_static (self);
 }
 
 static gboolean
@@ -1146,7 +1694,7 @@ gtk_expression_watch_cb (gpointer data)
 /**
  * gtk_expression_watch:
  * @self: a #GtkExpression
- * @this_: (transfer none) (type GObject) (nullable): the this argument to
+ * @this_: (transfer none) (type GObject) (nullable): the `this` argument to
  *     watch
  * @notify: (closure user_data): callback to invoke when the
  *     expression changes
@@ -1445,3 +1993,5 @@ gtk_expression_bind (GtkExpression *self,
 
   return bind->watch;
 }
+
+/* }}} */
diff --git a/gtk/gtkexpression.h b/gtk/gtkexpression.h
index 9705dae18f..44bebf75bb 100644
--- a/gtk/gtkexpression.h
+++ b/gtk/gtkexpression.h
@@ -25,6 +25,10 @@
 
 G_BEGIN_DECLS
 
+#define GTK_TYPE_EXPRESSION     (gtk_expression_get_type ())
+#define GTK_IS_EXPRESSION(obj)  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_EXPRESSION))
+#define GTK_EXPRESSION(obj)     (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_EXPRESSION, GtkExpression))
+
 typedef struct _GtkExpression GtkExpression;
 typedef struct _GtkExpressionWatch GtkExpressionWatch;
 
@@ -37,10 +41,6 @@ typedef struct _GtkExpressionWatch GtkExpressionWatch;
  */
 typedef void            (* GtkExpressionNotify)                 (gpointer                        user_data);
 
-#define GTK_IS_EXPRESSION(expr) ((expr) != NULL)
-
-#define GTK_TYPE_EXPRESSION (gtk_expression_get_type ())
-
 GDK_AVAILABLE_IN_ALL
 GType                   gtk_expression_get_type                 (void) G_GNUC_CONST;
 
@@ -79,6 +79,12 @@ gboolean                gtk_expression_watch_evaluate           (GtkExpressionWa
 GDK_AVAILABLE_IN_ALL
 void                    gtk_expression_watch_unwatch            (GtkExpressionWatch             *watch);
 
+#define GTK_TYPE_PROPERTY_EXPRESSION (gtk_property_expression_get_type())
+typedef struct _GtkPropertyExpression   GtkPropertyExpression;
+
+GDK_AVAILABLE_IN_ALL
+GType                   gtk_property_expression_get_type        (void) G_GNUC_CONST;
+
 GDK_AVAILABLE_IN_ALL
 GtkExpression *         gtk_property_expression_new             (GType                           this_type,
                                                                  GtkExpression                  *expression,
@@ -86,18 +92,46 @@ GtkExpression *         gtk_property_expression_new             (GType
 GDK_AVAILABLE_IN_ALL
 GtkExpression *         gtk_property_expression_new_for_pspec   (GtkExpression                  *expression,
                                                                  GParamSpec                     *pspec);
+
+#define GTK_TYPE_CONSTANT_EXPRESSION (gtk_constant_expression_get_type())
+typedef struct _GtkConstantExpression   GtkConstantExpression;
+
+GDK_AVAILABLE_IN_ALL
+GType                   gtk_constant_expression_get_type        (void) G_GNUC_CONST;
+
 GDK_AVAILABLE_IN_ALL
 GtkExpression *         gtk_constant_expression_new             (GType                           value_type,
                                                                  ...);
 GDK_AVAILABLE_IN_ALL
 GtkExpression *         gtk_constant_expression_new_for_value   (const GValue                   *value);
+
+#define GTK_TYPE_OBJECT_EXPRESSION (gtk_object_expression_get_type())
+typedef struct _GtkObjectExpression     GtkObjectExpression;
+
+GDK_AVAILABLE_IN_ALL
+GType                   gtk_object_expression_get_type          (void) G_GNUC_CONST;
+
 GDK_AVAILABLE_IN_ALL
 GtkExpression *         gtk_object_expression_new               (GObject                        *object);
+
+#define GTK_TYPE_CLOSURE_EXPRESSION (gtk_closure_expression_get_type())
+typedef struct _GtkClosureExpression    GtkClosureExpression;
+
+GDK_AVAILABLE_IN_ALL
+GType                   gtk_closure_expression_get_type         (void) G_GNUC_CONST;
+
 GDK_AVAILABLE_IN_ALL
 GtkExpression *         gtk_closure_expression_new              (GType                           value_type,
                                                                  GClosure                       *closure,
                                                                  guint                           n_params,
                                                                  GtkExpression                 **params);
+
+#define GTK_TYPE_CCLOSURE_EXPRESSION (gtk_cclosure_expression_get_type())
+typedef struct _GtkCClosureExpression   GtkCClosureExpression;
+
+GDK_AVAILABLE_IN_ALL
+GType                   gtk_cclosure_expression_get_type        (void) G_GNUC_CONST;
+
 GDK_AVAILABLE_IN_ALL
 GtkExpression *         gtk_cclosure_expression_new             (GType                           value_type,
                                                                  GClosureMarshal                 marshal,
@@ -107,6 +141,38 @@ GtkExpression *         gtk_cclosure_expression_new             (GType
                                                                  gpointer                        user_data,
                                                                  GClosureNotify                  
user_destroy);
 
+/* GObject integration, so we can use GtkBuilder */
+
+#define GTK_VALUE_HOLDS_EXPRESSION(value)       (G_VALUE_HOLDS ((value), GTK_TYPE_EXPRESSION))
+
+GDK_AVAILABLE_IN_ALL
+void            gtk_value_set_expression        (GValue        *value,
+                                                 GtkExpression *expression);
+GDK_AVAILABLE_IN_ALL
+void            gtk_value_take_expression       (GValue        *value,
+                                                 GtkExpression *expression);
+GDK_AVAILABLE_IN_ALL
+GtkExpression * gtk_value_get_expression        (const GValue  *value);
+GDK_AVAILABLE_IN_ALL
+GtkExpression * gtk_value_dup_expression        (const GValue  *value);
+
+#define GTK_TYPE_PARAM_SPEC_EXPRESSION (gtk_param_expression_get_type())
+#define GTK_PARAM_SPEC_EXPRESSION(obj)          (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
GTK_TYPE_PARAM_SPEC_EXPRESSION, GtkParamSpecExpression))
+#define GTK_IS_PARAM_SPEC_EXPRESSION(obj)       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
GTK_TYPE_PARAM_SPEC_EXPRESSION))
+
+typedef struct {
+  /*< private >*/
+  GParamSpec parent_instance;
+} GtkParamSpecExpression;
+
+GDK_AVAILABLE_IN_ALL
+GType           gtk_param_expression_get_type   (void) G_GNUC_CONST;
+GDK_AVAILABLE_IN_ALL
+GParamSpec *    gtk_param_spec_expression       (const char    *name,
+                                                 const char    *nick,
+                                                 const char    *blurb,
+                                                 GParamFlags    flags);
+
 G_END_DECLS
 
 #endif /* __GTK_EXPRESSION_H__ */
diff --git a/gtk/gtknumericsorter.c b/gtk/gtknumericsorter.c
index eac561241b..94ca187d6e 100644
--- a/gtk/gtknumericsorter.c
+++ b/gtk/gtknumericsorter.c
@@ -212,7 +212,7 @@ gtk_numeric_sorter_set_property (GObject      *object,
   switch (prop_id)
     {
     case PROP_EXPRESSION:
-      gtk_numeric_sorter_set_expression (self, g_value_get_boxed (value));
+      gtk_numeric_sorter_set_expression (self, gtk_value_get_expression (value));
       break;
 
     case PROP_SORT_ORDER:
@@ -236,7 +236,7 @@ gtk_numeric_sorter_get_property (GObject     *object,
   switch (prop_id)
     {
     case PROP_EXPRESSION:
-      g_value_set_boxed (value, self->expression);
+      gtk_value_set_expression (value, self->expression);
       break;
 
     case PROP_SORT_ORDER:
@@ -273,16 +273,15 @@ gtk_numeric_sorter_class_init (GtkNumericSorterClass *class)
   object_class->dispose = gtk_numeric_sorter_dispose;
 
   /**
-   * GtkNumericSorter:expression:
+   * GtkNumericSorter:expression: (type GtkExpression)
    *
    * The expression to evalute on items to get a number to compare with
    */
   properties[PROP_EXPRESSION] =
-      g_param_spec_boxed ("expression",
-                          P_("Expression"),
-                          P_("Expression to compare with"),
-                          GTK_TYPE_EXPRESSION,
-                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+    gtk_param_spec_expression ("expression",
+                               P_("Expression"),
+                               P_("Expression to compare with"),
+                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
 
   /**
    * GtkNumericSorter:sort-order:
@@ -290,12 +289,12 @@ gtk_numeric_sorter_class_init (GtkNumericSorterClass *class)
    * Whether the sorter will sort smaller numbers first
    */
   properties[PROP_SORT_ORDER] =
-      g_param_spec_enum ("sort-order",
-                         P_("Sort order"),
-                         P_("Whether to sort smaller numbers first"),
-                         GTK_TYPE_SORT_TYPE,
-                         GTK_SORT_ASCENDING,
-                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+    g_param_spec_enum ("sort-order",
+                       P_("Sort order"),
+                       P_("Whether to sort smaller numbers first"),
+                       GTK_TYPE_SORT_TYPE,
+                       GTK_SORT_ASCENDING,
+                       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
 
   g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
 
@@ -338,7 +337,7 @@ gtk_numeric_sorter_new (GtkExpression *expression)
  *
  * Gets the expression that is evaluated to obtain numbers from items.
  *
- * Returns: (nullable): a #GtkExpression, or %NULL
+ * Returns: (transfer none) (nullable): a #GtkExpression, or %NULL
  */
 GtkExpression *
 gtk_numeric_sorter_get_expression (GtkNumericSorter *self)
diff --git a/gtk/gtkstringfilter.c b/gtk/gtkstringfilter.c
index ff409be8d0..f998cbd662 100644
--- a/gtk/gtkstringfilter.c
+++ b/gtk/gtkstringfilter.c
@@ -164,7 +164,7 @@ gtk_string_filter_set_property (GObject      *object,
   switch (prop_id)
     {
     case PROP_EXPRESSION:
-      gtk_string_filter_set_expression (self, g_value_get_boxed (value));
+      gtk_string_filter_set_expression (self, gtk_value_get_expression (value));
       break;
 
     case PROP_IGNORE_CASE:
@@ -196,7 +196,7 @@ gtk_string_filter_get_property (GObject     *object,
   switch (prop_id)
     {
     case PROP_EXPRESSION:
-      g_value_set_boxed (value, self->expression);
+      gtk_value_set_expression (value, self->expression);
       break;
 
     case PROP_IGNORE_CASE:
@@ -243,16 +243,15 @@ gtk_string_filter_class_init (GtkStringFilterClass *class)
   object_class->dispose = gtk_string_filter_dispose;
 
   /**
-   * GtkStringFilter:expression:
+   * GtkStringFilter:expression: (type GtkExpression)
    *
    * The expression to evalute on item to get a string to compare with
    */
   properties[PROP_EXPRESSION] =
-      g_param_spec_boxed ("expression",
-                          P_("Expression"),
-                          P_("Expression to compare with"),
-                          GTK_TYPE_EXPRESSION,
-                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+    gtk_param_spec_expression ("expression",
+                               P_("Expression"),
+                               P_("Expression to compare with"),
+                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
 
   /**
    * GtkStringFilter:ignore-case:
@@ -382,7 +381,7 @@ gtk_string_filter_set_search (GtkStringFilter *self,
  * Gets the expression that the string filter uses to
  * obtain strings from items.
  *
- * Returns: a #GtkExpression
+ * Returns: (transfer none): a #GtkExpression
  */
 GtkExpression *
 gtk_string_filter_get_expression (GtkStringFilter *self)
diff --git a/gtk/gtkstringsorter.c b/gtk/gtkstringsorter.c
index 5fcc63c566..8ca9fce725 100644
--- a/gtk/gtkstringsorter.c
+++ b/gtk/gtkstringsorter.c
@@ -148,7 +148,7 @@ gtk_string_sorter_set_property (GObject      *object,
   switch (prop_id)
     {
     case PROP_EXPRESSION:
-      gtk_string_sorter_set_expression (self, g_value_get_boxed (value));
+      gtk_string_sorter_set_expression (self, gtk_value_get_expression (value));
       break;
 
     case PROP_IGNORE_CASE:
@@ -172,7 +172,7 @@ gtk_string_sorter_get_property (GObject     *object,
   switch (prop_id)
     {
     case PROP_EXPRESSION:
-      g_value_set_boxed (value, self->expression);
+      gtk_value_set_expression (value, self->expression);
       break;
 
     case PROP_IGNORE_CASE:
@@ -209,16 +209,15 @@ gtk_string_sorter_class_init (GtkStringSorterClass *class)
   object_class->dispose = gtk_string_sorter_dispose;
 
   /**
-   * GtkStringSorter:expression:
+   * GtkStringSorter:expression: (type GtkExpression)
    *
    * The expression to evalute on item to get a string to compare with
    */
   properties[PROP_EXPRESSION] =
-      g_param_spec_boxed ("expression",
-                          P_("Expression"),
-                          P_("Expression to compare with"),
-                          GTK_TYPE_EXPRESSION,
-                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+    gtk_param_spec_expression ("expression",
+                               P_("Expression"),
+                               P_("Expression to compare with"),
+                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
 
   /**
    * GtkStringSorter:ignore-case:
@@ -274,7 +273,7 @@ gtk_string_sorter_new (GtkExpression *expression)
  *
  * Gets the expression that is evaluated to obtain strings from items.
  *
- * Returns: (nullable): a #GtkExpression, or %NULL
+ * Returns: (transfer none) (nullable): a #GtkExpression, or %NULL
  */
 GtkExpression *
 gtk_string_sorter_get_expression (GtkStringSorter *self)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]