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="http://msdn.microsoft.com/en-us/library/ie/hh772103.aspx">MSDN</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 String pointerType_ = "";
52      private boolean isPrimary_;
53  
54      /**
55       * Default constructor.
56       */
57      public PointerEvent() {
58          super();
59      }
60  
61      /**
62       * JavaScript constructor.
63       * @param cx the current context
64       * @param scope the scope
65       * @param args the arguments to the WebSocket constructor
66       * @param ctorObj the function object
67       * @param inNewExpr Is new or not
68       * @return the java object to allow JavaScript to access
69       */
70      @JsxConstructor
71      public static Scriptable jsConstructor(final Context cx, final VarScope scope,
72              final Object[] args, final Function ctorObj, final boolean inNewExpr) {
73          final PointerEvent event = new PointerEvent();
74  
75          event.setBubbles(false);
76          event.setCancelable(false);
77  
78          if (args.length != 0) {
79              event.setType(JavaScriptEngine.toString(args[0]));
80              event.width_ = 1;
81              event.height_ = 1;
82          }
83  
84          if (args.length > 1) {
85              final NativeObject object = (NativeObject) args[1];
86              event.setBubbles((boolean) getValue(object, "bubbles", event.isBubbles()));
87  
88              event.pointerId_ = (int) getValue(object, "pointerId", event.pointerId_);
89              event.width_ = (int) getValue(object, "width", event.width_);
90              event.height_ = (int) getValue(object, "height", event.height_);
91              event.pressure_ = (double) getValue(object, "pressure", event.pressure_);
92              event.tiltX_ = (int) getValue(object, "tiltX", event.tiltX_);
93              event.tiltY_ = (int) getValue(object, "tiltY", event.tiltY_);
94              event.pointerType_ = (String) getValue(object, "pointerType", event.pointerType_);
95              event.isPrimary_ = (boolean) getValue(object, "isPrimary", event.isPrimary_);
96          }
97          return event;
98      }
99  
100     private static Object getValue(final ScriptableObject object, final String name, final Object defaulValue) {
101         Object value = object.get(name);
102         if (value == null) {
103             value = defaulValue;
104         }
105         else {
106             if (defaulValue instanceof String) {
107                 value = String.valueOf(value);
108             }
109             else if (defaulValue instanceof Double) {
110                 value = JavaScriptEngine.toNumber(value);
111             }
112             else if (defaulValue instanceof Number) {
113                 value = (int) JavaScriptEngine.toNumber(value);
114             }
115             else {
116                 value = JavaScriptEngine.toBoolean(value);
117             }
118         }
119         return value;
120     }
121 
122     /**
123      * Creates a new event instance.
124      *
125      * @param domNode the DOM node that triggered the event
126      * @param type the event type
127      * @param shiftKey true if SHIFT is pressed
128      * @param ctrlKey true if CTRL is pressed
129      * @param altKey true if ALT is pressed
130      * @param detail the detail value
131      * @param button the button code, must be {@link #BUTTON_LEFT}, {@link #BUTTON_MIDDLE} or {@link #BUTTON_RIGHT}
132      */
133     public PointerEvent(final DomNode domNode, final String type, final boolean shiftKey,
134             final boolean ctrlKey, final boolean altKey, final int button, final int detail) {
135         super(domNode, type, shiftKey, ctrlKey, altKey, button, detail);
136 
137         pointerId_ = 1;
138         width_ = 1;
139         height_ = 1;
140         pointerType_ = "mouse";
141         isPrimary_ = true;
142     }
143 
144     /**
145      * @return the pointerId
146      */
147     @JsxGetter
148     public long getPointerId() {
149         return pointerId_;
150     }
151 
152     /**
153      * @return the width
154      */
155     @JsxGetter
156     public long getWidth() {
157         return width_;
158     }
159 
160     /**
161      * @return the height
162      */
163     @JsxGetter
164     public long getHeight() {
165         return height_;
166     }
167 
168     /**
169      * @return the pressure
170      */
171     @JsxGetter
172     public double getPressure() {
173         return pressure_;
174     }
175 
176     /**
177      * @return the tiltX
178      */
179     @JsxGetter
180     public long getTiltX() {
181         return tiltX_;
182     }
183 
184     /**
185      * @return the tiltY
186      */
187     @JsxGetter
188     public long getTiltY() {
189         return tiltY_;
190     }
191 
192     /**
193      * @return the pointerType
194      */
195     @JsxGetter
196     public String getPointerType() {
197         return pointerType_;
198     }
199 
200     /**
201      * @return the isPrimary
202      */
203     @JsxGetter(propertyName = "isPrimary")
204     public boolean isPrimary_js() {
205         return isPrimary_;
206     }
207 
208     /**
209      * @return the pointerType
210      */
211     @JsxGetter
212     @SuppressWarnings("PMD.UseUnderscoresInNumericLiterals")
213     public double getAltitudeAngle() {
214         return 1.5707963267948966;
215     }
216 
217     /**
218      * @return the pointerType
219      */
220     @JsxGetter
221     public double getAzimuthAngle() {
222         return 0d;
223     }
224 
225     /**
226      * @return the persistentDeviceId
227      */
228     @JsxGetter({CHROME, EDGE, FF})
229     public double getPersistentDeviceId() {
230         // dummy but valid regarding the spec
231         // https://w3c.github.io/pointerevents/#dom-pointerevent-persistentdeviceid
232         return 0d;
233     }
234 }