Clear WS_CLIPCHILDREN on the client's window
CI / build (push) Successful in 54s

The client creates its 3D view's window with it, so not adding it wasn't
enough: covered entirely by the renderer's window, the client's window got no
WM_PAINT and the client still drew about once a second.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
dhkatzandClaude Opus 5.5 committed 2026-10-28 18:18:23 -07:00
1 parent 97b1d36466
commit 7bf29f3e4c
2 files changed
+6 -4

No files matched your search

+4 -3
View File
@@ -89,9 +89,10 @@ std::unique_ptr<RendererProcess> RendererProcess::start(HWND window, protocol::V
.reserved = 0}; .reserved = 0};
// The renderer's window goes on top of the client's 3D view, as a child window. The client's window mustn't clip // The renderer's window goes on top of the client's 3D view, as a child window. The client's window mustn't clip
// its children (WS_CLIPCHILDREN): the client draws a frame when its window gets WM_PAINT, which a window entirely // its children (WS_CLIPCHILDREN, which the client creates it with): the client draws a frame when its window gets
// covered by clipped children never gets (it then drew about once a second). The renderer's swap chain is a flip // WM_PAINT, which a window entirely covered by clipped children never gets (it then drew about once a second). The
// model one, which the compositor shows above the client's drawing anyway. // renderer's swap chain is a flip model one, which the compositor shows above the client's drawing anyway.
SetWindowLongW(window, GWL_STYLE, GetWindowLongW(window, GWL_STYLE) & ~WS_CLIPCHILDREN);
const auto exe = running_copy(module_folder() / L"t5de-renderer.exe"); const auto exe = running_copy(module_folder() / L"t5de-renderer.exe");
std::wstring command = std::format(L"\"{}\" --channel {} --parent {}", exe.wstring(), name, GetCurrentProcessId()); std::wstring command = std::format(L"\"{}\" --channel {} --parent {}", exe.wstring(), name, GetCurrentProcessId());
STARTUPINFOW startup{.cb = sizeof(STARTUPINFOW)}; STARTUPINFOW startup{.cb = sizeof(STARTUPINFOW)};
+2 -1
View File
@@ -30,7 +30,8 @@ creates (each 3D view, and again on room changes), the adapter:
The renderer process draws into a child window it creates inside the client's window: window handles are valid in The renderer process draws into a child window it creates inside the client's window: window handles are valid in
every process, and Windows allows child windows across processes (Chrome's GPU process works this way). The child every process, and Windows allows child windows across processes (Chrome's GPU process works this way). The child
is disabled so mouse input goes to the client's window under it. Its swap chain is a flip model one, which the is disabled so mouse input goes to the client's window under it. Its swap chain is a flip model one, which the
compositor shows above the client's own drawing. The client's window must not clip its children (`WS_CLIPCHILDREN`): compositor shows above the client's own drawing. The client's window must not clip its children (`WS_CLIPCHILDREN`,
which the client creates it with, so the adapter clears it):
the client draws a frame when its window gets `WM_PAINT` (`SceneWindow.dll` invalidates it, and draws on the paint), the client draws a frame when its window gets `WM_PAINT` (`SceneWindow.dll` invalidates it, and draws on the paint),
and a window entirely covered by clipped children never gets one, so the client fell to about one frame a second. and a window entirely covered by clipped children never gets one, so the client fell to about one frame a second.
The process exits when the engine is destroyed or the client exits. The process exits when the engine is destroyed or the client exits.