포인터 이벤트

레벨 3

W3C 후보 권고안 스냅샷

이 문서에 대한 자세한 정보
이 버전:
https://www.w3.org/TR/2025/CR-pointerevents3-20251106/
최신 발행 버전:
https://www.w3.org/TR/pointerevents3/
최신 에디터 초안:
https://w3c.github.io/pointerevents/
히스토리:
https://www.w3.org/standards/history/pointerevents3/
커밋 기록
테스트 스위트:
https://wpt.fyi/pointerevents/
구현 보고서:
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 제목에 [pointerevents3] … 메시지 주제 … 포함 (아카이브)
브라우저 지원:
caniuse.com

개요

이 명세의 기능은 'Pointer Events'에서 발견되는 기능을 확장하거나 수정합니다. 'Pointer Events'는 마우스, 펜, 터치스크린 등의 장치로부터 하드웨어에 독립적인 포인터 입력을 처리하기 위한 이벤트와 관련 인터페이스를 설명하는 W3C 권고안입니다. 기존 마우스 기반 콘텐츠와의 호환성을 위해, 이 명세는 다른 포인터 장치 유형에 대해서도 마우스 이벤트를 발생시키는 매핑을 설명합니다.

이 문서의 상태

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

이 명세는 [PointerEvents2]의 업데이트 버전입니다.

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

이 개정판에는 명확한 설명도 포함되어 있습니다:

이 명세가 후보 권고안 단계를 벗어나기 전에, 두 개 이상의 독립적인 구현이 각각의 테스트를 통과해야 하지만, 모든 테스트를 단일 구현이 통과할 필요는 없습니다.

이 문서는 Pointer Events 워킹 그룹권고안 트랙을 사용하여 후보 권고안 스냅샷으로 발행했습니다.

후보 권고안으로 발행된다고 해서 W3C와 그 구성원이 이를 승인했다는 것을 의미하지는 않습니다. 후보 권고안 스냅샷은 광범위한 검토를 받았으며, 구현 경험을 수집하기 위해 발행된 것으로, 워킹 그룹 구성원이 구현에 대해 로열티 없는 라이선스를 약속했음을 의미합니다.

이 후보 권고안은 2025년 12월 4일 이전에는 제안된 권고안 단계로 진입하지 않을 예정입니다.

이 문서는 W3C 특허 정책을 따르는 그룹에 의해 제작되었습니다. W3C공개 특허 공개 목록을 해당 그룹 산출물과 연결하여 관리합니다. 해당 페이지에는 특허 공개 방법도 안내되어 있습니다. 특정 특허에 대한 실질적인 정보를 가진 경우, Essential Claim이 포함되어 있다고 생각할 경우 W3C 특허 정책 6절에 따라 그 정보를 공개해야 합니다.

본 문서는 2025년 8월 18일 W3C 프로세스 문서에 의해 관리됩니다.

1. 소개

이 섹션은 권고 사항이 아닙니다.

오늘날 대부분의 [HTML] 콘텐츠는 마우스 입력에 맞추어 사용되거나 설계됩니다. 입력을 사용자 정의 방식으로 처리하는 경우 대개 [UIEVENTS] 마우스 이벤트에 맞추어 코딩합니다. 그러나 최근의 컴퓨팅 장치들은 터치스크린이나 펜 입력 등 다양한 입력 방식을 채택하고 있습니다. 각각의 입력 방식별로 이벤트 타입이 제안되어 왔지만, 이러한 접근법은 새 입력 타입을 지원할 때 불필요한 중복 로직 및 이벤트 처리 오버헤드를 초래합니다. 이로 인해 콘텐츠가 특정 단일 장치만을 염두에 두고 작성되면 호환성 문제가 자주 발생합니다. 또한, 기존 마우스 기반 콘텐츠와의 호환성 때문에 대부분의 user agents는 모든 입력 타입에 대해 마우스 이벤트를 발생시킵니다. 이로 인해 마우스 이벤트가 실제 마우스 장치에서 온 것인지, 아니면 호환성을 위해 다른 입력 장치에서 생성된 것인지 모호해지며, 두 장치 타입 모두를 동시에 지원하는 코드를 작성하기가 어렵습니다.

여러 입력 타입에 대응하는 코딩 비용을 줄이고, 위에서 언급한 마우스 이벤트의 모호성 문제를 해소하기 위해, 이 명세에서는 포인터라는 더 추상적인 입력 개념을 정의합니다. 포인터란 마우스 커서, 펜, 터치(멀티터치 포함), 또는 기타 포인팅 입력 장치로 화면에 접촉하는 모든 지점이 될 수 있습니다. 이 모델을 사용하면 사용자가 어떤 하드웨어를 사용하든 잘 동작하는 사이트와 애플리케이션을 쉽게 작성할 수 있습니다. 장치별 처리가 필요한 상황에 대비해, 이 명세는 이벤트를 생성한 장치 유형을 검사할 수 있는 속성도 정의합니다. 주요 목표는 크로스-디바이스 포인터 입력을 위해 더 쉽게 작성할 수 있도록 단일 이벤트 및 인터페이스 집합을 제공하되, 확장 경험에 필요한 경우 장치별 처리가 가능하도록 하는 것입니다.

또 다른 주요 목표는 멀티스레드 유저 에이전트가 직접 조작 동작(예: 터치스크린에서 손가락이나 스타일러스로 팬/줌 등)을, 스크립트 실행에 블로킹되지 않고 처리할 수 있도록 하는 것입니다.

참고

이 명세는 다양한 포인터 입력에 대해 통합된 이벤트 모델을 정의하지만, 키보드나 키보드와 유사한 인터페이스(예: 터치스크린 기반 장치에서 구동되는 화면 판독기 또는 유사 보조 기술 등과 같이, 사용자가 포커스 가능한 컨트롤 및 요소를 순차적으로 탐색하는 환경)는 포괄하지 않습니다. 유저 에이전트가 이러한 인터페이스에 반응하여 포인터 이벤트를 생성할 수도 있지만, 이 명세에서는 해당 시나리오를 다루지 않습니다.

우선, 작성자들은 focus, blur, click과 같은 고수준 이벤트에 응답하여 모든 입력 방식에 대해 동등한 기능을 제공하도록 권장합니다. 그러나 저수준 이벤트(예: 포인터 이벤트)를 사용할 경우 모든 입력 타입이 지원되는지 확인해야 합니다. 키보드 및 키보드와 유사한 인터페이스의 경우, 명시적 키보드 이벤트 처리가 추가로 필요할 수 있습니다. 자세한 내용은 키보드 접근성 [WCAG22]를 참고하시기 바랍니다.

포인터 입력은 마우스, 펜, 터치 등 다양한 입력 소스를 결합합니다
그림 1 포인터는 화면의 특정 좌표(또는 좌표 집합)를 대상으로 할 수 있는 입력 장치를 하드웨어에 구애받지 않고 표현한 개념입니다.

일반적인 포인터 입력 처리를 위한 이벤트는 마우스 이벤트와 매우 유사합니다: pointerdown, pointermove, pointerup, pointerover, pointerout 등등. 이로 인해 마우스 이벤트 기반 콘텐츠를 손쉽게 포인터 이벤트 기반으로 이관할 수 있습니다. 포인터 이벤트는 마우스 이벤트에 있는 모든 기존 속성(클라이언트 좌표, 타겟 요소, 버튼 상태 등)과 더불어 압력, 접촉 영역, 기울기 등 다른 입력 방식의 새로운 속성을 추가로 제공합니다. 작성자는 포인터 이벤트로 입력 타입 간에 로직을 공유하고, 필요할 때만 특정 입력 타입에 맞게 세부 구현을 분기할 수 있습니다.

포인터 이벤트는 다양한 입력 장치에서 기원하지만, 반드시 특정 장치별 이벤트를 기반으로 생성된다고 명의된 것은 아닙니다. 호환성을 위해 그럴 수도 있고 장려되지만, 이 명세는 마우스 이벤트나 터치 이벤트 같은 타 장치 이벤트 지원을 필수로 요구하지 않습니다. 유저 에이전트는 다른 장치 이벤트 지원 없이 포인터 이벤트만 지원할 수도 있습니다. 마우스 전용 이벤트에 맞추어 작성된 콘텐츠와의 호환성을 위해, 이 명세에서는 마우스가 아닌 장치의 포인터 입력을 기반으로 호환성 마우스 이벤트를 어떻게 생성할지에 대한 선택적 섹션도 제공합니다.

참고

이 명세는 [TOUCH-EVENTS]에 정의된 터치 이벤트와 포인터 이벤트를 모두 지원하는 유저 에이전트의 예상 동작에 대한 지침을 제공하지 않습니다. 두 명세의 관계에 대한 추가 정보는 Touch Events 커뮤니티 그룹을 참고하세요.

2. 적합성

비규범으로 표시된 섹션뿐 아니라, 이 명세의 모든 작성 가이드라인, 다이어그램, 예시 및 주석은 비규범입니다. 본 명세에서 그 외의 모든 내용이 규범적입니다.

이 문서에서 MAY, MUST, MUST NOT, OPTIONAL, SHOULD와 같은 주요 단어는 BCP 14 [RFC2119] [RFC8174] 에서 설명한 바와 같이, 오직 대문자로 나타날 때만 해당 의미를 갖습니다.

3. 예시

이 섹션은 권고 사항이 아닙니다.

아래는 본 명세의 일부 API를 작성자들이 어떻게 사용할 수 있는지 보여주는 기본 예시입니다. 더 구체적인 예시는 각 섹션에 따로 제공됩니다.

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

if (window.PointerEvent) {
    // Pointer Event가 지원되면 포인터 이벤트만 리슨
    target.addEventListener("pointerdown", function(e) {
        // 필요하다면 e.pointerType에 따라 별도 분기 처리
        // 터치/펜/마우스 구분 동작
        ...
    });
    ...
} else {
    // 기존 터치/마우스 이벤트 핸들러
    target.addEventListener('touchstart', function(e) {
        // 호환성을 위한 마우스 이벤트 및 클릭 방지
        e.preventDefault();
        ...
    });
    ...
    target.addEventListener('mousedown', ...);
    ...
}

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

function detectInputType(event) {
    switch(event.pointerType) {
        case "mouse":
            /* 마우스 입력 감지 */
            break;
        case "pen":
            /* 펜/스타일러스 입력 감지 */
            break;
        case "touch":
            /* 터치 입력 감지 */
            break;
        default:
            /* pointerType이 비어 있음(감지 불가)
            또는 UA별 커스텀 타입 */
    }
}
예제 3: 접촉 지오메트리에 맞춰 요소 크기 조절
<div style="position:absolute; top:0px; left:0px; width:100px;height:100px;"></div>
<script>
window.addEventListener("pointerdown", checkPointerSize);

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

let pointerEventInitDict =
{
  bubbles: true,
  cancelable: true,
  composed: true,
  pointerId: 42,
  pointerType: "pen",
  clientX: 300,
  clientY: 500,
};
const p1 = new PointerEvent("pointermove", pointerEventInitDict);
pointerEventInitDict.clientX += 10;
const p2 = new PointerEvent("pointermove", pointerEventInitDict);
pointerEventInitDict.coalescedEvents = [p1, p2];
const event2 = new PointerEvent("pointermove", pointerEventInitDict);
eventTarget.dispatchEvent(event2);

4. 포인터 이벤트와 인터페이스

4.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;
    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;
    [SecureContext] sequence<PointerEvent> getCoalescedEvents();
    sequence<PointerEvent> getPredictedEvents();
};
pointerId

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

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

Note

pointerId 선택 알고리즘은 구현별입니다. 작성자는 값이 활성 포인터들 간에서 고유한 식별자라는 것 이외의 의미를 전달한다고 가정해서는 안 됩니다. 예를 들어, 사용자 에이전트는 단순히 0부터 시작하여 활성화된 순서대로 포인터에 번호를 할당할 수 있지만, 이 값들이 단조 증가한다고 보장되지는 않습니다. 특정 포인팅 장치에 대해 동일한 pointerId를 재사용할지 여부는 구현에 맡겨지므로, 이에 의존하는 것은 강력히 권장되지 않습니다.

width

포인터의 접촉 지오메트리의 X축 방향 크기를 CSS 픽셀([CSS21])로 나타냅니다. 이 값은 주어진 포인터에 대해 각 이벤트마다 MAY 업데이트될 수 있습니다. (전통적인 마우스처럼) 일반적으로 접촉 지오메트리가 없는 입력이나, 하드웨어가 실제 지오메트리를 감지하지 못하는 경우에는 user agent가 기본값 1을 반환해야 MUST 합니다.

height

포인터의 접촉 지오메트리의 Y축 방향 크기를 CSS 픽셀([CSS21])로 나타냅니다. 이 값은 주어진 포인터에 대해 각 이벤트마다 MAY 업데이트될 수 있습니다. (전통적인 마우스처럼) 일반적으로 접촉 지오메트리가 없는 입력이나, 하드웨어가 실제 지오메트리를 감지하지 못하는 경우에는 user agent가 기본값 1을 반환해야 MUST 합니다.

pressure

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

tangentialPressure

정규화된 접선 압력(바렐 압력이라고도 함)으로, 일반적으로 추가 제어(예: 에어브러시 스타일러스의 휠)에 의해 설정됩니다. 값의 범위는 [-1,1]이며, 0은 제어의 중립 위치입니다. 일부 하드웨어는 [0,1] 범위의 양수 값만 지원할 수 있습니다. 접선 압력을 지원하지 않는 하드웨어나 플랫폼의 경우, 값은 0이어야 MUST 합니다.

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

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

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

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

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

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

altitudeAngle

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

Note
여기서 altitudeAngle의 기본값은 π/2로, 트랜스듀서를 표면에 수직으로 둡니다. 이는 Touch Events - Level 2 명세의 altitudeAngle 기본값(0) 정의와 다릅니다.
altitudeAngle 설명 다이어그램
그림 4 예: 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 설명 다이어그램
그림 5 예: azimuthAngle = π/6 (“4시” 방향).
pointerType

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

포인터 장치 유형 pointerType
Mouse mouse
Pen / stylus pen
Touch contact touch

장치 유형을 사용자 에이전트가 감지할 수 없다면, 값은 빈 문자열이어야 MUST 합니다. 위에 나열된 것 외의 포인터 장치 유형을 지원하는 사용자 에이전트는 서로 다른 장치 유형 간 이름 충돌을 피하기 위해 pointerType 값을 벤더 프리픽스 형태로 제공하는 것이 SHOULD 입니다. 향후 명세에서는 다른 장치 유형에 대해 추가적인 규범 값들을 MAY 제공할 수 있습니다.

Note
기본적인 pointerType 사용법은 예제 2를 참고하십시오. 또한, 일부 사용자 에이전트는 자체 커스텀 pointerType 값을 구현했거나, pointerType이 단순히 빈 문자열인 상황을 대비해 기본 처리 로직을 포함하는 것이 좋습니다.
isPrimary

해당 포인터가 이 포인터 유형의 기본 포인터를 나타내는지 여부를 표시합니다.

getCoalescedEvents()

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

getPredictedEvents()

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

PointerEventInit 딕셔너리는 PointerEvent 인터페이스의 생성자에서 사용되며, 신뢰할 수 없는(합성된) 포인터 이벤트를 구성하는 메커니즘을 제공합니다. 이는 [UIEVENTS]에 정의된 MouseEventInit 딕셔너리를 상속합니다. 신뢰할 수 없는 포인터 이벤트를 발생시키는 샘플 코드는 예시를 참고하십시오.

이벤트 구성 단계에서 PointerEventPointerEventInitcoalescedEventscoalesced 이벤트 목록으로 복제하고, PointerEventInitpredictedEventspredicted 이벤트 목록으로 복제합니다.

Note
PointerEvent 인터페이스는 UI Events에 정의된 MouseEvent를 상속합니다. 또한, 다양한 좌표 속성을 분수 좌표를 허용하도록 long에서 double로 변경하는 CSSOM View Module의 제안 확장에 유의하십시오. 이 제안 확장을 이미 PointerEvent에는 적용했지만 일반 MouseEvent에는 적용하지 않은 사용자 에이전트의 경우, click, auxclick, contextmenu 이벤트에 대해 추가 요구 사항이 있습니다.

4.1.1 버튼 상태

4.1.1.1 조합 버튼 상호작용

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

대신, 조합 버튼 누름은 buttonbuttons 속성의 변화를 검사하여 감지할 수 있습니다. buttonbuttons 속성은 MouseEvent 인터페이스에서 상속되지만, 다음 섹션에서 설명하듯 의미와 값이 변경됩니다.

buttonbuttons 속성에 대한 수정은 포인터 이벤트에만 적용됩니다. 그러나 click, auxclick, contextmenu의 경우 buttonbuttons의 값은 [UIEVENTS]을 MUST 따르며, 이는 호환성 마우스 이벤트에도 동일하게 적용됩니다.

4.1.1.2 button 속성

어떤 포인터 이벤트(그리고 pointerdownpointerup에 한정되지 않음)에서 버튼 상태 전환을 식별하기 위해, button 속성은 이벤트를 발생시킨 장치 버튼을 나타냅니다.

장치 버튼 변경 button
직전 이벤트 이후 버튼/터치·펜 접촉 모두 변화 없음 -1
왼쪽 마우스,
터치 접촉,
펜 접촉
0
가운데 마우스 1
오른쪽 마우스,
펜 바렐 버튼
2
X1(뒤로) 마우스 3
X2(앞으로) 마우스 4
펜 지우개 버튼 5
Note
마우스를 드래그하는 중에는, pointermove 이벤트의 button 값이 mousemove 이벤트의 것과 다를 수 있습니다. 예를 들어, 오른쪽 버튼을 누른 채 마우스를 이동하면 pointermove 이벤트의 button 값은 -1이지만, mousemove 이벤트의 button 값은 2입니다.
4.1.1.3 buttons 속성

buttons 속성은 장치 버튼의 현재 상태를 비트마스크로 제공합니다(MouseEvent와 동일하지만 값의 범위를 확장).

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

4.1.2 기본 포인터

멀티 포인터(예: 멀티 터치) 시나리오에서, isPrimary 속성은 각 포인터 유형에 대해 활성 포인터 집합 중 주 포인터를 식별하는 데 사용됩니다.

  • 어떤 시점에도 포인터 유형별로 기본 포인터는 최대 하나만 존재할 수 있습니다.
  • 특정 포인터 유형에 대해 가장 먼저 활성화된 포인터(예: 멀티 터치 상호작용에서 화면을 가장 먼저 터치한 손가락)가 해당 포인터 유형의 기본 포인터가 됩니다.
  • 기본 포인터만 호환성 마우스 이벤트를 생성합니다. 여러 기본 포인터가 있는 경우, 이들 모두가 호환성 마우스 이벤트를 생성합니다.
Note
단일 포인터 상호작용을 원하는 작성자는 기본이 아닌 포인터를 무시함으로써 이를 달성할 수 있습니다(단, 아래 여러 기본 포인터에 대한 주석을 참고).
Note
두 개 이상의 포인터 장치 유형이 동시에 사용되는 경우, 여러 포인터(각 pointerType별로 하나)가 기본으로 간주됩니다. 예를 들어, 터치 접촉과 마우스 커서를 동시에 이동하면 두 포인터 모두 기본으로 간주됩니다.
Note
일부 장치, 운영 체제 및 사용자 에이전트는 우발적 상호작용을 피하기 위해 둘 이상의 포인터 입력 유형의 동시 사용을 무시할 수 있습니다. 예를 들어, 터치와 펜 상호작용을 모두 지원하는 장치는 사용자가 펜을 사용하는 동안 터치를 무시하여, 펜을 사용하는 동안 손바닥을 화면에 올려둘 수 있게 할 수 있습니다(일반적으로 “팜 리젝션”이라고 함). 현재로서는 작성자가 이 동작을 억제할 방법이 없습니다.
Note
일부 경우에는 사용자 에이전트가 기본 포인터로 표시된 포인터가 없는 포인터 이벤트를 발행할 수 있습니다. 예를 들어, 특정 유형의 활성 포인터가 여러 개 있는 멀티 터치 상호작용에서 기본 포인터가 제거(예: 화면을 벗어남)되면 기본 포인터가 없을 수 있습니다. 또한, 장치의 동일 유형의 모든 활성 포인터(사용자 에이전트가 아닌 애플리케이션을 대상으로 하는 포인터 포함)를 사용해 기본 포인터를 결정하는 플랫폼에서는, 첫 번째(기본) 포인터가 사용자 에이전트 바깥에 있고 다른(기본이 아닌) 포인터가 사용자 에이전트 안을 대상으로 하는 경우, user agentisPrimaryfalse인 다른 포인터에 대한 포인터 이벤트를 MAY 발행할 수 있습니다.
Note
현재 운영 체제와 사용자 에이전트는 일반적으로 다중 마우스 입력의 개념을 갖고 있지 않습니다. 둘 이상의 마우스 장치가 존재하는 경우(예: 트랙패드와 외부 마우스를 모두 가진 노트북), 모든 마우스 장치는 일반적으로 하나의 장치로 취급됩니다 — 어느 장치에서의 움직임이든 단일 마우스 포인터의 움직임으로 변환되고, 서로 다른 마우스 장치의 버튼 누름 간 구분은 없습니다. 이 때문에 보통 단 하나의 마우스 포인터만 존재하며, 해당 포인터가 기본 포인터가 됩니다.

4.1.3 PointerEvent 인터페이스를 사용하여 이벤트 발생

포인터 이벤트를 발행한다는 것은, 이름이 e이벤트를 발행하되, PointerEvent를 사용하고 그 속성을 PointerEvent 인터페이스 및 속성과 기본 동작에 정의된 대로 설정하는 것을 의미합니다.

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

이벤트가 발행될 대상(대상 결정)은 다음과 같이 정합니다:

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

이 이벤트가 pointerdown, pointermove, 또는 pointerup인 경우, 해당 이벤트의 pointerId에 대한 활성 문서targetDocument로 설정합니다.

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

이 이벤트를 발행하기 전에, user agent이벤트 순서 보장 [UIEVENTS]을 위해, 포인팅 장치가 previousTarget에서 대상 위로 이동한 것처럼 대상을 취급해야 SHOULD 합니다. needsOverEvent 플래그가 설정되어 있으면, 대상 요소가 같더라도 pointerover 이벤트가 필요합니다.

결정된 대상에 이벤트를 발행합니다.

결정된 대상을 해당 포인터의 previousTarget으로 저장하고, needsOverEvent 플래그를 false로 재설정합니다. previousTarget이 더 이상 [DOM]의 연결됨 상태가 아니라면, previousTarget로 이벤트를 디스패치하는 이벤트 경로에 해당하는 가장 가까이 여전히 연결됨 [DOM] 부모로 previousTarget을 업데이트하고, needsOverEvent 플래그를 true로 설정합니다.

Note
정상적인 히트 테스트 결과 대신 대상로 포인터 캡처 대상 오버라이드를 사용하는 경우, [UIEVENTS]에 정의된 일부 경계 이벤트가 발생할 수 있습니다. 이는 포인터가 이전 대상에서 캡처링 대상로 떠나/진입하는 것과 동일합니다. 캡처가 해제될 때도 같은 상황이 발생할 수 있으며, 포인터가 캡처링 대상을 떠나 히트 테스트 대상으로 진입하게 됩니다.
4.1.3.1 속성과 기본 동작

이 명세에서 정의된 이벤트 유형에 대한 bubblescancelable 속성과 기본 동작은 다음 표에 나와 있습니다. 각 이벤트 유형의 세부 사항은 포인터 이벤트 유형에 설명되어 있습니다.

이벤트 유형 Bubbles Cancelable 기본 동작
pointerover Yes Yes None
pointerenter No No None
pointerdown Yes Yes Varies: 포인터가 기본일 때, mousedown 이벤트의 모든 기본 동작
이 이벤트를 취소하면 이후 호환성 마우스 이벤트 발행도 방지됩니다.
pointermove Yes Yes Varies: 포인터가 기본일 때, mousemove의 모든 기본 동작
pointerrawupdate Yes No None
pointerup Yes Yes Varies: 포인터가 기본일 때, mouseup의 모든 기본 동작
pointercancel Yes No None
pointerout Yes Yes None
pointerleave No No None
gotpointercapture Yes No None
lostpointercapture Yes No None

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

pointerenterpointerleave 이벤트의 경우, [DOM]의 composed 속성은 false여야 SHOULD 하며; 위 표의 다른 포인터 이벤트에서는 이 속성이 true여야 SHOULD 합니다.

위 표의 모든 포인터 이벤트에서, [UIEVENTS]의 detail 속성은 0이어야 SHOULD 합니다.

Note
많은 사용자 에이전트는 레거시 콘텐츠 지원을 위해 MouseEvent에 비표준 속성 fromElementtoElement를 노출합니다. 이러한 사용자 에이전트는 작성자가 표준화된 대체(targetrelatedTarget)로 전환할 수 있도록, 포인터 이벤트에서 해당(상속된) 속성 값들을 null로 설정하는 것이 좋습니다.

MouseEventrelatedTarget과 유사하게, relatedTarget는 ( pointerover 또는 pointerenter 이벤트의 경우) 포인터가 방금 떠난 요소, 또는 (pointerout 또는 pointerleave 이벤트의 경우) 포인터가 진입 중인 요소로 초기화되어야 합니다. 다른 포인터 이벤트의 경우 이 값은 기본적으로 null입니다. 요소가 포인터 캡처를 받으면, 해당 포인터에 대한 이후 모든 이벤트는 캡처링 요소의 경계 내부에 있는 것으로 간주됩니다.

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

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

user agent포인터 캡처를 암시적으로 해제할 때뿐 아니라, gotpointercapturelostpointercapture가 아닌 포인터 이벤트를 발행할 때도 아래 단계를 MUST 실행해야 합니다.

  1. 이 포인터에 대한 포인터 캡처 대상 오버라이드가 설정되어 있고 대기 중 포인터 캡처 대상 오버라이드와 다르면, lostpointercapture라는 이름의 포인터 이벤트를 포인터 캡처 대상 오버라이드 노드에 발행합니다.
  2. 이 포인터에 대한 대기 중 포인터 캡처 대상 오버라이드가 설정되어 있고 포인터 캡처 대상 오버라이드와 다르면, gotpointercapture라는 이름의 포인터 이벤트를 대기 중 포인터 캡처 대상 오버라이드에 발행합니다.
  3. 포인터 캡처 대상 오버라이드를, 설정된 경우 대기 중 포인터 캡처 대상 오버라이드로 설정합니다. 그렇지 않으면 포인터 캡처 대상 오버라이드를 해제합니다.
Note

click, auxclick, contextmenu 이벤트 섹션에 정의된 바와 같이, lostpointercapture 이벤트가 디스패치된 이후에도, 해당하는 click, auxclick 또는 contextmenu 이벤트(있는 경우)는 여전히 캡처링 대상에 디스패치됩니다.

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

user agent는 특정 pointerId로 웹 페이지가 포인터 이벤트를 계속 수신할 가능성이 낮다고 감지하는 경우, 포인터 이벤트 스트림을 억제해야 MUST 합니다. 다음 시나리오 중 하나라도 해당 조건을 만족합니다(추가 시나리오가 MAY 있을 수 있음):

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

user agent포인터 이벤트 스트림을 억제할 수 있는 다른 시나리오에는 다음이 포함됩니다:

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

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

user agent포인터 이벤트 스트림을 억제하기 위해 다음 단계를 MUST 실행합니다:

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

화면 표면에 대해 상대적으로 이동했거나 속성 중 일부가 변경된 포인터 장치는 포인터 이벤트 유형에 정의된 다양한 이벤트를 발생시킵니다. 화면 표면에 대해 상대적으로 이동하지 않았고 어떤 속성도 변경되지 않은 정지 상태의 포인터 장치의 경우, user agent는 레이아웃 변경이 포인터의 히트 테스트 대상을 변경했을 때 특정 경계 이벤트를 MUST 발생시켜야 합니다. 자세한 내용은 pointerover, pointerenter, pointerout, pointerleave를 참조하십시오. user agent는 성능상의 이유(예: 경계 이벤트 리스너로 인해 과도한 히트 테스트나 레이아웃 변경이 발생하는 것을 방지하기 위해) 이러한 경계 이벤트의 발생을 MAY 지연시킬 수 있습니다.

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

4.1.5 tiltX / tiltYaltitudeAngle / azimuthAngle 간 변환

Pointer Events는 X-Y 평면에 대한 트랜스듀서의 방향을 표현하기 위해 상호 보완적인 두 집합의 속성을 포함합니다: 원래 Pointer Events 명세에서 도입된 tiltX / tiltY, 그리고 Touch Events - Level 2 명세에서 채택한 azimuthAngle / altitudeAngle.

구체적인 하드웨어와 플랫폼에 따라, 사용자 에이전트는 화면 평면에 대한 트랜스듀서 방향 값 집합을 하나만 수신할 가능성이 높습니다 — tiltX / tiltY 또는 altitudeAngle / azimuthAngle 중 하나입니다. 사용자 에이전트는 이러한 값을 변환하기 위해 아래 알고리즘을 MUST 사용해야 합니다.

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

예제 5: tiltX/tiltY와 altitudeAngle/azimuthAngle 간 변환
/* tiltX/tiltY와 altitudeAngle/azimuthAngle 간 변환 */

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

  let tiltXrad = 0;
  let tiltYrad = 0;

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

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

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

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

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

  // 방위각 계산
  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) {
    // 방위각을 계산하기에 충분한 정보가 없음
    azimuthAngle = 0;
  } else {
    // 경계가 아닌 경우: tiltX와 tiltY가 0이나 ±90이 아님
    const tanX = Math.tan(tiltXrad);
    const tanY = Math.tan(tiltYrad);

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

  // 고도각 계산
  let altitudeAngle = 0;

  if (Math.abs(tiltX) == 90 || Math.abs(tiltY) == 90) {
      altitudeAngle = 0
  } else if (tiltX == 0) {
    altitudeAngle = Math.PI/2 - Math.abs(tiltYrad);
  } else if (tiltY == 0) {
    altitudeAngle = Math.PI/2 - Math.abs(tiltXrad);
  } else {
    // 경계가 아닌 경우: tiltX와 tiltY가 0이나 ±90이 아님
    altitudeAngle =  Math.atan(1.0/Math.sqrt(Math.pow(Math.tan(tiltXrad),2) + Math.pow(Math.tan(tiltYrad),2)));
  }

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

4.2 포인터 이벤트 유형

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

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

4.2.1 pointerover 이벤트

user agent는 다음 중 하나가 발생하면 MUST 이름이 pointerover인 포인터 이벤트를 발생시켜야 합니다:

4.2.2 pointerenter 이벤트

user agent는 다음 중 하나가 발생하면 MUST 이름이 pointerenter인 포인터 이벤트를 발생시켜야 합니다:

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

4.2.3 pointerdown 이벤트

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

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

호버를 지원하지 않는 입력 장치의 경우, user agentMUST 이름이 pointerover인 포인터 이벤트를, 이어서 pointerenter 이벤트를 발생시킨 다음 pointerdown 이벤트를 디스패치해야 합니다.

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

4.2.4 pointermove 이벤트

user agent는 포인터가 pointerdown 또는 pointerup 이벤트를 발생시키지 않는 속성들 중 어느 하나라도 변경될 때, 이름이 pointermove인 포인터 이벤트를 MUST 발생시켜야 합니다. 여기에는 좌표, 압력, 접선 압력, 기울기, 회전, 접촉 지오메트리(widthheight), 또는 조합 버튼에 대한 모든 변경이 포함됩니다.

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

4.2.5 pointerrawupdate 이벤트

user agent보안 컨텍스트 내에서만, 포인터가 pointerdown 또는 pointerup 이벤트를 발생시키지 않는 속성 중 일부를 변경할 때, MUST 이름이 pointerrawupdate인 포인터 이벤트를 발생시켜야 합니다. 해당 속성 목록은 pointermove 이벤트를 참조하십시오.

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

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

이와 동일한 pointerId를 가진 다른 pointerrawupdate가 이미 존재하고 아직 이벤트 루프에서 디스패치되지 않았다면, user agent는 새 pointerrawupdate를 별도의 태스크를 만들지 않고 해당 이벤트와 MAY 병합(coalesce)할 수 있습니다. 이로 인해 pointerrawupdate가 병합된 이벤트를 갖게 될 수 있으며, 이벤트가 이벤트 루프에서 처리되는 즉시, 하나의 pointerrawupdate 이벤트의 병합된 이벤트로 모두 전달됩니다. 자세한 내용은 getCoalescedEvents를 참조하십시오.

pointerrawupdatepointermove의 순서와 관련해, 플랫폼으로부터의 업데이트가 pointerrawupdatepointermove 이벤트를 모두 유발하는 경우, user agent는 대응되는 pointermove보다 먼저 pointerrawupdate 이벤트를 MUST 디스패치해야 합니다.

target을 제외하면, 마지막 pointermove 이벤트 이후 디스패치된 모든 pointerrawupdate 이벤트들의 병합된 이벤트 목록을 연결(concatenate)한 결과는, 다음 pointermove 이벤트의 병합된 이벤트와(다른 이벤트 속성 측면에서) 동일합니다. pointerrawupdate의 속성은 pointermove와 대부분 동일하나, pointerrawupdate의 경우 cancelable 속성은 MUST false여야 합니다.

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

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

4.2.6 pointerup 이벤트

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

호버를 지원하지 않는 입력 장치의 경우, user agentMUST 이름이 pointerout인 포인터 이벤트를, 이어서 pointerleave 이벤트를 발생시켜야 하며, 이는 pointerup 이벤트 디스패치 이후에 이루어집니다.

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

user agent는 포인터가 현재 캡처된 상태라면, 포인터 캡처를 암시적으로 해제해야 MUST 합니다.

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

4.2.7 pointercancel 이벤트

user agent포인터 이벤트 스트림을 억제해야 하는 시나리오를 감지하면, 이름이 pointercancel인 포인터 이벤트를 MUST 발생시켜야 합니다.

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

4.2.8 pointerout 이벤트

user agent는 다음 중 하나가 발생하면 MUST 이름이 pointerout인 포인터 이벤트를 발생시켜야 합니다:

4.2.9 pointerleave 이벤트

user agent는 다음 중 하나가 발생하면 MUST 이름이 pointerleave인 포인터 이벤트를 발생시켜야 합니다:

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

4.2.10 gotpointercapture 이벤트

user agent는 요소가 포인터 캡처를 받으면 MUST 이름이 gotpointercapture인 포인터 이벤트를 발생시켜야 합니다. 이 이벤트는 포인터 캡처를 수신하는 요소에서 발생합니다. 해당 포인터에 대한 이후 이벤트는 이 요소에서 발생합니다. 자세한 내용은 포인터 캡처 설정대기 중인 포인터 캡처 처리 섹션을 참조하십시오.

4.2.11 lostpointercapture 이벤트

user agent는 포인터에 대한 포인터 캡처가 해제된 후, 이름이 이름이 lostpointercapture인 포인터 이벤트를 MUST 발생시켜야 합니다. 이 이벤트는 캡처가 제거된 요소에서 발생합니다. 캡처가 해제된 후 해당 포인터에 대한 모든 후속 이벤트는, click, auxclick, contextmenu 이벤트를 제외하고, 이벤트 대상을 결정하기 위해 일반적인 히트 테스트 메커니즘(이 명세의 범위를 벗어남)을 따릅니다. 자세한 내용은 포인터 캡처 해제, 포인터 캡처의 암시적 해제, 대기 중인 포인터 캡처 처리 섹션을 참조하십시오.

4.2.12 click, auxclick, contextmenu 이벤트

이 섹션은 [UIEVENTS]에 정의된 click, auxclick, contextmenu 이벤트에 대한 추가 사항입니다. 이러한 이벤트는 일반적으로 사용자 인터페이스 활성화에 연결되며, 키보드 같은 포인터가 아닌 입력 장치에서도 발생할 수 있습니다.

이러한 이벤트는 PointerEvent 타입이어야 MUST 하며, 이 섹션의 나머지 부분에서 언급된 추가 요구 사항을 따릅니다.

4.2.12.1 이벤트 속성

이러한 이벤트의 경우, 이 명세에서 정의된 PointerEvent 전용 속성 중 pointerIdpointerType을 제외한 나머지는 기본값을 가져야 MUST 합니다. 또한:

  • 이벤트가 포인터 장치에 의해 생성된 경우, 해당 이벤트의 pointerIdpointerType은 이러한 이벤트를 유발한 PointerEvent들과 동일해야 MUST 합니다.
  • 이벤트가 포인터가 아닌 장치(예: 음성 인식 소프트웨어 또는 키보드 상호작용)에 의해 생성된 경우, pointerId-1, pointerType은 빈 문자열이어야 MUST 합니다.
4.2.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 값으로 변환해야 합니다.

4.2.12.3 이벤트 디스패치

click, auxclick 또는 contextmenu 이벤트는, 아래 알고리즘을 사용하여 이벤트 대상을 재정의한다는 점을 제외하고, [UIEVENTS] 명세에 정의된 디스패치 과정을 MUST 따라야 합니다:

  1. event를 디스패치되고 있는 click, auxclick 또는 contextmenu 이벤트로, userEventevent의 발생을 유발한 사용자 상호작용 이벤트로 둡니다.

    참고

    userEventPointerEvent가 아닐 수도 있습니다. 예를 들어, 체크박스 요소에서 스페이스바를 눌러 click 이벤트 디스패치를 유발한 경우 KeyboardEvent입니다.

    userEventPointerEvent인 경우, userEventclick 또는 auxclick 이벤트에 대해서는 pointerup이고, contextmenu 이벤트에 대해서는 네이티브 플랫폼 관례에 따라 pointerdown 또는 pointerup일 수 있습니다.

  2. userEventPointerEvent가 아닌 경우, event의 대상을 재정의하지 않고 [UIEVENTS] 명세에 따라 event를 디스패치하고, 아래 나머지 단계는 건너뜁니다.
  3. target을 다음과 같이 정의합니다:

    eventcontextmenu 이벤트이거나, 해당 포인터가 캡처된 상태에서 userEvent가 디스패치된 경우, targetuserEvent의 대상으로 둡니다.

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

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

    참고
    userEvent가 캡처된 상태에서 발생한 경우, 동일한 lostpointercapture 이벤트가 이미 디스패치되었더라도, eventuserEvent의 캡처 대상을 향해 디스패치됩니다.

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

다음 섹션은 기존 Element 인터페이스에 대한 확장을 설명하며, 포인터 캡처의 설정 및 해제를 용이하게 합니다.

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

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

releasePointerCapture()

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

hasPointerCapture

이 메서드가 호출된 요소가, 인수로 전달된 pointerId로 식별되는 포인터에 대해 포인터 캡처를 보유하고 있는지 여부를 나타냅니다. 구체적으로, 대기 중 포인터 캡처 대상 오버라이드pointerId에 대해 이 메서드가 호출된 요소로 설정되어 있으면 true를 반환하고, 그렇지 않으면 false를 반환합니다.

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

6. 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 이벤트 유형에 해당합니다.

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

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

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

장치가 지원하는 동시 터치 접촉 지점의 최대 개수입니다. 복수의 디지타이저(예: 여러 개의 터치스크린)를 가진 장치의 경우, 각 디지타이저가 지원하는 접촉 최대치 집합의 최댓값이어야 MUST 합니다.

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

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

8. 직접 조작 동작 선언

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

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

8.1 touch-action CSS 속성

이름: touch-action
값: auto | none | [ pan-x || pan-y ] | manipulation
초기값: auto
적용 대상: 다음 제외한 모든 요소: 대체되지 않은 인라인 요소, 테이블 행, 행 그룹, 테이블 열, 열 그룹
상속: no
백분율: N/A
미디어: visual
계산값: 지정된 값과 동일
정규 순서: 문법에 따름
애니메이션 유형: 애니메이션 불가

touch-action CSS 속성은 (속성 이름과 달리 터치에만 국한되지 않는) 직접 조작 상호작용이 사용자 에이전트의 패닝 및 줌 동작을 트리거할 수 있는지를 결정합니다(MAY). touch-action 섹션을 참조하십시오.

패닝 또는 줌을 시작하기 직전에, 다음 조건이 모두 참이면 user agentMUST 포인터 이벤트 스트림을 억제해야 합니다:

Note
일부 사용자 에이전트는 개별적인 여러 제스처의 집합으로 이루어지지만 하나의 연속적인 제스처의 일부로 취급되는 복잡한 동작을 구현합니다. 예를 들어, 터치스크린에서의 "플링하여 스크롤" 제스처를 생각해 보십시오. 사용자가 빠르게 손가락을 움직여 문서를 패닝하기 시작하고, 터치스크린에서 손가락을 떼면 문서는 관성 효과로 계속 패닝합니다. 문서가 여전히 움직이는 동안, 사용자는 터치스크린에 다시 손가락을 올려 패닝에 추가적인 가속을 주는 또 다른 "플링"을 실행하거나, 현재 패닝을 상쇄하여 속도를 줄이거나, 완전히 멈추거나, 방향을 반전시킬 수 있습니다. 이 명세는 제스처와 동작이 어떻게 구현되는지 규범적으로 정의하지 않으므로, 두 번째 터치가(두 번째 "플링"으로 해석되거나 현재 패닝의 반작용으로 해석되기 전까지) 포인터 이벤트를 발생시킬지 여부는 사용자 에이전트에 달려 있습니다.
Note
touch-action은 포함된 탐색 컨텍스트로 적용/캐스케이드되지 않습니다. 예를 들어, <iframe>touch-action을 적용하더라도, 해당 <iframe> 내부의 패닝 및 줌을 위한 직접 조작 동작에는 아무런 영향이 없습니다.

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

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

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

8.3 touch-action 값의 상세

touch-action 속성은 뷰포트 패닝과 줌과 관련된 직접 조작 동작을 다룹니다. 텍스트 선택/하이라이트, 링크 및 폼 컨트롤 활성화와 같은 사용자 에이전트의 추가 동작은 이 CSS 속성에 의해 영향을 받아서는 MUST NOT 합니다.

Note
"패닝"과 "스크롤링"은 동의어로 간주됩니다(좀 더 정확히는, "패닝"은 직접 조작 입력을 사용한 "스크롤링"입니다). 패닝/스크롤링을 트리거하기 위한 상호작용이나 제스처의 정의, 또는 autonone 값에 대한 동작을 트리거하기 위한 정의는 이 명세의 범위를 벗어납니다.
auto
user agent는 요소에서 시작되는 뷰포트의 패닝과 줌과 관련된 허용된 직접 조작 동작을 고려할 수 있습니다(MAY).
none
요소에서 시작되는 직접 조작 상호작용은 뷰포트 패닝과 줌과 관련된 동작을 트리거해서는 MUST NOT 합니다.
pan-x
pan-y
user agent는 요소에서 시작되는 직접 조작 상호작용을, 나열된 모든 값이 지정하는 방향 중 어느 방향에서든 시작하는 패닝에 대해서만 고려할 수 있습니다(MAY). 패닝이 시작된 후에는, 시작에 대해 허용되지 않는 방향이라 하더라도 사용자가 방향을 반대로 바꿀 수 있습니다. 반면, pan-x 또는 pan-y로 단일 축으로 패닝이 제한된 경우에는, 패닝 도중 축을 변경할 수 없습니다.
manipulation
user agent는 요소에서 시작되는 직접 조작 상호작용을 패닝 및 연속적인 줌(예: 핀치-줌) 목적으로만 고려할 수 있습니다(MAY). 단, 일정 시간 내에 여러 번의 활성화를 필요로 하는(예: 더블 탭 확대/축소, 길게 눌러 단일 손가락 확대/축소) 다른 관련 동작을 트리거해서는 MUST NOT 합니다.
Note
구현에서 흔히 볼 수 있는 추가 touch-action은 [COMPAT]에 정의되어 있습니다.
Note
touch-action 속성은 CSS widthheight 속성을 모두 지원하는 요소에만 적용됩니다([CSS21] 참조). 이 제한은 저지연 직접 조작 패닝과 줌을 위한 사용자 에이전트 최적화를 용이하게 하도록 설계되었습니다. 기본적으로 지원되지 않는 요소(예: 대체되지 않은 인라인 요소<span>)의 경우, 작성자는 display CSS 속성을 block과 같은, widthheight를 지원하는 값으로 설정할 수 있습니다. 향후 명세는 이 API를 모든 요소로 확장할 수 있습니다.
Note

방향별 pan 값은 일부 오버스크롤 동작을 커스터마이즈하는 데 유용합니다. 예를 들어, 간단한 풀-투-리프레시 효과를 구현하기 위해 문서의 touch-action을 스크롤 위치가 0일 때는 pan-x pan-down으로, 그 외에는 pan-x pan-y로 설정할 수 있습니다. 이렇게 하면 문서 상단에서 시작되는 위쪽 패닝/스크롤에 대해 포인터 이벤트 핸들러가 동작을 정의할 수 있습니다.

방향별 pan 값은 네이티브로 스크롤되는 요소 내부에서 포인터 이벤트 처리로 사용자 정의 패닝을 구현하는 구성요소(또는 그 반대)를 구성하는 데에도 사용할 수 있습니다. 예를 들어, 이미지 캐러셀은 문서의 수직 패닝을 방해하지 않으면서, 가로 방향 패닝 작업에 대해 포인터 이벤트를 수신하도록 pan-y를 사용할 수 있습니다. 캐러셀이 가장 오른쪽 끝에 도달하면, 그 이후의 스크롤 작업이 가능하다면 뷰포트 내에서 문서를 스크롤할 수 있도록 touch-actionpan-y pan-right로 변경할 수 있습니다. 진행 중인 패닝/스크롤링 작업의 동작은, 작업이 진행되는 동안 변경할 수 없습니다.

Note
패닝과 줌을 위한 일부 기본 직접 조작 동작을 비활성화하면, 사용자 에이전트가 다른 동작에 더 빠르게 반응할 수 있도록 할 수 있습니다. 예를 들어, auto에서는 사용자 에이전트가 보통 더블 탭 제스처 처리를 위해 click 전에 300ms의 지연을 추가합니다. 이러한 경우, touch-action: none 또는 touch-action: manipulation을 명시적으로 설정하면 이 지연이 제거됩니다. 탭 또는 더블 탭 제스처를 판단하는 방법은 이 명세의 범위를 벗어남에 유의하십시오.
예제 6: 모든 직접 조작 동작 허용 안 함
<div style="touch-action: none;">
    이 요소는 그렇지 않으면 패닝 또는 줌으로 이어지는 모든 직접 조작 상호작용에 대해 포인터 이벤트를 수신합니다.
</div>
예제 7: 수평 패닝만 허용
<div style="touch-action: pan-x;">
    이 요소는 수평 방향으로 패닝하지 않을 때 포인터 이벤트를 수신합니다.
</div>
예제 8: 패닝과 줌을 위한 직접 조작 동작을 허용하지 않는 자식 영역
<div style="overflow: auto;">
    <div style="touch-action: none;">
        이 요소는 그렇지 않으면 패닝 또는 줌으로 이어지는 모든 직접 조작 상호작용에 대해 포인터 이벤트를 수신합니다.
    </div>
    <div>
        이 요소에 대한 직접 조작 상호작용은 상위 요소를 조작하는 데 소비될 수 있습니다(MAY).
    </div>
</div>
예제 9: 패닝과 줌을 위한 직접 조작 동작을 허용하지 않는 중간 부모
<div style="overflow: auto;">
    <div style="touch-action: pan-y;">
        <div style="touch-action: pan-x;">
            이 요소는 모든 직접 조작 상호작용에 대해 포인터 이벤트를 수신합니다. 그 이유는
            이 요소는 가로 패닝만 허용하지만, 중간 조상
            (스크롤 가능한 요소와 이 요소 사이)이 세로 패닝만 허용하기 때문입니다.
            따라서 사용자 에이전트는 패닝/줌을 위한 어떠한 직접 조작 동작도
            처리하지 않습니다.
        </div>
    </div>
</div>

9. 포인터 캡처

9.1 소개

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

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

Custom Volume Slider
Figure 6 엄지 요소를 앞뒤로 슬라이드하여 값을 선택하는 사용자 정의 슬라이더 컨트롤의 예. 엄지에서 pointerdown 이후, 포인터 캡처를 사용하면 포인터가 엄지에서 벗어나더라도 사용자가 엄지를 슬라이드할 수 있습니다.

9.2 포인터 캡처 설정

포인터 캡처는 Element 타입의 element에 대해 element.setPointerCapture(pointerId) 메서드를 호출하여 설정합니다. 이 메서드가 호출되면, user agent는 다음 단계를 MUST 실행해야 합니다:

  1. 메서드의 인수로 제공된 pointerId가 어떤 활성 포인터와도 일치하지 않으면, throw a "NotFoundError" DOMException.
  2. pointer를, 주어진 pointerId로 지정된 활성 포인터로 둡니다.
  3. element가 [DOM]에서 connected 상태가 아니라면, throw an "InvalidStateError" DOMException.
  4. 이 메서드가 호출될 때 element의 [DOM] 노드 문서에 잠금 요소([PointerLock] pointerLockElement)가 있다면, throw an "InvalidStateError" DOMException.
  5. pointer활성 버튼 상태가 아니거나, element노드 문서pointer활성 문서가 아니라면, 이 단계를 종료합니다.
  6. 지정된 pointerId에 대해, 대기 중 포인터 캡처 대상 오버라이드를 이 메서드가 호출된 Element로 설정합니다.
Note
이전의 설정 또는 해제 호출이 대기 상태( 대기 중 포인터 캡처 처리 참조)인 동안 포인터 캡처 설정 또는 해제 호출이 이루어지면, 두 번째 호출이 성공하면 첫 번째 호출을 덮어쓰고, 그렇지 않으면 첫 번째 호출이 유효하게 유지됩니다. 이는 암시적 포인터 캡처pointerdown 리스너에서 해제하려는 실패한 시도에도 해당됩니다.

9.3 포인터 캡처 해제

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

  1. 메서드의 인수로 제공된 pointerId가 어떤 활성 포인터와도 일치하지 않고, 이 단계가 포인터 캡처의 암시적 해제의 결과로 호출된 것이 아니라면, throw a "NotFoundError" DOMException.
  2. 지정된 pointerId에 대해 해당 ElementhasPointerCapture가 false이면, 이 단계를 종료합니다.
  3. 지정된 pointerId에 대해, 설정되어 있다면 대기 중 포인터 캡처 대상 오버라이드를 해제합니다.
Note
포인터 캡처 설정 섹션의 참고를 참조하십시오.

9.4 암시적 포인터 캡처

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

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

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

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

포인터 캡처 대상 오버라이드가 더 이상 [DOM]에서 connected가 아닌 경우, 포인터 캡처 대상 오버라이드는 문서로 설정되어야 SHOULD 합니다.

대기 중 포인터 캡처 대상 오버라이드가 더 이상 [DOM]에서 connected가 아닌 경우, 대기 중 포인터 캡처 대상 오버라이드 노드는 해제되어야 SHOULD 합니다.

Note
위의 두 문단의 결과로, 캡처된 포인터에 해당하는 lostpointercapture 이벤트가 캡처 노드가 제거된 이후 다음 번 대기 중 포인터 캡처 처리 중에 문서에서 발생하게 됩니다.

어떤 요소에 포인터 락([PointerLock])이 성공적으로 적용되면, user agent는 어떤 요소가 캡처되었거나 캡처 대기 중인 경우가 있다면 releasePointerCapture 메서드가 호출된 것처럼 단계를 MUST 실행해야 합니다.

10. 병합된(coalesced) 및 예측된(predicted) 이벤트

Note
이 명세는 사용자 에이전트가 포인터 이동 데이터를 어떻게 병합하거나 예측해야 하는지에 대해서는 정의하지 않습니다. 이 정보에 접근하기 위한 API만을 규정합니다.

10.1 병합된(coalesced) 이벤트

성능상의 이유로, 사용자 에이전트는 포인터의 pointermove 이벤트를 포인터의 측정 가능한 속성 (좌표, 압력, 접선 압력, 기울기, 회전, 접촉 지오메트리 등)이 업데이트될 때마다 보내지 않기로 선택할 수 있습니다. 대신 여러 변경 사항을 하나의 pointermove 또는 pointerrawupdate 이벤트로 병합(coalesce, 결합/통합)할 수 있습니다. 이러한 접근은 user agent가 수행해야 하는 이벤트 처리량을 줄이는 데 MUST 도움이 되지만, 포인터 위치를 추적할 때의 세분성 및 충실도가 자연스럽게 낮아지며, 특히 빠르고 큰 움직임에서 두드러집니다. getCoalescedEvents 메서드를 사용하면 애플리케이션이 병합되지 않은(raw) 위치 변화를 직접 액세스할 수 있습니다. 이를 통해 포인터 이동 데이터를 보다 정밀하게 처리할 수 있습니다. 예를 들어 드로잉 애플리케이션의 경우, 병합되지 않은 이벤트를 사용해 포인터의 실제 움직임에 더욱 근접한 매끄러운 곡선을 그릴 수 있습니다.

곡선의 클로즈업 뷰로, 병합된 점과 비병합 점을 보여줌
Figure 7 드로잉 애플리케이션의 곡선 예시 — pointermove 이벤트의 병합된 좌표(회색 점)만 사용할 경우, 곡선이 눈에 띄게 각지고 들쭉날쭉해집니다. 반면 getCoalescedEvents()가 제공하는 더 세분화된 점들(빨간 원)로 같은 선을 그리면 포인터 움직임을 더 부드럽게 근사할 수 있습니다.

PointerEvent에는 병합된 이벤트 목록이 연관되어 있으며 (0개 이상의 PointerEvent로 이루어진 목록입니다), 신뢰할 수 있는(trusted) pointermovepointerrawupdate 이벤트의 경우 이 목록은 해당 이벤트로 병합된 모든 PointerEvent들의 시퀀스입니다. 신뢰할 수 있는 "부모" pointermovepointerrawupdate 이벤트는 이러한 병합된 이벤트들의 누적치를 나타내지만 (예: 디스플레이 새로고침 속도에 맞추기 위한 정렬 등) 추가 처리를 포함할 수 있습니다. 그 결과, 이들 이벤트의 병합된 이벤트 목록에는 항상 최소 한 개 이상의 이벤트가 포함됩니다. 다른 모든 신뢰할 수 있는 이벤트 유형의 경우 이 목록은 비어 있습니다. 신뢰할 수 없는(untrusted) 이벤트는 생성자에 전달된 값으로 병합된 이벤트 목록이 초기화됩니다.

Note
신뢰할 수 있는 부모 이벤트는 병합된 이벤트의 요약 또는 집계이므로, 개발자는 부모 이벤트들만 처리하거나 병합된 모든 이벤트를 처리하면 되며, 두 가지를 동시에 처리할 필요는 없습니다.
Note
JavaScript에서 병합된 이벤트 목록을 포함한 신뢰할 수 있는 이벤트를 다시 디스패치(re-dispatch)하는 경우, 이벤트 디스패치 알고리즘은 이벤트의 isTrusted 비트를 false로 설정하지만, 병합된 이벤트 목록 내부 이벤트들의 동일한 비트는 원래의 true 상태에서 변경되지 않습니다.

신뢰할 수 있는 이벤트의 병합된 이벤트 목록에 있는 이벤트들은 다음을 가집니다.

Example 10: 병합된 이벤트 목록을 사용하는 기본 캔버스 드로잉 애플리케이션
<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>
Note
PointerEvent의 속성은 병합된 이벤트 목록의 이벤트를 최적으로 표현하도록 초기화됩니다. 사용자 에이전트가 이를 수행하는 구체적인 방법은 이 명세에서 다루지 않습니다.

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

Note

다음은 증가하는 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개 포함

10.2 예측된(predicted) 이벤트

일부 사용자 에이전트에는 일련의 확정된 포인터 이동 이후에, 현재 제스처의 선행 이벤트 및 움직임의 속도/궤적을 바탕으로 향후 포인터 이동 위치가 어떻게 될지 예측할 수 있는 내장 알고리즘이 있습니다. 애플리케이션은 getPredictedEvents 메서드를 사용해 이 정보를 활용하여 지연 인식(latency)을 줄이기 위해 예측 위치로 미리 "그려 두고", 실제 포인트가 수신되면 이러한 예측 포인트들을 폐기할 수 있습니다.

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

PointerEvent에는 예측된 이벤트 목록이 연관되어 있으며 (0개 이상의 PointerEvent로 이루어진 목록), 신뢰할 수 있는 pointermove 이벤트의 경우 사용자 에이전트가 해당 이벤트 이후에 뒤따를 것으로 예측하는 PointerEvent들의 시퀀스입니다. 다른 모든 신뢰할 수 있는 이벤트 유형의 경우 이 목록은 비어 있습니다. 신뢰할 수 없는(untrusted) 이벤트는 생성자에 전달된 값으로 예측된 이벤트 목록이 초기화됩니다.

Note

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

Note
JavaScript에서 예측된 이벤트 목록을 포함한 신뢰할 수 있는 이벤트를 다시 디스패치하는 경우, 이벤트 디스패치 알고리즘은 이벤트의 isTrusted 비트를 false로 설정하지만, 예측된 이벤트 목록 내부 이벤트들의 동일한 비트는 원래의 true 상태에서 변경되지 않습니다.

목록의 이벤트 개수와 현재 타임스탬프로부터의 거리(시간적 간격)는 사용자 에이전트 및 사용 중인 예측 알고리즘에 의해 결정됩니다.

신뢰할 수 있는 이벤트의 예측된 이벤트 목록에 있는 이벤트들은 다음을 가집니다.

Note

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

Example 11: 병합된 이벤트와 예측된 이벤트를 사용한 개념적 드로잉 접근

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

10.3 병합 및 예측 이벤트 목록 채우기와 유지

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

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

신뢰할 수 있는 PointerEventtarget이 변경될 때, 사용자 에이전트는 병합된 이벤트 목록예측된 이벤트 목록의 각 이벤트에 대해 다음을 SHOULD 수행해야 합니다:

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

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

오늘날 존재하는 웹 콘텐츠의 절대다수는 마우스 이벤트만을 대상으로 작성되어 있습니다. 다음은 user agent가 일반 포인터 입력을 이 콘텐츠와의 호환성을 위해 마우스 이벤트에 매핑하는 방법에 대한 알고리즘을 설명합니다(MAY).

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

Note

개략적으로, 호환성 마우스 이벤트는 해당하는 포인터 이벤트와 "상호 끼어들도록(interleaved)" 의도되었습니다. 그러나 이 구체적인 순서는 필수 사항이 아니며, 호환성 마우스 이벤트를 구현하는 사용자 에이전트는 상대적 순서를 유지하는 한 마우스 이벤트의 디스패치를 지연하거나 그룹화하기로 MAY 선택할 수 있습니다.

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

호환성 마우스 이벤트 지원 여부와 관계없이, 사용자 에이전트는 click, auxclickcontextmenu 이벤트를 항상 MUST 지원해야 합니다. 이 이벤트들은 PointerEvent 타입이며, 따라서 호환성 마우스 이벤트가 아닙니다. 포인터 이벤트 중 preventDefault를 호출하는 것은 click, auxclick, 또는 contextmenu가 발행되는지 여부에 MUST NOT 영향을 미치지 않습니다.

Note

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

또한, 사용자 에이전트는 click, auxclick, 또는 contextmenu 이벤트를 발행할지 여부를 자체 휴리스틱으로 판단할 수 있습니다. 동일한 타입의 다른(비-기본) 포인터나 다른 타입의 다른 기본 포인터가 있는 경우, 일부 사용자 에이전트는 이러한 이벤트를 발행하지 않기로 선택할 수 있습니다. 사용자 에이전트는 특정 동작이 "깨끗한" 탭, 클릭 또는 길게 누르기가 아니라고 판단할 수 있으며(예: 터치스크린에서 손가락이 화면에 닿아 있는 동안 움직임이 너무 큰 경우), click, auxclick, 또는 contextmenu 이벤트를 발행하지 않기로 결정할 수 있습니다. 이러한 사용자 에이전트 동작의 측면은 이 명세에서 정의되지 않으며 구현마다 다를 수 있습니다.

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

작성자는 pointerdown 이벤트를 취소(cancelling)하여 특정 호환성 마우스 이벤트의 생성을 방지할 수 있습니다.

마우스 이벤트는 포인터가 눌린 상태일 때만 방지할 수 있습니다. 호버 중인 포인터(예: 버튼이 눌리지 않은 마우스)는 마우스 이벤트가 방지될 수 없습니다.

mouseover, mouseout, mouseenter, mouseleave 이벤트는 (포인터가 눌린 상태여도) 결코 방지되지 않습니다.

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

11.1 레거시 마우스 포인터의 실효 위치 추적

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

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

  1. pointerdown, pointerup 또는 pointermove 이벤트의 대상을 T로 둡니다. pointerleave 이벤트의 경우 T를 설정하지 않습니다.
  2. T와 현재 레거시 마우스 포인터의 실효 위치가 둘 다 설정되지 않았거나 서로 동일하면, 이 단계를 종료합니다.
  3. [UIEVENTS]에 따라, 현재 레거시 마우스 포인터의 실효 위치에서 T로 이동하는 마우스에 대한 mouseover, mouseout, mouseenter, mouseleave 이벤트를 디스패치합니다. 현재 레거시 마우스 포인터의 실효 위치 또는 T가 설정되지 않은 값인 경우, 이를 창 밖(out-of-window)의 마우스 위치로 간주합니다.
  4. 레거시 마우스 포인터의 실효 위치T로 설정합니다.
Note

레거시 마우스 포인터의 실효 위치 모델은 포인터 전이 이벤트(pointerover, pointerout, pointerenter, pointerleave)를 해당 레거시 마우스 전이 이벤트(mouseover, mouseout, mouseenter, mouseleave)에 항상 직접 매핑할 수는 없다는 사실을 반영합니다. 다음 애니메이션은 사용자 에이전트가 두 개의 기본 포인터를 단일 레거시 마우스 입력으로 조정하기 위해 포인터 전이 이벤트보다 더 많은 레거시 마우스 전이 이벤트를 디스패치해야 하는 사례를 보여줍니다.

Figure 9 동시에 존재하는 마우스 포인터(흰색 커서)와 터치 포인터(흰색 "손" 커서)로 인해 단일 레거시 마우스 입력(주황색 커서)이 두 포인터 사이를 이동하게 되는 모습.

이 애니메이션에서, 마우스 클릭과 터치 탭 사이의 시간 구간에 주목하십시오. 버튼 1은 이 기간 동안 "실제" 마우스 포인터가 버튼 사각형을 벗어나지 않았기 때문에 pointerout 이벤트를 받지 않습니다. 하지만 터치 탭으로 인해 레거시 마우스 포인터의 실효 위치가 버튼 2로 이동할 때 버튼 1은 mouseout 이벤트를 받습니다. 마찬가지로, 터치 탭과 마우스가 버튼 1을 떠나기 직전 사이의 시간 구간 동안 동일한 이유로 버튼 1은 pointerover 이벤트를 받지 않지만, 레거시 마우스 포인터의 실효 위치가 버튼 1 내부로 다시 이동할 때 mouseover 이벤트를 받습니다.

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

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

  1. 디스패치될 포인터 이벤트의 isPrimary 속성이 false라면 포인터 이벤트를 디스패치하고 이 단계를 종료합니다.
  2. 디스패치될 포인터 이벤트가 pointerdown, pointerup, pointermove 이벤트이거나, window에서의 pointerleave 이벤트인 경우, 레거시 마우스 포인터의 실효 위치 추적에 설명된 대로 호환성 마우스 전이 이벤트를 디스패치합니다.
  3. 포인터 이벤트를 디스패치합니다.
  4. 디스패치된 포인터 이벤트가 pointerdown이고 그 이벤트가 취소되었다면, 해당 pointerType에 대해 PREVENT MOUSE EVENT 플래그를 설정합니다.
  5. PREVENT MOUSE EVENT 플래그가 이 pointerType에 대해 설정되어 있지 않고, 디스패치된 포인터 이벤트가 다음 중 하나라면:
    • pointerdown인 경우, mousedown 이벤트를 발행합니다.
    • pointermove인 경우, mousemove 이벤트를 발행합니다.
    • pointerup인 경우, mouseup 이벤트를 발행합니다.
    • pointercancel인 경우, window에서 mouseup 이벤트를 발행합니다.
  6. 디스패치된 포인터 이벤트가 pointerup 또는 pointercancel이었다면, 이 pointerType에 대한 PREVENT MOUSE EVENT 플래그를 해제합니다.

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

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

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

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

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

사용자 에이전트가 [TOUCH-EVENTS]에 정의된 터치 이벤트와 포인터 이벤트를 모두 지원하는 경우, user agent는 이 절에서 설명하는 호환성 마우스 이벤트와 [TOUCH-EVENTS]에 요약된 대체 마우스 이벤트MUST NOT (둘 다) 생성해야 합니다.

Note

호버를 지원하지 않는 기본 포인터(예: 터치스크린의 단일 손가락)로 요소를 활성화(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 이벤트가 취소된 경우, 이벤트 시퀀스는 다음과 같습니다:

  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

12. 보안 및 프라이버시 고려사항

이 부록은 Pointer Events 구현에 대한 보안 및 프라이버시 고려사항을 논의합니다. 논의는 이 명세에서 정의된 이벤트 모델, API 및 이벤트의 구현으로부터 직접적으로 발생하는 보안 및 프라이버시 이슈로 한정됩니다.

이 명세에서 정의되는 많은 이벤트 유형은 사용자 동작에 대한 응답으로 디스패치됩니다. 이는 악의적인 이벤트 리스너가 사용자가 일반적으로 기밀로 여기는 정보(예: 페이지와 상호작용하는 동안 사용자의 마우스/스타일러스/손가락의 정확한 경로/움직임)에 접근할 수 있게 할 수 있습니다.

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

이러한 센서 데이터와 더불어, 사용된 입력 메커니즘(마우스, 터치, 펜)의 유형을 판별할 수 있는 능력은 사용자 또는 사용자의 기기 및 환경의 특성을 추론하는 데 사용될 수 있습니다. 추론된 특성과 모든 기기/환경 정보는 그 자체로 민감할 수 있습니다 — 예를 들어, 악의적인 사이트가 사용자가 보조 기술을 사용 중인지 추가로 추론하게 만들 수 있습니다. 이 정보는 또한 사용자 프로파일을 구축하거나 특정 사용자를 "fingerprint(핑거프린팅)" 및 추적하려는 목적으로 잠재적으로 사용될 수 있습니다.

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

센서에 대한 공장 보정 정보는 센서 데이터의 특정 변동과 특성을 기반으로 개별 기기를 핑거프린팅하는 데 사용될 수 있습니다. 이 명세는 많은 센서 관련 이벤트 속성을 floatdouble 정밀도로 정의하지만, 구현에서는 노출하는 센서 데이터의 정밀도를 실질적으로 유용한 수준으로 제한할 것을 권장합니다.

이 명세는 작성자가 "예측된 이벤트"에 접근할 수 있는 방법을 정의합니다. 명세 자체는 사용자 에이전트가 예측에 사용해야 하는 알고리즘을 정의하지 않습니다. 명세 작성자들은 알고리즘이 사용자가 수행 중인 현재 제스처와 관련된 이전 포인터 이벤트에만 의존하도록 상정합니다. 사용자 에이전트는 자신의 특정 예측 알고리즘 구현이 사용자에 대한 민감한 정보를 드러내거나 사용자를 "fingerprint(핑거프린팅)" 및 추적하는 데 사용될 수 있는 추가 데이터(예: 서로 다른 사이트에 걸친 사용자의 전체 상호작용 기록)에 의존하지 않도록 보장할 책임이 있습니다.

이러한 고려사항 외에, 워킹 그룹은 이 명세가 다음과 같다고 봅니다.

13. 용어집

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

활성 버튼 상태
포인터의 buttons 속성이 0이 아닌 값을 가질 때의 상태입니다. 마우스의 경우, 장치에 적어도 하나의 버튼이 눌려 있을 때입니다. 터치의 경우, 디지타이저와 물리적 접촉이 있을 때입니다. 펜의 경우, 펜이 디지타이저와 물리적 접촉을 하거나, 호버 중에 적어도 하나의 버튼이 눌려 있을 때입니다.
활성 문서
활성 포인터에 대해, 해당 포인터로부터 마지막 이벤트를 수신한 문서입니다.
활성 포인터
이벤트를 생성할 수 있는 모든 터치 접촉, 펜/스타일러스, 마우스 커서 또는 기타 포인터입니다. 특정 포인터(고유한 pointerId로 식별됨)가 문서 내에서 추가 이벤트를 생성할 수 있다면, 그 포인터는 여전히 활성으로 간주됩니다. 예:
  • 장치에 연결된 마우스는 항상 활성입니다.
  • 화면 위의 터치 접촉은 활성으로 간주됩니다.
  • 터치 접촉 또는 펜/스타일러스가 디지타이저의 범위를 넘어 들어 올려지면 더 이상 활성으로 간주되지 않습니다.
Note
일부 플랫폼에서는 활성 포인터의 집합에 사용자 에이전트를 대상으로 하지 않는 포인터 입력(예: 다른 애플리케이션을 대상으로 하는 입력)까지 포함한 장치의 모든 포인터 입력이 포함됩니다.
취소된 이벤트
preventDefault()의 사용, 이벤트 핸들러에서 false를 반환, 또는 [UIEVENTS] 및 [HTML]에 정의된 기타 수단으로 기본 동작이 방지된 이벤트입니다.
접촉 기하
디지타이저에서의 입력(가장 일반적으로 터치)의 경계 상자입니다. 이는 일반적으로 단일 픽셀보다 더 조악한 포인터 입력 해상도를 갖는 장치를 지칭합니다. 일부 장치는 이 데이터를 전혀 보고하지 않습니다.
디지타이저
표면이 접촉 및/또는 근접한 입력을 감지할 수 있는 유형의 입력 감지 장치입니다. 가장 일반적으로, 터치 접촉이나 펜/스타일러스로부터의 입력을 감지하는 표면을 말합니다.
직접 조작
일부 사용자 에이전트(예: 터치스크린 장치의 브라우저)는 포인터가 컨트롤과 상호작용할 뿐 아니라 현재 페이지를 직접 패닝 또는 줌하여 직접적인 물리적 접촉의 환상을 제공하는 "직접 조작" 은유를 구현합니다. 예를 들어, 터치스크린 장치의 사용자는 일반적으로 손가락이나 스타일러스를 사용해 페이지를 "잡고" 포인터를 움직여 페이지를 패닝함으로써 페이지를 직접 조작할 수 있습니다. 일반 데스크톱/노트북에서의 마우스 포인터와 대비하면, 패닝은 페이지를 "끌기"보다는 스크롤바를 사용하여 수행됩니다.
Note
일부 경우, 터치패드(노트북에서 볼 수 있는 종류)는 사용자가 터치패드를 "드래그"하여 스크롤할 수 있게 합니다. 그러나 이는 일반적으로 터치패드가 "가짜" 마우스 휠 이벤트를 생성함으로써 달성되므로, 직접 조작으로 간주되지 않습니다.
히트 테스트
사용자 에이전트가 포인터 이벤트의 대상 요소를 결정하는 과정입니다. 일반적으로, 이는 포인터의 위치와 화면 미디어에서 문서의 요소 시각적 레이아웃을 함께 고려하여 결정됩니다.
측정 가능한 속성들

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

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

포인터
마우스, 펜 또는 터치 접촉과 같이 화면의 특정 좌표(또는 좌표 집합)를 대상으로 할 수 있는 입력 장치를 하드웨어에 구애받지 않는 방식으로 표현한 것입니다.

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.

특히 1판의 개척을 도와주신 분들께 특별한 감사를 전합니다. 특히: Charu Chandiram, Peter Freiling, Nathan Furtwangler, Thomas Olsen, Matt Rakow, Ramu Ramanathan, Justin Rogers, Jacob Rossi, Reed Townsend, Steve Wright.

B. 변경 이력

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

다음은 [PointerEvents2] 명세와 비교하여, 이 명세의 출판물 간에 이루어진 중대하고 주요한 편집 변경 사항에 대한 정보 요약입니다. 이 명세의 에디터 초안에 대한 전체 변경 이력을 참조하십시오.

C. IDL 색인

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;
    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;
    [SecureContext] sequence<PointerEvent> getCoalescedEvents();
    sequence<PointerEvent> getPredictedEvents();
};

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

D. 참고 문헌

D.1 규범적 참고문헌

[CSS-OVERFLOW-3]
CSS Overflow Module Level 3. Elika Etemad; Florian Rivoal. W3C. 7 October 2025. W3C Working Draft. URL: https://www.w3.org/TR/css-overflow-3/
[CSS21]
Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification. Bert Bos; Tantek Çelik; Ian Hickson; Håkon Wium Lie. W3C. 7 June 2011. W3C Recommendation. URL: https://www.w3.org/TR/CSS2/
[CSSOM-VIEW]
CSSOM View Module. Simon Fraser; Emilio Cobos Álvarez. W3C. 16 September 2025. W3C Working Draft. URL: https://www.w3.org/TR/cssom-view-1/
[DOM]
DOM Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript Language Specification. Ecma International. URL: https://tc39.es/ecma262/multipage/
[HTML]
HTML Standard. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[infra]
Infra Standard. Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL: https://infra.spec.whatwg.org/
[PointerLock]
Pointer Lock. Vincent Scheib. W3C. 27 October 2016. W3C Recommendation. URL: https://www.w3.org/TR/pointerlock/
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. May 2017. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
[TOUCH-EVENTS]
Touch Events. Doug Schepers; Sangwhan Moon; Matt Brubeck; Arthur Barstow. W3C. 10 October 2013. W3C Recommendation. URL: https://www.w3.org/TR/touch-events/
[UIEVENTS]
UI Events. Gary Kacmarcik; Travis Leithead. W3C. 7 September 2024. W3C Working Draft. URL: https://www.w3.org/TR/uievents/
[WEBIDL]
Web IDL Standard. Edgar Chen; Timothy Gu. WHATWG. Living Standard. URL: https://webidl.spec.whatwg.org/

D.2 참고용 참고문헌

[COMPAT]
Compatibility Standard. Mike Taylor. WHATWG. Living Standard. URL: https://compat.spec.whatwg.org/
[PointerEvents]
Pointer Events. Jacob Rossi; Matt Brubeck. W3C. 4 April 2019. W3C Recommendation. URL: https://www.w3.org/TR/pointerevents/
[PointerEvents2]
Pointer Events. Matt Brubeck; Rick Byers; Patrick Lauke; Navid Zolghadr. W3C. 4 April 2019. W3C Recommendation. URL: https://www.w3.org/TR/pointerevents2/
[WCAG22]
Web Content Accessibility Guidelines (WCAG) 2.2. Michael Cooper; Andrew Kirkpatrick; Alastair Campbell; Rachael Bradley Montgomery; Charles Adams. W3C. 12 December 2024. W3C Recommendation. URL: https://www.w3.org/TR/WCAG22/