logo サブスレッド

macOSのチャタリングをソフトウェアで対応する

むおおおお!

メインはdebounce-macをビルドするなのでそこまで飛ばしてもOKです。

前置き

先日入社した際にMacBook Proを会社に支給して頂いた私なんですけども、日頃の行いがたたったのかチャタリングが発生するようになってしまいました。もともとだったが気づかなかったのか、最近なのかよく分からないんですけれども、多分最初からなんじゃないかなと、自分を慰め続けてもうはや日が変わって頃に夜中のテンションでブログを書いています。

チャタリング、最初は「まあ別に一日で数十回程度だし、まあ今のところは超支障があるわけではないしなあ」とか思ってたんですけども、この間先方にバグチケットを発行した際に「この状態だとずっとxxxとなってしまいます」っていうところで、”t”がチャタリング起こしていたのに気づいておらず、「ずっっとxxxとなってしまいます」となっていることに先方から返信があった後に気が付きまして。これはアカンなと。

社内チャットで聞いてると、MacBook Proでちょいちょいチャタリングの問題っていうのは起きているそう。ハードウェアの問題なので根本的に直すには修理しか無い様子。修理に出すのは時間がかかるので、なんかうまいことソフトウェアで対応している事例が無いかと思って、調べてみました。

debounce-macを見つけるまで

検索範囲を日本だけで絞るとなるとかなり情報が限られるはずなので、英語で検索することにしました。 chattering, chatter, bounce あたりがキーワードらしく、いろいろ調べてみたところ、 Karabinerの設定で直した事例 と、 メカニカルキーボードでチャタリングが発生していたのをツール作って直した 人の投稿がでてきました。もうちょっと調べてると、 Support for the old ignore keyboard bouncing/chatter という、Karabiner内のissueが見つかりました。どうやらこのissueは、 Ignore bouncing/chattering events はもう今はなくなっていて、それを再実装するにはどうすればいい?っていうものの様子。

issueはちょっとだけ続いていて、その後でKarabinerのコードを弄ってる人がいるんですが、その人がさっき検索でヒットしていた debounce-macを数週間使ってるっぽいコメントを残してました。debounce-macはGitHub starsも少ないし、2016年に適当に作って止まってるんだけど大丈夫かなと疑心暗鬼になってたんですが、一旦これを使ってみることに。

するとなんとまあ結構いい感じに動くではありませんか。めでたしめでたし。と、macOSでチャタリングが起きていてどうしようもない人がこうなれるまでの話を今回書きます。

debounce-macをビルドする

配布バイナリが無いので自分でビルドする必要があります。

# 適当な場所でリポジトリを取得
git clone https://github.com/toothbrush/debounce-mac.git
cd debounce-mac

# ビルドする
make -f GNUmakefile

# 実行する
sudo ./debounce

僕の場合は上記ですんなりバイナリが出来て実行出来ました。不安なので中のソースコードも覗いてみたところ、どうやらこのプログラムはキー入力をインターセプトして、100msより早く連続で同じキーが入力されたものは無視するもののようでした。

上記プログラムを実行した状態で一日とか運用してみて、うまく動作してそうか確認してみましょう。

バックグラウンドプロセスについて

僕の場合は上記でうまく動いたので、PC起動時に自動的に立ち上がるようにしたいなあと思いました。で、社内にチャット投げたところ、macOSだったらlaunchdでいけるかも、と岡山の戦闘民族からリプがあったので、調べてみました。よく知ってんな。

手元のコマンドラインでman launchdするとちゃんと公式ドキュメントへのリンクがあったのでこれを参考にすることに。英語を勉強中なので、日本語に頼らずに頑張って読むことにしてみました。

有用っぽいところを抜粋すると、

  • 文脈の違いにより、serviceとかdaemonとかいう言葉がでることがある。このドキュメントでは、何らかの方法でGUIサポートするバックグラウンドプロセスをserviceと呼ぶ。例えば、キーボードショートカットの登録やネットワーク通信などを担当するもの。daemonはその他のもの、とりわけ、UIを持たないものをそう呼ぶ。
  • バックグラウンドプロセスの種類はいくつかある
    • Login item
      • ログインした時に起動するアプリ。システム環境設定→ユーザとグループの「ログイン項目」のことっぽい
      • Login itemもユーザ毎に実行されるlaunchdによって起動はされるが、launchdによって管理はされない
    • XPC service
      • serviceの一つで、アプリの一部。例えばクラッシュした時なんかにアプリを再起動させたりしてくれるものの様子。よく分からない
    • Launch Daemon
      • システムサイドで動くバックグラウンドプロセス。直接ユーザプロセスにアクセスできない特徴がある。window serverにアクセスできない、つまりGUIアプリケーションに関与できないということ。
    • Launch Agent
      • ログインしてるユーザサイドで動くバックグラウンドプロセス。ユーザセッションに紐付くプロセスやデーモンプロセスとやりとりが可能。GUIの提供もできるが、オススメはしない
  • デーモンとエージェントは互換があり、基本的に設定等は同じ。
Login itemの画面
Login itemはこの「ログイン項目」のこと

デーモン化

上記により、Launch Daemonの節を見れば出来ることが分かりました。ということで設定ファイルを作っていきます。 

設定ファイルは/Library/LaunchDaemons/に置けば良い様子。/System/Library/LaunchDaemons/でも良いようで、どちらに置くか迷ったんですが、man launchctlの説明によると、/System/Library/LaunchDaemons/の方はシステム側のデーモンの様子。/Library/LaunchDaemons/もシステム側のデーモンではあるけれど、Administratorによって設定を準備されることを想定した場所のようです。

# 設定ファイル作成
sudo vim /Library/LaunchDaemons/jp.co.subthread.debounce.plist

# 少し前のセクションでビルドしたdebounce実行ファイルを、/usr/local/bin/へ移動しておく
sudo cp debounce /usr/local/bin/

# 手動で起動してみる
sudo launchctl load /Library/LaunchDaemons/jp.co.subthread.debounce.plist

# 動作しているか、ログ出力を確認
tail -f /var/log/jp.co.subthread.debounce.log

設定ファイルは、Writing a “Hello World!” launchd JobDebugging launchd Jobsのセクションを見ながら、こんな感じで指定。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>jp.co.subthread.debounce</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/debounce</string>
    </array>
    <key>KeepAlive</key>
    <true/>
    <key>StandardOutPath</key>
    <string>/var/log/jp.co.subthread.debounce.log</string>
    <key>StandardErrorPath</key>
    <string>/var/log/jp.co.subthread.debounce.log</string>
</dict>
</plist>

うまく動いたらPCを再起動して、再度ログファイルをtail -fしてみましょう。自動的に起動して動作しているはずです!

これでストレスなく文章を打てるようになりました。めでたしめでたし!!

typo等を修正

現在の位置:サブスレッド ホーム > 技術ブログ > macOSのチャタリングをソフトウェアで対応する