## 関連Issue
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://github.githubassets.com/favicons/favicon.svg" />
<span class="link-card-v2-site-name">GitHub</span>
</div>
<div class="link-card-v2-title">
focus backで消したウィンドウをスキップしてほしい · Issue #1 · tadashi-aikawa/jinrai
</div>
<div class="link-card-v2-content">
私は2アプリの往復作業が多くてfocus backを多用するのですが、途中で一時的に別のアプリを開くとfocus backのループに戻れなくなってしまいます。 利用例: ブラウザとエディターなどを往復して作業をしている想定 ...
</div>
<img class="link-card-v2-image" src="https://opengraph.githubassets.com/695fc3b490591e52a51b628ba8513828ccee7a70d842d74b3238de4a37182eaa/tadashi-aikawa/jinrai/issues/1" />
<a href="https://github.com/tadashi-aikawa/jinrai/issues/1"></a>
</div>
## 関連コミット
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://github.githubassets.com/favicons/favicon.svg" />
<span class="link-card-v2-site-name">GitHub</span>
</div>
<div class="link-card-v2-title">
fix(focus_back): 直前のウィンドウが閉じられている場合やstaleな場合でも、その不可視なウィンドウがアクティブになってしまう · tadashi-aikawa/jinrai@1fff5cf
</div>
<div class="link-card-v2-content">
A Hammerspoon script for switching and recognizing windows at the speed of thought ⚡ - fix(focus_back): 直前のウィンドウ ...
</div>
<img class="link-card-v2-image" src="https://opengraph.githubassets.com/e1891c837926ade815ca39d9d41af48a7b0750ae16d4bdc818b6bf40ef4417a7/tadashi-aikawa/jinrai/commit/1fff5cfeb89332f1060c5229a94a2a30175ea27e" />
<a href="https://github.com/tadashi-aikawa/jinrai/commit/1fff5cfeb89332f1060c5229a94a2a30175ea27e"></a>
</div>
不可視ウィンドウの判定が難しく、フレームサイズやフレーム位置を使って判定しているのがミソ。そのヒントなしでは[[Codex CLI]] x [[GPT-5.4]]でも対応できなかった。
---
> [!left-bubble] ![[colot-mini.webp]]
> 以下は[[GitHub Copilot CLI]] x [[Claude Opus 4.6]] とのやりとりです。
## 依頼
Focus Backについて、以下の問題が発生している。
### 再現手順
以下の手順でウィンドウを操作するケースを考える。
1. ウィンドウAを開く
2. ウィンドウBを開く
3. ウィンドウCを開く
4. ウィンドウCを閉じる
5. Focus Backを実行
### 期待値
ウィンドウAがアクティブになる
### 実際の挙動
ウィンドウが遷移しない
### 備考
不具合とは言い切れないが、直感的にはウィンドウAに戻るのが妥当と考えられる。
## 🤖 対応
**`Jinrai.spoon/focus_history.lua`**: `previousWindow` 単一変数を履歴スタック (`history`) に置き換え。`focusBack()` でスタックをポップし、不可視ウィンドウや現在のウィンドウと同一のエントリをスキップするようにした(深度上限20)。
**`spec/focus_back_spec.lua`**: 報告された再現手順(A→B→C→Cを閉じる→Focus Back→Aにフォーカス)に対応するテストケースを追加。全110テストがパス。
## 不具合報告
A, B, CはすべてChromeのウィンドウだけど、A -\> B -\> C -\> C閉じる をしたあとにFocus Backをやると不可視のChromeがフォーカスされてしまってそう。カーソルはメインディスプレイの座標(0,0)に移動している
## 🤖 対応
閉じたウィンドウが stale な状態(`isVisible()` が `true` を返すが実体がない)で Focus Back されてしまう問題を修正しました。
**`Jinrai.spoon/focus_history.lua`**: `isWindowVisible` にフレームサイズの検証を追加。`isVisible()` が `true` でも `frame()` が `{0,0,0,0}` のウィンドウは不可視として扱い、スキップするようにした。
**`Jinrai.spoon/focus_back.lua`**: `centerCursor` でカーソル移動する前にフレームの有効性をチェック。無効なフレーム(w=0 or h=0)の場合はカーソルを移動しないようにした(防御的チェック)。
**`spec/helpers/hs_focus_back_mock.lua`**: `frame()` が動的に `_frame` フィールドを参照するように変更。
**`spec/focus_back_spec.lua`**: stale ウィンドウ(visible=true, frame={0,0,0,0})をスキップするテストケースを追加。全111テストがパス。