ウィンドウが削除された後(ウィンドウの削除を参照)、たとえ一部のLisp変数が依然としてそのウィンドウを参照していたとしても、有効なウィンドウを引数として必要とする関数では、そのウィンドウをそれ以上使用できなくなります。ウィンドウへの最後の参照が消滅すると、そのウィンドウのLispオブジェクトは最終的にガベージコレクタによって回収されます(ガベージコレクションを参照)。
コレクタによってオブジェクトがまだ回収されていない削除済みウィンドウを復活させるには、2つの方法があります。1つ目は、保存済みのウィンドウ構成(ウィンドウ構成を参照)にそのウィンドウへの参照を保持し、その構成を引数としてset-window-configurationを呼び出す方法です。2つ目は、変数にそのウィンドウへの参照を保持するかlet-bindし、その参照をsplit-windowのrefer引数として使用する方法です(ウィンドウの分割を参照)。
これら2つの主な違いは、set-window-configurationがウィンドウを削除する前のフレームレイアウトを復元する点にあります。一方、split-windowの手法では、レイアウトを任意に変更することが可能です。
バッファ *scratch* を表示する単一のウィンドウを含むフレームから始まる、以下の例を考えてみましょう。
(let* ((old (selected-window))
(new (split-window old nil 'right))
overlay)
(with-current-buffer (get-buffer-create "*Messages*")
(set-window-buffer new (current-buffer))
(setq overlay (make-overlay (point-min) (point-max)))
(overlay-put overlay 'face 'highlight)
(overlay-put overlay 'window new)
(message "new %s parent %s" new (window-parent new))
(sit-for 3))
(delete-window new)
(setq new (split-window old nil 'left))
(set-window-buffer new (get-buffer-create "*Messages*"))
(format "new %s parent %s" new (window-parent new)))
*scratch* でそのコードを実行すると、まず *scratch* を表示しているウィンドウを分割し、右側の新しいウィンドウに *Messages* を表示します。また、新しいウィンドウ内の *Messages* のテキストを強調表示するためのウィンドウプロパティを持つオーバーレイを設定し、ウィンドウツリーにおける新しいウィンドウとその親ウィンドウを示すメッセージを表示します。その後、新しいウィンドウを削除して *scratch* ウィンドウの左側に再び表示させ、ウィンドウツリーにおける新しいウィンドウとその親ウィンドウを示すメッセージを再度表示します。
なお、*Messages*ウィンドウを左側に移動させた後、新しいウィンドウとその親ウィンドウの両方が変更されている点に注意してください。また、右側の新しいウィンドウに設定されたプロパティは、左側で新しいウィンドウが再作成される際に失われるため、ハイライトが消えます。
以下のコードでは、代わりに split-window の refer 引数を使用しています。
(let* ((old (selected-window))
(new (split-window old nil 'right))
overlay)
(with-current-buffer (get-buffer-create "*Messages*")
(set-window-buffer new (current-buffer))
(setq overlay (make-overlay (point-min) (point-max)))
(overlay-put overlay 'face 'highlight)
(overlay-put overlay 'window new)
(message "new %s parent %s" new (window-parent new))
(sit-for 3))
(delete-window new)
(split-window old nil 'left nil new)
(format "new %s parent %s" new (window-parent new)))
復活したウィンドウの装飾やパラメータ、およびウィンドウプロパティを持つオーバーレイといったすべてのプロパティは、あたかもそのウィンドウが一度も削除されていなかったかのように保持される点に注意してください。変更されるのは、ウィンドウツリーにおける位置のみであり、それに伴い、親ウィンドウの
window-left-child が返す値、ならびに当該ウィンドウとその兄弟ウィンドウの
window-prev-sibling および window-next-sibling が返す値も変更されます。
以下のコードでは、右側の新しいウィンドウとその親ウィンドウの両方を、refer 引数を介して代わりに
split-window に渡しています。
(let* ((old (selected-window))
(new (split-window old nil 'right))
(parent (window-parent new))
overlay)
(with-current-buffer (get-buffer-create "*Messages*")
(set-window-buffer new (current-buffer))
(setq overlay (make-overlay (point-min) (point-max)))
(overlay-put overlay 'face 'highlight)
(overlay-put overlay 'window new)
(message "new %s parent %s" new (window-parent new))
(sit-for 3))
(delete-window new)
(split-window old nil 'left nil (cons new parent))
(format "new %s parent %s" new (window-parent new)))
親ウィンドウが新しいウィンドウと共に復活したことに注意してください。
デッドウィンドウを復活させることは、フレーム上でのウィンドウ移動や一時的な非表示など、本来その機能を担うはずの操作において、ウィンドウの同一性を維持するのに有用です。装飾、以前に表示されていたバッファ、ウィンドウ内におけるそのバッファの開始位置とポイント位置、ウィンドウの専用ステータス、あるいはカーソルタイプといった当該ウィンドウのプロパティはそのまま保持されるため、ゼロから再作成する必要はありません。内部ウィンドウの場合、そのウィンドウの組み合わせ制限値が保持されるため、以前と同様に再結合(ウィンドウの再結合を参照)が可能です。