feat(input): wire native mouse-wheel scroll on Wayland + Win32, normalize all backends to ±1/detent (#32)
Window::onMouseScroll now fires on every backend and speaks one unit: signed whole detents packed in the uint32 payload, +1 = wheel down (DOM deltaY sign). - Wayland: implement the previously-stubbed PointerListenerHandleAxis — vertical axis only, wl_fixed_to_double / 15 (libinput's units-per- detent), sub-detent remainder accumulated and reset on pointer leave. - Win32: add the missing WM_MOUSEWHEEL case — -GET_WHEEL_DELTA_WPARAM / WHEEL_DELTA with a remainder accumulator for free-spinning wheels. - DOM: dom-env.js normalizes WheelEvent.deltaY per deltaMode (100px / 3 lines / 1 page per detent) with the same remainder scheme, so wasm delivers the identical unit instead of raw browser-specific deltas. - Document the contract on Window::onMouseScroll. - tests/MouseScroll: compositor-free regression test driving the Wayland axis handler directly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
c608d75a36
commit
419730f46b
8 changed files with 240 additions and 8 deletions
|
|
@ -78,6 +78,12 @@ export namespace Crafter {
|
|||
// the manager — Clipboard::SetText silently no-ops there.
|
||||
inline static wl_data_device_manager* dataDeviceManager = nullptr;
|
||||
inline static wl_data_device* dataDevice = nullptr;
|
||||
// Sub-detent scroll accumulator for PointerListenerHandleAxis.
|
||||
// wl_pointer.axis values are normalized to wheel detents (15 axis
|
||||
// units each, the libinput convention); whatever doesn't make a
|
||||
// whole detent yet is carried here so smooth-scroll devices add up
|
||||
// across events. Reset on pointer leave.
|
||||
inline static double scrollDetentRemainder = 0.0;
|
||||
|
||||
static void seat_handle_capabilities(void* data, wl_seat* seat, uint32_t capabilities);
|
||||
static void xdg_surface_handle_preferred_scale(void* data, wp_fractional_scale_v1*, std::uint32_t scale);
|
||||
|
|
@ -92,7 +98,7 @@ export namespace Crafter {
|
|||
static void keyboard_repeat_info(void *data, wl_keyboard *keyboard, int32_t rate, int32_t delay);
|
||||
static void pointer_handle_button(void* data, wl_pointer* pointer, std::uint32_t serial, std::uint32_t time, std::uint32_t button, std::uint32_t state);
|
||||
static void PointerListenerHandleMotion(void* data, wl_pointer* wl_pointer, std::uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y);
|
||||
static void PointerListenerHandleAxis(void*, wl_pointer*, std::uint32_t, std::uint32_t, wl_fixed_t value);
|
||||
static void PointerListenerHandleAxis(void*, wl_pointer*, std::uint32_t time, std::uint32_t axis, wl_fixed_t value);
|
||||
static void PointerListenerHandleEnter(void* data, wl_pointer* wl_pointer, std::uint32_t serial, wl_surface* surface, wl_fixed_t surface_x, wl_fixed_t surface_y);
|
||||
static void PointerListenerHandleLeave(void*, wl_pointer*, std::uint32_t, wl_surface*);
|
||||
|
||||
|
|
|
|||
|
|
@ -103,6 +103,15 @@ export namespace Crafter {
|
|||
Event<void> onMouseMove;
|
||||
Event<void> onMouseEnter;
|
||||
Event<void> onMouseLeave;
|
||||
// Mouse wheel, in whole detents per event, sign packed into the
|
||||
// uint32 payload (reinterpret as int32 to read it). Positive =
|
||||
// wheel down / toward the user — the DOM deltaY sign. Every
|
||||
// backend normalizes to ±1 per notch: dom-env.js divides
|
||||
// WheelEvent deltas by the per-deltaMode detent size, Wayland
|
||||
// divides the axis value by libinput's 15-units-per-detent,
|
||||
// Win32 divides by WHEEL_DELTA. Sub-detent motion (smooth-scroll
|
||||
// touchpads, free-spinning wheels) is accumulated backend-side
|
||||
// until a whole detent is reached.
|
||||
Event<std::uint32_t> onMouseScroll;
|
||||
Vector<float, 2> currentMousePos;
|
||||
Vector<float, 2> lastMousePos;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue