VOOZH about

URL: https://bugzilla.mozilla.org/1829401

⇱ 1829401 - [Cocoa] Support locking the pointer with unadjustedMovement


Closed Bug 1829401 Opened 3 years ago Closed 1 month ago

[Cocoa] Support locking the pointer with unadjustedMovement

[Cocoa] Support locking the pointer with unadjustedMovement
Core
DOM: Core & HTML
Firefox 112
Unspecified
Unspecified
enhancement
Points:
---
VERIFIED FIXED
VERIFIED
FIXED
152 Branch
Iteration:
---
a11y-review
Accessibility Severity
Performance Impact
Size Estimate
Webcompat Priority
Webcompat Score
Tracking Status
firefox152 --- verified
Tracking Status
relnote-firefox
thunderbird_esr115
thunderbird_esr140
firefox-esr115
firefox-esr140
firefox-esr153
firefox152
firefox153
firefox154
---
QA Whiteboard:
---
Has STR:
---
Change Request:
---
Bug Flags:
Signature:
None
This bug is publicly visible.
user-impact-score:400
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.

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.

Component: Untriaged β†’ DOM: Core & HTML
Product: Firefox β†’ Core
User Story: (updated)
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?

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. :)

Mentor: echen
Flags: needinfo?(noahbpeterson1997)
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.

Assignee: nobody β†’ noahbpeterson1997
Status: UNCONFIRMED β†’ ASSIGNED
Ever confirmed: true
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.

Depends on: 2036482
Priority: -- β†’ P1
Summary: Support locking the pointer with unadjustedMovement β†’ [Cocoa] Support locking the pointer with unadjustedMovement
Depends on: 2037356

(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.

Attachment #9574844 - Attachment is obsolete: true
Attachment #9574843 - Attachment is obsolete: true
Attachment #9574842 - Attachment is obsolete: true
Attachment #9574841 - Attachment description: Bug 1829401 - Add unadjustedMovement option and Promise return to Element.requestPointerLock r?#dom-core β†’ WIP: Bug 1829401 - Part 2: Support unadjustedMovement option and implement on macOS first;
Attachment #9583956 - Attachment is obsolete: true
Attachment #9583959 - Attachment description: WIP: Bug 1829401 - Part 1: Implements Element.requestPointerLock() to return Promise<undefined>; β†’ Bug 1829401 - Part 1: Implements Element.requestPointerLock() to return Promise<undefined>; r?smaug
Attachment #9574841 - Attachment description: WIP: Bug 1829401 - Part 2: Support unadjustedMovement option and implement on macOS first; β†’ Bug 1829401 - Part 2: Support unadjustedMovement option and implement on macOS first;

Comment 12

β€’
1 month ago
Pushed by echen@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/e4344e3d3c01 https://hg.mozilla.org/integration/autoland/rev/140369ca9933 Part 1: Implements Element.requestPointerLock() to return Promise<undefined>; r=smaug,webidl https://github.com/mozilla-firefox/firefox/commit/782dcf9aee2e https://hg.mozilla.org/integration/autoland/rev/4492cff6b8a1 Part 2: Support unadjustedMovement option and implement on macOS first; r=webidl,smaug,mstange

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
Status: ASSIGNED β†’ RESOLVED
Closed: 1 month ago
Resolution: --- β†’ FIXED
Target Milestone: --- β†’ 152 Branch

Comment 16

β€’
1 month ago
Pushed by csabou@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/53bb72f2746d https://hg.mozilla.org/integration/autoland/rev/354f17602229 Revert "Bug 1829401 - Part 2: Support unadjustedMovement option and implement on macOS first; r=webidl,smaug,mstange" for causing failures on pointerlock-maintains-mousedown.html.

Comment 17

β€’
1 month ago
Pushed by csabou@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/7fa25c8ffbac https://hg.mozilla.org/mozilla-central/rev/0e22635834d4 Revert "Bug 1829401 - Part 2: Support unadjustedMovement option and implement on macOS first; r=webidl,smaug,mstange" for causing failures on pointerlock-maintains-mousedown.html.
Status: RESOLVED β†’ REOPENED
Resolution: FIXED β†’ ---
Target Milestone: 152 Branch β†’ ---

Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/59764 for changes under testing/web-platform/tests

Blocks: 2038309
No longer blocks: 1898998

Comment 21

β€’
1 month ago
Pushed by echen@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/97c84d223966 https://hg.mozilla.org/integration/autoland/rev/521ba1138293 Part 1: Implements Element.requestPointerLock() to return Promise<undefined>; r=smaug,webidl https://github.com/mozilla-firefox/firefox/commit/90143df1b5db https://hg.mozilla.org/integration/autoland/rev/26dc07739a54 Part 2: Support unadjustedMovement option and implement on macOS first; r=webidl,smaug,mstange

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
Status: REOPENED β†’ RESOLVED
Closed: 1 month ago β†’ 1 month ago
Resolution: --- β†’ FIXED
Target Milestone: --- β†’ 152 Branch
Flags: needinfo?(noahbpeterson1997)

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.

Status: RESOLVED β†’ VERIFIED
You need to log in before you can comment on or make changes to this bug.