forked from w3c/pointerevents
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.html
1006 lines (958 loc) · 90.1 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html>
<head>
<title>Pointer Events - Level 2</title>
<meta http-equiv='Content-Type' content='text/html;charset=utf-8'/>
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<script type="text/javascript" src='https://www.w3.org/Tools/respec/respec-w3c-common.js' class='remove'></script>
<script type="text/javascript" class='remove'>
var respecConfig = {
specStatus: "ED",
shortName: "pointerevents2",
noIDLSorting: true,
edDraftURI: "https://w3c.github.io/pointerevents/",
license: "w3c-software-doc",
// editors, add as many as you like
// only "name" is required
editors: [
{ name: "Jacob Rossi",
company: "Microsoft Corporation", companyURL: "http://www.microsoft.com/" },
{ name: "Matt Brubeck",
company: "Mozilla", companyURL: "http://www.mozilla.org/" },
{ name: "Rick Byers",
company: "Google", companyURL: "http://www.google.com/" },
{ name: "Patrick H. Lauke",
company: "The Paciello Group", companyURL: "https://www.paciellogroup.com/" }
],
otherLinks: [{
key: 'Repository and Participation',
data: [
{
value: 'We are on github.',
href: 'https://github.com/w3c/pointerevents/'
}, {
value: 'File a bug/issue.',
href: 'https://github.com/w3c/pointerevents/issues'
}, {
value: 'Commit history.',
href: 'https://github.com/w3c/pointerevents/commits'
}, {
value: 'Mailing list archive.',
href: 'https://lists.w3.org/Archives/Public/public-pointer-events/'
}
]
}],
//authors: [
// { name: "Your Name", url: "http://example.org/",
// company: "Your Company", companyURL: "http://example.com/" },
//],
// name of the WG
wg: "Pointer Events Working Group",
// URI of the public WG page
wgURI: "http://www.w3.org/2012/pointerevents/",
// name (with the @w3c.org) of the public mailing to which comments are due
wgPublicList: "public-pointer-events",
// URI of the patent status for this WG, for Rec-track documents
wgPatentURI: "http://www.w3.org/2004/01/pp-impl/59096/status",
// previous REC spec
prevRecShortname: 'pointerevents',
//Biblio entry to point to W3 DOM4 snapshot
localBiblio: {
"DOM4" : {
"authors": [
"Anne van Kesteren",
"Aryeh Gregor",
"Ms2ger",
"Alex Russell",
"Robin Berjon"
],
"href": "http://www.w3.org/TR/dom/",
"publisher": "W3C",
"status": "Last Call Working Draft",
"title": "W3C DOM4"
}
}
};
</script>
<style>
.issue {background: #fcc !important;}
pre.idl::before, pre.example::before { font-family: sans-serif !important; }
ol:not([data-class='note-list'])>li { margin-bottom: 1em; }
</style>
</head>
<body>
<section id='abstract'>
<p>The features in this specification extend or modify those found in Pointer Events, a W3C Recommendation that describes events and related interfaces for handling hardware agnostic pointer input from devices including a mouse, pen, touchscreen, etc. For compatibility with existing mouse based content, this specification also describes a mapping to fire Mouse Events for other pointer device types.</p>
</section>
<section id="sotd">
<p>This specification is an update to [[PointerEvents]] which was shipped broadly only by Microsoft Internet Explorer and Microsoft Edge (though a further independent and mostly interoperable implementation was present in a pre-release build of Mozilla Firefox when the Pointer Events specification was published as a W3C Recommendation). Level 2 includes editorial clarifications, new features and minor breaking changes that address certain limitations and concerns that have been raised about aspects of the design, in an effort to enable wider browser adoption.</p>
</section>
<section id="intro" class="informative">
<h1>Introduction</h1>
<p>Today, most [[HTML5]] content is used with and/or designed for mouse input. Those that handle input in a custom manner typically code to [[!DOM-LEVEL-3-EVENTS]] Mouse Events. Newer computing devices today, however, incorporate other forms of input, including touchscreens, pen input, etc. 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 <a data-lt="user agent">user agents</a> 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.</p>
<p>To reduce the cost of coding to multiple input types and also to help with the above described ambiguity with Mouse Events, this specifications defines a more abstract form of input, called a <a>pointer</a>. 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.</p>
<p> An additional key goal is to enable multi-threaded user agents to handle default touch actions, such as scrolling, without blocking on script execution.</p>
<div class="note">
<p>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 screenreader 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.</p>
<p>In the first instance, authors are encouraged to provide equivalent functionality for all forms of input by responding to high-level events such as <code>focus</code>, <code>blur</code> and <code>click</code>. 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 <a href="http://www.w3.org/TR/WCAG20/#keyboard-operation">WCAG 2.0 Guideline 2.1</a> for further details.</p>
</div>
<figure id="figure_martini_glass">
<img src="pointer.png" alt="Pointer input combines input from mouse, pen, touch, etc.">
<figcaption>A pointer is a hardware agnostic representation of input devices that can target a specific coordinate (or set of coordinates) on a screen.</figcaption>
</figure>
<p>The events for handling generic pointer input look a lot like those for mouse: pointerdown, pointermove, pointerup, pointerover, pointerout, etc. This facilitates easy content migration from Mouse Events to Pointer Events.
Pointer Events provide all the usual properties present in Mouse Events (client coordinates, target element, button states, etc.) in addition to new properties for other forms of input: pressure, contact geometry, tilt, etc. So 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.</p>
<p>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 (e.g. mouse events, touch events, etc.). 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 <a>compatibility mouse events</a> based on pointer input from devices other than a mouse.</p>
<div class="note informative">
<p>This specification does not provide any advice on the expected behavior of user agents that support both Pointer Events and <a href="http://www.w3.org/TR/touch-events/">Touch Events</a>. For more information on the relationship between these two specifications, see the <a href="http://www.w3.org/community/touchevents/">Touch Events Community Group</a>.</p>
</div>
</section>
<section id="conformance">
</section>
<section class="informative">
<h1>Examples</h1>
<p>The following are example author code that demonstrates how the APIs in this specification might be used.</p>
<pre id="example_1" class="example" title="Basic HTML5 Canvas painting application">
<style>
/* Disable intrinsic user agent touch 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 type='text/javascript'>
var canvas = document.getElementById("drawSurface"),
context = canvas.getContext("2d");
if (window.PointerEvent) {
canvas.addEventListener("pointermove", paint, false);
if(window.navigator.maxTouchPoints>1)
/* User agent and hardware support multi-touch */
}
else {
//Provide fallback for user agents that do not support Pointer Events
canvas.addEventListener("mousemove", paint, false);
}
function paint(event) {
if(event.buttons>0)
context.fillRect(event.clientX, event.clientY, 5, 5);
}
</script>
</pre>
<pre id="example_2" class="example" title="Detecting the type of input from a user">
window.addEventListener("pointerdown", detectInputType, false);
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 */
}
}</pre>
<pre id="example_3" class="example" title="Resizing an element to match the contact geometry">
<div style="position:absolute; top:0px; left:0px; width:100px;height:100px;"></div>
<script>
window.addEventListener("pointerdown", checkPointerSize, false);
function checkPointerSize(event) {
event.target.style.width = event.width + "px";
event.target.style.height = event.height + "px";
}
</script>
</pre>
<pre id="example_4" class="example" title="Firing an untrusted pointer event from script">
var event = new PointerEvent("pointerover",
{bubbles: true,
cancelable: true,
composed: true,
pointerId: 42,
pointerType: "pen",
clientX: 300,
clientY: 500
});
eventTarget.dispatchEvent(event);
</pre>
</section>
<section class="informative">
<h1>Glossary</h1>
<dl>
<dt><dfn>active buttons state</dfn></dt>
<dd>The condition when a pointer has a non-zero value for the <code>buttons</code> 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.</dd>
<dt><dfn>active pointer</dfn></dt>
<dd>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 <code>pointerId</code>) to produce additional events within the document, then that pointer is still considered active. Examples:
<ul>
<li>A mouse connected to the device is always active.</li>
<li>A touch contact on the screen is considered active.</li>
<li>If a touch contact or pen stylus is lifted beyond the range of the digitizer, then it is no longer considered active.</li>
</ul>
<div class="note">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).</div>
<div class="note">Each active pointer should have the same id within the scope of the <a href="https://www.w3.org/TR/html5/browsers.html#top-level-browsing-context">top-level browsing context</a> (as defined by [[!HTML5]]). However, there is no such guarantee across multiple <a href="https://www.w3.org/TR/html5/browsers.html#top-level-browsing-context">top-level browsing contexts</a>. </div>
</dd>
<dt><dfn>canceled event</dfn></dt>
<dd>An event whose default action was prevented by means of <code>preventDefault()</code>, returning <code>false</code> in an event handler, or other means as defined by [[!DOM-LEVEL-3-EVENTS]] and [[!HTML5]].</dd>
<dt><dfn>contact geometry</dfn></dt>
<dd>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.</dd>
<dt><dfn>digitizer</dfn></dt>
<dd>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.</dd>
<dt><dfn>hit test</dfn></dt>
<dd>The process by which a user agent determines a target element for a pointer event. Typically, this is determined by considering the pointer's location and also the visual layout of elements in a document on screen media.</dd>
<dt><dfn>pointer</dfn></dt>
<dd>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.</dd>
<dt><dfn>user agent</dfn></dt>
<dd>A program, such as a browser or content authoring tool, normally running on a client machine, which acts on a user's behalf in retrieving, interpreting, executing, presenting, or creating content.</dd>
<dt><dfn>queue a task</dfn></dt>
<dd>Adding the task to events task queue of the relevant event loop, as defined in [[!HTML5]].</dd>
</dl>
</section>
<section>
<h1>Pointer Events and Interfaces</h1>
<section>
<h2><code>PointerEvent</code> Interface</h2>
<div>
<pre class="idl">
dictionary PointerEventInit : MouseEventInit {
long pointerId = 0;
double width = 1;
double height = 1;
float pressure = 0;
float tangentialPressure = 0;
long tiltX = 0;
long tiltY = 0;
long twist = 0;
DOMString pointerType = "";
boolean isPrimary = false;
};
[Constructor(DOMString type, optional PointerEventInit eventInitDict)]
interface PointerEvent : MouseEvent {
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 DOMString pointerType;
readonly attribute boolean isPrimary;
};
</pre>
<dl dfn-for="PointerEvent" link-for="PointerEvent">
<dt><dfn>pointerId<dfn></dt>
<dd>
<p>A unique identifier for the pointer causing the event. This identifier MUST be unique from all other <a data-lt="active pointer">active pointers</a> in the <a href="https://www.w3.org/TR/html5/browsers.html#top-level-browsing-context">top-level browsing context</a> (as defined by [[!HTML5]]) at the time. A user agent MAY recycle previously retired values for <code>pointerId</code> from previous active pointers, if necessary.</p>
<div class="note">The <code>pointerId</code> selection algorithm is implementation specific. Therefore 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, values are not guaranteed to be monotonically increasing.</div>
</dd>
<dt><dfn>width</dfn></dt>
<dd>
<p>The width (magnitude on the X axis), in CSS pixels (see [[CSS21]]), of the <a>contact geometry</a> 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 <a>user agent</a> MUST return a default value of 1.</p>
</dd>
<dt><dfn>height</dfn></dt>
<dd>
<p>The height (magnitude on the Y axis), in CSS pixels (see [[CSS21]]), of the <a>contact geometry</a> 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 <a>user agent</a> MUST return a default value of 1.</p>
</dd>
<dt><dfn>pressure</dfn></dt>
<dd>
<p>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 that does not support pressure, the value MUST be 0.5 when in the <a>active buttons state</a> and 0 otherwise.</p>
</dd>
<dt><dfn>tangentialPressure</dfn></dt>
<dd>
<p>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 that does not support tangential pressure, the value MUST be 0.</p>
</dd>
<dt><dfn>tiltX</dfn></dt>
<dd>
<p>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 <code>tiltX</code> is to the right. <code>tiltX</code> can be used along with <code>tiltY</code> to represent the tilt away from the normal of a transducer with the digitizer. For devices that do not report tilt, the value MUST be 0.</p>
<figure id="figure_tiltX">
<img src="tiltX_600px.png" alt="tiltX explanation diagram">
<figcaption>Positive <code>tiltX</code>.</figcaption>
</figure>
</dd>
<dt><dfn>tiltY</dfn></dt>
<dd>
<p>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 <code>tiltY</code> is towards the user. <code>tiltY</code> can be used along with <code>tiltX</code> to represent the tilt away from the normal of a transducer with the digitizer. For devices that do not report tilt, the value MUST be 0.</p>
<figure id="figure_tiltY">
<img src="tiltY_600px.png" alt="tiltY explanation diagram">
<figcaption>Negative <code>tiltY</code>.</figcaption>
</figure>
</dd>
<dt><dfn>twist</dfn></dt>
<dd>
<p>The clockwise rotation (in degrees, in the range of [0,359]) of a transducer (e.g. pen stylus) around its own major axis. For devices that do not report twist, the value MUST be 0.</p>
</dd>
<dt><dfn>pointerType</dfn></dt>
<dd>
<p>Indicates the device type that caused the event (mouse, pen, touch, etc.). If a user agent is to <a href="#firing-events-using-the-pointerevent-interface">fire a pointer event</a> for a mouse, pen stylus, or touch input device, then the value of <code>pointerType</code> MUST be according to the following table:</p>
<table class="simple">
<thead>
<tr><th>Pointer Device Type</th><th><code>pointerType</code> Value</th></tr>
</thead>
<tbody>
<tr><td>Mouse</td><td><code>mouse</code></td></tr>
<tr><td>Pen Stylus</td><td><code>pen</code></td></tr>
<tr><td>Touch Contact</td><td><code>touch</code></td></tr>
</tbody>
</table>
<p>If the device type cannot be detected by the user agent, then the value MUST be an empty string. If a user agent supports pointer device types other than those listed above, the value of <code>pointerType</code> SHOULD be vendor prefixed to avoid conflicting names for different types of devices. Future specifications MAY provide additional normative values for other device types.</p>
<div class="note">See <a href="#example_2" title="examples">Example 2</a> for a basic demonstration of how the <code>pointerType</code> 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 <code>pointerType</code> values and for situations where <code>pointerType</code> is simply an empty string.</div>
</dd>
<dt><dfn>isPrimary</dfn></dt>
<dd>
<p>Indicates if the pointer represents the <a>primary pointer</a> of this pointer type.</p>
</dd>
</dl>
<p>The <code>PointerEventInit</code> dictionary is used by the <code>PointerEvent</code> interface's constructor to provide a mechanism by which to construct untrusted (synthetic) pointer events. It inherits from the <code>MouseEventInit</code> dictionary defined in [[!DOM-LEVEL-3-EVENTS]]. The steps for constructing an event are defined in [[!DOM4]]. See the <a href="#examples" title="examples">examples</a> for sample code demonstrating how to fire an untrusted pointer event.</p>
<div class="note">The <code>PointerEvent</code> interface inherits from <code>MouseEvent</code>, defined in [[DOM-LEVEL-3-EVENTS]] and extended by [[CSSOM-VIEW]].</div>
</div>
<section>
<h2>Button States</h2>
<section>
<h3><dfn>Chorded Button Interactions</dfn></h3>
<p>Some pointer devices, such as mouse or pen, support multiple buttons. In the [[!DOM-LEVEL-3-EVENTS]] Mouse Event model, each button press produces a <code>mousedown</code> and <code>mouseup</code> event. To better abstract this hardware difference and simplify cross-device input authoring, Pointer Events do not fire overlapping <code>pointerdown</code> and <code>pointerup</code> events for <a data-lt="Chorded Button Interactions">chorded button presses</a> (depressing an additional button while another button on the pointer device is already depressed).</p>
<p>Instead, chorded button presses can be detected by inspecting changes to the <code>button</code> and <code>buttons</code> properties. The <code>button</code> and <code>buttons</code> properties are inherited from the [[!DOM-LEVEL-3-EVENTS]] <code>MouseEvent</code> interface, but with a change in semantics and values, as outlined in the following sections.</p>
<div class="note">The modifications to the <code>button</code> and <code>buttons</code> properties apply only to pointer events. For any <a>compatibility mouse events</a> the value of <code>button</code> and <code>buttons</code> should follow [[!DOM-LEVEL-3-EVENTS]].</div>
</section>
<section>
<h3>The <code>button</code> property</h3>
<p>To identify button state transitions in any pointer event (and not just <code>pointerdown</code> and <code>pointerup</code>), the <code>button</code> property indicates the device button whose state-change fired the event.</p>
<table class="simple">
<thead><tr><th>Device Button Changes</th><th><code>button</code></th></tr></thead>
<tbody>
<tr><td>Neither buttons nor touch/pen contact changed since last event</td><td>-1</td></tr>
<tr><td>Left Mouse,<br>Touch Contact,<br>Pen contact</td><td>0</td></tr>
<tr><td>Middle Mouse</td><td>1</td></tr>
<tr><td>Right Mouse,<br>Pen barrel button</td><td>2</td></tr>
<tr><td>X1 (back) Mouse</td><td>3</td></tr>
<tr><td>X2 (forward) Mouse</td><td>4</td></tr>
<tr><td>Pen eraser button</td><td>5</td></tr>
</tbody>
</table>
<div class="note">During a mouse drag, the value of the <code>button</code> property in a <code>pointermove</code> event will be different from that in a <code>mousemove</code> event. For example, while moving the mouse with the right button pressed, the <code>pointermove</code> events will have the <code>button</code> value -1, but the <code>mousemove</code> events will have the <code>button</code> value 2.</div>
</section>
<section>
<h3>The <code>buttons</code> property</h3>
<p>The <code>buttons</code> property gives the current state of the device buttons as a bitmask (same as in <code>MouseEvent</code>, but with an expanded set of possible values).</p>
<table class="simple">
<thead><tr><th>Current state of device buttons</th><th><code>buttons</code></th></tr></thead>
<tbody>
<tr><td><b>Mouse moved with no buttons pressed</b>,<br> Pen moved while hovering with no buttons pressed</td><td>0</td></tr>
<tr><td>Left Mouse,<br>Touch Contact,<br>Pen contact</td><td>1</td></tr>
<tr><td>Middle Mouse</td><td>4</td></tr>
<tr><td>Right Mouse,<br>Pen barrel button</td><td>2</td></tr>
<tr><td>X1 (back) Mouse</td><td>8</td></tr>
<tr><td>X2 (forward) Mouse</td><td>16</td></tr>
<tr><td>Pen eraser button</td><td>32</td></tr>
</tbody>
</table>
</section>
</section>
<section>
<h2>The <dfn>Primary Pointer</dfn></h2>
<p>In a multi-pointer (e.g. multi-touch) scenario, the <a href="#widl-PointerEvent-isPrimary"><code>isPrimary</code></a> property is used to identify a master pointer amongst the set of <a data-lt="active pointer">active pointers</a> for each pointer type.</p>
<ul>
<li>At any given time, there can only ever be at most one primary pointer for each pointer type.</li>
<li>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.</li>
<li>Only a primary pointer will produce <a>compatibility mouse events</a>. In the case where there are multiple <a data-lt="Primary Pointer">primary pointers</a>, these pointers will all produce <a>compatibility mouse events</a>.</li>
</ul>
<div class="note">Authors who desire single-pointer interaction can achieve this by ignoring non-primary pointers (however, see the note below on <a href="#multiple-primary-pointers">multiple primary pointers</a>).</div>
<div class="note" id="multiple-primary-pointers">When two or more pointer device types are being used concurrently, multiple pointers (one for each <code>pointerType</code>) are considered primary. For example, a touch contact and a mouse cursor moved simultaneously will produce pointers that are both considered primary.</div>
<div class="note">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 multi-touch and the primary pointer is removed (e.g. it leaves the screen), there will be no primary pointer events. Also on the platforms where the primary pointer is determined using all active pointers on the device (including those targeted at an application other than the user agent), if the first touch interaction is targeted outside the user agent and a secondary (multi-touch) touch interaction is targeted inside the user agent, then the user agent may fire pointer events for the second contact with a value of <code>false</code> for <code>isPrimary</code>.</div>
<div class="note" id="multiple-mouse-inputs">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.</div>
</section>
<section>
<h2>Firing events using the <code>PointerEvent</code> interface</h2>
<p>To <dfn>fire a pointer event name e</dfn> means to <dfn>fire an event named e</dfn> as defined in [[!DOM4]] with an event using the <a>PointerEvent</a> interface whose attributes are set as defined in <a href="#pointerevent-interface"><code>PointerEvent</code> Interface</a>.</p>
<p>Initialize the <code>composed</code> [[!WHATWG-DOM]] attribute to <code>true</code> for any pointer event.</p>
<p>Initialize the <code>bubbles</code> attribute for the event to <code>true</code> if the event name is</p>
<ul>
<li><code>pointerdown</code></li>
<li><code>pointerup</code></li>
<li><code>pointercancel</code></li>
<li><code>pointermove</code></li>
<li><code>pointerover</code></li>
<li><code>pointerout</code></li>
<li><code>gotpointercapture</code></li>
<li><code>lostpointercapture</code></li>
</ul>
<p>Initialize the <code>cancelable</code> attribute for the event to <code>true</code> if the event name is<p>
<ul>
<li><code>pointerdown</code></li>
<li><code>pointerup</code></li>
<li><code>pointermove</code></li>
<li><code>pointerover</code></li>
<li><code>pointerout</code></li>
</ul>
<p>The target object at which the event is fired is determined as follows:
<ul>
<li>If the <a>pointer capture target override</a> has been set for the pointer,
<ul>
<li>Set the <code>relatedTarget</code> attribute of the event to <code>null</code>.</li>
<li>Fire the event to the <a>pointer capture target override</a> object.</li>
</ul>
</li>
<li>Otherwise, fire the event to the object returned by normal hit test mechanisms (out of scope for this specification).</li>
</ul>
<section>
<h3>Process Pending Pointer Capture</h3>
<p>Whenever a user agent is to fire a Pointer Event that is not <code>gotpointercapture</code> or <code>lostpointercapture</code>, it must first run these steps:</p>
<ol>
<li>If the <a>pointer capture target override</a> for this pointer is set and is not equal to the <a>pending pointer capture target override</a>, then fire a pointer event named <code>lostpointercapture</code> at the <a>pointer capture target override</a> node.
<ul>
<li>Further, if the <a>pending pointer capture target override</a> is not set and, the <a>pointer capture target override</a> is not equal to the hit test node for the pointer event which invoked this process, then fire a pointer event named <code>pointerover</code> and a pointer event named <code>pointerenter</code> at the hit test node.</li>
</ul>
</li>
<li>If the <a>pending pointer capture target override</a> for this pointer is set and is not equal to the <a>pointer capture target override</a>, then fire a pointer event named <code>gotpointercapture</code> at the <a>pending pointer capture target override</a>.
<ul>
<li>Further, if the <a>pointer capture target override</a> is not set and, the <a>pending pointer capture target override</a> is not equal to the hit test node for the pointer event which invoked this process, and the hit test node has received <code>pointerover</code> and <code>pointerenter</code> events, then fire a pointer event named <code>pointerout</code> and a pointer event named <code>pointerleave</code> at the hit test node.</li>
</ul>
</li>
<li>Set the <dfn>pointer capture target override</dfn> to the <a>pending pointer capture target override</a>, if set. Otherwise, clear the <a>pointer capture target override</a>.</li>
</ol>
</section>
</section>
</section>
<section>
<h2>Pointer Event types</h2>
<p>The following table provides a summary of the event types defined in this specification.</p>
<table class="parameters">
<thead><tr>
<th>Event Type</th><th>Sync/Async</th><th>Bubbles</th><th>Cancelable</th><th>Composed</th><th>Default Action</th></tr>
</thead>
<tbody>
<tr>
<td><code>pointerover</code></td>
<td>Sync</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>None</td>
</tr>
<tr>
<td><code>pointerenter</code></td>
<td>Sync</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
<td>None</td>
</tr>
<tr>
<td><code>pointerdown</code></td>
<td>Sync</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Varies: when the pointer is primary, all default actions of the <code>mousedown</code> event
<br>Canceling this event also sets the <i>PREVENT MOUSE EVENT</i> flag for this <code>pointerType</code>, which prevents subsequent firing of certain <a>compatibility mouse events</a>.</td>
</tr>
<tr>
<td><code>pointermove</code></td>
<td>Sync</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Varies: when the pointer is primary, all default actions of <code>mousemove</code></td>
</tr>
<tr>
<td><code>pointerup</code></td>
<td>Sync</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Varies: when the pointer is primary, all default actions of <code>mouseup</code></td>
</tr>
<tr>
<td><code>pointercancel</code></td>
<td>Sync</td>
<td>Yes</td>
<td>No</td>
<td>Yes</td>
<td>None</td>
</tr>
<tr>
<td><code>pointerout</code></td>
<td>Sync</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>None</td>
</tr>
<tr>
<td><code>pointerleave</code></td>
<td>Sync</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
<td>None</td>
</tr>
<tr>
<td><code>gotpointercapture</code></td>
<td>Sync/Async</td>
<td>Yes</td>
<td>No</td>
<td>Yes</td>
<td>None</td>
</tr>
<tr>
<td><code>lostpointercapture</code></td>
<td>Sync/Async</td>
<td>Yes</td>
<td>No</td>
<td>Yes</td>
<td>None</td>
</tr>
</tbody>
</table>
<p>In the case of the <a>primary pointer</a>, these events (with the exception of <code>gotpointercapture</code>, and <code>lostpointercapture</code>) may also fire <a>compatibility mouse events</a>.</p>
<p>For all PointerEvents in the table above, <a href="https://www.w3.org/TR/uievents/#widl-UIEvent-detail">detail</a> attribute defined in [[!DOM-LEVEL-3-EVENTS]] SHOULD be 0.</p>
<section>
<h3><dfn>The <code>pointerover</code> event</dfn></h3>
<p>A user agent MUST <a href="#firing-events-using-the-pointerevent-interface">fire a pointer event</a> named <code>pointerover</code> when a pointing device is moved into the hit test boundaries of an element. A user agent MUST also fire this event prior to firing a <code>pointerdown</code> event for <a href=#mapping-for-devices-that-do-not-support-hover>devices that do not support hover</a> (see <code><a href="#the-pointerdown-event">pointerdown</a></code>).</p>
</section>
<section>
<h3><dfn>The <code>pointerenter</code> event</dfn></h3>
<p>A user agent MUST <a href="#firing-events-using-the-pointerevent-interface">fire a pointer event</a> named <code>pointerenter</code> when a pointing device is moved into the hit test boundaries of an element or one of its descendants, including as a result of a <code>pointerdown</code> event from a device that <a href=#mapping-for-devices-that-do-not-support-hover>does not support hover</a> (see <code><a href="#the-pointerdown-event">pointerdown</a></code>). This event type is similar to <code>pointerover</code>, but differs in that it does not bubble.</p>
<div class="note">There are similarities between this event type, the <code>mouseenter</code> event described in [[DOM-LEVEL-3-EVENTS]], and the CSS <code>:hover</code> pseudo-class described in [[CSS21]]. See also the <code>pointerleave</code> event.</div>
</section>
<section>
<h3><dfn>The <code>pointerdown</code> event</dfn></h3>
<p>A user agent MUST <a href="#firing-events-using-the-pointerevent-interface">fire a pointer event</a> named <code>pointerdown</code> when a pointer enters the <a>active buttons state</a>. 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 <a>digitizer</a>. 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.</p>
<div class="note">For mouse (or other multi-button pointer devices), this means <code>pointerdown</code> and <code>pointerup</code> are not fired for all of the same circumstances as <code>mousedown</code> and <code>mouseup</code>. See <a href="#chorded-button-interactions">chorded buttons</a> for more information.</div>
<p>For input <a href=#mapping-for-devices-that-do-not-support-hover>devices that do not support hover</a>, a user agent MUST also <a href="#firing-events-using-the-pointerevent-interface">fire a pointer event</a> named <code>pointerover</code> followed by a pointer event named <code>pointerenter</code> prior to dispatching the <code>pointerdown</code> event.</p>
<div class="note">Authors can prevent the firing of certain <a data-lt="compatibility mapping with mouse events">compatibility mouse events</a> by canceling the <code>pointerdown</code> event (if the <code>isPrimary</code> property is <code>true</code>). This sets the PREVENT MOUSE EVENT FLAG on the pointer. Note, however, that this does not prevent the <code>mouseover</code>, <code>mouseenter</code>, <code>mouseout</code>, or <code>mouseleave</code> events from firing.</div>
</section>
<section>
<h3><dfn>The <code>pointermove</code> event</dfn></h3>
<p>A user agent MUST <a href="#firing-events-using-the-pointerevent-interface">fire a pointer event</a> named <code>pointermove</code> when a pointer changes coordinates. Additionally, when a pointer changes button state, pressure, tangential pressure, tilt, twist, or contact geometry (e.g. <code>width</code> and <code>height</code>) and the circumstances produce no other pointer events defined in this specification then a user agent MUST <a href="#firing-events-using-the-pointerevent-interface">fire a pointer event</a> named <code>pointermove</code>.</p>
</section>
<section>
<h3><dfn>The <code>pointerup</code> event</dfn></h3>
<p>A user agent MUST <a href="#firing-events-using-the-pointerevent-interface">fire a pointer event</a> named <code>pointerup</code> when a pointer leaves the <a>active buttons state</a>. 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 <a>digitizer</a>. 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.</p>
<p>For input <a href=#mapping-for-devices-that-do-not-support-hover>devices that do not support hover</a>, a user agent MUST also <a href="#firing-events-using-the-pointerevent-interface">fire a pointer event</a> named <code>pointerout</code> followed by a pointer event named <code>pointerleave</code> after dispatching the <code>pointerup</code> event.</p>
<div class="note">For mouse (or other multi-button pointer devices), this means <code>pointerdown</code> and <code>pointerup</code> are not fired for all of the same circumstances as <code>mousedown</code> and <code>mouseup</code>. See <a href="#chorded-button-interactions">chorded buttons</a> for more information.</div>
</section>
<section>
<h3><dfn>The <code>pointercancel</code> event</dfn></h3>
<p>A user agent MUST <a href="#firing-events-using-the-pointerevent-interface">fire a pointer event</a> named <code>pointercancel</code> in the following circumstances:</p>
<ul>
<li>The user agent has determined that a pointer is unlikely to continue to produce events (for example, because of a hardware event).</li>
<li>After having fired the <code>pointerdown</code> event, if the pointer is subsequently used to manipulate the page viewport (e.g. panning or zooming).</li>
</ul>
<p>After firing the <code>pointercancel</code> event, a user agent MUST also fire a pointer event named <code>pointerout</code> followed by firing a pointer event named <code>pointerleave</code>.</p>
<div class="note">
<p><i>This section is non-normative.</i></p>
<p>Examples of scenarios in which a user agent might determine that a pointer is unlikely to continue to produce events include:
<ul>
<li>A device's screen orientation is changed while a pointer is active.</li>
<li>The user inputs a greater number of simultaneous pointers than is supported by the device.</li>
<li>The user agent interprets the input as accidental (for example, the hardware supports palm rejection).</li>
</ul>
<p>Methods for changing the device's screen orientation, recognizing accidental input, or using a pointer to manipulate the viewport (e.g. panning or zooming) are out of scope for this specification.</p>
</div>
</section>
<section>
<h3><dfn>The <code>pointerout</code> event</dfn></h3>
<p>A user agent MUST <a href="#firing-events-using-the-pointerevent-interface">fire a pointer event</a> named <code>pointerout</code> when any of the following occurs:</p>
<ul>
<li>A pointing device is moved out of the hit test boundaries of an element.</li>
<li>After firing the <code>pointerup</code> event for a device that <a href=#mapping-for-devices-that-do-not-support-hover>does not support hover</a> (see <code><a href="#the-pointerup-event">pointerup</a></code>).</li>
<li>After firing the <code>pointercancel</code> event (see <code><a href="#the-pointercancel-event">pointercancel</a></code>).</li>
<li>When a pen stylus leaves the hover range detectable by the digitizer.</li>
</ul>
</section>
<section>
<h3><dfn>The <code>pointerleave</code> event</dfn></h3>
<p>A user agent MUST <a href="#firing-events-using-the-pointerevent-interface">fire a pointer event</a> named <code>pointerleave</code> when a pointing device is moved out of the hit test boundaries of an element and all of its descendants, including as a result of a <code>pointerup</code> and <code>pointercancel</code> events from a device that <a href=#mapping-for-devices-that-do-not-support-hover>does not support hover</a> (see <code><a href="#the-pointerup-event">pointerup</a></code> and <code><a href="#the-pointercancel-event">pointercancel</a></code>). User agents MUST also <a href="#firing-events-using-the-pointerevent-interface">fire a pointer event</a> named <code>pointerleave</code> when a pen stylus leaves hover range detectable by the digitizer. This event type is similar to <code>pointerout</code>, but differs in that it does not bubble and that it MUST not be fired until the pointing device has left the boundaries of the element and the boundaries of all of its descendants.</p>
<div class="note">There are similarities between this event type, the <code>mouseleave</code> event described in [[DOM-LEVEL-3-EVENTS]], and the CSS <code>:hover</code> pseudo-class described in [[CSS21]]. See also the <code>pointerenter</code> event.</div>
</section>
<section>
<h3><dfn>The <code>gotpointercapture</code> event</dfn></h3>
<p>A user agent MUST <a href="#firing-events-using-the-pointerevent-interface">fire a pointer event</a> named <code>gotpointercapture</code> 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 <a href="#setting-pointer-capture">Setting Pointer Capture</a> and <a href="#process-pending-pointer-capture">Process Pending Pointer Capture</a> sections.</p>
</section>
<section>
<h3><dfn>The <code>lostpointercapture</code> event</dfn></h3>
<p>A user agent MUST <a href="#firing-events-using-the-pointerevent-interface">fire a pointer</a> event named <code>lostpointercapture</code> 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. Subsequent events for the pointer follow normal hit testing mechanisms (out of scope for this specification) for determining the event target. See the <a href="#releasing-pointer-capture">Releasing Pointer Capture</a>, <a href="#implicit-release-of-pointer-capture">Implicit Release of Pointer Capture</a>, and <a href="#process-pending-pointer-capture">Process Pending Pointer Capture</a> sections.</p>
</section>
</section>
</section>
<section>
<h2>Extensions to the <code>Element</code> interface</h2>
<div>
<p>The following section describes extensions to the existing <code>Element</code> interface, defined in [[!HTML5]], to facilitate the setting and releasing of pointer capture.</p>
<pre class="idl">
partial interface Element {
attribute EventHandler ongotpointercapture;
attribute EventHandler onlostpointercapture;
void setPointerCapture (long pointerId);
void releasePointerCapture (long pointerId);
};
</pre>
<dl dfn-for="Element" link-for="Element">
<dt><dfn>ongotpointercapture</dfn></dt>
<dd>
The event handler IDL attribute (see [[!HTML5]]) for the <code>gotpointercapture</code> event type.
</dd>
<dt><dfn>onlostpointercapture</dfn></dt>
<dd>
The event handler IDL attribute (see [[!HTML5]]) for the <code>lostpointercapture</code> event type.
</dd>
<dt><dfn>setPointerCapture</dfn></dt>
<dd>
<p><a href="#setting-pointer-capture">Sets pointer capture</a> for the pointer identified by the argument <code>pointerId</code> to the element on which this method is invoked. Subsequent events for the pointer MUST always be targeted at this element until capture is released. The pointer MUST be in its <a>active buttons state</a> for this method to be effective, otherwise it fails silently. Throws a <code>DOMException</code> with the name <code>InvalidPointerId</code> when the provided method's argument does not match any of the <a data-lt="active pointer">active pointers</a>.</p>
<div class="note">See <a href="#dfn-pointer-capture" title="pointer capture">Pointer Capture</a>.</div>
</dd>
<dt><dfn>releasePointerCapture</dfn></dt>
<dd>
<p><a href="#releasing-pointer-capture">Releases pointer capture</a> for the pointer identified by the argument <code>pointerId</code> 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. Throws a <code>DOMException</code> with the name <code>InvalidPointerId</code> when the provided the method's argument does not match any of the <a data-lt="active pointer">active pointers</a>.</p>
<div class="note">See <a href="#dfn-pointer-capture" title="pointer capture">Pointer Capture</a>.</div>
</dd>
</dl>
</div>
</section>
<section>
<h2>Extensions to the <code>GlobalEventHandlers</code> interface</h2>
<div>
<p>The following section describes extensions to the existing <code>GlobalEventHandlers</code> interface, defined in [[!HTML5]], to facilitate the event handler registration.</p>
<pre class="idl">
partial interface GlobalEventHandlers {
attribute EventHandler onpointerdown;
attribute EventHandler onpointermove;
attribute EventHandler onpointerup;
attribute EventHandler onpointercancel;
attribute EventHandler onpointerover;
attribute EventHandler onpointerout;
attribute EventHandler onpointerenter;
attribute EventHandler onpointerleave;
};
</pre>
<dl dfn-for="GlobalEventHandlers" link-for="GlobalEventHandlers">
<dt><dfn>onpointerdown</dfn></dt>
<dd>
The event handler IDL attribute (see [[!HTML5]]) for the <code>pointerdown</code> event type.
</dd>
<dt><dfn>onpointermove</dfn></dt>
<dd>
The event handler IDL attribute (see [[!HTML5]]) for the <code>pointermove</code> event type.
</dd>
<dt><dfn>onpointerup</dfn></dt>
<dd>
The event handler IDL attribute (see [[!HTML5]]) for the <code>pointerup</code> event type.
</dd>
<dt><dfn>onpointercancel</dfn></dt>
<dd>
The event handler IDL attribute (see [[!HTML5]]) for the <code>pointercancel</code> event type.
</dd>
<dt><dfn>onpointerover</dfn></dt>
<dd>
The event handler IDL attribute (see [[!HTML5]]) for the <code>pointerover</code> event type.
</dd>
<dt><dfn>onpointerout</dfn></dt>
<dd>
The event handler IDL attribute (see [[!HTML5]]) for the <code>pointerout</code> event type.
</dd>
<dt><dfn>onpointerenter</dfn></dt>
<dd>
The event handler IDL attribute (see [[!HTML5]]) for the <code>pointerenter</code> event type.
</dd>
<dt><dfn>onpointerleave</dfn></dt>
<dd>
The event handler IDL attribute (see [[!HTML5]]) for the <code>pointerleave</code> event type.
</dd>
</dl>
</div>
</section>
<section>
<h2>Extensions to the <code>Navigator</code> interface</h2>
<div>
<p>The <code>Navigator</code> interface is defined in [[!HTML5]]. This specification extends the <code>Navigator</code> interface to provide device detection support.</p>
<pre class="idl">
partial interface Navigator {
readonly attribute long maxTouchPoints;
};
</pre>
<dl dfn-for="Navigator" link-for="Navigator">
<dt><dfn>maxTouchPoints</dfn></dt>
<dd><p>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.</p>
<p>For example, suppose a device has 3 touchscreens, which support 2, 5, and 10 simultaneous touch contacts, respectively. The value of <code>maxTouchPoints</code> should be <code>10</code>.</p>
</dd>
</dl>
<div class="note">While a <code>maxTouchPoints</code> value of greater than 0 indicates the user's device is capable of supporting touch input, it does not necessarily mean the user <i>will</i> use touch input. Authors should be careful to also consider other input modalities that could be present on the system, such as mouse, pen, screen readers, etc.</div>
<div class="note"><code>maxTouchPoints</code> 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 <code>maxTouchPoints</code>.</div>
</div>
</section>
<section>
<h1>Declaring candidate regions for default touch behaviors</h1>
<p>For touch input, the default action of any and all pointer events MUST NOT be a manipulation of the viewport (e.g. panning or zooming).</p>
<div class="note">Touch manipulations are intentionally not a default action of pointer events. Removing this dependency on the cancellation of events facilitates performance optimizations by the user agent.</div>
<section>
<h2>The <code>touch-action</code> CSS property</h2>
<table class="simple">
<tr><th>Name:</th><td><code>touch-action</code></td></tr>
<tr><th>Value:</th><td><code>auto</code> | <code>none</code> | [ [ <code>pan-x</code> | <code>pan-left</code> | <code>pan-right</code> ] || [ <code>pan-y</code> | <code>pan-up</code> | <code>pan-down</code> ] ] | <code>manipulation</code></td></tr>
<tr><th>Initial:</th><td><code>auto</code></td></tr>
<tr><th>Applies to:</th><td>all elements except: non-replaced inline elements, table rows, row groups, table columns, and column groups.</td></tr>
<tr><th>Inherited:</th><td>no</td></tr>
<tr><th>Percentages:</th><td>N/A</td></tr>
<tr><th>Media:</th><td>visual</td></tr>
<tr><th>Computed value:</th><td>Same as specified value.</td></tr>
</table>
<p>The <code>touch-action</code> CSS property determines whether touch input MAY trigger default behavior supplied by user agent. This includes, but is not limited to, behaviors such as panning or zooming.</p>
<p>When a user touches an element, the effect of that touch is determined by the value of the <code>touch-action</code> property and the default touch behaviors on the element and its ancestors. A touch behavior is supported if allowed by the <code>touch-action</code> properties of all elements between the hit tested element and it's nearest ancestor with the default touch behavior (including both the hit tested element and the element with the default touch behavior).</p>
<div class="note">Some user agents support touch actions triggered by interactions of multiple concurrent pointers (e.g. multi-touch). Methods for processing or associating the <code>touch-action</code> values of multiple concurrent pointers is out of scope for this specification.</div>
<p>During the execution of a user agent touch behavior, the user agent MUST NOT fire subsequent pointer events for the pointer. The user agent MUST <a href="#firing-events-using-the-pointerevent-interface">fire a pointer event</a> named <code>pointercancel</code> (and subsequently a <code>pointerout</code> event and one or more <code>pointerleave</code> events) whenever all of the following are true, in order to end the stream of events for the pointer:</p>
<ul>
<li>The user agent has determined (via methods out of scope for this specification) that touch input is to be consumed for a touch behavior,</li>
<li>a <code>pointerdown</code> event has been sent for the pointer, and</li>
<li>a <code>pointerup</code> or <code>pointercancel</code> event (following the above mentioned <code>pointerdown</code>) has not yet been sent for the pointer.</li>
</ul>
<div class="note">Once a touch action has been started, and the user agent has already determined whether or not the action should be handled as a user agent touch behavior, any changes to the relevant <code>touch-action</code> value will be ignored for the duration of the touch action. For instance, programmatically changing the <code>touch-action</code> value for an element from <code>auto</code> to <code>none</code> as part of a <code>pointerdown</code> handler script will not result in the user agent aborting or suppressing any default touch behavior for that touch for as long as that pointer is active.</div>
<p>Values have the following meanings:</p>
<dl>
<dt>auto</dt>
<dd>The user agent MAY determine any permitted touch behaviors, such as panning and zooming manipulations of the viewport, for touches that begin on the element.</dd>
<dt>none</dt>
<dd>Touches that begin on the element MUST NOT trigger default touch behaviors.</dd>
<dt>pan-x<br>pan-left<br>pan-right<br>pan-y<br>pan-up<br>pan-down</dt>
<dd>
<p>The user agent MAY consider touches that begin on the element only for the purposes of scrolling that starts in any of the directions specified by all of the listed values. Once scrolling is started, the direction may be reversed by the user even if scrolls that start in the reversed direction are disallowed. In contrast, when scrolling is restricted to starting along a single axis (eg. <code>pan-y</code>), the axis cannot be changed during the scroll.<p>
<p>In the case of <code>pan-left</code>, <code>pan-right</code>, <code>pan-up</code> and <code>pan-down</code>, the direction is interpreted as the opposite of the physical movement in the screen co-ordinate space. For example, <code>pan-up</code> always corresponds to input event sequences where typically (ignoring situations such as <code>iframe</code> containers with CSS rotation transforms) <code>screenY</code> is increasing (i.e. an interaction where the user moves a touch point down the screen).</p></dd>
<dt>manipulation</dt>
<dd>The user agent MAY consider touches that begin on the element only for the purposes of scrolling and continuous zooming. Any additional behaviors supported by <code>auto</code> are out of scope for this specification.</dd>
</dl>
<div class="note">The terms "pan" and "scroll" are considered synonymous. Defining an interaction or gesture for triggering panning or scrolling, or for triggering behavior for the <code>auto</code> or <code>none</code> values are out of scope for this specification.</div>
<div class="note">The <code>touch-action</code> property only applies to elements that support both the CSS <code>width</code> and <code>height</code> properties (see [[CSS21]]). This restriction is designed to facilitate user agent optimizations for <span>low-latency</span> touch actions. For elements not supported by default, such as <code><span></code> which is a <span>non-replaced inline element</span> (see [[HTML5]]), authors can set the <code>display</code> CSS property to a value, such as <code>block</code>, that supports <code>width</code> and <code>height</code>. Future specifications could extend this API to all elements.</div>
<div class="note">
<p>The direction-specific pan values are useful for customizing overscroll behavior. For example, to implement a simple pull-to-refresh effect the document's touch-action can be set to <code>pan-x pan-down</code> whenever the scroll position is 0 and <code>pan-x pan-y</code> otherwise. This allows pointer event handlers to define the behavior for upward scrolls that start from the top of the document.</p>
<p>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 <code>pan-y</code> to ensure it receives pointer events for any horizontal pan operations without interfering with vertical scrolling of the document. When the carousel reaches its right-most extent, it may change its touch-action to <code>pan-y pan-right</code> so that a subsequent pan operation beyond it's extent can scroll the document within the viewport if possible. It's not possible to change the behavior of a pan in the middle of an operation.</p>
</div>
<div class="note">Disabling some default touch behaviors may allow user agents to respond to other behaviors more quickly. For example, with <code>auto</code> user agents typically add 300ms of delay before <code>click</code> to allow for double-tap gestures to be handled. In these cases, explicitly setting <code>touch-action: none</code> or <code>touch-action: manipulation</code> will remove this delay. Note that the methods for determining a tap or double-tap gesture are out of scope for this specification.</div>
<pre id="example_5" class="example" title="Disallowing all touch behaviors">
<div style="touch-action: none;">
This element receives pointer events for all touches.
</div>
</pre>
<pre id="example_6" class="example" title="Allowing horizontal panning only">
<div style="touch-action: pan-x;">
This element receives pointer events when not panning in the horizontal direction.
</div>
</pre>
<pre id="example_7" class="example" title="Child regions that disallow touch behaviors">
<div style="overflow: auto;">
<div style="touch-action: none;">
This element receives pointer events for all touches.
</div>
<div>
Touches on this element MAY be consumed for manipulating the parent.
</div>
</div>
</pre>
<pre id="example_8" class="example" title="Intermediate parent that disallows touch behaviors">
<div style="overflow: auto;">
<div style="touch-action: pan-y;">
<div style="touch-action: pan-x;">
This element receives pointer events for all touches because
it allows only horizontal panning yet an intermediate ancestor
(between it and the pannable element) only allows vertical panning.
Therefore, no touch behaviors are allowed.
</div>
</div>
</div>
</pre>
<pre id="example_9" class="example" title="Intermediate parent that restricts allowed touch behaviors">
<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>
</pre>
</section>
</section>
<section class="informative">
<h1><dfn>Pointer Capture</dfn></h1>
<p>Pointer capture allows the events for a particular pointer (including any <a data-lt="compatibility mapping with mouse events">compatibility mouse events</a>) 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 [[HTML5]] <code><input type="range"></code> 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.</p>
<figure id="figure_slider">
<img src="slider.png" alt="Custom Volume Slider">
<figcaption>Example of a custom slider control that chooses a value by sliding the thumb element back and forth. After <code>pointerdown</code> on the thumb, pointer capture can be used to allow the user to slide the thumb even if the pointer drifts off of it.</figcaption>
</figure>
<section>
<h2>Setting Pointer Capture</h2>
<p>Pointer capture is set on an element by calling the <code>element.setPointerCapture(pointerId)</code> method. When this method is invoked, a user agent MUST run the following steps:</p>
<ol>
<li>If the <code>pointerId</code> provided as the method's argument does not match any of the <a data-lt="active pointer">active pointers</a>, then throw a <code>DOMException</code> with the name <code>InvalidPointerId</code>.</li>
<li>If the <code>Element</code> on which this method is invoked does not participate in its <code>ownerDocument</code>'s tree, throw an exception with the name <code>InvalidStateError</code>.</li>
<li>If the pointer is not in the <a>active buttons state</a>, then terminate these steps.</li>
<li>For the specified <code>pointerId</code>, set the <dfn>pending pointer capture target override</dfn> to the <code>Element</code> on which this method was invoked.</li>
</ol>
<div class="note">When pointer capture is set, <code>pointerover</code>, <code>pointerout</code>, <code>pointerenter</code>, and <code>pointerleave</code> events are only generated when crossing the boundary of the element that has capture as other elements can no longer be targeted by the pointer. This has the effect of suppressing these events on all other elements.</div>
</section>
<section>
<h2>Releasing Pointer Capture</h2>
<p>Pointer capture is released on an element explicitly by calling the <code>element.releasePointerCapture(pointerId)</code> method. When this method is called, a user agent MUST run the following steps:</p>
<ol>
<li>If the <code>pointerId</code> provided as the method's argument does not match any of the <a data-lt="active pointer">active pointers</a> and these steps are not being invoked as a result of the <a href="#implicit-release-of-pointer-capture">implicit release of pointer capture</a>, then throw a <code>DOMException</code> with the name <code>InvalidPointerId</code>.</li>
<li>If pointer capture is not currently set for the specified pointer, then terminate these steps.</li>
<li>If the <a>pointer capture target override</a> for the specified <code>pointerId</code> is not the <code>Element</code> on which this method was invoked, then terminate these steps.</li>
<li>For the specified <code>pointerId</code>, clear the <a>pending pointer capture target override</a>, if set.</li>
</ol>
</section>
<section>
<h2>Implicit Pointer Capture</h2>
<div class="note">Some user agents implement their own implicit pointer capture behavior - for instance, for touch interactions, a user agent could automatically capture the pointer as part of an interaction on a form control (such as a button) to improve user interaction (allowing some finger movement to stray outside of the form control itself during the interaction). As part of this behavior, user agents typically fire <code>gotpointercapture</code> and <code>lostpointercapture</code> events, even though no explicit pointer capture functions (<code>setPointerCapture</code> and <code>releasePointerCapture</code>) were called.</div>
<section>
<h3>Implicit Release of Pointer Capture</h3>
<p>Immediately after firing the <code>pointerup</code> or <code>pointercancel</code> events, a user agent MUST run the steps as if the <code>releasePointerCapture()</code> method has been called with an argument equal to the <code>pointerId</code> property of the <code>pointerup</code> or <code>pointercancel</code> event just dispatched.</p>
<p>When the <a>pointer capture target override</a> is removed from its <code>ownerDocument</code>'s tree, clear the <a>pending pointer capture target override</a> and <a>pointer capture target override</a> nodes and fire a PointerEvent named <code>lostpointercapture</code> at the document.</p>
</section>
</section>
</section>
<section>
<h1><dfn lt="compatibility mouse events">Compatibility Mapping with Mouse Events</dfn></h1>
<p>The vast majority of web content existing today codes only to Mouse Events. The following describes an algorithm for how a user agent MAY map generic pointer input to mouse events for compatibility with this content.</p>
<p>The compatibility mapping with mouse events are an OPTIONAL feature of this specification. User agents are encouraged to support the feature for best compatibility with existing legacy content. User agents that do not support compatibility mouse events are still encouraged to support the <code>click</code> and <code>contextmenu</code> events (see the note below).</p>
<div class="note">
<p>The <code>click</code> event, defined in [[DOM-LEVEL-3-EVENTS]], and the <code>contextmenu</code> event, defined in [[HTML5]], are not considered <a title="compatibility mouse events" href="#dfn-compatibility-mouse-events">compatibility mouse events</a> as they are typically tied to user interface activation and are fired from other input devices, like keyboards.</p>
<p>In user agents that support firing <code>click</code> and/or <code>contextmenu</code>, calling <code>preventDefault</code> during a pointer event typically does not have an effect on whether <code>click</code> and/or <code>contextmenu</code> are fired or not. Because they are not compatibility mouse events, user agents typically fire <code>click</code> and <code>contextmenu</code> for all pointing devices, including pointers that are not primary pointers.</p>
<p>The relative ordering of these high-level events (<code>click</code>, <code>contextmenu</code>, <code>focus</code>, <code>blur</code>, etc.) with pointer events is undefined and varies between user agents. For example, in some user agents <code>contextmenu</code> will often follow a <code>pointerup</code>, in others it'll often precede a <code>pointerup</code> or <code>pointercancel</code>, and in some situations it may be fired without any corresponding pointer event (such as a keyboard shortcut).</p>
</div>
<p>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 <code>ownerDocument</code>'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 <code>ownerDocument</code>'s tree, meaning that a new event path (based on the new target node) is built for the mouse event.</p>
<p>Authors can prevent the production of certain compatibility mouse events by canceling the <code>pointerdown</code> event. </p>
<div class="note">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. And, the <code>mouseover</code>, <code>mouseout</code>, <code>mouseenter</code>, and <code>mouseleave</code> events are never prevented (even if the pointer is down).</div>
<section>
<h2><dfn>Tracking the effective position of the legacy mouse pointer</dfn></h2>
<p>While only the <a data-lt="Primary Pointer">primary pointers</a> can produce compatibility mouse events, <a href="#multiple-primary-pointers">multiple primary pointers</a> can be active simultaneously, each producing its own compatibility mouse events. Since all these compatibility events would appear to MouseEvent code to be coming from a single mouse device, user agents are encouraged to guarantee that the compatibility mouse events are consistent from a single device perspective. For mouse transition events (i.e., <code>mouseover</code>, <code>mouseout</code>, <code>mouseenter</code> and <code>mouseleave</code>), this means the entry/exit state for every event target is valid as implied by [[!DOM-LEVEL-3-EVENTS]]. Users agents SHOULD guarantee this by maintaining the <dfn>effective position of the legacy mouse pointer</dfn> in the document as follows.</p>
<p>Right before firing a <code>pointerdown</code>, <code>pointerup</code> or <code>pointermove</code> event, or a <code>pointerleave</code> event at the <code>window</code>, the user agent SHOULD run the following steps:</p>
<ol>
<li>Let <code>T</code> be the target of the <code>pointerdown</code>, <code>pointerup</code> or <code>pointermove</code> event being dispatched. For the <code>pointerleave</code> event, unset <code>T</code>.</li>
<li>If <code>T</code> and current <a data-lt="effective position of the legacy mouse pointer">effective legacy mouse pointer position</a> are both unset or they are uqual, terminate these steps.</li>
<li>Dispatch <code>mouseover</code>, <code>mouseout</code>, <code>mouseenter</code> and <code>mouseleave</code> events as per [[!DOM-LEVEL-3-EVENTS]] for a mouse moving from the current <a data-lt="effective position of the legacy mouse pointer">effective legacy mouse pointer position</a> to <code>T</code>. Consider an unset value of either current <a data-lt="effective position of the legacy mouse pointer">effective legacy mouse pointer position</a> or <code>T</code> as an out-of-window mouse position.</li>
<li>Set <a data-lt="effective position of the legacy mouse pointer">effective legacy mouse pointer position</a> to <code>T</code>.</li>
</ol>
</section>
<section>
<h2>Mapping for devices that support hover</h2>
<p>Whenever a user agent is to dispatch a pointer event for a device that supports hover, it SHOULD run the following steps:</p>
<ol>
<li>If the <code>isPrimary</code> property for the pointer event to be dispatched is <code>false</code> then dispatch the pointer event and terminate these steps.</li>
<li>If the pointer event to be is dispatched is <code>pointerdown</code>, <code>pointerup</code> or <code>pointermove</code>, dispatch compatibility mouse transition events as described in <a>Tracking the effective position of the legacy mouse pointer</a>.</li>
<li>Dispatch the pointer event.</li>
<li>If the pointer event dispatched was <code>pointerdown</code> and the event was <a data-lt="canceled event">canceled</a>, then set the <i>PREVENT MOUSE EVENT</i> flag for this <code>pointerType</code>.</li>
<li>If the <i>PREVENT MOUSE EVENT</i> flag is <b>not</b> set for this <code>pointerType</code> and the pointer event dispatched was:
<ul>
<li><code>pointerdown</code>, then fire a <code>mousedown</code> event.</li>
<li><code>pointermove</code>, then fire a <code>mousemove</code> event.</li>
<li><code>pointerup</code>, then fire a <code>mouseup</code> event.</li>
<li><code>pointercancel</code>, then fire a <code>mouseup</code> event at the <code>window</code>.</li>
</ul>
</li>
<li>If the pointer event dispatched was <code>pointerup</code> or <code>pointercancel</code>, clear the <i>PREVENT MOUSE EVENT</i> flag for this <code>pointerType</code>.</li>
</ol>
</section>
<section>
<h2>Mapping for devices that do not support hover</h2>
<p>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:</p>
<ul>
<li>The input can hover independently of activation (e.g. moving a mouse cursor without any buttons pressed).</li>
<li>The input will likely produce the <code>mousemove</code> event on an element before clicking it.</li>
</ul>
<div class="note">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 <a href=#mapping-for-devices-that-do-not-support-hover>devices that do not support hover</a>. 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.</div>
<p>This requires that user agents provide a different mapping for these types of input devices. Whenever a user agent is to dispatch a pointer event for a device that <a href=#mapping-for-devices-that-do-not-support-hover>does not support hover</a>, it SHOULD run the following steps:</p>
<ol>
<li>If the <code>isPrimary</code> property for the pointer event to be dispatched is <code>false</code> then dispatch the pointer event and terminate these steps.</li>
<li>If the pointer event to be dispatched is <code>pointerover</code> and the <code>pointerdown</code> event has not yet been dispatched for this pointer, then fire a <code>mousemove</code> event (for compatibility with legacy mouse-specific code).</li>
<li>If the pointer event to be is dispatched is <code>pointerdown</code>, <code>pointerup</code> or <code>pointermove</code>, dispatch compatibility mouse transition events as described in <a>Tracking the effective position of the legacy mouse pointer</a>.</li>
<li>Dispatch the pointer event.</li>
<li>If the pointer event dispatched was <code>pointerdown</code> and the event was <a data-lt="canceled event">canceled</a>, then set the <i>PREVENT MOUSE EVENT</i> flag for this <code>pointerType</code>.</li>
<li>If the <i>PREVENT MOUSE EVENT</i> flag is <b>not</b> set for this <code>pointerType</code> and the pointer event dispatched was:
<ul>
<li><code>pointerdown</code>, then fire a <code>mousedown</code> event.</li>
<li><code>pointermove</code>, then fire a <code>mousemove</code> event.</li>
<li><code>pointerup</code>, then fire a <code>mouseup</code> event.</li>
<li><code>pointercancel</code>, then fire a <code>mouseup</code> event at the <code>window</code>.</li>
</ul>
</li>
<li>If the pointer event dispatched was <code>pointerup</code> or <code>pointercancel</code>, clear the <i>PREVENT MOUSE EVENT</i> flag for this <code>pointerType</code>.</li>
</ol>
<div class="note">
<p>The activation of an element (<code>click</code>) with a primary pointer that <a href=#mapping-for-devices-that-do-not-support-hover>does not support hover</a> (e.g. single finger on a touchscreen) would typically produce the following event sequence:</p>
<ol data-class="note-list">
<li><code>mousemove</code></li>
<li><code>pointerover</code></li>
<li><code>mouseover</code></li>
<li><code>pointerenter</code></li>
<li><code>mouseenter</code></li>
<li><code>pointerdown</code></li>
<li><code>mousedown</code></li>
<li>Zero or more <code>pointermove</code> and <code>mousemove</code> events, depending on movement of the pointer</li>
<li><code>pointerup</code></li>
<li><code>mouseup</code></li>
<li><code>click</code></li>
<li><code>pointerout</code></li>
<li><code>mouseout</code></li>
<li><code>pointerleave</code></li>
<li><code>mouseleave</code></li>
</ol>
<p>If, however, the <code>pointerdown</code> event is <a data-lt="canceled event">canceled</a> during this interaction then the sequence of events would be:</p>
<ol data-class="note-list">
<li><code>mousemove</code></li>
<li><code>pointerover</code></li>
<li><code>mouseover</code></li>
<li><code>pointerenter</code></li>
<li><code>mouseenter</code></li>
<li><code>pointerdown</code></li>
<li>Zero or more <code>pointermove</code> events, depending on movement of the pointer</li>
<li><code>pointerup</code></li>
<li><code>click</code></li>
<li><code>pointerout</code></li>
<li><code>mouseout</code></li>
<li><code>pointerleave</code></li>
<li><code>mouseleave</code></li>
</ol>
</div>
</section>
</section>
<section class="appendix">
<h1>Acknowledgments</h1>
<p>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 group members:
Arthur Barstow,
Matt Brubeck,
Rick Byers,
Cathy Chan,
Scott González,
Patrick H. Lauke,
Sangwhan Moon,
Olli Pettay,
Jacob Rossi,
Doug Schepers and
Asir Vedamuthu.
</p>
<p>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.</p>
</section>
<section class="appendix informative">
<h1>Revision History</h1>
<p>The following is an informative summary of substantial and major editorial changes between publications of this specification, relative to the first [[PointerEvents]] specification. See the <a href="https://github.com/w3c/pointerevents/commits">complete revision history of the Editor's Drafts of this specification</a>.</p>
<h3>Changes since the 24 February 2015 Recommendation</h3>
<ul>
<li><a href="https://github.com/w3c/pointerevents/pull/96">Removed "pen contact" condition on button/buttons</a></li>
<li><a href="https://github.com/w3c/pointerevents/pull/92">Make all pointer events composed events</a></li>
<li><a href="https://github.com/w3c/pointerevents/pull/87">Add digitizer/pen tangential (barrel) pressure</a></li>
<li><a href="https://github.com/w3c/pointerevents/pull/79">Add digitizer/pen twist</a></li>
<li><a href="https://github.com/w3c/pointerevents/pull/69">Make width/height default to 1, remove UA "guessing"/faking geometry</a></li>
<li><a href="https://github.com/w3c/pointerevents/pull/56">Made mouseover/out/enter/leave event firing independent of corresponding PEs</a></li>
<li><a href="https://github.com/w3c/pointerevents/pull/53">Rewrite of primary pointer section</a> to simplify the wording and allow for possibility of multiple mouse input devices</li>
<li><a href="https://github.com/w3c/pointerevents/pull/50">Cover the case when primary pointer is removed</a></li>
<li><a href="https://github.com/w3c/pointerevents/pull/43">Clarification about dynamic touch-action changes</a></li>
<li><a href="https://github.com/w3c/pointerevents/pull/36">Add the missing pointerover/enter events</a> to the "Process Pending Pointer Capture" section</li>
<li><a href="https://github.com/w3c/pointerevents/pull/34">Clarify the button value for mouse drag</a></li>
<li><a href="https://github.com/w3c/pointerevents/pull/24">Fix the touch-action processing model for zoom scenarios</a></li>