
2026/01/21 18:04
やっと、私の好きなように自動起動される Sway レイアウトを完成させました。
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
改訂版まとめ
著者は sway‑layout を構築しました。これは Go 言語で実装されたツールで、人工的な遅延を使わずに各ウィンドウの PID を追跡することで Sway のウィンドウレイアウトを自動的に復元します。プロジェクトは、著者がデフォルトマネージャとして Sway を使用していた際、既存の保存/復元ソリューションがハッキーであったり任意の待機時間に依存していたことから始まりました。混沌としたホームラボ環境から Ansible で管理される再現可能な Arch ベース構成へ移行した後、著者は Claude などの AI アシスタントを試しましたが、競合状態を処理できずレイアウトメタデータを取得できないため失敗しました。
実験中に、Sway のイベントストリームには各ウィンドウを作成したプロセスの PID が含まれていることを発見しました。この知見から、新しい戦略が可能になりました。すべてのウィンドウを並列で起動し、PID で追跡して、準備が整ったら一括で再配置するという方法です。プロトタイプはこのアイデアを実装しましたが、誤って
exec コマンドを使用したためレイアウトメタデータが失われました。Sway の IPC API が入れ子構造をフラット化する制限に対処するため、任意の入れ子レイアウトを再構築する再帰アルゴリズムを開発しました。
sway‑layout は JSON ファイル(
~/.config/sway/layouts/startup.json)を読み取り、起動時にその内容に従ってウィンドウを配置します。ツールは任意の遅延を排除し、可変ウィンドウアプリケーションを堅牢に処理しますが、いくつかの制限があります:デタッチドプロセスを追跡できない、同一アプリケーションから生成された複数ウィンドウを1つのコンテナにまとめる、カスタムウィンドウサイズ設定が不可能、セッション進化に伴うレイアウト追跡をサポートしていない点です。
今後の作業としては、Sway のリアルタイムイベントへの購読、複数ウィンドウを生成する起動コマンドの重複除去、および IPC を使用した全レイアウトのスナップショットと自動復元が挙げられます。Sway ユーザーにとっては遅延のないスムーズな起動体験と一貫したウィンドウ配置が実現し、このアプローチは PID ベースの並列処理を採用して信頼性を向上させる他のタイル型ウィンドウマネージャにも影響を与える可能性があります。
本文
私は数年前からノートパソコンでデフォルトのウィンドウマネージャとして sway を使っています。
10 年以上 KDE を使ってきた中で、最もイライラする点は実行中のアプリケーションを自動的に保存・復元できないことでした。
アプリを自動起動させる方法はありますが、生成されるウィンドウのレイアウトを指定する手段はありません。
解決策を探すたびに、人工的な遅延で競合状態を回避しようとする部分的でハッキーなワークアラウンドしか見つからず、満足できるものがありませんでした。結局、再起動ごとに手動でスタートアップ構成を設定せざるを得ない状況になっていました。
もう一度試してみた
ここ数か月、Claude Code の大きな助けもあって、約 7 年間にわたり作られてきた乱雑なホームラボをより再現性のあるセットアップへ移行しています。Arch を標準化し、Ansible で各マシンをプロビジョニングしました。
メインノートパソコンの様々な設定ファイルを見ていると、またもやスムーズで自動的なセッション起動への欲求が思い出されました。Claude と数回実験してみました。
結果は正直言ってあまり良くありませんでした。
Claude はこれまで多くの人々が苦しんできた競合状態に遭遇し、勇敢な試みにもかかわらず満足のいくアプローチを提示できませんでした。RTFMI(Really Tried For Many Interventions)が諦めることなく続けた結果、私は sway のマニュアルページをしっかり読む時間を持ち、そこで解決策の核に気づきました:
「ウィンドウが作成されたときのイベントストリームには、そのウィンドウを生成したプロセスの PID が含まれている!」
もし…
それなら、各新しいウィンドウを起動する前にレイアウトを丁寧に設定し、各ウィンドウが立ち上がるのを待ってから次へ進む代わりに:
- すべてのウィンドウを一度に起動する
- それぞれ任意の場所へ移動させる
- 各ウィンドウがどのプロセスに対応しているか追跡し、
- すべてのウィンドウが立ち上がったら一括でレイアウトを再配置する
というアプローチは多くのメリットがあります:
- アプリケーションを並列で起動できるため、スタートアップが格段に高速化
- スペシフィックなルールを設定してウィンドウとレイアウト位置をマッピングする必要がない
- 可変数のウィンドウを生成するアプリケーションも簡単に扱える
- 全体として非常に堅牢で、任意の遅延を必要としない
この優れた方針を踏まえて Claude は十分な結果を出せました。プロセス起動と生成されたウィンドウの追跡には堅固な仕組みを構築しました。ただし、重要な点で失敗してしまいました:
レイアウトメタデータをプロセスタリーに導入するはずだったラッパースクリプトが、実際には
exec で元のコマンドを置き換えてしまい、プロセスツリー内のレイアウト情報を失ってしまったのです。おっと…
より深く掘り下げる
最初に動作するプロトタイプが完成した後、もう一つ不快な驚きがありました:
コードは常にレイアウトを単一コンテナへフラット化してしまい、任意の入れ子構造を忠実に再現できませんでした。
sway は空のコンテナを許可せず、段階的に入れ子構造を構築するためのプレースホルダーも提供しないので、これはかなり難しい問題です。
数時間の試行錯誤を経て、IPC API の制限と、任意のネストされたウィンドウ階層を再現できる簡単な再帰アルゴリズムを可能にする二つのプリミティブを洗練させました。
このコアロジックは 100 % AI なし で実装されています!
sway-layout
の登場
sway-layoutプロトタイプがうまく動作したので、コードを整理して公開することにしました。他の人も役立てられそうだと思いました。
Bash と Python を混在させたプロトタイプから、単一バイナリとしてデプロイしやすい Go へ移行しました。
ソースコードは以下の二つのミラーで入手可能です:
インストールは簡単です:
go build cp sway-layout /usr/local/bin
使用するには、
~/.config/sway/layouts/startup.json に JSON 形式でレイアウト設定を作成します。
設定例
{ "workspaces": { "6": { "splitv": [ { "splith": [ "speedcrunch", { "tabbed": [ "alacritty", "alacritty" ] }, { "stacking": [ "alacritty", "alacritty" ] } ] }, { "splith": [ "alacritty -e btop", "alacritty" ] }, "speedcrunch", "alacritty -e htop" ] } } }
そして、sway の起動時に呼び出すように設定ファイルに次の行を追加します(パスは適宜調整してください):
exec /usr/local/bin/sway-layout
制限と今後の課題
現状
sway-layout は目的を達成していますが、完璧ではありません。
- 親プロセスから切り離される(detach)プロセスは追跡できません。
detach が破綻すると PID をレイアウトメタデータにマッピングできなくなるためです。
しかし、グラフィカルアプリケーションで detach を使用するケースは稀なので、実務上の問題になる可能性は低いでしょう。 - 複数ウィンドウを生成するアプリケーションでは、すべてのウィンドウが順に並んだままグループ化されます。
デフォルトで分割コンテナ内に均等にスペースが配分されるため、カスタムサイズを指定する方法は現在ありません。 - さらに進めれば、セッション中のレイアウト変化を追跡し続けることも可能です。
sway のイベント購読とプロセストリーを走査して新しいウィンドウに対して実行コマンドを記録(複数ウィンドウ生成時は重複除外)し、
IPC 呼び出しで毎回レイアウトスナップショットを取得すれば、単なる自動起動だけでなく、堅牢な保存/復元機能を実装できます。get_tree
この点については、将来の私自身または興味を持った読者への挑戦課題として残しておきます :)