< Summary

Class:GDX.Developer.InputProxy
Assembly:GDX
File(s):./Packages/com.dotbunny.gdx/GDX/Developer/InputProxy.cs
Covered lines:0
Uncovered lines:219
Coverable lines:219
Total lines:723
Line coverage:0% (0 of 219)
Covered branches:0
Total branches:0
Covered methods:0
Total methods:18
Method coverage:0% (0 of 18)

Coverage History

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
GetKeyCode(...)0%1311011400%
IsExtendedKey(...)0%1821300%
Synthesize(...)0%2100%
Synthesize(...)0%12300%
Synthesize(...)0%2100%
Synthesize(...)0%12300%
Synthesize(...)0%2100%
Synthesize(...)0%12300%
KeyPress(...)0%2100%
MouseClick(...)0%2100%
KeyboardInput(...)0%20400%
InputProxy()0%2100%
HardwareInput(...)0%2100%
MouseInput(...)0%12300%
InputData(...)0%2100%
InputData(...)0%2100%
InputData(...)0%2100%
InputItem(...)0%2100%

File(s)

./Packages/com.dotbunny.gdx/GDX/Developer/InputProxy.cs

#LineLine coverage
 1// Copyright (c) 2020-2024 dotBunny Inc.
 2// dotBunny licenses this file to you under the BSL-1.0 license.
 3// See the LICENSE file in the project root for more information.
 4
 5using System;
 6using System.Collections.Generic;
 7using System.Runtime.CompilerServices;
 8using System.Runtime.InteropServices;
 9using UnityEngine;
 10
 11namespace GDX.Developer
 12{
 13    /// <summary>
 14    ///     A windows-based input simulator.
 15    /// </summary>
 16    /// <remarks>
 17    ///     This is NOT supported in batch mode operation of the editor.
 18    /// </remarks>
 19    public static class InputProxy
 20    {
 21        public enum SynthesizeMethod
 22        {
 23            Native,
 24            InputSystem // TODO:Add path to push the unity input system manually
 25        }
 26
 27        /// <summary>
 28        ///     A set of flags to describe various aspects of <see cref="KeyboardInput" />, mainly used to define
 29        ///     additional information related to <see cref="KeyboardInput.Key" />.
 30        /// </summary>
 31        [Flags]
 32        public enum KeyboardFlag : uint
 33        {
 34            KeyDown = 0x0000,
 35
 36            /// <summary>
 37            ///     Is the key part of the extended set.
 38            /// </summary>
 39            ExtendedKey = 0x0001,
 40
 41            /// <summary>
 42            ///     A key has been released.
 43            /// </summary>
 44            KeyUp = 0x0002,
 45            Unicode = 0x0004,
 46            ScanCode = 0x0008
 47        }
 48
 49        /// <summary>
 50        ///     Virtual key codes.
 51        /// </summary>
 52        /// <seealso href="https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes" />
 53        public enum KeyCode : ushort
 54        {
 55            Invalid = 0x00,
 56            Backspace = 0x08,
 57            Tab = 0x09,
 58            Clear = 0x0c,
 59            Return = 0x0d,
 60            Shift = 0x10,
 61            Control = 0x11,
 62            Alt = 0x12,
 63            Pause = 0x13,
 64            CapsLock = 0x14,
 65            Escape = 0x1b,
 66            Space = 0x20,
 67            PageUp = 0x21,
 68            PageDown = 0x22,
 69            End = 0x23,
 70            Home = 0x24,
 71            Left = 0x25,
 72            Up = 0x26,
 73            Right = 0x27,
 74            Down = 0x28,
 75            PrintScreen = 0x2c,
 76            Insert = 0x2d,
 77            Delete = 0x2e,
 78            Number0 = 0x30,
 79            Number1 = 0x31,
 80            Number2 = 0x32,
 81            Number3 = 0x33,
 82            Number4 = 0x34,
 83            Number5 = 0x35,
 84            Number6 = 0x36,
 85            Number7 = 0x37,
 86            Number8 = 0x38,
 87            Number9 = 0x39,
 88            A = 0x41,
 89            B = 0x42,
 90            C = 0x43,
 91            D = 0x44,
 92            E = 0x45,
 93            F = 0x46,
 94            G = 0x47,
 95            H = 0x48,
 96            I = 0x49,
 97            J = 0x4a,
 98            K = 0x4b,
 99            L = 0x4c,
 100            M = 0x4d,
 101            N = 0x4e,
 102            O = 0x4f,
 103            P = 0x50,
 104            Q = 0x51,
 105            R = 0x52,
 106            S = 0x53,
 107            T = 0x54,
 108            U = 0x55,
 109            V = 0x56,
 110            W = 0x57,
 111            X = 0x58,
 112            Y = 0x59,
 113            Z = 0x5a,
 114            LeftWindows = 0x5b,
 115            RightWindows = 0x5c,
 116            Applications = 0x5d,
 117            Sleep = 0x5f,
 118            NumPad0 = 0x60,
 119            NumPad1 = 0x61,
 120            NumPad2 = 0x62,
 121            NumPad3 = 0x63,
 122            NumPad4 = 0x64,
 123            NumPad5 = 0x65,
 124            NumPad6 = 0x66,
 125            NumPad7 = 0x67,
 126            NumPad8 = 0x68,
 127            NumPad9 = 0x69,
 128            NumPadMultiply = 0x6a,
 129            NumPadAdd = 0x6b,
 130            NumPadSubtract = 0x6d,
 131            NumPadDecimal = 0x6e,
 132            NumPadDivide = 0x6f,
 133            F1 = 0x70,
 134            F2 = 0x71,
 135            F3 = 0x72,
 136            F4 = 0x73,
 137            F5 = 0x74,
 138            F6 = 0x75,
 139            F7 = 0x76,
 140            F8 = 0x77,
 141            F9 = 0x78,
 142            F10 = 0x79,
 143            F11 = 0x7a,
 144            F12 = 0x7b,
 145            NumLock = 0x90,
 146            ScrollLock = 0x91,
 147            LeftShift = 0xa0,
 148            RightShift = 0xa1,
 149            LeftControl = 0xa2,
 150            RightControl = 0xa3
 151        }
 152
 153        public static KeyCode GetKeyCode(string keyCode)
 0154        {
 0155            int hash = keyCode.GetStableLowerCaseHashCode();
 0156            switch (hash)
 157            {
 158                case -68092673:
 0159                    return KeyCode.Backspace;
 160                case 696029671:
 0161                    return KeyCode.Tab;
 162                case 613662425:
 0163                    return KeyCode.Clear;
 164                case -607330920:
 0165                    return KeyCode.Return;
 166                case -387753726:
 0167                    return KeyCode.Shift;
 168                case -1166912341:
 0169                    return KeyCode.Control;
 170                case -63485571:
 0171                    return KeyCode.Alt;
 172                case -1685075688:
 0173                    return KeyCode.Pause;
 174                case -1943382536:
 0175                    return KeyCode.CapsLock;
 176                case 1110997421:
 0177                    return KeyCode.Escape;
 178                case 1144830560:
 0179                    return KeyCode.Space;
 180                case 234281596:
 0181                    return KeyCode.PageUp;
 182                case -1752670719:
 0183                    return KeyCode.PageDown;
 184                case -1226285125:
 0185                    return KeyCode.End;
 186                case 1414245067:
 0187                    return KeyCode.Home;
 188                case -871206253:
 0189                    return KeyCode.Left;
 190                case 1543969241:
 0191                    return KeyCode.Up;
 192                case 109637592:
 0193                    return KeyCode.Right;
 194                case 1367190538:
 0195                    return KeyCode.Down;
 196                case -98072495:
 0197                    return KeyCode.PrintScreen;
 198                case 695394959:
 0199                    return KeyCode.Insert;
 200                case 1381955065:
 0201                    return KeyCode.Delete;
 202                case -252055437:
 0203                    return KeyCode.Number0;
 204                case -252055438:
 0205                    return KeyCode.Number1;
 206                case -252055439:
 0207                    return KeyCode.Number2;
 208                case -252055440:
 0209                    return KeyCode.Number3;
 210                case -252055433:
 0211                    return KeyCode.Number4;
 212                case -252055434:
 0213                    return KeyCode.Number5;
 214                case -252055435:
 0215                    return KeyCode.Number6;
 216                case -252055436:
 0217                    return KeyCode.Number7;
 218                case -252055429:
 0219                    return KeyCode.Number8;
 220                case -252055430:
 0221                    return KeyCode.Number9;
 222                case 372029373:
 0223                    return KeyCode.A;
 224                case 372029376:
 0225                    return KeyCode.B;
 226                case 372029375:
 0227                    return KeyCode.C;
 228                case 372029370:
 0229                    return KeyCode.D;
 230                case 372029369:
 0231                    return KeyCode.E;
 232                case 372029372:
 0233                    return KeyCode.F;
 234                case 372029371:
 0235                    return KeyCode.G;
 236                case 372029382:
 0237                    return KeyCode.H;
 238                case 372029381:
 0239                    return KeyCode.I;
 240                case 372029384:
 0241                    return KeyCode.J;
 242                case 372029383:
 0243                    return KeyCode.K;
 244                case 372029378:
 0245                    return KeyCode.L;
 246                case 372029377:
 0247                    return KeyCode.M;
 248                case 372029380:
 0249                    return KeyCode.N;
 250                case 372029379:
 0251                    return KeyCode.O;
 252                case 372029390:
 0253                    return KeyCode.P;
 254                case 372029389:
 0255                    return KeyCode.Q;
 256                case 372029392:
 0257                    return KeyCode.R;
 258                case 372029391:
 0259                    return KeyCode.S;
 260                case 372029386:
 0261                    return KeyCode.T;
 262                case 372029385:
 0263                    return KeyCode.U;
 264                case 372029388:
 0265                    return KeyCode.V;
 266                case 372029387:
 0267                    return KeyCode.W;
 268                case 372029398:
 0269                    return KeyCode.X;
 270                case 372029397:
 0271                    return KeyCode.Y;
 272                case 372029400:
 0273                    return KeyCode.Z;
 274                case -1953951152:
 0275                    return KeyCode.LeftWindows;
 276                case -1623418013:
 0277                    return KeyCode.RightWindows;
 278                case 1523316373:
 0279                    return KeyCode.Applications;
 280                case -1711919009:
 0281                    return KeyCode.Sleep;
 282                case 191376843:
 0283                    return KeyCode.NumPad0;
 284                case 191376842:
 0285                    return KeyCode.NumPad1;
 286                case 191376841:
 0287                    return KeyCode.NumPad2;
 288                case 191376840:
 0289                    return KeyCode.NumPad3;
 290                case 191376839:
 0291                    return KeyCode.NumPad4;
 292                case 191376838:
 0293                    return KeyCode.NumPad5;
 294                case 191376837:
 0295                    return KeyCode.NumPad6;
 296                case 191376836:
 0297                    return KeyCode.NumPad7;
 298                case 191376851:
 0299                    return KeyCode.NumPad8;
 300                case 191376850:
 0301                    return KeyCode.NumPad9;
 302                case -1585322177:
 0303                    return KeyCode.NumPadMultiply;
 304                case 1476018722:
 0305                    return KeyCode.NumPadAdd;
 306                case 283539863:
 0307                    return KeyCode.NumPadSubtract;
 308                case -1957785586:
 0309                    return KeyCode.NumPadDecimal;
 310                case 1060101014:
 0311                    return KeyCode.NumPadDivide;
 312                case -1467239129:
 0313                    return KeyCode.F1;
 314                case -1063954602:
 0315                    return KeyCode.F2;
 316                case 1664928753:
 0317                    return KeyCode.F3;
 318                case -1870523656:
 0319                    return KeyCode.F4;
 320                case 858359699:
 0321                    return KeyCode.F5;
 322                case 1261644226:
 0323                    return KeyCode.F6;
 324                case -304439715:
 0325                    return KeyCode.F7;
 326                case -257385548:
 0327                    return KeyCode.F8;
 328                case -1823469489:
 0329                    return KeyCode.F9;
 330                case -1461555849:
 0331                    return KeyCode.F10;
 332                case -1461555850:
 0333                    return KeyCode.F11;
 334                case -1461555851:
 0335                    return KeyCode.F12;
 336                case -1717124259:
 0337                    return KeyCode.NumLock;
 338                case -1411354708:
 0339                    return KeyCode.ScrollLock;
 340                case -1825696445:
 0341                    return KeyCode.LeftShift;
 342                case 965494012:
 0343                    return KeyCode.RightShift;
 344                case -595951364:
 0345                    return KeyCode.LeftControl;
 346                case -873360029:
 0347                    return KeyCode.RightControl;
 348            }
 349
 0350            return KeyCode.Invalid;
 0351        }
 352
 353        /// <summary>
 354        /// </summary>
 355        /// <param name="keyCode"></param>
 356        /// <returns></returns>
 357        /// <seealso href="https://learn.microsoft.com/en-us/windows/win32/inputdev/about-keyboard-input" />
 358        public static bool IsExtendedKey(KeyCode keyCode)
 0359        {
 0360            if (keyCode == KeyCode.Control ||
 361                keyCode == KeyCode.RightControl ||
 362                keyCode == KeyCode.Insert ||
 363                keyCode == KeyCode.Delete ||
 364                keyCode == KeyCode.Home ||
 365                keyCode == KeyCode.End ||
 366                keyCode == KeyCode.Right ||
 367                keyCode == KeyCode.Up ||
 368                keyCode == KeyCode.Left ||
 369                keyCode == KeyCode.Down ||
 370                keyCode == KeyCode.NumLock ||
 371                keyCode == KeyCode.NumPadDivide)
 0372            {
 0373                return true;
 374            }
 375
 0376            return false;
 0377        }
 378
 379        /// <summary>
 380        ///     A set of flags to describe various aspects of <see cref="MouseInput" />, mainly used to define
 381        ///     additional information related to <see cref="MouseInput.Data" />.
 382        /// </summary>
 383        [Flags]
 384        public enum MouseFlag : uint
 385        {
 386            Move = 0x0001,
 387            LeftDown = 0x0002,
 388            LeftUp = 0x0004,
 389            RightDown = 0x0008,
 390            RightUp = 0x0010,
 391            MiddleDown = 0x0020,
 392            MiddleUp = 0x0040,
 393            VerticalWheel = 0x0800,
 394            HorizontalWheel = 0x1000,
 395
 396            /// <summary>
 397            ///     Used in multi-desktop scenarios where you want to treat X/Y against the combined screen space.
 398            ///     You must also use <see cref="MouseFlag.Absolute" />.
 399            /// </summary>
 400            VirtualDesk = 0x4000,
 401
 402            /// <summary>
 403            ///     Indicates provided X/Y are in absolute screenspace instead of deltas of previous position.
 404            /// </summary>
 405            Absolute = 0x8000
 406        }
 407
 408        /// <summary>
 409        ///     A precalculated size of the <see cref="InputItem" />. This is calculated by finding the largest InputDat
 410        ///     struct size and adding either 8 (64bit) or 4 (32bit) bytes to it to account for the difference in pointe
 411        /// </summary>
 412#if UNITY_64
 413        const uint k_InputStructureSize = 40;
 414#else
 415        const uint k_InputStructureSize = 36;
 416#endif // UNITY_64
 417
 418#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
 419        [DllImport("user32.dll", SetLastError = true)]
 420        static extern uint SendInput(uint numberOfInputs, InputItem[] inputs, uint sizeOfInputStructure);
 421
 422        [DllImport("user32.dll")]
 423        static extern uint MapVirtualKey(uint uCode, uint uMapType);
 424#else
 425        static uint SendInput(uint numberOfInputs, InputItem[] inputs, uint sizeOfInputStructure)
 426        {
 427            Debug.LogWarning("InputProxy::SendInput is not supported on this platform.");
 428            return 0;
 429        }
 430        static uint MapVirtualKey(uint uCode, uint uMapType)
 431        {
 432            Debug.LogWarning("InputProxy::MapVirtualKey is not supported on this platform.");
 433            return 0;
 434        }
 435#endif // UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
 436
 437        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 438        public static bool Synthesize(KeyboardInput keyboardInput, SynthesizeMethod method = SynthesizeMethod.Native)
 0439        {
 0440            return Synthesize(new[] { keyboardInput }, method) == 1;
 0441        }
 442
 443        public static uint Synthesize(KeyboardInput[] keyboardInputs, SynthesizeMethod method = SynthesizeMethod.Native)
 0444        {
 0445            uint count = (uint)keyboardInputs.Length;
 0446            if (count == 0)
 0447            {
 0448                return 0;
 449            }
 450
 0451            InputItem[] items = new InputItem[count];
 0452            for (int i = 0; i < count; i++)
 0453            {
 0454                items[i] = new InputItem(InputType.Keyboard, new InputData(keyboardInputs[i]));
 0455            }
 456
 0457            return SendInput(count, items, k_InputStructureSize);
 0458        }
 459
 460        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 461        public static bool Synthesize(MouseInput mouseInput, SynthesizeMethod method = SynthesizeMethod.Native)
 0462        {
 0463            return Synthesize(new[] { mouseInput }, method) == 1;
 0464        }
 465
 466        public static uint Synthesize(MouseInput[] mouseInputs, SynthesizeMethod method = SynthesizeMethod.Native)
 0467        {
 0468            uint count = (uint)mouseInputs.Length;
 0469            if (count == 0)
 0470            {
 0471                return 0;
 472            }
 473
 0474            InputItem[] items = new InputItem[count];
 0475            for (int i = 0; i < count; i++)
 0476            {
 0477                items[i] = new InputItem(InputType.Mouse, new InputData(mouseInputs[i]));
 0478            }
 479
 0480            return SendInput(count, items, k_InputStructureSize);
 0481        }
 482
 483        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 484        public static bool Synthesize(HardwareInput hardwareInput, SynthesizeMethod method = SynthesizeMethod.Native)
 0485        {
 0486            return Synthesize(new[] { hardwareInput }, method) == 1;
 0487        }
 488
 489        public static uint Synthesize(HardwareInput[] hardwareInputs, SynthesizeMethod method = SynthesizeMethod.Native)
 0490        {
 0491            uint count = (uint)hardwareInputs.Length;
 0492            if (count == 0)
 0493            {
 0494                return 0;
 495            }
 496
 0497            InputItem[] items = new InputItem[count];
 0498            for (int i = 0; i < count; i++)
 0499            {
 0500                items[i] = new InputItem(InputType.Hardware, new InputData(hardwareInputs[i]));
 0501            }
 502
 0503            return SendInput(count, items, k_InputStructureSize);
 0504        }
 505
 506        public static bool KeyPress(KeyCode keyCode, SynthesizeMethod method = SynthesizeMethod.Native)
 0507        {
 0508            return Synthesize(
 509                new[]
 510                {
 511                    new KeyboardInput(keyCode, KeyboardFlag.KeyDown, 0, IntPtr.Zero),
 512                    new KeyboardInput(keyCode, KeyboardFlag.KeyUp, 0, IntPtr.Zero)
 513                }, method) == 2;
 0514        }
 515
 516        public static bool MouseClick(int x, int y, bool virtualMode = false,
 517            SynthesizeMethod method = SynthesizeMethod.Native)
 0518        {
 0519            return Synthesize(
 520                new[]
 521                {
 522                    new MouseInput(x, y, 0, MouseFlag.Move & MouseFlag.Absolute, 0, IntPtr.Zero),
 523                    new MouseInput(x, y, 0, MouseFlag.LeftDown, 0, IntPtr.Zero),
 524                    new MouseInput(x, y, 0, MouseFlag.LeftUp, 0, IntPtr.Zero)
 525                }, method) == 3;
 0526        }
 527
 528        /// <summary>
 529        ///     The type of event being synthesized.
 530        /// </summary>
 531        enum InputType : uint
 532        {
 533            Mouse = 0,
 534            Keyboard = 1,
 535            Hardware = 2
 536        }
 537
 538        /// <summary>
 539        ///     A keyboard input event.
 540        /// </summary>
 541        /// <seealso href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-keybdinput" />
 542        /// <remarks>Order and types matters as it is mapped into native, using 24 bytes.</remarks>
 543        public struct KeyboardInput
 544        {
 545            public readonly ushort Key;
 546            public readonly ushort ScanCode;
 547            public readonly uint Flags;
 548
 549            /// <summary>
 550            ///     The timestamp of the event, if 0, OS will just make its own. This is useful if you want to simulate
 551            ///     a duration of time between input events.
 552            /// </summary>
 553            public uint Timestamp;
 554
 555            public IntPtr ExtraInfo;
 556
 557            public KeyboardInput(KeyCode key, KeyboardFlag flags, uint timestamp, IntPtr extraInfo)
 0558            {
 0559                Key = (ushort)key;
 560
 561                // Safety check for extended key
 0562                if (IsExtendedKey(key) && !flags.HasFlags(KeyboardFlag.ExtendedKey))
 0563                {
 0564                    Flags = (uint)(flags | KeyboardFlag.ExtendedKey);
 0565                }
 566                else
 0567                {
 0568                    Flags = (uint)flags;
 0569                }
 570
 0571                if (k_KnownScanCodes.TryGetValue(Key, out ushort value))
 0572                {
 0573                    ScanCode = value;
 0574                }
 575                else
 0576                {
 0577                    ScanCode = (ushort)(MapVirtualKey((uint)key, 0) & 0xFFU);
 0578                    k_KnownScanCodes.Add(Key, ScanCode);
 0579                }
 580
 0581                Timestamp = timestamp;
 0582                ExtraInfo = extraInfo;
 0583            }
 584        }
 585
 0586        static readonly Dictionary<ushort, ushort> k_KnownScanCodes = new Dictionary<ushort, ushort>();
 587
 588        /// <summary>
 589        ///     A generic hardware input event.
 590        /// </summary>
 591        /// <seealso href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-hardwareinput" />
 592        /// <remarks>
 593        ///     Order and types matters as it is mapped into native, using 8 bytes.
 594        /// </remarks>
 595        public struct HardwareInput
 596        {
 597            /// <summary>
 598            ///     The message generated by the input hardware.
 599            /// </summary>
 600            public uint Message;
 601
 602            /// <summary>
 603            ///     The low-order word of the lParam parameter for.
 604            /// </summary>
 605            public ushort ParamL;
 606
 607            /// <summary>
 608            ///     The high-order word of the lParam parameter for uMsg.
 609            /// </summary>
 610            public ushort ParamH;
 611
 612            public HardwareInput(uint message, ushort paramL, ushort paramH)
 0613            {
 0614                Message = message;
 0615                ParamL = paramL;
 0616                ParamH = paramH;
 0617            }
 618        }
 619
 620        /// <summary>
 621        ///     A mouse input event.
 622        /// </summary>
 623        /// <seealso href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-mouseinput" />
 624        /// <remarks>
 625        ///     Order and types matters as it is mapped into native, using 32 bytes.
 626        /// </remarks>
 627        public struct MouseInput
 628        {
 629            /// <summary>
 630            ///     The absolute X position or delta depending on the <see cref="MouseFlag" /> used.
 631            /// </summary>
 632            public readonly int X;
 633
 634            /// <summary>
 635            ///     The absolute Y position or delta depending on the <see cref="MouseFlag" /> used.
 636            /// </summary>
 637            public readonly int Y;
 638
 639            public uint Data;
 640            public readonly uint Flags;
 641
 642            /// <summary>
 643            ///     The timestamp of the event, if 0, OS will just make its own. This is useful if you want to simulate
 644            ///     a duration of time between input events.
 645            /// </summary>
 646            public uint Timestamp;
 647
 648            public IntPtr ExtraInfo;
 649
 650            public MouseInput(int x, int y, uint data, MouseFlag flags, uint timestamp, IntPtr extraInfo)
 0651            {
 0652                Data = data;
 653
 654                // Absolute on main monitor?
 0655                if (flags.HasFlags(MouseFlag.Absolute) && !flags.HasFlags(MouseFlag.VirtualDesk))
 0656                {
 0657                    float widthPercent = (float)x / Screen.currentResolution.width;
 0658                    float heightPercent = (float)y / Screen.currentResolution.height;
 0659                    X = (int)(widthPercent * 65535);
 0660                    Y = (int)(heightPercent * 65535);
 0661                }
 662                else
 0663                {
 0664                    X = x;
 0665                    Y = y;
 0666                }
 667
 0668                Flags = (uint)flags;
 0669                Timestamp = timestamp;
 0670                ExtraInfo = extraInfo;
 0671            }
 672        }
 673
 674        /// <summary>
 675        ///     An explicit data structure used to represent the input event being synthesized.
 676        /// </summary>
 677        [StructLayout(LayoutKind.Explicit)]
 678        struct InputData
 679        {
 680            [FieldOffset(0)] readonly MouseInput Mouse;
 681
 682            [FieldOffset(0)] readonly KeyboardInput Keyboard;
 683
 684            [FieldOffset(0)] readonly HardwareInput Hardware;
 685
 686            public InputData(MouseInput mouseInput)
 0687            {
 0688                Keyboard = default;
 0689                Hardware = default;
 0690                Mouse = mouseInput;
 0691            }
 692
 693            public InputData(KeyboardInput keyboardInput)
 0694            {
 0695                Hardware = default;
 0696                Mouse = default;
 0697                Keyboard = keyboardInput;
 0698            }
 699
 700            public InputData(HardwareInput hardwareInput)
 0701            {
 0702                Mouse = default;
 0703                Keyboard = default;
 0704                Hardware = hardwareInput;
 0705            }
 706        }
 707
 708        /// <summary>
 709        ///     An explicit data structure used to represent the input event being synthesized.
 710        /// </summary>
 711        struct InputItem
 712        {
 713            readonly InputType Type;
 714            readonly InputData Data;
 715
 716            public InputItem(InputType type, InputData data)
 0717            {
 0718                Type = type;
 0719                Data = data;
 0720            }
 721        }
 722    }
 723}