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