"Fossies" - the Fresh Open Source Software Archive 
Member "selenium-selenium-4.8.1/dotnet/src/webdriver/Interactions/PointerInputDevice.cs" (17 Feb 2023, 24987 Bytes) of package /linux/www/selenium-selenium-4.8.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C# source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "PointerInputDevice.cs" see the
Fossies "Dox" file reference documentation.
1 // <copyright file="PointerInputDevice.cs" company="WebDriver Committers">
2 // Licensed to the Software Freedom Conservancy (SFC) under one
3 // or more contributor license agreements. See the NOTICE file
4 // distributed with this work for additional information
5 // regarding copyright ownership. The SFC licenses this file
6 // to you under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 // You may obtain a copy of the License at
9 //
10 // http://www.apache.org/licenses/LICENSE-2.0
11 //
12 // Unless required by applicable law or agreed to in writing, software
13 // distributed under the License is distributed on an "AS IS" BASIS,
14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 // See the License for the specific language governing permissions and
16 // limitations under the License.
17 // </copyright>
18
19 using System;
20 using System.Collections.Generic;
21 using System.Globalization;
22 using System.Linq;
23 using System.Text;
24 using OpenQA.Selenium.Internal;
25 using OpenQA.Selenium.Remote;
26
27 namespace OpenQA.Selenium.Interactions
28 {
29 /// <summary>
30 /// Represents the origin of the coordinates for mouse movement.
31 /// </summary>
32 public enum CoordinateOrigin
33 {
34 /// <summary>
35 /// The coordinate origin is the origin of the view port of the browser.
36 /// </summary>
37 Viewport,
38
39 /// <summary>
40 /// The origin of the movement is the most recent pointer location.
41 /// </summary>
42 Pointer,
43
44 /// <summary>
45 /// The origin of the movement is the center of the element specified.
46 /// </summary>
47 Element
48 }
49
50 /// <summary>
51 /// Specifies the type of pointer a pointer device represents.
52 /// </summary>
53 public enum PointerKind
54 {
55 /// <summary>
56 /// The pointer device is a mouse.
57 /// </summary>
58 Mouse,
59
60 /// <summary>
61 /// The pointer device is a pen or stylus.
62 /// </summary>
63 Pen,
64
65 /// <summary>
66 /// The pointer device is a touch screen device.
67 /// </summary>
68 Touch
69 }
70
71 /// <summary>
72 /// Specifies the button used during a pointer down or up action.
73 /// </summary>
74 public enum MouseButton
75 {
76 /// <summary>
77 /// This button is used for signifying touch actions.
78 /// </summary>
79 Touch = 0,
80
81 /// <summary>
82 /// The button used is the primary button.
83 /// </summary>
84 Left = 0,
85
86 /// <summary>
87 /// The button used is the middle button or mouse wheel.
88 /// </summary>
89 Middle = 1,
90
91 /// <summary>
92 /// The button used is the secondary button.
93 /// </summary>
94 Right = 2,
95
96 /// <summary>
97 /// The X1 button used for navigating back.
98 /// </summary>
99 Back = 3,
100
101 /// <summary>
102 /// The X2 button used for navigating forward.
103 /// </summary>
104 Forward = 4,
105 }
106
107 /// <summary>
108 /// Represents a pointer input device, such as a stylus, mouse, or finger on a touch screen.
109 /// </summary>
110 public class PointerInputDevice : InputDevice
111 {
112 private PointerKind pointerKind;
113
114 /// <summary>
115 /// Initializes a new instance of the <see cref="PointerInputDevice"/> class.
116 /// </summary>
117 public PointerInputDevice()
118 : this(PointerKind.Mouse)
119 {
120 }
121
122 /// <summary>
123 /// Initializes a new instance of the <see cref="PointerInputDevice"/> class.
124 /// </summary>
125 /// <param name="pointerKind">The kind of pointer represented by this input device.</param>
126 public PointerInputDevice(PointerKind pointerKind)
127 : this(pointerKind, Guid.NewGuid().ToString())
128 {
129 }
130
131 /// <summary>
132 /// Initializes a new instance of the <see cref="PointerInputDevice"/> class.
133 /// </summary>
134 /// <param name="pointerKind">The kind of pointer represented by this input device.</param>
135 /// <param name="deviceName">The unique name for this input device.</param>
136 public PointerInputDevice(PointerKind pointerKind, string deviceName)
137 : base(deviceName)
138 {
139 this.pointerKind = pointerKind;
140 }
141
142 /// <summary>
143 /// Gets the type of device for this input device.
144 /// </summary>
145 public override InputDeviceKind DeviceKind
146 {
147 get { return InputDeviceKind.Pointer; }
148 }
149
150 /// <summary>
151 /// Returns a value for this input device that can be transmitted across the wire to a remote end.
152 /// </summary>
153 /// <returns>A <see cref="Dictionary{TKey, TValue}"/> representing this action.</returns>
154 public override Dictionary<string, object> ToDictionary()
155 {
156 Dictionary<string, object> toReturn = new Dictionary<string, object>();
157
158 toReturn["type"] = "pointer";
159 toReturn["id"] = this.DeviceName;
160
161 Dictionary<string, object> parameters = new Dictionary<string, object>();
162 parameters["pointerType"] = this.pointerKind.ToString().ToLowerInvariant();
163 toReturn["parameters"] = parameters;
164
165 return toReturn;
166 }
167
168 /// <summary>
169 /// Creates a pointer down action.
170 /// </summary>
171 /// <param name="button">The button of the pointer that should be pressed.</param>
172 /// <returns>The action representing the pointer down gesture.</returns>
173 public Interaction CreatePointerDown(MouseButton button)
174 {
175 return CreatePointerDown(button, new PointerEventProperties());
176 }
177
178 /// <summary>
179 /// Creates a pointer down action.
180 /// </summary>
181 /// <remarks>
182 /// MouseButton value applies to Pen types for primary, secondary and erase functionality (0, 2, and 5 respectively)
183 /// </remarks>
184 /// <param name="button">The button of the pointer that should be pressed.</param>
185 /// <param name="properties">The specifications for the pointer event interaction</param>
186 /// <returns>The action representing the pointer down gesture.</returns>
187 public Interaction CreatePointerDown(MouseButton button, PointerEventProperties properties)
188 {
189 return new PointerDownInteraction(this, button, properties);
190 }
191
192 /// <summary>
193 /// Creates a pointer up action.
194 /// </summary>
195 /// <param name="button">The button of the pointer that should be released.</param>
196 /// <returns>The action representing the pointer up gesture.</returns>
197 public Interaction CreatePointerUp(MouseButton button)
198 {
199 return CreatePointerUp(button, new PointerEventProperties());
200 }
201
202 /// <summary>
203 /// Creates a pointer down action.
204 /// </summary>
205 /// <remarks>
206 /// MouseButton value applies to Pen types for primary, secondary and erase functionality (0, 2, and 5 respectively)
207 /// </remarks>
208 /// <param name="button">The button of the pointer that should be pressed.</param>
209 /// <param name="properties">The specifications for the pointer event interaction</param>
210 /// <returns>The action representing the pointer down gesture.</returns>
211 public Interaction CreatePointerUp(MouseButton button, PointerEventProperties properties)
212 {
213 return new PointerUpInteraction(this, button, properties);
214 }
215
216 /// <summary>
217 /// Creates a pointer move action to a specific element.
218 /// </summary>
219 /// <param name="target">The <see cref="IWebElement"/> used as the target for the move.</param>
220 /// <param name="xOffset">The horizontal offset from the origin of the move.</param>
221 /// <param name="yOffset">The vertical offset from the origin of the move.</param>
222 /// <param name="duration">The length of time the move gesture takes to complete.</param>
223 /// <returns>The action representing the pointer move gesture.</returns>
224 public Interaction CreatePointerMove(IWebElement target, int xOffset, int yOffset, TimeSpan duration)
225 {
226 return CreatePointerMove(target, xOffset, yOffset, duration, new PointerEventProperties());
227 }
228
229 /// <summary>
230 /// Creates a pointer move action to a specific element.
231 /// </summary>
232 /// <param name="target">The <see cref="IWebElement"/> used as the target for the move.</param>
233 /// <param name="xOffset">The horizontal offset from the origin of the move.</param>
234 /// <param name="yOffset">The vertical offset from the origin of the move.</param>
235 /// <param name="duration">The length of time the move gesture takes to complete.</param>
236 /// <param name="properties">The specifications for the pointer event interaction</param>
237 /// <returns>The action representing the pointer move gesture.</returns>
238 public Interaction CreatePointerMove(IWebElement target, int xOffset, int yOffset, TimeSpan duration, PointerEventProperties properties)
239 {
240 return new PointerMoveInteraction(this, target, CoordinateOrigin.Element, xOffset, yOffset, duration, properties);
241 }
242
243 /// <summary>
244 /// Creates a pointer move action to an absolute coordinate.
245 /// </summary>
246 /// <param name="origin">The origin of coordinates for the move. Values can be relative to
247 /// the view port origin, or the most recent pointer position.</param>
248 /// <param name="xOffset">The horizontal offset from the origin of the move.</param>
249 /// <param name="yOffset">The vertical offset from the origin of the move.</param>
250 /// <param name="duration">The length of time the move gesture takes to complete.</param>
251 /// <returns>The action representing the pointer move gesture.</returns>
252 /// <exception cref="ArgumentException">Thrown when passing CoordinateOrigin.Element into origin.
253 /// Users should us the other CreatePointerMove overload to move to a specific element.</exception>
254 public Interaction CreatePointerMove(CoordinateOrigin origin, int xOffset, int yOffset, TimeSpan duration)
255 {
256 return CreatePointerMove(origin, xOffset, yOffset, duration, new PointerEventProperties());
257 }
258
259 /// <summary>
260 /// Creates a pointer move action to an absolute coordinate.
261 /// </summary>
262 /// <param name="origin">The origin of coordinates for the move. Values can be relative to
263 /// the view port origin, or the most recent pointer position.</param>
264 /// <param name="xOffset">The horizontal offset from the origin of the move.</param>
265 /// <param name="yOffset">The vertical offset from the origin of the move.</param>
266 /// <param name="duration">The length of time the move gesture takes to complete.</param>
267 /// <returns>The action representing the pointer move gesture.</returns>
268 /// <exception cref="ArgumentException">Thrown when passing CoordinateOrigin.Element into origin.
269 /// Users should us the other CreatePointerMove overload to move to a specific element.</exception>
270 public Interaction CreatePointerMove(CoordinateOrigin origin, int xOffset, int yOffset, TimeSpan duration, PointerEventProperties properties)
271 {
272 if (origin == CoordinateOrigin.Element)
273 {
274 throw new ArgumentException("Using a value of CoordinateOrigin.Element without an element is not supported.", nameof(origin));
275 }
276
277 return new PointerMoveInteraction(this, null, origin, xOffset, yOffset, duration, properties);
278 }
279
280 /// <summary>
281 /// Creates a pointer cancel action.
282 /// </summary>
283 /// <returns>The action representing the pointer cancel gesture.</returns>
284 public Interaction CreatePointerCancel()
285 {
286 return new PointerCancelInteraction(this);
287 }
288
289 public class PointerEventProperties
290 {
291 private double? width;
292 private double? height;
293 private double? pressure;
294 private double? tangentialPressure;
295 private int? tiltX;
296 private int? tiltY;
297 private int? twist;
298 private double? altitudeAngle;
299 private double? azimuthAngle;
300
301 /// <summary>
302 /// Gets or sets the width (magnitude on x-axis) in pixels of the contact geometry of the pointer.
303 /// </summary>
304 public double? Width
305 {
306 get { return this.width; }
307 set { this.width = value; }
308 }
309
310 /// <summary>
311 /// Gets or sets the height (magnitude on y-axis) in pixels of the contact geometry of the pointer.
312 /// </summary>
313 public double? Height
314 {
315 get { return this.height; }
316 set { this.height = value; }
317 }
318 /// <summary>
319 /// Gets or sets the normalized pressure of the pointer input.
320 /// </summary>
321 /// <remarks>
322 /// 0 and 1 represent the minimum and maximum pressure the hardware is capable of detecting, respectively.
323 /// </remarks>
324 public double? Pressure
325 {
326 get { return this.pressure; }
327 set { this.pressure = value; }
328 }
329 /// <summary>
330 /// Gets or sets the normalized tangential pressure (also known as barrel pressure) of the pointer input.
331 /// </summary>
332 /// <remarks>
333 /// Valid values are between -1 and 1 with 0 being the neutral position of the control.
334 /// Some hardware may only support positive values between 0 and 1.
335 /// </remarks>
336 public double? TangentialPressure
337 {
338 get { return this.tangentialPressure; }
339 set { this.tangentialPressure = value; }
340 }
341 /// <summary>
342 /// Gets or sets the plane angle in degrees between the Y-Z plane and the plane containing
343 /// both the transducer (e.g. pen stylus) axis and the Y axis..
344 /// </summary>
345 /// <remarks>
346 /// Valid values are between -90 and 90. A positive value is to the right.
347 /// </remarks>
348 public int? TiltX
349 {
350 get { return this.tiltX; }
351 set { this.tiltX = value; }
352 }
353 /// <summary>
354 /// Gets or sets the plane angle in degrees between the X-Z plane and the plane containing
355 /// both the transducer (e.g. pen stylus) axis and the X axis..
356 /// </summary>
357 /// <remarks>
358 /// Valid values are between -90 and 90. A positive value is toward the user.
359 /// </remarks>
360 public int? TiltY
361 {
362 get { return this.tiltY; }
363 set { this.tiltY = value; }
364 }
365 /// <summary>
366 /// Gets or sets the clockwise rotation in degrees of a transducer (e.g. stylus) around its own major axis
367 /// </summary>
368 /// <remarks>
369 /// Valid values are between 0 and 359.
370 /// </remarks>
371 public int? Twist
372 {
373 get { return this.twist; }
374 set { this.twist = value; }
375 }
376 /// <summary>
377 /// Gets or sets the altitude in radians of the transducer (e.g. pen/stylus)
378 /// </summary>
379 /// <remarks>
380 /// Valid values are between 0 and π/2, where 0 is parallel to the surface (X-Y plane),
381 /// and π/2 is perpendicular to the surface.
382 /// </remarks>
383 public double? AltitudeAngle
384 {
385 get { return this.altitudeAngle; }
386 set { this.altitudeAngle = value; }
387 }
388 /// <summary>
389 /// Gets or sets the azimuth angle (in radians) of the transducer (e.g. pen/stylus)
390 /// </summary>
391 /// <remarks>
392 /// Valid values are between 0 and 2π,
393 /// where 0 represents a transducer whose cap is pointing in the direction of increasing X values,
394 /// and the values progressively increase when going clockwise.
395 /// </remarks>
396 public double? AzimuthAngle
397 {
398 get { return this.azimuthAngle; }
399 set { this.azimuthAngle = value; }
400 }
401
402 public Dictionary<string, object> ToDictionary()
403 {
404 Dictionary<string, object> toReturn = new Dictionary<string, object>();
405
406 if (this.Width.HasValue)
407 {
408 toReturn["width"] = this.Width.Value;
409 }
410
411 if (this.height.HasValue)
412 {
413 toReturn["height"] = this.height.Value;
414 }
415
416 if (this.pressure.HasValue)
417 {
418 toReturn["pressure"] = this.pressure.Value;
419 }
420
421 if (this.tangentialPressure.HasValue)
422 {
423 toReturn["tangentialPressure"] = this.tangentialPressure.Value;
424 }
425
426 if (this.tiltX.HasValue)
427 {
428 toReturn["tiltX"] = this.tiltX.Value;
429 }
430
431 if (this.tiltY.HasValue)
432 {
433 toReturn["tiltY"] = this.tiltY.Value;
434 }
435
436 if (this.twist.HasValue)
437 {
438 toReturn["twist"] = this.twist.Value;
439 }
440
441 if (this.altitudeAngle.HasValue)
442 {
443 toReturn["altitudeAngle"] = this.altitudeAngle.Value;
444 }
445
446 if (this.azimuthAngle.HasValue)
447 {
448 toReturn["azimuthAngle"] = this.azimuthAngle.Value;
449 }
450
451 return toReturn;
452 }
453 }
454
455 private class PointerDownInteraction : Interaction
456 {
457 private MouseButton button;
458 private PointerEventProperties eventProperties;
459
460 public PointerDownInteraction(InputDevice sourceDevice, MouseButton button, PointerEventProperties properties)
461 : base(sourceDevice)
462 {
463 this.button = button;
464 this.eventProperties = properties;
465 }
466
467 public override Dictionary<string, object> ToDictionary()
468 {
469 Dictionary<string, object> toReturn;
470 if (eventProperties == null)
471 {
472 toReturn = new Dictionary<string, object>();
473 }
474 else
475 {
476 toReturn = eventProperties.ToDictionary();
477 }
478 toReturn["type"] = "pointerDown";
479 toReturn["button"] = Convert.ToInt32(this.button, CultureInfo.InvariantCulture);
480
481 return toReturn;
482 }
483
484 public override string ToString()
485 {
486 return "Pointer down";
487 }
488 }
489
490 private class PointerUpInteraction : Interaction
491 {
492 private MouseButton button;
493 private PointerEventProperties eventProperties;
494
495 public PointerUpInteraction(InputDevice sourceDevice, MouseButton button, PointerEventProperties properties)
496 : base(sourceDevice)
497 {
498 this.button = button;
499 }
500
501 public override Dictionary<string, object> ToDictionary()
502 {
503 Dictionary<string, object> toReturn;
504 if (eventProperties == null)
505 {
506 toReturn = new Dictionary<string, object>();
507 }
508 else
509 {
510 toReturn = eventProperties.ToDictionary();
511 }
512
513 toReturn["type"] = "pointerUp";
514 toReturn["button"] = Convert.ToInt32(this.button, CultureInfo.InvariantCulture);
515
516 return toReturn;
517 }
518
519 public override string ToString()
520 {
521 return "Pointer up";
522 }
523 }
524
525 private class PointerCancelInteraction : Interaction
526 {
527 public PointerCancelInteraction(InputDevice sourceDevice)
528 : base(sourceDevice)
529 {
530 }
531
532 public override Dictionary<string, object> ToDictionary()
533 {
534 Dictionary<string, object> toReturn = new Dictionary<string, object>();
535 toReturn["type"] = "pointerCancel";
536 return toReturn;
537 }
538
539 public override string ToString()
540 {
541 return "Pointer cancel";
542 }
543 }
544
545 private class PointerMoveInteraction : Interaction
546 {
547 private IWebElement target;
548 private int x = 0;
549 private int y = 0;
550 private TimeSpan duration = TimeSpan.MinValue;
551 private CoordinateOrigin origin = CoordinateOrigin.Pointer;
552 private PointerEventProperties eventProperties;
553
554 public PointerMoveInteraction(InputDevice sourceDevice, IWebElement target, CoordinateOrigin origin, int x, int y, TimeSpan duration, PointerEventProperties properties)
555 : base(sourceDevice)
556 {
557 if (target != null)
558 {
559 this.target = target;
560 this.origin = CoordinateOrigin.Element;
561 }
562 else
563 {
564 if (this.origin != CoordinateOrigin.Element)
565 {
566 this.origin = origin;
567 }
568 }
569
570 if (duration != TimeSpan.MinValue)
571 {
572 this.duration = duration;
573 }
574
575 this.x = x;
576 this.y = y;
577 this.eventProperties = properties;
578 }
579
580 public override Dictionary<string, object> ToDictionary()
581 {
582 Dictionary<string, object> toReturn;
583 if (eventProperties == null)
584 {
585 toReturn = new Dictionary<string, object>();
586 }
587 else
588 {
589 toReturn = eventProperties.ToDictionary();
590 }
591
592 toReturn["type"] = "pointerMove";
593 if (this.duration != TimeSpan.MinValue)
594 {
595 toReturn["duration"] = Convert.ToInt64(this.duration.TotalMilliseconds);
596 }
597
598 if (this.target != null)
599 {
600 toReturn["origin"] = this.ConvertElement();
601 }
602 else
603 {
604 toReturn["origin"] = this.origin.ToString().ToLowerInvariant();
605 }
606
607 toReturn["x"] = this.x;
608 toReturn["y"] = this.y;
609
610 return toReturn;
611 }
612
613 public override string ToString()
614 {
615 string originDescription = this.origin.ToString();
616 if (this.origin == CoordinateOrigin.Element)
617 {
618 originDescription = this.target.ToString();
619 }
620
621 return string.Format(CultureInfo.InvariantCulture, "Pointer move [origin: {0}, x offset: {1}, y offset: {2}, duration: {3}ms]", originDescription, this.x, this.y, this.duration.TotalMilliseconds);
622 }
623
624 private Dictionary<string, object> ConvertElement()
625 {
626 IWebDriverObjectReference elementReference = this.target as IWebDriverObjectReference;
627 if (elementReference == null)
628 {
629 IWrapsElement elementWrapper = this.target as IWrapsElement;
630 if (elementWrapper != null)
631 {
632 elementReference = elementWrapper.WrappedElement as IWebDriverObjectReference;
633 }
634 }
635
636 if (elementReference == null)
637 {
638 throw new ArgumentException("Target element cannot be converted to IWebElementReference");
639 }
640
641 Dictionary<string, object> elementDictionary = elementReference.ToDictionary();
642 return elementDictionary;
643 }
644 }
645 }
646 }