포인터 이벤트

레벨 4

W3C 워킹 드래프트

이 문서에 대한 추가 정보
이 버전:
https://www.w3.org/TR/2026/WD-pointerevents4-20260211/
최신 공개 버전:
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/pointerevents2
편집자:
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과 같은 단일 이벤트 집합을 제공함으로써, 개발자는 각 장치별로 별도의 로직을 작성하지 않고도 다양한 입력 방식을 지원할 수 있습니다.

이 명세는 또한 마우스 및 휠 이벤트와 기타 포인터 장치 유형에 대해 마우스 이벤트를 발생시키는 매핑도 정의합니다.

이 문서의 상태

이 섹션은 본 문서가 출판될 당시의 상태를 설명합니다. 최신 W3C 발행물 목록과 이 기술 보고서의 최신 개정본은 W3C 표준 및 초안 인덱스에서 확인할 수 있습니다.

본 명세는 [PointerEvents3] 명세의 업데이트 버전입니다. 또한, 기존 [UIEVENTS] 명세에 있던 마우스 및 휠 이벤트를 포함합니다.

이 개정판에는 다음과 같은 새로운 기능이 포함되어 있습니다:

본 문서는 Pointer Events Working Group에 의해 권고 트랙을 사용하여 작업 초안으로 발행되었습니다.

작업 초안으로서의 출판은 W3C 및 그 회원사의 승인 또는 동의를 의미하지 않습니다.

이 문서는 초안 상태이며, 언제든지 다른 문서로 대체, 수정, 폐기될 수 있습니다. 진행 중인 작업 외에는 이 문서를 인용하는 것은 적절하지 않습니다.

본 문서는 W3C 특허 정책에 따라 운영되는 그룹에 의해 작성되었습니다. W3C는 해당 그룹의 결과물과 관련하여 공개 특허 공개 목록 을 유지 관리합니다. 이 페이지에는 특허 공개 방법에 대한 안내도 포함되어 있습니다. 특정 특허에 Essential Claim(필수 청구)이 포함되어 있다고 인지한 개인은 W3C 특허 정책 제6조에 따라 이 정보를 공개해야 합니다.

이 문서는 2025년 8월 18일자 W3C 프로세스 문서의 적용을 받습니다.

1. 소개

이 섹션은 규범적이지 않습니다.

현재 대부분의 [HTML] 콘텐츠는 마우스 입력과 함께 사용되거나 이를 위해 설계됩니다. 입력을 커스텀 방식으로 처리하는 경우는 보통 [UIEVENTS] 마우스 이벤트에 맞춰 코드를 작성합니다. 하지만 최근의 컴퓨팅 장치는 터치스크린, 펜 입력 등 다양한 형태의 입력을 도입하고 있습니다. 이러한 입력 각각을 별도로 처리하기 위한 이벤트 타입들이 제안되었지만, 이 방식은 새로운 입력 타입을 지원할 때 불필요하게 로직의 중복과 이벤트 처리 오버헤드를 유발하곤 합니다. 그 결과, 하나의 장치만을 염두에 두고 작성된 콘텐츠에서는 호환성 문제가 발생하기도 합니다. 또한 기존 마우스 기반 콘텐츠와의 호환성을 위해 대부분의 user agent는 모든 입력 타입에 대해 마우스 이벤트를 발생시킵니다. 이로 인해 마우스 이벤트가 실제 마우스 장치에서 발생한 것인지, 아니면 호환성을 위해 다른 입력 타입에서 생성된 것인지 모호해집니다. 그 결과 두 장치 타입 모두를 동시에 처리하는 코드 작성이 어려워집니다.

여러 입력 타입에 맞춰 코드를 작성하는 비용을 줄이고 위에서 언급한 마우스 이벤트의 모호성 문제를 완화하기 위해, 이 명세는 포인터라는 보다 추상화된 입력 개념을 정의합니다. 포인터란 마우스 커서, 펜, 터치(멀티터치 포함), 그 외의 포인팅 입력 장치로 화면의 한 점(또는 여러 점)에 만든 접점을 의미합니다. 이 모델을 사용하면 사용자의 하드웨어가 무엇이든 상관없이 잘 동작하는 사이트와 애플리케이션을 더 쉽게 만들 수 있습니다. 장치별 처리 로직이 필요한 경우를 위해, 이 명세는 이벤트를 발생시킨 장치 유형을 조회할 수 있는 속성도 제공합니다. 주요 목표는, 교차 장치 포인터 입력을 간단히 처리할 수 있는 단일 이벤트 및 인터페이스 집합을 제공하되, 보다 향상된 경험을 위해 필요한 경우에만 장치별 처리를 허용하는 것입니다.

또 다른 핵심 목표는, 멀티스레드 user agent가 직접 조작 액션(예: 손가락이나 스타일러스로 터치스크린에서 팬 또는 줌)을, 자바스크립트 실행 차단 없이 처리할 수 있도록 지원하는 것입니다.

참고

이 명세는 다양한 포인터 입력에 대한 통합 이벤트 모델을 정의하지만, 키보드 또는 유사 키보드 인터페이스(예: 스크린 리더나, 터치스크린만 있는 기기의 보조 기술 등)와 같은 다른 형태의 입력은 포함하지 않습니다. 이러한 인터페이스에 대해 user agent가 포인터 이벤트를 생성할 수는 있지만, 이 상황은 본 명세의 범위에 포함되지 않습니다.

최우선으로, 작성자들은 focus, blurclick 등 상위 레벨 이벤트에 반응하여 모든 입력 방식에 대해 동등한 기능을 제공하는 것이 권장됩니다. 하지만 포인터 이벤트 같은 저수준 이벤트를 사용할 때에는, 모든 입력 타입이 지원되도록 확보해야 합니다. 키보드 및 유사 키보드 인터페이스의 경우, 명시적인 키보드 이벤트 처리가 추가로 필요할 수 있습니다. 더 자세한 내용은 키보드 접근성 [WCAG22]을 참고하세요.

Pointer input combines various input sources such as mouse, pen, and touch
그림 1 포인터는 화면의 특정 좌표(또는 좌표 집합)를 지정할 수 있는 입력 장치들의 하드웨어 비의존적표현입니다.

제네릭 포인터 입력을 처리하는 이벤트들은 마우스 이벤트들과 매우 유사합니다: pointerdown, pointermove, pointerup, pointerover, pointerout 등입니다. 이를 통해 마우스 이벤트에서 포인터 이벤트로의 손쉬운 콘텐츠 마이그레이션이 가능합니다. 포인터 이벤트는 (클라이언트 좌표, 대상 엘리먼트, 버튼 상태 등) Mouse Event에 존재하는 모든 일반 속성뿐만 아니라, 압력, 접촉면, 기울기 등 다른 입력 방식 전용의 새로운 속성도 제공합니다. 작성자는 포인터 이벤트를 사용해 다양한 입력 방식 간에 로직을 공유할 수 있고, 최고의 경험을 위해 특정 입력 방식에만 맞춤 동작을 추가할 수도 있습니다.

포인터 이벤트는 다양한 입력 장치에서 발생하지만, 특정 장치별 이벤트(예: MouseEvent, TouchEvent)로부터 생성되어야 한다는 정의는 없습니다. 호환성을 위해 실제로 그렇게 하는 것이 권장될 수 있지만, 본 명세는 다른 장치별 이벤트의 지원을 필수로 요구하지 않습니다. 즉, user agent는 포인터 이벤트만 지원하고 다른 장치별 이벤트를 지원하지 않을 수 있습니다. 마우스 이벤트에만 맞춰 작성된 콘텐츠와의 호환성을 위해, 이 명세는 마우스 이외 장치의 포인터 입력을 기반으로 호환성 마우스 이벤트를 생성하는 방법에 대한 선택적 섹션도 제공합니다.

참고

이 명세는 [TOUCH-EVENTS]에서 정의한 Touch Events와 Pointer Events 둘 다를 지원하는 user agent의 기대 동작에 대해 조언하지 않습니다. 이 두 명세 간의 관계에 대한 더 자세한 안내는 Touch Events Community Group을 참고하세요.

2. 적합성

비규범적으로 표시된 섹션뿐만 아니라, 이 명세에 있는 모든 작성 가이드라인, 다이어그램, 예제, 참고 사항들은 모두 비규범입니다. 이 명세의 그 외 모든 내용은 규범적입니다.

이 문서의 MAY, MUST, MUST NOT, OPTIONAL, SHOULD 키워드는 BCP 14 [RFC2119] [RFC8174] 문서에서 설명한 대로, 그리고 오직 여기처럼 모두 대문자로 나타날 때에만 그 의미로 해석되어야 합니다.

3. 예제

이 섹션은 비규범적입니다.

아래는 이 명세의 일부 API가 작성자에 의해 어떻게 사용될 수 있는지를 보여주는 기본 예제들입니다. 더 구체적인 예제는 본 문서의 관련 섹션에서 제공합니다.

예제 1: 기능 감지 및 이벤트 바인딩
/* Pointer Events 또는 기존 터치/마우스 이벤트 바인딩 */

if (window.PointerEvent) {
    // Pointer Events 지원 시, pointer 이벤트만 리스닝
    target.addEventListener("pointerdown", function(e) {
        // 필요 시 e.pointerType에 따라 별도 로직 처리
        // 각 터치/펜/마우스 동작 분기 처리
        ...
    });
    ...
} else {
    // 기존 터치/마우스 이벤트 핸들러
    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이 비어 있음(감지 불가)
            또는 user agent별 커스텀 타입 */
    }
}
예제 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 인터페이스는 마우스 이벤트와 관련된 구체적인 문맥 정보를 제공합니다.

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

참고

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

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은(는) 어떤 포인팅 장치 버튼이 상태를 변경했는지를 나타내기 위해 사용되어야 합니다.

button 속성의 값은 다음과 같아야 합니다:

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

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

참고

button의 값은 마우스 버튼의 눌림/해제로 인해 발생하지 않은 이벤트에서는 업데이트되지 않습니다. 이러한 경우, 값 0을 왼쪽 버튼으로 해석하지 않도록 주의하고, 대신 기본값으로 취급해야 합니다.

참고

mousedownmouseup 같은 이벤트와 관련된 일부 기본 동작은 사용 중인 특정 마우스 버튼에 따라 달라집니다.

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

buttons

모든 마우스 이벤트 동안, buttons는 현재 눌려 있는 마우스 버튼들의 조합을 비트마스크로 나타내기 위해 사용되어야 합니다.

참고

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

buttons 속성의 값은 다음과 같아야 합니다:

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

일부 포인팅 장치는 더 많은 버튼을 제공하거나 시뮬레이션합니다. 이러한 버튼을 나타내기 위해서는, 각 추가 버튼마다 값이 2배가 되어야 하며(이진 수열 8, 16, 32, ...), 이를 사용해야 합니다.

참고

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

참고

mousedownmouseup 같은 이벤트와 관련된 일부 기본 동작은 사용 중인 특정 마우스 버튼에 따라 달라집니다.

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

relatedTarget

이벤트 유형에 따라, UI 이벤트와 관련된 2차 EventTarget을(를) 식별하는 데 사용됩니다.

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

getModifierState(keyArg)

키 값으로 수정자(modifier)의 상태를 조회합니다.

수정자 키이며 해당 수정자가 활성화되어 있으면 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입니다).

구현체는 마우스 이벤트를 생성할 때 현재 클릭 횟수를 유지해야 합니다. 이는 특정 시간 내에 포인팅 장치 버튼의 연속 클릭 횟수를 나타내는 0 이상의 정수여야 합니다. 이 횟수가 리셋되는 지연 시간은 환경 설정에 따라 달라집니다.

4.2 MouseEvent 알고리즘

4.2.1 네이티브 OS 요구 사항

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

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

  • 네이티브 OS 데스크톱에 대한 상대 x,y 마우스 좌표
  • UA의 윈도우 뷰포트에 대한 상대 x,y 마우스 좌표
  • 현재 눌려 있는 키보드 수정자 키(모디파이어)

4.2.2 마우스 이벤트 구성하기

경고

이 섹션은 개정이 필요합니다.

일반적으로 Event 인터페이스의 생성자 또는 Event 인터페이스를 상속받은 인터페이스의 생성자가 호출되면, [DOM]에 기술된 단계를 따라야 합니다. 하지만 MouseEvent 인터페이스는 Event 객체의 키 수정자에 대한 내부 상태를 초기화하기 위한 추가 딕셔너리 멤버들을 제공합니다. 구체적으로는, getModifierState() 메서드로 조회되는 내부 상태입니다. 이 섹션은 새로운 MouseEvent 객체를 이러한 선택적 수정자 상태로 초기화하기 위한 [DOM]의 단계를 보완합니다.

MouseEvent 또는 아래 알고리즘을 사용해 이들로부터 파생된 객체를 구성하는 목적에서, 모든 MouseEvent 및 파생 객체는 내부 키 수정자 상태를 가지며, 이는 [UIEvents-Key]의 수정자 키 표에서 설명된 키 수정자 이름을 사용하여 설정 및 조회할 수 있습니다.

다음 단계는 [DOM]에서 이벤트를 구성하기 위해 정의된 알고리즘을 보완합니다:

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

4.2.3 MouseEvent의 전역 상태

경고

이 섹션은 개정이 필요합니다.

4.2.3.1 사용자 에이전트 레벨 상태

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

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

4.2.3.2 윈도우 레벨 상태

UA는 윈도우에 대해 공유되는 다음 값들을 유지해야 합니다.

마지막 마우스 요소 값(초기값은 undefined)으로, 우리가 MouseEvent를 보낸 마지막 Element를 추적합니다.

마지막 마우스 DOM 경로 값(초기값은 비어 있음)으로, 가장 최근 마우스 이벤트가 전송될 당시의 마지막 마우스 요소의 조상 Element들의 스냅샷을 포함합니다.

4.2.4 MouseEvent의 내부 상태

경고

이 섹션은 개정이 필요합니다.

MouseEvent에는 다양한 수정자 키의 상태를 추적하기 위해 사용되는 다음 내부 플래그들이 있습니다: shift 플래그, control 플래그, alt 플래그, altgraph 플래그, 그리고 meta 플래그. 이 플래그들은 마우스 이벤트 시점에 해당 수정자 키가 눌려 있었다면 설정됩니다.

4.2.5 히트 테스트

경고

이 섹션은 개정이 필요합니다.

  1. pos를 뷰포트에 대한 상대 x,y 좌표로 둡니다
  2. pos와 함수 [CSSOM-View]의 elementFromPoint()를 반환합니다( pos에서 가장 앞에 있는 DOM 요소)
    참고

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

4.2.6 MouseEvent 초기화하기

경고

이 섹션은 개정이 필요합니다.

event, eventType, eventTarget, bubbles, cancelableMouseEvent를 초기화하려면, 다음 단계를 실행합니다:

  1. event, eventType, eventTarget, bubbles, cancelableUIEvent 초기화를 수행합니다.
  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. 업데이트할 eventMouseEvent로 둡니다
  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. 유효한 MouseEvent 타입을 담은 DOMString을 eventType로 둡니다
  2. 이벤트의 EventTargeteventTarget로 둡니다
  3. bubbles를 true로 둡니다
  4. cancelable를 true로 둡니다
  5. 이벤트 생성의 결과를, MouseEvent를 사용해 event로 둡니다
  6. event, eventType, eventTarget, bubbles, cancelableMouseEvent 초기화를 수행합니다.
  7. event를 반환합니다

4.2.9 취소 불가 MouseEvent 생성

경고

이 섹션은 개정이 필요합니다.

  1. 유효한 MouseEvent 타입을 담은 DOMString을 eventType로 둡니다
  2. 이벤트의 EventTargeteventTarget로 둡니다
  3. bubbles를 "false"로 둡니다
  4. cancelable를 "false"로 둡니다
  5. 이벤트 생성의 결과를, MouseEvent를 사용해 event로 둡니다
  6. event, eventType, eventTarget, bubbles, cancelableMouseEvent 초기화를 수행합니다.
  7. event를 반환합니다

4.2.10 MouseEvent button 속성 계산

경고

이 섹션은 개정이 필요합니다.

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

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

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

경고

이 섹션은 개정이 필요합니다.

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

    TODO.

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

4.2.12 네이티브 마우스 다운 처리

경고

이 섹션은 개정이 필요합니다.

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

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

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

4.2.13 네이티브 마우스 업 처리

경고

이 섹션은 개정이 필요합니다.

  1. 네이티브 mouseup을 native로 둡니다
    참고

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

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

4.2.14 네이티브 마우스 클릭 처리

경고

이 섹션은 개정이 필요합니다.

  1. 네이티브 마우스 클릭을 native로 둡니다
    참고

    플랫폼은 클릭을 생성하는 mouseup에 대해, 네이티브 마우스 업 처리 직후에 즉시 이를 호출해야 합니다.

  2. native의 뷰포트 상대 좌표로 히트 테스트를 수행한 결과를 target으로 둡니다
  3. nativetarget클릭 이벤트 전송을 수행합니다.

4.2.15 클릭 이벤트 전송

경고

이 섹션은 개정이 필요합니다.

  1. 네이티브 mousedown을 native로 둡니다
  2. 이벤트의 EventTargettarget로 둡니다
  3. mbutton을 1(기본적으로 주 마우스 버튼)로 둡니다
  4. native가 유효하다면,
    1. 어떤 마우스 버튼이 눌렸는지 식별하는 native의 ID를 mbutton으로 둡니다
  5. mbutton이 주 마우스 버튼이면 eventType을 "click"으로, 아니면 "auxclick"으로 설정합니다
  6. eventTypetargetPointerEvent 생성의 결과를 event로 둡니다
  7. native가 유효하다면,
    1. event, native네이티브에서 MouseEvent 속성 설정을 수행합니다
    2. event.screenX가 정수 값이 아니면 반올림합니다.
    3. event.screenY가 정수 값이 아니면 반올림합니다.
  8. dispatch eventtarget에서 수행합니다
    참고

    PointerEvents를 사용하며 좌표를 반올림하는 브라우저에 대한 정보는 pointerevents/100을 참고하세요.

    편집자 참고

    어떤 "기본 동작"이든, 대상의 활성화 동작 알고리즘을 트리거함으로써 dispatch 중에 처리됩니다. 따라서 여기에서 이를 처리할 필요는 없습니다. 다만 기존 명세가 disabled/css-pointer-events/inert/...를 처리하는지 검증할 필요가 있습니다.

    참고

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

    참고

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

4.2.16 네이티브 마우스 더블 클릭 처리

경고

이 섹션은 개정이 필요합니다.

  1. 네이티브 마우스 더블 클릭을 native로 둡니다
    참고

    이는 더블 클릭을 생성하는 마우스 클릭에 대해, 네이티브 마우스 클릭 처리 직후에 즉시 호출되어야 합니다.

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

4.2.17 네이티브 마우스 이동 처리

경고

이 섹션은 개정이 필요합니다.

  1. 네이티브 마우스 이동을 native로 둡니다
    이슈 2

    이 알고리즘은 PointerEvents의 dispatch에 대해, 현재 명시적으로 지정되어 있지 않다는 이유로 가정을 합니다. pointerevents/285가 해결되면, 이는 업데이트가 필요할 수 있습니다.

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

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

    2. mouseoutpointerout 이벤트 전송 여부 판단을 수행합니다
    3. Dispatch mouseouttarget에서 수행합니다
      참고

      취소되었을 때의 동작을 검증할 것(영향이 없는 것으로 보임).

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

      element가 삭제된 경우를 처리할 것. 또한 이동된 경우도 처리할 것: DOM 변경이 mouseleave 이벤트를 트리거했어야 하는가? 지금 이를 보내야 하는가? 드롭해야 하는가? 현재 브라우저가 무엇을 하는지 검증할 필요가 있음.

      1. "mouseleave" 및 element취소 불가 MouseEvent 생성의 결과를 mouseleave로 둡니다
      2. mouseleave.Event.composed = false로 설정합니다
        참고

        호환성 확인: event.composed 값. 명세는 false라고 함. Chrome/Linux = true. Firefox/Linux = false.

      3. mouseleavepointerleave 이벤트 전송 여부 판단을 수행합니다
      4. dispatch mouseleaveelement에서 수행한 결과를 result로 둡니다
  5. 새 요소로 진입하는 이벤트 생성:
    1. target마지막 마우스 요소가 아니라면,
      1. "mouseover" 및 target취소 가능한 MouseEvent 생성의 결과를 mouseover로 둡니다
        편집자 참고

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

      2. mouseoverpointerover 이벤트 전송 여부 판단을 수행합니다
      3. Dispatch mouseouttarget에서 수행합니다
        참고

        취소되었을 때의 동작을 검증할 필요가 있음(영향이 없는 것으로 보임).

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

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

        1. "mouseenter" 및 element취소 불가 MouseEvent 생성의 결과를 mouseenter로 둡니다
        2. mouseenter.Event.composed = false로 설정합니다
          참고

          호환성 확인: event.composed 값. 명세는 false라고 함. Chrome/Linux = true. Firefox/Linux = false.

        3. mouseenterpointerenter 이벤트 전송 여부 판단을 수행합니다
          참고

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

        4. dispatch mouseenterelement에서 수행한 결과를 result로 둡니다
      6. 마지막 마우스 요소target으로 설정합니다
      7. 마지막 마우스 DOM 경로targetDomPath로 설정합니다
  6. "mousemove" 및 element취소 가능한 MouseEvent 생성의 결과를 mousemove로 둡니다
  7. mousemove에 대한 PointerLock 속성 설정을 수행합니다
  8. mousemovepointermove 이벤트 전송 여부 판단을 수행합니다
  9. Dispatch mousemoveelement에서 수행합니다

4.2.18 컨텍스트 메뉴 표시 여부

경고

이 섹션은 개정이 필요합니다.

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

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

4.3 마우스 이벤트 순서

이 명세에서 정의된 특정 마우스 이벤트는 서로에 대해 정해진 순서로 발생해야 합니다. 아래는 포인팅 장치의 커서가 어떤 요소 위로 이동할 때 반드시 발생해야 하는 이벤트 시퀀스를 보여줍니다:

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

포인팅 장치가 요소 A 안으로 이동한 다음, 중첩된 요소 B 안으로 이동했다가 다시 밖으로 나오는 경우, 다음 이벤트 시퀀스가 반드시 발생해야 합니다:

이벤트 유형 요소 비고
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의 자식입니다:

Graphical representation of three stacked elements all on top of each other. The bottom element is labeled A and the top element is C
그림 2 서로 위에 포개진 세 요소의 그래픽 표현이며, 포인팅 장치가 이 스택 위를 이동하는 상황을 나타냅니다.

포인팅 장치가 요소 스택 바깥에서 라벨 C의 요소(스택에서 가장 위에 있는 요소)로 이동했다가 다시 밖으로 나가는 경우, 다음 이벤트들의 연속이 반드시 발생해야 합니다:

이벤트 유형 요소 비고
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
참고

mousemove 이벤트가 mousedownmouseup 사이에 어느 정도(지연 시간, 정도, 거리, 개수)까지 허용되면서도 click 또는 dblclick 이벤트가 계속 발생할지는, 구현체/장치/플랫폼에 따라 달라집니다. 이러한 허용치는 포인팅 장치와 상호작용할 때 손이 떨리는 등 신체적 장애가 있는 사용자를 돕는 데 도움이 될 수 있습니다.

각 구현체는 적절한 히스테리시스 허용치를 결정할 것이며, 일반적으로는 연관된 mousedownmouseup 이벤트의 이벤트 타깃이 동일한 요소이고, 그 사이에 mouseout 또는 mouseleave 이벤트가 개입하지 않는 경우 clickdblclick 이벤트를 발생시키는 것이 바람직합니다. 또한 연관된 mousedownmouseup 이벤트 타깃이 서로 다른 경우에는, 가장 가까운 공통 포함 조상에서 clickdblclick 이벤트를 발생시키는 것이 바람직합니다.

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

마우스 이벤트 시퀀스 중에 target(예: 대상 요소)이 DOM에서 제거되면, 시퀀스의 나머지 이벤트들은 그 요소에서 발생해서는 안 됩니다.

mousedown 이벤트의 결과로 대상 요소가 DOM에서 제거되면, 해당 요소에 대해 mouseup, click, 또는 dblclick 이벤트는 디스패치되지 않으며, 어떤 기본 활성화 이벤트도 발생하지 않습니다. 다만 mouseup 이벤트는, 초기 타깃 요소가 제거된 뒤 마우스에 노출되는 요소에서 여전히 디스패치됩니다. 마찬가지로 대상 요소가 mouseup 이벤트의 디스패치 중에 DOM에서 제거되면, click 및 그 이후 이벤트들은 디스패치되지 않습니다.

4.4 마우스 이벤트 유형

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

4.4.1 auxclick

유형 auxclick
인터페이스 PointerEvent
동기 / 비동기 동기
버블링
신뢰할 수 있는 대상 Element
취소 가능
Composed
기본 동작 상황에 따라 다름
컨텍스트
(신뢰할 수 있는 이벤트)

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

auxclick 이벤트는 주 버튼이 아닌 포인터 버튼에 대해서만 발생해야 합니다(즉 button 값이 0이 아니고, buttons 값이 1보다 큰 경우). 주 버튼(표준 마우스의 왼쪽 버튼과 같은)은 auxclick 이벤트를 발생시키면 안 됩니다. 주 버튼과 연관된 대응 이벤트는 click을 참고하세요.

auxclick 이벤트는 동일한 요소에서 mousedownmouseup 이벤트가 먼저 발생한 뒤에 이어질 수도 있습니다 (텍스트 노드 같은 다른 노드 유형 간의 변경은 무시). 환경 설정에 따라, 포인팅 장치 버튼의 누름과 놓음 사이에 mouseover, mousemove, 및 mouseout 이벤트 유형 중 하나 이상이 발생하는 경우에도 auxclick 이벤트가 디스패치될 수도 있습니다(MAY).

auxclick 이벤트 유형의 기본 동작은 이벤트의 targetbutton 또는 buttons 속성의 값에 따라 달라집니다. auxclick 이벤트 유형의 전형적인 기본 동작은 다음과 같습니다:

  • target에 연관된 활성화 동작이 있다면, 기본 동작은 그 활성화 동작을 실행하는 것이어야 합니다(MUST).
6: 가운데 버튼에 대한 auxclick 수신 및 처리
myLink.addEventListener("auxclick", function(e) {
  if (e.button === 1) {
    // This would prevent the default behavior which is for example
    // opening a new tab when middle clicking on a link.
    e.preventDefault();
    // Do something else to handle middle button click like taking
    // care of opening link or non-link buttons in new tabs in a way
    // that fits the app. Other actions like closing a tab in a tab-strip
    // which should be done on the click action can be done here too.
  }
});
참고

오른쪽 버튼의 경우, auxclick 이벤트는 어떤 contextmenu 이벤트 이후에 디스패치됩니다. 일부 사용자 에이전트는 컨텍스트 메뉴가 표시되는 동안 모든 입력 이벤트를 삼켜 버리므로, 그런 시나리오에서는 auxclick을 애플리케이션에서 사용할 수 없을 수 있습니다. 더 명확한 설명은 7을 참고하세요.

7: 오른쪽 버튼에 대한 auxclick 수신 및 처리
myDiv.addEventListener("contextmenu", function(e) {
  // This call makes sure no context menu is shown
  // to interfere with page receiving the events.
  e.preventDefault();
});
myDiv.addEventListener("auxclick", function(e) {
  if (e.button === 2) {
    // Do something else to handle right button click like opening a
    // customized context menu inside the app.
  }
});

4.4.2 click

유형 click
인터페이스 PointerEvent
동기 / 비동기 동기
버블링
신뢰할 수 있는 대상 Element
취소 가능
Composed
기본 동작 상황에 따라 다름
컨텍스트
(신뢰할 수 있는 이벤트)

click 이벤트 유형은 사용자가 주 포인터 버튼을 누르고 놓을 때, 또는 그러한 동작을 시뮬레이션하는 방식으로 포인터를 활성화할 때, 포인터가 가리키는 최상위 이벤트 대상MUST 디스패치되어야 합니다. 마우스 버튼의 작동 방식은 포인팅 장치와 환경 설정에 따라 달라지며, 예를 들어 화면 위치 또는 포인팅 장치 버튼의 누름과 놓음 사이의 지연 시간에 의존할 수도 있습니다(MAY).

click 이벤트는 주 포인터 버튼에 대해서만 발생해야 합니다 (즉 button 값이 0이고, buttons 값이 1인 경우). 2차 버튼(표준 마우스의 가운데 또는 오른쪽 버튼과 같은)은 click 이벤트를 발생시키면 안 됩니다. 주 버튼이 아닌 버튼과 연관된 대응 이벤트는 auxclick을 참고하세요.

click 이벤트는 동일한 요소에서 mousedownmouseup 이벤트가 먼저 발생한 뒤에 이어질 수도 있습니다 (예: 텍스트 노드 같은 다른 노드 유형 간의 변경은 무시). 환경 설정에 따라, 포인팅 장치 버튼의 누름과 놓음 사이에 mouseover, mousemove, 및 mouseout 이벤트 유형 중 하나 이상이 발생하는 경우에도 click 이벤트가 디스패치될 수도 있습니다(MAY). 또한 click 이벤트 뒤에는 dblclick 이벤트가 뒤따를 수도 있습니다(MAY).

사용자가 큰 line-height로 스타일링된 <p> 요소의 텍스트 노드 자식에서 마우스를 누른 다음, 마우스를 약간 이동해 더 이상 텍스트가 포함된 영역 위에 있지는 않지만 여전히 그 <p> 요소의 포함 블록 안(즉 동일한 텍스트 블록의 줄 사이에는 있지만, 텍스트 노드 자체 위는 아님)에 있고, 이후 마우스를 놓는다면, 사용자가 동일 요소의 범위 안에 머물렀기 때문에 (일반적인 히스테리시스의 시간적 허용 범위 내의 click에 해당한다면) 여전히 click 이벤트가 트리거될 가능성이 높습니다. 사용자 에이전트가 생성한 마우스 이벤트는 텍스트 노드에서는 디스패치되지 않는다는 점에 유의하세요.

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

참고

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

click 이벤트 유형의 기본 동작은 이벤트의 targetbutton 또는 buttons 속성의 값에 따라 달라집니다. click 이벤트 유형의 전형적인 기본 동작은 다음과 같습니다:

  • target에 연관된 활성화 동작이 있다면, 기본 동작은 그 활성화 동작을 실행하는 것이어야 합니다(MUST).
  • target이 포커스 가능하다면, 기본 동작은 그 요소에 문서 포커스를 주는 것이어야 합니다(MUST).

4.4.3 contextmenu

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

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

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

참고

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

4.4.4 dblclick

유형 dblclick
인터페이스 MouseEvent
동기 / 비동기 동기
버블링
신뢰할 수 있는 대상 Element
취소 가능
Composed
기본 동작 없음
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 포인팅 장치의 주 버튼이 어떤 요소 위에서 두 번 클릭되었을 때 이 이벤트를 MUST 디스패치해야 합니다. 더블 클릭의 정의는 환경 설정에 따라 달라지지만, mousedown, mouseup, 및 dblclick 사이에서 이벤트 타깃은 동일해야 합니다(MUST). 클릭과 더블 클릭이 동시에 발생하는 경우, 이 이벤트 유형은 click 이벤트 유형 이후에 MUST 디스패치되어야 하며, 그 외의 경우에는 mouseup 이벤트 유형 이후에 디스패치되어야 합니다.

click 이벤트와 마찬가지로, dblclick 이벤트는 주 포인터 버튼에 대해서만 발생해야 합니다. 2차 버튼은 dblclick 이벤트를 발생시키면 안 됩니다.

참고

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

click 이벤트 유형과 마찬가지로, dblclick 이벤트 유형의 기본 동작은 이벤트의 targetbutton 또는 buttons 속성의 값에 따라 달라집니다. dblclick 이벤트 유형의 전형적인 기본 동작click 이벤트 유형의 것과 일치합니다.

4.4.5 mousedown

유형 mousedown
인터페이스 MouseEvent
동기 / 비동기 동기
버블링
신뢰할 수 있는 대상 Element
취소 가능
Composed
기본 동작 상황에 따라 다름: 드래그/드롭 작업 시작; 텍스트 선택 시작; 스크롤/팬 상호작용 시작 (지원되는 경우 가운데 마우스 버튼과 조합)
컨텍스트
(신뢰할 수 있는 이벤트)
사용자 에이전트는 포인팅 장치 버튼이 어떤 요소 위에서 눌렸을 때 이 이벤트를 MUST 디스패치해야 합니다.
참고

많은 구현은 mousedown 이벤트를 사용하여 다양한 상황 의존적인 기본 동작을 시작합니다. 이 이벤트가 취소되면 이러한 기본 동작을 막을 수 있습니다. 이러한 기본 동작에는 예를 들어 이미지나 링크와의 드래그/드롭 상호작용 시작, 텍스트 선택 시작 등이 포함될 수 있습니다. 또한 일부 구현은 mousedown 이벤트가 디스패치될 때 가운데 마우스 버튼이 눌려 있으면 활성화되는, 마우스 기반 패닝 기능을 제공하기도 합니다.

4.4.6 mouseenter

유형 mouseenter
인터페이스 MouseEvent
동기 / 비동기 동기
버블링 아니요
신뢰할 수 있는 대상 Element
취소 가능 아니요
Composed 아니요
기본 동작 없음
컨텍스트
(신뢰할 수 있는 이벤트)
사용자 에이전트는 포인팅 장치가 어떤 요소 또는 그 자손 요소 중 하나의 경계로 이동했을 때 이 이벤트를 MUST 디스패치해야 합니다. 또한 요소 또는 그 자손 중 하나가 이동하여 주 포인팅 장치 아래에 놓이게 되었을 때도 이 이벤트를 MUST 디스패치해야 합니다. 이 이벤트 유형은 mouseover와 유사하지만, 버블링되지 않으며, 포인팅 장치가 한 요소에서 그 자손 요소 중 하나의 경계로 이동할 때에는 디스패치되어서는 안 됩니다(MUST NOT).
참고

이 이벤트 유형과 CSS의 :hover 의사 클래스 [CSS2] 사이에는 유사점이 있습니다. 또한 mouseleave 이벤트 유형도 참고하세요.

4.4.7 mouseleave

유형 mouseleave
인터페이스 MouseEvent
동기 / 비동기 동기
버블링 아니요
신뢰할 수 있는 대상 Element
취소 가능 아니요
Composed 아니요
기본 동작 없음
컨텍스트
(신뢰할 수 있는 이벤트)
사용자 에이전트는 포인팅 장치가 어떤 요소 및 그 모든 자손 요소의 경계 밖으로 이동했을 때 이 이벤트를 MUST 디스패치해야 합니다. 또한 요소 또는 그 자손 중 하나가 이동하여 주 포인팅 장치 아래에 더 이상 놓이지 않게 되었을 때도 이 이벤트를 MUST 디스패치해야 합니다. 이 이벤트 유형은 mouseout와 유사하지만, 버블링되지 않으며, 포인팅 장치가 요소의 경계와 그 모든 자식의 경계를 떠나기 전까지는 디스패치되어서는 안 됩니다(MUST NOT).
참고

이 이벤트 유형과 CSS의 :hover 의사 클래스 [CSS2] 사이에는 유사점이 있습니다. 또한 mouseenter 이벤트 유형도 참고하세요.

4.4.8 mousemove

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

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

참고

이 이벤트는 DOM Level 2 Events에서는 취소 불가로 명시되어 있었지만, 사용자 에이전트 간의 기존 상호운용성을 반영하기 위해 변경되었습니다.

4.4.9 mouseout

유형 mouseout
인터페이스 MouseEvent
동기 / 비동기 동기
버블링
신뢰할 수 있는 대상 Element
취소 가능
Composed
기본 동작 없음
컨텍스트
(신뢰할 수 있는 이벤트)
사용자 에이전트는 포인팅 장치가 어떤 요소의 경계 밖으로 이동했을 때, 또는 요소가 이동하여 주 포인팅 장치 아래에 더 이상 놓이지 않게 되었을 때 이 이벤트를 MUST 디스패치해야 합니다. 이 이벤트 유형은 mouseleave와 유사하지만, 버블링되며, 포인팅 장치가 한 요소에서 그 자손 요소 중 하나의 경계로 이동할 때 디스패치되어야 합니다(MUST).
참고

mouseover 이벤트 유형도 참고하세요.

4.4.10 mouseover

유형 mouseover
인터페이스 MouseEvent
동기 / 비동기 동기
버블링
신뢰할 수 있는 대상 Element
취소 가능
Composed
기본 동작 없음
컨텍스트
(신뢰할 수 있는 이벤트)
사용자 에이전트는 포인팅 장치가 어떤 요소의 경계로 이동했을 때, 또는 요소가 이동하여 주 포인팅 장치 아래에 놓이게 되었을 때 이 이벤트를 MUST 디스패치해야 합니다. 이 이벤트 유형은 mouseenter와 유사하지만, 버블링되며, 동일한 이벤트 리스너 인스턴스에 대해 조상 요소가 동일한 target인 요소의 경계로 포인팅 장치가 이동할 때 디스패치되어야 합니다(MUST).
참고

mouseout 이벤트 유형도 참고하세요.

4.4.11 mouseup

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

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

5. 포인터 이벤트 및 인터페이스

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

포인터의 접촉 기하(contact geometry)에 대한 너비(X축 크기)이며, CSS 픽셀 단위입니다([CSS21] 참조). 이 값은 동일 포인터에 대해서도 각 이벤트마다 갱신될 수 있습니다(MAY). 일반적인 마우스처럼 접촉 기하가 보통 없는 입력의 경우, 그리고 입력의 실제 기하가 하드웨어에 의해 감지되지 않는 경우에는, 사용자 에이전트는 기본값 1을 반환해야 합니다(MUST).

height

포인터의 접촉 기하(contact geometry)에 대한 높이(Y축 크기)이며, CSS 픽셀 단위입니다([CSS21] 참조). 이 값은 동일 포인터에 대해서도 각 이벤트마다 갱신될 수 있습니다(MAY). 일반적인 마우스처럼 접촉 기하가 보통 없는 입력의 경우, 그리고 입력의 실제 기하가 하드웨어에 의해 감지되지 않는 경우에는, 사용자 에이전트는 기본값 1을 반환해야 합니다(MUST).

pressure

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

tangentialPressure

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

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

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

tiltX explanation diagram
그림 3 양의 tiltX.
tiltY

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

tiltY explanation diagram
그림 4 양의 tiltY.
twist

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

altitudeAngle

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

참고
여기에서 정의된 altitudeAngle의 기본값은 π/2이며, 이는 트랜스듀서가 표면에 수직으로 놓이도록 합니다. 이는 Touch Events - Level 2 명세의 altitudeAngle 속성 정의(기본값이 0)와 다릅니다.
altitudeAngle explanation diagram
그림 5 예: altitudeAngleπ/4인 경우(X-Y 평면으로부터 45도).
azimuthAngle

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

azimuthAngle explanation diagram
그림 6 예: azimuthAngleπ/6인 경우("4시").
pointerType

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

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

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

참고
기본적인 pointerType 사용 데모는 예 2를 참고하세요. 또한 개발자는 사용자 에이전트가 자체 커스텀 pointerType 값을 구현했을 수 있는 경우와, pointerType이 단순히 빈 문자열인 상황을 모두 포괄할 수 있도록 어떤 형태로든 기본 처리(default handling)를 포함해야 한다는 점에 유의하세요.
isPrimary

포인터가 이 포인터 유형의 주 포인터를 나타내는지 여부를 나타냅니다.

persistentDeviceId

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

참고
디지타이저 및 포인팅 장치 하드웨어 제약으로 인해, persistentDeviceId는 포인팅 장치에서 발생한 모든 포인터 이벤트에서 항상 사용 가능하다고 보장되지 않습니다. 예를 들어, 장치가 pointerdown에 대해 persistentDeviceId를 가지기 전에, 하드웨어 ID를 디지타이저에 제때 보고하지 못할 수 있습니다. 이러한 경우 persistentDeviceId는 처음에는 0일 수 있으며, 이후 유효한 값으로 변경될 수 있습니다.
getCoalescedEvents()

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

getPredictedEvents()

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

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

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

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

5.1.1 버튼 상태

5.1.1.1 코디드 버튼 상호작용

마우스나 펜 같은 일부 포인터 장치는 여러 개의 버튼을 지원합니다. [UIEVENTS] 마우스 이벤트 모델에서는 각 버튼 누름이 mousedownmouseup 이벤트를 생성합니다. 이러한 하드웨어 차이를 더 잘 추상화하고 장치 간 입력 작성(cross-device input authoring)을 단순화하기 위해, 포인터 이벤트는 코디드 버튼 누름(포인터 장치에서 한 버튼이 이미 눌린 상태에서 추가 버튼을 누르는 것)에 대해 겹치는 pointerdownpointerup 이벤트를 발생시키지 않습니다.

대신, 코디드 버튼 누름은 buttonbuttons 속성의 변화들을 검사하여 감지할 수 있습니다. buttonbuttons 속성은 MouseEvent 인터페이스에서 상속되지만, 다음 절에서 설명하는 대로 의미(semantics)와 값에 변경이 있습니다.

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 속성은 각 포인터 유형에 대해 활성 포인터 집합 중 마스터 포인터를 식별하는 데 사용됩니다.

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

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

e라는 이름의 포인터 이벤트를 발생시킨다는 것은, 이벤트를 발생시키는 것을 의미하며, PointerEvent를 사용해 PointerEvent 인터페이스 및 속성과 기본 동작에 정의된 대로 속성이 설정된 상태로 e라는 이름의 이벤트를 발생시키는 것을 말합니다.

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

이벤트가 발생되는 대상을 다음과 같이 대상 결정합니다:

targetDocument를 대상의 노드 문서 [DOM]로 둡니다.

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

이벤트가 pointerdown이고, 연결된 장치가 직접 조작 장치이며, 대상이 Element라면, 암시적 포인터 캡처에 설명된 대로, 이 pointerId에 대해 대상 요소로 포인터 캡처를 설정합니다.

이 이벤트를 발생시키기 전에, 사용자 에이전트이벤트 순서 보장 [UIEVENTS]의 목적을 위해, 대상을 previousTarget에서 포인팅 장치가 그 위로 이동해 온 것처럼 취급하는 것이 권장됩니다(SHOULD). needsOverEvent 플래그가 설정되어 있으면, 대상 요소가 동일하더라도 pointerover 이벤트가 필요합니다.

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

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

참고
일반적인 히트 테스트 결과 대신 포인터 캡처 대상 오버라이드를 대상으로 사용하는 경우, [UIEVENTS]에 정의된 일부 경계 이벤트가 발생할 수 있습니다. 이는 포인터가 이전 대상에서 떠나 새 캡처 대상에 들어가는 것과 동일합니다. 캡처가 해제될 때에도, 포인터가 캡처 대상에서 떠나 히트 테스트 대상으로 들어가는 방식으로 동일한 시나리오가 발생할 수 있습니다.
5.1.3.1 속성과 기본 동작

이 명세에서 정의하는 이벤트 유형들의 bubblescancelable 속성과 기본 동작은 다음 표에 나와 있습니다. 각 이벤트 유형의 상세 내용은 포인터 이벤트 유형에서 제공합니다.

이벤트 유형 버블링 취소 가능 기본 동작
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).

참고
많은 사용자 에이전트는 레거시 콘텐츠를 지원하기 위해 MouseEvent에 비표준 속성 fromElementtoElement를 노출합니다. 우리는 그러한 사용자 에이전트가, 작성자를 표준 대안(targetrelatedTarget) 사용으로 전환시키기 위해, PointerEvent에서 상속된 이러한 속성 값들을 null로 설정하도록 권장합니다.

MouseEventrelatedTarget과 유사하게, relatedTarget은 포인터가 막 떠난 요소의 경계를 나타내는 요소로 초기화되어야 합니다(예: pointerover 또는 pointerenter 이벤트의 경우). 또는 포인터가 들어가고 있는 요소의 경계를 나타내는 요소로 초기화되어야 합니다(예: pointerout 또는 pointerleave 이벤트의 경우). 다른 포인터 이벤트에 대해서는 이 값의 기본값은 null입니다. 요소가 포인터 캡처를 받으면, 해당 포인터에 대한 이후 모든 이벤트는 캡처 중인 요소의 경계 안에 있는 것으로 간주된다는 점에 유의하세요.

gotpointercapturelostpointercapture 이벤트의 경우, 위 표에 정의된 것들을 제외한 모든 속성은 사용자 에이전트가 대기 중인 포인터 캡처 처리 단계를 실행하고 gotpointercapturelostpointercapture 이벤트를 발생시키게 만든 포인터 이벤트와 동일해야 합니다.

5.1.3.2 대기 중인 포인터 캡처 처리

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

  1. 이 포인터에 대한 포인터 캡처 대상 오버라이드가 설정되어 있고, 대기 중인 포인터 캡처 대상 오버라이드와 같지 않다면, lostpointercapture라는 이름의 포인터 이벤트를 포인터 캡처 대상 오버라이드 노드에서 발생시킵니다.
  2. 이 포인터에 대한 대기 중인 포인터 캡처 대상 오버라이드가 설정되어 있고, 포인터 캡처 대상 오버라이드와 같지 않다면, gotpointercapture라는 이름의 포인터 이벤트를 대기 중인 포인터 캡처 대상 오버라이드에서 발생시킵니다.
  3. 포인터 캡처 대상 오버라이드를, 설정되어 있다면 대기 중인 포인터 캡처 대상 오버라이드로 설정합니다. 그렇지 않으면 포인터 캡처 대상 오버라이드를 지웁니다.
참고

click, auxclick, 및 contextmenu 이벤트 절에서 정의한 바와 같이, lostpointercapture 이벤트가 디스패치된 이후에도, 해당하는 click, auxclick 또는 contextmenu 이벤트가 있다면, 그 이벤트는 여전히 캡처 중인 대상(capturing target)으로 디스패치됩니다.

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

사용자 에이전트는 웹 페이지가 특정 pointerId에 대한 포인터 이벤트를 더 이상 계속 받을 가능성이 낮다고 감지하면 포인터 이벤트 스트림을 억제해야 합니다(MUST). 다음 시나리오 중 어느 하나라도 이 조건을 만족합니다(추가 시나리오가 있을 수도 있습니다(MAY)):

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

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

  • 포인터가 활성인 동안 장치의 화면 방향이 변경됩니다.
  • 사용자가 장치가 지원하는 것보다 더 많은 동시 포인터 입력으로 상호작용하려고 시도합니다.
  • 사용자 에이전트가 입력을 우발적인 것으로 해석합니다(예: 하드웨어가 팜 리젝션을 지원).

이러한 시나리오를 감지하는 방법은 본 명세의 범위를 벗어납니다.

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

5.1.4 레이아웃 변경으로 인해 발생하는 경계 이벤트

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

참고
정지 포인팅 장치(화면 표면에 대해 이동하지도 않았고 어떤 속성도 변경되지 않은)는 결코 pointermove 이벤트를 발생시키지 않습니다.

5.1.5 tiltX / tiltYaltitudeAngle / azimuthAngle 간 변환

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

특정 하드웨어와 플랫폼에 따라, 사용자 에이전트는 화면 평면에 대한 트랜스듀서 방향 값 집합 중 하나만 받을 가능성이 큽니다 — 즉 tiltX / tiltY 또는 altitudeAngle / azimuthAngle. 사용자 에이전트는 이 값들을 변환하기 위해 다음 알고리즘을 사용해야 합니다(MUST).

사용자 에이전트가 azimuthAngle / altitudeAngle로부터 tiltX / tiltY를 계산할 때는, Math.round [ECMASCRIPT] 규칙을 사용하여 최종 정수 값을 반올림하는 것이 권장됩니다(SHOULD).

8: tiltX/tiltY와 altitudeAngle/azimuthAngle 간 변환
/* Converting between tiltX/tiltY and altitudeAngle/azimuthAngle */

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

  let tiltXrad = 0;
  let tiltYrad = 0;

  if (altitudeAngle == 0) {
    // the pen is in the X-Y plane
    if (azimuthAngle == 0 || azimuthAngle == 2*Math.PI) {
      // pen is on positive X axis
      tiltXrad = Math.PI/2;
    }
    if (azimuthAngle == Math.PI/2) {
      // pen is on positive Y axis
      tiltYrad = Math.PI/2;
    }
    if (azimuthAngle == Math.PI) {
      // pen is on negative X axis
      tiltXrad = -Math.PI/2;
    }
    if (azimuthAngle == 3*Math.PI/2) {
      // pen is on negative Y axis
      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;

  // calculate 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) {
    // not enough information to calculate azimuth
    azimuthAngle = 0;
  } else {
    // Non-boundary case: neither tiltX nor tiltY is equal to 0 or +-90
    const tanX = Math.tan(tiltXrad);
    const tanY = Math.tan(tiltYrad);

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

  // calculate 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 {
    // Non-boundary case: neither tiltX nor tiltY is equal to 0 or +-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. MouseEvent 초기화event, eventTypeeventTarget, bubblescancelable로 실행합니다.
  2. 그 외 모든 속성을 기본 PointerEvent 값으로 초기화합니다.

5.2.2 PointerEvent 생성

eventTypeeventTarget, bubbles, cancelablePointerEvent를 생성하려면, 다음 단계를 실행합니다:

  1. event이벤트 생성PointerEvent를 사용해 수행한 결과로 둡니다.
  2. PointerEvent 초기화event, eventTypeeventTarget, bubblescancelable로 실행합니다.
  3. event를 반환합니다.

5.2.3 MouseEvent에서 PointerEvent 생성

  1. eventType를 이벤트 유형을 포함하는 DOMString으로 둡니다.
  2. mouseevent를 해당하는 MouseEvent로 둡니다.
  3. event이벤트 생성PointerEvent를 사용해 수행한 결과로 둡니다.
  4. targetmouseevent.target으로 둡니다.
  5. PointerEvent 초기화event, eventTypetarget으로 실행합니다.
  6. MouseEvent 속성을 mouseevent에서 event로 복사합니다.
  7. event를 반환합니다.

5.2.4 pointerout 이벤트를 보낼 수도 있음

  1. mouseout을 해당하는 mouseout MouseEvent로 둡니다.
  2. pointeroutMouseEvent에서 PointerEvent 생성을 "pointerout" 및 mouseout로 실행한 결과로 둡니다.
  3. pointerevent 속성 설정
    편집자 참고

    TODO.

  4. targetmouseout.target으로 둡니다.
  5. 디스패치 pointerouttarget에서 수행합니다.

5.2.5 pointerleave 이벤트를 보낼 수도 있음

  1. mouseout을 해당하는 mouseout MouseEvent로 둡니다.
  2. pointeroutMouseEvent에서 PointerEvent 생성을 "pointerout" 및 mouseout로 실행한 결과로 둡니다.
  3. pointerevent 속성 설정
    편집자 참고

    TODO.

  4. targetmouseout.target으로 둡니다.
  5. 디스패치 pointerouttarget에서 수행합니다.

5.2.6 pointerover 이벤트를 보낼 수도 있음

  1. mouseout을 해당하는 mouseout MouseEvent로 둡니다.
  2. pointeroutMouseEvent에서 PointerEvent 생성을 "pointerout" 및 mouseout로 실행한 결과로 둡니다.
  3. pointerevent 속성 설정
    편집자 참고

    TODO.

  4. targetmouseout.target으로 둡니다.
  5. 디스패치 pointerouttarget에서 수행합니다.

5.2.7 pointerenter 이벤트를 보낼 수도 있음

  1. mouseout을 해당하는 mouseout MouseEvent로 둡니다.
  2. pointeroutMouseEvent에서 PointerEvent 생성을 "pointerout" 및 mouseout로 실행한 결과로 둡니다.
  3. pointerevent 속성 설정
    편집자 참고

    TODO.

  4. targetmouseout.target으로 둡니다.
  5. 디스패치 pointerouttarget에서 수행합니다.

5.2.8 pointermove 이벤트를 보낼 수도 있음

  1. mouseout을 해당하는 mouseout MouseEvent로 둡니다.
    편집자 참고

    이것이 pointermove와 pointerrawupdate를 보낼 수 있나요? 아니면 2개의 메서드가 필요한가요?

    편집자 참고

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

  2. pointeroutMouseEvent에서 PointerEvent 생성을 "pointerout" 및 mouseout로 실행한 결과로 둡니다.
  3. pointerevent 속성 설정
    편집자 참고

    TODO.

  4. targetmouseout.target으로 둡니다.
  5. 디스패치 pointerouttarget에서 수행합니다.

5.2.9 pointerdown 이벤트를 보낼 수도 있음

  1. mouseout을 해당하는 mouseout MouseEvent로 둡니다.
    참고

    mousedown 이벤트와 달리, pointerdown 이벤트는 여러 버튼이 눌릴 때 중첩되지 않습니다. MouseEvent가 전달되는 이유는 그 필드들을 PointerEvent에 복사할 수 있게 하기 위함입니다.

  2. pointeroutMouseEvent에서 PointerEvent 생성을 "pointerout" 및 mouseout로 실행한 결과로 둡니다.
  3. pointerevent 속성 설정
    편집자 참고

    TODO.

  4. targetmouseout.target으로 둡니다.
  5. 디스패치 pointerouttarget에서 수행합니다.

5.2.10 pointerrawupdate 이벤트를 보낼 수도 있음

  1. mouseout을 해당하는 mouseout MouseEvent로 둡니다.
  2. targetmouseout.target으로 둡니다.
  3. 디스패치 pointerouttarget에서 수행합니다.

5.2.11 pointerup 이벤트를 보낼 수도 있음

  1. mouseout을 해당하는 mouseout MouseEvent로 둡니다.
    참고

    mouseup 이벤트와 달리, pointerup 이벤트는 여러 버튼이 눌릴 때 중첩되지 않습니다. MouseEvent가 전달되는 이유는 그 필드들을 PointerEvent에 복사할 수 있게 하기 위함입니다.

  2. pointeroutMouseEvent에서 PointerEvent 생성을 "pointerout" 및 mouseout로 실행한 결과로 둡니다.
  3. pointerevent 속성 설정
    편집자 참고

    TODO.

  4. targetmouseout.target으로 둡니다.
  5. 디스패치 pointerouttarget에서 수행합니다.

5.3 포인터 이벤트 유형

아래는 이 명세에서 정의하는 이벤트 유형입니다.

주 포인터의 경우, 이 이벤트들(gotpointercapturelostpointercapture는 예외)은 호환성 마우스 이벤트도 함께 발생시킬 수 있습니다.

5.3.1 pointerover 이벤트

사용자 에이전트MUST 다음 중 어느 하나라도 발생하면 포인터 이벤트를 발생시켜 pointerover라는 이름의 이벤트를 발생시켜야 합니다:

5.3.2 pointerenter 이벤트

사용자 에이전트MUST 다음 중 어느 하나라도 발생하면 포인터 이벤트를 발생시켜 pointerenter라는 이름의 이벤트를 발생시켜야 합니다:

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

5.3.3 pointerdown 이벤트

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

참고
마우스(또는 다른 다중 버튼 포인터 장치)의 경우, 이는 pointerdownpointerupmousedownmouseup과 동일한 모든 상황에서 발생되지 않음을 의미합니다. 자세한 내용은 코디드 버튼을 참고하세요.

호버를 지원하지 않는 입력 장치의 경우, 사용자 에이전트는 또한 MUST 포인터 이벤트를 발생시켜 pointerover라는 이름의 이벤트를 발생시킨 다음, 포인터 이벤트 pointerenter를 발생시키고, 그 후에 pointerdown 이벤트를 디스패치해야 합니다.

참고
작성자는 (isPrimary 속성이 true인 경우) pointerdown 이벤트를 취소함으로써 특정 호환성 마우스 이벤트의 발생을 방지할 수 있습니다. 이는 포인터에 PREVENT MOUSE EVENT 플래그를 설정합니다. 다만 이는 mouseover, mouseenter, mouseout, 또는 mouseleave 이벤트의 발생을 방지하지는 않습니다.

5.3.4 pointermove 이벤트

사용자 에이전트는 포인터가 pointerdown 또는 pointerup 이벤트를 발생시키지 않는 속성들 중 어떤 것이든 변경하면 MUST 포인터 이벤트를 발생시켜 pointermove라는 이름의 이벤트를 발생시켜야 합니다. 여기에는 좌표, 압력, 접선 압력, 기울기, 트위스트, 접촉 기하(widthheight) 또는 코디드 버튼의 어떤 변경도 포함됩니다.

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

5.3.5 pointerrawupdate 이벤트

사용자 에이전트는 포인터가 pointerdown 또는 pointerup 이벤트를 발생시키지 않는 속성들 중 어떤 것이든 변경할 때, MUST 포인터 이벤트를 발생시켜 pointerrawupdate라는 이름의 이벤트를 발생시켜야 하며, 또한 보안 컨텍스트 내에서만 이를 수행해야 합니다. 이러한 속성들의 목록은 pointermove 이벤트를 참고하세요.

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

pointerrawupdate 이벤트의 target은, pointermove 이벤트가 지연되거나 병합될 수 있고, 이벤트의 대상을 찾는 데 사용되는 최종 위치가 병합된 이벤트들과 다를 수 있기 때문에, pointermove 이벤트의 것과 다를 수 있습니다.

동일한 pointerId를 가지며 아직 이벤트 루프에서 디스패치되지 않은 다른 pointerrawupdate가 이미 있는 경우, 사용자 에이전트는 새로운 pointerrawupdate를 새 태스크를 만드는 대신 그 이벤트와 병합할 수도 있습니다(MAY). 이는 pointerrawupdate가 병합된 이벤트를 가지게 만들 수 있으며, 이벤트가 이벤트 루프에서 처리되는 즉시 하나의 pointerrawupdate 이벤트의 병합된 이벤트로 모두 전달됩니다. 자세한 내용은 getCoalescedEvents를 참고하세요.

pointerrawupdatepointermove의 순서에 관해서는, 플랫폼으로부터 두 이벤트 모두를 유발하는 업데이트를 사용자 에이전트가 받았다면, 사용자 에이전트MUST 해당하는 pointermove보다 먼저 pointerrawupdate 이벤트를 디스패치해야 합니다.

target을 제외하면, 마지막 pointermove 이벤트 이후 디스패치된 모든 pointerrawupdate 이벤트들의 병합된 이벤트 목록을 이어 붙인 것은, 다음 pointermove 이벤트의 병합된 이벤트와(다른 이벤트 속성들의 관점에서) 동일합니다. pointerrawupdate의 속성은 대부분 pointermove와 동일하지만, cancelable만은 예외이며 pointerrawupdate에서는 MUST false여야 합니다.

사용자 에이전트는 SHOULD 호환성 마우스 이벤트pointerrawupdate에 대해 발생시키지 말아야 합니다.

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

5.3.6 pointerup 이벤트

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

호버를 지원하지 않는 입력 장치의 경우, 사용자 에이전트는 또한 MUST 포인터 이벤트를 발생시켜 pointerout라는 이름의 이벤트를 발생시킨 다음, 포인터 이벤트 pointerleave를 발생시키고, 그 후에 pointerup 이벤트를 디스패치한 뒤에 수행해야 합니다.

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

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

참고
마우스(또는 다른 다중 버튼 포인터 장치)의 경우, 이는 pointerdownpointerupmousedownmouseup과 동일한 모든 상황에서 발생되지 않음을 의미합니다. 자세한 내용은 코디드 버튼을 참고하세요.

5.3.7 pointercancel 이벤트

사용자 에이전트포인터 이벤트 스트림을 억제하는 시나리오를 감지하면 MUST 포인터 이벤트를 발생시켜 pointercancel라는 이름의 이벤트를 발생시켜야 합니다.

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 이벤트

사용자 에이전트MUST 다음 중 어느 하나라도 발생하면 포인터 이벤트를 발생시켜 pointerout라는 이름의 이벤트를 발생시켜야 합니다:

5.3.9 pointerleave 이벤트

사용자 에이전트MUST 다음 중 어느 하나라도 발생하면 포인터 이벤트를 발생시켜 pointerleave라는 이름의 이벤트를 발생시켜야 합니다:

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

5.3.10 gotpointercapture 이벤트

사용자 에이전트는 요소가 포인터 캡처를 받으면 MUST 포인터 이벤트를 발생시켜 gotpointercapture라는 이름의 이벤트를 발생시켜야 합니다. 이 이벤트는 포인터 캡처를 받는 요소에서 발생합니다. 이후 해당 포인터에 대한 이벤트는 이 요소에서 발생됩니다. 포인터 캡처 설정대기 중인 포인터 캡처 처리 절을 참고하세요.

5.3.11 lostpointercapture 이벤트

사용자 에이전트는 포인터에 대한 포인터 캡처가 해제된 후 MUST 포인터 이벤트를 발생시켜 lostpointercapture라는 이름의 이벤트를 발생시켜야 합니다. 이 이벤트는 캡처가 해제된 이후 해당 포인터에 대한 이후 이벤트들보다 먼저 발생되어야 합니다(MUST). 이 이벤트는 포인터 캡처가 제거된 요소에서 발생합니다. 이후 해당 포인터에 대한 모든 이벤트는( click, auxclick, 및 contextmenu 이벤트는 예외) 이벤트 타깃을 결정하기 위해 일반적인 히트 테스트 메커니즘(이 명세의 범위를 벗어남)을 따릅니다. 포인터 캡처 해제, 포인터 캡처의 암시적 해제, 그리고 대기 중인 포인터 캡처 처리 절을 참고하세요.

5.3.12 click, auxclick, 및 contextmenu 이벤트

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

이 이벤트들은 MUST PointerEvent 타입이어야 하며, 이 절의 나머지에서 언급하는 추가 요구사항을 따릅니다.

5.3.12.1 이벤트 속성

이 이벤트들에 대해, pointerIdpointerType을 제외한(이 명세에서 정의한) 모든 PointerEvent 전용 속성은 기본값을 가져야 합니다(MUST). 또한:

  • 이 이벤트들이 포인팅 장치에 의해 생성된 경우, 그 pointerIdpointerType은 이 이벤트들을 유발한 PointerEvents와 동일해야 합니다(MUST).
  • 이 이벤트들이 비포인팅 장치(예: 음성 인식 소프트웨어 또는 키보드 상호작용)에 의해 생성된 경우, pointerIdMUST -1이어야 하며, pointerTypeMUST 빈 문자열이어야 합니다.
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에만 구현한 사용자 에이전트는 MUST click, auxclick, 및 contextmenu에 대한 다양한 좌표 속성을 Math.floor [ECMASCRIPT]를 사용하여(원래 UI Events에 정의된 대로) long 값으로 변환해야 합니다.

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가 아니라면, [UIEVENTS] 명세에 따라 event를 디스패치하되, event의 타깃을 오버라이드하지 말고, 아래의 나머지 단계를 건너뜁니다.
  3. target을 다음과 같이 정의합니다:

    eventcontextmenu 이벤트이거나, 해당 포인터가 캡처된 동안 userEvent가 디스패치되었다면, targetuserEvent의 타깃으로 둡니다.

    그렇지 않으면(eventclick 또는 auxclick 이벤트이고, userEvent가 캡처되지 않은 상태로 디스패치된 pointerup 이벤트인 경우), event가 디스패치되는 시점의 DOM에서 해당하는 pointerdownpointerup 타깃의 가장 가까운 공통 포함 조상( inclusive ancestor )을 target으로 둡니다.

  4. [UIEVENTS] 명세에 따라 eventtarget에 디스패치합니다.

    참고
    userEvent가 캡처된 경우, 동일한 pointerId를 가진 lostpointercapture 이벤트가 이미 디스패치되었더라도, eventuserEvent의 캡처 대상에 디스패치됩니다.

6. 휠 이벤트

휠은 하나 이상의 공간 차원에서 회전할 수 있으며, 포인터 장치와 연관될 수 있는 장치입니다. 좌표계는 환경 구성에 따라 달라집니다.

사용자의 환경은 세로 스크롤을 y축을 따라 회전하는 것과, 가로 스크롤을 x축을 따라 회전하는 것과, 확대/축소를 z축을 따라 회전하는 것과 연관시키도록 구성될 수 있습니다.

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

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

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

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

사용자 에이전트는 첫 번째 휠 이벤트가 발생할 때 MUST 휠 이벤트 트랜잭션을 생성해야 하며, 구현별로 정해진 일정 시간 내에 이어서 발생하는 모든 후속 휠 이벤트들이 동일한 요소를 대상으로 하게 해야 합니다. 휠 이벤트 트랜잭션은 단일 사용자 제스처와 연관된 일련의 휠 이벤트입니다. 이 휠 이벤트 트랜잭션은, 그룹 내에서 첫 번째 휠 이벤트가 발생하는 시점의 최상위 이벤트 대상을 연관된 이벤트 대상으로 가져야 합니다(MUST).

스크롤 가능한 요소에서 대상이 된 일련의 휠 이벤트가 어떤 자식 요소 위에서 시작되면, 동일한 사용자 제스처에 대한 이후 이벤트들은 그 자식 요소 위에서 발생할 수 있습니다.

6.1 WheelEvent 인터페이스

WheelEvent 인터페이스는 wheel 이벤트와 연관된 특정 컨텍스트 정보를 제공합니다. WheelEvent 인터페이스의 인스턴스를 생성하려면, WheelEvent 생성자를 사용하고, 선택적 WheelEventInit 딕셔너리를 전달합니다.

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;
};
DOM_DELTA_PIXEL
델타에 대한 측정 단위는 픽셀이어야 합니다(MUST). 이는 대부분의 운영체제 및 구현 구성에서 가장 일반적인 경우입니다.
DOM_DELTA_LINE
델타에 대한 측정 단위는 개별 텍스트 줄이어야 합니다(MUST). 이는 많은 폼 컨트롤에서 해당됩니다.
DOM_DELTA_PAGE
델타에 대한 측정 단위는 페이지여야 합니다(MUST). 페이지는 단일 화면으로 정의될 수도 있고, 구분된 페이지로 정의될 수도 있습니다.
deltaX
wheel 이벤트의 기본 동작이 스크롤인 사용자 에이전트에서는, 이벤트가 취소되지 않은 경우 스크롤될 x축 방향의 측정값(픽셀, 줄, 또는 페이지 단위)이어야 합니다(MUST). 그렇지 않으면 이는 x축을 중심으로 한 휠 장치의 이동에 대한 구현별 측정값(픽셀, 줄, 또는 페이지 단위)입니다. 이 속성의 초기화되지 않은 값MUST 0.0이어야 합니다.
deltaY
wheel 이벤트의 기본 동작이 스크롤인 사용자 에이전트에서는, 이벤트가 취소되지 않은 경우 스크롤될 y축 방향의 측정값(픽셀, 줄, 또는 페이지 단위)이어야 합니다(MUST). 그렇지 않으면 이는 y축을 중심으로 한 휠 장치의 이동에 대한 구현별 측정값(픽셀, 줄, 또는 페이지 단위)입니다. 이 속성의 초기화되지 않은 값MUST 0.0이어야 합니다.
deltaZ
wheel 이벤트의 기본 동작이 스크롤인 사용자 에이전트에서는, 이벤트가 취소되지 않은 경우 스크롤될 z축 방향의 측정값(픽셀, 줄, 또는 페이지 단위)이어야 합니다(MUST). 그렇지 않으면 이는 z축을 중심으로 한 휠 장치의 이동에 대한 구현별 측정값(픽셀, 줄, 또는 페이지 단위)입니다. 이 속성의 초기화되지 않은 값MUST 0.0이어야 합니다.
deltaMode
deltaMode 속성은 델타 값들에 대한 측정 단위를 나타냅니다. 기본값은 DOM_DELTA_PIXEL(픽셀)입니다. 이 속성은 델타 값의 측정 단위를 나타내기 위해 DOM_DELTA 상수 중 하나로 설정되어야 합니다(MUST). 정확한 측정은 장치, 운영 체제, 애플리케이션 구성에 따라 다릅니다. 이 속성의 초기화되지 않은 값MUST 0이어야 합니다.

6.1.2 WheelEventInit

WebIDLdictionary WheelEventInit : MouseEventInit {
	double deltaX = 0.0;
	double deltaY = 0.0;
	double deltaZ = 0.0;
	unsigned long deltaMode = 0;
};
deltaX
deltaZ 속성을 참고하세요.
deltaY
deltaZ 속성을 참고하세요.
deltaZ
deltaZ 속성을 WheelEvent 객체에서 초기화합니다. 이 속성(및 deltaX, deltaY 속성)의 상대적인 양수 값은, X, Y, Z 축이 각각 문서의 오른쪽 끝, 아래쪽 끝, 그리고 가장 먼 깊이(사용자에게서 멀어지는 방향)를 향하는 오른손 좌표계에 의해 주어집니다. 상대적인 음수 값은 각 축의 반대 방향입니다.
deltaMode
deltaMode 속성을 WheelEvent 객체에서 열거 값 0, 1 또는 2로 초기화합니다. 이는 휠의 회전이 스크롤을 유발했을 경우의 스크롤된 픽셀 수 (DOM_DELTA_PIXEL), 스크롤된 줄 수 (DOM_DELTA_LINE), 또는 스크롤된 페이지 수 (DOM_DELTA_PAGE)를 나타냅니다.

6.2 휠 이벤트 유형

6.2.1 wheel

Type wheel
Interface WheelEvent
Sync / Async 비동기
Bubbles
Trusted Targets Element
Cancelable 상황에 따라 다름
Composed
Default action 문서를 스크롤(또는 확대/축소)
Context
(trusted events)
  • Event.target : 현재 휠 이벤트 트랜잭션의 요소 대상
  • 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 이 이벤트를 디스패치해야 합니다. 플랫폼 및 입력 장치에 따라, 대각선 휠 델타는 여러 개의 0이 아닌 축을 가진 단일 wheel 이벤트로 전달될 수도 있고, 0이 아닌 각 축마다 별도의 wheel 이벤트로 전달될 수도 있습니다. wheel 이벤트 유형의 일반적인 기본 동작은 표시된 양만큼 문서를 스크롤(또는 경우에 따라 확대/축소)하는 것입니다. 이 이벤트가 취소되면, 구현은 MUST NOT 문서를 스크롤하거나 확대/축소(또는 이 이벤트 유형과 연관된 다른 구현별 기본 동작을 수행)해서는 안 됩니다.
참고

일부 사용자 에이전트 또는 일부 입력 장치에서는, 휠이 회전된 속도가 델타 값에 영향을 줄 수 있으며, 더 빠른 속도는 더 높은 델타 값을 만들 수 있습니다.

6.2.2 휠 이벤트의 취소 가능성

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

특히, 사용자 에이전트는 이벤트에 대해 비수동(non-passive) 리스너가 없음을 관찰할 때 오직 취소 불가능한 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
이벤트 핸들러 IDL 속성으로서, pointerover 이벤트 유형에 해당합니다.
onpointerenter
이벤트 핸들러 IDL 속성으로서, pointerenter 이벤트 유형에 해당합니다.
onpointerdown
이벤트 핸들러 IDL 속성으로서, pointerdown 이벤트 유형에 해당합니다.
onpointermove
이벤트 핸들러 IDL 속성으로서, pointermove 이벤트 유형에 해당합니다.
onpointerrawupdate
이벤트 핸들러 IDL 속성으로서, pointerrawupdate 이벤트 유형에 해당합니다.
onpointerup
이벤트 핸들러 IDL 속성으로서, pointerup 이벤트 유형에 해당합니다.
onpointercancel
이벤트 핸들러 IDL 속성으로서, pointercancel 이벤트 유형에 해당합니다.
onpointerout
이벤트 핸들러 IDL 속성으로서, pointerout 이벤트 유형에 해당합니다.
onpointerleave
이벤트 핸들러 IDL 속성으로서, pointerleave 이벤트 유형에 해당합니다.
ongotpointercapture
이벤트 핸들러 IDL 속성으로서, gotpointercapture 이벤트 유형에 해당합니다.
onlostpointercapture
이벤트 핸들러 IDL 속성으로서, lostpointercapture 이벤트 유형에 해당합니다.

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

Navigator 인터페이스는 [HTML]에서 정의됩니다. 이 명세는 장치 감지 지원을 제공하기 위해 Navigator 인터페이스를 확장합니다.

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

게터(getter) 단계는 다음과 같습니다:

  1. 에뮬레이트된 maxTouchPointsWebDriver BiDi 에뮬레이트된 최대 터치 포인트 [WEBDRIVER-BIDI]의 결과로 둡니다.
  2. 에뮬레이트된 maxTouchPoints가 null이 아니라면, 에뮬레이트된 maxTouchPoints를 반환합니다.
  3. 장치가 지원하는 동시 터치 접촉의 최대 개수를 반환합니다. 여러 디지타이저(예: 다중 터치스크린)를 가진 장치의 경우, 값은 각 개별 디지타이저가 지원하는 최대 접촉 수들의 집합 중 최댓값이어야 합니다(MUST).

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

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

10. 직접 조작 동작 선언

속성 및 기본 동작에서 언급했듯이, 뷰포트 조작(패닝 및 확대/축소)은 포인터 이벤트를 취소하는 것만으로 억제할 수 없습니다. 대신 작성자는 touch-action CSS 속성을 사용하여, 이 동작들 중 어떤 것을 허용하고 어떤 것을 억제할지 선언적으로 정의해야 합니다.

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

10.1 touch-action CSS 속성

Name: touch-action
Value: auto | none | [ [ pan-x | pan-left | pan-right ] || [ pan-y | pan-up | pan-down ] ] | manipulation
Initial: auto
Applies to: 비대체 인라인 요소, 테이블 행, 행 그룹, 테이블 열, 및 열 그룹을 제외한 모든 요소
Inherited: 아니오
Percentages: N/A
Media: 시각적
Computed value: 지정된 값과 동일
Canonical order: 문법에 따름
Animation type: 애니메이션 불가

touch-action CSS 속성은(속성의 이름과 달리 터치에만 제한되지 않는) 직접 조작 상호작용이 사용자 에이전트의 패닝 및 확대/축소 동작을 유발할 수 있는지 여부를 결정합니다(MAY). touch-action 절을 참고하세요.

패닝 또는 확대/축소를 시작하기 직전에, 다음 조건이 모두 참이면 사용자 에이전트MUST 포인터 이벤트 스트림을 억제해야 합니다:

참고
일부 사용자 에이전트는, 여러 개의 개별적인 이산 제스처들의 연쇄를 포함하지만 단일 연속 제스처의 일부로 취급되는 동작을 위해 복잡한 제스처를 구현합니다. 예를 들어 터치스크린에서의 "플링하여 스크롤" 제스처를 생각해 봅시다: 사용자는 빠른 손가락 움직임으로 문서를 패닝하기 시작하고, 터치스크린에서 손가락을 떼면 문서는 시뮬레이션된 관성으로 패닝을 계속합니다. 문서가 여전히 움직이는 동안, 사용자는 터치스크린에 손가락을 다시 올려 또 다른 "플링"을 실행해 패닝에 추가적인 운동량을 주거나, 현재 패닝을 상쇄하여 속도를 줄이거나, 완전히 멈추거나, 패닝 방향을 반대로 바꿀 수 있습니다. 이 명세는 제스처와 동작이 어떻게 구현되는지 규범적으로 정의하지 않으므로, 두 번째 터치가(두 번째 "플링" 또는 현재 패닝에 대한 상쇄 동작으로 해석되기 전까지) 포인터 이벤트를 발생시키는지 여부는 사용자 에이전트가 결정합니다.
참고
touch-action은 내장된 브라우징 컨텍스트로 적용/전파되지 않습니다. 예를 들어 <iframe>touch-action을 적용하더라도, <iframe> 자체 내부에서의 패닝 및 확대/축소를 위한 직접 조작 상호작용 동작에는 아무런 영향이 없습니다.

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

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

참고
일부 사용자 에이전트는 여러 개의 동시 포인터(예: 멀티터치)를 포함하는 패닝 및 확대/축소 상호작용을 지원합니다. 여러 동시 포인터의 touch-action 값들을 처리하거나 연관짓는 방법은 이 명세의 범위를 벗어납니다.

10.3 touch-action 값의 세부 사항

touch-action 속성은 뷰포트 패닝 및 확대/축소와 관련된 직접 조작 동작을 다룹니다. 텍스트 선택/강조 표시, 링크 및 폼 컨트롤 활성화와 같은 추가적인 사용자 에이전트 동작은 이 CSS 속성에 의해 영향을 받아서는 안 됩니다(MUST NOT).

참고
"패닝(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 속성을 block과 같이 widthheight를 지원하는 값으로 설정할 수 있습니다. 향후 명세는 이 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>
        이 요소에서의 직접 조작 상호작용은 부모를 조작하기 위해 소비될 수도 있습니다(MAY).
    </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 소개

이 절은 규범적이지 않습니다.

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

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

11.2 포인터 캡처 설정

포인터 캡처는 Element 타입의 element에 대해 element.setPointerCapture(pointerId) 메서드를 호출함으로써 설정됩니다. 이 메서드가 호출되면, 사용자 에이전트MUST 다음 단계를 실행해야 합니다:

  1. 메서드 인수로 제공된 pointerId가 어떤 활성 포인터와도 일치하지 않으면, "NotFoundError" DOMExceptionthrow합니다.
  2. pointer를, 주어진 pointerId로 지정된 활성 포인터로 둡니다.
  3. element연결됨(connected)이 아니라면 [DOM], "InvalidStateError" DOMExceptionthrow합니다.
  4. 이 메서드가 element노드 문서(node document) [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 암시적 포인터 캡처

패닝 및 확대/축소를 위한 직접 조작 상호작용을 구현하는 입력(예: 터치스크린에서의 터치 또는 스타일러스)은, 어떤 setPointerCapture가 모든 pointerdown 리스너가 호출되기 직전에 대상 요소에서 호출된 것과 정확히 동일하게 동작해야 합니다(SHOULD). hasPointerCapture API는(예: pointerdown 리스너에서) 이것이 발생했는지 여부를 결정하는 데 사용될 수 있습니다. 다음 포인터 이벤트가 발생하기 전에 포인터에 대해 releasePointerCapture가 호출되지 않으면, 캡처가 활성 상태임을 나타내기 위해(정상적으로) 대상에 gotpointercapture 이벤트가 디스패치됩니다.

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

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

pointerup 또는 pointercancel 이벤트를 발생시킨 직후, 사용자 에이전트MUST 방금 디스패치된 pointerId에 대해, 대기 중인 포인터 캡처 대상 오버라이드를 비운 뒤, 필요하다면 lostpointercapture를 발생시키기 위해 대기 중인 포인터 캡처 처리 단계를 실행해야 합니다. 대기 중인 포인터 캡처 처리 단계를 실행한 후, 포인터가 호버를 지원한다면, 사용자 에이전트MUST 캡처가 없는 포인터의 현재 위치를 반영하는 데 필요한 해당 경계 이벤트도 전송해야 합니다.

포인터 캡처 대상 오버라이드가 더 이상 연결됨이 아니라면 [DOM], 포인터 캡처 대상 오버라이드는 문서로 설정되어야 합니다(SHOULD).

대기 중인 포인터 캡처 대상 오버라이드가 더 이상 연결됨이 아니라면 [DOM], 대기 중인 포인터 캡처 대상 오버라이드 노드는 비워져야 합니다(SHOULD).

참고
앞의 두 문단은 캡처 노드가 제거된 후 다음 대기 중인 포인터 캡처 처리에서, 캡처된 포인터에 해당하는 lostpointercapture 이벤트가 문서에서 발생하게 만듭니다.

포인터 락 [PointerLock]이 요소에 성공적으로 적용되면, 사용자 에이전트MUST 어떤 요소가 캡처되었거나 캡처 대기 중인 상태라면, releasePointerCapture 메서드가 호출된 것처럼 단계를 실행해야 합니다.

12. 병합 및 예측 이벤트

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

12.1 병합된 이벤트

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

곡선의 확대 뷰로, 병합된 점과 병합되지 않은 점을 보여줌
그림 8 드로잉 애플리케이션에서의 곡선 예시 — pointermove 이벤트의 병합된 좌표만 사용하면(회색 점), 곡선이 눈에 띄게 각지고 울퉁불퉁해집니다; getCoalescedEvents()가 제공하는 더 세밀한 점(빨간 원)을 사용해 동일한 선을 그리면 포인터 이동에 대한 더 부드러운 근사치를 얻습니다.

PointerEvent에는 연관된 병합된 이벤트 목록이 있으며 (0개 이상의 PointerEvent의 목록), 신뢰된(trusted) pointermovepointerrawupdate 이벤트에 대해, 이 목록은 이 이벤트로 병합된 모든 PointerEvent들의 시퀀스입니다. "부모(parent)" 신뢰된 pointermovepointerrawupdate 이벤트는 이러한 병합된 이벤트들의 누적을 나타내지만, 추가적인 처리(예: 디스플레이 리프레시 레이트에 맞추기)가 있을 수 있습니다. 그 결과, 이러한 이벤트들의 병합된 이벤트 목록은 항상 최소 1개의 이벤트를 포함합니다. 다른 모든 신뢰된 이벤트 유형에 대해서는 빈 목록입니다. 신뢰되지 않은(untrusted) 이벤트의 병합된 이벤트 목록은 생성자에 전달된 값으로 초기화됩니다.

참고
신뢰된 부모 이벤트는 병합된 이벤트들의 요약 또는 집계이므로, 개발자는 보통 부모 이벤트 또는 병합된 이벤트 전체 중 하나만 처리하면 되며, 둘 다를 처리할 필요는 없습니다.
참고
병합된 이벤트 목록을 포함하는 신뢰된 이벤트가 JavaScript에서 재-디스패치되면, 이벤트 디스패치 알고리즘은 해당 이벤트의 isTrusted 비트를 false로 설정하지만, 병합된 이벤트 목록에 있는 이벤트들의 동일 비트는 원래의 true 값에서 변경되지 않습니다.

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

Example 14: 병합된 이벤트 목록을 사용하는 기본 캔버스 드로잉 애플리케이션
<style>
    /* 캔버스 요소에서의 모든 이벤트가 애플리케이션에 전달되도록,
    (패닝 또는 확대/축소 같은) 사용자 에이전트의 고유 직접 조작 동작을 비활성화한다. */

    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 이벤트들의 디스패치를 유발하는 경우, 사용자 에이전트MUST 먼저 해당 pointerId의 모든 병합된 이벤트를 포함하는 pointermove 이벤트 1개를 디스패치하고, 그 뒤에 pointerdown 이벤트를 디스패치해야 합니다.

참고

다음은 실제 이벤트가 timeStamp 값이 증가하는 순서로 발생하는 것과, 사용자 에이전트가 디스패치하는 이벤트의 예시입니다:

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

12.2 예측 이벤트

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

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

PointerEvent에는 연관된 예측 이벤트 목록이 있으며 (0개 이상의 PointerEvent의 목록), 신뢰된 pointermove 이벤트의 경우, 사용자 에이전트가 이후에 이어질 것이라고 예측하는 PointerEvent들의 시퀀스입니다. 다른 모든 신뢰된 이벤트 유형에 대해서는 빈 목록입니다. 신뢰되지 않은 이벤트는 생성자에 전달된 값으로 예측 이벤트 목록이 초기화됩니다.

참고

pointerrawupdate 이벤트는 비어 있지 않은 병합된 이벤트 목록을 가질 수도 있지만, 성능상의 이유로 예측 이벤트 목록은 보통 빈 목록입니다.

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

목록에 포함되는 이벤트 수와 현재 타임스탬프로부터 얼마나 떨어져 있는지는 사용자 에이전트 및 사용되는 예측 알고리즘에 의해 결정됩니다.

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

참고

작성자는 다음 포인터 이벤트가 디스패치될 때까지만 예측 이벤트를 유효한 예측으로 고려해야 합니다. 사용자 에이전트가 미래를 얼마나 멀리까지 예측하는지에 따라, 일반 포인터 이벤트가 하나 이상의 예측 이벤트 타임스탬프보다 더 일찍 디스패치될 수도 있습니다.

Example 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. 마우스 이벤트와의 호환성 매핑

현재 존재하는 웹 콘텐츠의 대다수는 마우스 이벤트만을 대상으로 코딩되어 있습니다. 아래에서는 이러한 콘텐츠와의 호환성을 위해 사용자 에이전트가 일반적인 포인터 입력을 마우스 이벤트로 매핑할 수 있는(MAY) 알고리즘을 설명합니다.

마우스 이벤트와의 호환성 매핑은 이 명세의 선택적(OPTIONAL) 기능입니다. 사용자 에이전트는 기존 레거시 콘텐츠와의 최상의 호환성을 위해 이 기능을 지원하도록 권장됩니다.

참고

개략적으로, 호환성 마우스 이벤트는 해당 포인터 이벤트들과 "교차(interleaved)"되도록 의도됩니다. 하지만 이 구체적인 순서는 필수는 아니며, 호환성 마우스 이벤트를 구현한 사용자 에이전트는 상대적 순서가 일관되기만 하면(MAY) 마우스 이벤트의 디스패치를 지연시키거나 묶어서(group) 디스패치하기로 결정할 수 있습니다.

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

호환성 마우스 이벤트 지원 여부와 관계없이, 사용자 에이전트는 click, auxclick, contextmenu 이벤트를 항상 지원해야 합니다(MUST). 왜냐하면 이 이벤트들은 PointerEvent 타입이며, 따라서 호환성 마우스 이벤트가 아니기 때문입니다. 포인터 이벤트 중에 preventDefault를 호출하는 것은 click, auxclick, 또는 contextmenu가 발생하는지 여부에 영향을 주어서는 안 됩니다(MUST NOT).

참고

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

또한 사용자 에이전트는 click, auxclick, 또는 contextmenu 이벤트를 발생시킬지 여부를 결정하기 위해 자체 휴리스틱을 적용할 수 있습니다. 일부 사용자 에이전트는 동일 타입의 다른(비-프라이머리) 포인터가 존재하거나, 다른 타입의 다른 프라이머리 포인터가 존재하면 이러한 이벤트를 발생시키지 않기로 선택할 수 있습니다. 사용자 에이전트는 특정 동작이 "깔끔한(clean)" 탭, 클릭, 또는 롱프레스가 아니라고(예: 터치스크린에서 손가락이 화면에 접촉한 상태에서 상호작용에 너무 많은 이동이 포함된 경우) 판단하고, click, auxclick, 또는 contextmenu 이벤트를 발생시키지 않기로 결정할 수 있습니다. 사용자 에이전트 동작의 이러한 측면은 이 명세에서 정의되지 않으며, 구현마다 다를 수 있습니다.

달리 명시되지 않는 한, 매핑된 마우스 이벤트의 대상은 대상이 더 이상 ownerDocument의 트리에 참여하지 않는 경우를 제외하고, 해당 포인터 이벤트의 대상과 동일해야 합니다(SHOULD). 이 경우 마우스 이벤트는 원래 대상의, 여전히 ownerDocument의 트리에 참여하는 가장 가까운 조상 노드(트리에서 제거되던 시점에)를 대상으로 발생해야 하며, 이는 마우스 이벤트를 위해(새 대상 노드를 기반으로) 새로운 이벤트 경로가 구축됨을 의미합니다.

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

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

mouseover, mouseout, mouseenter, mouseleave 이벤트는 (포인터가 내려가 있더라도) 절대로 방지되지 않습니다.

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

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

프라이머리 포인터만이 호환성 마우스 이벤트를 생성할 수 있지만, 복수의 프라이머리 포인터가 동시에 활성일 수 있으며, 각각이 자신의 호환성 마우스 이벤트를 생성할 수 있습니다. MouseEvents에 의존하는 스크립트와의 호환성을 위해, 마우스 전환 이벤트(mouseover, mouseout, mouseenter, mouseleave)는 단일 레거시 마우스 입력의 이동을 시뮬레이션해야 합니다(SHOULD). 이는 [UIEVENTS]에 따라, 모든 이벤트 대상에 대한 진입/이탈 상태가 유효함을 의미합니다. 사용자 에이전트는 문서에서 다음과 같이 레거시 마우스 포인터의 유효 위치를 유지함으로써 이를 보장해야 합니다(SHOULD).

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

  1. T를 디스패치되는 pointerdown, pointerup 또는 pointermove 이벤트의 대상으로 둡니다. pointerleave 이벤트의 경우 T를 설정 해제합니다.
  2. T와 현재 레거시 마우스 포인터의 유효 위치가 둘 다 설정 해제되어 있거나, 혹은 서로 같다면, 이 단계를 종료합니다.
  3. 현재 레거시 마우스 포인터의 유효 위치에서 T로 이동하는 마우스에 대해, [UIEVENTS]에 따라 mouseover, mouseout, mouseenter, mouseleave 이벤트를 디스패치합니다. 현재 레거시 마우스 포인터의 유효 위치 또는 T 중 하나라도 설정 해제된 값이라면, 이를 창 밖(out-of-window) 마우스 위치로 간주합니다.
  4. 레거시 마우스 포인터의 유효 위치T로 설정합니다.
참고

레거시 마우스 포인터의 유효 위치는, 포인터 전환 이벤트(pointerover, pointerout, pointerenter, pointerleave)에서 대응하는 레거시 마우스 전환 이벤트(mouseover, mouseout, mouseenter, mouseleave)로의 직접적인 매핑을 항상 가질 수는 없다는 사실을 모델링합니다. 아래 애니메이션은, 단일 레거시 마우스 입력을 사용하여 두 프라이머리 포인터를 조정(reconcile)하기 위해 사용자 에이전트가 포인터 전환 이벤트보다 더 많은 레거시 마우스 전환 이벤트를 디스패치해야 하는 경우를 보여줍니다.

그림 10 마우스 포인터(흰색 커서)와 터치 포인터(흰색 "손" 커서)가 동시에 존재하여, 단일 레거시 마우스 입력(주황색 커서)이 두 포인터 사이를 오가도록 만드는 상황.

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

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

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

  1. 디스패치될 포인터 이벤트의 isPrimary 속성이 false라면, 포인터 이벤트를 디스패치하고 이 단계를 종료합니다.
  2. 디스패치될 포인터 이벤트가 pointerdown, pointerup 또는 pointermove 이벤트이거나, window에서의 pointerleave 이벤트라면, 레거시 마우스 포인터의 유효 위치 추적에서 설명한 대로 호환성 마우스 전환 이벤트를 디스패치합니다.
  3. 포인터 이벤트를 디스패치합니다.
  4. 디스패치된 포인터 이벤트가 pointerdown이고, 이벤트의 취소됨(canceled) 플래그가 설정되어 있다면, 이 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) 플래그가 설정되어 있다면, 이 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]에서 정의됨)와 포인터 이벤트를 모두 지원한다면, 사용자 에이전트MUST NOT 이 절에서 설명한 호환성 마우스 이벤트와, [TOUCH-EVENTS]에 개요로 제시된 대체(fallback) 마우스 이벤트둘 다 생성해서는 안 됩니다.

참고

호버를 지원하지 않는 프라이머리 포인터(예: 터치스크린에서의 한 손가락)로 요소를 활성화(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) 플래그가 설정되면, 이벤트 시퀀스는 다음과 같습니다:

  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. 보안 및 개인정보 보호 고려사항

이 부록에서는 포인터 이벤트 구현에 대한 보안 및 개인정보 보호 고려사항을 다룹니다. 논의는 이 명세에서 정의한 이벤트 모델, API 및 이벤트의 구현으로부터 직접 발생하는 보안 및 개인정보 보호 문제로 제한됩니다.

이 명세에서 정의된 많은 이벤트 유형은 사용자 동작에 대한 응답으로 디스패치됩니다. 이는 악의적인 이벤트 리스너가 사용자가 일반적으로 기밀로 간주할 정보를 획득할 수 있게 합니다. 예를 들어, 사용자가 페이지와 상호작용하는 동안 사용자의 마우스/스타일러스/손가락의 정확한 경로/이동입니다.

포인터 이벤트에는(사용자의 장치에서 지원되는 경우) 펜 입력이 잡히는 각도나 기울기, 접촉 표면의 기하, 스타일러스 또는 터치스크린에 가해지는 압력과 같은 추가 정보가 포함됩니다. 각도, 기울기, 기하 및 압력에 대한 정보는 사용자의 장치에 있는 센서와 직접적으로 연관되어 있으므로, 이 명세는 오리진이 이러한 센서에 접근할 수 있도록 합니다.

이러한 센서 데이터와, 사용된 입력 메커니즘 유형(마우스, 터치, 펜)을 판별할 수 있는 능력은 사용자 또는 사용자의 장치와 환경의 특성을 추론하는 데 사용될 수 있습니다. 이러한 추론된 특성과 장치/환경 정보는 그 자체로 민감할 수 있습니다. 예를 들어, 악의적인 사이트가 사용자가 보조 기술을 사용하고 있는지 여부를 추가로 추론할 수 있게 할 수 있습니다. 이 정보는 또한 사용자 프로필을 구축하거나, 특정 사용자를 “지문 채집(fingerprint)”하여 추적하는 목적으로 잠재적으로 사용될 수 있습니다.

완화책으로, 사용자 에이전트는 사용자가 특정 센서 데이터(예: 각도, 기울기, 압력)에 대한 접근을 비활성화할 수 있는 기능을 포함하는 것을 고려할 수 있으며, 그리고/또는 사용자로부터의 명시적 옵트인 이후에만 이를 사용할 수 있게 하는 것을 고려할 수 있습니다.

이 명세는 작성자가 “예측 이벤트(predicted events)”에 접근할 수 있는 방법을 정의합니다. 하지만 이 명세 자체는 사용자 에이전트가 예측에 사용해야 하는 알고리즘을 정의하지 않습니다. 명세 작성자는 알고리즘이 사용자가 수행 중인 현재 제스처와 관련된 선행 포인터 이벤트에만 의존하도록 예상합니다. 사용자 에이전트는 예측 알고리즘의 구체적인 구현이 다른 사이트에 걸친 사용자의 전체 상호작용 이력 같은 추가 데이터에 의존하지 않도록 보장할 책임이 있으며, 그러한 데이터는 사용자에 대한 민감한 정보를 드러내거나 사용자를 “지문 채집(fingerprint)”하여 추적하는 데 사용될 수 있습니다.

이러한 고려사항을 넘어, 작업 그룹은 이 명세가 다음을 만족한다고 믿습니다:

15. 용어집

이 절은 규범적이지 않습니다.

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

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

반면 pointerId, pointerType, isPrimary, 그리고 [UIEVENTS]의 마우스 이벤트 모델 속성 button, buttons, ctrlKey, shiftKey, altKey, metaKey는 센서 데이터와 관련되지 않으므로 측정 가능한 속성으로 간주되지 않습니다.

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

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

이 절은 규범적입니다. 다음 기능들은 폐기(obsolete)되었으며, 레거시 소프트웨어와의 호환성이 필요한 사용자 에이전트만 구현해야 합니다. 또한 [UIEvents]의 레거시 이벤트 초기화기도 참고하세요.

16.1 MouseEvent 인터페이스용 초기화기

WebIDLpartial interface MouseEvent {
	// 이 명세에서 폐기됨(Deprecated)
	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 Draft 전체 개정 이력을 참고하세요.

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;
};

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

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]
포인터 이벤트. Jacob Rossi; Matt Brubeck. W3C. 2019년 4월 4일. W3C 권고안. URL: https://www.w3.org/TR/pointerevents/
[PointerLock]
포인터 락. Vincent Scheib. W3C. 2016년 10월 27일. W3C 권고안. URL: https://www.w3.org/TR/pointerlock/
[RFC2119]
RFC에서 요구 수준을 나타내기 위해 사용하는 키워드. S. Bradner. IETF. 1997년 3월. 현행 모범 관행(BCP). URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC8174]
RFC 2119 키워드에서 대문자/소문자 사용의 모호성. B. Leiba. IETF. 2017년 5월. 현행 모범 관행(BCP). URL: https://www.rfc-editor.org/rfc/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월 10일. 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년 2월 10일. 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년 1월 25일. CRD. 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/