summaryrefslogtreecommitdiffstats
path: root/src/modules/my/idle_mac.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/my/idle_mac.cpp')
-rw-r--r--src/modules/my/idle_mac.cpp162
1 files changed, 162 insertions, 0 deletions
diff --git a/src/modules/my/idle_mac.cpp b/src/modules/my/idle_mac.cpp
new file mode 100644
index 00000000..92de564d
--- /dev/null
+++ b/src/modules/my/idle_mac.cpp
@@ -0,0 +1,162 @@
+/*
+ * idle_mac.cpp - detect desktop idle time
+ * Copyright (C) 2003 Tarkvara Design Inc.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef Q_OS_MACX
+
+#include"idle.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 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;
+}
+#endif \ No newline at end of file