The Pointer Events specification defines a unified hardware-agnostic framework for handling input from various devices, including mice, touchscreens, and pens/styluses. By providing a single set of events (e.g., pointerdown, pointermove, pointerup), it allows developers to support diverse input methods without writing device-specific logic for each.

This specification also defines Mouse and Wheel Events, as well as a mapping to fire Mouse Events for other pointer device types.

This specification is an update to [[PointerEvents3]] specification. It also includes the Mouse and Wheel Events, previously in the [[UIEVENTS]] specification.

This revision includes new features:

Introduction

Today, most [[HTML]] content is used with and/or designed for mouse input. Those that handle input in a custom manner typically code to [[UIEVENTS]] Mouse Events. Newer computing devices today, however, incorporate other forms of input, including touchscreens and pen input. Event types have been proposed for handling each of these forms of input individually. However, that approach often incurs unnecessary duplication of logic and event handling overhead when adding support for a new input type. This often creates a compatibility problem when content is written with only one device type in mind. Additionally, for compatibility with existing mouse-based content, most user agents fire Mouse Events for all input types. This makes it ambiguous whether a Mouse Event represents an actual mouse device or is being produced from another input type for compatibility, which makes it hard to code to both device types simultaneously.

To reduce the cost of coding to multiple input types and also to help with the above described ambiguity with Mouse Events, this specification defines a more abstract form of input, called a pointer. A pointer can be any point of contact on the screen made by a mouse cursor, pen, touch (including multi-touch), or other pointing input device. This model makes it easier to write sites and applications that work well no matter what hardware the user has. For scenarios when device-specific handling is desired, this specification also defines properties for inspecting the device type which produced the event. The primary goal is to provide a single set of events and interfaces that allow for easier authoring for cross-device pointer input while still allowing for device-specific handling only when necessary for an augmented experience.

An additional key goal is to enable multi-threaded user agents to handle direct manipulation actions for panning and zooming (for instance, with a finger or stylus on a touchscreen), without blocking on script execution.

While this specification defines a unified event model for a variety of pointer inputs, this model does not cover other forms of input such as keyboards or keyboard-like interfaces (for instance, a screen reader or similar assistive technology running on a touchscreen-only device, which allows users sequential navigation through focusable controls and elements). While user agents might choose to also generate pointer events in response to these interfaces, this scenario is not covered in this specification.

In the first instance, authors are encouraged to provide equivalent functionality for all forms of input by responding to high-level events such as [=HTMLElement/focus=], [=HTMLElement/blur=] and click. However, when using low-level events (such as Pointer Events), authors are encouraged to ensure that all types of input are supported. In the case of keyboards and keyboard-like interfaces, this might require the addition of explicit keyboard event handling. See Keyboard Accessible [[WCAG22]] for further details.

Pointer input combines various input sources such as mouse, pen, and touch
A pointer is a hardware-agnostic representation of input devices that can target a specific coordinate (or set of coordinates) on a screen.

The events for handling generic pointer input look a lot like those for mouse: {{pointerdown}}, {{pointermove}}, {{pointerup}}, {{pointerover}}, {{pointerout}}, and so on. This facilitates easy content migration from Mouse Events to Pointer Events. Pointer Events provide all the usual properties present in Mouse Events (including client coordinates, target element, button states) in addition to new properties for other forms of input, such as pressure, contact geometry, tilt. Authors can easily code to Pointer Events to share logic between different input types where it makes sense, and customize for a particular type of input only where necessary to get the best experience.

While Pointer Events are sourced from a variety of input devices, they are not defined as being generated from some other set of device-specific events. While possible and encouraged for compatibility, this spec does not require other device-specific events be supported (such as mouse events or touch events). A user agent could support pointer events without supporting any other device events. For compatibility with content written to mouse-specific events, this specification does provide an optional section describing how to generate compatibility mouse events based on pointer input from devices other than a mouse.

This specification does not provide any advice on the expected behavior of user agents that support both Touch Events (as defined in [[TOUCH-EVENTS]]) and Pointer Events. For more information on the relationship between these two specifications, see the Touch Events Community Group.

Examples

The following are basic examples that demonstrate how some of the APIs in this specification might be used by authors. Further, more specific examples are provided in the relevant sections of this document.

/* Bind to either Pointer Events or traditional touch/mouse */

if (window.PointerEvent) {
    // if Pointer Events are supported, only listen to pointer events
    target.addEventListener("pointerdown", function(e) {
        // if necessary, apply separate logic based on e.pointerType
        // for different touch/pen/mouse behavior
        ...
    });
    ...
} else {
    // traditional touch/mouse event handlers
    target.addEventListener('touchstart', function(e) {
        // prevent compatibility mouse events and click
        e.preventDefault();
        ...
    });
    ...
    target.addEventListener('mousedown', ...);
    ...
}

// additional event listeners for keyboard handling
...
window.addEventListener("pointerdown", detectInputType);

function detectInputType(event) {
    switch(event.pointerType) {
        case "mouse":
            /* mouse input detected */
            break;
        case "pen":
            /* pen/stylus input detected */
            break;
        case "touch":
            /* touch input detected */
            break;
        default:
            /* pointerType is empty (could not be detected)
            or UA-specific custom type */
    }
}
<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>
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);
    <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;
        // Check if a unique Id exists.
        if (uniqueId == 0) {
            return;
        }
        // Check if a color has been assigned to the device.
        if (map.has(uniqueId)) {
            return;
        }
        // Assign a color to the device.
        let newColor = getNewColor();
        map.set(uniqueId, newColor);
        return newColor;
    }

    function getNewColor() {
        /* return some color value */
    }
    </script>

Mouse Events

The mouse event module originates from the [[HTML401]] onclick, ondblclick, onmousedown, onmouseup, onmouseover, onmousemove, and onmouseout attributes. This event module is specifically designed for use with pointing input devices, such as a mouse or a trackball.

Interface MouseEvent

Introduced in DOM Level 2, modified in this specification.

The {{MouseEvent}} interface provides specific contextual information associated with Mouse events.

In the case of nested elements, mouse events are always targeted at the most deeply nested element.

Ancestors of the targeted element can use event bubbling to obtain notifications of mouse events which occur within their descendent elements.

To create an instance of the {{MouseEvent}} interface, use the {{MouseEvent}} constructor, passing an optional {{MouseEventInit}} dictionary.

When initializing {{MouseEvent}} objects using initMouseEvent, implementations can use the client coordinates {{MouseEvent/clientX}} and {{MouseEvent/clientY}} for calculation of other coordinates (such as target coordinates exposed by DOM Level 0 implementations or other proprietary attributes, e.g., pageX).

MouseEvent
[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

The horizontal coordinate at which the event occurred relative to the origin of the screen coordinate system.

The [=un-initialized value=] of this attribute MUST be 0.

screenY

The vertical coordinate at which the event occurred relative to the origin of the screen coordinate system.

The [=un-initialized value=] of this attribute MUST be 0.

clientX

The horizontal coordinate at which the event occurred relative to the viewport associated with the event.

The [=un-initialized value=] of this attribute MUST be 0.

clientY

The vertical coordinate at which the event occurred relative to the viewport associated with the event.

The [=un-initialized value=] of this attribute MUST be 0.

layerX

The horizontal offset from the nearest [=tree/ancestor=] element which is a [=stacking context=], is positioned, or paints in the positioned phase when painting a stacking context.

The [=un-initialized value=] of this attribute MUST be 0.

layerY

The vertical offset from the nearest [=tree/ancestor=] element which is a [=stacking context=], is positioned, or paints in the positioned phase when painting a stacking context.

The [=un-initialized value=] of this attribute MUST be 0.

ctrlKey

Refer to the {{KeyboardEvent}}'s {{KeyboardEvent/ctrlKey}} attribute.

The [=un-initialized value=] of this attribute MUST be false.

shiftKey

Refer to the {{KeyboardEvent}}'s {{KeyboardEvent/shiftKey}} attribute.

The [=un-initialized value=] of this attribute MUST be false.

altKey

Refer to the {{KeyboardEvent}}'s {{KeyboardEvent/altKey}} attribute.

The [=un-initialized value=] of this attribute MUST be false.

metaKey

Refer to the {{KeyboardEvent}}'s {{KeyboardEvent/metaKey}} attribute.

The [=un-initialized value=] of this attribute MUST be false.

button

During mouse events caused by the depression or release of a mouse button, {{MouseEvent/button}} MUST be used to indicate which pointer device button changed state.

The value of the {{MouseEvent/button}} attribute MUST be as follows:

Some pointing devices provide or simulate more button states, and values higher than 2 or lower than 0 MAY be used to represent such buttons.

The value of {{MouseEvent/button}} is not updated for events not caused by the depression/release of a mouse button. In these scenarios, take care not to interpret the value 0 as the left button, but rather as the default value.

Some default actions related to events such as {{mousedown}} and {{mouseup}} depend on the specific mouse button in use.

The [=un-initialized value=] of this attribute MUST be 0.

buttons

During any mouse events, {{MouseEvent/buttons}} MUST be used to indicate which combination of mouse buttons are currently being pressed, expressed as a bitmask.

Though similarly named, the values for the {{MouseEvent/buttons}} attribute and the {{MouseEvent/button}} attribute are very different. The value of {{MouseEvent/button}} is assumed to be valid during {{mousedown}} / {{mouseup}} event handlers, whereas the {{MouseEvent/buttons}} attribute reflects the state of the mouse's buttons for any trusted {{MouseEvent}} object (while it is being dispatched), because it can represent the "no button currently active" state (0).

The value of the {{MouseEvent/buttons}} attribute MUST be as follows:

Some pointing devices provide or simulate more buttons. To represent such buttons, the value MUST be doubled for each successive button (in the binary series 8, 16, 32, ... ).

Because the sum of any set of button values is a unique number, a content author can use a bitwise operation to determine how many buttons are currently being pressed and which buttons they are, for an arbitrary number of mouse buttons on a device. For example, the value 3 indicates that the left and right button are currently both pressed, while the value 5 indicates that the left and middle button are currently both pressed.

Some default actions related to events such as {{mousedown}} and {{mouseup}} depend on the specific mouse button in use.

The [=un-initialized value=] of this attribute MUST be 0.

relatedTarget

Used to identify a secondary {{EventTarget}} related to a UI event, depending on the type of event.

The [=un-initialized value=] of this attribute MUST be null.

getModifierState(keyArg)

Queries the state of a modifier using a key value.

Returns true if it is a modifier key and the modifier is activated, false otherwise.

{{DOMString}} keyArg
Refer to the {{KeyboardEvent}}'s {{KeyboardEvent/getModifierState()}} method for a description of this parameter.
MouseEventInit
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;
};
            
screenX

Initializes the {{MouseEvent/screenX}} attribute of the {{MouseEvent}} object to the desired horizontal relative position of the mouse pointer on the user's screen.

Initializing the event object to the given mouse position must not move the user's mouse pointer to the initialized position.

screenY

Initializes the {{MouseEvent/screenY}} attribute of the {{MouseEvent}} object to the desired vertical relative position of the mouse pointer on the user's screen.

Initializing the event object to the given mouse position must not move the user's mouse pointer to the initialized position.

clientX

Initializes the {{MouseEvent/clientX}} attribute of the {{MouseEvent}} object to the desired horizontal position of the mouse pointer relative to the client window of the user's browser.

Initializing the event object to the given mouse position must not move the user's mouse pointer to the initialized position.

clientY

Initializes the {{MouseEvent/clientY}} attribute of the {{MouseEvent}} object to the desired vertical position of the mouse pointer relative to the client window of the user's browser.

Initializing the event object to the given mouse position must not move the user's mouse pointer to the initialized position.

button

Initializes the {{MouseEvent/button}} attribute of the {{MouseEvent}} object to a number representing the desired state of the button(s) of the mouse.

The value 0 is used to represent the primary mouse button, 1 is used to represent the auxiliary/middle mouse button, and 2 to represent the right mouse button. Numbers greater than 2 are also possible, but are not specified in this document.

buttons

Initializes the {{MouseEvent/buttons}} attribute of the {{MouseEvent}} object to a number representing one or more of the button(s) of the mouse that are to be considered active.

The {{MouseEvent/buttons}} attribute is a bit-field. If a mask value of 1 is true when applied to the value of the bit field, then the primary mouse button is down. If a mask value of 2 is true when applied to the value of the bit field, then the right mouse button is down. If a mask value of 4 is true when applied to the value of the bit field, then the auxiliary/middle button is down.

In JavaScript, to initialize the {{MouseEvent/buttons}} attribute as if the right (2) and middlebutton (4) were being pressed simultaneously, the buttons value can be assigned as either:

{ buttons: 2 | 4 }

or:

{ buttons: 6 }
relatedTarget

The {{MouseEvent/relatedTarget}} should be initialized to the element whose bounds the mouse pointer just left (in the case of a {{mouseover}} or {{mouseenter}} event) or the element whose bounds the mouse pointer is entering (in the case of a {{mouseout}} or {{mouseleave}} or [=focusout=] event). For other events, this value need not be assigned (and will default to null).

Implementations MUST maintain the current click count when generating mouse events. This MUST be a non-negative integer indicating the number of consecutive clicks of a pointing device button within a specific time. The delay after which the count resets is specific to the environment configuration.

MouseEvent Algorithms

Native OS Requirements

The algorithms in this section assume that the native platform OS will provide the following:

For these events, the OS will be able to provide the following info:

Constructing Mouse Events

This section needs to be revised.

Generally, when a constructor of an {{Event}} interface, or of an interface inherited from the {{Event}} interface, is invoked, the steps described in [[DOM]] should be followed. However the {{MouseEvent}} interfaces provide additional dictionary members for initializing the internal state of the {{Event}} object's key modifiers: specifically, the internal state queried for using the {{MouseEvent/getModifierState()}} methods. This section supplements the [[DOM]] steps for intializing a new {{MouseEvent}} object with these optional modifier states.

For the purposes of constructing a {{MouseEvent}}, or object derived from these objects using the algorithm below, all {{MouseEvent}}, and derived objects have internal key modifier state which can be set and retrieved using the key modifier names described in the Modifier Keys table in [[UIEvents-Key]].

The following steps supplement the algorithm defined for constructing events in [[DOM]]:

Global State for MouseEvent

This section needs to be revised.

User Agent-Level State

The UA must maintain the following values that are shared for the entire User Agent.

A mouse button bitmask that tracks the current state of the mouse buttons.

Window-Level State

The UA must maintain the following values that are shared for the Window.

A last mouse element value (initially undefined) that keeps track of the last {{Element}} that we sent a MouseEvent to.

A last mouse DOM path value (initially empty) that contains a snapshot of the ancestors {{Element}}s of the last mouse element when the most recent mouse event was sent.

Internal State for MouseEvent

This section needs to be revised.

A {{MouseEvent}} has the following internal flags that are used to track the state of various modifier keys: shift flag, control flag, alt flag, altgraph flag, and meta flag. These flags are set if the corresponding modifier key was pressed at the time of the mouse event.

hit test

This section needs to be revised.

  1. Let |pos| be the x,y coordinates relative to the viewport
  2. Return [[CSSOM-View]]'s {{Document/elementFromPoint()}} with |pos| (the frontmost DOM element at |pos|)

    To account for inert or disabled elements. this should call {{Document/elementsFromPoint()}} and reject invalid elements.

initialize a {{MouseEvent}}

This section needs to be revised.

To initialize a MouseEvent with |event|, |eventType| and |eventTarget|, |bubbles|, and |cancelable|, run the following steps:

  1. [=Initialize a UIEvent=] with |event|, |eventType|, |eventTarget|, |bubbles| and |cancelable|.
  2. Set |event|.{{MouseEvent/screenX}} to the x-coordinate of the position where the event occurred relative to the origin of the desktop
  3. Set |event|.{{MouseEvent/screenY}} to the y-coordinate of the position where the event occurred relative to the origin of the desktop
  4. Set |event|.{{MouseEvent/clientX}} to the x-coordinate of the position where the event occurred relative to the origin of the viewport
  5. Set |event|.{{MouseEvent/clientY}} to the y-coordinate of the position where the event occurred relative to the origin of the viewport
  6. Set mouse event modifiers with |event|
  7. Set |event|.{{MouseEvent/button}} to 0
  8. Set |event|.{{MouseEvent/buttons}} to mouse button bitmask
  9. Initialize PointerLock attributes for MouseEvent with |event|

    We should provide a hook for PointerLock instead of hardcoding it here.

set mouse event modifiers

This section needs to be revised.

  1. Let |event| be the {{MouseEvent}} to update
  2. Set |event|'s shift flag if key modifier state includes "Shift", unset it otherwise
  3. Set |event|'s control flag if key modifier state includes "Control", unset it otherwise
  4. Set |event|'s alt flag if key modifier state includes "Alt", unset it otherwise
  5. Set |event|'s altgraph flag if key modifier state includes "AltGraph", unset it otherwise
  6. Set |event|'s meta flag if key modifier state includes "Meta", unset it otherwise
  7. Set |event|.{{MouseEvent/shiftKey}} to true if the event's shift flag is set, false otherwise
  8. Set |event|.{{MouseEvent/ctrlKey}} to true if the event's control flag is set, false otherwise
  9. Set |event|.{{MouseEvent/altKey}} to true if the event's alt flag or altgraph flag is set, false otherwise
  10. Set |event|.{{MouseEvent/metaKey}} to true if the event's meta flag is set, false otherwise
create a cancelable MouseEvent

This section needs to be revised.

  1. Let |eventType| be a DOMString containing a valid {{MouseEvent}} type
  2. Let |eventTarget| be the {{EventTarget}} of the event
  3. Let |bubbles| be true
  4. Let |cancelable| be true
  5. Let |event| be the result of [=creating an event=] using {{MouseEvent}}
  6. Initialize a MouseEvent with |event|, |eventType|, |eventTarget|, |bubbles| and |cancelable|.
  7. Return |event|
create a non-cancelable MouseEvent

This section needs to be revised.

  1. Let |eventType| be a DOMString containing a valid {{MouseEvent}} type
  2. Let |eventTarget| be the {{EventTarget}} of the event
  3. Let |bubbles| be "false"
  4. Let |cancelable| be "false"
  5. Let |event| be the result of [=creating an event=] using {{MouseEvent}}
  6. Initialize a MouseEvent with |event|, |eventType|, |eventTarget|, |bubbles| and |cancelable|.
  7. Return |event|
calculate MouseEvent button attribute

This section needs to be revised.

This will return a button ID suitable for storing in the {{MouseEvent}}'s {{MouseEvent/button}} attribute.

  1. Let |mbutton| be an ID that identifies a mouse button
  2. If |mbutton| is the primary mouse button, then return 0
  3. If |mbutton| is the auxiliary (middle) mouse button, then return 1
  4. If |mbutton| is the secondary mouse button, then return 2
  5. If |mbutton| is the X1 (back) button, then return 3
  6. If |mbutton| is the X2 (forward) button, then return 4
set MouseEvent attributes from native

This section needs to be revised.

  1. Let |event| be the {{MouseEvent}} to initialize
  2. Let |native| be the native mouse event

    TODO.

  3. If |event|.{{Event/type}} is one of [ mousedown, mouseup ], then
    1. Let |mbutton| be an ID from |native| that identifies which mouse button was pressed
    2. Set |event|.{{MouseEvent/button}} to calculate MouseEvent button attribute with |mbutton|
handle native mouse down

This section needs to be revised.

  1. Let |native| be the native mousedown
  2. Let |mbutton| be an ID from |native| that identifies which mouse button was pressed
  3. Update the mouse button bitmask as follows:
    1. If |mbutton| is the primary mouse button, then set the 0x01 bit
    2. If |mbutton| is the secondary mouse button, then set the 0x02 bit
    3. If |mbutton| is the auxiliary (middle) mouse button, then set the 0x04 bit

      Other buttons can be added starting with 0x08 .

  4. Let |target| be hit test with viewport-relative coordinates from |native|
  5. Let |event| be the result of creating a cancelable MouseEvent with "mousedown", |target|
  6. Set MouseEvent attributes from native with |native|
  7. Maybe send pointerdown event with |event|
  8. Let |result| be dispatch |event| at |target|
  9. If |result| is true and |target| is a focusable area that is click focusable, then
    1. Run the focusing steps at |target|
  10. if |mbutton| is the secondary mouse button, then
    1. Maybe show context menu with |native|, |target|
handle native mouse up

This section needs to be revised.

  1. Let |native| be the native mouseup

    Other mouse events can occur between the mousedown and mouseup.

  2. Let |mbutton| be an ID from |native| that identifies which mouse button was pressed
  3. Update the mouse button bitmask as follows:
    1. If |mbutton| is the primary mouse button, then clear the 0x01 bit
    2. If |mbutton| is the secondary mouse button, then clear the 0x02 bit
    3. If |mbutton| is the auxiliary (middle) mouse button, then clear the 0x04 bit
  4. Let |target| be hit test with viewport-relative coordinates from |native|
  5. Let |event| be the result of creating a cancelable MouseEvent with "mouseup", |target|
  6. Set MouseEvent attributes from native with |native|
  7. Maybe send pointerup event with |event|
  8. dispatch |event| at |target|
handle native mouse click

This section needs to be revised.

  1. Let |native| be the native mouse click

    The platform should call this immediately after handle native mouse up for mouseups that generate clicks.

  2. Let |target| be hit test with viewport-relative coordinates from |native|
  3. Send click event with |native| and |target|.
send click event

This section needs to be revised.

  1. Let |native| be the native mousedown
  2. Let |target| be the {{EventTarget}} of the event
  3. Let |mbutton| be 1 (primary mouse button by default)
  4. If |native| is valid, then
    1. Let |mbutton| be an ID from |native| that identifies which mouse button was pressed
  5. Set |eventType| to "click" if |mbutton| is the primary mouse button, otherwise "auxclick"
  6. Let |event| be the result of creating a PointerEvent with |eventType| and |target|
  7. If |native| is valid, then
    1. Set MouseEvent attributes from native with |event|, |native|
    2. If |event|.{{MouseEvent/screenX}} is not an integer value, then round it.
    3. If |event|.{{MouseEvent/screenY}} is not an integer value, then round it.
  8. dispatch |event| at |target|

    See pointerevents/100 for info about browsers using PointerEvents and rounded coordinates.

    Any "default action" is handled during dispatch by triggering the activation behavior algorithm for the target. So there is no need for handle that here. However, need to verify that the existing spec handles disabled/css-pointer-events/inert/...

    To handle `HTMLelement.click()`, call this algorithm with |native| = null and |target| = `HTMLelement`.

    To handle keyboard-initiated clicks, call this algorithm with |native| = null and |target| = currently focused element.

handle native mouse double click

This section needs to be revised.

  1. Let |native| be the native mouse double click

    This should be called immediately after handle native mouse click for mouse clicks that generate double clicks.

  2. Let |mbutton| be an ID from |native| that identifies which mouse button was pressed
  3. If |mbutton| is not the primary mouse button, then return
  4. Let |target| be hit test with viewport-relative coordinates from |native|
  5. Let |event| be the result of creating a PointerEvent with "dblclick" and |target|
  6. Set MouseEvent attributes from native with |event|, |native|
  7. If |event|.{{MouseEvent/screenX}} is not an integer value, then round it.
  8. If |event|.{{MouseEvent/screenY}} is not an integer value, then round it.
  9. dispatch |event| at |target|
handle native mouse move

This section needs to be revised.

  1. Let |native| be the native mouse move

    This algorithm makes assumptions about the dispatch of PointerEvents because they are not currently specified explicitly. Once pointerevents/285 is resolved this may need to be updated.

  2. Let |target| be hit test with viewport-relative coordinates from |native|
  3. Let |targetDomPath| be [=tree/inclusive ancestors=] of |target|
  4. Generate events for leaving the current element:
    1. If last mouse element is defined and not equal to |target|, then
      1. Let |mouseout| be the result of creating a cancelable MouseEvent with "mouseout" and last mouse element

        TODO: Set |mouseout| attributes from |native|. +CSSOM attributes.

    2. Maybe send pointerout event with |mouseout|
    3. Dispatch |mouseout| at |target|

      Verify behavior when canceled (appears to have no effect).

    4. Let |leaveElements| be a copy of last mouse DOM path with all elements common to |targetDomPath| removed.
    5. For each |element| in |leaveElements|, do

      Handle case where |element| has been deleted. Also case where it has been moved: Should the DOM mutation have triggered a mouseleave event? Should we sent it now? Should it be dropped? Need to verify what current browsers do.

      1. Let |mouseleave| be the result of creating a non-cancelable MouseEvent with "mouseleave" and |element|
      2. Set |mouseleave|.{{Event.composed}} = false

        Check compat: Value of event.composed. Spec says false. Chrome/Linux = true. Firefox/Linux = false.

      3. Maybe send pointerleave event with |mouseleave|
      4. Let |result| be dispatch |mouseleave| at |element|
  • Generate events for entering the new element:
    1. If |target| is not last mouse element, then
      1. Let |mouseover| be the result of creating a cancelable MouseEvent with "mouseover" and |target|

        TODO: Set |mouseout| attributes from |native|. +CSSOM attributes.

      2. Maybe send pointerover event with |mouseover|
      3. Dispatch |mouseout| at |target|

        Need to verify behavior when canceled (appears to have no effect).

      4. Let |enterElements| be a copy of |targetDomPath| with all elements common to last mouse DOM path removed.
      5. For each |element| in |enterElements|, do

        Handle case where |element| has been deleted or moved.

        1. Let |mouseenter| be the result of creating a non-cancelable MouseEvent with "mouseenter" and |element|
        2. Set |mouseenter|.{{Event.composed}} = false

          Check compat: Value of event.composed. Spec says false. Chrome/Linux = true. Firefox/Linux = false.

        3. Maybe send pointerenter event with |mouseenter|

          Check compat for shadow DOM elements. Chrome/Linux fires this event at the element and the shadow root.

        4. Let |result| be dispatch |mouseenter| at |element|
      6. Set last mouse element to |target|
      7. Set last mouse DOM path to |targetDomPath|
  • Let |mousemove| be the result of creating a cancelable MouseEvent with "mousemove" and |element|
  • Set PointerLock attributes for mousemove
  • Maybe send pointermove event with |mousemove|
  • Dispatch |mousemove| at |element|
  • maybe show context menu

    This section needs to be revised.

    1. Let |native| be the native mousedown or pointer event
    2. Let |target| be the {{EventTarget}} of the event
      1. Let |menuevent| be the result of creating a PointerEvent with "contextmenu", |target|
      2. If |native| is valid, then
        1. Set MouseEvent attributes from native with |native|
      3. Let |result| be dispatch |menuevent| at |target|
      4. If |result| is true, then show the UA context menu

    To handle a context menu triggered by the keyboard, call this algorithm with |native| = null and |target| = currently focused element.

    Mouse Event Order

    Certain mouse events defined in this specification MUST occur in a set order relative to one another. The following shows the event sequence that MUST occur when a pointing device's cursor is moved over an element:

    # Event Type Element Notes
    1 {{mousemove}}
    Pointing device is moved into element A...
    2 {{mouseover}} A
    3 {{mouseenter}} A
    4 {{mousemove}} A Multiple {{mousemove}} events
    Pointing device is moved out of element A...
    5 {{mouseout}} A
    6 {{mouseleave}} A

    When a pointing device is moved into an element A, and then into a nested element B and then back out again, the following sequence of events MUST occur:

    Event Type Element Notes
    1 {{mousemove}}
    Pointing device is moved into element A...
    2 {{mouseover}} A
    3 {{mouseenter}} A
    4 {{mousemove}} A Multiple {{mousemove}} events
    Pointing device is moved into nested element B...
    5 {{mouseout}} A
    6 {{mouseover}} B
    7 {{mouseenter}} B
    8 {{mousemove}} B Multiple {{mousemove}} events
    Pointing device is moved from element B into A...
    9 {{mouseout}} B
    10 {{mouseleave}} B
    11 {{mouseover}} A
    12 {{mousemove}} A Multiple {{mousemove}} events
    Pointing device is moved out of element A...
    13 {{mouseout}} A
    14 {{mouseleave}} A

    Sometimes elements can be visually overlapped using CSS. In the following example, three elements labeled A, B, and C all have the same dimensions and absolute position on a web page. Element C is a child of B, and B is a child of A in the DOM:

    Graphical representation of three stacked elements all on top of each other. The bottom element is labeled A and the top element is C
    Graphical representation of three stacked elements all on top of each other, with the pointing device moving over the stack.

    When the pointing device is moved from outside the element stack to the element labeled C and then moved out again, the following series of events MUST occur:

    Event Type Element Notes
    1 {{mousemove}}
    Pointing device is moved into element C, the topmost element in the stack
    2 {{mouseover}} C
    3 {{mouseenter}} A
    4 {{mouseenter}} B
    5 {{mouseenter}} C
    6 {{mousemove}} C Multiple {{mousemove}} events
    Pointing device is moved out of element C...
    7 {{mouseout}} C
    8 {{mouseleave}} C
    9 {{mouseleave}} B
    10 {{mouseleave}} A

    The {{mouseover}}/{{mouseout}} events are only fired once, while {{mouseenter}}/{{mouseleave}} events are fired three times (once to each element).

    The following is the typical sequence of events when a button associated with a pointing device (e.g., a mouse button or trackpad) is pressed and released over an element:

    Event Type Notes
    1 {{mousedown}}
    2 {{mousemove}} OPTIONAL, multiple events, some limits
    3 {{mouseup}}
    4 {{click}}
    5 {{mousemove}} OPTIONAL, multiple events, some limits
    6 {{mousedown}}
    7 {{mousemove}} OPTIONAL, multiple events, some limits
    8 {{mouseup}}
    9 {{click}}
    10 {{dblclick}}

    The lag time, degree, distance, and number of {{mousemove}} events allowed between the {{mousedown}} and {{mouseup}} events while still firing a {{click}} or {{dblclick}} event will be implementation-, device-, and platform-specific. This tolerance can aid users that have physical disabilities like unsteady hands when these users interact with a pointing device.

    Each implementation will determine the appropriate hysteresis tolerance, but in general SHOULD fire {{click}} and {{dblclick}} events when the event target of the associated {{mousedown}} and {{mouseup}} events is the same element with no {{mouseout}} or {{mouseleave}} events intervening, and SHOULD fire {{click}} and {{dblclick}} events on the nearest common inclusive ancestor when the associated {{mousedown}} and {{mouseup}} event targets are different.

    If a {{mousedown}} event was targeted at an HTML document's body element, and the corresponding {{mouseup}} event was targeted at the document element, then the {{click}} event will be dispatched to the document element, since it is the nearest common inclusive ancestor.

    If the [=Event/target=] (e.g. the target element) is removed from the DOM during the mouse events sequence, the remaining events of the sequence MUST NOT be fired on that element.

    If the target element is removed from the DOM as the result of a {{mousedown}} event, no events for that element will be dispatched for {{mouseup}}, {{click}}, or {{dblclick}}, nor any default activation events. However, the {{mouseup}} event will still be dispatched on the element that is exposed to the mouse after the removal of the initial target element. Similarly, if the target element is removed from the DOM during the dispatch of a {{mouseup}} event, the {{click}} and subsequent events will not be dispatched.

    Mouse Event Types

    The Mouse event types are listed below. In the case of nested elements, mouse event types are always targeted at the most deeply nested element. Ancestors of the targeted element MAY use bubbling to obtain notification of mouse events which occur within its descendent elements.
    auxclick
    Type auxclick
    Interface {{PointerEvent}}
    Sync / Async Sync
    Bubbles Yes
    Trusted Targets Element
    Cancelable Yes
    Composed Yes
    Default action Varies
    Context
    (trusted events)
    • {{Event.target}} : [=topmost event target=]
    • {{UIEvent.view}} : {{Window}}
    • {{UIEvent.detail}} : indicates the [=current click count=]; the attribute value MUST be 1 when the user begins this action and increments by 1 for each click.
    • {{MouseEvent.screenX}} : value based on the pointer position on the screen
    • {{MouseEvent.screenY}} : value based on the pointer position on the screen
    • {{MouseEvent.clientX}} : value based on the pointer position within the viewport
    • {{MouseEvent.clientY}} : value based on the pointer position within the viewport
    • {{MouseEvent.layerX}} : value based on the pointer position within the containing element
    • {{MouseEvent.layerY}} : value based on the pointer position within the containing element
    • {{MouseEvent.altKey}} : true if Alt modifier was active, otherwise false
    • {{MouseEvent.ctrlKey}} : true if Control modifier was active, otherwise false
    • {{MouseEvent.shiftKey}} : true if Shift modifier was active, otherwise false
    • {{MouseEvent.metaKey}} : true if Meta modifier was active, otherwise false
    • {{MouseEvent.button}} : value based on current button pressed
    • {{MouseEvent.buttons}} : value based on all buttons currently depressed, 0 if no buttons pressed
    • {{MouseEvent.relatedTarget}} : null
    • For {{PointerEvent}} specific attributes, see the [[PointerEvents]] spec.

    The {{auxclick}} event type MUST be dispatched on the topmost event target indicated by the pointer, when the user presses down and releases the non-primary pointer button, or otherwise activates the pointer in a manner that simulates such an action. The actuation method of the mouse button depends upon the pointer device and the environment configuration, e.g., it MAY depend on the screen location or the delay between the press and release of the pointing device button.

    The {{auxclick}} event should only be fired for the non-primary pointer buttons (i.e., when {{MouseEvent/button}} value is not 0, {{MouseEvent/buttons}} value is greater than 1). The primary button (like the left button on a standard mouse) MUST NOT fire {{auxclick}} events. See {{click}} for a corresponding event that is associated with the primary button.

    The {{auxclick}} event MAY be preceded by the {{mousedown}} and {{mouseup}} events on the same element, disregarding changes between other node types (e.g., text nodes). Depending upon the environment configuration, the {{auxclick}} event MAY be dispatched if one or more of the event types {{mouseover}}, {{mousemove}}, and {{mouseout}} occur between the press and release of the pointing device button.

    The default action of the {{auxclick}} event type varies based on the [=Event/target=] of the event and the value of the {{MouseEvent/button}} or {{MouseEvent/buttons}} attributes. Typical default actions of the {{auxclick}} event type are as follows:

    myLink.addEventListener("auxclick", function(e) {
      if (e.button === 1) {
        // This would prevent the default behavior which is for example
        // opening a new tab when middle clicking on a link.
        e.preventDefault();
        // Do something else to handle middle button click like taking
        // care of opening link or non-link buttons in new tabs in a way
        // that fits the app. Other actions like closing a tab in a tab-strip
        // which should be done on the click action can be done here too.
      }
    });
    

    In the case of right button, the {{auxclick}} event is dispatched after any {{contextmenu}} event. Note that some user agents swallow all input events while a context menu is being displayed, so auxclick may not be available to applications in such scenarios. See for more clarification.

    myDiv.addEventListener("contextmenu", function(e) {
      // This call makes sure no context menu is shown
      // to interfere with page receiving the events.
      e.preventDefault();
    });
    myDiv.addEventListener("auxclick", function(e) {
      if (e.button === 2) {
        // Do something else to handle right button click like opening a
        // customized context menu inside the app.
      }
    });
    
    click
    Type click
    Interface {{PointerEvent}}
    Sync / Async Sync
    Bubbles Yes
    Trusted Targets Element
    Cancelable Yes
    Composed Yes
    Default action Varies
    Context
    (trusted events)
    • {{Event.target}} : [=topmost event target=]
    • {{UIEvent.view}} : {{Window}}
    • {{UIEvent.detail}} : indicates the [=current click count=]; the attribute value MUST be 1 when the user begins this action and increments by 1 for each click.
    • {{MouseEvent.screenX}} : value based on the pointer position on the screen
    • {{MouseEvent.screenY}} : value based on the pointer position on the screen
    • {{MouseEvent.clientX}} : value based on the pointer position within the viewport
    • {{MouseEvent.clientY}} : value based on the pointer position within the viewport
    • {{MouseEvent.layerX}} : value based on the pointer position within the containing element
    • {{MouseEvent.layerY}} : value based on the pointer position within the containing element
    • {{MouseEvent.altKey}} : true if Alt modifier was active, otherwise false
    • {{MouseEvent.ctrlKey}} : true if Control modifier was active, otherwise false
    • {{MouseEvent.shiftKey}} : true if Shift modifier was active, otherwise false
    • {{MouseEvent.metaKey}} : true if Meta modifier was active, otherwise false
    • {{MouseEvent.button}} : value based on current button pressed
    • {{MouseEvent.buttons}} : value based on all buttons currently depressed, 0 if no buttons pressed
    • {{MouseEvent.relatedTarget}} : null
    • For {{PointerEvent}} specific attributes, see the [PointerEvents] spec.

    The {{click}} event type MUST be dispatched on the topmost event target indicated by the pointer, when the user presses down and releases the primary pointer button, or otherwise activates the pointer in a manner that simulates such an action. The actuation method of the mouse button depends upon the pointer device and the environment configuration, e.g., it MAY depend on the screen location or the delay between the press and release of the pointing device button.

    The {{click}} event should only be fired for the primary pointer button (i.e., when {{MouseEvent/button}} value is 0, {{MouseEvent/buttons}} value is 1). Secondary buttons (like the middle or right button on a standard mouse) MUST NOT fire {{click}} events. See {{auxclick}} for a corresponding event that is associated with the non-primary buttons.

    The {{click}} event MAY be preceded by the {{mousedown}} and {{mouseup}} events on the same element, disregarding changes between other node types (e.g., text nodes). Depending upon the environment configuration, the {{click}} event MAY be dispatched if one or more of the event types {{mouseover}}, {{mousemove}}, and {{mouseout}} occur between the press and release of the pointing device button. The {{click}} event MAY also be followed by the {{dblclick}} event.

    If a user mouses down on a text node child of a <p> element which has been styled with a large line-height, shifts the mouse slightly such that it is no longer over an area containing text but is still within the containing block of that <p> element (i.e., the pointer is between lines of the same text block, but not over the text node per se), then subsequently mouses up, this will likely still trigger a {{click}} event (if it falls within the normal temporal hysteresis for a {{click}}), since the user has stayed within the scope of the same element. Note that user-agent-generated mouse events are not dispatched on text nodes.

    In addition to being associated with pointer devices, the {{click}} event type MUST be dispatched as part of an element activation.

    For maximum accessibility, content authors are encouraged to use the {{click}} event type when defining activation behavior for custom controls, rather than other pointing-device event types such as {{mousedown}} or {{mouseup}}, which are more device-specific. Though the {{click}} event type has its origins in pointer devices (e.g., a mouse), subsequent implementation enhancements have extended it beyond that association, and it can be considered a device-independent event type for element activation.

    The default action of the {{click}} event type varies based on the [=Event/target=] of the event and the value of the {{MouseEvent/button}} or {{MouseEvent/buttons}} attributes. Typical default actions of the {{click}} event type are as follows:

    contextmenu
    Type contextmenu
    Interface {{PointerEvent}}
    Sync / Async Sync
    Bubbles Yes
    Trusted Targets Element
    Cancelable Yes
    Composed Yes
    Default action Invoke a context menu if supported.
    Context
    (trusted events)
    • {{Event}}.{{Event/target}} : topmost event target
    • {{UIEvent}}.{{UIEvent/view}} : {{Window}}
    • {{UIEvent}}.{{UIEvent/detail}} : 0
    • {{MouseEvent}}.{{MouseEvent/screenX}} : value based on the pointer position on the screen
    • {{MouseEvent}}.{{MouseEvent/screenY}} : value based on the pointer position on the screen
    • {{MouseEvent}}.{{MouseEvent/clientX}} : value based on the pointer position within the viewport
    • {{MouseEvent}}.{{MouseEvent/clientY}} : value based on the pointer position within the viewport
    • {{MouseEvent}}.{{MouseEvent/layerX}} : value based on the pointer position within the containing element
    • {{MouseEvent}}.{{MouseEvent/layerY}} : value based on the pointer position within the containing element
    • {{MouseEvent}}.{{MouseEvent/altKey}} : true if Alt modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/ctrlKey}} : true if Control modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/shiftKey}} : true if Shiftmodifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/metaKey}} : true if Meta modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/button}} : value based on current button pressed
    • {{MouseEvent}}.{{MouseEvent/buttons}} : value based on all buttons currently depressed, 0 if no buttons pressed
    • {{MouseEvent}}.{{MouseEvent/relatedTarget}} : null

    A user agent MUST dispatch this event before invoking a context menu.

    When the {{contextmenu}} event is triggered by right mouse button, the {{contextmenu}} event MUST be dispatched after the {{mousedown}} event.

    Depending on the platform, the {{contextmenu}} event may be dispatched before or after the {{mouseup}} event.

    dblclick
    Type dblclick
    Interface {{MouseEvent}}
    Sync / AsyncSync
    BubblesYes
    Trusted TargetsElement
    CancelableYes
    ComposedYes
    Default actionNone
    Context
    (trusted events)
    • {{UIEvent}}.{{UIEvent/view}} : {{Window}}
    • {{UIEvent}}.{{UIEvent/detail}} : indicates the current click count
    • {{MouseEvent}}.{{MouseEvent/screenX}} : value based on the pointer position on the screen
    • {{MouseEvent}}.{{MouseEvent/screenY}} : value based on the pointer position on the screen
    • {{MouseEvent}}.{{MouseEvent/clientX}} : value based on the pointer position within the viewport
    • {{MouseEvent}}.{{MouseEvent/clientY}} : value based on the pointer position within the viewport
    • {{MouseEvent}}.{{MouseEvent/layerX}} : value based on the pointer position within the containing element
    • {{MouseEvent}}.{{MouseEvent/layerY}} : value based on the pointer position within the containing element
    • {{MouseEvent}}.{{MouseEvent/altKey}} : true if Alt modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/ctrlKey}} : true if Control modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/shiftKey}} : true if Shift modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/metaKey}} : true if Meta modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/button}} : value based on current button pressed
    • {{MouseEvent}}.{{MouseEvent/buttons}} : value based on all buttons currently depressed, 0 if no buttons pressed
    • {{MouseEvent}}.{{MouseEvent/relatedTarget}} : null

    A user agent MUST dispatch this event when the primary button of a pointing device is clicked twice over an element. The definition of a double click depends on the environment configuration, except that the event target MUST be the same between {{mousedown}}, {{mouseup}}, and {{dblclick}}. This event type MUST be dispatched after the event type {{click}} if a click and double click occur simultaneously, and after the event type {{mouseup}} otherwise.

    As with the {{click}} event, the {{dblclick}} event should only be fired for the primary pointer button. Secondary buttons MUST NOT fire {{dblclick}} events.

    Canceling the {{click}} event does not affect the firing of a {{dblclick}} event.

    As with the {{click}} event type, the default action of the {{dblclick}} event type varies based on the [=Event/target=] of the event and the value of the {{MouseEvent/button}} or {{MouseEvent/buttons}} attributes. The typical default actions of the {{dblclick}} event type match those of the {{click}} event type.
    mousedown
    Type mousedown
    Interface{{MouseEvent}}
    Sync / AsyncSync
    BubblesYes
    Trusted TargetsElement
    CancelableYes
    ComposedYes
    Default actionVaries: Start a drag/drop operation; start a text selection; start a scroll/pan interaction (in combination with the middle mouse button, if supported)
    Context
    (trusted events)
    • {{Event}}.{{Event/target}} : topmost event target
    • {{UIEvent}}.{{UIEvent/view}} : {{Window}}
    • {{UIEvent}}.{{UIEvent/detail}} : indicates the current click count incremented by one. For example, if no click happened before the {{mousedown}}, {{UIEvent/detail}} will contain the value 1
    • {{MouseEvent}}.{{MouseEvent/screenX}} : value based on the pointer position on the screen
    • {{MouseEvent}}.{{MouseEvent/screenY}} : value based on the pointer position on the screen
    • {{MouseEvent}}.{{MouseEvent/clientX}} : value based on the pointer position within the viewport
    • {{MouseEvent}}.{{MouseEvent/clientY}} : value based on the pointer position within the viewport
    • {{MouseEvent}}.{{MouseEvent/layerX}} : value based on the pointer position within the containing element
    • {{MouseEvent}}.{{MouseEvent/layerY}} : value based on the pointer position within the containing element
    • {{MouseEvent}}.{{MouseEvent/altKey}} : true if Alt modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/ctrlKey}} : true if Control modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/shiftKey}} : true if Shift modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/metaKey}} : true if Meta modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/button}} : value based on current button pressed
    • {{MouseEvent}}.{{MouseEvent/buttons}} : value based on all buttons currently depressed, 0 if no buttons pressed
    • {{MouseEvent}}.{{MouseEvent/relatedTarget}} : null
    A user agent MUST dispatch this event when a pointing device button is pressed over an element.

    Many implementations use the {{mousedown}} event to begin a variety of contextually dependent default actions. These default actions can be prevented if this event is canceled. Some of these default actions could include: beginning a drag/drop interaction with an image or link, starting text selection, etc. Additionally, some implementations provide a mouse-driven panning feature that is activated when the middle mouse button is pressed at the time the {{mousedown}} event is dispatched.

    mouseenter
    Type mouseenter
    Interface{{MouseEvent}}
    Sync / AsyncSync
    BubblesNo
    Trusted TargetsElement
    CancelableNo
    ComposedNo
    Default actionNone
    Context
    (trusted events)
    • {{Event}}.{{Event/target}} : topmost event target
    • {{UIEvent}}.{{UIEvent/view}} : {{Window}}
    • {{UIEvent}}.{{UIEvent/detail}} : 0
    • {{MouseEvent}}.{{MouseEvent/screenX}} : value based on the pointer position on the screen
    • {{MouseEvent}}.{{MouseEvent/screenY}} : value based on the pointer position on the screen
    • {{MouseEvent}}.{{MouseEvent/clientX}} : value based on the pointer position within the viewport
    • {{MouseEvent}}.{{MouseEvent/clientY}} : value based on the pointer position within the viewport
    • {{MouseEvent}}.{{MouseEvent/layerX}} : value based on the pointer position within the containing element
    • {{MouseEvent}}.{{MouseEvent/layerY}} : value based on the pointer position within the containing element
    • {{MouseEvent}}.{{MouseEvent/altKey}} : true if Alt modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/ctrlKey}} : true if Control modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/shiftKey}} : true if Shift modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/metaKey}} : true if Meta modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/button}} : 0
    • {{MouseEvent}}.{{MouseEvent/buttons}} : value based on all buttons currently depressed, 0 if no buttons pressed
    • {{MouseEvent}}.{{MouseEvent/relatedTarget}} : indicates the [=Event/target=] | a pointing device is exiting, if any.
    A user agent MUST dispatch this event when a pointing device is moved onto the boundaries of an element or one of its descendent elements. A user agent MUST also dispatch this event when the element or one of its descendants moves to be underneath the primary pointing device. This event type is similar to {{mouseover}}, but differs in that it does not bubble, and MUST NOT be dispatched when the pointer device moves from an element onto the boundaries of one of its descendent elements.

    There are similarities between this event type and the CSS :hover pseudo-class [[CSS2]]. See also the {{mouseleave}} event type.

    mouseleave
    Type mouseleave
    Interface{{MouseEvent}}
    Sync / AsyncSync
    BubblesNo
    Trusted TargetsElement
    CancelableNo
    ComposedNo
    Default actionNone
    Context
    (trusted events)
    • {{Event}}.{{Event/target}} : topmost event target
    • {{UIEvent}}.{{UIEvent/view}} : {{Window}}
    • {{UIEvent}}.{{UIEvent/detail}} : 0
    • {{MouseEvent}}.{{MouseEvent/screenX}} : value based on the pointer position on the screen
    • {{MouseEvent}}.{{MouseEvent/screenY}} : value based on the pointer position on the screen
    • {{MouseEvent}}.{{MouseEvent/clientX}} : value based on the pointer position within the viewport
    • {{MouseEvent}}.{{MouseEvent/clientY}} : value based on the pointer position within the viewport
    • {{MouseEvent}}.{{MouseEvent/layerX}} : value based on the pointer position within the containing element
    • {{MouseEvent}}.{{MouseEvent/layerY}} : value based on the pointer position within the containing element
    • {{MouseEvent}}.{{MouseEvent/altKey}} : true if Alt modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/ctrlKey}} : true if Control modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/shiftKey}} : true if Shift modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/metaKey}} : true if Meta modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/button}} : 0
    • {{MouseEvent}}.{{MouseEvent/buttons}} : value based on all buttons currently depressed, 0 if no buttons pressed
    • {{MouseEvent}}.{{MouseEvent/relatedTarget}} : indicates the [=Event/target=] | a pointing device is exiting, if any.
    A user agent MUST dispatch this event when a pointing device is moved off of the boundaries of an element and all of its descendent elements. A user agent MUST also dispatch this event when the element or one of its descendants moves to be no longer underneath the primary pointing device. This event type is similar to {{mouseout}}, but differs in that does not bubble, and that it MUST NOT be dispatched until the pointing device has left the boundaries of the element and the boundaries of all of its children.

    There are similarities between this event type and the CSS :hover pseudo-class [[CSS2]]. See also the {{mouseenter}} event type.

    mousemove
    Type mousemove
    Interface{{MouseEvent}}
    Sync / AsyncSync
    BubblesYes
    Trusted TargetsElement
    CancelableYes
    ComposedYes
    Default actionNone
    Context
    (trusted events)
    • {{Event}}.{{Event/target}} : topmost event target
    • {{UIEvent}}.{{UIEvent/view}} : {{Window}}
    • {{UIEvent}}.{{UIEvent/detail}} : 0
    • {{MouseEvent}}.{{MouseEvent/screenX}} : value based on the pointer position on the screen
    • {{MouseEvent}}.{{MouseEvent/screenY}} : value based on the pointer position on the screen
    • {{MouseEvent}}.{{MouseEvent/clientX}} : value based on the pointer position within the viewport
    • {{MouseEvent}}.{{MouseEvent/clientY}} : value based on the pointer position within the viewport
    • {{MouseEvent}}.{{MouseEvent/layerX}} : value based on the pointer position within the containing element
    • {{MouseEvent}}.{{MouseEvent/layerY}} : value based on the pointer position within the containing element
    • {{MouseEvent}}.{{MouseEvent/altKey}} : true if Alt modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/ctrlKey}} : true if Control modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/shiftKey}} : true if Shift modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/metaKey}} : true if Meta modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/button}} : 0
    • {{MouseEvent}}.{{MouseEvent/buttons}} : value based on all buttons currently depressed, 0 if no buttons pressed
    • {{MouseEvent}}.{{MouseEvent/relatedTarget}} : null
    A user agent MUST dispatch this event when a pointing device is moved while it is over an element. The frequency rate of events while the pointing device is moved is implementation-, device-, and platform-specific, but multiple consecutive {{mousemove}} events SHOULD be fired for sustained pointer-device movement, rather than a single event for each instance of mouse movement. Implementations are encouraged to determine the optimal frequency rate to balance responsiveness with performance.

    In some implementation environments, such as a browser, {{mousemove}} events can continue to fire if the user began a drag operation (e.g., a mouse button is pressed) and the pointing device has left the boundary of the user agent.

    This event was formerly specified to be non-cancelable in DOM Level 2 Events, but was changed to reflect existing interoperability between user agents.

    mouseout
    Type mouseout
    Interface{{MouseEvent}}
    Sync / AsyncSync
    BubblesYes
    Trusted TargetsElement
    CancelableYes
    ComposedYes
    Default actionNone
    Context
    (trusted events)
    • {{Event}}.{{Event/target}} : topmost event target
    • {{UIEvent}}.{{UIEvent/view}} : {{Window}}
    • {{UIEvent}}.{{UIEvent/detail}} : 0
    • {{MouseEvent}}.{{MouseEvent/screenX}} : value based on the pointer position on the screen
    • {{MouseEvent}}.{{MouseEvent/screenY}} : value based on the pointer position on the screen
    • {{MouseEvent}}.{{MouseEvent/clientX}} : value based on the pointer position within the viewport
    • {{MouseEvent}}.{{MouseEvent/clientY}} : value based on the pointer position within the viewport
    • {{MouseEvent}}.{{MouseEvent/layerX}} : value based on the pointer position within the containing element
    • {{MouseEvent}}.{{MouseEvent/layerY}} : value based on the pointer position within the containing element
    • {{MouseEvent}}.{{MouseEvent/altKey}} : true if Alt modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/ctrlKey}} : true if Control modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/shiftKey}} : true if Shift modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/metaKey}} : true if Meta modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/button}} : 0
    • {{MouseEvent}}.{{MouseEvent/buttons}} : value based on all buttons currently depressed, 0 if no buttons pressed
    • {{MouseEvent}}.{{MouseEvent/relatedTarget}} : indicates the [=Event/target=] | a pointing device is entering, if any.
    A user agent MUST dispatch this event when a pointing device is moved off of the boundaries of an element or when the element is moved to be no longer underneath the primary pointing device. This event type is similar to {{mouseleave}}, but differs in that does bubble, and that it MUST be dispatched when the pointer device moves from an element onto the boundaries of one of its descendent elements.

    See also the {{mouseover}} event type.

    mouseover
    Type mouseover
    Interface{{MouseEvent}}
    Sync / AsyncSync
    BubblesYes
    Trusted TargetsElement
    CancelableYes
    ComposedYes
    Default actionNone
    Context
    (trusted events)
    • {{Event}}.{{Event/target}} : topmost event target
    • {{UIEvent}}.{{UIEvent/view}} : {{Window}}
    • {{UIEvent}}.{{UIEvent/detail}} : 0
    • {{MouseEvent}}.{{MouseEvent/screenX}} : value based on the pointer position on the screen
    • {{MouseEvent}}.{{MouseEvent/screenY}} : value based on the pointer position on the screen
    • {{MouseEvent}}.{{MouseEvent/clientX}} : value based on the pointer position within the viewport
    • {{MouseEvent}}.{{MouseEvent/clientY}} : value based on the pointer position within the viewport
    • {{MouseEvent}}.{{MouseEvent/layerX}} : value based on the pointer position within the containing element
    • {{MouseEvent}}.{{MouseEvent/layerY}} : value based on the pointer position within the containing element
    • {{MouseEvent}}.{{MouseEvent/altKey}} : true if Alt modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/ctrlKey}} : true if Control modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/shiftKey}} : true if Shift modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/metaKey}} : true if Meta modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/button}} : 0
    • {{MouseEvent}}.{{MouseEvent/buttons}} : value based on all buttons currently depressed, 0 if no buttons pressed
    • {{MouseEvent}}.{{MouseEvent/relatedTarget}} : indicates the [=Event/target=] | a pointing device is entering, if any.
    A user agent MUST dispatch this event when a pointing device is moved onto the boundaries of an element or when the element is moved to be underneath the primary pointing device. This event type is similar to {{mouseenter}}, but differs in that it bubbles, and that it MUST be dispatched when the pointer device moves onto the boundaries of an element whose ancestor element is the [=Event/target=] for the same event listener instance.

    See also the {{mouseout}} event type.

    mouseup
    Type mouseup
    Interface{{MouseEvent}}
    Sync / AsyncSync
    BubblesYes
    Trusted TargetsElement
    CancelableYes
    ComposedYes
    Default actionNone
    Context
    (trusted events)
    • {{Event}}.{{Event/target}} : topmost event target
    • {{UIEvent}}.{{UIEvent/view}} : {{Window}}
    • {{UIEvent}}.{{UIEvent/detail}} : indicates the current click count incremented by one.
    • {{MouseEvent}}.{{MouseEvent/screenX}} : value based on the pointer position on the screen
    • {{MouseEvent}}.{{MouseEvent/screenY}} : value based on the pointer position on the screen
    • {{MouseEvent}}.{{MouseEvent/clientX}} : value based on the pointer position within the viewport
    • {{MouseEvent}}.{{MouseEvent/clientY}} : value based on the pointer position within the viewport
    • {{MouseEvent}}.{{MouseEvent/layerX}} : value based on the pointer position within the containing element
    • {{MouseEvent}}.{{MouseEvent/layerY}} : value based on the pointer position within the containing element
    • {{MouseEvent}}.{{MouseEvent/altKey}} : true if Alt modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/ctrlKey}} : true if Control modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/shiftKey}} : true if Shift modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/metaKey}} : true if Meta modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/button}} : value based on current button pressed
    • {{MouseEvent}}.{{MouseEvent/buttons}} : value based on all buttons currently depressed, 0 if no buttons pressed
    • {{MouseEvent}}.{{MouseEvent/relatedTarget}} : null
    A user agent MUST dispatch this event when a pointing device button is released over an element.

    In some implementation environments, such as a browser, a {{mouseup}} event can be dispatched even if the pointing device has left the boundary of the user agent, e.g., if the user began a drag operation with a mouse button pressed.

    Pointer Events and interfaces

    PointerEvent interface

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

    A unique identifier for the pointer causing the event. user agents MAY reserve a generic {{pointerId}} value of 0 or 1 for the primary mouse pointer. The {{pointerId}} value of -1 MUST be reserved and used to indicate events that were generated by something other than a pointing device. For any other pointers, user agents are free to implement different strategies and approaches in how they assign a {{pointerId}} value. However, all active pointers in the [=top-level browsing context=] (as defined by [[HTML]]) must be unique, and the identifier MUST NOT be influenced by any other top-level browsing context (i.e. one top-level browsing context cannot assume that the {{pointerId}} of a pointer will be the same when the pointer moves outside of the browsing context and into another top-level browsing context).

    The user agent MAY recycle previously retired values for {{pointerId}} from previous active pointers, or it MAY always reuse the same {{pointerId}} for a particular pointing device (for instance, to uniquely identify particular pen/stylus inputs from a specific user in a multi-user collaborative application). However, in the latter case, to minimize the chance of fingerprinting and tracking across different pages or domains, the {{pointerId}} MUST only be associated explicitly with that particular pointing device for the lifetime of the page / session, and a new randomized {{pointerId}} MUST be chosen the next time that particular pointing device is used again in a new session.

    The {{pointerId}} selection algorithm is implementation specific. Authors cannot assume values convey any particular meaning other than an identifier for the pointer that is unique from all other active pointers. As an example, user agents may simply assign a number, starting from 0, to any active pointers, in the order that they become active — but these values are not guaranteed to be monotonically increasing. As the reuse of the same {{pointerId}} for a particular pointing device is left up to individual implementations, authors are strongly discouraged from relying on it, and to refer to {{persistentDeviceId}} instead.

    width

    The width (magnitude on the X axis), in CSS pixels (see [[CSS21]]), of the contact geometry of the pointer. This value MAY be updated on each event for a given pointer. For inputs that typically lack contact geometry (such as a traditional mouse), and in cases where the actual geometry of the input is not detected by the hardware, the user agent MUST return a default value of 1.

    height

    The height (magnitude on the Y axis), in CSS pixels (see [[CSS21]]), of the contact geometry of the pointer. This value MAY be updated on each event for a given pointer. For inputs that typically lack contact geometry (such as a traditional mouse), and in cases where the actual geometry of the input is not detected by the hardware, the user agent MUST return a default value of 1.

    pressure

    The normalized pressure of the pointer input in the range of [0,1], where 0 and 1 represent the minimum and maximum pressure the hardware is capable of detecting, respectively. For hardware and platforms that do not support pressure, the value MUST be 0.5 when in the active buttons state and 0 otherwise.

    tangentialPressure

    The normalized tangential pressure (also known as barrel pressure), typically set by an additional control (e.g. a finger wheel on an airbrush stylus), of the pointer input in the range of [-1,1], where 0 is the neutral position of the control. Note that some hardware may only support positive values in the range of [0,1]. For hardware and platforms that do not support tangential pressure, the value MUST be 0.

    Despite the property's name, in practice the hardware controls/sensors that generate the values for this property may not necessarily be pressure sensitive. As an example, in most cases the finger wheel on most airbrush/painting stylus implementations can be freely set, rather than requiring the user to apply a constant pressure on the wheel to prevent it from returning to the zero position.
    tiltX

    The plane angle (in degrees, in the range of [-90,90]) between the Y-Z plane and the plane containing both the transducer (e.g. pen/stylus) axis and the Y axis. A positive tiltX is to the right, in the direction of increasing X values. tiltX can be used along with tiltY to represent the tilt away from the normal of a transducer with the digitizer. For hardware and platforms that do not report tilt or angle, the value MUST be 0.

    tiltX explanation diagram
    Positive tiltX.
    tiltY

    The plane angle (in degrees, in the range of [-90,90]) between the X-Z plane and the plane containing both the transducer (e.g. pen/stylus) axis and the X axis. A positive tiltY is towards the user, in the direction of increasing Y values. tiltY can be used along with tiltX to represent the tilt away from the normal of a transducer with the digitizer. For hardware and platforms that do not report tilt or angle, the value MUST be 0.

    tiltY explanation diagram
    Positive tiltY.
    twist

    The clockwise rotation (in degrees, in the range of [0,359]) of a transducer (e.g. pen/stylus) around its own major axis. For hardware and platforms that do not report twist, the value MUST be 0.

    altitudeAngle

    The altitude (in radians) of the transducer (e.g. pen/stylus), in the range [0,π/2] — where 0 is parallel to the surface (X-Y plane), and π/2 is perpendicular to the surface. For hardware and platforms that do not report tilt or angle, the value MUST be π/2.

    The default value defined here for altitudeAngle is π/2, which positions the transducer as being perpendicular to the surface. This differs from the Touch Events - Level 2 specification's definition for the altitudeAngle property, which has a default value of 0.
    altitudeAngle explanation diagram
    Example altitudeAngle of π/4 (45 degrees from the X-Y plane).
    azimuthAngle

    The azimuth angle (in radians) of the transducer (e.g. pen/stylus), in the range [0, 2π] — where 0 represents a transducer whose cap is pointing in the direction of increasing X values (point to "3 o'clock" if looking straight down) on the X-Y plane, and the values progressively increase when going clockwise (π/2 at "6 o'clock", π at "9 o'clock", 3π/2 at "12 o'clock"). When the transducer is perfectly perpendicular to the surface (altitudeAngle of π/2), the value MUST be 0. For hardware and platforms that do not report tilt or angle, the value MUST be 0.

    azimuthAngle explanation diagram
    Example azimuthAngle of π/6 ("4 o'clock").
    pointerType

    Indicates the device type that caused the event (such as mouse, pen, touch). If the user agent is to fire a pointer event for a mouse, pen/stylus, or touch input device, then the value of pointerType MUST be according to the following table:

    Pointer Device TypepointerType Value
    Mousemouse
    Pen / styluspen
    Touch contacttouch

    If the device type cannot be detected by the user agent, then the value MUST be an empty string. If the user agent supports pointer device types other than those listed above, the value of pointerType SHOULD be vendor prefixed to avoid conflicting names for different types of devices. Future specifications MAY provide additional normative values for other device types.

    See Example 2 for a basic demonstration of how the pointerType can be used. Also note that developers should include some form of default handling to cover user agents that may have implemented their own custom pointerType values and for situations where pointerType is simply an empty string.
    isPrimary

    Indicates if the pointer represents the primary pointer of this pointer type.

    persistentDeviceId

    A unique identifier for the pointing device. If the hardware supports multiple pointers, pointer events generated from pointing devices MUST only get a persistentDeviceId if those pointers are uniquely identifiable over the session. If the pointer is uniquely identifiable, the assigned persistentDeviceId to that pointing device will remain constant for the remainder of the session. The persistentDeviceId value of 0 MUST be reserved and used to indicate events whose generating device could not be identified. Like pointerId, to minimize the chance of fingerprinting and tracking across different pages or domains, the persistentDeviceId MUST only be associated explicitly with that particular pointing device for the lifetime of the page / session, and a new randomized persistentDeviceId MUST be chosen the next time that particular pointing device is used again in a new session.

    Due to digitizer and pointing device hardware constraints, a persistentDeviceId is not guaranteed to be available for all pointer events from a pointing device. For example, the device may not report its hardware id to the digitizer in time for pointerdown to have a persistentDeviceId. In such a case, the persistentDeviceId may initially be 0 and change to a valid value.
    getCoalescedEvents()

    A method that returns the list of coalesced events.

    getPredictedEvents()

    A method that returns the list of predicted events.

    The PointerEventInit dictionary is used by the {{PointerEvent}} interface's constructor to provide a mechanism by which to construct untrusted (synthetic) pointer events. It inherits from the {{MouseEventInit}} dictionary defined in [[UIEVENTS]]. See the examples for sample code demonstrating how to fire an untrusted pointer event.

    The [=event constructing steps=] for PointerEvent clones {{PointerEventInit}}'s {{PointerEventInit/coalescedEvents}} to coalesced events list and clones {{PointerEventInit}}'s {{PointerEventInit/predictedEvents}} to predicted events list.

    The PointerEvent interface inherits from {{MouseEvent}}, defined in [[[UIEVENTS]]]. Also note the proposed extension in [[[CSSOM-VIEW]]], which changes the various coordinate properties from long to double to allow for fractional coordinates. For user agents that already implement this proposed extension for {{PointerEvent}}, but not for regular {{MouseEvent}}, there are additional requirements when it comes to the click, auxclick, and contextmenu events.

    Button states

    Chorded button interactions

    Some pointer devices, such as mouse or pen, support multiple buttons. In the [[UIEVENTS]] Mouse Event model, each button press produces a mousedown and mouseup event. To better abstract this hardware difference and simplify cross-device input authoring, Pointer Events do not fire overlapping {{pointerdown}} and {{pointerup}} events for chorded button presses (depressing an additional button while another button on the pointer device is already depressed).

    Instead, chorded button presses can be detected by inspecting changes to the button and buttons properties. The button and buttons properties are inherited from the {{MouseEvent}} interface, but with a change in semantics and values, as outlined in the following sections.

    The modifications to the button and buttons properties apply only to pointer events. However for click, auxclick and contextmenu the value of button and buttons MUST follow [[UIEVENTS]], as is the case for compatibility mouse events .

    The button property

    To identify button state transitions in any pointer event (and not just {{pointerdown}} and {{pointerup}}), the button property indicates the device button whose state change fired the event.

    Device Button Changesbutton
    Neither buttons nor touch/pen contact changed since last event-1
    Left Mouse,
    Touch contact,
    Pen contact
    0
    Middle Mouse1
    Right Mouse,
    Pen barrel button
    2
    X1 (back) Mouse3
    X2 (forward) Mouse4
    Pen eraser button5
    During a mouse drag, the value of the button property in a {{pointermove}} event will be different from that in a mousemove event. For example, while moving the mouse with the right button pressed, the {{pointermove}} events will have the button value -1, but the mousemove events will have the button value 2.

    The buttons property

    The buttons property gives the current state of the device buttons as a bitmask (same as in MouseEvent, but with an expanded set of possible values).

    Current state of device buttonsbuttons
    Mouse moved with no buttons pressed,
    Pen moved while hovering with no buttons pressed
    0
    Left Mouse,
    Touch contact,
    Pen contact
    1
    Middle Mouse4
    Right Mouse,
    Pen barrel button
    2
    X1 (back) Mouse8
    X2 (forward) Mouse16
    Pen eraser button32

    The primary pointer

    In a multi-pointer (e.g. multi-touch) scenario, the isPrimary property is used to identify a master pointer amongst the set of active pointers for each pointer type.

    • At any given time, there can only ever be at most one primary pointer for each pointer type.
    • The first pointer to become active for a particular pointer type (e.g. the first finger to touch the screen in a multi-touch interaction) becomes the primary pointer for that pointer type.
    • Only a primary pointer will produce compatibility mouse events. In the case where there are multiple primary pointers, these pointers will all produce compatibility mouse events.
    Authors who desire single-pointer interaction can achieve this by ignoring non-primary pointers (however, see the note below on multiple primary pointers).
    When two or more pointer device types are being used concurrently, multiple pointers (one for each pointerType) are considered primary. For example, a touch contact and a mouse cursor moved simultaneously will produce pointers that are both considered primary.
    Some devices, operating systems and user agents may ignore the concurrent use of more than one type of pointer input to avoid accidental interactions. For instance, devices that support both touch and pen interactions may ignore touch inputs while the pen is actively being used, to allow users to rest their hand on the touchscreen while using the pen (a feature commonly referred to as "palm rejection"). Currently, it is not possible for authors to suppress this behavior.
    In some cases, it is possible for the user agent to fire pointer events in which no pointer is marked as a primary pointer. For instance, when there are multiple active pointers of a particular type, like a multi-touch interaction, and the primary pointer is removed (e.g. it leaves the screen), there may end up being no primary pointers. Also on platforms where the primary pointer is determined using all active pointers of the same type on the device (including those targeted at an application other than the user agent), if the first (primary) pointer is outside of the user agent and other (non-primary) pointers targeted inside the user agent, then the user agent MAY fire pointer events for the other pointers with a value of false for isPrimary.
    Current operating systems and user agents don't usually have a concept of multiple mouse inputs. When more than one mouse device is present (for instance, on a laptop with both a trackpad and an external mouse), all mouse devices are generally treated as a single device — movements on any of the devices are translated to movement of a single mouse pointer, and there is no distinction between button presses on different mouse devices. For this reason, there will usually only be a single mouse pointer, and that pointer will be primary.

    Firing events using the PointerEvent interface

    To fire a pointer event named |e| means to [=fire an event=] named |e| using PointerEvent whose attributes are set as defined in {{PointerEvent}} Interface and Attributes and Default Actions.

    If the event is not a {{gotpointercapture}}, {{lostpointercapture}}, click, auxclick or contextmenu event, run the process pending pointer capture steps for this PointerEvent.

    Determine the target at which the event is fired as follows:

    Let |targetDocument| be target's [=Node/node document=] [[DOM]].

    If the event is {{pointerdown}}, {{pointermove}}, or {{pointerup}}, set active document for the event's {{PointerEvent/pointerId}} to |targetDocument|.

    If the event is {{pointerdown}}, the associated device is a direct manipulation device, and the target is an {{Element}}, then set pointer capture for this {{PointerEvent/pointerId}} to the target element as described in implicit pointer capture.

    Before firing this event, the user agent SHOULD treat the target as if the pointing device has moved over it from the |previousTarget| for the purpose of ensuring event ordering [[UIEVENTS]]. If the |needsOverEvent| flag is set, a {{pointerover}} event is needed even if the target element is the same.

    Fire the event to the determined target.

    Save the determined target as the |previousTarget| for the given pointer, and reset the |needsOverEvent| flag to false. If the |previousTarget| at any point will no longer be [=connected=] [[DOM]], update the |previousTarget| to the nearest still [=connected=] [[DOM]] parent following the event path corresponding to dispatching events to the |previousTarget|, and set the |needsOverEvent| flag to true.

    Using the pointer capture target override as the target instead of the normal hit-test result may fire some boundary events, as defined by [[UIEVENTS]]. This is the same as the pointer leaving its previous target and entering this new capturing target. When the capture is released, the same scenario may happen, as the pointer is leaving the capturing target and entering the hit-test target.

    Attributes and default actions

    The bubbles and cancelable properties and the default actions for the event types defined in this specification appear in the following table. Details of each of these event types are provided in Pointer Event types.

    Event TypeBubblesCancelableDefault Action
    {{pointerover}} Yes Yes None
    {{pointerenter}} No No None
    {{pointerdown}} Yes Yes Varies: when the pointer is primary, all default actions of the mousedown event
    Canceling this event also prevents subsequent firing of compatibility mouse events.
    {{pointermove}} Yes Yes Varies: when the pointer is primary, all default actions of mousemove
    {{pointerrawupdate}} Yes No None
    {{pointerup}} Yes Yes Varies: when the pointer is primary, all default actions of mouseup
    {{pointercancel}} Yes No None
    {{pointerout}} Yes Yes None
    {{pointerleave}} No No None
    {{gotpointercapture}} Yes No None
    {{lostpointercapture}} Yes No None

    Viewport manipulations (panning and zooming) — generally, as a result of a direct manipulation interaction — are intentionally NOT a default action of pointer events, meaning that these behaviors (e.g. panning a page as a result of moving a finger on a touchscreen) cannot be suppressed by canceling a pointer event. Authors must instead use touch-action to explicitly declare the direct manipulation behavior for a region of the document. Removing this dependency on the cancelation of events facilitates performance optimizations by the user agent.

    For {{pointerenter}} and {{pointerleave}} events, the {{EventInit/composed}} [[DOM]] attribute SHOULD be false; for all other pointer events in the table above, the attribute SHOULD be true.

    For all pointer events in the table above, the {{UIEvent/detail}} [[UIEVENTS]] attribute SHOULD be 0.

    Many user agents expose non-standard attributes fromElement and toElement in MouseEvents to support legacy content. We encourage those user agents to set the values of those (inherited) attributes in PointerEvents to null to transition authors to the use of standardized alternates (target and relatedTarget).

    Similar to MouseEvent {{MouseEventInit/relatedTarget}}, the relatedTarget should be initialized to the element whose bounds the pointer just left (in the case of a {{pointerover}} or pointerenter event) or the element whose bounds the pointer is entering (in the case of a {{pointerout}} or {{pointerleave}}). For other pointer events, this value will default to null. Note that when an element receives the pointer capture all the following events for that pointer are considered to be inside the boundary of the capturing element.

    For {{gotpointercapture}} and {{lostpointercapture}} events, all the attributes except the ones defined in the table above should be the same as the Pointer Event that caused the user agent to run the process pending pointer capture steps and fire the {{gotpointercapture}} and {{lostpointercapture}} events.

    Process pending pointer capture

    The user agent MUST run the following steps when implicitly releasing pointer capture as well as when firing Pointer Events that are not {{gotpointercapture}} or {{lostpointercapture}}.

    1. If the pointer capture target override for this pointer is set and is not equal to the pending pointer capture target override, then fire a pointer event named {{lostpointercapture}} at the pointer capture target override node.
    2. If the pending pointer capture target override for this pointer is set and is not equal to the pointer capture target override, then fire a pointer event named {{gotpointercapture}} at the pending pointer capture target override.
    3. Set the pointer capture target override to the pending pointer capture target override, if set. Otherwise, clear the pointer capture target override.

    As defined in the section for click, auxclick, and contextmenu events, even after the {{lostpointercapture}} event has been dispatched, the corresponding click, auxclick or contextmenu event, if any, would still be dispatched to the capturing target.

    Suppressing a pointer event stream

    The user agent MUST suppress a pointer event stream when it detects that the web page is unlikely to continue to receive pointer events with a specific {{PointerEvent/pointerId}}. Any of the following scenarios satisfy this condition (there MAY be additional scenarios):

    • The user agent has opened a modal dialog or menu.
    • A pointer input device is physically disconnected, or a hoverable pointer input device (e.g. a hoverable pen/stylus) has left the hover range detectable by the digitizer.
    • The pointer is subsequently used by the user agent to manipulate the page viewport (e.g. panning or zooming). See the section on touch-action CSS property for details.
      User agents can trigger panning or zooming through multiple pointer types (such as touch and pen), and therefore the start of a pan or zoom action may result in the suppression of various pointers, including pointers with different pointer types.
    • As part of the drag operation initiation algorithm as defined in the drag and drop processing model [[HTML]], for the pointer that caused the drag operation.

    Other scenarios in which the user agent MAY suppress a pointer event stream include:

    • A device's screen orientation is changed while a pointer is active.
    • The user attempts to interact using more simultaneous pointer inputs than the device supports.
    • The user agent interprets the input as accidental (for example, the hardware supports palm rejection).

    Methods for detecting any of these scenarios are out of scope for this specification.

    The user agent MUST run the following steps to suppress a pointer event stream:

    Boundary events caused by layout changes

    A pointing device that moved relative to the screen surface or underwent some change in any of its properties fires various events as defined in Pointer Event types. For a stationary pointing device (that neither moved relative to the screen surface nor underwent any change in any properties), the user agent MUST fire certain boundary events after a layout change that affected the hit test target for the pointer, see {{pointerover}}, {{pointerenter}}, {{pointerout}} and {{pointerleave}} for details. The user agent MAY delay the firing of these boundary events because of performance reasons (e.g. to avoid too many hit-tests or layout changes caused by boundary event listeners).

    A stationary pointing device (that neither moved relative to the screen surface nor underwent any change in any properties) never fires a {{pointermove}} event.

    Converting between tiltX / tiltY and altitudeAngle / azimuthAngle

    Pointer Events include two complementary sets of attributes to express the orientation of a transducer relative to the X-Y plane: tiltX / tiltY (introduced in the original Pointer Events specification), and azimuthAngle / altitudeAngle (adopted from the Touch Events - Level 2 specification).

    Depending on the specific hardware and platform, user agents will likely only receive one set of values for the transducer orientation relative to the screen plane — either tiltX / tiltY or altitudeAngle / azimuthAngle. User agents MUST use the following algorithm for converting these values.

    When the user agent calculates tiltX / tiltY from azimuthAngle / altitudeAngle it SHOULD round the final integer values using Math.round [[ECMASCRIPT]] rules.

    /* Converting between tiltX/tiltY and altitudeAngle/azimuthAngle */
    
    function spherical2tilt(altitudeAngle, azimuthAngle) {
      const radToDeg = 180/Math.PI;
    
      let tiltXrad = 0;
      let tiltYrad = 0;
    
      if (altitudeAngle == 0) {
        // the pen is in the X-Y plane
        if (azimuthAngle == 0 || azimuthAngle == 2*Math.PI) {
          // pen is on positive X axis
          tiltXrad = Math.PI/2;
        }
        if (azimuthAngle == Math.PI/2) {
          // pen is on positive Y axis
          tiltYrad = Math.PI/2;
        }
        if (azimuthAngle == Math.PI) {
          // pen is on negative X axis
          tiltXrad = -Math.PI/2;
        }
        if (azimuthAngle == 3*Math.PI/2) {
          // pen is on negative Y axis
          tiltYrad = -Math.PI/2;
        }
        if (azimuthAngle>0 && azimuthAngle<Math.PI/2) {
          tiltXrad = Math.PI/2;
          tiltYrad = Math.PI/2;
        }
        if (azimuthAngle>Math.PI/2 && azimuthAngle<Math.PI) {
          tiltXrad = -Math.PI/2;
          tiltYrad = Math.PI/2;
        }
        if (azimuthAngle>Math.PI && azimuthAngle<3*Math.PI/2) {
          tiltXrad = -Math.PI/2;
          tiltYrad = -Math.PI/2;
        }
        if (azimuthAngle>3*Math.PI/2 && azimuthAngle<2*Math.PI) {
          tiltXrad = Math.PI/2;
          tiltYrad = -Math.PI/2;
        }
      }
    
      if (altitudeAngle != 0) {
        const tanAlt = Math.tan(altitudeAngle);
    
        tiltXrad = Math.atan(Math.cos(azimuthAngle) / tanAlt);
        tiltYrad = Math.atan(Math.sin(azimuthAngle) / tanAlt);
      }
    
      return {"tiltX":tiltXrad*radToDeg, "tiltY":tiltYrad*radToDeg};
    }
    
    function tilt2spherical(tiltX, tiltY) {
      const tiltXrad = tiltX * Math.PI/180;
      const tiltYrad = tiltY * Math.PI/180;
    
      // calculate azimuth angle
      let azimuthAngle = 0;
    
      if (tiltX == 0) {
        if (tiltY > 0) {
          azimuthAngle = Math.PI/2;
        }
        else if (tiltY < 0) {
          azimuthAngle = 3*Math.PI/2;
        }
      } else if (tiltY == 0) {
        if (tiltX < 0) {
          azimuthAngle = Math.PI;
        }
      } else if (Math.abs(tiltX) == 90 || Math.abs(tiltY) == 90) {
        // not enough information to calculate azimuth
        azimuthAngle = 0;
      } else {
        // Non-boundary case: neither tiltX nor tiltY is equal to 0 or +-90
        const tanX = Math.tan(tiltXrad);
        const tanY = Math.tan(tiltYrad);
    
        azimuthAngle = Math.atan2(tanY, tanX);
        if (azimuthAngle < 0) {
          azimuthAngle += 2*Math.PI;
        }
      }
    
      // calculate altitude angle
      let altitudeAngle = 0;
    
      if (Math.abs(tiltX) == 90 || Math.abs(tiltY) == 90) {
          altitudeAngle = 0
      } else if (tiltX == 0) {
        altitudeAngle = Math.PI/2 - Math.abs(tiltYrad);
      } else if (tiltY == 0) {
        altitudeAngle = Math.PI/2 - Math.abs(tiltXrad);
      } else {
        // Non-boundary case: neither tiltX nor tiltY is equal to 0 or +-90
        altitudeAngle =  Math.atan(1.0/Math.sqrt(Math.pow(Math.tan(tiltXrad),2) + Math.pow(Math.tan(tiltYrad),2)));
      }
    
      return {"altitudeAngle":altitudeAngle, "azimuthAngle":azimuthAngle};
    }
    

    PointerEvent Algorithms

    initialize a {{PointerEvent}}

    To initialize a PointerEvent with |event|, |eventType| and |eventTarget|, |bubbles|, and |cancelable|, run the following steps:

    1. [=Initialize a MouseEvent=] with |event|, |eventType| and |eventTarget|, |bubbles| and |cancelable|
    2. Initialize all other attributes to default {{PointerEvent}} values.

    create a {{PointerEvent}}

    To create a {{PointerEvent}} with |eventType| and |eventTarget|, |bubbles|, and |cancelable|, run the following steps:

    1. Let |event| be the result of [=creating an event=] using {{PointerEvent}}
    2. [=Initialize a PointerEvent=] with |event|, |eventType| and |eventTarget|, |bubbles| and |cancelable|
    3. Return |event|

    create {{PointerEvent}} from {{MouseEvent}}

    1. Let |eventType| be a {{DOMString}} containing the event type
    2. Let |mouseevent| be the corresponding {{MouseEvent}}
    3. Let |event| be the result of [=creating an event=] using {{PointerEvent}}
    4. Let |target| be the |mouseevent|.{{Event/target}}
    5. [=Initialize a PointerEvent=] with |event|, |eventType| and |target|
    6. Copy {{MouseEvent}} attributes from |mouseevent| into |event|
    7. Return |event|

    maybe send pointerout event

    1. Let |mouseout| be the corresponding mouseout {{MouseEvent}}
    2. Let |pointerout| be the result of [=creating PointerEvent from MouseEvent=] with "pointerout" and |mouseout|
    3. Set pointerevent attributes

      TODO.

    4. Let |target| be the |mouseout|.{{Event/target}}
    5. [=dispatch=] |pointerout| at |target|

    maybe send pointerleave event

    1. Let |mouseout| be the corresponding mouseout {{MouseEvent}}
    2. Let |pointerout| be the result of [=creating PointerEvent from MouseEvent=] with "pointerout" and |mouseout|
    3. Set pointerevent attributes

      TODO.

    4. Let |target| be the |mouseout|.{{Event/target}}
    5. [=dispatch=] |pointerout| at |target|

    maybe send pointerover event

    1. Let |mouseout| be the corresponding mouseout {{MouseEvent}}
    2. Let |pointerout| be the result of [=creating PointerEvent from MouseEvent=] with "pointerout" and |mouseout|
    3. Set pointerevent attributes

      TODO.

    4. Let |target| be the |mouseout|.{{Event/target}}
    5. [=dispatch=] |pointerout| at |target|

    maybe send pointerenter event

    1. Let |mouseout| be the corresponding mouseout {{MouseEvent}}
    2. Let |pointerout| be the result of [=creating PointerEvent from MouseEvent=] with "pointerout" and |mouseout|
    3. Set pointerevent attributes

      TODO.

    4. Let |target| be the |mouseout|.{{Event/target}}
    5. [=dispatch=] |pointerout| at |target|

    maybe send pointermove event

    1. Let |mouseout| be the corresponding mouseout {{MouseEvent}}

      Can this send pointermove and pointerrawupdate? Or do we need 2 methods?

      What is needed to properly define how pointermove events are coalesced?

    2. Let |pointerout| be the result of [=creating PointerEvent from MouseEvent=] with "pointerout" and |mouseout|
    3. Set pointerevent attributes

      TODO.

    4. Let |target| be the |mouseout|.{{Event/target}}
    5. [=dispatch=] |pointerout| at |target|

    maybe send pointerdown event

    1. Let |mouseout| be the corresponding mouseout {{MouseEvent}}

      Unlike mousedown events, {{pointerdown}} events are not nested when multiple buttons are pressed. The {{MouseEvent}} is passed so that the fields can be copied into the PointerEvent.

    2. Let |pointerout| be the result of [=creating PointerEvent from MouseEvent=] with "pointerout" and |mouseout|
    3. Set pointerevent attributes

      TODO.

    4. Let |target| be the |mouseout|.{{Event/target}}
    5. [=dispatch=] |pointerout| at |target|

    maybe send pointerrawupdate event

    1. Let |mouseout| be the corresponding mouseout {{MouseEvent}}
    2. Let |target| be the |mouseout|.{{Event/target}}
    3. [=dispatch=] |pointerout| at |target|

    maybe send pointerup event

    1. Let |mouseout| be the corresponding mouseout {{MouseEvent}}

      Unlike mouseup events, {{pointerup}} events are not nested when multiple buttons are pressed. The {{MouseEvent}} is passed so that the fields can be copied into the PointerEvent.

    2. Let |pointerout| be the result of [=creating PointerEvent from MouseEvent=] with "pointerout" and |mouseout|
    3. Set pointerevent attributes

      TODO.

    4. Let |target| be the |mouseout|.{{Event/target}}
    5. [=dispatch=] |pointerout| at |target|

    Pointer Event types

    Below are the event types defined in this specification.

    In the case of the primary pointer, these events (with the exception of {{gotpointercapture}} and {{lostpointercapture}}) may also fire compatibility mouse events.

    The pointerover event

    The user agent MUST fire a pointer event named {{pointerover}} when any of the following occurs:

    • The step to determine the target of a pointer detects that the pointer has moved into an element.
    • A layout change causes the hit test boundaries of an element to move underneath an uncaptured pointer of a stationary pointing device.
    • Before the user agent fires a {{pointerdown}} event for a device that does not support hover (see {{pointerdown}}).

    The pointerenter event

    The user agent MUST fire a pointer event named {{pointerenter}} when any of the following occurs:

    • The step to determine the target of a pointer detects that the pointer has moved into an element or one of its descendants.
    • A layout change causes the hit test boundaries of an element or one of its descendants to move underneath an uncaptured pointer of a stationary pointing device.
    • Before the user agent fires a {{pointerdown}} event for a device that does not support hover (see {{pointerdown}}).
    This event type is similar to {{pointerover}} but with two differences: {{pointerenter}} does not bubble, and its dispatch considers the hit test boundaries of even descendant elements.
    There are similarities between this event type, the mouseenter event described in [[UIEVENTS]], and the CSS :hover pseudo-class described in [[CSS21]]. See also the {{pointerleave}} event.

    The pointerdown event

    The user agent MUST fire a pointer event named {{pointerdown}} when a pointer enters the active buttons state. For mouse, this is when the device transitions from no buttons depressed to at least one button depressed. For touch, this is when physical contact is made with the digitizer. For pen, this is when the pen either makes physical contact with the digitizer without any button depressed, or transitions from no buttons depressed to at least one button depressed while hovering.

    For mouse (or other multi-button pointer devices), this means {{pointerdown}} and {{pointerup}} are not fired for all of the same circumstances as mousedown and mouseup. See chorded buttons for more information.

    For input devices that do not support hover, the user agent MUST also fire a pointer event named {{pointerover}} followed by a pointer event named {{pointerenter}} prior to dispatching the {{pointerdown}} event.

    Authors can prevent the firing of certain compatibility mouse events by canceling the {{pointerdown}} event (if the isPrimary property is true). This sets the PREVENT MOUSE EVENT flag on the pointer. Note, however, that this does not prevent the mouseover, mouseenter, mouseout, or mouseleave events from firing.

    The pointermove event

    The user agent MUST fire a pointer event named {{pointermove}} when a pointer changes any properties that don't fire {{pointerdown}} or {{pointerup}} events. This includes any changes to coordinates, pressure, tangential pressure, tilt, twist, contact geometry (width and height) or chorded buttons.

    User agents MAY delay dispatch of the {{pointermove}} event (for instance, for performance reasons). The coalesced events information will be exposed via the{{PointerEvent/getCoalescedEvents}} method for the single dispatched {{pointermove}} event. The final coordinates of such events should be used for finding the target of the event.

    The pointerrawupdate event

    The user agent MUST fire a pointer event named {{pointerrawupdate}}, and only do so within a [=secure context=], when a pointer changes any properties that don't fire pointerdown or pointerup events. See pointermove event for a list of such properties.

    In contrast with {{pointermove}}, user agents SHOULD dispatch {{pointerrawupdate}} events as soon as possible and as frequently as the JavaScript can handle the events.

    The target of {{pointerrawupdate}} events might be different from the {{pointermove}} events due to the fact that {{pointermove}} events might get delayed or coalesced, and the final position of the event which is used for finding the target could be different from its coalesced events.

    Note that if there is already another {{pointerrawupdate}} with the same {{PointerEvent/pointerId}} that hasn't been dispatched in the [=event loop=], the user agent MAY coalesce the new {{pointerrawupdate}} with that event instead of creating a new [=task=]. This may cause {{pointerrawupdate}} to have coalesced events, and they will all be delivered as coalesced events of one {{pointerrawupdate}} event as soon as the event is processed in the [=event loop=]. See{{PointerEvent/getCoalescedEvents}} for more information.

    In terms of ordering of {{pointerrawupdate}} and {{pointermove}}, if the user agent received an update from the platform that causes both {{pointerrawupdate}} and {{pointermove}} events, then the user agent MUST dispatch the {{pointerrawupdate}} event before the corresponding {{pointermove}}.

    Other than the target, the concatenation of coalesced events lists of all dispatched {{pointerrawupdate}} events since the last {{pointermove}} event is the same as the coalesced events of the next {{pointermove}} event in terms of the other event attributes. The attributes of {{pointerrawupdate}} are mostly the same as {{pointermove}}, with the exception of cancelable which MUST be false for {{pointerrawupdate}}.

    User agents SHOULD not fire compatibility mouse events for {{pointerrawupdate}}.

    Adding listeners for the {{pointerrawupdate}} event might negatively impact the performance of the web page, depending on the implementation of the user agent. For most use cases the other pointerevent types should suffice. A {{pointerrawupdate}} listener should only be added if JavaScript needs high frequency events and can handle them just as fast. In these cases, there is probably no need to listen to other types of pointer events.

    The pointerup event

    The user agent MUST fire a pointer event named {{pointerup}} when a pointer leaves the active buttons state. For mouse, this is when the device transitions from at least one button depressed to no buttons depressed. For touch, this is when physical contact is removed from the digitizer. For pen, this is when the pen is removed from the physical contact with the digitizer while no button is depressed, or transitions from at least one button depressed to no buttons depressed while hovering.

    For input devices that do not support hover, the user agent MUST also fire a pointer event named {{pointerout}} followed by a pointer event named {{pointerleave}} after dispatching the {{pointerup}} event.

    All {{pointerup}} events have a pressure value of 0.

    The user agent MUST also implicitly release the pointer capture if the pointer is currently captured.

    For mouse (or other multi-button pointer devices), this means {{pointerdown}} and {{pointerup}} are not fired for all of the same circumstances as mousedown and mouseup. See chorded buttons for more information.

    The pointercancel event

    The user agent MUST fire a pointer event named {{pointercancel}} when it detects a scenario to suppress a pointer event stream.

    The values of the following properties of the {{pointercancel}} event MUST match the values of the last dispatched pointer event with the same {{PointerEvent/pointerId}}: width, height, pressure, tangentialPressure, tiltX, tiltY, twist, altitudeAngle, azimuthAngle, pointerType, isPrimary, and the coordinates inherited from [[UIEVENTS]]. The coalescedEvents and predictedEvents lists in the {{pointercancel}} event MUST be empty, and the event's {{Event/cancelable}} attribute MUST be false.

    The pointerout event

    The user agent MUST fire a pointer event named {{pointerout}} when any of the following occurs:

    The pointerleave event

    The user agent MUST fire a pointer event named {{pointerleave}} when any of the following occurs:

    • The step to determine the target of a pointer detects that the pointer has moved out of an element and all of its descendants.
    • A layout change causes the hit test boundaries of an element and all of its descendants to move away from underneath an uncaptured pointer of a stationary pointing device.
    • After the user agent fires the {{pointerup}} event for a device that does not support hover (see {{pointerup}}).
    • The user agent has detected a scenario to suppress a pointer event stream.
    This event type is similar to {{pointerout}} but with two differences: {{pointerleave}} does not bubble, and its dispatch considers the hit test boundaries of even descendant elements.
    There are similarities between this event type, the mouseleave event described in [[UIEVENTS]], and the CSS :hover pseudo-class described in [[CSS21]]. See also the {{pointerenter}} event.

    The gotpointercapture event

    The user agent MUST fire a pointer event named {{gotpointercapture}} when an element receives pointer capture. This event is fired at the element that is receiving pointer capture. Subsequent events for that pointer will be fired at this element. See the setting pointer capture and process pending pointer capture sections.

    The lostpointercapture event

    The user agent MUST fire a pointer event named {{lostpointercapture}} after pointer capture is released for a pointer. This event MUST be fired prior to any subsequent events for the pointer after capture was released. This event is fired at the element from which pointer capture was removed. All subsequent events for the pointer except click, auxclick, and contextmenu events follow normal hit testing mechanisms (out of scope for this specification) for determining the event target. See the releasing pointer capture, implicit release of pointer capture, and process pending pointer capture sections.

    The click, auxclick, and contextmenu events

    This section is an addition to click, auxclick and contextmenu events defined in [[UIEVENTS]]. These events are typically tied to user interface activation, and are fired even from non-pointer input devices, such as keyboards.

    These events MUST be of type PointerEvent, and are subject to the additional requirements mentioned in the rest of this section.

    Event attributes

    For these events, all PointerEvent specific attributes (defined in this spec) other than {{PointerEvent/pointerId}} and pointerType MUST have their default values. In addition:

    • If the events are generated by a pointing device, their {{PointerEvent/pointerId}} and pointerType MUST be the same as the PointerEvents that caused these events.
    • If the events are generated by a non-pointing device (such as voice recognition software or a keyboard interaction), {{PointerEvent/pointerId}} MUST be -1 and pointerType MUST be an empty string.

    Event coordinates

    As noted in {{PointerEvent}}, [[[CSSOM-VIEW]]] proposes to redefine the various coordinate properties (screenX, screenY, pageX, pageY, clientX, clientY, x, y, offsetX, offsetY) as double, to allow for fractional coordinates. However, this change — when applied only to {{PointerEvent}}, but not to regular {{MouseEvent}} — has proven to lead to web compatibility issues with legacy code in the case of click, auxclick, and contextmenu. For this reason, user agents that have implemented the proposed change in [[[CSSOM-VIEW]]] only for {{PointerEvent}} MUST convert the various coordinate properties for the click, auxclick, and contextmenu to long values (as defined in the original [[[UIEVENTS]]]) using Math.floor [[ECMASCRIPT]].

    Event dispatch

    A click, auxclick or contextmenu event MUST follow the dispatch process defined in the [[UIEVENTS]] spec except that the event target is overridden using the algorithm below:

    1. Let |event| be the click, auxclick or contextmenu event being dispatched, and |userEvent| be the user interaction event that caused the firing of |event|.

      Event |userEvent| could be a non-PointerEvent; for example, it is a KeyboardEvent when a click event dispatch is caused by hitting the spacebar on a checkbox element.

      When |userEvent| is a PointerEvent, |userEvent| is a {{pointerup}} for a click or auxclick event, and either a {{pointerdown}} or a {{pointerup}} event (depending on native platform convention) for a contextmenu event.

    2. If |userEvent| is not a PointerEvent, dispatch |event| following the [[UIEVENTS]] spec without overriding |event| target and skip the remaining steps below.
    3. Define |target| as follows:

      If |event| is a contextmenu event, or |userEvent| was dispatched while the corresponding pointer was captured, then let |target| be the target of |userEvent|.

      Otherwise (|event| is a click or auxclick event for which |userEvent| is a pointerup event that was dispatched uncaptured) let |target| be the nearest common inclusive ancestor of the corresponding pointerdown and pointerup targets in the DOM at the moment |event| is being dispatched.

    4. Dispatch |event| to |target| following the [[UIEVENTS]] spec.

      If |userEvent| was captured, |event| is dispatched to the capturing target of |userEvent| even though the {{lostpointercapture}} event with the same {{PointerEvent/pointerId}} has been dispatched already.

    Wheel Events

    Wheels are devices that can be rotated in one or more spatial dimensions, and which can be associated with a pointer device. The coordinate system depends on the environment configuration.

    The user's environment might be configured to associate vertical scrolling with rotation along the y-axis, horizontal scrolling with rotation along the x-axis, and zooming with rotation along the z-axis.

    The deltaX, deltaY, and deltaZ attributes of {{WheelEvent}} objects indicate a measurement along their respective axes in units of pixels, lines, or pages. The reported measurements are provided after an environment-specific algorithm translates the actual rotation/movement of the wheel device into the appropriate values and units.

    A user's environment settings can be customized to interpret actual rotation/movement of a wheel device in different ways. One movement of a common dented mouse wheel can produce a measurement of 162 pixels (162 is just an example value, actual values can depend on the current screen dimensions of the user-agent). But a user can change their default environment settings to speed-up their mouse wheel, increasing this number. Furthermore, some mouse wheel software can support acceleration (the faster the wheel is rotated/moved, the greater the delta of each measurement) or even sub-pixel rotation measurements. Because of this, authors can not assume a given rotation amount in one user agent will produce the same delta value in all user agents.

    The sign (positive or negative) of the values of the deltaX, deltaY, and deltaZ attributes MUST be consistent between multiple dispatches of the {{wheel}} event while the motion of the actual wheel device is rotating/moving in the same direction. If a user agent scrolls as the default action of the {{wheel}} event then the sign of the delta SHOULD be given by a right-hand coordinate system where positive X, Y, and Z axes are directed towards the right-most edge, bottom-most edge, and farthest depth (away from the user) of the document, respectively.

    Individual user agents can (depending on their environment and hardware configuration) interpret the same physical user interaction on the wheel differently. For example, a vertical swipe on the edge of a trackpad from top to bottom can be interpreted as a wheel action intended to either scroll the page down or to pan the page up (i.e., resulting in either a positive or negative deltaY value respectively).

    A user agent MUST create a wheel event transaction when the first wheel event is fired, so that all subsequent wheel events within a implementation-specific amount of time can be targetted at the same element. A wheel event transaction is series of wheel events that are associated with a single user gesture. The wheel event transaction MUST have an associated event target that is the topmost event target at the time the first wheel event occurs in the group.

    If a series of wheel events targetted in a scrollable element start above a child element, later events for the same user gesture may occur over the child element.

    Interface WheelEvent

    The {{WheelEvent}} interface provides specific contextual information associated with {{wheel}} events. To create an instance of the {{WheelEvent}} interface, use the {{WheelEvent}} constructor, passing an optional {{WheelEventInit}} dictionary.
    WheelEvent
    			[Exposed=Window]
    			interface WheelEvent : MouseEvent {
    				constructor(DOMString type, optional WheelEventInit eventInitDict = {});
    				// DeltaModeCode
    				const unsigned long DOM_DELTA_PIXEL = 0x00;
    				const unsigned long DOM_DELTA_LINE	= 0x01;
    				const unsigned long DOM_DELTA_PAGE	= 0x02;
    
    				readonly attribute double deltaX;
    				readonly attribute double deltaY;
    				readonly attribute double deltaZ;
    				readonly attribute unsigned long deltaMode;
    			};
    			
    DOM_DELTA_PIXEL
    The units of measurement for the delta MUST be pixels. This is the most typical case in most operating system and implementation configurations.
    DOM_DELTA_LINE
    The units of measurement for the delta MUST be individual lines of text. This is the case for many form controls.
    DOM_DELTA_PAGE
    The units of measurement for the delta MUST be pages, either defined as a single screen or as a demarcated page.
    deltaX
    In user agents where the default action of the {{wheel}} event is to scroll, the value MUST be the measurement along the x-axis (in pixels, lines, or pages) to be scrolled in the case where the event is not cancelled. Otherwise, this is an implementation-specific measurement (in pixels, lines, or pages) of the movement of a wheel device around the x-axis. The un-initialized value of this attribute MUST be 0.0.
    deltaY
    In user agents where the default action of the {{wheel}} event is to scroll, the value MUST be the measurement along the y-axis (in pixels, lines, or pages) to be scrolled in the case where the event is not cancelled. Otherwise, this is an implementation-specific measurement (in pixels, lines, or pages) of the movement of a wheel device around the y-axis. The un-initialized value of this attribute MUST be 0.0.
    deltaZ
    In user agents where the default action of the {{wheel}} event is to scroll, the value MUST be the measurement along the z-axis (in pixels, lines, or pages) to be scrolled in the case where the event is not cancelled. Otherwise, this is an implementation-specific measurement (in pixels, lines, or pages) of the movement of a wheel device around the z-axis. The un-initialized value of this attribute MUST be 0.0.
    deltaMode
    The deltaMode attribute contains an indication of the units of measurement for the delta values. The default value is {{WheelEvent/DOM_DELTA_PIXEL}} (pixels). This attribute MUST be set to one of the DOM_DELTA constants to indicate the units of measurement for the delta values. The precise measurement is specific to device, operating system, and application configurations. The un-initialized value of this attribute MUST be 0.
    WheelEventInit
    			dictionary WheelEventInit : MouseEventInit {
    				double deltaX = 0.0;
    				double deltaY = 0.0;
    				double deltaZ = 0.0;
    				unsigned long deltaMode = 0;
    			};
    			
    deltaX
    See deltaZ attribute.
    deltaY
    See deltaZ attribute.
    deltaZ
    Initializes the {{WheelEvent/deltaZ}} attribute of the {{WheelEvent}} object. Relative positive values for this attribute (as well as the {{WheelEvent/deltaX}} and {{WheelEvent/deltaY}} attributes) are given by a right-hand coordinate system where the X, Y, and Z axes are directed towards the right-most edge, bottom-most edge, and farthest depth (away from the user) of the document, respectively. Negative relative values are in the respective opposite directions.
    deltaMode
    Initializes the {{WheelEvent/deltaMode}} attribute on the {{WheelEvent}} object to the enumerated values 0, 1, or 2, which represent the amount of pixels scrolled ({{WheelEvent/DOM_DELTA_PIXEL}}), lines scrolled ({{WheelEvent/DOM_DELTA_LINE}}), or pages scrolled ({{WheelEvent/DOM_DELTA_PAGE}}) if the rotation of the wheel would have resulted in scrolling.

    Wheel Event Types

    wheel
    Type wheel
    Interface {{WheelEvent}}
    Sync / Async Async
    Bubbles Yes
    Trusted Targets Element
    Cancelable Varies
    Composed Yes
    Default action Scroll (or zoom) the document
    Context
    (trusted events)
    • {{Event}}.{{Event/target}} : element target for the current wheel event transaction
    • {{UIEvent}}.{{UIEvent/view}} : {{Window}}
    • {{UIEvent}}.{{UIEvent/detail}} : 0
    • {{MouseEvent}}.{{MouseEvent/screenX}} : if the wheel is associated with a pointing device, the value based on the pointer position on the screen, otherwise 0
    • {{MouseEvent}}.{{MouseEvent/screenY}} : if the wheel is associated with a pointing device, the value based on the pointer position on the screen, otherwise 0
    • {{MouseEvent}}.{{MouseEvent/clientX}} : if the wheel is associated with a pointing device, the value based on the pointer position within the viewport, otherwise 0
    • {{MouseEvent}}.{{MouseEvent/clientY}} : if the wheel is associated with a pointing device, the value based on the pointer position within the viewport, otherwise 0
    • {{MouseEvent}}.{{MouseEvent/altKey}} : true if Alt modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/ctrlKey}} : true if Control modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/shiftKey}} : true if Shift modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/metaKey}} : true if Meta modifier was active, otherwise false
    • {{MouseEvent}}.{{MouseEvent/button}} : if wheel is associated with a pointing device, value based on current button pressed, otherwise 0
    • {{MouseEvent}}.{{MouseEvent/buttons}} : if wheel is associated with a pointing device, value based on all buttons current depressed, 0 if no buttons pressed
    • {{MouseEvent}}.{{MouseEvent/relatedTarget}} : indicates the [=Event/target=] the pointing device is pointing at, if any
    • {{WheelEvent}}.{{WheelEvent/deltaX}} : expected amount that the page will scroll along the x-axis according to the deltaMode units; or an implementation-specific value of movement of a wheel around the x-axis
    • {{WheelEvent}}.{{WheelEvent/deltaY}} : expected amount that the page will scroll along the y-axis according to the deltaMode units; or an implementation-specific value of movement of a wheel around the y-axis
    • {{WheelEvent}}.{{WheelEvent/deltaZ}} : expected amount that the page will scroll along the z-axis according to the deltaMode units; or an implementation-specific value of movement of a wheel around the z-axis
    • {{WheelEvent}}.{{WheelEvent/deltaMode}} : unit indicator (pixels, lines, or pages) for the deltaX, deltaY, and deltaZ attributes
    A user agent MUST dispatch this event when a mouse wheel has been rotated around any axis, or when an equivalent input device (such as a mouse-ball, certain tablets or touchpads, etc.) has emulated such an action. Depending on the platform and input device, diagonal wheel deltas MAY be delivered either as a single {{wheel}} event with multiple non-zero axes or as separate {{wheel}} events for each non-zero axis. The typical default action of the {{wheel}} event type is to scroll (or in some cases, zoom) the document by the indicated amount. If this event is canceled, the implementation MUST NOT scroll or zoom the document (or perform whatever other implementation-specific default action is associated with this event type).

    In some user agents, or with some input devices, the speed that the wheel has been turned can affect the delta values, with a faster speed producing a higher delta value.

    cancelability of wheel events

    Calling preventDefault on a wheel event can prevent or otherwise interrupt scrolling. For maximum scroll performance, a user agent may not wait for each wheel event associated with the scroll to be processed to see if it will be canceled. In such cases the user agent should generate wheel events whose cancelable property is false, indicating that preventDefault cannot be used to prevent or interrupt scrolling. Otherwise cancelable will be true.

    In particular, a user agent should generate only uncancelable wheel events when it observes that there are no non-passive listeners for the event.

    Extensions to the `Element` interface

    The following section describes extensions to the existing {{Element}} interface to facilitate the setting and releasing of pointer capture.

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

    Set pointer capture for the pointer identified by the argument {{PointerEvent/pointerId}} to the element on which this method is invoked. For subsequent events of the pointer, the capturing target will substitute the normal hit testing result as if the pointer is always over the capturing target, and they MUST always be targeted at this element until capture is released. The pointer MUST be in its active buttons state for this method to be effective, otherwise it fails silently. When the provided method's argument does not match any of the active pointers, [=exception/throw=] a {{"NotFoundError"}} {{DOMException}}.

    releasePointerCapture()

    Release pointer capture for the pointer identified by the argument {{PointerEvent/pointerId}} from the element on which this method is invoked. Subsequent events for the pointer follow normal hit testing mechanisms (out of scope for this specification) for determining the event target. When the provided method's argument does not match any of the active pointers, [=exception/throw=] a {{"NotFoundError"}} {{DOMException}}.

    hasPointerCapture

    Indicates whether the element on which this method is invoked has pointer capture for the pointer identified by the argument {{PointerEvent/pointerId}}. In particular, returns true if the pending pointer capture target override for {{PointerEvent/pointerId}} is set to the element on which this method is invoked, and false otherwise.

    This method will return true immediately after a call to setPointerCapture(), even though that element will not yet have received a {{gotpointercapture}} event. As a result it can be useful for detecting implicit pointer capture from inside of a {{pointerdown}} event listener.

    Extensions to the `GlobalEventHandlers` mixin

    The following section describes extensions to the existing {{GlobalEventHandlers}} mixin to facilitate the event handler registration.

    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;
    };
    
    onpointerover
    The [=event handler IDL attribute=] for the {{pointerover}} event type.
    onpointerenter
    The [=event handler IDL attribute=] for the {{pointerenter}} event type.
    onpointerdown
    The [=event handler IDL attribute=] for the {{pointerdown}} event type.
    onpointermove
    The [=event handler IDL attribute=] for the {{pointermove}} event type.
    onpointerrawupdate
    The [=event handler IDL attribute=] for the {{pointerrawupdate}} event type.
    onpointerup
    The [=event handler IDL attribute=] for the {{pointerup}} event type.
    onpointercancel
    The [=event handler IDL attribute=] for the {{pointercancel}} event type.
    onpointerout
    The [=event handler IDL attribute=] for the {{pointerout}} event type.
    onpointerleave
    The [=event handler IDL attribute=] for the {{pointerleave}} event type.
    ongotpointercapture
    The [=event handler IDL attribute=] for the {{gotpointercapture}} event type.
    onlostpointercapture
    The [=event handler IDL attribute=] for the {{lostpointercapture}} event type.

    Extensions to the `Navigator` interface

    The {{Navigator}} interface is defined in [[HTML]]. This specification extends the Navigator interface to provide device detection support.

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

    The getter steps are:

    1. Let |emulated maxTouchPoints| be the result of WebDriver BiDi emulated max touch points [[!WEBDRIVER-BIDI]].
    2. If |emulated maxTouchPoints| is not null, return |emulated maxTouchPoints|.
    3. Return the maximum number of simultaneous touch contacts supported by the device. In the case of devices with multiple digitizers (e.g. multiple touchscreens), the value MUST be the maximum of the set of maximum supported contacts by each individual digitizer.

      For example, suppose a device has 3 touchscreens, which support 2, 5, and 10 simultaneous touch contacts, respectively. The value of maxTouchPoints should be 10.

    While a maxTouchPoints value of greater than 0 indicates the user's device is capable of supporting touch input, it does not necessarily mean the user will use touch input. Authors should be careful to also consider other input modalities that could be present on the system, such as mouse, pen, or screen readers.
    maxTouchPoints is often used to ensure that the interaction model of the content can be recognized by the current hardware. UI affordances can be provided to users with less capable hardware. On platforms where the precise number of touch points is not known, the minimum number guaranteed to be recognized is provided. Therefore, it is possible for the number of recognized touch points to exceed the value of maxTouchPoints.

    Declaring direct manipulation behavior

    As noted in Attributes and Default Actions, viewport manipulations (panning and zooming) cannot be suppressed by canceling a pointer event. Instead, authors must declaratively define which of these behaviors they want to allow, and which they want to suppress, using the touch-action CSS property.

    While the issue of pointers used to manipulate the viewport is generally limited to touch input (where a user's finger can both interact with content and pan/zoom the page), certain user agents may also allow the same types of (direct or indirect) manipulation for other pointer types. For instance, on mobile/tablet devices, users may also be able to scroll using a stylus. While, for historical reasons, the touch-action CSS property defined in this specification appears to refer only to touch inputs, it does in fact apply to all forms of pointer inputs that allow direct manipulation for panning and zooming.

    The touch-action CSS property

    Name:touch-action
    Value:auto | none | [ [ pan-x | pan-left | pan-right ] || [ pan-y | pan-up | pan-down ] ] | manipulation
    Initial:auto
    Applies to:all elements except: non-replaced inline elements, table rows, row groups, table columns, and column groups
    Inherited:no
    Percentages:N/A
    Media:visual
    Computed value:same as specified value
    Canonical order:per grammar
    Animation type:not animatable

    The touch-action CSS property determines whether direct manipulation interactions (which are not limited to touch, despite the property's name) MAY trigger the user agent's panning and zooming behavior. See the section on touch-action values.

    Right before starting to pan or zoom, the user agent MUST suppress a pointer event stream if all of the following conditions are true:

    Some user agents implement complex gestures for behaviors that involve a series of separate discrete gestures, but which are all treated as part of a single continuous gesture. For example, consider a "fling to scroll" gesture on a touchscreen: a user starts panning the document with a rapid finger movement, lifts the finger from the touchscreen, and the document continues panning with simulated inertia. While the document is still moving, the user may place their finger on the touchscreen and execute another "fling" to provide further momentum for the panning, or counteract the current panning to slow it down, stop panning altogether, or reverse the direction of the panning. As this specification does not normatively define how gestures and behaviors are implemented, it is left up to the user agent to decide whether or not the second touch (before it is interpreted as a second "fling" or counteraction of the current panning) fires pointer events or not.
    touch-action does not apply/cascade through to embedded browsing contexts. For instance, even applying touch-action to an <iframe> won't have any effect on the behavior of direct manipulation interactions for panning and zooming within the <iframe> itself.

    Determining supported direct manipulation behavior

    When a user interacts with an element using a direct manipulation pointer (such as touch or stylus on a touchscreen), the effect of that input is determined by the value of the touch-action property, and the default direct manipulation behaviors of the element and its ancestors, as follows:

    Some user agents support panning and zooming interactions involving multiple concurrent pointers (e.g. multi-touch). Methods for processing or associating the touch-action values of multiple concurrent pointers is out of scope for this specification.

    Details of touch-action values

    The touch-action property covers direct manipulation behaviors related to viewport panning and zooming. Any additional user agent behaviors, such as text selection/highlighting, or activating links and form controls, MUST NOT be affected by this CSS property.

    The terms "panning" and "scrolling" are considered synonymous (or, more aptly, "panning" is "scrolling" using a direct manipulation input). Defining an interaction or gesture for triggering panning/scrolling, or for triggering behavior for the auto or none values, are out of scope for this specification.
    auto
    The user agent MAY consider any permitted direct manipulation behaviors related to panning and zooming of the viewport that begin on the element.
    none
    Direct manipulation interactions that begin on the element MUST NOT trigger behaviors related to viewport panning and zooming.
    pan-x
    pan-left
    pan-right
    pan-y
    pan-up
    pan-down
    The user agent MAY consider direct manipulation interactions that begin on the element only for the purposes of panning that starts in any of the directions specified by all of the listed values. Once panning has started, the direction may be reversed by the user even if panning that starts in the reversed direction is disallowed. In contrast, when panning is restricted to a single axis (for instance, with pan-x or pan-y), the axis cannot be changed during panning.
    manipulation
    The user agent MAY consider direct manipulation interactions that begin on the element only for the purposes of panning and continuous zooming (such as pinch-zoom), but MUST NOT trigger other related behaviors that rely on multiple activations that must happen within a set period of time (such as double-tap to zoom, or double-tap and hold for single-finger zoom).
    Additional touch-action values common in implementations are defined in [[COMPAT]].
    The touch-action property only applies to elements that support both the CSS width and height properties (see [[CSS21]]). This restriction is designed to facilitate user agent optimizations for low-latency direct manipulation panning and zooming. For elements not supported by default, such as <span> which is a non-replaced inline element, authors can set the display CSS property to a value, such as block, that supports width and height. Future specifications could extend this API to all elements.

    The direction-specific pan values are useful for customizing some overscroll behaviors. For example, to implement a simple pull-to-refresh effect the document's touch-action can be set to pan-x pan-down whenever the scroll position is 0 and pan-x pan-y otherwise. This allows pointer event handlers to define the behavior for upward panning/scrolling that start from the top of the document.

    The direction-specific pan values can also be used for composing a component that implements custom panning with pointer event handling within an element that scrolls natively (or vice-versa). For example, an image carousel may use pan-y to ensure it receives pointer events for any horizontal pan operations without interfering with vertical panning of the document. When the carousel reaches its right-most extent, it may change its touch-action to pan-y pan-right so that a subsequent scroll operation beyond its extent can scroll the document within the viewport if possible. It's not possible to change the behavior of a panning/scrolling operation while it is taking place.

    Disabling some default direct manipulation behaviors for panning and zooming may allow user agents to respond to other behaviors more quickly. For example, with auto user agents typically add 300ms of delay before click to allow for double-tap gestures to be handled. In these cases, explicitly setting touch-action: none or touch-action: manipulation will remove this delay. Note that the methods for determining a tap or double-tap gesture are out of scope for this specification.
    <div style="touch-action: none;">
        This element receives pointer events for all direct manipulation interactions that otherwise lead to panning or zooming.
    </div>
    
    <div style="touch-action: pan-x;">
        This element receives pointer events when not panning in the horizontal direction.
    </div>
    
    <div style="overflow: auto;">
        <div style="touch-action: none;">
            This element receives pointer events for all direct manipulation interactions that otherwise lead to panning or zooming.
        </div>
        <div>
            Direct manipulation interactions on this element MAY be consumed for manipulating the parent.
        </div>
    </div>
    
    <div style="overflow: auto;">
        <div style="touch-action: pan-y;">
            <div style="touch-action: pan-x;">
                This element receives pointer events for all direct manipulation interactions because
                it allows only horizontal panning yet an intermediate ancestor
                (between it and the scrollable element) only allows vertical panning.
                Therefore, no direct manipulation behaviors for panning/zooming are
                handled by the user agent.
            </div>
        </div>
    </div>
    
    <div style="overflow: auto;">
        <div style="touch-action: pan-y pan-left;">
            <div style="touch-action: pan-x;">
                This element receives pointer events when not panning to the left.
            </div>
        </div>
    </div>
    

    Pointer capture

    Introduction

    Pointer capture allows the events for a particular pointer (including any compatibility mouse events) to be retargeted to a particular element other than the normal hit test result of the pointer's location. This is useful in scenarios like a custom slider control (e.g. similar to the [[HTML]] <input type="range"> control). Pointer capture can be set on the slider thumb element, allowing the user to slide the control back and forth even if the pointer slides off of the thumb.

    Custom Volume Slider
    Example of a custom slider control that chooses a value by sliding the thumb element back and forth. After {{pointerdown}} on the thumb, pointer capture can be used to allow the user to slide the thumb even if the pointer drifts off of it.

    Setting pointer capture

    Pointer capture is set on an |element| of type {{Element}} by calling the element.setPointerCapture(pointerId) method. When this method is invoked, the user agent MUST run the following steps:

    1. If the {{PointerEvent/pointerId}} provided as the method's argument does not match any of the active pointers, then [=exception/throw=] a {{"NotFoundError"}} {{DOMException}}.
    2. Let the |pointer| be the active pointer specified by the given {{PointerEvent/pointerId}}.
    3. If the |element| is not [=connected=] [[DOM]], [=exception/throw=] an {{"InvalidStateError"}} {{DOMException}}.
    4. If this method is invoked while the |element|'s [=Node/node document=] [[DOM]] has a locked element ([[PointerLock]] {{DocumentOrShadowRoot/pointerLockElement}}), [=exception/throw=] an {{"InvalidStateError"}} {{DOMException}}.
    5. If the |pointer| is not in the active buttons state or the |element|'s [=Node/node document=] is not the active document of the |pointer|, then terminate these steps.
    6. For the specified {{PointerEvent/pointerId}}, set the pending pointer capture target override to the {{Element}} on which this method was invoked.
    If a call to set or release a pointer capture is made while a previous set or release call is in a pending state (see process pending pointer capture), the second call overrides the first call if the second call is successful, otherwise the first call remains effective. This is true for a failed attempt to release an implicit pointer capture at a {{pointerdown}} listener.

    Releasing pointer capture

    Pointer capture is released on an element explicitly by calling the element.releasePointerCapture(pointerId) method. When this method is called, the user agent MUST run the following steps:

    1. If the {{PointerEvent/pointerId}} provided as the method's argument does not match any of the active pointers and these steps are not being invoked as a result of the implicit release of pointer capture, then [=exception/throw=] a {{"NotFoundError"}} {{DOMException}}.
    2. If {{Element/hasPointerCapture}} is false for the {{Element}} with the specified {{PointerEvent/pointerId}}, then terminate these steps.
    3. For the specified {{PointerEvent/pointerId}}, clear the pending pointer capture target override, if set.
    See the note in the section Setting pointer capture.

    Implicit pointer capture

    Inputs that implement direct manipulation interactions for panning and zooming (such as touch or stylus on a touchscreen) SHOULD behave exactly as if {{Element/setPointerCapture}} was called on the target element just before the invocation of any {{pointerdown}} listeners. The {{Element/hasPointerCapture}} API may be used (for instance, in a {{pointerdown}} listener) to determine whether this has occurred. If {{Element/releasePointerCapture}} is not called for the pointer before the next pointer event is fired, then a {{gotpointercapture}} event will be dispatched to the target (as normal) indicating that capture is active.

    This is a breaking change from [[PointerEvents]], but does not impact the vast majority of existing content. In addition to matching typical platform UX conventions, this design for implicit capture enables user agents to make a performance optimization which prevents the need to invoke hit-testing on touch movement events without explicit developer opt-in (consistent with the performance properties of existing dominant native and web APIs for touch input).
    In addition, user agents may implement implicit pointer capture behavior for all input devices on specific UI widgets such as input range controls (allowing some finger movement to stray outside of the form control itself during the interaction).

    Implicit release of pointer capture

    Immediately after firing the {{pointerup}} or {{pointercancel}} events, the user agent MUST clear the pending pointer capture target override for the {{PointerEvent/pointerId}} of the {{pointerup}} or {{pointercancel}} event that was just dispatched, and then run process pending pointer capture steps to fire {{lostpointercapture}} if necessary. After running process pending pointer capture steps, if the pointer supports hover, user agent MUST also send corresponding boundary events necessary to reflect the current position of the pointer with no capture.

    When the pointer capture target override is no longer [=connected=] [[DOM]], the pointer capture target override SHOULD be set to the document.

    When the pending pointer capture target override is no longer [=connected=] [[DOM]], the pending pointer capture target override node SHOULD be cleared.

    The previous two paragraphs result in a {{lostpointercapture}} event corresponding to the captured pointer being fired at the document during the next Process pending pointer capture after the capture node is removed.

    When a pointer lock [[PointerLock]] is successfully applied on an element, the user agent MUST run the steps as if the {{Element/releasePointerCapture}} method has been called if any element is set to be captured or pending to be captured.

    Coalesced and predicted events

    This specification does not define how user agents should coalesce or predict pointer movement data. It only specifies the API for accessing this information.

    Coalesced events

    For performance reasons, user agents may choose not to send a {{pointermove}} event every time a measurable property (such as coordinates, pressure, tangential pressure, tilt, twist, or contact geometry) of a pointer is updated. Instead, they may coalesce (combine/merge) multiple changes into a single {{pointermove}} or {{pointerrawupdate}} event. While this approach helps in reducing the amount of event handling the user agent MUST perform, it will naturally reduce the granularity and fidelity when tracking a pointer position, particularly for fast and large movements. Using the {{PointerEvent/getCoalescedEvents}} method it is possible for applications to access the raw, un-coalesced position changes. These allow for a more precise handling of pointer movement data. In the case of drawing applications, for instance, the un-coalesced events can be used to draw smoother curves that more closely match the actual movement of a pointer.

    Close-up view of a curve, showing coalesced and un-coalesced points
    Example of a curve in a drawing application — using only the coalesced coordinates from {{pointermove}} events (the grey dots), the curve is noticeably angular and jagged; the same line drawn using the more granular points provided by getCoalescedEvents() (the red circles) results in a smoother approximation of the pointer movement.

    A PointerEvent has an associated coalesced events list (a list of zero or more PointerEvents). For trusted {{pointermove}} and {{pointerrawupdate}} events, the list is a sequence of all PointerEvents that were coalesced into this event. The "parent" trusted {{pointermove}} and {{pointerrawupdate}} event represents an accumulation of these coalesced events, but may have additional processing (for example to align with the display refresh rate). As a result, the coalesced events lists for these events always contain at least one event. For all other trusted event types, it is an empty list. Untrusted events have their coalesced events list initialized to the value passed to the constructor.

    Since a trusted parent event is a summary or aggregation of the coalesced events, developers should only need to process either the parent events or all of the coalesced events, but not both.
    When a trusted event containing a coalesced events list is re-dispatched from JavaScript, the event dispatch algorithm sets the {{Event/isTrusted}} bit of the event to false but the same bits in the coalesced events list remain unchanged from their original true values.

    The events in the coalesced events list of a trusted event will have:

    <style>
        /* Disable intrinsic user agent direct manipulation behaviors (such as panning or zooming)
        so that all events on the canvas element are given to the application instead. */
    
        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); // Paint all raw/non-coalesced points
                }
            } else {
                paint(e); // Paint the final coalesced point
            }
        });
    
        function paint(event) {
            if (event.buttons>0) {
                context.fillRect(event.clientX, event.clientY, 5, 5);
            }
        }
    
    </script>
    
    The PointerEvent's attributes will be initialized in a way that best represents the events in the coalesced events list. The specific method by which user agents should do this is not covered by this specification.

    The order of all these dispatched events MUST match the actual order of the original events. For example if a {{pointerdown}} event causes the dispatch for the coalesced {{pointermove}} events the user agent MUST first dispatch one {{pointermove}} event with all those coalesced events of a {{PointerEvent/pointerId}} followed by the {{pointerdown}} event.

    Here is an example of the actual events happening with increasing {{Event/timeStamp}} values and the events dispatched by the user agent:

    Actual eventsDispatched events
    pointer ({{PointerEvent/pointerId}}=2) coordinate change{{pointerrawupdate}} ({{PointerEvent/pointerId}}=2) w/ one coalesced event
    pointer ({{PointerEvent/pointerId}}=1) coordinate change{{pointerrawupdate}} ({{PointerEvent/pointerId}}=1) w/ one coalesced event
    pointer ({{PointerEvent/pointerId}}=2) coordinate change{{pointerrawupdate}} ({{PointerEvent/pointerId}}=2) w/ one coalesced event
    pointer ({{PointerEvent/pointerId}}=2) coordinate change{{pointerrawupdate}} ({{PointerEvent/pointerId}}=2) w/ one coalesced event
    pointer ({{PointerEvent/pointerId}}=1) coordinate change{{pointerrawupdate}} ({{PointerEvent/pointerId}}=1) w/ one coalesced event
    pointer ({{PointerEvent/pointerId}}=2) coordinate change{{pointerrawupdate}} ({{PointerEvent/pointerId}}=2) w/ one coalesced event
    pointer ({{PointerEvent/pointerId}}=1) button press {{pointermove}} ({{PointerEvent/pointerId}}=1) w/ two coalesced events
    {{pointermove}} ({{PointerEvent/pointerId}}=2) w/ four coalesced events
    {{pointerdown}} ({{PointerEvent/pointerId}}=1) w/ zero coalesced events
    pointer ({{PointerEvent/pointerId}}=2) coordinate change{{pointerrawupdate}} ({{PointerEvent/pointerId}}=2) w/ one coalesced event
    pointer ({{PointerEvent/pointerId}}=2) coordinate change{{pointerrawupdate}} ({{PointerEvent/pointerId}}=2) w/ one coalesced event
    pointer ({{PointerEvent/pointerId}}=1) button release {{pointermove}} ({{PointerEvent/pointerId}}=2) w/ two coalesced events
    {{pointerup}} ({{PointerEvent/pointerId}}=1) w/ zero coalesced events

    Predicted events

    Some user agents have built-in algorithms which, after a series of confirmed pointer movements, can make a prediction (based on the preceding events for the current gesture, and the speed/trajectory of the movement) what the position of future pointer movements may be. Applications can use this information with the {{PointerEvent/getPredictedEvents}} method to speculatively "draw ahead" to a predicted position to reduce perceived latency, and then discarding these predicted points once the actual points are received.

    A line drawn using coalesced points, showing predicted future points
    Example of a line in a drawing application (the result of a drawing gesture from the bottom left to the top right), using the coalesced coordinates from {{pointermove}} events, showing the user agent's predicted future points (the grey circles).

    A PointerEvent has an associated predicted events list (a list of zero or more PointerEvents). For trusted {{pointermove}} events, it is a sequence of PointerEvents that the user agent predicts will follow the event in the future. For all other trusted event types, it is an empty list. Untrusted events have their predicted events list initialized to the value passed to the constructor.

    While pointerrawupdate events may have a non-empty coalesced events list, their predicted events list will, for performance reasons, usually be an empty list.

    When a trusted event containing a predicted events list is re-dispatched from JavaScript, the event dispatch algorithm sets the {{Event/isTrusted}} bit of the event to false but the same bits in the predicted events list remain unchanged from their original true values.

    The number of events in the list and how far they are from the current timestamp are determined by the user agent and the prediction algorithm it uses.

    The events in the predicted events list of a trusted event will have:

    Note that authors should only consider predicted events as valid predictions until the next pointer event is dispatched. It is possible, depending on how far into the future the user agent predicts events, that regular pointer events are dispatched earlier than the timestamp of one or more of the predicted events.

    
    let predicted_points = [];
    window.addEventListener("pointermove", function(event) {
        // Clear the previously drawn predicted points.
        for (let e of predicted_points.reverse()) {
            clearPoint(e.pageX, e.pageY);
        }
    
        // Draw the actual movements that happened since the last received event.
        for (let e of event.getCoalescedEvents()) {
            drawPoint(e.pageX, e.pageY);
        }
    
        // Draw the current predicted points to reduce the perception of latency.
        predicted_points = event.getPredictedEvents();
        for (let e of predicted_points) {
            drawPoint(e.pageX, e.pageY);
        }
    });
    
    

    Populating and maintaining the coalesced and predicted events lists

    When a trusted PointerEvent is created, user agents SHOULD run the following steps for each event in the coalesced events list and predicted events list:

    1. Set the event's {{PointerEvent/pointerId}}, pointerType, isPrimary and {{Event/isTrusted}} to match the respective properties of the "parent" pointer event.
    2. Set the event's {{Event/cancelable}} and {{Event/bubbles}} to false (as these events will never be dispatched in isolation).
    3. Set the event's coalesced events list and predicted events list to an empty list.
    4. Initialize all other attributes to default {{PointerEvent}} values.

    When a trusted PointerEvent's {{Event/target}} is changed, user agents SHOULD, for each event in the coalesced events list and predicted events list:

    1. Set the event's {{Event/target}} to match the {{Event/target}} of the "parent" pointer event.

    Compatibility mapping with mouse events

    The vast majority of web content existing today codes only to Mouse Events. The following describes an algorithm for how the user agent MAY map generic pointer input to mouse events for compatibility with this content.

    The compatibility mapping with mouse events is an OPTIONAL feature of this specification. User agents are encouraged to support the feature for best compatibility with existing legacy content.

    At a high level, compatibility mouse events are intended to be "interleaved" with their respective pointer events. However, this specific order is not mandatory, and user agents that implement compatibility mouse events MAY decide to delay or group the dispatch of mouse events, as long as their relative order is consistent.

    Particularly in the case of touchscreen inputs, user agents MAY apply additional heuristics for gesture recognition (unless explicitly suppressed by authors through touch-action). During a sequence of events between a {{pointerdown}} event and a {{pointerup}} event, the gesture recognition may have to wait until the {{pointerup}} event to detect or ignore a gesture. As a result the compatibility mouse events for the whole sequence may be dispatched together after the last {{pointerup}} event, if the user agent determined that an interaction was not intended as a particular gesture. These specifics of user agent gesture recognition are not defined in this specification, and they may differ between implementations.

    Regardless of their support for compatibility mouse events, the user agents MUST always support the click, auxclick and contextmenu events because these events are of type PointerEvent and are therefore not compatibility mouse events. Calling preventDefault during a pointer event MUST NOT have an effect on whether click, auxclick, or contextmenu are fired or not.

    The relative order of some of these high-level events (such as contextmenu, [=HTMLElement/focus=], [=HTMLElement/blur=]) with pointer events is undefined and varies between user agents. For example, in some user agents contextmenu will often follow a {{pointerup}}, while in others it'll often precede a {{pointerup}} or {{pointercancel}}, and in some situations it may be fired without any corresponding pointer event (for instance, as a result of a keyboard interaction).

    In addition, user agents may apply their own heuristics to determine whether or not a click, auxclick, or contextmenu event should be fired. Some user agents may choose not to fire these events if there are other (non-primary) pointers of the same type, or other primary pointers of a different type. User agents may determine that a particular action was not a "clean" tap, click, or long-press (for instance, if an interaction with a finger on a touch screen includes too much movement while the finger is in contact with the screen) and decide not to fire a click, auxclick, or contextmenu event. These aspects of user agent behavior are not defined in this specification, and they may differ between implementations.

    Unless otherwise noted, the target of any mapped mouse event SHOULD be the same target as the respective pointer event unless the target is no longer participating in its ownerDocument's tree. In this case, the mouse event should be fired at the original target's nearest ancestor node (at the time it was removed from the tree) that still participates in its ownerDocument's tree, meaning that a new event path (based on the new target node) is built for the mouse event.

    Authors can prevent the production of certain compatibility mouse events by canceling the {{pointerdown}} event.

    Mouse events can only be prevented when the pointer is down. Hovering pointers (e.g. a mouse with no buttons pressed) cannot have their mouse events prevented.

    The mouseover, mouseout, mouseenter, and mouseleave events are never prevented (even if the pointer is down).

    Compatibility mouse events can't be prevented when a pointer event {{EventListener}} is set to be {{AddEventListenerOptions/passive}} [[DOM]].

    Tracking the effective position of the legacy mouse pointer

    While only primary pointers can produce compatibility mouse events, multiple primary pointers can be active simultaneously, each producing its own compatibility mouse events. For compatibility with scripts relying on MouseEvents, the mouse transition events (mouseover, mouseout, mouseenter and mouseleave) SHOULD simulate the movement of a single legacy mouse input. This means that the entry/exit state for every event target is valid, in accordance with [[UIEVENTS]]. User agents SHOULD guarantee this by maintaining the effective position of the legacy mouse pointer in the document as follows.

    Right before firing a {{pointerdown}}, {{pointerup}} or {{pointermove}} event, or a {{pointerleave}} event at the window, the user agent SHOULD run the following steps:

    1. Let |T| be the target of the {{pointerdown}}, {{pointerup}} or {{pointermove}} event being dispatched. For the {{pointerleave}} event, unset |T|.
    2. If |T| and current effective legacy mouse pointer position are both unset or they are equal, terminate these steps.
    3. Dispatch mouseover, mouseout, mouseenter and mouseleave events as per [[UIEVENTS]] for a mouse moving from the current effective legacy mouse pointer position to |T|. Consider an unset value of either current effective legacy mouse pointer position or |T| as an out-of-window mouse position.
    4. Set effective legacy mouse pointer position to |T|.

    The effective position of the legacy mouse pointer models the fact that we cannot always have a direct mapping from pointer transition events (pointerover, pointerout, pointerenter and pointerleave) to corresponding legacy mouse transition events (mouseover, mouseout, mouseenter and mouseleave). The following animation illustrates a case where a user agent needs to dispatch more legacy mouse transition events than pointer transition events to be able to reconcile two primary pointers using a single legacy mouse input.

    Simultaneous mouse pointer (white cursor) and touch pointer (white "hand" cursor) causing the single legacy mouse input (orange cursor) to move between the two pointers.

    In this animation, note the time period between the mouse click and the touch tap. Button 1 receives no pointerout event (because the "real" mouse pointer didn't leave the button rectangle within this period), but Button 1 receives a mouseout event when the effective position of the legacy mouse pointer moves to Button 2 on touch tap. Similarly, in the time period between the touch tap and the moment before the mouse leaves Button 1, Button 1 receives no pointerover event for the same reason, but Button 1 receives a mouseover event when the effective position of the legacy mouse pointer moves back inside Button 1.

    Mapping for devices that support hover

    Whenever the user agent is to dispatch a pointer event for a device that supports hover, it SHOULD run the following steps:

    1. If the isPrimary property for the pointer event to be dispatched is false then dispatch the pointer event and terminate these steps.
    2. If the pointer event to be dispatched is a {{pointerdown}}, {{pointerup}} or {{pointermove}} event, or a {{pointerleave}} event at the window, dispatch compatibility mouse transition events as described in Tracking the effective position of the legacy mouse pointer.
    3. Dispatch the pointer event.
    4. If the pointer event dispatched was {{pointerdown}} and event's [=Event/canceled flag=] is set, then set the PREVENT MOUSE EVENT flag for this pointerType.
    5. If the PREVENT MOUSE EVENT flag is not set for this pointerType and the pointer event dispatched was:
      • {{pointerdown}}, then fire a mousedown event.
      • {{pointermove}}, then fire a mousemove event.
      • {{pointerup}}, then fire a mouseup event.
      • {{pointercancel}}, then fire a mouseup event at the window.
    6. If the pointer event dispatched was {{pointerup}} or {{pointercancel}}, clear the PREVENT MOUSE EVENT flag for this pointerType.

    Mapping for devices that do not support hover

    Some devices, such as most touchscreens, do not support hovering a coordinate (or set of coordinates) while not in the active state. Much existing content coded to mouse events assumes that a mouse is producing the events and thus certain qualities are generally true:

    Hover is sometimes used to toggle the visibility of UI elements in content designed for mouse (e.g. "hover menus"). This content is often incompatible with devices that do not support hover. This specification does not define a mapping or behavior for compatibility with this scenario. It will be considered in a future version of the specification.

    This requires that user agents provide a different mapping for these types of input devices. Whenever the user agent is to dispatch a pointer event for a device that does not support hover, it SHOULD run the following steps:

    1. If the isPrimary property for the pointer event to be dispatched is false then dispatch the pointer event and terminate these steps.
    2. If the pointer event to be dispatched is {{pointerover}} and the {{pointerdown}} event has not yet been dispatched for this pointer, then fire a mousemove event (for compatibility with legacy mouse-specific code).
    3. If the pointer event to be dispatched is a {{pointerdown}}, {{pointerup}} or {{pointermove}} event, or a {{pointerleave}} event at the window, dispatch compatibility mouse transition events as described in Tracking the effective position of the legacy mouse pointer.
    4. Dispatch the pointer event.
    5. If the pointer event dispatched was {{pointerdown}} and event's [=Event/canceled flag=] is set, then set the PREVENT MOUSE EVENT flag for this pointerType.
    6. If the PREVENT MOUSE EVENT flag is not set for this pointerType and the pointer event dispatched was:
      • {{pointerdown}}, then fire a mousedown event.
      • {{pointermove}}, then fire a mousemove event.
      • {{pointerup}}, then fire a mouseup event.
      • {{pointercancel}}, then fire a mouseup event at the window.
    7. If the pointer event dispatched was {{pointerup}} or {{pointercancel}}, clear the PREVENT MOUSE EVENT flag for this pointerType.

    If the user agent supports both Touch Events (as defined in [[TOUCH-EVENTS]]) and Pointer Events, the user agent MUST NOT generate both the compatibility mouse events as described in this section, and the fallback mouse events outlined in [[TOUCH-EVENTS]].

    The activation of an element (click) with a primary pointer that does not support hover (e.g. single finger on a touchscreen) would typically produce the following event sequence:

    1. mousemove
    2. {{pointerover}}
    3. pointerenter
    4. mouseover
    5. mouseenter
    6. {{pointerdown}}
    7. mousedown
    8. Zero or more {{pointermove}} and mousemove events, depending on movement of the pointer
    9. {{pointerup}}
    10. mouseup
    11. {{pointerout}}
    12. {{pointerleave}}
    13. mouseout
    14. mouseleave
    15. click

    If, however, the {{pointerdown}} event [=Event/canceled flag=] is set during this interaction then the sequence of events would be:

    1. mousemove
    2. {{pointerover}}
    3. pointerenter
    4. mouseover
    5. mouseenter
    6. {{pointerdown}}
    7. Zero or more {{pointermove}} events, depending on movement of the pointer
    8. {{pointerup}}
    9. {{pointerout}}
    10. {{pointerleave}}
    11. mouseout
    12. mouseleave
    13. click

    Security and privacy considerations

    This appendix discusses security and privacy considerations for Pointer Events implementations. The discussion is limited to security and privacy issues that arise directly from implementation of the event model, APIs and events defined in this specification.

    Many of the event types defined in this specification are dispatched in response to user actions. This allows malicious event listeners to gain access to information users would typically consider confidential, e.g., the exact path/movement of a user's mouse/stylus/finger while interacting with a page.

    Pointer events contain additional information (where supported by the user's device), such as the angle or tilt at which a pen input is held, the geometry of the contact surface, and the pressure exerted on the stylus or touch screen. Information about angle, tilt, geometry and pressure are directly related to sensors on the user's device, meaning that this specification allows an origin access to these sensors.

    This sensor data, as well as the ability to determine the type of input mechanism (mouse, touch, pen) used, may be used to infer characteristics of a user, or of the user's device and environment. These inferred characteristics and any device/environment information may themselves be sensitive — for instance, they may allow a malicious site to further infer if a user is using assistive technologies. This information can also be potentially used for the purposes of building a user profile and/or attempting to "fingerprint" and track a particular user.

    As mitigation, user agents may consider including the ability for users to disable access to particular sensor data (such as angle, tilt, pressure), and/or to make it available only after an explicit opt-in from the user.

    This specification defines the method by which authors can access "predicted events". The specification does not, itself, define the algorithms that user agents should use for their prediction. The specification authors envisage the algorithms to only rely on preceding pointer events related to the current gesture that a user is performing. It is the responsibility of user agents to ensure that their specific implementation of a prediction algorithm does not rely on any additional data - such as the user's full interaction history across different sites - that could reveal sensitive information about a user or be used to "fingerprint" and track them.

    Beyond these considerations, the working group believes that this specification:

    Glossary

    active buttons state
    The condition when a pointer has a non-zero value for the buttons property. For mouse, this is when the device has at least one button depressed. For touch, this is when there is physical contact with the digitizer. For pen, this is when either the pen has physical contact with the digitizer, or at least one button is depressed while hovering.
    active document
    For every active pointer, the document that received the last event from that pointer.
    active pointer
    Any touch contact, pen/stylus, mouse cursor, or other pointer that can produce events. If it is possible for a given pointer (identified by a unique {{PointerEvent/pointerId}}) to produce additional events within the document, then that pointer is still considered active. Examples:
    • A mouse connected to the device is always active.
    • A touch contact on the screen is considered active.
    • If a touch contact or pen/stylus is lifted beyond the range of the digitizer, then it is no longer considered active.
    On some platforms, the set of active pointers includes all pointer input to the device, including any that are not targeted at the user agent (e.g. those targeted at other applications).
    contact geometry
    The bounding box of an input (most commonly, touch) on a digitizer. This typically refers to devices with coarser pointer input resolution than a single pixel. Some devices do not report this data at all.
    delta
    The estimated scroll amount (in pixels, lines, or pages) that the user agent will scroll or zoom the page in response to the physical movement of an input device that supports the {{WheelEvent}} interface (such as a mouse wheel or touch pad). The value of a delta (e.g., the {{WheelEvent/deltaX}}, {{WheelEvent/deltaY}}, or {{WheelEvent/deltaZ}} attributes) is to be interpreted in the context of the current {{WheelEvent/deltaMode}} property. The relationship between the physical movement of a wheel (or other device) and whether the delta is positive or negative is environment and device dependent. However, if a user agent scrolls as the default action then the sign of the delta is given by a right-hand coordinate system where positive X,Y, and Z axes are directed towards the right-most edge, bottom-most edge, and farthest depth (away from the user) of the [=document=], respectively.
    digitizer
    A type of input sensing device in which a surface can detect input which is in contact and/or in close proximity. Most commonly, this is the surface that senses input from the touch contact or a pen/stylus.
    direct manipulation
    Certain user agents (such as browsers on a touchscreen device) implement a "direct manipulation" metaphor where a pointer not only interacts with controls, but is also used to directly pan or zoom the current page, providing the illusion of direct physical contact. As an example, users on a touchscreen device are generally able to use a finger or a stylus to "grab" a page and pan it by moving the pointer, directly manipulating the page. Contrast this with a mouse pointer on a regular desktop/laptop, where panning is done by using a scrollbar, rather than by "dragging" the page.
    In some cases, touchpads (like those found on a laptop) will allow the user to scroll by "dragging" on the touchpad. However, this is generally achieved by the touchpad generating "fake" mouse wheel events, so this wouldn't count as a direct manipulation.
    hysteresis
    A feature of human interface design to accept input values within a certain range of location or time, in order to improve the user experience. For example, allowing for small deviation in the time it takes for a user to double-click a mouse button is temporal hysteresis, and not immediately closing a nested menu if the user mouses out from the parent window when transitioning to the child menu is locative hysteresis.
    measurable properties

    Measurable properties represent values relating to continuous pointer sensor data that is expressed using a real number or an integer from a large domain. For pointer events, width, height, pressure, tangentialPressure, tiltX, tiltY, twist, altitudeAngle, azimuthAngle, and the [[UIEVENTS]] Mouse Event model properties screenX, screenY, clientX, clientY are measurable properties.

    In contrast {{PointerEvent/pointerId}}, pointerType, isPrimary, and the [[UIEVENTS]] Mouse Event model properties button, buttons, ctrlKey, shiftKey, altKey, and metaKey are not considered measurable properties, as they don't relate to sensor data.

    pointer
    A hardware-agnostic representation of input devices that can target a specific coordinate (or set of coordinates) on a screen, such as a mouse, pen, or touch contact.
    rotation
    An indication of incremental change on an input device using the {{WheelEvent}} interface. On some devices this MAY be a literal rotation of a wheel, while on others, it MAY be movement along a flat surface, or pressure on a particular button.
    topmost event target
    The topmost event target MUST be the element highest in the rendering order which is capable of being a [=Event/target=]. In graphical user interfaces this is the element under the user's pointing device. A user interface's hit testing facility is used to determine the target. For specific details regarding hit testing and stacking order, refer to the host language.

    Legacy Event Initializers

    This section is normative. The following features are obsolete and should only be implemented by user agents that require compatibility with legacy software. See also the legacy event initializers in [[UIEvents]].

    Initializers for interface MouseEvent

    		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);
    		};
    		
    initMouseEvent(typeArg)
    Initializes attributes of a {{MouseEvent}} object. This method has the same behavior as UIEvent.initUIEvent().

    The initMouseEvent method is deprecated, but supported for backwards-compatibility with widely-deployed implementations.

    DOMString typeArg
    Refer to the {{Event/initEvent()}} method for a description of this parameter.
    boolean bubblesArg
    Refer to the {{Event/initEvent()}} method for a description of this parameter.
    boolean cancelableArg
    Refer to the {{Event/initEvent()}} method for a description of this parameter.
    Window? viewArg
    Specifies {{UIEvent/view}}. This value MAY be null.
    long detailArg
    Specifies {{UIEvent/detail}}.
    long screenXArg
    Specifies {{MouseEvent/screenX}}.
    long screenYArg
    Specifies {{MouseEvent/screenY}}.
    long clientXArg
    Specifies {{MouseEvent/clientX}}.
    long clientYArg
    Specifies {{MouseEvent/clientY}}.
    boolean ctrlKeyArg
    Specifies {{MouseEvent/ctrlKey}}.
    boolean altKeyArg
    Specifies {{MouseEvent/altKey}}.
    boolean shiftKeyArg
    Specifies {{MouseEvent/shiftKey}}.
    boolean metaKeyArg
    Specifies {{MouseEvent/metaKey}}.
    short buttonArg
    Specifies {{MouseEvent/button}}.
    EventTarget? relatedTargetArg
    Specifies {{MouseEvent/relatedTarget}}. This value MAY be null.

    Acknowledgments

    Many thanks to lots of people for their proposals and recommendations, some of which are incorporated into this document. The group's Chair acknowledges contributions from the following past and present group members and participants: 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.

    Thanks to those who took care of mouse and wheel events in the past: Gary Kacmarcik, Travis Leithead, and the various contributors over the years.

    Special thanks to those that helped pioneer the first edition of this model, including especially: Charu Chandiram, Peter Freiling, Nathan Furtwangler, Thomas Olsen, Matt Rakow, Ramu Ramanathan, Justin Rogers, Jacob Rossi, Reed Townsend and Steve Wright.

    Revision history

    The following is an informative summary of substantial and major editorial changes between publications of this specification, relative to the [[PointerEvents3]] specification. See the complete revision history of the Editor's Drafts of this specification.