概要
自席では複数の外部ディスプレイを使っているため、
- ターミナルは内蔵ディスプレイ
- ブラウザは外部ディスプレイ1
- Slackは外部ディスプレイ2
のように配置することが多い自分です。
また外部ディスプレイを使わない場合は、内蔵ディスプレイで
- ターミナルは仮想デスクトップ1
- ブラウザは仮想デスクトップ2
- Slackは仮想デスクトップ4
のように配置しています。
問題はミーティングなどで外部ディスプレイを付けたり外したりする度に、上記のアプリの配置を手動で都度直さないといけない点です。
ただ残念ながら、よくあるウィンドウマネージャー・タイルマネージャーは仮想デスクトップ(Spaces)の操作まではできないため、この問題を解決することができませんでした。
しかしyabaiというツールは、SIPの一部をdisableにすることで上記を解決する事が可能です。
環境
- macOS 15.1.1
- yabai v7.1.5
- skhd v0.3.9
対応方法
yabai は macOS 用のウィンドウマネージャで、非公開のAPIを利用して Spaces を含めた詳細なウィンドウ操作を行うことが可能です。
※加えてSIP(System Integrity Protection)の部分的な無効化を必要とする等、セキュリティリスクやmacOSのアップデートで動かなくなる可能性があります。
SIPの一部無効化
以下の手順をとることでSIPを部分的に無効化します。
- 電源を落とす
- リカバリモードで起動
Loading startup options
が出るまで電源ボタンを押す
- オプション > 自分のユーザでログイン > ユーティリティ > ターミナル
csrutil enable --without fs --without debug --without nvram
を入力- 再起動し、通常モードへ
- ターミナルで
sudo nvram boot-args=-arm64e_preview_abi
を実行 - 再起動
ref: Disabling System Integrity Protection · koekeishiya/yabai Wiki · GitHub
yabai
次にyabai の設定です。
インストール
以下のコマンドでインストールします。
$ brew install koekeishiya/formulae/yabai
$ yabai --start-service
上記の中でアクセシビリティの許可などが必要になります。
rootユーザ許可
yabaiはmacOS Mach APIを使ってDock.appにコードを注入します。これにはroot権限が必要なため以下の設定をします。
echo "$(whoami) ALL=(root) NOPASSWD: sha256:$(shasum -a 256 $(which yabai) | cut -d " " -f 1) $(which yabai) --load-sa" | sudo tee /private/etc/sudoers.d/yabai
設定ファイル
.config/yabai/yabairc
というファイルを作成し、以下を記述します。
#!/usr/bin/env sh # # for this to work you must configure sudo such that # it will be able to run the command without password # # see this wiki page for information: # - https://github.com/koekeishiya/yabai/wiki/Installing-yabai-(latest-release)#configure-scripting-addition # yabai -m signal --add event=dock_did_restart action="sudo yabai --load-sa" sudo yabai --load-sa
yabaiのconfigは以下の順に読み込まれるので、$HOME/.yabairc
でも大丈夫です。
$XDG_CONFIG_HOME/yabai/yabairc
$HOME/.config/yabai/yabairc
$HOME/.yabairc
設定ファイルを用意したらyabaiを再起動します。
$ yabai --restart-service
アプリを各Spacesへ送るスクリプトの用意
次にアプリを各Spacesへ送るスクリプトを用意します。
僕の環境では以下の様な状態で話を進めます。
ディスプレイ | 仮想デスクトップ(Spaces) |
---|---|
内蔵ディスプレイ | デスクトップ1〜5 |
外部ディスプレイ1 | デスクトップ6〜7 |
外部ディスプレイ2 | デスクトップ8 |
外部ディスプレイあり用
``.config/yabai/display2.sh
#!/usr/bin/env bash # 1. すべてのウィンドウ情報をまとめて取得し、変数に格納 WINDOWS_JSON=$(yabai -m query --windows) # 2. jq で Google Chrome のウィンドウ ID を取り出し CHROME_ID=$(echo "$WINDOWS_JSON" \ | jq '.[] | select(.app == "Google Chrome") | .id' \ | head -n1) # 3. jq で Slack のウィンドウ ID を取り出し SLACK_ID=$(echo "$WINDOWS_JSON" \ | jq '.[] | select(.app == "Slack") | .id' \ | head -n1) # 4. 取得できているかチェックしつつ操作 if [ -n "$CHROME_ID" ]; then yabai -m window "$CHROME_ID" --space 6 yabai -m window "$CHROME_ID" --grid 1:1:0:0:1:1 else echo "Google Chrome のウィンドウが見つかりませんでした。" fi if [ -n "$SLACK_ID" ]; then yabai -m window "$SLACK_ID" --space 8 yabai -m window "$SLACK_ID" --grid 1:1:0:0:1:1 else echo "Slack のウィンドウが見つかりませんでした。" fi
- Google Chromeをデスクトップ6(外部ディスプレイ1)へ
- アプリを全画面表示に
- Slackをデスクトップ8(外部ディスプレイ2)へ
- アプリを全画面表示に
という設定です。
外部ディスプレイなし用
.config/yabai/default.sh
#!/usr/bin/env bash WINDOWS_JSON=$(yabai -m query --windows) CHROME_ID=$(echo "$WINDOWS_JSON" \ | jq '.[] | select(.app == "Google Chrome") | .id' \ | head -n1) SLACK_ID=$(echo "$WINDOWS_JSON" \ | jq '.[] | select(.app == "Slack") | .id' \ | head -n1) if [ -n "$CHROME_ID" ]; then yabai -m window "$CHROME_ID" --space 2 yabai -m window "$CHROME_ID" --grid 1:1:0:0:1:1 else echo "Google Chrome のウィンドウが見つかりませんでした。" fi if [ -n "$SLACK_ID" ]; then yabai -m window "$SLACK_ID" --space 4 yabai -m window "$SLACK_ID" --grid 1:1:0:0:1:1 else echo "Slack のウィンドウが見つかりませんでした。" fi
- Google Chromeをデスクトップ2へ
- アプリを全画面表示に
- Slackをデスクトップ4へ
- アプリを全画面表示に
という設定です。
直接シェルスクリプトを実行してみて、期待する挙動になるか確認しておきます。
skhd
skhdはシンプルなホットキー設定ツールです。
一般的には各yabaiコマンドを色んなホットキーとして設定しますが、僕の場合は上記スクリプトを実行する設定のみします。
インストール
$ brew install koekeishiya/formulae/skhd
$ skhd --start-service
設定ファイル
.config/skhd/skhdrc
というファイルを作り、以下を記述します。
shift + cmd - 1 : ~/.config/yabai/default.sh shift + cmd - 2 : ~/.config/yabai/display2.sh
用意できたら設定をリロードします。
$ skhd --reload
動作確認
shift + cmd + 1
を押したら外部ディスプレイなし用の配置にshift + cmd + 2
を押したら外部ディスプレイあり用の配置に
ということが確認できます。
まとめ
yabaiを使ってホットキーのみでアプリを各仮想デスクトップに移動する方法を説明しました。
同じような悩みを持っている人の参考になれば幸いです。