"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 }