/* GestureTracker.c generated by valac 0.56.3, the Vala compiler
 * generated from GestureTracker.vala, do not modify */

/*
 * Copyright 2021 elementary, Inc (https://elementary.io)
 *           2021 José Expósito <jose.exposito89@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <glib-object.h>
#include <glib.h>
#include <gee.h>
#include <float.h>
#include <math.h>
#include <clutter/clutter.h>
#include <string.h>

#define GALA_GESTURE_TRACKER_SUCCESS_PERCENTAGE_THRESHOLD 0.2
#define GALA_GESTURE_TRACKER_SUCCESS_VELOCITY_THRESHOLD 0.003
#define GALA_GESTURE_TRACKER_ANIMATION_BASE_VELOCITY 0.002
#define GALA_GESTURE_TRACKER_MAX_VELOCITY 0.01
#define GALA_GESTURE_TRACKER_DURATION_MULTIPLIER 3
#if !defined(VALA_EXTERN)
#if defined(_MSC_VER)
#define VALA_EXTERN __declspec(dllexport) extern
#elif __GNUC__ >= 4
#define VALA_EXTERN __attribute__((visibility("default"))) extern
#else
#define VALA_EXTERN extern
#endif
#endif

#define GALA_TYPE_GESTURE_TRACKER (gala_gesture_tracker_get_type ())
#define GALA_GESTURE_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GALA_TYPE_GESTURE_TRACKER, GalaGestureTracker))
#define GALA_GESTURE_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GALA_TYPE_GESTURE_TRACKER, GalaGestureTrackerClass))
#define GALA_IS_GESTURE_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GALA_TYPE_GESTURE_TRACKER))
#define GALA_IS_GESTURE_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GALA_TYPE_GESTURE_TRACKER))
#define GALA_GESTURE_TRACKER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GALA_TYPE_GESTURE_TRACKER, GalaGestureTrackerClass))

typedef struct _GalaGestureTracker GalaGestureTracker;
typedef struct _GalaGestureTrackerClass GalaGestureTrackerClass;
typedef struct _GalaGestureTrackerPrivate GalaGestureTrackerPrivate;

#define GALA_TYPE_GESTURE_SETTINGS (gala_gesture_settings_get_type ())
#define GALA_GESTURE_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GALA_TYPE_GESTURE_SETTINGS, GalaGestureSettings))
#define GALA_GESTURE_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GALA_TYPE_GESTURE_SETTINGS, GalaGestureSettingsClass))
#define GALA_IS_GESTURE_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GALA_TYPE_GESTURE_SETTINGS))
#define GALA_IS_GESTURE_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GALA_TYPE_GESTURE_SETTINGS))
#define GALA_GESTURE_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GALA_TYPE_GESTURE_SETTINGS, GalaGestureSettingsClass))

typedef struct _GalaGestureSettings GalaGestureSettings;
typedef struct _GalaGestureSettingsClass GalaGestureSettingsClass;

#define GALA_TYPE_TOUCHEGG_BACKEND (gala_touchegg_backend_get_type ())
#define GALA_TOUCHEGG_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GALA_TYPE_TOUCHEGG_BACKEND, GalaToucheggBackend))
#define GALA_TOUCHEGG_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GALA_TYPE_TOUCHEGG_BACKEND, GalaToucheggBackendClass))
#define GALA_IS_TOUCHEGG_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GALA_TYPE_TOUCHEGG_BACKEND))
#define GALA_IS_TOUCHEGG_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GALA_TYPE_TOUCHEGG_BACKEND))
#define GALA_TOUCHEGG_BACKEND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GALA_TYPE_TOUCHEGG_BACKEND, GalaToucheggBackendClass))

typedef struct _GalaToucheggBackend GalaToucheggBackend;
typedef struct _GalaToucheggBackendClass GalaToucheggBackendClass;

#define GALA_TYPE_SCROLL_BACKEND (gala_scroll_backend_get_type ())
#define GALA_SCROLL_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GALA_TYPE_SCROLL_BACKEND, GalaScrollBackend))
#define GALA_SCROLL_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GALA_TYPE_SCROLL_BACKEND, GalaScrollBackendClass))
#define GALA_IS_SCROLL_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GALA_TYPE_SCROLL_BACKEND))
#define GALA_IS_SCROLL_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GALA_TYPE_SCROLL_BACKEND))
#define GALA_SCROLL_BACKEND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GALA_TYPE_SCROLL_BACKEND, GalaScrollBackendClass))

typedef struct _GalaScrollBackend GalaScrollBackend;
typedef struct _GalaScrollBackendClass GalaScrollBackendClass;
enum  {
	GALA_GESTURE_TRACKER_0_PROPERTY,
	GALA_GESTURE_TRACKER_SETTINGS_PROPERTY,
	GALA_GESTURE_TRACKER_MIN_ANIMATION_DURATION_PROPERTY,
	GALA_GESTURE_TRACKER_MAX_ANIMATION_DURATION_PROPERTY,
	GALA_GESTURE_TRACKER_ENABLED_PROPERTY,
	GALA_GESTURE_TRACKER_NUM_PROPERTIES
};
static GParamSpec* gala_gesture_tracker_properties[GALA_GESTURE_TRACKER_NUM_PROPERTIES];
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))

#define GALA_TYPE_GESTURE (gala_gesture_get_type ())
#define GALA_GESTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GALA_TYPE_GESTURE, GalaGesture))
#define GALA_GESTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GALA_TYPE_GESTURE, GalaGestureClass))
#define GALA_IS_GESTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GALA_TYPE_GESTURE))
#define GALA_IS_GESTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GALA_TYPE_GESTURE))
#define GALA_GESTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GALA_TYPE_GESTURE, GalaGestureClass))

typedef struct _GalaGesture GalaGesture;
typedef struct _GalaGestureClass GalaGestureClass;
typedef void (*GalaGestureTrackerOnBegin) (gdouble percentage, gpointer user_data);
typedef void (*GalaGestureTrackerOnUpdate) (gdouble percentage, gpointer user_data);
typedef void (*GalaGestureTrackerOnEnd) (gdouble percentage, gboolean cancel_action, gint calculated_duration, gpointer user_data);
typedef struct _Block54Data Block54Data;
enum  {
	GALA_GESTURE_TRACKER_ON_GESTURE_DETECTED_SIGNAL,
	GALA_GESTURE_TRACKER_ON_BEGIN_SIGNAL,
	GALA_GESTURE_TRACKER_ON_UPDATE_SIGNAL,
	GALA_GESTURE_TRACKER_ON_END_SIGNAL,
	GALA_GESTURE_TRACKER_NUM_SIGNALS
};
static guint gala_gesture_tracker_signals[GALA_GESTURE_TRACKER_NUM_SIGNALS] = {0};

struct _GalaGestureTracker {
	GObject parent_instance;
	GalaGestureTrackerPrivate * priv;
};

struct _GalaGestureTrackerClass {
	GObjectClass parent_class;
};

struct _GalaGestureTrackerPrivate {
	GalaGestureSettings* _settings;
	gint _min_animation_duration;
	gint _max_animation_duration;
	gboolean _enabled;
	GalaToucheggBackend* touchpad_backend;
	GalaScrollBackend* scroll_backend;
	GeeArrayList* handlers;
	gdouble previous_percentage;
	guint64 previous_time;
	gdouble percentage_delta;
	gdouble velocity;
};

struct _Block54Data {
	int _ref_count_;
	GalaGestureTracker* self;
	GalaGestureTrackerOnBegin on_begin_handler;
	gpointer on_begin_handler_target;
	GDestroyNotify on_begin_handler_target_destroy_notify;
	GalaGestureTrackerOnUpdate on_update_handler;
	gpointer on_update_handler_target;
	GDestroyNotify on_update_handler_target_destroy_notify;
	GalaGestureTrackerOnEnd on_end_handler;
	gpointer on_end_handler_target;
	GDestroyNotify on_end_handler_target_destroy_notify;
};

static gint GalaGestureTracker_private_offset;
static gpointer gala_gesture_tracker_parent_class = NULL;

VALA_EXTERN GType gala_gesture_tracker_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GalaGestureTracker, g_object_unref)
VALA_EXTERN GType gala_gesture_settings_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GalaGestureSettings, g_object_unref)
VALA_EXTERN GType gala_touchegg_backend_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GalaToucheggBackend, g_object_unref)
VALA_EXTERN GType gala_scroll_backend_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GalaScrollBackend, g_object_unref)
VALA_EXTERN GalaGestureTracker* gala_gesture_tracker_new (gint min_animation_duration,
                                              gint max_animation_duration);
VALA_EXTERN GalaGestureTracker* gala_gesture_tracker_construct (GType object_type,
                                                    gint min_animation_duration,
                                                    gint max_animation_duration);
VALA_EXTERN void gala_gesture_tracker_enable_touchpad (GalaGestureTracker* self);
VALA_EXTERN GalaToucheggBackend* gala_touchegg_backend_get_default (void);
VALA_EXTERN gpointer gala_gesture_ref (gpointer instance);
VALA_EXTERN void gala_gesture_unref (gpointer instance);
VALA_EXTERN GParamSpec* gala_param_spec_gesture (const gchar* name,
                                     const gchar* nick,
                                     const gchar* blurb,
                                     GType object_type,
                                     GParamFlags flags);
VALA_EXTERN void gala_value_set_gesture (GValue* value,
                             gpointer v_object);
VALA_EXTERN void gala_value_take_gesture (GValue* value,
                              gpointer v_object);
VALA_EXTERN gpointer gala_value_get_gesture (const GValue* value);
VALA_EXTERN GType gala_gesture_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GalaGesture, gala_gesture_unref)
static void gala_gesture_tracker_gesture_detected (GalaGestureTracker* self,
                                            GalaGesture* gesture);
static void _gala_gesture_tracker_gesture_detected_gala_touchegg_backend_on_gesture_detected (GalaToucheggBackend* _sender,
                                                                                       GalaGesture* gesture,
                                                                                       gpointer self);
static void gala_gesture_tracker_gesture_begin (GalaGestureTracker* self,
                                         gdouble percentage,
                                         guint64 elapsed_time);
static void _gala_gesture_tracker_gesture_begin_gala_touchegg_backend_on_begin (GalaToucheggBackend* _sender,
                                                                         gdouble delta,
                                                                         guint64 time,
                                                                         gpointer self);
static void gala_gesture_tracker_gesture_update (GalaGestureTracker* self,
                                          gdouble percentage,
                                          guint64 elapsed_time);
static void _gala_gesture_tracker_gesture_update_gala_touchegg_backend_on_update (GalaToucheggBackend* _sender,
                                                                           gdouble delta,
                                                                           guint64 time,
                                                                           gpointer self);
static void gala_gesture_tracker_gesture_end (GalaGestureTracker* self,
                                       gdouble percentage,
                                       guint64 elapsed_time);
static void _gala_gesture_tracker_gesture_end_gala_touchegg_backend_on_end (GalaToucheggBackend* _sender,
                                                                     gdouble delta,
                                                                     guint64 time,
                                                                     gpointer self);
VALA_EXTERN void gala_gesture_tracker_enable_scroll (GalaGestureTracker* self,
                                         ClutterActor* actor,
                                         ClutterOrientation orientation);
VALA_EXTERN GalaGestureSettings* gala_gesture_tracker_get_settings (GalaGestureTracker* self);
VALA_EXTERN GalaScrollBackend* gala_scroll_backend_new (ClutterActor* actor,
                                            ClutterOrientation orientation,
                                            GalaGestureSettings* settings);
VALA_EXTERN GalaScrollBackend* gala_scroll_backend_construct (GType object_type,
                                                  ClutterActor* actor,
                                                  ClutterOrientation orientation,
                                                  GalaGestureSettings* settings);
static void _gala_gesture_tracker_gesture_detected_gala_scroll_backend_on_gesture_detected (GalaScrollBackend* _sender,
                                                                                     GalaGesture* gesture,
                                                                                     gpointer self);
static void _gala_gesture_tracker_gesture_begin_gala_scroll_backend_on_begin (GalaScrollBackend* _sender,
                                                                       gdouble delta,
                                                                       guint64 time,
                                                                       gpointer self);
static void _gala_gesture_tracker_gesture_update_gala_scroll_backend_on_update (GalaScrollBackend* _sender,
                                                                         gdouble delta,
                                                                         guint64 time,
                                                                         gpointer self);
static void _gala_gesture_tracker_gesture_end_gala_scroll_backend_on_end (GalaScrollBackend* _sender,
                                                                   gdouble delta,
                                                                   guint64 time,
                                                                   gpointer self);
VALA_EXTERN void gala_gesture_tracker_connect_handlers (GalaGestureTracker* self,
                                            GalaGestureTrackerOnBegin on_begin_handler,
                                            gpointer on_begin_handler_target,
                                            GDestroyNotify on_begin_handler_target_destroy_notify,
                                            GalaGestureTrackerOnUpdate on_update_handler,
                                            gpointer on_update_handler_target,
                                            GDestroyNotify on_update_handler_target_destroy_notify,
                                            GalaGestureTrackerOnEnd on_end_handler,
                                            gpointer on_end_handler_target,
                                            GDestroyNotify on_end_handler_target_destroy_notify);
static Block54Data* block54_data_ref (Block54Data* _data54_);
static void block54_data_unref (void * _userdata_);
static void ___lambda36_ (Block54Data* _data54_,
                   gdouble percentage);
static void ____lambda36__gala_gesture_tracker_on_begin (GalaGestureTracker* _sender,
                                                  gdouble percentage,
                                                  gpointer self);
static void ___lambda37_ (Block54Data* _data54_,
                   gdouble percentage);
static void ____lambda37__gala_gesture_tracker_on_update (GalaGestureTracker* _sender,
                                                   gdouble percentage,
                                                   gpointer self);
static void ___lambda38_ (Block54Data* _data54_,
                   gdouble percentage,
                   gboolean cancel_action,
                   gint duration);
static void ____lambda38__gala_gesture_tracker_on_end (GalaGestureTracker* _sender,
                                                gdouble percentage,
                                                gboolean cancel_action,
                                                gint calculated_duration,
                                                gpointer self);
static void gala_gesture_tracker_disconnect_all_handlers (GalaGestureTracker* self);
VALA_EXTERN gfloat gala_gesture_tracker_animation_value (gfloat initial_value,
                                             gfloat target_value,
                                             gdouble percentage,
                                             gboolean rounded);
VALA_EXTERN gint gala_internal_utils_pixel_align (gfloat value);
VALA_EXTERN gboolean gala_gesture_tracker_get_enabled (GalaGestureTracker* self);
static gdouble gala_gesture_tracker_applied_percentage (gdouble percentage,
                                                 gdouble percentage_delta);
static gint gala_gesture_tracker_calculate_end_animation_duration (GalaGestureTracker* self,
                                                            gdouble end_percentage,
                                                            gboolean cancel_action);
VALA_EXTERN gint gala_gesture_tracker_get_min_animation_duration (GalaGestureTracker* self);
VALA_EXTERN gint gala_gesture_tracker_get_max_animation_duration (GalaGestureTracker* self);
static void gala_gesture_tracker_set_settings (GalaGestureTracker* self,
                                        GalaGestureSettings* value);
static void gala_gesture_tracker_set_min_animation_duration (GalaGestureTracker* self,
                                                      gint value);
static void gala_gesture_tracker_set_max_animation_duration (GalaGestureTracker* self,
                                                      gint value);
VALA_EXTERN void gala_gesture_tracker_set_enabled (GalaGestureTracker* self,
                                       gboolean value);
static void g_cclosure_user_marshal_VOID__GALA_GESTURE (GClosure * closure,
                                                 GValue * return_value,
                                                 guint n_param_values,
                                                 const GValue * param_values,
                                                 gpointer invocation_hint,
                                                 gpointer marshal_data);
static void g_cclosure_user_marshal_VOID__DOUBLE_BOOLEAN_INT (GClosure * closure,
                                                       GValue * return_value,
                                                       guint n_param_values,
                                                       const GValue * param_values,
                                                       gpointer invocation_hint,
                                                       gpointer marshal_data);
static GObject * gala_gesture_tracker_constructor (GType type,
                                            guint n_construct_properties,
                                            GObjectConstructParam * construct_properties);
VALA_EXTERN GalaGestureSettings* gala_gesture_settings_new (void);
VALA_EXTERN GalaGestureSettings* gala_gesture_settings_construct (GType object_type);
static void gala_gesture_tracker_finalize (GObject * obj);
static GType gala_gesture_tracker_get_type_once (void);
static void _vala_gala_gesture_tracker_get_property (GObject * object,
                                              guint property_id,
                                              GValue * value,
                                              GParamSpec * pspec);
static void _vala_gala_gesture_tracker_set_property (GObject * object,
                                              guint property_id,
                                              const GValue * value,
                                              GParamSpec * pspec);
static inline gpointer _vala_memdup2 (gconstpointer mem,
                        gsize byte_size);

static inline gpointer
gala_gesture_tracker_get_instance_private (GalaGestureTracker* self)
{
	return G_STRUCT_MEMBER_P (self, GalaGestureTracker_private_offset);
}

GalaGestureTracker*
gala_gesture_tracker_construct (GType object_type,
                                gint min_animation_duration,
                                gint max_animation_duration)
{
	GalaGestureTracker * self = NULL;
	self = (GalaGestureTracker*) g_object_new (object_type, "min-animation-duration", min_animation_duration, "max-animation-duration", max_animation_duration, NULL);
	return self;
}

GalaGestureTracker*
gala_gesture_tracker_new (gint min_animation_duration,
                          gint max_animation_duration)
{
	return gala_gesture_tracker_construct (GALA_TYPE_GESTURE_TRACKER, min_animation_duration, max_animation_duration);
}

/**
     * Allow to receive touchpad multi-touch gestures.
     */
static gpointer
_g_object_ref0 (gpointer self)
{
	return self ? g_object_ref (self) : NULL;
}

static void
_gala_gesture_tracker_gesture_detected_gala_touchegg_backend_on_gesture_detected (GalaToucheggBackend* _sender,
                                                                                  GalaGesture* gesture,
                                                                                  gpointer self)
{
	gala_gesture_tracker_gesture_detected ((GalaGestureTracker*) self, gesture);
}

static void
_gala_gesture_tracker_gesture_begin_gala_touchegg_backend_on_begin (GalaToucheggBackend* _sender,
                                                                    gdouble delta,
                                                                    guint64 time,
                                                                    gpointer self)
{
	gala_gesture_tracker_gesture_begin ((GalaGestureTracker*) self, delta, time);
}

static void
_gala_gesture_tracker_gesture_update_gala_touchegg_backend_on_update (GalaToucheggBackend* _sender,
                                                                      gdouble delta,
                                                                      guint64 time,
                                                                      gpointer self)
{
	gala_gesture_tracker_gesture_update ((GalaGestureTracker*) self, delta, time);
}

static void
_gala_gesture_tracker_gesture_end_gala_touchegg_backend_on_end (GalaToucheggBackend* _sender,
                                                                gdouble delta,
                                                                guint64 time,
                                                                gpointer self)
{
	gala_gesture_tracker_gesture_end ((GalaGestureTracker*) self, delta, time);
}

void
gala_gesture_tracker_enable_touchpad (GalaGestureTracker* self)
{
	GalaToucheggBackend* _tmp0_;
	GalaToucheggBackend* _tmp1_;
	GalaToucheggBackend* _tmp2_;
	GalaToucheggBackend* _tmp3_;
	GalaToucheggBackend* _tmp4_;
	GalaToucheggBackend* _tmp5_;
	g_return_if_fail (self != NULL);
	_tmp0_ = gala_touchegg_backend_get_default ();
	_tmp1_ = _g_object_ref0 (_tmp0_);
	_g_object_unref0 (self->priv->touchpad_backend);
	self->priv->touchpad_backend = _tmp1_;
	_tmp2_ = self->priv->touchpad_backend;
	g_signal_connect_object (_tmp2_, "on-gesture-detected", (GCallback) _gala_gesture_tracker_gesture_detected_gala_touchegg_backend_on_gesture_detected, self, 0);
	_tmp3_ = self->priv->touchpad_backend;
	g_signal_connect_object (_tmp3_, "on-begin", (GCallback) _gala_gesture_tracker_gesture_begin_gala_touchegg_backend_on_begin, self, 0);
	_tmp4_ = self->priv->touchpad_backend;
	g_signal_connect_object (_tmp4_, "on-update", (GCallback) _gala_gesture_tracker_gesture_update_gala_touchegg_backend_on_update, self, 0);
	_tmp5_ = self->priv->touchpad_backend;
	g_signal_connect_object (_tmp5_, "on-end", (GCallback) _gala_gesture_tracker_gesture_end_gala_touchegg_backend_on_end, self, 0);
}

/**
     * Allow to receive scroll gestures.
     * @param actor Clutter actor that will receive the scroll events.
     * @param orientation If we are interested in the horizontal or vertical axis.
     */
static void
_gala_gesture_tracker_gesture_detected_gala_scroll_backend_on_gesture_detected (GalaScrollBackend* _sender,
                                                                                GalaGesture* gesture,
                                                                                gpointer self)
{
	gala_gesture_tracker_gesture_detected ((GalaGestureTracker*) self, gesture);
}

static void
_gala_gesture_tracker_gesture_begin_gala_scroll_backend_on_begin (GalaScrollBackend* _sender,
                                                                  gdouble delta,
                                                                  guint64 time,
                                                                  gpointer self)
{
	gala_gesture_tracker_gesture_begin ((GalaGestureTracker*) self, delta, time);
}

static void
_gala_gesture_tracker_gesture_update_gala_scroll_backend_on_update (GalaScrollBackend* _sender,
                                                                    gdouble delta,
                                                                    guint64 time,
                                                                    gpointer self)
{
	gala_gesture_tracker_gesture_update ((GalaGestureTracker*) self, delta, time);
}

static void
_gala_gesture_tracker_gesture_end_gala_scroll_backend_on_end (GalaScrollBackend* _sender,
                                                              gdouble delta,
                                                              guint64 time,
                                                              gpointer self)
{
	gala_gesture_tracker_gesture_end ((GalaGestureTracker*) self, delta, time);
}

void
gala_gesture_tracker_enable_scroll (GalaGestureTracker* self,
                                    ClutterActor* actor,
                                    ClutterOrientation orientation)
{
	GalaGestureSettings* _tmp0_;
	GalaScrollBackend* _tmp1_;
	GalaScrollBackend* _tmp2_;
	GalaScrollBackend* _tmp3_;
	GalaScrollBackend* _tmp4_;
	GalaScrollBackend* _tmp5_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (actor != NULL);
	_tmp0_ = self->priv->_settings;
	_tmp1_ = gala_scroll_backend_new (actor, orientation, _tmp0_);
	_g_object_unref0 (self->priv->scroll_backend);
	self->priv->scroll_backend = _tmp1_;
	_tmp2_ = self->priv->scroll_backend;
	g_signal_connect_object (_tmp2_, "on-gesture-detected", (GCallback) _gala_gesture_tracker_gesture_detected_gala_scroll_backend_on_gesture_detected, self, 0);
	_tmp3_ = self->priv->scroll_backend;
	g_signal_connect_object (_tmp3_, "on-begin", (GCallback) _gala_gesture_tracker_gesture_begin_gala_scroll_backend_on_begin, self, 0);
	_tmp4_ = self->priv->scroll_backend;
	g_signal_connect_object (_tmp4_, "on-update", (GCallback) _gala_gesture_tracker_gesture_update_gala_scroll_backend_on_update, self, 0);
	_tmp5_ = self->priv->scroll_backend;
	g_signal_connect_object (_tmp5_, "on-end", (GCallback) _gala_gesture_tracker_gesture_end_gala_scroll_backend_on_end, self, 0);
}

static Block54Data*
block54_data_ref (Block54Data* _data54_)
{
	g_atomic_int_inc (&_data54_->_ref_count_);
	return _data54_;
}

static void
block54_data_unref (void * _userdata_)
{
	Block54Data* _data54_;
	_data54_ = (Block54Data*) _userdata_;
	if (g_atomic_int_dec_and_test (&_data54_->_ref_count_)) {
		GalaGestureTracker* self;
		self = _data54_->self;
		(_data54_->on_begin_handler_target_destroy_notify == NULL) ? NULL : (_data54_->on_begin_handler_target_destroy_notify (_data54_->on_begin_handler_target), NULL);
		_data54_->on_begin_handler = NULL;
		_data54_->on_begin_handler_target = NULL;
		_data54_->on_begin_handler_target_destroy_notify = NULL;
		(_data54_->on_update_handler_target_destroy_notify == NULL) ? NULL : (_data54_->on_update_handler_target_destroy_notify (_data54_->on_update_handler_target), NULL);
		_data54_->on_update_handler = NULL;
		_data54_->on_update_handler_target = NULL;
		_data54_->on_update_handler_target_destroy_notify = NULL;
		(_data54_->on_end_handler_target_destroy_notify == NULL) ? NULL : (_data54_->on_end_handler_target_destroy_notify (_data54_->on_end_handler_target), NULL);
		_data54_->on_end_handler = NULL;
		_data54_->on_end_handler_target = NULL;
		_data54_->on_end_handler_target_destroy_notify = NULL;
		_g_object_unref0 (self);
		g_slice_free (Block54Data, _data54_);
	}
}

static void
___lambda36_ (Block54Data* _data54_,
              gdouble percentage)
{
	GalaGestureTracker* self;
	self = _data54_->self;
	_data54_->on_begin_handler (percentage, _data54_->on_begin_handler_target);
}

static void
____lambda36__gala_gesture_tracker_on_begin (GalaGestureTracker* _sender,
                                             gdouble percentage,
                                             gpointer self)
{
	___lambda36_ (self, percentage);
}

static void
___lambda37_ (Block54Data* _data54_,
              gdouble percentage)
{
	GalaGestureTracker* self;
	self = _data54_->self;
	_data54_->on_update_handler (percentage, _data54_->on_update_handler_target);
}

static void
____lambda37__gala_gesture_tracker_on_update (GalaGestureTracker* _sender,
                                              gdouble percentage,
                                              gpointer self)
{
	___lambda37_ (self, percentage);
}

static void
___lambda38_ (Block54Data* _data54_,
              gdouble percentage,
              gboolean cancel_action,
              gint duration)
{
	GalaGestureTracker* self;
	self = _data54_->self;
	_data54_->on_end_handler (percentage, cancel_action, duration, _data54_->on_end_handler_target);
}

static void
____lambda38__gala_gesture_tracker_on_end (GalaGestureTracker* _sender,
                                           gdouble percentage,
                                           gboolean cancel_action,
                                           gint calculated_duration,
                                           gpointer self)
{
	___lambda38_ (self, percentage, cancel_action, calculated_duration);
}

void
gala_gesture_tracker_connect_handlers (GalaGestureTracker* self,
                                       GalaGestureTrackerOnBegin on_begin_handler,
                                       gpointer on_begin_handler_target,
                                       GDestroyNotify on_begin_handler_target_destroy_notify,
                                       GalaGestureTrackerOnUpdate on_update_handler,
                                       gpointer on_update_handler_target,
                                       GDestroyNotify on_update_handler_target_destroy_notify,
                                       GalaGestureTrackerOnEnd on_end_handler,
                                       gpointer on_end_handler_target,
                                       GDestroyNotify on_end_handler_target_destroy_notify)
{
	Block54Data* _data54_;
	g_return_if_fail (self != NULL);
	_data54_ = g_slice_new0 (Block54Data);
	_data54_->_ref_count_ = 1;
	_data54_->self = g_object_ref (self);
	(_data54_->on_begin_handler_target_destroy_notify == NULL) ? NULL : (_data54_->on_begin_handler_target_destroy_notify (_data54_->on_begin_handler_target), NULL);
	_data54_->on_begin_handler = NULL;
	_data54_->on_begin_handler_target = NULL;
	_data54_->on_begin_handler_target_destroy_notify = NULL;
	_data54_->on_begin_handler = on_begin_handler;
	_data54_->on_begin_handler_target = on_begin_handler_target;
	_data54_->on_begin_handler_target_destroy_notify = on_begin_handler_target_destroy_notify;
	(_data54_->on_update_handler_target_destroy_notify == NULL) ? NULL : (_data54_->on_update_handler_target_destroy_notify (_data54_->on_update_handler_target), NULL);
	_data54_->on_update_handler = NULL;
	_data54_->on_update_handler_target = NULL;
	_data54_->on_update_handler_target_destroy_notify = NULL;
	_data54_->on_update_handler = on_update_handler;
	_data54_->on_update_handler_target = on_update_handler_target;
	_data54_->on_update_handler_target_destroy_notify = on_update_handler_target_destroy_notify;
	(_data54_->on_end_handler_target_destroy_notify == NULL) ? NULL : (_data54_->on_end_handler_target_destroy_notify (_data54_->on_end_handler_target), NULL);
	_data54_->on_end_handler = NULL;
	_data54_->on_end_handler_target = NULL;
	_data54_->on_end_handler_target_destroy_notify = NULL;
	_data54_->on_end_handler = on_end_handler;
	_data54_->on_end_handler_target = on_end_handler_target;
	_data54_->on_end_handler_target_destroy_notify = on_end_handler_target_destroy_notify;
	if (_data54_->on_begin_handler != NULL) {
		gulong handler_id = 0UL;
		gulong _tmp0_;
		GeeArrayList* _tmp1_;
		_tmp0_ = g_signal_connect_data (self, "on-begin", (GCallback) ____lambda36__gala_gesture_tracker_on_begin, block54_data_ref (_data54_), (GClosureNotify) block54_data_unref, 0);
		handler_id = _tmp0_;
		_tmp1_ = self->priv->handlers;
		gee_abstract_collection_add ((GeeAbstractCollection*) _tmp1_, (gpointer) ((guintptr) handler_id));
	}
	if (_data54_->on_update_handler != NULL) {
		gulong handler_id = 0UL;
		gulong _tmp2_;
		GeeArrayList* _tmp3_;
		_tmp2_ = g_signal_connect_data (self, "on-update", (GCallback) ____lambda37__gala_gesture_tracker_on_update, block54_data_ref (_data54_), (GClosureNotify) block54_data_unref, 0);
		handler_id = _tmp2_;
		_tmp3_ = self->priv->handlers;
		gee_abstract_collection_add ((GeeAbstractCollection*) _tmp3_, (gpointer) ((guintptr) handler_id));
	}
	if (_data54_->on_end_handler != NULL) {
		gulong handler_id = 0UL;
		gulong _tmp4_;
		GeeArrayList* _tmp5_;
		_tmp4_ = g_signal_connect_data (self, "on-end", (GCallback) ____lambda38__gala_gesture_tracker_on_end, block54_data_ref (_data54_), (GClosureNotify) block54_data_unref, 0);
		handler_id = _tmp4_;
		_tmp5_ = self->priv->handlers;
		gee_abstract_collection_add ((GeeAbstractCollection*) _tmp5_, (gpointer) ((guintptr) handler_id));
	}
	block54_data_unref (_data54_);
	_data54_ = NULL;
}

static void
gala_gesture_tracker_disconnect_all_handlers (GalaGestureTracker* self)
{
	GeeArrayList* _tmp8_;
	g_return_if_fail (self != NULL);
	{
		GeeArrayList* _handler_list = NULL;
		GeeArrayList* _tmp0_;
		gint _handler_size = 0;
		GeeArrayList* _tmp1_;
		gint _tmp2_;
		gint _tmp3_;
		gint _handler_index = 0;
		_tmp0_ = self->priv->handlers;
		_handler_list = _tmp0_;
		_tmp1_ = _handler_list;
		_tmp2_ = gee_abstract_collection_get_size ((GeeAbstractCollection*) _tmp1_);
		_tmp3_ = _tmp2_;
		_handler_size = _tmp3_;
		_handler_index = -1;
		while (TRUE) {
			gint _tmp4_;
			gint _tmp5_;
			gulong handler = 0UL;
			GeeArrayList* _tmp6_;
			gpointer _tmp7_;
			_handler_index = _handler_index + 1;
			_tmp4_ = _handler_index;
			_tmp5_ = _handler_size;
			if (!(_tmp4_ < _tmp5_)) {
				break;
			}
			_tmp6_ = _handler_list;
			_tmp7_ = gee_abstract_list_get ((GeeAbstractList*) _tmp6_, _handler_index);
			handler = (gulong) ((guintptr) _tmp7_);
			g_signal_handler_disconnect ((GObject*) self, handler);
		}
	}
	_tmp8_ = self->priv->handlers;
	gee_abstract_collection_clear ((GeeAbstractCollection*) _tmp8_);
}

/**
     * Utility method to calculate the current animation value based on the percentage of the
     * gesture performed.
     * Animations are always linear, as they are 1:1 to the user's movement.
     * @param initial_value Animation start value.
     * @param target_value Animation end value.
     * @param percentage Current animation percentage.
     * @param rounded If the returned value should be rounded to match physical pixels.
     * Default to false because some animations, like for example scaling an actor, use intermediate
     * values not divisible by physical pixels.
     * @returns The linear animation value at the specified percentage.
     */
gfloat
gala_gesture_tracker_animation_value (gfloat initial_value,
                                      gfloat target_value,
                                      gdouble percentage,
                                      gboolean rounded)
{
	gfloat value = 0.0F;
	gfloat result;
	value = ((target_value - initial_value) * ((gfloat) percentage)) + initial_value;
	if (rounded) {
		value = (gfloat) gala_internal_utils_pixel_align (value);
	}
	result = value;
	return result;
}

static void
gala_gesture_tracker_gesture_detected (GalaGestureTracker* self,
                                       GalaGesture* gesture)
{
	gboolean _tmp0_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (gesture != NULL);
	_tmp0_ = self->priv->_enabled;
	if (_tmp0_) {
		g_signal_emit (self, gala_gesture_tracker_signals[GALA_GESTURE_TRACKER_ON_GESTURE_DETECTED_SIGNAL], 0, gesture);
	}
}

static void
gala_gesture_tracker_gesture_begin (GalaGestureTracker* self,
                                    gdouble percentage,
                                    guint64 elapsed_time)
{
	gboolean _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->_enabled;
	if (_tmp0_) {
		g_signal_emit (self, gala_gesture_tracker_signals[GALA_GESTURE_TRACKER_ON_BEGIN_SIGNAL], 0, percentage);
	}
	self->priv->previous_percentage = percentage;
	self->priv->previous_time = elapsed_time;
}

static void
gala_gesture_tracker_gesture_update (GalaGestureTracker* self,
                                     gdouble percentage,
                                     guint64 elapsed_time)
{
	gboolean _tmp0_;
	g_return_if_fail (self != NULL);
	if (elapsed_time != self->priv->previous_time) {
		gdouble distance = 0.0;
		gdouble time = 0.0;
		distance = percentage - self->priv->previous_percentage;
		time = (gdouble) (elapsed_time - self->priv->previous_time);
		self->priv->velocity = distance / time;
		if (self->priv->velocity > GALA_GESTURE_TRACKER_MAX_VELOCITY) {
			gdouble used_percentage = 0.0;
			self->priv->velocity = GALA_GESTURE_TRACKER_MAX_VELOCITY;
			used_percentage = (GALA_GESTURE_TRACKER_MAX_VELOCITY * time) + self->priv->previous_percentage;
			self->priv->percentage_delta = self->priv->percentage_delta + (percentage - used_percentage);
		}
	}
	_tmp0_ = self->priv->_enabled;
	if (_tmp0_) {
		g_signal_emit (self, gala_gesture_tracker_signals[GALA_GESTURE_TRACKER_ON_UPDATE_SIGNAL], 0, gala_gesture_tracker_applied_percentage (percentage, self->priv->percentage_delta));
	}
	self->priv->previous_percentage = percentage;
	self->priv->previous_time = elapsed_time;
}

static void
gala_gesture_tracker_gesture_end (GalaGestureTracker* self,
                                  gdouble percentage,
                                  guint64 elapsed_time)
{
	gdouble end_percentage = 0.0;
	gboolean _tmp0_ = FALSE;
	gboolean cancel_action = FALSE;
	gint calculated_duration = 0;
	gboolean _tmp2_;
	g_return_if_fail (self != NULL);
	end_percentage = gala_gesture_tracker_applied_percentage (percentage, self->priv->percentage_delta);
	if (end_percentage < GALA_GESTURE_TRACKER_SUCCESS_PERCENTAGE_THRESHOLD) {
		gboolean _tmp1_ = FALSE;
		if (end_percentage <= self->priv->previous_percentage) {
			_tmp1_ = self->priv->velocity < GALA_GESTURE_TRACKER_SUCCESS_VELOCITY_THRESHOLD;
		} else {
			_tmp1_ = FALSE;
		}
		_tmp0_ = _tmp1_;
	} else {
		_tmp0_ = FALSE;
	}
	cancel_action = _tmp0_;
	calculated_duration = gala_gesture_tracker_calculate_end_animation_duration (self, end_percentage, cancel_action);
	_tmp2_ = self->priv->_enabled;
	if (_tmp2_) {
		g_signal_emit (self, gala_gesture_tracker_signals[GALA_GESTURE_TRACKER_ON_END_SIGNAL], 0, end_percentage, cancel_action, calculated_duration);
	}
	gala_gesture_tracker_disconnect_all_handlers (self);
	self->priv->previous_percentage = (gdouble) 0;
	self->priv->previous_time = (guint64) 0;
	self->priv->percentage_delta = (gdouble) 0;
	self->priv->velocity = (gdouble) 0;
}

static gdouble
gala_gesture_tracker_applied_percentage (gdouble percentage,
                                         gdouble percentage_delta)
{
	gdouble result;
	result = CLAMP (percentage - percentage_delta, (gdouble) 0, (gdouble) 1);
	return result;
}

/**
     * Calculates the end animation duration using the current gesture velocity.
     */
static gint
gala_gesture_tracker_calculate_end_animation_duration (GalaGestureTracker* self,
                                                       gdouble end_percentage,
                                                       gboolean cancel_action)
{
	gdouble _tmp0_ = 0.0;
	gdouble animation_velocity = 0.0;
	gdouble _tmp1_ = 0.0;
	gdouble pending_percentage = 0.0;
	gint duration = 0;
	gint _tmp2_;
	gint _tmp3_;
	gint result;
	g_return_val_if_fail (self != NULL, 0);
	if (self->priv->velocity > GALA_GESTURE_TRACKER_ANIMATION_BASE_VELOCITY) {
		_tmp0_ = self->priv->velocity;
	} else {
		_tmp0_ = GALA_GESTURE_TRACKER_ANIMATION_BASE_VELOCITY;
	}
	animation_velocity = _tmp0_;
	if (cancel_action) {
		_tmp1_ = end_percentage;
	} else {
		_tmp1_ = 1 - end_percentage;
	}
	pending_percentage = _tmp1_;
	_tmp2_ = self->priv->_min_animation_duration;
	_tmp3_ = self->priv->_max_animation_duration;
	duration = CLAMP (((gint) fabs (pending_percentage / animation_velocity)) * GALA_GESTURE_TRACKER_DURATION_MULTIPLIER, _tmp2_, _tmp3_);
	result = duration;
	return result;
}

GalaGestureSettings*
gala_gesture_tracker_get_settings (GalaGestureTracker* self)
{
	GalaGestureSettings* result;
	GalaGestureSettings* _tmp0_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->_settings;
	result = _tmp0_;
	return result;
}

static void
gala_gesture_tracker_set_settings (GalaGestureTracker* self,
                                   GalaGestureSettings* value)
{
	GalaGestureSettings* old_value;
	g_return_if_fail (self != NULL);
	old_value = gala_gesture_tracker_get_settings (self);
	if (old_value != value) {
		GalaGestureSettings* _tmp0_;
		_tmp0_ = _g_object_ref0 (value);
		_g_object_unref0 (self->priv->_settings);
		self->priv->_settings = _tmp0_;
		g_object_notify_by_pspec ((GObject *) self, gala_gesture_tracker_properties[GALA_GESTURE_TRACKER_SETTINGS_PROPERTY]);
	}
}

gint
gala_gesture_tracker_get_min_animation_duration (GalaGestureTracker* self)
{
	gint result;
	g_return_val_if_fail (self != NULL, 0);
	result = self->priv->_min_animation_duration;
	return result;
}

static void
gala_gesture_tracker_set_min_animation_duration (GalaGestureTracker* self,
                                                 gint value)
{
	gint old_value;
	g_return_if_fail (self != NULL);
	old_value = gala_gesture_tracker_get_min_animation_duration (self);
	if (old_value != value) {
		self->priv->_min_animation_duration = value;
		g_object_notify_by_pspec ((GObject *) self, gala_gesture_tracker_properties[GALA_GESTURE_TRACKER_MIN_ANIMATION_DURATION_PROPERTY]);
	}
}

gint
gala_gesture_tracker_get_max_animation_duration (GalaGestureTracker* self)
{
	gint result;
	g_return_val_if_fail (self != NULL, 0);
	result = self->priv->_max_animation_duration;
	return result;
}

static void
gala_gesture_tracker_set_max_animation_duration (GalaGestureTracker* self,
                                                 gint value)
{
	gint old_value;
	g_return_if_fail (self != NULL);
	old_value = gala_gesture_tracker_get_max_animation_duration (self);
	if (old_value != value) {
		self->priv->_max_animation_duration = value;
		g_object_notify_by_pspec ((GObject *) self, gala_gesture_tracker_properties[GALA_GESTURE_TRACKER_MAX_ANIMATION_DURATION_PROPERTY]);
	}
}

gboolean
gala_gesture_tracker_get_enabled (GalaGestureTracker* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	result = self->priv->_enabled;
	return result;
}

void
gala_gesture_tracker_set_enabled (GalaGestureTracker* self,
                                  gboolean value)
{
	gboolean old_value;
	g_return_if_fail (self != NULL);
	old_value = gala_gesture_tracker_get_enabled (self);
	if (old_value != value) {
		self->priv->_enabled = value;
		g_object_notify_by_pspec ((GObject *) self, gala_gesture_tracker_properties[GALA_GESTURE_TRACKER_ENABLED_PROPERTY]);
	}
}

static void
g_cclosure_user_marshal_VOID__GALA_GESTURE (GClosure * closure,
                                            GValue * return_value,
                                            guint n_param_values,
                                            const GValue * param_values,
                                            gpointer invocation_hint,
                                            gpointer marshal_data)
{
	typedef void (*GMarshalFunc_VOID__GALA_GESTURE) (gpointer data1, gpointer arg_1, gpointer data2);
	register GMarshalFunc_VOID__GALA_GESTURE callback;
	register GCClosure * cc;
	register gpointer data1;
	register gpointer data2;
	cc = (GCClosure *) closure;
	g_return_if_fail (n_param_values == 2);
	if (G_CCLOSURE_SWAP_DATA (closure)) {
		data1 = closure->data;
		data2 = param_values->data[0].v_pointer;
	} else {
		data1 = param_values->data[0].v_pointer;
		data2 = closure->data;
	}
	callback = (GMarshalFunc_VOID__GALA_GESTURE) (marshal_data ? marshal_data : cc->callback);
	callback (data1, gala_value_get_gesture (param_values + 1), data2);
}

static void
g_cclosure_user_marshal_VOID__DOUBLE_BOOLEAN_INT (GClosure * closure,
                                                  GValue * return_value,
                                                  guint n_param_values,
                                                  const GValue * param_values,
                                                  gpointer invocation_hint,
                                                  gpointer marshal_data)
{
	typedef void (*GMarshalFunc_VOID__DOUBLE_BOOLEAN_INT) (gpointer data1, gdouble arg_1, gboolean arg_2, gint arg_3, gpointer data2);
	register GMarshalFunc_VOID__DOUBLE_BOOLEAN_INT callback;
	register GCClosure * cc;
	register gpointer data1;
	register gpointer data2;
	cc = (GCClosure *) closure;
	g_return_if_fail (n_param_values == 4);
	if (G_CCLOSURE_SWAP_DATA (closure)) {
		data1 = closure->data;
		data2 = param_values->data[0].v_pointer;
	} else {
		data1 = param_values->data[0].v_pointer;
		data2 = closure->data;
	}
	callback = (GMarshalFunc_VOID__DOUBLE_BOOLEAN_INT) (marshal_data ? marshal_data : cc->callback);
	callback (data1, g_value_get_double (param_values + 1), g_value_get_boolean (param_values + 2), g_value_get_int (param_values + 3), data2);
}

static GObject *
gala_gesture_tracker_constructor (GType type,
                                  guint n_construct_properties,
                                  GObjectConstructParam * construct_properties)
{
	GObject * obj;
	GObjectClass * parent_class;
	GalaGestureTracker * self;
	GalaGestureSettings* _tmp0_;
	GalaGestureSettings* _tmp1_;
	GeeArrayList* _tmp2_;
	parent_class = G_OBJECT_CLASS (gala_gesture_tracker_parent_class);
	obj = parent_class->constructor (type, n_construct_properties, construct_properties);
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, GALA_TYPE_GESTURE_TRACKER, GalaGestureTracker);
	_tmp0_ = gala_gesture_settings_new ();
	_tmp1_ = _tmp0_;
	gala_gesture_tracker_set_settings (self, _tmp1_);
	_g_object_unref0 (_tmp1_);
	_tmp2_ = gee_array_list_new (G_TYPE_ULONG, NULL, NULL, NULL, NULL, NULL);
	_g_object_unref0 (self->priv->handlers);
	self->priv->handlers = _tmp2_;
	self->priv->previous_percentage = (gdouble) 0;
	self->priv->previous_time = (guint64) 0;
	self->priv->percentage_delta = (gdouble) 0;
	self->priv->velocity = (gdouble) 0;
	return obj;
}

static void
gala_gesture_tracker_class_init (GalaGestureTrackerClass * klass,
                                 gpointer klass_data)
{
	gala_gesture_tracker_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &GalaGestureTracker_private_offset);
	G_OBJECT_CLASS (klass)->get_property = _vala_gala_gesture_tracker_get_property;
	G_OBJECT_CLASS (klass)->set_property = _vala_gala_gesture_tracker_set_property;
	G_OBJECT_CLASS (klass)->constructor = gala_gesture_tracker_constructor;
	G_OBJECT_CLASS (klass)->finalize = gala_gesture_tracker_finalize;
	g_object_class_install_property (G_OBJECT_CLASS (klass), GALA_GESTURE_TRACKER_SETTINGS_PROPERTY, gala_gesture_tracker_properties[GALA_GESTURE_TRACKER_SETTINGS_PROPERTY] = g_param_spec_object ("settings", "settings", "settings", GALA_TYPE_GESTURE_SETTINGS, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GALA_GESTURE_TRACKER_MIN_ANIMATION_DURATION_PROPERTY, gala_gesture_tracker_properties[GALA_GESTURE_TRACKER_MIN_ANIMATION_DURATION_PROPERTY] = g_param_spec_int ("min-animation-duration", "min-animation-duration", "min-animation-duration", G_MININT, G_MAXINT, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GALA_GESTURE_TRACKER_MAX_ANIMATION_DURATION_PROPERTY, gala_gesture_tracker_properties[GALA_GESTURE_TRACKER_MAX_ANIMATION_DURATION_PROPERTY] = g_param_spec_int ("max-animation-duration", "max-animation-duration", "max-animation-duration", G_MININT, G_MAXINT, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
	/**
	     * Property to control when event signals are emitted or not.
	     */
	g_object_class_install_property (G_OBJECT_CLASS (klass), GALA_GESTURE_TRACKER_ENABLED_PROPERTY, gala_gesture_tracker_properties[GALA_GESTURE_TRACKER_ENABLED_PROPERTY] = g_param_spec_boolean ("enabled", "enabled", "enabled", TRUE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE));
	/**
	     * Emitted when a new gesture is detected.
	     * If the receiving code needs to handle this gesture, it should call to connect_handlers to
	     * start receiving updates.
	     * @param gesture Information about the gesture.
	     */
	gala_gesture_tracker_signals[GALA_GESTURE_TRACKER_ON_GESTURE_DETECTED_SIGNAL] = g_signal_new ("on-gesture-detected", GALA_TYPE_GESTURE_TRACKER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__GALA_GESTURE, G_TYPE_NONE, 1, GALA_TYPE_GESTURE);
	/**
	     * Emitted right after on_gesture_detected with the initial gesture information.
	     * @param percentage Value between 0 and 1.
	     */
	gala_gesture_tracker_signals[GALA_GESTURE_TRACKER_ON_BEGIN_SIGNAL] = g_signal_new ("on-begin", GALA_TYPE_GESTURE_TRACKER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__DOUBLE, G_TYPE_NONE, 1, G_TYPE_DOUBLE);
	/**
	     * Called every time the percentage changes.
	     * @param percentage Value between 0 and 1.
	     */
	gala_gesture_tracker_signals[GALA_GESTURE_TRACKER_ON_UPDATE_SIGNAL] = g_signal_new ("on-update", GALA_TYPE_GESTURE_TRACKER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__DOUBLE, G_TYPE_NONE, 1, G_TYPE_DOUBLE);
	/**
	     * @param percentage Value between 0 and 1.
	     * @param cancel_action
	     * @param calculated_duration
	     */
	gala_gesture_tracker_signals[GALA_GESTURE_TRACKER_ON_END_SIGNAL] = g_signal_new ("on-end", GALA_TYPE_GESTURE_TRACKER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__DOUBLE_BOOLEAN_INT, G_TYPE_NONE, 3, G_TYPE_DOUBLE, G_TYPE_BOOLEAN, G_TYPE_INT);
}

static void
gala_gesture_tracker_instance_init (GalaGestureTracker * self,
                                    gpointer klass)
{
	self->priv = gala_gesture_tracker_get_instance_private (self);
	self->priv->_enabled = TRUE;
}

static void
gala_gesture_tracker_finalize (GObject * obj)
{
	GalaGestureTracker * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, GALA_TYPE_GESTURE_TRACKER, GalaGestureTracker);
	_g_object_unref0 (self->priv->_settings);
	_g_object_unref0 (self->priv->touchpad_backend);
	_g_object_unref0 (self->priv->scroll_backend);
	_g_object_unref0 (self->priv->handlers);
	G_OBJECT_CLASS (gala_gesture_tracker_parent_class)->finalize (obj);
}

/**
 * Allow to use multi-touch gestures from different sources (backends).
 * Usage:
 * - Create a new instance of the class
 * - Use the enable_* methods to enable different backends
 * - Connect the on_gesture_detected to your code
 * - When on_gesture_detected is emitted, if you want to handle the gesture, call connect_handlers
 *   to start receiving events
 * - on_begin will be emitted once right after on_gesture_detected
 * - on_update will be emitted 0 or more times
 * - on_end will be emitted once when the gesture end
 * - When on_end is emitted, the handler connected with connect_handlers will be automatically
 *   disconnected and you will only receive on_gesture_detected signals
 * - The enabled flag is usually disabled on_end and re-enabled once the end animation finish. In
 *   this way, new gestures are not received while animating
 */
static GType
gala_gesture_tracker_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (GalaGestureTrackerClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gala_gesture_tracker_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (GalaGestureTracker), 0, (GInstanceInitFunc) gala_gesture_tracker_instance_init, NULL };
	GType gala_gesture_tracker_type_id;
	gala_gesture_tracker_type_id = g_type_register_static (G_TYPE_OBJECT, "GalaGestureTracker", &g_define_type_info, 0);
	GalaGestureTracker_private_offset = g_type_add_instance_private (gala_gesture_tracker_type_id, sizeof (GalaGestureTrackerPrivate));
	return gala_gesture_tracker_type_id;
}

GType
gala_gesture_tracker_get_type (void)
{
	static volatile gsize gala_gesture_tracker_type_id__once = 0;
	if (g_once_init_enter (&gala_gesture_tracker_type_id__once)) {
		GType gala_gesture_tracker_type_id;
		gala_gesture_tracker_type_id = gala_gesture_tracker_get_type_once ();
		g_once_init_leave (&gala_gesture_tracker_type_id__once, gala_gesture_tracker_type_id);
	}
	return gala_gesture_tracker_type_id__once;
}

static void
_vala_gala_gesture_tracker_get_property (GObject * object,
                                         guint property_id,
                                         GValue * value,
                                         GParamSpec * pspec)
{
	GalaGestureTracker * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, GALA_TYPE_GESTURE_TRACKER, GalaGestureTracker);
	switch (property_id) {
		case GALA_GESTURE_TRACKER_SETTINGS_PROPERTY:
		g_value_set_object (value, gala_gesture_tracker_get_settings (self));
		break;
		case GALA_GESTURE_TRACKER_MIN_ANIMATION_DURATION_PROPERTY:
		g_value_set_int (value, gala_gesture_tracker_get_min_animation_duration (self));
		break;
		case GALA_GESTURE_TRACKER_MAX_ANIMATION_DURATION_PROPERTY:
		g_value_set_int (value, gala_gesture_tracker_get_max_animation_duration (self));
		break;
		case GALA_GESTURE_TRACKER_ENABLED_PROPERTY:
		g_value_set_boolean (value, gala_gesture_tracker_get_enabled (self));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
_vala_gala_gesture_tracker_set_property (GObject * object,
                                         guint property_id,
                                         const GValue * value,
                                         GParamSpec * pspec)
{
	GalaGestureTracker * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, GALA_TYPE_GESTURE_TRACKER, GalaGestureTracker);
	switch (property_id) {
		case GALA_GESTURE_TRACKER_SETTINGS_PROPERTY:
		gala_gesture_tracker_set_settings (self, g_value_get_object (value));
		break;
		case GALA_GESTURE_TRACKER_MIN_ANIMATION_DURATION_PROPERTY:
		gala_gesture_tracker_set_min_animation_duration (self, g_value_get_int (value));
		break;
		case GALA_GESTURE_TRACKER_MAX_ANIMATION_DURATION_PROPERTY:
		gala_gesture_tracker_set_max_animation_duration (self, g_value_get_int (value));
		break;
		case GALA_GESTURE_TRACKER_ENABLED_PROPERTY:
		gala_gesture_tracker_set_enabled (self, g_value_get_boolean (value));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static inline gpointer
_vala_memdup2 (gconstpointer mem,
               gsize byte_size)
{
	gpointer new_mem;
	if (mem && byte_size != 0) {
		new_mem = g_malloc (byte_size);
		memcpy (new_mem, mem, byte_size);
	} else {
		new_mem = NULL;
	}
	return new_mem;
}

