From b801de1f302d3cd9df3ca9d0a3584921920053bd Mon Sep 17 00:00:00 2001 From: Robert Date: Mon, 6 Dec 2021 00:44:25 +0100 Subject: [PATCH] Windows - Added input provider Debugger - Fixed data model list display --- src/Artemis.Core/Constants.cs | 2 +- .../Services/Input/InputService.cs | 6 +- .../Artemis.UI.Avalonia.Shared.xml | 60 +- ...Model.cs => DataModelListItemViewModel.cs} | 28 +- .../DataModelListPropertiesViewModel.cs | 83 - .../Shared/DataModelListViewModel.cs | 23 +- .../Shared/DataModelVisualizationViewModel.cs | 2 +- .../Display/DefaultDataModelDisplayView.axaml | 13 +- .../DefaultDataModelDisplayViewModel.cs | 36 +- .../Artemis.UI.Shared/Styles/Sidebar.axaml | 4 +- src/Avalonia/Artemis.UI.Windows/App.axaml.cs | 22 +- .../Artemis.UI.Windows.csproj | 3 + .../Providers/Input/SpongeWindow.cs | 26 + .../Providers/Input/SpongeWindowEventArgs.cs | 20 + .../Providers/Input/WindowsInputProvider.cs | 281 ++++ .../Utilities/InputUtilities.cs | 1400 +++++++++++++++++ .../Utilities/WindowUtilities.cs | 23 + .../Artemis.UI.Windows/packages.lock.json | 38 +- .../Providers/AvaloniaInputProvider.cs | 8 - .../Screens/Debugger/DebugView.axaml.cs | 5 + .../Tabs/DataModel/DataModelDebugView.axaml | 79 +- .../Performance/PerformanceDebugView.axaml | 35 +- .../Artemis.UI/Screens/Root/RootViewModel.cs | 25 +- .../Interfaces/IRegistrationService.cs | 1 - .../Services/RegistrationService.cs | 6 - 25 files changed, 1941 insertions(+), 288 deletions(-) rename src/Avalonia/Artemis.UI.Shared/DataModelVisualization/Shared/{DataModelListPropertyViewModel.cs => DataModelListItemViewModel.cs} (64%) delete mode 100644 src/Avalonia/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertiesViewModel.cs create mode 100644 src/Avalonia/Artemis.UI.Windows/Providers/Input/SpongeWindow.cs create mode 100644 src/Avalonia/Artemis.UI.Windows/Providers/Input/SpongeWindowEventArgs.cs create mode 100644 src/Avalonia/Artemis.UI.Windows/Providers/Input/WindowsInputProvider.cs create mode 100644 src/Avalonia/Artemis.UI.Windows/Utilities/InputUtilities.cs create mode 100644 src/Avalonia/Artemis.UI.Windows/Utilities/WindowUtilities.cs delete mode 100644 src/Avalonia/Artemis.UI/Providers/AvaloniaInputProvider.cs diff --git a/src/Artemis.Core/Constants.cs b/src/Artemis.Core/Constants.cs index 1de1f02e4..b63d493c2 100644 --- a/src/Artemis.Core/Constants.cs +++ b/src/Artemis.Core/Constants.cs @@ -27,7 +27,7 @@ namespace Artemis.Core /// /// The base path for Artemis application data folder /// - public static readonly string BaseFolder = Environment.GetFolderPath(OperatingSystem.IsWindows() ? Environment.SpecialFolder.ApplicationData : Environment.SpecialFolder.LocalApplicationData); + public static readonly string BaseFolder = Environment.GetFolderPath(OperatingSystem.IsWindows() ? Environment.SpecialFolder.CommonApplicationData : Environment.SpecialFolder.LocalApplicationData); /// /// The full path to the Artemis data folder diff --git a/src/Artemis.Core/Services/Input/InputService.cs b/src/Artemis.Core/Services/Input/InputService.cs index 9b42bc54f..510b095f7 100644 --- a/src/Artemis.Core/Services/Input/InputService.cs +++ b/src/Artemis.Core/Services/Input/InputService.cs @@ -25,7 +25,11 @@ namespace Artemis.Core.Services public void Dispose() { while (_inputProviders.Any()) - RemoveInputProvider(_inputProviders.First()); + { + InputProvider provider = _inputProviders.First(); + RemoveInputProvider(provider); + provider.Dispose(); + } } #endregion diff --git a/src/Artemis.UI.Avalonia.Shared/Artemis.UI.Avalonia.Shared.xml b/src/Artemis.UI.Avalonia.Shared/Artemis.UI.Avalonia.Shared.xml index 44de98edf..36b985041 100644 --- a/src/Artemis.UI.Avalonia.Shared/Artemis.UI.Avalonia.Shared.xml +++ b/src/Artemis.UI.Avalonia.Shared/Artemis.UI.Avalonia.Shared.xml @@ -374,67 +374,39 @@ - - - Represents a view model that wraps a regular but contained in - a - - - - - Gets the index of the element within the list - - - - - Gets the type of elements contained in the list - - - - - Gets the value of the property that is being visualized - - - - - Gets the view model that handles displaying the property - - - - - - - - - - - - - - - + Represents a view model that visualizes a single data model property contained in a - + + + Gets the view model used to display the display value + + + Gets the index of the element within the list - + Gets the type of elements contained in the list - + + + Gets the value of the property that is being visualized + + + - + - + diff --git a/src/Avalonia/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertyViewModel.cs b/src/Avalonia/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListItemViewModel.cs similarity index 64% rename from src/Avalonia/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertyViewModel.cs rename to src/Avalonia/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListItemViewModel.cs index 161b76cbe..1697e164f 100644 --- a/src/Avalonia/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertyViewModel.cs +++ b/src/Avalonia/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListItemViewModel.cs @@ -9,22 +9,33 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared /// Represents a view model that visualizes a single data model property contained in a /// /// - public class DataModelListPropertyViewModel : DataModelPropertyViewModel + public class DataModelListItemViewModel : DataModelVisualizationViewModel { private int _index; private Type? _listType; + private object? _displayValue; + private DataModelDisplayViewModel? _displayViewModel; - internal DataModelListPropertyViewModel(Type listType, DataModelDisplayViewModel displayViewModel, string? name) : base(null, null, null) + internal DataModelListItemViewModel(Type listType, DataModelDisplayViewModel displayViewModel, string? name) : base(null, null, null) { ListType = listType; DisplayViewModel = displayViewModel; } - internal DataModelListPropertyViewModel(Type listType, string? name) : base(null, null, null) + internal DataModelListItemViewModel(Type listType, string? name) : base(null, null, null) { ListType = listType; } + /// + /// Gets the view model used to display the display value + /// + public DataModelDisplayViewModel? DisplayViewModel + { + get => _displayViewModel; + internal set => this.RaiseAndSetIfChanged(ref _displayViewModel, value); + } + /// /// Gets the index of the element within the list /// @@ -43,6 +54,15 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared private set => this.RaiseAndSetIfChanged(ref _listType, value); } + /// + /// Gets the value of the property that is being visualized + /// + public object? DisplayValue + { + get => _displayValue; + internal set => this.RaiseAndSetIfChanged(ref _displayValue, value); + } + /// public override object? GetCurrentValue() { @@ -66,7 +86,7 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared /// public override string ToString() { - return $"[List item {Index}] {DisplayPath ?? Path} - {DisplayValue}"; + return $"[List item {Index}]"; } } } \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertiesViewModel.cs b/src/Avalonia/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertiesViewModel.cs deleted file mode 100644 index 8bd21ea38..000000000 --- a/src/Avalonia/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertiesViewModel.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System; -using System.Linq; -using Artemis.UI.Shared.Services; -using Artemis.UI.Shared.Services.Interfaces; -using ReactiveUI; - -namespace Artemis.UI.Shared.DataModelVisualization.Shared -{ - /// - /// Represents a view model that wraps a regular but contained in - /// a - /// - public class DataModelListPropertiesViewModel : DataModelPropertiesViewModel - { - private object? _displayValue; - private int _index; - private Type? _listType; - - internal DataModelListPropertiesViewModel(Type listType, string? name) : base(null, null, null) - { - ListType = listType; - } - - /// - /// Gets the index of the element within the list - /// - public int Index - { - get => _index; - set => this.RaiseAndSetIfChanged(ref _index, value); - } - - /// - /// Gets the type of elements contained in the list - /// - public Type? ListType - { - get => _listType; - set => this.RaiseAndSetIfChanged(ref _listType, value); - } - - /// - /// Gets the value of the property that is being visualized - /// - public new object? DisplayValue - { - get => _displayValue; - set => this.RaiseAndSetIfChanged(ref _displayValue, value); - } - - /// - /// Gets the view model that handles displaying the property - /// - public DataModelVisualizationViewModel? DisplayViewModel => Children.FirstOrDefault(); - - /// - public override string? DisplayPath => null; - - /// - public override void Update(IDataModelUIService dataModelUIService, DataModelUpdateConfiguration? configuration) - { - PopulateProperties(dataModelUIService, configuration); - if (DisplayViewModel == null) - return; - - if (IsVisualizationExpanded && !DisplayViewModel.IsVisualizationExpanded) - DisplayViewModel.IsVisualizationExpanded = IsVisualizationExpanded; - DisplayViewModel.Update(dataModelUIService, null); - } - - /// - public override object? GetCurrentValue() - { - return DisplayValue; - } - - /// - public override string ToString() - { - return $"[List item {Index}] {DisplayPath ?? Path}"; - } - } -} \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs b/src/Avalonia/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs index 975a06295..9ec4838d9 100644 --- a/src/Avalonia/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs +++ b/src/Avalonia/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs @@ -98,22 +98,15 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared ListChildren.Add(child); } else - { child = ListChildren[index]; - } - if (child is DataModelListPropertiesViewModel dataModelListClassViewModel) - { - dataModelListClassViewModel.DisplayValue = item; - dataModelListClassViewModel.Index = index; - } - else if (child is DataModelListPropertyViewModel dataModelListPropertyViewModel) + if (child is DataModelListItemViewModel dataModelListPropertyViewModel) { dataModelListPropertyViewModel.DisplayValue = item; dataModelListPropertyViewModel.Index = index; + dataModelListPropertyViewModel.Update(dataModelUIService, configuration); } - child.Update(dataModelUIService, configuration); index++; } @@ -135,16 +128,10 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared { // If a display VM was found, prefer to use that in any case DataModelDisplayViewModel? typeViewModel = dataModelUIService.GetDataModelDisplayViewModel(listType, PropertyDescription); - if (typeViewModel != null) - return new DataModelListPropertyViewModel(listType, typeViewModel, name); - // For primitives, create a property view model, it may be null that is fine - if (listType.IsPrimitive || listType.IsEnum || listType == typeof(string)) - return new DataModelListPropertyViewModel(listType, name); - // For other value types create a child view model - if (listType.IsClass || listType.IsStruct()) - return new DataModelListPropertiesViewModel(listType, name); - return null; + return typeViewModel != null + ? new DataModelListItemViewModel(listType, typeViewModel, name) + : new DataModelListItemViewModel(listType, name); } } } \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs b/src/Avalonia/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs index aaa651957..aef7040af 100644 --- a/src/Avalonia/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs +++ b/src/Avalonia/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs @@ -215,7 +215,7 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared foreach (PropertyInfo propertyInfo in modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(t => t.MetadataToken)) { string childPath = AppendToPath(propertyInfo.Name); - if (Children.Any(c => c.Path != null && c.Path.Equals(childPath))) + if (Children.Any(c => c?.Path != null && c.Path.Equals(childPath))) continue; if (propertyInfo.GetCustomAttribute() != null) continue; diff --git a/src/Avalonia/Artemis.UI.Shared/DefaultTypes/DataModel/Display/DefaultDataModelDisplayView.axaml b/src/Avalonia/Artemis.UI.Shared/DefaultTypes/DataModel/Display/DefaultDataModelDisplayView.axaml index 5a9933b5f..8b3e3f3ee 100644 --- a/src/Avalonia/Artemis.UI.Shared/DefaultTypes/DataModel/Display/DefaultDataModelDisplayView.axaml +++ b/src/Avalonia/Artemis.UI.Shared/DefaultTypes/DataModel/Display/DefaultDataModelDisplayView.axaml @@ -13,17 +13,8 @@ Margin="0 0 5 0" /> - - - + + internal class DefaultDataModelDisplayViewModel : DataModelDisplayViewModel { - private bool _showNull; - private bool _showToString; + private readonly JsonSerializerSettings _serializerSettings; + private string _display; - internal DefaultDataModelDisplayViewModel() + public DefaultDataModelDisplayViewModel() { - ShowNull = true; + _serializerSettings = new JsonSerializerSettings() + { + ReferenceLoopHandling = ReferenceLoopHandling.Ignore, + PreserveReferencesHandling = PreserveReferencesHandling.None + }; } - public bool ShowToString + public string Display { - get => _showToString; - private set => this.RaiseAndSetIfChanged(ref _showToString, value); + get => _display; + set => this.RaiseAndSetIfChanged(ref _display, value); } - - public bool ShowNull - { - get => _showNull; - set => this.RaiseAndSetIfChanged(ref _showNull, value); - } - + protected override void OnDisplayValueUpdated() { if (DisplayValue is Enum enumDisplayValue) - DisplayValue = EnumUtilities.HumanizeValue(enumDisplayValue); - - ShowToString = DisplayValue != null; - ShowNull = DisplayValue == null; + Display = EnumUtilities.HumanizeValue(enumDisplayValue); + else if (DisplayValue is not string) + Display = JsonConvert.SerializeObject(DisplayValue, _serializerSettings); + else + Display = DisplayValue?.ToString() ?? "null"; } } } \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI.Shared/Styles/Sidebar.axaml b/src/Avalonia/Artemis.UI.Shared/Styles/Sidebar.axaml index e4d4ac6b1..95359910d 100644 --- a/src/Avalonia/Artemis.UI.Shared/Styles/Sidebar.axaml +++ b/src/Avalonia/Artemis.UI.Shared/Styles/Sidebar.axaml @@ -13,7 +13,9 @@ + \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI.Windows/App.axaml.cs b/src/Avalonia/Artemis.UI.Windows/App.axaml.cs index 4d6c655bf..e37a0763f 100644 --- a/src/Avalonia/Artemis.UI.Windows/App.axaml.cs +++ b/src/Avalonia/Artemis.UI.Windows/App.axaml.cs @@ -1,3 +1,6 @@ +using Artemis.Core.Services; +using Artemis.UI.Windows.Providers; +using Artemis.UI.Windows.Providers.Input; using Avalonia; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Markup.Xaml; @@ -9,16 +12,13 @@ namespace Artemis.UI.Windows { public class App : Application { - // ReSharper disable NotAccessedField.Local - private StandardKernel? _kernel; - private ApplicationStateManager? _applicationStateManager; - // ReSharper restore NotAccessedField.Local - public override void Initialize() { _kernel = ArtemisBootstrapper.Bootstrap(this); RxApp.MainThreadScheduler = AvaloniaScheduler.Instance; AvaloniaXamlLoader.Load(this); + + RegisterProviders(_kernel); } public override void OnFrameworkInitializationCompleted() @@ -27,5 +27,17 @@ namespace Artemis.UI.Windows if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) _applicationStateManager = new ApplicationStateManager(_kernel!, desktop.Args); } + + private void RegisterProviders(StandardKernel standardKernel) + { + IInputService inputService = standardKernel.Get(); + inputService.AddInputProvider(standardKernel.Get()); + } + + // ReSharper disable NotAccessedField.Local + private StandardKernel? _kernel; + + private ApplicationStateManager? _applicationStateManager; + // ReSharper restore NotAccessedField.Local } } \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI.Windows/Artemis.UI.Windows.csproj b/src/Avalonia/Artemis.UI.Windows/Artemis.UI.Windows.csproj index 36ed75d6c..3e6be8758 100644 --- a/src/Avalonia/Artemis.UI.Windows/Artemis.UI.Windows.csproj +++ b/src/Avalonia/Artemis.UI.Windows/Artemis.UI.Windows.csproj @@ -14,6 +14,9 @@ + + + diff --git a/src/Avalonia/Artemis.UI.Windows/Providers/Input/SpongeWindow.cs b/src/Avalonia/Artemis.UI.Windows/Providers/Input/SpongeWindow.cs new file mode 100644 index 000000000..c2b1ff85c --- /dev/null +++ b/src/Avalonia/Artemis.UI.Windows/Providers/Input/SpongeWindow.cs @@ -0,0 +1,26 @@ +using System; +using Avalonia.Win32; + +namespace Artemis.UI.Windows.Providers.Input +{ + public class SpongeWindow : WindowImpl + { + #region Overrides of WindowImpl + + /// + protected override IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) + { + OnWndProcCalled(new SpongeWindowEventArgs(hWnd, msg, wParam, lParam)); + return base.WndProc(hWnd, msg, wParam, lParam); + } + + #endregion + + public event EventHandler? WndProcCalled; + + protected virtual void OnWndProcCalled(SpongeWindowEventArgs e) + { + WndProcCalled?.Invoke(this, e); + } + } +} \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI.Windows/Providers/Input/SpongeWindowEventArgs.cs b/src/Avalonia/Artemis.UI.Windows/Providers/Input/SpongeWindowEventArgs.cs new file mode 100644 index 000000000..bdf5ec87e --- /dev/null +++ b/src/Avalonia/Artemis.UI.Windows/Providers/Input/SpongeWindowEventArgs.cs @@ -0,0 +1,20 @@ +using System; + +namespace Artemis.UI.Windows.Providers.Input +{ + public class SpongeWindowEventArgs : EventArgs + { + public IntPtr HWnd { get; } + public uint Msg { get; } + public IntPtr WParam { get; } + public IntPtr LParam { get; } + + public SpongeWindowEventArgs(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) + { + HWnd = hWnd; + Msg = msg; + WParam = wParam; + LParam = lParam; + } + } +} \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI.Windows/Providers/Input/WindowsInputProvider.cs b/src/Avalonia/Artemis.UI.Windows/Providers/Input/WindowsInputProvider.cs new file mode 100644 index 000000000..4aca8e831 --- /dev/null +++ b/src/Avalonia/Artemis.UI.Windows/Providers/Input/WindowsInputProvider.cs @@ -0,0 +1,281 @@ +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Timers; +using Artemis.Core; +using Artemis.Core.Services; +using Artemis.UI.Windows.Utilities; +using Linearstar.Windows.RawInput; +using Linearstar.Windows.RawInput.Native; +using Serilog; +using MouseButton = Artemis.Core.Services.MouseButton; + +namespace Artemis.UI.Windows.Providers.Input +{ + public class WindowsInputProvider : InputProvider + { + private const int WM_INPUT = 0x00FF; + + private readonly IInputService _inputService; + private readonly ILogger _logger; + private DateTime _lastMouseUpdate; + private int _lastProcessId; + private SpongeWindow _sponge; + private readonly Timer _taskManagerTimer; + + public WindowsInputProvider(ILogger logger, IInputService inputService) + { + _logger = logger; + _inputService = inputService; + + _sponge = new SpongeWindow(); + _sponge.WndProcCalled += SpongeOnWndProcCalled; + + _taskManagerTimer = new Timer(500); + _taskManagerTimer.Elapsed += TaskManagerTimerOnElapsed; + _taskManagerTimer.Start(); + + RawInputDevice.RegisterDevice(HidUsageAndPage.Keyboard, RawInputDeviceFlags.InputSink, _sponge.Handle.Handle); + RawInputDevice.RegisterDevice(HidUsageAndPage.Mouse, RawInputDeviceFlags.InputSink, _sponge.Handle.Handle); + } + + + #region Overrides of InputProvider + + /// + public override void OnKeyboardToggleStatusRequested() + { + UpdateToggleStatus(); + } + + #endregion + + #region IDisposable + + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + _sponge.Dispose(); + _taskManagerTimer.Dispose(); + } + + base.Dispose(disposing); + } + + #endregion + + private void SpongeOnWndProcCalled(object? sender, SpongeWindowEventArgs message) + { + if (message.Msg != WM_INPUT) + return; + + RawInputData data = RawInputData.FromHandle(message.LParam); + switch (data) + { + case RawInputMouseData mouse: + HandleMouseData(data, mouse); + break; + case RawInputKeyboardData keyboard: + HandleKeyboardData(data, keyboard); + break; + } + } + + private void TaskManagerTimerOnElapsed(object sender, ElapsedEventArgs e) + { + int processId = WindowUtilities.GetActiveProcessId(); + if (processId == _lastProcessId) + return; + + _lastProcessId = processId; + + // If task manager has focus then we can't track keys properly, release everything to avoid them getting stuck + // Same goes for Idle which is what you get when you press Ctrl+Alt+Del + Process active = Process.GetProcessById(processId); + if (active?.ProcessName == "Taskmgr" || active?.ProcessName == "Idle") + _inputService.ReleaseAll(); + } + + #region Keyboard + + private void HandleKeyboardData(RawInputData data, RawInputKeyboardData keyboardData) + { + KeyboardKey key = InputUtilities.KeyFromVirtualKey(keyboardData.Keyboard.VirutalKey); + // Debug.WriteLine($"VK: {key} ({keyboardData.Keyboard.VirutalKey}), Flags: {keyboardData.Keyboard.Flags}, Scan code: {keyboardData.Keyboard.ScanCode}"); + + // Sometimes we get double hits and they resolve to None, ignore those + if (key == KeyboardKey.None) + return; + + // Right alt triggers LeftCtrl with a different scan code for some reason, ignore those + if (key == KeyboardKey.LeftCtrl && keyboardData.Keyboard.ScanCode == 56) + return; + + string identifier = data.Device?.DevicePath; + + // Let the core know there is an identifier so it can store new identifications if applicable + if (identifier != null) + OnIdentifierReceived(identifier, InputDeviceType.Keyboard); + + ArtemisDevice device = null; + if (identifier != null) + try + { + device = _inputService.GetDeviceByIdentifier(this, identifier, InputDeviceType.Keyboard); + } + catch (Exception e) + { + _logger.Warning(e, "Failed to retrieve input device by its identifier"); + } + + // Duplicate keys with different positions can be identified by the LeftKey flag (even though its set of the key that's physically on the right) + if (keyboardData.Keyboard.Flags == RawKeyboardFlags.KeyE0 || keyboardData.Keyboard.Flags == (RawKeyboardFlags.KeyE0 | RawKeyboardFlags.Up)) + { + if (key == KeyboardKey.Enter) + key = KeyboardKey.NumPadEnter; + if (key == KeyboardKey.LeftCtrl) + key = KeyboardKey.RightCtrl; + if (key == KeyboardKey.LeftAlt) + key = KeyboardKey.RightAlt; + } + + if (key == KeyboardKey.LeftShift && keyboardData.Keyboard.ScanCode == 54) + key = KeyboardKey.RightShift; + + bool isDown = keyboardData.Keyboard.Flags != RawKeyboardFlags.Up && + keyboardData.Keyboard.Flags != (RawKeyboardFlags.Up | RawKeyboardFlags.KeyE0) && + keyboardData.Keyboard.Flags != (RawKeyboardFlags.Up | RawKeyboardFlags.KeyE1); + + OnKeyboardDataReceived(device, key, isDown); + UpdateToggleStatus(); + } + + private void UpdateToggleStatus() + { + OnKeyboardToggleStatusReceived(new KeyboardToggleStatus( + InputUtilities.IsKeyToggled(KeyboardKey.NumLock), + InputUtilities.IsKeyToggled(KeyboardKey.CapsLock), + InputUtilities.IsKeyToggled(KeyboardKey.Scroll) + )); + } + + #endregion + + #region Mouse + + private int _mouseDeltaX; + private int _mouseDeltaY; + + private void HandleMouseData(RawInputData data, RawInputMouseData mouseData) + { + // Only submit mouse movement 25 times per second but increment the delta + // This can create a small inaccuracy of course, but Artemis is not a shooter :') + if (mouseData.Mouse.Buttons == RawMouseButtonFlags.None) + { + _mouseDeltaX += mouseData.Mouse.LastX; + _mouseDeltaY += mouseData.Mouse.LastY; + if (DateTime.Now - _lastMouseUpdate < TimeSpan.FromMilliseconds(40)) + return; + } + + ArtemisDevice device = null; + string identifier = data.Device?.DevicePath; + if (identifier != null) + try + { + device = _inputService.GetDeviceByIdentifier(this, identifier, InputDeviceType.Keyboard); + } + catch (Exception e) + { + _logger.Warning(e, "Failed to retrieve input device by its identifier"); + } + + // Debug.WriteLine($"Buttons: {mouseData.Mouse.Buttons}, Data: {mouseData.Mouse.ButtonData}, Flags: {mouseData.Mouse.Flags}, XY: {mouseData.Mouse.LastX},{mouseData.Mouse.LastY}"); + + // Movement + if (mouseData.Mouse.Buttons == RawMouseButtonFlags.None) + { + Win32Point cursorPosition = GetCursorPosition(); + OnMouseMoveDataReceived(device, cursorPosition.X, cursorPosition.Y, _mouseDeltaX, _mouseDeltaY); + _mouseDeltaX = 0; + _mouseDeltaY = 0; + _lastMouseUpdate = DateTime.Now; + return; + } + + // Now we know its not movement, let the core know there is an identifier so it can store new identifications if applicable + if (identifier != null) + OnIdentifierReceived(identifier, InputDeviceType.Mouse); + + // Scrolling + if (mouseData.Mouse.ButtonData != 0) + { + if (mouseData.Mouse.Buttons == RawMouseButtonFlags.MouseWheel) + OnMouseScrollDataReceived(device, MouseScrollDirection.Vertical, mouseData.Mouse.ButtonData); + else if (mouseData.Mouse.Buttons == RawMouseButtonFlags.MouseHorizontalWheel) + OnMouseScrollDataReceived(device, MouseScrollDirection.Horizontal, mouseData.Mouse.ButtonData); + return; + } + + // Button presses + MouseButton button = MouseButton.Left; + bool isDown = false; + + // Left + if (DetermineMouseButton(mouseData, RawMouseButtonFlags.LeftButtonDown, RawMouseButtonFlags.LeftButtonUp, ref isDown)) + button = MouseButton.Left; + // Middle + else if (DetermineMouseButton(mouseData, RawMouseButtonFlags.MiddleButtonDown, RawMouseButtonFlags.MiddleButtonUp, ref isDown)) + button = MouseButton.Middle; + // Right + else if (DetermineMouseButton(mouseData, RawMouseButtonFlags.RightButtonDown, RawMouseButtonFlags.RightButtonUp, ref isDown)) + button = MouseButton.Right; + // Button 4 + else if (DetermineMouseButton(mouseData, RawMouseButtonFlags.Button4Down, RawMouseButtonFlags.Button4Up, ref isDown)) + button = MouseButton.Button4; + else if (DetermineMouseButton(mouseData, RawMouseButtonFlags.Button5Down, RawMouseButtonFlags.Button5Up, ref isDown)) + button = MouseButton.Button5; + + OnMouseButtonDataReceived(device, button, isDown); + } + + private bool DetermineMouseButton(RawInputMouseData data, RawMouseButtonFlags downButton, RawMouseButtonFlags upButton, ref bool isDown) + { + if (data.Mouse.Buttons == downButton || data.Mouse.Buttons == upButton) + { + isDown = data.Mouse.Buttons == downButton; + return true; + } + + isDown = false; + return false; + } + + #endregion + + #region Native + + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool GetCursorPos(ref Win32Point pt); + + [StructLayout(LayoutKind.Sequential)] + private struct Win32Point + { + public readonly int X; + public readonly int Y; + } + + private static Win32Point GetCursorPosition() + { + Win32Point w32Mouse = new(); + GetCursorPos(ref w32Mouse); + + return w32Mouse; + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI.Windows/Utilities/InputUtilities.cs b/src/Avalonia/Artemis.UI.Windows/Utilities/InputUtilities.cs new file mode 100644 index 000000000..04d256df1 --- /dev/null +++ b/src/Avalonia/Artemis.UI.Windows/Utilities/InputUtilities.cs @@ -0,0 +1,1400 @@ +using System; +using System.Runtime.InteropServices; +using Artemis.Core.Services; +using Microsoft.Win32; + +namespace Artemis.UI.Windows.Utilities +{ + /// + /// Provides static methods to convert between Win32 VirtualKeys + /// and our Key enum. + /// + public static class InputUtilities + { + [Flags] + private enum KeyStates + { + None = 0, + Down = 1, + Toggled = 2 + } + + [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] + private static extern short GetKeyState(int keyCode); + + private static KeyStates GetKeyState(KeyboardKey key) + { + KeyStates state = KeyStates.None; + + short retVal = GetKeyState(VirtualKeyFromKey(key)); + + //If the high-order bit is 1, the key is down + //otherwise, it is up. + if ((retVal & 0x8000) == 0x8000) + state |= KeyStates.Down; + + //If the low-order bit is 1, the key is toggled. + if ((retVal & 1) == 1) + state |= KeyStates.Toggled; + + return state; + } + + public static bool IsKeyDown(KeyboardKey key) + { + return KeyStates.Down == (GetKeyState(key) & KeyStates.Down); + } + + public static bool IsKeyToggled(KeyboardKey key) + { + return KeyStates.Toggled == (GetKeyState(key) & KeyStates.Toggled); + } + + /// + /// Convert a Win32 VirtualKey into our Key enum. + /// + public static KeyboardKey KeyFromVirtualKey(int virtualKey) + { + KeyboardKey key = KeyboardKey.None; + + switch (virtualKey) + { + case NativeMethods.VK_CANCEL: + key = KeyboardKey.Cancel; + break; + + case NativeMethods.VK_BACK: + key = KeyboardKey.Back; + break; + + case NativeMethods.VK_TAB: + key = KeyboardKey.Tab; + break; + + case NativeMethods.VK_CLEAR: + key = KeyboardKey.Clear; + break; + + case NativeMethods.VK_RETURN: + key = KeyboardKey.Return; + break; + + case NativeMethods.VK_PAUSE: + key = KeyboardKey.Pause; + break; + + case NativeMethods.VK_CAPSLOCK: + key = KeyboardKey.CapsLock; + break; + + case NativeMethods.VK_JUNJA: + key = KeyboardKey.JunjaMode; + break; + + case NativeMethods.VK_FINAL: + key = KeyboardKey.FinalMode; + break; + + case NativeMethods.VK_ESCAPE: + key = KeyboardKey.Escape; + break; + + case NativeMethods.VK_CONVERT: + key = KeyboardKey.ImeConvert; + break; + + case NativeMethods.VK_NONCONVERT: + key = KeyboardKey.ImeNonConvert; + break; + + case NativeMethods.VK_ACCEPT: + key = KeyboardKey.ImeAccept; + break; + + case NativeMethods.VK_MODECHANGE: + key = KeyboardKey.ImeModeChange; + break; + + case NativeMethods.VK_SPACE: + key = KeyboardKey.Space; + break; + + case NativeMethods.VK_PRIOR: + key = KeyboardKey.Prior; + break; + + case NativeMethods.VK_NEXT: + key = KeyboardKey.Next; + break; + + case NativeMethods.VK_END: + key = KeyboardKey.End; + break; + + case NativeMethods.VK_HOME: + key = KeyboardKey.Home; + break; + + case NativeMethods.VK_LEFT: + key = KeyboardKey.Left; + break; + + case NativeMethods.VK_UP: + key = KeyboardKey.Up; + break; + + case NativeMethods.VK_RIGHT: + key = KeyboardKey.Right; + break; + + case NativeMethods.VK_DOWN: + key = KeyboardKey.Down; + break; + + case NativeMethods.VK_SELECT: + key = KeyboardKey.Select; + break; + + case NativeMethods.VK_PRINT: + key = KeyboardKey.Print; + break; + + case NativeMethods.VK_EXECUTE: + key = KeyboardKey.Execute; + break; + + case NativeMethods.VK_INSERT: + key = KeyboardKey.Insert; + break; + + case NativeMethods.VK_DELETE: + key = KeyboardKey.Delete; + break; + + case NativeMethods.VK_HELP: + key = KeyboardKey.Help; + break; + + case NativeMethods.VK_0: + key = KeyboardKey.D0; + break; + + case NativeMethods.VK_1: + key = KeyboardKey.D1; + break; + + case NativeMethods.VK_2: + key = KeyboardKey.D2; + break; + + case NativeMethods.VK_3: + key = KeyboardKey.D3; + break; + + case NativeMethods.VK_4: + key = KeyboardKey.D4; + break; + + case NativeMethods.VK_5: + key = KeyboardKey.D5; + break; + + case NativeMethods.VK_6: + key = KeyboardKey.D6; + break; + + case NativeMethods.VK_7: + key = KeyboardKey.D7; + break; + + case NativeMethods.VK_8: + key = KeyboardKey.D8; + break; + + case NativeMethods.VK_9: + key = KeyboardKey.D9; + break; + + case NativeMethods.VK_A: + key = KeyboardKey.A; + break; + + case NativeMethods.VK_B: + key = KeyboardKey.B; + break; + + case NativeMethods.VK_C: + key = KeyboardKey.C; + break; + + case NativeMethods.VK_D: + key = KeyboardKey.D; + break; + + case NativeMethods.VK_E: + key = KeyboardKey.E; + break; + + case NativeMethods.VK_F: + key = KeyboardKey.F; + break; + + case NativeMethods.VK_G: + key = KeyboardKey.G; + break; + + case NativeMethods.VK_H: + key = KeyboardKey.H; + break; + + case NativeMethods.VK_I: + key = KeyboardKey.I; + break; + + case NativeMethods.VK_J: + key = KeyboardKey.J; + break; + + case NativeMethods.VK_K: + key = KeyboardKey.K; + break; + + case NativeMethods.VK_L: + key = KeyboardKey.L; + break; + + case NativeMethods.VK_M: + key = KeyboardKey.M; + break; + + case NativeMethods.VK_N: + key = KeyboardKey.N; + break; + + case NativeMethods.VK_O: + key = KeyboardKey.O; + break; + + case NativeMethods.VK_P: + key = KeyboardKey.P; + break; + + case NativeMethods.VK_Q: + key = KeyboardKey.Q; + break; + + case NativeMethods.VK_R: + key = KeyboardKey.R; + break; + + case NativeMethods.VK_S: + key = KeyboardKey.S; + break; + + case NativeMethods.VK_T: + key = KeyboardKey.T; + break; + + case NativeMethods.VK_U: + key = KeyboardKey.U; + break; + + case NativeMethods.VK_V: + key = KeyboardKey.V; + break; + + case NativeMethods.VK_W: + key = KeyboardKey.W; + break; + + case NativeMethods.VK_X: + key = KeyboardKey.X; + break; + + case NativeMethods.VK_Y: + key = KeyboardKey.Y; + break; + + case NativeMethods.VK_Z: + key = KeyboardKey.Z; + break; + + case NativeMethods.VK_LWIN: + key = KeyboardKey.LWin; + break; + + case NativeMethods.VK_RWIN: + key = KeyboardKey.RWin; + break; + + case NativeMethods.VK_APPS: + key = KeyboardKey.Apps; + break; + + case NativeMethods.VK_SLEEP: + key = KeyboardKey.Sleep; + break; + + case NativeMethods.VK_NUMPAD0: + key = KeyboardKey.NumPad0; + break; + + case NativeMethods.VK_NUMPAD1: + key = KeyboardKey.NumPad1; + break; + + case NativeMethods.VK_NUMPAD2: + key = KeyboardKey.NumPad2; + break; + + case NativeMethods.VK_NUMPAD3: + key = KeyboardKey.NumPad3; + break; + + case NativeMethods.VK_NUMPAD4: + key = KeyboardKey.NumPad4; + break; + + case NativeMethods.VK_NUMPAD5: + key = KeyboardKey.NumPad5; + break; + + case NativeMethods.VK_NUMPAD6: + key = KeyboardKey.NumPad6; + break; + + case NativeMethods.VK_NUMPAD7: + key = KeyboardKey.NumPad7; + break; + + case NativeMethods.VK_NUMPAD8: + key = KeyboardKey.NumPad8; + break; + + case NativeMethods.VK_NUMPAD9: + key = KeyboardKey.NumPad9; + break; + + case NativeMethods.VK_MULTIPLY: + key = KeyboardKey.Multiply; + break; + + case NativeMethods.VK_ADD: + key = KeyboardKey.Add; + break; + + case NativeMethods.VK_SEPARATOR: + key = KeyboardKey.Separator; + break; + + case NativeMethods.VK_SUBTRACT: + key = KeyboardKey.Subtract; + break; + + case NativeMethods.VK_DECIMAL: + key = KeyboardKey.Decimal; + break; + + case NativeMethods.VK_DIVIDE: + key = KeyboardKey.Divide; + break; + + case NativeMethods.VK_F1: + key = KeyboardKey.F1; + break; + + case NativeMethods.VK_F2: + key = KeyboardKey.F2; + break; + + case NativeMethods.VK_F3: + key = KeyboardKey.F3; + break; + + case NativeMethods.VK_F4: + key = KeyboardKey.F4; + break; + + case NativeMethods.VK_F5: + key = KeyboardKey.F5; + break; + + case NativeMethods.VK_F6: + key = KeyboardKey.F6; + break; + + case NativeMethods.VK_F7: + key = KeyboardKey.F7; + break; + + case NativeMethods.VK_F8: + key = KeyboardKey.F8; + break; + + case NativeMethods.VK_F9: + key = KeyboardKey.F9; + break; + + case NativeMethods.VK_F10: + key = KeyboardKey.F10; + break; + + case NativeMethods.VK_F11: + key = KeyboardKey.F11; + break; + + case NativeMethods.VK_F12: + key = KeyboardKey.F12; + break; + + case NativeMethods.VK_F13: + key = KeyboardKey.F13; + break; + + case NativeMethods.VK_F14: + key = KeyboardKey.F14; + break; + + case NativeMethods.VK_F15: + key = KeyboardKey.F15; + break; + + case NativeMethods.VK_F16: + key = KeyboardKey.F16; + break; + + case NativeMethods.VK_F17: + key = KeyboardKey.F17; + break; + + case NativeMethods.VK_F18: + key = KeyboardKey.F18; + break; + + case NativeMethods.VK_F19: + key = KeyboardKey.F19; + break; + + case NativeMethods.VK_F20: + key = KeyboardKey.F20; + break; + + case NativeMethods.VK_F21: + key = KeyboardKey.F21; + break; + + case NativeMethods.VK_F22: + key = KeyboardKey.F22; + break; + + case NativeMethods.VK_F23: + key = KeyboardKey.F23; + break; + + case NativeMethods.VK_F24: + key = KeyboardKey.F24; + break; + + case NativeMethods.VK_NUMLOCK: + key = KeyboardKey.NumLock; + break; + + case NativeMethods.VK_SCROLL: + key = KeyboardKey.Scroll; + break; + + case NativeMethods.VK_SHIFT: + case NativeMethods.VK_LSHIFT: + key = KeyboardKey.LeftShift; + break; + + case NativeMethods.VK_RSHIFT: + key = KeyboardKey.RightShift; + break; + + case NativeMethods.VK_CONTROL: + case NativeMethods.VK_LCONTROL: + key = KeyboardKey.LeftCtrl; + break; + + case NativeMethods.VK_RCONTROL: + key = KeyboardKey.RightCtrl; + break; + + case NativeMethods.VK_MENU: + case NativeMethods.VK_LMENU: + key = KeyboardKey.LeftAlt; + break; + + case NativeMethods.VK_RMENU: + key = KeyboardKey.RightAlt; + break; + + case NativeMethods.VK_BROWSER_BACK: + key = KeyboardKey.BrowserBack; + break; + + case NativeMethods.VK_BROWSER_FORWARD: + key = KeyboardKey.BrowserForward; + break; + + case NativeMethods.VK_BROWSER_REFRESH: + key = KeyboardKey.BrowserRefresh; + break; + + case NativeMethods.VK_BROWSER_STOP: + key = KeyboardKey.BrowserStop; + break; + + case NativeMethods.VK_BROWSER_SEARCH: + key = KeyboardKey.BrowserSearch; + break; + + case NativeMethods.VK_BROWSER_FAVORITES: + key = KeyboardKey.BrowserFavorites; + break; + + case NativeMethods.VK_BROWSER_HOME: + key = KeyboardKey.BrowserHome; + break; + + case NativeMethods.VK_VOLUME_MUTE: + key = KeyboardKey.VolumeMute; + break; + + case NativeMethods.VK_VOLUME_DOWN: + key = KeyboardKey.VolumeDown; + break; + + case NativeMethods.VK_VOLUME_UP: + key = KeyboardKey.VolumeUp; + break; + + case NativeMethods.VK_MEDIA_NEXT_TRACK: + key = KeyboardKey.MediaNextTrack; + break; + + case NativeMethods.VK_MEDIA_PREV_TRACK: + key = KeyboardKey.MediaPreviousTrack; + break; + + case NativeMethods.VK_MEDIA_STOP: + key = KeyboardKey.MediaStop; + break; + + case NativeMethods.VK_MEDIA_PLAY_PAUSE: + key = KeyboardKey.MediaPlayPause; + break; + + case NativeMethods.VK_LAUNCH_MAIL: + key = KeyboardKey.LaunchMail; + break; + + case NativeMethods.VK_LAUNCH_MEDIA_SELECT: + key = KeyboardKey.SelectMedia; + break; + + case NativeMethods.VK_LAUNCH_APP1: + key = KeyboardKey.LaunchApplication1; + break; + + case NativeMethods.VK_LAUNCH_APP2: + key = KeyboardKey.LaunchApplication2; + break; + + case NativeMethods.VK_OEM_1: + key = KeyboardKey.OemSemicolon; + break; + + case NativeMethods.VK_OEM_PLUS: + key = KeyboardKey.OemPlus; + break; + + case NativeMethods.VK_OEM_COMMA: + key = KeyboardKey.OemComma; + break; + + case NativeMethods.VK_OEM_MINUS: + key = KeyboardKey.OemMinus; + break; + + case NativeMethods.VK_OEM_PERIOD: + key = KeyboardKey.OemPeriod; + break; + + case NativeMethods.VK_OEM_2: + key = KeyboardKey.OemQuestion; + break; + + case NativeMethods.VK_OEM_3: + key = KeyboardKey.OemTilde; + break; + + + case NativeMethods.VK_OEM_4: + key = KeyboardKey.OemOpenBrackets; + break; + + case NativeMethods.VK_OEM_5: + key = KeyboardKey.OemPipe; + break; + + case NativeMethods.VK_OEM_6: + key = KeyboardKey.OemCloseBrackets; + break; + + case NativeMethods.VK_OEM_7: + key = KeyboardKey.OemQuotes; + break; + + case NativeMethods.VK_OEM_102: + key = KeyboardKey.OemBackslash; + break; + + case NativeMethods.VK_PROCESSKEY: + key = KeyboardKey.ImeProcessed; + break; + + case NativeMethods.VK_OEM_ATTN: // VK_DBE_ALPHANUMERIC + key = KeyboardKey.OemAttn; // DbeAlphanumeric + break; + + case NativeMethods.VK_OEM_FINISH: // VK_DBE_KATAKANA + key = KeyboardKey.OemFinish; // DbeKatakana + break; + + case NativeMethods.VK_OEM_COPY: // VK_DBE_HIRAGANA + key = KeyboardKey.OemCopy; // DbeHiragana + break; + + case NativeMethods.VK_OEM_AUTO: // VK_DBE_SBCSCHAR + key = KeyboardKey.OemAuto; // DbeSbcsChar + break; + + case NativeMethods.VK_OEM_ENLW: // VK_DBE_DBCSCHAR + key = KeyboardKey.OemEnlw; // DbeDbcsChar + break; + + case NativeMethods.VK_OEM_BACKTAB: // VK_DBE_ROMAN + key = KeyboardKey.OemBackTab; // DbeRoman + break; + + case NativeMethods.VK_ATTN: // VK_DBE_NOROMAN + key = KeyboardKey.Attn; // DbeNoRoman + break; + + case NativeMethods.VK_CRSEL: // VK_DBE_ENTERWORDREGISTERMODE + key = KeyboardKey.CrSel; // DbeEnterWordRegisterMode + break; + + case NativeMethods.VK_EXSEL: // VK_DBE_ENTERIMECONFIGMODE + key = KeyboardKey.ExSel; // DbeEnterImeConfigMode + break; + + case NativeMethods.VK_EREOF: // VK_DBE_FLUSHSTRING + key = KeyboardKey.EraseEof; // DbeFlushString + break; + + case NativeMethods.VK_PLAY: // VK_DBE_CODEINPUT + key = KeyboardKey.Play; // DbeCodeInput + break; + + case NativeMethods.VK_ZOOM: // VK_DBE_NOCODEINPUT + key = KeyboardKey.Zoom; // DbeNoCodeInput + break; + + case NativeMethods.VK_NONAME: // VK_DBE_DETERMINESTRING + key = KeyboardKey.NoName; // DbeDetermineString + break; + + case NativeMethods.VK_PA1: // VK_DBE_ENTERDLGCONVERSIONMODE + key = KeyboardKey.Pa1; // DbeEnterDlgConversionMode + break; + + case NativeMethods.VK_OEM_CLEAR: + key = KeyboardKey.OemClear; + break; + + default: + key = KeyboardKey.None; + break; + } + + return key; + } + + /// + /// Convert our Key enum into a Win32 VirtualKeyboardKey. + /// + public static int VirtualKeyFromKey(KeyboardKey key) + { + int virtualKey = 0; + + switch (key) + { + case KeyboardKey.Cancel: + virtualKey = NativeMethods.VK_CANCEL; + break; + + case KeyboardKey.Back: + virtualKey = NativeMethods.VK_BACK; + break; + + case KeyboardKey.Tab: + virtualKey = NativeMethods.VK_TAB; + break; + + case KeyboardKey.Clear: + virtualKey = NativeMethods.VK_CLEAR; + break; + + case KeyboardKey.Return: + virtualKey = NativeMethods.VK_RETURN; + break; + + case KeyboardKey.Pause: + virtualKey = NativeMethods.VK_PAUSE; + break; + + case KeyboardKey.CapsLock: + virtualKey = NativeMethods.VK_CAPSLOCK; + break; + + case KeyboardKey.JunjaMode: + virtualKey = NativeMethods.VK_JUNJA; + break; + + case KeyboardKey.FinalMode: + virtualKey = NativeMethods.VK_FINAL; + break; + + case KeyboardKey.Escape: + virtualKey = NativeMethods.VK_ESCAPE; + break; + + case KeyboardKey.ImeConvert: + virtualKey = NativeMethods.VK_CONVERT; + break; + + case KeyboardKey.ImeNonConvert: + virtualKey = NativeMethods.VK_NONCONVERT; + break; + + case KeyboardKey.ImeAccept: + virtualKey = NativeMethods.VK_ACCEPT; + break; + + case KeyboardKey.ImeModeChange: + virtualKey = NativeMethods.VK_MODECHANGE; + break; + + case KeyboardKey.Space: + virtualKey = NativeMethods.VK_SPACE; + break; + + case KeyboardKey.Prior: + virtualKey = NativeMethods.VK_PRIOR; + break; + + case KeyboardKey.Next: + virtualKey = NativeMethods.VK_NEXT; + break; + + case KeyboardKey.End: + virtualKey = NativeMethods.VK_END; + break; + + case KeyboardKey.Home: + virtualKey = NativeMethods.VK_HOME; + break; + + case KeyboardKey.Left: + virtualKey = NativeMethods.VK_LEFT; + break; + + case KeyboardKey.Up: + virtualKey = NativeMethods.VK_UP; + break; + + case KeyboardKey.Right: + virtualKey = NativeMethods.VK_RIGHT; + break; + + case KeyboardKey.Down: + virtualKey = NativeMethods.VK_DOWN; + break; + + case KeyboardKey.Select: + virtualKey = NativeMethods.VK_SELECT; + break; + + case KeyboardKey.Print: + virtualKey = NativeMethods.VK_PRINT; + break; + + case KeyboardKey.Execute: + virtualKey = NativeMethods.VK_EXECUTE; + break; + + case KeyboardKey.Insert: + virtualKey = NativeMethods.VK_INSERT; + break; + + case KeyboardKey.Delete: + virtualKey = NativeMethods.VK_DELETE; + break; + + case KeyboardKey.Help: + virtualKey = NativeMethods.VK_HELP; + break; + + case KeyboardKey.D0: + virtualKey = NativeMethods.VK_0; + break; + + case KeyboardKey.D1: + virtualKey = NativeMethods.VK_1; + break; + + case KeyboardKey.D2: + virtualKey = NativeMethods.VK_2; + break; + + case KeyboardKey.D3: + virtualKey = NativeMethods.VK_3; + break; + + case KeyboardKey.D4: + virtualKey = NativeMethods.VK_4; + break; + + case KeyboardKey.D5: + virtualKey = NativeMethods.VK_5; + break; + + case KeyboardKey.D6: + virtualKey = NativeMethods.VK_6; + break; + + case KeyboardKey.D7: + virtualKey = NativeMethods.VK_7; + break; + + case KeyboardKey.D8: + virtualKey = NativeMethods.VK_8; + break; + + case KeyboardKey.D9: + virtualKey = NativeMethods.VK_9; + break; + + case KeyboardKey.A: + virtualKey = NativeMethods.VK_A; + break; + + case KeyboardKey.B: + virtualKey = NativeMethods.VK_B; + break; + + case KeyboardKey.C: + virtualKey = NativeMethods.VK_C; + break; + + case KeyboardKey.D: + virtualKey = NativeMethods.VK_D; + break; + + case KeyboardKey.E: + virtualKey = NativeMethods.VK_E; + break; + + case KeyboardKey.F: + virtualKey = NativeMethods.VK_F; + break; + + case KeyboardKey.G: + virtualKey = NativeMethods.VK_G; + break; + + case KeyboardKey.H: + virtualKey = NativeMethods.VK_H; + break; + + case KeyboardKey.I: + virtualKey = NativeMethods.VK_I; + break; + + case KeyboardKey.J: + virtualKey = NativeMethods.VK_J; + break; + + case KeyboardKey.K: + virtualKey = NativeMethods.VK_K; + break; + + case KeyboardKey.L: + virtualKey = NativeMethods.VK_L; + break; + + case KeyboardKey.M: + virtualKey = NativeMethods.VK_M; + break; + + case KeyboardKey.N: + virtualKey = NativeMethods.VK_N; + break; + + case KeyboardKey.O: + virtualKey = NativeMethods.VK_O; + break; + + case KeyboardKey.P: + virtualKey = NativeMethods.VK_P; + break; + + case KeyboardKey.Q: + virtualKey = NativeMethods.VK_Q; + break; + + case KeyboardKey.R: + virtualKey = NativeMethods.VK_R; + break; + + case KeyboardKey.S: + virtualKey = NativeMethods.VK_S; + break; + + case KeyboardKey.T: + virtualKey = NativeMethods.VK_T; + break; + + case KeyboardKey.U: + virtualKey = NativeMethods.VK_U; + break; + + case KeyboardKey.V: + virtualKey = NativeMethods.VK_V; + break; + + case KeyboardKey.W: + virtualKey = NativeMethods.VK_W; + break; + + case KeyboardKey.X: + virtualKey = NativeMethods.VK_X; + break; + + case KeyboardKey.Y: + virtualKey = NativeMethods.VK_Y; + break; + + case KeyboardKey.Z: + virtualKey = NativeMethods.VK_Z; + break; + + case KeyboardKey.LWin: + virtualKey = NativeMethods.VK_LWIN; + break; + + case KeyboardKey.RWin: + virtualKey = NativeMethods.VK_RWIN; + break; + + case KeyboardKey.Apps: + virtualKey = NativeMethods.VK_APPS; + break; + + case KeyboardKey.Sleep: + virtualKey = NativeMethods.VK_SLEEP; + break; + + case KeyboardKey.NumPad0: + virtualKey = NativeMethods.VK_NUMPAD0; + break; + + case KeyboardKey.NumPad1: + virtualKey = NativeMethods.VK_NUMPAD1; + break; + + case KeyboardKey.NumPad2: + virtualKey = NativeMethods.VK_NUMPAD2; + break; + + case KeyboardKey.NumPad3: + virtualKey = NativeMethods.VK_NUMPAD3; + break; + + case KeyboardKey.NumPad4: + virtualKey = NativeMethods.VK_NUMPAD4; + break; + + case KeyboardKey.NumPad5: + virtualKey = NativeMethods.VK_NUMPAD5; + break; + + case KeyboardKey.NumPad6: + virtualKey = NativeMethods.VK_NUMPAD6; + break; + + case KeyboardKey.NumPad7: + virtualKey = NativeMethods.VK_NUMPAD7; + break; + + case KeyboardKey.NumPad8: + virtualKey = NativeMethods.VK_NUMPAD8; + break; + + case KeyboardKey.NumPad9: + virtualKey = NativeMethods.VK_NUMPAD9; + break; + + case KeyboardKey.Multiply: + virtualKey = NativeMethods.VK_MULTIPLY; + break; + + case KeyboardKey.Add: + virtualKey = NativeMethods.VK_ADD; + break; + + case KeyboardKey.Separator: + virtualKey = NativeMethods.VK_SEPARATOR; + break; + + case KeyboardKey.Subtract: + virtualKey = NativeMethods.VK_SUBTRACT; + break; + + case KeyboardKey.Decimal: + virtualKey = NativeMethods.VK_DECIMAL; + break; + + case KeyboardKey.Divide: + virtualKey = NativeMethods.VK_DIVIDE; + break; + + case KeyboardKey.F1: + virtualKey = NativeMethods.VK_F1; + break; + + case KeyboardKey.F2: + virtualKey = NativeMethods.VK_F2; + break; + + case KeyboardKey.F3: + virtualKey = NativeMethods.VK_F3; + break; + + case KeyboardKey.F4: + virtualKey = NativeMethods.VK_F4; + break; + + case KeyboardKey.F5: + virtualKey = NativeMethods.VK_F5; + break; + + case KeyboardKey.F6: + virtualKey = NativeMethods.VK_F6; + break; + + case KeyboardKey.F7: + virtualKey = NativeMethods.VK_F7; + break; + + case KeyboardKey.F8: + virtualKey = NativeMethods.VK_F8; + break; + + case KeyboardKey.F9: + virtualKey = NativeMethods.VK_F9; + break; + + case KeyboardKey.F10: + virtualKey = NativeMethods.VK_F10; + break; + + case KeyboardKey.F11: + virtualKey = NativeMethods.VK_F11; + break; + + case KeyboardKey.F12: + virtualKey = NativeMethods.VK_F12; + break; + + case KeyboardKey.F13: + virtualKey = NativeMethods.VK_F13; + break; + + case KeyboardKey.F14: + virtualKey = NativeMethods.VK_F14; + break; + + case KeyboardKey.F15: + virtualKey = NativeMethods.VK_F15; + break; + + case KeyboardKey.F16: + virtualKey = NativeMethods.VK_F16; + break; + + case KeyboardKey.F17: + virtualKey = NativeMethods.VK_F17; + break; + + case KeyboardKey.F18: + virtualKey = NativeMethods.VK_F18; + break; + + case KeyboardKey.F19: + virtualKey = NativeMethods.VK_F19; + break; + + case KeyboardKey.F20: + virtualKey = NativeMethods.VK_F20; + break; + + case KeyboardKey.F21: + virtualKey = NativeMethods.VK_F21; + break; + + case KeyboardKey.F22: + virtualKey = NativeMethods.VK_F22; + break; + + case KeyboardKey.F23: + virtualKey = NativeMethods.VK_F23; + break; + + case KeyboardKey.F24: + virtualKey = NativeMethods.VK_F24; + break; + + case KeyboardKey.NumLock: + virtualKey = NativeMethods.VK_NUMLOCK; + break; + + case KeyboardKey.Scroll: + virtualKey = NativeMethods.VK_SCROLL; + break; + + case KeyboardKey.LeftShift: + virtualKey = NativeMethods.VK_LSHIFT; + break; + + case KeyboardKey.RightShift: + virtualKey = NativeMethods.VK_RSHIFT; + break; + + case KeyboardKey.LeftCtrl: + virtualKey = NativeMethods.VK_LCONTROL; + break; + + case KeyboardKey.RightCtrl: + virtualKey = NativeMethods.VK_RCONTROL; + break; + + case KeyboardKey.LeftAlt: + virtualKey = NativeMethods.VK_LMENU; + break; + + case KeyboardKey.RightAlt: + virtualKey = NativeMethods.VK_RMENU; + break; + + case KeyboardKey.BrowserBack: + virtualKey = NativeMethods.VK_BROWSER_BACK; + break; + + case KeyboardKey.BrowserForward: + virtualKey = NativeMethods.VK_BROWSER_FORWARD; + break; + + case KeyboardKey.BrowserRefresh: + virtualKey = NativeMethods.VK_BROWSER_REFRESH; + break; + + case KeyboardKey.BrowserStop: + virtualKey = NativeMethods.VK_BROWSER_STOP; + break; + + case KeyboardKey.BrowserSearch: + virtualKey = NativeMethods.VK_BROWSER_SEARCH; + break; + + case KeyboardKey.BrowserFavorites: + virtualKey = NativeMethods.VK_BROWSER_FAVORITES; + break; + + case KeyboardKey.BrowserHome: + virtualKey = NativeMethods.VK_BROWSER_HOME; + break; + + case KeyboardKey.VolumeMute: + virtualKey = NativeMethods.VK_VOLUME_MUTE; + break; + + case KeyboardKey.VolumeDown: + virtualKey = NativeMethods.VK_VOLUME_DOWN; + break; + + case KeyboardKey.VolumeUp: + virtualKey = NativeMethods.VK_VOLUME_UP; + break; + + case KeyboardKey.MediaNextTrack: + virtualKey = NativeMethods.VK_MEDIA_NEXT_TRACK; + break; + + case KeyboardKey.MediaPreviousTrack: + virtualKey = NativeMethods.VK_MEDIA_PREV_TRACK; + break; + + case KeyboardKey.MediaStop: + virtualKey = NativeMethods.VK_MEDIA_STOP; + break; + + case KeyboardKey.MediaPlayPause: + virtualKey = NativeMethods.VK_MEDIA_PLAY_PAUSE; + break; + + case KeyboardKey.LaunchMail: + virtualKey = NativeMethods.VK_LAUNCH_MAIL; + break; + + case KeyboardKey.SelectMedia: + virtualKey = NativeMethods.VK_LAUNCH_MEDIA_SELECT; + break; + + case KeyboardKey.LaunchApplication1: + virtualKey = NativeMethods.VK_LAUNCH_APP1; + break; + + case KeyboardKey.LaunchApplication2: + virtualKey = NativeMethods.VK_LAUNCH_APP2; + break; + + case KeyboardKey.OemSemicolon: + virtualKey = NativeMethods.VK_OEM_1; + break; + + case KeyboardKey.OemPlus: + virtualKey = NativeMethods.VK_OEM_PLUS; + break; + + case KeyboardKey.OemComma: + virtualKey = NativeMethods.VK_OEM_COMMA; + break; + + case KeyboardKey.OemMinus: + virtualKey = NativeMethods.VK_OEM_MINUS; + break; + + case KeyboardKey.OemPeriod: + virtualKey = NativeMethods.VK_OEM_PERIOD; + break; + + case KeyboardKey.OemQuestion: + virtualKey = NativeMethods.VK_OEM_2; + break; + + case KeyboardKey.OemTilde: + virtualKey = NativeMethods.VK_OEM_3; + break; + + case KeyboardKey.OemOpenBrackets: + virtualKey = NativeMethods.VK_OEM_4; + break; + + case KeyboardKey.OemPipe: + virtualKey = NativeMethods.VK_OEM_5; + break; + + case KeyboardKey.OemCloseBrackets: + virtualKey = NativeMethods.VK_OEM_6; + break; + + case KeyboardKey.OemQuotes: + virtualKey = NativeMethods.VK_OEM_7; + break; + + case KeyboardKey.OemBackslash: + virtualKey = NativeMethods.VK_OEM_102; + break; + + case KeyboardKey.ImeProcessed: + virtualKey = NativeMethods.VK_PROCESSKEY; + break; + + case KeyboardKey.OemAttn: // DbeAlphanumeric + virtualKey = NativeMethods.VK_OEM_ATTN; // VK_DBE_ALPHANUMERIC + break; + + case KeyboardKey.OemFinish: // DbeKatakana + virtualKey = NativeMethods.VK_OEM_FINISH; // VK_DBE_KATAKANA + break; + + case KeyboardKey.OemCopy: // DbeHiragana + virtualKey = NativeMethods.VK_OEM_COPY; // VK_DBE_HIRAGANA + break; + + case KeyboardKey.OemAuto: // DbeSbcsChar + virtualKey = NativeMethods.VK_OEM_AUTO; // VK_DBE_SBCSCHAR + break; + + case KeyboardKey.OemEnlw: // DbeDbcsChar + virtualKey = NativeMethods.VK_OEM_ENLW; // VK_DBE_DBCSCHAR + break; + + case KeyboardKey.OemBackTab: // DbeRoman + virtualKey = NativeMethods.VK_OEM_BACKTAB; // VK_DBE_ROMAN + break; + + case KeyboardKey.Attn: // DbeNoRoman + virtualKey = NativeMethods.VK_ATTN; // VK_DBE_NOROMAN + break; + + case KeyboardKey.CrSel: // DbeEnterWordRegisterMode + virtualKey = NativeMethods.VK_CRSEL; // VK_DBE_ENTERWORDREGISTERMODE + break; + + case KeyboardKey.ExSel: // EnterImeConfigureMode + virtualKey = NativeMethods.VK_EXSEL; // VK_DBE_ENTERIMECONFIGMODE + break; + + case KeyboardKey.EraseEof: // DbeFlushString + virtualKey = NativeMethods.VK_EREOF; // VK_DBE_FLUSHSTRING + break; + + case KeyboardKey.Play: // DbeCodeInput + virtualKey = NativeMethods.VK_PLAY; // VK_DBE_CODEINPUT + break; + + case KeyboardKey.Zoom: // DbeNoCodeInput + virtualKey = NativeMethods.VK_ZOOM; // VK_DBE_NOCODEINPUT + break; + + case KeyboardKey.NoName: // DbeDetermineString + virtualKey = NativeMethods.VK_NONAME; // VK_DBE_DETERMINESTRING + break; + + case KeyboardKey.Pa1: // DbeEnterDlgConversionMode + virtualKey = NativeMethods.VK_PA1; // VK_ENTERDLGCONVERSIONMODE + break; + + case KeyboardKey.OemClear: + virtualKey = NativeMethods.VK_OEM_CLEAR; + break; + + case KeyboardKey.DeadCharProcessed: //This is usused. It's just here for completeness. + virtualKey = 0; //There is no Win32 VKey for this. + break; + + default: + virtualKey = 0; + break; + } + + return virtualKey; + } + } +} + diff --git a/src/Avalonia/Artemis.UI.Windows/Utilities/WindowUtilities.cs b/src/Avalonia/Artemis.UI.Windows/Utilities/WindowUtilities.cs new file mode 100644 index 000000000..1f45e44d0 --- /dev/null +++ b/src/Avalonia/Artemis.UI.Windows/Utilities/WindowUtilities.cs @@ -0,0 +1,23 @@ +using System; +using System.Runtime.InteropServices; + +namespace Artemis.UI.Windows.Utilities +{ + public static class WindowUtilities + { + public static int GetActiveProcessId() + { + // Get foreground window handle + IntPtr hWnd = GetForegroundWindow(); + + GetWindowThreadProcessId(hWnd, out uint processId); + return (int) processId; + } + + [DllImport("user32.dll")] + private static extern IntPtr GetForegroundWindow(); + + [DllImport("user32.dll")] + private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); + } +} \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI.Windows/packages.lock.json b/src/Avalonia/Artemis.UI.Windows/packages.lock.json index e5f9d627d..c2d37b9eb 100644 --- a/src/Avalonia/Artemis.UI.Windows/packages.lock.json +++ b/src/Avalonia/Artemis.UI.Windows/packages.lock.json @@ -53,6 +53,33 @@ "System.Reactive": "5.0.0" } }, + "Avalonia.Win32": { + "type": "Direct", + "requested": "[0.10.10, )", + "resolved": "0.10.10", + "contentHash": "6AS6yIB+OS8+g96mj+ShJihjxqhVH6v7jfdqLwjQfGAsqqqN7zBNsFdvoVVCnutuVx0g/9FhCnBTIZyZDlwqkA==", + "dependencies": { + "Avalonia": "0.10.10", + "Avalonia.Angle.Windows.Natives": "2.1.0.2020091801", + "System.Drawing.Common": "4.5.0", + "System.Numerics.Vectors": "4.5.0" + } + }, + "Microsoft.Win32": { + "type": "Direct", + "requested": "[2.0.1, )", + "resolved": "2.0.1", + "contentHash": "V1I3Mvj0g6YFoVywl0uoPh7fJ4y7xTewBGrW9FN70dr9LruFnC4rJ/bJ2wxIvZyeVrsj2JaqxvkuSw9fhk9UKA==" + }, + "RawInput.Sharp": { + "type": "Direct", + "requested": "[0.0.4, )", + "resolved": "0.0.4", + "contentHash": "JAHC4oBBzvwvehjiWTUW0UAjptprQuX+21d/7LrsMAjBSrT9GB6q6JiEm0bQi69uTkBPohHNF7O8Wgcz3oVXkA==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, "Avalonia.Angle.Windows.Natives": { "type": "Transitive", "resolved": "2.1.0.2020091801", @@ -122,17 +149,6 @@ "Svg.Skia": "0.5.10" } }, - "Avalonia.Win32": { - "type": "Transitive", - "resolved": "0.10.10", - "contentHash": "6AS6yIB+OS8+g96mj+ShJihjxqhVH6v7jfdqLwjQfGAsqqqN7zBNsFdvoVVCnutuVx0g/9FhCnBTIZyZDlwqkA==", - "dependencies": { - "Avalonia": "0.10.10", - "Avalonia.Angle.Windows.Natives": "2.1.0.2020091801", - "System.Drawing.Common": "4.5.0", - "System.Numerics.Vectors": "4.5.0" - } - }, "Avalonia.X11": { "type": "Transitive", "resolved": "0.10.10", diff --git a/src/Avalonia/Artemis.UI/Providers/AvaloniaInputProvider.cs b/src/Avalonia/Artemis.UI/Providers/AvaloniaInputProvider.cs deleted file mode 100644 index 72a8d394b..000000000 --- a/src/Avalonia/Artemis.UI/Providers/AvaloniaInputProvider.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Artemis.Core.Services; - -namespace Artemis.UI.Providers -{ - public class AvaloniaInputProvider : InputProvider - { - } -} \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI/Screens/Debugger/DebugView.axaml.cs b/src/Avalonia/Artemis.UI/Screens/Debugger/DebugView.axaml.cs index 07bc6b909..5d4428442 100644 --- a/src/Avalonia/Artemis.UI/Screens/Debugger/DebugView.axaml.cs +++ b/src/Avalonia/Artemis.UI/Screens/Debugger/DebugView.axaml.cs @@ -2,6 +2,7 @@ using System; using System.Reactive.Disposables; using System.Reactive.Linq; using Artemis.UI.Shared.Events; +using Avalonia; using Avalonia.Controls; using Avalonia.Markup.Xaml; using Avalonia.ReactiveUI; @@ -16,6 +17,10 @@ namespace Artemis.UI.Screens.Debugger public DebugView() { InitializeComponent(); +#if DEBUG + this.AttachDevTools(); +#endif + NavigationView navigation = this.Get("Navigation"); this.WhenActivated(d => diff --git a/src/Avalonia/Artemis.UI/Screens/Debugger/Tabs/DataModel/DataModelDebugView.axaml b/src/Avalonia/Artemis.UI/Screens/Debugger/Tabs/DataModel/DataModelDebugView.axaml index 4e8fb46ef..4032e4ec9 100644 --- a/src/Avalonia/Artemis.UI/Screens/Debugger/Tabs/DataModel/DataModelDebugView.axaml +++ b/src/Avalonia/Artemis.UI/Screens/Debugger/Tabs/DataModel/DataModelDebugView.axaml @@ -7,23 +7,25 @@ mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="Artemis.UI.Screens.Debugger.Tabs.DataModel.DataModelDebugView"> - + - - Data Model - - On this page you can view the contents of the Artemis data model. - - - Please note that having this window open can have a performance impact on your system. - + + + Data Model + + On this page you can view the contents of the Artemis data model. + + + Please note that having this window open can have a performance impact on your system. + + - - - - + + + + @@ -35,9 +37,9 @@ + Text="{Binding DisplayValue}" + FontFamily="Consolas" + HorizontalAlignment="Right" /> @@ -50,9 +52,9 @@ + Text="{Binding CountDisplay, Mode=OneWay}" + FontFamily="Consolas" + HorizontalAlignment="Right" /> @@ -70,22 +72,20 @@ - + - [ - + ] - - List item [ - - ] - + + List item # + + - + @@ -99,20 +99,13 @@ + Text="{Binding CountDisplay, Mode=OneWay}" + FontFamily="Consolas" + HorizontalAlignment="Right" /> + + + - - - List item [ - - ] - - - - - \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI/Screens/Debugger/Tabs/Performance/PerformanceDebugView.axaml b/src/Avalonia/Artemis.UI/Screens/Debugger/Tabs/Performance/PerformanceDebugView.axaml index 15a902eed..a028787f8 100644 --- a/src/Avalonia/Artemis.UI/Screens/Debugger/Tabs/Performance/PerformanceDebugView.axaml +++ b/src/Avalonia/Artemis.UI/Screens/Debugger/Tabs/Performance/PerformanceDebugView.axaml @@ -5,22 +5,25 @@ xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="Artemis.UI.Screens.Debugger.Tabs.Performance.PerformanceDebugView"> - - Performance - - On this page you can see how much CPU time different plugin features are taking. If you are having performance issues, below you can find out which plugin might be the culprit. - - - - These performance stats are rather basic, for advanced performance profiling check out the wiki. + + + Performance + + On this page you can see how much CPU time different plugin features are taking. If you are having performance issues, below you can find out which plugin might be the culprit. - - JetBrains Profiling Guide - - + + + These performance stats are rather basic, for advanced performance profiling check out the wiki. + + + JetBrains Profiling Guide + + + + + + + + - - - - \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI/Screens/Root/RootViewModel.cs b/src/Avalonia/Artemis.UI/Screens/Root/RootViewModel.cs index 177d5496a..68c7cd9be 100644 --- a/src/Avalonia/Artemis.UI/Screens/Root/RootViewModel.cs +++ b/src/Avalonia/Artemis.UI/Screens/Root/RootViewModel.cs @@ -4,11 +4,7 @@ using System.Threading.Tasks; using Artemis.Core; using Artemis.Core.Services; using Artemis.UI.Ninject.Factories; -using Artemis.UI.Screens.Home; using Artemis.UI.Screens.Root.Sidebar; -using Artemis.UI.Screens.Settings; -using Artemis.UI.Screens.SurfaceEditor; -using Artemis.UI.Screens.Workshop; using Artemis.UI.Services.Interfaces; using Artemis.UI.Shared; using Artemis.UI.Shared.Services.Interfaces; @@ -18,21 +14,19 @@ using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Platform; using Avalonia.Threading; -using Ninject; -using Ninject.Parameters; using ReactiveUI; namespace Artemis.UI.Screens.Root { public class RootViewModel : ActivatableViewModelBase, IScreen, IMainWindowProvider { - private readonly IClassicDesktopStyleApplicationLifetime _lifeTime; - private readonly ICoreService _coreService; - private readonly ISettingsService _settingsService; - private readonly IWindowService _windowService; - private readonly IDebugService _debugService; private readonly IAssetLoader _assetLoader; + private readonly ICoreService _coreService; + private readonly IDebugService _debugService; + private readonly IClassicDesktopStyleApplicationLifetime _lifeTime; + private readonly ISettingsService _settingsService; private readonly ISidebarVmFactory _sidebarVmFactory; + private readonly IWindowService _windowService; private SidebarViewModel? _sidebarViewModel; private TrayIcon? _trayIcon; private TrayIcons? _trayIcons; @@ -58,7 +52,6 @@ namespace Artemis.UI.Screens.Root coreService.StartupArguments = _lifeTime.Args.ToList(); mainWindowService.ConfigureMainWindowProvider(this); - registrationService.RegisterProviders(); DisplayAccordingToSettings(); Task.Run(coreService.Initialize); @@ -70,9 +63,6 @@ namespace Artemis.UI.Screens.Root set => this.RaiseAndSetIfChanged(ref _sidebarViewModel, value); } - /// - public RoutingState Router { get; } - private void CurrentMainWindowOnClosed(object? sender, EventArgs e) { _lifeTime.MainWindow = null; @@ -113,7 +103,7 @@ namespace Artemis.UI.Screens.Root { _trayIcon = new TrayIcon { - Icon = new WindowIcon(_assetLoader.Open(new Uri("avares://Artemis.UI/Assets/Images/Logo/bow.ico"))), + Icon = new WindowIcon(_assetLoader.Open(new Uri("avares://Artemis.UI/Assets/Images/Logo/bow.ico"))), Command = ReactiveCommand.Create(OpenMainWindow) }; _trayIcon.Menu = (NativeMenu?) Application.Current.FindResource("TrayIconMenu"); @@ -130,6 +120,9 @@ namespace Artemis.UI.Screens.Root _trayIcons = null; } + /// + public RoutingState Router { get; } + #region Tray commands public void OpenScreen(string displayName) diff --git a/src/Avalonia/Artemis.UI/Services/Interfaces/IRegistrationService.cs b/src/Avalonia/Artemis.UI/Services/Interfaces/IRegistrationService.cs index 86b0f2d50..4c45d8b28 100644 --- a/src/Avalonia/Artemis.UI/Services/Interfaces/IRegistrationService.cs +++ b/src/Avalonia/Artemis.UI/Services/Interfaces/IRegistrationService.cs @@ -5,7 +5,6 @@ void RegisterBuiltInDataModelDisplays(); void RegisterBuiltInDataModelInputs(); void RegisterBuiltInPropertyEditors(); - void RegisterProviders(); void RegisterControllers(); void ApplyPreferredGraphicsContext(); } diff --git a/src/Avalonia/Artemis.UI/Services/RegistrationService.cs b/src/Avalonia/Artemis.UI/Services/RegistrationService.cs index e6a1f9b4d..c2681436a 100644 --- a/src/Avalonia/Artemis.UI/Services/RegistrationService.cs +++ b/src/Avalonia/Artemis.UI/Services/RegistrationService.cs @@ -1,5 +1,4 @@ using Artemis.Core.Services; -using Artemis.UI.Providers; using Artemis.UI.Services.Interfaces; namespace Artemis.UI.Services @@ -24,11 +23,6 @@ namespace Artemis.UI.Services { } - public void RegisterProviders() - { - _inputService.AddInputProvider(new AvaloniaInputProvider()); - } - public void RegisterControllers() { }