環境設定パネルから常駐プログラムを制御する時の覚え書き、その4。
PFKeyAvailerPrefは、ファンクションキーにアプリケーションや書類を登録して、キー一発で起動できるようにするシステム環境設定パネルです。
その1の動作概要に沿って具体的な処理を記載します。
今回は、「終了時の流れ」です。
PFKeyAvailerPrefでファンクションキーをホットキーとして使用するのを停止する時の処理と、PFKeyAvailerPrefをシステム環境設定から削除する時の処理は、以下のとおりです。
3 終了時の流れ
3.1(PFKeyAvailerXdの停止)
PFKeyAvailerPrefの「ファンクションキーを有効にする」のチェックボックスからチェックが外された時の処理です。
ホットキーの登録を削除します。
3.1.1 ユーザーが、システム環境設定上でPFKeyAvailerPref起動する。
3.1.2 ユーザーが、「ファンクションキーを有効にする」のチェックボックスのチェックを外す。
PFKeyAvailerPrefの「ファンクションキーを有効にする」のチェックボックスからチェックを外すとバインドされたアクション myAvailBox: が呼ばれます。
ソース:PFKeyAvailerXPrefPref.m
// ファンクションキー有効/無効チェックボックス
- (IBAction)myAvailBox:(id)sender
{
// 初期設定ファイルに書き込み
[myData1 setKeyAvailOnOffState:[keyAvail state]];
if ( [sender state] == NSOnState ) {
[self start_daemon];// PFKeyAvailerXdを起動する
[self register_startup_daemon]; // 起動項目にPFKeyAvailerXdを登録する
} else {
[self unregister_startup_daemon];// 起動項目からPFKeyAvailerXdを削除する
[self quit_daemon]; // PFKeyAvailerXdを終了させる
}
}
まず、チェックボックスのチェックが外れた(NSOffState)ことを初期設定ファイルに記録します。
次に、else 以降の処理を行います。まず、起動項目からPFKeyAvailerXdを削除し、次にPFKeyAvailerXdを終了させます(次項以降の処理)。 …説明と順番が逆ですが(^^;
3.1.3 PFKeyAvailerPrefが、PFKeyAvailerXdを終了させる。
ソース:PFKeyAvailerXPrefPref.m
// PFKeyAvailerXdを終了させる
- (void)quit_daemon
{
// killallだとデーモンのapplicationWillTerminate:が呼ばれないので、
// AppleScriptでPFKeyAvailerXdを終了させる
NSMutableString *script2 = [[[NSMutableString alloc] initWithString:@"tell application \"PFKeyAvailerXd\"\n Quit\n end tell"] autorelease];
{
NSDictionary *asErrDic = nil; // エラー情報
NSAppleScript *as = [[[ NSAppleScript alloc ] initWithSource : script2 ] autorelease]; // 初期化
[ as executeAndReturnError : &asErrDic ];// 実行
}
}
AppleScriptで、PFKeyAvailerXd に Quit を送り終了させています。
アプリケーションを終了させるのにUnixのkillallコマンドを使うことも出来ますが、killallで終了させるとPFKeyAvailerXdのデリゲートのapplicationWillTerminate: が呼ばれないので、ここではAppleScriptを使用しています。
PFKeyAvailerXdのデリゲートでは、ホットキーの削除処理を行っています。
3.1.4 PFKeyAvailerPrefが、ユーザーの起動項目のPFKeyAvailerXdを削除する。
AppleScriptで、カレントユーザーの起動項目からPFKeyAvailerXdを削除します。
ソース:PFKeyAvailerXPrefPref.m
// AppleScriptで起動項目からPFKeyAvailerXdを削除する
- (void)unregister_startup_daemon
{
NSMutableString *script;
script = [[[NSMutableString alloc] initWithString:@"tell application \"System Events\"\n delete login item \"PFKeyAvailerXd\"\n end tell"] autorelease];
{
NSDictionary *asErrDic = nil; // エラー情報
NSAppleScript *as = [[[ NSAppleScript alloc ] initWithSource : script ] autorelease]; // 初期化
[ as executeAndReturnError : &asErrDic ];// 実行
}
3.2(PFKeyAvailerPrefの削除)
PFKeyAvailerPrefがシステム環境設定から削除された時の処理です。
システム環境設定からの環境設定パネルの削除は、すべてを表示させている状態で削除対象の環境設定パネルを右クリックして、コンテキストメニューから「"PFKeyAvailer"環境設定パネルを取り除く」を実行します。
※ここでのポイントは、上記削除時にはPFKeyAvailerPrefは起動しておらず、自分が削除されたことが認識できない!ということです。
つまり、常駐ファイルであるPFKeyAvailerXdを終了させてくれる人が居なくなるということになります。
このため、PFKeyAvailerXd自身が環境設定パネルが削除されたことを感知して、自分自身を終了させる必要があります。
(もちろん、PFKeyAvailerPrefを削除する前に、チェックボックスからチェックを外してPFKeyAvailerXdを終了すれば問題ないのですが、そこまでユーザーにお願いするのは酷だと思います)
3.2.1 ユーザーが、システム環境設定からPFKeyAvailerPrefを削除する。
3.2.2 PFKeyAvailerXdが常駐していなければ終わり。
3.2.3 PFKeyAvailerXdが常駐している場合は、PFKeyAvailerXdがシステム環境設定からPFKeyAvailerPrefが削除されたことを感知して、ユーザーの起動項目からPFKeyAvailerXdを削除する。
デリゲートの applicationDidFinishLaunching: にシステム環境設定からPFKeyAvailerPrefが削除されたかどうかをチェックするための繰り返しタイマーを登録しておきます。
ソース:PFKeyAvailerXdAppDelegate.m
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
~~~~
// システム環境設定からPFKeyAvailerPrefが削除されたかどうかをチェックためのタイマー
_tmTimer = [NSTimer scheduledTimerWithTimeInterval:CHECK_INTERVAL
target:self
selector:@selector(checkPrefExist)
userInfo:nil
repeats:YES];
~~~~
}
タイマーによって、 checkPrefExist が一定時間毎に呼び出されます。
ソース:PFKeyAvailerXdAppDelegate.m
// NSTimerからのイベント処理
- (void)checkPrefExist
{
NSString *fpath;
fpath = [self getPrefFilePath:kPref];
if ( fpath == nil ) {
// AppleScriptで起動項目からPFKeyAvailerXdを削除する
[self unregister_startup_daemon];
// 初期設定をファンクションキー未使用に設定
[myData1 setPref_NoUse];
// 自分自身を終了させる
[NSApp terminate:self];
}
return;
}
まず、PFKeyAvailerPrefのファイルパスを取得します。
[self getPrefFilePath:] では、PFKeyAvailerPrefが特定ユーザーのみにインストールされている場合と、すべのユーザーにインストールされている場合の両方のファイルパスでのPFKeyAvailerPrefの存在確認を[[NSFileManager defaultManager] fileExistsAtPath:fpath] で行い、PFKeyAvailerPrefが存在すればそのフルパスを、無ければnilを返します。
[self getPrefFilePath:] で nil が返却された時は、PFKeyAvailerPrefが存在しない(=システム環境設定から削除された)ため、次の処理を行います。
まず、AppleScriptで起動項目からPFKeyAvailerXdを削除します。
次に、チェックボックスのチェックが外された状態(NSOffState)を初期設定ファイルに記録します。
3.2.4 PFKeyAvailerXd自身を終了させる。
最後に、PFKeyAvailerXd自身を終了させます。