포인터 이벤트

레벨 4

W3C 작업 초안

이 문서에 대한 자세한 내용
이 버전:
https://www.w3.org/TR/2026/WD-pointerevents4-20260701/
최신 발행 버전:
https://www.w3.org/TR/pointerevents4/
최신 편집자 초안:
https://w3c.github.io/pointerevents/
이력:
https://www.w3.org/standards/history/pointerevents4/
커밋 이력
테스트 스위트:
https://wpt.fyi/pointerevents/
최신 권고안:
https://www.w3.org/TR/pointerevents3
편집자:
Patrick H. Lauke (TetraLogical)
Robert Flack (Google)
이전 편집자:
Matt Brubeck (Mozilla)
Rick Byers (Google)
Navid Zolghadr (Google)
피드백:
GitHub w3c/pointerevents (풀 리퀘스트, 새 이슈, 열린 이슈)
public-pointer-events@w3.org 제목 줄은 [pointerevents4] … 메시지 주제 …로 한다 (아카이브)
브라우저 지원:
caniuse.com

초록

Pointer Events 사양은 마우스, 터치스크린, 펜/스타일러스 등 다양한 장치의 입력을 처리하기 위한 통합된 하드웨어 독립적 프레임워크를 정의한다. 단일 이벤트 집합(예: pointerdown, pointermove, pointerup)을 제공함으로써, 개발자가 각 장치별 로직을 작성하지 않고도 다양한 입력 방식을 지원할 수 있게 한다.

이 사양은 Mouse 및 Wheel 이벤트와, 다른 포인터 장치 유형에 대해 Mouse 이벤트를 발생시키기 위한 매핑도 정의한다.

이 문서의 상태

이 절은 이 문서가 발행된 시점의 문서 상태를 설명한다. 현재 W3C 발행물과 이 기술 보고서의 최신 개정판 목록은 W3C 표준 및 초안 색인에서 확인할 수 있다.

이 사양은 [PointerEvents3] 사양의 갱신판이다. 또한 이전에 [UIEVENTS] 사양에 있었던 Mouse 및 Wheel 이벤트를 포함한다.

이 개정판에는 새로운 기능이 포함된다:

이 문서는 Pointer Events Working Group권고안 트랙을 사용하여 작업 초안으로 발행하였다.

작업 초안으로 발행되었다는 사실이 W3C와 그 회원들의 승인을 의미하지는 않는다.

이 문서는 초안 문서이며 언제든지 다른 문서로 갱신, 대체 또는 폐기될 수 있다. 이 문서를 진행 중인 작업 이외의 것으로 인용하는 것은 부적절하다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에 의해 작성되었다. W3C는 이 그룹의 산출물과 관련하여 이루어진 모든 특허 공개의 공개 목록을 유지하며, 해당 페이지에는 특허 공개 지침도 포함되어 있다. 어떤 개인이 자신이 보유한 실제 지식에 비추어 그 개인이 필수 청구항을 포함한다고 믿는 특허를 알고 있는 경우, 그 개인은 W3C 특허 정책 제6절에 따라 해당 정보를 공개해야 한다.

이 문서는 2025년 8월 18일 W3C 절차 문서의 적용을 받는다.

1. 소개

이 절은 비규범적이다.

오늘날 대부분의 [HTML] 콘텐츠는 마우스 입력과 함께 사용되거나 및/또는 마우스 입력을 위해 설계된다. 입력을 사용자 정의 방식으로 처리하는 콘텐츠는 일반적으로 [UIEVENTS] Mouse Events에 맞춰 코드를 작성한다. 그러나 오늘날의 더 새로운 컴퓨팅 장치는 터치스크린과 펜 입력을 포함하여 다른 형태의 입력을 통합하고 있다. 이러한 각 입력 형태를 개별적으로 처리하기 위한 이벤트 유형이 제안되어 왔다. 그러나 이러한 접근 방식은 새 입력 유형에 대한 지원을 추가할 때 불필요한 로직 중복과 이벤트 처리 오버헤드를 유발하는 경우가 많다. 이는 콘텐츠가 하나의 장치 유형만 염두에 두고 작성될 때 호환성 문제를 자주 만든다. 또한 기존의 마우스 기반 콘텐츠와의 호환성을 위해 대부분의 사용자 에이전트는 모든 입력 유형에 대해 Mouse Events를 발생시킨다. 이 때문에 Mouse Event가 실제 마우스 장치를 나타내는 것인지, 아니면 호환성을 위해 다른 입력 유형에서 생성된 것인지 모호해지며, 두 장치 유형 모두에 동시에 맞춰 코드를 작성하기 어렵게 된다.

여러 입력 유형에 맞춰 코드를 작성하는 비용을 줄이고, 위에서 설명한 Mouse Events의 모호성에도 도움을 주기 위해, 이 사양은 포인터라고 하는 더 추상적인 형태의 입력을 정의한다. 포인터는 마우스 커서, 펜, 터치(멀티터치 포함), 또는 기타 포인팅 입력 장치가 화면에 만든 임의의 접촉점일 수 있다. 이 모델을 사용하면 사용자가 어떤 하드웨어를 가지고 있는지와 상관없이 잘 동작하는 사이트와 애플리케이션을 더 쉽게 작성할 수 있다. 장치별 처리가 필요한 시나리오를 위해, 이 사양은 이벤트를 생성한 장치 유형을 검사하기 위한 속성도 정의한다. 주요 목표는 장치 간 포인터 입력에 대한 저작을 더 쉽게 해 주는 단일 이벤트 및 인터페이스 집합을 제공하면서도, 향상된 경험을 위해 필요한 경우에만 장치별 처리를 허용하는 것이다.

또 하나의 핵심 목표는 다중 스레드 사용자 에이전트가 스크립트 실행에 의해 차단되지 않고, 패닝 및 줌을 위한 직접 조작 동작(예를 들어 터치스크린에서 손가락이나 스타일러스를 사용하는 경우)을 처리할 수 있게 하는 것이다.

참고

이 사양은 다양한 포인터 입력을 위한 통합 이벤트 모델을 정의하지만, 이 모델은 키보드나 키보드와 유사한 인터페이스와 같은 다른 입력 형태(예를 들어 터치스크린 전용 장치에서 실행되어, 사용자가 포커스 가능한 컨트롤과 요소를 순차적으로 탐색할 수 있게 하는 스크린 리더 또는 유사한 보조 기술)는 다루지 않는다. 사용자 에이전트가 이러한 인터페이스에 대한 응답으로 포인터 이벤트도 생성하도록 선택할 수는 있지만, 이 시나리오는 이 사양에서 다루지 않는다.

우선적으로 저자는 focus, blurclick과 같은 고수준 이벤트에 응답하여 모든 형태의 입력에 대해 동등한 기능을 제공하는 것이 권장된다. 그러나 (Pointer Events와 같은) 저수준 이벤트를 사용하는 경우, 저자는 모든 유형의 입력이 지원되도록 보장하는 것이 권장된다. 키보드와 키보드 유사 인터페이스의 경우, 이를 위해 명시적인 키보드 이벤트 처리를 추가해야 할 수 있다. 자세한 내용은 Keyboard Accessible [WCAG22]을 참조하라.

포인터 입력은 마우스, 펜, 터치와 같은 다양한 입력 소스를 결합한다
그림 1 포인터는 화면의 특정 좌표(또는 좌표 집합)를 대상으로 할 수 있는 입력 장치의 하드웨어 독립적 표현이다.

일반적인 포인터 입력을 처리하기 위한 이벤트는 마우스의 이벤트와 매우 비슷하다. pointerdown, pointermove, pointerup, pointerover, pointerout 등이 있다. 이는 콘텐츠를 Mouse Events에서 Pointer Events로 쉽게 이전할 수 있게 한다. Pointer Events는 Mouse Events에 있는 일반적인 모든 속성(클라이언트 좌표, 대상 요소, 버튼 상태 포함)을 제공하며, 압력, 접촉 기하, 기울기와 같은 다른 형태의 입력을 위한 새 속성도 추가로 제공한다. 저자는 의미가 있는 경우 여러 입력 유형 간에 로직을 공유하도록 Pointer Events에 맞춰 쉽게 코드를 작성할 수 있으며, 최상의 경험을 얻기 위해 필요한 경우에만 특정 입력 유형에 맞게 사용자 정의할 수 있다.

Pointer Events는 다양한 입력 장치에서 비롯되지만, 다른 장치별 이벤트 집합에서 생성되는 것으로 정의되지는 않는다. 호환성을 위해 가능하고 권장되기는 하지만, 이 사양은 다른 장치별 이벤트 (예: 마우스 이벤트 또는 터치 이벤트)가 지원되어야 한다고 요구하지 않는다. 사용자 에이전트는 다른 어떤 장치 이벤트도 지원하지 않고 포인터 이벤트만 지원할 수 있다. 마우스 전용 이벤트에 맞춰 작성된 콘텐츠와의 호환성을 위해, 이 사양은 마우스가 아닌 장치의 포인터 입력을 기반으로 호환성 마우스 이벤트를 생성하는 방법을 설명하는 선택적 절을 제공한다.

참고

이 사양은 ( [TOUCH-EVENTS]에 정의된) Touch Events와 Pointer Events를 모두 지원하는 사용자 에이전트의 예상 동작에 대한 조언을 제공하지 않는다. 이 두 사양의 관계에 대한 자세한 내용은 Touch Events Community Group을 참조하라.

2. 적합성

비규범으로 표시된 절뿐 아니라, 이 사양의 모든 저작 지침, 다이어그램, 예제 및 참고는 비규범적이다. 이 사양의 그 밖의 모든 것은 규범적이다.

이 문서의 핵심 단어 MAY, MUST, MUST NOT, OPTIONAL, 및 SHOULD는 여기에 표시된 것처럼 모두 대문자로 나타날 때, 그리고 그 경우에만, BCP 14 [RFC2119] [RFC8174]에 설명된 대로 해석되어야 한다.

3. 예제

이 절은 비규범적이다.

다음은 이 사양의 일부 API가 저자에 의해 어떻게 사용될 수 있는지를 보여 주는 기본 예제이다. 더 구체적인 추가 예제는 이 문서의 관련 절에서 제공된다.

예제 1: 기능 감지 및 이벤트 바인딩
/* Pointer Events 또는 기존 touch/mouse 중 하나에 바인딩 */

if (window.PointerEvent) {
    // Pointer Events가 지원되면 pointer 이벤트만 수신한다
    target.addEventListener("pointerdown", function(e) {
        // 필요한 경우 e.pointerType을 기반으로 별도의 로직을 적용한다
        // 서로 다른 touch/pen/mouse 동작에 대해
        ...
    });
    ...
} else {
    // 기존 touch/mouse 이벤트 핸들러
    target.addEventListener('touchstart', function(e) {
        // 호환성 마우스 이벤트와 click을 방지한다
        e.preventDefault();
        ...
    });
    ...
    target.addEventListener('mousedown', ...);
    ...
}

// 키보드 처리를 위한 추가 이벤트 리스너
...
예제 2: 사용자로부터의 입력 유형 감지
window.addEventListener("pointerdown", detectInputType);

function detectInputType(event) {
    switch(event.pointerType) {
        case "mouse":
            /* 마우스 입력 감지됨 */
            break;
        case "pen":
            /* 펜/스타일러스 입력 감지됨 */
            break;
        case "touch":
            /* 터치 입력 감지됨 */
            break;
        default:
            /* pointerType이 비어 있음(감지할 수 없음)
            또는 UA별 사용자 정의 유형 */
    }
}
예제 3: 접촉 기하에 맞게 요소 크기 조정
<div style="position:absolute; top:0px; left:0px; width:100px;height:100px;"></div>
<script>
window.addEventListener("pointerdown", checkPointerSize);

function checkPointerSize(event) {
    event.target.style.width = event.width + "px";
    event.target.style.height = event.height + "px";
}
</script>
예제 4: 스크립트에서 신뢰할 수 없는 포인터 이벤트 발생
const event1 = new PointerEvent("pointerover",
  { bubbles: true,
    cancelable: true,
    composed: true,
    pointerId: 42,
    pointerType: "pen",
    clientX: 300,
    clientY: 500
  });
eventTarget.dispatchEvent(event1);

let pointerEventInitDict =
{
  bubbles: true,
  cancelable: true,
  composed: true,
  pointerId: 42,
  pointerType: "pen",
  clientX: 300,
  clientY: 500,
};
const p1 = new PointerEvent("pointermove", pointerEventInitDict);
pointerEventInitDict.clientX += 10;
const p2 = new PointerEvent("pointermove", pointerEventInitDict);
pointerEventInitDict.coalescedEvents = [p1, p2];
const event2 = new PointerEvent("pointermove", pointerEventInitDict);
eventTarget.dispatchEvent(event2);
예제 5: PointerDown에서 펜 색상 할당
<div style="position:absolute; top:0px; left:0px; width:100px;height:100px;"></div>
<script>
window.addEventListener("pointerdown", assignPenColor);
window.addEventListener("pointermove", assignPenColor);
const colorMap = new Map();

function assignPenColor(event) {
    const uniqueId = event.persistentDeviceId;
    // 고유 ID가 존재하는지 확인한다.
    if (uniqueId == 0) {
        return;
    }
    // 장치에 색상이 할당되었는지 확인한다.
    if (map.has(uniqueId)) {
        return;
    }
    // 장치에 색상을 할당한다.
    let newColor = getNewColor();
    map.set(uniqueId, newColor);
    return newColor;
}

function getNewColor() {
    /* 어떤 색상 값을 반환한다 */
}
</script>

4. 마우스 이벤트

마우스 이벤트 모듈은 [HTML401]의 onclick, ondblclick, onmousedown, onmouseup, onmouseover, onmousemove, 및 onmouseout 속성에서 유래한다. 이 이벤트 모듈은 마우스나 트랙볼과 같은 포인팅 입력 장치와 함께 사용하도록 특별히 설계되었다.

4.1 MouseEvent 인터페이스

DOM Level 2에서 도입되었으며, 이 사양에서 수정되었다.

MouseEvent 인터페이스는 Mouse 이벤트와 관련된 구체적인 문맥 정보를 제공한다.

중첩된 요소의 경우, 마우스 이벤트는 항상 가장 깊게 중첩된 요소를 대상으로 한다.

참고

대상 요소의 조상은 이벤트 버블링을 사용하여 그 자손 요소 내에서 발생하는 마우스 이벤트에 대한 알림을 얻을 수 있다.

MouseEvent 인터페이스의 인스턴스를 만들려면, 선택적인 MouseEventInit 딕셔너리를 전달하여 MouseEvent 생성자를 사용한다.

참고

initMouseEvent를 사용하여 MouseEvent 객체를 초기화할 때, 구현은 다른 좌표(예: DOM Level 0 구현 또는 기타 독점 속성에서 노출되는 대상 좌표, 예를 들어 pageX)를 계산하기 위해 클라이언트 좌표 clientXclientY를 사용할 수 있다.

4.1.1 MouseEvent

WebIDL[Exposed=Window]
interface MouseEvent : UIEvent {
	constructor(DOMString type, optional MouseEventInit eventInitDict = {});
	readonly attribute long screenX;
	readonly attribute long screenY;
	readonly attribute long clientX;
	readonly attribute long clientY;
	readonly attribute long layerX;
	readonly attribute long layerY;

	readonly attribute boolean ctrlKey;
	readonly attribute boolean shiftKey;
	readonly attribute boolean altKey;
	readonly attribute boolean metaKey;

	readonly attribute short button;
	readonly attribute unsigned short buttons;

	readonly attribute EventTarget? relatedTarget;

	boolean getModifierState(DOMString keyArg);
};
screenX

이벤트가 발생한 수평 좌표로, 화면 좌표계의 원점을 기준으로 한다.

이 속성의 초기화되지 않은 값MUST 0이어야 한다.

screenY

이벤트가 발생한 수직 좌표로, 화면 좌표계의 원점을 기준으로 한다.

이 속성의 초기화되지 않은 값MUST 0이어야 한다.

clientX

이벤트가 발생한 수평 좌표로, 이벤트와 연결된 뷰포트를 기준으로 한다.

이 속성의 초기화되지 않은 값MUST 0이어야 한다.

clientY

이벤트가 발생한 수직 좌표로, 이벤트와 연결된 뷰포트를 기준으로 한다.

이 속성의 초기화되지 않은 값MUST 0이어야 한다.

layerX

조상 요소 중 가장 가까운 요소에서의 수평 오프셋이다. 해당 요소는 쌓임 맥락이거나, 위치 지정된 요소이거나, 쌓임 맥락을 페인팅할 때 위치 지정 단계에서 페인팅된다.

이 속성의 초기화되지 않은 값MUST 0이어야 한다.

layerY

조상 요소 중 가장 가까운 요소에서의 수직 오프셋이다. 해당 요소는 쌓임 맥락이거나, 위치 지정된 요소이거나, 쌓임 맥락을 페인팅할 때 위치 지정 단계에서 페인팅된다.

이 속성의 초기화되지 않은 값MUST 0이어야 한다.

ctrlKey

KeyboardEventctrlKey 속성을 참조하라.

이 속성의 초기화되지 않은 값MUST false이어야 한다.

shiftKey

KeyboardEventshiftKey 속성을 참조하라.

이 속성의 초기화되지 않은 값MUST false이어야 한다.

altKey

KeyboardEventaltKey 속성을 참조하라.

이 속성의 초기화되지 않은 값MUST false이어야 한다.

metaKey

KeyboardEventmetaKey 속성을 참조하라.

이 속성의 초기화되지 않은 값MUST false이어야 한다.

button

마우스 버튼을 누르거나 놓아서 발생한 마우스 이벤트 동안, button은 어떤 포인터 장치 버튼의 상태가 변경되었는지를 나타내는 데 MUST 사용되어야 한다.

button 속성의 값은 다음과 같아야 MUST 한다:

  • 0은 장치의 주 버튼(일반적으로 왼쪽 버튼 또는 단일 버튼 장치의 유일한 버튼으로, 사용자 인터페이스 컨트롤을 활성화하거나 텍스트를 선택하는 데 사용됨) 또는 초기화되지 않은 값을 나타내야 MUST 한다.
  • 1은 보조 버튼(일반적으로 마우스 휠과 결합된 가운데 버튼)을 나타내야 MUST 한다.
  • 2는 부 버튼(일반적으로 컨텍스트 메뉴를 표시하는 데 자주 사용되는 오른쪽 버튼)을 나타내야 MUST 한다.
  • 3은 X1(뒤로) 버튼을 나타내야 MUST 한다.
  • 4는 X2(앞으로) 버튼을 나타내야 MUST 한다.

일부 포인팅 장치는 더 많은 버튼 상태를 제공하거나 시뮬레이션하며, 2보다 크거나 0보다 작은 값은 이러한 버튼을 나타내는 데 MAY 사용될 수 있다.

참고

button 값은 마우스 버튼을 누르거나 놓아서 발생하지 않은 이벤트에 대해서는 갱신되지 않는다. 이러한 시나리오에서는 값 0을 왼쪽 버튼으로 해석하지 말고, 기본값으로 해석하도록 주의하라.

참고

mousedownmouseup과 같은 이벤트와 관련된 일부 기본 동작은 사용 중인 특정 마우스 버튼에 의존한다.

이 속성의 초기화되지 않은 값MUST 0이어야 한다.

buttons

모든 마우스 이벤트 동안, buttons는 현재 눌려 있는 마우스 버튼의 조합을 비트마스크로 표현하여 나타내는 데 MUST 사용되어야 한다.

참고

이름은 비슷하지만, buttons 속성과 button 속성의 값은 매우 다르다. button 값은 mousedown / mouseup 이벤트 핸들러 동안 유효하다고 가정되는 반면, buttons 속성은 신뢰된 MouseEvent 객체가 (디스패치되는 동안) 임의의 마우스 버튼 상태를 반영한다. 이는 "현재 활성 버튼 없음" 상태(0)를 나타낼 수 있기 때문이다.

buttons 속성의 값은 다음과 같아야 MUST 한다:

  • 0은 현재 활성인 버튼이 없음을 나타내야 MUST 한다.
  • 1은 장치의 주 버튼(일반적으로 왼쪽 버튼 또는 단일 버튼 장치의 유일한 버튼으로, 사용자 인터페이스 컨트롤을 활성화하거나 텍스트를 선택하는 데 사용됨)을 나타내야 MUST 한다.
  • 2는 존재하는 경우 부 버튼(일반적으로 컨텍스트 메뉴를 표시하는 데 자주 사용되는 오른쪽 버튼)을 나타내야 MUST 한다.
  • 4는 보조 버튼(일반적으로 마우스 휠과 결합된 가운데 버튼)을 나타내야 MUST 한다.

일부 포인팅 장치는 더 많은 버튼을 제공하거나 시뮬레이션한다. 이러한 버튼을 나타내기 위해, 값은 각 후속 버튼마다 두 배가 되어야 MUST 한다(이진 계열 8, 16, 32, ... ).

참고

버튼 값들의 임의 집합의 합은 고유한 숫자이므로, 콘텐츠 저자는 비트 연산을 사용하여 현재 몇 개의 버튼이 눌려 있는지와 어떤 버튼인지, 장치의 임의 개수 마우스 버튼에 대해 판별할 수 있다. 예를 들어 값 3은 왼쪽 버튼과 오른쪽 버튼이 현재 모두 눌려 있음을 나타내고, 값 5는 왼쪽 버튼과 가운데 버튼이 현재 모두 눌려 있음을 나타낸다.

참고

mousedownmouseup과 같은 이벤트와 관련된 일부 기본 동작은 사용 중인 특정 마우스 버튼에 의존한다.

이 속성의 초기화되지 않은 값MUST 0이어야 한다.

relatedTarget

이벤트 유형에 따라 UI 이벤트와 관련된 보조 EventTarget을 식별하는 데 사용된다.

이 속성의 초기화되지 않은 값MUST null이어야 한다.

getModifierState(keyArg)

키 값을 사용하여 수정자의 상태를 질의한다.

수정자 키이고 그 수정자가 활성화되어 있으면 true를 반환하고, 그렇지 않으면 false를 반환한다.

DOMString keyArg
이 매개변수에 대한 설명은 KeyboardEventgetModifierState() 메서드를 참조하라.

4.1.2 MouseEventInit

WebIDLdictionary MouseEventInit : EventModifierInit {
	long screenX = 0;
	long screenY = 0;
	long clientX = 0;
	long clientY = 0;

	short button = 0;
	unsigned short buttons = 0;
	EventTarget? relatedTarget = null;
};
screenX

screenX 속성의 MouseEvent 객체를 사용자 화면에서의 마우스 포인터의 원하는 수평 상대 위치로 초기화한다.

이벤트 객체를 주어진 마우스 위치로 초기화하더라도 사용자의 마우스 포인터가 초기화된 위치로 이동해서는 안 된다.

screenY

screenY 속성의 MouseEvent 객체를 사용자 화면에서의 마우스 포인터의 원하는 수직 상대 위치로 초기화한다.

이벤트 객체를 주어진 마우스 위치로 초기화하더라도 사용자의 마우스 포인터가 초기화된 위치로 이동해서는 안 된다.

clientX

clientX 속성의 MouseEvent 객체를 사용자의 브라우저 클라이언트 창을 기준으로 한 마우스 포인터의 원하는 수평 위치로 초기화한다.

이벤트 객체를 주어진 마우스 위치로 초기화하더라도 사용자의 마우스 포인터가 초기화된 위치로 이동해서는 안 된다.

clientY

clientY 속성의 MouseEvent 객체를 사용자의 브라우저 클라이언트 창을 기준으로 한 마우스 포인터의 원하는 수직 위치로 초기화한다.

이벤트 객체를 주어진 마우스 위치로 초기화하더라도 사용자의 마우스 포인터가 초기화된 위치로 이동해서는 안 된다.

button

button 속성의 MouseEvent 객체를 마우스 버튼(들)의 원하는 상태를 나타내는 숫자로 초기화한다.

참고

값 0은 주 마우스 버튼을 나타내는 데 사용되고, 1은 보조/가운데 마우스 버튼을 나타내는 데 사용되며, 2는 오른쪽 마우스 버튼을 나타내는 데 사용된다. 2보다 큰 숫자도 가능하지만, 이 문서에서는 지정하지 않는다.

buttons

buttons 속성의 MouseEvent 객체를 활성으로 간주되어야 하는 마우스 버튼(들) 중 하나 또는 그 이상을 나타내는 숫자로 초기화한다.

참고

buttons 속성은 비트 필드이다. 마스크 값 1을 비트 필드 값에 적용했을 때 참이면 주 마우스 버튼이 눌린 것이다. 마스크 값 2를 비트 필드 값에 적용했을 때 참이면 오른쪽 마우스 버튼이 눌린 것이다. 마스크 값 4를 비트 필드 값에 적용했을 때 참이면 보조/가운데 버튼이 눌린 것이다.

JavaScript에서, 오른쪽(2) 버튼과 가운데 버튼(4)이 동시에 눌린 것처럼 buttons 속성을 초기화하려면, buttons 값은 다음 중 하나로 할당할 수 있다:

{ buttons: 2 | 4 }

또는:

{ buttons: 6 }
relatedTarget

relatedTarget는 ( mouseover 또는 mouseenter 이벤트의 경우) 마우스 포인터가 방금 경계를 떠난 요소, 또는 ( mouseout 또는 mouseleave 또는 focusout 이벤트의 경우) 마우스 포인터가 경계 안으로 들어가고 있는 요소로 초기화되어야 한다. 다른 이벤트의 경우, 이 값은 할당할 필요가 없다 (그리고 기본값은 null이 된다).

구현은 마우스 이벤트를 생성할 때 현재 클릭 횟수를 유지해야 MUST 한다. 이는 특정 시간 안에 포인팅 장치 버튼이 연속으로 클릭된 횟수를 나타내는 음이 아닌 정수여야 MUST 한다. 그 횟수가 재설정되는 지연 시간은 환경 구성에 따라 다르다.

4.2 MouseEvent 알고리즘

4.2.1 네이티브 OS 요구사항

이 절의 알고리즘은 네이티브 플랫폼 OS가 다음을 제공한다고 가정한다:

이러한 이벤트에 대해, OS는 다음 정보를 제공할 수 있다:

  • 네이티브 OS 데스크톱을 기준으로 한 x,y 마우스 좌표
  • UA의 창 뷰포트를 기준으로 한 x,y 마우스 좌표
  • 현재 누르고 있는 키보드 수정자

4.2.2 Mouse 이벤트 생성

경고

이 절은 개정이 필요하다.

일반적으로, Event 인터페이스의 생성자, 또는 Event 인터페이스에서 상속된 인터페이스의 생성자가 호출되면, [DOM]에 설명된 단계를 따라야 한다. 그러나 MouseEvent 인터페이스는 Event 객체의 키 수정자의 내부 상태, 구체적으로 getModifierState() 메서드를 사용하여 질의되는 내부 상태를 초기화하기 위한 추가 딕셔너리 멤버를 제공한다. 이 절은 이러한 선택적 수정자 상태를 사용하여 새 MouseEvent 객체를 초기화하기 위한 [DOM] 단계를 보완한다.

아래 알고리즘을 사용하여 MouseEvent, 또는 이러한 객체에서 파생된 객체를 생성하기 위한 목적상, 모든 MouseEvent 및 파생 객체는 내부 키 수정자 상태를 가지며, 이는 [UIEvents-Key]의 Modifier Keys 표에 설명된 키 수정자 이름을 사용하여 설정하고 가져올 수 있다.

다음 단계는 [DOM]에 정의된 이벤트 생성 알고리즘을 보완한다:

  • 생성 중인 EventMouseEvent 객체이거나 그로부터 파생된 객체이고, 생성자에 EventModifierInit 인수가 제공되었다면, 다음 하위 단계를 실행한다:

4.2.3 MouseEvent의 전역 상태

경고

이 절은 개정이 필요하다.

4.2.3.1 사용자 에이전트 수준 상태

UA는 전체 사용자 에이전트에 대해 공유되는 다음 값을 유지해야 한다.

마우스 버튼의 현재 상태를 추적하는 마우스 버튼 비트마스크.

4.2.3.2 Window 수준 상태

UA는 Window에 대해 공유되는 다음 값을 유지해야 한다.

MouseEvent를 보낸 마지막 Element를 추적하는 마지막 마우스 요소 값(초기값은 undefined).

가장 최근의 마우스 이벤트가 전송되었을 때 마지막 마우스 요소의 조상 Element들의 스냅샷을 포함하는 마지막 마우스 DOM 경로 값(초기값은 비어 있음).

4.2.4 MouseEvent의 내부 상태

경고

이 절은 개정이 필요하다.

MouseEvent는 다양한 수정자 키의 상태를 추적하는 데 사용되는 다음 내부 플래그를 가진다: shift 플래그, control 플래그, alt 플래그, altgraph 플래그, 및 meta 플래그. 이러한 플래그는 마우스 이벤트가 발생한 시점에 해당 수정자 키가 눌려 있었다면 설정된다.

4.2.5 히트 테스트

경고

이 절은 개정이 필요하다.

  1. pos를 뷰포트를 기준으로 한 x,y 좌표로 둔다
  2. [CSSOM-View]의 elementFromPoint()pos와 함께 반환한다(pos에 있는 가장 앞쪽 DOM 요소)
    참고

    inert 또는 disabled 요소를 고려하기 위해, 이는 elementsFromPoint()를 호출하고 유효하지 않은 요소를 거부해야 한다.

4.2.6 MouseEvent 초기화

경고

이 절은 개정이 필요하다.

event, eventType, eventTarget, bubblescancelableMouseEvent를 초기화하려면, 다음 단계를 실행한다:

  1. event, eventType, eventTarget, bubblescancelableUIEvent를 초기화한다.
  2. event.screenX를 이벤트가 발생한 위치의 데스크톱 원점을 기준으로 한 x 좌표로 설정한다
  3. event.screenY를 이벤트가 발생한 위치의 데스크톱 원점을 기준으로 한 y 좌표로 설정한다
  4. event.clientX를 이벤트가 발생한 위치의 뷰포트 원점을 기준으로 한 x 좌표로 설정한다
  5. event.clientY를 이벤트가 발생한 위치의 뷰포트 원점을 기준으로 한 y 좌표로 설정한다
  6. event마우스 이벤트 수정자 설정을 수행한다
  7. event.button을 0으로 설정한다
  8. event.buttons마우스 버튼 비트마스크로 설정한다
  9. eventMouseEvent에 대한 PointerLock 속성 초기화를 수행한다
    이슈 1

    여기서 하드코딩하는 대신 PointerLock을 위한 훅을 제공해야 한다.

4.2.7 마우스 이벤트 수정자 설정

경고

이 절은 개정이 필요하다.

  1. event를 갱신할 MouseEvent로 둔다
  2. 키 수정자 상태가 "Shift"를 포함하면 eventshift 플래그를 설정하고, 그렇지 않으면 해제한다
  3. 키 수정자 상태가 "Control"을 포함하면 eventcontrol 플래그를 설정하고, 그렇지 않으면 해제한다
  4. 키 수정자 상태가 "Alt"를 포함하면 eventalt 플래그를 설정하고, 그렇지 않으면 해제한다
  5. 키 수정자 상태가 "AltGraph"를 포함하면 eventaltgraph 플래그를 설정하고, 그렇지 않으면 해제한다
  6. 키 수정자 상태가 "Meta"를 포함하면 eventmeta 플래그를 설정하고, 그렇지 않으면 해제한다
  7. 이벤트의 shift 플래그가 설정되어 있으면 event.shiftKey를 true로 설정하고, 그렇지 않으면 false로 설정한다
  8. 이벤트의 control 플래그가 설정되어 있으면 event.ctrlKey를 true로 설정하고, 그렇지 않으면 false로 설정한다
  9. 이벤트의 alt 플래그 또는 altgraph 플래그가 설정되어 있으면 event.altKey를 true로 설정하고, 그렇지 않으면 false로 설정한다
  10. 이벤트의 meta 플래그가 설정되어 있으면 event.metaKey를 true로 설정하고, 그렇지 않으면 false로 설정한다

4.2.8 취소 가능한 MouseEvent 생성

경고

이 절은 개정이 필요하다.

  1. eventType을 유효한 MouseEvent 유형을 포함하는 DOMString으로 둔다
  2. eventTarget을 이벤트의 EventTarget으로 둔다
  3. bubbles를 true로 둔다
  4. cancelable을 true로 둔다
  5. eventMouseEvent를 사용하여 이벤트를 생성한 결과로 둔다
  6. event, eventType, eventTarget, bubblescancelableMouseEvent를 초기화한다.
  7. event를 반환한다

4.2.9 취소 불가능한 MouseEvent 생성

경고

이 절은 개정이 필요하다.

  1. eventType을 유효한 MouseEvent 유형을 포함하는 DOMString으로 둔다
  2. eventTarget을 이벤트의 EventTarget으로 둔다
  3. bubbles를 "false"로 둔다
  4. cancelable을 "false"로 둔다
  5. eventMouseEvent를 사용하여 이벤트를 생성한 결과로 둔다
  6. event, eventType, eventTarget, bubblescancelableMouseEvent를 초기화한다.
  7. event를 반환한다

4.2.10 MouseEvent button 속성 계산

경고

이 절은 개정이 필요하다.

이는 MouseEventbutton 속성에 저장하기에 적합한 버튼 ID를 반환한다.

  1. mbutton을 마우스 버튼을 식별하는 ID로 둔다
  2. mbutton이 주 마우스 버튼이면 0을 반환한다
  3. mbutton이 보조(가운데) 마우스 버튼이면 1을 반환한다
  4. mbutton이 부 마우스 버튼이면 2를 반환한다
  5. mbutton이 X1(뒤로) 버튼이면 3을 반환한다
  6. mbutton이 X2(앞으로) 버튼이면 4를 반환한다

4.2.11 네이티브에서 MouseEvent 속성 설정

경고

이 절은 개정이 필요하다.

  1. event를 초기화할 MouseEvent로 둔다
  2. native를 네이티브 마우스 이벤트로 둔다
    편집자 참고

    TODO.

  3. event.type이 [ mousedown, mouseup ] 중 하나이면,
    1. mbutton을 어떤 마우스 버튼이 눌렸는지를 식별하는 native의 ID로 둔다
    2. event.buttonmbuttonMouseEvent button 속성 계산을 수행한 값으로 설정한다

4.2.12 네이티브 mouse down 처리

경고

이 절은 개정이 필요하다.

  1. native를 네이티브 mousedown으로 둔다
  2. mbutton을 어떤 마우스 버튼이 눌렸는지를 식별하는 native의 ID로 둔다
  3. 마우스 버튼 비트마스크를 다음과 같이 갱신한다:
    1. mbutton이 주 마우스 버튼이면, 0x01 비트를 설정한다
    2. mbutton이 부 마우스 버튼이면, 0x02 비트를 설정한다
    3. mbutton이 보조(가운데) 마우스 버튼이면, 0x04 비트를 설정한다
      참고

      다른 버튼은 0x08부터 추가할 수 있다.

  4. targetnative의 뷰포트 상대 좌표로 히트 테스트한 값으로 둔다
  5. event를 "mousedown" 및 target으로 취소 가능한 MouseEvent 생성을 수행한 결과로 둔다
  6. native네이티브에서 MouseEvent 속성 설정을 수행한다
  7. eventpointerdown 이벤트 전송 여부 결정을 수행한다
  8. resulttargetevent디스패치한 결과로 둔다
  9. result가 true이고 target포커스 가능한 영역이며 클릭 포커스 가능하다면,
    1. target에서 포커싱 단계를 실행한다
  10. mbutton이 부 마우스 버튼이면,
    1. native, target컨텍스트 메뉴 표시 여부 결정을 수행한다

4.2.13 네이티브 mouse up 처리

경고

이 절은 개정이 필요하다.

  1. native를 네이티브 mouseup으로 둔다
    참고

    mousedown과 mouseup 사이에 다른 마우스 이벤트가 발생할 수 있다.

  2. mbutton을 어떤 마우스 버튼이 눌렸는지를 식별하는 native의 ID로 둔다
  3. 마우스 버튼 비트마스크를 다음과 같이 갱신한다:
    1. mbutton이 주 마우스 버튼이면, 0x01 비트를 지운다
    2. mbutton이 부 마우스 버튼이면, 0x02 비트를 지운다
    3. mbutton이 보조(가운데) 마우스 버튼이면, 0x04 비트를 지운다
  4. targetnative의 뷰포트 상대 좌표로 히트 테스트한 값으로 둔다
  5. event를 "mouseup" 및 target으로 취소 가능한 MouseEvent 생성을 수행한 결과로 둔다
  6. native네이티브에서 MouseEvent 속성 설정을 수행한다
  7. eventpointerup 이벤트 전송 여부 결정을 수행한다
  8. targetevent디스패치한다

4.2.14 네이티브 mouse click 처리

경고

이 절은 개정이 필요하다.

  1. native를 네이티브 마우스 클릭으로 둔다
    참고

    플랫폼은 클릭을 생성하는 mouseup에 대해 네이티브 mouse up 처리 직후에 이를 호출해야 한다.

  2. targetnative의 뷰포트 상대 좌표로 히트 테스트한 값으로 둔다
  3. nativetarget으로 click 이벤트 전송을 수행한다.

4.2.15 click 이벤트 전송

경고

이 절은 개정이 필요하다.

  1. native를 네이티브 mousedown으로 둔다
  2. target을 이벤트의 EventTarget으로 둔다
  3. mbutton을 1로 둔다(기본값으로 주 마우스 버튼)
  4. native가 유효하면,
    1. mbutton을 어떤 마우스 버튼이 눌렸는지를 식별하는 native의 ID로 둔다
  5. mbutton이 주 마우스 버튼이면 eventType을 "click"으로 설정하고, 그렇지 않으면 "auxclick"으로 설정한다
  6. eventeventTypetarget으로 PointerEvent 생성을 수행한 결과로 둔다
  7. native가 유효하면,
    1. event, native네이티브에서 MouseEvent 속성 설정을 수행한다
    2. event.screenX가 정수 값이 아니면, 반올림한다.
    3. event.screenY가 정수 값이 아니면, 반올림한다.
  8. targetevent디스패치한다
    참고

    PointerEvents와 반올림된 좌표를 사용하는 브라우저에 대한 정보는 pointerevents/100을 참조하라.

    편집자 참고

    모든 "기본 동작"은 디스패치 중 대상에 대한 활성화 동작 알고리즘을 트리거하여 처리된다. 따라서 여기서 이를 처리할 필요는 없다. 그러나 기존 사양이 disabled/css-pointer-events/inert/...를 처리하는지 확인해야 한다.

    참고

    HTMLelement.click()을 처리하려면, native = null 및 target = HTMLelement로 이 알고리즘을 호출한다.

    참고

    키보드로 시작된 클릭을 처리하려면, native = null 및 target = 현재 포커스된 요소로 이 알고리즘을 호출한다.

4.2.16 네이티브 mouse double click 처리

경고

이 절은 개정이 필요하다.

  1. native를 네이티브 마우스 더블 클릭으로 둔다
    참고

    이는 더블 클릭을 생성하는 마우스 클릭에 대해 handle native mouse click 직후에 호출되어야 한다.

  2. mbutton을 어떤 마우스 버튼이 눌렸는지를 식별하는 native의 ID로 둔다
  3. mbutton이 주 마우스 버튼이 아니면, 반환한다
  4. targetnative의 뷰포트 상대 좌표로 히트 테스트한 값으로 둔다
  5. event를 "dblclick" 및 target으로 PointerEvent 생성을 수행한 결과로 둔다
  6. event, native네이티브에서 MouseEvent 속성 설정을 수행한다
  7. event.screenX가 정수 값이 아니면, 반올림한다.
  8. event.screenY가 정수 값이 아니면, 반올림한다.
  9. targetevent디스패치한다

4.2.17 네이티브 mouse move 처리

경고

이 절은 개정이 필요하다.

  1. native를 네이티브 mouse move로 둔다
    이슈 2

    이 알고리즘은 PointerEvents의 디스패치에 대해 가정한다. 이는 현재 명시적으로 지정되어 있지 않기 때문이다. pointerevents/285가 해결되면 이를 갱신해야 할 수 있다.

  2. targetnative의 뷰포트 상대 좌표로 히트 테스트한 값으로 둔다
  3. targetDomPathtarget포함 조상으로 둔다
  4. 현재 요소를 떠나는 이벤트를 생성한다:
    1. 마지막 마우스 요소가 정의되어 있고 target과 같지 않으면,
      1. mouseout을 "mouseout" 및 마지막 마우스 요소취소 가능한 MouseEvent 생성을 수행한 결과로 둔다
        편집자 참고

        TODO: native에서 mouseout 속성을 설정한다. +CSSOM 속성.

    2. mouseout으로 pointerout 이벤트 전송 여부 결정을 수행한다
    3. targetmouseout디스패치한다
      참고

      취소되었을 때의 동작을 확인한다(효과가 없는 것으로 보인다).

    4. leaveElementstargetDomPath와 공통인 모든 요소를 제거한 마지막 마우스 DOM 경로의 복사본으로 둔다.
    5. leaveElements의 각 element에 대해 다음을 수행한다
      편집자 참고

      element가 삭제된 경우를 처리한다. 또한 이동된 경우도 처리한다: DOM 변이가 mouseleave 이벤트를 트리거했어야 하는가? 지금 전송해야 하는가? 버려야 하는가? 현재 브라우저가 무엇을 하는지 확인해야 한다.

      1. mouseleave를 "mouseleave" 및 element취소 불가능한 MouseEvent 생성을 수행한 결과로 둔다
      2. mouseleave.Event.composed = false로 설정한다
        참고

        호환성을 확인한다: event.composed의 값. 사양은 false라고 한다. Chrome/Linux = true. Firefox/Linux = false.

      3. mouseleavepointerleave 이벤트 전송 여부 결정을 수행한다
      4. resultelementmouseleave디스패치한 결과로 둔다
  5. 새 요소에 들어가는 이벤트를 생성한다:
    1. target마지막 마우스 요소가 아니면,
      1. mouseover를 "mouseover" 및 target으로 취소 가능한 MouseEvent 생성을 수행한 결과로 둔다
        편집자 참고

        TODO: native에서 mouseout 속성을 설정한다. +CSSOM 속성.

      2. mouseoverpointerover 이벤트 전송 여부 결정을 수행한다
      3. targetmouseout디스패치한다
        참고

        취소되었을 때의 동작을 확인해야 한다(효과가 없는 것으로 보인다).

      4. enterElements마지막 마우스 DOM 경로와 공통인 모든 요소를 제거한 targetDomPath의 복사본으로 둔다.
      5. enterElements의 각 element에 대해 다음을 수행한다
        참고

        element가 삭제되었거나 이동된 경우를 처리한다.

        1. mouseenter를 "mouseenter" 및 element취소 불가능한 MouseEvent 생성을 수행한 결과로 둔다
        2. mouseenter.Event.composed = false로 설정한다
          참고

          호환성을 확인한다: event.composed의 값. 사양은 false라고 한다. Chrome/Linux = true. Firefox/Linux = false.

        3. mouseenterpointerenter 이벤트 전송 여부 결정을 수행한다
          참고

          섀도 DOM 요소에 대한 호환성을 확인한다. Chrome/Linux는 이 이벤트를 요소와 섀도 루트에서 발생시킨다.

        4. resultelementmouseenter디스패치한 결과로 둔다
      6. 마지막 마우스 요소target으로 설정한다
      7. 마지막 마우스 DOM 경로targetDomPath로 설정한다
  6. mousemove를 "mousemove" 및 element취소 가능한 MouseEvent 생성을 수행한 결과로 둔다
  7. mousemove에 대한 PointerLock 속성 설정
  8. mousemovepointermove 이벤트 전송 여부 결정을 수행한다
  9. elementmousemove디스패치한다

4.2.18 컨텍스트 메뉴 표시 여부 결정

경고

이 절은 개정이 필요하다.

  1. native를 네이티브 mousedown 또는 포인터 이벤트로 둔다
  2. target을 이벤트의 EventTarget으로 둔다
    1. menuevent를 "contextmenu", targetPointerEvent 생성을 수행한 결과로 둔다
    2. native가 유효하면,
      1. native네이티브에서 MouseEvent 속성 설정을 수행한다
    3. resulttargetmenuevent디스패치한 결과로 둔다
    4. result가 true이면, UA 컨텍스트 메뉴를 표시한다
참고

키보드로 트리거된 컨텍스트 메뉴를 처리하려면, native = null 및 target = 현재 포커스된 요소로 이 알고리즘을 호출한다.

4.3 마우스 이벤트 순서

이 사양에 정의된 특정 마우스 이벤트는 서로에 대해 정해진 순서로 발생해야 MUST 한다. 다음은 포인팅 장치의 커서가 요소 위로 이동할 때 발생해야 MUST 하는 이벤트 순서를 보여 준다:

# 이벤트 유형 요소 참고
1 mousemove
포인팅 장치가 요소 A 안으로 이동한다...
2 mouseover A
3 mouseenter A
4 mousemove A 여러 mousemove 이벤트
포인팅 장치가 요소 A 밖으로 이동한다...
5 mouseout A
6 mouseleave A

포인팅 장치가 요소 A 안으로 이동한 다음, 중첩된 요소 B 안으로 이동하고 다시 밖으로 이동할 때, 다음 이벤트 순서가 발생해야 MUST 한다:

이벤트 유형 요소 참고
1 mousemove
포인팅 장치가 요소 A 안으로 이동한다...
2 mouseover A
3 mouseenter A
4 mousemove A 여러 mousemove 이벤트
포인팅 장치가 중첩된 요소 B 안으로 이동한다...
5 mouseout A
6 mouseover B
7 mouseenter B
8 mousemove B 여러 mousemove 이벤트
포인팅 장치가 요소 B에서 A 안으로 이동한다...
9 mouseout B
10 mouseleave B
11 mouseover A
12 mousemove A 여러 mousemove 이벤트
포인팅 장치가 요소 A 밖으로 이동한다...
13 mouseout A
14 mouseleave A

때때로 요소들은 CSS를 사용하여 시각적으로 서로 겹칠 수 있다. 다음 예제에서는 A, B, C로 표시된 세 요소가 모두 웹 페이지에서 같은 크기와 절대 위치를 가진다. 요소 C는 B의 자식이고, B는 DOM에서 A의 자식이다:

서로 위에 모두 겹쳐진 세 요소의 그래픽 표현. 맨 아래 요소는 A로 표시되고 맨 위 요소는 C이다
그림 2 포인팅 장치가 스택 위로 이동하는, 서로 위에 모두 겹쳐진 세 요소의 그래픽 표현.

포인팅 장치가 요소 스택 밖에서 C로 표시된 요소로 이동한 뒤 다시 밖으로 이동할 때, 다음 일련의 이벤트가 발생해야 MUST 한다:

이벤트 유형 요소 참고
1 mousemove
포인팅 장치가 스택에서 가장 위에 있는 요소 C 안으로 이동한다
2 mouseover C
3 mouseenter A
4 mouseenter B
5 mouseenter C
6 mousemove C 여러 mousemove 이벤트
포인팅 장치가 요소 C 밖으로 이동한다...
7 mouseout C
8 mouseleave C
9 mouseleave B
10 mouseleave A
참고

mouseover/mouseout 이벤트는 한 번만 발생하는 반면, mouseenter/mouseleave 이벤트는 세 번 발생한다(각 요소마다 한 번).

다음은 포인팅 장치와 연결된 버튼(예: 마우스 버튼 또는 트랙패드)을 요소 위에서 누르고 놓을 때의 일반적인 이벤트 순서이다:

이벤트 유형 참고
1 mousedown
2 mousemove OPTIONAL, 여러 이벤트, 일부 제한
3 mouseup
4 click
5 mousemove OPTIONAL, 여러 이벤트, 일부 제한
6 mousedown
7 mousemove OPTIONAL, 여러 이벤트, 일부 제한
8 mouseup
9 click
10 dblclick
참고

mousedownmouseup 이벤트 사이에서, 여전히 click 또는 dblclick 이벤트를 발생시키면서 허용되는 지연 시간, 정도, 거리 및 mousemove 이벤트의 수는 구현, 장치 및 플랫폼에 따라 다르다. 이러한 허용 오차는 손 떨림과 같은 신체적 장애가 있는 사용자가 포인팅 장치와 상호작용할 때 도움을 줄 수 있다.

각 구현은 적절한 히스테리시스 허용 오차를 결정하지만, 일반적으로 관련 mousedownmouseup 이벤트의 이벤트 대상이 같고 중간에 mouseout 또는 mouseleave 이벤트가 끼어들지 않은 경우, clickdblclick 이벤트를 발생시키는 것이 좋으며 SHOULD, 관련 mousedownmouseup 이벤트 대상이 서로 다를 때는 가장 가까운 공통 포함 조상에서 clickdblclick 이벤트를 발생시키는 것이 좋다 SHOULD.

mousedown 이벤트가 HTML 문서의 body 요소를 대상으로 하고, 해당 mouseup 이벤트가 문서 요소를 대상으로 했다면, click 이벤트는 가장 가까운 공통 포함 조상이므로 문서 요소에 디스패치된다.

대상(예: 대상 요소)이 마우스 이벤트 순서 중에 DOM에서 제거되면, 그 순서의 나머지 이벤트는 해당 요소에서 발생해서는 MUST NOT 안 된다.

mousedown 이벤트의 결과로 대상 요소가 DOM에서 제거되면, 해당 요소에 대해서는 mouseup, click, 또는 dblclick에 대한 이벤트나 기본 활성화 이벤트가 디스패치되지 않는다. 그러나 mouseup 이벤트는 초기 대상 요소가 제거된 후 마우스에 노출되는 요소에서 여전히 디스패치된다. 마찬가지로, mouseup 이벤트의 디스패치 중에 대상 요소가 DOM에서 제거되면, click 및 그 이후의 이벤트는 디스패치되지 않는다.

4.4 마우스 이벤트 유형

Mouse 이벤트 유형은 아래에 나열되어 있다. 중첩된 요소의 경우, 마우스 이벤트 유형은 항상 가장 깊게 중첩된 요소를 대상으로 한다. 대상 요소의 조상은 그 자손 요소 내에서 발생하는 마우스 이벤트에 대한 알림을 얻기 위해 버블링을 사용할 수 MAY 있다.

4.4.1 auxclick

유형 auxclick
인터페이스 PointerEvent
동기 / 비동기 동기
버블링
신뢰된 대상 Element
취소 가능
합성됨
기본 동작 다양함
문맥
(신뢰된 이벤트)

사용자가 주가 아닌 포인터 버튼을 누르고 놓거나, 그러한 동작을 시뮬레이션하는 방식으로 포인터를 활성화할 때, auxclick 이벤트 유형은 포인터가 가리키는 최상위 이벤트 대상에 디스패치되어야 MUST 한다. 마우스 버튼의 작동 방식은 포인터 장치와 환경 구성에 따라 달라지며, 예를 들어 화면 위치나 포인팅 장치 버튼을 누른 뒤 놓기까지의 지연 시간에 따라 달라질 수 MAY 있다.

auxclick 이벤트는 주가 아닌 포인터 버튼에 대해서만 발생해야 한다(즉, button 값이 0이 아니고, buttons 값이 1보다 큰 경우). 주 버튼 (표준 마우스의 왼쪽 버튼과 같은 것)은 auxclick 이벤트를 발생시켜서는 MUST NOT 안 된다. 주 버튼과 연결된 대응 이벤트는 click을 참조하라.

auxclick 이벤트 앞에는 같은 요소에서 mousedownmouseup 이벤트가 올 수 MAY 있으며, 다른 노드 유형(예: 텍스트 노드) 사이의 변경은 무시한다. 환경 구성에 따라, 포인팅 장치 버튼을 누른 것과 놓은 것 사이에 mouseover, mousemove, 및 mouseout 이벤트 유형 중 하나 이상이 발생하더라도 auxclick 이벤트가 디스패치될 수 MAY 있다.

auxclick 이벤트 유형의 기본 동작은 이벤트의 대상button 또는 buttons 속성의 값에 따라 달라진다. auxclick 이벤트 유형의 일반적인 기본 동작은 다음과 같다:

  • 대상에 연결된 활성화 동작이 있으면, 기본 동작은 그 활성화 동작을 실행하는 것이어야 MUST 한다.
예제 6: 가운데 버튼에 대한 auxclick 수신 및 처리
myLink.addEventListener("auxclick", function(e) {
  if (e.button === 1) {
    // 이는 기본 동작을 방지한다. 예를 들어
    // 링크를 가운데 클릭했을 때 새 탭을 여는 동작이다.
    e.preventDefault();
    // 새 탭에서 링크 또는 링크가 아닌 버튼을 여는 처리를
    // 앱에 맞는 방식으로 수행하는 등, 가운데 버튼 클릭을 처리하기 위한
    // 다른 작업을 수행한다. 탭 스트립에서 탭을 닫는 것처럼 클릭 동작에서
    // 수행되어야 하는 다른 동작도 여기서 수행할 수 있다.
  }
});
참고

오른쪽 버튼의 경우, auxclick 이벤트는 모든 contextmenu 이벤트 이후에 디스패치된다. 일부 사용자 에이전트는 컨텍스트 메뉴가 표시되는 동안 모든 입력 이벤트를 삼킬 수 있으므로, 이러한 시나리오에서는 auxclick을 애플리케이션에서 사용할 수 없을 수도 있다는 점에 유의하라. 더 자세한 설명은 예제 7을 참조하라.

예제 7: 오른쪽 버튼에 대한 auxclick 수신 및 처리
myDiv.addEventListener("contextmenu", function(e) {
  // 이 호출은 컨텍스트 메뉴가 표시되지 않도록 보장하여
  // 페이지가 이벤트를 수신하는 것을 방해하지 않게 한다.
  e.preventDefault();
});
myDiv.addEventListener("auxclick", function(e) {
  if (e.button === 2) {
    // 앱 내부에서 사용자 정의 컨텍스트 메뉴를 여는 것처럼
    // 오른쪽 버튼 클릭을 처리하기 위한 다른 작업을 수행한다.
  }
});

4.4.2 click

유형 click
인터페이스 PointerEvent
동기 / 비동기 동기
버블링
신뢰된 대상 Element
취소 가능
합성됨
기본 동작 다양함
문맥
(신뢰된 이벤트)

사용자가 주 포인터 버튼을 누르고 놓거나, 그러한 동작을 시뮬레이션하는 방식으로 포인터를 활성화할 때, click 이벤트 유형은 포인터가 가리키는 최상위 이벤트 대상에 디스패치되어야 MUST 한다. 마우스 버튼의 작동 방식은 포인터 장치와 환경 구성에 따라 달라지며, 예를 들어 화면 위치나 포인팅 장치 버튼을 누른 뒤 놓기까지의 지연 시간에 따라 달라질 수 MAY 있다.

click 이벤트는 주 포인터 버튼에 대해서만 발생해야 한다(즉, button 값이 0이고, buttons 값이 1인 경우). 보조 버튼 (표준 마우스의 가운데 또는 오른쪽 버튼과 같은 것)은 click 이벤트를 발생시켜서는 MUST NOT 안 된다. 주가 아닌 버튼과 연결된 대응 이벤트는 auxclick을 참조하라.

click 이벤트 앞에는 같은 요소에서 mousedownmouseup 이벤트가 올 수 MAY 있으며, 다른 노드 유형(예: 텍스트 노드) 사이의 변경은 무시한다. 환경 구성에 따라, 포인팅 장치 버튼을 누른 것과 놓은 것 사이에 mouseover, mousemove, 및 mouseout 이벤트 유형 중 하나 이상이 발생하더라도 click 이벤트가 디스패치될 수 MAY 있다. 또한 click 이벤트 뒤에는 dblclick 이벤트가 올 수 MAY 있다.

사용자가 큰 line-height로 스타일이 지정된 <p> 요소의 텍스트 노드 자식에서 마우스를 누른 뒤, 마우스를 약간 움직여 더 이상 텍스트를 포함하는 영역 위에는 있지 않지만 여전히 그 <p> 요소의 포함 블록 안에 있도록 한 다음(즉, 포인터가 같은 텍스트 블록의 줄 사이에 있지만 텍스트 노드 자체 위에 있지는 않은 경우), 이후 마우스를 놓으면, 사용자가 같은 요소의 범위 안에 머물렀으므로 이는 ( click에 대한 일반적인 시간적 히스테리시스 안에 해당한다면) 여전히 click 이벤트를 트리거할 가능성이 크다. 사용자 에이전트가 생성한 마우스 이벤트는 텍스트 노드에 디스패치되지 않는다는 점에 유의하라.

포인터 장치와 연결되는 것 외에도, click 이벤트 유형은 요소 활성화의 일부로 디스패치되어야 MUST 한다.

참고

접근성을 최대화하기 위해, 콘텐츠 저자는 사용자 정의 컨트롤의 활성화 동작을 정의할 때 click 이벤트 유형을 사용하는 것이 권장된다. 이는 mousedown 또는 mouseup과 같은 다른 포인팅 장치 이벤트 유형보다 덜 장치별이기 때문이다. click 이벤트 유형은 포인터 장치(예: 마우스)에서 유래했지만, 이후 구현 개선으로 그 연결을 넘어 확장되었으며, 요소 활성화를 위한 장치 독립적 이벤트 유형으로 간주할 수 있다.

click 이벤트 유형의 기본 동작은 이벤트의 대상button 또는 buttons 속성의 값에 따라 달라진다. click 이벤트 유형의 일반적인 기본 동작은 다음과 같다:

  • 대상에 연결된 활성화 동작이 있으면, 기본 동작은 그 활성화 동작을 실행하는 것이어야 MUST 한다.
  • 대상이 포커스 가능하면, 기본 동작은 그 요소에 문서 포커스를 주는 것이어야 MUST 한다.

4.4.3 contextmenu

유형 contextmenu
인터페이스 PointerEvent
동기 / 비동기 동기
버블링
신뢰된 대상 Element
취소 가능
합성됨
기본 동작 지원되는 경우 컨텍스트 메뉴를 호출한다.
문맥
(신뢰된 이벤트)

사용자 에이전트는 컨텍스트 메뉴를 호출하기 전에 이 이벤트를 디스패치해야 MUST 한다.

contextmenu 이벤트가 오른쪽 마우스 버튼에 의해 트리거되는 경우, contextmenu 이벤트는 mousedown 이벤트 이후에 디스패치되어야 MUST 한다.

참고

플랫폼에 따라, contextmenu 이벤트는 mouseup 이벤트 전 또는 후에 디스패치될 수 있다.

4.4.4 dblclick

유형 dblclick
인터페이스 MouseEvent
동기 / 비동기 동기
버블링
신뢰된 대상 Element
취소 가능
합성됨
기본 동작 없음
문맥
(신뢰된 이벤트)

사용자 에이전트는 포인팅 장치의 주 버튼이 요소 위에서 두 번 클릭될 때 이 이벤트를 디스패치해야 MUST 한다. 더블 클릭의 정의는 환경 구성에 따라 달라지지만, mousedown, mouseup, 및 dblclick 사이에서 이벤트 대상은 같아야 MUST 한다. 클릭과 더블 클릭이 동시에 발생하면 이 이벤트 유형은 이벤트 유형 click 이후에 디스패치되어야 MUST 하며, 그렇지 않으면 이벤트 유형 mouseup 이후에 디스패치되어야 한다.

click 이벤트와 마찬가지로, dblclick 이벤트는 주 포인터 버튼에 대해서만 발생해야 한다. 보조 버튼은 dblclick 이벤트를 발생시켜서는 MUST NOT 안 된다.

참고

click 이벤트를 취소해도 dblclick 이벤트 발생에는 영향을 주지 않는다.

click 이벤트 유형과 마찬가지로, 기본 동작dblclick 이벤트 유형의 경우 이벤트의 대상button 또는 buttons 속성의 값에 따라 달라진다. dblclick 이벤트 유형의 일반적인 기본 동작click 이벤트 유형의 기본 동작과 일치한다.

4.4.5 mousedown

유형 mousedown
인터페이스 MouseEvent
동기 / 비동기 동기
버블링
신뢰된 대상 Element
취소 가능
합성됨
기본 동작 다양함: 드래그/드롭 작업 시작, 텍스트 선택 시작, 스크롤/팬 상호작용 시작 (지원되는 경우 가운데 마우스 버튼과 함께)
문맥
(신뢰된 이벤트)
포인팅 장치 버튼이 요소 위에서 눌렸을 때 사용자 에이전트는 이 이벤트를 디스패치해야 MUST 한다.
참고

많은 구현은 mousedown 이벤트를 사용하여 문맥에 따라 달라지는 다양한 기본 동작을 시작한다. 이러한 기본 동작은 이 이벤트가 취소되면 방지될 수 있다. 이러한 기본 동작의 일부 예로는 이미지나 링크와의 드래그/드롭 상호작용 시작, 텍스트 선택 시작 등이 있다. 또한 일부 구현은 mousedown 이벤트가 디스패치되는 시점에 가운데 마우스 버튼이 눌렸을 때 활성화되는 마우스 기반 팬 기능을 제공한다.

4.4.6 mouseenter

유형 mouseenter
인터페이스 MouseEvent
동기 / 비동기 동기
버블링 아니요
신뢰된 대상 Element
취소 가능 아니요
합성됨 아니요
기본 동작 없음
문맥
(신뢰된 이벤트)
포인팅 장치가 요소 또는 그 자손 요소 중 하나의 경계 위로 이동할 때, 사용자 에이전트는 이 이벤트를 디스패치해야 MUST 한다. 또한 요소나 그 자손 중 하나가 주 포인팅 장치 아래에 오도록 이동할 때도 사용자 에이전트는 이 이벤트를 디스패치해야 MUST 한다. 이 이벤트 유형은 mouseover와 비슷하지만, 버블링하지 않으며, 포인터 장치가 요소에서 그 자손 요소 중 하나의 경계 위로 이동할 때 디스패치되어서는 MUST NOT 안 된다는 점이 다르다.
참고

이 이벤트 유형과 CSS :hover 의사 클래스 [CSS2] 사이에는 유사점이 있다. mouseleave 이벤트 유형도 참조하라.

4.4.7 mouseleave

유형 mouseleave
인터페이스 MouseEvent
동기 / 비동기 동기
버블링 아니요
신뢰된 대상 Element
취소 가능 아니요
합성됨 아니요
기본 동작 없음
문맥
(신뢰된 이벤트)
포인팅 장치가 요소와 그 모든 자손 요소의 경계 밖으로 이동할 때, 사용자 에이전트는 이 이벤트를 디스패치해야 MUST 한다. 또한 요소나 그 자손 중 하나가 더 이상 주 포인팅 장치 아래에 있지 않도록 이동할 때도 이 이벤트를 디스패치해야 MUST 한다. 이 이벤트 유형은 mouseout과 비슷하지만, 버블링하지 않으며, 포인팅 장치가 요소의 경계와 그 모든 자식의 경계를 떠날 때까지 디스패치되어서는 MUST NOT 안 된다는 점이 다르다.
참고

이 이벤트 유형과 CSS :hover 의사 클래스 [CSS2] 사이에는 유사점이 있다. mouseenter 이벤트 유형도 참조하라.

4.4.8 mousemove

유형 mousemove
인터페이스 MouseEvent
동기 / 비동기 동기
버블링
신뢰된 대상 Element
취소 가능
합성됨
기본 동작 없음
문맥
(신뢰된 이벤트)
포인팅 장치가 요소 위에 있는 동안 이동할 때, 사용자 에이전트는 이 이벤트를 디스패치해야 MUST 한다. 포인팅 장치가 이동하는 동안의 이벤트 빈도는 구현, 장치 및 플랫폼에 따라 다르지만, 지속적인 포인터 장치 이동에 대해서는 마우스 이동의 각 인스턴스마다 단일 이벤트를 발생시키기보다는, 연속된 여러 mousemove 이벤트를 발생시키는 것이 좋다 SHOULD. 구현은 응답성과 성능의 균형을 맞추기 위해 최적의 빈도를 결정하는 것이 권장된다.
참고

브라우저와 같은 일부 구현 환경에서는, 사용자가 드래그 작업(예: 마우스 버튼이 눌림)을 시작했고 포인팅 장치가 사용자 에이전트의 경계를 벗어난 경우에도 mousemove 이벤트가 계속 발생할 수 있다.

참고

이 이벤트는 이전에는 DOM Level 2 Events에서 취소 불가능한 것으로 지정되었지만, 사용자 에이전트 간의 기존 상호운용성을 반영하도록 변경되었다.

4.4.9 mouseout

유형 mouseout
인터페이스 MouseEvent
동기 / 비동기 동기
버블링
신뢰된 대상 Element
취소 가능
합성됨
기본 동작 없음
문맥
(신뢰된 이벤트)
포인팅 장치가 요소의 경계 밖으로 이동하거나 요소가 더 이상 주 포인팅 장치 아래에 있지 않도록 이동할 때, 사용자 에이전트는 이 이벤트를 디스패치해야 MUST 한다. 이 이벤트 유형은 mouseleave와 비슷하지만, 버블링하며, 포인터 장치가 요소에서 그 자손 요소 중 하나의 경계 위로 이동할 때 디스패치되어야 MUST 한다는 점이 다르다.
참고

mouseover 이벤트 유형도 참조하라.

4.4.10 mouseover

유형 mouseover
인터페이스 MouseEvent
동기 / 비동기 동기
버블링
신뢰된 대상 Element
취소 가능
합성됨
기본 동작 없음
문맥
(신뢰된 이벤트)
포인팅 장치가 요소의 경계 위로 이동하거나 요소가 주 포인팅 장치 아래에 오도록 이동할 때, 사용자 에이전트는 이 이벤트를 디스패치해야 MUST 한다. 이 이벤트 유형은 mouseenter와 비슷하지만, 버블링하며, 포인터 장치가 동일한 이벤트 리스너 인스턴스에 대한 대상의 조상 요소를 가진 요소의 경계 위로 이동할 때 디스패치되어야 MUST 한다는 점이 다르다.
참고

mouseout 이벤트 유형도 참조하라.

4.4.11 mouseup

유형 mouseup
인터페이스 MouseEvent
동기 / 비동기 동기
버블링
신뢰된 대상 Element
취소 가능
합성됨
기본 동작 없음
문맥
(신뢰된 이벤트)
포인팅 장치 버튼이 요소 위에서 놓였을 때 사용자 에이전트는 이 이벤트를 디스패치해야 MUST 한다.
참고

브라우저와 같은 일부 구현 환경에서는, 예를 들어 사용자가 마우스 버튼을 누른 상태로 드래그 작업을 시작한 경우처럼 포인팅 장치가 사용자 에이전트의 경계를 벗어났더라도 mouseup 이벤트가 디스패치될 수 있다.

5. Pointer Events 및 인터페이스

5.1 PointerEvent 인터페이스

WebIDLdictionary PointerEventInit : MouseEventInit {
    long        pointerId = 0;
    double      width = 1;
    double      height = 1;
    float       pressure = 0;
    float       tangentialPressure = 0;
    long        tiltX;
    long        tiltY;
    long        twist = 0;
    double      altitudeAngle;
    double      azimuthAngle;
    DOMString   pointerType = "";
    boolean     isPrimary = false;
    long        persistentDeviceId = 0;
    sequence<PointerEvent> coalescedEvents = [];
    sequence<PointerEvent> predictedEvents = [];
};

[Exposed=Window]
interface PointerEvent : MouseEvent {
    constructor(DOMString type, optional PointerEventInit eventInitDict = {});
    readonly        attribute long        pointerId;
    readonly        attribute double      width;
    readonly        attribute double      height;
    readonly        attribute float       pressure;
    readonly        attribute float       tangentialPressure;
    readonly        attribute long        tiltX;
    readonly        attribute long        tiltY;
    readonly        attribute long        twist;
    readonly        attribute double      altitudeAngle;
    readonly        attribute double      azimuthAngle;
    readonly        attribute DOMString   pointerType;
    readonly        attribute boolean     isPrimary;
    readonly        attribute long        persistentDeviceId;
    [SecureContext] sequence<PointerEvent> getCoalescedEvents();
    sequence<PointerEvent> getPredictedEvents();
};
pointerId

이벤트를 일으킨 포인터의 고유 식별자이다. 사용자 에이전트는 기본 마우스 포인터에 대해 0 또는 1의 일반적인 pointerId 값을 예약할 수 MAY 있다. -1pointerId 값은 예약되어야 MUST 하며, 포인팅 장치가 아닌 것에 의해 생성된 이벤트를 나타내는 데 사용되어야 한다. 그 밖의 모든 포인터에 대해서는, 사용자 에이전트가 pointerId 값을 할당하는 방식에 대해 서로 다른 전략과 접근 방식을 자유롭게 구현할 수 있다. 그러나 [HTML]에 정의된 최상위 브라우징 컨텍스트 안의 모든 활성 포인터는 고유해야 하며, 식별자는 다른 어떤 최상위 브라우징 컨텍스트의 영향도 받아서는 MUST NOT 안 된다(즉, 한 최상위 브라우징 컨텍스트는 포인터가 브라우징 컨텍스트 밖으로 이동해 다른 최상위 브라우징 컨텍스트로 들어갈 때 그 포인터의 pointerId가 같을 것이라고 가정할 수 없다).

사용자 에이전트는 이전 활성 포인터에서 폐기된 pointerId 값을 재활용할 수 MAY 있거나, 특정 포인팅 장치에 대해 항상 같은 pointerId 를 재사용할 수 MAY 있다(예를 들어, 다중 사용자 협업 애플리케이션에서 특정 사용자의 특정 펜/스타일러스 입력을 고유하게 식별하기 위해). 그러나 후자의 경우, 서로 다른 페이지나 도메인 간의 핑거프린팅 및 추적 가능성을 최소화하기 위해, pointerId는 페이지/세션의 수명 동안에만 해당 특정 포인팅 장치와 명시적으로 연결되어야 MUST 하며, 다음에 해당 특정 포인팅 장치가 새 세션에서 다시 사용될 때는 새로운 무작위 pointerId가 선택되어야 MUST 한다.

참고

pointerId 선택 알고리즘은 구현별이다. 저자는 값이 다른 모든 활성 포인터와 고유한 포인터 식별자라는 것 외에 어떤 특정 의미를 전달한다고 가정할 수 없다. 예를 들어, 사용자 에이전트는 활성화되는 순서대로 활성 포인터에 0부터 시작하는 숫자를 단순히 할당할 수 있지만, 이러한 값이 단조 증가한다고 보장되지는 않는다. 특정 포인팅 장치에 대해 같은 pointerId를 재사용할지 여부는 개별 구현에 맡겨져 있으므로, 저자는 이에 의존하지 말고 대신 persistentDeviceId 를 참조하는 것이 강하게 권장된다.

width

포인터의 접촉 기하 구조의 너비(X축에서의 크기)이며, CSS 픽셀 단위이다([CSS21] 참조). 이 값은 주어진 포인터에 대해 각 이벤트마다 갱신될 수 MAY 있다. 일반적으로 접촉 기하 구조가 없는 입력(예: 전통적인 마우스) 및 입력의 실제 기하 구조가 하드웨어에 의해 감지되지 않는 경우, 사용자 에이전트는 기본값 1을 반환해야 MUST 한다.

height

포인터의 접촉 기하 구조의 높이(Y축에서의 크기)이며, CSS 픽셀 단위이다([CSS21] 참조). 이 값은 주어진 포인터에 대해 각 이벤트마다 갱신될 수 MAY 있다. 일반적으로 접촉 기하 구조가 없는 입력(예: 전통적인 마우스) 및 입력의 실제 기하 구조가 하드웨어에 의해 감지되지 않는 경우, 사용자 에이전트는 기본값 1을 반환해야 MUST 한다.

pressure

[0,1] 범위의 포인터 입력의 정규화된 압력이며, 여기서 01은 각각 하드웨어가 감지할 수 있는 최소 및 최대 압력을 나타낸다. 압력을 지원하지 않는 하드웨어 및 플랫폼의 경우, 활성 버튼 상태에서는 값이 0.5이어야 MUST 하며, 그렇지 않으면 0이어야 한다.

tangentialPressure

포인터 입력의 정규화된 접선 압력(배럴 압력이라고도 함)으로, 일반적으로 추가 컨트롤(예: 에어브러시 스타일러스의 핑거 휠)에 의해 설정되며 [-1,1] 범위이다. 여기서 0은 컨트롤의 중립 위치이다. 일부 하드웨어는 [0,1] 범위의 양수 값만 지원할 수 있음에 유의하라. 접선 압력을 지원하지 않는 하드웨어 및 플랫폼의 경우 값은 MUST 0이어야 한다.

참고
속성 이름에도 불구하고, 실제로 이 속성의 값을 생성하는 하드웨어 컨트롤/센서는 반드시 압력에 민감하지 않을 수 있다. 예를 들어, 대부분의 경우 에어브러시/페인팅 스타일러스 구현의 핑거 휠은 사용자가 휠에 지속적인 압력을 가해 0 위치로 돌아가지 않게 할 필요 없이 자유롭게 설정될 수 있다.
tiltX

Y-Z 평면과 트랜스듀서(예: 펜/스타일러스) 축 및 Y축을 모두 포함하는 평면 사이의 평면 각도(도 단위, [-90,90] 범위)이다. 양의 tiltX는 X 값이 증가하는 방향인 오른쪽을 의미한다. tiltXtiltY와 함께 사용되어 디지타이저에 대한 트랜스듀서의 법선으로부터의 기울기를 나타낼 수 있다. 기울기나 각도를 보고하지 않는 하드웨어 및 플랫폼의 경우 값은 MUST 0이어야 한다.

tiltX 설명 다이어그램
그림 3 양의 tiltX.
tiltY

X-Z 평면과 트랜스듀서(예: 펜/스타일러스) 축 및 X축을 모두 포함하는 평면 사이의 평면 각도(도 단위, [-90,90] 범위)이다. 양의 tiltY는 Y 값이 증가하는 방향인 사용자 쪽을 의미한다. tiltYtiltX와 함께 사용되어 디지타이저에 대한 트랜스듀서의 법선으로부터의 기울기를 나타낼 수 있다. 기울기나 각도를 보고하지 않는 하드웨어 및 플랫폼의 경우 값은 MUST 0이어야 한다.

tiltY 설명 다이어그램
그림 4 양의 tiltY.
twist

트랜스듀서(예: 펜/스타일러스)가 자신의 주축 주위로 시계 방향으로 회전한 값(도 단위, [0,359] 범위)이다. twist를 보고하지 않는 하드웨어 및 플랫폼의 경우 값은 MUST 0이어야 한다.

altitudeAngle

트랜스듀서(예: 펜/스타일러스)의 고도각(라디안 단위)이며, 범위는 [0,π/2]이다. 여기서 0은 표면(X-Y 평면)과 평행함을, π/2는 표면에 수직임을 의미한다. 기울기나 각도를 보고하지 않는 하드웨어 및 플랫폼의 경우 값은 MUST π/2이어야 한다.

참고
여기에서 정의된 altitudeAngle의 기본값은 π/2이며, 이는 트랜스듀서가 표면에 수직인 것으로 위치시킨다. 이는 Touch Events - Level 2 사양의 altitudeAngle 속성 정의와 다르며, 그 사양의 기본값은 0이다.
altitudeAngle 설명 다이어그램
그림 5 π/4(X-Y 평면에서 45도)의 altitudeAngle 예.
azimuthAngle

트랜스듀서(예: 펜/스타일러스)의 방위각(라디안 단위)이며, 범위는 [0, 2π]이다. 여기서 0은 캡이 X 값이 증가하는 방향을 가리키는 트랜스듀서(X-Y 평면을 바로 내려다보면 "3시" 방향)를 나타내며, 값은 시계 방향으로 진행할수록 점진적으로 증가한다(π/2는 "6시", π는 "9시", 3π/2는 "12시"). 트랜스듀서가 표면에 완전히 수직일 때 (altitudeAngleπ/2인 경우), 값은 MUST 0이어야 한다. 기울기나 각도를 보고하지 않는 하드웨어 및 플랫폼의 경우 값은 MUST 0이어야 한다.

azimuthAngle 설명 다이어그램
그림 6 π/6 ("4시")의 azimuthAngle 예.
pointerType

이벤트를 일으킨 장치 유형(mouse, pen, touch 등)을 나타낸다. 사용자 에이전트가 마우스, 펜/스타일러스 또는 터치 입력 장치에 대해 포인터 이벤트를 발생시켜야 한다면, pointerType의 값은 다음 표에 따라야 MUST 한다:

포인터 장치 유형 pointerType
마우스 mouse
펜 / 스타일러스 pen
터치 접촉 touch

사용자 에이전트가 장치 유형을 감지할 수 없으면, 값은 빈 문자열이어야 MUST 한다. 사용자 에이전트가 위에 나열된 것 이외의 포인터 장치 유형을 지원하는 경우, pointerType 값은 서로 다른 장치 유형의 이름 충돌을 피하기 위해 벤더 접두사를 붙이는 것이 좋다 SHOULD. 향후 사양은 다른 장치 유형에 대한 추가 규범 값을 제공할 수 MAY 있다.

참고
pointerType을 어떻게 사용할 수 있는지에 대한 기본 데모는 예제 2를 참조하라. 또한 개발자는 사용자 에이전트가 자체 사용자 정의 pointerType 값을 구현했을 수 있는 경우 및 pointerType이 단순히 빈 문자열인 상황을 포괄하기 위해 어떤 형태의 기본 처리를 포함해야 한다는 점에 유의하라.
isPrimary

포인터가 이 포인터 유형의 기본 포인터를 나타내는지 여부를 나타낸다.

persistentDeviceId

포인팅 장치의 고유 식별자이다. 하드웨어가 여러 포인터를 지원하는 경우, 포인팅 장치에서 생성된 포인터 이벤트는 해당 포인터가 세션 전체에서 고유하게 식별 가능한 경우에만 persistentDeviceId를 가져야 MUST 한다. 포인터가 고유하게 식별 가능하면, 해당 포인팅 장치에 할당된 persistentDeviceId는 세션의 나머지 기간 동안 일정하게 유지된다. 0persistentDeviceId 값은 예약되어야 MUST 하며, 생성 장치를 식별할 수 없는 이벤트를 나타내는 데 사용되어야 한다. pointerId와 마찬가지로, 서로 다른 페이지나 도메인 간의 핑거프린팅 및 추적 가능성을 최소화하기 위해, persistentDeviceId는 페이지/세션의 수명 동안에만 해당 특정 포인팅 장치와 명시적으로 연결되어야 MUST 하며, 다음에 해당 특정 포인팅 장치가 새 세션에서 다시 사용될 때는 새로운 무작위 persistentDeviceId가 선택되어야 MUST 한다.

참고
디지타이저 및 포인팅 장치 하드웨어 제약으로 인해, persistentDeviceId가 포인팅 장치의 모든 포인터 이벤트에서 사용 가능하다고 보장되지는 않는다. 예를 들어, 장치가 pointerdownpersistentDeviceId가 포함될 만큼 제때 자신의 하드웨어 ID를 디지타이저에 보고하지 않을 수 있다. 이러한 경우 persistentDeviceId는 처음에는 0이었다가 유효한 값으로 변경될 수 있다.
getCoalescedEvents()

병합된 이벤트의 목록을 반환하는 메서드이다.

getPredictedEvents()

예측된 이벤트의 목록을 반환하는 메서드이다.

PointerEventInit 딕셔너리는 신뢰되지 않은(합성) 포인터 이벤트를 구성하기 위한 메커니즘을 제공하기 위해 PointerEvent 인터페이스의 생성자에서 사용된다. 이는 [UIEVENTS]에 정의된 MouseEventInit 딕셔너리에서 상속한다. 신뢰되지 않은 포인터 이벤트를 발생시키는 방법을 보여 주는 샘플 코드는 예제를 참조하라.

PointerEvent이벤트 구성 단계PointerEventInitcoalescedEvents병합된 이벤트 목록으로 복제하고, PointerEventInitpredictedEvents예측된 이벤트 목록으로 복제한다.

참고
PointerEvent 인터페이스는 UI Events에 정의된 MouseEvent에서 상속한다. 또한 다양한 좌표 속성을 long에서 double로 변경하여 소수 좌표를 허용하는 CSSOM View Module의 제안된 확장도 유의하라. 이 제안된 확장을 PointerEvent에 대해서는 이미 구현했지만 일반 MouseEvent에 대해서는 구현하지 않은 사용자 에이전트의 경우, click, auxclick, 및 contextmenu 이벤트와 관련해 추가 요구사항이 있다.

5.1.1 버튼 상태

5.1.1.1 코드형 버튼 상호작용

마우스나 펜과 같은 일부 포인터 장치는 여러 버튼을 지원한다. [UIEVENTS] Mouse Event 모델에서는, 각 버튼 누름이 mousedownmouseup 이벤트를 생성한다. 이러한 하드웨어 차이를 더 잘 추상화하고 교차 장치 입력 작성을 단순화하기 위해, Pointer Events는 코드형 버튼 누름(포인터 장치의 다른 버튼이 이미 눌려 있는 동안 추가 버튼을 누르는 것)에 대해 겹치는 pointerdownpointerup 이벤트를 발생시키지 않는다.

대신, 코드형 버튼 누름은 buttonbuttons 속성의 변화를 검사하여 감지할 수 있다. buttonbuttons 속성은 MouseEvent 인터페이스에서 상속되지만, 다음 절에서 설명하는 것처럼 의미와 값이 변경된다.

buttonbuttons 속성에 대한 수정은 포인터 이벤트에만 적용된다. 그러나 click, auxclickcontextmenu의 경우 buttonbuttons의 값은 호환성 마우스 이벤트의 경우와 마찬가지로 [UIEVENTS]를 따라야 MUST 한다 .

5.1.1.2 button 속성

모든 포인터 이벤트에서(단지 pointerdownpointerup만이 아니라) 버튼 상태 전환을 식별하기 위해, button 속성은 상태 변경으로 인해 이벤트가 발생한 장치 버튼을 나타낸다.

장치 버튼 변경 button
이전 이벤트 이후 버튼도 터치/펜 접촉도 변경되지 않음 -1
왼쪽 마우스,
터치 접촉,
펜 접촉
0
가운데 마우스 1
오른쪽 마우스,
펜 배럴 버튼
2
X1(뒤로) 마우스 3
X2(앞으로) 마우스 4
펜 지우개 버튼 5
참고
마우스 드래그 중에는 pointermove 이벤트의 button 속성 값이 mousemove 이벤트의 값과 다르다. 예를 들어, 오른쪽 버튼을 누른 상태로 마우스를 이동하는 동안, pointermove 이벤트는 button 값 -1을 가지지만, mousemove 이벤트는 button 값 2를 가진다.
5.1.1.3 buttons 속성

buttons 속성은 장치 버튼의 현재 상태를 비트마스크로 제공한다 (MouseEvent와 같지만, 가능한 값의 집합이 확장되어 있다).

장치 버튼의 현재 상태 buttons
버튼이 눌리지 않은 상태로 마우스가 이동함,
버튼이 눌리지 않은 호버 상태에서 펜이 이동함
0
왼쪽 마우스,
터치 접촉,
펜 접촉
1
가운데 마우스 4
오른쪽 마우스,
펜 배럴 버튼
2
X1(뒤로) 마우스 8
X2(앞으로) 마우스 16
펜 지우개 버튼 32

5.1.2 기본 포인터

다중 포인터(예: 멀티터치) 시나리오에서는, isPrimary 속성이 각 포인터 유형별 활성 포인터 집합에서 마스터 포인터를 식별하는 데 사용된다.

  • 어떤 주어진 시점에도, 각 포인터 유형마다 기본 포인터는 최대 하나만 존재할 수 있다.
  • 특정 포인터 유형에서 처음 활성화된 포인터(예: 멀티터치 상호작용에서 화면을 처음 터치한 손가락)가 해당 포인터 유형의 기본 포인터가 된다.
  • 기본 포인터만 호환성 마우스 이벤트를 생성한다. 여러 기본 포인터가 있는 경우, 이러한 포인터는 모두 호환성 마우스 이벤트를 생성한다.
참고
단일 포인터 상호작용을 원하는 저자는 기본이 아닌 포인터를 무시함으로써 이를 달성할 수 있다 (그러나 아래의 여러 기본 포인터에 관한 참고를 참조하라).
참고
두 개 이상의 포인터 장치 유형이 동시에 사용되는 경우, 여러 포인터 (각 pointerType마다 하나씩)가 기본으로 간주된다. 예를 들어, 터치 접촉과 마우스 커서가 동시에 이동하면 둘 다 기본으로 간주되는 포인터를 생성한다.
참고
일부 장치, 운영 체제 및 사용자 에이전트는 우발적인 상호작용을 피하기 위해 둘 이상의 포인터 입력 유형이 동시에 사용되는 것을 무시할 수 있다. 예를 들어, 터치와 펜 상호작용을 모두 지원하는 장치는 사용자가 펜을 사용하는 동안 손을 터치스크린에 얹을 수 있도록, 펜이 활발히 사용되는 동안 터치 입력을 무시할 수 있다(일반적으로 "palm rejection"이라고 하는 기능). 현재 저자가 이 동작을 억제하는 것은 불가능하다.
참고
경우에 따라 사용자 에이전트는 어떤 포인터도 기본 포인터로 표시되지 않은 포인터 이벤트를 발생시킬 수 있다. 예를 들어, 멀티터치 상호작용처럼 특정 유형의 활성 포인터가 여러 개 있고, 기본 포인터가 제거된 경우(예: 화면을 떠나는 경우), 결과적으로 기본 포인터가 없을 수 있다. 또한 장치의 동일한 유형의 모든 활성 포인터(사용자 에이전트가 아닌 애플리케이션을 대상으로 하는 포인터 포함)를 사용해 기본 포인터가 결정되는 플랫폼에서, 첫 번째(기본) 포인터가 사용자 에이전트 밖에 있고 다른(비기본) 포인터들이 사용자 에이전트 안을 대상으로 하는 경우, 사용자 에이전트는 다른 포인터에 대해 isPrimary 값이 false인 포인터 이벤트를 발생시킬 수 MAY 있다.
참고
현재 운영 체제와 사용자 에이전트는 일반적으로 여러 마우스 입력이라는 개념을 갖고 있지 않다. 하나보다 많은 마우스 장치가 존재하는 경우(예: 트랙패드와 외부 마우스가 모두 있는 노트북), 모든 마우스 장치는 일반적으로 하나의 장치로 취급된다 — 어떤 장치에서의 움직임도 단일 마우스 포인터의 움직임으로 변환되며, 서로 다른 마우스 장치의 버튼 누름 사이에는 구분이 없다. 이러한 이유로, 보통 마우스 포인터는 하나만 존재하며 그 포인터가 기본이 된다.

5.1.3 PointerEvent 인터페이스를 사용하여 이벤트 발생시키기

e라는 포인터 이벤트를 발생시킨다는 것은, e라는 이벤트를 발생시키되, PointerEvent 인터페이스 및 속성과 기본 동작에 정의된 대로 속성이 설정된 PointerEvent를 사용하여 발생시키는 것을 의미한다.

이벤트가 gotpointercapture, lostpointercapture, click, auxclick 또는 contextmenu 이벤트가 아니면, 이 PointerEvent에 대해 보류 중인 포인터 캡처 처리 단계를 실행한다.

이벤트가 발생되는 대상 결정은 다음과 같이 한다:

targetDocument를 target의 노드 문서 [DOM]로 둔다.

이벤트가 pointerdown, pointermove, 또는 pointerup이면, 이벤트의 활성 문서를 해당 pointerId에 대해 targetDocument로 설정한다.

이벤트가 pointerdown이고, 관련 장치가 직접 조작 장치이며, 대상이 Element이면, 암시적 포인터 캡처에 설명된 대로 이 pointerId에 대한 포인터 캡처 설정을 대상 요소로 수행한다.

이 이벤트를 발생시키기 전에, 사용자 에이전트이벤트 순서 보장 [UIEVENTS]을 위해 포인팅 장치가 previousTarget에서 대상으로 이동한 것처럼 대상을 처리하는 것이 좋다 SHOULD. needsOverEvent 플래그가 설정되어 있으면, 대상 요소가 같더라도 pointerover 이벤트가 필요하다.

결정된 대상에 이벤트를 발생시킨다.

결정된 대상을 주어진 포인터의 previousTarget으로 저장하고, needsOverEvent 플래그를 false로 재설정한다. 어느 시점에서든 previousTarget이 더 이상 연결됨 [DOM] 상태가 아니게 되면, previousTarget으로 이벤트를 디스패치할 때의 이벤트 경로를 따라 가장 가까운 아직 연결됨 [DOM] 상태인 부모로 previousTarget을 갱신하고, needsOverEvent 플래그를 true로 설정한다.

참고
일반 히트 테스트 결과 대신 포인터 캡처 대상 재정의를 대상으로 사용하면 [UIEVENTS]에 정의된 일부 경계 이벤트가 발생할 수 있다. 이는 포인터가 이전 대상을 떠나 이 새로운 캡처 대상에 들어가는 것과 같다. 캡처가 해제될 때도 포인터가 캡처 대상에서 나가 히트 테스트 대상으로 들어가므로 같은 시나리오가 발생할 수 있다.
5.1.3.1 속성 및 기본 동작

이 사양에 정의된 이벤트 유형에 대한 bubblescancelable 속성과 기본 동작은 다음 표에 나타난다. 이러한 각 이벤트 유형의 세부 사항은 Pointer Event 유형에서 제공된다.

이벤트 유형 버블링 취소 가능 기본 동작
pointerover 없음
pointerenter 아니요 아니요 없음
pointerdown 다양함: 포인터가 기본일 때, mousedown 이벤트의 모든 기본 동작
이 이벤트를 취소하면 이후의 호환성 마우스 이벤트 발생도 방지된다.
pointermove 다양함: 포인터가 기본일 때, mousemove의 모든 기본 동작
pointerrawupdate 아니요 없음
pointerup 다양함: 포인터가 기본일 때, mouseup의 모든 기본 동작
pointercancel 아니요 없음
pointerout 없음
pointerleave 아니요 아니요 없음
gotpointercapture 아니요 없음
lostpointercapture 아니요 없음

뷰포트 조작(팬 및 줌) — 일반적으로 직접 조작 상호작용의 결과 — 은 의도적으로 포인터 이벤트의 기본 동작이 아니다. 즉 이러한 동작(예: 터치스크린에서 손가락을 움직인 결과로 페이지를 팬하는 것)은 포인터 이벤트를 취소하여 억제할 수 없다. 대신 저자는 touch-action을 사용하여 문서의 한 영역에 대한 직접 조작 동작을 명시적으로 선언해야 한다. 이벤트 취소에 대한 이 의존성을 제거하면 사용자 에이전트의 성능 최적화가 쉬워진다.

pointerenterpointerleave 이벤트의 경우, composed [DOM] 속성은 false인 것이 좋다 SHOULD; 위 표의 다른 모든 포인터 이벤트의 경우, 그 속성은 true인 것이 좋다 SHOULD.

위 표의 모든 포인터 이벤트에 대해, detail [UIEVENTS] 속성은 0인 것이 좋다 SHOULD.

참고
많은 사용자 에이전트는 레거시 콘텐츠를 지원하기 위해 MouseEvents에 비표준 속성인 fromElementtoElement를 노출한다. 우리는 이러한 사용자 에이전트가 PointerEvents에서 이러한 (상속된) 속성 값을 null로 설정하여 저자가 표준화된 대체 속성 (targetrelatedTarget)을 사용하도록 전환하기를 권장한다.

MouseEventrelatedTarget와 마찬가지로, relatedTarget은 포인터가 방금 떠난 경계를 가진 요소(pointerover 또는 pointerenter 이벤트의 경우), 또는 포인터가 들어가고 있는 경계를 가진 요소 (pointerout 또는 pointerleave 이벤트의 경우)로 초기화되어야 한다. 다른 포인터 이벤트의 경우, 이 값은 기본적으로 null이 된다. 요소가 포인터 캡처를 받으면 해당 포인터에 대한 이후 모든 이벤트는 캡처 요소의 경계 안에 있는 것으로 간주된다는 점에 유의하라.

gotpointercapturelostpointercapture 이벤트의 경우, 위 표에 정의된 속성을 제외한 모든 속성은 사용자 에이전트가 보류 중인 포인터 캡처 처리 단계를 실행하고 gotpointercapturelostpointercapture 이벤트를 발생시키게 한 Pointer Event와 같아야 한다.

5.1.3.2 보류 중인 포인터 캡처 처리

사용자 에이전트포인터 캡처를 암시적으로 해제할 때뿐 아니라 gotpointercapture 또는 lostpointercapture가 아닌 Pointer Events를 발생시킬 때, 다음 단계를 실행해야 MUST 한다.

  1. 이 포인터의 포인터 캡처 대상 재정의가 설정되어 있고 보류 중인 포인터 캡처 대상 재정의와 같지 않으면, 포인터 캡처 대상 재정의 노드에서 lostpointercapture라는 이름의 포인터 이벤트를 발생시킨다.
  2. 이 포인터의 보류 중인 포인터 캡처 대상 재정의가 설정되어 있고 포인터 캡처 대상 재정의와 같지 않으면, 보류 중인 포인터 캡처 대상 재정의에서 gotpointercapture라는 이름의 포인터 이벤트를 발생시킨다.
  3. 포인터 캡처 대상 재정의보류 중인 포인터 캡처 대상 재정의로 설정한다(설정되어 있는 경우). 그렇지 않으면 포인터 캡처 대상 재정의를 지운다.
참고

click, auxclick, 및 contextmenu 이벤트에 대한 절에 정의된 것처럼, lostpointercapture 이벤트가 디스패치된 후에도, 대응하는 click, auxclick 또는 contextmenu 이벤트가 있으면 여전히 캡처 대상으로 디스패치된다.

5.1.3.3 포인터 이벤트 스트림 억제

사용자 에이전트는 웹 페이지가 특정 pointerId를 가진 포인터 이벤트를 계속 수신할 가능성이 낮다는 것을 감지하면 포인터 이벤트 스트림을 억제해야 MUST 한다. 다음 시나리오 중 하나가 이 조건을 만족한다(추가 시나리오가 있을 수 MAY 있다):

  • 사용자 에이전트가 모달 대화상자 또는 메뉴를 열었다.
  • 포인터 입력 장치가 물리적으로 분리되었거나, 호버 가능한 포인터 입력 장치(예: 호버 가능한 펜/스타일러스)가 디지타이저가 감지할 수 있는 호버 범위를 벗어났다.
  • 포인터가 이후 사용자 에이전트에 의해 페이지 뷰포트를 조작하는 데 사용된다(예: 팬 또는 줌). 자세한 내용은 touch-action CSS 속성에 관한 절을 참조하라.
    참고
    사용자 에이전트는 여러 포인터 유형(예: 터치 및 펜)을 통해 팬 또는 줌을 트리거할 수 있으므로, 팬 또는 줌 동작의 시작은 서로 다른 포인터 유형을 가진 포인터를 포함하여 다양한 포인터의 억제로 이어질 수 있다.
  • 드래그 앤 드롭 처리 모델 [HTML]에 정의된 드래그 작업 시작 알고리즘의 일부로, 드래그 작업을 일으킨 포인터에 대해.
참고

사용자 에이전트포인터 이벤트 스트림을 억제할 수 MAY 있는 다른 시나리오는 다음을 포함한다:

  • 포인터가 활성 상태인 동안 장치의 화면 방향이 변경된다.
  • 사용자가 장치가 지원하는 것보다 더 많은 동시 포인터 입력을 사용하여 상호작용하려고 한다.
  • 사용자 에이전트가 입력을 우발적인 것으로 해석한다(예: 하드웨어가 palm rejection을 지원함).

이러한 시나리오를 감지하는 방법은 이 사양의 범위 밖이다.

사용자 에이전트포인터 이벤트 스트림을 억제하기 위해 다음 단계를 실행해야 MUST 한다:

5.1.4 레이아웃 변경으로 인한 경계 이벤트

화면 표면을 기준으로 이동했거나 어떤 속성에 변화가 생긴 포인팅 장치는 Pointer Event 유형에 정의된 대로 다양한 이벤트를 발생시킨다. 정지한 포인팅 장치(화면 표면을 기준으로 이동하지도 않았고 어떤 속성에도 변화가 없었던 장치)의 경우, 포인터의 히트 테스트 대상에 영향을 준 레이아웃 변경 이후, 사용자 에이전트는 특정 경계 이벤트를 발생시켜야 MUST 한다. 자세한 내용은 pointerover, pointerenter, pointeroutpointerleave를 참조하라. 사용자 에이전트는 성능상의 이유로(예: 경계 이벤트 리스너로 인해 너무 많은 히트 테스트나 레이아웃 변경이 발생하는 것을 피하기 위해) 이러한 경계 이벤트의 발생을 지연할 수 MAY 있다.

참고
정지한 포인팅 장치(화면 표면을 기준으로 이동하지도 않았고 어떤 속성에도 변화가 없었던 장치)는 결코 pointermove 이벤트를 발생시키지 않는다.

5.1.5 tiltX / tiltYaltitudeAngle / azimuthAngle 사이의 변환

Pointer Events는 X-Y 평면을 기준으로 한 트랜스듀서의 방향을 표현하기 위해 서로 보완적인 두 속성 집합을 포함한다: tiltX / tiltY(원래 Pointer Events 사양에서 도입됨) 및 azimuthAngle / altitudeAngle (Touch Events - Level 2 사양에서 채택됨).

특정 하드웨어 및 플랫폼에 따라, 사용자 에이전트는 화면 평면을 기준으로 한 트랜스듀서 방향에 대해 하나의 값 집합만 수신할 가능성이 높다 — tiltX / tiltY 또는 altitudeAngle / azimuthAngle. 사용자 에이전트는 이러한 값을 변환하기 위해 다음 알고리즘을 사용해야 MUST 한다.

사용자 에이전트가 azimuthAngle / altitudeAngle에서 tiltX / tiltY를 계산할 때, 최종 정수 값은 Math.round [ECMASCRIPT] 규칙을 사용하여 반올림하는 것이 좋다 SHOULD.

예제 8: tiltX/tiltY와 altitudeAngle/azimuthAngle 사이의 변환
/* tiltX/tiltY와 altitudeAngle/azimuthAngle 사이의 변환 */

function spherical2tilt(altitudeAngle, azimuthAngle) {
  const radToDeg = 180/Math.PI;

  let tiltXrad = 0;
  let tiltYrad = 0;

  if (altitudeAngle == 0) {
    // 펜이 X-Y 평면에 있다
    if (azimuthAngle == 0 || azimuthAngle == 2*Math.PI) {
      // 펜이 양의 X축 위에 있다
      tiltXrad = Math.PI/2;
    }
    if (azimuthAngle == Math.PI/2) {
      // 펜이 양의 Y축 위에 있다
      tiltYrad = Math.PI/2;
    }
    if (azimuthAngle == Math.PI) {
      // 펜이 음의 X축 위에 있다
      tiltXrad = -Math.PI/2;
    }
    if (azimuthAngle == 3*Math.PI/2) {
      // 펜이 음의 Y축 위에 있다
      tiltYrad = -Math.PI/2;
    }
    if (azimuthAngle>0 && azimuthAngle<Math.PI/2) {
      tiltXrad = Math.PI/2;
      tiltYrad = Math.PI/2;
    }
    if (azimuthAngle>Math.PI/2 && azimuthAngle<Math.PI) {
      tiltXrad = -Math.PI/2;
      tiltYrad = Math.PI/2;
    }
    if (azimuthAngle>Math.PI && azimuthAngle<3*Math.PI/2) {
      tiltXrad = -Math.PI/2;
      tiltYrad = -Math.PI/2;
    }
    if (azimuthAngle>3*Math.PI/2 && azimuthAngle<2*Math.PI) {
      tiltXrad = Math.PI/2;
      tiltYrad = -Math.PI/2;
    }
  }

  if (altitudeAngle != 0) {
    const tanAlt = Math.tan(altitudeAngle);

    tiltXrad = Math.atan(Math.cos(azimuthAngle) / tanAlt);
    tiltYrad = Math.atan(Math.sin(azimuthAngle) / tanAlt);
  }

  return {"tiltX":tiltXrad*radToDeg, "tiltY":tiltYrad*radToDeg};
}

function tilt2spherical(tiltX, tiltY) {
  const tiltXrad = tiltX * Math.PI/180;
  const tiltYrad = tiltY * Math.PI/180;

  // azimuth angle 계산
  let azimuthAngle = 0;

  if (tiltX == 0) {
    if (tiltY > 0) {
      azimuthAngle = Math.PI/2;
    }
    else if (tiltY < 0) {
      azimuthAngle = 3*Math.PI/2;
    }
  } else if (tiltY == 0) {
    if (tiltX < 0) {
      azimuthAngle = Math.PI;
    }
  } else if (Math.abs(tiltX) == 90 || Math.abs(tiltY) == 90) {
    // azimuth를 계산하기에 정보가 충분하지 않다
    azimuthAngle = 0;
  } else {
    // 비경계 사례: tiltX와 tiltY 모두 0 또는 +-90이 아님
    const tanX = Math.tan(tiltXrad);
    const tanY = Math.tan(tiltYrad);

    azimuthAngle = Math.atan2(tanY, tanX);
    if (azimuthAngle < 0) {
      azimuthAngle += 2*Math.PI;
    }
  }

  // altitude angle 계산
  let altitudeAngle = 0;

  if (Math.abs(tiltX) == 90 || Math.abs(tiltY) == 90) {
      altitudeAngle = 0
  } else if (tiltX == 0) {
    altitudeAngle = Math.PI/2 - Math.abs(tiltYrad);
  } else if (tiltY == 0) {
    altitudeAngle = Math.PI/2 - Math.abs(tiltXrad);
  } else {
    // 비경계 사례: tiltX와 tiltY 모두 0 또는 +-90이 아님
    altitudeAngle =  Math.atan(1.0/Math.sqrt(Math.pow(Math.tan(tiltXrad),2) + Math.pow(Math.tan(tiltYrad),2)));
  }

  return {"altitudeAngle":altitudeAngle, "azimuthAngle":azimuthAngle};
}

5.2 PointerEvent 알고리즘

5.2.1 PointerEvent 초기화

event, eventTypeeventTarget, bubbles, 그리고 cancelablePointerEvent를 초기화하려면, 다음 단계를 실행한다:

  1. event, eventTypeeventTarget, bubblescancelableMouseEvent 초기화를 수행한다
  2. 다른 모든 속성을 기본 PointerEvent 값으로 초기화한다.

5.2.2 PointerEvent 생성

eventTypeeventTarget, bubbles, 그리고 cancelable PointerEvent를 생성하려면, 다음 단계를 실행한다:

  1. eventPointerEvent를 사용하여 이벤트를 생성한 결과로 둔다
  2. event, eventTypeeventTarget, bubblescancelablePointerEvent 초기화를 수행한다
  3. event를 반환한다

5.2.3 MouseEvent에서 PointerEvent 생성

  1. eventType을 이벤트 유형을 포함하는 DOMString으로 둔다
  2. mouseevent를 대응하는 MouseEvent로 둔다
  3. eventPointerEvent를 사용하여 이벤트를 생성한 결과로 둔다
  4. targetmouseevent.target으로 둔다
  5. event, eventTypetargetPointerEvent 초기화를 수행한다
  6. mouseeventMouseEvent 속성을 event로 복사한다
  7. event를 반환한다

5.2.4 pointerout 이벤트 전송 여부 결정

  1. mouseout을 대응하는 mouseout MouseEvent로 둔다
  2. pointerout을 "pointerout" 및 mouseoutMouseEvent에서 PointerEvent 생성을 수행한 결과로 둔다
  3. pointerevent 속성을 설정한다
    편집자 참고

    TODO.

  4. targetmouseout.target으로 둔다
  5. targetpointerout디스패치한다

5.2.5 pointerleave 이벤트 전송 여부 결정

  1. mouseout을 대응하는 mouseout MouseEvent로 둔다
  2. pointerout을 "pointerout" 및 mouseoutMouseEvent에서 PointerEvent 생성을 수행한 결과로 둔다
  3. pointerevent 속성을 설정한다
    편집자 참고

    TODO.

  4. targetmouseout.target으로 둔다
  5. targetpointerout디스패치한다

5.2.6 pointerover 이벤트 전송 여부 결정

  1. mouseout을 대응하는 mouseout MouseEvent로 둔다
  2. pointerout을 "pointerout" 및 mouseoutMouseEvent에서 PointerEvent 생성을 수행한 결과로 둔다
  3. pointerevent 속성을 설정한다
    편집자 참고

    TODO.

  4. targetmouseout.target으로 둔다
  5. targetpointerout디스패치한다

5.2.7 pointerenter 이벤트 전송 여부 결정

  1. mouseout을 대응하는 mouseout MouseEvent로 둔다
  2. pointerout을 "pointerout" 및 mouseoutMouseEvent에서 PointerEvent 생성을 수행한 결과로 둔다
  3. pointerevent 속성을 설정한다
    편집자 참고

    TODO.

  4. targetmouseout.target으로 둔다
  5. targetpointerout디스패치한다

5.2.8 pointermove 이벤트 전송 여부 결정

  1. mouseout을 대응하는 mouseout MouseEvent로 둔다
    편집자 참고

    이것이 pointermove와 pointerrawupdate를 전송할 수 있는가? 아니면 두 개의 메서드가 필요한가?

    편집자 참고

    pointermove 이벤트가 병합되는 방식을 제대로 정의하려면 무엇이 필요한가?

  2. pointerout을 "pointerout" 및 mouseoutMouseEvent에서 PointerEvent 생성을 수행한 결과로 둔다
  3. pointerevent 속성을 설정한다
    편집자 참고

    TODO.

  4. targetmouseout.target으로 둔다
  5. targetpointerout디스패치한다

5.2.9 pointerdown 이벤트 전송 여부 결정

  1. mouseout을 대응하는 mouseout MouseEvent로 둔다
    참고

    mousedown 이벤트와 달리, 여러 버튼이 눌렸을 때 pointerdown 이벤트는 중첩되지 않는다. 필드를 PointerEvent로 복사할 수 있도록 MouseEvent가 전달된다.

  2. pointerout을 "pointerout" 및 mouseoutMouseEvent에서 PointerEvent 생성을 수행한 결과로 둔다
  3. pointerevent 속성을 설정한다
    편집자 참고

    TODO.

  4. targetmouseout.target으로 둔다
  5. targetpointerout디스패치한다

5.2.10 pointerrawupdate 이벤트 전송 여부 결정

  1. mouseout을 대응하는 mouseout MouseEvent로 둔다
  2. targetmouseout.target으로 둔다
  3. targetpointerout디스패치한다

5.2.11 pointerup 이벤트 전송 여부 결정

  1. mouseout을 대응하는 mouseout MouseEvent로 둔다
    참고

    mouseup 이벤트와 달리, 여러 버튼이 눌렸을 때 pointerup 이벤트는 중첩되지 않는다. 필드를 PointerEvent로 복사할 수 있도록 MouseEvent가 전달된다.

  2. pointerout을 "pointerout" 및 mouseoutMouseEvent에서 PointerEvent 생성을 수행한 결과로 둔다
  3. pointerevent 속성을 설정한다
    편집자 참고

    TODO.

  4. targetmouseout.target으로 둔다
  5. targetpointerout디스패치한다

5.3 Pointer Event 유형

아래는 이 사양에 정의된 이벤트 유형이다.

기본 포인터의 경우, 이러한 이벤트는(gotpointercapturelostpointercapture 제외) 호환성 마우스 이벤트도 발생시킬 수 있다.

5.3.1 pointerover 이벤트

사용자 에이전트는 다음 중 하나가 발생할 때 포인터 이벤트를 발생시키되, pointerover라는 이름으로 발생시켜야 MUST 한다:

5.3.2 pointerenter 이벤트

사용자 에이전트는 다음 중 하나가 발생할 때 포인터 이벤트를 발생시키되, pointerenter라는 이름으로 발생시켜야 MUST 한다:

참고
이 이벤트 유형은 pointerover와 비슷하지만 두 가지 차이가 있다: pointerenter는 버블링하지 않으며, 그 디스패치는 자손 요소의 히트 테스트 경계까지 고려한다.
참고
이 이벤트 유형, [UIEVENTS]에 설명된 mouseenter 이벤트, 그리고 [CSS21]에 설명된 CSS :hover 의사 클래스 사이에는 유사점이 있다. pointerleave 이벤트도 참조하라.

5.3.3 pointerdown 이벤트

사용자 에이전트는 포인터가 활성 버튼 상태에 들어갈 때 포인터 이벤트를 발생시키되, pointerdown이라는 이름으로 발생시켜야 MUST 한다. 마우스의 경우, 이는 장치가 버튼이 눌리지 않은 상태에서 하나 이상의 버튼이 눌린 상태로 전환될 때이다. 터치의 경우, 이는 디지타이저와 물리적 접촉이 이루어질 때이다. 펜의 경우, 이는 펜이 어떤 버튼도 눌리지 않은 상태에서 디지타이저와 물리적으로 접촉하거나, 호버 중에 버튼이 눌리지 않은 상태에서 하나 이상의 버튼이 눌린 상태로 전환될 때이다.

참고
마우스(또는 다른 다중 버튼 포인터 장치)의 경우, 이는 pointerdownpointerupmousedownmouseup과 같은 모든 상황에서 발생하지 않는다는 것을 의미한다. 자세한 내용은 코드형 버튼을 참조하라.

호버를 지원하지 않는 입력 장치의 경우, 사용자 에이전트pointerdown 이벤트를 디스패치하기 전에 포인터 이벤트를 발생시키되, pointerover라는 이름으로 발생시키고, 이어서 pointerenter라는 이름의 포인터 이벤트도 발생시켜야 MUST 한다.

참고
저자는 호환성 마우스 이벤트 중 일부의 발생을 pointerdown 이벤트를 취소함으로써 방지할 수 있다 (isPrimary 속성이 true인 경우). 이는 포인터에 PREVENT MOUSE EVENT 플래그를 설정한다. 그러나 이것이 mouseover, mouseenter, mouseout 또는 mouseleave 이벤트의 발생을 방지하지는 않는다는 점에 유의하라.

5.3.4 pointermove 이벤트

사용자 에이전트는 포인터가 pointerdown 또는 pointerup 이벤트를 발생시키지 않는 속성을 변경할 때 포인터 이벤트를 발생시키되, pointermove라는 이름으로 발생시켜야 MUST 한다. 여기에는 좌표, 압력, 접선 압력, 기울기, twist, 접촉 기하 구조(widthheight) 또는 코드형 버튼에 대한 모든 변경이 포함된다.

사용자 에이전트는 pointermove 이벤트의 디스패치를 (예를 들어 성능상의 이유로) 지연할 수 MAY 있다. 병합된 이벤트 정보는 단일 디스패치된 pointermove 이벤트의 getCoalescedEvents 메서드를 통해 노출된다. 이러한 이벤트의 최종 좌표는 이벤트의 대상을 찾는 데 사용되어야 한다.

5.3.5 pointerrawupdate 이벤트

사용자 에이전트는 포인터가 pointerdown 또는 pointerup 이벤트를 발생시키지 않는 속성을 변경할 때 포인터 이벤트를 발생시키되, pointerrawupdate라는 이름으로, 그리고 보안 컨텍스트 안에서만 발생시켜야 MUST 한다. 이러한 속성 목록은 pointermove 이벤트를 참조하라.

pointermove와 달리, 사용자 에이전트는 pointerrawupdate 이벤트를 가능한 한 빨리, 그리고 JavaScript가 이벤트를 처리할 수 있는 만큼 자주 디스패치하는 것이 좋다 SHOULD.

pointerrawupdate 이벤트의 targetpointermove 이벤트와 다를 수 있다. 이는 pointermove 이벤트가 지연되거나 병합될 수 있고, target을 찾는 데 사용되는 이벤트의 최종 위치가 그 병합된 이벤트와 다를 수 있기 때문이다.

같은 pointerId를 가진 다른 pointerrawupdate가 이미 있고 그것이 이벤트 루프에서 아직 디스패치되지 않았다면, 사용자 에이전트는 새 pointerrawupdate를 새 작업을 만드는 대신 그 이벤트와 병합할 수 MAY 있다. 이로 인해 pointerrawupdate가 병합된 이벤트를 가질 수 있으며, 이벤트가 이벤트 루프에서 처리되는 즉시 이들은 모두 하나의 pointerrawupdate 이벤트의 병합된 이벤트로 전달된다. 자세한 내용은 getCoalescedEvents를 참조하라.

pointerrawupdatepointermove의 순서와 관련해, 사용자 에이전트가 플랫폼으로부터 pointerrawupdatepointermove 이벤트를 모두 발생시키는 업데이트를 수신했다면, 사용자 에이전트는 대응하는 pointermove보다 먼저 pointerrawupdate 이벤트를 디스패치해야 MUST 한다.

target을 제외하면, 마지막 pointermove 이벤트 이후 디스패치된 모든 pointerrawupdate 이벤트의 병합된 이벤트 목록을 연결한 것은, 다른 이벤트 속성 측면에서 다음 pointermove 이벤트의 병합된 이벤트와 같다. pointerrawupdate의 속성은 대부분 pointermove와 같지만, 예외적으로 cancelablepointerrawupdate에 대해 false여야 MUST 한다.

사용자 에이전트는 호환성 마우스 이벤트pointerrawupdate에 대해 발생시키지 않는 것이 좋다 SHOULD.

참고
pointerrawupdate 이벤트에 리스너를 추가하면, 사용자 에이전트의 구현에 따라 웹 페이지의 성능에 부정적인 영향을 줄 수 있다. 대부분의 사용 사례에서는 다른 pointerevent 유형으로 충분하다. JavaScript가 고빈도 이벤트를 필요로 하고 이를 그만큼 빠르게 처리할 수 있는 경우에만 pointerrawupdate 리스너를 추가하는 것이 좋다. 이러한 경우에는 다른 유형의 포인터 이벤트를 수신할 필요가 없을 가능성이 높다.

5.3.6 pointerup 이벤트

사용자 에이전트는 포인터가 활성 버튼 상태를 떠날 때 포인터 이벤트를 발생시키되, pointerup이라는 이름으로 발생시켜야 MUST 한다. 마우스의 경우, 이는 장치가 하나 이상의 버튼이 눌린 상태에서 버튼이 눌리지 않은 상태로 전환될 때이다. 터치의 경우, 이는 디지타이저로부터 물리적 접촉이 제거될 때이다. 펜의 경우, 이는 버튼이 눌리지 않은 상태에서 펜이 디지타이저와의 물리적 접촉에서 제거되거나, 호버 중에 하나 이상의 버튼이 눌린 상태에서 버튼이 눌리지 않은 상태로 전환될 때이다.

호버를 지원하지 않는 입력 장치의 경우, 사용자 에이전트pointerup 이벤트를 디스패치한 후 포인터 이벤트를 발생시키되, pointerout이라는 이름으로 발생시키고, 이어서 pointerleave라는 이름의 포인터 이벤트도 발생시켜야 MUST 한다.

모든 pointerup 이벤트는 pressure 값이 0이다.

사용자 에이전트는 포인터가 현재 캡처되어 있는 경우에도 포인터 캡처를 암시적으로 해제해야 MUST 한다.

참고
마우스(또는 다른 다중 버튼 포인터 장치)의 경우, 이는 pointerdownpointerupmousedownmouseup과 같은 모든 상황에서 발생하지 않는다는 것을 의미한다. 자세한 내용은 코드형 버튼을 참조하라.

5.3.7 pointercancel 이벤트

사용자 에이전트포인터 이벤트 스트림을 억제할 시나리오를 감지하면 포인터 이벤트를 발생시키되, pointercancel이라는 이름으로 발생시켜야 MUST 한다.

pointercancel 이벤트의 다음 속성 값은 같은 pointerId를 가진 마지막으로 디스패치된 포인터 이벤트의 값과 일치해야 MUST 한다: width, height, pressure, tangentialPressure, tiltX, tiltY, twist, altitudeAngle, azimuthAngle, pointerType, isPrimary, 그리고 [UIEVENTS]에서 상속된 좌표. pointercancel 이벤트의 coalescedEventspredictedEvents 목록은 비어 있어야 하며 MUST, 이벤트의 cancelable 속성은 false여야 MUST 한다.

5.3.8 pointerout 이벤트

사용자 에이전트는 다음 중 하나가 발생할 때 포인터 이벤트를 발생시키되, pointerout이라는 이름으로 발생시켜야 MUST 한다:

5.3.9 pointerleave 이벤트

사용자 에이전트는 다음 중 하나가 발생할 때 포인터 이벤트를 발생시키되, pointerleave라는 이름으로 발생시켜야 MUST 한다:

참고
이 이벤트 유형은 pointerout과 비슷하지만 두 가지 차이가 있다: pointerleave는 버블링하지 않으며, 그 디스패치는 자손 요소의 히트 테스트 경계까지 고려한다.
참고
이 이벤트 유형, [UIEVENTS]에 설명된 mouseleave 이벤트, 그리고 [CSS21]에 설명된 CSS :hover 의사 클래스 사이에는 유사점이 있다. pointerenter 이벤트도 참조하라.

5.3.10 gotpointercapture 이벤트

사용자 에이전트는 요소가 포인터 캡처를 받을 때 포인터 이벤트를 발생시키되, gotpointercapture라는 이름으로 발생시켜야 MUST 한다. 이 이벤트는 포인터 캡처를 받고 있는 요소에서 발생한다. 해당 포인터의 이후 이벤트는 이 요소에서 발생한다. 포인터 캡처 설정보류 중인 포인터 캡처 처리 절을 참조하라.

5.3.11 lostpointercapture 이벤트

사용자 에이전트는 포인터에 대한 포인터 캡처가 해제된 후 포인터 이벤트를 발생시키되, lostpointercapture라는 이름으로 발생시켜야 MUST 한다. 이 이벤트는 캡처가 해제된 후 해당 포인터에 대한 이후 이벤트보다 먼저 발생해야 MUST 한다. 이 이벤트는 포인터 캡처가 제거된 요소에서 발생한다. 해당 포인터에 대한 이후 모든 이벤트는 click, auxclick, 및 contextmenu 이벤트를 제외하고, 이벤트 대상을 결정하기 위해 일반적인 히트 테스트 메커니즘(이 사양의 범위 밖)을 따른다. 포인터 캡처 해제, 포인터 캡처의 암시적 해제, 및 보류 중인 포인터 캡처 처리 절을 참조하라.

5.3.12 click, auxclick, 및 contextmenu 이벤트

이 절은 [UIEVENTS]에 정의된 click, auxclickcontextmenu 이벤트에 대한 추가 사항이다. 이러한 이벤트는 일반적으로 사용자 인터페이스 활성화와 연결되며, 키보드와 같은 비포인터 입력 장치에서도 발생한다.

이러한 이벤트는 PointerEvent 유형이어야 MUST 하며, 이 절의 나머지 부분에서 언급하는 추가 요구사항의 적용을 받는다.

5.3.12.1 이벤트 속성

이러한 이벤트의 경우, pointerIdpointerType을 제외한 모든 PointerEvent 전용 속성(이 사양에서 정의됨)은 기본값을 가져야 MUST 한다. 또한:

  • 이벤트가 포인팅 장치에 의해 생성된 경우, 그 pointerIdpointerType은 이러한 이벤트를 일으킨 PointerEvents와 같아야 MUST 한다.
  • 이벤트가 비포인팅 장치(예: 음성 인식 소프트웨어 또는 키보드 상호작용)에 의해 생성된 경우, pointerId-1이어야 MUST 하며, pointerType은 빈 문자열이어야 MUST 한다.
5.3.12.2 이벤트 좌표

PointerEvent에서 언급한 것처럼, CSSOM View Module은 소수 좌표를 허용하기 위해 다양한 좌표 속성 (screenX, screenY, pageX, pageY, clientX, clientY, x, y, offsetX, offsetY)을 double로 재정의할 것을 제안한다. 그러나 이 변경이 일반 MouseEvent에는 적용되지 않고 PointerEvent에만 적용되는 경우, click, auxclick, 및 contextmenu에서 레거시 코드와의 웹 호환성 문제를 일으키는 것으로 확인되었다. 이러한 이유로, CSSOM View Module에서 제안된 변경을 PointerEvent에만 구현한 사용자 에이전트는 click, auxclick, 및 contextmenu에 대한 다양한 좌표 속성을 Math.floor [ECMASCRIPT]를 사용하여 (원래 UI Events에 정의된 대로) long 값으로 변환해야 MUST 한다.

5.3.12.3 이벤트 디스패치

click, auxclick 또는 contextmenu 이벤트는 아래 알고리즘을 사용해 이벤트 대상을 재정의한다는 점을 제외하고, [UIEVENTS] 사양에 정의된 디스패치 절차를 따라야 MUST 한다:

  1. event를 디스패치 중인 click, auxclick 또는 contextmenu 이벤트로 두고, userEventevent의 발생을 일으킨 사용자 상호작용 이벤트로 둔다.

    참고

    userEvent 이벤트는 비-PointerEvent일 수 있다. 예를 들어, 체크박스 요소에서 스페이스바를 눌러 click 이벤트 디스패치가 발생한 경우 이는 KeyboardEvent이다.

    userEventPointerEvent인 경우, userEventclick 또는 auxclick 이벤트에 대해서는 pointerup이며, contextmenu 이벤트에 대해서는 (네이티브 플랫폼 관례에 따라) pointerdown 또는 pointerup 이벤트이다.

  2. userEventPointerEvent가 아니면, event 대상을 재정의하지 않고 [UIEVENTS] 사양에 따라 event를 디스패치하고, 아래의 나머지 단계를 건너뛴다.
  3. target을 다음과 같이 정의한다:

    eventcontextmenu 이벤트이거나, userEvent가 해당 포인터가 캡처된 동안 디스패치된 경우, targetuserEvent의 대상으로 둔다.

    그렇지 않으면(eventclick 또는 auxclick 이벤트이고 userEvent가 캡처되지 않은 상태로 디스패치된 pointerup 이벤트인 경우), event가 디스패치되는 순간의 DOM에서 대응하는 pointerdownpointerup 대상의 가장 가까운 공통 포함 조상을 target으로 둔다.

  4. [UIEVENTS] 사양에 따라 eventtarget에 디스패치한다.

    참고
    userEvent가 캡처된 경우, 같은 pointerId를 가진 lostpointercapture 이벤트가 이미 디스패치되었더라도 eventuserEvent의 캡처 대상으로 디스패치된다.

6. 휠 이벤트

휠은 하나 이상의 공간 차원에서 회전할 수 있고 포인터 장치와 연결될 수 있는 장치이다. 좌표계는 환경 구성에 따라 달라진다.

사용자의 환경은 y축을 따른 회전을 세로 스크롤과 연결하고, x축을 따른 회전을 가로 스크롤과 연결하며, z축을 따른 회전을 줌과 연결하도록 구성될 수 있다.

WheelEvent 객체의 deltaX, deltaY, deltaZ 속성은 각 축을 따라 픽셀, 줄 또는 페이지 단위의 측정값을 나타낸다. 보고되는 측정값은 환경별 알고리즘이 휠 장치의 실제 회전/이동을 적절한 값과 단위로 변환한 뒤 제공된다.
참고

사용자의 환경 설정은 휠 장치의 실제 회전/이동을 서로 다른 방식으로 해석하도록 사용자 정의될 수 있다. 일반적인 홈이 있는 마우스 휠의 한 번 움직임은 162픽셀의 측정값을 생성할 수 있다 (162는 단지 예시 값이며, 실제 값은 사용자 에이전트의 현재 화면 크기에 따라 달라질 수 있다). 그러나 사용자는 기본 환경 설정을 변경하여 마우스 휠을 더 빠르게 만들 수 있고, 이 숫자를 증가시킬 수 있다. 또한 일부 마우스 휠 소프트웨어는 가속(휠이 더 빠르게 회전/이동할수록 각 측정값의 delta가 더 커짐) 또는 서브픽셀 회전 측정값까지 지원할 수 있다. 이 때문에 저자는 어떤 사용자 에이전트에서의 특정 회전량이 모든 사용자 에이전트에서 같은 delta 값을 생성한다고 가정할 수 없다.

실제 휠 장치의 동작이 같은 방향으로 회전/이동하는 동안 wheel 이벤트가 여러 번 디스패치될 때, deltaX, deltaY 및 deltaZ 속성 값의 부호(양수 또는 음수)는 일관되어야 MUST 한다. 사용자 에이전트가 wheel 이벤트의 기본 동작으로 스크롤한다면, delta의 부호는 양의 X, Y, Z축이 각각 문서의 가장 오른쪽 가장자리, 가장 아래쪽 가장자리, 그리고 가장 먼 깊이(사용자로부터 멀어지는 방향)를 향하는 오른손 좌표계에 의해 주어지는 것이 좋다 SHOULD.
참고

개별 사용자 에이전트는(환경 및 하드웨어 구성에 따라) 휠에서의 동일한 물리적 사용자 상호작용을 서로 다르게 해석할 수 있다. 예를 들어, 트랙패드 가장자리에서 위에서 아래로 하는 세로 스와이프는 페이지를 아래로 스크롤하려는 휠 동작으로 해석될 수도 있고, 페이지를 위로 팬하려는 휠 동작으로 해석될 수도 있다(즉, 각각 양수 또는 음수 deltaY 값을 결과로 낼 수 있다).

첫 번째 wheel 이벤트가 발생할 때, 사용자 에이전트wheel 이벤트 트랜잭션을 생성해야 MUST 하며, 이렇게 하면 이후 구현별 시간 범위 안의 모든 wheel 이벤트가 같은 요소를 대상으로 할 수 있다. wheel 이벤트 트랜잭션은 단일 사용자 제스처와 연결된 일련의 wheel 이벤트이다. wheel 이벤트 트랜잭션은 그룹에서 첫 번째 wheel 이벤트가 발생한 시점의 최상위 이벤트 대상인 연관 이벤트 대상을 가져야 MUST 한다.

스크롤 가능한 요소를 대상으로 하는 일련의 wheel 이벤트가 자식 요소 위에서 시작하면, 같은 사용자 제스처의 이후 이벤트는 그 자식 요소 위에서 발생할 수 있다.

6.1 WheelEvent 인터페이스

WheelEvent 인터페이스는 wheel 이벤트와 관련된 특정 문맥 정보를 제공한다. WheelEvent 인터페이스의 인스턴스를 만들려면, 선택적 WheelEventInit 딕셔너리를 전달하여 WheelEvent 생성자를 사용한다.

6.1.1 WheelEvent

WebIDL[Exposed=Window]
interface WheelEvent : MouseEvent {
	constructor(DOMString type, optional WheelEventInit eventInitDict = {});
	// DeltaModeCode
	const unsigned long DOM_DELTA_PIXEL = 0x00;
	const unsigned long DOM_DELTA_LINE	= 0x01;
	const unsigned long DOM_DELTA_PAGE	= 0x02;

	readonly attribute double deltaX;
	readonly attribute double deltaY;
	readonly attribute double deltaZ;
	readonly attribute unsigned long deltaMode;
	readonly attribute boolean momentum;
};
DOM_DELTA_PIXEL
delta의 측정 단위는 픽셀이어야 MUST 한다. 이는 대부분의 운영 체제 및 구현 구성에서 가장 일반적인 경우이다.
DOM_DELTA_LINE
delta의 측정 단위는 개별 텍스트 줄이어야 MUST 한다. 이는 많은 폼 컨트롤에서의 경우이다.
DOM_DELTA_PAGE
delta의 측정 단위는 단일 화면 또는 구분된 페이지로 정의되는 페이지여야 MUST 한다.
deltaX
wheel 이벤트의 기본 동작이 스크롤인 사용자 에이전트에서, 이벤트가 취소되지 않은 경우 이 값은 스크롤될 x축 방향의 측정값(픽셀, 줄 또는 페이지 단위)이어야 MUST 한다. 그렇지 않으면 이는 x축 주위의 휠 장치 움직임에 대한 구현별 측정값(픽셀, 줄 또는 페이지 단위)이다. 이 속성의 초기화되지 않은 값0.0이어야 MUST 한다.
deltaY
wheel 이벤트의 기본 동작이 스크롤인 사용자 에이전트에서, 이벤트가 취소되지 않은 경우 이 값은 스크롤될 y축 방향의 측정값(픽셀, 줄 또는 페이지 단위)이어야 MUST 한다. 그렇지 않으면 이는 y축 주위의 휠 장치 움직임에 대한 구현별 측정값(픽셀, 줄 또는 페이지 단위)이다. 이 속성의 초기화되지 않은 값0.0이어야 MUST 한다.
deltaZ
wheel 이벤트의 기본 동작이 스크롤인 사용자 에이전트에서, 이벤트가 취소되지 않은 경우 이 값은 스크롤될 z축 방향의 측정값(픽셀, 줄 또는 페이지 단위)이어야 MUST 한다. 그렇지 않으면 이는 z축 주위의 휠 장치 움직임에 대한 구현별 측정값(픽셀, 줄 또는 페이지 단위)이다. 이 속성의 초기화되지 않은 값0.0이어야 MUST 한다.
deltaMode
deltaMode 속성은 delta 값의 측정 단위에 대한 표시를 포함한다. 기본값은 DOM_DELTA_PIXEL(픽셀)이다. 이 속성은 delta 값의 측정 단위를 나타내기 위해 DOM_DELTA 상수 중 하나로 설정되어야 MUST 한다. 정확한 측정값은 장치, 운영 체제 및 애플리케이션 구성에 따라 다르다. 이 속성의 초기화되지 않은 값0이어야 MUST 한다.
momentum
이 속성은 사용자가 물리적 스크롤 상호작용을 끝낸 뒤(예: 플링 후 트랙패드에서 손가락을 뗀 경우) 스크롤 관성을 시뮬레이트하기 위해 플랫폼이 이 이벤트를 합성한 경우 true여야 하며, 그렇지 않으면 false여야 한다. 이 속성의 초기화되지 않은 값false여야 MUST 한다.

6.1.2 WheelEventInit

WebIDLdictionary WheelEventInit : MouseEventInit {
	double deltaX = 0.0;
	double deltaY = 0.0;
	double deltaZ = 0.0;
	unsigned long deltaMode = 0;
	boolean momentum = false;
};
이슈 3

아래 정의들은 위에서 이미 해당 속성들이 정의되어 있으므로 중복되는 것처럼 보입니다. 다음을 참조하세요: pointerevents/646.

deltaX
deltaZ 속성을 참조하라.
deltaY
deltaZ 속성을 참조하라.
deltaZ
WheelEvent 객체의 deltaZ 속성을 초기화한다. 이 속성(및 deltaXdeltaY 속성)에 대한 상대적인 양수 값은 X, Y, Z축이 각각 문서의 가장 오른쪽 가장자리, 가장 아래쪽 가장자리, 그리고 가장 먼 깊이(사용자로부터 멀어지는 방향)를 향하는 오른손 좌표계에 의해 주어진다. 음의 상대값은 각각 그 반대 방향이다.
deltaMode
WheelEvent 객체의 deltaMode 속성을 열거 값 0, 1 또는 2로 초기화한다. 이는 휠의 회전이 스크롤을 일으켰을 경우 스크롤된 픽셀 양 (DOM_DELTA_PIXEL), 스크롤된 줄 (DOM_DELTA_LINE), 또는 스크롤된 페이지 (DOM_DELTA_PAGE)를 나타낸다.
momentum
momentum 속성을 초기화합니다.

6.2 휠 이벤트 유형

6.2.1 wheel

유형 wheel
인터페이스 WheelEvent
동기 / 비동기 비동기
버블링
신뢰된 대상 Element
취소 가능 다양함
합성됨
기본 동작 문서를 스크롤(또는 줌)한다
문맥
(신뢰된 이벤트)
  • Event.target : 현재 wheel 이벤트 트랜잭션의 요소 대상
  • UIEvent.view : Window
  • UIEvent.detail : 0
  • MouseEvent.screenX : 휠이 포인팅 장치와 연결되어 있으면 화면에서의 포인터 위치에 기반한 값, 그렇지 않으면 0
  • MouseEvent.screenY : 휠이 포인팅 장치와 연결되어 있으면 화면에서의 포인터 위치에 기반한 값, 그렇지 않으면 0
  • MouseEvent.clientX : 휠이 포인팅 장치와 연결되어 있으면 뷰포트 내 포인터 위치에 기반한 값, 그렇지 않으면 0
  • MouseEvent.clientY : 휠이 포인팅 장치와 연결되어 있으면 뷰포트 내 포인터 위치에 기반한 값, 그렇지 않으면 0
  • MouseEvent.altKey : Alt 수정자가 활성 상태이면 true, 그렇지 않으면 false
  • MouseEvent.ctrlKey : Control 수정자가 활성 상태이면 true, 그렇지 않으면 false
  • MouseEvent.shiftKey : Shift 수정자가 활성 상태이면 true, 그렇지 않으면 false
  • MouseEvent.metaKey : Meta 수정자가 활성 상태이면 true, 그렇지 않으면 false
  • MouseEvent.button : 휠이 포인팅 장치와 연결되어 있으면 현재 눌린 버튼에 기반한 값, 그렇지 않으면 0
  • MouseEvent.buttons : 휠이 포인팅 장치와 연결되어 있으면 현재 눌려 있는 모든 버튼에 기반한 값, 눌린 버튼이 없으면 0
  • MouseEvent.relatedTarget : 포인팅 장치가 가리키고 있는 대상이 있으면 그것을 나타낸다
  • WheelEvent.deltaX : deltaMode 단위에 따라 페이지가 x축 방향으로 스크롤될 것으로 예상되는 양; 또는 x축 주위의 휠 움직임에 대한 구현별 값
  • WheelEvent.deltaY : deltaMode 단위에 따라 페이지가 y축 방향으로 스크롤될 것으로 예상되는 양; 또는 y축 주위의 휠 움직임에 대한 구현별 값
  • WheelEvent.deltaZ : deltaMode 단위에 따라 페이지가 z축 방향으로 스크롤될 것으로 예상되는 양; 또는 z축 주위의 휠 움직임에 대한 구현별 값
  • WheelEvent.deltaMode : deltaX, deltaY 및 deltaZ 속성에 대한 단위 표시자(픽셀, 줄 또는 페이지)
마우스 휠이 임의의 축 주위로 회전했거나 동등한 입력 장치 (예: 마우스 볼, 특정 태블릿 또는 터치패드 등)가 그러한 동작을 에뮬레이트한 경우, 사용자 에이전트는 이 이벤트를 디스패치해야 MUST 한다. 플랫폼과 입력 장치에 따라, 대각선 휠 delta는 여러 개의 0이 아닌 축을 가진 단일 wheel 이벤트로 전달될 수도 있고, 각 0이 아닌 축마다 별도의 wheel 이벤트로 전달될 수도 MAY 있다. wheel 이벤트 유형의 일반적인 기본 동작은 표시된 양만큼 문서를 스크롤(또는 경우에 따라 줌)하는 것이다. 이 이벤트가 취소되면, 구현은 문서를 스크롤하거나 줌해서는 안 되며 MUST NOT, 이 이벤트 유형과 연결된 다른 어떤 구현별 기본 동작도 수행해서는 안 된다.
참고

일부 사용자 에이전트나 일부 입력 장치에서는, 휠이 돌아간 속도가 delta 값에 영향을 줄 수 있으며, 더 빠른 속도는 더 높은 delta 값을 생성한다.

6.2.2 wheel 이벤트의 취소 가능성

wheel 이벤트에서 preventDefault를 호출하면 스크롤을 방지하거나 그 밖의 방식으로 중단할 수 있다. 최대 스크롤 성능을 위해, 사용자 에이전트는 스크롤과 연결된 각 wheel 이벤트가 취소될지 확인하기 위해 처리될 때까지 기다리지 않을 수 있다. 이러한 경우 사용자 에이전트는 cancelable 속성이 falsewheel 이벤트를 생성하는 것이 좋으며, 이는 preventDefault를 사용하여 스크롤을 방지하거나 중단할 수 없음을 나타낸다. 그렇지 않으면 cancelabletrue가 된다.

특히 사용자 에이전트는 해당 이벤트에 대해 비수동 리스너가 없음을 관찰한 경우, 취소 불가능한 wheel 이벤트만 생성하는 것이 좋다.

7. Element 인터페이스에 대한 확장

다음 절은 포인터 캡처의 설정과 해제를 용이하게 하기 위해 기존 Element 인터페이스에 대한 확장을 설명한다.

WebIDLpartial interface Element {
  undefined setPointerCapture (long pointerId);
  undefined releasePointerCapture (long pointerId);
  boolean hasPointerCapture (long pointerId);
};
setPointerCapture()

인수 pointerId로 식별되는 포인터에 대해, 이 메서드가 호출된 요소로 포인터 캡처를 설정한다. 해당 포인터의 이후 이벤트에서는 포인터가 항상 캡처 대상 위에 있는 것처럼 캡처 대상이 일반 히트 테스트 결과를 대체하며, 캡처가 해제될 때까지 항상 이 요소를 대상으로 해야 MUST 한다. 이 메서드가 유효하려면 포인터가 활성 버튼 상태에 있어야 MUST 하며, 그렇지 않으면 조용히 실패한다. 제공된 메서드의 인수가 어떤 활성 포인터와도 일치하지 않으면, "NotFoundError" DOMExceptionthrow한다.

releasePointerCapture()

인수 pointerId로 식별되는 포인터에 대해, 이 메서드가 호출된 요소에서 포인터 캡처를 해제한다. 해당 포인터의 이후 이벤트는 이벤트 대상을 결정하기 위해 일반적인 히트 테스트 메커니즘 (이 사양의 범위 밖)을 따른다. 제공된 메서드의 인수가 어떤 활성 포인터와도 일치하지 않으면, "NotFoundError" DOMExceptionthrow한다.

hasPointerCapture

이 메서드가 호출된 요소가 인수 pointerId로 식별되는 포인터에 대한 포인터 캡처를 가지고 있는지 여부를 나타낸다. 특히 pointerId에 대한 보류 중인 포인터 캡처 대상 재정의가 이 메서드가 호출된 요소로 설정되어 있으면 true를 반환하고, 그렇지 않으면 false를 반환한다.

참고
이 메서드는 setPointerCapture() 호출 직후에는, 해당 요소가 아직 gotpointercapture 이벤트를 받지 않았더라도 true를 반환한다. 따라서 pointerdown 이벤트 리스너 안에서 암시적 포인터 캡처를 감지하는 데 유용할 수 있다.

8. GlobalEventHandlers 믹스인에 대한 확장

다음 절은 이벤트 핸들러 등록을 용이하게 하기 위해 기존 GlobalEventHandlers 믹스인에 대한 확장을 설명한다.

WebIDLpartial interface mixin GlobalEventHandlers {
    attribute EventHandler onpointerover;
    attribute EventHandler onpointerenter;
    attribute EventHandler onpointerdown;
    attribute EventHandler onpointermove;
    [SecureContext] attribute EventHandler onpointerrawupdate;
    attribute EventHandler onpointerup;
    attribute EventHandler onpointercancel;
    attribute EventHandler onpointerout;
    attribute EventHandler onpointerleave;
    attribute EventHandler ongotpointercapture;
    attribute EventHandler onlostpointercapture;
};
onpointerover
pointerover 이벤트 유형에 대한 이벤트 핸들러 IDL 속성.
onpointerenter
pointerenter 이벤트 유형에 대한 이벤트 핸들러 IDL 속성.
onpointerdown
pointerdown 이벤트 유형에 대한 이벤트 핸들러 IDL 속성.
onpointermove
pointermove 이벤트 유형에 대한 이벤트 핸들러 IDL 속성.
onpointerrawupdate
pointerrawupdate 이벤트 유형에 대한 이벤트 핸들러 IDL 속성.
onpointerup
pointerup 이벤트 유형에 대한 이벤트 핸들러 IDL 속성.
onpointercancel
pointercancel 이벤트 유형에 대한 이벤트 핸들러 IDL 속성.
onpointerout
pointerout 이벤트 유형에 대한 이벤트 핸들러 IDL 속성.
onpointerleave
pointerleave 이벤트 유형에 대한 이벤트 핸들러 IDL 속성.
ongotpointercapture
gotpointercapture 이벤트 유형에 대한 이벤트 핸들러 IDL 속성.
onlostpointercapture
lostpointercapture 이벤트 유형에 대한 이벤트 핸들러 IDL 속성.

9. Navigator 인터페이스에 대한 확장

Navigator 인터페이스는 [HTML]에 정의되어 있다. 이 사양은 장치 감지 지원을 제공하기 위해 Navigator 인터페이스를 확장한다.

WebIDLpartial interface Navigator {
    readonly  attribute long maxTouchPoints;
};
maxTouchPoints

getter 단계는 다음과 같다:

  1. emulated maxTouchPointsWebDriver BiDi emulated max touch points [WEBDRIVER-BIDI]의 결과로 둔다.
  2. emulated maxTouchPoints가 null이 아니면, emulated maxTouchPoints를 반환한다.
  3. 장치가 지원하는 동시 터치 접촉의 최대 개수를 반환한다. 여러 디지타이저가 있는 장치의 경우 (예: 여러 터치스크린), 값은 각 개별 디지타이저가 지원하는 최대 접촉 수의 집합 중 최댓값이어야 MUST 한다.

    예를 들어, 어떤 장치에 각각 2개, 5개, 10개의 동시 터치 접촉을 지원하는 터치스크린 3개가 있다고 가정하자. maxTouchPoints의 값은 10이어야 한다.

참고
maxTouchPoints 값이 0보다 크다는 것은 사용자의 장치가 터치 입력을 지원할 수 있음을 나타내지만, 사용자가 터치 입력을 사용할 것임을 반드시 의미하지는 않는다. 저자는 시스템에 있을 수 있는 마우스, 펜 또는 스크린 리더와 같은 다른 입력 방식도 함께 고려하도록 주의해야 한다.
참고
maxTouchPoints는 콘텐츠의 상호작용 모델이 현재 하드웨어에서 인식될 수 있음을 보장하는 데 자주 사용된다. 기능이 더 제한적인 하드웨어를 사용하는 사용자에게 UI 어포던스를 제공할 수 있다. 터치 지점의 정확한 개수를 알 수 없는 플랫폼에서는, 인식이 보장되는 최소 개수가 제공된다. 따라서 인식되는 터치 지점의 수가 maxTouchPoints 값보다 많을 수 있다.

10. 직접 조작 동작 선언

속성 및 기본 동작에서 언급한 것처럼, 뷰포트 조작(팬 및 줌)은 포인터 이벤트를 취소하여 억제할 수 없다. 대신, 저자는 touch-action CSS 속성을 사용하여 이러한 동작 중 어떤 것을 허용하고 어떤 것을 억제할지 선언적으로 정의해야 한다.

참고
뷰포트를 조작하는 데 사용되는 포인터의 문제는 일반적으로 터치 입력(사용자의 손가락이 콘텐츠와 상호작용하는 동시에 페이지를 팬/줌할 수 있는 경우)에 한정되지만, 특정 사용자 에이전트는 다른 포인터 유형에 대해서도 같은 종류의 (직접 또는 간접) 조작을 허용할 수 있다. 예를 들어, 모바일/태블릿 장치에서는 사용자가 스타일러스를 사용하여 스크롤할 수도 있다. 역사적인 이유로, 이 사양에 정의된 touch-action CSS 속성은 터치 입력만 가리키는 것처럼 보이지만, 실제로는 팬 및 줌을 위한 직접 조작을 허용하는 모든 형태의 포인터 입력에 적용된다.

10.1 touch-action CSS 속성

이름: touch-action
값: auto | none | [ [ pan-x | pan-left | pan-right ] || [ pan-y | pan-up | pan-down ] ] | manipulation
초깃값: auto
적용 대상: 다음을 제외한 모든 요소: 비치환 인라인 요소, 표 행, 행 그룹, 표 열, 및 열 그룹
상속됨: 아니요
백분율: N/A
미디어: visual
계산값: 지정값과 같음
표준 순서: 문법에 따름
애니메이션 유형: 애니메이션 불가

touch-action CSS 속성은 직접 조작 상호작용(속성 이름에도 불구하고 터치에만 한정되지 않음)이 사용자 에이전트의 팬 및 줌 동작을 트리거할 수 MAY 있는지를 결정한다. touch-action에 관한 절을 참조하라.

팬 또는 줌을 시작하기 직전, 다음 조건이 모두 참이면 사용자 에이전트포인터 이벤트 스트림을 억제해야 MUST 한다:

참고
일부 사용자 에이전트는 별개의 개별 제스처들의 연속을 포함하지만 모두 단일 연속 제스처의 일부로 처리되는 동작에 대해 복잡한 제스처를 구현한다. 예를 들어, 터치스크린에서의 "fling to scroll" 제스처를 생각해 보자. 사용자는 빠른 손가락 움직임으로 문서를 팬하기 시작하고, 터치스크린에서 손가락을 떼며, 문서는 시뮬레이션된 관성으로 계속 팬된다. 문서가 아직 움직이는 동안, 사용자는 터치스크린에 손가락을 올리고 또 다른 "fling"을 실행하여 팬에 추가 모멘텀을 제공하거나, 현재 팬에 반작용하여 속도를 늦추거나, 팬을 완전히 멈추거나, 팬 방향을 반대로 바꿀 수 있다. 이 사양은 제스처와 동작이 어떻게 구현되는지를 규범적으로 정의하지 않으므로, 두 번째 터치가(두 번째 "fling" 또는 현재 팬에 대한 반작용으로 해석되기 전에) 포인터 이벤트를 발생시키는지 여부는 사용자 에이전트가 결정하도록 남겨둔다.
참고
touch-action은 임베디드 브라우징 컨텍스트로 적용/캐스케이드되지 않는다. 예를 들어, <iframe>touch-action을 적용하더라도 <iframe> 자체 내부에서의 팬 및 줌을 위한 직접 조작 상호작용의 동작에는 아무런 영향을 주지 않는다.

10.2 지원되는 직접 조작 동작 결정

사용자가 직접 조작 포인터(예: 터치스크린의 터치 또는 스타일러스)를 사용하여 요소와 상호작용할 때, 그 입력의 효과는 touch-action 속성의 값과 요소 및 그 조상의 기본 직접 조작 동작에 의해 다음과 같이 결정된다:

참고
일부 사용자 에이전트는 여러 동시 포인터(예: 멀티터치)를 포함하는 팬 및 줌 상호작용을 지원한다. 여러 동시 포인터의 touch-action 값을 처리하거나 연관시키는 방법은 이 사양의 범위 밖이다.

10.3 touch-action 값의 세부 사항

touch-action 속성은 뷰포트 팬 및 줌과 관련된 직접 조작 동작을 다룬다. 텍스트 선택/강조 또는 링크와 폼 컨트롤 활성화와 같은 추가 사용자 에이전트 동작은 이 CSS 속성의 영향을 받아서는 안 된다 MUST NOT.

참고
"panning"과 "scrolling"이라는 용어는 동의어로 간주된다(또는 더 정확히 말하면, "panning"은 직접 조작 입력을 사용하는 "scrolling"이다). 팬/스크롤을 트리거하기 위한 상호작용 또는 제스처, 또는 autonone 값에 대한 동작을 트리거하기 위한 상호작용 또는 제스처의 정의는 이 사양의 범위 밖이다.
auto
사용자 에이전트는 해당 요소에서 시작되는 뷰포트 팬 및 줌과 관련된 허용된 모든 직접 조작 동작을 고려할 수 MAY 있다.
none
해당 요소에서 시작되는 직접 조작 상호작용은 뷰포트 팬 및 줌과 관련된 동작을 트리거해서는 안 된다 MUST NOT.
pan-x
pan-left
pan-right
pan-y
pan-up
pan-down
사용자 에이전트는 나열된 모든 값이 지정한 방향 중 하나에서 시작하는 팬의 목적으로만 해당 요소에서 시작되는 직접 조작 상호작용을 고려할 수 MAY 있다. 팬이 시작된 뒤에는, 반대 방향에서 시작하는 팬이 허용되지 않더라도 사용자가 방향을 반대로 바꿀 수 있다. 반대로, 팬이 단일 축으로 제한된 경우 (예: pan-x 또는 pan-y), 팬 도중 축을 변경할 수 없다.
manipulation
사용자 에이전트는 팬 및 연속적인 줌(예: 핀치 줌)의 목적으로만 해당 요소에서 시작되는 직접 조작 상호작용을 고려할 수 MAY 있지만, 정해진 시간 안에 여러 번의 활성화가 발생해야 하는 다른 관련 동작(예: 더블 탭하여 줌, 또는 한 손가락 줌을 위한 더블 탭 후 누르고 있기)은 트리거해서는 안 된다 MUST NOT.
참고
구현에서 공통적으로 쓰이는 추가 touch-action은 [COMPAT]에 정의되어 있다.
참고
touch-action 속성은 CSS widthheight 속성을 모두 지원하는 요소에만 적용된다([CSS21] 참조). 이 제한은 낮은 지연 시간직접 조작 팬 및 줌에 대한 사용자 에이전트 최적화를 용이하게 하기 위해 설계되었다. 기본적으로 지원되지 않는 요소, 예를 들어 비치환 인라인 요소<span>의 경우, 저자는 display CSS 속성을 widthheight를 지원하는 block 같은 값으로 설정할 수 있다. 미래의 사양은 이 API를 모든 요소로 확장할 수 있다.
참고

방향별 pan 값은 일부 오버스크롤 동작을 사용자 정의하는 데 유용하다. 예를 들어, 단순한 pull-to-refresh 효과를 구현하려면 스크롤 위치가 0일 때마다 문서의 touch-actionpan-x pan-down으로 설정하고, 그렇지 않으면 pan-x pan-y로 설정할 수 있다. 이를 통해 포인터 이벤트 핸들러가 문서 맨 위에서 시작되는 위쪽 팬/스크롤에 대한 동작을 정의할 수 있다.

방향별 pan 값은 네이티브로 스크롤되는 요소 안에서 포인터 이벤트 처리를 통해 사용자 정의 팬을 구현하는 컴포넌트를 구성하는 데도 사용할 수 있다(또는 그 반대도 가능하다). 예를 들어, 이미지 캐러셀은 pan-y를 사용하여 문서의 세로 팬을 방해하지 않으면서 모든 가로 팬 작업에 대한 포인터 이벤트를 수신하도록 보장할 수 있다. 캐러셀이 가장 오른쪽 끝에 도달하면, 이후 그 범위를 넘어서는 스크롤 작업이 가능하다면 뷰포트 내에서 문서를 스크롤할 수 있도록 touch-actionpan-y pan-right로 변경할 수 있다. 팬/스크롤 작업이 진행되는 동안 그 동작을 변경하는 것은 불가능하다.

참고
팬 및 줌에 대한 일부 기본 직접 조작 동작을 비활성화하면 사용자 에이전트가 다른 동작에 더 빠르게 응답할 수 있다. 예를 들어, auto에서는 사용자 에이전트가 보통 더블 탭 제스처를 처리할 수 있도록 click 전에 300ms의 지연을 추가한다. 이러한 경우 touch-action: none 또는 touch-action: manipulation을 명시적으로 설정하면 이 지연이 제거된다. 탭 또는 더블 탭 제스처를 결정하는 방법은 이 사양의 범위 밖임에 유의하라.
예제 9: 모든 직접 조작 동작 금지
<div style="touch-action: none;">
    이 요소는 그렇지 않으면 팬 또는 줌으로 이어지는 모든 직접 조작 상호작용에 대해 포인터 이벤트를 수신한다.
</div>
예제 10: 가로 팬만 허용
<div style="touch-action: pan-x;">
    이 요소는 가로 방향으로 팬하지 않을 때 포인터 이벤트를 수신한다.
</div>
예제 11: 팬 및 줌에 대한 직접 조작 동작을 금지하는 자식 영역
<div style="overflow: auto;">
    <div style="touch-action: none;">
        이 요소는 그렇지 않으면 팬 또는 줌으로 이어지는 모든 직접 조작 상호작용에 대해 포인터 이벤트를 수신한다.
    </div>
    <div>
        이 요소에서의 직접 조작 상호작용은 부모를 조작하는 데 소비될 수 있다.
    </div>
</div>
예제 12: 팬 및 줌에 대한 직접 조작 동작을 금지하는 중간 부모
<div style="overflow: auto;">
    <div style="touch-action: pan-y;">
        <div style="touch-action: pan-x;">
            이 요소는 모든 직접 조작 상호작용에 대해 포인터 이벤트를 수신한다. 왜냐하면
            이 요소는 가로 팬만 허용하지만, 이 요소와 스크롤 가능한 요소 사이의
            중간 조상이 세로 팬만 허용하기 때문이다.
            따라서 팬/줌을 위한 직접 조작 동작은 사용자 에이전트에 의해 처리되지 않는다.
        </div>
    </div>
</div>
예제 13: 팬 및 줌에 대해 허용된 직접 조작 동작을 제한하는 중간 부모
<div style="overflow: auto;">
    <div style="touch-action: pan-y pan-left;">
        <div style="touch-action: pan-x;">
            이 요소는 왼쪽으로 팬하지 않을 때 포인터 이벤트를 수신한다.
        </div>
    </div>
</div>

11. 포인터 캡처

11.1 소개

이 절은 비규범적이다.

포인터 캡처는 특정 포인터에 대한 이벤트(모든 호환성 마우스 이벤트 포함)를 포인터 위치의 일반적인 히트 테스트 결과가 아닌 특정 요소로 다시 대상 지정할 수 있게 한다. 이는 사용자 정의 슬라이더 컨트롤(예: [HTML] <input type="range"> 컨트롤과 유사한 것) 같은 시나리오에서 유용하다. 포인터 캡처는 슬라이더 thumb 요소에 설정할 수 있으며, 이를 통해 포인터가 thumb에서 벗어나더라도 사용자가 컨트롤을 앞뒤로 슬라이드할 수 있다.

사용자 정의 볼륨 슬라이더
그림 7 thumb 요소를 앞뒤로 슬라이드하여 값을 선택하는 사용자 정의 슬라이더 컨트롤의 예. thumb에서 pointerdown 이후, 포인터가 thumb에서 벗어나더라도 사용자가 thumb를 슬라이드할 수 있도록 포인터 캡처를 사용할 수 있다.

11.2 포인터 캡처 설정

포인터 캡처는 element.setPointerCapture(pointerId) 메서드를 호출하여 Element 유형의 element에 설정된다. 이 메서드가 호출되면, 사용자 에이전트는 다음 단계를 실행해야 MUST 한다:

  1. 메서드의 인수로 제공된 pointerId가 어떤 활성 포인터와도 일치하지 않으면, "NotFoundError" DOMExceptionthrow한다.
  2. pointer를 주어진 pointerId로 지정된 활성 포인터로 둔다.
  3. element연결되어 있지 않으면 [DOM], "InvalidStateError" DOMExceptionthrow한다.
  4. 이 메서드가 호출될 때 element노드 문서 [DOM]에 잠긴 요소([PointerLock] pointerLockElement)가 있으면, "InvalidStateError" DOMExceptionthrow한다.
  5. pointer활성 버튼 상태에 있지 않거나, element노드 문서pointer활성 문서가 아니면, 이 단계를 종료한다.
  6. 지정된 pointerId에 대해, 보류 중인 포인터 캡처 대상 재정의를 이 메서드가 호출된 Element로 설정한다.
참고
이전의 설정 또는 해제 호출이 보류 상태인 동안( 보류 중인 포인터 캡처 처리 참조) 포인터 캡처 설정 또는 해제 호출이 이루어지면, 두 번째 호출이 성공한 경우 두 번째 호출이 첫 번째 호출을 재정의하며, 그렇지 않으면 첫 번째 호출이 계속 유효하다. 이는 암시적 포인터 캡처pointerdown 리스너에서 해제하려는 실패한 시도에도 적용된다.

11.3 포인터 캡처 해제

포인터 캡처는 element.releasePointerCapture(pointerId) 메서드를 호출하여 요소에서 명시적으로 해제된다. 이 메서드가 호출되면, 사용자 에이전트는 다음 단계를 실행해야 MUST 한다:

  1. 메서드의 인수로 제공된 pointerId가 어떤 활성 포인터와도 일치하지 않고, 이 단계들이 포인터 캡처의 암시적 해제의 결과로 호출되는 것이 아니면, "NotFoundError" DOMExceptionthrow한다.
  2. 지정된 pointerId를 가진 Element에 대해 hasPointerCapture가 false이면, 이 단계를 종료한다.
  3. 지정된 pointerId에 대해, 설정되어 있다면 보류 중인 포인터 캡처 대상 재정의를 지운다.
참고
포인터 캡처 설정 절의 참고를 참조하라.

11.4 암시적 포인터 캡처

팬 및 줌을 위한 직접 조작 상호작용을 구현하는 입력 (예: 터치스크린의 터치 또는 스타일러스)은, 모든 pointerdown 리스너가 호출되기 직전에 대상 요소에서 setPointerCapture가 호출된 것과 정확히 같이 동작하는 것이 좋다 SHOULD. 이것이 발생했는지 확인하기 위해 hasPointerCapture API를 사용할 수 있다 (예를 들어 pointerdown 리스너 안에서). 다음 포인터 이벤트가 발생하기 전에 해당 포인터에 대해 releasePointerCapture가 호출되지 않으면, 캡처가 활성 상태임을 나타내는 gotpointercapture 이벤트가 (일반적으로) 대상에 디스패치된다.

참고
이는 [PointerEvents]로부터의 호환성을 깨는 변경이지만, 기존 콘텐츠의 대부분에는 영향을 주지 않는다. 일반적인 플랫폼 UX 관례와 일치하는 것에 더해, 암시적 캡처를 위한 이 설계는 사용자 에이전트가 명시적인 개발자 옵트인 없이 터치 이동 이벤트에서 히트 테스트를 호출할 필요를 방지하는 성능 최적화를 가능하게 한다 (터치 입력을 위한 기존의 지배적인 네이티브 및 웹 API의 성능 특성과 일치함).
참고
또한 사용자 에이전트는 input range 컨트롤과 같은 특정 UI 위젯에서 모든 입력 장치에 대해 암시적 포인터 캡처 동작을 구현할 수 있다(상호작용 중 일부 손가락 움직임이 폼 컨트롤 자체 밖으로 벗어나는 것을 허용함).

11.5 포인터 캡처의 암시적 해제

pointerup 또는 pointercancel 이벤트를 발생시킨 직후, 사용자 에이전트는 방금 디스패치된 pointerup 또는 pointercancel 이벤트의 pointerId에 대해 보류 중인 포인터 캡처 대상 재정의를 지워야 MUST 하며, 그 다음 필요한 경우 lostpointercapture를 발생시키기 위해 보류 중인 포인터 캡처 처리 단계를 실행한다. 보류 중인 포인터 캡처 처리 단계를 실행한 뒤, 포인터가 호버를 지원하면, 사용자 에이전트는 캡처가 없는 상태에서 포인터의 현재 위치를 반영하는 데 필요한 대응하는 경계 이벤트도 보내야 MUST 한다.

포인터 캡처 대상 재정의가 더 이상 연결되어 있지 않으면 [DOM], 포인터 캡처 대상 재정의는 document로 설정되는 것이 좋다 SHOULD.

보류 중인 포인터 캡처 대상 재정의가 더 이상 연결되어 있지 않으면 [DOM], 보류 중인 포인터 캡처 대상 재정의 노드는 지워지는 것이 좋다 SHOULD.

참고
앞의 두 문단으로 인해, 캡처 노드가 제거된 후 다음 보류 중인 포인터 캡처 처리 중에 캡처된 포인터에 대응하는 lostpointercapture 이벤트가 document에서 발생한다.

포인터 잠금 [PointerLock]이 요소에 성공적으로 적용되면, 어떤 요소가 캡처되도록 설정되어 있거나 캡처되도록 보류 중인 경우 사용자 에이전트releasePointerCapture 메서드가 호출된 것처럼 단계를 실행해야 MUST 한다.

12. 병합된 이벤트와 예측된 이벤트

참고
이 사양은 사용자 에이전트가 포인터 이동 데이터를 어떻게 병합하거나 예측해야 하는지를 정의하지 않는다. 이 사양은 이 정보에 접근하기 위한 API만 명시한다.

12.1 병합된 이벤트

성능상의 이유로, 사용자 에이전트는 포인터의 측정 가능한 속성 (예: 좌표, 압력, 접선 압력, 기울기, twist 또는 접촉 기하 구조)이 업데이트될 때마다 pointermove 이벤트를 보내지 않도록 선택할 수 있다. 대신, 여러 변경을 하나의 pointermove 또는 pointerrawupdate 이벤트로 병합(결합/통합)할 수 있다. 이 접근 방식은 사용자 에이전트가 수행해야 MUST 하는 이벤트 처리량을 줄이는 데 도움이 되지만, 특히 빠르고 큰 움직임에서 포인터 위치를 추적할 때 자연스럽게 세분성과 충실도가 낮아진다. getCoalescedEvents 메서드를 사용하면 애플리케이션이 원시의 병합되지 않은 위치 변경에 접근할 수 있다. 이를 통해 포인터 이동 데이터를 더 정밀하게 처리할 수 있다. 예를 들어 드로잉 애플리케이션의 경우, 병합되지 않은 이벤트를 사용하여 포인터의 실제 움직임에 더 가깝게 맞는 더 부드러운 곡선을 그릴 수 있다.

병합된 점과 병합되지 않은 점을 보여주는 곡선의 확대 보기
그림 8 드로잉 애플리케이션에서의 곡선 예 — pointermove 이벤트의 병합된 좌표만 사용하면(회색 점), 곡선은 눈에 띄게 각지고 들쭉날쭉하다. getCoalescedEvents()가 제공하는 더 세분화된 점(빨간 원)을 사용해 같은 선을 그리면 포인터 이동에 대한 더 부드러운 근사가 된다.

PointerEvent는 연관된 병합된 이벤트 목록(0개 이상의 PointerEvent의 목록)을 가진다. 신뢰된 pointermovepointerrawupdate 이벤트의 경우, 목록은 이 이벤트로 병합된 모든 PointerEvent의 시퀀스이다. "부모"인 신뢰된 pointermovepointerrawupdate 이벤트는 이러한 병합된 이벤트의 누적을 나타내지만, 추가 처리(예: 디스플레이 새로 고침 속도에 맞추기)를 가질 수 있다. 그 결과, 이러한 이벤트의 병합된 이벤트 목록은 항상 적어도 하나의 이벤트를 포함한다. 다른 모든 신뢰된 이벤트 유형의 경우, 이는 빈 목록이다. 신뢰되지 않은 이벤트는 그 병합된 이벤트 목록이 생성자에 전달된 값으로 초기화된다.

참고
신뢰된 부모 이벤트는 병합된 이벤트의 요약 또는 집계이므로, 개발자는 부모 이벤트나 모든 병합된 이벤트 중 하나만 처리하면 되며, 둘 다 처리할 필요는 없다.
참고
병합된 이벤트 목록을 포함하는 신뢰된 이벤트가 JavaScript에서 다시 디스패치되면, 이벤트 디스패치 알고리즘은 이벤트의 isTrusted 비트를 false로 설정하지만, 병합된 이벤트 목록의 같은 비트들은 원래의 true 값에서 변경되지 않은 채로 유지된다.

신뢰된 이벤트의 병합된 이벤트 목록에 있는 이벤트는 다음을 가진다:

예제 14: 병합된 이벤트 목록을 사용하는 기본 canvas 드로잉 애플리케이션
<style>
    /* 내장 사용자 에이전트 직접 조작 동작(예: 팬 또는 줌)을 비활성화하여
    canvas 요소의 모든 이벤트가 대신 애플리케이션에 전달되도록 한다. */

    canvas { touch-action: none; }
</style>

<canvas id="drawSurface" width="500px" height="500px" style="border:1px solid black;"></canvas>

<script>
    const canvas = document.getElementById("drawSurface"),
    context = canvas.getContext("2d");

    canvas.addEventListener("pointermove", (e)=> {

        if (e.getCoalescedEvents) {
            for (let coalesced_event of e.getCoalescedEvents()) {
                paint(coalesced_event); // 모든 원시/비병합 점을 그린다
            }
        } else {
            paint(e); // 최종 병합 점을 그린다
        }
    });

    function paint(event) {
        if (event.buttons>0) {
            context.fillRect(event.clientX, event.clientY, 5, 5);
        }
    }

</script>
참고
PointerEvent의 속성은 병합된 이벤트 목록의 이벤트를 가장 잘 나타내는 방식으로 초기화된다. 사용자 에이전트가 이를 수행해야 하는 구체적인 방법은 이 사양에서 다루지 않는다.

디스패치되는 이러한 모든 이벤트의 순서는 원래 이벤트의 실제 순서와 일치해야 MUST 한다. 예를 들어 pointerdown 이벤트가 병합된 pointermove 이벤트의 디스패치를 유발하는 경우, 사용자 에이전트는 먼저 해당 pointerId의 모든 병합된 이벤트를 가진 하나의 pointermove 이벤트를 디스패치한 뒤, pointerdown 이벤트를 디스패치해야 MUST 한다.

참고

다음은 증가하는 timeStamp 값과 함께 발생하는 실제 이벤트와 사용자 에이전트가 디스패치하는 이벤트의 예이다:

실제 이벤트 디스패치된 이벤트
포인터 (pointerId=2) 좌표 변경 pointerrawupdate (pointerId=2), 병합된 이벤트 하나 포함
포인터 (pointerId=1) 좌표 변경 pointerrawupdate (pointerId=1), 병합된 이벤트 하나 포함
포인터 (pointerId=2) 좌표 변경 pointerrawupdate (pointerId=2), 병합된 이벤트 하나 포함
포인터 (pointerId=2) 좌표 변경 pointerrawupdate (pointerId=2), 병합된 이벤트 하나 포함
포인터 (pointerId=1) 좌표 변경 pointerrawupdate (pointerId=1), 병합된 이벤트 하나 포함
포인터 (pointerId=2) 좌표 변경 pointerrawupdate (pointerId=2), 병합된 이벤트 하나 포함
포인터 (pointerId=1) 버튼 누름 pointermove (pointerId=1), 병합된 이벤트 두 개 포함
pointermove (pointerId=2), 병합된 이벤트 네 개 포함
pointerdown (pointerId=1), 병합된 이벤트 0개 포함
포인터 (pointerId=2) 좌표 변경 pointerrawupdate (pointerId=2), 병합된 이벤트 하나 포함
포인터 (pointerId=2) 좌표 변경 pointerrawupdate (pointerId=2), 병합된 이벤트 하나 포함
포인터 (pointerId=1) 버튼 해제 pointermove (pointerId=2), 병합된 이벤트 두 개 포함
pointerup (pointerId=1), 병합된 이벤트 0개 포함

12.2 예측된 이벤트

일부 사용자 에이전트에는 일련의 확인된 포인터 이동 이후, 현재 제스처의 선행 이벤트와 이동의 속도/궤적에 기반하여 미래 포인터 이동의 위치가 어디일지 예측할 수 있는 내장 알고리즘이 있다. 애플리케이션은 getPredictedEvents 메서드를 사용하여 이 정보를 활용할 수 있으며, 체감 지연 시간을 줄이기 위해 예측된 위치까지 추측적으로 "앞서 그린" 뒤 실제 점이 수신되면 이러한 예측 점을 폐기할 수 있다.

병합된 점을 사용해 그린 선과 예측된 미래 점을 보여주는 그림
그림 9 드로잉 애플리케이션에서의 선 예(왼쪽 아래에서 오른쪽 위로 그리는 제스처의 결과)로, pointermove 이벤트의 병합된 좌표를 사용하며, 사용자 에이전트의 예측된 미래 점(회색 원)을 보여준다.

PointerEvent는 연관된 예측된 이벤트 목록(0개 이상의 PointerEvent의 목록)을 가진다. 신뢰된 pointermove 이벤트의 경우, 이는 사용자 에이전트가 미래에 해당 이벤트 뒤를 따를 것으로 예측하는 PointerEvent들의 시퀀스이다. 다른 모든 신뢰된 이벤트 유형의 경우, 이는 빈 목록이다. 신뢰되지 않은 이벤트는 그 예측된 이벤트 목록이 생성자에 전달된 값으로 초기화된다.

참고

pointerrawupdate 이벤트는 비어 있지 않은 병합된 이벤트 목록을 가질 수 있지만, 성능상의 이유로 그 예측된 이벤트 목록은 일반적으로 빈 목록이 된다.

참고
예측된 이벤트 목록을 포함하는 신뢰된 이벤트가 JavaScript에서 다시 디스패치되면, 이벤트 디스패치 알고리즘은 이벤트의 isTrusted 비트를 false로 설정하지만, 예측된 이벤트 목록의 같은 비트들은 원래의 true 값에서 변경되지 않은 채로 유지된다.

목록 안의 이벤트 수와 현재 타임스탬프로부터 얼마나 떨어져 있는지는 사용자 에이전트와 그 사용자 에이전트가 사용하는 예측 알고리즘에 의해 결정된다.

신뢰된 이벤트의 예측된 이벤트 목록에 있는 이벤트는 다음을 가진다:

참고

저자는 예측된 이벤트를 다음 포인터 이벤트가 디스패치될 때까지만 유효한 예측으로 간주해야 한다. 사용자 에이전트가 얼마나 먼 미래까지 이벤트를 예측하는지에 따라, 일반적인 포인터 이벤트가 하나 이상의 예측된 이벤트의 타임스탬프보다 더 이르게 디스패치될 수 있다.

예제 15: 병합된 이벤트와 예측된 이벤트를 사용한 드로잉의 개념적 접근 방식

let predicted_points = [];
window.addEventListener("pointermove", function(event) {
    // 이전에 그린 예측 점을 지운다.
    for (let e of predicted_points.reverse()) {
        clearPoint(e.pageX, e.pageY);
    }

    // 마지막으로 수신한 이벤트 이후 실제로 발생한 움직임을 그린다.
    for (let e of event.getCoalescedEvents()) {
        drawPoint(e.pageX, e.pageY);
    }

    // 지연 시간의 체감을 줄이기 위해 현재 예측 점을 그린다.
    predicted_points = event.getPredictedEvents();
    for (let e of predicted_points) {
        drawPoint(e.pageX, e.pageY);
    }
});

12.3 병합된 이벤트 목록과 예측된 이벤트 목록 채우기 및 유지

신뢰된 PointerEvent가 생성될 때, 사용자 에이전트는 병합된 이벤트 목록예측된 이벤트 목록 안의 각 이벤트에 대해 다음 단계를 실행하는 것이 좋다 SHOULD:

  1. 이벤트의 pointerId, pointerType, isPrimaryisTrusted를 "부모" 포인터 이벤트의 각각의 속성과 일치하도록 설정한다.
  2. 이벤트의 cancelablebubbles를 false로 설정한다(이러한 이벤트는 결코 단독으로 디스패치되지 않기 때문이다).
  3. 이벤트의 병합된 이벤트 목록예측된 이벤트 목록을 빈 목록으로 설정한다.
  4. 다른 모든 속성을 기본 PointerEvent 값으로 초기화한다.

신뢰된 PointerEventtarget이 변경될 때, 사용자 에이전트는 병합된 이벤트 목록예측된 이벤트 목록 안의 각 이벤트에 대해 다음을 실행하는 것이 좋다 SHOULD:

  1. 이벤트의 target을 "부모" 포인터 이벤트의 target과 일치하도록 설정한다.

13. 마우스 이벤트와의 호환성 매핑

오늘날 존재하는 웹 콘텐츠의 압도적 다수는 Mouse Events만을 대상으로 작성되어 있다. 다음은 사용자 에이전트가 이러한 콘텐츠와의 호환성을 위해 일반 포인터 입력을 마우스 이벤트로 매핑할 수 MAY 있는 방법에 대한 알고리즘을 설명한다.

마우스 이벤트와의 호환성 매핑은 이 사양의 OPTIONAL 기능이다. 사용자 에이전트는 기존 레거시 콘텐츠와의 최상의 호환성을 위해 이 기능을 지원하는 것이 권장된다.

참고

높은 수준에서, 호환성 마우스 이벤트는 각각의 포인터 이벤트와 "끼워 넣어져" 발생하도록 의도되어 있다. 그러나 이 특정 순서는 필수는 아니며, 호환성 마우스 이벤트를 구현하는 사용자 에이전트는 상대적 순서가 일관되는 한 마우스 이벤트의 디스패치를 지연하거나 그룹화하기로 결정할 수 MAY 있다.

특히 터치스크린 입력의 경우, 사용자 에이전트는 제스처 인식을 위해 추가 휴리스틱을 적용할 수 MAY 있다(저자가 touch-action을 통해 명시적으로 억제하지 않는 한). pointerdown 이벤트와 pointerup 이벤트 사이의 이벤트 시퀀스 동안, 제스처 인식은 제스처를 감지하거나 무시하기 위해 pointerup 이벤트까지 기다려야 할 수 있다. 그 결과, 사용자 에이전트가 상호작용이 특정 제스처로 의도되지 않았다고 판단한 경우 전체 시퀀스에 대한 호환성 마우스 이벤트는 마지막 pointerup 이벤트 이후에 함께 디스패치될 수 있다. 사용자 에이전트 제스처 인식의 이러한 세부 사항은 이 사양에서 정의하지 않으며, 구현마다 다를 수 있다.

호환성 마우스 이벤트 지원 여부와 관계없이, 사용자 에이전트는 click, auxclickcontextmenu 이벤트를 항상 지원해야 MUST 한다. 이러한 이벤트는 PointerEvent 유형이므로 호환성 마우스 이벤트가 아니기 때문이다. 포인터 이벤트 중 preventDefault를 호출하는 것은 click, auxclick 또는 contextmenu가 발생하는지 여부에 영향을 주어서는 안 된다 MUST NOT.

참고

이러한 고수준 이벤트 중 일부(예: contextmenu, focus, blur)와 포인터 이벤트의 상대적 순서는 정의되어 있지 않으며 사용자 에이전트마다 다르다. 예를 들어, 어떤 사용자 에이전트에서는 contextmenu가 종종 pointerup 뒤에 오지만, 다른 사용자 에이전트에서는 종종 pointerup 또는 pointercancel보다 앞서며, 어떤 상황에서는 대응하는 포인터 이벤트 없이 발생할 수 있다(예: 키보드 상호작용의 결과로).

또한, 사용자 에이전트는 click, auxclick 또는 contextmenu 이벤트를 발생시킬지 여부를 결정하기 위해 자체 휴리스틱을 적용할 수 있다. 일부 사용자 에이전트는 같은 유형의 다른(기본이 아닌) 포인터가 있거나 다른 유형의 다른 기본 포인터가 있는 경우 이러한 이벤트를 발생시키지 않기로 선택할 수 있다. 사용자 에이전트는 특정 동작이 "깔끔한" 탭, 클릭 또는 길게 누르기가 아니라고 판단할 수 있으며(예를 들어 터치스크린 위의 손가락 상호작용에서 손가락이 화면에 닿아 있는 동안 너무 많이 움직인 경우), click, auxclick 또는 contextmenu 이벤트를 발생시키지 않기로 결정할 수 있다. 사용자 에이전트 동작의 이러한 측면은 이 사양에서 정의하지 않으며, 구현마다 다를 수 있다.

달리 명시되지 않는 한, 매핑된 모든 마우스 이벤트의 대상은 그 대상이 더 이상 자신의 ownerDocument 트리에 참여하지 않는 경우를 제외하고는 각각의 포인터 이벤트와 같은 대상인 것이 좋다 SHOULD. 이 경우, 마우스 이벤트는 원래 대상이 트리에서 제거된 시점에 그 원래 대상의 가장 가까운 조상 노드 중 여전히 자신의 ownerDocument 트리에 참여하는 노드에서 발생하는 것이 좋으며, 이는 마우스 이벤트에 대해 (새 대상 노드에 기반한) 새 이벤트 경로가 만들어짐을 의미한다.

저자는 pointerdown 이벤트를 취소함으로써 특정 호환성 마우스 이벤트의 생성을 방지할 수 있다.

마우스 이벤트는 포인터가 내려가 있는 동안에만 방지될 수 있다. 호버 중인 포인터(예: 버튼이 눌리지 않은 마우스)는 그 마우스 이벤트를 방지할 수 없다.

mouseover, mouseout, mouseenter, 및 mouseleave 이벤트는 결코 방지되지 않는다(포인터가 내려가 있더라도).

포인터 이벤트 EventListenerpassive로 설정된 경우, 호환성 마우스 이벤트는 방지될 수 없다 [DOM].

13.1 레거시 마우스 포인터의 유효 위치 추적

기본 포인터만 호환성 마우스 이벤트를 생성할 수 있지만, 여러 기본 포인터가 동시에 활성화될 수 있으며, 각각은 자체 호환성 마우스 이벤트를 생성한다. MouseEvents에 의존하는 스크립트와의 호환성을 위해, 마우스 전환 이벤트(mouseover, mouseout, mouseentermouseleave)는 단일 레거시 마우스 입력의 이동을 시뮬레이트하는 것이 좋다 SHOULD. 이는 모든 이벤트 대상에 대한 진입/이탈 상태가 [UIEVENTS]에 따라 유효하다는 것을 의미한다. 사용자 에이전트는 문서에서 레거시 마우스 포인터의 유효 위치를 다음과 같이 유지함으로써 이를 보장하는 것이 좋다 SHOULD.

pointerdown, pointerup 또는 pointermove 이벤트, 또는 window에서의 pointerleave 이벤트를 발생시키기 직전에, 사용자 에이전트는 다음 단계를 실행하는 것이 좋다 SHOULD:

  1. T를 디스패치 중인 pointerdown, pointerup 또는 pointermove 이벤트의 대상으로 둔다. pointerleave 이벤트의 경우, T를 설정 해제한다.
  2. T와 현재 레거시 마우스 포인터의 유효 위치가 모두 설정 해제되어 있거나 서로 같으면, 이 단계를 종료한다.
  3. 마우스가 현재 레거시 마우스 포인터의 유효 위치에서 T로 이동하는 것에 대해 [UIEVENTS]에 따라 mouseover, mouseout, mouseentermouseleave 이벤트를 디스패치한다. 현재 레거시 마우스 포인터의 유효 위치 또는 T 중 하나의 설정 해제 값을 창 밖의 마우스 위치로 간주한다.
  4. 레거시 마우스 포인터의 유효 위치T로 설정한다.
참고

레거시 마우스 포인터의 유효 위치는 포인터 전환 이벤트(pointerover, pointerout, pointerenterpointerleave)에서 대응하는 레거시 마우스 전환 이벤트 (mouseover, mouseout, mouseentermouseleave)로 항상 직접 매핑할 수는 없다는 사실을 모델링한다. 다음 애니메이션은 단일 레거시 마우스 입력을 사용하여 두 기본 포인터를 조정할 수 있도록, 사용자 에이전트가 포인터 전환 이벤트보다 더 많은 레거시 마우스 전환 이벤트를 디스패치해야 하는 경우를 보여준다.

그림 10 동시 마우스 포인터(흰색 커서)와 터치 포인터(흰색 "손" 커서)가 단일 레거시 마우스 입력 (주황색 커서)을 두 포인터 사이로 이동하게 하는 모습.

이 애니메이션에서 마우스 클릭과 터치 탭 사이의 시간 구간에 주목하라. Button 1은 pointerout 이벤트를 받지 않는다(이 기간 동안 "실제" 마우스 포인터가 버튼 사각형을 떠나지 않았기 때문). 그러나 터치 탭에서 레거시 마우스 포인터의 유효 위치가 Button 2로 이동할 때 Button 1은 mouseout 이벤트를 받는다. 마찬가지로, 터치 탭과 마우스가 Button 1을 떠나기 직전 사이의 시간 구간에서 Button 1은 같은 이유로 pointerover 이벤트를 받지 않지만, 레거시 마우스 포인터의 유효 위치가 Button 1 안으로 다시 이동할 때 Button 1은 mouseover 이벤트를 받는다.

13.2 호버를 지원하는 장치에 대한 매핑

사용자 에이전트가 호버를 지원하는 장치에 대해 포인터 이벤트를 디스패치하려 할 때마다, 다음 단계를 실행하는 것이 좋다 SHOULD:

  1. 디스패치할 포인터 이벤트의 isPrimary 속성이 false이면, 포인터 이벤트를 디스패치하고 이 단계를 종료한다.
  2. 디스패치할 포인터 이벤트가 pointerdown, pointerup 또는 pointermove 이벤트이거나, window에서의 pointerleave 이벤트이면, 레거시 마우스 포인터의 유효 위치 추적에 설명된 대로 호환성 마우스 전환 이벤트를 디스패치한다.
  3. 포인터 이벤트를 디스패치한다.
  4. 디스패치된 포인터 이벤트가 pointerdown이고 이벤트의 canceled flag가 설정되어 있으면, 이 pointerType에 대한 PREVENT MOUSE EVENT 플래그를 설정한다.
  5. pointerType에 대해 PREVENT MOUSE EVENT 플래그가 설정되어 있지 않고, 디스패치된 포인터 이벤트가 다음과 같은 경우:
    • pointerdown이면, mousedown 이벤트를 발생시킨다.
    • pointermove이면, mousemove 이벤트를 발생시킨다.
    • pointerup이면, mouseup 이벤트를 발생시킨다.
    • pointercancel이면, window에서 mouseup 이벤트를 발생시킨다.
  6. 디스패치된 포인터 이벤트가 pointerup 또는 pointercancel이면, 이 pointerType에 대한 PREVENT MOUSE EVENT 플래그를 지운다.

13.3 호버를 지원하지 않는 장치에 대한 매핑

대부분의 터치스크린과 같은 일부 장치는 활성 상태가 아닐 때 좌표(또는 좌표 집합)를 호버하는 것을 지원하지 않는다. 마우스 이벤트를 대상으로 작성된 많은 기존 콘텐츠는 마우스가 이벤트를 생성한다고 가정하므로 일반적으로 특정 성질이 참이라고 가정한다:

참고
호버는 마우스용으로 설계된 콘텐츠에서 UI 요소의 가시성을 토글하는 데 사용되기도 한다 (예: "호버 메뉴"). 이러한 콘텐츠는 종종 호버를 지원하지 않는 장치와 호환되지 않는다. 이 사양은 이 시나리오와의 호환성을 위한 매핑이나 동작을 정의하지 않는다. 이는 사양의 향후 버전에서 고려될 것이다.

이는 사용자 에이전트가 이러한 유형의 입력 장치에 대해 다른 매핑을 제공해야 함을 요구한다. 사용자 에이전트가 호버를 지원하지 않는 장치에 대해 포인터 이벤트를 디스패치하려 할 때마다, 다음 단계를 실행하는 것이 좋다 SHOULD:

  1. 디스패치할 포인터 이벤트의 isPrimary 속성이 false이면, 포인터 이벤트를 디스패치하고 이 단계를 종료한다.
  2. 디스패치할 포인터 이벤트가 pointerover이고, 이 포인터에 대해 pointerdown 이벤트가 아직 디스패치되지 않았다면, (레거시 마우스 전용 코드와의 호환성을 위해) mousemove 이벤트를 발생시킨다.
  3. 디스패치할 포인터 이벤트가 pointerdown, pointerup 또는 pointermove 이벤트이거나, window에서의 pointerleave 이벤트이면, 레거시 마우스 포인터의 유효 위치 추적에 설명된 대로 호환성 마우스 전환 이벤트를 디스패치한다.
  4. 포인터 이벤트를 디스패치한다.
  5. 디스패치된 포인터 이벤트가 pointerdown이고 이벤트의 canceled flag가 설정되어 있으면, 이 pointerType에 대한 PREVENT MOUSE EVENT 플래그를 설정한다.
  6. pointerType에 대해 PREVENT MOUSE EVENT 플래그가 설정되어 있지 않고, 디스패치된 포인터 이벤트가 다음과 같은 경우:
    • pointerdown이면, mousedown 이벤트를 발생시킨다.
    • pointermove이면, mousemove 이벤트를 발생시킨다.
    • pointerup이면, mouseup 이벤트를 발생시킨다.
    • pointercancel이면, window에서 mouseup 이벤트를 발생시킨다.
  7. 디스패치된 포인터 이벤트가 pointerup 또는 pointercancel이면, 이 pointerType에 대한 PREVENT MOUSE EVENT 플래그를 지운다.

사용자 에이전트가 [TOUCH-EVENTS]에 정의된 Touch Events와 Pointer Events를 모두 지원하는 경우, 사용자 에이전트는 이 절에 설명된 호환성 마우스 이벤트와 [TOUCH-EVENTS]에 개요로 제시된 fallback mouse events둘 다 생성해서는 안 된다 MUST NOT.

참고

호버를 지원하지 않는 기본 포인터(예: 터치스크린의 한 손가락)를 사용한 요소의 활성화(click)는 일반적으로 다음 이벤트 시퀀스를 생성한다:

  1. mousemove
  2. pointerover
  3. pointerenter
  4. mouseover
  5. mouseenter
  6. pointerdown
  7. mousedown
  8. 포인터의 이동에 따라 0개 이상의 pointermovemousemove 이벤트
  9. pointerup
  10. mouseup
  11. pointerout
  12. pointerleave
  13. mouseout
  14. mouseleave
  15. click

그러나 이 상호작용 중 pointerdown 이벤트의 canceled flag가 설정되면 이벤트 시퀀스는 다음과 같다:

  1. mousemove
  2. pointerover
  3. pointerenter
  4. mouseover
  5. mouseenter
  6. pointerdown
  7. 포인터의 이동에 따라 0개 이상의 pointermove 이벤트
  8. pointerup
  9. pointerout
  10. pointerleave
  11. mouseout
  12. mouseleave
  13. click

14. 보안 및 개인정보 보호 고려사항

이 부록은 Pointer Events 구현에 대한 보안 및 개인정보 보호 고려사항을 논의한다. 논의는 이 사양에 정의된 이벤트 모델, API 및 이벤트의 구현에서 직접 발생하는 보안 및 개인정보 보호 문제로 제한된다.

이 사양에 정의된 많은 이벤트 유형은 사용자 동작에 응답하여 디스패치된다. 이는 악의적인 이벤트 리스너가 사용자가 일반적으로 기밀이라고 생각할 정보, 예를 들어 페이지와 상호작용하는 동안 사용자의 마우스/스타일러스/손가락의 정확한 경로/움직임에 접근할 수 있게 한다.

포인터 이벤트는 (사용자 장치에서 지원되는 경우) 펜 입력이 유지되는 각도나 기울기, 접촉면의 기하 구조, 스타일러스 또는 터치스크린에 가해지는 압력과 같은 추가 정보를 포함한다. 각도, 기울기, 기하 구조 및 압력에 대한 정보는 사용자 장치의 센서와 직접 관련되어 있으며, 이는 이 사양이 origin에 이러한 센서에 대한 접근을 허용함을 의미한다.

이 센서 데이터뿐 아니라 사용된 입력 메커니즘(마우스, 터치, 펜)의 유형을 결정할 수 있는 능력은 사용자, 또는 사용자의 장치와 환경의 특성을 추론하는 데 사용될 수 있다. 이러한 추론된 특성과 모든 장치/환경 정보는 그 자체로 민감할 수 있다. 예를 들어, 악의적인 사이트가 사용자가 보조 기술을 사용하고 있는지를 추가로 추론할 수 있게 할 수 있다. 이 정보는 또한 사용자 프로필을 만들거나 특정 사용자를 "fingerprint"하고 추적하려는 목적으로 잠재적으로 사용될 수 있다.

완화책으로, 사용자 에이전트는 사용자가 특정 센서 데이터(예: 각도, 기울기, 압력)에 대한 접근을 비활성화할 수 있는 기능을 포함하거나, 사용자의 명시적 opt-in 이후에만 이를 사용할 수 있도록 하는 것을 고려할 수 있다.

이 사양은 저자가 "예측된 이벤트"에 접근할 수 있는 방법을 정의한다. 사양 자체는 사용자 에이전트가 예측에 사용해야 하는 알고리즘을 정의하지 않는다. 사양 저자들은 알고리즘이 사용자가 수행 중인 현재 제스처와 관련된 선행 포인터 이벤트에만 의존할 것을 예상한다. 예측 알고리즘의 특정 구현이 사용자의 여러 사이트에 걸친 전체 상호작용 기록과 같은 추가 데이터에 의존하지 않도록 보장하는 것은 사용자 에이전트의 책임이다. 그러한 데이터는 사용자에 대한 민감한 정보를 드러내거나 사용자를 "fingerprint"하고 추적하는 데 사용될 수 있다.

이러한 고려사항 외에도, 작업 그룹은 이 사양이 다음과 같다고 믿는다:

15. 용어집

이 절은 비규범적이다.

활성 버튼 상태
포인터가 buttons 속성에 대해 0이 아닌 값을 가지는 상태. 마우스의 경우, 이는 장치의 적어도 하나의 버튼이 눌려 있을 때이다. 터치의 경우, 이는 디지타이저와 물리적 접촉이 있을 때이다. 펜의 경우, 이는 펜이 디지타이저와 물리적으로 접촉하고 있거나, 호버 중에 적어도 하나의 버튼이 눌려 있을 때이다.
활성 문서
모든 활성 포인터에 대해, 해당 포인터로부터 마지막 이벤트를 받은 문서.
활성 포인터
이벤트를 생성할 수 있는 모든 터치 접촉, 펜/스타일러스, 마우스 커서 또는 기타 포인터. 주어진 포인터(고유한 pointerId로 식별됨)가 문서 안에서 추가 이벤트를 생성할 수 있다면, 그 포인터는 여전히 활성 상태로 간주된다. 예:
  • 장치에 연결된 마우스는 항상 활성 상태이다.
  • 화면 위의 터치 접촉은 활성 상태로 간주된다.
  • 터치 접촉 또는 펜/스타일러스가 디지타이저 범위를 벗어나 들어 올려지면, 더 이상 활성 상태로 간주되지 않는다.
참고
일부 플랫폼에서 활성 포인터 집합은 사용자 에이전트를 대상으로 하지 않는 것 (예: 다른 애플리케이션을 대상으로 하는 것)을 포함하여 장치에 대한 모든 포인터 입력을 포함한다.
접촉 기하 구조
디지타이저 위 입력(가장 일반적으로 터치)의 경계 상자. 이는 일반적으로 단일 픽셀보다 더 거친 포인터 입력 해상도를 가진 장치를 가리킨다. 일부 장치는 이 데이터를 전혀 보고하지 않는다.
delta
WheelEvent 인터페이스를 지원하는 입력 장치 (예: 마우스 휠 또는 터치패드)의 물리적 움직임에 응답하여 사용자 에이전트가 페이지를 스크롤하거나 줌할 것으로 예상되는 스크롤 양(픽셀, 줄 또는 페이지 단위). delta의 값(예: deltaX, deltaY, 또는 deltaZ 속성)은 현재 deltaMode 속성의 문맥에서 해석되어야 한다. 휠(또는 다른 장치)의 물리적 움직임과 delta가 양수인지 음수인지의 관계는 환경 및 장치에 따라 달라진다. 그러나 사용자 에이전트가 기본 동작으로 스크롤한다면, delta의 부호는 양의 X, Y, Z축이 각각 document의 가장 오른쪽 가장자리, 가장 아래쪽 가장자리, 그리고 가장 먼 깊이(사용자로부터 멀어지는 방향)를 향하는 오른손 좌표계에 의해 주어진다.
디지타이저
접촉 중이거나 가까운 근접 상태에 있는 입력을 표면이 감지할 수 있는 입력 감지 장치의 한 유형. 가장 일반적으로 이는 터치 접촉 또는 펜/스타일러스의 입력을 감지하는 표면이다.
직접 조작
일부 사용자 에이전트(예: 터치스크린 장치의 브라우저)는 포인터가 컨트롤과 상호작용할 뿐 아니라 현재 페이지를 직접 팬하거나 줌하는 데도 사용되어 직접적인 물리적 접촉의 환상을 제공하는 "직접 조작" 은유를 구현한다. 예를 들어, 터치스크린 장치의 사용자는 일반적으로 손가락이나 스타일러스를 사용해 페이지를 "잡고" 포인터를 움직여 팬할 수 있으며, 페이지를 직접 조작한다. 이를 일반 데스크톱/노트북의 마우스 포인터와 대조하라. 여기서 팬은 페이지를 "드래그"하는 대신 스크롤바를 사용해 수행된다.
참고
일부 경우, (노트북에 있는 것과 같은) 터치패드는 사용자가 터치패드 위에서 "드래그"하여 스크롤할 수 있게 한다. 그러나 이는 일반적으로 터치패드가 "가짜" 마우스 휠 이벤트를 생성하여 이루어지므로, 직접 조작으로 간주되지 않는다.
히스테리시스
사용자 경험을 개선하기 위해 위치 또는 시간의 일정 범위 안의 입력 값을 허용하는 인간 인터페이스 설계의 기능. 예를 들어, 사용자가 마우스 버튼을 더블 클릭하는 데 걸리는 시간의 작은 편차를 허용하는 것은 시간적 히스테리시스이며, 사용자가 부모 창에서 자식 메뉴로 이동할 때 부모 창 밖으로 마우스를 이동해도 중첩 메뉴를 즉시 닫지 않는 것은 위치적 히스테리시스이다.
측정 가능한 속성

측정 가능한 속성은 실수 또는 큰 도메인의 정수로 표현되는 연속적인 포인터 센서 데이터와 관련된 값을 나타낸다. 포인터 이벤트의 경우, width, height, pressure, tangentialPressure, tiltX, tiltY, twist, altitudeAngle, azimuthAngle, 그리고 [UIEVENTS] Mouse Event 모델 속성 screenX, screenY, clientX, clientY는 측정 가능한 속성이다.

반대로 pointerId, pointerType, isPrimary, 그리고 [UIEVENTS] Mouse Event 모델 속성 button, buttons, ctrlKey, shiftKey, altKey, 및 metaKey는 센서 데이터와 관련되지 않으므로 측정 가능한 속성으로 간주되지 않는다.

포인터
마우스, 펜 또는 터치 접촉과 같이 화면의 특정 좌표(또는 좌표 집합)를 대상으로 할 수 있는 입력 장치에 대한 하드웨어 독립적 표현.
회전
WheelEvent 인터페이스를 사용하는 입력 장치에서 점진적 변화의 표시. 일부 장치에서는 이것이 휠의 문자 그대로의 회전일 수 MAY 있으며, 다른 장치에서는 평평한 표면을 따라 움직이는 것이거나 특정 버튼에 대한 압력일 수 MAY 있다.
최상위 이벤트 대상
최상위 이벤트 대상은 렌더링 순서에서 가장 위에 있으며 대상이 될 수 있는 요소여야 MUST 한다. 그래픽 사용자 인터페이스에서 이는 사용자의 포인팅 장치 아래에 있는 요소이다. 사용자 인터페이스의 히트 테스트 기능이 대상을 결정하는 데 사용된다. 히트 테스트 및 쌓임 순서에 관한 구체적인 세부 사항은 호스트 언어를 참조하라.

16. 레거시 이벤트 초기화자

이 절은 규범적이다. 다음 기능은 폐기되었으며, 레거시 소프트웨어와의 호환성을 요구하는 사용자 에이전트에 의해서만 구현되어야 한다. [UIEvents]의 레거시 이벤트 초기화자도 참조하라.

16.1 MouseEvent 인터페이스의 초기화자

WebIDLpartial interface MouseEvent {
	// Deprecated in this specification
	undefined initMouseEvent(DOMString typeArg,
		optional boolean bubblesArg = false,
		optional boolean cancelableArg = false,
		optional Window? viewArg = null,
		optional long detailArg = 0,
		optional long screenXArg = 0,
		optional long screenYArg = 0,
		optional long clientXArg = 0,
		optional long clientYArg = 0,
		optional boolean ctrlKeyArg = false,
		optional boolean altKeyArg = false,
		optional boolean shiftKeyArg = false,
		optional boolean metaKeyArg = false,
		optional short buttonArg = 0,
		optional EventTarget? relatedTargetArg = null);
};
initMouseEvent(typeArg)
MouseEvent 객체의 속성을 초기화한다. 이 메서드는 UIEvent.initUIEvent()와 같은 동작을 가진다.
경고

initMouseEvent 메서드는 폐기되었지만, 널리 배포된 구현과의 하위 호환성을 위해 지원된다.

DOMString typeArg
이 매개변수의 설명은 initEvent() 메서드를 참조하라.
boolean bubblesArg
이 매개변수의 설명은 initEvent() 메서드를 참조하라.
boolean cancelableArg
이 매개변수의 설명은 initEvent() 메서드를 참조하라.
Window? viewArg
view를 지정한다. 이 값은 null일 수 MAY 있다.
long detailArg
detail을 지정한다.
long screenXArg
screenX를 지정한다.
long screenYArg
screenY를 지정한다.
long clientXArg
clientX를 지정한다.
long clientYArg
clientY를 지정한다.
boolean ctrlKeyArg
ctrlKey를 지정한다.
boolean altKeyArg
altKey를 지정한다.
boolean shiftKeyArg
shiftKey를 지정한다.
boolean metaKeyArg
metaKey를 지정한다.
short buttonArg
button을 지정한다.
EventTarget? relatedTargetArg
relatedTarget을 지정한다. 이 값은 null일 수 MAY 있다.

A. 감사의 말

제안과 권고를 해준 많은 사람들에게 감사드리며, 그중 일부는 이 문서에 반영되어 있다. 그룹 의장은 다음의 과거 및 현재 그룹 구성원과 참여자의 기여를 인정한다: Mustaq Ahmed, Arthur Barstow, Ben Boyle, Matt Brubeck, Rick Byers, Marcos Cáceres, Cathy Chan, Bo Cupp, Domenic Denicola, Ted Dinklocker, Adam Ettenberger, Robert Flack, Dave Fleck, Mike Fraser, Ella Ge, Olga Gerchikov, Scott González, Kartikaya Gupta, Dominique Hazael-Massieux, Philippe Le Hégaret, Hayato Ito, Patrick Kettner, Patrick H. Lauke, Scott Low, Sangwhan Moon, Masayuki Nakano, Olli Pettay, Addison Phillips, Alan Pyne, Antoine Quint, Jacob Rossi, Kagami Sascha Rosylight, Doug Schepers, Ming-Chou Shih, Brenton Simpson, Dave Tapuska, Liviu Tinta, Asir Vedamuthu, Lan Wei, Jeffrey Yasskin, Navid Zolghadr.

과거에 마우스 및 휠 이벤트를 맡아 준 다음 사람들에게 감사드린다: Gary Kacmarcik, Travis Leithead, 그리고 수년간의 다양한 기여자들.

이 모델의 초판을 개척하는 데 도움을 준 이들에게 특별히 감사드리며, 특히 다음을 포함한다: Charu Chandiram, Peter Freiling, Nathan Furtwangler, Thomas Olsen, Matt Rakow, Ramu Ramanathan, Justin Rogers, Jacob Rossi, Reed Townsend 및 Steve Wright.

B. 개정 이력

이 절은 비규범적이다.

다음은 [PointerEvents3] 사양과 비교하여, 이 사양의 발행물 사이에 이루어진 실질적이고 주요한 편집 변경에 대한 정보 제공용 요약이다. 이 사양의 Editor's Drafts 전체 개정 이력을 참조하라.

C. IDL 색인

WebIDL[Exposed=Window]
interface MouseEvent : UIEvent {
	constructor(DOMString type, optional MouseEventInit eventInitDict = {});
	readonly attribute long screenX;
	readonly attribute long screenY;
	readonly attribute long clientX;
	readonly attribute long clientY;
	readonly attribute long layerX;
	readonly attribute long layerY;

	readonly attribute boolean ctrlKey;
	readonly attribute boolean shiftKey;
	readonly attribute boolean altKey;
	readonly attribute boolean metaKey;

	readonly attribute short button;
	readonly attribute unsigned short buttons;

	readonly attribute EventTarget? relatedTarget;

	boolean getModifierState(DOMString keyArg);
};

dictionary MouseEventInit : EventModifierInit {
	long screenX = 0;
	long screenY = 0;
	long clientX = 0;
	long clientY = 0;

	short button = 0;
	unsigned short buttons = 0;
	EventTarget? relatedTarget = null;
};

dictionary PointerEventInit : MouseEventInit {
    long        pointerId = 0;
    double      width = 1;
    double      height = 1;
    float       pressure = 0;
    float       tangentialPressure = 0;
    long        tiltX;
    long        tiltY;
    long        twist = 0;
    double      altitudeAngle;
    double      azimuthAngle;
    DOMString   pointerType = "";
    boolean     isPrimary = false;
    long        persistentDeviceId = 0;
    sequence<PointerEvent> coalescedEvents = [];
    sequence<PointerEvent> predictedEvents = [];
};

[Exposed=Window]
interface PointerEvent : MouseEvent {
    constructor(DOMString type, optional PointerEventInit eventInitDict = {});
    readonly        attribute long        pointerId;
    readonly        attribute double      width;
    readonly        attribute double      height;
    readonly        attribute float       pressure;
    readonly        attribute float       tangentialPressure;
    readonly        attribute long        tiltX;
    readonly        attribute long        tiltY;
    readonly        attribute long        twist;
    readonly        attribute double      altitudeAngle;
    readonly        attribute double      azimuthAngle;
    readonly        attribute DOMString   pointerType;
    readonly        attribute boolean     isPrimary;
    readonly        attribute long        persistentDeviceId;
    [SecureContext] sequence<PointerEvent> getCoalescedEvents();
    sequence<PointerEvent> getPredictedEvents();
};

[Exposed=Window]
interface WheelEvent : MouseEvent {
	constructor(DOMString type, optional WheelEventInit eventInitDict = {});
	// DeltaModeCode
	const unsigned long DOM_DELTA_PIXEL = 0x00;
	const unsigned long DOM_DELTA_LINE	= 0x01;
	const unsigned long DOM_DELTA_PAGE	= 0x02;

	readonly attribute double deltaX;
	readonly attribute double deltaY;
	readonly attribute double deltaZ;
	readonly attribute unsigned long deltaMode;
	readonly attribute boolean momentum;
};

dictionary WheelEventInit : MouseEventInit {
	double deltaX = 0.0;
	double deltaY = 0.0;
	double deltaZ = 0.0;
	unsigned long deltaMode = 0;
	boolean momentum = false;
};

partial interface Element {
  undefined setPointerCapture (long pointerId);
  undefined releasePointerCapture (long pointerId);
  boolean hasPointerCapture (long pointerId);
};

partial interface mixin GlobalEventHandlers {
    attribute EventHandler onpointerover;
    attribute EventHandler onpointerenter;
    attribute EventHandler onpointerdown;
    attribute EventHandler onpointermove;
    [SecureContext] attribute EventHandler onpointerrawupdate;
    attribute EventHandler onpointerup;
    attribute EventHandler onpointercancel;
    attribute EventHandler onpointerout;
    attribute EventHandler onpointerleave;
    attribute EventHandler ongotpointercapture;
    attribute EventHandler onlostpointercapture;
};

partial interface Navigator {
    readonly  attribute long maxTouchPoints;
};

partial interface MouseEvent {
	// Deprecated in this specification
	undefined initMouseEvent(DOMString typeArg,
		optional boolean bubblesArg = false,
		optional boolean cancelableArg = false,
		optional Window? viewArg = null,
		optional long detailArg = 0,
		optional long screenXArg = 0,
		optional long screenYArg = 0,
		optional long clientXArg = 0,
		optional long clientYArg = 0,
		optional boolean ctrlKeyArg = false,
		optional boolean altKeyArg = false,
		optional boolean shiftKeyArg = false,
		optional boolean metaKeyArg = false,
		optional short buttonArg = 0,
		optional EventTarget? relatedTargetArg = null);
};

D. 참고 문헌

D.1 규범적 참고 문헌

[CSS-OVERFLOW-3]
CSS 오버플로 모듈 레벨 3. Elika Etemad; Florian Rivoal. W3C. 2025년 10월 7일. W3C 작업 초안. URL: https://www.w3.org/TR/css-overflow-3/
[css-position]
CSS 위치 지정 레이아웃 모듈 레벨 3. Elika Etemad; Tab Atkins Jr. W3C. 2025년 10월 7일. W3C 작업 초안. URL: https://www.w3.org/TR/css-position-3/
[CSS21]
종속형 스타일 시트 레벨 2 개정 1 (CSS 2.1) 명세. Bert Bos; Tantek Çelik; Ian Hickson; Håkon Wium Lie. W3C. 2011년 6월 7일. W3C 권고안. URL: https://www.w3.org/TR/CSS2/
[CSSOM-View]
CSSOM 뷰 모듈. Simon Fraser; Emilio Cobos Álvarez. W3C. 2025년 9월 16일. W3C 작업 초안. URL: https://www.w3.org/TR/cssom-view-1/
[DOM]
DOM 표준. Anne van Kesteren. WHATWG. 현행 표준. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript 언어 명세. Ecma International. URL: https://tc39.es/ecma262/multipage/
[HTML]
HTML 표준. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. 상시 표준. URL: https://html.spec.whatwg.org/multipage/
[HTML401]
HTML 4.01 명세. Dave Raggett; Arnaud Le Hors; Ian Jacobs. W3C. 2018년 3월 27일. W3C 권고안. URL: https://www.w3.org/TR/html401/
[infra]
Infra 표준. Anne van Kesteren; Domenic Denicola. WHATWG. 현행 표준. URL: https://infra.spec.whatwg.org/
[PointerEvents]
포인터 이벤트. Patrick Lauke; Robert Flack. W3C. 2026년 6월 16일. W3C 작업 초안. URL: https://www.w3.org/TR/pointerevents4/
[PointerLock]
포인터 잠금 2.0. Mustaq Ahmed; Vincent Scheib. W3C. 2026년 2월 25일. W3C 작업 초안. URL: https://www.w3.org/TR/pointerlock-2/
[RFC2119]
RFC에서 요구 수준을 나타내는 데 사용하는 핵심 단어. S. Bradner. IETF. 1997년 3월. 현재 모범 사례. URL: https://www.rfc-editor.org/info/rfc2119/
[RFC8174]
RFC 2119 핵심 단어에서 대문자와 소문자의 모호성. B. Leiba. IETF. 2017년 5월. 현재 모범 사례. URL: https://www.rfc-editor.org/info/rfc8174/
[TOUCH-EVENTS]
터치 이벤트. Doug Schepers; Sangwhan Moon; Matt Brubeck; Arthur Barstow. W3C. 2013년 10월 10일. W3C 권고안. URL: https://www.w3.org/TR/touch-events/
[UIEVENTS]
UI 이벤트. Xiaoqian Wu. W3C. 2026년 2월 21일. W3C 작업 초안. URL: https://www.w3.org/TR/uievents/
[UIEvents-Key]
UI 이벤트 KeyboardEvent key 값. Travis Leithead; Gary Kacmarcik. W3C. 2025년 4월 22일. W3C 권고안. URL: https://www.w3.org/TR/uievents-key/
[WEBDRIVER-BIDI]
WebDriver BiDi. James Graham; Alex Rudenko; Maksim Sadym. W3C. 2026년 6월 29일. W3C 작업 초안. URL: https://www.w3.org/TR/webdriver-bidi/
[WEBIDL]
Web IDL 표준. Edgar Chen; Timothy Gu. WHATWG. 현행 표준. URL: https://webidl.spec.whatwg.org/

D.2 정보 제공용 참고 문헌

[COMPAT]
호환성 표준. Mike Taylor. WHATWG. 현행 표준. URL: https://compat.spec.whatwg.org/
[PointerEvents3]
포인터 이벤트. Patrick Lauke; Robert Flack. W3C. 2026년 6월 30일. W3C 권고안. URL: https://www.w3.org/TR/pointerevents3/
[WCAG22]
웹 콘텐츠 접근성 지침(WCAG) 2.2. Michael Cooper; Andrew Kirkpatrick; Alastair Campbell; Rachael Bradley Montgomery; Charles Adams. W3C. 2024년 12월 12일. W3C 권고안. URL: https://www.w3.org/TR/WCAG22/