diff libpurple/idle.c @ 17977:f71bd7e56389

propagate from branch 'im.pidgin.pidgin' (head b438ea0760758dc547f95d62892455f50ee4c4f1) to branch 'im.pidgin.soc.2007.remotelogging' (head 7e683fd40634aa3eb22dcf25cbd25c8959d76662)
author Michael Shkutkov <mshkutkov@soc.pidgin.im>
date Sat, 09 Jun 2007 12:01:29 +0000
parents ac504f643092
children 81d42bfe31fa 2f9eabdc6011
line wrap: on
line diff
--- a/libpurple/idle.c	Sun Apr 22 11:11:49 2007 +0000
+++ b/libpurple/idle.c	Sat Jun 09 12:01:29 2007 +0000
@@ -31,7 +31,6 @@
 #include "signals.h"
 
 #define IDLEMARK 600 /* 10 minutes! */
-#define IDLE_CHECK_INTERVAL 5 /* 5 seconds */
 
 typedef enum
 {
@@ -92,6 +91,9 @@
 	purple_presence_set_idle(presence, FALSE, 0);
 }
 
+
+static gboolean no_away = FALSE;
+static gint time_until_next_idle_event;
 /*
  * This function should be called when you think your idle state
  * may have changed.  Maybe you're over the 10-minute mark and
@@ -100,9 +102,8 @@
  * should be set.
  *
  * There is no harm to calling this many many times, other than
- * it will be kinda slow.  This is called every 5 seconds by a
- * timer set when Purple starts.  It is also called when
- * you send an IM, a chat, etc.
+ * it will be kinda slow.  This is called by a timer set when
+ * Purple starts.  It is also called when you send an IM, a chat, etc.
  *
  * This function has 3 sections.
  * 1. Get your idle time.  It will query XScreenSaver or Windows
@@ -110,62 +111,95 @@
  * 2. Set or unset your auto-away message.
  * 3. Report your current idle time to the IM server.
  */
-static gint
-check_idleness()
+
+static void
+check_idleness(void)
 {
 	time_t time_idle;
 	gboolean auto_away;
 	const gchar *idle_reporting;
-	gboolean report_idle;
-	GList *l;
+	gboolean report_idle = TRUE;
+	gint away_seconds = 0;
+	gint idle_recheck_interval = 0;
 
 	purple_signal_emit(purple_blist_get_handle(), "update-idle");
 
-	idle_reporting = purple_prefs_get_string("/core/away/idle_reporting");
-	report_idle = TRUE;
+	idle_reporting = purple_prefs_get_string("/purple/away/idle_reporting");
+	auto_away = purple_prefs_get_bool("/purple/away/away_when_idle");
+
 	if (!strcmp(idle_reporting, "system") &&
 		(idle_ui_ops != NULL) && (idle_ui_ops->get_time_idle != NULL))
 	{
 		/* Use system idle time (mouse or keyboard movement, etc.) */
 		time_idle = idle_ui_ops->get_time_idle();
+		idle_recheck_interval = 60;
 	}
 	else if (!strcmp(idle_reporting, "purple"))
 	{
 		/* Use 'Purple idle' */
 		time_idle = time(NULL) - last_active_time;
+		idle_recheck_interval = 0;
 	}
 	else
 	{
 		/* Don't report idle time */
 		time_idle = 0;
 		report_idle = FALSE;
+
+		/* If we're not reporting idle, we can still do auto-away.
+		 * First try "system" and if that isn't possible, use "purple" */
+		if (auto_away)
+		{
+			if ((idle_ui_ops != NULL) && (idle_ui_ops->get_time_idle != NULL))
+			{
+				time_idle = idle_ui_ops->get_time_idle();
+				idle_recheck_interval = 60;
+			}
+			else
+			{
+				time_idle = time(NULL) - last_active_time;
+				idle_recheck_interval = 0;
+			}
+		}
+		else
+		{
+			if (!no_away)
+			{
+				purple_savedstatus_set_idleaway(FALSE);
+				no_away = TRUE;
+			}
+			time_until_next_idle_event = 0;
+			return;
+		}
 	}
 
-	/* Auto-away stuff */
-	auto_away = purple_prefs_get_bool("/core/away/away_when_idle");
-
-	/* If we're not reporting idle, we can still do auto-away.
-	 * First try "system" and if that isn't possible, use "purple" */
-	if (!report_idle && auto_away) {
-		if ((idle_ui_ops != NULL) && (idle_ui_ops->get_time_idle != NULL))
-			time_idle = idle_ui_ops->get_time_idle();
-		else
-			time_idle = time(NULL) - last_active_time;
+	time_until_next_idle_event = IDLEMARK - time_idle;
+	if (time_until_next_idle_event < 0)
+	{
+		/* If we're already idle, check again as appropriate. */
+		time_until_next_idle_event = idle_recheck_interval;
 	}
 
-	if (auto_away &&
-		(time_idle > (60 * purple_prefs_get_int("/core/away/mins_before_away"))))
+	if (auto_away || !no_away)
+		away_seconds = 60 * purple_prefs_get_int("/purple/away/mins_before_away");
+
+	if (auto_away && time_idle > away_seconds)
 	{
 		purple_savedstatus_set_idleaway(TRUE);
+		no_away = FALSE;
 	}
-	else if (time_idle < 60 * purple_prefs_get_int("/core/away/mins_before_away"))
+	else if (!no_away && time_idle < away_seconds)
 	{
+		no_away = TRUE;
 		purple_savedstatus_set_idleaway(FALSE);
+		if (time_until_next_idle_event == 0 || (away_seconds - time_idle) < time_until_next_idle_event)
+			time_until_next_idle_event = away_seconds - time_idle;
 	}
 
 	/* Idle reporting stuff */
 	if (report_idle && (time_idle >= IDLEMARK))
 	{
+		GList *l;
 		for (l = purple_connections_get_all(); l != NULL; l = l->next)
 		{
 			PurpleConnection *gc = l->data;
@@ -177,8 +211,21 @@
 		while (idled_accts != NULL)
 			set_account_unidle(idled_accts->data);
 	}
+}
 
-	return TRUE;
+
+/*
+ * Check idle and set the timer to fire at the next idle-worth event 
+ */
+static gint
+check_idleness_timer()
+{
+	check_idleness();
+	if (time_until_next_idle_event == 0)
+		idle_timer = 0;
+	else
+		idle_timer = purple_timeout_add(1000 * (time_until_next_idle_event + 1), check_idleness_timer, NULL);
+	return FALSE;
 }
 
 static void
@@ -205,10 +252,26 @@
 	set_account_unidle(account);
 }
 
+static void
+idle_reporting_cb(const char *name, PurplePrefType type, gconstpointer val, gpointer data)
+{
+	if (idle_timer)
+		purple_timeout_remove(idle_timer);
+	idle_timer = 0;
+	check_idleness_timer();
+}
+
 void
 purple_idle_touch()
 {
 	time(&last_active_time);
+	if (!no_away)
+	{
+		if (idle_timer)
+			purple_timeout_remove(idle_timer);
+		idle_timer = 0;
+		check_idleness_timer();
+	}
 }
 
 void
@@ -241,7 +304,7 @@
 purple_idle_init()
 {
 	/* Add the timer to check if we're idle */
-	idle_timer = purple_timeout_add(IDLE_CHECK_INTERVAL * 1000, check_idleness, NULL);
+	idle_timer = purple_timeout_add(1000 * (IDLEMARK + 1), check_idleness_timer, NULL);
 
 	purple_signal_connect(purple_conversations_get_handle(), "sent-im-msg",
 						purple_idle_get_handle(),
@@ -253,6 +316,9 @@
 						purple_idle_get_handle(),
 						PURPLE_CALLBACK(signing_off_cb), NULL);
 
+	purple_prefs_connect_callback(purple_idle_get_handle(), "/purple/away/idle_reporting",
+	                              idle_reporting_cb, NULL);
+
 	purple_idle_touch();
 }
 
@@ -260,6 +326,7 @@
 purple_idle_uninit()
 {
 	purple_signals_disconnect_by_handle(purple_idle_get_handle());
+	purple_prefs_disconnect_by_handle(purple_idle_get_handle());
 
 	/* Remove the idle timer */
 	if (idle_timer > 0)