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

/*
 * This file is part of budgie-desktop
 *
 * Copyright © 2014-2022 Budgie Desktop Developers
 *
 * 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 2 of the License, or
 * (at your option) any later version.
 */

#include "appsys.h"
#include <glib.h>
#include <stdlib.h>
#include <string.h>
#include <gio/gdesktopappinfo.h>
#include <gio/gio.h>
#include <glib-object.h>
#include <libwnck/libwnck.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <X11/Xregion.h>

enum  {
	BUDGIE_APP_SYSTEM_0_PROPERTY,
	BUDGIE_APP_SYSTEM_NUM_PROPERTIES
};
static GParamSpec* budgie_app_system_properties[BUDGIE_APP_SYSTEM_NUM_PROPERTIES];
#define _g_hash_table_unref0(var) ((var == NULL) ? NULL : (var = (g_hash_table_unref (var), NULL)))
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL)))
#define _g_variant_unref0(var) ((var == NULL) ? NULL : (var = (g_variant_unref (var), NULL)))
#define _g_free0(var) (var = (g_free (var), NULL))
enum  {
	BUDGIE_APP_SYSTEM_APP_LAUNCHED_SIGNAL,
	BUDGIE_APP_SYSTEM_NUM_SIGNALS
};
static guint budgie_app_system_signals[BUDGIE_APP_SYSTEM_NUM_SIGNALS] = {0};

struct _BudgieAppSystemPrivate {
	GHashTable* startupids;
	GHashTable* simpletons;
	GHashTable* desktops;
	GHashTable* exec_cache;
	GHashTable* pid_cache;
	GAppInfoMonitor* monitor;
	gboolean invalidated;
	GRecMutex __lock_invalidated;
	GDBusConnection* bus;
};

static gint BudgieAppSystem_private_offset;
static gpointer budgie_app_system_parent_class = NULL;

static void _g_free0_ (gpointer var);
static void __lambda4_ (BudgieAppSystem* self,
                 GObject* obj,
                 GAsyncResult* res);
static void budgie_app_system_signal_received (BudgieAppSystem* self,
                                        GDBusConnection* connection,
                                        const gchar* sender,
                                        const gchar* object_path,
                                        const gchar* interface_name,
                                        const gchar* signal_name,
                                        GVariant* parameters);
static void _budgie_app_system_signal_received_gd_bus_signal_callback (GDBusConnection* connection,
                                                                const gchar* sender_name,
                                                                const gchar* object_path,
                                                                const gchar* interface_name,
                                                                const gchar* signal_name,
                                                                GVariant* parameters,
                                                                gpointer self);
static void ___lambda4__gasync_ready_callback (GObject* source_object,
                                        GAsyncResult* res,
                                        gpointer self);
static void __lambda5_ (BudgieAppSystem* self);
static gboolean __lambda6_ (BudgieAppSystem* self);
static gboolean ___lambda6__gsource_func (gpointer self);
static void ___lambda5__g_app_info_monitor_changed (GAppInfoMonitor* _sender,
                                             gpointer self);
static void budgie_app_system_reload_ids (BudgieAppSystem* self);
static gint64* _int64_dup (gint64* self);
static void budgie_app_system_check_invalidated (BudgieAppSystem* self);
static void _g_object_unref0_ (gpointer var);
static inline void _g_list_free__g_object_unref0_ (GList* self);
static gchar* budgie_app_system_query_atom_string_internal (BudgieAppSystem* self,
                                                     gulong xid,
                                                     GdkAtom atom,
                                                     gboolean utf8);
static void budgie_app_system_finalize (GObject * obj);
static GType budgie_app_system_get_type_once (void);
static void _vala_array_destroy (gpointer array,
                          gssize array_length,
                          GDestroyNotify destroy_func);
static void _vala_array_free (gpointer array,
                       gssize array_length,
                       GDestroyNotify destroy_func);

static inline gpointer
budgie_app_system_get_instance_private (BudgieAppSystem* self)
{
	return G_STRUCT_MEMBER_P (self, BudgieAppSystem_private_offset);
}

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

static void
_budgie_app_system_signal_received_gd_bus_signal_callback (GDBusConnection* connection,
                                                           const gchar* sender_name,
                                                           const gchar* object_path,
                                                           const gchar* interface_name,
                                                           const gchar* signal_name,
                                                           GVariant* parameters,
                                                           gpointer self)
{
	budgie_app_system_signal_received ((BudgieAppSystem*) self, connection, sender_name, object_path, interface_name, signal_name, parameters);
}

static void
__lambda4_ (BudgieAppSystem* self,
            GObject* obj,
            GAsyncResult* res)
{
	GError* _inner_error0_ = NULL;
	g_return_if_fail (res != NULL);
	{
		GDBusConnection* _tmp0_ = NULL;
		GDBusConnection* _tmp1_;
		GDBusConnection* _tmp2_;
		GDBusConnection* _tmp3_;
		_tmp1_ = g_bus_get_finish (res, &_inner_error0_);
		_tmp0_ = _tmp1_;
		if (G_UNLIKELY (_inner_error0_ != NULL)) {
			if (_inner_error0_->domain == G_IO_ERROR) {
				goto __catch0_g_io_error;
			}
			g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return;
		}
		_tmp2_ = _tmp0_;
		_tmp0_ = NULL;
		_g_object_unref0 (self->priv->bus);
		self->priv->bus = _tmp2_;
		_tmp3_ = self->priv->bus;
		g_dbus_connection_signal_subscribe (_tmp3_, NULL, "org.gtk.gio.DesktopAppInfo", "Launched", "/org/gtk/gio/DesktopAppInfo", NULL, 0, _budgie_app_system_signal_received_gd_bus_signal_callback, g_object_ref (self), g_object_unref);
		_g_object_unref0 (_tmp0_);
	}
	goto __finally0;
	__catch0_g_io_error:
	{
		GError* e = NULL;
		GError* _tmp4_;
		const gchar* _tmp5_;
		e = _inner_error0_;
		_inner_error0_ = NULL;
		_tmp4_ = e;
		_tmp5_ = _tmp4_->message;
		g_warning ("AppSystem.vala:52: %s", _tmp5_);
		_g_error_free0 (e);
	}
	__finally0:
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
		g_clear_error (&_inner_error0_);
		return;
	}
}

static void
___lambda4__gasync_ready_callback (GObject* source_object,
                                   GAsyncResult* res,
                                   gpointer self)
{
	__lambda4_ ((BudgieAppSystem*) self, source_object, res);
	g_object_unref (self);
}

static gboolean
__lambda6_ (BudgieAppSystem* self)
{
	GError* _inner_error0_ = NULL;
	gboolean result;
	{
		g_rec_mutex_lock (&self->priv->__lock_invalidated);
		{
			self->priv->invalidated = TRUE;
		}
		__finally0:
		{
			g_rec_mutex_unlock (&self->priv->__lock_invalidated);
		}
		if (G_UNLIKELY (_inner_error0_ != NULL)) {
			gboolean _tmp0_ = FALSE;
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return _tmp0_;
		}
	}
	result = FALSE;
	return result;
}

static gboolean
___lambda6__gsource_func (gpointer self)
{
	gboolean result;
	result = __lambda6_ ((BudgieAppSystem*) self);
	return result;
}

static void
__lambda5_ (BudgieAppSystem* self)
{
	g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, ___lambda6__gsource_func, g_object_ref (self), g_object_unref);
}

static void
___lambda5__g_app_info_monitor_changed (GAppInfoMonitor* _sender,
                                        gpointer self)
{
	__lambda5_ ((BudgieAppSystem*) self);
}

BudgieAppSystem*
budgie_app_system_construct (GType object_type)
{
	BudgieAppSystem * self = NULL;
	GHashFunc _tmp0_;
	GEqualFunc _tmp1_;
	GHashTable* _tmp2_;
	GHashTable* _tmp3_;
	gchar* _tmp4_;
	gchar* _tmp5_;
	GHashTable* _tmp6_;
	gchar* _tmp7_;
	gchar* _tmp8_;
	GHashTable* _tmp9_;
	gchar* _tmp10_;
	gchar* _tmp11_;
	GHashTable* _tmp12_;
	gchar* _tmp13_;
	gchar* _tmp14_;
	GHashTable* _tmp15_;
	gchar* _tmp16_;
	gchar* _tmp17_;
	GHashTable* _tmp18_;
	gchar* _tmp19_;
	gchar* _tmp20_;
	GHashTable* _tmp21_;
	gchar* _tmp22_;
	gchar* _tmp23_;
	GHashFunc _tmp24_;
	GEqualFunc _tmp25_;
	GHashTable* _tmp26_;
	GAppInfoMonitor* _tmp27_;
	GAppInfoMonitor* _tmp28_;
	self = (BudgieAppSystem*) g_object_new (object_type, NULL);
	_tmp0_ = g_str_hash;
	_tmp1_ = g_str_equal;
	_tmp2_ = g_hash_table_new_full (_tmp0_, _tmp1_, _g_free0_, _g_free0_);
	_g_hash_table_unref0 (self->priv->simpletons);
	self->priv->simpletons = _tmp2_;
	_tmp3_ = self->priv->simpletons;
	_tmp4_ = g_strdup ("google-chrome-stable");
	_tmp5_ = g_strdup ("google-chrome");
	g_hash_table_insert (_tmp3_, _tmp4_, _tmp5_);
	_tmp6_ = self->priv->simpletons;
	_tmp7_ = g_strdup ("calibre-gui");
	_tmp8_ = g_strdup ("calibre");
	g_hash_table_insert (_tmp6_, _tmp7_, _tmp8_);
	_tmp9_ = self->priv->simpletons;
	_tmp10_ = g_strdup ("code - oss");
	_tmp11_ = g_strdup ("vscode-oss");
	g_hash_table_insert (_tmp9_, _tmp10_, _tmp11_);
	_tmp12_ = self->priv->simpletons;
	_tmp13_ = g_strdup ("code");
	_tmp14_ = g_strdup ("vscode");
	g_hash_table_insert (_tmp12_, _tmp13_, _tmp14_);
	_tmp15_ = self->priv->simpletons;
	_tmp16_ = g_strdup ("psppire");
	_tmp17_ = g_strdup ("pspp");
	g_hash_table_insert (_tmp15_, _tmp16_, _tmp17_);
	_tmp18_ = self->priv->simpletons;
	_tmp19_ = g_strdup ("gnome-twitch");
	_tmp20_ = g_strdup ("com.vinszent.gnometwitch");
	g_hash_table_insert (_tmp18_, _tmp19_, _tmp20_);
	_tmp21_ = self->priv->simpletons;
	_tmp22_ = g_strdup ("anoise.py");
	_tmp23_ = g_strdup ("anoise");
	g_hash_table_insert (_tmp21_, _tmp22_, _tmp23_);
	_tmp24_ = g_str_hash;
	_tmp25_ = g_str_equal;
	_tmp26_ = g_hash_table_new_full (_tmp24_, _tmp25_, _g_free0_, _g_free0_);
	_g_hash_table_unref0 (self->priv->pid_cache);
	self->priv->pid_cache = _tmp26_;
	g_bus_get (G_BUS_TYPE_SESSION, NULL, ___lambda4__gasync_ready_callback, g_object_ref (self));
	_tmp27_ = g_app_info_monitor_get ();
	_g_object_unref0 (self->priv->monitor);
	self->priv->monitor = _tmp27_;
	_tmp28_ = self->priv->monitor;
	g_signal_connect_object (_tmp28_, "changed", (GCallback) ___lambda5__g_app_info_monitor_changed, self, 0);
	budgie_app_system_reload_ids (self);
	return self;
}

BudgieAppSystem*
budgie_app_system_new (void)
{
	return budgie_app_system_construct (BUDGIE_TYPE_APP_SYSTEM);
}

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

static gpointer
__int64_dup0 (gpointer self)
{
	return self ? _int64_dup (self) : NULL;
}

static void
budgie_app_system_signal_received (BudgieAppSystem* self,
                                   GDBusConnection* connection,
                                   const gchar* sender,
                                   const gchar* object_path,
                                   const gchar* interface_name,
                                   const gchar* signal_name,
                                   GVariant* parameters)
{
	GVariant* desktop_variant = NULL;
	gint64 pid = 0LL;
	GVariant* _tmp0_ = NULL;
	gint64 _tmp1_ = 0LL;
	gchar* desktop_file = NULL;
	GVariant* _tmp2_;
	const gchar* _tmp3_;
	gchar* _tmp4_;
	gboolean _tmp5_ = FALSE;
	const gchar* _tmp6_;
	GHashTable* _tmp7_;
	gint64* _tmp8_;
	const gchar* _tmp9_;
	gchar* _tmp10_;
	const gchar* _tmp11_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (connection != NULL);
	g_return_if_fail (object_path != NULL);
	g_return_if_fail (interface_name != NULL);
	g_return_if_fail (signal_name != NULL);
	g_return_if_fail (parameters != NULL);
	g_variant_get (parameters, "(@aysxas@a{sv})", &_tmp0_, NULL, &_tmp1_, NULL, NULL, NULL);
	_g_variant_unref0 (desktop_variant);
	desktop_variant = _tmp0_;
	pid = _tmp1_;
	_tmp2_ = desktop_variant;
	_tmp3_ = g_variant_get_bytestring (_tmp2_);
	_tmp4_ = g_strdup (_tmp3_);
	desktop_file = _tmp4_;
	_tmp6_ = desktop_file;
	if (g_strcmp0 (_tmp6_, "") == 0) {
		_tmp5_ = TRUE;
	} else {
		_tmp5_ = pid == ((gint64) 0);
	}
	if (_tmp5_) {
		_g_free0 (desktop_file);
		_g_variant_unref0 (desktop_variant);
		return;
	}
	_tmp7_ = self->priv->pid_cache;
	_tmp8_ = __int64_dup0 (&pid);
	_tmp9_ = desktop_file;
	_tmp10_ = g_strdup (_tmp9_);
	g_hash_table_insert (_tmp7_, _tmp8_, _tmp10_);
	_tmp11_ = desktop_file;
	g_signal_emit (self, budgie_app_system_signals[BUDGIE_APP_SYSTEM_APP_LAUNCHED_SIGNAL], 0, _tmp11_);
	_g_free0 (desktop_file);
	_g_variant_unref0 (desktop_variant);
}

/**
* We lazily check if at some point we became invalidated. In most cases
* a package operation or similar modified a desktop file, i.e. making it
* available or unavailable.
*
* Instead of immediately reloading the appsystem we wait until something
* is actually requested again, check if we're invalidated, reload and then
* set us validated again.
*/
static void
budgie_app_system_check_invalidated (BudgieAppSystem* self)
{
	GError* _inner_error0_ = NULL;
	g_return_if_fail (self != NULL);
	if (self->priv->invalidated) {
		{
			g_rec_mutex_lock (&self->priv->__lock_invalidated);
			{
				budgie_app_system_reload_ids (self);
				self->priv->invalidated = FALSE;
			}
			__finally0:
			{
				g_rec_mutex_unlock (&self->priv->__lock_invalidated);
			}
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
				g_clear_error (&_inner_error0_);
				return;
			}
		}
	}
}

/**
* Reload and cache all the desktop IDS
*/
static void
_g_object_unref0_ (gpointer var)
{
	(var == NULL) ? NULL : (var = (g_object_unref (var), NULL));
}

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

static inline void
_g_list_free__g_object_unref0_ (GList* self)
{
	g_list_free_full (self, (GDestroyNotify) _g_object_unref0_);
}

static void
budgie_app_system_reload_ids (BudgieAppSystem* self)
{
	GHashFunc _tmp0_;
	GEqualFunc _tmp1_;
	GHashTable* _tmp2_;
	GHashFunc _tmp3_;
	GEqualFunc _tmp4_;
	GHashTable* _tmp5_;
	GHashFunc _tmp6_;
	GEqualFunc _tmp7_;
	GHashTable* _tmp8_;
	GList* _tmp9_;
	g_return_if_fail (self != NULL);
	_tmp0_ = g_str_hash;
	_tmp1_ = g_str_equal;
	_tmp2_ = g_hash_table_new_full (_tmp0_, _tmp1_, _g_free0_, _g_free0_);
	_g_hash_table_unref0 (self->priv->startupids);
	self->priv->startupids = _tmp2_;
	_tmp3_ = g_str_hash;
	_tmp4_ = g_str_equal;
	_tmp5_ = g_hash_table_new_full (_tmp3_, _tmp4_, _g_free0_, _g_object_unref0_);
	_g_hash_table_unref0 (self->priv->desktops);
	self->priv->desktops = _tmp5_;
	_tmp6_ = g_str_hash;
	_tmp7_ = g_str_equal;
	_tmp8_ = g_hash_table_new_full (_tmp6_, _tmp7_, _g_free0_, _g_free0_);
	_g_hash_table_unref0 (self->priv->exec_cache);
	self->priv->exec_cache = _tmp8_;
	_tmp9_ = g_app_info_get_all ();
	{
		GList* appinfo_collection = NULL;
		GList* appinfo_it = NULL;
		appinfo_collection = _tmp9_;
		for (appinfo_it = appinfo_collection; appinfo_it != NULL; appinfo_it = appinfo_it->next) {
			GAppInfo* _tmp10_;
			GAppInfo* appinfo = NULL;
			_tmp10_ = _g_object_ref0 ((GAppInfo*) appinfo_it->data);
			appinfo = _tmp10_;
			{
				GDesktopAppInfo* dinfo = NULL;
				GAppInfo* _tmp11_;
				GDesktopAppInfo* _tmp12_;
				GDesktopAppInfo* _tmp13_;
				const gchar* _tmp14_;
				GHashTable* _tmp22_;
				GDesktopAppInfo* _tmp23_;
				const gchar* _tmp24_;
				gchar* _tmp25_;
				GDesktopAppInfo* _tmp26_;
				GDesktopAppInfo* _tmp27_;
				gchar* try_exec = NULL;
				GDesktopAppInfo* _tmp28_;
				gchar* _tmp29_;
				const gchar* _tmp30_;
				const gchar* _tmp34_;
				const gchar* _tmp35_;
				gchar* _tmp36_;
				const gchar* _tmp37_;
				gchar* _tmp38_;
				GHashTable* _tmp39_;
				const gchar* _tmp40_;
				gchar* _tmp41_;
				GDesktopAppInfo* _tmp42_;
				const gchar* _tmp43_;
				gchar* _tmp44_;
				_tmp11_ = appinfo;
				_tmp12_ = _g_object_ref0 (G_TYPE_CHECK_INSTANCE_TYPE (_tmp11_, G_TYPE_DESKTOP_APP_INFO) ? ((GDesktopAppInfo*) _tmp11_) : NULL);
				dinfo = _tmp12_;
				_tmp13_ = dinfo;
				_tmp14_ = g_desktop_app_info_get_startup_wm_class (_tmp13_);
				if (_tmp14_ != NULL) {
					GHashTable* _tmp15_;
					GDesktopAppInfo* _tmp16_;
					const gchar* _tmp17_;
					gchar* _tmp18_;
					GDesktopAppInfo* _tmp19_;
					const gchar* _tmp20_;
					gchar* _tmp21_;
					_tmp15_ = self->priv->startupids;
					_tmp16_ = dinfo;
					_tmp17_ = g_desktop_app_info_get_startup_wm_class (_tmp16_);
					_tmp18_ = g_utf8_strdown (_tmp17_, (gssize) -1);
					_tmp19_ = dinfo;
					_tmp20_ = g_app_info_get_id ((GAppInfo*) _tmp19_);
					_tmp21_ = g_strdup (_tmp20_);
					g_hash_table_insert (_tmp15_, _tmp18_, _tmp21_);
				}
				_tmp22_ = self->priv->desktops;
				_tmp23_ = dinfo;
				_tmp24_ = g_app_info_get_id ((GAppInfo*) _tmp23_);
				_tmp25_ = g_utf8_strdown (_tmp24_, (gssize) -1);
				_tmp26_ = dinfo;
				_tmp27_ = _g_object_ref0 (_tmp26_);
				g_hash_table_insert (_tmp22_, _tmp25_, _tmp27_);
				_tmp28_ = dinfo;
				_tmp29_ = g_desktop_app_info_get_string (_tmp28_, "TryExec");
				try_exec = _tmp29_;
				_tmp30_ = try_exec;
				if (_tmp30_ == NULL) {
					GDesktopAppInfo* _tmp31_;
					const gchar* _tmp32_;
					gchar* _tmp33_;
					_tmp31_ = dinfo;
					_tmp32_ = g_app_info_get_executable ((GAppInfo*) _tmp31_);
					_tmp33_ = g_strdup (_tmp32_);
					_g_free0 (try_exec);
					try_exec = _tmp33_;
				}
				_tmp34_ = try_exec;
				if (_tmp34_ == NULL) {
					_g_free0 (try_exec);
					_g_object_unref0 (dinfo);
					_g_object_unref0 (appinfo);
					continue;
				}
				_tmp35_ = try_exec;
				_tmp36_ = g_uri_unescape_string (_tmp35_, NULL);
				_g_free0 (try_exec);
				try_exec = _tmp36_;
				_tmp37_ = try_exec;
				_tmp38_ = g_path_get_basename (_tmp37_);
				_g_free0 (try_exec);
				try_exec = _tmp38_;
				_tmp39_ = self->priv->exec_cache;
				_tmp40_ = try_exec;
				_tmp41_ = g_strdup (_tmp40_);
				_tmp42_ = dinfo;
				_tmp43_ = g_app_info_get_id ((GAppInfo*) _tmp42_);
				_tmp44_ = g_strdup (_tmp43_);
				g_hash_table_insert (_tmp39_, _tmp41_, _tmp44_);
				_g_free0 (try_exec);
				_g_object_unref0 (dinfo);
				_g_object_unref0 (appinfo);
			}
		}
		(appinfo_collection == NULL) ? NULL : (appinfo_collection = (_g_list_free__g_object_unref0_ (appinfo_collection), NULL));
	}
}

/**
* Attempt to gain the DesktopAppInfo relating to a given window
*/
GDesktopAppInfo*
budgie_app_system_query_window (BudgieAppSystem* self,
                                WnckWindow* window)
{
	gulong xid = 0UL;
	gint64 pid = 0LL;
	gchar* cls_name = NULL;
	const gchar* _tmp0_;
	gchar* _tmp1_;
	gchar* grp_name = NULL;
	const gchar* _tmp2_;
	gchar* _tmp3_;
	gchar** checks = NULL;
	const gchar* _tmp4_;
	gchar* _tmp5_;
	const gchar* _tmp6_;
	gchar* _tmp7_;
	gchar** _tmp8_;
	gint checks_length1;
	gint _checks_size_;
	gchar** _tmp9_;
	gint _tmp9__length1;
	GHashTable* _tmp34_;
	gchar* gtk_id = NULL;
	gchar* _tmp40_;
	const gchar* _tmp41_;
	gboolean _tmp52_ = FALSE;
	const gchar* _tmp53_;
	gchar** _tmp90_;
	gint _tmp90__length1;
	GDesktopAppInfo* result;
	g_return_val_if_fail (self != NULL, NULL);
	xid = wnck_window_get_xid (window);
	pid = (gint64) wnck_window_get_pid (window);
	if (window == NULL) {
		result = NULL;
		return result;
	}
	_tmp0_ = wnck_window_get_class_instance_name (window);
	_tmp1_ = g_strdup (_tmp0_);
	cls_name = _tmp1_;
	_tmp2_ = wnck_window_get_class_group_name (window);
	_tmp3_ = g_strdup (_tmp2_);
	grp_name = _tmp3_;
	budgie_app_system_check_invalidated (self);
	_tmp4_ = cls_name;
	_tmp5_ = g_strdup (_tmp4_);
	_tmp6_ = grp_name;
	_tmp7_ = g_strdup (_tmp6_);
	_tmp8_ = g_new0 (gchar*, 2 + 1);
	_tmp8_[0] = _tmp5_;
	_tmp8_[1] = _tmp7_;
	checks = _tmp8_;
	checks_length1 = 2;
	_checks_size_ = checks_length1;
	_tmp9_ = checks;
	_tmp9__length1 = checks_length1;
	{
		gchar** check_collection = NULL;
		gint check_collection_length1 = 0;
		gint _check_collection_size_ = 0;
		gint check_it = 0;
		check_collection = _tmp9_;
		check_collection_length1 = _tmp9__length1;
		for (check_it = 0; check_it < check_collection_length1; check_it = check_it + 1) {
			gchar* _tmp10_;
			gchar* check = NULL;
			_tmp10_ = g_strdup (check_collection[check_it]);
			check = _tmp10_;
			{
				const gchar* _tmp11_;
				const gchar* _tmp12_;
				gchar* _tmp13_;
				GHashTable* _tmp14_;
				const gchar* _tmp15_;
				gchar* dname = NULL;
				const gchar* _tmp26_;
				gchar* _tmp27_;
				GHashTable* _tmp28_;
				const gchar* _tmp29_;
				_tmp11_ = check;
				if (_tmp11_ == NULL) {
					_g_free0 (check);
					continue;
				}
				_tmp12_ = check;
				_tmp13_ = g_utf8_strdown (_tmp12_, (gssize) -1);
				_g_free0 (check);
				check = _tmp13_;
				_tmp14_ = self->priv->startupids;
				_tmp15_ = check;
				if (g_hash_table_contains (_tmp14_, _tmp15_)) {
					gchar* dname = NULL;
					GHashTable* _tmp16_;
					const gchar* _tmp17_;
					gconstpointer _tmp18_;
					gchar* _tmp19_;
					GHashTable* _tmp20_;
					const gchar* _tmp21_;
					_tmp16_ = self->priv->startupids;
					_tmp17_ = check;
					_tmp18_ = g_hash_table_lookup (_tmp16_, _tmp17_);
					_tmp19_ = g_utf8_strdown ((const gchar*) _tmp18_, (gssize) -1);
					dname = _tmp19_;
					_tmp20_ = self->priv->desktops;
					_tmp21_ = dname;
					if (g_hash_table_contains (_tmp20_, _tmp21_)) {
						GHashTable* _tmp22_;
						const gchar* _tmp23_;
						gconstpointer _tmp24_;
						GDesktopAppInfo* _tmp25_;
						_tmp22_ = self->priv->desktops;
						_tmp23_ = dname;
						_tmp24_ = g_hash_table_lookup (_tmp22_, _tmp23_);
						_tmp25_ = _g_object_ref0 ((GDesktopAppInfo*) _tmp24_);
						result = _tmp25_;
						_g_free0 (dname);
						_g_free0 (check);
						checks = (_vala_array_free (checks, checks_length1, (GDestroyNotify) g_free), NULL);
						_g_free0 (grp_name);
						_g_free0 (cls_name);
						return result;
					}
					_g_free0 (dname);
				}
				_tmp26_ = check;
				_tmp27_ = g_strconcat (_tmp26_, ".desktop", NULL);
				dname = _tmp27_;
				_tmp28_ = self->priv->desktops;
				_tmp29_ = dname;
				if (g_hash_table_contains (_tmp28_, _tmp29_)) {
					GHashTable* _tmp30_;
					const gchar* _tmp31_;
					gconstpointer _tmp32_;
					GDesktopAppInfo* _tmp33_;
					_tmp30_ = self->priv->desktops;
					_tmp31_ = dname;
					_tmp32_ = g_hash_table_lookup (_tmp30_, _tmp31_);
					_tmp33_ = _g_object_ref0 ((GDesktopAppInfo*) _tmp32_);
					result = _tmp33_;
					_g_free0 (dname);
					_g_free0 (check);
					checks = (_vala_array_free (checks, checks_length1, (GDestroyNotify) g_free), NULL);
					_g_free0 (grp_name);
					_g_free0 (cls_name);
					return result;
				}
				_g_free0 (dname);
				_g_free0 (check);
			}
		}
	}
	_tmp34_ = self->priv->pid_cache;
	if (g_hash_table_contains (_tmp34_, &pid)) {
		gchar* filename = NULL;
		GHashTable* _tmp35_;
		gconstpointer _tmp36_;
		gchar* _tmp37_;
		GDesktopAppInfo* info = NULL;
		const gchar* _tmp38_;
		GDesktopAppInfo* _tmp39_;
		_tmp35_ = self->priv->pid_cache;
		_tmp36_ = g_hash_table_lookup (_tmp35_, &pid);
		_tmp37_ = g_strdup ((const gchar*) _tmp36_);
		filename = _tmp37_;
		_tmp38_ = filename;
		_tmp39_ = g_desktop_app_info_new_from_filename (_tmp38_);
		info = _tmp39_;
		result = info;
		_g_free0 (filename);
		checks = (_vala_array_free (checks, checks_length1, (GDestroyNotify) g_free), NULL);
		_g_free0 (grp_name);
		_g_free0 (cls_name);
		return result;
	}
	_tmp40_ = budgie_app_system_query_gtk_application_id (self, xid);
	gtk_id = _tmp40_;
	_tmp41_ = gtk_id;
	if (_tmp41_ != NULL) {
		const gchar* _tmp42_;
		gchar* _tmp43_;
		gchar* _tmp44_;
		gchar* _tmp45_;
		GHashTable* _tmp46_;
		const gchar* _tmp47_;
		_tmp42_ = gtk_id;
		_tmp43_ = g_utf8_strdown (_tmp42_, (gssize) -1);
		_tmp44_ = _tmp43_;
		_tmp45_ = g_strconcat (_tmp44_, ".desktop", NULL);
		_g_free0 (gtk_id);
		gtk_id = _tmp45_;
		_g_free0 (_tmp44_);
		_tmp46_ = self->priv->desktops;
		_tmp47_ = gtk_id;
		if (g_hash_table_contains (_tmp46_, _tmp47_)) {
			GHashTable* _tmp48_;
			const gchar* _tmp49_;
			gconstpointer _tmp50_;
			GDesktopAppInfo* _tmp51_;
			_tmp48_ = self->priv->desktops;
			_tmp49_ = gtk_id;
			_tmp50_ = g_hash_table_lookup (_tmp48_, _tmp49_);
			_tmp51_ = _g_object_ref0 ((GDesktopAppInfo*) _tmp50_);
			result = _tmp51_;
			_g_free0 (gtk_id);
			checks = (_vala_array_free (checks, checks_length1, (GDestroyNotify) g_free), NULL);
			_g_free0 (grp_name);
			_g_free0 (cls_name);
			return result;
		}
	}
	_tmp53_ = grp_name;
	if (_tmp53_ != NULL) {
		GHashTable* _tmp54_;
		const gchar* _tmp55_;
		gchar* _tmp56_;
		gchar* _tmp57_;
		_tmp54_ = self->priv->simpletons;
		_tmp55_ = grp_name;
		_tmp56_ = g_utf8_strdown (_tmp55_, (gssize) -1);
		_tmp57_ = _tmp56_;
		_tmp52_ = g_hash_table_contains (_tmp54_, _tmp57_);
		_g_free0 (_tmp57_);
	} else {
		_tmp52_ = FALSE;
	}
	if (_tmp52_) {
		gchar* dname = NULL;
		GHashTable* _tmp58_;
		const gchar* _tmp59_;
		gchar* _tmp60_;
		gchar* _tmp61_;
		gconstpointer _tmp62_;
		gchar* _tmp63_;
		gchar* _tmp64_;
		GHashTable* _tmp65_;
		const gchar* _tmp66_;
		_tmp58_ = self->priv->simpletons;
		_tmp59_ = grp_name;
		_tmp60_ = g_utf8_strdown (_tmp59_, (gssize) -1);
		_tmp61_ = _tmp60_;
		_tmp62_ = g_hash_table_lookup (_tmp58_, _tmp61_);
		_tmp63_ = g_strconcat ((const gchar*) _tmp62_, ".desktop", NULL);
		_tmp64_ = _tmp63_;
		_g_free0 (_tmp61_);
		dname = _tmp64_;
		_tmp65_ = self->priv->desktops;
		_tmp66_ = dname;
		if (g_hash_table_contains (_tmp65_, _tmp66_)) {
			GHashTable* _tmp67_;
			const gchar* _tmp68_;
			gconstpointer _tmp69_;
			GDesktopAppInfo* _tmp70_;
			_tmp67_ = self->priv->desktops;
			_tmp68_ = dname;
			_tmp69_ = g_hash_table_lookup (_tmp67_, _tmp68_);
			_tmp70_ = _g_object_ref0 ((GDesktopAppInfo*) _tmp69_);
			result = _tmp70_;
			_g_free0 (dname);
			_g_free0 (gtk_id);
			checks = (_vala_array_free (checks, checks_length1, (GDestroyNotify) g_free), NULL);
			_g_free0 (grp_name);
			_g_free0 (cls_name);
			return result;
		}
		_g_free0 (dname);
	} else {
		gboolean _tmp71_ = FALSE;
		const gchar* _tmp72_;
		_tmp72_ = cls_name;
		if (_tmp72_ != NULL) {
			GHashTable* _tmp73_;
			const gchar* _tmp74_;
			gchar* _tmp75_;
			gchar* _tmp76_;
			_tmp73_ = self->priv->simpletons;
			_tmp74_ = cls_name;
			_tmp75_ = g_utf8_strdown (_tmp74_, (gssize) -1);
			_tmp76_ = _tmp75_;
			_tmp71_ = g_hash_table_contains (_tmp73_, _tmp76_);
			_g_free0 (_tmp76_);
		} else {
			_tmp71_ = FALSE;
		}
		if (_tmp71_) {
			gchar* dname = NULL;
			GHashTable* _tmp77_;
			const gchar* _tmp78_;
			gchar* _tmp79_;
			gchar* _tmp80_;
			gconstpointer _tmp81_;
			gchar* _tmp82_;
			gchar* _tmp83_;
			GHashTable* _tmp84_;
			const gchar* _tmp85_;
			_tmp77_ = self->priv->simpletons;
			_tmp78_ = cls_name;
			_tmp79_ = g_utf8_strdown (_tmp78_, (gssize) -1);
			_tmp80_ = _tmp79_;
			_tmp81_ = g_hash_table_lookup (_tmp77_, _tmp80_);
			_tmp82_ = g_strconcat ((const gchar*) _tmp81_, ".desktop", NULL);
			_tmp83_ = _tmp82_;
			_g_free0 (_tmp80_);
			dname = _tmp83_;
			_tmp84_ = self->priv->desktops;
			_tmp85_ = dname;
			if (g_hash_table_contains (_tmp84_, _tmp85_)) {
				GHashTable* _tmp86_;
				const gchar* _tmp87_;
				gconstpointer _tmp88_;
				GDesktopAppInfo* _tmp89_;
				_tmp86_ = self->priv->desktops;
				_tmp87_ = dname;
				_tmp88_ = g_hash_table_lookup (_tmp86_, _tmp87_);
				_tmp89_ = _g_object_ref0 ((GDesktopAppInfo*) _tmp88_);
				result = _tmp89_;
				_g_free0 (dname);
				_g_free0 (gtk_id);
				checks = (_vala_array_free (checks, checks_length1, (GDestroyNotify) g_free), NULL);
				_g_free0 (grp_name);
				_g_free0 (cls_name);
				return result;
			}
			_g_free0 (dname);
		}
	}
	_tmp90_ = checks;
	_tmp90__length1 = checks_length1;
	{
		gchar** check_collection = NULL;
		gint check_collection_length1 = 0;
		gint _check_collection_size_ = 0;
		gint check_it = 0;
		check_collection = _tmp90_;
		check_collection_length1 = _tmp90__length1;
		for (check_it = 0; check_it < check_collection_length1; check_it = check_it + 1) {
			gchar* _tmp91_;
			gchar* check = NULL;
			_tmp91_ = g_strdup (check_collection[check_it]);
			check = _tmp91_;
			{
				const gchar* _tmp92_;
				const gchar* _tmp93_;
				gchar* _tmp94_;
				gchar* id = NULL;
				GHashTable* _tmp95_;
				const gchar* _tmp96_;
				gconstpointer _tmp97_;
				gchar* _tmp98_;
				const gchar* _tmp99_;
				GDesktopAppInfo* a = NULL;
				GHashTable* _tmp100_;
				const gchar* _tmp101_;
				gconstpointer _tmp102_;
				GDesktopAppInfo* _tmp103_;
				_tmp92_ = check;
				if (_tmp92_ == NULL) {
					_g_free0 (check);
					continue;
				}
				_tmp93_ = check;
				_tmp94_ = g_utf8_strdown (_tmp93_, (gssize) -1);
				_g_free0 (check);
				check = _tmp94_;
				_tmp95_ = self->priv->exec_cache;
				_tmp96_ = check;
				_tmp97_ = g_hash_table_lookup (_tmp95_, _tmp96_);
				_tmp98_ = g_strdup ((const gchar*) _tmp97_);
				id = _tmp98_;
				_tmp99_ = id;
				if (_tmp99_ == NULL) {
					_g_free0 (id);
					_g_free0 (check);
					continue;
				}
				_tmp100_ = self->priv->desktops;
				_tmp101_ = id;
				_tmp102_ = g_hash_table_lookup (_tmp100_, _tmp101_);
				a = (GDesktopAppInfo*) _tmp102_;
				_tmp103_ = a;
				if (_tmp103_ != NULL) {
					GDesktopAppInfo* _tmp104_;
					GDesktopAppInfo* _tmp105_;
					_tmp104_ = a;
					_tmp105_ = _g_object_ref0 (_tmp104_);
					result = _tmp105_;
					_g_free0 (id);
					_g_free0 (check);
					_g_free0 (gtk_id);
					checks = (_vala_array_free (checks, checks_length1, (GDestroyNotify) g_free), NULL);
					_g_free0 (grp_name);
					_g_free0 (cls_name);
					return result;
				}
				_g_free0 (id);
				_g_free0 (check);
			}
		}
	}
	result = NULL;
	_g_free0 (gtk_id);
	checks = (_vala_array_free (checks, checks_length1, (GDestroyNotify) g_free), NULL);
	_g_free0 (grp_name);
	_g_free0 (cls_name);
	return result;
}

/**
* Return a plain STRING value for the given window id
*/
gchar*
budgie_app_system_query_atom_string (BudgieAppSystem* self,
                                     gulong xid,
                                     GdkAtom atom)
{
	gchar* _tmp0_;
	gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = budgie_app_system_query_atom_string_internal (self, xid, atom, FALSE);
	result = _tmp0_;
	return result;
}

/**
* Return a UTF8_STRING value for the given window id
*/
gchar*
budgie_app_system_query_atom_string_utf8 (BudgieAppSystem* self,
                                          gulong xid,
                                          GdkAtom atom)
{
	gchar* _tmp0_;
	gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = budgie_app_system_query_atom_string_internal (self, xid, atom, TRUE);
	result = _tmp0_;
	return result;
}

static gchar*
budgie_app_system_query_atom_string_internal (BudgieAppSystem* self,
                                              gulong xid,
                                              GdkAtom atom,
                                              gboolean utf8)
{
	guint8* data = NULL;
	gint data_length1;
	gint _data_size_;
	GdkAtom a_type = (GdkAtom) 0U;
	gint a_f = 0;
	GdkX11Display* display = NULL;
	GdkDisplay* _tmp0_;
	GdkX11Display* _tmp1_;
	GdkAtom req_type = (GdkAtom) 0U;
	GdkWindow* foreign = NULL;
	GdkX11Display* _tmp2_;
	GdkX11Window* _tmp3_;
	GdkWindow* _tmp4_;
	GdkWindow* _tmp5_;
	GdkAtom _tmp6_ = (GdkAtom) 0U;
	gint _tmp7_ = 0;
	guint8* _tmp8_ = NULL;
	gint _tmp9_ = 0;
	const gchar* _tmp10_ = NULL;
	guint8* _tmp11_;
	gint _tmp11__length1;
	gchar* _tmp13_;
	gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	data = NULL;
	data_length1 = 0;
	_data_size_ = data_length1;
	_tmp0_ = gdk_display_get_default ();
	_tmp1_ = _g_object_ref0 (G_TYPE_CHECK_INSTANCE_CAST (_tmp0_, gdk_x11_display_get_type (), GdkX11Display));
	display = _tmp1_;
	if (utf8) {
		req_type = gdk_atom_intern ("UTF8_STRING", FALSE);
	} else {
		req_type = gdk_atom_intern ("STRING", FALSE);
	}
	_tmp2_ = display;
	_tmp3_ = (GdkX11Window*) gdk_x11_window_foreign_new_for_display (_tmp2_, (Window) xid);
	foreign = (GdkWindow*) _tmp3_;
	_tmp4_ = foreign;
	if (_tmp4_ == NULL) {
		result = NULL;
		_g_object_unref0 (foreign);
		_g_object_unref0 (display);
		data = (g_free (data), NULL);
		return result;
	}
	_tmp5_ = foreign;
	gdk_property_get (_tmp5_, atom, req_type, (gulong) 0, (gulong) G_MAXLONG, 0, &_tmp6_, &_tmp7_, &_tmp9_, &_tmp8_);
	a_type = _tmp6_;
	a_f = _tmp7_;
	data = (g_free (data), NULL);
	data = _tmp8_;
	data_length1 = _tmp9_;
	_data_size_ = data_length1;
	_tmp11_ = data;
	_tmp11__length1 = data_length1;
	if (_tmp11_ != NULL) {
		guint8* _tmp12_;
		gint _tmp12__length1;
		_tmp12_ = data;
		_tmp12__length1 = data_length1;
		_tmp10_ = (const gchar*) _tmp12_;
	} else {
		_tmp10_ = NULL;
	}
	_tmp13_ = g_strdup (_tmp10_);
	result = _tmp13_;
	_g_object_unref0 (foreign);
	_g_object_unref0 (display);
	data = (g_free (data), NULL);
	return result;
}

/**
* Obtain the GtkApplication id for a given window
*/
gchar*
budgie_app_system_query_gtk_application_id (BudgieAppSystem* self,
                                            gulong window)
{
	gchar* _tmp0_;
	gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = budgie_app_system_query_atom_string_utf8 (self, window, gdk_atom_intern ("_GTK_APPLICATION_ID", FALSE));
	result = _tmp0_;
	return result;
}

static void
budgie_app_system_class_init (BudgieAppSystemClass * klass,
                              gpointer klass_data)
{
	budgie_app_system_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &BudgieAppSystem_private_offset);
	G_OBJECT_CLASS (klass)->finalize = budgie_app_system_finalize;
	budgie_app_system_signals[BUDGIE_APP_SYSTEM_APP_LAUNCHED_SIGNAL] = g_signal_new ("app-launched", BUDGIE_TYPE_APP_SYSTEM, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
}

static void
budgie_app_system_instance_init (BudgieAppSystem * self,
                                 gpointer klass)
{
	self->priv = budgie_app_system_get_instance_private (self);
	self->priv->startupids = NULL;
	self->priv->simpletons = NULL;
	self->priv->desktops = NULL;
	self->priv->exec_cache = NULL;
	self->priv->pid_cache = NULL;
	self->priv->monitor = NULL;
	g_rec_mutex_init (&self->priv->__lock_invalidated);
	self->priv->invalidated = FALSE;
}

static void
budgie_app_system_finalize (GObject * obj)
{
	BudgieAppSystem * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, BUDGIE_TYPE_APP_SYSTEM, BudgieAppSystem);
	_g_hash_table_unref0 (self->priv->startupids);
	_g_hash_table_unref0 (self->priv->simpletons);
	_g_hash_table_unref0 (self->priv->desktops);
	_g_hash_table_unref0 (self->priv->exec_cache);
	_g_hash_table_unref0 (self->priv->pid_cache);
	_g_object_unref0 (self->priv->monitor);
	g_rec_mutex_clear (&self->priv->__lock_invalidated);
	_g_object_unref0 (self->priv->bus);
	G_OBJECT_CLASS (budgie_app_system_parent_class)->finalize (obj);
}

static GType
budgie_app_system_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (BudgieAppSystemClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) budgie_app_system_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (BudgieAppSystem), 0, (GInstanceInitFunc) budgie_app_system_instance_init, NULL };
	GType budgie_app_system_type_id;
	budgie_app_system_type_id = g_type_register_static (G_TYPE_OBJECT, "BudgieAppSystem", &g_define_type_info, 0);
	BudgieAppSystem_private_offset = g_type_add_instance_private (budgie_app_system_type_id, sizeof (BudgieAppSystemPrivate));
	return budgie_app_system_type_id;
}

GType
budgie_app_system_get_type (void)
{
	static volatile gsize budgie_app_system_type_id__once = 0;
	if (g_once_init_enter (&budgie_app_system_type_id__once)) {
		GType budgie_app_system_type_id;
		budgie_app_system_type_id = budgie_app_system_get_type_once ();
		g_once_init_leave (&budgie_app_system_type_id__once, budgie_app_system_type_id);
	}
	return budgie_app_system_type_id__once;
}

static void
_vala_array_destroy (gpointer array,
                     gssize array_length,
                     GDestroyNotify destroy_func)
{
	if ((array != NULL) && (destroy_func != NULL)) {
		gssize i;
		for (i = 0; i < array_length; i = i + 1) {
			if (((gpointer*) array)[i] != NULL) {
				destroy_func (((gpointer*) array)[i]);
			}
		}
	}
}

static void
_vala_array_free (gpointer array,
                  gssize array_length,
                  GDestroyNotify destroy_func)
{
	_vala_array_destroy (array, array_length, destroy_func);
	g_free (array);
}

