4 * Purple is the legal property of its developers, whose names are too numerous
5 * to list here. Please refer to the COPYRIGHT file distributed with this
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
25 #include "connection.h"
27 #include "eventloop.h"
31 #include "savedstatuses.h"
36 PURPLE_IDLE_NOT_AWAY
= 0,
37 PURPLE_IDLE_AUTO_AWAY
,
38 PURPLE_IDLE_AWAY_BUT_NOT_AUTO_AWAY
40 } PurpleAutoAwayState
;
42 static PurpleIdleUiOps
*idle_ui_ops
= NULL
;
45 * This is needed for the I'dle Mak'er plugin to work correctly. We
46 * use it to determine if we're the ones who set our accounts idle
47 * or if someone else did it (the I'dle Mak'er plugin, for example).
48 * Basically we just keep track of which accounts were set idle by us,
49 * and then we'll only set these specific accounts unidle when the
52 static GList
*idled_accts
= NULL
;
54 static guint idle_timer
= 0;
56 static time_t last_active_time
= 0;
59 set_account_idle(PurpleAccount
*account
, int time_idle
)
61 PurplePresence
*presence
;
63 presence
= purple_account_get_presence(account
);
65 if (purple_presence_is_idle(presence
))
66 /* This account is already idle! */
69 purple_debug_info("idle", "Setting %s idle %d seconds\n",
70 purple_account_get_username(account
), time_idle
);
71 purple_presence_set_idle(presence
, TRUE
, time(NULL
) - time_idle
);
72 idled_accts
= g_list_prepend(idled_accts
, account
);
76 set_account_unidle(PurpleAccount
*account
)
78 PurplePresence
*presence
;
80 presence
= purple_account_get_presence(account
);
82 idled_accts
= g_list_remove(idled_accts
, account
);
84 if (!purple_presence_is_idle(presence
))
85 /* This account is already unidle! */
88 purple_debug_info("idle", "Setting %s unidle\n",
89 purple_account_get_username(account
));
90 purple_presence_set_idle(presence
, FALSE
, 0);
94 static gboolean no_away
= FALSE
;
95 static gint time_until_next_idle_event
;
97 * This function should be called when you think your idle state
98 * may have changed. Maybe you're over the 10-minute mark and
99 * Purple should start reporting idle time to the server. Maybe
100 * you've returned from being idle. Maybe your auto-away message
103 * There is no harm to calling this many many times, other than
104 * it will be kinda slow. This is called by a timer set when
105 * Purple starts. It is also called when you send an IM, a chat, etc.
107 * This function has 3 sections.
108 * 1. Get your idle time. It will query XScreenSaver or Windows
109 * or use the Purple idle time. Whatever.
110 * 2. Set or unset your auto-away message.
111 * 3. Report your current idle time to the IM server.
119 const gchar
*idle_reporting
;
120 gboolean report_idle
= TRUE
;
121 gint away_seconds
= 0;
122 gint idle_recheck_interval
= 0;
123 gint idle_poll_seconds
= purple_prefs_get_int("/purple/away/mins_before_away") * 60;
124 purple_signal_emit(purple_blist_get_handle(), "update-idle");
126 idle_reporting
= purple_prefs_get_string("/purple/away/idle_reporting");
127 auto_away
= purple_prefs_get_bool("/purple/away/away_when_idle");
129 if (purple_strequal(idle_reporting
, "system") &&
130 (idle_ui_ops
!= NULL
) && (idle_ui_ops
->get_time_idle
!= NULL
))
132 /* Use system idle time (mouse or keyboard movement, etc.) */
133 time_idle
= idle_ui_ops
->get_time_idle();
134 idle_recheck_interval
= 1;
136 else if (purple_strequal(idle_reporting
, "purple"))
138 /* Use 'Purple idle' */
139 time_idle
= time(NULL
) - last_active_time
;
140 idle_recheck_interval
= 0;
144 /* Don't report idle time */
148 /* If we're not reporting idle, we can still do auto-away.
149 * First try "system" and if that isn't possible, use "purple" */
152 if ((idle_ui_ops
!= NULL
) && (idle_ui_ops
->get_time_idle
!= NULL
))
154 time_idle
= idle_ui_ops
->get_time_idle();
155 idle_recheck_interval
= 1;
159 time_idle
= time(NULL
) - last_active_time
;
160 idle_recheck_interval
= 0;
168 purple_savedstatus_set_idleaway(FALSE
);
170 time_until_next_idle_event
= 0;
175 time_until_next_idle_event
= idle_poll_seconds
- time_idle
;
176 if (time_until_next_idle_event
< 0)
178 /* If we're already idle, check again as appropriate. */
179 time_until_next_idle_event
= idle_recheck_interval
;
182 if (auto_away
|| !no_away
)
183 away_seconds
= 60 * purple_prefs_get_int("/purple/away/mins_before_away");
185 if (auto_away
&& time_idle
> away_seconds
)
187 purple_savedstatus_set_idleaway(TRUE
);
190 else if (purple_savedstatus_is_idleaway() && time_idle
< away_seconds
)
192 purple_savedstatus_set_idleaway(FALSE
);
193 if (time_until_next_idle_event
== 0 || (away_seconds
- time_idle
) < time_until_next_idle_event
)
194 time_until_next_idle_event
= away_seconds
- time_idle
;
197 /* Idle reporting stuff */
198 if (report_idle
&& (time_idle
>= idle_poll_seconds
))
201 for (l
= purple_connections_get_all(); l
!= NULL
; l
= l
->next
)
203 PurpleConnection
*gc
= l
->data
;
204 set_account_idle(purple_connection_get_account(gc
), time_idle
);
207 else if (!report_idle
|| (time_idle
< idle_poll_seconds
))
209 while (idled_accts
!= NULL
)
210 set_account_unidle(idled_accts
->data
);
216 * Check idle and set the timer to fire at the next idle-worth event
219 check_idleness_timer(void)
222 if (time_until_next_idle_event
== 0)
226 /* +1 for the boundary,
227 * +1 more for g_timeout_add_seconds rounding. */
228 idle_timer
= purple_timeout_add_seconds(time_until_next_idle_event
+ 2, (GSourceFunc
)check_idleness_timer
, NULL
);
234 im_msg_sent_cb(PurpleAccount
*account
, const char *receiver
,
235 const char *message
, void *data
)
237 /* Check our idle time after an IM is sent */
242 signing_on_cb(PurpleConnection
*gc
, void *data
)
244 /* When signing on a new account, check if the account should be idle */
249 signing_off_cb(PurpleConnection
*gc
, void *data
)
251 PurpleAccount
*account
;
253 account
= purple_connection_get_account(gc
);
254 set_account_unidle(account
);
258 idle_reporting_cb(const char *name
, PurplePrefType type
, gconstpointer val
, gpointer data
)
261 purple_timeout_remove(idle_timer
);
263 check_idleness_timer();
269 time(&last_active_time
);
273 purple_timeout_remove(idle_timer
);
275 check_idleness_timer();
280 purple_idle_set(time_t time
)
282 last_active_time
= time
;
286 purple_idle_set_ui_ops(PurpleIdleUiOps
*ops
)
292 purple_idle_get_ui_ops(void)
298 purple_idle_get_handle(void)
305 static gboolean
_do_purple_idle_touch_cb(gpointer data
)
307 int idle_poll_minutes
= purple_prefs_get_int("/purple/away/mins_before_away");
309 /* +1 more for g_timeout_add_seconds rounding. */
310 idle_timer
= purple_timeout_add_seconds((idle_poll_minutes
* 60) + 2, (GSourceFunc
)check_idleness_timer
, NULL
);
321 purple_signal_connect(purple_conversations_get_handle(), "sent-im-msg",
322 purple_idle_get_handle(),
323 PURPLE_CALLBACK(im_msg_sent_cb
), NULL
);
324 purple_signal_connect(purple_connections_get_handle(), "signing-on",
325 purple_idle_get_handle(),
326 PURPLE_CALLBACK(signing_on_cb
), NULL
);
327 purple_signal_connect(purple_connections_get_handle(), "signing-off",
328 purple_idle_get_handle(),
329 PURPLE_CALLBACK(signing_off_cb
), NULL
);
331 purple_prefs_connect_callback(purple_idle_get_handle(), "/purple/away/idle_reporting",
332 idle_reporting_cb
, NULL
);
334 /* Initialize the idleness asynchronously so it doesn't check idleness,
335 * and potentially try to change the status before the UI is initialized */
336 purple_timeout_add(0, _do_purple_idle_touch_cb
, NULL
);
343 purple_signals_disconnect_by_handle(purple_idle_get_handle());
344 purple_prefs_disconnect_by_handle(purple_idle_get_handle());
346 /* Remove the idle timer */
348 purple_timeout_remove(idle_timer
);