diff --git a/src/Consolonia.GuiCS/Consolonia.GuiCS.csproj b/src/Consolonia.GuiCS/Consolonia.GuiCS.csproj index 5173a009..00bcfc9f 100644 --- a/src/Consolonia.GuiCS/Consolonia.GuiCS.csproj +++ b/src/Consolonia.GuiCS/Consolonia.GuiCS.csproj @@ -5,5 +5,8 @@ false false + + + diff --git a/src/Consolonia.GuiCS/WindowsDriver.cs b/src/Consolonia.GuiCS/WindowsDriver.cs index 1465dd66..8263a8f5 100644 --- a/src/Consolonia.GuiCS/WindowsDriver.cs +++ b/src/Consolonia.GuiCS/WindowsDriver.cs @@ -2,294 +2,63 @@ using System; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; - +using System.Runtime.Versioning; +using Vanara.PInvoke; +using static Vanara.PInvoke.Kernel32; namespace Terminal.Gui { - internal class WindowsConsole { - public const int STD_INPUT_HANDLE = -10; - - internal IntPtr InputHandle; - readonly uint originalConsoleMode; - - public WindowsConsole () - { - InputHandle = GetStdHandle (STD_INPUT_HANDLE); - originalConsoleMode = ConsoleMode; - var newConsoleMode = originalConsoleMode; - newConsoleMode |= (uint)(ConsoleModes.EnableMouseInput | ConsoleModes.EnableExtendedFlags); - newConsoleMode &= ~(uint)ConsoleModes.EnableQuickEditMode; - newConsoleMode &= ~(uint)ConsoleModes.EnableProcessedInput; - ConsoleMode = newConsoleMode; - } - - public uint ConsoleMode { - get { - GetConsoleMode (InputHandle, out uint v); - return v; - } - set { - SetConsoleMode (InputHandle, value); - } - } - - [Flags] - public enum ConsoleModes : uint { - EnableProcessedInput = 1, - EnableMouseInput = 16, - EnableQuickEditMode = 64, - EnableExtendedFlags = 128, - } - - [StructLayout (LayoutKind.Explicit, CharSet = CharSet.Unicode)] - public struct KeyEventRecord { - [FieldOffset (0), MarshalAs (UnmanagedType.Bool)] - public bool bKeyDown; - [FieldOffset (4), MarshalAs (UnmanagedType.U2)] - public ushort wRepeatCount; - [FieldOffset (6), MarshalAs (UnmanagedType.U2)] - public ushort wVirtualKeyCode; - [FieldOffset (8), MarshalAs (UnmanagedType.U2)] - public ushort wVirtualScanCode; - [FieldOffset (10)] - public char UnicodeChar; - [FieldOffset (12), MarshalAs (UnmanagedType.U4)] - public ControlKeyState dwControlKeyState; - } - - [Flags] - public enum ButtonState { - Button1Pressed = 1, - Button2Pressed = 4, - Button3Pressed = 8, - Button4Pressed = 16, - RightmostButtonPressed = 2 - } - - [Flags] - public enum ControlKeyState { - RightAltPressed = 1, - LeftAltPressed = 2, - RightControlPressed = 4, - LeftControlPressed = 8, - ShiftPressed = 16, - NumlockOn = 32, - ScrolllockOn = 64, - CapslockOn = 128, - EnhancedKey = 256 - } - - [Flags] - public enum EventFlags { - MouseMoved = 1, - DoubleClick = 2, - MouseWheeled = 4, - MouseHorizontalWheeled = 8 - } - - [StructLayout (LayoutKind.Explicit)] - public struct MouseEventRecord { - [FieldOffset (0)] - public Coord MousePosition; - [FieldOffset (4)] - public ButtonState ButtonState; - [FieldOffset (8)] - public ControlKeyState ControlKeyState; - [FieldOffset (12)] - public EventFlags EventFlags; - - public override string ToString () - { - return $"[Mouse({MousePosition},{ButtonState},{ControlKeyState},{EventFlags}"; - } - } - - public struct WindowBufferSizeRecord { -#pragma warning disable CS0649 - public Coord size; -#pragma warning restore CS0649 - - public override string ToString () => $"[WindowBufferSize{size}"; - } - - [StructLayout (LayoutKind.Sequential)] - public struct MenuEventRecord { - public uint dwCommandId; - } - - [StructLayout (LayoutKind.Sequential)] - public struct FocusEventRecord { - public uint bSetFocus; - } - - public enum EventType : ushort { - Focus = 0x10, - Key = 0x1, - Menu = 0x8, - Mouse = 2, - WindowBufferSize = 4 - } - - [StructLayout (LayoutKind.Explicit)] - public struct InputRecord { - [FieldOffset (0)] - public EventType EventType; - [FieldOffset (4)] - public KeyEventRecord KeyEvent; - [FieldOffset (4)] - public MouseEventRecord MouseEvent; - [FieldOffset (4)] - public WindowBufferSizeRecord WindowBufferSizeEvent; - [FieldOffset (4)] - public MenuEventRecord MenuEvent; - [FieldOffset (4)] - public FocusEventRecord FocusEvent; - - public override string ToString () - { - switch (EventType) { - case EventType.Focus: - return FocusEvent.ToString (); - case EventType.Key: - return KeyEvent.ToString (); - case EventType.Menu: - return MenuEvent.ToString (); - case EventType.Mouse: - return MouseEvent.ToString (); - case EventType.WindowBufferSize: - return WindowBufferSizeEvent.ToString (); - default: - return "Unknown event type: " + EventType; - } - } - }; - - - [StructLayout (LayoutKind.Sequential)] - public struct Coord { - public short X; - public short Y; - - public Coord (short X, short Y) - { - this.X = X; - this.Y = Y; - } - public override string ToString () => $"({X},{Y})"; - }; - - [StructLayout (LayoutKind.Explicit, CharSet = CharSet.Unicode)] - public struct CharUnion { - [FieldOffset (0)] public char UnicodeChar; - [FieldOffset (0)] public byte AsciiChar; - } - - [StructLayout (LayoutKind.Sequential)] - public struct SmallRect { - public short Left; - public short Top; - public short Right; - public short Bottom; - - public SmallRect (short left, short top, short right, short bottom) - { - Left = left; - Top = top; - Right = right; - Bottom = bottom; - } - - - public override string ToString () - { - return $"Left={Left},Top={Top},Right={Right},Bottom={Bottom}"; - } - } - - [DllImport ("kernel32.dll", SetLastError = true)] - static extern IntPtr GetStdHandle (int nStdHandle); - - [DllImport ("kernel32.dll", EntryPoint = "ReadConsoleInputW", CharSet = CharSet.Unicode)] - public static extern bool ReadConsoleInput ( - IntPtr hConsoleInput, - IntPtr lpBuffer, - uint nLength, - out uint lpNumberOfEventsRead); - - - [StructLayout (LayoutKind.Sequential)] - public struct ConsoleCursorInfo { - public uint dwSize; - public bool bVisible; - } - - [DllImport ("kernel32.dll")] - static extern bool GetConsoleMode (IntPtr hConsoleHandle, out uint lpMode); - - - [DllImport ("kernel32.dll")] - static extern bool SetConsoleMode (IntPtr hConsoleHandle, uint dwMode); - - public InputRecord [] ReadConsoleInput () - { - const int bufferSize = 1; - var pRecord = Marshal.AllocHGlobal (Marshal.SizeOf () * bufferSize); - try { - ReadConsoleInput (InputHandle, pRecord, bufferSize, - out var numberEventsRead); - - return numberEventsRead == 0 - ? null - : new [] { Marshal.PtrToStructure (pRecord) }; - } catch (Exception) { - return null; - } finally { - Marshal.FreeHGlobal (pRecord); - } - } - - [StructLayout (LayoutKind.Sequential)] - public struct CONSOLE_SCREEN_BUFFER_INFOEX { - public uint cbSize; - public Coord dwSize; - public Coord dwCursorPosition; - public ushort wAttributes; - public SmallRect srWindow; - public Coord dwMaximumWindowSize; - public ushort wPopupAttributes; - public bool bFullscreenSupported; - - [MarshalAs (UnmanagedType.ByValArray, SizeConst = 16)] - public COLORREF [] ColorTable; - } - - [StructLayout (LayoutKind.Explicit, Size = 4)] - public struct COLORREF { - public COLORREF (byte r, byte g, byte b) - { - Value = 0; - R = r; - G = g; - B = b; - } - - public COLORREF (uint value) - { - R = 0; - G = 0; - B = 0; - Value = value & 0x00FFFFFF; - } - - [FieldOffset (0)] - public byte R; - [FieldOffset (1)] - public byte G; - [FieldOffset (2)] - public byte B; - - [FieldOffset (0)] - public uint Value; - } + [SupportedOSPlatform("windows")] + internal class WindowsConsole + { + + internal HFILE InputHandle; + readonly CONSOLE_INPUT_MODE originalConsoleMode; + + public WindowsConsole() + { + InputHandle = GetStdHandle(StdHandleType.STD_INPUT_HANDLE); + originalConsoleMode = ConsoleMode; + var newConsoleMode = originalConsoleMode; + newConsoleMode |= (CONSOLE_INPUT_MODE.ENABLE_MOUSE_INPUT | + CONSOLE_INPUT_MODE.ENABLE_EXTENDED_FLAGS); + newConsoleMode &= ~CONSOLE_INPUT_MODE.ENABLE_QUICK_EDIT_MODE; + newConsoleMode &= ~CONSOLE_INPUT_MODE.ENABLE_PROCESSED_INPUT; + ConsoleMode = newConsoleMode; + } + + public CONSOLE_INPUT_MODE ConsoleMode + { + get + { + if (!GetConsoleMode(InputHandle, out CONSOLE_INPUT_MODE v)) + throw GetLastError().GetException(); + return v; + } + set + { + if (!SetConsoleMode(InputHandle, value)) + throw GetLastError().GetException(); + } + } + + public INPUT_RECORD[] ReadConsoleInput() + { + const int bufferSize = 1; + var records = new INPUT_RECORD[bufferSize]; + try + { + Kernel32.ReadConsoleInput(InputHandle, records, bufferSize, + out var numberEventsRead); + + return numberEventsRead == 0 + ? null + : records; + } + catch (Exception) + { + return null; + } + } } } \ No newline at end of file diff --git a/src/Consolonia.PlatformSupport/Consolonia.PlatformSupport.csproj b/src/Consolonia.PlatformSupport/Consolonia.PlatformSupport.csproj index 358aea17..820b2216 100644 --- a/src/Consolonia.PlatformSupport/Consolonia.PlatformSupport.csproj +++ b/src/Consolonia.PlatformSupport/Consolonia.PlatformSupport.csproj @@ -1,5 +1,8 @@ + + + diff --git a/src/Consolonia.PlatformSupport/PlatformSupportExtensions.cs b/src/Consolonia.PlatformSupport/PlatformSupportExtensions.cs index c78c51ab..3e6450ec 100644 --- a/src/Consolonia.PlatformSupport/PlatformSupportExtensions.cs +++ b/src/Consolonia.PlatformSupport/PlatformSupportExtensions.cs @@ -8,8 +8,10 @@ using Consolonia.PlatformSupport; // ReSharper disable CheckNamespace +#pragma warning disable IDE0130 #pragma warning disable IDE0161 namespace Consolonia +#pragma warning restore IDE0130 #pragma warning restore IDE0161 { public static class PlatformSupportExtensions @@ -20,12 +22,14 @@ public static AppBuilder UseAutoDetectedConsole(this AppBuilder builder) // in design mode we can't use any console operations at all, so we use a dummy IConsole. return builder.UseConsole(new DummyConsole()); +#pragma warning disable CA1416 IConsole console = Environment.OSVersion.Platform switch { PlatformID.Win32S or PlatformID.Win32Windows or PlatformID.Win32NT => new Win32Console(), PlatformID.Unix or PlatformID.MacOSX => new CursesConsole(), _ => new DefaultNetConsole() }; +#pragma warning restore CA1416 return builder.UseConsole(console).UseAutoDetectConsoleColorMode(); } diff --git a/src/Consolonia.PlatformSupport/WindowsConsole.cs b/src/Consolonia.PlatformSupport/WindowsConsole.cs index 283756b1..8dbd9ddd 100644 --- a/src/Consolonia.PlatformSupport/WindowsConsole.cs +++ b/src/Consolonia.PlatformSupport/WindowsConsole.cs @@ -12,47 +12,65 @@ using Terminal.Gui; using Key = Avalonia.Input.Key; using Point = Avalonia.Point; - +using static Vanara.PInvoke.Kernel32; +using System.Runtime.Versioning; // ReSharper disable UnusedMember.Local #pragma warning disable CS0649 namespace Consolonia.PlatformSupport { + [SupportedOSPlatform("windows")] public class Win32Console : InputLessDefaultNetConsole { - private static readonly FlagTranslator - ModifiersFlagTranslator = new(new[] - { - (WindowsConsole.ControlKeyState.ShiftPressed, RawInputModifiers.Shift), - (WindowsConsole.ControlKeyState.LeftAltPressed, RawInputModifiers.Alt), - (WindowsConsole.ControlKeyState.RightAltPressed, RawInputModifiers.Alt), - (WindowsConsole.ControlKeyState.LeftControlPressed, RawInputModifiers.Control), - (WindowsConsole.ControlKeyState.RightControlPressed, RawInputModifiers.Control) - }); + private static readonly FlagTranslator + KeyModifiersTranslator = new( + [ + (CONTROL_KEY_STATE.NONE, RawInputModifiers.None), + (CONTROL_KEY_STATE.SHIFT_PRESSED, RawInputModifiers.Shift), + (CONTROL_KEY_STATE.LEFT_ALT_PRESSED, RawInputModifiers.Alt), + (CONTROL_KEY_STATE.RIGHT_ALT_PRESSED, RawInputModifiers.Alt), + (CONTROL_KEY_STATE.LEFT_CTRL_PRESSED, RawInputModifiers.Control), + (CONTROL_KEY_STATE.RIGHT_CTRL_PRESSED, RawInputModifiers.Control), + ]); + + private static readonly FlagTranslator + MouseModifiersTranslator = new( + [ + (MOUSE_BUTTON_STATE.NONE, RawInputModifiers.None), + (MOUSE_BUTTON_STATE.FROM_LEFT_1ST_BUTTON_PRESSED, RawInputModifiers.LeftMouseButton), + (MOUSE_BUTTON_STATE.RIGHTMOST_BUTTON_PRESSED, RawInputModifiers.RightMouseButton), + (MOUSE_BUTTON_STATE.FROM_LEFT_2ND_BUTTON_PRESSED, RawInputModifiers.MiddleMouseButton), + (MOUSE_BUTTON_STATE.FROM_LEFT_3RD_BUTTON_PRESSED, RawInputModifiers.XButton1MouseButton), + (MOUSE_BUTTON_STATE.FROM_LEFT_4TH_BUTTON_PRESSED, RawInputModifiers.XButton2MouseButton) + ]); + + + private static readonly FlagTranslator + MouseButtonDownEventTypeTranslator = new( + [ + (MOUSE_BUTTON_STATE.FROM_LEFT_1ST_BUTTON_PRESSED, RawPointerEventType.LeftButtonDown), + (MOUSE_BUTTON_STATE.RIGHTMOST_BUTTON_PRESSED, RawPointerEventType.RightButtonDown), + (MOUSE_BUTTON_STATE.FROM_LEFT_2ND_BUTTON_PRESSED, RawPointerEventType.MiddleButtonDown), + (MOUSE_BUTTON_STATE.FROM_LEFT_3RD_BUTTON_PRESSED, RawPointerEventType.XButton1Down), + (MOUSE_BUTTON_STATE.FROM_LEFT_4TH_BUTTON_PRESSED, RawPointerEventType.XButton2Down), + (MOUSE_BUTTON_STATE.NONE, RawPointerEventType.LeaveWindow) // ugh. that's default + ]); + + private static readonly FlagTranslator + MouseButtonUpEventTypeTranslator = new( + [ + (MOUSE_BUTTON_STATE.FROM_LEFT_1ST_BUTTON_PRESSED, RawPointerEventType.LeftButtonUp), + (MOUSE_BUTTON_STATE.RIGHTMOST_BUTTON_PRESSED, RawPointerEventType.RightButtonUp), + (MOUSE_BUTTON_STATE.FROM_LEFT_2ND_BUTTON_PRESSED, RawPointerEventType.MiddleButtonUp), + (MOUSE_BUTTON_STATE.FROM_LEFT_3RD_BUTTON_PRESSED, RawPointerEventType.XButton1Up), + (MOUSE_BUTTON_STATE.FROM_LEFT_4TH_BUTTON_PRESSED, RawPointerEventType.XButton2Up), + (MOUSE_BUTTON_STATE.NONE, RawPointerEventType.LeaveWindow) // ugh. that's default + ]); - private static readonly FlagTranslator - MouseButtonFlagTranslator = new(new[] - { - (WindowsConsole.ButtonState.Button1Pressed, RawPointerEventType.LeftButtonDown), - (WindowsConsole.ButtonState.RightmostButtonPressed, RawPointerEventType.RightButtonDown), - (WindowsConsole.ButtonState.Button2Pressed, RawPointerEventType.MiddleButtonDown), - (WindowsConsole.ButtonState.Button3Pressed, RawPointerEventType.XButton1Down), - (WindowsConsole.ButtonState.Button4Pressed, RawPointerEventType.XButton2Down) - }); - - private static readonly FlagTranslator - MouseModifiersFlagTranslator = new(new[] - { - (WindowsConsole.ButtonState.Button1Pressed, RawInputModifiers.LeftMouseButton), - (WindowsConsole.ButtonState.RightmostButtonPressed, RawInputModifiers.RightMouseButton), - (WindowsConsole.ButtonState.Button2Pressed, RawInputModifiers.MiddleMouseButton), - (WindowsConsole.ButtonState.Button3Pressed, RawInputModifiers.XButton1MouseButton), - (WindowsConsole.ButtonState.Button4Pressed, RawInputModifiers.XButton2MouseButton) - }); private readonly WindowsConsole _windowsConsole; - private int _mouseButtonsState; + private MOUSE_BUTTON_STATE _mouseButtonsState = MOUSE_BUTTON_STATE.NONE; public Win32Console() { @@ -72,7 +90,7 @@ public override void PauseIO(Task task) var inputRecords = new INPUT_RECORD[1]; // Create a focus event - inputRecords[0].EventType = 0x0010; // FOCUS_EVENT + inputRecords[0].EventType = EVENT_TYPE.FOCUS_EVENT; // FOCUS_EVENT inputRecords[0].Event.FocusEvent = new FOCUS_EVENT_RECORD { bSetFocus = true @@ -97,178 +115,140 @@ private void StartEventLoop() var readConsoleInput = _windowsConsole.ReadConsoleInput(); if (!readConsoleInput.Any()) throw new NotImplementedException(); - foreach (WindowsConsole.InputRecord inputRecord in readConsoleInput) + foreach (var inputRecord in readConsoleInput) // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault switch (inputRecord.EventType) { - case WindowsConsole.EventType.WindowBufferSize: + case EVENT_TYPE.WINDOW_BUFFER_SIZE_EVENT: + //var windowBufferSize = inputRecord.Event.WindowBufferSizeEvent; + //Size = new PixelBufferSize((ushort)windowBufferSize.dwSize.X, (ushort)windowBufferSize.dwSize.Y); ActualizeSize(); break; - case WindowsConsole.EventType.Focus: - WindowsConsole.FocusEventRecord focusEvent = inputRecord.FocusEvent; + case EVENT_TYPE.FOCUS_EVENT: + var focusEvent = inputRecord.Event.FocusEvent; RaiseFocusEvent(focusEvent.bSetFocus != 0); break; - case WindowsConsole.EventType.Key: - HandleKeyInput(inputRecord); + case EVENT_TYPE.KEY_EVENT: + HandleKeyInput(inputRecord.Event.KeyEvent); break; - case WindowsConsole.EventType.Mouse: - - WindowsConsole.MouseEventRecord mouseEvent = inputRecord.MouseEvent; - - if (HandleMouseInput(mouseEvent)) return; //todo: implement + case EVENT_TYPE.MOUSE_EVENT: + var mouseEvent = inputRecord.Event.MouseEvent; + HandleMouseInput(mouseEvent); break; } } }); } - private bool HandleMouseInput(WindowsConsole.MouseEventRecord mouseEvent) + private void HandleMouseInput(MOUSE_EVENT_RECORD mouseEvent) { - var point = new Point(mouseEvent.MousePosition.X, - mouseEvent.MousePosition.Y); - int incomeMouseState = (int)mouseEvent.ButtonState; + var point = new Point(mouseEvent.dwMousePosition.X, mouseEvent.dwMousePosition.Y); RawInputModifiers inputModifiers = - ModifiersFlagTranslator.Translate(mouseEvent.ControlKeyState) | - MouseModifiersFlagTranslator.Translate((WindowsConsole.ButtonState)incomeMouseState); + KeyModifiersTranslator.Translate(mouseEvent.dwControlKeyState) | + MouseModifiersTranslator.Translate(mouseEvent.dwButtonState); - RawPointerEventType eventType = default; + RawPointerEventType eventType = RawPointerEventType.Move; Vector? wheelDelta = null; - short repeat = 1; - switch (mouseEvent.EventFlags) + switch (mouseEvent.dwEventFlags) { - case WindowsConsole.EventFlags.DoubleClick: - repeat = 2; //todo: now supporting only leftbutton - eventType = RawPointerEventType.LeftButtonDown; + case MOUSE_EVENT_FLAG.DOUBLE_CLICK: + var downButtonEvent = MouseButtonDownEventTypeTranslator.Translate(mouseEvent.dwButtonState); + if (downButtonEvent != RawPointerEventType.LeaveWindow) + { + var upButtonEvent = MouseButtonUpEventTypeTranslator.Translate(mouseEvent.dwButtonState); + for (int i = 0; i < 2; i++) + { + RaiseMouseEvent(downButtonEvent, + point, + wheelDelta, + inputModifiers); + + RaiseMouseEvent(upButtonEvent, + point, + wheelDelta, + inputModifiers); + } + } break; - case default(WindowsConsole.EventFlags): - int xor = _mouseButtonsState ^ incomeMouseState; - foreach (RawPointerEventType pointerEventType in ((WindowsConsole.ButtonState)(xor & - incomeMouseState)).GetFlags() - .Select(MouseButtonFlagTranslator.Translate)) - //todo: вернуть mouse gesture на элементы - RaiseMouseEvent(pointerEventType, - point, - null, - inputModifiers); - //todo: refactor: code clone - foreach (RawPointerEventType pointerEventType in ((WindowsConsole.ButtonState)(xor & - _mouseButtonsState)).GetFlags() - .Select(MouseButtonFlagTranslator.Translate)) + case MOUSE_EVENT_FLAG.NONE: + foreach (var flag in Enum.GetValues()) { - RawPointerEventType rawPointerEventType = pointerEventType + 1; - RaiseMouseEvent(rawPointerEventType, - point, - null, - inputModifiers); + if (!_mouseButtonsState.HasFlag(flag) && mouseEvent.dwButtonState.HasFlag(flag)) + { + // If we went from flag off to flag on + var buttonEventType = MouseButtonDownEventTypeTranslator.Translate(flag); + if (buttonEventType != default) + { + RaiseMouseEvent(buttonEventType, + point, + null, + inputModifiers); + } + } + + else if (_mouseButtonsState.HasFlag(flag) && !mouseEvent.dwButtonState.HasFlag(flag)) + { + // If we went from flag On to flag off + var buttonEventType = MouseButtonUpEventTypeTranslator.Translate(flag); + if (buttonEventType != default) + { + RaiseMouseEvent(buttonEventType, + point, + null, + inputModifiers); + } + } + else + { + RaiseMouseEvent(eventType, + point, + null, + inputModifiers); + } } - _mouseButtonsState = incomeMouseState; - repeat = 0; break; - case WindowsConsole.EventFlags.MouseWheeled: - double velocity = incomeMouseState < 0 ? -1 : 1; + + case MOUSE_EVENT_FLAG.MOUSE_WHEELED: + double velocity = mouseEvent.dwButtonState < 0 ? -1 : 1; wheelDelta = new Vector(0, velocity); - eventType = RawPointerEventType.Wheel; + RaiseMouseEvent(RawPointerEventType.Wheel, + point, + wheelDelta, + inputModifiers); break; - case WindowsConsole.EventFlags.MouseHorizontalWheeled: - return true; - case WindowsConsole.EventFlags.MouseMoved: - eventType = RawPointerEventType.Move; + case MOUSE_EVENT_FLAG.MOUSE_HWHEELED: break; - case WindowsConsole.EventFlags.MouseMoved | WindowsConsole.EventFlags.DoubleClick: - RaiseMouseEvent(RawPointerEventType.LeftButtonDown, point, null, inputModifiers); - RaiseMouseEvent(RawPointerEventType.Move, point, null, inputModifiers); - return false; - default: - throw new InvalidOperationException(mouseEvent.EventFlags.ToString()); - } - - for (short i = 0; i < repeat; i++) - { - RaiseMouseEvent(eventType, - point, - wheelDelta, - inputModifiers); - - if (eventType <= RawPointerEventType.XButton2Down) - RaiseMouseEvent(eventType + 1, + case MOUSE_EVENT_FLAG.MOUSE_MOVED: + RaiseMouseEvent(RawPointerEventType.Move, point, wheelDelta, inputModifiers); + _mouseButtonsState = mouseEvent.dwButtonState; + break; + case MOUSE_EVENT_FLAG.MOUSE_MOVED | MOUSE_EVENT_FLAG.DOUBLE_CLICK: + RaiseMouseEvent(RawPointerEventType.LeftButtonDown, point, null, inputModifiers); + RaiseMouseEvent(RawPointerEventType.Move, point, null, inputModifiers); + //RaiseMouseEvent(RawPointerEventType.LeftButtonUp, point, null, inputModifiers); + break; + default: + throw new InvalidOperationException(mouseEvent.dwEventFlags.ToString()); } - - return false; + _mouseButtonsState = mouseEvent.dwButtonState; } - private void HandleKeyInput(WindowsConsole.InputRecord inputRecord) + private void HandleKeyInput(KEY_EVENT_RECORD keyEvent) { - WindowsConsole.KeyEventRecord keyEvent = inputRecord.KeyEvent; - char character = keyEvent.UnicodeChar; + char character = keyEvent.uChar; RawInputModifiers modifiers = - ModifiersFlagTranslator.Translate(keyEvent.dwControlKeyState); + KeyModifiersTranslator.Translate(keyEvent.dwControlKeyState); Key key = DefaultNetConsole.ConvertToKey((ConsoleKey)keyEvent.wVirtualKeyCode); if (key == Key.LeftAlt || key == Key.RightAlt) modifiers |= RawInputModifiers.Alt; RaiseKeyPress(key, character, modifiers, keyEvent.bKeyDown, (ulong)Stopwatch.GetTimestamp()); } - - #region chatGPT - - // Resharper disable MemberCanBePrivate.Global - // Resharper disable MemberCanBePrivate.Local - // Resharper disable FieldCanBeMadeReadOnly.Global - // Resharper disable FieldCanBeMadeReadOnly.Local - // ReSharper disable InconsistentNaming - [StructLayout(LayoutKind.Sequential)] - private struct INPUT_RECORD - { - public ushort EventType; - public UnionRecord Event; - - [StructLayout(LayoutKind.Explicit)] - public struct UnionRecord - { - [FieldOffset(0)] public KEY_EVENT_RECORD KeyEvent; - - [FieldOffset(0)] public FOCUS_EVENT_RECORD FocusEvent; - // Other event types omitted for brevity - } - } - - [StructLayout(LayoutKind.Sequential)] - internal struct KEY_EVENT_RECORD - { -#pragma warning disable IDE1006 - public bool bKeyDown; -#pragma warning restore IDE1006 - // Other fields omitted for brevity - } - - [StructLayout(LayoutKind.Sequential)] - private struct FOCUS_EVENT_RECORD - { -#pragma warning disable IDE1006 - public bool bSetFocus; -#pragma warning restore IDE1006 - } - - [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] -#pragma warning disable CA5392 - private static extern bool WriteConsoleInput( -#pragma warning restore CA5392 - IntPtr hConsoleInput, - INPUT_RECORD[] lpBuffer, - uint nLength, - out uint lpNumberOfEventsWritten); - // Resharper restore MemberCanBePrivate.Global - // Resharper restore MemberCanBePrivate.Local - // Resharper restore FieldCanBeMadeReadOnly.Global - // Resharper restore FieldCanBeMadeReadOnly.Local - // ReSharper restore InconsistentNaming - - #endregion } } \ No newline at end of file