[Mac]Touch Barをカスタマイズするアプリ'Pock'のプラグイン開発

#はじめに
まずは僕が使っているMacBookProのTouch Barをご覧ください！
![touchbar.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377767/af9ba171-b120-b1fb-3903-94ae9e0096ab.png)

左から、`escキー`、`ストップウォッチ`、`Dock`、`音楽プレーヤ`、`明るさ・音量設定`となってます。良い評判はあまり聞こえてくることのないMacBook ProのTouch Barですが、こんな感じでカスタマイズして使用すると割と便利だったりします。

#Pockとは
このようにTouch Barをカスタマイズするアプリの一つが`Pock`というものです。他にも`BetterTouchTool`というものがありますがこちらは有料であるのに対し、Pockはオープンソースで開発されており無料で使用することができます。(BTTも便利なので利用していますが。。)
[GitHubのリポジトリ](https://github.com/pock/pock)
##install方法
HomeBrewで簡単にインストールできます。


```
brew install pock
```

こちらの[公式サイト](https://pock.dev)からもインストールできます。
[2021.3.14]
開発者様のツイートより、現在公式サイト復旧中であるとのことですのでgithubよりダウンロードするのが良いかもしれません。
↓
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">OVH had a considerable incident today. SBG-2, the datacenter where Pock’s website was hosted, is destroyed.<br><br>I will try to bring the site back to life as soon as possible. In the meantime, you can find the latest versions of Pock directly on GitHub. <a href="https://t.co/j5uzgtTXba">https://t.co/j5uzgtTXba</a></p>&mdash; Pierluigi Galdi (@pigigaldi) <a href="https://twitter.com/pigigaldi/status/1369583881389826050?ref_src=twsrc%5Etfw">March 10, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
初めて起動した際、いくつかアクセシビリティやプライバシーの権限が求められますので各自判断して許可を与えてください。

##Widget
Pockをインストールするとデフォルトで、`Dock`、`Now Playing`、`ESC key`、`Status`、`Control Center`、`Weather`の６つが使用できるようになります。(詳しい内容は[こちら](https://pock.dev)をご覧ください)
サードパーティ製のプラグインも開発できるようになってはいるようですが、現状公開されているものはほとんど見つけることが出来ませんでした。

##機能
###マウスでの操作
Pockの設定から`Enable Mouse control`をオンにするとマウスでTouch Bar上のアイテムを操作できるようになります。Widget側が対応していないとクリックしても反応しないので注意が必要です。デフォルトでインストールされるwidgetの中にも対応していないものもありました。
###通常のTouch Bar表示との切り替え
macOS標準やアプリ標準のTouch Bar表示へも簡単に切り替えることが出来ます。キーボードの`control`を2回早押しすると切り替わります。

#Pockプラグインの開発
Pockプラグイン開発には、PockKitというライブラリを使用することとなります。[こちら](https://pock.dev/docs/)にドキュメントが公開されるようですが、現状ではあまり詳細には記述されていないようです。そのため各自でライブラリのコードを読む必要がありますが、本記事で簡単に解説します。

###1. プラグインテンプレートをダウンロードする。
[こちらのページ](https://github.com/p-x9/pock-plugin-templete)からダウンロードします。初めから自分で作成したい場合は、Xcodeのプロジェクト作成から、macOS->Bundleと進み、Bundle Extensionの欄を`pock`に変更して作成してください。
以下のようなファイルが確認できると思います。
![スクリーンショット 2021-03-15 13.51.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377767/4f6b16f4-1c55-fdb3-cd8e-6d5074a7eebf.png)

###2. PockKitフレームワークのダウンロード
ダウンロードしたディレクトリ配下に移動し`pod install`コマンドでPockKitをダウンロードします。
今のところSwift Packageには対応していないようですが、[ここ](https://pock.dev/docs/)にはSwift Packageから入れられると書いてあるので将来的には対応するのだろうと思われます。

<!-- また、Swift Packageにも対応しているので、`pock-plugin-templete.xcodeproj`->`PROJECT`->`Swift Package`から以下のURLを追加してダウンロードすることも可能です。
```
https://github.com/pock/pockkit.git
```
-->

###3. リネーム
Xcodeプロジェクト自体の名前など各自好きな名前に変更してください。`SampleWidget`クラスの名前を変更する場合、`Info.plist`の`Principal class`の部分も変更する必要があります。

###4. 表示したいviewの実装
表示したいviewを実装します。viewの実装に関しては通常のCocoaアプリの開発と変わりはないので割愛させていただきます。xibを使ったviewでも大丈夫です。(Bundleの指定には注意してください、自分も引っかかったのでw)

###5. widgetクラスの実装
widgetクラスは、`PKWidget`プロトコルに準拠している必要があります。
### ・ identifier
Touch Bar上のitemの識別子です。無難に逆ドメイン名を指定しておくと良いと思います。
### ・ customizationLabel
Pock上で使用されるwidgetのタイトルに当たる部分です。具体的にはTouch barカスタマイズ画面やWidget設定画面で表示されます。
### ・ view
表示したいviewのインスタンスを指定します。Touch Barの高さは30pointですので、作成するviewについてはこれより小さくある必要があります。

###6. Build&Install
ビルドすると`.pock`という拡張子のファイルができるので、pockの`Install Widget...`をクリックして表示された画面にドラッグ&ドロップしてインストールします。するとpockからリロードを求められるのでリロードを行うと完了です。カスタマイズ画面から作成したwidgetを追加できるようになっていると思います。
また、普通に`.pock`ファイルをダブルクリックするだけでもインストールできるかと思います。

##オプション
###マウスでの操作
Widgetクラスを`PKScreenEdgeMouseDelegate`プロトコルに準拠させることでマウスでの操作に対応することが出来ます。
以下が実装が必要なメソッドとなっています。

```swift
/// マウスがTouch Bar上に侵入した時(Widgetのviewに侵入した時ではないので注意)
func screenEdgeController(_ controller: PKScreenEdgeController, mouseEnteredAtLocation location: NSPoint, in view: NSView)

/// マウスがTouch Bar上を移動した時
func screenEdgeController(_ controller: PKScreenEdgeController, mouseMovedAtLocation location: NSPoint, in view: NSView)

///マウスがTouch Bar上の任意の点をクリックした時
func screenEdgeController(_ controller: PKScreenEdgeController, mouseClickAtLocation location: NSPoint, in view: NSView)

//マウスがTouch Bar上から退避した時
func screenEdgeController(_ controller: PKScreenEdgeController, mouseExitedAtLocation location: NSPoint, in view: NSView)
```

他にもドラッグジェスチャーなどについても実装することが出来ます。

###開発者名の指定
`Info.plist`の`PKWidgetAuthor`に名前を指定することで実装できます。Widget設定画面に表示することが出来ます。
![author.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377767/82be04d0-7801-581b-c6c8-2b75b4a876c7.png)


###widgetの設定画面
作成したWidgetの設定画面を作ることも可能です。`PKWidgetPreference`プロトコルに準拠したViewControllerを作成し、`Info.plist`の`PKWidgetPreferenceClass`に作成したクラス名を指定することで実装できます。

例として標準でインストールできるControlCenter widgetの設定画面は以下のようになっています。

![スクリーンショット 2021-03-15 14.43.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377767/696f13bf-4ee2-80fd-2cab-ced1e649a125.png)

templeteでは例として以下のような設定画面を実装しています。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">pockプラグインの設定画面のサンプル <a href="https://t.co/8NvvVq8z8t">pic.twitter.com/8NvvVq8z8t</a></p>&mdash; M (@p_x9) <a href="https://twitter.com/p_x9/status/1371484652368769028?ref_src=twsrc%5Etfw">March 15, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


#おわりに
最後までお読みいただきありがとうございました。
何か質問などありましたら[Twitter](https://twitter.com/p_x9)やこの記事のコメント欄までお願いします。答えられる範囲ではありますがお答えさせて頂きます。

自分も以下のようなプラグインを作ってみました。気軽にタイム測定ができるので我ながら愛用しています。
[このGitHubページ](https://github.com/p-x9/pock-timer-widget![author.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377767/c2ed4798-db57-b6f5-87be-47637d72b095.png)
)からダウンロードできるので試してみてください。


<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Touch Barに簡易的なタイマーitemを作った。<br><br>タップでstart/stop<br>長押しでreset<br><br>Touch Barがスリープ状態に入ってもタイマーは継続するようにしてる。<br>割と便利に使えそうかもと思ってる。 <a href="https://t.co/sUKYuqFjKd">pic.twitter.com/sUKYuqFjKd</a></p>&mdash; M (@p_x9) <a href="https://twitter.com/p_x9/status/1368933700482723840?ref_src=twsrc%5Etfw">March 8, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>