OSX アプリで option キーを押しながらボタンが押されたことを検出する

Swift プログラミング

OSX アプリのプログラミングで、ボタンを普通にクリックしたときと option キーを押しながらクリックしたときとで異なる挙動をさせる方法を調べてみました。


OSX アプリを作っていて、ボタンを 普通にクリック したときと option キーを押しながらクリック したときとで少し異なる挙動をさせたくなったので、実装してみることにしました。

例えば ViewControllerview 上に配置したボタンをクリックしたときに option キーが押されていたかによって処理を切り替えてみます。

現在の修飾キーを調べる

option キーが押されているかを判定するには、NSEvent が持っている静的プロパティー modifierFlags を参照することで、そのときに押されている修飾キーを取得できる様子でした。

if NSEvent.modifierFlags.contains(.option) {

}
else {

}

修飾キーが押されたことを検出する

そのほかにも、NSResponder を継承ているコンポーネントで修飾キーの状態を知りたい場合には、NSResponder が持っている flagsChanged メソッドを使うことで修飾キーの変化を監視することもできる様子でした。

たとえば、ボタンが配置されている ViewController でこれを行うことで、修飾キーの監視を行えるようです。

class ViewController : NSViewController {

	private var modifierFlags: NSEvent.modifierFlags = []

	override func flagsChanged(with event: NSEvent) {

		self.modifierFlags = event.modifierFlags
		super.flagsChanged(event)
	}
}

たとえばこんな感じにして、修飾キーの変化を self.modifierFlags に随時確保しておくようにします。

ちなみにこの時、修飾キーの変化を受け取るためには、このビューコントローラーがキーの入力を受け入れられる状態になっている必要があります。これが管理しているビュー上のテキストフィールドが入力状態になっているような場合は、普通はそこでの修飾キーの変化がコントローラーにも伝わってきてちゃんと把握できる様子です。

ただし、もしキー入力を受け付けているコントロールで flagsChanged がオーバーライドされていて、その中で親の flagsChanged が呼び出されていない場合は、修飾キーの変化がコントローラーまで伝わってこなかったりするので注意が必要です。

現在の修飾キーの状態に合わせて処理を切り替える

修飾キーの変化さえ把握できれば、後は普通にボタンが押されたときに状況に合わせて処理を切り替えてあげます。

extension ViewController {

	@IBAction func buttonPushed(sender: AnyObject) {

		if modifierFlags.contains(.option) {

		}
		else {

		}
	}
}

判定できる修飾キー

修飾キーの状態は NSEventModifierFlags で規定されていて、次の修飾キーの変化を捉えられるようになっています。

識別子 対象の修飾キー
ModifierFlags.capsLock caps lock キーが ON の状態でセットされます。
ModifierFlags.shift shift キーが押されている状態でセットされます。
ModifierFlags.control control キーが押されている状態でセットされます。
ModifierFlags.option option キーが押されている状態でセットされます。
ModifierFlags.command command キーが押されている状態でセットされます。
ModifierFlags.numericPad テンキーを押した時に添えられる修飾キーですが、単純に Num Lock キーが ON になっているかを検出することはできない様子です。
ModifierFlags.help help キーが押されている状態でセットされるものらしいのですが、肝心の help キーがキーボードに見当たらなくて試せませんでした。
ModifierFlags.function F5 などのファンクションキーを押した時に添えられる修飾キーですが、単純に fn キーが押されたかを検出することはできない様子です。
ModifierFlags.deviceIndependentFlagsMask ハードウェアに固有の修飾キーが押されたことを検出するのに使うものらしいです。

ひとつのキーボードに同じ修飾キーが複数ある場合は、片方が押された状態でもう片方を押しても 変化した と認識される様子です。

また、複数のキーボードで修飾キーを操作したときにも、たとえば片方のキーボードで shift キーを押したままもう片方のキーボードで shift キーを押すと、改めてshift キーが押されたという状況になります。ここまではキーボードが1つの場合と同じなのですが、ここで片方の shift キーを離すともう片方の shift キーが押されているのにshift キーが押されていないという状態になるみたいなので、もしかすると気をつけたいところかもしれません。