KUtils
macpoller.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2009 Dario Freddi <drf at kde.org> 00003 Copyright (C) 2003 Tarkvara Design Inc. (from KVIrc source code) 00004 Copyright (c) 2008 Roman Jarosz <kedgedev at centrum.cz> 00005 Copyright (c) 2008 the Kopete developers <kopete-devel at kde.org> 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License version 2 as published by the Free Software Foundation. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 Boston, MA 02110-1301, USA. 00020 */ 00021 00022 #include "macpoller.h" 00023 00024 // Why does Apple have to make this so complicated? 00025 static OSStatus LoadFrameworkBundle(CFStringRef framework, CFBundleRef *bundlePtr) 00026 { 00027 OSStatus err; 00028 FSRef frameworksFolderRef; 00029 CFURLRef baseURL; 00030 CFURLRef bundleURL; 00031 00032 if (bundlePtr == nil) 00033 return(-1); 00034 00035 *bundlePtr = nil; 00036 00037 baseURL = nil; 00038 bundleURL = nil; 00039 00040 err = FSFindFolder(kOnAppropriateDisk, kFrameworksFolderType, true, &frameworksFolderRef); 00041 if (err == noErr) { 00042 baseURL = CFURLCreateFromFSRef(kCFAllocatorSystemDefault, &frameworksFolderRef); 00043 if (baseURL == nil) 00044 err = coreFoundationUnknownErr; 00045 } 00046 00047 if (err == noErr) { 00048 bundleURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, baseURL, framework, false); 00049 if (bundleURL == nil) 00050 err = coreFoundationUnknownErr; 00051 } 00052 00053 if (err == noErr) { 00054 *bundlePtr = CFBundleCreate(kCFAllocatorSystemDefault, bundleURL); 00055 if (*bundlePtr == nil) 00056 err = coreFoundationUnknownErr; 00057 } 00058 00059 if (err == noErr) { 00060 if (!CFBundleLoadExecutable(*bundlePtr)) 00061 err = coreFoundationUnknownErr; 00062 } 00063 00064 // Clean up. 00065 if (err != noErr && *bundlePtr != nil) { 00066 CFRelease(*bundlePtr); 00067 *bundlePtr = nil; 00068 } 00069 00070 if (bundleURL != nil) 00071 CFRelease(bundleURL); 00072 00073 if (baseURL != nil) 00074 CFRelease(baseURL); 00075 00076 return err; 00077 } 00078 00079 pascal void MacPoller::IdleTimerAction(EventLoopTimerRef, EventLoopIdleTimerMessage inState, void* inUserData) 00080 { 00081 Q_ASSERT(inUserData); 00082 switch (inState) { 00083 case kEventLoopIdleTimerStarted: 00084 case kEventLoopIdleTimerStopped: 00085 // Get invoked with this constant at the start of the idle period, 00086 // or whenever user activity cancels the idle. 00087 ((MacPoller*)inUserData)->m_secondsIdle = 0; 00088 ((MacPoller*)inUserData)->triggerResume(); 00089 break; 00090 case kEventLoopIdleTimerIdling: 00091 // Called every time the timer fires (i.e. every second). 00092 ((MacPoller*)inUserData)->m_secondsIdle++; 00093 ((MacPoller*)inUserData)->poll(); 00094 break; 00095 } 00096 } 00097 00098 // Typedef for the function we're getting back from CFBundleGetFunctionPointerForName. 00099 typedef OSStatus(*InstallEventLoopIdleTimerPtr)(EventLoopRef inEventLoop, 00100 EventTimerInterval inFireDelay, 00101 EventTimerInterval inInterval, 00102 EventLoopIdleTimerUPP inTimerProc, 00103 void * inTimerData, 00104 EventLoopTimerRef * outTimer); 00105 00106 MacPoller::MacPoller(QWidget *parent) 00107 : AbstractSystemPoller(parent) 00108 , m_timerRef(0) 00109 , m_secondsIdle(0) 00110 , m_catch(false) 00111 { 00112 } 00113 00114 MacPoller::~MacPoller() 00115 { 00116 } 00117 00118 void MacPoller::unloadPoller() 00119 { 00120 RemoveEventLoopTimer(m_timerRef); 00121 } 00122 00123 bool MacPoller::isAvailable() 00124 { 00125 return true; 00126 } 00127 00128 bool MacPoller::setUpPoller() 00129 { 00130 // May already be init'ed. 00131 if (m_timerRef) { 00132 return true; 00133 } 00134 00135 // According to the docs, InstallEventLoopIdleTimer is new in 10.2. 00136 // According to the headers, it has been around since 10.0. 00137 // One of them is lying. We'll play it safe and weak-link the function. 00138 00139 // Load the "Carbon.framework" bundle. 00140 CFBundleRef carbonBundle; 00141 00142 if (LoadFrameworkBundle(CFSTR("Carbon.framework"), &carbonBundle) != noErr) { 00143 return false; 00144 } 00145 00146 // Load the Mach-O function pointers for the routine we will be using. 00147 InstallEventLoopIdleTimerPtr myInstallEventLoopIdleTimer = 00148 (InstallEventLoopIdleTimerPtr)CFBundleGetFunctionPointerForName(carbonBundle, CFSTR("InstallEventLoopIdleTimer")); 00149 00150 if (myInstallEventLoopIdleTimer == 0) { 00151 return false; 00152 } 00153 00154 EventLoopIdleTimerUPP timerUPP = NewEventLoopIdleTimerUPP(IdleTimerAction); 00155 if ((*myInstallEventLoopIdleTimer)(GetMainEventLoop(), kEventDurationSecond, kEventDurationSecond, timerUPP, this, &m_timerRef)) { 00156 return true; 00157 } 00158 00159 return false; 00160 } 00161 00162 QList<int> MacPoller::timeouts() const 00163 { 00164 return m_timeouts; 00165 } 00166 00167 void MacPoller::addTimeout(int nextTimeout) 00168 { 00169 m_timeouts.append(nextTimeout); 00170 poll(); 00171 } 00172 00173 int MacPoller::poll() 00174 { 00175 int idle = m_secondsIdle * 1000; 00176 00177 // Check if we reached a timeout.. 00178 foreach(int i, m_timeouts) { 00179 if ((i - idle < 1000 && i > idle) || (idle - i < 1000 && idle > i)) { 00180 // Bingo! 00181 emit timeoutReached(i); 00182 } 00183 } 00184 00185 return idle; 00186 } 00187 00188 int MacPoller::forcePollRequest() 00189 { 00190 return poll(); 00191 } 00192 00193 void MacPoller::removeTimeout(int timeout) 00194 { 00195 m_timeouts.removeOne(timeout); 00196 poll(); 00197 } 00198 00199 void MacPoller::catchIdleEvent() 00200 { 00201 m_catch = true; 00202 } 00203 00204 void MacPoller::stopCatchingIdleEvents() 00205 { 00206 m_catch = false; 00207 } 00208 00209 void MacPoller::triggerResume() 00210 { 00211 if (m_catch) { 00212 emit resumingFromIdle(); 00213 stopCatchingIdleEvents(); 00214 } 00215 } 00216 00217 void MacPoller::simulateUserActivity() 00218 { 00219 // TODO 00220 } 00221 00222 #include "macpoller.moc"
KDE 4.7 API Reference