From 3d4a2781b0654cf7e2f4a488c510d3bb624ac89f Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Sat, 10 Aug 2019 10:21:26 +0300 Subject: [PATCH 1/6] Switched key events to use KeyModifiers --- .../Platform/InProcessDragSource.cs | 16 ++++++---- .../Remote/Server/RemoteServerTopLevelImpl.cs | 6 +++- src/Avalonia.Diagnostics/DevTools.xaml.cs | 4 +-- src/Avalonia.Input/IKeyboardDevice.cs | 31 ++++++++++++++++++- src/Avalonia.Input/KeyEventArgs.cs | 5 ++- src/Avalonia.Input/KeyGesture.cs | 9 +++++- src/Avalonia.Input/KeyboardDevice.cs | 2 +- src/Avalonia.Input/Raw/RawKeyEventArgs.cs | 4 +-- src/Avalonia.Native/WindowImplBase.cs | 2 +- src/Avalonia.X11/X11Window.cs | 3 +- .../Input/WindowsKeyboardDevice.cs | 1 + src/Windows/Avalonia.Win32/WindowImpl.cs | 4 +-- .../TextBoxTests.cs | 30 +++++++++--------- .../TopLevelTests.cs | 2 +- .../TreeViewTests.cs | 6 ++-- 15 files changed, 87 insertions(+), 38 deletions(-) diff --git a/src/Avalonia.Controls/Platform/InProcessDragSource.cs b/src/Avalonia.Controls/Platform/InProcessDragSource.cs index 85916bcdd0..d4df41d2f2 100644 --- a/src/Avalonia.Controls/Platform/InProcessDragSource.cs +++ b/src/Avalonia.Controls/Platform/InProcessDragSource.cs @@ -57,11 +57,15 @@ namespace Avalonia.Platform } - private DragDropEffects RaiseEventAndUpdateCursor(RawDragEventType type, IInputElement root, Point pt, InputModifiers modifiers) + private DragDropEffects RaiseEventAndUpdateCursor(RawDragEventType type, IInputElement root, Point pt, + InputModifiers modifiers) + => RaiseEventAndUpdateCursor(type, root, pt, (RawInputModifiers)modifiers); + + private DragDropEffects RaiseEventAndUpdateCursor(RawDragEventType type, IInputElement root, Point pt, RawInputModifiers modifiers) { _lastPosition = pt; - RawDragEvent rawEvent = new RawDragEvent(_dragDrop, type, root, pt, _draggedData, _allowedEffects, modifiers); + RawDragEvent rawEvent = new RawDragEvent(_dragDrop, type, root, pt, _draggedData, _allowedEffects, (InputModifiers)modifiers); var tl = root.GetSelfAndVisualAncestors().OfType().FirstOrDefault(); tl.PlatformImpl?.Input(rawEvent); @@ -70,13 +74,13 @@ namespace Avalonia.Platform return effect; } - private DragDropEffects GetPreferredEffect(DragDropEffects effect, InputModifiers modifiers) + private DragDropEffects GetPreferredEffect(DragDropEffects effect, RawInputModifiers modifiers) { if (effect == DragDropEffects.Copy || effect == DragDropEffects.Move || effect == DragDropEffects.Link || effect == DragDropEffects.None) return effect; // No need to check for the modifiers. - if (effect.HasFlag(DragDropEffects.Link) && modifiers.HasFlag(InputModifiers.Alt)) + if (effect.HasFlag(DragDropEffects.Link) && modifiers.HasFlag(RawInputModifiers.Alt)) return DragDropEffects.Link; - if (effect.HasFlag(DragDropEffects.Copy) && modifiers.HasFlag(InputModifiers.Control)) + if (effect.HasFlag(DragDropEffects.Copy) && modifiers.HasFlag(RawInputModifiers.Control)) return DragDropEffects.Copy; return DragDropEffects.Move; } @@ -132,7 +136,7 @@ namespace Avalonia.Platform private void CancelDragging() { if (_lastRoot != null) - RaiseEventAndUpdateCursor(RawDragEventType.DragLeave, _lastRoot, _lastPosition, InputModifiers.None); + RaiseEventAndUpdateCursor(RawDragEventType.DragLeave, _lastRoot, _lastPosition, RawInputModifiers.None); UpdateCursor(null, DragDropEffects.None); _result.OnNext(DragDropEffects.None); } diff --git a/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs b/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs index 1ef03b49ce..cfd28106eb 100644 --- a/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs +++ b/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs @@ -57,6 +57,10 @@ namespace Avalonia.Controls.Remote.Server } } + private static RawInputModifiers GetAvaloniaRawInputModifiers( + Avalonia.Remote.Protocol.Input.InputModifiers[] modifiers) + => (RawInputModifiers)GetAvaloniaInputModifiers(modifiers); + private static InputModifiers GetAvaloniaInputModifiers (Avalonia.Remote.Protocol.Input.InputModifiers[] modifiers) { var result = InputModifiers.None; @@ -225,7 +229,7 @@ namespace Avalonia.Controls.Remote.Server 0, key.IsDown ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp, (Key)key.Key, - GetAvaloniaInputModifiers(key.Modifiers))); + GetAvaloniaRawInputModifiers(key.Modifiers))); }, DispatcherPriority.Input); } if(obj is TextInputEventMessage text) diff --git a/src/Avalonia.Diagnostics/DevTools.xaml.cs b/src/Avalonia.Diagnostics/DevTools.xaml.cs index ddd3e29e43..1fcfb525cb 100644 --- a/src/Avalonia.Diagnostics/DevTools.xaml.cs +++ b/src/Avalonia.Diagnostics/DevTools.xaml.cs @@ -116,9 +116,9 @@ namespace Avalonia.Diagnostics private void RawKeyDown(RawKeyEventArgs e) { - const InputModifiers modifiers = InputModifiers.Control | InputModifiers.Shift; + const RawInputModifiers modifiers = RawInputModifiers.Control | RawInputModifiers.Shift; - if ((e.Modifiers) == modifiers) + if (e.Modifiers == modifiers) { var point = (Root.VisualRoot as IInputRoot)?.MouseDevice?.GetPosition(Root) ?? default(Point); var control = Root.GetVisualsAt(point, x => (!(x is AdornerLayer) && x.IsVisible)) diff --git a/src/Avalonia.Input/IKeyboardDevice.cs b/src/Avalonia.Input/IKeyboardDevice.cs index 1410476267..6b3e8435d9 100644 --- a/src/Avalonia.Input/IKeyboardDevice.cs +++ b/src/Avalonia.Input/IKeyboardDevice.cs @@ -6,7 +6,7 @@ using System.ComponentModel; namespace Avalonia.Input { - [Flags] + [Flags, Obsolete("Use KeyModifiers and PointerPointProperties")] public enum InputModifiers { None = 0, @@ -19,6 +19,16 @@ namespace Avalonia.Input MiddleMouseButton = 64 } + [Flags] + public enum KeyModifiers + { + None = 0, + Alt = 1, + Control = 2, + Shift = 4, + Meta = 8, + } + [Flags] public enum KeyStates { @@ -27,6 +37,25 @@ namespace Avalonia.Input Toggled = 2, } + public enum RawInputModifiers + { + None = 0, + Alt = 1, + Control = 2, + Shift = 4, + Meta = 8, + LeftMouseButton = 16, + RightMouseButton = 32, + MiddleMouseButton = 64, + KeyboardMask = Alt | Control | Shift | Meta + } + + internal static class KeyModifiersUtils + { + public static KeyModifiers ConvertToKey(RawInputModifiers modifiers) => + (KeyModifiers)(modifiers & RawInputModifiers.KeyboardMask); + } + public interface IKeyboardDevice : IInputDevice, INotifyPropertyChanged { IInputElement FocusedElement { get; } diff --git a/src/Avalonia.Input/KeyEventArgs.cs b/src/Avalonia.Input/KeyEventArgs.cs index 89053c6f61..8aef81503f 100644 --- a/src/Avalonia.Input/KeyEventArgs.cs +++ b/src/Avalonia.Input/KeyEventArgs.cs @@ -1,6 +1,7 @@ // Copyright (c) The Avalonia Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. +using System; using Avalonia.Interactivity; namespace Avalonia.Input @@ -11,6 +12,8 @@ namespace Avalonia.Input public Key Key { get; set; } - public InputModifiers Modifiers { get; set; } + [Obsolete("Use KeyModifiers")] + public InputModifiers Modifiers => (InputModifiers)KeyModifiers; + public KeyModifiers KeyModifiers { get; set; } } } diff --git a/src/Avalonia.Input/KeyGesture.cs b/src/Avalonia.Input/KeyGesture.cs index c945902def..2377edf640 100644 --- a/src/Avalonia.Input/KeyGesture.cs +++ b/src/Avalonia.Input/KeyGesture.cs @@ -51,7 +51,14 @@ namespace Avalonia.Input public Key Key { get; set; } - public InputModifiers Modifiers { get; set; } + [Obsolete("Use KeyModifiers")] + public InputModifiers Modifiers + { + get => (InputModifiers)KeyModifiers; + set => KeyModifiers = (KeyModifiers)(((int)value) & 0xf); + } + + public KeyModifiers KeyModifiers { get; set; } static readonly Dictionary KeySynonyms = new Dictionary diff --git a/src/Avalonia.Input/KeyboardDevice.cs b/src/Avalonia.Input/KeyboardDevice.cs index 00606bd9b1..a02c580ad2 100644 --- a/src/Avalonia.Input/KeyboardDevice.cs +++ b/src/Avalonia.Input/KeyboardDevice.cs @@ -91,7 +91,7 @@ namespace Avalonia.Input RoutedEvent = routedEvent, Device = this, Key = keyInput.Key, - Modifiers = keyInput.Modifiers, + KeyModifiers = KeyModifiersUtils.ConvertToKey(keyInput.Modifiers), Source = element, }; diff --git a/src/Avalonia.Input/Raw/RawKeyEventArgs.cs b/src/Avalonia.Input/Raw/RawKeyEventArgs.cs index 044f244138..cd8b2eacf7 100644 --- a/src/Avalonia.Input/Raw/RawKeyEventArgs.cs +++ b/src/Avalonia.Input/Raw/RawKeyEventArgs.cs @@ -15,7 +15,7 @@ namespace Avalonia.Input.Raw IKeyboardDevice device, ulong timestamp, RawKeyEventType type, - Key key, InputModifiers modifiers) + Key key, RawInputModifiers modifiers) : base(device, timestamp) { Key = key; @@ -25,7 +25,7 @@ namespace Avalonia.Input.Raw public Key Key { get; set; } - public InputModifiers Modifiers { get; set; } + public RawInputModifiers Modifiers { get; set; } public RawKeyEventType Type { get; set; } } diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index ae0a2f535b..dd03f7d81e 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -209,7 +209,7 @@ namespace Avalonia.Native { Dispatcher.UIThread.RunJobs(DispatcherPriority.Input + 1); - var args = new RawKeyEventArgs(_keyboard, timeStamp, (RawKeyEventType)type, (Key)key, (InputModifiers)modifiers); + var args = new RawKeyEventArgs(_keyboard, timeStamp, (RawKeyEventType)type, (Key)key, (RawInputModifiers)modifiers); Input?.Invoke(args); diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 5481862f23..95b3e40063 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -438,7 +438,7 @@ namespace Avalonia.X11 ScheduleInput(new RawKeyEventArgs(_keyboard, (ulong)ev.KeyEvent.time.ToInt64(), ev.type == XEventName.KeyPress ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp, - X11KeyTransform.ConvertKey(key), TranslateModifiers(ev.KeyEvent.state)), ref ev); + X11KeyTransform.ConvertKey(key), TranslateRawModifiers(ev.KeyEvent.state)), ref ev); if (ev.type == XEventName.KeyPress) { @@ -559,6 +559,7 @@ namespace Avalonia.X11 } + RawInputModifiers TranslateRawModifiers(XModifierMask state) => (RawInputModifiers)TranslateModifiers(state); InputModifiers TranslateModifiers(XModifierMask state) { var rv = default(InputModifiers); diff --git a/src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs b/src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs index fee1fe2ae6..93adf7bee3 100644 --- a/src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs +++ b/src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs @@ -14,6 +14,7 @@ namespace Avalonia.Win32.Input public new static WindowsKeyboardDevice Instance { get; } = new WindowsKeyboardDevice(); + public RawInputModifiers RawModifiers => (RawInputModifiers)Modifiers; public InputModifiers Modifiers { get diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index e33e1f11dc..65fb2e447e 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -510,7 +510,7 @@ namespace Avalonia.Win32 WindowsKeyboardDevice.Instance, timestamp, RawKeyEventType.KeyDown, - KeyInterop.KeyFromVirtualKey(ToInt32(wParam)), WindowsKeyboardDevice.Instance.Modifiers); + KeyInterop.KeyFromVirtualKey(ToInt32(wParam)), WindowsKeyboardDevice.Instance.RawModifiers); break; case UnmanagedMethods.WindowsMessage.WM_MENUCHAR: @@ -523,7 +523,7 @@ namespace Avalonia.Win32 WindowsKeyboardDevice.Instance, timestamp, RawKeyEventType.KeyUp, - KeyInterop.KeyFromVirtualKey(ToInt32(wParam)), WindowsKeyboardDevice.Instance.Modifiers); + KeyInterop.KeyFromVirtualKey(ToInt32(wParam)), WindowsKeyboardDevice.Instance.RawModifiers); break; case UnmanagedMethods.WindowsMessage.WM_CHAR: // Ignore control chars diff --git a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs index 35f0b39210..febc1de5f9 100644 --- a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs @@ -55,7 +55,7 @@ namespace Avalonia.Controls.UnitTests Text = "1234" }; - RaiseKeyEvent(target, Key.A, InputModifiers.Control); + RaiseKeyEvent(target, Key.A, KeyModifiers.Control); Assert.Equal(0, target.SelectionStart); Assert.Equal(4, target.SelectionEnd); @@ -72,7 +72,7 @@ namespace Avalonia.Controls.UnitTests Template = CreateTemplate() }; - RaiseKeyEvent(target, Key.A, InputModifiers.Control); + RaiseKeyEvent(target, Key.A, KeyModifiers.Control); Assert.Equal(0, target.SelectionStart); Assert.Equal(0, target.SelectionEnd); @@ -90,7 +90,7 @@ namespace Avalonia.Controls.UnitTests Text = "1234" }; - RaiseKeyEvent(target, Key.Z, InputModifiers.Control); + RaiseKeyEvent(target, Key.Z, KeyModifiers.Control); Assert.Equal("1234", target.Text); } @@ -136,29 +136,29 @@ namespace Avalonia.Controls.UnitTests }; // (First| Second Third Fourth) - RaiseKeyEvent(textBox, Key.Back, InputModifiers.Control); + RaiseKeyEvent(textBox, Key.Back, KeyModifiers.Control); Assert.Equal(" Second Third Fourth", textBox.Text); // ( Second |Third Fourth) textBox.CaretIndex = 8; - RaiseKeyEvent(textBox, Key.Back, InputModifiers.Control); + RaiseKeyEvent(textBox, Key.Back, KeyModifiers.Control); Assert.Equal(" Third Fourth", textBox.Text); // ( Thi|rd Fourth) textBox.CaretIndex = 4; - RaiseKeyEvent(textBox, Key.Back, InputModifiers.Control); + RaiseKeyEvent(textBox, Key.Back, KeyModifiers.Control); Assert.Equal(" rd Fourth", textBox.Text); // ( rd F[ou]rth) textBox.SelectionStart = 5; textBox.SelectionEnd = 7; - RaiseKeyEvent(textBox, Key.Back, InputModifiers.Control); + RaiseKeyEvent(textBox, Key.Back, KeyModifiers.Control); Assert.Equal(" rd Frth", textBox.Text); // ( |rd Frth) textBox.CaretIndex = 1; - RaiseKeyEvent(textBox, Key.Back, InputModifiers.Control); + RaiseKeyEvent(textBox, Key.Back, KeyModifiers.Control); Assert.Equal("rd Frth", textBox.Text); } } @@ -175,30 +175,30 @@ namespace Avalonia.Controls.UnitTests }; // (First Second Third |Fourth) - RaiseKeyEvent(textBox, Key.Delete, InputModifiers.Control); + RaiseKeyEvent(textBox, Key.Delete, KeyModifiers.Control); Assert.Equal("First Second Third ", textBox.Text); // (First Second |Third ) textBox.CaretIndex = 13; - RaiseKeyEvent(textBox, Key.Delete, InputModifiers.Control); + RaiseKeyEvent(textBox, Key.Delete, KeyModifiers.Control); Assert.Equal("First Second ", textBox.Text); // (First Sec|ond ) textBox.CaretIndex = 9; - RaiseKeyEvent(textBox, Key.Delete, InputModifiers.Control); + RaiseKeyEvent(textBox, Key.Delete, KeyModifiers.Control); Assert.Equal("First Sec", textBox.Text); // (Fi[rs]t Sec ) textBox.SelectionStart = 2; textBox.SelectionEnd = 4; - RaiseKeyEvent(textBox, Key.Delete, InputModifiers.Control); + RaiseKeyEvent(textBox, Key.Delete, KeyModifiers.Control); Assert.Equal("Fit Sec", textBox.Text); // (Fit Sec| ) textBox.Text += " "; textBox.CaretIndex = 7; - RaiseKeyEvent(textBox, Key.Delete, InputModifiers.Control); + RaiseKeyEvent(textBox, Key.Delete, KeyModifiers.Control); Assert.Equal("Fit Sec", textBox.Text); } } @@ -486,12 +486,12 @@ namespace Avalonia.Controls.UnitTests }.RegisterInNameScope(scope)); } - private void RaiseKeyEvent(TextBox textBox, Key key, InputModifiers inputModifiers) + private void RaiseKeyEvent(TextBox textBox, Key key, KeyModifiers inputModifiers) { textBox.RaiseEvent(new KeyEventArgs { RoutedEvent = InputElement.KeyDownEvent, - Modifiers = inputModifiers, + KeyModifiers = inputModifiers, Key = key }); } diff --git a/tests/Avalonia.Controls.UnitTests/TopLevelTests.cs b/tests/Avalonia.Controls.UnitTests/TopLevelTests.cs index 0ee772425b..c744543f99 100644 --- a/tests/Avalonia.Controls.UnitTests/TopLevelTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TopLevelTests.cs @@ -183,7 +183,7 @@ namespace Avalonia.Controls.UnitTests new Mock().Object, 0, RawKeyEventType.KeyDown, - Key.A, InputModifiers.None); + Key.A, RawInputModifiers.None); impl.Object.Input(input); inputManagerMock.Verify(x => x.ProcessInput(input)); diff --git a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs index 5646e86f7a..f51a50c0d5 100644 --- a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs @@ -619,7 +619,7 @@ namespace Avalonia.Controls.UnitTests { RoutedEvent = InputElement.KeyDownEvent, Key = selectAllGesture.Key, - Modifiers = selectAllGesture.Modifiers + KeyModifiers = selectAllGesture.KeyModifiers }; target.RaiseEvent(keyEvent); @@ -665,7 +665,7 @@ namespace Avalonia.Controls.UnitTests { RoutedEvent = InputElement.KeyDownEvent, Key = selectAllGesture.Key, - Modifiers = selectAllGesture.Modifiers + KeyModifiers = selectAllGesture.KeyModifiers }; target.RaiseEvent(keyEvent); @@ -711,7 +711,7 @@ namespace Avalonia.Controls.UnitTests { RoutedEvent = InputElement.KeyDownEvent, Key = selectAllGesture.Key, - Modifiers = selectAllGesture.Modifiers + KeyModifiers = selectAllGesture.KeyModifiers }; target.RaiseEvent(keyEvent); From 0bad390dac05b4dde51dcb5d58469abd6320d0c3 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Sat, 10 Aug 2019 11:21:26 +0300 Subject: [PATCH 2/6] Added PointerUpdateKind and replaced InputModifiers with KeyModifiers --- src/Avalonia.Controls/MenuItem.cs | 4 +- .../Platform/InProcessDragSource.cs | 4 +- .../Remote/Server/RemoteServerTopLevelImpl.cs | 18 ++-- src/Avalonia.Input/IKeyboardDevice.cs | 1 + src/Avalonia.Input/MouseDevice.cs | 85 +++++++++++-------- src/Avalonia.Input/PointerEventArgs.cs | 50 +++++++++-- src/Avalonia.Input/PointerPoint.cs | 54 +++++++++--- src/Avalonia.Input/PointerWheelEventArgs.cs | 2 +- .../Raw/RawMouseWheelEventArgs.cs | 2 +- src/Avalonia.Input/Raw/RawPointerEventArgs.cs | 4 +- src/Avalonia.Input/Raw/RawTouchEventArgs.cs | 2 +- src/Avalonia.Input/TouchDevice.cs | 31 ++++--- src/Avalonia.Native/WindowImplBase.cs | 4 +- src/Avalonia.X11/X11Window.cs | 18 ++-- src/Avalonia.X11/XI2Manager.cs | 16 ++-- .../Input/LibInput/LibInputBackend.cs | 6 +- .../Input/WindowsKeyboardDevice.cs | 14 +-- src/Windows/Avalonia.Win32/WindowImpl.cs | 8 +- .../DefaultMenuInteractionHandlerTests.cs | 6 +- .../MouseDeviceTests.cs | 2 +- tests/Avalonia.UnitTests/MouseTestHelper.cs | 23 +++-- 21 files changed, 223 insertions(+), 131 deletions(-) diff --git a/src/Avalonia.Controls/MenuItem.cs b/src/Avalonia.Controls/MenuItem.cs index 38cc3f6daf..33a708b6a5 100644 --- a/src/Avalonia.Controls/MenuItem.cs +++ b/src/Avalonia.Controls/MenuItem.cs @@ -339,7 +339,7 @@ namespace Avalonia.Controls var point = e.GetPointerPoint(null); RaiseEvent(new PointerEventArgs(PointerEnterItemEvent, this, e.Pointer, this.VisualRoot, point.Position, - e.Timestamp, point.Properties, e.InputModifiers)); + e.Timestamp, point.Properties, e.KeyModifiers)); } /// @@ -349,7 +349,7 @@ namespace Avalonia.Controls var point = e.GetPointerPoint(null); RaiseEvent(new PointerEventArgs(PointerLeaveItemEvent, this, e.Pointer, this.VisualRoot, point.Position, - e.Timestamp, point.Properties, e.InputModifiers)); + e.Timestamp, point.Properties, e.KeyModifiers)); } /// diff --git a/src/Avalonia.Controls/Platform/InProcessDragSource.cs b/src/Avalonia.Controls/Platform/InProcessDragSource.cs index d4df41d2f2..2765cd7106 100644 --- a/src/Avalonia.Controls/Platform/InProcessDragSource.cs +++ b/src/Avalonia.Controls/Platform/InProcessDragSource.cs @@ -14,7 +14,7 @@ namespace Avalonia.Platform { class InProcessDragSource : IPlatformDragSource { - private const InputModifiers MOUSE_INPUTMODIFIERS = InputModifiers.LeftMouseButton|InputModifiers.MiddleMouseButton|InputModifiers.RightMouseButton; + private const RawInputModifiers MOUSE_INPUTMODIFIERS = RawInputModifiers.LeftMouseButton|RawInputModifiers.MiddleMouseButton|RawInputModifiers.RightMouseButton; private readonly IDragDropDevice _dragDrop; private readonly IInputManager _inputManager; private readonly Subject _result = new Subject(); @@ -25,7 +25,7 @@ namespace Avalonia.Platform private Point _lastPosition; private StandardCursorType _lastCursorType; private object _originalCursor; - private InputModifiers? _initialInputModifiers; + private RawInputModifiers? _initialInputModifiers; public InProcessDragSource() { diff --git a/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs b/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs index cfd28106eb..be24f22e20 100644 --- a/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs +++ b/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs @@ -61,9 +61,9 @@ namespace Avalonia.Controls.Remote.Server Avalonia.Remote.Protocol.Input.InputModifiers[] modifiers) => (RawInputModifiers)GetAvaloniaInputModifiers(modifiers); - private static InputModifiers GetAvaloniaInputModifiers (Avalonia.Remote.Protocol.Input.InputModifiers[] modifiers) + private static RawInputModifiers GetAvaloniaInputModifiers (Avalonia.Remote.Protocol.Input.InputModifiers[] modifiers) { - var result = InputModifiers.None; + var result = RawInputModifiers.None; if (modifiers == null) { @@ -75,31 +75,31 @@ namespace Avalonia.Controls.Remote.Server switch (modifier) { case Avalonia.Remote.Protocol.Input.InputModifiers.Control: - result |= InputModifiers.Control; + result |= RawInputModifiers.Control; break; case Avalonia.Remote.Protocol.Input.InputModifiers.Alt: - result |= InputModifiers.Alt; + result |= RawInputModifiers.Alt; break; case Avalonia.Remote.Protocol.Input.InputModifiers.Shift: - result |= InputModifiers.Shift; + result |= RawInputModifiers.Shift; break; case Avalonia.Remote.Protocol.Input.InputModifiers.Windows: - result |= InputModifiers.Windows; + result |= RawInputModifiers.Meta; break; case Avalonia.Remote.Protocol.Input.InputModifiers.LeftMouseButton: - result |= InputModifiers.LeftMouseButton; + result |= RawInputModifiers.LeftMouseButton; break; case Avalonia.Remote.Protocol.Input.InputModifiers.MiddleMouseButton: - result |= InputModifiers.MiddleMouseButton; + result |= RawInputModifiers.MiddleMouseButton; break; case Avalonia.Remote.Protocol.Input.InputModifiers.RightMouseButton: - result |= InputModifiers.RightMouseButton; + result |= RawInputModifiers.RightMouseButton; break; } } diff --git a/src/Avalonia.Input/IKeyboardDevice.cs b/src/Avalonia.Input/IKeyboardDevice.cs index 6b3e8435d9..1a82f7d671 100644 --- a/src/Avalonia.Input/IKeyboardDevice.cs +++ b/src/Avalonia.Input/IKeyboardDevice.cs @@ -37,6 +37,7 @@ namespace Avalonia.Input Toggled = 2, } + [Flags] public enum RawInputModifiers { None = 0, diff --git a/src/Avalonia.Input/MouseDevice.cs b/src/Avalonia.Input/MouseDevice.cs index ee7d0c9501..d5152f58d5 100644 --- a/src/Avalonia.Input/MouseDevice.cs +++ b/src/Avalonia.Input/MouseDevice.cs @@ -94,11 +94,13 @@ namespace Avalonia.Input { if (_pointer.Captured == null) { - SetPointerOver(this, 0 /* TODO: proper timestamp */, root, clientPoint, InputModifiers.None); + SetPointerOver(this, 0 /* TODO: proper timestamp */, root, clientPoint, + PointerPointProperties.None, KeyModifiers.None); } else { - SetPointerOver(this, 0 /* TODO: proper timestamp */, root, _pointer.Captured, InputModifiers.None); + SetPointerOver(this, 0 /* TODO: proper timestamp */, root, _pointer.Captured, + PointerPointProperties.None, KeyModifiers.None); } } } @@ -123,69 +125,73 @@ namespace Avalonia.Input Position = e.Root.PointToScreen(e.Position); var props = CreateProperties(e); + var keyModifiers = KeyModifiersUtils.ConvertToKey(e.InputModifiers); switch (e.Type) { case RawPointerEventType.LeaveWindow: - LeaveWindow(mouse, e.Timestamp, e.Root, e.InputModifiers); + LeaveWindow(mouse, e.Timestamp, e.Root, props, keyModifiers); break; case RawPointerEventType.LeftButtonDown: case RawPointerEventType.RightButtonDown: case RawPointerEventType.MiddleButtonDown: if (ButtonCount(props) > 1) - e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, e.InputModifiers); + e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers); else e.Handled = MouseDown(mouse, e.Timestamp, e.Root, e.Position, - props, e.InputModifiers); + props, keyModifiers); break; case RawPointerEventType.LeftButtonUp: case RawPointerEventType.RightButtonUp: case RawPointerEventType.MiddleButtonUp: if (ButtonCount(props) != 0) - e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, e.InputModifiers); + e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers); else - e.Handled = MouseUp(mouse, e.Timestamp, e.Root, e.Position, props, e.InputModifiers); + e.Handled = MouseUp(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers); break; case RawPointerEventType.Move: - e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, e.InputModifiers); + e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers); break; case RawPointerEventType.Wheel: - e.Handled = MouseWheel(mouse, e.Timestamp, e.Root, e.Position, props, ((RawMouseWheelEventArgs)e).Delta, e.InputModifiers); + e.Handled = MouseWheel(mouse, e.Timestamp, e.Root, e.Position, props, ((RawMouseWheelEventArgs)e).Delta, keyModifiers); break; } } - private void LeaveWindow(IMouseDevice device, ulong timestamp, IInputRoot root, InputModifiers inputModifiers) + private void LeaveWindow(IMouseDevice device, ulong timestamp, IInputRoot root, PointerPointProperties properties, + KeyModifiers inputModifiers) { Contract.Requires(device != null); Contract.Requires(root != null); - ClearPointerOver(this, timestamp, root, inputModifiers); + ClearPointerOver(this, timestamp, root, properties, inputModifiers); } PointerPointProperties CreateProperties(RawPointerEventArgs args) { - var rv = new PointerPointProperties(args.InputModifiers); + + var kind = PointerUpdateKind.Other; if (args.Type == RawPointerEventType.LeftButtonDown) - rv.IsLeftButtonPressed = true; + kind = PointerUpdateKind.LeftButtonPressed; if (args.Type == RawPointerEventType.MiddleButtonDown) - rv.IsMiddleButtonPressed = true; + kind = PointerUpdateKind.MiddleButtonPressed; if (args.Type == RawPointerEventType.RightButtonDown) - rv.IsRightButtonPressed = true; + kind = PointerUpdateKind.RightButtonPressed; if (args.Type == RawPointerEventType.LeftButtonUp) - rv.IsLeftButtonPressed = false; + kind = PointerUpdateKind.LeftButtonReleased; if (args.Type == RawPointerEventType.MiddleButtonUp) - rv.IsMiddleButtonPressed = false; + kind = PointerUpdateKind.MiddleButtonReleased; if (args.Type == RawPointerEventType.RightButtonUp) - rv.IsRightButtonPressed = false; - return rv; + kind = PointerUpdateKind.RightButtonReleased; + + return new PointerPointProperties(args.InputModifiers, kind); } private MouseButton _lastMouseDownButton; private bool MouseDown(IMouseDevice device, ulong timestamp, IInputElement root, Point p, PointerPointProperties properties, - InputModifiers inputModifiers) + KeyModifiers inputModifiers) { Contract.Requires(device != null); Contract.Requires(root != null); @@ -221,7 +227,7 @@ namespace Avalonia.Input } private bool MouseMove(IMouseDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties properties, - InputModifiers inputModifiers) + KeyModifiers inputModifiers) { Contract.Requires(device != null); Contract.Requires(root != null); @@ -230,11 +236,11 @@ namespace Avalonia.Input if (_pointer.Captured == null) { - source = SetPointerOver(this, timestamp, root, p, inputModifiers); + source = SetPointerOver(this, timestamp, root, p, properties, inputModifiers); } else { - SetPointerOver(this, timestamp, root, _pointer.Captured, inputModifiers); + SetPointerOver(this, timestamp, root, _pointer.Captured, properties, inputModifiers); source = _pointer.Captured; } @@ -246,7 +252,7 @@ namespace Avalonia.Input } private bool MouseUp(IMouseDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties props, - InputModifiers inputModifiers) + KeyModifiers inputModifiers) { Contract.Requires(device != null); Contract.Requires(root != null); @@ -256,8 +262,7 @@ namespace Avalonia.Input if (hit != null) { var source = GetSource(hit); - var e = new PointerReleasedEventArgs(source, _pointer, root, p, timestamp, props, inputModifiers, - _lastMouseDownButton); + var e = new PointerReleasedEventArgs(source, _pointer, root, p, timestamp, props, inputModifiers); source?.RaiseEvent(e); _pointer.Capture(null); @@ -269,7 +274,7 @@ namespace Avalonia.Input private bool MouseWheel(IMouseDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties props, - Vector delta, InputModifiers inputModifiers) + Vector delta, KeyModifiers inputModifiers) { Contract.Requires(device != null); Contract.Requires(root != null); @@ -304,19 +309,23 @@ namespace Avalonia.Input return _pointer.Captured ?? root.InputHitTest(p); } - PointerEventArgs CreateSimpleEvent(RoutedEvent ev, ulong timestamp, IInteractive source, InputModifiers inputModifiers) + PointerEventArgs CreateSimpleEvent(RoutedEvent ev, ulong timestamp, IInteractive source, + PointerPointProperties properties, + KeyModifiers inputModifiers) { return new PointerEventArgs(ev, source, _pointer, null, default, - timestamp, new PointerPointProperties(inputModifiers), inputModifiers); + timestamp, properties, inputModifiers); } - private void ClearPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root, InputModifiers inputModifiers) + private void ClearPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root, + PointerPointProperties properties, + KeyModifiers inputModifiers) { Contract.Requires(device != null); Contract.Requires(root != null); var element = root.PointerOverElement; - var e = CreateSimpleEvent(InputElement.PointerLeaveEvent, timestamp, element, inputModifiers); + var e = CreateSimpleEvent(InputElement.PointerLeaveEvent, timestamp, element, properties, inputModifiers); if (element!=null && !element.IsAttachedToVisualTree) { @@ -353,7 +362,9 @@ namespace Avalonia.Input } } - private IInputElement SetPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root, Point p, InputModifiers inputModifiers) + private IInputElement SetPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root, Point p, + PointerPointProperties properties, + KeyModifiers inputModifiers) { Contract.Requires(device != null); Contract.Requires(root != null); @@ -364,18 +375,20 @@ namespace Avalonia.Input { if (element != null) { - SetPointerOver(device, timestamp, root, element, inputModifiers); + SetPointerOver(device, timestamp, root, element, properties, inputModifiers); } else { - ClearPointerOver(device, timestamp, root, inputModifiers); + ClearPointerOver(device, timestamp, root, properties, inputModifiers); } } return element; } - private void SetPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root, IInputElement element, InputModifiers inputModifiers) + private void SetPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root, IInputElement element, + PointerPointProperties properties, + KeyModifiers inputModifiers) { Contract.Requires(device != null); Contract.Requires(root != null); @@ -397,7 +410,7 @@ namespace Avalonia.Input el = root.PointerOverElement; - var e = CreateSimpleEvent(InputElement.PointerLeaveEvent, timestamp, el, inputModifiers); + var e = CreateSimpleEvent(InputElement.PointerLeaveEvent, timestamp, el, properties, inputModifiers); if (el!=null && branch!=null && !el.IsAttachedToVisualTree) { ClearChildrenPointerOver(e,branch,false); diff --git a/src/Avalonia.Input/PointerEventArgs.cs b/src/Avalonia.Input/PointerEventArgs.cs index c827822192..0fda4e2465 100644 --- a/src/Avalonia.Input/PointerEventArgs.cs +++ b/src/Avalonia.Input/PointerEventArgs.cs @@ -20,7 +20,7 @@ namespace Avalonia.Input IVisual rootVisual, Point rootVisualPosition, ulong timestamp, PointerPointProperties properties, - InputModifiers modifiers) + KeyModifiers modifiers) : base(routedEvent) { Source = source; @@ -29,7 +29,7 @@ namespace Avalonia.Input _properties = properties; Pointer = pointer; Timestamp = timestamp; - InputModifiers = modifiers; + KeyModifiers = modifiers; } class EmulatedDevice : IPointerDevice @@ -60,7 +60,39 @@ namespace Avalonia.Input [Obsolete("Use Pointer to get pointer-specific information")] public IPointerDevice Device => _device ?? (_device = new EmulatedDevice(this)); - public InputModifiers InputModifiers { get; } + [Obsolete("Use KeyModifiers and PointerPointProperties")] + public InputModifiers InputModifiers + { + get + { + var mods = (InputModifiers)KeyModifiers; + if (_properties.IsLeftButtonPressed) + mods |= InputModifiers.LeftMouseButton; + if (_properties.IsMiddleButtonPressed) + mods |= InputModifiers.MiddleMouseButton; + if (_properties.IsRightButtonPressed) + mods |= InputModifiers.RightMouseButton; + + // The old InputModifiers has indicated the *previous* state, so we are emulating this legacy behavior + if (_properties.PointerUpdateKind == PointerUpdateKind.LeftButtonPressed) + mods &= ~InputModifiers.LeftMouseButton; + if (_properties.PointerUpdateKind == PointerUpdateKind.MiddleButtonPressed) + mods &= ~InputModifiers.MiddleMouseButton; + if (_properties.PointerUpdateKind == PointerUpdateKind.RightButtonPressed) + mods &= ~InputModifiers.RightMouseButton; + + if (_properties.PointerUpdateKind == PointerUpdateKind.LeftButtonReleased) + mods |= InputModifiers.LeftMouseButton; + if (_properties.PointerUpdateKind == PointerUpdateKind.MiddleButtonReleased) + mods |= InputModifiers.MiddleMouseButton; + if (_properties.PointerUpdateKind == PointerUpdateKind.RightButtonReleased) + mods |= InputModifiers.RightMouseButton; + + return mods; + } + } + + public KeyModifiers KeyModifiers { get; } public Point GetPosition(IVisual relativeTo) { @@ -73,6 +105,8 @@ namespace Avalonia.Input public PointerPoint GetPointerPoint(IVisual relativeTo) => new PointerPoint(Pointer, GetPosition(relativeTo), _properties); + + protected PointerPointProperties Properties => _properties; } public enum MouseButton @@ -93,7 +127,7 @@ namespace Avalonia.Input IVisual rootVisual, Point rootVisualPosition, ulong timestamp, PointerPointProperties properties, - InputModifiers modifiers, + KeyModifiers modifiers, int obsoleteClickCount = 1) : base(InputElement.PointerPressedEvent, source, pointer, rootVisual, rootVisualPosition, timestamp, properties, modifiers) @@ -112,15 +146,15 @@ namespace Avalonia.Input public PointerReleasedEventArgs( IInteractive source, IPointer pointer, IVisual rootVisual, Point rootVisualPosition, ulong timestamp, - PointerPointProperties properties, InputModifiers modifiers, MouseButton obsoleteMouseButton) + PointerPointProperties properties, KeyModifiers modifiers) : base(InputElement.PointerReleasedEvent, source, pointer, rootVisual, rootVisualPosition, timestamp, properties, modifiers) { - MouseButton = obsoleteMouseButton; + } - [Obsolete()] - public MouseButton MouseButton { get; private set; } + [Obsolete("Use PointerUpdateKind")] + public MouseButton MouseButton => Properties.GetObsoleteMouseButton(); } public class PointerCaptureLostEventArgs : RoutedEventArgs diff --git a/src/Avalonia.Input/PointerPoint.cs b/src/Avalonia.Input/PointerPoint.cs index 7117b5709c..d823a78090 100644 --- a/src/Avalonia.Input/PointerPoint.cs +++ b/src/Avalonia.Input/PointerPoint.cs @@ -15,31 +15,61 @@ namespace Avalonia.Input public sealed class PointerPointProperties { - public bool IsLeftButtonPressed { get; set; } - public bool IsMiddleButtonPressed { get; set; } - public bool IsRightButtonPressed { get; set; } - - public PointerPointProperties() + public bool IsLeftButtonPressed { get; } + public bool IsMiddleButtonPressed { get; } + public bool IsRightButtonPressed { get; } + public PointerUpdateKind PointerUpdateKind { get; } + private PointerPointProperties() { } - public PointerPointProperties(InputModifiers modifiers) + public PointerPointProperties(RawInputModifiers modifiers, PointerUpdateKind kind) { - IsLeftButtonPressed = modifiers.HasFlag(InputModifiers.LeftMouseButton); - IsMiddleButtonPressed = modifiers.HasFlag(InputModifiers.MiddleMouseButton); - IsRightButtonPressed = modifiers.HasFlag(InputModifiers.RightMouseButton); + PointerUpdateKind = kind; + IsLeftButtonPressed = modifiers.HasFlag(RawInputModifiers.LeftMouseButton); + IsMiddleButtonPressed = modifiers.HasFlag(RawInputModifiers.MiddleMouseButton); + IsRightButtonPressed = modifiers.HasFlag(RawInputModifiers.RightMouseButton); + + // The underlying input source might be reporting the previous state, + // so make sure that we reflect the current state + + if (kind == PointerUpdateKind.LeftButtonPressed) + IsLeftButtonPressed = true; + if (kind == PointerUpdateKind.LeftButtonReleased) + IsLeftButtonPressed = false; + if (kind == PointerUpdateKind.MiddleButtonPressed) + IsMiddleButtonPressed = true; + if (kind == PointerUpdateKind.MiddleButtonReleased) + IsMiddleButtonPressed = false; + if (kind == PointerUpdateKind.RightButtonPressed) + IsRightButtonPressed = true; + if (kind == PointerUpdateKind.RightButtonReleased) + IsRightButtonPressed = false; } + + public static PointerPointProperties None { get; } = new PointerPointProperties(); public MouseButton GetObsoleteMouseButton() { - if (IsLeftButtonPressed) + if (PointerUpdateKind == PointerUpdateKind.LeftButtonPressed || PointerUpdateKind == PointerUpdateKind.LeftButtonReleased) return MouseButton.Left; - if (IsMiddleButtonPressed) + if (PointerUpdateKind == PointerUpdateKind.MiddleButtonPressed || PointerUpdateKind == PointerUpdateKind.MiddleButtonReleased) return MouseButton.Middle; - if (IsRightButtonPressed) + if (PointerUpdateKind == PointerUpdateKind.RightButtonPressed || PointerUpdateKind == PointerUpdateKind.RightButtonReleased) return MouseButton.Right; return MouseButton.None; } } + + public enum PointerUpdateKind + { + LeftButtonPressed, + MiddleButtonPressed, + RightButtonPressed, + LeftButtonReleased, + MiddleButtonReleased, + RightButtonReleased, + Other + } } diff --git a/src/Avalonia.Input/PointerWheelEventArgs.cs b/src/Avalonia.Input/PointerWheelEventArgs.cs index de1badfe96..3d7f93ddde 100644 --- a/src/Avalonia.Input/PointerWheelEventArgs.cs +++ b/src/Avalonia.Input/PointerWheelEventArgs.cs @@ -12,7 +12,7 @@ namespace Avalonia.Input public PointerWheelEventArgs(IInteractive source, IPointer pointer, IVisual rootVisual, Point rootVisualPosition, ulong timestamp, - PointerPointProperties properties, InputModifiers modifiers, Vector delta) + PointerPointProperties properties, KeyModifiers modifiers, Vector delta) : base(InputElement.PointerWheelChangedEvent, source, pointer, rootVisual, rootVisualPosition, timestamp, properties, modifiers) { diff --git a/src/Avalonia.Input/Raw/RawMouseWheelEventArgs.cs b/src/Avalonia.Input/Raw/RawMouseWheelEventArgs.cs index 186ad99efc..516234de7e 100644 --- a/src/Avalonia.Input/Raw/RawMouseWheelEventArgs.cs +++ b/src/Avalonia.Input/Raw/RawMouseWheelEventArgs.cs @@ -11,7 +11,7 @@ namespace Avalonia.Input.Raw ulong timestamp, IInputRoot root, Point position, - Vector delta, InputModifiers inputModifiers) + Vector delta, RawInputModifiers inputModifiers) : base(device, timestamp, root, RawPointerEventType.Wheel, position, inputModifiers) { Delta = delta; diff --git a/src/Avalonia.Input/Raw/RawPointerEventArgs.cs b/src/Avalonia.Input/Raw/RawPointerEventArgs.cs index 6fac90f255..88f6daf11f 100644 --- a/src/Avalonia.Input/Raw/RawPointerEventArgs.cs +++ b/src/Avalonia.Input/Raw/RawPointerEventArgs.cs @@ -43,7 +43,7 @@ namespace Avalonia.Input.Raw IInputRoot root, RawPointerEventType type, Point position, - InputModifiers inputModifiers) + RawInputModifiers inputModifiers) : base(device, timestamp) { Contract.Requires(device != null); @@ -73,6 +73,6 @@ namespace Avalonia.Input.Raw /// /// Gets the input modifiers. /// - public InputModifiers InputModifiers { get; private set; } + public RawInputModifiers InputModifiers { get; private set; } } } diff --git a/src/Avalonia.Input/Raw/RawTouchEventArgs.cs b/src/Avalonia.Input/Raw/RawTouchEventArgs.cs index 5299633b26..020b40e55b 100644 --- a/src/Avalonia.Input/Raw/RawTouchEventArgs.cs +++ b/src/Avalonia.Input/Raw/RawTouchEventArgs.cs @@ -3,7 +3,7 @@ namespace Avalonia.Input.Raw public class RawTouchEventArgs : RawPointerEventArgs { public RawTouchEventArgs(IInputDevice device, ulong timestamp, IInputRoot root, - RawPointerEventType type, Point position, InputModifiers inputModifiers, + RawPointerEventType type, Point position, RawInputModifiers inputModifiers, long touchPointId) : base(device, timestamp, root, type, position, inputModifiers) { diff --git a/src/Avalonia.Input/TouchDevice.cs b/src/Avalonia.Input/TouchDevice.cs index c85f98b04a..765e02848f 100644 --- a/src/Avalonia.Input/TouchDevice.cs +++ b/src/Avalonia.Input/TouchDevice.cs @@ -15,14 +15,15 @@ namespace Avalonia.Input { Dictionary _pointers = new Dictionary(); - static InputModifiers GetModifiers(InputModifiers modifiers, bool left) + KeyModifiers GetKeyModifiers(RawInputModifiers modifiers) => + (KeyModifiers)(modifiers & RawInputModifiers.KeyboardMask); + + RawInputModifiers GetModifiers(RawInputModifiers modifiers, bool isLeftButtonDown) { - var mask = (InputModifiers)0x7fffffff ^ InputModifiers.LeftMouseButton ^ InputModifiers.MiddleMouseButton ^ - InputModifiers.RightMouseButton; - modifiers &= mask; - if (left) - modifiers |= InputModifiers.LeftMouseButton; - return modifiers; + var rv = modifiers &= RawInputModifiers.KeyboardMask; + if (isLeftButtonDown) + rv |= RawInputModifiers.LeftMouseButton; + return rv; } public void ProcessRawEvent(RawInputEventArgs ev) @@ -45,8 +46,9 @@ namespace Avalonia.Input { target.RaiseEvent(new PointerPressedEventArgs(target, pointer, args.Root, args.Position, ev.Timestamp, - new PointerPointProperties(GetModifiers(args.InputModifiers, pointer.IsPrimary)), - GetModifiers(args.InputModifiers, false))); + new PointerPointProperties(GetModifiers(args.InputModifiers, true), + PointerUpdateKind.LeftButtonPressed), + GetKeyModifiers(args.InputModifiers))); } if (args.Type == RawPointerEventType.TouchEnd) @@ -56,11 +58,12 @@ namespace Avalonia.Input { target.RaiseEvent(new PointerReleasedEventArgs(target, pointer, args.Root, args.Position, ev.Timestamp, - new PointerPointProperties(GetModifiers(args.InputModifiers, false)), - GetModifiers(args.InputModifiers, pointer.IsPrimary), - pointer.IsPrimary ? MouseButton.Left : MouseButton.None)); + new PointerPointProperties(GetModifiers(args.InputModifiers, false), + PointerUpdateKind.LeftButtonReleased), + GetKeyModifiers(args.InputModifiers))); } } + if (args.Type == RawPointerEventType.TouchCancel) { _pointers.Remove(args.TouchPointId); @@ -72,7 +75,9 @@ namespace Avalonia.Input { var modifiers = GetModifiers(args.InputModifiers, pointer.IsPrimary); target.RaiseEvent(new PointerEventArgs(InputElement.PointerMovedEvent, target, pointer, args.Root, - args.Position, ev.Timestamp, new PointerPointProperties(modifiers), modifiers)); + args.Position, ev.Timestamp, + new PointerPointProperties(GetModifiers(args.InputModifiers, true), PointerUpdateKind.Other), + GetKeyModifiers(args.InputModifiers))); } diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index dd03f7d81e..217fb4b078 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -223,11 +223,11 @@ namespace Avalonia.Native switch (type) { case AvnRawMouseEventType.Wheel: - Input?.Invoke(new RawMouseWheelEventArgs(_mouse, timeStamp, _inputRoot, point.ToAvaloniaPoint(), new Vector(delta.X, delta.Y), (InputModifiers)modifiers)); + Input?.Invoke(new RawMouseWheelEventArgs(_mouse, timeStamp, _inputRoot, point.ToAvaloniaPoint(), new Vector(delta.X, delta.Y), (RawInputModifiers)modifiers)); break; default: - Input?.Invoke(new RawPointerEventArgs(_mouse, timeStamp, _inputRoot, (RawPointerEventType)type, point.ToAvaloniaPoint(), (InputModifiers)modifiers)); + Input?.Invoke(new RawPointerEventArgs(_mouse, timeStamp, _inputRoot, (RawPointerEventType)type, point.ToAvaloniaPoint(), (RawInputModifiers)modifiers)); break; } } diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 95b3e40063..accd7ea40a 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -560,23 +560,23 @@ namespace Avalonia.X11 RawInputModifiers TranslateRawModifiers(XModifierMask state) => (RawInputModifiers)TranslateModifiers(state); - InputModifiers TranslateModifiers(XModifierMask state) + RawInputModifiers TranslateModifiers(XModifierMask state) { - var rv = default(InputModifiers); + var rv = default(RawInputModifiers); if (state.HasFlag(XModifierMask.Button1Mask)) - rv |= InputModifiers.LeftMouseButton; + rv |= RawInputModifiers.LeftMouseButton; if (state.HasFlag(XModifierMask.Button2Mask)) - rv |= InputModifiers.RightMouseButton; + rv |= RawInputModifiers.RightMouseButton; if (state.HasFlag(XModifierMask.Button2Mask)) - rv |= InputModifiers.MiddleMouseButton; + rv |= RawInputModifiers.MiddleMouseButton; if (state.HasFlag(XModifierMask.ShiftMask)) - rv |= InputModifiers.Shift; + rv |= RawInputModifiers.Shift; if (state.HasFlag(XModifierMask.ControlMask)) - rv |= InputModifiers.Control; + rv |= RawInputModifiers.Control; if (state.HasFlag(XModifierMask.Mod1Mask)) - rv |= InputModifiers.Alt; + rv |= RawInputModifiers.Alt; if (state.HasFlag(XModifierMask.Mod4Mask)) - rv |= InputModifiers.Windows; + rv |= RawInputModifiers.Meta; return rv; } diff --git a/src/Avalonia.X11/XI2Manager.cs b/src/Avalonia.X11/XI2Manager.cs index 0a78c0dfd9..cf75572601 100644 --- a/src/Avalonia.X11/XI2Manager.cs +++ b/src/Avalonia.X11/XI2Manager.cs @@ -247,7 +247,7 @@ namespace Avalonia.X11 unsafe class ParsedDeviceEvent { public XiEventType Type { get; } - public InputModifiers Modifiers { get; } + public RawInputModifiers Modifiers { get; } public ulong Timestamp { get; } public Point Position { get; } public int Button { get; set; } @@ -260,25 +260,25 @@ namespace Avalonia.X11 Timestamp = (ulong)ev->time.ToInt64(); var state = (XModifierMask)ev->mods.Effective; if (state.HasFlag(XModifierMask.ShiftMask)) - Modifiers |= InputModifiers.Shift; + Modifiers |= RawInputModifiers.Shift; if (state.HasFlag(XModifierMask.ControlMask)) - Modifiers |= InputModifiers.Control; + Modifiers |= RawInputModifiers.Control; if (state.HasFlag(XModifierMask.Mod1Mask)) - Modifiers |= InputModifiers.Alt; + Modifiers |= RawInputModifiers.Alt; if (state.HasFlag(XModifierMask.Mod4Mask)) - Modifiers |= InputModifiers.Windows; + Modifiers |= RawInputModifiers.Meta; if (ev->buttons.MaskLen > 0) { var buttons = ev->buttons.Mask; if (XIMaskIsSet(buttons, 1)) - Modifiers |= InputModifiers.LeftMouseButton; + Modifiers |= RawInputModifiers.LeftMouseButton; if (XIMaskIsSet(buttons, 2)) - Modifiers |= InputModifiers.MiddleMouseButton; + Modifiers |= RawInputModifiers.MiddleMouseButton; if (XIMaskIsSet(buttons, 3)) - Modifiers |= InputModifiers.RightMouseButton; + Modifiers |= RawInputModifiers.RightMouseButton; } Valuators = new Dictionary(); diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.cs b/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.cs index 723028c666..432344955a 100644 --- a/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.cs +++ b/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.cs @@ -125,7 +125,7 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput : type == LibInputEventType.LIBINPUT_EVENT_TOUCH_UP ? RawPointerEventType.TouchEnd : type == LibInputEventType.LIBINPUT_EVENT_TOUCH_MOTION ? RawPointerEventType.TouchUpdate : RawPointerEventType.TouchCancel, - pt, InputModifiers.None, slot)); + pt, RawInputModifiers.None, slot)); } } @@ -140,7 +140,7 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput _mousePosition = new Point(libinput_event_pointer_get_absolute_x_transformed(pev, (int)info.Width), libinput_event_pointer_get_absolute_y_transformed(pev, (int)info.Height)); ScheduleInput(new RawPointerEventArgs(_mouse, ts, _inputRoot, RawPointerEventType.Move, _mousePosition, - InputModifiers.None)); + RawInputModifiers.None)); } else if (type == LibInputEventType.LIBINPUT_EVENT_POINTER_BUTTON) { @@ -162,7 +162,7 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput ScheduleInput( - new RawPointerEventArgs(_mouse, ts, _inputRoot, evnt, _mousePosition, InputModifiers.None)); + new RawPointerEventArgs(_mouse, ts, _inputRoot, evnt, _mousePosition, RawInputModifiers.None)); } } diff --git a/src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs b/src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs index 93adf7bee3..233f110c37 100644 --- a/src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs +++ b/src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs @@ -14,32 +14,32 @@ namespace Avalonia.Win32.Input public new static WindowsKeyboardDevice Instance { get; } = new WindowsKeyboardDevice(); - public RawInputModifiers RawModifiers => (RawInputModifiers)Modifiers; - public InputModifiers Modifiers + public RawInputModifiers RawModifiers => Modifiers; + public RawInputModifiers Modifiers { get { UpdateKeyStates(); - InputModifiers result = 0; + RawInputModifiers result = 0; if (IsDown(Key.LeftAlt) || IsDown(Key.RightAlt)) { - result |= InputModifiers.Alt; + result |= RawInputModifiers.Alt; } if (IsDown(Key.LeftCtrl) || IsDown(Key.RightCtrl)) { - result |= InputModifiers.Control; + result |= RawInputModifiers.Control; } if (IsDown(Key.LeftShift) || IsDown(Key.RightShift)) { - result |= InputModifiers.Shift; + result |= RawInputModifiers.Shift; } if (IsDown(Key.LWin) || IsDown(Key.RWin)) { - result |= InputModifiers.Windows; + result |= RawInputModifiers.Meta; } return result; diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 65fb2e447e..c3a0a9c717 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -762,16 +762,16 @@ namespace Avalonia.Win32 return UnmanagedMethods.DefWindowProc(hWnd, msg, wParam, lParam); } - static InputModifiers GetMouseModifiers(IntPtr wParam) + static RawInputModifiers GetMouseModifiers(IntPtr wParam) { var keys = (UnmanagedMethods.ModifierKeys)ToInt32(wParam); var modifiers = WindowsKeyboardDevice.Instance.Modifiers; if (keys.HasFlag(UnmanagedMethods.ModifierKeys.MK_LBUTTON)) - modifiers |= InputModifiers.LeftMouseButton; + modifiers |= RawInputModifiers.LeftMouseButton; if (keys.HasFlag(UnmanagedMethods.ModifierKeys.MK_RBUTTON)) - modifiers |= InputModifiers.RightMouseButton; + modifiers |= RawInputModifiers.RightMouseButton; if (keys.HasFlag(UnmanagedMethods.ModifierKeys.MK_MBUTTON)) - modifiers |= InputModifiers.MiddleMouseButton; + modifiers |= RawInputModifiers.MiddleMouseButton; return modifiers; } diff --git a/tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs b/tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs index ba4d6ca9c5..ff11bc513d 100644 --- a/tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs @@ -11,14 +11,14 @@ namespace Avalonia.Controls.UnitTests.Platform public class DefaultMenuInteractionHandlerTests { static PointerEventArgs CreateArgs(RoutedEvent ev, IInteractive source) - => new PointerEventArgs(ev, source, new FakePointer(), (IVisual)source, default, 0, new PointerPointProperties(), default); + => new PointerEventArgs(ev, source, new FakePointer(), (IVisual)source, default, 0, PointerPointProperties.None, default); static PointerPressedEventArgs CreatePressed(IInteractive source) => new PointerPressedEventArgs(source, - new FakePointer(), (IVisual)source, default,0, new PointerPointProperties {IsLeftButtonPressed = true}, + new FakePointer(), (IVisual)source, default,0, new PointerPointProperties (RawInputModifiers.None, PointerUpdateKind.LeftButtonPressed), default); static PointerReleasedEventArgs CreateReleased(IInteractive source) => new PointerReleasedEventArgs(source, - new FakePointer(), (IVisual)source, default,0, new PointerPointProperties(), default, MouseButton.Left); + new FakePointer(), (IVisual)source, default,0, new PointerPointProperties(RawInputModifiers.None, PointerUpdateKind.LeftButtonReleased), default); public class TopLevel { diff --git a/tests/Avalonia.Input.UnitTests/MouseDeviceTests.cs b/tests/Avalonia.Input.UnitTests/MouseDeviceTests.cs index 983f541c2a..214aead521 100644 --- a/tests/Avalonia.Input.UnitTests/MouseDeviceTests.cs +++ b/tests/Avalonia.Input.UnitTests/MouseDeviceTests.cs @@ -231,7 +231,7 @@ namespace Avalonia.Input.UnitTests root, RawPointerEventType.Move, p, - InputModifiers.None)); + RawInputModifiers.None)); } private void SetHit(Mock renderer, IControl hit) diff --git a/tests/Avalonia.UnitTests/MouseTestHelper.cs b/tests/Avalonia.UnitTests/MouseTestHelper.cs index 00ad850cf8..d6e64936c7 100644 --- a/tests/Avalonia.UnitTests/MouseTestHelper.cs +++ b/tests/Avalonia.UnitTests/MouseTestHelper.cs @@ -32,7 +32,8 @@ namespace Avalonia.UnitTests private MouseButton _pressedButton; - InputModifiers GetModifiers(InputModifiers modifiers) => modifiers | _pressedButtons; + KeyModifiers GetModifiers(InputModifiers modifiers) => + (KeyModifiers)((int)modifiers & (int)RawInputModifiers.KeyboardMask); public void Down(IInteractive target, MouseButton mouseButton = MouseButton.Left, Point position = default, InputModifiers modifiers = default, int clickCount = 1) @@ -44,7 +45,11 @@ namespace Avalonia.UnitTests Point position = default, InputModifiers modifiers = default, int clickCount = 1) { _pressedButtons |= Convert(mouseButton); - var props = new PointerPointProperties(_pressedButtons); + var props = new PointerPointProperties((RawInputModifiers)_pressedButtons, + mouseButton == MouseButton.Left ? PointerUpdateKind.LeftButtonPressed + : mouseButton == MouseButton.Middle ? PointerUpdateKind.MiddleButtonPressed + : mouseButton == MouseButton.Right ? PointerUpdateKind.RightButtonPressed : PointerUpdateKind.Other + ); if (ButtonCount(props) > 1) Move(target, source, position); else @@ -60,7 +65,7 @@ namespace Avalonia.UnitTests public void Move(IInteractive target, IInteractive source, in Point position, InputModifiers modifiers = default) { target.RaiseEvent(new PointerEventArgs(InputElement.PointerMovedEvent, source, _pointer, (IVisual)target, position, - Timestamp(), new PointerPointProperties(_pressedButtons), GetModifiers(modifiers))); + Timestamp(), new PointerPointProperties((RawInputModifiers)_pressedButtons, PointerUpdateKind.Other), GetModifiers(modifiers))); } public void Up(IInteractive target, MouseButton mouseButton = MouseButton.Left, Point position = default, @@ -72,13 +77,17 @@ namespace Avalonia.UnitTests { var conv = Convert(mouseButton); _pressedButtons = (_pressedButtons | conv) ^ conv; - var props = new PointerPointProperties(_pressedButtons); + var props = new PointerPointProperties((RawInputModifiers)_pressedButtons, + mouseButton == MouseButton.Left ? PointerUpdateKind.LeftButtonReleased + : mouseButton == MouseButton.Middle ? PointerUpdateKind.MiddleButtonReleased + : mouseButton == MouseButton.Right ? PointerUpdateKind.RightButtonReleased : PointerUpdateKind.Other + ); if (ButtonCount(props) == 0) { _pointer.Capture(null); target.RaiseEvent(new PointerReleasedEventArgs(source, _pointer, (IVisual)target, position, Timestamp(), props, - GetModifiers(modifiers), _pressedButton)); + GetModifiers(modifiers))); } else Move(target, source, position); @@ -97,13 +106,13 @@ namespace Avalonia.UnitTests public void Enter(IInteractive target) { target.RaiseEvent(new PointerEventArgs(InputElement.PointerEnterEvent, target, _pointer, (IVisual)target, default, - Timestamp(), new PointerPointProperties(_pressedButtons), _pressedButtons)); + Timestamp(), new PointerPointProperties((RawInputModifiers)_pressedButtons, PointerUpdateKind.Other), KeyModifiers.None)); } public void Leave(IInteractive target) { target.RaiseEvent(new PointerEventArgs(InputElement.PointerLeaveEvent, target, _pointer, (IVisual)target, default, - Timestamp(), new PointerPointProperties(_pressedButtons), _pressedButtons)); + Timestamp(), new PointerPointProperties((RawInputModifiers)_pressedButtons, PointerUpdateKind.Other), KeyModifiers.None)); } } From b7f971d87d5bc15f1f084769313f4fa904319372 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Thu, 8 Aug 2019 13:55:54 +0300 Subject: [PATCH 3/6] Updated mobile/interop backends --- .../Helpers/AndroidKeyboardEventsHelper.cs | 8 ++--- .../Helpers/AndroidTouchEventsHelper.cs | 6 ++-- .../Wpf/WpfTopLevelImpl.cs | 32 +++++++++++-------- .../Specific/KeyboardEventsHelper.cs | 2 +- src/iOS/Avalonia.iOS/TopLevelImpl.cs | 10 +++--- 5 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs index c7b01413a9..1179ce9235 100644 --- a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs +++ b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs @@ -72,12 +72,12 @@ namespace Avalonia.Android.Platform.Specific.Helpers return false; } - private static InputModifiers GetModifierKeys(KeyEvent e) + private static RawInputModifiers GetModifierKeys(KeyEvent e) { - var rv = InputModifiers.None; + var rv = RawInputModifiers.None; - if (e.IsCtrlPressed) rv |= InputModifiers.Control; - if (e.IsShiftPressed) rv |= InputModifiers.Shift; + if (e.IsCtrlPressed) rv |= RawInputModifiers.Control; + if (e.IsShiftPressed) rv |= RawInputModifiers.Shift; return rv; } diff --git a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs index 463d499aad..0bfbb1c2df 100644 --- a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs +++ b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs @@ -78,12 +78,12 @@ namespace Avalonia.Android.Platform.Specific.Helpers if (mouseEventType == RawPointerEventType.LeftButtonDown) { var me = new RawPointerEventArgs(mouseDevice, (uint)eventTime.Ticks, inputRoot, - RawPointerEventType.Move, _point, InputModifiers.None); + RawPointerEventType.Move, _point, RawInputModifiers.None); _view.Input(me); } var mouseEvent = new RawPointerEventArgs(mouseDevice, (uint)eventTime.Ticks, inputRoot, - mouseEventType.Value, _point, InputModifiers.LeftMouseButton); + mouseEventType.Value, _point, RawInputModifiers.LeftMouseButton); _view.Input(mouseEvent); if (e.Action == MotionEventActions.Move && mouseDevice.Captured == null) @@ -102,7 +102,7 @@ namespace Avalonia.Android.Platform.Specific.Helpers (uint)eventTime.Ticks, inputRoot, _point, - new Vector(vectorX * correction / ps, vectorY * correction / ps), InputModifiers.LeftMouseButton); + new Vector(vectorX * correction / ps, vectorY * correction / ps), RawInputModifiers.LeftMouseButton); _view.Input(mouseWheelEvent); } _lastTouchMovePoint = _point; diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs index f698266610..71c398481b 100644 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs +++ b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs @@ -142,27 +142,33 @@ namespace Avalonia.Win32.Interop.Wpf protected override void OnLostFocus(RoutedEventArgs e) => LostFocus?.Invoke(); - InputModifiers GetModifiers() + RawInputModifiers GetModifiers(MouseEventArgs e) { var state = Keyboard.Modifiers; - var rv = default(InputModifiers); + var rv = default(RawInputModifiers); if (state.HasFlag(ModifierKeys.Windows)) - rv |= InputModifiers.Windows; + rv |= RawInputModifiers.Meta; if (state.HasFlag(ModifierKeys.Alt)) - rv |= InputModifiers.Alt; + rv |= RawInputModifiers.Alt; if (state.HasFlag(ModifierKeys.Control)) - rv |= InputModifiers.Control; + rv |= RawInputModifiers.Control; if (state.HasFlag(ModifierKeys.Shift)) - rv |= InputModifiers.Shift; - //TODO: mouse modifiers - - + rv |= RawInputModifiers.Shift; + if (e != null) + { + if (e.LeftButton == MouseButtonState.Pressed) + rv |= RawInputModifiers.LeftMouseButton; + if (e.RightButton == MouseButtonState.Pressed) + rv |= RawInputModifiers.RightMouseButton; + if (e.MiddleButton == MouseButtonState.Pressed) + rv |= RawInputModifiers.MiddleMouseButton; + } return rv; } void MouseEvent(RawPointerEventType type, MouseEventArgs e) => _ttl.Input?.Invoke(new RawPointerEventArgs(_mouse, (uint)e.Timestamp, _inputRoot, type, - e.GetPosition(this).ToAvaloniaPoint(), GetModifiers())); + e.GetPosition(this).ToAvaloniaPoint(), GetModifiers(e))); protected override void OnMouseDown(MouseButtonEventArgs e) { @@ -201,19 +207,19 @@ namespace Avalonia.Win32.Interop.Wpf protected override void OnMouseWheel(MouseWheelEventArgs e) => _ttl.Input?.Invoke(new RawMouseWheelEventArgs(_mouse, (uint) e.Timestamp, _inputRoot, - e.GetPosition(this).ToAvaloniaPoint(), new Vector(0, e.Delta), GetModifiers())); + e.GetPosition(this).ToAvaloniaPoint(), new Vector(0, e.Delta), GetModifiers(e))); protected override void OnMouseLeave(MouseEventArgs e) => MouseEvent(RawPointerEventType.LeaveWindow, e); protected override void OnKeyDown(KeyEventArgs e) => _ttl.Input?.Invoke(new RawKeyEventArgs(_keyboard, (uint) e.Timestamp, RawKeyEventType.KeyDown, (Key) e.Key, - GetModifiers())); + GetModifiers(null))); protected override void OnKeyUp(KeyEventArgs e) => _ttl.Input?.Invoke(new RawKeyEventArgs(_keyboard, (uint)e.Timestamp, RawKeyEventType.KeyUp, (Key)e.Key, - GetModifiers())); + GetModifiers(null))); protected override void OnTextInput(TextCompositionEventArgs e) => _ttl.Input?.Invoke(new RawTextInputEventArgs(_keyboard, (uint) e.Timestamp, e.Text)); diff --git a/src/iOS/Avalonia.iOS/Specific/KeyboardEventsHelper.cs b/src/iOS/Avalonia.iOS/Specific/KeyboardEventsHelper.cs index be32d12315..cdf244d330 100644 --- a/src/iOS/Avalonia.iOS/Specific/KeyboardEventsHelper.cs +++ b/src/iOS/Avalonia.iOS/Specific/KeyboardEventsHelper.cs @@ -76,7 +76,7 @@ namespace Avalonia.iOS.Specific private void HandleKey(Key key, RawKeyEventType type) { - var rawKeyEvent = new RawKeyEventArgs(KeyboardDevice.Instance, (uint)DateTime.Now.Ticks, type, key, InputModifiers.None); + var rawKeyEvent = new RawKeyEventArgs(KeyboardDevice.Instance, (uint)DateTime.Now.Ticks, type, key, RawInputModifiers.None); _view.Input(rawKeyEvent); } diff --git a/src/iOS/Avalonia.iOS/TopLevelImpl.cs b/src/iOS/Avalonia.iOS/TopLevelImpl.cs index d5f456409f..a5342b227f 100644 --- a/src/iOS/Avalonia.iOS/TopLevelImpl.cs +++ b/src/iOS/Avalonia.iOS/TopLevelImpl.cs @@ -92,7 +92,7 @@ namespace Avalonia.iOS _inputRoot, RawPointerEventType.LeftButtonUp, location, - InputModifiers.None)); + RawInputModifiers.None)); } } @@ -105,10 +105,10 @@ namespace Avalonia.iOS var location = touch.LocationInView(this).ToAvalonia(); _touchLastPoint = location; Input?.Invoke(new RawPointerEventArgs(iOSPlatform.MouseDevice, (uint)touch.Timestamp, _inputRoot, - RawPointerEventType.Move, location, InputModifiers.None)); + RawPointerEventType.Move, location, RawInputModifiers.None)); Input?.Invoke(new RawPointerEventArgs(iOSPlatform.MouseDevice, (uint)touch.Timestamp, _inputRoot, - RawPointerEventType.LeftButtonDown, location, InputModifiers.None)); + RawPointerEventType.LeftButtonDown, location, RawInputModifiers.None)); } } @@ -120,14 +120,14 @@ namespace Avalonia.iOS var location = touch.LocationInView(this).ToAvalonia(); if (iOSPlatform.MouseDevice.Captured != null) Input?.Invoke(new RawPointerEventArgs(iOSPlatform.MouseDevice, (uint)touch.Timestamp, _inputRoot, - RawPointerEventType.Move, location, InputModifiers.LeftMouseButton)); + RawPointerEventType.Move, location, RawInputModifiers.LeftMouseButton)); else { //magic number based on test - correction of 0.02 is working perfect double correction = 0.02; Input?.Invoke(new RawMouseWheelEventArgs(iOSPlatform.MouseDevice, (uint)touch.Timestamp, - _inputRoot, location, (location - _touchLastPoint) * correction, InputModifiers.LeftMouseButton)); + _inputRoot, location, (location - _touchLastPoint) * correction, RawInputModifiers.LeftMouseButton)); } _touchLastPoint = location; } From 6d6b1d5e87dab585dae9f30c5cbf8d612bd7f08b Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Sat, 10 Aug 2019 11:57:56 +0300 Subject: [PATCH 4/6] Removed X11 input modifier emulation --- src/Avalonia.Input/PointerEventArgs.cs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/Avalonia.Input/PointerEventArgs.cs b/src/Avalonia.Input/PointerEventArgs.cs index 0fda4e2465..dd9ac593aa 100644 --- a/src/Avalonia.Input/PointerEventArgs.cs +++ b/src/Avalonia.Input/PointerEventArgs.cs @@ -72,21 +72,6 @@ namespace Avalonia.Input mods |= InputModifiers.MiddleMouseButton; if (_properties.IsRightButtonPressed) mods |= InputModifiers.RightMouseButton; - - // The old InputModifiers has indicated the *previous* state, so we are emulating this legacy behavior - if (_properties.PointerUpdateKind == PointerUpdateKind.LeftButtonPressed) - mods &= ~InputModifiers.LeftMouseButton; - if (_properties.PointerUpdateKind == PointerUpdateKind.MiddleButtonPressed) - mods &= ~InputModifiers.MiddleMouseButton; - if (_properties.PointerUpdateKind == PointerUpdateKind.RightButtonPressed) - mods &= ~InputModifiers.RightMouseButton; - - if (_properties.PointerUpdateKind == PointerUpdateKind.LeftButtonReleased) - mods |= InputModifiers.LeftMouseButton; - if (_properties.PointerUpdateKind == PointerUpdateKind.MiddleButtonReleased) - mods |= InputModifiers.MiddleMouseButton; - if (_properties.PointerUpdateKind == PointerUpdateKind.RightButtonReleased) - mods |= InputModifiers.RightMouseButton; return mods; } From 0cd25052fb11fc9a41cafbdf144fb56c6db6b27d Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Sat, 10 Aug 2019 11:59:22 +0300 Subject: [PATCH 5/6] Cleanup --- src/Avalonia.Input/PointerEventArgs.cs | 3 ++- src/Avalonia.X11/X11Window.cs | 4 +--- src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs | 1 - src/Windows/Avalonia.Win32/WindowImpl.cs | 4 ++-- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Avalonia.Input/PointerEventArgs.cs b/src/Avalonia.Input/PointerEventArgs.cs index dd9ac593aa..5b3c43e4df 100644 --- a/src/Avalonia.Input/PointerEventArgs.cs +++ b/src/Avalonia.Input/PointerEventArgs.cs @@ -123,7 +123,8 @@ namespace Avalonia.Input [Obsolete("Use DoubleTapped or DoubleRightTapped event instead")] public int ClickCount => _obsoleteClickCount; - [Obsolete] public MouseButton MouseButton => GetPointerPoint(null).Properties.GetObsoleteMouseButton(); + [Obsolete("Use PointerUpdateKind")] + public MouseButton MouseButton => Properties.GetObsoleteMouseButton(); } public class PointerReleasedEventArgs : PointerEventArgs diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index accd7ea40a..975b3d11d7 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -438,7 +438,7 @@ namespace Avalonia.X11 ScheduleInput(new RawKeyEventArgs(_keyboard, (ulong)ev.KeyEvent.time.ToInt64(), ev.type == XEventName.KeyPress ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp, - X11KeyTransform.ConvertKey(key), TranslateRawModifiers(ev.KeyEvent.state)), ref ev); + X11KeyTransform.ConvertKey(key), TranslateModifiers(ev.KeyEvent.state)), ref ev); if (ev.type == XEventName.KeyPress) { @@ -558,8 +558,6 @@ namespace Avalonia.X11 } - - RawInputModifiers TranslateRawModifiers(XModifierMask state) => (RawInputModifiers)TranslateModifiers(state); RawInputModifiers TranslateModifiers(XModifierMask state) { var rv = default(RawInputModifiers); diff --git a/src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs b/src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs index 233f110c37..fda5483b00 100644 --- a/src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs +++ b/src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs @@ -14,7 +14,6 @@ namespace Avalonia.Win32.Input public new static WindowsKeyboardDevice Instance { get; } = new WindowsKeyboardDevice(); - public RawInputModifiers RawModifiers => Modifiers; public RawInputModifiers Modifiers { get diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index c3a0a9c717..9bd58c10bc 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -510,7 +510,7 @@ namespace Avalonia.Win32 WindowsKeyboardDevice.Instance, timestamp, RawKeyEventType.KeyDown, - KeyInterop.KeyFromVirtualKey(ToInt32(wParam)), WindowsKeyboardDevice.Instance.RawModifiers); + KeyInterop.KeyFromVirtualKey(ToInt32(wParam)), WindowsKeyboardDevice.Instance.Modifiers); break; case UnmanagedMethods.WindowsMessage.WM_MENUCHAR: @@ -523,7 +523,7 @@ namespace Avalonia.Win32 WindowsKeyboardDevice.Instance, timestamp, RawKeyEventType.KeyUp, - KeyInterop.KeyFromVirtualKey(ToInt32(wParam)), WindowsKeyboardDevice.Instance.RawModifiers); + KeyInterop.KeyFromVirtualKey(ToInt32(wParam)), WindowsKeyboardDevice.Instance.Modifiers); break; case UnmanagedMethods.WindowsMessage.WM_CHAR: // Ignore control chars From 66963a28b7c9d1ed70227caa9038e7f8c88489b8 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Sat, 10 Aug 2019 17:37:54 +0300 Subject: [PATCH 6/6] DnD fix --- .../Platform/InProcessDragSource.cs | 15 +++++---------- src/Avalonia.Input/Raw/RawDragEvent.cs | 4 ++-- src/Windows/Avalonia.Win32/OleDropTarget.cs | 18 +++++++++--------- 3 files changed, 16 insertions(+), 21 deletions(-) diff --git a/src/Avalonia.Controls/Platform/InProcessDragSource.cs b/src/Avalonia.Controls/Platform/InProcessDragSource.cs index 2765cd7106..6eb056bb32 100644 --- a/src/Avalonia.Controls/Platform/InProcessDragSource.cs +++ b/src/Avalonia.Controls/Platform/InProcessDragSource.cs @@ -56,16 +56,11 @@ namespace Avalonia.Platform return DragDropEffects.None; } - - private DragDropEffects RaiseEventAndUpdateCursor(RawDragEventType type, IInputElement root, Point pt, - InputModifiers modifiers) - => RaiseEventAndUpdateCursor(type, root, pt, (RawInputModifiers)modifiers); - private DragDropEffects RaiseEventAndUpdateCursor(RawDragEventType type, IInputElement root, Point pt, RawInputModifiers modifiers) { _lastPosition = pt; - RawDragEvent rawEvent = new RawDragEvent(_dragDrop, type, root, pt, _draggedData, _allowedEffects, (InputModifiers)modifiers); + RawDragEvent rawEvent = new RawDragEvent(_dragDrop, type, root, pt, _draggedData, _allowedEffects, modifiers); var tl = root.GetSelfAndVisualAncestors().OfType().FirstOrDefault(); tl.PlatformImpl?.Input(rawEvent); @@ -164,7 +159,7 @@ namespace Avalonia.Platform _initialInputModifiers = e.InputModifiers & MOUSE_INPUTMODIFIERS; - void CheckDraggingAccepted(InputModifiers changedMouseButton) + void CheckDraggingAccepted(RawInputModifiers changedMouseButton) { if (_initialInputModifiers.Value.HasFlag(changedMouseButton)) { @@ -189,11 +184,11 @@ namespace Avalonia.Platform case RawPointerEventType.LeaveWindow: RaiseEventAndUpdateCursor(RawDragEventType.DragLeave, e.Root, e.Position, e.InputModifiers); break; case RawPointerEventType.LeftButtonUp: - CheckDraggingAccepted(InputModifiers.LeftMouseButton); break; + CheckDraggingAccepted(RawInputModifiers.LeftMouseButton); break; case RawPointerEventType.MiddleButtonUp: - CheckDraggingAccepted(InputModifiers.MiddleMouseButton); break; + CheckDraggingAccepted(RawInputModifiers.MiddleMouseButton); break; case RawPointerEventType.RightButtonUp: - CheckDraggingAccepted(InputModifiers.RightMouseButton); break; + CheckDraggingAccepted(RawInputModifiers.RightMouseButton); break; case RawPointerEventType.Move: var mods = e.InputModifiers & MOUSE_INPUTMODIFIERS; if (_initialInputModifiers.Value != mods) diff --git a/src/Avalonia.Input/Raw/RawDragEvent.cs b/src/Avalonia.Input/Raw/RawDragEvent.cs index 208d898a8a..1480f92f03 100644 --- a/src/Avalonia.Input/Raw/RawDragEvent.cs +++ b/src/Avalonia.Input/Raw/RawDragEvent.cs @@ -10,7 +10,7 @@ public InputModifiers Modifiers { get; } public RawDragEvent(IDragDropDevice inputDevice, RawDragEventType type, - IInputElement inputRoot, Point location, IDataObject data, DragDropEffects effects, InputModifiers modifiers) + IInputElement inputRoot, Point location, IDataObject data, DragDropEffects effects, RawInputModifiers modifiers) :base(inputDevice, 0) { Type = type; @@ -18,7 +18,7 @@ Location = location; Data = data; Effects = effects; - Modifiers = modifiers; + Modifiers = (InputModifiers)modifiers; } } } diff --git a/src/Windows/Avalonia.Win32/OleDropTarget.cs b/src/Windows/Avalonia.Win32/OleDropTarget.cs index 28065566d0..8ac0f25598 100644 --- a/src/Windows/Avalonia.Win32/OleDropTarget.cs +++ b/src/Windows/Avalonia.Win32/OleDropTarget.cs @@ -45,23 +45,23 @@ namespace Avalonia.Win32 return result; } - private static InputModifiers ConvertKeyState(int grfKeyState) + private static RawInputModifiers ConvertKeyState(int grfKeyState) { - InputModifiers modifiers = InputModifiers.None; + var modifiers = RawInputModifiers.None; var state = (UnmanagedMethods.ModifierKeys)grfKeyState; if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_LBUTTON)) - modifiers |= InputModifiers.LeftMouseButton; + modifiers |= RawInputModifiers.LeftMouseButton; if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_MBUTTON)) - modifiers |= InputModifiers.MiddleMouseButton; + modifiers |= RawInputModifiers.MiddleMouseButton; if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_RBUTTON)) - modifiers |= InputModifiers.RightMouseButton; + modifiers |= RawInputModifiers.RightMouseButton; if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_SHIFT)) - modifiers |= InputModifiers.Shift; + modifiers |= RawInputModifiers.Shift; if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_CONTROL)) - modifiers |= InputModifiers.Control; + modifiers |= RawInputModifiers.Control; if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_ALT)) - modifiers |= InputModifiers.Alt; + modifiers |= RawInputModifiers.Alt; return modifiers; } @@ -127,7 +127,7 @@ namespace Avalonia.Win32 default(Point), null, DragDropEffects.None, - InputModifiers.None + RawInputModifiers.None )); return UnmanagedMethods.HRESULT.S_OK; }