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

/*
 * Copyright 2021 elementary, Inc. <https://elementary.io>
 * Copyright 2021 Corentin Noël <tintou@noel.tf>
 * SPDX-License-Identifier: GPL-3.0-or-later
 */

#include <glib-object.h>
#include "gala.h"
#include <glib.h>
#include <meta/window.h>
#include <meta/display.h>
#include <meta/meta-startup-notification.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <meta/group.h>

#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_WINDOW_TRACKER (gala_window_tracker_get_type ())
#define GALA_WINDOW_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GALA_TYPE_WINDOW_TRACKER, GalaWindowTracker))
#define GALA_WINDOW_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GALA_TYPE_WINDOW_TRACKER, GalaWindowTrackerClass))
#define GALA_IS_WINDOW_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GALA_TYPE_WINDOW_TRACKER))
#define GALA_IS_WINDOW_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GALA_TYPE_WINDOW_TRACKER))
#define GALA_WINDOW_TRACKER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GALA_TYPE_WINDOW_TRACKER, GalaWindowTrackerClass))

typedef struct _GalaWindowTracker GalaWindowTracker;
typedef struct _GalaWindowTrackerClass GalaWindowTrackerClass;
typedef struct _GalaWindowTrackerPrivate GalaWindowTrackerPrivate;
enum  {
	GALA_WINDOW_TRACKER_0_PROPERTY,
	GALA_WINDOW_TRACKER_NUM_PROPERTIES
};
static GParamSpec* gala_window_tracker_properties[GALA_WINDOW_TRACKER_NUM_PROPERTIES];
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _g_hash_table_unref0(var) ((var == NULL) ? NULL : (var = (g_hash_table_unref (var), NULL)))
#define _g_free0(var) (var = (g_free (var), NULL))
enum  {
	GALA_WINDOW_TRACKER_WINDOWS_CHANGED_SIGNAL,
	GALA_WINDOW_TRACKER_NUM_SIGNALS
};
static guint gala_window_tracker_signals[GALA_WINDOW_TRACKER_NUM_SIGNALS] = {0};

struct _GalaWindowTracker {
	GObject parent_instance;
	GalaWindowTrackerPrivate * priv;
};

struct _GalaWindowTrackerClass {
	GObjectClass parent_class;
};

struct _GalaWindowTrackerPrivate {
	GalaApp* focused_app;
	GHashTable* window_to_app;
};

static gint GalaWindowTracker_private_offset;
static gpointer gala_window_tracker_parent_class = NULL;

VALA_EXTERN GType gala_window_tracker_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GalaWindowTracker, g_object_unref)
VALA_EXTERN void gala_window_tracker_init (GalaWindowTracker* self,
                               MetaDisplay* display);
static void gala_window_tracker_on_startup_sequence_changed (GalaWindowTracker* self,
                                                      MetaStartupSequence* sequence);
static void _gala_window_tracker_on_startup_sequence_changed_meta_startup_notification_changed (MetaStartupNotification* _sender,
                                                                                         MetaStartupSequence* object,
                                                                                         gpointer self);
static void gala_window_tracker_load_initial_windows (GalaWindowTracker* self,
                                               MetaDisplay* display);
static void gala_window_tracker_init_window_tracking (GalaWindowTracker* self,
                                               MetaDisplay* display);
static void gala_window_tracker_track_window (GalaWindowTracker* self,
                                       MetaWindow* window);
static void __lambda30_ (GalaWindowTracker* self);
static void ___lambda30__g_object_notify (GObject* _sender,
                                   GParamSpec* pspec,
                                   gpointer self);
static void __lambda31_ (GalaWindowTracker* self,
                  MetaWindow* window);
static void ___lambda31__meta_display_window_created (MetaDisplay* _sender,
                                               MetaWindow* object,
                                               gpointer self);
static GalaApp* gala_window_tracker_get_app_from_id (const gchar* id);
static GalaApp* gala_window_tracker_get_app_from_gapplication_id (MetaWindow* window);
static GalaApp* gala_window_tracker_get_app_from_pid (pid_t pid);
static pid_t* _pid_t_dup (pid_t* self);
static gboolean _pid_t_equal (const pid_t * s1,
                       const pid_t * s2);
static void _g_free0_ (gpointer var);
static inline void _g_slist_free__g_free0_ (GSList* self);
static GalaApp* gala_window_tracker_get_app_from_window_pid (GalaWindowTracker* self,
                                                      MetaWindow* window);
static gboolean gala_window_tracker_check_app_id_prefix (GalaApp* app,
                                                  const gchar* prefix);
static GalaApp* gala_window_tracker_get_app_from_window_wmclass (GalaWindowTracker* self,
                                                          MetaWindow* window);
static GalaApp* gala_window_tracker_get_app_from_sandboxed_app_id (GalaWindowTracker* self,
                                                            MetaWindow* window);
static GalaApp* gala_window_tracker_get_app_from_window_group (GalaWindowTracker* self,
                                                        MetaWindow* window);
static GalaApp* gala_window_tracker_get_app_for_window (GalaWindowTracker* self,
                                                 MetaWindow* window);
static void gala_window_tracker_tracked_window_changed (GalaWindowTracker* self,
                                                 MetaWindow* window);
static void gala_window_tracker_disassociate_window (GalaWindowTracker* self,
                                              MetaWindow* window);
static void gala_window_tracker_tracked_window_notified (GalaWindowTracker* self,
                                                  GObject* object,
                                                  GParamSpec* pspec);
static void _gala_window_tracker_tracked_window_notified_g_object_notify (GObject* _sender,
                                                                   GParamSpec* pspec,
                                                                   gpointer self);
static void _gala_window_tracker_disassociate_window_meta_window_unmanaged (MetaWindow* _sender,
                                                                     gpointer self);
VALA_EXTERN GalaWindowTracker* gala_window_tracker_new (void);
VALA_EXTERN GalaWindowTracker* gala_window_tracker_construct (GType object_type);
static GObject * gala_window_tracker_constructor (GType type,
                                           guint n_construct_properties,
                                           GObjectConstructParam * construct_properties);
static void _g_object_unref0_ (gpointer var);
static void gala_window_tracker_finalize (GObject * obj);
static GType gala_window_tracker_get_type_once (void);
static inline gpointer _vala_memdup2 (gconstpointer mem,
                        gsize byte_size);

static inline gpointer
gala_window_tracker_get_instance_private (GalaWindowTracker* self)
{
	return G_STRUCT_MEMBER_P (self, GalaWindowTracker_private_offset);
}

static void
_gala_window_tracker_on_startup_sequence_changed_meta_startup_notification_changed (MetaStartupNotification* _sender,
                                                                                    MetaStartupSequence* object,
                                                                                    gpointer self)
{
	gala_window_tracker_on_startup_sequence_changed ((GalaWindowTracker*) self, object);
}

void
gala_window_tracker_init (GalaWindowTracker* self,
                          MetaDisplay* display)
{
	MetaStartupNotification* sn = NULL;
	MetaStartupNotification* _tmp0_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (display != NULL);
	_tmp0_ = meta_display_get_startup_notification (display);
	sn = _tmp0_;
	g_signal_connect_object (sn, "changed", (GCallback) _gala_window_tracker_on_startup_sequence_changed_meta_startup_notification_changed, self, 0);
	gala_window_tracker_load_initial_windows (self, display);
	gala_window_tracker_init_window_tracking (self, display);
}

static void
gala_window_tracker_load_initial_windows (GalaWindowTracker* self,
                                          MetaDisplay* display)
{
	GList* windows = NULL;
	GList* _tmp0_;
	GList* _tmp1_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (display != NULL);
	_tmp0_ = meta_display_list_all_windows (display);
	windows = _tmp0_;
	_tmp1_ = windows;
	{
		GList* window_collection = NULL;
		GList* window_it = NULL;
		window_collection = _tmp1_;
		for (window_it = window_collection; window_it != NULL; window_it = window_it->next) {
			MetaWindow* window = NULL;
			window = (MetaWindow*) window_it->data;
			{
				MetaWindow* _tmp2_;
				_tmp2_ = window;
				gala_window_tracker_track_window (self, _tmp2_);
			}
		}
	}
	(windows == NULL) ? NULL : (windows = (g_list_free (windows), NULL));
}

static void
__lambda30_ (GalaWindowTracker* self)
{
}

static void
___lambda30__g_object_notify (GObject* _sender,
                              GParamSpec* pspec,
                              gpointer self)
{
	__lambda30_ ((GalaWindowTracker*) self);
}

static void
__lambda31_ (GalaWindowTracker* self,
             MetaWindow* window)
{
	g_return_if_fail (window != NULL);
	gala_window_tracker_track_window (self, window);
}

static void
___lambda31__meta_display_window_created (MetaDisplay* _sender,
                                          MetaWindow* object,
                                          gpointer self)
{
	__lambda31_ ((GalaWindowTracker*) self, object);
}

static void
gala_window_tracker_init_window_tracking (GalaWindowTracker* self,
                                          MetaDisplay* display)
{
	g_return_if_fail (self != NULL);
	g_return_if_fail (display != NULL);
	g_signal_connect_object ((GObject*) display, "notify::focus-window", (GCallback) ___lambda30__g_object_notify, self, 0);
	g_signal_connect_object (display, "window-created", (GCallback) ___lambda31__meta_display_window_created, self, 0);
}

static void
gala_window_tracker_on_startup_sequence_changed (GalaWindowTracker* self,
                                                 MetaStartupSequence* sequence)
{
	GalaApp* app = NULL;
	GalaApp* _tmp0_;
	GalaApp* _tmp1_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (sequence != NULL);
	_tmp0_ = gala_app_new_from_startup_sequence (sequence);
	app = _tmp0_;
	_tmp1_ = app;
	if (_tmp1_ != NULL) {
		GalaApp* _tmp2_;
		_tmp2_ = app;
		gala_app_handle_startup_sequence (_tmp2_, sequence);
	}
}

static GalaApp*
gala_window_tracker_get_app_from_id (const gchar* id)
{
	gchar* desktop_file = NULL;
	gchar* _tmp0_;
	GalaAppSystem* _tmp1_;
	GalaApp* _tmp2_;
	GalaApp* result;
	g_return_val_if_fail (id != NULL, NULL);
	_tmp0_ = g_strconcat (id, ".desktop", NULL);
	desktop_file = _tmp0_;
	_tmp1_ = gala_app_system_get_default ();
	_tmp2_ = gala_app_system_lookup_app (_tmp1_, desktop_file);
	result = _tmp2_;
	_g_free0 (desktop_file);
	return result;
}

static GalaApp*
gala_window_tracker_get_app_from_gapplication_id (MetaWindow* window)
{
	const gchar* id = NULL;
	const gchar* _tmp0_;
	const gchar* _tmp1_;
	const gchar* _tmp2_;
	GalaApp* _tmp3_;
	GalaApp* result;
	g_return_val_if_fail (window != NULL, NULL);
	_tmp0_ = meta_window_get_gtk_application_id (window);
	id = _tmp0_;
	_tmp1_ = id;
	if (_tmp1_ == NULL) {
		result = NULL;
		return result;
	}
	_tmp2_ = id;
	_tmp3_ = gala_window_tracker_get_app_from_id (_tmp2_);
	result = _tmp3_;
	return result;
}

static pid_t*
_pid_t_dup (pid_t* self)
{
	pid_t* dup;
	dup = g_new0 (pid_t, 1);
	memcpy (dup, self, sizeof (pid_t));
	return dup;
}

static gpointer
__pid_t_dup0 (gpointer self)
{
	return self ? _pid_t_dup (self) : NULL;
}

static gboolean
_pid_t_equal (const pid_t * s1,
              const pid_t * s2)
{
	if (s1 == s2) {
		return TRUE;
	}
	if (s1 == NULL) {
		return FALSE;
	}
	if (s2 == NULL) {
		return FALSE;
	}
	return (*s1) == (*s2);
}

static void
_g_free0_ (gpointer var)
{
	(var == NULL) ? NULL : (var = (g_free (var), NULL));
}

static inline void
_g_slist_free__g_free0_ (GSList* self)
{
	g_slist_free_full (self, (GDestroyNotify) _g_free0_);
}

static GalaApp*
gala_window_tracker_get_app_from_pid (pid_t pid)
{
	GList* running_apps = NULL;
	GalaAppSystem* _tmp0_;
	GList* _tmp1_;
	GList* _tmp2_;
	GalaApp* result;
	_tmp0_ = gala_app_system_get_default ();
	_tmp1_ = gala_app_system_get_running_apps (_tmp0_);
	running_apps = _tmp1_;
	_tmp2_ = running_apps;
	{
		GList* app_collection = NULL;
		GList* app_it = NULL;
		app_collection = _tmp2_;
		for (app_it = app_collection; app_it != NULL; app_it = app_it->next) {
			GalaApp* app = NULL;
			app = (GalaApp*) app_it->data;
			{
				GSList* app_pids = NULL;
				GalaApp* _tmp3_;
				GSList* _tmp4_;
				GSList* _tmp5_;
				_tmp3_ = app;
				_tmp4_ = gala_app_get_pids (_tmp3_);
				app_pids = _tmp4_;
				_tmp5_ = app_pids;
				{
					GSList* app_pid_collection = NULL;
					GSList* app_pid_it = NULL;
					app_pid_collection = _tmp5_;
					for (app_pid_it = app_pid_collection; app_pid_it != NULL; app_pid_it = app_pid_it->next) {
						pid_t* _tmp6_;
						pid_t* app_pid = NULL;
						_tmp6_ = __pid_t_dup0 ((pid_t*) app_pid_it->data);
						app_pid = _tmp6_;
						{
							pid_t* _tmp7_;
							_tmp7_ = app_pid;
							if (_pid_t_equal (_tmp7_, &pid) == TRUE) {
								GalaApp* _tmp8_;
								_tmp8_ = app;
								result = _tmp8_;
								_g_free0 (app_pid);
								(app_pids == NULL) ? NULL : (app_pids = (_g_slist_free__g_free0_ (app_pids), NULL));
								(running_apps == NULL) ? NULL : (running_apps = (g_list_free (running_apps), NULL));
								return result;
							}
							_g_free0 (app_pid);
						}
					}
				}
				(app_pids == NULL) ? NULL : (app_pids = (_g_slist_free__g_free0_ (app_pids), NULL));
			}
		}
	}
	result = NULL;
	(running_apps == NULL) ? NULL : (running_apps = (g_list_free (running_apps), NULL));
	return result;
}

static GalaApp*
gala_window_tracker_get_app_from_window_pid (GalaWindowTracker* self,
                                             MetaWindow* window)
{
	gint pid = 0;
	GalaApp* _tmp0_;
	GalaApp* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (window != NULL, NULL);
	if (meta_window_is_remote (window)) {
		result = NULL;
		return result;
	}
	pid = meta_window_get_pid (window);
	if (pid < 1) {
		result = NULL;
		return result;
	}
	_tmp0_ = gala_window_tracker_get_app_from_pid ((pid_t) pid);
	result = _tmp0_;
	return result;
}

static gboolean
gala_window_tracker_check_app_id_prefix (GalaApp* app,
                                         const gchar* prefix)
{
	const gchar* _tmp0_;
	const gchar* _tmp1_;
	gboolean result;
	g_return_val_if_fail (app != NULL, FALSE);
	if (prefix == NULL) {
		result = TRUE;
		return result;
	}
	_tmp0_ = gala_app_get_id (app);
	_tmp1_ = _tmp0_;
	result = g_str_has_prefix (_tmp1_, prefix);
	return result;
}

static GalaApp*
gala_window_tracker_get_app_from_window_wmclass (GalaWindowTracker* self,
                                                 MetaWindow* window)
{
	gchar* app_prefix = NULL;
	const gchar* sandbox_id = NULL;
	const gchar* _tmp0_;
	const gchar* _tmp1_;
	const gchar* wm_instance = NULL;
	const gchar* _tmp4_;
	GalaAppSystem* appsys = NULL;
	GalaAppSystem* _tmp5_;
	GalaApp* app = NULL;
	GalaAppSystem* _tmp6_;
	const gchar* _tmp7_;
	GalaApp* _tmp8_;
	gboolean _tmp9_ = FALSE;
	GalaApp* _tmp10_;
	const gchar* wm_class = NULL;
	const gchar* _tmp14_;
	GalaAppSystem* _tmp15_;
	const gchar* _tmp16_;
	GalaApp* _tmp17_;
	gboolean _tmp18_ = FALSE;
	GalaApp* _tmp19_;
	GalaAppSystem* _tmp23_;
	const gchar* _tmp24_;
	GalaApp* _tmp25_;
	gboolean _tmp26_ = FALSE;
	GalaApp* _tmp27_;
	GalaAppSystem* _tmp31_;
	const gchar* _tmp32_;
	GalaApp* _tmp33_;
	gboolean _tmp34_ = FALSE;
	GalaApp* _tmp35_;
	GalaApp* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (window != NULL, NULL);
	app_prefix = NULL;
	_tmp0_ = meta_window_get_sandboxed_app_id (window);
	sandbox_id = _tmp0_;
	_tmp1_ = sandbox_id;
	if (_tmp1_ != NULL) {
		const gchar* _tmp2_;
		gchar* _tmp3_;
		_tmp2_ = sandbox_id;
		_tmp3_ = g_strdup_printf ("%s.", _tmp2_);
		_g_free0 (app_prefix);
		app_prefix = _tmp3_;
	}
	_tmp4_ = meta_window_get_wm_class_instance (window);
	wm_instance = _tmp4_;
	_tmp5_ = gala_app_system_get_default ();
	appsys = _tmp5_;
	_tmp6_ = appsys;
	_tmp7_ = wm_instance;
	_tmp8_ = gala_app_system_lookup_startup_wmclass (_tmp6_, _tmp7_);
	app = _tmp8_;
	_tmp10_ = app;
	if (_tmp10_ != NULL) {
		GalaApp* _tmp11_;
		const gchar* _tmp12_;
		_tmp11_ = app;
		_tmp12_ = app_prefix;
		_tmp9_ = gala_window_tracker_check_app_id_prefix (_tmp11_, _tmp12_);
	} else {
		_tmp9_ = FALSE;
	}
	if (_tmp9_) {
		GalaApp* _tmp13_;
		_tmp13_ = app;
		result = _tmp13_;
		_g_free0 (app_prefix);
		return result;
	}
	_tmp14_ = meta_window_get_wm_class (window);
	wm_class = _tmp14_;
	_tmp15_ = appsys;
	_tmp16_ = wm_class;
	_tmp17_ = gala_app_system_lookup_startup_wmclass (_tmp15_, _tmp16_);
	app = _tmp17_;
	_tmp19_ = app;
	if (_tmp19_ != NULL) {
		GalaApp* _tmp20_;
		const gchar* _tmp21_;
		_tmp20_ = app;
		_tmp21_ = app_prefix;
		_tmp18_ = gala_window_tracker_check_app_id_prefix (_tmp20_, _tmp21_);
	} else {
		_tmp18_ = FALSE;
	}
	if (_tmp18_) {
		GalaApp* _tmp22_;
		_tmp22_ = app;
		result = _tmp22_;
		_g_free0 (app_prefix);
		return result;
	}
	_tmp23_ = appsys;
	_tmp24_ = wm_instance;
	_tmp25_ = gala_app_system_lookup_desktop_wmclass (_tmp23_, _tmp24_);
	app = _tmp25_;
	_tmp27_ = app;
	if (_tmp27_ != NULL) {
		GalaApp* _tmp28_;
		const gchar* _tmp29_;
		_tmp28_ = app;
		_tmp29_ = app_prefix;
		_tmp26_ = gala_window_tracker_check_app_id_prefix (_tmp28_, _tmp29_);
	} else {
		_tmp26_ = FALSE;
	}
	if (_tmp26_) {
		GalaApp* _tmp30_;
		_tmp30_ = app;
		result = _tmp30_;
		_g_free0 (app_prefix);
		return result;
	}
	_tmp31_ = appsys;
	_tmp32_ = wm_class;
	_tmp33_ = gala_app_system_lookup_desktop_wmclass (_tmp31_, _tmp32_);
	app = _tmp33_;
	_tmp35_ = app;
	if (_tmp35_ != NULL) {
		GalaApp* _tmp36_;
		const gchar* _tmp37_;
		_tmp36_ = app;
		_tmp37_ = app_prefix;
		_tmp34_ = gala_window_tracker_check_app_id_prefix (_tmp36_, _tmp37_);
	} else {
		_tmp34_ = FALSE;
	}
	if (_tmp34_) {
		GalaApp* _tmp38_;
		_tmp38_ = app;
		result = _tmp38_;
		_g_free0 (app_prefix);
		return result;
	}
	result = NULL;
	_g_free0 (app_prefix);
	return result;
}

static GalaApp*
gala_window_tracker_get_app_from_sandboxed_app_id (GalaWindowTracker* self,
                                                   MetaWindow* window)
{
	const gchar* id = NULL;
	const gchar* _tmp0_;
	const gchar* _tmp1_;
	const gchar* _tmp2_;
	GalaApp* _tmp3_;
	GalaApp* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (window != NULL, NULL);
	_tmp0_ = meta_window_get_sandboxed_app_id (window);
	id = _tmp0_;
	_tmp1_ = id;
	if (_tmp1_ == NULL) {
		result = NULL;
		return result;
	}
	_tmp2_ = id;
	_tmp3_ = gala_window_tracker_get_app_from_id (_tmp2_);
	result = _tmp3_;
	return result;
}

static GalaApp*
gala_window_tracker_get_app_from_window_group (GalaWindowTracker* self,
                                               MetaWindow* window)
{
	MetaGroup* group = NULL;
	MetaGroup* _tmp0_;
	MetaGroup* _tmp1_;
	GSList* group_windows = NULL;
	MetaGroup* _tmp2_;
	GSList* _tmp3_;
	GSList* _tmp4_;
	GalaApp* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (window != NULL, NULL);
	_tmp0_ = meta_window_get_group (window);
	group = _tmp0_;
	_tmp1_ = group;
	if (_tmp1_ == NULL) {
		result = NULL;
		return result;
	}
	_tmp2_ = group;
	_tmp3_ = meta_group_list_windows (_tmp2_);
	group_windows = _tmp3_;
	_tmp4_ = group_windows;
	{
		GSList* group_window_collection = NULL;
		GSList* group_window_it = NULL;
		group_window_collection = _tmp4_;
		for (group_window_it = group_window_collection; group_window_it != NULL; group_window_it = group_window_it->next) {
			MetaWindow* group_window = NULL;
			group_window = (MetaWindow*) group_window_it->data;
			{
				MetaWindow* _tmp5_;
				MetaWindowType _tmp6_;
				MetaWindowType _tmp7_;
				GalaApp* _result_ = NULL;
				GHashTable* _tmp8_;
				MetaWindow* _tmp9_;
				gconstpointer _tmp10_;
				GalaApp* _tmp11_;
				_tmp5_ = group_window;
				_tmp6_ = meta_window_get_window_type (_tmp5_);
				_tmp7_ = _tmp6_;
				if (_tmp7_ != META_WINDOW_NORMAL) {
					continue;
				}
				_tmp8_ = self->priv->window_to_app;
				_tmp9_ = group_window;
				_tmp10_ = g_hash_table_lookup (_tmp8_, _tmp9_);
				_result_ = (GalaApp*) _tmp10_;
				_tmp11_ = _result_;
				if (_tmp11_ != NULL) {
					GalaApp* _tmp12_;
					_tmp12_ = _result_;
					result = _tmp12_;
					(group_windows == NULL) ? NULL : (group_windows = (g_slist_free (group_windows), NULL));
					return result;
				}
			}
		}
	}
	result = NULL;
	(group_windows == NULL) ? NULL : (group_windows = (g_slist_free (group_windows), NULL));
	return result;
}

static gpointer
_g_object_ref0 (gpointer self)
{
	return self ? g_object_ref (self) : NULL;
}

static GalaApp*
gala_window_tracker_get_app_for_window (GalaWindowTracker* self,
                                        MetaWindow* window)
{
	MetaWindow* transient_for = NULL;
	MetaWindow* _tmp0_;
	MetaWindow* _tmp1_;
	GalaApp* _result_ = NULL;
	gboolean _tmp4_ = FALSE;
	MetaWindowType _tmp5_;
	MetaWindowType _tmp6_;
	GalaApp* _tmp13_;
	GalaApp* _tmp14_;
	GalaApp* _tmp17_;
	GalaApp* _tmp18_;
	GalaApp* _tmp21_;
	GalaApp* _tmp22_;
	GalaApp* _tmp25_;
	GalaApp* _tmp26_;
	const gchar* startup_id = NULL;
	const gchar* _tmp29_;
	const gchar* _tmp30_;
	GalaApp* _tmp51_;
	GalaApp* _tmp52_;
	GalaApp* _tmp55_;
	GalaApp* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (window != NULL, NULL);
	_tmp0_ = meta_window_get_transient_for (window);
	transient_for = _tmp0_;
	_tmp1_ = transient_for;
	if (_tmp1_ != NULL) {
		MetaWindow* _tmp2_;
		GalaApp* _tmp3_;
		_tmp2_ = transient_for;
		_tmp3_ = gala_window_tracker_get_app_for_window (self, _tmp2_);
		result = _tmp3_;
		return result;
	}
	_tmp5_ = meta_window_get_window_type (window);
	_tmp6_ = _tmp5_;
	if (_tmp6_ == META_WINDOW_NORMAL) {
		_tmp4_ = TRUE;
	} else {
		_tmp4_ = meta_window_is_remote (window);
	}
	if (_tmp4_) {
		GHashTable* _tmp7_;
		gconstpointer _tmp8_;
		GalaApp* _tmp9_;
		_tmp7_ = self->priv->window_to_app;
		_tmp8_ = g_hash_table_lookup (_tmp7_, window);
		_result_ = (GalaApp*) _tmp8_;
		_tmp9_ = _result_;
		if (_tmp9_ != NULL) {
			GalaApp* _tmp10_;
			GalaApp* _tmp11_;
			_tmp10_ = _result_;
			_tmp11_ = _g_object_ref0 (_tmp10_);
			result = _tmp11_;
			return result;
		}
	}
	if (meta_window_is_remote (window)) {
		GalaApp* _tmp12_;
		_tmp12_ = gala_app_new_for_window (window);
		result = _tmp12_;
		return result;
	}
	_tmp13_ = gala_window_tracker_get_app_from_window_wmclass (self, window);
	_result_ = _tmp13_;
	_tmp14_ = _result_;
	if (_tmp14_ != NULL) {
		GalaApp* _tmp15_;
		GalaApp* _tmp16_;
		_tmp15_ = _result_;
		_tmp16_ = _g_object_ref0 (_tmp15_);
		result = _tmp16_;
		return result;
	}
	_tmp17_ = gala_window_tracker_get_app_from_sandboxed_app_id (self, window);
	_result_ = _tmp17_;
	_tmp18_ = _result_;
	if (_tmp18_ != NULL) {
		GalaApp* _tmp19_;
		GalaApp* _tmp20_;
		_tmp19_ = _result_;
		_tmp20_ = _g_object_ref0 (_tmp19_);
		result = _tmp20_;
		return result;
	}
	_tmp21_ = gala_window_tracker_get_app_from_gapplication_id (window);
	_result_ = _tmp21_;
	_tmp22_ = _result_;
	if (_tmp22_ != NULL) {
		GalaApp* _tmp23_;
		GalaApp* _tmp24_;
		_tmp23_ = _result_;
		_tmp24_ = _g_object_ref0 (_tmp23_);
		result = _tmp24_;
		return result;
	}
	_tmp25_ = gala_window_tracker_get_app_from_window_pid (self, window);
	_result_ = _tmp25_;
	_tmp26_ = _result_;
	if (_tmp26_ != NULL) {
		GalaApp* _tmp27_;
		GalaApp* _tmp28_;
		_tmp27_ = _result_;
		_tmp28_ = _g_object_ref0 (_tmp27_);
		result = _tmp28_;
		return result;
	}
	_tmp29_ = meta_window_get_startup_id (window);
	startup_id = _tmp29_;
	_tmp30_ = startup_id;
	if (_tmp30_ != NULL) {
		MetaStartupNotification* sn = NULL;
		MetaDisplay* _tmp31_;
		MetaStartupNotification* _tmp32_;
		GSList* sequences = NULL;
		MetaStartupNotification* _tmp33_;
		GSList* _tmp34_;
		GSList* _tmp35_;
		_tmp31_ = meta_window_get_display (window);
		_tmp32_ = meta_display_get_startup_notification (_tmp31_);
		sn = _tmp32_;
		_tmp33_ = sn;
		_tmp34_ = meta_startup_notification_get_sequences (_tmp33_);
		sequences = _tmp34_;
		_tmp35_ = sequences;
		{
			GSList* sequence_collection = NULL;
			GSList* sequence_it = NULL;
			sequence_collection = _tmp35_;
			for (sequence_it = sequence_collection; sequence_it != NULL; sequence_it = sequence_it->next) {
				MetaStartupSequence* sequence = NULL;
				sequence = (MetaStartupSequence*) sequence_it->data;
				{
					const gchar* id = NULL;
					MetaStartupSequence* _tmp36_;
					const gchar* _tmp37_;
					const gchar* _tmp38_;
					const gchar* _tmp39_;
					const gchar* appid = NULL;
					MetaStartupSequence* _tmp40_;
					const gchar* _tmp41_;
					const gchar* _tmp42_;
					_tmp36_ = sequence;
					_tmp37_ = meta_startup_sequence_get_id (_tmp36_);
					id = _tmp37_;
					_tmp38_ = id;
					_tmp39_ = startup_id;
					if (g_strcmp0 (_tmp38_, _tmp39_) != 0) {
						continue;
					}
					_tmp40_ = sequence;
					_tmp41_ = meta_startup_sequence_get_application_id (_tmp40_);
					appid = _tmp41_;
					_tmp42_ = appid;
					if (_tmp42_ != NULL) {
						GalaAppSystem* _tmp43_;
						const gchar* _tmp44_;
						gchar* _tmp45_;
						gchar* _tmp46_;
						GalaApp* _tmp47_;
						GalaApp* _tmp48_;
						_tmp43_ = gala_app_system_get_default ();
						_tmp44_ = appid;
						_tmp45_ = g_path_get_basename (_tmp44_);
						_tmp46_ = _tmp45_;
						_tmp47_ = gala_app_system_lookup_app (_tmp43_, _tmp46_);
						_result_ = _tmp47_;
						_g_free0 (_tmp46_);
						_tmp48_ = _result_;
						if (_tmp48_ != NULL) {
							GalaApp* _tmp49_;
							GalaApp* _tmp50_;
							_tmp49_ = _result_;
							_tmp50_ = _g_object_ref0 (_tmp49_);
							result = _tmp50_;
							return result;
						}
					}
				}
			}
		}
	}
	_tmp51_ = gala_window_tracker_get_app_from_window_group (self, window);
	_result_ = _tmp51_;
	_tmp52_ = _result_;
	if (_tmp52_ != NULL) {
		GalaApp* _tmp53_;
		GalaApp* _tmp54_;
		_tmp53_ = _result_;
		_tmp54_ = _g_object_ref0 (_tmp53_);
		result = _tmp54_;
		return result;
	}
	_tmp55_ = gala_app_new_for_window (window);
	result = _tmp55_;
	return result;
}

static void
gala_window_tracker_tracked_window_changed (GalaWindowTracker* self,
                                            MetaWindow* window)
{
	g_return_if_fail (self != NULL);
	g_return_if_fail (window != NULL);
	gala_window_tracker_disassociate_window (self, window);
	gala_window_tracker_track_window (self, window);
}

static void
gala_window_tracker_tracked_window_notified (GalaWindowTracker* self,
                                             GObject* object,
                                             GParamSpec* pspec)
{
	g_return_if_fail (self != NULL);
	g_return_if_fail (object != NULL);
	g_return_if_fail (pspec != NULL);
	gala_window_tracker_tracked_window_changed (self, G_TYPE_CHECK_INSTANCE_CAST (object, meta_window_get_type (), MetaWindow));
}

static void
_gala_window_tracker_tracked_window_notified_g_object_notify (GObject* _sender,
                                                              GParamSpec* pspec,
                                                              gpointer self)
{
	gala_window_tracker_tracked_window_notified ((GalaWindowTracker*) self, _sender, pspec);
}

static void
_gala_window_tracker_disassociate_window_meta_window_unmanaged (MetaWindow* _sender,
                                                                gpointer self)
{
	gala_window_tracker_disassociate_window ((GalaWindowTracker*) self, _sender);
}

static void
gala_window_tracker_track_window (GalaWindowTracker* self,
                                  MetaWindow* window)
{
	GalaApp* app = NULL;
	GalaApp* _tmp0_;
	GalaApp* _tmp1_;
	GHashTable* _tmp2_;
	GalaApp* _tmp3_;
	GalaApp* _tmp4_;
	GalaApp* _tmp5_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (window != NULL);
	_tmp0_ = gala_window_tracker_get_app_for_window (self, window);
	app = _tmp0_;
	_tmp1_ = app;
	if (_tmp1_ == NULL) {
		_g_object_unref0 (app);
		return;
	}
	_tmp2_ = self->priv->window_to_app;
	_tmp3_ = app;
	_tmp4_ = _g_object_ref0 (_tmp3_);
	g_hash_table_insert (_tmp2_, window, _tmp4_);
	g_signal_connect_object ((GObject*) window, "notify::wm-class", (GCallback) _gala_window_tracker_tracked_window_notified_g_object_notify, self, 0);
	g_signal_connect_object ((GObject*) window, "notify::gtk-application-id", (GCallback) _gala_window_tracker_tracked_window_notified_g_object_notify, self, 0);
	g_signal_connect_object (window, "unmanaged", (GCallback) _gala_window_tracker_disassociate_window_meta_window_unmanaged, self, 0);
	_tmp5_ = app;
	gala_app_add_window (_tmp5_, window);
	g_signal_emit (self, gala_window_tracker_signals[GALA_WINDOW_TRACKER_WINDOWS_CHANGED_SIGNAL], 0);
	_g_object_unref0 (app);
}

static void
gala_window_tracker_disassociate_window (GalaWindowTracker* self,
                                         MetaWindow* window)
{
	GalaApp* app = NULL;
	GalaApp* _tmp0_;
	GalaApp* _tmp1_;
	guint _tmp2_;
	guint _tmp3_;
	GQuark _tmp4_;
	guint _tmp5_;
	GQuark _tmp6_;
	GalaApp* _tmp7_;
	GHashTable* _tmp8_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (window != NULL);
	_tmp0_ = gala_window_tracker_get_app_for_window (self, window);
	app = _tmp0_;
	_tmp1_ = app;
	if (_tmp1_ == NULL) {
		_g_object_unref0 (app);
		return;
	}
	g_signal_parse_name ("unmanaged", meta_window_get_type (), &_tmp2_, NULL, FALSE);
	g_signal_handlers_disconnect_matched (window, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp2_, 0, NULL, (GCallback) _gala_window_tracker_disassociate_window_meta_window_unmanaged, self);
	g_signal_parse_name ("notify::wm-class", G_TYPE_OBJECT, &_tmp3_, &_tmp4_, TRUE);
	g_signal_handlers_disconnect_matched ((GObject*) window, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp3_, _tmp4_, NULL, (GCallback) _gala_window_tracker_tracked_window_notified_g_object_notify, self);
	g_signal_parse_name ("notify::gtk-application-id", G_TYPE_OBJECT, &_tmp5_, &_tmp6_, TRUE);
	g_signal_handlers_disconnect_matched ((GObject*) window, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp5_, _tmp6_, NULL, (GCallback) _gala_window_tracker_tracked_window_notified_g_object_notify, self);
	_tmp7_ = app;
	gala_app_remove_window (_tmp7_, window);
	_tmp8_ = self->priv->window_to_app;
	g_hash_table_remove (_tmp8_, window);
	g_signal_emit (self, gala_window_tracker_signals[GALA_WINDOW_TRACKER_WINDOWS_CHANGED_SIGNAL], 0);
	_g_object_unref0 (app);
}

GalaWindowTracker*
gala_window_tracker_construct (GType object_type)
{
	GalaWindowTracker * self = NULL;
	self = (GalaWindowTracker*) g_object_new (object_type, NULL);
	return self;
}

GalaWindowTracker*
gala_window_tracker_new (void)
{
	return gala_window_tracker_construct (GALA_TYPE_WINDOW_TRACKER);
}

static void
_g_object_unref0_ (gpointer var)
{
	(var == NULL) ? NULL : (var = (g_object_unref (var), NULL));
}

static GObject *
gala_window_tracker_constructor (GType type,
                                 guint n_construct_properties,
                                 GObjectConstructParam * construct_properties)
{
	GObject * obj;
	GObjectClass * parent_class;
	GalaWindowTracker * self;
	GHashFunc _tmp0_;
	GEqualFunc _tmp1_;
	GHashTable* _tmp2_;
	parent_class = G_OBJECT_CLASS (gala_window_tracker_parent_class);
	obj = parent_class->constructor (type, n_construct_properties, construct_properties);
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, GALA_TYPE_WINDOW_TRACKER, GalaWindowTracker);
	_tmp0_ = g_direct_hash;
	_tmp1_ = g_direct_equal;
	_tmp2_ = g_hash_table_new_full (_tmp0_, _tmp1_, NULL, _g_object_unref0_);
	_g_hash_table_unref0 (self->priv->window_to_app);
	self->priv->window_to_app = _tmp2_;
	return obj;
}

static void
gala_window_tracker_class_init (GalaWindowTrackerClass * klass,
                                gpointer klass_data)
{
	gala_window_tracker_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &GalaWindowTracker_private_offset);
	G_OBJECT_CLASS (klass)->constructor = gala_window_tracker_constructor;
	G_OBJECT_CLASS (klass)->finalize = gala_window_tracker_finalize;
	gala_window_tracker_signals[GALA_WINDOW_TRACKER_WINDOWS_CHANGED_SIGNAL] = g_signal_new ("windows-changed", GALA_TYPE_WINDOW_TRACKER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}

static void
gala_window_tracker_instance_init (GalaWindowTracker * self,
                                   gpointer klass)
{
	self->priv = gala_window_tracker_get_instance_private (self);
	self->priv->focused_app = NULL;
}

static void
gala_window_tracker_finalize (GObject * obj)
{
	GalaWindowTracker * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, GALA_TYPE_WINDOW_TRACKER, GalaWindowTracker);
	_g_object_unref0 (self->priv->focused_app);
	_g_hash_table_unref0 (self->priv->window_to_app);
	G_OBJECT_CLASS (gala_window_tracker_parent_class)->finalize (obj);
}

static GType
gala_window_tracker_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (GalaWindowTrackerClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gala_window_tracker_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (GalaWindowTracker), 0, (GInstanceInitFunc) gala_window_tracker_instance_init, NULL };
	GType gala_window_tracker_type_id;
	gala_window_tracker_type_id = g_type_register_static (G_TYPE_OBJECT, "GalaWindowTracker", &g_define_type_info, 0);
	GalaWindowTracker_private_offset = g_type_add_instance_private (gala_window_tracker_type_id, sizeof (GalaWindowTrackerPrivate));
	return gala_window_tracker_type_id;
}

GType
gala_window_tracker_get_type (void)
{
	static volatile gsize gala_window_tracker_type_id__once = 0;
	if (g_once_init_enter (&gala_window_tracker_type_id__once)) {
		GType gala_window_tracker_type_id;
		gala_window_tracker_type_id = gala_window_tracker_get_type_once ();
		g_once_init_leave (&gala_window_tracker_type_id__once, gala_window_tracker_type_id);
	}
	return gala_window_tracker_type_id__once;
}

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;
}

