Macアプリでグローバルホットキーを使用する


Macアプリケーションを作成する際、通常のアプリメニューに登録できるホットキー以外のホットキーを使用したい場合があります。
また、常駐アプリ等メニューを持たないアプリケーションに関してはホットキーを使用するためにはを全てアプリケーション側で管理する必要があります。

今までこのような時は自身で実装するかPTHotKeyを使用するのが一般的だったかと思います。
しかし、この PTHotKey は長らくメンテナンスされておらず、各アプリがソースコードをコピーし独自改造が加えられて使用されていたりと新規で使用する際かなりの問題点がありました。

ここ最近Macアプリを作成する人が増えてきた中、このような基本となるライブラリがないため作成を諦めてしまうのはもったいないですし、iosのようにmacOS周辺ライブラリを増やすため、swiftを使用したホットキーを使用するためのライブラリを作成しました。

本ライブラリはClipyを作成する上で使用した物をライブラリとして切り出したものです。
Clipyの開発については少し古いですがこちらのQiitaの記事を参照ください。

Magnet.framework

リポジトリ: Clipy/Magnet

基本的な使用方法はPTHotKeyに準拠しましたが、わかりずらいCarbonCocoaフレームワークの違いを明確にし、Alfredのショートカットのような修飾キーダブルタップのホットキーにも対応しています。

下記のような簡単な登録を行うことでアプリにホットキーを導入することができます。
また、本ライブラリはSanbox環境にも対応していますので、AppStoreで配布するアプリにも使用することができます。

使用方法

+ Control + B のホットキーを登録する場合は以下のような形となります。
キーコードに関してはstackoverflow等を参考にしてください。

if let keyCombo = KeyCombo(keyCode: 11, carbonModifiers: 4352) {
   let hotKey = HotKey(identifier: "CommandControlB", keyCombo: keyCombo, target: self, action: #selector())
   hotKey.register() // or HotKeyCenter.shared.register(with: hotKey)
}

Carbonの修飾キーだけでなく、CocoaNSEventModifierFlags にも対応しています。
上記のKeyComboを書き換えるとこのように書くことができます。

let keyCombo = KeyCombo(keyCode: 11, cocoaModifiers: [.command, .control])

ダブルタップ

ダブルタップのホットキーを登録する場合は以下のような形となります。

if let keyCombo = KeyCombo(doubledCarbonModifiers: cmdKey) {
   let hotKey = HotKey(identifier: "CommandDobuleTap", keyCombo: keyCombo, target: self, action: #selector())
   hotKey.register()
}

同様にCocoaではこのように書き換えることができます。

keyCombo = KeyCombo(doubledCocoaModifiers: .command)

ホットキーの登録

内部的にはホットキーの管理をidentifierを使用しておこなっています。
複数のホットキーを使用する場合はこのidentifierが重複しないように注意してください。

keyCodeに関して現状数値のみでしか入力できませんが、将来的にはenumや文字で入力できるようにする予定です。

KeyHolder.framework

PTHotKeyとよく同時に使用されていたものにshortcutrecorderShortcutRecorder 2があります。
こちらはユーザが任意のホットキーを登録する際に使用されるライブラリで内部的にPTHotKeyがカスタマイズされて使用されています。

上記のライブラリは比較的メンテナンスされていますが日本語IMEでのバグがでていたりしていたためClipyではforkプロジェクトを元々使用していました。
今回Magnetの作成に合わせてこちらも新しいライブラリとして作成しました。

リポジトリ: Clipy/KeyHolder

KeyHolderではShortcutRecorderの機能に加えMagnetで追加された修飾キーダブルタップのホットキー入力に対応しています

 

入力UIはAlfredをホットキー入力部を模倣し作成しています。
簡単ではありますが@IBDesignableに対応していますのでStoryboard等でグラフィカルに表示することもできます。

使用方法

入力パーツを画面に追加し文字色や角丸等を変更することができます。
keyComboを設定することでデフォルトで表示されるホットキーも指定できます。

let recordView = RecordView(frame: CGRect.zero)
recordView.delegate = self
recordView.tintColor = NSColor(red: 0.164, green: 0.517, blue: 0.823, alpha: 1)
let keyCombo = KeyCombo(doubledModifiers: .command)
recordView.keyCombo = keyCombo

下記のdelegateを使用し入力のキャンセルや変更の取得、バリデーションを行うことができます。

func recordViewShouldBeginRecording(_ recordView: RecordView) -> Bool
func recordView(_ recordView: RecordView, canRecordShortcut keyCombo: KeyCombo) -> Bool
func recordViewDidClearShortcut(_ recordView: RecordView)
func recordViewDidEndRecording(_ recordView: RecordView)

まとめ

簡単にですが2個のライブラリを紹介させていただきました。
上記のライブラリ郡を使用すればmacアプリ上で比較的簡単にホットキーの登録、ユーザー入力を実装することができますので、ぜひ使用してみてください。

ClipyのリポジトリにはClipy内で使用される機能が他にもライブラリとして書き出されています。
多くの人が使用しそうな機能はライブラリとして書き出すことで誰かを助けることがあるかもしれませんので、みなさんもぜひライブラリとして機能を分離し公開してみてださい。

要望やバグ等ありました、Issueか@econa77までご連絡ください。