[Cocoa] Support locking the pointer with unadjustedMovement
| Tracking | Status | |
|---|---|---|
| firefox152 | --- | verified |
user-impact-score:400
|
48 bytes,
text/x-phabricator-request
|
Details | Review |
|
48 bytes,
text/x-phabricator-request
|
Details | Review |
|
48 bytes,
text/x-phabricator-request
|
Details | Review |
|
48 bytes,
text/x-phabricator-request
|
Details | Review |
|
48 bytes,
text/x-phabricator-request
|
Details | Review |
|
48 bytes,
text/x-phabricator-request
|
Details | Review |
| Reporter | |
Descriptionβ’3 years ago
|
User Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36
Steps to reproduce:
document.body.requestPointerLock({
unadjustedMovement: true,
})
Actual results:
No noticable difference between this and unadjustedMovement: false
Expected results:
Mouse acceleration should be disabled.
Comment 1β’3 years ago
|
The Bugbug bot thinks this bug should belong to the 'Core::DOM: Core & HTML' component, and is moving the bug to that component. Please correct in case you think the bot is wrong.
Updatedβ’1 year ago
|
Updatedβ’1 year ago
|
Updatedβ’9 months ago
|
Updatedβ’8 months ago
|
| Assignee | |
Comment 3β’1 month ago
|
An official web standard has been created for this, and it has been moved to position: positive: https://github.com/mozilla/standards-positions/issues/448
Is this up for grabs? If I were to put in a PR, would it be reviewed?
Comment 4β’1 month ago
|
Hi Noah, thank you for your interests in working on this bug. Please feel free to take it. I've added Edgar as a mentor - feel free to reach out for questions and discussions. Thanks again. :)
Updatedβ’1 month ago
|
| Assignee | |
Comment 5β’1 month ago
|
Implements the PointerLockOptions dictionary and changes
Element.requestPointerLock() to return Promise<undefined>, matching the
spec at https://w3c.github.io/pointerlock/#extensions-to-the-element-interface
and the API surface shipped by Chromium and WebKit.
The unadjustedMovement member is plumbed through PointerLockManager,
PBrowser IPC, and a new nsIWidget::SetPointerLockUnadjustedMovement
hook. The Cocoa widget stores the flag for the follow-up patch that
will source unaccelerated mouse delta from
kCGEventUnacceleratedPointerMovementX/Y. The option is gated behind
the new dom.pointer-lock.unadjusted-movement.enabled pref (Nightly
only); when the pref is off, requesting unadjustedMovement: true
rejects with NotSupportedError as the spec mandates.
Promise rejection paths now use spec-mapped DOMException names
(NotSupportedError, WrongDocumentError, SecurityError, etc.) instead
of only firing the legacy pointerlockerror event.
The wpt tests pointerlock_promise.html and idlharness.window.js for
requestPointerLock(optional PointerLockOptions) now pass.
Updatedβ’1 month ago
|
| Assignee | |
Comment 6β’1 month ago
|
Adds Maybe<LayoutDeviceIntPoint> mUnadjustedMovement to WidgetMouseEvent.
When set, MouseEvent::movementX/Y returns this value verbatim instead
of computing a delta from mRefPoint/mLastRefPoint, since cursor
warping done to keep a locked cursor in place would otherwise expose
OS mouse acceleration to the page.
The Cocoa widget's convertCocoaMouseEvent path populates the field
from kCGEventUnacceleratedPointerMovementX/Y on the underlying
CGEvent whenever pointer lock is active with the unadjustedMovement
option (mPointerLockUnadjustedMovement on nsCocoaWindow). This is the
same approach Chromium uses on macOS.
The new field round-trips through PBrowser IPC for OOP iframes via
the hand-written WidgetMouseEvent ParamTraits.
The wpt test pointerlock_unadjustedMovement.html now passes on macOS;
its expected:FAIL metadata is removed.
| Assignee | |
Comment 7β’1 month ago
|
Builds on the API surface and initial CGEvent read path so
unadjustedMovement: true behaves correctly in practice on macOS.
-
IPC propagation: BrowserParent::RecvRequestPointerLock now invokes
widget->SetPointerLockUnadjustedMovement on the parent-process widget
that owns the real native window. Without this, only the content
process's PuppetWidget (a no-op default) was being notified, so the
Cocoa widget never learned about the option. -
Cursor dissociation: nsCocoaWindow::SetPointerLockUnadjustedMovement
toggles CGAssociateMouseAndMouseCursorPosition to keep the OS cursor
frozen while the lock is active, matching Chromium. Without this the
cursor would drift off-screen during the lock. -
Skip cursor warp under unadjusted:
nsCocoaWindow::SynthesizeNativeMouseEvent no longer calls
CGWarpMouseCursorPosition + CGAssociateMouseAndMouseCursorPosition(true)
when the widget is in unadjusted mode, otherwise the synthetic mouse
move triggered by EventStateManager::SetPointerLock at lock-acquire
would immediately undo the dissociation. -
Skip per-event recenter under unadjusted:
EventStateManager::ResetPointerToWindowCenterWhilePointerLocked
early-returns when PointerLockManager::IsCurrentLockUnadjustedMovement
is true, since the dissociated cursor doesn't move and warping it
back is unnecessary churn that would also re-associate it. -
Dead-zone filter: when NSEvent.deltaX/Y is zero (Apple's OS-level
acceleration filter says no real motion), report no raw movement
either. This filters Apple's idle trackpad sensor calibration
residual without losing real motion. -
Coalesce accumulation: CoalescedMouseData::Coalesce now sums
mUnadjustedMovement across coalesced samples so the dispatched parent
event reports the cumulative raw delta instead of just the first
sub-event's. Pages reading MouseEvent.movementX/Y without iterating
getCoalescedEvents now see correct total motion. -
Match Chromium's coordinate convention: MouseEvent::GetMovementPoint
returns the unadjusted delta verbatim in device pixels rather than
converting through CSS pixels. Callers asking for raw, unaccelerated
motion calibrate around physical sensor fidelity and shouldn't be
halved on HiDPI displays vs. Chrome.
The wpt tests pointerlock_unadjustedMovement.html, pointerlock_promise.html,
and idlharness.window.js continue to pass.
| Assignee | |
Comment 8β’1 month ago
|
Adds a per-widget capability bit nsIWidget::SupportsPointerLockUnadjustedMovement
defaulting to false. Only nsCocoaWindow overrides to true, since macOS is the
only Gecko widget currently wired to deliver raw, unaccelerated mouse delta.
BrowserParent::RecvRequestPointerLock consults the bit when unadjustedMovement
is requested and resolves the IPC with "PointerLockDeniedUnadjustedMovement"
-- which PointerLockManager already maps to NotSupportedError -- when the
widget can't deliver. Without this, Windows and Linux would silently accept
the option without honoring it, violating the spec's "If the user agent does
not support unadjusted movement, fail with NotSupportedError" requirement.
Follow-up bugs will flip the override on the Windows widget (raw input via
WM_INPUT), the X11 widget (XInput2 raw events), and the Wayland widget
(zwp_relative_pointer_v1 protocol) once each platform's raw-input path is
wired up.
The wpt test pointerlock_unadjustedMovement.html continues to pass on macOS.
Updatedβ’1 month ago
|
Updatedβ’1 month ago
|
Comment 9β’1 month ago
|
(In reply to Hsin-Yi Tsai (she/her)[:hsinyi] from comment #4)
Hi Noah, thank you for your interests in working on this bug. Please feel free to take it. I've added Edgar as a mentor - feel free to reach out for questions and discussions. Thanks again. :)
Thanks Noah for the patches! :)
Since this has become time-critical and weβre aiming to bring the feature to users soon, Edgar is going to help take this forward and get it over the line. Weβve synced up with Noah on this approach and will keep authorship on the commits.
Comment 10β’1 month ago
|
Matching the spec at https://w3c.github.io/pointerlock/#requestPointerLock.
Co-authored-by: Noah Peterson <noahbpeterson1997@gmail.com>
Updatedβ’1 month ago
|
Updatedβ’1 month ago
|
Updatedβ’1 month ago
|
Updatedβ’1 month ago
|
Comment 11β’1 month ago
|
Matching the spec at https://w3c.github.io/pointerlock/#requestPointerLock.
Co-authored-by: Noah Peterson <noahbpeterson1997@gmail.com>
Updatedβ’1 month ago
|
Updatedβ’1 month ago
|
Updatedβ’1 month ago
|
Comment 12β’1 month ago
|
Comment 13β’1 month ago
|
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/59743 for changes under testing/web-platform/tests
Comment 14β’1 month ago
|
|
| bugherder | |
https://hg.mozilla.org/mozilla-central/rev/140369ca9933
https://hg.mozilla.org/mozilla-central/rev/4492cff6b8a1
Comment 15β’1 month ago
|
Upstream PR merged by moz-wptsync-bot
Comment 16β’1 month ago
|
Comment 17β’1 month ago
|
Comment 18β’1 month ago
|
Backout merged to central: https://hg.mozilla.org/mozilla-central/rev/0e22635834d4
Backed out for causing
Failures from platforms here: https://treeherder.mozilla.org/intermittent-failures/bugdetails?startday=2026-05-01&endday=2026-05-08&tree=all&bug=2014003
Comment 19β’1 month ago
|
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/59764 for changes under testing/web-platform/tests
Updatedβ’1 month ago
|
Comment 20β’1 month ago
|
Upstream PR merged by moz-wptsync-bot
Comment 21β’1 month ago
|
Comment 22β’1 month ago
|
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/59773 for changes under testing/web-platform/tests
Comment 23β’1 month ago
|
|
| bugherder | |
https://hg.mozilla.org/mozilla-central/rev/521ba1138293
https://hg.mozilla.org/mozilla-central/rev/26dc07739a54
Comment 24β’1 month ago
|
Upstream PR merged by moz-wptsync-bot
Updatedβ’1 month ago
|
Comment 25β’1 month ago
|
I've verified that the issue was fixed, using krunker.io as a base since it uses requestPointerLock() without unadjustedMovement and mouse.scaling set to 5 to create a noticeable difference between acceleration ON and OFF. Verified that there isn't a difference between acceleration ON and OFF for browser first-person games that use unadjustedMovement:true.
Tested using Firefox Nightly 152.0a1, Build ID 20260511160144 on macOS 26.4.1.
