ユーザ切り替えの通知


ユーザ切り替え【user switch】が発生したとき、Mac OS Xは興味を持つすべてのアプリケーションに対してイベントを生成します。イベントは、ログインセッションがアクティブか非アクティブかに関わらず、ログインセッション内のアプリケーションへ送信されます。もしログインセッションがアクティブ化または非アクティブ化されていなければ、イベントを受信することはありません。あなたは以下の種類の作業を行うために、アクティブ化イベントを利用できます…

  • サウンド再生の停止、または再開
  • アニメーションの停止、または再開
  • 共有リソースの開放、または獲得
  • 全体的なシステムの性能を向上するために、あなたのアプリケーションを停止【quiescent】状態にする

Carbon通知

Carbonアプリケーションに対しては、ユーザ切り替えの通知はCarbon Event Managerを通じてやってきます。アプリケーションは、いつ切り替えが発生したのかを知りたければ、kEventSystemUserSessionActivated および kEventSystemUserSessionDeactivated イベントを受け取るために登録することができます。以下の例は、これらのイベントのための登録をどのように行うかを示します…

pascal OSStatus switchEventsHandler(EventHandlerCallRef nextHandler, 
	EventRefswitchEvent, 
	void*userData) 
{ 
	if (GetEventKind(switchEvent) == kEventSystemUserSessionDeactivated) 
	{ 
		// ここで非アクティブ化処理を行います。
	} 
	else 
	{ 
		// ここでアクティブ化処理を行います。
	} 	
	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); 
} 

Cocoa通知

Cocoaアプリケーションに対しては、ユーザ切り替えの通知は NSWorkspace 共有通知センター【shared notification center】 を通じてやってきます。ユーザ切り替えイベントそのものは NSWorkspace で定義されており、NSWorkspaceSessionDidBecomeActiveNotification と NSWorkspaceSessionDidResignActiveNotification があります。これらの通知のために登録するには、あなたのアプリケーション(またはそのデリゲート)がハンドラメソッドを提供し、さらにそれ自体を通知のオブザーバとして追加することでハンドラを登録します。以下のサンプルメソッドは、これをどのように行うかを示しています…

- (void) switchHandler:(NSNotification*) notification 
{ 
	if ([[notification name] isEqualToString: 
		NSWorkspaceSessionDidResignActiveNotification]) 
	{ 
		// ここで非アクティブ化処理を行います。
	} 
	else 
	{ 
		// ここでアクティブ化処理を行います。
	} 
} 

// ハンドラを登録
- (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]; 
} 

イベントのタイミング

ユーザ切り替え通知は、切り替えが発生すると同時にアプリケーションへ送信されます。切り替えは比較的高速に発生するため、これは通常問題となることはありません。

けれども、他のアプリケーションが非アクティブ化イベントを受信する前に、あるアプリケーションがアクティブ化イベントを受信してしまう可能性は存在します。これは共有リソースを開放しようとするアプリケーションと、獲得しようとするアプリケーションとの間で、潜在的な競合状態をもたらすことがあります。

競合状態を回避するためには、非アクティブ化されているセッション内のアプリケーションは、あらゆる共有リソースを可及的速やかに開放し続けるべきです。アクティブ化されているセッション内のアプリケーションは、実際に必要となるまで、共有リソースの獲得を遅らせるべきです。

これは競合状態の可能性を避けるために役立つのみならず、全体的なシステムの性能を向上させることもできます。もしあなたのアプリケーションが、特定のリソースを今すぐ必要としているのに、それを獲得しようとする間にエラーに出くわした場合は、タイマをセットしてから、短い時間を置いて、再度そのリソースの獲得を試みてください。

シャットダウンの通知

シャットダウンと再起動のシーケンス【手順】は、切り替えられたログインセッションに対する特別な通知は何も発行しません。

ファストユーザスイッチを有効にしていない、通常のシーケンスは、終了が差し迫っており、シーケンスを中断する機会が与えられることについて、ユーザのアプリケーションへ通知するためのものです。

けれども、ファストユーザスイッチが有効な場合、アクティブユーザのためのアプリケーションだけが【終了を】促されます。

切り替えられたログインセッション内のアプリケーションは、変更を保存する機会を与えられずに殺されます。その一方、こうしたセッションの一つにあるプロセスは、システムをハングさせる可能性があります。

もし他のユーザがログインしていたら、システムはシャットダウンまたは再起動のシーケンスを開始した者に対して、これらのユーザは保存していない変更を失うかもしれないという警告を行います。この警告は、他のユーザがログインしていたときにのみ現れます。

ユーザはマシンをシャットダウンもしくは再起動するために正当な理由があることを保証するために、管理者パスワードの入力を促されます。ユーザが有効な管理者パスワードを持ってさえいれば、シーケンスは続行します。

アクティブなログインセッションに対するシャットダウンと再起動のシーケンスに関する詳細は、System Startup Programming Topicsを参照してください。