[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kopete-devel
Subject:    [kopete-devel] [PATCH] Multiplatform idle timer
From:       "Roman Jarosz" <kedgedev () centrum ! cz>
Date:       2008-07-27 9:09:18
Message-ID: op.uex01siayuholc () localhost
[Download RAW message or body]

Hi,

I've changed the implementation of idle timer because it was only
implemented for x11. With this patch it should work on all platforms.
Most of the code was taken from KVirc.

I've successfully tested it on Linux and Windows. The MacOS version wasn't tested.

Can I commit it?

Regards,
Roman

PS. There's one problem. If you lock the screen and then interact with mouse or keyboard
the idle time will be set back to 0. I'll try to investigate if we can somehow
detect if the screen is locked.

QDBusInterface caller("org.freedesktop.ScreenSaver", "/ScreenSaver", "org.freedesktop.ScreenSaver");     
QDBusReply<bool> reply = caller.call("GetActive");  
This somehow isn't working.
["idletimer-mp.diff" (idletimer-mp.diff)]

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;
+}



_______________________________________________
kopete-devel mailing list
kopete-devel@kde.org
https://mail.kde.org/mailman/listinfo/kopete-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic