comparison src/gtkidle.c @ 11907:d2db6426c88a

[gaim-migrate @ 14198] sf patch #1342817, from Evan Schoenberg "As discussed in #gaim, this patch removes idle.c and replaces it with gtkidle.c and gtkidle.h. The attached diff removes the idle management from its various hiding places in connection.c, server.c, and gaim.h. The plugins Changelog.API is appropriately updated. The new gtkidle files are attached; idle.c should be removed from CVS." committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Sun, 30 Oct 2005 23:00:47 +0000
parents
children 73777ad45562
comparison
equal deleted inserted replaced
11906:8913546c6a4e 11907:d2db6426c88a
1 /*
2 * gaim
3 *
4 * Gaim 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
6 * source distribution.
7 *
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.
12 *
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.
17 *
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23 #include "internal.h"
24
25 #ifdef USE_SCREENSAVER
26 # ifndef _WIN32
27 # include <X11/Xlib.h>
28 # include <X11/Xutil.h>
29 # include <X11/extensions/scrnsaver.h>
30 # include <gdk/gdkx.h>
31 # else
32 # include "idletrack.h"
33 # endif
34 #endif /* USE_SCREENSAVER */
35
36 #include "connection.h"
37 #include "debug.h"
38 #include "log.h"
39 #include "prefs.h"
40 #include "savedstatuses.h"
41 #include "signals.h"
42
43 #define IDLEMARK 600 /* 10 minutes! */
44 #define IDLE_CHECK_INTERVAL 20000 /* 20 seconds */
45
46 typedef enum
47 {
48 GAIM_IDLE_NOT_AWAY = 0,
49 GAIM_IDLE_AUTO_AWAY,
50 GAIM_IDLE_AWAY_BUT_NOT_AUTO_AWAY
51
52 } GaimAutoAwayState;
53
54 #ifdef USE_SCREENSAVER
55 /**
56 * Get the number of seconds the user has been idle. In Unix-world
57 * this is based on the X Windows usage. In MS Windows this is based
58 * on keyboard/mouse usage.
59 *
60 * In Debian bug #271639, jwz says:
61 *
62 * Gaim should simply ask xscreensaver how long the user has been idle:
63 * % xscreensaver-command -time
64 * XScreenSaver 4.18: screen blanked since Tue Sep 14 14:10:45 2004
65 *
66 * Or you can monitor the _SCREENSAVER_STATUS property on root window #0.
67 * Element 0 is the status (0, BLANK, LOCK), element 1 is the time_t since
68 * the last state change, and subsequent elements are which hack is running
69 * on the various screens:
70 * % xprop -f _SCREENSAVER_STATUS 32ac -root _SCREENSAVER_STATUS
71 * _SCREENSAVER_STATUS(INTEGER) = BLANK, 1095196626, 10, 237
72 *
73 * See watch() in xscreensaver/driver/xscreensaver-command.c.
74 *
75 * @return The number of seconds the user has been idle.
76 */
77 static int
78 get_idle_time_from_system()
79 {
80 #ifndef _WIN32
81 static XScreenSaverInfo *mit_info = NULL;
82 int event_base, error_base;
83 if (XScreenSaverQueryExtension(GDK_DISPLAY(), &event_base, &error_base)) {
84 if (mit_info == NULL) {
85 mit_info = XScreenSaverAllocInfo();
86 }
87 XScreenSaverQueryInfo(GDK_DISPLAY(), GDK_ROOT_WINDOW(), mit_info);
88 return (mit_info->idle) / 1000;
89 } else
90 return 0;
91 #else
92 return (GetTickCount() - wgaim_get_lastactive()) / 1000;
93 #endif
94 }
95 #endif /* USE_SCREENSAVER */
96
97 /*
98 * This function should be called when you think your idle state
99 * may have changed. Maybe you're over the 10-minute mark and
100 * Gaim should start reporting idle time to the server. Maybe
101 * you've returned from being idle. Maybe your auto-away message
102 * should be set.
103 *
104 * There is no harm to calling this many many times, other than
105 * it will be kinda slow. This is called every 20 seconds by a
106 * timer set when an account logs in. It is also called when
107 * you send an IM, a chat, etc.
108 *
109 * This function has 3 sections.
110 * 1. Get your idle time. It will query XScreenSaver or Windows
111 * or get the Gaim idle time. Whatever.
112 * 2. Set or unset your auto-away message.
113 * 3. Report your current idle time to the IM server.
114 */
115 gint
116 gaim_gtk_idle_check(gpointer data)
117 {
118 GaimConnection *gc = (GaimConnection *)data;
119 gboolean report_idle;
120 GaimAccount *account;
121 time_t t;
122 int idle_time;
123
124 account = gaim_connection_get_account(gc);
125
126 gaim_signal_emit(gaim_blist_get_handle(), "update-idle");
127
128 time(&t);
129
130 report_idle = gaim_prefs_get_bool("/gaim/gtk/idle/report");
131
132 #ifdef USE_SCREENSAVER
133 idle_time = get_idle_time_from_system();
134 #else
135 /*
136 * If Gaim wasn't built with xscreensaver support, then
137 * fallback to calculating our idle time based on when
138 * we last sent a message.
139 */
140 idle_time = t - gc->last_sent_time;
141 #endif /* USE_SCREENSAVER */
142
143 /* Should we become auto-away? */
144 if (gaim_prefs_get_bool("/core/away/away_when_idle") &&
145 (idle_time > (60 * gaim_prefs_get_int("/core/away/mins_before_away")))
146 && (!gc->is_auto_away))
147 {
148 GaimPresence *presence;
149
150 presence = gaim_account_get_presence(account);
151
152 if (gaim_presence_is_available(presence))
153 {
154 const char *idleaway_name;
155 GaimSavedStatus *saved_status;
156
157 gaim_debug_info("idle", "Making %s auto-away\n",
158 gaim_account_get_username(account));
159
160 /* Mark our accounts "away" using the idleaway status */
161 idleaway_name = gaim_prefs_get_string("/core/status/idleaway");
162 saved_status = gaim_savedstatus_find(idleaway_name);
163 if (saved_status)
164 gaim_savedstatus_activate(saved_status);
165
166 gc->is_auto_away = GAIM_IDLE_AUTO_AWAY;
167 } else {
168 gc->is_auto_away = GAIM_IDLE_AWAY_BUT_NOT_AUTO_AWAY;
169 }
170
171 /* Should we return from being auto-away? */
172 } else if (gc->is_auto_away &&
173 idle_time < 60 * gaim_prefs_get_int("/core/away/mins_before_away")) {
174 if (gc->is_auto_away == GAIM_IDLE_AWAY_BUT_NOT_AUTO_AWAY) {
175 gc->is_auto_away = GAIM_IDLE_NOT_AWAY;
176 return TRUE;
177 }
178 gc->is_auto_away = GAIM_IDLE_NOT_AWAY;
179
180 /* XXX STATUS AWAY CORE/UI */
181 /* Need to set this connection to available here */
182 }
183
184 /* Deal with reporting idleness to the server, if appropriate */
185 if (report_idle && idle_time >= IDLEMARK && !gc->is_idle) {
186 gaim_debug_info("idle", "Setting %s idle %d seconds\n",
187 gaim_account_get_username(account), idle_time);
188 serv_set_idle(gc, idle_time);
189 gc->is_idle = 1;
190 /* LOG system_log(log_idle, gc, NULL, OPT_LOG_BUDDY_IDLE | OPT_LOG_MY_SIGNON); */
191 } else if ((!report_idle || idle_time < IDLEMARK) && gc->is_idle) {
192 gaim_debug_info("idle", "Setting %s unidle\n",
193 gaim_account_get_username(account));
194 gc->is_idle = 0;
195 serv_set_idle(gc, 0);
196 /* LOG system_log(log_unidle, gc, NULL, OPT_LOG_BUDDY_IDLE | OPT_LOG_MY_SIGNON); */
197 }
198
199 return TRUE;
200 }
201
202 static void
203 im_msg_sent_cb(GaimAccount *account, const char *receiver,
204 const char *message, void *data)
205 {
206 GaimConnection *gc = gaim_account_get_connection(account);
207
208 /* After an IM is sent, check our idle time */
209 gaim_gtk_idle_check(gc);
210 }
211
212 static void
213 remove_idle_timer(GaimConnection *gc)
214 {
215 /* Remove any existing idle_timer */
216 if (gc->idle_timer > 0)
217 gaim_timeout_remove(gc->idle_timer);
218 gc->idle_timer = 0;
219 }
220
221 static void
222 connection_disconnected_cb(GaimConnection *gc, gpointer user_data)
223 {
224 remove_idle_timer(gc);
225 }
226
227 static void
228 connection_connected_cb(GaimConnection *gc, gpointer user_data)
229 {
230 /* Now that we are connected, check for idleness every 20 seconds */
231 remove_idle_timer(gc);
232 gc->idle_timer = gaim_timeout_add(IDLE_CHECK_INTERVAL, gaim_gtk_idle_check, gc);
233
234 /* Immediately update our idleness, in case we connected while idle */
235 gaim_gtk_idle_check(gc);
236 }
237
238 void *
239 gaim_gtk_idle_get_handle()
240 {
241 static int handle;
242
243 return &handle;
244 }
245
246 void
247 gaim_gtk_idle_init()
248 {
249 gaim_signal_connect(gaim_conversations_get_handle(), "sent-im-msg",
250 gaim_gtk_idle_get_handle(),
251 GAIM_CALLBACK(im_msg_sent_cb), NULL);
252
253 gaim_signal_connect(gaim_connections_get_handle(), "signed-on",
254 gaim_gtk_idle_get_handle(),
255 GAIM_CALLBACK(connection_connected_cb), NULL);
256 gaim_signal_connect(gaim_connections_get_handle(), "signed-off",
257 gaim_gtk_idle_get_handle(),
258 GAIM_CALLBACK(connection_disconnected_cb), NULL);
259 }
260
261 void
262 gaim_gtk_idle_uninit()
263 {
264 gaim_signals_disconnect_by_handle(gaim_gtk_idle_get_handle());
265 }