Open9

yabai + skhd での快適Mac生活

NanamiiiiiNanamiiiii

3ヶ月くらい熟成したconfig

条件

  • macOS Ventura Sonoma
  • M1 MacBook Pro (2021)
  • SIP一部無効化済み(scripting additionのため)
  • Status Bar Widgetとして,Übersichtのsimple-barを使用(若干カスタム済み) Sketchybarに移行
yabairc
#!/usr/bin/env sh
# loading sa
yabai -m signal --add event=dock_did_restart action="sudo yabai --load-sa"
sudo yabai --load-sa

# global settings
yabai -m config mouse_follows_focus          off
yabai -m config focus_follows_mouse          on
yabai -m config window_origin_display        default
yabai -m config window_placement             second_child
yabai -m config window_topmost               off
yabai -m config window_shadow                on
yabai -m config window_opacity               off
yabai -m config window_opacity_duration      0.0
yabai -m config active_window_opacity        1.0
yabai -m config normal_window_opacity        0.90
yabai -m config window_border                off
yabai -m config window_border_width          6
yabai -m config active_window_border_color   0xff775759
yabai -m config normal_window_border_color   0xff555555
yabai -m config insert_feedback_color        0xffd75f5f
yabai -m config split_ratio                  0.50
yabai -m config auto_balance                 off
yabai -m config mouse_modifier               fn
yabai -m config mouse_action1                move
yabai -m config mouse_action2                resize
yabai -m config mouse_drop_action            swap

# general space settings
yabai -m config layout                       bsp
yabai -m config top_padding                  12
yabai -m config bottom_padding               12
yabai -m config left_padding                 12
yabai -m config right_padding                12
yabai -m config window_gap                   06

# in external display, top padding is different
# on M1 or later macbook, the notch space working as padding
DISPLAY_UUID=37D8832A-2D66-02CA-B9F7-8F30A301B230 # UUID of built-in display
BAR_PADDING=50
SPACES_ON_SUB=$(yabai -m query --displays | jq ".[] | select(.uuid != \"${DISPLAY_UUID}\") | .spaces[]")
for idx in ${SPACES_ON_SUB}
do
    yabai -m config --space "$idx" top_padding "$BAR_PADDING"
done

# Rules
yabai -m rule --add app="^System Settings$" manage=off
yabai -m rule --add app="^Termius$" manage=off
yabai -m rule --add app="^zoom\.us$" manage=off
yabai -m rule --add app="^Docker Desktop$" manage=off
yabai -m rule --add app="^Calculator$" manage=off
yabai -m rule --add app="^Finder$" title="^Connect to Server$" manage=off
yabai -m rule --add app="^Finder$" title="^Connecting to Server$" manage=off
yabai -m rule --add app="^Finder$" title="^.* Info$" manage=off
yabai -m rule --add app="^Finder$" title="^Copy$" manage=off
yabai -m rule --add app="^Inkdrop$" title="^Preferences$" manage=off
yabai -m rule --add app="^Weather$" manage=off
yabai -m rule --add app="^Clock$" manage=off
yabai -m rule --add app="^1Password$" manage=off
yabai -m rule --add app="^Discord$" title="^Discord Updater$" manage=off
yabai -m rule --add app="^Archive Utility$" manage=off
yabai -m rule --add app="^Microsoft To Do$" manage=off
yabai -m rule --add app="^UTM$" manage=off
yabai -m rule --add app="^GitKraken$" manage=off
yabai -m rule --add app="^Parallels Desktop$" manage=off
yabai -m rule --add app="^Plexamp$" sticky=on

echo "yabai configuration loaded.."
skhdrc
# focus window
alt - x : yabai -m window --focus recent
alt - h : yabai -m window --focus west
alt - j : yabai -m window --focus south
alt - k : yabai -m window --focus north
alt - l : yabai -m window --focus east
alt - n : ~/.scripts/yabai_next_window.sh
alt - p : ~/.scripts/yabai_prev_window.sh

# swap window
shift + alt - x : yabai -m window --swap recent
shift + alt - h : yabai -m window --swap west
shift + alt - j : yabai -m window --swap south
shift + alt - k : yabai -m window --swap north
shift + alt - l : yabai -m window --swap east

# move window
shift + cmd - h : yabai -m window --warp west
shift + cmd - j : yabai -m window --warp south
shift + cmd - k : yabai -m window --warp north
shift + cmd - l : yabai -m window --warp east

# move window
shift + ctrl - a : yabai -m window --move rel:-20:0
shift + ctrl - s : yabai -m window --move rel:0:20
shift + ctrl - w : yabai -m window --move rel:0:-20
shift + ctrl - d : yabai -m window --move rel:20:0

# increase window size
shift + alt - a : yabai -m window --resize left:-20:0
shift + alt - s : yabai -m window --resize bottom:0:20
shift + alt - w : yabai -m window --resize top:0:-20
shift + alt - d : yabai -m window --resize right:20:0

# decrease window size
shift + cmd - a : yabai -m window --resize left:20:0
shift + cmd - s : yabai -m window --resize bottom:0:-20
shift + cmd - w : yabai -m window --resize top:0:20
shift + cmd - d : yabai -m window --resize right:-20:0

# rotate tree
alt - r : yabai -m space --rotate 90

# mirror tree y-axis
alt - y : yabai -m space --mirror y-axis

# mirror tree x-axis
alt - x : yabai -m space --mirror x-axis

# toggle desktop offset
alt - a : yabai -m space --toggle padding && yabai -m space --toggle gap

# toggle window fullscreen zoom
alt - f : yabai -m window --toggle zoom-fullscreen

# toggle window native fullscreen
shift + alt - f : yabai -m window --toggle native-fullscreen

# toggle window split type
alt - e : yabai -m window --toggle split

# float / unfloat window and restore position
# alt - t : yabai -m window --toggle float && /tmp/yabai-restore/$(yabai -m query --windows --window | jq -re '.id').restore 2>/dev/null || true
alt - t : yabai -m window --toggle float && yabai -m window --grid 4:4:1:1:2:2

# toggle sticky window
alt - s : yabai -m window --toggle sticky

# restart yabai
shift + alt - r : yabai --restart-service && osascript -e 'tell application id "tracesOf.Uebersicht" to reload widget id "simple-bar-index-jsx"'

# restart skhd
shift + ctrl - r : skhd --restart-service

# Close app
alt - q : yabai -m window --close

# Focus spaces (require sa)
alt - 1 : yabai -m space --focus 1
alt - 2 : yabai -m space --focus 2
alt - 3 : yabai -m space --focus 3
alt - 4 : yabai -m space --focus 4
alt - 5 : yabai -m space --focus 5
alt - 6 : yabai -m space --focus 6
alt - 7 : yabai -m space --focus 7
alt - 8 : yabai -m space --focus 8
alt - 9 : yabai -m space --focus 9
alt - 0 : yabai -m space --focus 10

# Move spaces (require sa)
shift + alt - 1 : yabai -m window --space 1
shift + alt - 2 : yabai -m window --space 2
shift + alt - 3 : yabai -m window --space 3
shift + alt - 4 : yabai -m window --space 4
shift + alt - 5 : yabai -m window --space 5
shift + alt - 6 : yabai -m window --space 6
shift + alt - 7 : yabai -m window --space 7
shift + alt - 8 : yabai -m window --space 8
shift + alt - 9 : yabai -m window --space 9
shift + alt - 0 : yabai -m window --space 10

# Move display
shift + alt - p : yabai -m space --move prev
shift + alt - n : yabai -m space --move next

# Launch Apps
## WezTerm
alt - return : open -a "WezTerm"
## memos
alt - m : open "https://memos.myuu.dev"
## FireFox
alt - b : open -a "Firefox Developer Edition"
## Vivaldi
shift + alt - b : open -a "Firefox"
## Finder
alt - g : osascript ~/.config/skhd/finder.scpt
## Inkdrop
cmd + alt - m : open -a "Inkdrop"
## Code
cmd + alt - o : open -a "Visual Studio Code"
## 1Password
cmd + alt - k : open -a "1Password"

https://raw.githubusercontent.com/Nanamiiiii/dotfiles/main/yabai/yabairc

https://raw.githubusercontent.com/Nanamiiiii/dotfiles/main/skhd/skhdrc

NanamiiiiiNanamiiiii

Built-inディスプレイと外部ディスプレイのpaddingをよしなにする

yabairc
# in external display, top padding is different
# on M1 or later macbook, the notch space working as padding
DISPLAY_UUID=37D8832A-2D66-02CA-B9F7-8F30A301B230 # UUID of built-in display
BAR_PADDING=50
SPACES_ON_SUB=$(yabai -m query --displays | jq ".[] | select(.uuid != \"${DISPLAY_UUID}\") | .spaces[]")
for idx in ${SPACES_ON_SUB}
do
    yabai -m config --space "$idx" top_padding "$BAR_PADDING"
done

Why

M1搭載以降のMBPは,ノッチを避けるためにデフォルトでパディングが存在する.
そのため,Built-inディスプレイではパディングなしで独自のステータスバー領域を確保できる.
しかし,外部ディスプレイにはノッチのためのパディングが確保されない(当然)ので,外部ディスプレイにのみyabai側でパディングを設定する.

How

各ディスプレイに振られるuuidを利用する.Built-inのuuidは基本変化しないとしてベタ書きし,これに該当しないディスプレイ上のspace対してのみパディングを与える.

  • 外部ディスプレイ上のspaceの取得
    yabai -m query --displays | jq ".[] | select(.uuid != \"${DISPLAY_UUID}\") | .spaces[]"
  • spaceごとにパディングを設定
    yabai -m config --space SPACE_ID top_padding PADDING
NanamiiiiiNanamiiiii

Space内でcyclicにwindowを切り替える

What

アクティブなspace内にあるwindowを巡回したかったが,yabai側でそれができる機能がなかったっぽい?
shellscriptでゴリゴリとやった

Why

floatingなwindowがあるとき,これにfocusする手段がなかった

Keybind

skhdrc
alt - n : ~/.scripts/yabai_next_window.sh
alt - p : ~/.scripts/yabai_prev_window.sh

nextprev はwindow idの前後

Script

yabai_next_window.sh
#!/bin/bash

# focusされてるwindowの情報
FOCUSED=$(yabai -m query --windows --window 2> /dev/null)
# focusされてるwindow id
FOCUSED_ID=$(echo "$FOCUSED" | jq ".id")

# focusされてるwindowが存在するとき
if [ -n "$FOCUSED_ID" ]; then
    UNFOCUSED=$(yabai -m query --windows --space | jq "[ .[] | if .id != $FOCUSED_ID then . else empty end]")
    UPPER_ID=$(echo "$UNFOCUSED" | jq "[ .[] | if .id > $FOCUSED_ID then . else empty end]")
    if [ "$(echo "$UPPER_ID" | jq ". | length")" -gt 0 ]; then
        NEXT=$(echo "$UPPER_ID" | jq "[ .[].id ] | min")
        yabai -m window --focus "$NEXT"
    else
        NEXT=$(echo "$UNFOCUSED" | jq "[ .[].id ] | min")
        yabai -m window --focus "$NEXT"
    fi
else # なにもfocusされてないとき
    UNFOCUSED=$(yabai -m query --windows --space)
    NEXT=$(echo "$UNFOCUSED" | jq "[ .[].id ] | min")
    yabai -m window --focus "$NEXT"
fi
  • window idに基づいて,直後・直前のwindowにfocusする
  • なにもfocusされていない場合,idが先頭・末尾のwindowへfocus
  • prevはidの大小比較を真逆にしたもの

https://raw.githubusercontent.com/Nanamiiiii/dotfiles/main/scripts/yabai_next_window.sh

NanamiiiiiNanamiiiii

SIPの無効化について

しないと実際どうなのか

個人的には不快.マウス操作したほうがマシだった.

なにができないのか

  • スムーズなspace (仮想デスクトップ) の移動
    • scripting-additionはアニメーションとかその他いらない視覚効果を無効化できる
  • windowのspace間移動
  • yabai側からのspace追加・削除
  • sticky windowが使えない
  • などなど…

指示通り設定するとシステム保護機能はこうなる

最低限の保護は効いてるはずなので,まあ個人使用マシンならそこまで問題はないだろう…
今のところその他アプリケーションへの影響もない.

NanamiiiiiNanamiiiii

Übersicht

React / jsx (tsx) で記述したウィジェットを画面上にレンダリングできる.
任意のコマンド実行結果を取得して,それを表示するなど.

https://github.com/felixhageloh/uebersicht

Install

Homebrew or Website

brew install ubersicht

simple-bar

yabaiへのメッセージパッシングを実装しているÜbersichtのウィジェット.
yabai以外にSpotifyなどの表示にも対応している.

https://github.com/Jean-Tinland/simple-bar

作者はApple Silicon非所持で動作保証はしないよ!と言っているが,今のところ支障はない.
(むしろAppleSilicon以降のノッチが丁度余白になってて良き)

Install

Übersichtのウィジェットディレクトリに直接cloneすればよい

  • ~/Library/Application Support/Übersicht/widgets

カスタマイズ

Reactが分かれば容易.画面サイズとかに合わせてPadding/Marginはカスタムした方がよさそうな所感.

完全に自分用にカスタムしただけのやつ
https://github.com/Nanamiiiii/simple-bar

Refresh / Reload

yabaiをrestartするとメッセージパッシングが効かなくなる(多分古いsocketを参照したままだから?)
skhdでyabaiのrestartにあわせてwidgetをreloadする設定にするといい.
CLIからのÜbersichtの制御はAppleScriptで可能.

# restart yabai
shift + alt - r : yabai --restart-service && osascript -e 'tell application id "tracesOf.Uebersicht" to reload widget id "simple-bar-index-jsx"'
NanamiiiiiNanamiiiii

ÜbersichtをやめてSketchybarに移行した

https://github.com/FelixKratz/SketchyBar

理由

  • 最近Übersichtの挙動が怪しかった
    • 起動オーバーヘッドが著しい
    • 一部コンテンツがバグる(たまに読み込まない)
    • しばらく使ってるとyabaiとのやりとりが遅くなる(メッセージパッシングが詰まってるかのような挙動)
    • ぶっちゃけReactである必要がない(そこまでカスタマイズしないので)

Sketchybar,非常に軽くて良い.見た目も思ったよりカスタムできるし,何よりも✝️黒魔術️✝️(ShellScript)で項目を作れるのがいい.