When a user switch occurs, Mac OS X generates events for all interested applications. Events are sent to applications in a login session whenever the login session is activated or deactivated. If a login session is not being activated or deactivated, it receives no events. You can use the activation events to perform the following kinds of tasks:
Halt or restart sound playback
Halt or restart animations
Give up or acquire shared resources
Put your application into a quiescent state to improve overall system performance
Carbon Notifications
Cocoa Notifications
Event Timing
Shutdown Notifications
For Carbon applications, user switch notifications come through the Carbon Event Manager. Applications can register to receive the kEventSystemUserSessionActivated
and kEventSystemUserSessionDeactivated
events if they want to know when a switch occurs. The following example shows you how to register for these events:
pascal OSStatus switchEventsHandler (EventHandlerCallRef nextHandler, |
EventRef switchEvent, |
void* userData) |
{ |
if (GetEventKind(switchEvent)== kEventSystemUserSessionDeactivated) |
{ |
// Perform deactivation tasks here. |
} |
else |
{ |
// Perform activation tasks here. |
} |
return noErr; |
} |
void SwitchEventsRegister() |
{ |
EventTypeSpec switchEventTypes[2]; |
EventHandlerUPP switchEventHandler; |
switchEventTypes[0].eventClass = kEventClassSystem; |
switchEventTypes[0].eventKind = kEventSystemUserSessionDeactivated; |
switchEventTypes[1].eventClass = kEventClassSystem; |
switchEventTypes[1].eventKind = kEventSystemUserSessionActivated; |
switchEventHandler = NewEventHandlerUPP(switchEventsHandler); |
InstallApplicationEventHandler(switchEventHandler, 2, |
switchEventTypes, NULL, NULL); |
} |
For Cocoa applications, user switch notifications come through the NSWorkspace shared notification center. The user-switch events themselves are defined in NSWorkspace and are NSWorkspaceSessionDidBecomeActiveNotification
and NSWorkspaceSessionDidResignActiveNotification
. To register for these notifications, your application (or its delegate) would provide a handler method and then register that handler by adding itself as an observer of the notification. The following sample methods illustrate how to do this:
- (void) switchHandler:(NSNotification*) notification |
{ |
if ([[notification name] isEqualToString: |
NSWorkspaceSessionDidResignActiveNotification]) |
{ |
// Perform deactivation tasks here. |
} |
else |
{ |
// Perform activation tasks here. |
} |
} |
// Register the handler |
- (void) applicationDidFinishLaunching:(NSNotification*) aNotification |
{ |
[[[NSWorkspace sharedWorkspace] notificationCenter] |
addObserver:self |
selector:@selector(switchHandler:) |
name:NSWorkspaceSessionDidBecomeActiveNotification |
object:nil]; |
[[[NSWorkspace sharedWorkspace] notificationCenter] |
addObserver:self |
selector:@selector(switchHandler:) |
name:NSWorkspaceSessionDidResignActiveNotification |
object:nil]; |
} |
User switch notifications are sent to applications at the same time the switch occurs. Because the switch occurs relatively quickly, this is normally not a problem. However, it is possible for an application to receive its activation event before other applications have received their deactivation events. This could lead to potential race conditions between applications releasing and acquiring shared resources.
To avoid race conditions, applications in the session being deactivated should continue to release any shared resources as soon as possible. Applications in the session being activated should delay the acquisition of any shared resources until those resources are actually used. Not only can this help avoid potential race conditions, it can also improve overall system performance. If your application needs a particular resource right away but encounters errors while trying to acquire it, set a timer and try to acquire the resource again a short time later.
Shutdown and restart sequences do not generate any special notifications to switched out login sessions. Without fast user switching enabled, the normal sequence is to notify the user’s applications about the impending termination and give them a chance to abort the sequence. However, with fast user switching enabled, only the applications for the active user are prompted. Applications in switched out login sessions are killed without the chance to save any changes; otherwise, there is the potential that a process in one of those sessions could hang the system.
If other users are logged in, the system warns the initiator of a shutdown or restart sequence that those users might lose unsaved changes. This warning only appears when other users are logged in. The user is prompted for an administrative password to ensure that there is a good reason to shutdown or restart the machine. As long as the user has a valid administrator password, the sequence proceeds.
For more information about the shutdown and restart sequence for the active login session, see System Startup Programming Topics.
© 2003, 2005 Apple Computer, Inc. All Rights Reserved. (Last updated: 2005-07-07)