View Javadoc
1   /*
2    * Copyright (c) 2002-2026 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript.host.event;
16  
17  import static org.htmlunit.javascript.configuration.SupportedBrowser.CHROME;
18  import static org.htmlunit.javascript.configuration.SupportedBrowser.EDGE;
19  import static org.htmlunit.javascript.configuration.SupportedBrowser.FF;
20  
21  import org.htmlunit.corejs.javascript.Context;
22  import org.htmlunit.corejs.javascript.Function;
23  import org.htmlunit.corejs.javascript.NativeObject;
24  import org.htmlunit.corejs.javascript.Scriptable;
25  import org.htmlunit.corejs.javascript.ScriptableObject;
26  import org.htmlunit.corejs.javascript.VarScope;
27  import org.htmlunit.html.DomNode;
28  import org.htmlunit.javascript.JavaScriptEngine;
29  import org.htmlunit.javascript.configuration.JsxClass;
30  import org.htmlunit.javascript.configuration.JsxConstructor;
31  import org.htmlunit.javascript.configuration.JsxGetter;
32  
33  /**
34   * JavaScript object representing a {@code PointerEvent}.
35   * @see <a href="http://www.w3.org/TR/pointerevents/">W3C Spec</a>
36   * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent">MDN</a>
37   *
38   * @author Frank Danek
39   * @author Ahmed Ashour
40   * @author Ronald Brill
41   */
42  @JsxClass
43  public class PointerEvent extends MouseEvent {
44  
45      private int pointerId_;
46      private int width_;
47      private int height_;
48      private double pressure_;
49      private int tiltX_;
50      private int tiltY_;
51      private double altitudeAngle_;
52      private double azimuthAngle_;
53      private String pointerType_ = "";
54      private boolean isPrimary_;
55  
56      /**
57       * Default constructor.
58       */
59      public PointerEvent() {
60          super();
61      }
62  
63      /**
64       * JavaScript constructor.
65       * @param cx the current context
66       * @param scope the scope
67       * @param args the arguments to the WebSocket constructor
68       * @param ctorObj the function object
69       * @param inNewExpr Is new or not
70       * @return the java object to allow JavaScript to access
71       */
72      @JsxConstructor
73      public static Scriptable jsConstructor(final Context cx, final VarScope scope,
74              final Object[] args, final Function ctorObj, final boolean inNewExpr) {
75          final PointerEvent event = new PointerEvent();
76  
77          event.setBubbles(false);
78          event.setCancelable(false);
79  
80          event.altitudeAngle_ = Math.PI / 2d;
81  
82          if (args.length != 0) {
83              event.setType(JavaScriptEngine.toString(args[0]));
84              event.width_ = 1;
85              event.height_ = 1;
86          }
87  
88          if (args.length > 1) {
89              final NativeObject object = (NativeObject) args[1];
90              event.setBubbles((boolean) getValue(object, "bubbles", event.isBubbles()));
91  
92              event.pointerId_ = (int) getValue(object, "pointerId", event.pointerId_);
93              event.width_ = (int) getValue(object, "width", event.width_);
94              event.height_ = (int) getValue(object, "height", event.height_);
95              event.pressure_ = (double) getValue(object, "pressure", event.pressure_);
96              event.tiltX_ = (int) getValue(object, "tiltX", event.tiltX_);
97              event.tiltY_ = (int) getValue(object, "tiltY", event.tiltY_);
98              event.pointerType_ = (String) getValue(object, "pointerType", event.pointerType_);
99              event.isPrimary_ = (boolean) getValue(object, "isPrimary", event.isPrimary_);
100 
101             if (object.has("tiltX", object) || object.has("tiltY", object)) {
102                 event.altitudeAngle_ = 1.4105561004354874;
103                 event.azimuthAngle_ = 0.8628261898537035;
104             }
105         }
106         return event;
107     }
108 
109     private static Object getValue(final ScriptableObject object, final String name, final Object defaulValue) {
110         Object value = object.get(name);
111         if (value == null) {
112             value = defaulValue;
113         }
114         else {
115             if (defaulValue instanceof String) {
116                 value = String.valueOf(value);
117             }
118             else if (defaulValue instanceof Double) {
119                 value = JavaScriptEngine.toNumber(value);
120             }
121             else if (defaulValue instanceof Number) {
122                 value = (int) JavaScriptEngine.toNumber(value);
123             }
124             else {
125                 value = JavaScriptEngine.toBoolean(value);
126             }
127         }
128         return value;
129     }
130 
131     /**
132      * Creates a new event instance.
133      *
134      * @param domNode the DOM node that triggered the event
135      * @param type the event type
136      * @param shiftKey true if SHIFT is pressed
137      * @param ctrlKey true if CTRL is pressed
138      * @param altKey true if ALT is pressed
139      * @param detail the detail value
140      * @param button the button code, must be {@link #BUTTON_LEFT}, {@link #BUTTON_MIDDLE} or {@link #BUTTON_RIGHT}
141      */
142     public PointerEvent(final DomNode domNode, final String type, final boolean shiftKey,
143             final boolean ctrlKey, final boolean altKey, final int button, final int detail) {
144         super(domNode, type, shiftKey, ctrlKey, altKey, button, detail);
145 
146         pointerId_ = 1;
147         width_ = 1;
148         height_ = 1;
149         pointerType_ = "mouse";
150         isPrimary_ = true;
151     }
152 
153     /**
154      * Returns the pointer identifier.
155      *
156      * @return the pointer identifier
157      */
158     @JsxGetter
159     public long getPointerId() {
160         return pointerId_;
161     }
162 
163     /**
164      * Returns the pointer contact width.
165      *
166      * @return the pointer contact width
167      */
168     @JsxGetter
169     public long getWidth() {
170         return width_;
171     }
172 
173     /**
174      * Returns the pointer contact height.
175      *
176      * @return the pointer contact height
177      */
178     @JsxGetter
179     public long getHeight() {
180         return height_;
181     }
182 
183     /**
184      * Returns the normalized pointer pressure.
185      *
186      * @return the normalized pointer pressure
187      */
188     @JsxGetter
189     public double getPressure() {
190         return pressure_;
191     }
192 
193     /**
194      * Returns the pointer tilt along the X axis.
195      *
196      * @return the pointer tilt along the X axis
197      */
198     @JsxGetter
199     public long getTiltX() {
200         return tiltX_;
201     }
202 
203     /**
204      * Returns the pointer tilt along the Y axis.
205      *
206      * @return the pointer tilt along the Y axis
207      */
208     @JsxGetter
209     public long getTiltY() {
210         return tiltY_;
211     }
212 
213     /**
214      * Returns the pointer type.
215      *
216      * @return the pointer type
217      */
218     @JsxGetter
219     public String getPointerType() {
220         return pointerType_;
221     }
222 
223     /**
224      * Returns whether this is the primary pointer.
225      *
226      * @return whether this is the primary pointer
227      */
228     @JsxGetter(propertyName = "isPrimary")
229     public boolean isPrimary_js() {
230         return isPrimary_;
231     }
232 
233     /**
234      * Returns the pointer altitude angle.
235      *
236      * @return the pointer altitude angle
237      */
238     @JsxGetter
239     @SuppressWarnings("PMD.UseUnderscoresInNumericLiterals")
240     public double getAltitudeAngle() {
241         return altitudeAngle_;
242     }
243 
244     /**
245      * Returns the pointer azimuth angle.
246      *
247      * @return the pointer azimuth angle
248      */
249     @JsxGetter
250     public double getAzimuthAngle() {
251         return azimuthAngle_;
252     }
253 
254     /**
255      * Returns the persistent device identifier.
256      *
257      * @return the persistent device identifier
258      */
259     @JsxGetter({CHROME, EDGE, FF})
260     public double getPersistentDeviceId() {
261         // dummy but valid regarding the spec
262         // https://w3c.github.io/pointerevents/#dom-pointerevent-persistentdeviceid
263         return 0d;
264     }
265 }