bool CheckValidKeyDown(out FakeCursorGesture gesture)
        {
            for (int i = 0; i != validKeys.Count; i++)
            {
                if (Input.GetKeyDown(validKeys[i]) && !Input.GetKeyUp(validKeys[i]))
                {
                    gesture = (FakeCursorGesture)(i + 1);
                    return(true);
                }
            }

            gesture = FakeCursorGesture.Null;
            return(false);
        }
 private bool fakeTouchReleased()
 {
     if (!CheckValidKeyState())
     {
         // Alt is released, need to kill the fake touch
         fakeGesture = FakeCursorGesture.Null;
         fakeMousePointer.Buttons = PointerUtils.UpPressedButtons(fakeMousePointer.Buttons); // Convert current pressed buttons to UP
         releasePointer(fakeMousePointer);
         removePointer(fakeMousePointer);
         fakeMousePointer = null; // Will be returned to the pool by INTERNAL_DiscardPointer
         return(true);
     }
     return(false);
 }
        /// <inheritdoc />
        public bool UpdateInput()
        {
            var     pos         = Input.mousePosition;
            Vector2 remappedPos = new Vector2(0, 0);
            bool    updated     = false;

            if (mousePointPos != pos)
            {
                remappedPos = remapCoordinates(new Vector2(pos.x, pos.y));

                if (mousePointer == null)
                {
                    mousePointer = internalAddPointer(remappedPos);
                }
                else
                {
                    mousePointer.Position = remappedPos;
                    updatePointer(mousePointer);
                }
                updated = true;
            }

            if (mousePointer == null)
            {
                return(false);
            }

            var buttons    = state == State.MouseAndFake ? fakeMousePointer.Buttons : mousePointer.Buttons;
            var newButtons = getMouseButtons();
            var scroll     = Input.mouseScrollDelta;

            if (!Mathf.Approximately(scroll.sqrMagnitude, 0.0f))
            {
                mousePointer.ScrollDelta = scroll;
                updatePointer(mousePointer);
            }
            else
            {
                mousePointer.ScrollDelta = Vector2.zero;
            }

            if (emulateSecondMousePointer)
            {
                switch (state)
                {
                case State.Mouse:
                    FakeCursorGesture gesture;
                    if (CheckValidKeyDown(out gesture) &&
                        ((newButtons & Pointer.PointerButtonState.AnyButtonPressed) == 0))
                    {
                        fakeGesture = gesture;
                        stateWaitingForFake();
                    }
                    else
                    {
                        if (buttons != newButtons)
                        {
                            updateButtons(buttons, newButtons);
                        }
                    }
                    break;

                case State.WaitingForFake:
                    if (CheckValidKeyState())
                    {
                        if ((newButtons & Pointer.PointerButtonState.AnyButtonDown) != 0)
                        {
                            // A button is down while holding Alt

                            mouseInitPos = pos;
                            //Debug.Log("Set: mouseInitPos: "+ mouseInitPos.ToString());

                            fakeMousePointer = internalAddPointer(pos, newButtons, mousePointer.Flags | Pointer.FLAG_ARTIFICIAL);
                            pressPointer(fakeMousePointer);
                            stateMouseAndFake();
                        }
                    }
                    else
                    {
                        fakeGesture = FakeCursorGesture.Null;
                        stateMouse();
                    }
                    break;

                case State.MouseAndFake:
                    if (fakeTouchReleased())
                    {
                        stateMouse();
                    }
                    else
                    {
                        if (mousePointPos != pos)
                        {
                            mouseInitPos = pos;
                            fakeMousePointer.Position = remappedPos;
                            updatePointer(fakeMousePointer);
                        }
                        if ((newButtons & Pointer.PointerButtonState.AnyButtonPressed) == 0)
                        {
                            // All buttons are released, Alt is still holding
                            stateStationaryFake();
                        }
                        else if (buttons != newButtons)
                        {
                            fakeMousePointer.Buttons = newButtons;
                            updatePointer(fakeMousePointer);
                        }
                    }
                    break;

                case State.StationaryFake:
                    if (buttons != newButtons)
                    {
                        updateButtons(buttons, newButtons);
                    }

                    if ((newButtons & Pointer.PointerButtonState.AnyButtonDown) != 0)
                    {
                        //  Calc Center Pos And Offset
                        Vector2 mousePos = new Vector2(pos.x, pos.y);
                        mouseInitCenter = (mouseInitPos + mousePos) / 2;
                        mousePosOffset  = mousePos - mouseInitPos;

                        //Debug.LogFormat("Calc Center Pos And Offset: mousePos: {0}.\n mouseInitPos: {1}, mouseInitCenter: {2}, mousePosOffset: {3}",
                        //    pos, mouseInitPos, mouseInitCenter, mousePosOffset);
                    }

                    if ((newButtons & Pointer.PointerButtonState.AnyButtonPressed) != 0)
                    {
                        switch (fakeGesture)
                        {
                        case FakeCursorGesture.Stationary:
                            //  虚拟点静态
                            break;

                        case FakeCursorGesture.Pan:
                            //  虚拟点平移
                            fakeMousePointer.Position = new Vector2(pos.x, pos.y) - mousePosOffset;
                            updatePointer(fakeMousePointer);
                            break;

                        case FakeCursorGesture.Zoom:
                            //  虚拟点缩放
                            Vector2 mousePos = new Vector2(pos.x, pos.y);
                            Vector2 offset   = mousePos - mouseInitCenter;

                            fakeMousePointer.Position = mouseInitCenter - offset;
                            updatePointer(fakeMousePointer);
                            break;
                        }
                    }

                    if (fakeTouchReleased())
                    {
                        stateMouse();
                    }

                    break;
                }
            }
            else
            {
                if (buttons != newButtons)
                {
                    updateButtons(buttons, newButtons);
                    updated = true;
                }
            }

            mousePointPos = pos;
            return(updated);
        }