├── .github ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── auto-publish.yml │ └── tidy.yml ├── .gitignore ├── .pr-preview.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── FeatureRequests.md ├── LICENSE.md ├── README.md ├── index.html ├── publish ├── Errata.md ├── index-2013-10-31-LCWD-flattened.html ├── index-2013-10-31-LCWD.html ├── index-2013-12-17-CR-flattened.html ├── index-2016-07-05-CR-flattened.html ├── index-2016-07-05-CR.html ├── index-2016-08-30-PR-flattened.html ├── index-2016-10-27-REC-flattened.html ├── index-v2-2016-11-22-FPWD-flattened.html └── index-v2-2018-02-08-WD-flattened.html ├── tests ├── movementX_Y_basic-manual.html ├── movementX_Y_no-jumps-manual.html ├── pointerlock_basic-manual.html ├── pointerlock_fullscreen-manual.html ├── pointerlock_indefinite-manual.html ├── pointerlock_leave_Tab-manual.html ├── pointerlock_leave_UA-manual.html ├── pointerlock_remove_target-manual.html ├── resources │ ├── LICENSE │ ├── readme.md │ ├── testharness.css │ ├── testharness.js │ └── testharnessreport.js └── test-results │ ├── Ch53.json │ ├── Ed25.json │ ├── Ff51.json │ ├── all.html │ ├── analysis.css │ ├── bootstrap.min.css │ ├── complete-fails.html │ └── less-than-2.html ├── tidyconfig.txt └── w3c.json /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Closes #??? 2 | 3 | The following tasks have been completed: 4 | 5 | * [ ] Modified Web platform tests (link to pull request) 6 | 7 | Implementation commitment: 8 | 9 | * [ ] WebKit (https://bugs.webkit.org/show_bug.cgi?id=) 10 | * [ ] Chromium (https://bugs.chromium.org/p/chromium/issues/detail?id=) 11 | * [ ] Gecko (https://bugzilla.mozilla.org/show_bug.cgi?id=) -------------------------------------------------------------------------------- /.github/workflows/auto-publish.yml: -------------------------------------------------------------------------------- 1 | name: Node CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - gh-pages 7 | pull_request: {} 8 | 9 | jobs: 10 | validate-and-publish: 11 | name: Validate and Publish 12 | runs-on: ubuntu-latest # only linux supported at present 13 | steps: 14 | - uses: actions/checkout@v2 15 | - uses: w3c/spec-prod@v2 16 | with: 17 | TOOLCHAIN: respec 18 | VALIDATE_LINKS: true 19 | W3C_ECHIDNA_TOKEN: ${{ secrets.ECHIDNA_TOKEN }} 20 | W3C_WG_DECISION_URL: "https://lists.w3.org/Archives/Public/public-webapps/2014JulSep/0627.html" 21 | W3C_NOTIFICATIONS_CC: "${{ secrets.CC }}" 22 | W3C_BUILD_OVERRIDE: | 23 | specStatus: WD 24 | shortName: pointerlock-2 25 | -------------------------------------------------------------------------------- /.github/workflows/tidy.yml: -------------------------------------------------------------------------------- 1 | name: Tidy document 2 | on: 3 | workflow_dispatch: {} 4 | push: 5 | branches: 6 | - gh-pages 7 | 8 | jobs: 9 | tidy: 10 | name: Tidy up 11 | runs-on: macos-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | - run: brew install tidy-html5 15 | - run: tidy -config tidyconfig.txt -o index.html index.html 16 | - uses: peter-evans/create-pull-request@v3 17 | with: 18 | title: "Tidied up document using tidy-html5" 19 | commit-message: "chore: tidy up index.html" 20 | branch: html-tidy 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .hg 2 | .hgignore 3 | -------------------------------------------------------------------------------- /.pr-preview.json: -------------------------------------------------------------------------------- 1 | { 2 | "src_file": "index.html", 3 | "type": "respec" 4 | } -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | All documentation, code and communication under this repository are covered by the [W3C Code of Ethics and Professional Conduct](https://www.w3.org/Consortium/cepc/). 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributions to this repository are intended to become part of Recommendation-track documents governed by the 2 | [W3C Patent Policy](http://www.w3.org/Consortium/Patent-Policy-20040205/) and 3 | [Software and Document License](http://www.w3.org/Consortium/Legal/copyright-software). To make substantive contributions to specifications, you must either participate 4 | in the relevant W3C Working Group or make a non-member patent licensing commitment. 5 | 6 | If you are not the sole contributor to a contribution (pull request), please identify all 7 | contributors in the pull request comment. 8 | 9 | To add a contributor (other than yourself, that's automatic), mark them one per line as follows: 10 | 11 | ``` 12 | +@github_username 13 | ``` 14 | 15 | If you added a contributor by mistake, you can remove them in a comment with: 16 | 17 | ``` 18 | -@github_username 19 | ``` 20 | 21 | If you are making a pull request on behalf of someone else but you had no part in designing the 22 | feature, you can remove yourself with the above syntax. 23 | 24 | # Tests 25 | 26 | For normative changes, a corresponding 27 | [web-platform-tests](https://github.com/web-platform-tests/wpt) PR is highly appreciated. Typically, 28 | both PRs will be merged at the same time. Note that a test change that contradicts the spec should 29 | not be merged before the corresponding spec change. If testing is not practical, please explain why 30 | and if appropriate [file an issue](https://github.com/web-platform-tests/wpt/issues/new) to follow 31 | up later. Add the `type:untestable` or `type:missing-coverage` label as appropriate. 32 | -------------------------------------------------------------------------------- /FeatureRequests.md: -------------------------------------------------------------------------------- 1 | # Features to be considered for Next Version 2 | 3 | Feature requests and new requirements for the next version of the [Pointer Lock specification](https://w3c.github.io/pointerlock/) are gathered here for consideration in subsiquent versions of the specification. 4 | 5 | Submit a feature request by filing a [Pointer Lock Issue](https://github.com/w3c/pointerlock/issues) or submiting a pull request with changes to this document. 6 | 7 | ## Pointer Clip: Limiting movement of the cursor without hiding it 8 | 9 | https://github.com/w3c/pointerlock/issues/27 10 | 11 | * Restrict pointer to a rectangle (while either windowed or in fullscreen (relevant for multi-display)) 12 | * Suppress any user agent or operating system UI elements that appear when hovering cursor in a region. This prevents e.g. a "hover near top of screen to bring down fullscreen exit instruction reminder" or the Mac OSX Dock that appears at screen edges. 13 | * Security issues would then be essentially the same as pointer lock, the difference being that a) the pointer is not hidden, b) the pointer is not warped, c) the pointer is bounded by the area specified by the web app - not the user agent selected rectangle used as an implementation detail of pointer lock. 14 | * [Notes on Pointer Clip from a Chromium discussion](https://docs.google.com/a/chromium.org/document/d/1lfU5BwiBaC0CeqsbUWLGGKtAr5tho6PBrN2zXk3he6A/edit?pli=1). 15 | * See thread [Problems with mouse-edge scrolling and games](http://lists.w3.org/Archives/Public/public-webapps/2014JanMar/0473.html). 16 | 17 | 18 | ## Raw movement data, not pixel location clamped, and unmodified by operating system 'acceleration' or 'ballistics' 19 | 20 | * Operating systems perform conditioning of mouse input data to facilitate use for a system pointer. Typically faster mouse movement results in a larger pointer movement for the same distance traveled. Some articles on this topic: 21 | * http://blog.codinghorror.com/mouse-ballistics/ 22 | * https://msdn.microsoft.com/en-us/library/windows/desktop/ee418864.aspx 23 | * Sub pixel movement accuracy doesn't offer a pixel based screen pointer an advantage, but may have meaningful interpretation by applications using Pointer Lock. 24 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | All documents in this Repository are licensed by contributors 2 | under the 3 | [W3C Software and Document License](http://www.w3.org/Consortium/Legal/copyright-software). -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | The Web Applications Working Group's 2 | 3 | [Pointer Lock 2 Specification](https://w3c.github.io/pointerlock/) 4 | 5 | which extends the initial 6 | 7 | [Pointer Lock W3C Recommendation Specification](https://www.w3.org/TR/pointerlock/). 8 | 9 | See also the [Pointer Lock Feature Requests](FeatureRequests.md). 10 | -------------------------------------------------------------------------------- /publish/Errata.md: -------------------------------------------------------------------------------- 1 | # Pointer Lock Errata for W3C Recommendation 20 October 2016 2 | 3 | This document describes the known errata and proposed corrections for the Pointer Lock API published as an [Recommendation](https://www.w3.org/TR/pointerlock/) on 20 October 2016. -------------------------------------------------------------------------------- /publish/index-2013-10-31-LCWD.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |The Pointer Lock API provides for input methods of applications based on 118 | the movement of the mouse, not just the absolute position of a cursor. A 119 | popular example is that of first person movement controls in three 120 | dimensional graphics applications such as games. Movement of the mouse is 121 | interpreted for rotation of the view-port, there is no limit to how far 122 | movement can go, and no mouse cursor is displayed.
123 | 124 |Pointer Lock is related to Mouse Capture [[MDN-SETCAPTURE]]. Capture provides 125 | continued event delivery to a target element while a mouse is being 126 | dragged, but ceases when the mouse button is released. Pointer Lock differs 127 | by being persistent, not limited by screen boundaries, sending events 128 | regardless of mouse button state, hiding the cursor, and not releasing 129 | until an API call or specific default unlock gesture by the user.
130 | 131 |Pointer Lock deals with capturing a single resource and relating it to 132 | a single element. This is similar to the Fullscreen API [[FULLSCREEN]], which 133 | promotes a single element to be full screen. The Pointer Lock API chooses 134 | to pattern the resource capture, state change, and release API as closely 135 | as possible after the Fullscreen API.
136 | 137 |The Pointer Lock interaction mode was previously referred to as 138 | mouse lock. The name was changed as many different controller types 139 | besides mice can manipulate the on screen pointing cursor, and they are 140 | all impacted.
141 | 142 |146 | This specification defines conformance criteria that apply to a single 147 | product: the user agent that implements 148 | the interfaces that it contains. 149 |
150 | 151 |152 | Implementations that use ECMAScript to implement the APIs defined in 153 | this specification MUST implement them in a manner consistent with the 154 | ECMAScript Bindings defined in the Web IDL specification [[!WEBIDL]] as 155 | this specification uses that specification and terminology. 156 |
157 | 158 |159 | A conforming implementation is required to implement all fields 160 | defined in this specification. 161 |
162 |click
, but not
171 | mousemove
.
172 | Engagement gestures are any events included in the definition of being
173 |
174 | allowed to show a popup
175 | with the addition of keypress
and keyup
.
176 | pointerlockchange
and pointerlockerror
EventsTwo events are used to communicate pointer lock state change or 185 | an error in changing state. They are named pointerlockchange 186 | and pointerlockerror. If pointer lock is entered or exited 187 | for any reason a pointerlockchange event must be sent.
188 | 189 |User agents
190 | must deliver these events by
192 | queuing a task to
194 | fire an event of the appropriate name with its
195 | bubble
attribute set to false to the pointer lock
196 | target element's
198 | node document.
204 | The Element interface is extended to provide the ability to 205 | request the the pointer be locked. 206 |
207 | 208 |Requests that the pointer be locked to a DOM element 214 | target. The user agent determines if pointer lock 215 | state will be entered and upon lock state change or error must send 216 | either a pointerlockchange or pointerlockerror 217 | event respectively. 218 | 219 |
Pointer lock must succeed only if the document object's 220 | 221 | active sandboxing flag set does not have the 222 | sandboxed pointer lock browsing context flag set. 223 | 224 |
Pointer lock must succeed only if the target is 225 | in 226 | the 227 | active document 228 | of a 229 | browsing context 230 | which is (or has an 231 | ancestor browsing context 232 | which is) in focus by a window which is in focus by the 233 | operating system's window manager. The target element and its 234 | browsing context 235 | need not be in focus.
236 | 237 |If a user has exited pointer lock via the default unlock user 238 | gesture, or pointer lock has not previously been entered for this 239 | document, an event generated as a result of an 240 | engagement gesture must be received by the document before 241 | requestPointerLock will succeed.
242 | 243 |
244 | This ensures a user can leave a
245 | document that constantly attempts to lock the pointer. The document
246 | will be blocked from locking upon initial navigation or re-acquiring
247 | lock unless the user re-engages directly with the document.
248 |
249 | Conversely, if pointer lock is exited via exitPointerLock
250 | no engagement gesture is required to reenter pointer lock. This enables
251 | applications that frequently move between interaction modes, and
252 | ones that may do so based on a timer or remote network activity.
253 |
254 |
255 | Pointer lock is commonly combined with fullscreen [[FULLSCREEN]], and
256 | if an engagement gesture is used to enter fullscreen it is sufficient
257 | for a subsequent requestPointerLock.
258 |
If any element (including this one) in the same document 261 | is already locked (or pending lock) the pointer 262 | lock target must be updated to this element and a 263 | pointerlockchange event sent.
264 | 265 |If any element in another document is already locked the request 266 | must fail and a pointerlockerror event be sent.
267 | 268 |Once in the locked state the user agent must fire all relevant
269 | user generated MouseEvent
events (for example:
270 | mousemove
, mousedown
, mouseup
,
271 | click
, wheel
)[[!DOM-LEVEL-3-CORE]]
272 | to the target of pointer lock, and not fire mouse events to
273 | other elements. Events that require the concept of a mouse cursor must
274 | not be dispatched (for example: mouseover
,
275 | mouseout
, drag
, drop
).
In the locked state the system mouse cursor 278 | must be hidden. Movement and button presses of the mouse must not 279 | cause the window to lose focus.
280 | 281 |Synthetic mouse events created by application script act the same 282 | regardless of lock state.
283 |
An event handler 296 | for pointerlockchange events.
297 |An event handler 304 | for pointerlockerror events.
305 |Returns the element set as the target for mouse events 312 | while the pointer is locked. Null if lock is pending, pointer is 313 | unlocked, or if the target is in another document.
314 |Initiates an exit from pointer lock state if currently locked 321 | to a target in this document, 322 | and sends a pointerlockchange event when the lock state 323 | has been exited.
324 | 325 |The system mouse cursor must be displayed again and positioned at
326 | the same location that it was when pointer lock was entered (the same
327 | location that is reported in screenX
/Y
328 | when the pointer is locked).
User agents must extend the MouseEvent interface [DOMMOUSE] 338 | with two members:
339 | 340 |The members movementX
and movementY
must
348 | provide the change in position of the pointer, as if the values of
349 | screenX
/Y
were stored between two subsequent
350 | mousemove
events eNow
and
351 | ePrevious
and the difference taken
352 | movementX = eNow.screenX-ePrevious.screenX
.
movementX
/Y
must be zero for all mouse events
355 | except mousemove
. All motion data must be delivered via
356 | mousemove
events such that between any two mouse events
357 | earlierEvent
and currentEvent
the value of
358 | currentEvent.screenX-earlierEvent.screenX
is equivalent to
359 | the sum of all movementX
values received on
360 | mousemove
events after earlierEvent
.
movementX
/Y
must be valid regardless of pointer
363 | lock state.
When unlocked, the system cursor can exit and re-enter the user
366 | agent window. If it does so and the user agent was not the
367 | target of operating system mouse move events then the most recent pointer
368 | position will be unknown to the user agent and
369 | movementX
/Y
can not be computed and must be set
370 | to zero.
When pointer lock is enabled clientX
, clientY
,
373 | screenX
, and screenY
must hold constant values
374 | as if the pointer did not move at all once pointer lock was entered. But
375 | movementX
/Y
must continue to provide the change
376 | in position of the pointer as when the pointer is unlocked. There will be no
377 | limit to movementX
/Y
values if the mouse is
378 | continuously moved in a single direction. The concept of the mouse cursor
379 | will have been removed, and it will not move off the window or be clamped
380 | by a screen edge.
A default unlock gesture must always be available that 387 | will exit pointer lock.
388 |The ESC key is the recommended default unlock 389 | gesture for user agents with keyboard input. It is recommended that 390 | the unlock gesture also match any used to exit fullscreen 391 | [[FULLSCREEN]].
392 | 393 |Pointer lock must be exited if the 394 | target is removed from its document, or the user agent, 395 | window, or tab loses focus. Moving focus between elements of 396 | active documents, 397 | including between 398 | browsing contexts, 399 | does not exit pointer lock. E.g. using the keyboard 400 | to move focus between contents of frames or iframes will not exit.
401 | 402 |Pointer lock must not be exited when fullscreen [[FULLSCREEN]] is 403 | entered or exited unless the pointer is required to enable interaction 404 | with the user agent graphical user interface or the default 405 | unlock gesture was used to exit both fullscreen and pointer 406 | lock.
407 |A player on a first/third person game will need to control the 416 | view-port orientation. A widely used method is the use of mouse movements 417 | to control the viewing angle. This kind of application can use the Pointer 418 | Lock API to allow a complete freedom of control over the viewport's yaw 419 | and pitch even when the user is not pressing mouse buttons. Those buttons 420 | can be used for other actions while constantly providing navigation via 421 | mouse movement.
422 |Users of a three dimensional modeling application will need to rotate 428 | models. A application can use the Pointer Lock API to enable the author to 429 | rotate the model freely in a drag operation without limiting motion. 430 | Without pointer lock a drag would stop providing motion data when the mouse 431 | cursor is limited by the edge of the screen.
432 | 433 |Similarly, absolute motion panning of a large two dimensional image 434 | could be permitted in a single drag operation without cursor / screen 435 | limits.
436 |A player on a fast reflexes game controls a paddle to bounce back a 442 | ball to the opponent, while allowing the same paddle to execute actions 443 | based on different mouse buttons being pressed. The application can use 444 | the Pointer Lock API to allow the player to react quickly without being 445 | concerned about the mouse cursor leaving the game play area and clicking 446 | another system application, thus breaking the game flow.
447 |When modifying numerically magnitudes in applications sometimes the 453 | user will prefer to "drag" a numeric control by its button handles to 454 | increment or decrement the numeric value. E.g. a spinner with a 455 | number entry text box and arrows pointing up and down that can be 456 | clicked or dragged on to change the value. An 457 | application could use the Pointer Lock API to allow modifying the numeric 458 | values beyond what the logical screen bounds allow. The same could apply 459 | for a control that fast forwards or rewinds a video or audio stream like a 460 | "jog".
461 |Some games use a classical cursor, however they want it to be limited 467 | or controlled in some manner. E.g. limited to the bounds of the game, or 468 | movable by the game. Locking the pointer enables this if the application 469 | creates their own cursor. However HTML and DOM should still be available 470 | to use for user interface. Synthetic mouse events should be permitted to 471 | allow an application defined cursor to interact with DOM. E.g. the 472 | following code should permit a custom cursor to send click events while 473 | the pointer is locked:
474 | 475 |476 | document.addEventListener("click", function (e) { 477 | if (e._isSynthetic) 478 | return; 479 | // send a synthetic click 480 | var ee = document.createEvent("MouseEvents"); 481 | ee._isSynthetic = true; 482 | x = myCursor.x; 483 | y = myCursor.y; 484 | ee.initMouseEvent("click", true, true, null, 1, 485 | x + e.screenX - e.clientX, 486 | y + e.screenY - e.clientY, 487 | x, 488 | y); 489 | var target = document.elementFromPoint(x, y) 490 | if (target) 491 | target.dispatchEvent(ee) 492 | }); 493 |494 | 495 |
Note that synthetic clicks may not be permitted by a user agent to 496 | produce the same default action as a non-synthetic click. However, 497 | application handlers can still take action and provide user interface with 498 | existing HTML & DOM mechanisms.
499 |Real Time Strategy games often use this technique. When the player 506 | moves the pointer to the view-port borders, if they "push" the border 507 | with a mouse movement, the view-port is panned over the game area 508 | according to how much they move the mouse. When moving the mouse cursor 509 | within the bounds of the view port it acts at is typically would on a 510 | system. Applications may choose to implement this using pointer lock and 511 | the previous use case of "Synthetic cursor interaction with HTML DOM UI" 512 | to bring cursor behavior completely under their control.
513 |Games that use pointer lock may desire a traditional UI and system cursor 519 | while players prepare in a game lobby. Games usually start after a short 520 | timer when all players are ready. Ideally the game could then switch to 521 | pointer lock mode without requiring an engagement gesture. 522 | Players should be able 523 | to seamlessly move from the game lobby into game navigation.
524 |Game portals, and other sites such as Facebook and Google Plus, host 530 | games for users to play. These games may be hosted and served from a 531 | different origin from that of the portal site. Embedded games should be 532 | able to lock the pointer, even in non-full screen mode.
533 |Security Concerns:
541 |Responses:
557 |Recommendations:
580 |Pointer lock is a required user interaction mode for certain application 588 | types, but carries a usability concern if maliciously used. An attacker 589 | could remove the ability for a user to control their mouse cursor on their 590 | system. User agents will prevent this by always providing a mechanism to 591 | exit pointer lock, by informing the user of how, and by limiting how pointer 592 | lock can be entered.
593 | 594 |User agents will determine their own appropriate policies, which may be 595 | specialized per device or differ based on user options. 596 |
Mouse Capture [[MDN-SETCAPTURE]] 605 | handles low security risk mouse event target lock for the duration of a 606 | mouse drag gesture. pointer lock removes the concept of the cursor and 607 | directs all events to a given target. They are related, but 608 | different.
609 | 610 |If a browser implemented both, it would be reasonable to support a 611 | combination of traits: The security simplicity of "automatically release 612 | lock when mouse up" and the increased functionality of total control over 613 | mouse input and removal of the system cursor. The security trait would 614 | allow more permissive use of the feature for applications that only 615 | required a short burst of pointer lock during a drag event.
616 | 617 |This functionality is omitted from the initial version of this spec 618 | because it helps the minor use cases in windowed mode but we still do not 619 | have an implementation solving the major ones. And, to implement this a 620 | browser must implement both, which none does yet. It is not clear if this 621 | feature should live on .lock or on .setCapture. If both were 622 | implemented, either API could be augmented fairly easily to offer the 623 | hybrid functionality.
624 |Even in non locked state, the delta values of mouse movement are 630 | useful. Changing the meaning of .client or .screen based on lock state 631 | would also cause easy errors in code not carefully monitoring the lock 632 | state.
633 |When the pointer is locked 'wheel' events should be sent to the pointer 639 | lock target element just as 'mousemove' events are. There is a naming 640 | conflict with .deltaX/Y/Z as defined in DOM 642 | 3 'wheel' event.
643 |There are good motivations to provide a more fine grained approach. 652 | E.g. the use case "View-port panning by moving a mouse cursor against the 653 | bounds of a view-port" doesn't require hiding the mouse cursor, only 654 | bounding it and always having delta values available. Also, this 655 | specification defines the movement deltas to be taken from how the system 656 | mouse cursor moves, which incorporates operating system filtering and 657 | acceleration of the mouse movement data. Applications may desire access 658 | to a more raw form of movement data prior to adjustments appropriate for a 659 | mouse cursor. Also, raw data may provide better than pixel level accuracy 660 | for movement, as well as higher frequency updates. Providing the raw 661 | delta movement would also not require special permission or mode from a 662 | user, and for some set of applications that do not require bounding the 663 | cursor may reduce the security barriers and prompts needed.
664 | 665 |There are two justifications for postponing this finer grained 666 | approach. The first is a concern of specifying what units mouse movement 667 | data are provided in. This specification defines .movementX/Y precisely 668 | as the same values that could be recorded when the mouse is not under lock 669 | by changes in .screenX/Y. Implementations across multiple user agents and 670 | operating systems will easily be able to meet that requirement and provide 671 | application developers and users with a consistent experience. Further, 672 | users are expected to have already configured the full system of hardware 673 | input and operating system options resulting in a comfortable control the 674 | system mouse cursor. By specifying .movementX/Y in the same units mouse 675 | lock API applications will be instantly usable to all users because they 676 | have already settled their preferences.
677 | 678 |Secondly, the implementation of providing movement data and bounding 679 | the mouse cursor is more difficult in the fine grained approach. Bundling 680 | the features together gives implementations freedom to use a variety of 681 | techniques as appropriate on each operating system and is more practical 682 | to implement. Direct APIs do not exist on all platforms (Win, Mac, Linux) 683 | to bound the cursor to a specific rectangle, and prototypes have not yet 684 | been developed to demonstrate building that behavior by e.g. invisible 685 | windows with xlib or manual cursor movement on Mac. Unaccelerated Delta 686 | values have been proposed to be accessed by reading raw Human Interface 687 | Device (HID) data. E.g. WM_INPUT messages on windows, and USB device 688 | APIs on Mac / Linux. The challenge here is interpreting and normalizing 689 | the units to some consistent and specifiable scale. Also, most APIs 690 | considered to date are limited to USB devices.
691 | 692 |It would be reasonable to consider adding these capabilities in the 693 | future, as the currently specified pointer lock API would be easy to 694 | continue to support if the finer grained delta and confinement features 695 | were implemented.
696 | 697 |The bundled API is selected for implementation practicality, because 698 | the desired use cases are supported, and because it will not conflict with 699 | future improvements as discussed here.
700 |Not yet, for the same reasons in the previous Q. See "Why bundle all 706 | functionality (hiding cursor, providing mouse deltas) instead of using CSS 707 | to hide the cursor, always providing delta values, and offering an API to 708 | restrict the cursor movement to a portion of the web page?" above.
709 |When under pointer lock many mouse events remain relevant, e.g. click, 716 | mousedown, etc. These all share the same event data structure MouseEvent. 717 | If movement data were reported via a new data structure then a new event 718 | would be needed for reporting delta movement. The new data structure 719 | would have many parallels to MouseEvent to offer the same conveniences, 720 | e.g. button and modifier key states. When handling click, down, and up 721 | events would the existing mousedown, mouseup be used? If so, they would 722 | provide .clientX/Y and .screenX/Y with no useful data, but would lack the 723 | convenience of containing the current movement data. Or, new events would 724 | also be required for when the mouse is locked.
725 | 726 |Also, movementX/Y are convenient even when the mouse is not locked. 727 | This spec requires movement members to always be valid, even when the 728 | mouse cursor exists. This reduces code required to track the last cursor 729 | state and mouseover/mouseout transitions if applications wish to make 730 | use of delta motion of the mouse.
731 | 732 |The only negative of adding movementX/Y to MouseEvent appears to be the 733 | unused values in clientX/Y and screenX/Y when under pointer lock. This does 734 | not seem to be a significant problem.
735 | 736 |Therefore the minimal change to add movementX/Y to MouseEvent is 737 | selected to reduce API and implementation complexity.
738 |Consider a game with a 3D view controlled by moving the mouse cursor, 745 | while the user may still chat with other users via a text console. It is 746 | reasonable for the application to accept text input to an element that is 747 | different than where mouse events are being dispatched. This is similar 748 | to pre-existing behavior of receiving mousemove events over any element 749 | while typing into a form on a page.
750 |Many have made contributions to the discussions of this 758 | specification:
759 | 760 |122 | A history of changes to this document can be found at 123 | 124 | http://dvcs.w3.org/hg/pointerlock/log/default/index.html 125 |
126 |127 | Summary of changes: 128 |
The Pointer Lock API provides for input methods of applications based on 158 | the movement of the mouse, not just the absolute position of a cursor. A 159 | popular example is that of first person movement controls in three 160 | dimensional graphics applications such as games. Movement of the mouse is 161 | interpreted for rotation of the view-port, there is no limit to how far 162 | movement can go, and no mouse cursor is displayed.
163 | 164 |Pointer Lock is related to 165 | Mouse Capture [[MSDN-SETCAPTURE]] [[MDN-SETCAPTURE]] 166 | (Mouse Capture is unspecified: bug 167 | 14600). 168 | Capture provides 169 | continued event delivery to a target element while a mouse is being 170 | dragged, but ceases when the mouse button is released. Pointer Lock differs 171 | by being persistent, not limited by screen boundaries, sending events 172 | regardless of mouse button state, hiding the cursor, and not releasing 173 | until an API call or specific default unlock gesture by the user.
174 | 175 |Pointer Lock deals with capturing a single resource and relating it to 176 | a single element. This is similar to the Fullscreen API [[FULLSCREEN]], which 177 | promotes a single element to be full screen. The Pointer Lock API chooses 178 | to pattern the resource capture, state change, and release API as closely 179 | as possible after the Fullscreen API.
180 | 181 |The Pointer Lock interaction mode was previously referred to as 182 | mouse lock. The name was changed as many different controller types 183 | besides mice can manipulate the on screen pointing cursor, and they are 184 | all impacted.
185 | 186 |190 | This specification defines conformance criteria that apply to a single 191 | product: the user agent that implements 192 | the interfaces that it contains. 193 |
194 | 195 |196 | Implementations that use ECMAScript to implement the APIs defined in 197 | this specification MUST implement them in a manner consistent with the 198 | ECMAScript Bindings defined in the Web IDL specification [[!WEBIDL]] as 199 | this specification uses that specification and terminology. 200 |
201 | 202 |203 | A conforming implementation is required to implement all fields 204 | defined in this specification. 205 |
206 |click
, but not
215 | mousemove
.
216 | Engagement gestures are any events included in the definition of being
217 |
218 | allowed to show a popup
219 | with the addition of keypress
and keyup
.
220 | Note that operating system level accessibility and internationalization
221 | features may intercept gestures before the user agent processes them
222 | for interaction with a page. E.g. multiple key press codes used to enter
223 | an extended international character.
224 | pointerlockchange
and pointerlockerror
EventsTwo events are used to communicate pointer lock state change or 233 | an error in changing state. They are named pointerlockchange 234 | and pointerlockerror. If pointer lock is entered or exited 235 | for any reason a pointerlockchange event must be sent.
236 | 237 |User agents
238 | must deliver these events by
240 | queuing a task to
242 | fire an event of the appropriate name with its
243 | bubbles
attribute [[!DOM4]]
244 | set to false to the pointer lock
245 | target element's
247 | node document.
Magnification software increases the size of content on 250 | the screen. It uses the mouse to move the magnified point of focus 251 | around. When a pointer lock is initiated, the magnification software 252 | needs to switch to using the keyboard to move the magnified point of 253 | focus around instead. When a pointerlockchange event is fired, web 254 | browsers therefore need to make sure the event is communicated to 255 | assistive technologies like screen magnifiers.
256 |261 | The Element interface is extended to provide the ability to 262 | request the the pointer be locked. 263 |
264 | 265 |Requests that the pointer be locked to a DOM element 271 | target. The user agent determines if pointer lock 272 | state will be entered and upon lock state change or error must send 273 | either a pointerlockchange or pointerlockerror 274 | event respectively. 275 | 276 |
Pointer lock must succeed only if the document object's 277 | 278 | active sandboxing flag set does not have the 279 | sandboxed pointer lock browsing context flag set. 280 | 281 |
Pointer lock must succeed only if the target is 282 | in 283 | the 284 | active document 285 | of a 286 | browsing context 287 | which is (or has an 288 | ancestor browsing context 289 | which is) in focus by a window which is in focus by the 290 | operating system's window manager. The target element and its 291 | browsing context 292 | need not be in focus.
293 | 294 |If a user has exited pointer lock via the default unlock user 295 | gesture, or pointer lock has not previously been entered for this 296 | document, an event generated as a result of an 297 | engagement gesture must be received by the document before 298 | requestPointerLock will succeed.
299 | 300 |
301 | This ensures a user can leave a
302 | document that constantly attempts to lock the pointer. The document
303 | will be blocked from locking upon initial navigation or re-acquiring
304 | lock unless the user re-engages directly with the document.
305 |
306 | Conversely, if pointer lock is exited via exitPointerLock
307 | no engagement gesture is required to reenter pointer lock. This enables
308 | applications that frequently move between interaction modes, and
309 | ones that may do so based on a timer or remote network activity.
310 |
311 |
312 | Pointer lock is commonly combined with fullscreen [[FULLSCREEN]], and
313 | if an engagement gesture is used to enter fullscreen it is sufficient
314 | for a subsequent requestPointerLock.
315 |
If any element (including this one) in the same document 318 | is already locked (or pending lock) the pointer 319 | lock target must be updated to this element and a 320 | pointerlockchange event sent.
321 | 322 |If any element in another document is already locked the request 323 | must fail and a pointerlockerror event be sent.
324 | 325 |Once in the locked state the user agent must fire all relevant
326 | user generated MouseEvent
events (for example:
327 | mousemove
, mousedown
, mouseup
,
328 | click
, and wheel
)[[!UIEVENTS]]
329 | to the target of pointer lock, and not fire mouse events to
330 | other elements. Events that require the concept of a mouse cursor must
331 | not be dispatched (for example: mouseover
,
332 | mouseout
, drag
, and drop
).
In the locked state the system mouse cursor 335 | must be hidden. Movement and button presses of the mouse must not 336 | cause the window to lose focus.
337 | 338 |Synthetic mouse events created by application script act the same 339 | regardless of lock state.
340 |
An event handler 353 | for pointerlockchange events.
354 |An event handler 361 | for pointerlockerror events.
362 |Returns the element set as the target for mouse events 369 | while the pointer is locked. Null if lock is pending, pointer is 370 | unlocked, or if the target is in another document.
371 |Initiates an exit from pointer lock state if currently locked 378 | to a target in this document, 379 | and sends a pointerlockchange event when the lock state 380 | has been exited.
381 | 382 |The system mouse cursor must be displayed again and positioned at
383 | the same location that it was when pointer lock was entered (the same
384 | location that is reported in screenX
, screenY
,
385 | when the pointer is locked).
User agents must extend the MouseEvent interface 394 | [[!UIEVENTS]] 395 | with two members:
396 | 397 |The members movementX
and movementY
must
405 | provide the change in position of the pointer, as if the values of
406 | screenX
, screenY
, were stored between two subsequent
407 | mousemove
events eNow
and
408 | ePrevious
and the difference taken
409 | movementX = eNow.screenX-ePrevious.screenX
.
movementX
/Y
must be zero for all mouse events
412 | except mousemove
. All motion data must be delivered via
413 | mousemove
events such that between any two mouse events
414 | earlierEvent
and currentEvent
the value of
415 | currentEvent.screenX-earlierEvent.screenX
is equivalent to
416 | the sum of all movementX
values received on
417 | mousemove
events after earlierEvent
, with
418 | the exception of when screenX can not be updated because the pointer
419 | is clipped by the user agent screen boundaries.
movementX
/Y
must be updated regardless of pointer
422 | lock state.
When unlocked, the system cursor can exit and re-enter the user
425 | agent window. If it does so and the user agent was not the
426 | target of operating system mouse move events then the most recent pointer
427 | position will be unknown to the user agent and
428 | movementX
/Y
can not be computed and must be set
429 | to zero.
When pointer lock is enabled clientX
, clientY
,
432 | screenX
, and screenY
must hold constant values
433 | as if the pointer did not move at all once pointer lock was entered. But
434 | movementX
/Y
must continue to provide the change
435 | in position of the pointer as when the pointer is unlocked. There will be no
436 | limit to movementX
/Y
values if the mouse is
437 | continuously moved in a single direction. The concept of the mouse cursor
438 | will have been removed, and it will not move off the window or be clamped
439 | by a screen edge.
The un-initialized value of movementX
/Y
must
442 | be 0
.
User agents must extend the MouseEventInit dictionary
449 | [[!UIEVENTS]] with two members movementX
and
450 | movementY
used to initialize respective members
451 | of MouseEvent
.
A default unlock gesture must always be available that 465 | will exit pointer lock.
466 |The ESC key is the recommended default unlock 467 | gesture for user agents with keyboard input. It is recommended that 468 | the unlock gesture also match any used to exit fullscreen 469 | [[FULLSCREEN]].
470 | 471 |Pointer lock must be exited if the 472 | target is removed from its document, or the user agent, 473 | window, or tab loses focus. Moving focus between elements of 474 | active documents, 475 | including between 476 | browsing contexts, 477 | does not exit pointer lock. E.g. using the keyboard 478 | to move focus between contents of frames or iframes will not exit.
479 | 480 |Pointer lock must not be exited when fullscreen [[FULLSCREEN]] is 481 | entered or exited unless the pointer is required to enable interaction 482 | with the user agent graphical user interface, the default 483 | unlock gesture was used to exit both fullscreen and pointer 484 | lock, or window or tab focus was lost.
485 |A player on a first/third person game will need to control the 494 | view-port orientation. A widely used method is the use of mouse movements 495 | to control the viewing angle. This kind of application can use the Pointer 496 | Lock API to allow a complete freedom of control over the viewport's yaw 497 | and pitch even when the user is not pressing mouse buttons. Those buttons 498 | can be used for other actions while constantly providing navigation via 499 | mouse movement.
500 |Users of a three dimensional modeling application will need to rotate 506 | models. A application can use the Pointer Lock API to enable the author to 507 | rotate the model freely in a drag operation without limiting motion. 508 | Without pointer lock a drag would stop providing motion data when the mouse 509 | cursor is limited by the edge of the screen.
510 | 511 |Similarly, absolute motion panning of a large two dimensional image 512 | could be permitted in a single drag operation without cursor / screen 513 | limits.
514 |A player on a fast reflexes game controls a paddle to bounce back a 520 | ball to the opponent, while allowing the same paddle to execute actions 521 | based on different mouse buttons being pressed. The application can use 522 | the Pointer Lock API to allow the player to react quickly without being 523 | concerned about the mouse cursor leaving the game play area and clicking 524 | another system application, thus breaking the game flow.
525 |When modifying numerically magnitudes in applications sometimes the 531 | user will prefer to "drag" a numeric control by its button handles to 532 | increment or decrement the numeric value. E.g. a spinner with a 533 | number entry text box and arrows pointing up and down that can be 534 | clicked or dragged on to change the value. An 535 | application could use the Pointer Lock API to allow modifying the numeric 536 | values beyond what the logical screen bounds allow. The same could apply 537 | for a control that fast forwards or rewinds a video or audio stream like a 538 | "jog".
539 |Some games use a classical cursor, however they want it to be limited 545 | or controlled in some manner. E.g. limited to the bounds of the game, or 546 | movable by the game. Locking the pointer enables this if the application 547 | creates their own cursor. However HTML and DOM should still be available 548 | to use for user interface. Synthetic mouse events should be permitted to 549 | allow an application defined cursor to interact with DOM. E.g. the 550 | following code should permit a custom cursor to send click events while 551 | the pointer is locked:
552 | 553 |554 | document.addEventListener("click", function (e) { 555 | if (e._isSynthetic) 556 | return; 557 | // send a synthetic click 558 | var ee = document.createEvent("MouseEvents"); 559 | ee._isSynthetic = true; 560 | x = myCursor.x; 561 | y = myCursor.y; 562 | ee.initMouseEvent("click", true, true, null, 1, 563 | x + e.screenX - e.clientX, 564 | y + e.screenY - e.clientY, 565 | x, 566 | y); 567 | var target = document.elementFromPoint(x, y); 568 | if (target) 569 | target.dispatchEvent(ee); 570 | }); 571 |572 | 573 |
Note that synthetic clicks may not be permitted by a user agent to 574 | produce the same default action as a non-synthetic click. However, 575 | application handlers can still take action and provide user interface with 576 | existing HTML & DOM mechanisms.
577 |Real Time Strategy games often use this technique. When the player 584 | moves the pointer to the view-port borders, if they "push" the border 585 | with a mouse movement, the view-port is panned over the game area 586 | according to how much they move the mouse. When moving the mouse cursor 587 | within the bounds of the view port it acts at is typically would on a 588 | system. Applications may choose to implement this using pointer lock and 589 | the previous use case of "Synthetic cursor interaction with HTML DOM UI" 590 | to bring cursor behavior completely under their control.
591 |Games that use pointer lock may desire a traditional UI and system cursor 597 | while players prepare in a game lobby. Games usually start after a short 598 | timer when all players are ready. Ideally the game could then switch to 599 | pointer lock mode without requiring an engagement gesture. 600 | Players should be able 601 | to seamlessly move from the game lobby into game navigation.
602 |Game portals, and other sites such as Facebook and Google Plus, host 608 | games for users to play. These games may be hosted and served from a 609 | different origin from that of the portal site. Embedded games should be 610 | able to lock the pointer, even in non-full screen mode.
611 |Security Concerns:
619 |Responses:
635 |Recommendations:
658 |Pointer lock is a required user interaction mode for certain application 666 | types, but carries a usability concern if maliciously used. An attacker 667 | could remove the ability for a user to control their mouse cursor on their 668 | system. User agents will prevent this by always providing a mechanism to 669 | exit pointer lock, by informing the user of how, and by limiting how pointer 670 | lock can be entered.
671 | 672 |User agents will determine their own appropriate policies, which may be 673 | specialized per device or differ based on user options. 674 |
Mouse Capture [[MDN-SETCAPTURE]] 683 | handles low security risk mouse event target lock for the duration of a 684 | mouse drag gesture. Pointer lock removes the concept of the cursor and 685 | directs all events to a given target. They are related, but 686 | different.
687 | 688 |If a browser implemented both, it would be reasonable to support a 689 | combination of traits: The security simplicity of "automatically release 690 | lock when mouse up" and the increased functionality of total control over 691 | mouse input and removal of the system cursor. The security trait would 692 | allow more permissive use of the feature for applications that only 693 | required a short burst of pointer lock during a drag event.
694 | 695 |This functionality is omitted from the initial version of this spec 696 | because it helps the minor use cases in windowed mode but we still do not 697 | have an implementation solving the major ones. And, to implement this a 698 | browser must implement both, which none does yet. It is not clear if this 699 | feature should live on .lock or on .setCapture. If both were 700 | implemented, either API could be augmented fairly easily to offer the 701 | hybrid functionality.
702 |Even in non locked state, the delta values of mouse movement are 708 | useful. Changing the meaning of .client or .screen based on lock state 709 | would also cause easy errors in code not carefully monitoring the lock 710 | state.
711 |When the pointer is locked 'wheel' events should be sent to the pointer 717 | lock target element just as 'mousemove' events are. There is a naming 718 | conflict with .deltaX/Y/Z as defined in DOM 720 | 3 'wheel' event.
721 |There are good motivations to provide a more fine grained approach. 730 | E.g. the use case "View-port panning by moving a mouse cursor against the 731 | bounds of a view-port" doesn't require hiding the mouse cursor, only 732 | bounding it and always having delta values available. Also, this 733 | specification defines the movement deltas to be taken from how the system 734 | mouse cursor moves, which incorporates operating system filtering and 735 | acceleration of the mouse movement data. Applications may desire access 736 | to a more raw form of movement data prior to adjustments appropriate for a 737 | mouse cursor. Also, raw data may provide better than pixel level accuracy 738 | for movement, as well as higher frequency updates. Providing the raw 739 | delta movement would also not require special permission or mode from a 740 | user, and for some set of applications that do not require bounding the 741 | cursor may reduce the security barriers and prompts needed.
742 | 743 |There are two justifications for postponing this finer grained 744 | approach. The first is a concern of specifying what units mouse movement 745 | data are provided in. This specification defines .movementX/Y precisely 746 | as the same values that could be recorded when the mouse is not under lock 747 | by changes in .screenX/Y. Implementations across multiple user agents and 748 | operating systems will easily be able to meet that requirement and provide 749 | application developers and users with a consistent experience. Further, 750 | users are expected to have already configured the full system of hardware 751 | input and operating system options resulting in a comfortable control the 752 | system mouse cursor. By specifying .movementX/Y in the same units mouse 753 | lock API applications will be instantly usable to all users because they 754 | have already settled their preferences.
755 | 756 |Secondly, the implementation of providing movement data and bounding 757 | the mouse cursor is more difficult in the fine grained approach. Bundling 758 | the features together gives implementations freedom to use a variety of 759 | techniques as appropriate on each operating system and is more practical 760 | to implement. Direct APIs do not exist on major desktop platforms 761 | (Windows, Mac OS X, Linux) 762 | to bound the cursor to a specific rectangle, and prototypes have not yet 763 | been developed to demonstrate building that behavior by e.g. 764 | 765 | invisible windows 766 | with Xlib 767 | or manual cursor movement on Mac. Unaccelerated Delta 768 | values have been proposed to be accessed by reading raw Human Interface 769 | Device (HID) data. E.g. WM_INPUT messages on Windows, and USB device 770 | APIs on Mac OS X / Linux. The challenge here is interpreting and normalizing 771 | the units to some consistent and specifiable scale. Also, most APIs 772 | considered to date are limited to USB devices.
773 | 774 |It would be reasonable to consider adding these capabilities in the 775 | future, as the currently specified pointer lock API would be easy to 776 | continue to support if the finer grained delta and confinement features 777 | were implemented.
778 | 779 |The bundled API is selected for implementation practicality, because 780 | the desired use cases are supported, and because it will not conflict with 781 | future improvements as discussed here.
782 |Not yet, for the same reasons in the previous question: 788 | "Why bundle all 789 | functionality (hiding cursor, providing mouse deltas) instead of using CSS 790 | to hide the cursor, always providing delta values, and offering an API to 791 | restrict the cursor movement to a portion of the web page?".
792 |When under pointer lock many mouse events remain relevant, e.g. click, 799 | mousedown, etc. These all share the same event data structure MouseEvent. 800 | If movement data were reported via a new data structure then a new event 801 | would be needed for reporting delta movement. The new data structure 802 | would have many parallels to MouseEvent to offer the same conveniences, 803 | e.g. button and modifier key states. When handling click, down, and up 804 | events would the existing mousedown, mouseup be used? If so, they would 805 | provide .clientX/Y and .screenX/Y with no useful data, but would lack the 806 | convenience of containing the current movement data. Or, new events would 807 | also be required for when the mouse is locked.
808 | 809 |Also, movementX/Y are convenient even when the mouse is not locked. 810 | This spec requires movement members to always be valid, even when the 811 | mouse cursor exists. This reduces code required to track the last cursor 812 | state and mouseover/mouseout transitions if applications wish to make 813 | use of delta motion of the mouse.
814 | 815 |The only negative of adding movementX/Y to MouseEvent appears to be the 816 | unused values in clientX/Y and screenX/Y when under pointer lock. This does 817 | not seem to be a significant problem.
818 | 819 |Therefore the minimal change to add movementX/Y to MouseEvent is 820 | selected to reduce API and implementation complexity.
821 |Consider a game with a 3D view controlled by moving the mouse cursor, 828 | while the user may still chat with other users via a text console. It is 829 | reasonable for the application to accept text input to an element that is 830 | different than where mouse events are being dispatched. This is similar 831 | to pre-existing behavior of receiving mousemove events over any element 832 | while typing into a form on a page.
833 |Many have made contributions to the discussions of this 841 | specification:
842 | 843 |This test if movementX/Y can provide the change in position of the pointer, as if movementX/Y = eNow.screenX/Y-ePrevious.screenX/Y
19 |23 |
X | Y | |
client_init: | X | Y |
client_last: | X | Y |
client_delta: | X | Y |
movement_sum: | X | Y |
movement: | X | Y |
This test that movementX/Y do not jump by a large value when exiting and re-entering the window.
19 |23 |
X | Y | |
client_init: | X | Y |
client_last: | X | Y |
client_delta: | X | Y |
movement_sum: | X | Y |
movement: | X | Y |
This test validates that the pointer properly be locked in a DOM element, and exit afterwards.
31 |35 |
This test validates that pointer lock won't be exited when fullscreen is entered or exited, unless fullscreen is exited with the same user gesture as pointer lock.
38 |42 |
This test validates that movementX/Y provided indefinitely even when the mouse cursor would have otherwise hit the edge of a screen.
29 |33 |
screenSize: NaN
46 |movementX_sum: NaN
47 |movementY_sum: NaN
48 |This test validates that pointer lock will be lost the user agent / window loses focus.
38 |42 |
This test validates that pointer lock will be lost the user agent / window loses focus.
38 |42 |
This test validates that pointer lock will be lost when the target is disconnected.
38 |42 |