ウィンドウが消えます。Alt-Tab に出ず、タスクバーにも並ばない。プロセスは動いたままです。

GlazeWM は非アクティブなワークスペースのウィンドウを画面外へ退かしません。DWM の cloak をかけます。cloak されたウィンドウは合成の対象から外れ、それ以外は元のままです。API に聞けば可視だと答え、画面内の矩形を返し、最小化フラグも立っていません。 z オーダーを上げても出てきません。

GlazeWM を起動し直すと、シェルが報告するウィンドウを列挙します。cloak されているものもそこに並びますが、直前まで管理下にあったという情報は付いてきません。管理だけが失われ、cloak は残ったままになります。

意図的な再起動は稀

実際にこの状態を作るのは 3 つです。

  • GlazeWM がクラッシュして起動し直したとき
  • モニターを挿したとき、外したとき
  • プレゼンテーションモードを on / off したとき

後ろの 2 つは同じ事象です。ディスプレイ構成が変わると、GlazeWM はモニターとワークスペースの対応を作り直します。そこで参照するのはシェルの報告で、cloak は現在値としてしか読めません。誰がいつ付けたかは、どこにも残っていないのです。

見ていないワークスペースへウィンドウを送る設定は、どれも該当件数を押し上げます。送られた先で即座に cloak されるからです。起動時にアプリを所定のワークスペースへ配置する window_rules が、たいていの発生源になります。

cloak を外せるのは所有プロセスだけ

別プロセスから DwmSetWindowAttribute(DWMWA_CLOAK, 0) を呼ぶとE_ACCESSDENIED が返ります。権限を上げても変わりません。GlazeWM 自身も同じユーザーの非昇格プロセスで、cloak には未文書のシェル COM 経由で触れていて、その vtable レイアウトは Windows のビルドごとに変わる。汎用の復帰手段はここで消えます。残るのは、アプリ側が入口を持っている場合だけ。

wezterm は持っています。GUI プロセスごとに~/.local/share/wezterm/gui-sock-<pid> へ制御ソケットを開いているので、WEZTERM_UNIX_SOCKET をそこへ向ければ wezterm cli の宛先がそのプロセスに固定されます。ペインを新しいウィンドウへ移すよう指示すると、ウィンドウを作るのは wezterm 自身です。作られたばかりのウィンドウに cloak は付いていません。

glazewm/rescue-window.ps1 は、そのプロセスが持つペインを全部集めます。cloak されていないウィンドウに既にあったぶんも一緒に、新しいウィンドウへ移します。それ以外のアプリでは、分かっていることを表示して終わりです。アプリを再起動するか、explorer.exe を再起動してシェル側の cloak を全ウィンドウ分リセットするか。

「管理されていない」は 3 種類ある

難しいのは復帰よりも一覧のほうでした。「GlazeWM が管理していない」という条件は、異常 1 種と正常 2 種を同時に拾ってしまいます。

cloakimmersive
管理を失った> 0いいえどこにも描かれない。対処すべきもの
未管理だが描画済み0config.yamlignore ルール
サスペンド中の UWP> 0はいシェルによる cloak で GlazeWM は無関係

このマシンでは ignore ルールが 11 プロセスぶん動いていて、UWP のサスペンドも常時起きています。3 つを同じ扱いで出すと、直したい 1 件が十数件の中に沈みます。

1 行目と 3 行目を分けるのが IsImmersiveProcess です。現在管理下にあるハンドルはglazewm query windows が JSON で返すので、全体からそれを引きます。全体のほうはEnumWindows の結果を、タイトルを持つトップレベルのうち最小化でもツールウィンドウでもないものに絞ったものです。