fix(win32): restore mouse moves, add enter and leave, capture drags, and close and destroy windows cleanly
Win32
- WM_MOUSEMOVE is handled again: c9ebd44 put the WM_CHAR case where it
was, so currentMousePos stopped following the mouse and onMouseMove
never fired. Positions are read signed (GET_X_LPARAM), since under
capture they run past the client area.
- onMouseEnter and onMouseLeave. The first move over the client area
after a leave is the enter, and arms the TME_LEAVE whose WM_MOUSELEAVE
is the leave. An enter counts only once that is armed, a leave only
after an enter, and a move past the client area is a move only.
- A press captures the mouse, so a drag that leaves the window still
sends its moves and its release, as Wayland's implicit grab does.
Losing the capture releases what is held, and a button-up without its
press fires nothing.
- WM_CLOSE fires onClose and clears open, as xdg_toplevel.close does,
instead of destroying the HWND under the swapchain. WM_DESTROY no
longer posts WM_QUIT, which nothing read.
- ~Window detaches the HWND and destroys it. It stayed on screen, and its
messages went to the freed Window. WndProc hands messages without a
Window to DefWindowProc, and looks the Window up again after an event
that more work follows, in case a listener destroyed it.
- The constructor's message pump leaves input queued for StartSync: the
WM_MOUSEMOVE sent when a window appears under the cursor made an
onMouseEnter nobody could hear yet. The mouse state is reset before
the platform code, no longer after it.
- A window after the first finds its class registered, which showed an
error box.
- The wheel remainder is the window's, no longer a function static that
every window shared, and a leave drops it.
Window
- PointerEnter, PointerMove, PointerLeave and PointerScroll hold the rules
both native backends report the pointer by. An enter puts the entry
position in currentMousePos before onMouseEnter fires, and is followed
by a move, on Wayland too now. scrollRemainder replaces
Device::scrollDetentRemainder, and mouseInside is shared.
Tests
- PointerEnterLeave: enter, move and leave through the wl_pointer
callbacks.
- PointerWin32: posts a real HWND the messages above and pumps them as
StartSync does. Built for x86_64-w64-mingw32 it runs under Wine, and is
skipped where Wine is not on PATH.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
397ff2db51
commit
c62109caf3
7 changed files with 504 additions and 62 deletions
17
project.cpp
17
project.cpp
|
|
@ -326,6 +326,18 @@ extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> a
|
|||
pcTest.requires_ = { "tool:glslang", "tool:spirv-val" };
|
||||
cfg.tests.push_back(std::move(pcTest));
|
||||
|
||||
// The Win32 backend's pointer, capture, close and teardown handling,
|
||||
// through a real HWND: posts it the messages Windows would and checks
|
||||
// what the Window made of them. The Window needs Vulkan for its
|
||||
// swapchain. Built on Linux it runs under Wine, which may be absent.
|
||||
if (windows) {
|
||||
Test win32PointerTest = LibraryTest("PointerWin32");
|
||||
#ifndef _WIN32
|
||||
win32PointerTest.requires_ = { "tool:wine" };
|
||||
#endif
|
||||
cfg.tests.push_back(std::move(win32PointerTest));
|
||||
}
|
||||
|
||||
// Regression test for issue #32: the Wayland scroll-wheel chain
|
||||
// (wl_pointer.axis → Window::onMouseScroll). Drives the listener
|
||||
// callback directly, so it needs no compositor — but it does need
|
||||
|
|
@ -333,6 +345,11 @@ extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> a
|
|||
if (!windows) {
|
||||
cfg.tests.push_back(LibraryTest("MouseScroll"));
|
||||
|
||||
// The pointer's enter, move and leave through the helpers both
|
||||
// native backends report with (Window::PointerEnter and co.).
|
||||
// Drives the wl_pointer callbacks directly, as MouseScroll does.
|
||||
cfg.tests.push_back(LibraryTest("PointerEnterLeave"));
|
||||
|
||||
// Issue #40: multi-frame-in-flight frame pacing (per-image fences
|
||||
// + per-frame semaphores, no steady-state wait-idle). Drives the
|
||||
// real frame loop against a live Wayland compositor for many more
|
||||
|
|
|
|||
Loading…
Reference in a new issue