Copyright © 2024 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
이 섹션은 이 문서가 발행된 시점의 상태를 설명합니다. 현재 W3C 출판물 목록과 이 기술 보고서의 최신 개정판은 W3C 기술 보고서 인덱스 https://www.w3.org/TR/에서 확인할 수 있습니다.
이 문서의 변경 이력은 https://github.com/w3c/pointerlock/commits/gh-pages/index.html에서 확인할 수 있습니다.
2016년 10월 27일 W3C 권고안 이후의 변경 요약:
이 문서는 웹 애플리케이션 워킹 그룹에서 권고안 경로를 사용하여 워킹 드래프트로 발행되었습니다.
워킹 드래프트로서의 발행은 W3C 및 그 회원사의 지지를 의미하지 않습니다.
이 문서는 초안이며, 언제든지 다른 문서로 업데이트, 대체, 폐기될 수 있습니다. 진행 중인 작업 외에는 이 문서를 인용하는 것은 부적절합니다.
이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 작성되었습니다. W3C는 관련 특허 공개의 공개 목록을 관리합니다. 해당 페이지에는 특허 공개 방법에 대한 안내도 포함되어 있습니다. 특정 특허가 필수 권리 주장을 포함한다고 판단되는 경우, W3C 특허 정책 6절에 따라 정보를 공개해야 합니다.
이 문서는 2023년 11월 3일 W3C 프로세스 문서에 따라 관리됩니다.
이 절은 규범적이지 않습니다.
포인터 잠금 API는 애플리케이션이 마우스 커서의 위치만 읽는 것에 제한되지 않고, 마우스 움직임 자체를 입력 방식으로 직접 해석할 수 있게 해줍니다. 대표적인 예는 3차원 그래픽 애플리케이션(게임 등)에서의 1인칭 이동 컨트롤입니다: 마우스의 움직임이 플레이어의 카메라 회전/방향을 제어하며, 마우스 커서는 표시되지 않고, 움직임이 기존의 경계(예: 사용자 에이전트 창, 전체 화면 등)에 제한되지 않아 마우스 움직임을 어느 방향으로든 무한히 추적할 수 있습니다.
포인터 잠금은 Mouse Capture [MDN-SETCAPTURE]와 관련이 있습니다(마우스 캡처는 명세화되어 있지 않음: 버그 14600). 캡처는 마우스가 드래그되는 동안 타겟 요소에 이벤트 전달을 지속하지만, 마우스 버튼이 놓이면 중단됩니다. 포인터 잠금은 지속적이며, 화면 경계에 제한되지 않고, 마우스 버튼 상태와 관계없이 이벤트를 보내며, 커서를 숨기고, API 호출이나 사용자의 특정 기본 잠금 해제 제스처가 있을 때까지 해제되지 않습니다.
포인터 잠금은 단일 리소스를 캡처하고 이를 단일 요소에 연결하는 기능을 다룹니다. 이는 Fullscreen API [FULLSCREEN]와 유사하며, 해당 API는 단일 요소를 전체 화면으로 승격합니다. 포인터 잠금 API는 리소스 캡처, 상태 변화, 해제 API를 Fullscreen API와 최대한 유사하게 설계하였습니다.
포인터 잠금 상호작용 모드는 이전에는 마우스 잠금으로 불렸습니다. 마우스 이외에도 다양한 컨트롤러 타입이 화면상의 포인팅 커서를 조작할 수 있으므로, 모두 영향을 받는다는 의미를 담아 명칭이 변경되었습니다.
포인터 잠금 상태란, 하나의 DOM 요소(포인터-잠금 대상이라 부름)가 모든 마우스 이벤트를 받고 커서가 숨겨지는 상태를 의미합니다.
포인터 잠금 상태에 들어가면 사용자 에이전트는 포인터-잠금 대상, 포인터-잠금 옵션(PointerLockOptions
), 그리고 커서 위치(포인터 잠금
상태 진입 시 시스템 마우스 커서의 위치, screenX
, screenY
로 보고됨)을 갖게 됩니다. 포인터-잠금 대상은 모든 사용자 생성 MouseEvent
이벤트(즉,
mousemove
, mousedown
, mouseup
,
click
,
dblclick
, auxclick
, wheel
[ui-events])를 모두 받습니다.
포인터 잠금 상태에서는 다른 요소가 이러한 이벤트를 받지 않습니다. 마우스 커서 개념이 필요한 이벤트(예: mouseenter
,
mouseleave
, mouseover
, mouseout
,
drag
,
drop
)는 디스패치되지 않습니다.
이벤트 목록을 예시만 들지 말고 규범적으로 명시할 수 있나요?
현재 텍스트도 괜찮다고 생각하지만, 여기서의 불명확함은 전체적으로 마우스 이벤트 명세가 불명확한 점의 일부일 뿐입니다. 일부 진전은 w3c/uievents#200에서 이루어지고 있으며, 해당 논의가 결론나면 이 문단을 UI 이벤트 명세의 처리 모델 변경으로 이관할 수 있습니다.
하지만 그 전까지는 호환성을 위해 이벤트 목록을 명확하게 규정하는 것이 도움이 될 것입니다.
예를 들어, pointer 이벤트가 이 변경의 영향을 받는지 명확하지 않습니다.
포인터 잠금 상태에서 포인터-잠금
옵션의 unadjustedMovement
멤버가
true
이면,
이벤트 좌표가 플랫폼의 마우스 가속 등 기본 동작에 영향을 받지 않습니다. 즉, 사용자 에이전트는 플랫폼에서 제공하는 API를 사용하여 원시 이벤트를 보장합니다. PointerLockOptions
의 unadjustedMovement
가
false
이면,
사용자 에이전트는 플랫폼의 기본 마우스 가속 동작을 따릅니다.
포인터 잠금 상태에서는 시스템 마우스 커서가 숨겨지고, 마우스 이동이나 버튼 클릭과 상관없이 윈도우 포커스가 잃지 않도록 합니다. 이는 OS API를 직접 또는 간접적으로 활용하여 달성됩니다.
애플리케이션 스크립트로 생성된 합성 마우스 이벤트는 잠금 상태와 관계없이 동일하게 동작합니다.
WebIDLdictionary PointerLockOptions
{
boolean unadjustedMovement
= false;
};
PointerLockOptions
딕셔너리
잠금 모드에서 포인터 동작을 커스터마이즈할 수 있는 옵션 딕셔너리입니다.
unadjustedMovement
멤버
이 값이 true
로 설정되면, 포인터 움직임은 플랫폼의 마우스 가속 등 수정 동작의 영향을 받지 않습니다.
포인터 잠금 상태 변화 또는 상태 변경 오류를 알리기 위해 두 가지 이벤트가 사용됩니다. 각각 pointerlockchange와 pointerlockerror입니다.
자세한 내용은
3.
Element
인터페이스의 확장 절의 알고리즘을 참조하십시오.
화면 확대 소프트웨어는 화면의 콘텐츠를 확대합니다. 확대 포커스를 이동시키기 위해 마우스를 사용하지만, 포인터 잠금이 시작되면 키보드를 통해 확대 포커스 이동을 해야 합니다. pointerlockchange
이벤트가 발생하면, 웹 브라우저는 해당 이벤트가 화면 확대 등 접근성 기술에 전달되도록 해야 합니다.
element에 대해 포인터 잠금 해제 과정은 다음과 같습니다:
pointerlockchange
라는 이름으로 해당 element의 노드 문서에 전달합니다.
Element
인터페이스는 포인터를 잠그는 기능을 요청할 수 있도록
확장되었습니다.
WebIDLpartial interface Element {
Promise<undefined> requestPointerLock
(optional PointerLockOptions
options = {});
};
const lock_element = document.getElementById("lock_element");
const lock_button = document.getElementById("lock");
lock_button.addEventListener("click", async (event) => {
try {
await lock_element.requestPointerLock({ unadjustedMovement: true });
console.log("성공적으로 잠금됨!");
} catch (e) {
console.log("잠금 실패, 에러: ", e);
}
});
PointerLockOptions
options) 메서드
lock
requests queue라는 이름의 병렬 큐를 사용하여
모든 요청을 큐에 저장합니다. requestPointerLock()
호출 시 다음 단계를 수행합니다:
window
가 포커스 상태일 때, this의 shadow-including root
가 활성
문서의 탐색
컨텍스트(또는 조상 탐색
컨텍스트)가 포커스되어 있지 않으면:
WrongDocumentError
"
DOMException
을
전달합니다.
Document
가
exitPointerLock
()
호출로 성공적으로 포인터 잠금을 해제한 적이 없다면:
NotAllowedError
"
DOMException
을
전달합니다.
SecurityError
"
DOMException
을
전달합니다.
unadjustedMovement
"]
값이 true이고, 플랫폼에서 unadjustedMovement
를
지원하지 않으면:
NotSupportedError
"
DOMException
을
전달합니다.
InvalidStateError
"
DOMException
을
전달합니다.
NotSupportedError
"
DOMException
을
전달합니다.
WebIDLpartial interface Document {
attribute EventHandler onpointerlockchange
;
attribute EventHandler onpointerlockerror
;
undefined exitPointerLock
();
};
onpointerlockchange
속성
이벤트
핸들러 IDL 속성으로,
pointerlockchange
이벤트를 처리합니다.
onpointerlockerror
속성
이벤트
핸들러 IDL 속성으로,
pointerlockerror
이벤트를 처리합니다.
exitPointerLock()
메서드
WebIDLpartial interface mixin DocumentOrShadowRoot {
readonly attribute Element? pointerLockElement
;
};
pointerLockElement
포인터가 잠긴 동안, 해당 요소를 재타겟팅한 결과를 반환합니다. 이 재타겟팅된 요소가 마우스 이벤트의 대상이 되며, this 요소와 같은 트리에 속해 있다면 그 결과 요소를, 아니라면 null을 반환합니다.
lock이 대기 중이거나 포인터가 잠금 해제 상태라면 null을 반환합니다.
<body>
<div id="host1">
<shadow-root id="root1">
<canvas id="canvas1"></canvas>
</shadow-root>
</div>
<div id="host2">
<shadow-root id="root2">
<canvas id="canvas2"></canvas>
</shadow-root>
</div>
</body>
예시에서는 가상의 shadow-root
요소를 사용하여 shadow root 인스턴스를 표현합니다.
#canvas1
이 대상일 때 document.pointerLockElement
는 #host1
를,
root1.pointerLockElement
는 #canvas1
을 반환합니다. 재타겟팅 결과 #canvas1
을
#root2
에 대해 재타겟팅하면 #host1
가 되지만, #host1
이 #root2
와
같은 트리에 속하지 않으므로 root2.pointerLockElement
는 null을 반환합니다.
WebIDLpartial interface MouseEvent {
readonly attribute double movementX
;
readonly attribute double movementY
;
};
movementX
속성
movementY
속성
movementX
와 movementY
속성은 포인터 위치가 변화한 값을 제공합니다. 두
mousemove
이벤트 eNow
와 ePrevious
사이에 screenX
,
screenY
값을 저장하고, movementX = eNow.screenX - ePrevious.screenX
과 같이 차이를 계산하는
것과 같습니다.
movementX
와 movementY
는 mousemove
이벤트를
제외한 모든 마우스 이벤트에서는 0이어야 합니다. 모든 움직임 데이터는 mousemove
이벤트로 전달되어야 하며, 두 마우스 이벤트
earlierEvent
와 currentEvent
사이의
currentEvent.screenX - earlierEvent.screenX
값은 earlierEvent
이후 이벤트들의 movementX
합계와 같아야 합니다(단, 포인터가 사용자 에이전트
화면 경계에 의해 클립되어 screenX
를 갱신하지 못하는 경우는 예외).
movementX
와 movementY
는 포인터 잠금 상태와 관계없이 항상 갱신되어야
합니다.
잠금 해제 상태에서는 시스템 커서가 사용자 에이전트 창을 나갔다가 다시 진입할 수 있습니다. 이 경우 운영체제의 마우스 이동 이벤트의 대상이 사용자 에이전트가 아니면, 가장 최근의
포인터 위치를 사용자 에이전트가 알 수 없어 movementX
/ movementY
값을 계산할 수 없으므로 0으로 설정해야 합니다.
포인터 잠금이 활성화되면 clientX
, clientY
, screenX
,
screenY
는 포인터가 전혀 움직이지 않은 것처럼 일정한 값을 유지해야 합니다. 하지만 movementX
와
movementY
는 잠금 해제 상태와 동일하게 포인터 이동 변화를 계속
제공해야 하며, 마우스를 한 방향으로 계속 이동하면 movementX
와 movementY
값에 제한이 없습니다. 마우스 커서 개념이 제거되어
창을 벗어나거나 화면 경계에 의해 클램프되지 않습니다.
movementX
와 movementY
의 초기화되지 않은 값은
0
이어야 합니다.
마우스 입력이 중단되는 상황(예: 마우스 커서가 창을 나갔다가 다른 위치로 다시 진입)에서는 큰 movement 값이 나타나면 안 됩니다. 사용자 에이전트가 운영체제에서 마우스
입력 데이터를 받지 못하는 간격이 생기면, 다음 mousemove
이벤트는 movementX
와 movementY
를 0
으로 설정해야 합니다.
이러한 간격은 사용자 에이전트가 창 시스템 API에서 마우스 이탈 이벤트를 받을 때 등 발생할 수 있습니다. 예외적으로 마우스 캡처가 활성화되면 커서가 창 밖으로 이동해도 사용자
에이전트가 계속 마우스 이벤트를 받을 수 있습니다.
WebIDLpartial dictionary MouseEventInit {
double movementX
= 0;
double movementY
= 0;
};
movementX
멤버
movementY
멤버
movementX
와 movementY
멤버는 각각 MouseEvent
의 해당 멤버를 초기화하는 데 사용됩니다.
기본 잠금 해제 제스처는 항상 제공되어야 하며, 포인터 잠금 해제를 사용자 에이전트의 포인터-잠금 대상과 함께 수행해야 합니다.
포인터-잠금 대상이 연결 해제되거나, 사용자 에이전트, 윈도우, 탭이 포커스를 잃으면 포인터 잠금은 해제되어야 합니다. 활성 문서(active document)의 요소들 사이, 또는 탐색 컨텍스트 사이로 포커스를 이동하는 것은 포인터 잠금 해제를 일으키지 않습니다. 예를 들어, 키보드로 프레임이나 iframe 내의 콘텐츠 사이로 포커스를 이동해도 해제되지 않습니다.
전체 화면 [FULLSCREEN]이 진입하거나 해제될 때, 포인터가 사용자 에이전트의 그래픽 UI와 상호작용해야 하거나, 기본 잠금 해제 제스처로 전체 화면과 포인터 잠금을 동시에 해제하거나, 윈도우나 탭 포커스를 잃은 경우를 제외하고 포인터 잠금이 해제되어서는 안 됩니다.
이 절은 규범적이지 않습니다.
1인칭/3인칭 게임의 플레이어는 뷰포트 방향을 제어해야 합니다. 널리 사용되는 방법은 마우스 움직임으로 시야 각도를 조절하는 것입니다. 이런 종류의 애플리케이션은 Pointer Lock API를 사용하여 뷰포트의 요(yaw)와 피치(pitch)를 마우스 버튼을 누르지 않은 상태에서도 완전히 자유롭게 제어할 수 있습니다. 버튼은 다른 동작에 사용할 수 있고, 마우스 이동만으로 지속적으로 내비게이션이 가능합니다.
3차원 모델링 애플리케이션 사용자들은 모델을 회전시켜야 합니다. 애플리케이션은 Pointer Lock API를 사용하여 드래그 동작 중 움직임 제한 없이 모델을 자유롭게 회전시킬 수 있습니다. 포인터 잠금이 없으면 마우스 커서가 화면의 가장자리에서 움직임 데이터 제공이 멈춥니다.
마찬가지로, 큰 2차원 이미지를 단일 드래그 동작으로 커서/화면의 한계를 넘어서 절대 이동(panning)할 수도 있습니다.
빠른 반사신경이 요구되는 게임에서 플레이어는 패들을 조작해 공을 상대에게 튕겨내야 하는데, 패들은 다른 마우스 버튼에 따라 다양한 동작도 할 수 있습니다. 애플리케이션은 Pointer Lock API를 사용하여, 마우스 커서가 게임 영역을 벗어나 시스템의 다른 애플리케이션을 클릭해 게임 흐름이 중단되는 걱정 없이 플레이어가 빠르게 반응할 수 있게 해줍니다.
애플리케이션에서 수치적인 값을 조절할 때, 사용자는 버튼 핸들을 드래그하여 값을 증감시키는 방식을 선호할 수 있습니다. 예를 들어, 숫자 입력 박스와 위/아래 화살표가 있는 스피너에서 화살표를 클릭하거나 드래그해 값을 바꾸는 경우입니다. 애플리케이션은 Pointer Lock API를 사용하여 논리적 화면 한계를 넘어서 값을 조절할 수 있게 합니다. 비디오 또는 오디오 스트림을 빠르게 감거나 되감는 "조그" 컨트롤에도 적용할 수 있습니다.
일부 게임에서는 고전적인 커서를 사용하지만, 커서의 이동을 제한하거나 제어하고자 할 수 있습니다. 예를 들어 게임 경계 안에서만 움직이거나, 게임에서 직접 커서를 이동시키는 경우입니다. 포인터를 잠그면 애플리케이션이 자체 커서를 만들 수 있고, HTML 및 DOM은 UI로 사용할 수 있습니다. 합성 마우스 이벤트를 허용하면 애플리케이션이 정의한 커서로 DOM과 상호작용할 수 있습니다. 예를 들어 아래 코드처럼 포인터가 잠긴 상태에서 커스텀 커서가 클릭 이벤트를 보낼 수 있습니다:
document.addEventListener("click", function (e) {
if (e._isSynthetic)
return;
// send a synthetic click
var ee = document.createEvent("MouseEvents");
ee._isSynthetic = true;
x = myCursor.x;
y = myCursor.y;
ee.initMouseEvent("click", true, true, null, 1,
x + e.screenX - e.clientX,
y + e.screenY - e.clientY,
x,
y);
var target = document.elementFromPoint(x, y);
if (target)
target.dispatchEvent(ee);
});
합성 클릭은 사용자 에이전트에 의해 일반 클릭과 동일한 기본 동작을 허용하지 않을 수 있습니다. 하지만 애플리케이션 핸들러에서 추가 동작을 구현하거나 기존 HTML & DOM 메커니즘으로 UI를 제공할 수 있습니다.
실시간 전략(RTS) 게임에서 자주 쓰이는 방식입니다. 플레이어가 포인터를 뷰포트의 경계까지 이동하면, 마우스 움직임으로 경계를 "밀면" 뷰포트가 게임 영역을 마우스 이동량만큼 패닝합니다. 뷰포트 경계 내에서 마우스 커서를 이동할 때는 시스템과 동일하게 동작합니다. 애플리케이션은 pointer lock과 "HTML DOM UI와의 합성 커서 상호작용" 사례를 함께 활용해 커서 동작을 완전히 제어할 수 있습니다.
포인터 잠금을 사용하는 게임은 플레이어가 게임 로비에서 준비하는 동안에는 일반 UI와 시스템 커서를 원할 수 있습니다. 모든 플레이어가 준비되면 보통 짧은 타이머 후 게임이 시작됩니다. 이상적으로는 게임이 사용자 활성화 없이 pointer lock 모드로 전환될 수 있어야 합니다. 플레이어는 게임 로비에서 게임 내비게이션으로 끊김 없이 이동할 수 있어야 합니다.
게임 포털 및 Facebook, Google Plus 같은 사이트는 사용자가 즐길 수 있는 게임을 호스팅합니다. 이 게임들은 포털 사이트와 다른 오리진에서 제공될 수 있습니다. 임베드된 게임은 전체 화면이 아니더라도 포인터를 잠글 수 있어야 합니다.
이 절은 규범적이지 않습니다.
보안 우려:
대응 방안:
권장 사항:
포인터 잠금은 특정 애플리케이션 유형에서 필수적인 사용자 상호작용 모드지만, 악의적으로 사용될 경우 사용성 문제가 있습니다. 공격자는 사용자가 시스템에서 마우스 커서를 제어할 수 있는 능력을 제거할 수 있습니다. 사용자 에이전트는 항상 포인터 잠금 해제가 가능한 메커니즘을 제공하고, 방법을 사용자에게 안내하며, 포인터 잠금을 활성화할 수 있는 조건을 제한함으로써 이를 방지합니다.
사용자 에이전트는 각 기기별 또는 사용자 옵션에 따라 자체적인 정책을 결정할 수 있습니다.
이 절은 규범적이지 않습니다.
Mouse Capture [MDN-SETCAPTURE]는 마우스 드래그 동작 동안 마우스 이벤트 타겟을 잠그는 낮은 보안 위험의 기능입니다. 포인터 잠금은 커서 개념을 제거하고 모든 이벤트를 특정 타겟으로 전달합니다. 둘은 관련 있지만 다릅니다.
브라우저가 둘 다 구현한다면, "마우스 업 시 자동 잠금 해제"의 보안 단순성과 마우스 입력 전체 제어 및 시스템 커서 제거 기능을 조합할 수 있을 것입니다. 이 보안 특성은 드래그 이벤트 중 잠깐의 포인터 잠금만 필요한 애플리케이션에서 더 자유롭게 기능을 사용할 수 있게 해줍니다.
이 기능은 윈도우 모드에서 일부 마이너한 사용 사례에는 도움이 되지만, 주요 사용 사례를 해결하는 구현이 아직 없으므로 첫 버전 명세에서 제외되었습니다. 또한 브라우저가 둘 다 구현해야 하는데, 아직 그런 브라우저는 없습니다. 이 기능이 .lock에 있어야 할지 .setCapture에 있어야 할지 명확하지 않습니다. 둘 다 구현된다면, 어느 API든 하이브리드 기능을 쉽게 확장할 수 있습니다.
포인터가 잠금되지 않은 상태에서도 마우스 이동 델타 값은 유용합니다. 잠금 상태에 따라 .client 또는 .screen의 의미가 바뀌면, 잠금 상태를 신중히 관리하지 않는 코드에서 오류가 발생하기 쉽습니다.
포인터 잠금 중에는 'wheel' 이벤트도 포인터-잠금 대상 요소에 'mousemove' 이벤트처럼 전달되어야 합니다. .deltaX/Y/Z는 DOM 3 'wheel' 이벤트에서 이미 정의되어 있어서 이름 충돌이 발생합니다.
보다 세분화된 접근을 제공하는 동기도 충분합니다. 예를 들어 "뷰포트 경계에 마우스 커서를 이동하여 뷰포트 패닝" 사례는 커서 숨김이 필요 없고, 커서를 경계 내에만 제한하며 항상 델타 값을 사용할 수 있으면 됩니다. 또한, 이 명세는 시스템 마우스 커서의 움직임에서 델타 값을 정의하는데, 이 값은 운영체제의 필터링 및 가속이 적용된 데이터입니다. 애플리케이션은 커서에 맞춘 조정 전의 좀 더 원시적인 움직임 데이터를 원할 수 있습니다. 원시 데이터는 픽셀 단위보다 더 정확한 움직임이나 더 높은 빈도의 업데이트도 가능하게 합니다. 원시 델타 제공은 사용자에게 특수 권한이나 모드가 필요하지 않으며, 커서 구속이 필요 없는 애플리케이션에서는 보안 장벽과 프롬프트를 줄일 수 있습니다.
이처럼 세분화된 접근을 미루는 두 가지 이유가 있습니다. 첫째는 마우스 움직임 데이터가 어떤 단위로 제공되는지를 명확히 해야 하는데, 명세는 .movementX/Y를 잠금 상태가 아닐 때 .screenX/Y 변화로 얻을 수 있는 값과 동일하게 정의합니다. 여러 사용자 에이전트와 운영체제에서 쉽게 일관성 있는 경험을 제공할 수 있습니다. 사용자는 이미 하드웨어 입력과 운영체제 옵션을 조정해 커서를 편하게 사용하도록 설정했으므로, 동일 단위의 .movementX/Y를 명세하면 모든 사용자에게 바로 쓸 수 있습니다.
둘째, 움직임 데이터 제공이나 마우스 커서 구속을 세분화된 방식으로 구현하는 것은 더 어렵습니다. 번들 기능을 제공하면 각 운영체제에 맞는 다양한 기법을 구현할 자유가 생기고 실제 구현이 더 쉽습니다. 주요 데스크탑 플랫폼(Windows, Mac OS X, Linux)에는 커서를 특정 사각형에 구속하는 직접 API가 없고, 이를 구현한 프로토타입도 없습니다. 예를 들어 보이지 않는 창과 Xlib, Mac에서 수동 커서 이동 등으로 시도해야 합니다. 가속되지 않은 델타 값은 HID(raw Human Interface Device) 데이터 읽기로 접근하는 방안이 있는데, 예를 들면 Windows의 WM_INPUT 메시지, Mac OS X/Linux의 USB 장치 API 등입니다. 여기서 단위를 해석하고 일관성 있게 정규화하는 것이 과제입니다. 그리고 대부분의 API는 USB 장치에만 한정됩니다.
향후 이러한 기능을 추가하는 것은 충분히 고려할 만하며, 현재 명세된 pointer lock API는 이러한 세분화된 델타 및 구속 기능이 구현되어도 계속 지원할 수 있습니다.
번들 API는 구현의 실용성, 원하는 사용 사례 지원, 그리고 향후 개선과 충돌하지 않기 때문에 선택되었습니다.
아직 아닙니다. 이유는 앞선 질문과 동일합니다: "모든 기능(커서 숨기기, 마우스 델타 제공 등)을 번들로 제공하고 CSS로 커서를 숨기거나 항상 델타 값을 제공하거나 웹 페이지 일부로 커서 이동을 제한하는 API를 제공하지 않는 이유?".
포인터 잠금 중에도 click, mousedown 등 많은 마우스 이벤트가 중요합니다. 이들은 모두 동일한 MouseEvent 데이터 구조를 공유합니다. 만약 움직임 데이터를 새로운 데이터 구조로 보고하면, 델타 움직임을 보고하는 새로운 이벤트가 필요합니다. 새로운 구조는 MouseEvent와 동일한 편의성을 제공하려면, 버튼 및 수정키 상태 등도 포함해야 합니다. click, down, up 이벤트 처리에 기존 mousedown, mouseup을 사용할 것이라면 .clientX/Y와 .screenX/Y에는 쓸모 없는 값이 들어가지만, 현재 움직임 데이터가 빠집니다. 아니면 마우스 잠금 중에만 새로운 이벤트도 필요하게 됩니다.
또한, movementX/Y는 마우스가 잠금되지 않은 상태에서도 편리합니다. 이 명세는 커서가 존재할 때도 movement 속성이 항상 유효해야 한다고 요구합니다. 이로써 애플리케이션이 델타 움직임을 활용하려면 마지막 커서 상태나 mouseover/mouseout 전환 관리 코드를 줄일 수 있습니다.
MouseEvent에 movementX/Y를 추가하면 포인터 잠금 중 clientX/Y와 screenX/Y 값이 사용되지 않는다는 점만 단점입니다. 하지만 이는 큰 문제가 아니라고 판단됩니다.
따라서 API 및 구현 복잡도를 줄이기 위해 MouseEvent에 movementX/Y를 최소한의 변경으로 추가하는 방식을 선택했습니다.
마우스 커서로 3D 뷰를 제어하면서 텍스트 콘솔로 다른 사용자와 채팅하는 게임을 생각해보면, 마우스 이벤트가 전달되는 요소와 키보드 입력을 받는 요소가 서로 다른 것이 합리적입니다. 이는 폼에 입력하면서 페이지의 어떤 요소에도 mousemove 이벤트가 전달되는 기존 동작과 유사합니다.
비규범적으로 표시된 섹션뿐만 아니라, 이 명세서의 모든 작성 지침, 다이어그램, 예시, 참고 사항은 비규범적입니다. 그 외 모든 내용은 규범적입니다.
이 명세서는 하나의 제품에 적용되는 준수 기준을 정의합니다: 해당 명세서에 포함된 인터페이스를 구현하는 사용자 에이전트입니다.
이 절은 비규범적입니다.
이 명세서의 논의에 기여해 주신 많은 분들께 감사드립니다:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: