Index: kopeteidletimer.cpp
===================================================================
--- kopeteidletimer.cpp	(revision 837950)
+++ kopeteidletimer.cpp	(working copy)
@@ -15,39 +15,19 @@
     *                                                                       *
     *************************************************************************
 */
-#include <config-kopete.h>
 
 #include "kopeteidletimer.h"
+#include "kopeteidleplatform_p.h"
 
 #include <QtCore/QTimer>
-#include <QtCore/QTime>
-#include <QtDBus/QtDBus>
+#include <QtCore/QDateTime>
+#include <QtGui/QCursor>
 
 #include <kdebug.h>
 
-#ifdef Q_WS_X11
-  #include <X11/Xlib.h>
-  #include <X11/Xatom.h>
-  #include <X11/Xresource.h>
-  // The following include is to make --enable-final work
-  #include <X11/Xutil.h>
-
-  #ifdef HAVE_XSCREENSAVER
-    #define HasScreenSaver
-    #include <X11/extensions/scrnsaver.h>
-  #endif
-  
-  #include <QX11Info>
-#endif // Q_WS_X11
-
-// As this is an untested X extension we better leave it off
-#undef HAVE_XIDLE
-#undef HasXidle
-
 class Kopete::IdleTimer::Private
 {
 public:
-	QTime idleTime;
 	struct TimeoutReceiver {
 		bool active;
 		int msec;
@@ -56,19 +36,12 @@
 		const char * memberIdle;
 	};
 	QList<TimeoutReceiver> receiverList;
-	QTimer *timer;
+	QTimer timer;
 
-	int mouse_x;
-	int mouse_y;
-	unsigned int mouse_mask;
-#ifdef Q_WS_X11
-	Window    root;               /* root window the pointer is on */
-	Screen*   screen;             /* screen the pointer is on      */
-	
-	Time xIdleTime;
-#endif
-	bool useXidle;
-	bool useMit;
+	QPoint lastMousePos;
+	QDateTime idleSince;
+
+	Kopete::IdlePlatform *platform;
 };
 
 Kopete::IdleTimer *Kopete::IdleTimer::instance = 0L;
@@ -76,70 +49,64 @@
 Kopete::IdleTimer::IdleTimer()
 : QObject(), d( new Private )
 {
-	int dummy = 0;	
+	d->platform = 0;
 
-	// set the XAutoLock info
-#ifdef Q_WS_X11
-	Display *dsp = QX11Info::display();
-#endif
-	d->mouse_x = d->mouse_y=0;
-	d->mouse_mask = 0;
-#ifdef Q_WS_X11
-	d->root = DefaultRootWindow (dsp);
-	d->screen = ScreenOfDisplay (dsp, DefaultScreen (dsp));
-#endif
-	d->useXidle = false;
-	d->useMit = false;
-#ifdef HasXidle
-	d->useXidle = XidleQueryExtension(QX11Info::display(), &dummy, &dummy);
-#endif
-#ifdef HasScreenSaver
-	if(!d->useXidle)
-		d->useMit = XScreenSaverQueryExtension(QX11Info::display(), &dummy, &dummy);
-#endif
-#ifdef Q_WS_X11
-	d->xIdleTime = 0;
-#endif
-	kDebug(14010) << k_funcinfo << "Idle detection methods:";
-	kDebug(14010) << k_funcinfo << "\tKScreensaverIface::isBlanked()";
-#ifdef Q_WS_X11
-	kDebug(14010) << k_funcinfo << "\tX11 XQueryPointer()";
-#endif
-	if (d->useXidle)
+	Kopete::IdlePlatform *p = new Kopete::IdlePlatform();
+	if ( p->init() )
 	{
-		kDebug(14010) << k_funcinfo << "\tX11 Xidle extension";
+		kDebug() << "Using platform idle timer";
+		d->platform = p;
 	}
-	if (d->useMit)
+	else
 	{
-		kDebug(14010) << k_funcinfo << "\tX11 MIT Screensaver extension";
+		kDebug() << "Using dummy idle timer";
+		delete p;
+
+		d->lastMousePos = QCursor::pos();
+		d->idleSince = QDateTime::currentDateTime();
 	}
 
 	// init the timer
-	d->timer = new QTimer(this);
-	connect(d->timer, SIGNAL(timeout()), this, SLOT(slotTimerTimeout()));
-	d->timer->start(4000);
-
-	d->idleTime.start();
+	connect(&d->timer, SIGNAL(timeout()), this, SLOT(updateIdleTime()));
+	d->timer.start(4000);
 }
 
 Kopete::IdleTimer *Kopete::IdleTimer::self()
 {
 	if ( !instance )
 		instance = new IdleTimer;
-	
+
 	return instance;
 }
 
 Kopete::IdleTimer::~IdleTimer()
 {
+	if ( d->platform )
+		delete d->platform;
+
 	delete d;
 }
 
 int Kopete::IdleTimer::idleTime()
 {
-	//FIXME: the time is reset to zero if more than 24 hours are elapsed
-	// we can imagine someone who leave his PC for several weeks
-	return (d->idleTime.elapsed() / 1000);
+	int idle;
+	if ( d->platform )
+	{
+		idle = d->platform->secondsIdle();
+	}
+	else
+	{
+		QPoint curMousePos = QCursor::pos();
+		QDateTime curDateTime = QDateTime::currentDateTime();
+		if ( d->lastMousePos != curMousePos )
+		{
+			d->lastMousePos = curMousePos;
+			d->idleSince = curDateTime;
+		}
+		idle = d->idleSince.secsTo(curDateTime);
+	}
+
+	return idle;
 }
 
 void Kopete::IdleTimer::registerTimeout( int idleSeconds, QObject *receiver,
@@ -164,25 +131,15 @@
 	}
 }
 
-void Kopete::IdleTimer::slotTimerTimeout()
+void Kopete::IdleTimer::updateIdleTime()
 {
-#ifdef __GNUC__
-#warning verify dcop call
-#endif
-	QDBusInterface caller("org.freedesktop.ScreenSaver", "/ScreenSaver", "org.freedesktop.ScreenSaver");
-	QDBusReply<bool> reply = caller.call("GetActive");
-	
-	// If the screensaver is active, ignore any activity	
-	bool activity = ( reply.isValid() && reply.value() ) ? false : isActivity();
+	int idle = idleTime() * 1000;
+	bool activity = ( idle < 10 );
 
-	//kDebug(14010) << "idle: " << idleTime() << " active:" << activity;
-	if ( activity )
-		d->idleTime.start();
-
 	for ( int i = 0; i < d->receiverList.size(); i++ )
 	{
 		Private::TimeoutReceiver item = d->receiverList.at(i);
-		if ( item.active != activity && (activity == true || d->idleTime.elapsed() > item.msec ) )
+		if ( item.active != activity && (activity == true || idle > item.msec ) )
 		{
 			d->receiverList[i].active = activity;
 			if ( activity )
@@ -193,100 +150,5 @@
 	}
 }
 
-bool Kopete::IdleTimer::isActivity()
-{
-	// Copyright (c) 1999 Martin R. Jones <mjones@kde.org>
-	//
-	// KDE screensaver engine
-	//
-	// This module is a heavily modified xautolock.
-	// In fact as of KDE 2.0 this code is practically unrecognisable as xautolock.
-	
-	bool activity = false;
-	
-#ifdef Q_WS_X11
-	Display *dsp = QX11Info::display();
-	Window           dummy_w;
-	int              dummy_c;
-	unsigned int     mask;               /* modifier mask                 */
-	int              root_x;
-	int              root_y;
-	
-	/*
-	*  Find out whether the pointer has moved. Using XQueryPointer for this
-	*  is gross, but it also is the only way never to mess up propagation
-	*  of pointer events.
-	*
-	*  Remark : Unlike XNextEvent(), XPending () doesn't notice if the
-	*           connection to the server is lost. For this reason, earlier
-	*           versions of xautolock periodically called XNoOp (). But
-	*           why not let XQueryPointer () do the job for us, since
-	*           we now call that periodically anyway?
-	*/
-	if (!XQueryPointer (dsp, d->root, &(d->root), &dummy_w, &root_x, &root_y,
-	                    &dummy_c, &dummy_c, &mask))
-	{
-		/*
-		*  Pointer has moved to another screen, so let's find out which one.
-		*/
-		for (int i = 0; i < ScreenCount(dsp); i++)
-		{
-			if (d->root == RootWindow(dsp, i))
-			{
-				d->screen = ScreenOfDisplay (dsp, i);
-				break;
-			}
-		}
-	}
-	
-	// =================================================================================
-	
-	Time xIdleTime = 0; // millisecs since last input event
-	
-#ifdef HasXidle
-	if (d->useXidle)
-	{
-		XGetIdleTime(dsp, &xIdleTime);
-	}
-	else
-#endif /* HasXIdle */
-		
-	{
-#ifdef HasScreenSaver
-		if(d->useMit)
-		{
-			static XScreenSaverInfo* mitInfo = 0;
-			if (!mitInfo) mitInfo = XScreenSaverAllocInfo();
-			XScreenSaverQueryInfo (dsp, d->root, mitInfo);
-			xIdleTime = mitInfo->idle;
-		}
-#endif /* HasScreenSaver */
-	}
-	
-	// =================================================================================
-	
-	// Only check idle time if we have some way of measuring it, otherwise if
-	// we've neither Mit nor Xidle it'll still be zero and we'll always appear active.
-	// FIXME: what problem does the 2000ms fudge solve?
-	if (root_x != d->mouse_x || root_y != d->mouse_y || mask != d->mouse_mask
-	    || ((d->useXidle || d->useMit) && xIdleTime < d->xIdleTime + 2000))
-	{
-		// -1 => just gone autoaway, ignore apparent activity this time round
-		// anything else => genuine activity
-		// See setAutoAway().
-		if (d->mouse_x != -1)
-		{
-			activity = true;
-		}
-		d->mouse_x = root_x;
-		d->mouse_y = root_y;
-		d->mouse_mask = mask;
-		d->xIdleTime = xIdleTime;
-	}
-#endif // Q_WS_X11
-
-	return activity;
-}
-
 #include "kopeteidletimer.moc"
 // vim: set et ts=4 sts=4 sw=4:
Index: kopeteidletimer.h
===================================================================
--- kopeteidletimer.h	(revision 837950)
+++ kopeteidletimer.h	(working copy)
@@ -65,19 +65,11 @@
 	void unregisterTimeout( QObject *receiver );
 
 private slots:
-	void slotTimerTimeout();
+	void updateIdleTime();
 
 private:
 	IdleTimer();
 
-	/**
-	 * @brief Check for activity using X11 methods
-	 * @return true if activity was detected, otherwise false
-	 *
-	 * Attempt to detect activity using a variety of X11 methods.
-	 */
-	bool isActivity();
-
 	static IdleTimer *instance;
 
 	class Private;
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt	(revision 837950)
+++ CMakeLists.txt	(working copy)
@@ -16,6 +16,20 @@
   private/kopeteviewmanager.cpp
 )
 
+if (Q_WS_X11)
+ if (X11_Xss_FOUND)
+  set(kopete_private_SRCS ${kopete_private_SRCS} private/kopeteidleplatform_x11.cpp )
+ else (X11_Xss_FOUND)
+  set(kopete_private_SRCS ${kopete_private_SRCS} private/kopeteidleplatform_dummy.cpp )
+ endif (X11_Xss_FOUND)
+endif (Q_WS_X11)
+if (Q_WS_MAC)
+ set(kopete_private_SRCS ${kopete_private_SRCS} private/kopeteidleplatform_mac.cpp )
+endif (Q_WS_MAC)
+if (Q_WS_WIN)
+ set(kopete_private_SRCS ${kopete_private_SRCS} private/kopeteidleplatform_win.cpp )
+endif (Q_WS_WIN)
+
 set(kopete_ui_SRCS
   ui/accountselector.cpp
   ui/addcontactpage.cpp
Index: private/kopeteidleplatform_p.h
===================================================================
--- private/kopeteidleplatform_p.h	(revision 0)
+++ private/kopeteidleplatform_p.h	(revision 0)
@@ -0,0 +1,38 @@
+/*
+    kopeteidleplatform_p.h  -  Kopete Idle Platform
+
+    Copyright (c) 2008      by Roman Jarosz          <kedgedev@centrum.cz>
+    Kopete    (c) 2008      by the Kopete developers <kopete-devel@kde.org>
+
+    *************************************************************************
+    *                                                                       *
+    * This library is free software; you can redistribute it and/or         *
+    * modify it under the terms of the GNU Lesser General Public            *
+    * License as published by the Free Software Foundation; either          *
+    * version 2 of the License, or (at your option) any later version.      *
+    *                                                                       *
+    *************************************************************************
+*/
+#ifndef KOPETEIDLEPLATFORM_P_H
+#define KOPETEIDLEPLATFORM_P_H
+
+namespace Kopete
+{
+
+class IdlePlatform
+{
+public:
+	IdlePlatform();
+	~IdlePlatform();
+
+	bool init();
+	int secondsIdle();
+
+private:
+	class Private;
+	Private *d;
+};
+
+}
+
+#endif
\ No newline at end of file
Index: private/kopeteidleplatform_x11.cpp
===================================================================
--- private/kopeteidleplatform_x11.cpp	(revision 0)
+++ private/kopeteidleplatform_x11.cpp	(revision 0)
@@ -0,0 +1,90 @@
+/*
+    kopeteidleplatform_x11.cpp  -  Kopete Idle Platform
+
+    Copyright (C) 2003      by Justin Karneges       (from KVIrc source code)
+    Copyright (c) 2008      by Roman Jarosz          <kedgedev@centrum.cz>
+    Kopete    (c) 2008      by the Kopete developers <kopete-devel@kde.org>
+
+    *************************************************************************
+    *                                                                       *
+    * This library is free software; you can redistribute it and/or         *
+    * modify it under the terms of the GNU Lesser General Public            *
+    * License as published by the Free Software Foundation; either          *
+    * version 2 of the License, or (at your option) any later version.      *
+    *                                                                       *
+    *************************************************************************
+*/
+
+#include "kopeteidleplatform_p.h"
+
+#include <QtGui/QX11Info>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/scrnsaver.h>
+
+static XErrorHandler old_handler = 0;
+extern "C" int xerrhandler( Display* dpy, XErrorEvent* err )
+{
+	if ( err->error_code == BadDrawable )
+		return 0;
+
+	return (*old_handler)(dpy, err);
+}
+
+
+class Kopete::IdlePlatform::Private
+{
+public:
+	Private() {}
+
+	XScreenSaverInfo *ss_info;
+};
+
+Kopete::IdlePlatform::IdlePlatform()
+: d( new Private() )
+{
+	d->ss_info = 0;
+}
+
+Kopete::IdlePlatform::~IdlePlatform()
+{
+	if ( d->ss_info )
+		XFree(d->ss_info);
+
+	if ( old_handler )
+	{
+		XSetErrorHandler( old_handler );
+		old_handler = 0;
+	}
+
+	delete d;
+}
+
+bool Kopete::IdlePlatform::init()
+{
+	if ( d->ss_info )
+		return true;
+
+	old_handler = XSetErrorHandler( xerrhandler );
+
+	int event_base, error_base;
+	if ( XScreenSaverQueryExtension( QX11Info::display(), &event_base, &error_base ) )
+	{
+		d->ss_info = XScreenSaverAllocInfo();
+		return true;
+	}
+
+	return false;
+}
+
+int Kopete::IdlePlatform::secondsIdle()
+{
+	if ( !d->ss_info )
+		return 0;
+
+	if ( !XScreenSaverQueryInfo( QX11Info::display(), QX11Info::appRootWindow(), d->ss_info ) )
+		return 0;
+
+	return d->ss_info->idle / 1000;
+}
Index: private/kopeteidleplatform_dummy.cpp
===================================================================
--- private/kopeteidleplatform_dummy.cpp	(revision 0)
+++ private/kopeteidleplatform_dummy.cpp	(revision 0)
@@ -0,0 +1,36 @@
+/*
+    kopeteidleplatform_dummy.cpp  -  Kopete Idle Platform
+
+    Copyright (c) 2008      by Roman Jarosz          <kedgedev@centrum.cz>
+    Kopete    (c) 2008      by the Kopete developers <kopete-devel@kde.org>
+
+    *************************************************************************
+    *                                                                       *
+    * This library is free software; you can redistribute it and/or         *
+    * modify it under the terms of the GNU Lesser General Public            *
+    * License as published by the Free Software Foundation; either          *
+    * version 2 of the License, or (at your option) any later version.      *
+    *                                                                       *
+    *************************************************************************
+*/
+
+#include "kopeteidleplatform_p.h"
+
+Kopete::IdlePlatform::IdlePlatform()
+{
+}
+
+Kopete::IdlePlatform::~IdlePlatform()
+{
+
+}
+
+bool Kopete::IdlePlatform::init()
+{
+	return false;
+}
+
+int Kopete::IdlePlatform::secondsIdle()
+{
+	return 0;
+}
\ No newline at end of file
Index: private/kopeteidleplatform_win.cpp
===================================================================
--- private/kopeteidleplatform_win.cpp	(revision 0)
+++ private/kopeteidleplatform_win.cpp	(revision 0)
@@ -0,0 +1,117 @@
+/*
+    kopeteidleplatform_win.cpp  -  Kopete Idle Platform
+
+    Copyright (C) 2003      by Justin Karneges       (from KVIrc source code)
+    Copyright (c) 2008      by Roman Jarosz          <kedgedev@centrum.cz>
+    Kopete    (c) 2008      by the Kopete developers <kopete-devel@kde.org>
+
+    *************************************************************************
+    *                                                                       *
+    * This library is free software; you can redistribute it and/or         *
+    * modify it under the terms of the GNU Lesser General Public            *
+    * License as published by the Free Software Foundation; either          *
+    * version 2 of the License, or (at your option) any later version.      *
+    *                                                                       *
+    *************************************************************************
+*/
+
+#include "kopeteidleplatform_p.h"
+
+#include <QtCore/QLibrary>
+#include< windows.h>
+
+namespace Kopete
+{
+
+typedef struct tagLASTINPUTINFO
+{
+	UINT cbSize;
+	DWORD dwTime;
+} LASTINPUTINFO, *PLASTINPUTINFO;
+
+class Kopete::IdlePlatform::Private
+{
+public:
+	Private()
+	{
+		GetLastInputInfo = 0;
+		IdleUIGetLastInputTime = 0;
+		lib = 0;
+	}
+	
+	BOOL (__stdcall * GetLastInputInfo)(PLASTINPUTINFO);
+	DWORD (__stdcall * IdleUIGetLastInputTime)(void);
+	QLibrary *lib;
+};
+
+Kopete::IdlePlatform::IdlePlatform()
+{
+	d = new Private;
+}
+
+Kopete::IdlePlatform::~IdlePlatform()
+{
+	delete d->lib;
+	delete d;
+}
+
+bool Kopete::IdlePlatform::init()
+{
+	if ( d->lib )
+		return true;
+
+	void *p;
+
+	// try to find the built-in Windows 2000 function
+	d->lib = new QLibrary( "user32" );
+	if ( d->lib->load() && (p = d->lib->resolve( "GetLastInputInfo" )) )
+	{
+		d->GetLastInputInfo = (BOOL (__stdcall *)(PLASTINPUTINFO))p;
+		return true;
+	}
+	else
+	{
+		delete d->lib;
+		d->lib = 0;
+	}
+
+	// fall back on idleui
+	d->lib = new QLibrary( "idleui" );
+	if ( d->lib->load() && (p = d->lib->resolve("IdleUIGetLastInputTime")) )
+	{
+		d->IdleUIGetLastInputTime = (DWORD (__stdcall *)(void))p;
+		return true;
+	}
+	else
+	{
+		delete d->lib;
+		d->lib = 0;
+	}
+
+	return false;
+}
+
+int Kopete::IdlePlatform::secondsIdle()
+{
+	int i;
+	if ( d->GetLastInputInfo )
+	{
+		LASTINPUTINFO li;
+		li.cbSize = sizeof(LASTINPUTINFO);
+		bool ok = d->GetLastInputInfo( &li );
+		if ( !ok )
+			return 0;
+
+		i = li.dwTime;
+	}
+	else if ( d->IdleUIGetLastInputTime )
+	{
+		i = d->IdleUIGetLastInputTime();
+	}
+	else
+		return 0;
+	
+	return (GetTickCount() - i) / 1000;
+}
+
+}
Index: private/kopeteidleplatform_mac.cpp
===================================================================
--- private/kopeteidleplatform_mac.cpp	(revision 0)
+++ private/kopeteidleplatform_mac.cpp	(revision 0)
@@ -0,0 +1,162 @@
+/*
+    kopeteidleplatform_mac.cpp  -  Kopete Idle Platform
+
+    Copyright (C) 2003      by Tarkvara Design Inc.  (from KVIrc source code)
+    Copyright (c) 2008      by Roman Jarosz          <kedgedev@centrum.cz>
+    Kopete    (c) 2008      by the Kopete developers <kopete-devel@kde.org>
+
+    *************************************************************************
+    *                                                                       *
+    * This library is free software; you can redistribute it and/or         *
+    * modify it under the terms of the GNU Lesser General Public            *
+    * License as published by the Free Software Foundation; either          *
+    * version 2 of the License, or (at your option) any later version.      *
+    *                                                                       *
+    *************************************************************************
+*/
+
+#include "kopeteidleplatform_p.h"
+#include <Carbon/Carbon.h>
+
+// Why does Apple have to make this so complicated?
+static OSStatus LoadFrameworkBundle( CFStringRef framework, CFBundleRef *bundlePtr )
+{
+	OSStatus  err;
+	FSRef   frameworksFolderRef;
+	CFURLRef baseURL;
+	CFURLRef bundleURL;
+
+	if ( bundlePtr == nil )
+		return( -1 );
+
+	*bundlePtr = nil;
+
+	baseURL = nil;
+	bundleURL = nil;
+
+	err = FSFindFolder( kOnAppropriateDisk, kFrameworksFolderType, true, &frameworksFolderRef );
+	if ( err == noErr )
+	{
+		baseURL = CFURLCreateFromFSRef( kCFAllocatorSystemDefault, &frameworksFolderRef );
+		if ( baseURL == nil )
+			err = coreFoundationUnknownErr;
+	}
+
+	if ( err == noErr )
+	{
+		bundleURL = CFURLCreateCopyAppendingPathComponent( kCFAllocatorSystemDefault, baseURL, framework, false );
+		if ( bundleURL == nil )
+			err = coreFoundationUnknownErr;
+	}
+
+	if ( err == noErr )
+	{
+		*bundlePtr = CFBundleCreate( kCFAllocatorSystemDefault, bundleURL );
+		if ( *bundlePtr == nil )
+			err = coreFoundationUnknownErr;
+	}
+
+	if ( err == noErr )
+	{
+		if ( !CFBundleLoadExecutable( *bundlePtr ) )
+			err = coreFoundationUnknownErr;
+	}
+
+		// Clean up.
+	if ( err != noErr && *bundlePtr != nil )
+	{
+		CFRelease( *bundlePtr );
+		*bundlePtr = nil;
+	}
+
+	if ( bundleURL != nil )
+		CFRelease( bundleURL );
+
+	if ( baseURL != nil )
+		CFRelease( baseURL );
+
+	return err;
+}
+
+
+class Kopete::IdlePlatform::Private
+{
+public:
+	EventLoopTimerRef mTimerRef;
+	int mSecondsIdle;
+
+	Private() : mTimerRef(0), mSecondsIdle(0) {}
+
+	static pascal void IdleTimerAction( EventLoopTimerRef, EventLoopIdleTimerMessage inState, void* inUserData );
+	
+};
+
+
+pascal void Kopete::IdlePlatform::Private::IdleTimerAction( EventLoopTimerRef, EventLoopIdleTimerMessage inState, void* inUserData )
+{
+	switch (inState)
+	{
+	case kEventLoopIdleTimerStarted:
+	case kEventLoopIdleTimerStopped:
+		// Get invoked with this constant at the start of the idle period,
+		// or whenever user activity cancels the idle.
+		((Kopete::IdlePlatform::Private*)inUserData)->mSecondsIdle = 0;
+		break;
+	case kEventLoopIdleTimerIdling:
+		// Called every time the timer fires (i.e. every second).
+		((Kopete::IdlePlatform::Private*)inUserData)->mSecondsIdle++;
+		break;
+	}
+}
+
+
+Kopete::IdlePlatform::IdlePlatform()
+{
+	d = new Private();
+}
+
+Kopete::IdlePlatform::~IdlePlatform()
+{
+	RemoveEventLoopTimer( d->mTimerRef );
+	delete d;
+}
+
+// Typedef for the function we're getting back from CFBundleGetFunctionPointerForName.
+typedef OSStatus (*InstallEventLoopIdleTimerPtr)(EventLoopRef inEventLoop,
+                                                 EventTimerInterval   inFireDelay,
+                                                 EventTimerInterval   inInterval,
+                                                 EventLoopIdleTimerUPP    inTimerProc,
+                                                 void *               inTimerData,
+                                                 EventLoopTimerRef *  outTimer);
+
+bool Kopete::IdlePlatform::init()
+{
+	// May already be init'ed.
+	if ( d->mTimerRef )
+		return true;
+
+	// According to the docs, InstallEventLoopIdleTimer is new in 10.2.
+	// According to the headers, it has been around since 10.0.
+	// One of them is lying.  We'll play it safe and weak-link the function.
+
+	// Load the "Carbon.framework" bundle.
+	CFBundleRef carbonBundle;
+	if ( LoadFrameworkBundle( CFSTR("Carbon.framework"), &carbonBundle ) != noErr )
+		return false;
+
+	// Load the Mach-O function pointers for the routine we will be using.
+	InstallEventLoopIdleTimerPtr myInstallEventLoopIdleTimer = (InstallEventLoopIdleTimerPtr)CFBundleGetFunctionPointerForName( carbonBundle, CFSTR("InstallEventLoopIdleTimer") );
+	if ( myInstallEventLoopIdleTimer == 0 )
+		return false;
+
+	EventLoopIdleTimerUPP timerUPP = NewEventLoopIdleTimerUPP( Private::IdleTimerAction );
+	if ( (*myInstallEventLoopIdleTimer)(GetMainEventLoop(), kEventDurationSecond, kEventDurationSecond, timerUPP, 0, &d->mTimerRef) )
+		return true;
+
+	return false;
+}
+
+int Kopete::IdlePlatform::secondsIdle()
+{
+	return d->mSecondsIdle;
+}
