private void SendEvents(MouseState mouseState, KeyboardState keyboardState)
        {
            if (FMouseState != mouseState)
            {
                var x         = (int)VMath.Map(mouseState.X, -1, 1, 0, FWidth, TMapMode.Clamp);
                var y         = (int)VMath.Map(mouseState.Y, 1, -1, 0, FHeight, TMapMode.Clamp);
                var mouseDown = FMouseState.Button == MouseButton.None && mouseState.Button != MouseButton.None;
                var mouseUp   = FMouseState.Button != MouseButton.None && mouseState.Button == MouseButton.None;
                var button    = mouseState.Button;
                if (mouseUp)
                {
                    button = FMouseState.Button;
                }
                if (mouseDown || mouseUp)
                {
                    switch (button)
                    {
                    case MouseButton.Left:
                        FBrowser.SendMouseClickEvent(x, y, CefMouseButtonType.Left, mouseUp, 1);
                        break;

                    case MouseButton.Middle:
                        FBrowser.SendMouseClickEvent(x, y, CefMouseButtonType.Middle, mouseUp, 1);
                        break;

                    case MouseButton.Right:
                        FBrowser.SendMouseClickEvent(x, y, CefMouseButtonType.Right, mouseUp, 1);
                        break;

                    default:
                        throw new Exception(string.Format("Unknown mouse button {0}.", button));
                    }
                }
                else
                {
                    FBrowser.SendMouseMoveEvent(x, y, false);
                }
                var mouseWheelDelta = mouseState.MouseWheel - FMouseState.MouseWheel;
                if (mouseWheelDelta != 0)
                {
                    FBrowser.SendMouseWheelEvent(x, y, mouseWheelDelta);
                }
                FMouseState = mouseState;
            }

            keyboardState = keyboardState ?? KeyboardState.Empty;
            if (FKeyboardState != keyboardState)
            {
                var isKeyUp = FKeyboardState.KeyCodes.Count > keyboardState.KeyCodes.Count;
                if (isKeyUp)
                {
                    var releasedKeys = FKeyboardState.KeyCodes.Except(keyboardState.KeyCodes);
                    var modifiers    = (CefHandlerKeyEventModifiers)((int)(FKeyboardState.Modifiers) >> 16);
                    foreach (var key in releasedKeys)
                    {
                        FBrowser.SendKeyEvent(CefKeyType.KeyUp, (int)key, modifiers, false, false);
                    }
                }
                var isKeyDown = keyboardState.KeyCodes.Count > FKeyboardState.KeyCodes.Count;
                if (isKeyDown)
                {
                    var pressedKeys = keyboardState.KeyCodes.Except(FKeyboardState.KeyCodes);
                    var modifiers   = (CefHandlerKeyEventModifiers)((int)(keyboardState.Modifiers) >> 16);
                    foreach (var key in pressedKeys)
                    {
                        FBrowser.SendKeyEvent(CefKeyType.KeyDown, (int)key, modifiers, false, false);
                    }
                }
                if (!isKeyUp)
                {
                    var keyChar = keyboardState.KeyChars.LastOrDefault();
                    if (keyChar != 0 && !(keyChar == '\t' || keyChar == '\b'))
                    {
                        var modifiers = (CefHandlerKeyEventModifiers)((int)(keyboardState.Modifiers) >> 16);
                        FBrowser.SendKeyEvent(CefKeyType.Char, (int)keyChar, modifiers, false, false);
                    }
                }
                FKeyboardState = keyboardState;
            }
        }