포인터 이벤트

레벨 4

W3C 작업 초안

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

초록

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

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

이 문서의 상태

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

이 명세는 [PointerEvents3] 명세의 업데이트이다. 또한 이전에 [UIEVENTS] 명세에 있던 Mouse 및 Wheel 이벤트를 포함한다.

이번 개정판에는 다음과 같은 새로운 기능이 포함된다:

이 문서는 Pointer Events 작업 그룹권고안 트랙을 사용하여 작업 초안으로 공개했다.

작업 초안으로 공개되었다고 해서 W3C 및 그 회원들이 이를 승인한다는 의미는 아니다.

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

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 작성했다. W3C는 해당 그룹의 결과물과 관련하여 이루어진 모든 특허 공개의 공개 목록을 유지한다. 해당 페이지에는 특허를 공개하기 위한 지침도 포함되어 있다. 자신이 필수 청구항을 포함한다고 판단하는 특허를 실제로 알고 있는 개인은 W3C 특허 정책 제6절에 따라 해당 정보를 공개해야 한다.

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

1. 소개

이 섹션은 비규범적이다.

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

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

또 다른 주요 목표는 멀티스레드 사용자 에이전트가 직접 조작 방식의 패닝 및 확대/축소 동작(예: 터치스크린에서 손가락이나 스타일러스를 사용하는 경우)을 스크립트 실행을 차단하지 않고 처리할 수 있도록 하는 것이다.

참고

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

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

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

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

Pointer 이벤트는 다양한 입력 장치에서 발생하지만, 다른 장치별 이벤트 집합으로부터 생성되는 것으로 정의되지 않는다. 호환성을 위해 그렇게 하는 것이 가능하며 권장되지만, 이 명세는 다른 장치별 이벤트(예: 마우스 이벤트 또는 터치 이벤트)의 지원을 요구하지 않는다. 사용자 에이전트는 다른 어떤 장치 이벤트도 지원하지 않고 포인터 이벤트만 지원할 수 있다. 마우스별 이벤트를 대상으로 작성된 콘텐츠와의 호환성을 위해 이 명세에서는 마우스 이외의 장치에서 발생하는 포인터 입력을 기반으로 호환성 마우스 이벤트를 생성하는 방법을 설명하는 선택적 섹션을 제공한다.

참고

이 명세는 Touch 이벤트([TOUCH-EVENTS]에서 정의됨)와 Pointer 이벤트를 모두 지원하는 사용자 에이전트의 예상 동작에 대한 어떠한 조언도 제공하지 않는다. 이 두 명세 간의 관계에 대한 자세한 내용은 Touch Events 커뮤니티 그룹을 참조한다.

2. 적합성

비규범적으로 표시된 섹션뿐만 아니라 이 명세의 모든 작성 지침, 다이어그램, 예제 및 참고 사항은 비규범적이다. 이 명세의 그 밖의 모든 내용은 규범적이다.

이 문서에서 핵심어 MAY, MUST, MUST NOT, OPTIONALSHOULD는 여기에서와 같이 모두 대문자로 표시되는 경우에만 BCP 14 [RFC2119] [RFC8174]에 설명된 대로 해석해야 한다.

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

3.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

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

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

참고

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

width

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

height

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

pressure

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

tangentialPressure

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

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

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

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

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

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

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

altitudeAngle

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

참고
여기서 altitudeAngle에 대해 정의된 기본값은 π/2이며, 이는 트랜스듀서가 표면에 수직으로 위치함을 나타낸다. 이는 기본값이 0Touch Events - Level 2 명세의 altitudeAngle 속성 정의와 다르다.
altitudeAngle 설명 다이어그램
그림 4 π/4altitudeAngle의 예(X-Y 평면으로부터 45도).
azimuthAngle

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

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

이벤트를 발생시킨 장치 유형(예: 마우스, 펜, 터치)을 나타낸다. 사용자 에이전트가 마우스, 펜/스타일러스 또는 터치 입력 장치에 대해 포인터 이벤트를 발생시키는 경우 pointerType 값은 반드시 다음 표를 따라야 한다:

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

사용자 에이전트가 장치 유형을 감지할 수 없는 경우 값은 반드시 빈 문자열이어야 한다. 사용자 에이전트가 위에 나열된 것 이외의 포인터 장치 유형을 지원하는 경우 서로 다른 장치 유형의 이름 충돌을 방지하기 위해 pointerType 값에 공급업체 접두사를 붙이는 것이 좋다. 향후 명세에서 다른 장치 유형에 대해 추가적인 규범적 값을 제공할 수 있다.

참고
pointerType을 사용하는 방법의 기본적인 예는 예제 2를 참조한다. 또한 개발자는 자체 사용자 정의 pointerType 값을 구현했을 수 있는 사용자 에이전트와 pointerType이 단순히 빈 문자열인 상황을 처리할 수 있도록 어떤 형태로든 기본 처리를 포함해야 한다.
isPrimary

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

persistentDeviceId

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

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

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

getPredictedEvents()

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

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

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

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

3.1.1 버튼 상태

3.1.1.1 동시 버튼 상호작용

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

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

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

3.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이다.
3.1.1.3 buttons 속성

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

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

3.1.2 주 포인터

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

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

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

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

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

이벤트가 발생하는 대상을 결정하는 방법은 다음과 같다:

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

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

이벤트가 pointerdown이고, 연결된 장치가 직접 조작 장치이며 대상이 Element인 경우, 암시적 포인터 캡처에 설명된 대로 이 pointerId포인터 캡처를 설정하여 대상 요소를 가리키게 한다.

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

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

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

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

이 명세에서 정의된 이벤트 유형의 bubblescancelable 속성과 기본 동작은 다음 표에 나와 있다. 각 이벤트 유형에 대한 자세한 내용은 포인터 이벤트 유형에서 제공한다.

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

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

pointerenterpointerleave 이벤트의 경우 composed [DOM] 속성은 false인 것이 좋고, 위 표의 다른 모든 포인터 이벤트에 대해서는 이 속성이 true인 것이 좋다.

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

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

MouseEvent relatedTarget과 유사하게, relatedTarget은 포인터가 방금 경계를 벗어난 요소(pointerover 또는 pointerenter 이벤트의 경우) 또는 포인터가 경계 안으로 들어가는 요소 (pointerout 또는 pointerleave 이벤트의 경우)로 초기화해야 한다. 다른 포인터 이벤트에서는 이 값의 기본값이 null이다. 요소가 포인터 캡처를 받으면 해당 포인터의 이후 모든 이벤트가 캡처 요소의 경계 내부에 있는 것으로 간주됨에 유의한다.

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

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

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

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

click, auxclickcontextmenu 이벤트에 대한 섹션에 정의된 대로, lostpointercapture 이벤트가 이미 디스패치된 후에도 해당 click, auxclick 또는 contextmenu 이벤트가 있다면 여전히 캡처 대상으로 디스패치된다.

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

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

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

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

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

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

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

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

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

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

3.1.5 tiltX / tiltYaltitudeAngle / azimuthAngle 간 변환

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

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

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

예제 1: 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};
}

3.2 PointerEvent 알고리즘

3.2.1 PointerEvent 초기화

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

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

3.2.2 PointerEvent 생성

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

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

3.2.3 MouseEvent에서 PointerEvent 생성

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

3.2.4 pointerout 이벤트를 전송할 수 있음

  1. mouseout을 해당 mouseout MouseEvent로 둔다
  2. pointerout을 "pointerout" 및 mouseout으로 MouseEvent에서 PointerEvent를 생성한 결과로 둔다
  3. pointerevent 속성을 설정한다
    편집자 주

    TODO.

  4. targetmouseout.target으로 둔다
  5. pointerouttarget에서 디스패치한다

3.2.5 pointerleave 이벤트를 전송할 수 있음

  1. mouseout을 해당 mouseout MouseEvent로 둔다
  2. pointerout을 "pointerout" 및 mouseout으로 MouseEvent에서 PointerEvent를 생성한 결과로 둔다
  3. pointerevent 속성을 설정한다
    편집자 주

    TODO.

  4. targetmouseout.target으로 둔다
  5. pointerouttarget에서 디스패치한다

3.2.6 pointerover 이벤트를 전송할 수 있음

  1. mouseout을 해당 mouseout MouseEvent로 둔다
  2. pointerout을 "pointerout" 및 mouseout으로 MouseEvent에서 PointerEvent를 생성한 결과로 둔다
  3. pointerevent 속성을 설정한다
    편집자 주

    TODO.

  4. targetmouseout.target으로 둔다
  5. pointerouttarget에서 디스패치한다

3.2.7 pointerenter 이벤트를 전송할 수 있음

  1. mouseout을 해당 mouseout MouseEvent로 둔다
  2. pointerout을 "pointerout" 및 mouseout으로 MouseEvent에서 PointerEvent를 생성한 결과로 둔다
  3. pointerevent 속성을 설정한다
    편집자 주

    TODO.

  4. targetmouseout.target으로 둔다
  5. pointerouttarget에서 디스패치한다

3.2.8 pointermove 이벤트를 전송할 수 있음

  1. mouseout을 해당 mouseout MouseEvent로 둔다
    편집자 주

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

    편집자 주

    pointermove 이벤트가 병합되는 방식을 올바르게 정의하려면 무엇이 필요한가?

  2. pointerout을 "pointerout" 및 mouseout으로 MouseEvent에서 PointerEvent를 생성한 결과로 둔다
  3. pointerevent 속성을 설정한다
    편집자 주

    TODO.

  4. targetmouseout.target으로 둔다
  5. pointerouttarget에서 디스패치한다

3.2.9 pointerdown 이벤트를 전송할 수 있음

  1. mouseout을 해당 mouseout MouseEvent로 둔다
    참고

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

  2. pointerout을 "pointerout" 및 mouseout으로 MouseEvent에서 PointerEvent를 생성한 결과로 둔다
  3. pointerevent 속성을 설정한다
    편집자 주

    TODO.

  4. targetmouseout.target으로 둔다
  5. pointerouttarget에서 디스패치한다

3.2.10 pointerrawupdate 이벤트를 전송할 수 있음

  1. mouseout을 해당 mouseout MouseEvent로 둔다
  2. targetmouseout.target으로 둔다
  3. pointerouttarget에서 디스패치한다

3.2.11 pointerup 이벤트를 전송할 수 있음

  1. mouseout을 해당 mouseout MouseEvent로 둔다
    참고

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

  2. pointerout을 "pointerout" 및 mouseout으로 MouseEvent에서 PointerEvent를 생성한 결과로 둔다
  3. pointerevent 속성을 설정한다
    편집자 주

    TODO.

  4. targetmouseout.target으로 둔다
  5. pointerouttarget에서 디스패치한다

3.3 포인터 이벤트 유형

다음은 이 명세에서 정의하는 이벤트 유형이다.

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

3.3.1 pointerover

유형 pointerover
인터페이스 PointerEvent
버블링
취소 가능
합성
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 다음 중 하나가 발생하면 포인터 이벤트를 발생시켜 pointerover라고 명명해야 한다:

3.3.2 pointerenter

유형 pointerenter
인터페이스 PointerEvent
버블링 아니요
취소 가능 아니요
합성 아니요
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 다음 중 하나가 발생하면 포인터 이벤트를 발생시켜 pointerenter라고 명명해야 한다:

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

3.3.3 pointerdown

유형 pointerdown
인터페이스 PointerEvent
버블링
취소 가능
합성
컨텍스트
(신뢰할 수 있는 이벤트)

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

참고
마우스(또는 다른 다중 버튼 포인터 장치)의 경우 이는 pointerdownpointerupmousedownmouseup과 동일한 모든 상황에서 발생하는 것은 아니라는 의미이다. 자세한 내용은 동시 버튼을 참조한다.

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

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

3.3.4 pointermove

유형 pointermove
인터페이스 PointerEvent
버블링
취소 가능
합성
컨텍스트
(신뢰할 수 있는 이벤트)

포인터에서 pointerdown 또는 pointerup 이벤트를 발생시키지 않는 속성이 변경되면 사용자 에이전트포인터 이벤트를 발생시켜 pointermove라고 명명해야 한다. 여기에는 좌표, 압력, 접선 압력, 기울기, 비틀림, 접촉 형상(widthheight) 또는 동시 버튼의 변경이 포함된다.

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

3.3.5 pointerrawupdate

유형 pointerrawupdate
인터페이스 PointerEvent
버블링
취소 가능 아니요
합성
컨텍스트
(신뢰할 수 있는 이벤트)

포인터에서 pointerdown 또는 pointerup 이벤트를 발생시키지 않는 속성이 변경되면 사용자 에이전트포인터 이벤트를 발생시켜 pointerrawupdate라고 명명해야 하며, 보안 컨텍스트 내에서만 그렇게 해야 한다. 이러한 속성의 목록은 pointermove 이벤트를 참조한다.

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

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

아직 이벤트 루프에서 디스패치되지 않은 동일한 pointerId를 가진 다른 pointerrawupdate가 이미 있는 경우, 사용자 에이전트는 새 pointerrawupdate를 새 태스크를 생성하는 대신 해당 이벤트와 병합할 수 있다. 이로 인해 pointerrawupdate에 병합된 이벤트가 포함될 수 있으며, 이벤트가 이벤트 루프에서 처리되는 즉시 모두 하나의 pointerrawupdate 이벤트의 병합된 이벤트로 전달된다. 자세한 내용은 getCoalescedEvents를 참조한다.

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

target을 제외하면 마지막 pointermove 이벤트 이후 디스패치된 모든 pointerrawupdate 이벤트의 병합된 이벤트 목록을 연결한 것은 다른 이벤트 속성 측면에서 다음 pointermove 이벤트의 병합된 이벤트와 동일하다. pointerrawupdate의 속성은 대부분 pointermove와 동일하지만, pointerrawupdate에서는 cancelable반드시 false여야 한다는 점이 다르다.

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

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

3.3.6 pointerup

유형 pointerup
인터페이스 PointerEvent
버블링
취소 가능
합성
컨텍스트
(신뢰할 수 있는 이벤트)

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

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

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

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

참고
마우스(또는 다른 다중 버튼 포인터 장치)의 경우 이는 pointerdownpointerupmousedownmouseup과 동일한 모든 상황에서 발생하는 것은 아니라는 의미이다. 자세한 내용은 동시 버튼을 참조한다.

3.3.7 pointercancel

유형 pointercancel
인터페이스 PointerEvent
버블링
취소 가능 아니요
합성
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트포인터 이벤트 스트림을 억제해야 하는 시나리오를 감지하면 포인터 이벤트를 발생시켜 pointercancel이라고 명명해야 한다.

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

3.3.8 pointerout

유형 pointerout
인터페이스 PointerEvent
버블링
취소 가능
합성
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 다음 중 하나가 발생하면 포인터 이벤트를 발생시켜 pointerout이라고 명명해야 한다:

3.3.9 pointerleave

유형 pointerleave
인터페이스 PointerEvent
버블링 아니요
취소 가능 아니요
합성 아니요
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 다음 중 하나가 발생하면 포인터 이벤트를 발생시켜 pointerleave라고 명명해야 한다:

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

3.3.10 gotpointercapture

유형 gotpointercapture
인터페이스 PointerEvent
버블링
취소 가능 아니요
합성
컨텍스트
(신뢰할 수 있는 이벤트)

요소가 포인터 캡처를 받으면 사용자 에이전트포인터 이벤트를 발생시켜 gotpointercapture라고 명명해야 한다. 이 이벤트는 포인터 캡처를 받는 요소에서 발생한다. 이후 해당 포인터의 이벤트는 이 요소에서 발생한다. 포인터 캡처 설정대기 중인 포인터 캡처 처리 섹션을 참조한다.

3.3.11 lostpointercapture

유형 lostpointercapture
인터페이스 PointerEvent
버블링
취소 가능 아니요
합성
컨텍스트
(신뢰할 수 있는 이벤트)

포인터의 포인터 캡처가 해제된 후 사용자 에이전트포인터 이벤트를 발생시켜 lostpointercapture라고 명명해야 한다. 이 이벤트는 캡처가 해제된 후 해당 포인터의 후속 이벤트보다 먼저 발생해야 한다. 이 이벤트는 포인터 캡처가 제거된 요소에서 발생한다. click, auxclickcontextmenu 이벤트를 제외한 해당 포인터의 모든 후속 이벤트는 이벤트 대상을 결정하기 위해 일반적인 히트 테스트 메커니즘(이 명세의 범위를 벗어남)을 따른다. 포인터 캡처 해제, 포인터 캡처의 암시적 해제대기 중인 포인터 캡처 처리 섹션을 참조한다.

3.3.12 click, auxclickcontextmenu

이 섹션은 MouseEventclick, auxclickcontextmenu 이벤트 정의에 추가되는 내용이다. 이러한 이벤트는 일반적으로 사용자 인터페이스 활성화와 연관되며 키보드와 같은 비포인터 입력 장치에서도 발생한다.

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

3.3.12.1 이벤트 속성

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

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

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

3.3.12.3 이벤트 디스패치

click, auxclick 또는 contextmenu 이벤트는 표준 디스패치 절차를 따라야 하지만, 이벤트 대상은 아래 알고리즘을 사용하여 재정의한다:

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

    참고

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

    userEventPointerEvent인 경우, userEventclick 또는 auxclick 이벤트에 대해서는 pointerup이고, contextmenu 이벤트에 대해서는 네이티브 플랫폼의 규칙에 따라 pointerdown 또는 pointerup 이벤트이다.

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

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

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

  4. eventtarget에 디스패치한다.

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

4. Element 인터페이스 확장

다음 섹션에서는 포인터 캡처의 설정 및 해제를 용이하게 하기 위한 기존 Element 인터페이스의 확장을 설명한다.

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

인수 pointerId로 식별되는 포인터의 포인터 캡처를 설정하여 이 메서드가 호출된 요소를 가리키게 한다. 포인터의 후속 이벤트에서는 포인터가 항상 캡처 대상 위에 있는 것처럼 캡처 대상이 일반적인 히트 테스트 결과를 대신하며, 캡처가 해제될 때까지 이러한 이벤트는 항상 이 요소를 대상으로 해야 한다. 이 메서드가 효과를 가지려면 포인터가 활성 버튼 상태에 있어야 하며, 그렇지 않으면 아무 알림 없이 실패한다. 제공된 메서드의 인수가 활성 포인터 중 어느 것과도 일치하지 않으면 "NotFoundError" DOMException발생시킨다.

releasePointerCapture()

인수 pointerId로 식별되는 포인터의 포인터 캡처를 해제하여 이 메서드가 호출된 요소에서 제거한다. 포인터의 후속 이벤트는 이벤트 대상을 결정하기 위해 일반적인 히트 테스트 메커니즘(이 명세의 범위를 벗어남)을 따른다. 제공된 메서드의 인수가 활성 포인터 중 어느 것과도 일치하지 않으면 "NotFoundError" DOMException발생시킨다.

hasPointerCapture

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

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

5. GlobalEventHandlers 믹스인 확장

다음 섹션에서는 이벤트 핸들러 등록을 용이하게 하기 위한 기존 GlobalEventHandlers 믹스인의 확장을 설명한다.

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

6. Navigator 인터페이스 확장

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

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

getter 단계는 다음과 같다:

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

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

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

7. 직접 조작 동작 선언

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

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

7.1 touch-action CSS 속성

이름: touch-action
값: auto | none | [ [ pan-x | pan-left | pan-right ] || [ pan-y | pan-up | pan-down ] ] | manipulation
초깃값: auto
적용 대상: 대체되지 않은 인라인 요소, 테이블 행, 행 그룹, 테이블 열, 열 그룹을 제외한 모든 요소
상속: 아니요
백분율: 해당 없음
미디어: 시각적
계산값: 지정된 값과 동일
정규 순서: 문법에 따름
애니메이션 유형: 애니메이션 불가

touch-action CSS 속성은 직접 조작 상호작용(속성 이름과 달리 터치에만 한정되지 않음)이 사용자 에이전트의 패닝 및 확대/축소 동작을 트리거할 수 있는지 결정한다. touch-action에 대한 섹션을 참조한다.

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

참고
일부 사용자 에이전트는 일련의 개별적인 불연속 제스처로 이루어지지만 모두 하나의 연속적인 제스처의 일부로 처리되는 동작에 대해 복잡한 제스처를 구현한다. 예를 들어 터치스크린의 "플링하여 스크롤" 제스처를 생각해 보자. 사용자가 빠르게 손가락을 움직여 문서를 패닝하기 시작하고 터치스크린에서 손가락을 떼면 문서는 시뮬레이션된 관성에 따라 계속 패닝된다. 문서가 계속 움직이는 동안 사용자는 터치스크린에 다시 손가락을 대고 또 다른 "플링"을 수행하여 패닝에 추가 운동량을 제공하거나, 현재 패닝에 반대되는 동작을 하여 속도를 늦추거나, 패닝을 완전히 멈추거나, 패닝 방향을 반대로 바꿀 수 있다. 이 명세는 제스처와 동작이 구현되는 방식을 규범적으로 정의하지 않으므로, 두 번째 터치가 두 번째 "플링" 또는 현재 패닝에 대한 반작용으로 해석되기 전에 포인터 이벤트를 발생시키는지 여부는 사용자 에이전트가 결정한다.
참고
touch-action은 임베드된 브라우징 컨텍스트까지 적용되거나 캐스케이드되지 않는다. 예를 들어 <iframe>touch-action을 적용하더라도 <iframe> 자체 내부에서 패닝 및 확대/축소를 위한 직접 조작 상호작용의 동작에는 영향을 주지 않는다.

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

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

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

7.3 touch-action 값의 세부 사항

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

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

방향별 pan 값은 일부 오버스크롤 동작을 사용자 정의하는 데 유용하다. 예를 들어 간단한 당겨서 새로고침 효과를 구현하려면 문서의 스크롤 위치가 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을 명시적으로 설정하면 이 지연이 제거된다. 탭 또는 두 번 탭 제스처를 결정하는 방법은 이 명세의 범위를 벗어남에 유의한다.
예제 2: 모든 직접 조작 동작 금지
<div style="touch-action: none;">
    이 요소는 그렇지 않으면 패닝 또는 확대/축소로 이어지는 모든 직접 조작 상호작용에 대한 포인터 이벤트를 수신한다.
</div>
예제 3: 수평 패닝만 허용
<div style="touch-action: pan-x;">
    이 요소는 수평 방향으로 패닝하지 않을 때 포인터 이벤트를 수신한다.
</div>
예제 4: 패닝 및 확대/축소를 위한 직접 조작 동작을 허용하지 않는 자식 영역
<div style="overflow: auto;">
    <div style="touch-action: none;">
        이 요소는 그렇지 않으면 패닝 또는 확대/축소로 이어지는 모든 직접 조작 상호작용에 대한 포인터 이벤트를 수신한다.
    </div>
    <div>
        이 요소에서의 직접 조작 상호작용은 부모를 조작하는 데 사용될 수 있다.
    </div>
</div>
예제 5: 패닝 및 확대/축소를 위한 직접 조작 동작을 허용하지 않는 중간 부모
<div style="overflow: auto;">
    <div style="touch-action: pan-y;">
        <div style="touch-action: pan-x;">
            이 요소는 수평 패닝만 허용하지만 중간 조상
            (이 요소와 스크롤 가능한 요소 사이)은 수직 패닝만 허용하므로
            모든 직접 조작 상호작용에 대한 포인터 이벤트를 수신한다.
            따라서 패닝/확대/축소를 위한 직접 조작 동작은
            사용자 에이전트가 처리하지 않는다.
        </div>
    </div>
</div>
예제 6: 패닝 및 확대/축소에 허용되는 직접 조작 동작을 제한하는 중간 부모
<div style="overflow: auto;">
    <div style="touch-action: pan-y pan-left;">
        <div style="touch-action: pan-x;">
            이 요소는 왼쪽으로 패닝하지 않을 때 포인터 이벤트를 수신한다.
        </div>
    </div>
</div>

8. 포인터 캡처

8.1 소개

이 섹션은 비규범적이다.

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

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

8.2 포인터 캡처 설정

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

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

8.3 포인터 캡처 해제

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

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

8.4 암시적 포인터 캡처

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

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

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

pointerup 또는 pointercancel 이벤트를 발생시킨 직후 사용자 에이전트는 방금 디스패치된 pointerup 또는 pointercancel 이벤트의 pointerId에 대한 대기 중인 포인터 캡처 대상 재정의를 지우고, 필요한 경우 lostpointercapture를 발생시키도록 대기 중인 포인터 캡처 처리 단계를 실행해야 한다. 대기 중인 포인터 캡처 처리 단계를 실행한 후 포인터가 호버를 지원하면 사용자 에이전트는 캡처되지 않은 상태의 현재 포인터 위치를 반영하는 데 필요한 해당 경계 이벤트도 전송해야 한다.

포인터 캡처 대상 재정의가 더 이상 연결된 상태가 아니면 [DOM], 포인터 캡처 대상 재정의를 문서로 설정하는 것이 좋다.

대기 중인 포인터 캡처 대상 재정의가 더 이상 연결된 상태가 아니면 [DOM], 대기 중인 포인터 캡처 대상 재정의 노드를 지우는 것이 좋다.

참고
앞의 두 단락에 따라 캡처 노드가 제거된 후 다음 대기 중인 포인터 캡처 처리 중에 캡처된 포인터에 해당하는 lostpointercapture 이벤트가 문서에서 발생한다.

요소에 포인터 잠금 [PointerLock]이 성공적으로 적용되었을 때, 캡처되도록 설정되었거나 캡처 대기 중인 요소가 하나라도 있다면 사용자 에이전트releasePointerCapture 메서드가 호출된 것처럼 단계를 실행해야 한다.

9. 병합 및 예측 이벤트

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

9.1 병합된 이벤트

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

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

PointerEvent에는 연결된 병합된 이벤트 목록(0개 이상의 PointerEvent 목록)이 있다. 신뢰할 수 있는 pointermovepointerrawupdate 이벤트의 경우 이 목록은 해당 이벤트로 병합된 모든 PointerEvent의 시퀀스이다. "부모"인 신뢰할 수 있는 pointermovepointerrawupdate 이벤트는 이러한 병합된 이벤트의 누적을 나타내지만 추가 처리가 적용될 수 있다(예: 디스플레이 재생률에 맞추기 위해). 따라서 이러한 이벤트의 병합된 이벤트 목록에는 항상 최소 하나의 이벤트가 포함된다. 그 밖의 모든 신뢰할 수 있는 이벤트 유형에서는 빈 목록이다. 신뢰할 수 없는 이벤트의 병합된 이벤트 목록은 생성자에 전달된 값으로 초기화된다.

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

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

예제 7: 병합된 이벤트 목록을 사용하는 기본 캔버스 그리기 애플리케이션
<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의 속성은 병합된 이벤트 목록의 이벤트를 가장 잘 나타내는 방식으로 초기화된다. 사용자 에이전트가 이를 수행해야 하는 구체적인 방법은 이 명세에서 다루지 않는다.

디스패치된 이 모든 이벤트의 순서는 원래 이벤트의 실제 순서와 일치해야 한다. 예를 들어 pointerdown 이벤트가 병합된 pointermove 이벤트의 디스패치를 발생시키는 경우 사용자 에이전트는 먼저 특정 pointerId의 모든 병합된 이벤트를 포함하는 하나의 pointermove 이벤트를 디스패치한 다음 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개 포함

9.2 예측된 이벤트

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

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

PointerEvent에는 연결된 예측된 이벤트 목록(0개 이상의 PointerEvent 목록)이 있다. 신뢰할 수 있는 pointermove 이벤트의 경우 이 목록은 사용자 에이전트가 미래에 해당 이벤트 뒤에 이어질 것으로 예측하는 PointerEvent의 시퀀스이다. 그 밖의 모든 신뢰할 수 있는 이벤트 유형에서는 빈 목록이다. 신뢰할 수 없는 이벤트의 예측된 이벤트 목록은 생성자에 전달된 값으로 초기화된다.

참고

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

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

목록의 이벤트 수와 현재 타임스탬프에서 얼마나 먼지는 사용자 에이전트 및 사용자 에이전트가 사용하는 예측 알고리즘에 의해 결정된다.

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

참고

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

예제 8: 병합된 이벤트 및 예측된 이벤트를 사용한 그리기의 개념적 접근 방식

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

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

신뢰할 수 있는 PointerEvent가 생성되면 사용자 에이전트는 병합된 이벤트 목록예측된 이벤트 목록의 각 이벤트에 대해 다음 단계를 실행하는 것이 좋다:

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

신뢰할 수 있는 PointerEventtarget이 변경되면 사용자 에이전트는 병합된 이벤트 목록예측된 이벤트 목록의 각 이벤트에 대해 다음을 수행하는 것이 좋다:

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

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

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

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

참고

개념적으로 호환성 마우스 이벤트는 각각에 해당하는 포인터 이벤트와 "교차 배치"되도록 의도되어 있다. 그러나 이 특정 순서는 필수가 아니며, 호환성 마우스 이벤트를 구현하는 사용자 에이전트는 상대적인 순서가 일관되기만 한다면 마우스 이벤트의 디스패치를 지연하거나 그룹화하기로 결정할 수 있다.

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

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

참고

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

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

달리 언급되지 않는 한, 매핑된 모든 마우스 이벤트의 대상은 해당 대상이 더 이상 ownerDocument의 트리에 참여하지 않는 경우를 제외하면 각각의 포인터 이벤트와 동일한 대상인 것이 좋다. 이 경우 마우스 이벤트는 원래 대상이 트리에서 제거된 시점에 ownerDocument의 트리에 여전히 참여하고 있던 원래 대상의 가장 가까운 조상 노드에서 발생시키는 것이 좋다. 즉, 마우스 이벤트를 위해 (새 대상 노드를 기반으로 한) 새 이벤트 경로가 구성된다.

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

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

mouseover, mouseout, mouseentermouseleave 이벤트는 절대로 방지되지 않는다(포인터가 눌린 상태인 경우에도).

포인터 이벤트 EventListenerpassive로 설정되어 있으면 [DOM] 호환성 마우스 이벤트를 방지할 수 없다.

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

주 포인터만 호환성 마우스 이벤트를 생성할 수 있지만, 여러 주 포인터가 동시에 활성 상태일 수 있으며, 각각 자체적인 호환성 마우스 이벤트를 생성할 수 있다. MouseEvents에 의존하는 스크립트와의 호환성을 위해 마우스 전환 이벤트 (mouseover, mouseout, mouseentermouseleave)는 단일 레거시 마우스 입력의 움직임을 시뮬레이션하는 것이 좋다. 이는 모든 이벤트 대상의 진입/이탈 상태가 유효하다는 의미이다. 사용자 에이전트는 다음과 같이 문서에서 레거시 마우스 포인터의 유효 위치를 유지하여 이를 보장하는 것이 좋다.

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

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

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

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

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

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

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

  1. 디스패치할 포인터 이벤트의 isPrimary 속성이 false이면 포인터 이벤트를 디스패치하고 이 단계를 종료한다.
  2. 디스패치할 포인터 이벤트가 pointerdown, pointerup 또는 pointermove 이벤트이거나, window에서의 pointerleave 이벤트인 경우 레거시 마우스 포인터의 유효 위치 추적에 설명된 대로 호환성 마우스 전환 이벤트를 디스패치한다.
  3. 포인터 이벤트를 디스패치한다.
  4. 디스패치된 포인터 이벤트가 pointerdown이고 이벤트의 취소 플래그가 설정되어 있으면 이 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 플래그를 지운다.

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

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

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

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

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

사용자 에이전트가 Touch Events([TOUCH-EVENTS]에서 정의됨)와 Pointer Events를 모두 지원하는 경우 사용자 에이전트는 이 섹션에서 설명한 호환성 마우스 이벤트와 [TOUCH-EVENTS]에 설명된 대체 마우스 이벤트둘 다 생성해서는 안 된다.

참고

호버를 지원하지 않는 주 포인터 (예: 터치스크린의 한 손가락)를 사용하여 요소를 활성화(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

11. 마우스 이벤트 및 인터페이스

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

DOM 레벨 2에서 도입되었으며 이 명세에서 수정되었다.

MouseEvent 인터페이스는 마우스 이벤트와 관련된 특정 컨텍스트 정보를 제공한다.

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

참고

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

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

참고

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

11.1 MouseEvent 인터페이스

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

[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

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

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

screenY

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

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

clientX

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

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

clientY

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

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

layerX

조상 요소 중 스태킹 컨텍스트이거나, 위치가 지정되어 있거나, 스태킹 컨텍스트를 페인트할 때 위치 지정 단계에서 페인트되는 가장 가까운 요소로부터의 수평 오프셋.

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

layerY

조상 요소 중 스태킹 컨텍스트이거나, 위치가 지정되어 있거나, 스태킹 컨텍스트를 페인트할 때 위치 지정 단계에서 페인트되는 가장 가까운 요소로부터의 수직 오프셋.

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

ctrlKey

KeyboardEventctrlKey 속성을 참조한다.

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

shiftKey

KeyboardEventshiftKey 속성을 참조한다.

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

altKey

KeyboardEventaltKey 속성을 참조한다.

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

metaKey

KeyboardEventmetaKey 속성을 참조한다.

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

button

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

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

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

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

참고

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

참고

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

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

buttons

모든 마우스 이벤트 동안 buttons는 현재 어떤 마우스 버튼 조합이 눌려 있는지를 비트마스크로 나타내는 데 사용해야 한다.

참고

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

참고

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

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

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

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

참고

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

참고

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

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

relatedTarget

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

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

relatedTarget은 마우스 포인터가 방금 경계를 벗어난 요소(mouseover 또는 mouseenter 이벤트의 경우) 또는 마우스 포인터가 경계 안으로 들어가는 요소(mouseout, mouseleave 또는 focusout 이벤트의 경우)로 초기화하는 것이 좋다. 다른 이벤트에서는 이 값을 할당할 필요가 없으며 기본값은 null이다.

getModifierState(keyArg)

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

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

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

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

11.2 MouseEvent 알고리즘

11.2.1 네이티브 OS 요구사항

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

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

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

11.2.2 Mouse 이벤트 구성

경고

이 섹션은 수정이 필요하다.

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

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

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

  • 구성 중인 EventMouseEvent 객체 또는 그로부터 파생된 객체이고, EventModifierInit 인수가 생성자에 제공된 경우 다음 하위 단계를 실행한다:

11.2.3 MouseEvent의 전역 상태

경고

이 섹션은 수정이 필요하다.

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

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

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

11.2.3.2 Window 수준 상태

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

MouseEvent를 전송한 마지막 Element를 추적하는 마지막 마우스 요소 값(초기에는 undefined).

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

11.2.4 MouseEvent의 내부 상태

경고

이 섹션은 수정이 필요하다.

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

11.2.5 히트 테스트

경고

이 섹션은 수정이 필요하다.

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

    비활성 또는 사용 불가 요소를 고려하려면, 이는 elementsFromPoint()를 호출하고 유효하지 않은 요소를 제외해야 한다.

11.2.6 MouseEvent 초기화

경고

이 섹션은 수정이 필요하다.

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

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

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

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

경고

이 섹션은 수정이 필요하다.

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

11.2.8 취소 가능한 MouseEvent 생성

경고

이 섹션은 수정이 필요하다.

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

11.2.9 취소할 수 없는 MouseEvent 생성

경고

이 섹션은 수정이 필요하다.

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

11.2.10 MouseEvent button 속성 계산

경고

이 섹션은 수정이 필요하다.

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

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

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

경고

이 섹션은 수정이 필요하다.

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

    TODO.

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

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

경고

이 섹션은 수정이 필요하다.

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

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

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

11.2.13 네이티브 마우스 업 처리

경고

이 섹션은 수정이 필요하다.

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

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

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

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

경고

이 섹션은 수정이 필요하다.

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

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

  2. targetnative의 뷰포트 상대 좌표로 히트 테스트한 결과로 둔다
  3. nativetarget으로 click 이벤트를 전송한다.

11.2.15 click 이벤트 전송

경고

이 섹션은 수정이 필요하다.

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

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

    편집자 주

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

    참고

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

    참고

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

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

경고

이 섹션은 수정이 필요하다.

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

    더블 클릭을 생성하는 마우스 클릭의 경우 네이티브 마우스 클릭 처리 직후에 이를 호출해야 한다.

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

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

경고

이 섹션은 수정이 필요하다.

  1. native를 네이티브 마우스 이동으로 둔다
    이슈 2

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

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

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

    2. mouseout으로 pointerout 이벤트를 전송할 수 있음을 실행한다
    3. target에서 mouseout디스패치한다
      참고

      취소된 경우의 동작을 확인해야 한다(영향이 없는 것으로 보임).

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

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

      1. mouseleave를 "mouseleave" 및 element취소할 수 없는 MouseEvent를 생성한 결과로 둔다
      2. mouseleave.Event.composed = false로 설정한다
        참고

        호환성 확인: event.composed의 값. 명세에서는 false라고 한다. Chrome/Linux = true. Firefox/Linux = false.

      3. mouseleavepointerleave 이벤트를 전송할 수 있음을 실행한다
      4. resultelement에서 mouseleave디스패치한 결과로 둔다
  5. 새 요소에 들어가는 이벤트를 생성한다:
    1. target마지막 마우스 요소가 아니면
      1. mouseover를 "mouseover" 및 target으로 취소 가능한 MouseEvent를 생성한 결과로 둔다
        편집자 주

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

      2. mouseoverpointerover 이벤트를 전송할 수 있음을 실행한다
      3. target에서 mouseout디스패치한다
        참고

        취소된 경우의 동작을 확인해야 한다(영향이 없는 것으로 보임).

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

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

        1. mouseenter를 "mouseenter" 및 element취소할 수 없는 MouseEvent를 생성한 결과로 둔다
        2. mouseenter.Event.composed = false로 설정한다
          참고

          호환성 확인: event.composed의 값. 명세에서는 false라고 한다. Chrome/Linux = true. Firefox/Linux = false.

        3. mouseenterpointerenter 이벤트를 전송할 수 있음을 실행한다
          참고

          shadow DOM 요소의 호환성을 확인해야 한다. Chrome/Linux는 요소와 shadow root에서 이 이벤트를 발생시킨다.

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

11.2.18 컨텍스트 메뉴를 표시할 수 있음

경고

이 섹션은 수정이 필요하다.

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

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

11.3 Mouse 이벤트 순서

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

# 이벤트 유형 요소 참고
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로 표시된 세 요소는 모두 웹 페이지에서 동일한 크기와 절대 위치를 가진다. DOM에서 요소 C는 B의 자식이고, B는 A의 자식이다:

서로 완전히 겹쳐 쌓인 세 요소의 그래픽 표현. 가장 아래 요소는 A로 표시되고 가장 위 요소는 C로 표시됨
그림 10 서로 완전히 겹쳐 쌓인 세 요소와 포인팅 장치가 그 스택 위로 이동하는 모습을 나타낸 그래픽 표현.

포인팅 장치가 요소 스택 바깥에서 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 선택 사항, 여러 이벤트, 일부 제한
3 mouseup
4 click
5 mousemove 선택 사항, 여러 이벤트, 일부 제한
6 mousedown
7 mousemove 선택 사항, 여러 이벤트, 일부 제한
8 mouseup
9 click
10 dblclick
참고

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

각 구현은 적절한 히스테리시스 허용 오차를 결정하지만, 일반적으로 연관된 mousedownmouseup 이벤트의 이벤트 대상이 동일한 요소이고 그 사이에 mouseout 또는 mouseleave 이벤트가 없는 경우 clickdblclick 이벤트를 발생시키는 것이 좋고, 연관된 mousedownmouseup 이벤트의 대상이 서로 다른 경우에는 가장 가까운 공통 포괄 조상에서 clickdblclick 이벤트를 발생시키는 것이 좋다.

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

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

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

11.4 Mouse 이벤트 유형

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

11.4.1 auxclick

유형 auxclick
인터페이스 PointerEvent
버블링
취소 가능
합성
컨텍스트
(신뢰할 수 있는 이벤트)

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

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

auxclick 이벤트보다 먼저 동일한 요소에서 mousedownmouseup 이벤트가 발생할 MAY 있으며, 다른 노드 유형 (예: 텍스트 노드) 사이의 변화는 무시한다. 환경 구성에 따라 포인팅 장치 버튼을 누르고 놓는 사이에 mouseover, mousemovemouseout 이벤트 유형 중 하나 이상이 발생하더라도 auxclick 이벤트가 디스패치될 MAY 있다.

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

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

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

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

11.4.2 click

유형 click
인터페이스 PointerEvent
버블링
취소 가능
합성
컨텍스트
(신뢰할 수 있는 이벤트)

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

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

click 이벤트보다 먼저 mousedownmouseup 이벤트가 동일한 요소에서 발생할 MAY 있으며, 다른 노드 유형 (예: 텍스트 노드) 사이의 변화는 무시한다. 환경 구성에 따라 포인팅 장치 버튼을 누르고 놓는 사이에 mouseover, mousemovemouseout 이벤트 유형 중 하나 이상이 발생하더라도 click 이벤트가 디스패치될 MAY 있다. 또한 click 이벤트 뒤에 dblclick 이벤트가 이어질 MAY 있다.

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

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

참고

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

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

  • 대상에 연결된 활성화 동작이 있는 경우 기본 동작은 해당 활성화 동작을 실행하는 것이어MUST 한다.
  • 대상이 포커스 가능하면 기본 동작은 해당 요소에 문서 포커스를 부여하는 것이어MUST 한다.

11.4.3 contextmenu

유형 contextmenu
인터페이스 PointerEvent
버블링
취소 가능
합성
컨텍스트
(신뢰할 수 있는 이벤트)

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

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

참고

플랫폼에 따라 contextmenu 이벤트는 mouseup 이벤트보다 먼저 또는 나중에 디스패치될 수 있다.

11.4.4 dblclick

유형 dblclick
인터페이스 MouseEvent
버블링
취소 가능
합성
컨텍스트
(신뢰할 수 있는 이벤트)

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

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

참고

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

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

11.4.5 mousedown

유형 mousedown
인터페이스 MouseEvent
버블링
취소 가능
합성
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 포인팅 장치 버튼이 요소 위에서 눌릴 때 이 이벤트를 디스패치해MUST 한다.

참고

많은 구현은 mousedown 이벤트를 사용하여 컨텍스트에 따라 달라지는 다양한 기본 동작을 시작한다. 이러한 기본 동작은 이 이벤트가 취소되면 방지할 수 있다. 이러한 기본 동작에는 이미지 또는 링크에 대한 드래그 앤 드롭 상호작용 시작, 텍스트 선택 시작 등이 포함될 수 있다. 또한 일부 구현은 mousedown 이벤트가 디스패치되는 시점에 가운데 마우스 버튼이 눌려 있으면 활성화되는 마우스 기반 패닝 기능을 제공한다.

11.4.6 mouseenter

유형 mouseenter
인터페이스 MouseEvent
버블링 아니요
취소 가능 아니요
합성 아니요
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 포인팅 장치가 요소 또는 그 자손 요소 중 하나의 경계 안으로 이동할 때 이 이벤트를 디스패치해MUST 한다. 또한 사용자 에이전트는 요소 또는 그 자손 중 하나가 이동하여 주 포인팅 장치 아래에 위치하게 될 때 이 이벤트를 디스패치해MUST 한다. 이 이벤트 유형은 mouseover와 유사하지만 버블링되지 않으며, 포인팅 장치가 요소에서 그 자손 요소 중 하나의 경계로 이동할 때는 디스패치되어MUST NOT 한다는 점에서 다르다.

참고

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

11.4.7 mouseleave

유형 mouseleave
인터페이스 MouseEvent
버블링 아니요
취소 가능 아니요
합성 아니요
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 포인팅 장치가 요소와 그 모든 자손 요소의 경계 밖으로 이동할 때 이 이벤트를 디스패치해MUST 한다. 또한 사용자 에이전트는 요소 또는 그 자손 중 하나가 이동하여 더 이상 주 포인팅 장치 아래에 있지 않게 될 때 이 이벤트를 디스패치해MUST 한다. 이 이벤트 유형은 mouseout과 유사하지만 버블링되지 않으며, 포인팅 장치가 요소와 모든 자식 요소의 경계를 떠날 때까지 디스패치되어MUST NOT 한다는 점에서 다르다.

참고

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

11.4.8 mousemove

유형 mousemove
인터페이스 MouseEvent
버블링
취소 가능
합성
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 포인팅 장치가 요소 위에서 이동할 때 이 이벤트를 디스패치해MUST 한다. 포인팅 장치가 이동하는 동안의 이벤트 발생 빈도는 구현, 장치 및 플랫폼에 따라 다르지만, 지속적인 포인터 장치 이동에서는 각 마우스 이동마다 단일 이벤트만 발생시키는 대신 연속된 여러 mousemove 이벤트를 발생시키는 것이 SHOULD 좋다. 구현은 응답성과 성능의 균형을 맞추기 위한 최적의 빈도를 결정하는 것이 권장된다.

참고

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

참고

이 이벤트는 이전에 DOM 레벨 2 Events에서 취소할 수 없는 것으로 명시되었지만, 사용자 에이전트 간 기존 상호운용성을 반영하기 위해 변경되었다.

11.4.9 mouseout

유형 mouseout
인터페이스 MouseEvent
버블링
취소 가능
합성
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 포인팅 장치가 요소의 경계 밖으로 이동하거나 요소가 이동하여 더 이상 주 포인팅 장치 아래에 있지 않게 될 때 이 이벤트를 디스패치해MUST 한다. 이 이벤트 유형은 mouseleave와 유사하지만 버블링되며, 포인팅 장치가 요소에서 그 자손 요소 중 하나의 경계로 이동할 때 디스패치되어MUST 한다는 점에서 다르다.

참고

mouseover 이벤트 유형도 참조한다.

11.4.10 mouseover

유형 mouseover
인터페이스 MouseEvent
버블링
취소 가능
합성
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 포인팅 장치가 요소의 경계 안으로 이동하거나 요소가 이동하여 주 포인팅 장치 아래에 위치하게 될 때 이 이벤트를 디스패치해MUST 한다. 이 이벤트 유형은 mouseenter와 유사하지만 버블링되며, 같은 이벤트 리스너 인스턴스의 대상인 조상 요소를 가진 요소의 경계 안으로 포인터 장치가 이동할 때 디스패치되어MUST 한다는 점에서 다르다.

참고

mouseout 이벤트 유형도 참조한다.

11.4.11 mouseup

유형 mouseup
인터페이스 MouseEvent
버블링
취소 가능
합성
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 포인팅 장치 버튼이 요소 위에서 놓일 때 이 이벤트를 디스패치해MUST 한다.

참고

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

12. 휠 이벤트 및 인터페이스

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

사용자의 환경은 수직 스크롤을 y축을 따른 회전과, 수평 스크롤을 x축을 따른 회전과, 확대/축소를 z축을 따른 회전과 연결하도록 구성되어 있을 수 있다.

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

참고

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

deltaX, deltaY 및 deltaZ 속성 값의 부호(양수 또는 음수)는 실제 휠 장치의 움직임이 동일한 방향으로 회전/이동하는 동안 wheel 이벤트가 여러 번 디스패치되더라도 일관되어MUST 한다. 사용자 에이전트가 wheel 이벤트의 기본 동작으로 스크롤하는 경우 델타의 부호는 양의 X, Y 및 Z축이 각각 문서의 가장 오른쪽 가장자리, 가장 아래쪽 가장자리 및 가장 먼 깊이(사용자에서 멀어지는 방향)를 향하는 오른손 좌표계에 따라 주어지는 것이 SHOULD 좋다.

참고

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

사용자 에이전트는 첫 번째 휠 이벤트가 발생할 때 휠 이벤트 트랜잭션을 생성MUST 하여, 구현별 시간 범위 내의 모든 후속 휠 이벤트가 동일한 요소를 대상으로 할 수 있도록 해야 한다. 휠 이벤트 트랜잭션은 하나의 사용자 제스처와 연결된 일련의 휠 이벤트이다. 휠 이벤트 트랜잭션은 그룹의 첫 번째 휠 이벤트가 발생할 당시의 최상위 이벤트 대상인 연결된 이벤트 대상을 가져MUST 한다.

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

12.1 WheelEvent 인터페이스

WheelEvent 인터페이스는 wheel 이벤트와 관련된 특정 컨텍스트 정보를 제공한다.

WheelEvent 인터페이스의 인스턴스를 생성하려면 WheelEvent 생성자를 사용하고 선택적인 WheelEventInit 딕셔너리를 전달한다.

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

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

    readonly attribute double deltaX;
    readonly attribute double deltaY;
    readonly attribute double deltaZ;
    readonly attribute unsigned long deltaMode;
    readonly attribute boolean momentum;
};
DOM_DELTA_PIXEL
델타의 측정 단위는 픽셀이어MUST 한다. 이는 대부분의 운영체제 및 구현 구성에서 가장 일반적인 경우이다.
DOM_DELTA_LINE
델타의 측정 단위는 개별 텍스트 줄이어MUST 한다. 이는 많은 폼 컨트롤에 해당한다.
DOM_DELTA_PAGE
델타의 측정 단위는 페이지여MUST 하며, 단일 화면 또는 구분된 페이지로 정의될 수 있다.
deltaX
wheel 이벤트의 기본 동작이 스크롤인 사용자 에이전트에서는, 이벤트가 취소되지 않았을 때 스크롤할 x축 방향의 측정값(픽셀, 줄 또는 페이지 단위)이 값이어MUST 한다. 그렇지 않은 경우 이는 휠 장치의 x축 주위 움직임에 대한 구현별 측정값(픽셀, 줄 또는 페이지 단위)이다. 이 속성의 초기화되지 않은 값0.0이어MUST 한다.
deltaY
wheel 이벤트의 기본 동작이 스크롤인 사용자 에이전트에서는, 이벤트가 취소되지 않았을 때 스크롤할 y축 방향의 측정값(픽셀, 줄 또는 페이지 단위)이 값이어MUST 한다. 그렇지 않은 경우 이는 휠 장치의 y축 주위 움직임에 대한 구현별 측정값(픽셀, 줄 또는 페이지 단위)이다. 이 속성의 초기화되지 않은 값0.0이어MUST 한다.
deltaZ

wheel 이벤트의 기본 동작이 스크롤인 사용자 에이전트에서는, 이벤트가 취소되지 않았을 때 스크롤할 z축 방향의 측정값(픽셀, 줄 또는 페이지 단위)이 값이어MUST 한다. 그렇지 않은 경우 이는 휠 장치의 z축 주위 움직임에 대한 구현별 측정값(픽셀, 줄 또는 페이지 단위)이다.

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

WheelEvent 객체의 deltaZ 속성을 초기화한다. 이 속성의 상대적인 양수 값(deltaXdeltaY 속성도 마찬가지)은 X, Y 및 Z축이 각각 문서의 가장 오른쪽 가장자리, 가장 아래쪽 가장자리, 가장 먼 깊이(사용자에서 멀어지는 방향)를 향하는 오른손 좌표계에 의해 주어진다. 음의 상대 값은 각각 반대 방향이다.

deltaMode

deltaMode 속성은 델타 값의 측정 단위를 나타낸다. 기본값은 DOM_DELTA_PIXEL(픽셀)이다.

이 속성은 델타 값의 측정 단위를 나타내기 위해 DOM_DELTA 상수 중 하나로 설정되어MUST 한다. 정확한 측정 방식은 장치, 운영체제 및 애플리케이션 구성에 따라 달라진다.

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

momentum

사용자가 물리적인 스크롤 상호작용을 끝낸 후 (예: 플링 후 트랙패드에서 손가락을 뗀 경우) 스크롤 관성을 시뮬레이션하기 위해 플랫폼이 이 이벤트를 합성했다면 이 속성은 true여야 하고, 그렇지 않으면 false여야 한다.

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

12.2 휠 이벤트 유형

12.3 wheel

유형 wheel
인터페이스 WheelEvent
버블링
취소 가능 경우에 따라 다름
합성
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 마우스 휠이 어떤 축을 중심으로 회전했거나, 동등한 입력 장치 (예: 마우스 볼, 특정 태블릿 또는 터치패드 등)가 이러한 동작을 에뮬레이션했을 때 이 이벤트를 디스패치해MUST 한다. 플랫폼과 입력 장치에 따라 대각선 휠 델타는 0이 아닌 여러 축을 가진 하나의 wheel 이벤트로 전달되거나, 0이 아닌 각 축마다 별도의 wheel 이벤트로 전달될 MAY 있다.

wheel 이벤트 유형의 일반적인 기본 동작은 표시된 양만큼 문서를 스크롤(또는 일부 경우 확대/축소)하는 것이다. 이 이벤트가 취소되면 구현은 문서를 스크롤하거나 확대/축소해MUST NOT 하며 (또는 이 이벤트 유형과 연결된 다른 구현별 기본 동작을 수행해서는 안 된다).

참고

일부 사용자 에이전트 또는 일부 입력 장치에서는 휠을 돌린 속도가 델타 값에 영향을 줄 수 있으며, 더 빠른 속도는 더 큰 델타 값을 생성한다.

12.3.1 휠 이벤트의 취소 가능성

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

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

13. 예제

이 섹션은 비규범적이다.

다음은 저자가 이 명세의 일부 API를 어떻게 사용할 수 있는지 보여 주는 기본 예제이다. 더 구체적인 예제는 이 문서의 관련 섹션에서 제공한다.

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

if (window.PointerEvent) {
    // 포인터 이벤트가 지원되면 포인터 이벤트만 수신한다
    target.addEventListener("pointerdown", function(e) {
        // 필요한 경우 e.pointerType에 따라 별도의 로직을 적용한다
        // 서로 다른 터치/펜/마우스 동작에 대해
        ...
    });
    ...
} else {
    // 기존 터치/마우스 이벤트 핸들러
    target.addEventListener('touchstart', function(e) {
        // 호환성 마우스 이벤트 및 click을 방지한다
        e.preventDefault();
        ...
    });
    ...
    target.addEventListener('mousedown', ...);
    ...
}

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

function detectInputType(event) {
    switch(event.pointerType) {
        case "mouse":
            /* 마우스 입력 감지 */
            break;
        case "pen":
            /* 펜/스타일러스 입력 감지 */
            break;
        case "touch":
            /* 터치 입력 감지 */
            break;
        default:
            /* pointerType이 비어 있음(감지할 수 없음)
            또는 UA별 사용자 정의 유형 */
    }
}
예제 13: 접촉 형상에 맞게 요소 크기 조정
<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>
예제 14: 스크립트에서 신뢰할 수 없는 포인터 이벤트 발생시키기
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);
예제 15: 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>

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

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

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

포인터 이벤트에는 사용자의 장치에서 지원되는 경우 펜 입력을 잡고 있는 각도 또는 기울기, 접촉 표면의 형상, 스타일러스나 터치스크린에 가해지는 압력과 같은 추가 정보가 포함된다. 각도, 기울기, 형상 및 압력에 관한 정보는 사용자의 장치에 있는 센서와 직접 관련되므로 이 명세는 오리진이 이러한 센서에 접근할 수 있도록 한다.

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

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

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

이러한 고려사항 외에도 작업 그룹은 이 명세가 다음과 같다고 본다:

15. 용어집

이 섹션은 비규범적이다.

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

측정 가능한 속성은 실수 또는 넓은 도메인의 정수를 사용하여 표현되는 연속적인 포인터 센서 데이터와 관련된 값을 나타낸다. 포인터 이벤트에서는 width, height, pressure, tangentialPressure, tiltX, tiltY, twist, altitudeAngle, azimuthAngle 및 Mouse Event 모델 속성인 screenX, screenY, clientX, clientY가 측정 가능한 속성이다.

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

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

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

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

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

WebIDLpartial interface MouseEvent {
	// 이 명세에서 폐기됨
	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를 지정한다. 이 값은 nullMAY 있다.
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을 지정한다. 이 값은 nullMAY 있다.

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] 명세와 비교한, 이 명세의 각 공개 버전 사이의 실질적이고 주요한 편집 변경 사항에 대한 정보 제공용 요약이다. 이 명세의 편집자 초안의 전체 개정 이력을 참조한다.

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

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

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

[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 WheelEventInit : MouseEventInit {
    double deltaX = 0.0;
    double deltaY = 0.0;
    double deltaZ = 0.0;
    unsigned long deltaMode = 0;
    boolean momentum = false;
};

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

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

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 View 모듈. 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/
[PointerLock]
Pointer Lock 2.0. Mustaq Ahmed; Vincent Scheib. W3C. 2026년 2월 25일. W3C 작업 초안. URL: https://www.w3.org/TR/pointerlock-2/
[RFC2119]
요구사항 수준을 나타내기 위해 RFC에서 사용하는 핵심 단어. S. Bradner. IETF. 1997년 3월. 현행 모범 사례. URL: https://www.rfc-editor.org/info/rfc2119/
[RFC8174]
RFC 2119 핵심 단어에서 대문자와 소문자의 모호성. B. Leiba. IETF. 2017년 5월. 현행 모범 사례. URL: https://www.rfc-editor.org/info/rfc8174/
[TOUCH-EVENTS]
터치 이벤트. Doug Schepers; Sangwhan Moon; Matt Brubeck; Arthur Barstow. W3C. 2013년 10월 10일. W3C 권고안. URL: https://www.w3.org/TR/touch-events/
[UIEvents]
UI 이벤트. Xiaoqian Wu. W3C. 2026년 2월 21일. W3C 작업 초안. URL: https://www.w3.org/TR/uievents/
[UIEvents-Key]
UI Events 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년 8월 18일. 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/
[PointerEvents]
포인터 이벤트. Patrick Lauke; Robert Flack. W3C. 2026년 7월 1일. W3C 작업 초안. URL: https://www.w3.org/TR/pointerevents4/
[PointerEvents3]
포인터 이벤트. Patrick Lauke; Robert Flack. W3C. 2026년 6월 30일. W3C 권고안. URL: https://www.w3.org/TR/pointerevents3/
[WCAG22]
웹 콘텐츠 접근성 지침(WCAG) 2.2. Michael Cooper; Andrew Kirkpatrick; Alastair Campbell; Rachael Bradley Montgomery; Charles Adams. W3C. 2024년 12월 12일. W3C 권고안. URL: https://www.w3.org/TR/WCAG22/