diff --git a/retroshare-gui/src/idle/idle.cpp b/retroshare-gui/src/idle/idle.cpp index 8b39996b7..5110a10b3 100644 --- a/retroshare-gui/src/idle/idle.cpp +++ b/retroshare-gui/src/idle/idle.cpp @@ -126,5 +126,5 @@ int Idle::secondsIdle() void Idle::doCheck() { - secondsIdle(secondsIdle()); + emit secondsIdle(secondsIdle()); } diff --git a/retroshare-gui/src/idle/idle_platform.cpp b/retroshare-gui/src/idle/idle_platform.cpp new file mode 100644 index 000000000..91aba8dd7 --- /dev/null +++ b/retroshare-gui/src/idle/idle_platform.cpp @@ -0,0 +1,329 @@ +/* + * idle_x11.cpp - detect desktop idle time + * Copyright (C) 2003 Justin Karneges + * + * 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.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "idle.h" + +//linux +#ifdef HAVE_XSS + +#include +#include +#include + +#include +#include +#include + +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 IdlePlatform::Private +{ +public: + Private() {} + + XScreenSaverInfo *ss_info; +}; + +IdlePlatform::IdlePlatform() +{ + d = new Private; + d->ss_info = 0; +} + +IdlePlatform::~IdlePlatform() +{ + if(d->ss_info) + XFree(d->ss_info); + if(old_handler) { + XSetErrorHandler(old_handler); + old_handler = 0; + } + delete d; +} + +bool IdlePlatform::init() +{ + if(d->ss_info) + return true; + + old_handler = XSetErrorHandler(xerrhandler); + + int event_base, error_base; + if(XScreenSaverQueryExtension(QApplication::desktop()->screen()->x11Info().display(), &event_base, &error_base)) { + d->ss_info = XScreenSaverAllocInfo(); + return true; + } + return false; +} + +int IdlePlatform::secondsIdle() +{ + if(!d->ss_info) + return 0; + if(!XScreenSaverQueryInfo(QApplication::desktop()->screen()->x11Info().display(), QX11Info::appRootWindow(), d->ss_info)) + return 0; + return d->ss_info->idle / 1000; +} + +#else // windows +#ifdef WINDOWS_SYS + +#include +#include + +#ifndef tagLASTINPUTINFO +typedef struct __tagLASTINPUTINFO { + UINT cbSize; + DWORD dwTime; + } __LASTINPUTINFO, *__PLASTINPUTINFO; +#endif + +class IdlePlatform::Private +{ +public: + Private() + { + GetLastInputInfo = NULL; + lib = 0; + } + + BOOL (__stdcall * GetLastInputInfo)(__PLASTINPUTINFO); + DWORD (__stdcall * IdleUIGetLastInputTime)(void); + QLibrary *lib; +}; + +IdlePlatform::IdlePlatform() +{ + d = new Private; +} + +IdlePlatform::~IdlePlatform() +{ + delete d->lib; + delete d; +} + +bool 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 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; +} + +#else //mac +#ifdef MAC_IDLE + +#include + + +// 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 IdlePlatform::Private { +public: + EventLoopTimerRef mTimerRef; + int mSecondsIdle; + + Private() : mTimerRef(0), mSecondsIdle(0) {} + + static pascal void IdleTimerAction(EventLoopTimerRef, EventLoopIdleTimerMessage inState, void* inUserData); + +}; + + +pascal void 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. + ((IdlePlatform::Private*)inUserData)->mSecondsIdle = 0; + break; + case kEventLoopIdleTimerIdling: + // Called every time the timer fires (i.e. every second). + ((IdlePlatform::Private*)inUserData)->mSecondsIdle++; + break; + } +} + + +IdlePlatform::IdlePlatform() { + d = new Private(); +} + +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 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 IdlePlatform::secondsIdle() { + return d->mSecondsIdle; +} + +#else + +IdlePlatform::IdlePlatform() {} +IdlePlatform::~IdlePlatform() {} +bool IdlePlatform::init() { return false; } +int IdlePlatform::secondsIdle() { return 0; } + +#endif +#endif +#endif diff --git a/retroshare-gui/src/idle/idle_x11.cpp b/retroshare-gui/src/idle/idle_x11.cpp deleted file mode 100644 index 2263ade8e..000000000 --- a/retroshare-gui/src/idle/idle_x11.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * idle_x11.cpp - detect desktop idle time - * Copyright (C) 2003 Justin Karneges - * - * 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.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "idle.h" - -#ifndef HAVE_XSS - -IdlePlatform::IdlePlatform() {} -IdlePlatform::~IdlePlatform() {} -bool IdlePlatform::init() { return false; } -int IdlePlatform::secondsIdle() { return 0; } - -#else - -#include -#include -#include - -#include -#include -#include - -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 IdlePlatform::Private -{ -public: - Private() {} - - XScreenSaverInfo *ss_info; -}; - -IdlePlatform::IdlePlatform() -{ - d = new Private; - d->ss_info = 0; -} - -IdlePlatform::~IdlePlatform() -{ - if(d->ss_info) - XFree(d->ss_info); - if(old_handler) { - XSetErrorHandler(old_handler); - old_handler = 0; - } - delete d; -} - -bool IdlePlatform::init() -{ - if(d->ss_info) - return true; - - old_handler = XSetErrorHandler(xerrhandler); - - int event_base, error_base; - if(XScreenSaverQueryExtension(QApplication::desktop()->screen()->x11Display(), &event_base, &error_base)) { - d->ss_info = XScreenSaverAllocInfo(); - return true; - } - return false; -} - -int IdlePlatform::secondsIdle() -{ - if(!d->ss_info) - return 0; - if(!XScreenSaverQueryInfo(QApplication::desktop()->screen()->x11Display(), QX11Info::appRootWindow(), d->ss_info)) - return 0; - return d->ss_info->idle / 1000; -} - -#endif