[83] [DFN[Pointer Lock]] は、[[マウスカーソル]]を非表示とし、
特定の[[要素]]のみが[[マウス]]の移動量や各種操作の[[イベント]]を受信できる状態
([[固定状態]]) とする機能群です。

[84] [[ゲーム]]や[[3次元モデル]]の表示などで通常の[[マウス]]による操作を無効化し、
特別な動作モードを実現したい場合に使うことができます。

* 仕様書

[REFS[
- [20] [CITE@en[Pointer Lock]] ([TIME[2016-10-19 08:10:29 +09:00]]) <https://w3c.github.io/pointerlock/>
-- [21] [CITE@en[Pointer Lock]] ([TIME[2016-10-19 08:10:29 +09:00]]) <https://w3c.github.io/pointerlock/#h-pointerlockchange-and-pointerlockerror-events>
-- [31] [CITE@en[Pointer Lock]] ([TIME[2016-10-19 08:10:29 +09:00]]) <https://w3c.github.io/pointerlock/#widl-Element-requestPointerLock-void>
-- [59] [CITE@en[Pointer Lock]] ([TIME[2016-10-19 08:10:29 +09:00]]) <https://w3c.github.io/pointerlock/#h-extensions-to-the-document-interface>
-- [62] [CITE@en[Pointer Lock]] ([TIME[2016-10-19 08:10:29 +09:00]]) <https://w3c.github.io/pointerlock/#widl-Document-exitPointerLock-void>
-- [71] [CITE@en[Pointer Lock]] ([TIME[2016-10-19 08:10:29 +09:00]]) <https://w3c.github.io/pointerlock/#dfn-default-unlock-gesture>
]REFS]

* API

** メソッドと属性

[30] 
[FIG(short list)[
- [CODE(DOMm)@en[requestPointerLock]]
- [CODE(DOMm)@en[exitPointerLock]]
- [CODE(DOMa)@en[pointerLockElement]]
]FIG]

** イベント

[22] [DFN[[CODE[pointerlockchange]]]] [[イベント]]は、 [[Pointer Lock]]
の状態変更を通知するために使われます [SRC[>>21]]。

[24] [[利用者エージェント]]は、 [[Pointer Lock]] の開始時と終了時に、
[CODE[pointerlockchange]] [[イベント]]を送信しなければ[MUST[なりません]] [SRC[>>21]]。

[87] [[スクリプト]]は、 [CODE(DOMe)@en[pointerlockchange]] [[イベント]]を受信したら、
[CODE(DOMa)@en[pointerLockElement]] [[IDL属性]]を確認することで、
要求した[[要素]]に関する[[固定状態]]への移行に成功したしたかを判断できます。

-*-*-

[23] [DFN[[CODE[pointerlockerror]]]] [[イベント]]は、 [[Pointer Lock]]
の状態変更の[[誤り]]を通知するために使われます [SRC[>>21]]。

-*-*-

[60] [CODE[Document]] [[インターフェイス]]は、
[DFN[[CODE(DOMa)@en[onpointerlockchange]]]],
[DFN[[CODE(DOMa)@en[onpointerlockerror]]]]
両[[IDL属性]]を持ちます。それぞれ、
[CODE[pointerlockchange]],
[CODE[pointerlockerror]]
各[[イベント]]の[[イベントハンドラーIDL属性]]です。 [SRC[>>59]]

* 処理

** 固定状態への移行

[32] [CODE(DOMm)@en[requestPointerLock]] [[メソッド]]は、
次のようにしなければ[MUST[なりません]] [SRC[>>31]]。
[FIG(steps)[
= [35] 
[FIG(list)[
- [36] [[文脈オブジェクト]]の[F[節点文書]]の[F[活性砂箱化フラグ集合]]の
[DFN[[F[sandboxed pointer lock browsing context flag]]]] が設定されている
- [37] 次の条件の''いずれか''を満たさ''ない''
-- [38] [[文脈オブジェクト]]の[F[影を含む根]]が[[文書]]
-- [39] [[文脈オブジェクト]]の[F[影を含む根]]の[F[閲覧文脈]]の[F[活性文書]]が[[文脈オブジェクト]]の[F[影を含む根]]
-- [40] [[文脈オブジェクト]]の[F[影を含む根]]の[F[閲覧文脈]]の[F[最上位閲覧文脈]]の[F[窓][窓 (Web)]]が[F[プラットフォームの焦点を持つ]]
- [43] [[文脈オブジェクト]]の[F[影を含む根]]の[F[Pointer Lock要求不能]]が[[真]]
- [48] [[対象][Pointer Lock対象]]が [CODE[null]] ではなく、
[[文脈オブジェクト]]の[F[影を含む根]]が[[対象][Pointer Lock対象]]の[F[影を含む根]]と異なる
]FIG]
... の''いずれか''を満たす場合、
== [42] [CODE[pointerlockerror]] [[イベント]]を[[文脈オブジェクト]]について通知 (>>25) します。
= [33] それ以外の場合、
== [49] [[対象][Pointer Lock対象]]が [CODE[null]] でないなら、
=== [50] [CODE[pointerlockchange]] [[イベント]]を[[対象][Pointer Lock対象]]について通知 (>>25) します。
== [66] それ以外の場合、
=== [67] [[元のマウスカーソル位置]]を、現在の[[マウスカーソル]]の位置に設定します。
== [34] [[対象][Pointer Lock状態]]を、[[文脈オブジェクト]]に設定します。
== [41] [CODE[pointerlockchange]] [[イベント]]を[[文脈オブジェクト]]について通知 (>>25) します。
]FIG]

[44] [[文書]]は、[DFN[[F[Pointer Lock要求不能]]]]フラグを持ちます。初期値は[[偽]]です。

[46] [[engagement gesture]] が[[発火]]される際は、
[[影を含む根]]の[F[Pointer Lock要求不能]]フラグを[[偽]]に設定しなければ[MUST[なりません]]
[SRC[>>31]]。

[47] [[Pointer Lock要求不能]]フラグにより、[[利用者]]が [[Pointer Lock]]
状態を解除した場合に[[スクリプト]]から再度 [[Pointer Lock]]
を開始することは拒否されます。これによって、むやみやたらに [[Pointer Lock]]
状態に入らせようとするのを拒み、[[利用者]]に他の動作を行う機会を与えます。
([CODE[exitPointerLock]] により解除からの [CODE[requestPointerLock]]
は拒絶されないので、自動的に解除と再設定を繰り返す必要がある場合はこの制限にかかりません。)
[SRC[>>31]]

[51] [[対象][Pointer Lock対象]]が他の[[要素]]に変わる場合、新旧両[[要素]]で
[CODE[pointerlockchange]] を[[発火]]しなければならないことになりますが、
その順序は不明です。また新旧が同じ場合にどうするべきなのかも不明です。

[69] [[利用者エージェント]]は、[DFN[[F[元のマウスカーソル位置]]]]を持ちます。
[[固定状態]]が終了すると、開始前の位置で再度[[マウスカーソル]]が表示されるようになります
[SRC[>>62]]。[[座標]]の他、[[マルチディスプレイ]]の場合はどの[[画面]]に表示されていたかも復元されることが当然に期待されるものと思われます。
[F[元のマウスカーソル位置]]は、他に[[固定状態]]下での[[マウスイベント]]の座標値の決定にも使われます。

** 固定状態

[52] [[利用者エージェント]]は[F[[[[RUBYB[対象]@en[target]]]]][Pointer Lock対象]]を持ちます。
初期状態は [CODE[null]] です。これが非 [CODE[null]] の値なら、
[DFN[[RUBYB[固定状態]@en[locked state]]]]です。

[53] [[固定状態]]では、[[利用者]]の動作に起因して[[利用者エージェント]]が[[発火]]するすべての[[マウスイベント]]の[[対象][イベント対象]]は、
[[対象][Pointer Lock対象]]としなければ[MUST[なりません]] [SRC[>>31]]。

;; [57] [[合成マウスイベント]]には適用されません [SRC[>>31]]。

[54] [[固定状態]]では、[[マウスカーソル]]を隠さなければ[MUST[なりません]] [SRC[>>31]]。

[58] [[固定状態]]では、[[利用者エージェント]]は[[マウスカーソル]]の概念が必要な[[マウスイベント]]
([CODE[mouseover]], [CODE[mouseout]], [CODE[drag]], [CODE[drop]] など)
を[[発火]]しては[MUST[なりません]] [SRC[>>31]]。

[55] [[固定状態]]では、[[マウス]]の[[押下]]や[[移動]]によって[[窓][窓 (Web)]]が[[フォーカス]]を失っては[MUST[なりません]] [SRC[>>31]]。

;; [56] [[プラットフォーム]]がそのような機能を提供していることが前提ですが、
一般的な[[ウィンドウマネージャー]]はそのような [[API]] が提供されているようです。

** 固定状態の終了

[74] 次の場合に、[[固定状態]]を終了しなければ[MUST[なりません]]。
[FIG(list)[
- [CODE(DOMm)@en[exitPointerLock]]
- [[default unlock gesture]]
- [[対象][Pointer Lock対象]]が[[切断][節点の切断]]された時 [SRC[>>71]]
- [[対象][Pointer Lock対象]]の[F[節点文書]]の[F[影を含む根]]の[F[閲覧文脈]]が[F[プラットフォームの焦点を持つ]]状態でなくなった時 [SRC[>>71]]
]FIG]

;; [75] 終了方法の規定は、なぜか [CODE(DOMm)@en[exitPointerLock]] にしかありませんが、
他の方法での終了時も同様と思われます。

[78] [[navigate]] などで[[活性文書]]ではなくなったときも終了する必要がありそうですが、
なぜか規定がありません。

[79] [[ダイアログ]]表示時の扱いは不明です。
最低でも、[[モーダルダイアログ]]が操作できなくなってしまわないような配慮が必要です。

[80] [[全画面表示]]に入ったり、解除されたりしたこと自体を理由に終了してはなりません。
しかし [[default unlock gesture]] などで同時に終了することはあり得ます。 [SRC[>>71]]

-*-*-

[77] [[固定状態]]の終了は、次のようにしなければなりません [SRC[>>62]]。
[FIG(steps)[
= [65] [CODE[pointerlockchange]] [[イベント]]を[[対象][Pointer Lock対象]]について通知 (>>25) します。
= [45] [[default unlock user gesture]] からの呼び出しの場合、
== [81] [[対象][PointerLock]]の[F[節点文書]]の[F[影を含む根]]の[F[Pointer Lock要求不能]]フラグを[[真]]に設定します [SRC[>>31]]。
= [64] [[対象][Pointer Lock対象]]を、 [CODE[null]] に設定します。
= [68] [[マウスカーソル]]の位置を、[[元のマウスカーソル位置]]に設定します。
]FIG]

-*-*-

[61] [CODE(DOMm)@en[exitPointerLock]] は、次のようにしなければなりません [SRC[>>62]]。
[FIG(steps)[
= [63] [[対象][Pointer Lock対象]]が [CODE[null]] ではなく、
[[対象][Pointer Lock対象]]の[F[影を含む根]]が[[文脈オブジェクト]]なら、
== [76] [[固定状態]]を終了させます。
]FIG]

-*-*-

[70] [[利用者エージェント]]は、[[利用者]]に [DFN[default unlock gesture]]
を常に提供しなければ[MUST[なりません]]。これは、[[固定状態]]を終了させるものです。
[SRC[>>71]]

[72] [[鍵盤入力]]が利用できる場合、 [KBD[ESC]] を [[default unlock gesture]]
とするべきです [SRC[>>71]]。

[73] [[default unlock gesture]] は[[全画面]]の終了の方法を同じとするべきです [SRC[>>71]]。

** イベントの発火


[25] 両[[イベント]]の通知は、[VAR[イベント型]]、[VAR[対象]]について、
次のようにしなければ[MUST[なりません]] [SRC[>>21]]。
[FIG(steps)[
= [26] [[タスクをキューに追加]]します。
[FIG(list members)[ [27] [[タスク]]

: [F[処理]] :
[FIG(steps)[

= [28] [[イベントを発火]]します。
[FIG(list members middle)[
: [VAR[名前]] : [VAR[イベント型]]
: [VAR[対象]] : [VAR[対象]]の[F[節点文書]]
]FIG]

]FIG]
: [F[タスク源]] : ?

]FIG]
]FIG]

[29] 画面の[[拡大鏡]]ソフトウェアは、普通[[マウス]]の移動によって画面上の拡大範囲を変更しますが、
[[Pointer Lock]] が有効な間は[[鍵盤]]操作で変更するようにしなければならず、
[[Webブラウザー]]とそのような[[ソフトウェア]]とで協調が必要です [SRC[>>21]]。

* 砂箱化との関係

[85] [CODE(DOMa)@en[sandbox]] により、[[Pointer Lock]] の利用を拒否できます。

[86] [DFN[[CODE(HTML)@en[allow-pointer-lock]]]] により、
[[砂箱化]]時に例外的に [[Pointer Lock]] を許可することを記述できます。

* 歴史

** Mouse Lock

[REFS[
- [4] [CITE[Mouse Lock Specification Draft - Google Docs]]
( ([TIME[2011-09-19 14:36:15 +09:00]] 版))
<https://docs.google.com/document/d/1uV4uDVIe9-8XdVndW8nNGWBfqn9ieeop-5TRfScOG_o/edit?hl=en_US&authkey=CM-dw7QG&pli=1>
- [5] [CITE@en[Re: Mouse Lock]]
( ([[Vincent Scheib]] 著, [TIME[2011-09-13 06:11:49 +09:00]] 版))
<http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/1387.html>
- [6] [CITE@en[Mouse Lock]]
( ([TIME[2011-11-14 21:43:11 +09:00]] 版))
<http://dvcs.w3.org/hg/webevents/raw-file/default/mouse-lock.html>
]REFS]

** Pointer Lock

[REFS[
- [1] [CITE@en[Pointer Lock]]
( ([TIME[2012-05-25 22:10:08 +09:00]] 版))
<http://www.w3.org/TR/2012/WD-pointerlock-20120529/>
- [2] [CITE@en[Pointer Lock]]
( ([TIME[2013-10-30 23:44:03 +09:00]] 版))
<http://www.w3.org/TR/2013/WD-pointerlock-20131031/>
- [3] [CITE@en[Pointer Lock]]
( ([TIME[2013-12-12 23:05:22 +09:00]] 版))
<http://www.w3.org/TR/2013/CR-pointerlock-20131217/>
]REFS]


[7] [CITE@en[Webapps/PointerLockFeatures - W3C Wiki]]
([TIME[2015-03-23 19:55:50 +09:00]] 版)
<https://www.w3.org/wiki/Webapps/PointerLockFeatures>

[8] [CITE@en[Moving XHR, DOM Parsing and Pointer Lock to Github]]
([[Arthur Barstow]] 著, [TIME[2015-08-04 23:54:29 +09:00]] 版)
<https://lists.w3.org/Archives/Public/www-archive/2015Aug/0001.html>

[9] [CITE@en[Pointer Lock]]
([TIME[2015-08-05 05:05:36 +09:00]] 版)
<https://w3c.github.io/pointerlock/>

[10] [CITE@en[Create FeatureRequests.md. · w3c/pointerlock@7aebdfc]]
([TIME[2015-10-14 11:01:43 +09:00]] 版)
<https://github.com/w3c/pointerlock/commit/7aebdfcb7b1aa6bef190acee1a0a170e3d118edd>

[11] [CITE@en[''''''[''''''pointerlock'''''']'''''' Oct 2015 Pointer Lock Status]]
([[Vincent Scheib]] 著, [TIME[2015-10-24 05:57:06 +09:00]] 版)
<https://lists.w3.org/Archives/Public/public-webapps/2015OctDec/0116.html>

[12] [CITE@en[CFC: Republish Pointer Lock as CR]]
( ([[Léonie Watson]]著, [TIME[2016-06-14 01:12:42 +09:00]]))
<https://lists.w3.org/Archives/Public/public-webapps/2016AprJun/0127.html>

[13] [CITE@en[Pointer Lock]]
([TIME[2016-07-04 17:29:48 +09:00]])
<https://www.w3.org/TR/2016/CR-pointerlock-20160705/>

[14] [CITE@en[CfC: Pointer Lock to Proposed Recommendation; deadline August 20]]
([[Xiaoqian Wu]]著, [TIME[2016-08-14 08:01:41 +09:00]])
<https://lists.w3.org/Archives/Public/public-webapps/2016JulSep/0054.html>

[15] [CITE@en[Pointer Lock]]
([TIME[2016-08-29 18:27:23 +09:00]])
<https://www.w3.org/TR/2016/PR-pointerlock-20160830/>

[16] [CITE@en[Fwd: Pointer Lock is a W3C Proposed Recommendation (Call for Review)]]
([[Léonie Watson]]著, [TIME[2016-08-30 23:21:03 +09:00]])
<https://lists.w3.org/Archives/Public/public-webapps/2016JulSep/0083.html>

[17] [CITE@en[w3c/pointerlock: Pointer Lock]]
([TIME[2016-10-23 12:03:57 +09:00]])
<https://github.com/w3c/pointerlock>

[18] [CITE@en[Fwd: Pointer Lock is now a W3C Recommendation]]
([[chaals@yandex-team.ru]]著, [TIME[2016-10-27 17:37:36 +09:00]])
<https://lists.w3.org/Archives/Public/public-webapps/2016OctDec/0015.html>

[19] [CITE@en[Pointer Lock]]
([TIME[2016-10-26 21:34:57 +09:00]])
<https://www.w3.org/TR/2016/REC-pointerlock-20161027/>

[82] [[Pointer Lock]] [[仕様書]]は、未だに10年以上前の、[[アルゴリズム]]的でない方法で規定されていて、
その意図する動作は非常に曖昧です。同じく曖昧な [[UI Events]] を暗黙裡に[[猿パッチ]]する形になっていて、
とても曖昧です。

[88] [CITE@en[Update Summary of changes: Now relative to W3C Recommendation 27 Octo…]]
([[scheib]]著, [TIME[2016-11-01 03:40:26 +09:00]])
<https://github.com/w3c/pointerlock/commit/01fefaa0d264189eae831fc099a45610208d58df>

[89] [CITE@en[CFC notification: Publish FPWD of Pointer Lock 2.0 (closes 14th Nov  2016)]]
([[Léonie Watson]]著, [TIME[2016-11-08 01:52:10 +09:00]])
<https://lists.w3.org/Archives/Public/public-webapps/2016OctDec/0024.html>

[90] [CITE@en[Pointer Lock 2.0]]
([TIME[2016-11-19 03:31:20 +09:00]])
<https://www.w3.org/TR/2016/WD-pointerlock-2-20161122/>

[91] [CITE@en[FPWD of Pointer Lock 2.0]]
([[Léonie Watson]]著, [TIME[2016-11-22 17:55:15 +09:00]])
<https://lists.w3.org/Archives/Public/public-webapps/2016OctDec/0030.html>

[92] [CITE@en[Update ED to pointerlock-2]]
([[scheib]]著, [TIME[2017-04-27 12:27:57 +09:00]])
<https://github.com/w3c/pointerlock/commit/5caaf81899b5e6157dee4e7f63b4870d6a37b552>

[93] [CITE@en[Record published v2 FPWD.]]
([[scheib]]著, [TIME[2017-04-27 12:48:06 +09:00]])
<https://github.com/w3c/pointerlock/commit/a2af723e21146205f17cf9876f56f87ef32cb1ad>

[94] [CITE@en[Record published v1 REC.]]
([[scheib]]著, [TIME[2017-04-27 12:46:30 +09:00]])
<https://github.com/w3c/pointerlock/commit/7ca1b4a26ebf593a2b85371deaaf214b051ce57b>

[95] [CITE@en[Ask for web-platform-tests in CONTRIBUTING.md (#20)]]
([[foolip]]著, [TIME[2017-05-17 01:20:01 +09:00]])
<https://github.com/w3c/pointerlock/commit/0f1eaa16bdf681505e9f52ccc5f2e1bbfa271873>

[96] [CITE@en[455882 - Treat file:// URLs as having unique origin - chromium - Monorail]]
( ([TIME[2017-08-11 02:59:54 +09:00]]))
<https://bugs.chromium.org/p/chromium/issues/detail?id=455882>

[97] [CITE@en[Change of editor for Pointer Lock]]
([[Léonie Watson]]著, [TIME[2018-01-19 02:04:42 +09:00]])
<https://lists.w3.org/Archives/Public/public-webapps/2018JanMar/0000.html>

[98] [CITE@en[Update the editor]]
([[NavidZ]]著, [TIME[2018-01-20 03:45:01 +09:00]])
<https://github.com/w3c/pointerlock/commit/b0b9773999c0845b23c7fa1f532b189f9f06efa1>

[99] [CITE@en[Update the editor by NavidZ · Pull Request #30 · w3c/pointerlock]]
([TIME[2018-01-21 15:04:31 +09:00]])
<https://github.com/w3c/pointerlock/pull/30>

[100] [CITE@en[Update the editor]]
([[NavidZ]]著, [TIME[2018-01-20 03:45:01 +09:00]])
<https://github.com/w3c/pointerlock/commit/b0b9773999c0845b23c7fa1f532b189f9f06efa1>