1 /*
2  * pidgin
3  *
4  * Pidgin 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., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
21  *
22  */
23 #include "internal.h"
24 #include "gtkidle.h"
25 
26 #ifdef HAVE_IOKIT
27 # include <CoreFoundation/CoreFoundation.h>
28 # include <IOKit/IOKitLib.h>
29 #else
30 # ifdef USE_SCREENSAVER
31 #  ifdef _WIN32
32 #   include "gtkwin32dep.h"
33 #  else
34     /* We're on X11 and not MacOS X with IOKit. */
35 #   include <X11/Xlib.h>
36 #   include <X11/Xutil.h>
37 #   include <X11/extensions/scrnsaver.h>
38 #   include <gdk/gdkx.h>
39 #  endif /* !_WIN32 */
40 # endif /* USE_SCREENSAVER */
41 #endif /* !HAVE_IOKIT */
42 
43 #include "idle.h"
44 
45 /**
46  * Get the number of seconds the user has been idle.  In Unix-world
47  * this is based on the X Windows usage.  In MS Windows this is
48  * based on keyboard/mouse usage information obtained from the OS.
49  * In MacOS X, this is based on keyboard/mouse usage information
50  * obtained from the OS, if configure detected IOKit.  Otherwise,
51  * MacOS X is handled as a case of X Windows.
52  *
53  * In Debian bug #271639, jwz says:
54  *
55  * Purple should simply ask xscreensaver how long the user has been idle:
56  *   % xscreensaver-command -time
57  *   XScreenSaver 4.18: screen blanked since Tue Sep 14 14:10:45 2004
58  *
59  * Or you can monitor the _SCREENSAVER_STATUS property on root window #0.
60  * Element 0 is the status (0, BLANK, LOCK), element 1 is the time_t since
61  * the last state change, and subsequent elements are which hack is running
62  * on the various screens:
63  *   % xprop -f _SCREENSAVER_STATUS 32ac -root _SCREENSAVER_STATUS
64  *   _SCREENSAVER_STATUS(INTEGER) = BLANK, 1095196626, 10, 237
65  *
66  * See watch() in xscreensaver/driver/xscreensaver-command.c.
67  *
68  * @return The number of seconds the user has been idle.
69  */
70 #if defined(USE_SCREENSAVER) || defined(HAVE_IOKIT)
71 static time_t
pidgin_get_time_idle(void)72 pidgin_get_time_idle(void)
73 {
74 # ifdef HAVE_IOKIT
75 	/* Query the IOKit API */
76 
77 	static io_service_t macIOsrvc = NULL;
78 	CFTypeRef property;
79 	uint64_t idle_time = 0; /* nanoseconds */
80 
81 	if (macIOsrvc == NULL)
82 	{
83 		mach_port_t master;
84 		IOMasterPort(MACH_PORT_NULL, &master);
85 		macIOsrvc = IOServiceGetMatchingService(master,
86 		                                        IOServiceMatching("IOHIDSystem"));
87 	}
88 
89 	property = IORegistryEntryCreateCFProperty(macIOsrvc, CFSTR("HIDIdleTime"),
90 	                                           kCFAllocatorDefault, 0);
91 	CFNumberGetValue((CFNumberRef)property,
92 	                 kCFNumberSInt64Type, &idle_time);
93 	CFRelease(property);
94 
95 	/* convert nanoseconds to seconds */
96 	return idle_time / 1000000000;
97 # else
98 #  ifdef _WIN32
99 	/* Query Windows */
100 	return (GetTickCount() - winpidgin_get_lastactive()) / 1000;
101 #  else
102 	/* We're on X11 and not MacOS X with IOKit. */
103 
104 	/* Query xscreensaver */
105 	static XScreenSaverInfo *mit_info = NULL;
106 	static int has_extension = -1;
107 	int event_base, error_base;
108 
109 	if (has_extension == -1)
110 		has_extension = XScreenSaverQueryExtension(GDK_DISPLAY(), &event_base, &error_base);
111 
112 	if (has_extension)
113 	{
114 		if (mit_info == NULL)
115 			mit_info = XScreenSaverAllocInfo();
116 
117 		XScreenSaverQueryInfo(GDK_DISPLAY(), GDK_ROOT_WINDOW(), mit_info);
118 		return (mit_info->idle) / 1000;
119 	}
120 	else
121 		return 0;
122 #  endif /* !_WIN32 */
123 # endif /* !HAVE_IOKIT */
124 }
125 #endif /* USE_SCREENSAVER || HAVE_IOKIT */
126 
127 static PurpleIdleUiOps ui_ops =
128 {
129 #if defined(USE_SCREENSAVER) || defined(HAVE_IOKIT)
130 	pidgin_get_time_idle,
131 #else
132 	NULL,
133 #endif /* USE_SCREENSAVER || HAVE_IOKIT */
134 	NULL,
135 	NULL,
136 	NULL,
137 	NULL
138 };
139 
140 PurpleIdleUiOps *
pidgin_idle_get_ui_ops()141 pidgin_idle_get_ui_ops()
142 {
143 	return &ui_ops;
144 }
145