/* Set monitor index this object belongs to and to monitor */
static void _xfdashboard_window_tracker_monitor_set_index(XfdashboardWindowTrackerMonitor *self, gint inIndex)
{
	XfdashboardWindowTrackerMonitorPrivate		*priv;

	g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_MONITOR(self));
	g_return_if_fail(inIndex>=0);
	g_return_if_fail(inIndex<gdk_screen_get_n_monitors(self->priv->screen));

	priv=self->priv;

	/* Freeze notification */
	g_object_freeze_notify(G_OBJECT(self));

	/* Set value if changed */
	if(priv->monitorIndex!=inIndex)
	{
		/* Set value */
		priv->monitorIndex=inIndex;

		/* Update primary monitor flag */
		_xfdashboard_window_tracker_monitor_update_primary(self);

		/* Update geometry of monitor */
		_xfdashboard_window_tracker_monitor_update_geometry(self);
	}

	/* Thaw notification */
	g_object_thaw_notify(G_OBJECT(self));
}
/* Set primary monitor flag */
static void _xfdashboard_window_tracker_monitor_update_primary(XfdashboardWindowTrackerMonitor *self)
{
	XfdashboardWindowTrackerMonitorPrivate		*priv;
	gint										primaryIndex;
	gboolean									isPrimary;

	g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_MONITOR(self));

	priv=self->priv;

	/* Get primary flag */
	primaryIndex=gdk_screen_get_primary_monitor(priv->screen);
	if(primaryIndex==priv->monitorIndex) isPrimary=TRUE;
		else isPrimary=FALSE;

	/* Set value if changed */
	if(priv->isPrimary!=isPrimary)
	{
		g_debug("Monitor %d changes primary state from %s to %s",
					priv->monitorIndex,
					isPrimary ? "yes" : "no",
					priv->isPrimary ? "yes" : "no");

		/* Set value */
		priv->isPrimary=isPrimary;

		/* Notify about property change */
		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardWindowTrackerMonitorProperties[PROP_IS_PRIMARY]);

		/* Emit signal */
		g_signal_emit(self, XfdashboardWindowTrackerMonitorSignals[SIGNAL_PRIMARY_CHANGED], 0);
	}
}
/* Update monitor geometry */
static void _xfdashboard_window_tracker_monitor_update_geometry(XfdashboardWindowTrackerMonitor *self)
{
	XfdashboardWindowTrackerMonitorPrivate		*priv;
	GdkRectangle								geometry;

	g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_MONITOR(self));

	priv=self->priv;

	/* Check if monitor is valid */
	if(priv->monitorIndex>=gdk_screen_get_n_monitors(priv->screen)) return;

	/* Get monitor geometry */
	gdk_screen_get_monitor_geometry(priv->screen, priv->monitorIndex, &geometry);

	/* Set value if changed */
	if(geometry.x!=priv->geometry.x ||
		geometry.y!=priv->geometry.y ||
		geometry.width!=priv->geometry.width ||
		geometry.height!=priv->geometry.height)
	{
		/* Set value */
		priv->geometry.x=geometry.x;
		priv->geometry.y=geometry.y;
		priv->geometry.width=geometry.width;
		priv->geometry.height=geometry.height;

		/* Emit signal */
		g_signal_emit(self, XfdashboardWindowTrackerMonitorSignals[SIGNAL_GEOMETRY_CHANGED], 0);
		g_debug("Monitor %d moved to %d,%d and resized to %dx%d",
					priv->monitorIndex,
					priv->geometry.x, priv->geometry.y,
					priv->geometry.width, priv->geometry.height);
	}
}
/* Check if both monitors are the same */
gboolean xfdashboard_window_tracker_monitor_is_equal(XfdashboardWindowTrackerMonitor *inLeft,
														XfdashboardWindowTrackerMonitor *inRight)
{
	gint			leftIndex, rightIndex;

	g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_MONITOR(inLeft), FALSE);
	g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_MONITOR(inRight), FALSE);

	/* Check if both are the same workspace or refer to same one */
	leftIndex=xfdashboard_window_tracker_monitor_get_number(inLeft);
	rightIndex=xfdashboard_window_tracker_monitor_get_number(inRight);
	if(inLeft==inRight || leftIndex==rightIndex) return(TRUE);

	/* If we get here then they cannot be considered equal */
	return(FALSE);
}
/* Number of monitors, primary monitor or size of any monitor changed */
static void _xfdashboard_window_tracker_monitor_on_monitors_changed(XfdashboardWindowTrackerMonitor *self,
																	gpointer inUserData)
{
	g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_MONITOR(self));
	g_return_if_fail(GDK_IS_SCREEN(inUserData));

	/* Update primary monitor flag */
	_xfdashboard_window_tracker_monitor_update_primary(self);

	/* Update geometry of monitor */
	_xfdashboard_window_tracker_monitor_update_geometry(self);
}
void xfdashboard_stage_interface_set_monitor(XfdashboardStageInterface *self, XfdashboardWindowTrackerMonitor *inMonitor)
{
	XfdashboardStageInterfacePrivate	*priv;

	g_return_if_fail(XFDASHBOARD_IS_STAGE_INTERFACE(self));
	g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_MONITOR(inMonitor));

	priv=self->priv;

	/* Set value if changed */
	if(priv->monitor!=inMonitor)
	{
		/* Set value */
		if(priv->monitor)
		{
			if(priv->geometryChangedID)
			{
				g_signal_handler_disconnect(priv->monitor, priv->geometryChangedID);
				priv->geometryChangedID=0;
			}

			if(priv->primaryChangedID)
			{
				g_signal_handler_disconnect(priv->monitor, priv->primaryChangedID);
				priv->primaryChangedID=0;
			}

			g_object_unref(priv->monitor);
			priv->monitor=NULL;
		}

		priv->monitor=XFDASHBOARD_WINDOW_TRACKER_MONITOR(g_object_ref(inMonitor));

		/* Connect signals */
		priv->geometryChangedID=g_signal_connect_swapped(priv->monitor,
															"geometry-changed",
															G_CALLBACK(_xfdashboard_stage_interface_on_geometry_changed),
															self);
		priv->primaryChangedID=g_signal_connect_swapped(priv->monitor,
															"primary-changed",
															G_CALLBACK(_xfdashboard_stage_interface_on_primary_changed),
															self);

		/* Resize actor to new monitor */
		_xfdashboard_stage_interface_on_geometry_changed(self, priv->monitor);

		/* Update actor from primary state */
		_xfdashboard_stage_interface_on_primary_changed(self, priv->monitor);

		/* Notify about property change */
		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardStageInterfaceProperties[PROP_MONITOR]);
	}
}
void xfdashboard_window_tracker_monitor_get_geometry(XfdashboardWindowTrackerMonitor *self,
														gint *outX,
														gint *outY,
														gint *outWidth,
														gint *outHeight)
{
	XfdashboardWindowTrackerMonitorPrivate		*priv;

	g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_MONITOR(self));

	priv=self->priv;

	/* Set position and size of monitor */
	if(outX) *outX=priv->geometry.x;
	if(outY) *outY=priv->geometry.y;
	if(outWidth) *outWidth=priv->geometry.width;
	if(outHeight) *outHeight=priv->geometry.height;
}
/* Check if requested position is inside monitor's geometry */
gboolean xfdashboard_window_tracker_monitor_contains(XfdashboardWindowTrackerMonitor *self,
														gint inX,
														gint inY)
{
	XfdashboardWindowTrackerMonitorPrivate		*priv;

	g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_MONITOR(self), FALSE);

	priv=self->priv;

	/* Check if requested position is inside monitor's geometry */
	if(inX>=priv->geometry.x &&
		inX<(priv->geometry.x+priv->geometry.width) &&
		inY>=priv->geometry.y &&
		inY<(priv->geometry.y+priv->geometry.height))
	{
		return(TRUE);
	}

	/* If we get here the requested position is not inside this monitor's geometry,
	 * so return FALSE.
	 */
	return(FALSE);
}
gint xfdashboard_window_tracker_monitor_get_height(XfdashboardWindowTrackerMonitor *self)
{
	g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_MONITOR(self), 0);

	return(self->priv->geometry.height);
}
/* Determine if monitor is primary one */
gboolean xfdashboard_window_tracker_monitor_is_primary(XfdashboardWindowTrackerMonitor *self)
{
	g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_MONITOR(self), FALSE);

	return(self->priv->isPrimary);
}
/* Get monitor index */
gint xfdashboard_window_tracker_monitor_get_number(XfdashboardWindowTrackerMonitor *self)
{
	g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_MONITOR(self), 0);

	return(self->priv->monitorIndex);
}