[gtk/ebassi/surface-event] Use the right types for the GdkSurface::event arguments



commit dd4d6930b5cbd2e63f9b875477f1311780ce5c08
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Tue May 19 12:18:24 2020 +0100

    Use the right types for the GdkSurface::event arguments
    
    We pass the GdkEvent as a pointer, because the autogenerated marshallers
    don't know how to handle GTypeInstance-derived classes.
    
    Since the GValue box that we use in the marshaller passes the GdkEvent
    instance as is, we also need to acquire a reference before invoking the
    closure, and release it afterwards, to ensure that the GdkEvent instance
    survices the invocation.

 gdk/gdksurface.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 61 insertions(+), 3 deletions(-)
---
diff --git a/gdk/gdksurface.c b/gdk/gdksurface.c
index 31fcf9659f..5fcb20de9a 100644
--- a/gdk/gdksurface.c
+++ b/gdk/gdksurface.c
@@ -380,6 +380,64 @@ gdk_surface_layout_popup_helper (GdkSurface     *surface,
   *out_final_rect = final_rect;
 }
 
+/* Since GdkEvent is a GTypeInstance, GValue can only store it as a pointer,
+ * and GClosure does not know how to handle its memory management. To avoid
+ * the event going away in the middle of the signal emission, we provide a
+ * marshaller that keeps the event alive for the duration of the closure.
+ */
+static void
+gdk_surface_event_marshaller (GClosure     *closure,
+                              GValue       *return_value,
+                              guint         n_param_values,
+                              const GValue *param_values,
+                              gpointer      invocation_hint,
+                              gpointer      marshal_data)
+{
+  GdkEvent *event = g_value_get_pointer (&param_values[1]);
+
+  gdk_event_ref (event);
+
+  _gdk_marshal_BOOLEAN__POINTER (closure,
+                                 return_value,
+                                 n_param_values,
+                                 param_values,
+                                 invocation_hint,
+                                 marshal_data);
+
+
+  gdk_event_unref (event);
+}
+
+static void
+gdk_surface_event_marshallerv (GClosure *closure,
+                               GValue   *return_value,
+                               gpointer  instance,
+                               va_list   args,
+                               gpointer  marshal_data,
+                               int       n_params,
+                               GType    *param_types)
+{
+  va_list args_copy;
+  GdkEvent *event;
+
+  G_VA_COPY (args_copy, args);
+  event = va_arg (args_copy, gpointer);
+
+  gdk_event_ref (event);
+
+  _gdk_marshal_BOOLEAN__POINTERv (closure,
+                                  return_value,
+                                  instance,
+                                  args,
+                                  marshal_data,
+                                  n_params,
+                                  param_types);
+
+  gdk_event_unref (event);
+
+  va_end (args_copy);
+}
+
 static void
 gdk_surface_init (GdkSurface *surface)
 {
@@ -533,13 +591,13 @@ gdk_surface_class_init (GdkSurfaceClass *klass)
                   0,
                   g_signal_accumulator_true_handled,
                   NULL,
-                  _gdk_marshal_BOOLEAN__POINTER,
+                  gdk_surface_event_marshaller,
                   G_TYPE_BOOLEAN,
                   1,
-                  GDK_TYPE_EVENT);
+                  G_TYPE_POINTER);
   g_signal_set_va_marshaller (signals[EVENT],
                               G_OBJECT_CLASS_TYPE (object_class),
-                              _gdk_marshal_BOOLEAN__POINTERv);
+                              gdk_surface_event_marshallerv);
 
   /**
    * GdkSurface::enter-montor:


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