Win32: a titled window is on screen untitled until its constructor finishes #183

Open
opened 2026-10-31 17:22:46 +00:00 by jorijnvdgraaf · 0 comments

Summary

Window(width, height, title) sets the title only after the delegated Window(width, height) has created the HWND with an empty name, shown and activated it, and built the surface, swapchain and sync objects (implementations/Crafter.Graphics-Window.cpp:347-349, :417-435 at 852ae8a). Until then the window has an empty caption, and the taskbar and Alt+Tab show it without a name. A shell or accessibility hook that reads the name when the window appears (EVENT_OBJECT_SHOW, HSHELL_WINDOWCREATED) gets "". Cosmetic, and over before the constructor returns.

On master, SetTitle does nothing on Win32 at all; claude/win32-title makes it work, and this is what is left after that.

The title can't simply go to CreateWindowEx instead: WM_NCCREATE returns TRUE without calling DefWindowProc (:140-148), and it is DefWindowProc's WM_NCCREATE that stores the create name. Under Wine, a name given to CreateWindowExW came back empty from GetWindowTextW, and came through once WM_NCCREATE went on to DefWindowProcW.

Suggested fix

Have WM_NCCREATE return DefWindowProcW(hwnd, msg, wParam, lParam) after storing the pointer, and give the title to CreateWindowExW. That means the three-argument constructor holds the body and the two-argument one delegates with an empty title. On Wayland the title can then be set before the first commit, and left unset when it is empty, as the two-argument constructor leaves it today. TextWin32's first check covers the result.

## Summary `Window(width, height, title)` sets the title only after the delegated `Window(width, height)` has created the HWND with an empty name, shown and activated it, and built the surface, swapchain and sync objects (`implementations/Crafter.Graphics-Window.cpp:347-349`, `:417-435` at `852ae8a`). Until then the window has an empty caption, and the taskbar and Alt+Tab show it without a name. A shell or accessibility hook that reads the name when the window appears (`EVENT_OBJECT_SHOW`, `HSHELL_WINDOWCREATED`) gets "". Cosmetic, and over before the constructor returns. On `master`, `SetTitle` does nothing on Win32 at all; `claude/win32-title` makes it work, and this is what is left after that. The title can't simply go to `CreateWindowEx` instead: `WM_NCCREATE` returns `TRUE` without calling `DefWindowProc` (`:140-148`), and it is `DefWindowProc`'s `WM_NCCREATE` that stores the create name. Under Wine, a name given to `CreateWindowExW` came back empty from `GetWindowTextW`, and came through once `WM_NCCREATE` went on to `DefWindowProcW`. ## Suggested fix Have `WM_NCCREATE` return `DefWindowProcW(hwnd, msg, wParam, lParam)` after storing the pointer, and give the title to `CreateWindowExW`. That means the three-argument constructor holds the body and the two-argument one delegates with an empty title. On Wayland the title can then be set before the first commit, and left unset when it is empty, as the two-argument constructor leaves it today. `TextWin32`'s first check covers the result.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Catcrafts/Crafter.Graphics#183
No description provided.