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 (¶m_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: