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
|
|
@ -472,7 +472,22 @@ function domAttachWindow(windowHandle) {
|
|||
}
|
||||
fire("__crafterDom_mouseUp", [e.button]);
|
||||
};
|
||||
__windowListeners.wheel = (e) => fire("__crafterDom_wheel", [e.deltaY]);
|
||||
// Window::onMouseScroll speaks whole wheel detents (+1 = wheel down),
|
||||
// the same unit the Wayland and Win32 backends deliver. WheelEvent
|
||||
// deltas arrive in browser-specific units, so normalize per deltaMode
|
||||
// (Chromium: ~100px per detent in pixel mode; Firefox: 3 lines in line
|
||||
// mode) and carry the sub-detent remainder so smooth-scroll trackpads
|
||||
// add up instead of each event truncating to zero.
|
||||
let __wheelDetentRemainder = 0;
|
||||
__windowListeners.wheel = (e) => {
|
||||
const perDetent = e.deltaMode === 1 ? 3 : e.deltaMode === 2 ? 1 : 100;
|
||||
__wheelDetentRemainder += e.deltaY / perDetent;
|
||||
const whole = Math.trunc(__wheelDetentRemainder);
|
||||
if (whole !== 0) {
|
||||
__wheelDetentRemainder -= whole;
|
||||
fire("__crafterDom_wheel", [whole]);
|
||||
}
|
||||
};
|
||||
__windowListeners.contextmenu = (e) => { e.preventDefault(); };
|
||||
__windowListeners.pointerlockchange = () => {
|
||||
// Reset the synthetic accumulator when lock is released so the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue