Web apps can now disable mouse acceleration when capturing pointer events.
Accelerated movement is an ergonomic feature when using a mouse or trackpad to move the pointer on screen. It allows precise movement by moving slowly while also allowing the pointer to cross the entire screen with a quick short motion. Specifically, for the same physical distance that you move the mouse, the pointer on screen travels further if the distance was traveled faster.
Operating systems enable mouse acceleration by default. For some first-party perspective games, commonly first-person shooters (FPS), raw mouse input data is used to control camera rotation without an acceleration adjustment. The same physical motion, slow or fast, results in the same rotation. This results in a better gaming experience and higher accuracy according to professional gamers.
Starting in Chrome 88, web apps can switch back and forth between accelerated and non-accelerated mouse movement data thanks to the updated Pointer Lock API.
Web-based gaming platforms such as Google Stadia and Nvidia GeForce Now already use these new capabilities to please FPS gamers.
Using the API
Request a pointer lock
A pointer lock is the canonical term for when a desktop application hides the pointer icon and interprets mouse motion for something else, e.g. looking around in a 3D world.
The movementX
and movementY
attributes from the mousemove
document events
tell you how much the mouse pointer moved since the last move event. However,
those are not updated when the pointer moves outside of the web page.
document.addEventListener("mousemove", (event) => {
console.log(`movementX: ${event.movementX} movementY: ${event.movementY}`);
});
Capturing the mouse pointer (or requesting a pointer lock) allows you to not worry about the pointer moving outside anymore. This is especially useful for immersive web games. When the pointer is locked, all mouse events go to the target element of the pointer lock.
Call requestPointerLock()
on the target element to request a pointer lock, and
listen to pointerlockchange
and pointerlockerror
events to monitor pointer
lock changes.
const myTargetElement = document.body;
// Call this function to request a pointer lock.
function requestPointerLock() {
myTargetElement.requestPointerLock();
}
document.addEventListener("pointerlockchange", () => {
if (document.pointerLockElement) {
console.log(`pointer is locked on ${document.pointerLockElement}`);
} else {
console.log("pointer is unlocked");
}
});
document.addEventListener("pointerlockerror", () => {
console.log("pointer lock error");
});
Disable mouse acceleration
Call requestPointerLock()
with { unadjustedMovement: true }
to disable
OS-level adjustment for mouse acceleration, and access raw mouse input.
This way, mouse movement data from mousemove
events won't include mouse
acceleration when the pointer is locked.
Use the new returned promise from requestPointerLock()
to know if the request
was successful.
function requestPointerLockWithUnadjustedMovement() {
const promise = myTargetElement.requestPointerLock({
unadjustedMovement: true,
});
if (!promise) {
console.log("disabling mouse acceleration is not supported");
return;
}
return promise
.then(() => console.log("pointer is locked"))
.catch((error) => {
if (error.name === "NotSupportedError") {
// Some platforms may not support unadjusted movement.
// You can request again a regular pointer lock.
return myTargetElement.requestPointerLock();
}
});
}
It is possible to toggle between accelerated and non-accelerated mouse movement data without releasing the pointer lock. Simply request the pointer lock again with the desired option. If that request fails, the original lock will remain intact and the returned promise will reject. No pointer lock events will fire for a failed change request.
Browser support
The Pointer Lock API is well supported across browsers. However Chromium-based browsers (e.g. Chrome, Edge, etc.) are the only ones to support disabling OS-level adjustment for mouse acceleration as of October 2020. See MDN's Browser compatibility table for updates.
Operating system support
Disabling OS-level adjustment for mouse acceleration is supported on ChromeOS, macOS Catalina 10.15.1, and Windows. Linux will follow.
Sample
You can play with the Pointer Lock API by running the sample on Glitch. Be sure to check out the source code.
Helpful links
- Explainer
- Specification PR
- GitHub repository
- ChromeStatus entry
- Chrome tracking bug
- Intent to ship
- Mozilla's position
- WebKit's position
Acknowledgements
Thanks to James Hollyer, Thomas Steiner, Joe Medley, Kayce Basques, and Vincent Scheib for their reviews of this article.