William Bowling is sharing code with you
Bitbucket is a code hosting site. Unlimited public and private repositories. Free for small teams.
Don't show this again1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | //
// AdiumIdleManager.m
// Adium
//
// Created by Evan Schoenberg on 7/5/05.
//
#import "AdiumIdleManager.h"
#import "AIStatusController.h"
#define MACHINE_IDLE_THRESHOLD 30 //30 seconds of inactivity is considered idle
#define MACHINE_ACTIVE_POLL_INTERVAL 30 //Poll every 30 seconds when the user is active
#define MACHINE_IDLE_POLL_INTERVAL 1 //Poll every second when the user is idle
@interface AdiumIdleManager ()
- (void)_setMachineIsIdle:(BOOL)inIdle;
- (void)screenSaverDidStart;
- (void)screenSaverDidStop;
@end
/*!
* @class AdiumIdleManager
* @brief Core class to manage sending notifications when the system is idle or no longer idle
*
* Posts AIMachineIsIdleNotification to adium's notification center when the machine becomes idle.
* Posts AIMachineIsActiveNotification when the machine is no longer idle
* Posts AIMachineIdleUpdateNotification periodically while idle with an NSDictionary userInfo
* containing an NSNumber double value @"Duration" (a CFTimeInterval) and an NSDate @"IdleSince".
*/
@implementation AdiumIdleManager
/*!
* @brief Initialize
*/
- (id)init
{
if ((self = [super init])) {
[self _setMachineIsIdle:NO];
[[NSDistributedNotificationCenter defaultCenter] addObserver:self
selector:@selector(screenSaverDidStart)
name:@"com.apple.screensaver.didstart"
object:nil];
[[NSDistributedNotificationCenter defaultCenter] addObserver:self
selector:@selector(screenSaverDidStop)
name:@"com.apple.screensaver.didstop"
object:nil];
}
return self;
}
/*!
* @brief Returns the current machine idle time
*
* Returns the current number of seconds the machine has been idle. The machine is idle when there are no input
* events from the user (such as mouse movement or keyboard input) or when the screen saver is active.
* In addition to this method, the status controller sends out notifications when the machine becomes idle,
* stays idle, and returns to an active state.
*/
- (CFTimeInterval)currentMachineIdle
{
return CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGAnyInputEventType);
}
/*!
* @brief Timer that checkes for machine idle
*
* This timer periodically checks the machine for inactivity. When the machine has been inactive for atleast
* MACHINE_IDLE_THRESHOLD seconds, a notification is broadcast.
*
* When the machine is active, this timer is called infrequently. It's not important to notice that the user went
* idle immediately, so we relax our CPU usage while waiting for an idle state to begin.
*
* When the machine is idle, the timer is called frequently. It's important to notice immediately when the user
* returns.
*/
- (void)_idleCheckTimer:(NSTimer *)inTimer
{
CFTimeInterval currentIdle = [self currentMachineIdle];
if (machineIsIdle) {
if (currentIdle < lastSeenIdle) {
/* If the machine is less idle than the last time we recorded, it means that activity has occured and the
* user is no longer idle.
*/
[self _setMachineIsIdle:NO];
} else {
//Periodically broadcast a 'MachineIdleUpdate' notification
[[NSNotificationCenter defaultCenter] postNotificationName:AIMachineIdleUpdateNotification
object:nil
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithDouble:currentIdle], @"Duration",
[NSDate dateWithTimeIntervalSinceNow:-currentIdle], @"IdleSince",
nil]];
}
} else {
//If machine inactivity is over the threshold, the user has gone idle.
if (currentIdle > MACHINE_IDLE_THRESHOLD) [self _setMachineIsIdle:YES];
}
lastSeenIdle = currentIdle;
}
/*!
* @brief Sets the machine as idle or not
*
* This internal method updates the frequency of our idle timer depending on whether the machine is considered
* idle or not. It also posts the AIMachineIsIdleNotification and AIMachineIsActiveNotification notifications
* based on the passed idle state
*/
- (void)_setMachineIsIdle:(BOOL)inIdle
{
machineIsIdle = inIdle;
//Post the appropriate idle or active notification
if (machineIsIdle) {
[[NSNotificationCenter defaultCenter] postNotificationName:AIMachineIsIdleNotification object:nil];
} else {
[[NSNotificationCenter defaultCenter] postNotificationName:AIMachineIsActiveNotification object:nil];
}
//Update our timer interval for either idle or active polling
[idleTimer invalidate];
[idleTimer release];
idleTimer = [[NSTimer scheduledTimerWithTimeInterval:(machineIsIdle ? MACHINE_IDLE_POLL_INTERVAL : MACHINE_ACTIVE_POLL_INTERVAL)
target:self
selector:@selector(_idleCheckTimer:)
userInfo:nil
repeats:YES] retain];
}
/*!
* @brief Called by the screen saver when it starts
*
* When the screen saver starts, we set ourself to idle.
*/
- (void)screenSaverDidStart
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[self _setMachineIsIdle:YES];
[pool release];
}
/*!
* @brief Called by the screen saver when it starts
*
* When the screen saver stops, we set ourself to active.
*/
- (void)screenSaverDidStop
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[self _setMachineIsIdle:NO];
[pool release];
}
@end
|