adium-1.4 3007:12f682d53ecb: Patch from sphynx which fixes handl...
commits at adium.im
commits at adium.im
Mon Aug 16 02:01:10 UTC 2010
details: http://hg.adium.im/adium-1.4/rev/12f682d53ecb
revision: 3007:12f682d53ecb
author: Evan Schoenberg
date: Sun Aug 15 19:24:31 2010 -0500
Patch from sphynx which fixes handling of automatic status triggers when the screensaver is activated via a hot corner and which also fixes handling of screen locking (which is treated as the same as screensaver activation). Fixes #13955. Thanks :)
(transplanted from da8c39de33cebeaea144ffda3a0eae4f720c8b24)
diffs (290 lines):
diff -r e63789abc563 -r 12f682d53ecb Source/AIAutomaticStatus.h
--- a/Source/AIAutomaticStatus.h Sun Aug 15 21:34:25 2010 -0400
+++ b/Source/AIAutomaticStatus.h Sun Aug 15 19:24:31 2010 -0500
@@ -18,11 +18,16 @@
#define AIScreensaverDidStartNotification @"com.apple.screensaver.didstart"
#define AIScreensaverDidStopNotification @"com.apple.screensaver.didstop"
+#define AIScreenLockDidStartNotification @"com.apple.screenIsLocked"
+#define AIScreenLockDidStopNotification @"com.apple.screenIsUnlocked"
+
@interface AIAutomaticStatus : AIPlugin {
NSNumber *fastUserSwitchID;
NSNumber *screenSaverID;
NSNumber *idleID;
+ NSNumber *oldStatusID;
+
NSMutableDictionary *previousStatus;
NSMutableSet *accountsToReconnect;
@@ -34,9 +39,7 @@
double idleReportInterval;
double idleStatusInterval;
- BOOL automaticStatusSet;
- BOOL automaticIdleSet;
- BOOL confirmReturn;
+ unsigned automaticStatusBitMap;
}
@end
diff -r e63789abc563 -r 12f682d53ecb Source/AIAutomaticStatus.m
--- a/Source/AIAutomaticStatus.m Sun Aug 15 21:34:25 2010 -0400
+++ b/Source/AIAutomaticStatus.m Sun Aug 15 19:24:31 2010 -0500
@@ -23,6 +23,13 @@
#import <Adium/AIStatus.h>
#import <Adium/AIStatusGroup.h>
+typedef enum {
+ AIAwayIdle = (1 << 1),
+ AIAwayScreenSaved = (1 << 2),
+ AIAwayScreenLocked = (1 << 3),
+ AIAwayFastUserSwitched = (1 << 4)
+} AIAwayAutomaticType;
+
@interface AIAutomaticStatus ()
- (void)notificationHandler:(NSNotification *)notification;
- (void)triggerAutoAwayWithStatusID:(NSNumber *)statusID;
@@ -34,7 +41,7 @@
*
* Automatically set accounts to certain statuses when events occur. Currently this handles:
* - Fast user switching
- * - Screensaver activation
+ * - Screen(saver|lock) activation
* - Idle time
*/
@implementation AIAutomaticStatus
@@ -82,6 +89,16 @@
name:AIScreensaverDidStopNotification
object:nil];
+ [notificationCenter addObserver:self
+ selector:@selector(notificationHandler:)
+ name:AIScreenLockDidStartNotification
+ object:nil];
+
+ [notificationCenter addObserver:self
+ selector:@selector(notificationHandler:)
+ name:AIScreenLockDidStopNotification
+ object:nil];
+
// Idle events are in the Adium notification center, posted by the AdiumIdleManager
notificationCenter = [NSNotificationCenter defaultCenter];
@@ -116,7 +133,7 @@
[adium.preferenceController unregisterPreferenceObserver:self];
// Revert to our stored statuses
- if (automaticStatusSet) {
+ if (automaticStatusBitMap != 0) {
[self returnFromAutoAway];
}
}
@@ -135,6 +152,8 @@
[screenSaverID release];
[idleID release];
+ [oldStatusID release];
+
[super dealloc];
}
@@ -181,76 +200,99 @@
*
* When a notification comes in, this checks if it's a start or end event
*
- * A start event will set the status, and the end will revert to the previous status.
+ * If this event changes one of the automatic statusses, the user is set again
+ * to the highest priority automatic away status, or if none, returns from autoaway.
+ *
+ * Priorities: Fast User Switch'ed > Screen(saver|lock) > Idle.
*/
- (void)notificationHandler:(NSNotification *)notification
{
NSString *notificationName = [notification name];
- NSNumber *statusID = nil;
- BOOL startEvent = NO, endEvent = NO;
+ unsigned oldBitMap = automaticStatusBitMap;
// Start events
if ([notificationName isEqualToString:NSWorkspaceSessionDidResignActiveNotification]) {
AILogWithSignature(@"Fast user switch (start) detected");
-
- startEvent = fastUserSwitchEnabled;
- statusID = fastUserSwitchID;
+
+ if (fastUserSwitchEnabled) automaticStatusBitMap |= AIAwayFastUserSwitched;
+
} else if ([notificationName isEqualToString:AIScreensaverDidStartNotification]) {
AILogWithSignature(@"Screensaver (start) detected.");
- startEvent = screenSaverEnabled;
- statusID = screenSaverID;
+ if (screenSaverEnabled) automaticStatusBitMap |= AIAwayScreenSaved;
+
} else if ([notificationName isEqualToString:AIMachineIdleUpdateNotification]) {
double duration = [[[notification userInfo] objectForKey:@"Duration"] doubleValue];
- // Update our idle time
- if (!automaticIdleSet && reportIdleEnabled && duration >= idleReportInterval) {
- AILogWithSignature(@"Idle (report) detected.");
+ // This is very spammy when we're already idle.
+ if (duration >= idleStatusInterval && !(automaticStatusBitMap & AIAwayIdle)) {
+ AILogWithSignature(@"Idle (start) detected.");
- automaticIdleSet = YES;
+ if (idleEnabled) automaticStatusBitMap |= AIAwayIdle;
- [adium.preferenceController setPreference:[[notification userInfo] objectForKey:@"IdleSince"]
- forKey:@"IdleSince"
- group:GROUP_ACCOUNT_STATUS];
+ // Update our idle time
+ if (reportIdleEnabled) {
+ [adium.preferenceController setPreference:[[notification userInfo] objectForKey:@"IdleSince"]
+ forKey:@"IdleSince"
+ group:GROUP_ACCOUNT_STATUS];
+ }
}
+ } if ([notificationName isEqualToString:AIScreenLockDidStartNotification]) {
+ AILogWithSignature(@"Screenlock (start) detected.");
- // Idle events require that we've been idle longer than required
- startEvent = (idleEnabled && duration >= idleStatusInterval);
- statusID = idleID;
-
- // This is very spammy when we're already idle.
- if (startEvent && !automaticStatusSet) {
- AILogWithSignature(@"Idle (start) detected.");
- }
+ if (screenSaverEnabled) automaticStatusBitMap |= AIAwayScreenLocked;
}
// End events
if ([notificationName isEqualToString:NSWorkspaceSessionDidBecomeActiveNotification]) {
AILogWithSignature(@"Fast user switch (end) detected.");
- endEvent = fastUserSwitchEnabled;
+ automaticStatusBitMap &= ~AIAwayFastUserSwitched;
+
} else if ([notificationName isEqualToString:AIScreensaverDidStopNotification]) {
AILogWithSignature(@"Screensaver (end) detected.");
+
+ automaticStatusBitMap &= ~AIAwayScreenSaved;
- endEvent = screenSaverEnabled;
} else if ([notificationName isEqualToString:AIMachineIsActiveNotification]) {
- AILogWithSignature(@"Idle (end) detected.");
- if (automaticIdleSet) {
- automaticIdleSet = NO;
+ if (automaticStatusBitMap & AIAwayIdle) {
+ AILogWithSignature(@"Idle (end) detected.");
+ automaticStatusBitMap &= ~AIAwayIdle;
+ }
+
+ if (reportIdleEnabled) {
[adium.preferenceController setPreference:nil
forKey:@"IdleSince"
- group:GROUP_ACCOUNT_STATUS];
+ group:GROUP_ACCOUNT_STATUS];
}
- endEvent = idleEnabled;
+ } else if ([notificationName isEqualToString:AIScreenLockDidStopNotification]) {
+ AILogWithSignature(@"Screenlock (end) detected.");
+
+ automaticStatusBitMap &= ~AIAwayScreenLocked;
}
- if (startEvent && statusID && !automaticStatusSet) {
- [self triggerAutoAwayWithStatusID:statusID];
- } else if (endEvent && automaticStatusSet) {
- [self returnFromAutoAway];
+ // Check if a change in status is required: if so, look for the one with the highest priority
+ if (oldBitMap != automaticStatusBitMap) {
+ NSNumber *statusID = nil;
+
+ if (automaticStatusBitMap & AIAwayFastUserSwitched)
+ statusID = fastUserSwitchID;
+
+ else if ((automaticStatusBitMap & AIAwayScreenLocked)
+ || (automaticStatusBitMap & AIAwayScreenSaved))
+ statusID = screenSaverID;
+
+ else if (automaticStatusBitMap & AIAwayIdle)
+ statusID = idleID;
+
+ else
+ [self returnFromAutoAway];
+
+ if (statusID)
+ [self triggerAutoAwayWithStatusID:statusID];
}
}
@@ -266,27 +308,30 @@
{
AIStatusItem *targetStatusState = [adium.statusController statusStateWithUniqueStatusID:statusID];
- // Grab any group memeber if possible
+ // Grab any group member if possible
if ([targetStatusState isKindOfClass:[AIStatusGroup class]]) {
targetStatusState = [(AIStatusGroup *)targetStatusState anyContainedStatus];
}
- // If we weren't given a valid state, fail.
- if (!targetStatusState) {
+ // If we weren't given a valid and new state, fail.
+ if (!targetStatusState || [oldStatusID isEqualToNumber:statusID]) {
return;
}
for (AIAccount *account in adium.accountController.accounts) {
AIStatus *currentStatusState = account.statusState;
- // Don't modify or store the status of non-available accounts
- if (currentStatusState.statusType != AIAvailableStatusType) {
- continue;
- }
-
- // Store the state of the account
- [previousStatus setObject:currentStatusState
- forKey:[NSNumber numberWithUnsignedInt:[account hash]]];
+// Store the state of the account if there is no previous one saved
+ if (![previousStatus objectForKey:[NSNumber numberWithUnsignedInteger:[account hash]]]) {
+
+ // Don't modify or store the status of (originally!) non-available accounts
+ if (currentStatusState.statusType != AIAvailableStatusType) {
+ continue;
+ }
+
+ [previousStatus setObject:currentStatusState
+ forKey:[NSNumber numberWithUnsignedInteger:[account hash]]];
+ }
AILogWithSignature(@"Setting %@ to status %@", account, targetStatusState);
@@ -303,7 +348,8 @@
}
}
- automaticStatusSet = YES;
+ [oldStatusID release];
+ oldStatusID = [statusID retain];
}
/*!
@@ -335,7 +381,10 @@
[accountsToReconnect removeAllObjects];
[previousStatus removeAllObjects];
- automaticStatusSet = NO;
+ automaticStatusBitMap = 0;
+
+ [oldStatusID release];
+ oldStatusID = nil;
}
@end
More information about the commits
mailing list