1 | /*
|
---|
2 | * idle_mac.cpp - detect desktop idle time
|
---|
3 | * Copyright (C) 2003 Tarkvara Design Inc.
|
---|
4 | *
|
---|
5 | * This library is free software; you can redistribute it and/or
|
---|
6 | * modify it under the terms of the GNU Lesser General Public
|
---|
7 | * License as published by the Free Software Foundation; either
|
---|
8 | * version 2.1 of the License, or (at your option) any later version.
|
---|
9 | *
|
---|
10 | * This library is distributed in the hope that it will be useful,
|
---|
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
13 | * Lesser General Public License for more details.
|
---|
14 | *
|
---|
15 | * You should have received a copy of the GNU Lesser General Public
|
---|
16 | * License along with this library; if not, write to the Free Software
|
---|
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
---|
18 | *
|
---|
19 | */
|
---|
20 |
|
---|
21 | #include"idle.h"
|
---|
22 | #include <Carbon/Carbon.h>
|
---|
23 |
|
---|
24 |
|
---|
25 | // Why does Apple have to make this so complicated?
|
---|
26 | static OSStatus LoadFrameworkBundle(CFStringRef framework, CFBundleRef *bundlePtr) {
|
---|
27 | OSStatus err;
|
---|
28 | FSRef frameworksFolderRef;
|
---|
29 | CFURLRef baseURL;
|
---|
30 | CFURLRef bundleURL;
|
---|
31 |
|
---|
32 | if ( bundlePtr == nil ) return( -1 );
|
---|
33 |
|
---|
34 | *bundlePtr = nil;
|
---|
35 |
|
---|
36 | baseURL = nil;
|
---|
37 | bundleURL = nil;
|
---|
38 |
|
---|
39 | err = FSFindFolder(kOnAppropriateDisk, kFrameworksFolderType, true, &frameworksFolderRef);
|
---|
40 | if (err == noErr) {
|
---|
41 | baseURL = CFURLCreateFromFSRef(kCFAllocatorSystemDefault, &frameworksFolderRef);
|
---|
42 | if (baseURL == nil) {
|
---|
43 | err = coreFoundationUnknownErr;
|
---|
44 | }
|
---|
45 | }
|
---|
46 | if (err == noErr) {
|
---|
47 | bundleURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, baseURL, framework, false);
|
---|
48 | if (bundleURL == nil) {
|
---|
49 | err = coreFoundationUnknownErr;
|
---|
50 | }
|
---|
51 | }
|
---|
52 | if (err == noErr) {
|
---|
53 | *bundlePtr = CFBundleCreate(kCFAllocatorSystemDefault, bundleURL);
|
---|
54 | if (*bundlePtr == nil) {
|
---|
55 | err = coreFoundationUnknownErr;
|
---|
56 | }
|
---|
57 | }
|
---|
58 | if (err == noErr) {
|
---|
59 | if ( ! CFBundleLoadExecutable( *bundlePtr ) ) {
|
---|
60 | err = coreFoundationUnknownErr;
|
---|
61 | }
|
---|
62 | }
|
---|
63 |
|
---|
64 | // Clean up.
|
---|
65 | if (err != noErr && *bundlePtr != nil) {
|
---|
66 | CFRelease(*bundlePtr);
|
---|
67 | *bundlePtr = nil;
|
---|
68 | }
|
---|
69 | if (bundleURL != nil) {
|
---|
70 | CFRelease(bundleURL);
|
---|
71 | }
|
---|
72 | if (baseURL != nil) {
|
---|
73 | CFRelease(baseURL);
|
---|
74 | }
|
---|
75 |
|
---|
76 | return err;
|
---|
77 | }
|
---|
78 |
|
---|
79 |
|
---|
80 | class IdlePlatform::Private {
|
---|
81 | public:
|
---|
82 | EventLoopTimerRef mTimerRef;
|
---|
83 | int mSecondsIdle;
|
---|
84 |
|
---|
85 | Private() : mTimerRef(0), mSecondsIdle(0) {}
|
---|
86 |
|
---|
87 | static pascal void IdleTimerAction(EventLoopTimerRef, EventLoopIdleTimerMessage inState, void* inUserData);
|
---|
88 |
|
---|
89 | };
|
---|
90 |
|
---|
91 |
|
---|
92 | pascal void IdlePlatform::Private::IdleTimerAction(EventLoopTimerRef, EventLoopIdleTimerMessage inState, void* inUserData) {
|
---|
93 | switch (inState) {
|
---|
94 | case kEventLoopIdleTimerStarted:
|
---|
95 | case kEventLoopIdleTimerStopped:
|
---|
96 | // Get invoked with this constant at the start of the idle period,
|
---|
97 | // or whenever user activity cancels the idle.
|
---|
98 | ((IdlePlatform::Private*)inUserData)->mSecondsIdle = 0;
|
---|
99 | break;
|
---|
100 | case kEventLoopIdleTimerIdling:
|
---|
101 | // Called every time the timer fires (i.e. every second).
|
---|
102 | ((IdlePlatform::Private*)inUserData)->mSecondsIdle++;
|
---|
103 | break;
|
---|
104 | }
|
---|
105 | }
|
---|
106 |
|
---|
107 |
|
---|
108 | IdlePlatform::IdlePlatform() {
|
---|
109 | d = new Private();
|
---|
110 | }
|
---|
111 |
|
---|
112 | IdlePlatform::~IdlePlatform() {
|
---|
113 | RemoveEventLoopTimer(d->mTimerRef);
|
---|
114 | delete d;
|
---|
115 | }
|
---|
116 |
|
---|
117 |
|
---|
118 | // Typedef for the function we're getting back from CFBundleGetFunctionPointerForName.
|
---|
119 | typedef OSStatus (*InstallEventLoopIdleTimerPtr)(EventLoopRef inEventLoop,
|
---|
120 | EventTimerInterval inFireDelay,
|
---|
121 | EventTimerInterval inInterval,
|
---|
122 | EventLoopIdleTimerUPP inTimerProc,
|
---|
123 | void * inTimerData,
|
---|
124 | EventLoopTimerRef * outTimer);
|
---|
125 |
|
---|
126 |
|
---|
127 | bool IdlePlatform::init() {
|
---|
128 | // May already be init'ed.
|
---|
129 | if (d->mTimerRef) {
|
---|
130 | return true;
|
---|
131 | }
|
---|
132 |
|
---|
133 | // According to the docs, InstallEventLoopIdleTimer is new in 10.2.
|
---|
134 | // According to the headers, it has been around since 10.0.
|
---|
135 | // One of them is lying. We'll play it safe and weak-link the function.
|
---|
136 |
|
---|
137 | // Load the "Carbon.framework" bundle.
|
---|
138 | CFBundleRef carbonBundle;
|
---|
139 | if (LoadFrameworkBundle( CFSTR("Carbon.framework"), &carbonBundle ) != noErr) {
|
---|
140 | return false;
|
---|
141 | }
|
---|
142 |
|
---|
143 | // Load the Mach-O function pointers for the routine we will be using.
|
---|
144 | InstallEventLoopIdleTimerPtr myInstallEventLoopIdleTimer = (InstallEventLoopIdleTimerPtr)CFBundleGetFunctionPointerForName(carbonBundle, CFSTR("InstallEventLoopIdleTimer"));
|
---|
145 | if (myInstallEventLoopIdleTimer == 0) {
|
---|
146 | return false;
|
---|
147 | }
|
---|
148 |
|
---|
149 | EventLoopIdleTimerUPP timerUPP = NewEventLoopIdleTimerUPP(Private::IdleTimerAction);
|
---|
150 | if ((*myInstallEventLoopIdleTimer)(GetMainEventLoop(), kEventDurationSecond, kEventDurationSecond, timerUPP, 0, &d->mTimerRef)) {
|
---|
151 | return true;
|
---|
152 | }
|
---|
153 |
|
---|
154 | return false;
|
---|
155 | }
|
---|
156 |
|
---|
157 |
|
---|
158 | int IdlePlatform::secondsIdle() {
|
---|
159 | return d->mSecondsIdle;
|
---|
160 | }
|
---|