/* HotCorner.c generated by valac 0.56.18-dirty, the Vala compiler
 * generated from HotCorner.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 <stdlib.h>
#include <string.h>
#include <glib.h>
#include <meta/meta-backend.h>
#include <float.h>
#include <math.h>
#include <mtk/mtk.h>
#include <clutter/clutter.h>
#include <meta/barrier.h>
#include "gala.h"

#define GALA_HOT_CORNER_POSITION_TOP_LEFT "hotcorner-topleft"
#define GALA_HOT_CORNER_POSITION_TOP_RIGHT "hotcorner-topright"
#define GALA_HOT_CORNER_POSITION_BOTTOM_LEFT "hotcorner-bottomleft"
#define GALA_HOT_CORNER_POSITION_BOTTOM_RIGHT "hotcorner-bottomright"
#define GALA_HOT_CORNER_BARRIER_SIZE 30
#define GALA_HOT_CORNER_TRIGGER_PRESSURE_THRESHOLD 50
#define GALA_HOT_CORNER_RELEASE_PRESSURE_THRESHOLD 100
#define GALA_HOT_CORNER_RETRIGGER_PRESSURE_THRESHOLD 500
#define GALA_HOT_CORNER_RETRIGGER_DELAY 600
#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif
#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_HOT_CORNER (gala_hot_corner_get_type ())
#define GALA_HOT_CORNER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GALA_TYPE_HOT_CORNER, GalaHotCorner))
#define GALA_HOT_CORNER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GALA_TYPE_HOT_CORNER, GalaHotCornerClass))
#define GALA_IS_HOT_CORNER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GALA_TYPE_HOT_CORNER))
#define GALA_IS_HOT_CORNER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GALA_TYPE_HOT_CORNER))
#define GALA_HOT_CORNER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GALA_TYPE_HOT_CORNER, GalaHotCornerClass))

typedef struct _GalaHotCorner GalaHotCorner;
typedef struct _GalaHotCornerClass GalaHotCornerClass;
typedef struct _GalaHotCornerPrivate GalaHotCornerPrivate;

#define GALA_TYPE_BARRIER (gala_barrier_get_type ())
#define GALA_BARRIER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GALA_TYPE_BARRIER, GalaBarrier))
#define GALA_BARRIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GALA_TYPE_BARRIER, GalaBarrierClass))
#define GALA_IS_BARRIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GALA_TYPE_BARRIER))
#define GALA_IS_BARRIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GALA_TYPE_BARRIER))
#define GALA_BARRIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GALA_TYPE_BARRIER, GalaBarrierClass))

typedef struct _GalaBarrier GalaBarrier;
typedef struct _GalaBarrierClass GalaBarrierClass;
enum  {
	GALA_HOT_CORNER_0_PROPERTY,
	GALA_HOT_CORNER_NUM_PROPERTIES
};
static GParamSpec* gala_hot_corner_properties[GALA_HOT_CORNER_NUM_PROPERTIES];
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
enum  {
	GALA_HOT_CORNER_TRIGGER_SIGNAL,
	GALA_HOT_CORNER_NUM_SIGNALS
};
static guint gala_hot_corner_signals[GALA_HOT_CORNER_NUM_SIGNALS] = {0};

struct _GalaHotCorner {
	GObject parent_instance;
	GalaHotCornerPrivate * priv;
};

struct _GalaHotCornerClass {
	GObjectClass parent_class;
};

struct _GalaHotCornerPrivate {
	GalaBarrier* vertical_barrier;
	GalaBarrier* horizontal_barrier;
};

static gint GalaHotCorner_private_offset;
static gpointer gala_hot_corner_parent_class = NULL;

VALA_EXTERN GType gala_hot_corner_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GalaHotCorner, g_object_unref)
VALA_EXTERN GType gala_barrier_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GalaBarrier, g_object_unref)
VALA_EXTERN GalaHotCorner* gala_hot_corner_new (MetaBackend* backend,
                                    gfloat x,
                                    gfloat y,
                                    gfloat scale,
                                    const gchar* hot_corner_position);
VALA_EXTERN GalaHotCorner* gala_hot_corner_construct (GType object_type,
                                          MetaBackend* backend,
                                          gfloat x,
                                          gfloat y,
                                          gfloat scale,
                                          const gchar* hot_corner_position);
static void gala_hot_corner_add_barriers (GalaHotCorner* self,
                                   MetaBackend* backend,
                                   gfloat x,
                                   gfloat y,
                                   gfloat scale,
                                   const gchar* hot_corner_position);
VALA_EXTERN void gala_hot_corner_destroy_barriers (GalaHotCorner* self);
static void gala_hot_corner_get_barrier_rect (gfloat x,
                                       gfloat y,
                                       gfloat scale,
                                       const gchar* hot_corner_position,
                                       ClutterOrientation orientation,
                                       MtkRectangle* result);
static MetaBarrierDirection gala_hot_corner_get_barrier_direction (const gchar* hot_corner_position,
                                                            ClutterOrientation orientation);
VALA_EXTERN GalaBarrier* gala_barrier_new (MetaBackend* backend,
                               gint x1,
                               gint y1,
                               gint x2,
                               gint y2,
                               MetaBarrierDirection directions,
                               gdouble trigger_pressure_threshold,
                               gdouble release_pressure_threshold,
                               gdouble retrigger_pressure_threshold,
                               gint retrigger_delay);
VALA_EXTERN GalaBarrier* gala_barrier_construct (GType object_type,
                                     MetaBackend* backend,
                                     gint x1,
                                     gint y1,
                                     gint x2,
                                     gint y2,
                                     MetaBarrierDirection directions,
                                     gdouble trigger_pressure_threshold,
                                     gdouble release_pressure_threshold,
                                     gdouble retrigger_pressure_threshold,
                                     gint retrigger_delay);
static void gala_hot_corner_on_barrier_trigger (GalaHotCorner* self);
static void _gala_hot_corner_on_barrier_trigger_gala_barrier_trigger (GalaBarrier* _sender,
                                                               gpointer self);
VALA_EXTERN gboolean gala_barrier_get_triggered (GalaBarrier* self);
static void gala_hot_corner_finalize (GObject * obj);
static GType gala_hot_corner_get_type_once (void);

static inline gpointer
gala_hot_corner_get_instance_private (GalaHotCorner* self)
{
	return G_STRUCT_MEMBER_P (self, GalaHotCorner_private_offset);
}

GalaHotCorner*
gala_hot_corner_construct (GType object_type,
                           MetaBackend* backend,
                           gfloat x,
                           gfloat y,
                           gfloat scale,
                           const gchar* hot_corner_position)
{
	GalaHotCorner * self = NULL;
	g_return_val_if_fail (backend != NULL, NULL);
	g_return_val_if_fail (hot_corner_position != NULL, NULL);
	self = (GalaHotCorner*) g_object_new (object_type, NULL);
	gala_hot_corner_add_barriers (self, backend, x, y, scale, hot_corner_position);
	return self;
}

GalaHotCorner*
gala_hot_corner_new (MetaBackend* backend,
                     gfloat x,
                     gfloat y,
                     gfloat scale,
                     const gchar* hot_corner_position)
{
	return gala_hot_corner_construct (GALA_TYPE_HOT_CORNER, backend, x, y, scale, hot_corner_position);
}

void
gala_hot_corner_destroy_barriers (GalaHotCorner* self)
{
	g_return_if_fail (self != NULL);
	_g_object_unref0 (self->priv->vertical_barrier);
	self->priv->vertical_barrier = NULL;
	_g_object_unref0 (self->priv->horizontal_barrier);
	self->priv->horizontal_barrier = NULL;
}

static void
_gala_hot_corner_on_barrier_trigger_gala_barrier_trigger (GalaBarrier* _sender,
                                                          gpointer self)
{
	gala_hot_corner_on_barrier_trigger ((GalaHotCorner*) self);
}

static void
gala_hot_corner_add_barriers (GalaHotCorner* self,
                              MetaBackend* backend,
                              gfloat x,
                              gfloat y,
                              gfloat scale,
                              const gchar* hot_corner_position)
{
	MtkRectangle vrect = {0};
	MtkRectangle _tmp0_ = {0};
	MtkRectangle hrect = {0};
	MtkRectangle _tmp1_ = {0};
	MetaBarrierDirection vdir = 0U;
	MetaBarrierDirection hdir = 0U;
	MtkRectangle _tmp2_;
	MtkRectangle _tmp3_;
	MtkRectangle _tmp4_;
	MtkRectangle _tmp5_;
	MtkRectangle _tmp6_;
	MtkRectangle _tmp7_;
	GalaBarrier* _tmp8_;
	MtkRectangle _tmp9_;
	MtkRectangle _tmp10_;
	MtkRectangle _tmp11_;
	MtkRectangle _tmp12_;
	MtkRectangle _tmp13_;
	MtkRectangle _tmp14_;
	GalaBarrier* _tmp15_;
	GalaBarrier* _tmp16_;
	GalaBarrier* _tmp17_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (backend != NULL);
	g_return_if_fail (hot_corner_position != NULL);
	gala_hot_corner_get_barrier_rect (x, y, scale, hot_corner_position, CLUTTER_ORIENTATION_VERTICAL, &_tmp0_);
	vrect = _tmp0_;
	gala_hot_corner_get_barrier_rect (x, y, scale, hot_corner_position, CLUTTER_ORIENTATION_HORIZONTAL, &_tmp1_);
	hrect = _tmp1_;
	vdir = gala_hot_corner_get_barrier_direction (hot_corner_position, CLUTTER_ORIENTATION_VERTICAL);
	hdir = gala_hot_corner_get_barrier_direction (hot_corner_position, CLUTTER_ORIENTATION_HORIZONTAL);
	_tmp2_ = vrect;
	_tmp3_ = vrect;
	_tmp4_ = vrect;
	_tmp5_ = vrect;
	_tmp6_ = vrect;
	_tmp7_ = vrect;
	_tmp8_ = gala_barrier_new (backend, _tmp2_.x, _tmp3_.y, _tmp4_.x + _tmp5_.width, _tmp6_.y + _tmp7_.height, vdir, (gdouble) GALA_HOT_CORNER_TRIGGER_PRESSURE_THRESHOLD, (gdouble) GALA_HOT_CORNER_RELEASE_PRESSURE_THRESHOLD, (gdouble) GALA_HOT_CORNER_RETRIGGER_PRESSURE_THRESHOLD, GALA_HOT_CORNER_RETRIGGER_DELAY);
	_g_object_unref0 (self->priv->vertical_barrier);
	self->priv->vertical_barrier = _tmp8_;
	_tmp9_ = hrect;
	_tmp10_ = hrect;
	_tmp11_ = hrect;
	_tmp12_ = hrect;
	_tmp13_ = hrect;
	_tmp14_ = hrect;
	_tmp15_ = gala_barrier_new (backend, _tmp9_.x, _tmp10_.y, _tmp11_.x + _tmp12_.width, _tmp13_.y + _tmp14_.height, hdir, (gdouble) GALA_HOT_CORNER_TRIGGER_PRESSURE_THRESHOLD, (gdouble) GALA_HOT_CORNER_RELEASE_PRESSURE_THRESHOLD, (gdouble) GALA_HOT_CORNER_RETRIGGER_PRESSURE_THRESHOLD, GALA_HOT_CORNER_RETRIGGER_DELAY);
	_g_object_unref0 (self->priv->horizontal_barrier);
	self->priv->horizontal_barrier = _tmp15_;
	_tmp16_ = self->priv->vertical_barrier;
	g_signal_connect_object (_tmp16_, "trigger", (GCallback) _gala_hot_corner_on_barrier_trigger_gala_barrier_trigger, self, 0);
	_tmp17_ = self->priv->horizontal_barrier;
	g_signal_connect_object (_tmp17_, "trigger", (GCallback) _gala_hot_corner_on_barrier_trigger_gala_barrier_trigger, self, 0);
}

static MetaBarrierDirection
gala_hot_corner_get_barrier_direction (const gchar* hot_corner_position,
                                       ClutterOrientation orientation)
{
	gboolean vert = FALSE;
	const gchar* _tmp0_;
	GQuark _tmp2_ = 0U;
	static GQuark _tmp1_label0 = 0;
	static GQuark _tmp1_label1 = 0;
	static GQuark _tmp1_label2 = 0;
	MetaBarrierDirection result;
	g_return_val_if_fail (hot_corner_position != NULL, 0U);
	vert = orientation == CLUTTER_ORIENTATION_VERTICAL;
	_tmp0_ = hot_corner_position;
	_tmp2_ = (NULL == _tmp0_) ? 0 : g_quark_from_string (_tmp0_);
	if (_tmp2_ == ((0 != _tmp1_label0) ? _tmp1_label0 : (_tmp1_label0 = g_quark_from_static_string (GALA_HOT_CORNER_POSITION_TOP_LEFT)))) {
		switch (0) {
			default:
			{
				MetaBarrierDirection _tmp3_ = 0U;
				if (vert) {
					_tmp3_ = META_BARRIER_DIRECTION_POSITIVE_X;
				} else {
					_tmp3_ = META_BARRIER_DIRECTION_POSITIVE_Y;
				}
				result = _tmp3_;
				return result;
			}
		}
	} else if (_tmp2_ == ((0 != _tmp1_label1) ? _tmp1_label1 : (_tmp1_label1 = g_quark_from_static_string (GALA_HOT_CORNER_POSITION_TOP_RIGHT)))) {
		switch (0) {
			default:
			{
				MetaBarrierDirection _tmp4_ = 0U;
				if (vert) {
					_tmp4_ = META_BARRIER_DIRECTION_NEGATIVE_X;
				} else {
					_tmp4_ = META_BARRIER_DIRECTION_POSITIVE_Y;
				}
				result = _tmp4_;
				return result;
			}
		}
	} else if (_tmp2_ == ((0 != _tmp1_label2) ? _tmp1_label2 : (_tmp1_label2 = g_quark_from_static_string (GALA_HOT_CORNER_POSITION_BOTTOM_LEFT)))) {
		switch (0) {
			default:
			{
				MetaBarrierDirection _tmp5_ = 0U;
				if (vert) {
					_tmp5_ = META_BARRIER_DIRECTION_POSITIVE_X;
				} else {
					_tmp5_ = META_BARRIER_DIRECTION_NEGATIVE_Y;
				}
				result = _tmp5_;
				return result;
			}
		}
	} else {
		switch (0) {
			default:
			{
				MetaBarrierDirection _tmp6_ = 0U;
				if (vert) {
					_tmp6_ = META_BARRIER_DIRECTION_NEGATIVE_X;
				} else {
					_tmp6_ = META_BARRIER_DIRECTION_NEGATIVE_Y;
				}
				result = _tmp6_;
				return result;
			}
		}
	}
}

static void
gala_hot_corner_get_barrier_rect (gfloat x,
                                  gfloat y,
                                  gfloat scale,
                                  const gchar* hot_corner_position,
                                  ClutterOrientation orientation,
                                  MtkRectangle* result)
{
	gint barrier_size = 0;
	gint x1 = 0;
	gint y1 = 0;
	gint x2 = 0;
	gint y2 = 0;
	gboolean vert = FALSE;
	const gchar* _tmp0_;
	GQuark _tmp2_ = 0U;
	static GQuark _tmp1_label0 = 0;
	static GQuark _tmp1_label1 = 0;
	static GQuark _tmp1_label2 = 0;
	MtkRectangle _tmp11_ = {0};
	g_return_if_fail (hot_corner_position != NULL);
	barrier_size = gala_utils_scale_to_int (GALA_HOT_CORNER_BARRIER_SIZE, scale);
	x1 = (gint) x;
	y1 = (gint) y;
	vert = orientation == CLUTTER_ORIENTATION_VERTICAL;
	_tmp0_ = hot_corner_position;
	_tmp2_ = (NULL == _tmp0_) ? 0 : g_quark_from_string (_tmp0_);
	if (_tmp2_ == ((0 != _tmp1_label0) ? _tmp1_label0 : (_tmp1_label0 = g_quark_from_static_string (GALA_HOT_CORNER_POSITION_TOP_LEFT)))) {
		switch (0) {
			default:
			{
				gint _tmp3_ = 0;
				gint _tmp4_ = 0;
				if (vert) {
					_tmp3_ = x1;
				} else {
					_tmp3_ = x1 + barrier_size;
				}
				x2 = _tmp3_;
				if (vert) {
					_tmp4_ = y1 + barrier_size;
				} else {
					_tmp4_ = y1;
				}
				y2 = _tmp4_;
				break;
			}
		}
	} else if (_tmp2_ == ((0 != _tmp1_label1) ? _tmp1_label1 : (_tmp1_label1 = g_quark_from_static_string (GALA_HOT_CORNER_POSITION_TOP_RIGHT)))) {
		switch (0) {
			default:
			{
				gint _tmp5_ = 0;
				gint _tmp6_ = 0;
				if (vert) {
					_tmp5_ = x1;
				} else {
					_tmp5_ = x1 - barrier_size;
				}
				x2 = _tmp5_;
				if (vert) {
					_tmp6_ = y1 + barrier_size;
				} else {
					_tmp6_ = y1;
				}
				y2 = _tmp6_;
				break;
			}
		}
	} else if (_tmp2_ == ((0 != _tmp1_label2) ? _tmp1_label2 : (_tmp1_label2 = g_quark_from_static_string (GALA_HOT_CORNER_POSITION_BOTTOM_LEFT)))) {
		switch (0) {
			default:
			{
				gint _tmp7_ = 0;
				gint _tmp8_ = 0;
				if (vert) {
					_tmp7_ = x1;
				} else {
					_tmp7_ = x1 + barrier_size;
				}
				x2 = _tmp7_;
				if (vert) {
					_tmp8_ = y1 - barrier_size;
				} else {
					_tmp8_ = y1;
				}
				y2 = _tmp8_;
				break;
			}
		}
	} else {
		switch (0) {
			default:
			{
				gint _tmp9_ = 0;
				gint _tmp10_ = 0;
				if (vert) {
					_tmp9_ = x1;
				} else {
					_tmp9_ = x1 - barrier_size;
				}
				x2 = _tmp9_;
				if (vert) {
					_tmp10_ = y1 - barrier_size;
				} else {
					_tmp10_ = y1;
				}
				y2 = _tmp10_;
				break;
			}
		}
	}
	_tmp11_.x = x1;
	_tmp11_.y = y1;
	_tmp11_.width = x2 - x1;
	_tmp11_.height = y2 - y1;
	*result = _tmp11_;
	return;
}

static void
gala_hot_corner_on_barrier_trigger (GalaHotCorner* self)
{
	gboolean _tmp0_ = FALSE;
	GalaBarrier* _tmp1_;
	gboolean _tmp2_;
	gboolean _tmp3_;
	g_return_if_fail (self != NULL);
	_tmp1_ = self->priv->vertical_barrier;
	_tmp2_ = gala_barrier_get_triggered (_tmp1_);
	_tmp3_ = _tmp2_;
	if (_tmp3_) {
		GalaBarrier* _tmp4_;
		gboolean _tmp5_;
		gboolean _tmp6_;
		_tmp4_ = self->priv->horizontal_barrier;
		_tmp5_ = gala_barrier_get_triggered (_tmp4_);
		_tmp6_ = _tmp5_;
		_tmp0_ = _tmp6_;
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		g_signal_emit (self, gala_hot_corner_signals[GALA_HOT_CORNER_TRIGGER_SIGNAL], 0);
	}
}

static void
gala_hot_corner_class_init (GalaHotCornerClass * klass,
                            gpointer klass_data)
{
	gala_hot_corner_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &GalaHotCorner_private_offset);
	G_OBJECT_CLASS (klass)->finalize = gala_hot_corner_finalize;
	gala_hot_corner_signals[GALA_HOT_CORNER_TRIGGER_SIGNAL] = g_signal_new ("trigger", GALA_TYPE_HOT_CORNER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}

static void
gala_hot_corner_instance_init (GalaHotCorner * self,
                               gpointer klass)
{
	self->priv = gala_hot_corner_get_instance_private (self);
	self->priv->vertical_barrier = NULL;
	self->priv->horizontal_barrier = NULL;
}

static void
gala_hot_corner_finalize (GObject * obj)
{
	GalaHotCorner * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, GALA_TYPE_HOT_CORNER, GalaHotCorner);
	_g_object_unref0 (self->priv->vertical_barrier);
	_g_object_unref0 (self->priv->horizontal_barrier);
	G_OBJECT_CLASS (gala_hot_corner_parent_class)->finalize (obj);
}

 G_GNUC_NO_INLINE static GType
gala_hot_corner_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (GalaHotCornerClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gala_hot_corner_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (GalaHotCorner), 0, (GInstanceInitFunc) gala_hot_corner_instance_init, NULL };
	GType gala_hot_corner_type_id;
	gala_hot_corner_type_id = g_type_register_static (G_TYPE_OBJECT, "GalaHotCorner", &g_define_type_info, 0);
	GalaHotCorner_private_offset = g_type_add_instance_private (gala_hot_corner_type_id, sizeof (GalaHotCornerPrivate));
	return gala_hot_corner_type_id;
}

GType
gala_hot_corner_get_type (void)
{
	static gsize gala_hot_corner_type_id__once = 0;
	if (g_once_init_enter (&gala_hot_corner_type_id__once)) {
		GType gala_hot_corner_type_id;
		gala_hot_corner_type_id = gala_hot_corner_get_type_once ();
		g_once_init_leave (&gala_hot_corner_type_id__once, gala_hot_corner_type_id);
	}
	return gala_hot_corner_type_id__once;
}

