Browse Source

Added PointerUpdateKind and replaced InputModifiers with KeyModifiers

Nikita Tsukanov 6 năm trước cách đây
mục cha
commit
0bad390dac

+ 2 - 2
src/Avalonia.Controls/MenuItem.cs

@@ -339,7 +339,7 @@ namespace Avalonia.Controls
 
 
             var point = e.GetPointerPoint(null);
             var point = e.GetPointerPoint(null);
             RaiseEvent(new PointerEventArgs(PointerEnterItemEvent, this, e.Pointer, this.VisualRoot, point.Position,
             RaiseEvent(new PointerEventArgs(PointerEnterItemEvent, this, e.Pointer, this.VisualRoot, point.Position,
-                e.Timestamp, point.Properties, e.InputModifiers));
+                e.Timestamp, point.Properties, e.KeyModifiers));
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
@@ -349,7 +349,7 @@ namespace Avalonia.Controls
 
 
             var point = e.GetPointerPoint(null);
             var point = e.GetPointerPoint(null);
             RaiseEvent(new PointerEventArgs(PointerLeaveItemEvent, this, e.Pointer, this.VisualRoot, point.Position,
             RaiseEvent(new PointerEventArgs(PointerLeaveItemEvent, this, e.Pointer, this.VisualRoot, point.Position,
-                e.Timestamp, point.Properties, e.InputModifiers));
+                e.Timestamp, point.Properties, e.KeyModifiers));
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 2 - 2
src/Avalonia.Controls/Platform/InProcessDragSource.cs

@@ -14,7 +14,7 @@ namespace Avalonia.Platform
 {
 {
     class InProcessDragSource : IPlatformDragSource
     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 IDragDropDevice _dragDrop;
         private readonly IInputManager _inputManager;
         private readonly IInputManager _inputManager;
         private readonly Subject<DragDropEffects> _result = new Subject<DragDropEffects>();
         private readonly Subject<DragDropEffects> _result = new Subject<DragDropEffects>();
@@ -25,7 +25,7 @@ namespace Avalonia.Platform
         private Point _lastPosition;
         private Point _lastPosition;
         private StandardCursorType _lastCursorType;
         private StandardCursorType _lastCursorType;
         private object _originalCursor;
         private object _originalCursor;
-        private InputModifiers? _initialInputModifiers;
+        private RawInputModifiers? _initialInputModifiers;
 
 
         public InProcessDragSource()
         public InProcessDragSource()
         {
         {

+ 9 - 9
src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs

@@ -61,9 +61,9 @@ namespace Avalonia.Controls.Remote.Server
             Avalonia.Remote.Protocol.Input.InputModifiers[] modifiers)
             Avalonia.Remote.Protocol.Input.InputModifiers[] modifiers)
             => (RawInputModifiers)GetAvaloniaInputModifiers(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)
             if (modifiers == null)
             {
             {
@@ -75,31 +75,31 @@ namespace Avalonia.Controls.Remote.Server
                 switch (modifier)
                 switch (modifier)
                 {
                 {
                     case Avalonia.Remote.Protocol.Input.InputModifiers.Control:
                     case Avalonia.Remote.Protocol.Input.InputModifiers.Control:
-                        result |= InputModifiers.Control;
+                        result |= RawInputModifiers.Control;
                         break;
                         break;
 
 
                     case Avalonia.Remote.Protocol.Input.InputModifiers.Alt:
                     case Avalonia.Remote.Protocol.Input.InputModifiers.Alt:
-                        result |= InputModifiers.Alt;
+                        result |= RawInputModifiers.Alt;
                         break;
                         break;
 
 
                     case Avalonia.Remote.Protocol.Input.InputModifiers.Shift:
                     case Avalonia.Remote.Protocol.Input.InputModifiers.Shift:
-                        result |= InputModifiers.Shift;
+                        result |= RawInputModifiers.Shift;
                         break;
                         break;
 
 
                     case Avalonia.Remote.Protocol.Input.InputModifiers.Windows:
                     case Avalonia.Remote.Protocol.Input.InputModifiers.Windows:
-                        result |= InputModifiers.Windows;
+                        result |= RawInputModifiers.Meta;
                         break;
                         break;
 
 
                     case Avalonia.Remote.Protocol.Input.InputModifiers.LeftMouseButton:
                     case Avalonia.Remote.Protocol.Input.InputModifiers.LeftMouseButton:
-                        result |= InputModifiers.LeftMouseButton;
+                        result |= RawInputModifiers.LeftMouseButton;
                         break;
                         break;
 
 
                     case Avalonia.Remote.Protocol.Input.InputModifiers.MiddleMouseButton:
                     case Avalonia.Remote.Protocol.Input.InputModifiers.MiddleMouseButton:
-                        result |= InputModifiers.MiddleMouseButton;
+                        result |= RawInputModifiers.MiddleMouseButton;
                         break;
                         break;
 
 
                     case Avalonia.Remote.Protocol.Input.InputModifiers.RightMouseButton:
                     case Avalonia.Remote.Protocol.Input.InputModifiers.RightMouseButton:
-                        result |= InputModifiers.RightMouseButton;
+                        result |= RawInputModifiers.RightMouseButton;
                         break;
                         break;
                 }
                 }
             }
             }

+ 1 - 0
src/Avalonia.Input/IKeyboardDevice.cs

@@ -37,6 +37,7 @@ namespace Avalonia.Input
         Toggled = 2,
         Toggled = 2,
     }
     }
 
 
+    [Flags]
     public enum RawInputModifiers
     public enum RawInputModifiers
     {
     {
         None = 0,
         None = 0,

+ 49 - 36
src/Avalonia.Input/MouseDevice.cs

@@ -94,11 +94,13 @@ namespace Avalonia.Input
             {
             {
                 if (_pointer.Captured == null)
                 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
                 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);
             Position = e.Root.PointToScreen(e.Position);
             var props = CreateProperties(e);
             var props = CreateProperties(e);
+            var keyModifiers = KeyModifiersUtils.ConvertToKey(e.InputModifiers);
             switch (e.Type)
             switch (e.Type)
             {
             {
                 case RawPointerEventType.LeaveWindow:
                 case RawPointerEventType.LeaveWindow:
-                    LeaveWindow(mouse, e.Timestamp, e.Root, e.InputModifiers);
+                    LeaveWindow(mouse, e.Timestamp, e.Root, props, keyModifiers);
                     break;
                     break;
                 case RawPointerEventType.LeftButtonDown:
                 case RawPointerEventType.LeftButtonDown:
                 case RawPointerEventType.RightButtonDown:
                 case RawPointerEventType.RightButtonDown:
                 case RawPointerEventType.MiddleButtonDown:
                 case RawPointerEventType.MiddleButtonDown:
                     if (ButtonCount(props) > 1)
                     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
                     else
                         e.Handled = MouseDown(mouse, e.Timestamp, e.Root, e.Position,
                         e.Handled = MouseDown(mouse, e.Timestamp, e.Root, e.Position,
-                            props, e.InputModifiers);
+                            props, keyModifiers);
                     break;
                     break;
                 case RawPointerEventType.LeftButtonUp:
                 case RawPointerEventType.LeftButtonUp:
                 case RawPointerEventType.RightButtonUp:
                 case RawPointerEventType.RightButtonUp:
                 case RawPointerEventType.MiddleButtonUp:
                 case RawPointerEventType.MiddleButtonUp:
                     if (ButtonCount(props) != 0)
                     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
                     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;
                     break;
                 case RawPointerEventType.Move:
                 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;
                     break;
                 case RawPointerEventType.Wheel:
                 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;
                     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<ArgumentNullException>(device != null);
             Contract.Requires<ArgumentNullException>(device != null);
             Contract.Requires<ArgumentNullException>(root != null);
             Contract.Requires<ArgumentNullException>(root != null);
 
 
-            ClearPointerOver(this, timestamp, root, inputModifiers);
+            ClearPointerOver(this, timestamp, root, properties, inputModifiers);
         }
         }
 
 
 
 
         PointerPointProperties CreateProperties(RawPointerEventArgs args)
         PointerPointProperties CreateProperties(RawPointerEventArgs args)
         {
         {
-            var rv = new PointerPointProperties(args.InputModifiers);
+
+            var kind = PointerUpdateKind.Other;
 
 
             if (args.Type == RawPointerEventType.LeftButtonDown)
             if (args.Type == RawPointerEventType.LeftButtonDown)
-                rv.IsLeftButtonPressed = true;
+                kind = PointerUpdateKind.LeftButtonPressed;
             if (args.Type == RawPointerEventType.MiddleButtonDown)
             if (args.Type == RawPointerEventType.MiddleButtonDown)
-                rv.IsMiddleButtonPressed = true;
+                kind = PointerUpdateKind.MiddleButtonPressed;
             if (args.Type == RawPointerEventType.RightButtonDown)
             if (args.Type == RawPointerEventType.RightButtonDown)
-                rv.IsRightButtonPressed = true;
+                kind = PointerUpdateKind.RightButtonPressed;
             if (args.Type == RawPointerEventType.LeftButtonUp)
             if (args.Type == RawPointerEventType.LeftButtonUp)
-                rv.IsLeftButtonPressed = false;
+                kind = PointerUpdateKind.LeftButtonReleased;
             if (args.Type == RawPointerEventType.MiddleButtonUp)
             if (args.Type == RawPointerEventType.MiddleButtonUp)
-                rv.IsMiddleButtonPressed = false;
+                kind = PointerUpdateKind.MiddleButtonReleased;
             if (args.Type == RawPointerEventType.RightButtonUp)
             if (args.Type == RawPointerEventType.RightButtonUp)
-                rv.IsRightButtonPressed = false;
-            return rv;
+                kind = PointerUpdateKind.RightButtonReleased;
+            
+            return new PointerPointProperties(args.InputModifiers, kind);
         }
         }
 
 
         private MouseButton _lastMouseDownButton;
         private MouseButton _lastMouseDownButton;
         private bool MouseDown(IMouseDevice device, ulong timestamp, IInputElement root, Point p,
         private bool MouseDown(IMouseDevice device, ulong timestamp, IInputElement root, Point p,
             PointerPointProperties properties,
             PointerPointProperties properties,
-            InputModifiers inputModifiers)
+            KeyModifiers inputModifiers)
         {
         {
             Contract.Requires<ArgumentNullException>(device != null);
             Contract.Requires<ArgumentNullException>(device != null);
             Contract.Requires<ArgumentNullException>(root != null);
             Contract.Requires<ArgumentNullException>(root != null);
@@ -221,7 +227,7 @@ namespace Avalonia.Input
         }
         }
 
 
         private bool MouseMove(IMouseDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties properties,
         private bool MouseMove(IMouseDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties properties,
-            InputModifiers inputModifiers)
+            KeyModifiers inputModifiers)
         {
         {
             Contract.Requires<ArgumentNullException>(device != null);
             Contract.Requires<ArgumentNullException>(device != null);
             Contract.Requires<ArgumentNullException>(root != null);
             Contract.Requires<ArgumentNullException>(root != null);
@@ -230,11 +236,11 @@ namespace Avalonia.Input
 
 
             if (_pointer.Captured == null)
             if (_pointer.Captured == null)
             {
             {
-                source = SetPointerOver(this, timestamp, root, p, inputModifiers);
+                source = SetPointerOver(this, timestamp, root, p,  properties, inputModifiers);
             }
             }
             else
             else
             {
             {
-                SetPointerOver(this, timestamp, root, _pointer.Captured, inputModifiers);
+                SetPointerOver(this, timestamp, root, _pointer.Captured, properties, inputModifiers);
                 source = _pointer.Captured;
                 source = _pointer.Captured;
             }
             }
 
 
@@ -246,7 +252,7 @@ namespace Avalonia.Input
         }
         }
 
 
         private bool MouseUp(IMouseDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties props,
         private bool MouseUp(IMouseDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties props,
-            InputModifiers inputModifiers)
+            KeyModifiers inputModifiers)
         {
         {
             Contract.Requires<ArgumentNullException>(device != null);
             Contract.Requires<ArgumentNullException>(device != null);
             Contract.Requires<ArgumentNullException>(root != null);
             Contract.Requires<ArgumentNullException>(root != null);
@@ -256,8 +262,7 @@ namespace Avalonia.Input
             if (hit != null)
             if (hit != null)
             {
             {
                 var source = GetSource(hit);
                 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);
                 source?.RaiseEvent(e);
                 _pointer.Capture(null);
                 _pointer.Capture(null);
@@ -269,7 +274,7 @@ namespace Avalonia.Input
 
 
         private bool MouseWheel(IMouseDevice device, ulong timestamp, IInputRoot root, Point p,
         private bool MouseWheel(IMouseDevice device, ulong timestamp, IInputRoot root, Point p,
             PointerPointProperties props,
             PointerPointProperties props,
-            Vector delta, InputModifiers inputModifiers)
+            Vector delta, KeyModifiers inputModifiers)
         {
         {
             Contract.Requires<ArgumentNullException>(device != null);
             Contract.Requires<ArgumentNullException>(device != null);
             Contract.Requires<ArgumentNullException>(root != null);
             Contract.Requires<ArgumentNullException>(root != null);
@@ -304,19 +309,23 @@ namespace Avalonia.Input
             return _pointer.Captured ?? root.InputHitTest(p);
             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,
             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<ArgumentNullException>(device != null);
             Contract.Requires<ArgumentNullException>(device != null);
             Contract.Requires<ArgumentNullException>(root != null);
             Contract.Requires<ArgumentNullException>(root != null);
 
 
             var element = root.PointerOverElement;
             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)
             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<ArgumentNullException>(device != null);
             Contract.Requires<ArgumentNullException>(device != null);
             Contract.Requires<ArgumentNullException>(root != null);
             Contract.Requires<ArgumentNullException>(root != null);
@@ -364,18 +375,20 @@ namespace Avalonia.Input
             {
             {
                 if (element != null)
                 if (element != null)
                 {
                 {
-                    SetPointerOver(device, timestamp, root, element, inputModifiers);
+                    SetPointerOver(device, timestamp, root, element, properties, inputModifiers);
                 }
                 }
                 else
                 else
                 {
                 {
-                    ClearPointerOver(device, timestamp, root, inputModifiers);
+                    ClearPointerOver(device, timestamp, root, properties, inputModifiers);
                 }
                 }
             }
             }
 
 
             return element;
             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<ArgumentNullException>(device != null);
             Contract.Requires<ArgumentNullException>(device != null);
             Contract.Requires<ArgumentNullException>(root != null);
             Contract.Requires<ArgumentNullException>(root != null);
@@ -397,7 +410,7 @@ namespace Avalonia.Input
 
 
             el = root.PointerOverElement;
             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)
             if (el!=null && branch!=null && !el.IsAttachedToVisualTree)
             {
             {
                 ClearChildrenPointerOver(e,branch,false);
                 ClearChildrenPointerOver(e,branch,false);

+ 42 - 8
src/Avalonia.Input/PointerEventArgs.cs

@@ -20,7 +20,7 @@ namespace Avalonia.Input
             IVisual rootVisual, Point rootVisualPosition,
             IVisual rootVisual, Point rootVisualPosition,
             ulong timestamp,
             ulong timestamp,
             PointerPointProperties properties,
             PointerPointProperties properties,
-            InputModifiers modifiers)
+            KeyModifiers modifiers)
            : base(routedEvent)
            : base(routedEvent)
         {
         {
             Source = source;
             Source = source;
@@ -29,7 +29,7 @@ namespace Avalonia.Input
             _properties = properties;
             _properties = properties;
             Pointer = pointer;
             Pointer = pointer;
             Timestamp = timestamp;
             Timestamp = timestamp;
-            InputModifiers = modifiers;
+            KeyModifiers = modifiers;
         }
         }
 
 
         class EmulatedDevice : IPointerDevice
         class EmulatedDevice : IPointerDevice
@@ -60,7 +60,39 @@ namespace Avalonia.Input
         [Obsolete("Use Pointer to get pointer-specific information")]
         [Obsolete("Use Pointer to get pointer-specific information")]
         public IPointerDevice Device => _device ?? (_device = new EmulatedDevice(this));
         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)
         public Point GetPosition(IVisual relativeTo)
         {
         {
@@ -73,6 +105,8 @@ namespace Avalonia.Input
 
 
         public PointerPoint GetPointerPoint(IVisual relativeTo)
         public PointerPoint GetPointerPoint(IVisual relativeTo)
             => new PointerPoint(Pointer, GetPosition(relativeTo), _properties);
             => new PointerPoint(Pointer, GetPosition(relativeTo), _properties);
+
+        protected PointerPointProperties Properties => _properties;
     }
     }
     
     
     public enum MouseButton
     public enum MouseButton
@@ -93,7 +127,7 @@ namespace Avalonia.Input
             IVisual rootVisual, Point rootVisualPosition,
             IVisual rootVisual, Point rootVisualPosition,
             ulong timestamp,
             ulong timestamp,
             PointerPointProperties properties,
             PointerPointProperties properties,
-            InputModifiers modifiers,
+            KeyModifiers modifiers,
             int obsoleteClickCount = 1)
             int obsoleteClickCount = 1)
             : base(InputElement.PointerPressedEvent, source, pointer, rootVisual, rootVisualPosition,
             : base(InputElement.PointerPressedEvent, source, pointer, rootVisual, rootVisualPosition,
                 timestamp, properties, modifiers)
                 timestamp, properties, modifiers)
@@ -112,15 +146,15 @@ namespace Avalonia.Input
         public PointerReleasedEventArgs(
         public PointerReleasedEventArgs(
             IInteractive source, IPointer pointer,
             IInteractive source, IPointer pointer,
             IVisual rootVisual, Point rootVisualPosition, ulong timestamp,
             IVisual rootVisual, Point rootVisualPosition, ulong timestamp,
-            PointerPointProperties properties, InputModifiers modifiers, MouseButton obsoleteMouseButton)
+            PointerPointProperties properties, KeyModifiers modifiers)
             : base(InputElement.PointerReleasedEvent, source, pointer, rootVisual, rootVisualPosition,
             : base(InputElement.PointerReleasedEvent, source, pointer, rootVisual, rootVisualPosition,
                 timestamp, properties, modifiers)
                 timestamp, properties, modifiers)
         {
         {
-            MouseButton = obsoleteMouseButton;
+            
         }
         }
 
 
-        [Obsolete()]
-        public MouseButton MouseButton { get; private set; }
+        [Obsolete("Use PointerUpdateKind")] 
+        public MouseButton MouseButton => Properties.GetObsoleteMouseButton();
     }
     }
 
 
     public class PointerCaptureLostEventArgs : RoutedEventArgs
     public class PointerCaptureLostEventArgs : RoutedEventArgs

+ 42 - 12
src/Avalonia.Input/PointerPoint.cs

@@ -15,31 +15,61 @@ namespace Avalonia.Input
 
 
     public sealed class PointerPointProperties
     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()
         public MouseButton GetObsoleteMouseButton()
         {
         {
-            if (IsLeftButtonPressed)
+            if (PointerUpdateKind == PointerUpdateKind.LeftButtonPressed || PointerUpdateKind == PointerUpdateKind.LeftButtonReleased)
                 return MouseButton.Left;
                 return MouseButton.Left;
-            if (IsMiddleButtonPressed)
+            if (PointerUpdateKind == PointerUpdateKind.MiddleButtonPressed || PointerUpdateKind == PointerUpdateKind.MiddleButtonReleased)
                 return MouseButton.Middle;
                 return MouseButton.Middle;
-            if (IsRightButtonPressed)
+            if (PointerUpdateKind == PointerUpdateKind.RightButtonPressed || PointerUpdateKind == PointerUpdateKind.RightButtonReleased)
                 return MouseButton.Right;
                 return MouseButton.Right;
             return MouseButton.None;
             return MouseButton.None;
         }
         }
     }
     }
+
+    public enum PointerUpdateKind
+    {
+        LeftButtonPressed,
+        MiddleButtonPressed,
+        RightButtonPressed,
+        LeftButtonReleased,
+        MiddleButtonReleased,
+        RightButtonReleased,
+        Other
+    }
 }
 }

+ 1 - 1
src/Avalonia.Input/PointerWheelEventArgs.cs

@@ -12,7 +12,7 @@ namespace Avalonia.Input
 
 
         public PointerWheelEventArgs(IInteractive source, IPointer pointer, IVisual rootVisual,
         public PointerWheelEventArgs(IInteractive source, IPointer pointer, IVisual rootVisual,
             Point rootVisualPosition, ulong timestamp,
             Point rootVisualPosition, ulong timestamp,
-            PointerPointProperties properties, InputModifiers modifiers, Vector delta) 
+            PointerPointProperties properties, KeyModifiers modifiers, Vector delta) 
             : base(InputElement.PointerWheelChangedEvent, source, pointer, rootVisual, rootVisualPosition,
             : base(InputElement.PointerWheelChangedEvent, source, pointer, rootVisual, rootVisualPosition,
                 timestamp, properties, modifiers)
                 timestamp, properties, modifiers)
         {
         {

+ 1 - 1
src/Avalonia.Input/Raw/RawMouseWheelEventArgs.cs

@@ -11,7 +11,7 @@ namespace Avalonia.Input.Raw
             ulong timestamp,
             ulong timestamp,
             IInputRoot root,
             IInputRoot root,
             Point position,
             Point position,
-            Vector delta, InputModifiers inputModifiers)
+            Vector delta, RawInputModifiers inputModifiers)
             : base(device, timestamp, root, RawPointerEventType.Wheel, position, inputModifiers)
             : base(device, timestamp, root, RawPointerEventType.Wheel, position, inputModifiers)
         {
         {
             Delta = delta;
             Delta = delta;

+ 2 - 2
src/Avalonia.Input/Raw/RawPointerEventArgs.cs

@@ -43,7 +43,7 @@ namespace Avalonia.Input.Raw
             IInputRoot root,
             IInputRoot root,
             RawPointerEventType type,
             RawPointerEventType type,
             Point position, 
             Point position, 
-            InputModifiers inputModifiers)
+            RawInputModifiers inputModifiers)
             : base(device, timestamp)
             : base(device, timestamp)
         {
         {
             Contract.Requires<ArgumentNullException>(device != null);
             Contract.Requires<ArgumentNullException>(device != null);
@@ -73,6 +73,6 @@ namespace Avalonia.Input.Raw
         /// <summary>
         /// <summary>
         /// Gets the input modifiers.
         /// Gets the input modifiers.
         /// </summary>
         /// </summary>
-        public InputModifiers InputModifiers { get; private set; }
+        public RawInputModifiers InputModifiers { get; private set; }
     }
     }
 }
 }

+ 1 - 1
src/Avalonia.Input/Raw/RawTouchEventArgs.cs

@@ -3,7 +3,7 @@ namespace Avalonia.Input.Raw
     public class RawTouchEventArgs : RawPointerEventArgs
     public class RawTouchEventArgs : RawPointerEventArgs
     {
     {
         public RawTouchEventArgs(IInputDevice device, ulong timestamp, IInputRoot root,
         public RawTouchEventArgs(IInputDevice device, ulong timestamp, IInputRoot root,
-            RawPointerEventType type, Point position, InputModifiers inputModifiers,
+            RawPointerEventType type, Point position, RawInputModifiers inputModifiers,
             long touchPointId) 
             long touchPointId) 
             : base(device, timestamp, root, type, position, inputModifiers)
             : base(device, timestamp, root, type, position, inputModifiers)
         {
         {

+ 18 - 13
src/Avalonia.Input/TouchDevice.cs

@@ -15,14 +15,15 @@ namespace Avalonia.Input
     {
     {
         Dictionary<long, Pointer> _pointers = new Dictionary<long, Pointer>();
         Dictionary<long, Pointer> _pointers = new Dictionary<long, Pointer>();
 
 
-        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)
         public void ProcessRawEvent(RawInputEventArgs ev)
@@ -45,8 +46,9 @@ namespace Avalonia.Input
             {
             {
                 target.RaiseEvent(new PointerPressedEventArgs(target, pointer,
                 target.RaiseEvent(new PointerPressedEventArgs(target, pointer,
                     args.Root, args.Position, ev.Timestamp,
                     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)
             if (args.Type == RawPointerEventType.TouchEnd)
@@ -56,11 +58,12 @@ namespace Avalonia.Input
                 {
                 {
                     target.RaiseEvent(new PointerReleasedEventArgs(target, pointer,
                     target.RaiseEvent(new PointerReleasedEventArgs(target, pointer,
                         args.Root, args.Position, ev.Timestamp,
                         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)
             if (args.Type == RawPointerEventType.TouchCancel)
             {
             {
                 _pointers.Remove(args.TouchPointId);
                 _pointers.Remove(args.TouchPointId);
@@ -72,7 +75,9 @@ namespace Avalonia.Input
             {
             {
                 var modifiers = GetModifiers(args.InputModifiers, pointer.IsPrimary);
                 var modifiers = GetModifiers(args.InputModifiers, pointer.IsPrimary);
                 target.RaiseEvent(new PointerEventArgs(InputElement.PointerMovedEvent, target, pointer, args.Root,
                 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)));
             }
             }
 
 
             
             

+ 2 - 2
src/Avalonia.Native/WindowImplBase.cs

@@ -223,11 +223,11 @@ namespace Avalonia.Native
             switch (type)
             switch (type)
             {
             {
                 case AvnRawMouseEventType.Wheel:
                 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;
                     break;
 
 
                 default:
                 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;
                     break;
             }
             }
         }
         }

+ 9 - 9
src/Avalonia.X11/X11Window.cs

@@ -560,23 +560,23 @@ namespace Avalonia.X11
 
 
 
 
         RawInputModifiers TranslateRawModifiers(XModifierMask state) => (RawInputModifiers)TranslateModifiers(state);
         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))
             if (state.HasFlag(XModifierMask.Button1Mask))
-                rv |= InputModifiers.LeftMouseButton;
+                rv |= RawInputModifiers.LeftMouseButton;
             if (state.HasFlag(XModifierMask.Button2Mask))
             if (state.HasFlag(XModifierMask.Button2Mask))
-                rv |= InputModifiers.RightMouseButton;
+                rv |= RawInputModifiers.RightMouseButton;
             if (state.HasFlag(XModifierMask.Button2Mask))
             if (state.HasFlag(XModifierMask.Button2Mask))
-                rv |= InputModifiers.MiddleMouseButton;
+                rv |= RawInputModifiers.MiddleMouseButton;
             if (state.HasFlag(XModifierMask.ShiftMask))
             if (state.HasFlag(XModifierMask.ShiftMask))
-                rv |= InputModifiers.Shift;
+                rv |= RawInputModifiers.Shift;
             if (state.HasFlag(XModifierMask.ControlMask))
             if (state.HasFlag(XModifierMask.ControlMask))
-                rv |= InputModifiers.Control;
+                rv |= RawInputModifiers.Control;
             if (state.HasFlag(XModifierMask.Mod1Mask))
             if (state.HasFlag(XModifierMask.Mod1Mask))
-                rv |= InputModifiers.Alt;
+                rv |= RawInputModifiers.Alt;
             if (state.HasFlag(XModifierMask.Mod4Mask))
             if (state.HasFlag(XModifierMask.Mod4Mask))
-                rv |= InputModifiers.Windows;
+                rv |= RawInputModifiers.Meta;
             return rv;
             return rv;
         }
         }
         
         

+ 8 - 8
src/Avalonia.X11/XI2Manager.cs

@@ -247,7 +247,7 @@ namespace Avalonia.X11
     unsafe class ParsedDeviceEvent
     unsafe class ParsedDeviceEvent
     {
     {
         public XiEventType Type { get; }
         public XiEventType Type { get; }
-        public InputModifiers Modifiers { get; }
+        public RawInputModifiers Modifiers { get; }
         public ulong Timestamp { get; }
         public ulong Timestamp { get; }
         public Point Position { get; }
         public Point Position { get; }
         public int Button { get; set; }
         public int Button { get; set; }
@@ -260,25 +260,25 @@ namespace Avalonia.X11
             Timestamp = (ulong)ev->time.ToInt64();
             Timestamp = (ulong)ev->time.ToInt64();
             var state = (XModifierMask)ev->mods.Effective;
             var state = (XModifierMask)ev->mods.Effective;
             if (state.HasFlag(XModifierMask.ShiftMask))
             if (state.HasFlag(XModifierMask.ShiftMask))
-                Modifiers |= InputModifiers.Shift;
+                Modifiers |= RawInputModifiers.Shift;
             if (state.HasFlag(XModifierMask.ControlMask))
             if (state.HasFlag(XModifierMask.ControlMask))
-                Modifiers |= InputModifiers.Control;
+                Modifiers |= RawInputModifiers.Control;
             if (state.HasFlag(XModifierMask.Mod1Mask))
             if (state.HasFlag(XModifierMask.Mod1Mask))
-                Modifiers |= InputModifiers.Alt;
+                Modifiers |= RawInputModifiers.Alt;
             if (state.HasFlag(XModifierMask.Mod4Mask))
             if (state.HasFlag(XModifierMask.Mod4Mask))
-                Modifiers |= InputModifiers.Windows;
+                Modifiers |= RawInputModifiers.Meta;
 
 
             if (ev->buttons.MaskLen > 0)
             if (ev->buttons.MaskLen > 0)
             {
             {
                 var buttons = ev->buttons.Mask;
                 var buttons = ev->buttons.Mask;
                 if (XIMaskIsSet(buttons, 1))
                 if (XIMaskIsSet(buttons, 1))
-                    Modifiers |= InputModifiers.LeftMouseButton;
+                    Modifiers |= RawInputModifiers.LeftMouseButton;
                 
                 
                 if (XIMaskIsSet(buttons, 2))
                 if (XIMaskIsSet(buttons, 2))
-                    Modifiers |= InputModifiers.MiddleMouseButton;
+                    Modifiers |= RawInputModifiers.MiddleMouseButton;
                 
                 
                 if (XIMaskIsSet(buttons, 3))
                 if (XIMaskIsSet(buttons, 3))
-                    Modifiers |= InputModifiers.RightMouseButton;
+                    Modifiers |= RawInputModifiers.RightMouseButton;
             }
             }
 
 
             Valuators = new Dictionary<int, double>();
             Valuators = new Dictionary<int, double>();

+ 3 - 3
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_UP ? RawPointerEventType.TouchEnd
                     : type == LibInputEventType.LIBINPUT_EVENT_TOUCH_MOTION ? RawPointerEventType.TouchUpdate
                     : type == LibInputEventType.LIBINPUT_EVENT_TOUCH_MOTION ? RawPointerEventType.TouchUpdate
                     : RawPointerEventType.TouchCancel,
                     : 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),
                 _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));
                     libinput_event_pointer_get_absolute_y_transformed(pev, (int)info.Height));
                 ScheduleInput(new RawPointerEventArgs(_mouse, ts, _inputRoot, RawPointerEventType.Move, _mousePosition,
                 ScheduleInput(new RawPointerEventArgs(_mouse, ts, _inputRoot, RawPointerEventType.Move, _mousePosition,
-                    InputModifiers.None));
+                    RawInputModifiers.None));
             }
             }
             else if (type == LibInputEventType.LIBINPUT_EVENT_POINTER_BUTTON)
             else if (type == LibInputEventType.LIBINPUT_EVENT_POINTER_BUTTON)
             {
             {
@@ -162,7 +162,7 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
                         
                         
 
 
                 ScheduleInput(
                 ScheduleInput(
-                    new RawPointerEventArgs(_mouse, ts, _inputRoot, evnt, _mousePosition, InputModifiers.None));
+                    new RawPointerEventArgs(_mouse, ts, _inputRoot, evnt, _mousePosition, RawInputModifiers.None));
             }
             }
             
             
         }
         }

+ 7 - 7
src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs

@@ -14,32 +14,32 @@ namespace Avalonia.Win32.Input
 
 
         public new static WindowsKeyboardDevice Instance { get; } = new WindowsKeyboardDevice();
         public new static WindowsKeyboardDevice Instance { get; } = new WindowsKeyboardDevice();
 
 
-        public RawInputModifiers RawModifiers => (RawInputModifiers)Modifiers;
-        public InputModifiers Modifiers
+        public RawInputModifiers RawModifiers => Modifiers;
+        public RawInputModifiers Modifiers
         {
         {
             get
             get
             {
             {
                 UpdateKeyStates();
                 UpdateKeyStates();
-                InputModifiers result = 0;
+                RawInputModifiers result = 0;
 
 
                 if (IsDown(Key.LeftAlt) || IsDown(Key.RightAlt))
                 if (IsDown(Key.LeftAlt) || IsDown(Key.RightAlt))
                 {
                 {
-                    result |= InputModifiers.Alt;
+                    result |= RawInputModifiers.Alt;
                 }
                 }
 
 
                 if (IsDown(Key.LeftCtrl) || IsDown(Key.RightCtrl))
                 if (IsDown(Key.LeftCtrl) || IsDown(Key.RightCtrl))
                 {
                 {
-                    result |= InputModifiers.Control;
+                    result |= RawInputModifiers.Control;
                 }
                 }
 
 
                 if (IsDown(Key.LeftShift) || IsDown(Key.RightShift))
                 if (IsDown(Key.LeftShift) || IsDown(Key.RightShift))
                 {
                 {
-                    result |= InputModifiers.Shift;
+                    result |= RawInputModifiers.Shift;
                 }
                 }
 
 
                 if (IsDown(Key.LWin) || IsDown(Key.RWin))
                 if (IsDown(Key.LWin) || IsDown(Key.RWin))
                 {
                 {
-                    result |= InputModifiers.Windows;
+                    result |= RawInputModifiers.Meta;
                 }
                 }
 
 
                 return result;
                 return result;

+ 4 - 4
src/Windows/Avalonia.Win32/WindowImpl.cs

@@ -762,16 +762,16 @@ namespace Avalonia.Win32
                 return UnmanagedMethods.DefWindowProc(hWnd, msg, wParam, lParam);
                 return UnmanagedMethods.DefWindowProc(hWnd, msg, wParam, lParam);
         }
         }
 
 
-        static InputModifiers GetMouseModifiers(IntPtr wParam)
+        static RawInputModifiers GetMouseModifiers(IntPtr wParam)
         {
         {
             var keys = (UnmanagedMethods.ModifierKeys)ToInt32(wParam);
             var keys = (UnmanagedMethods.ModifierKeys)ToInt32(wParam);
             var modifiers = WindowsKeyboardDevice.Instance.Modifiers;
             var modifiers = WindowsKeyboardDevice.Instance.Modifiers;
             if (keys.HasFlag(UnmanagedMethods.ModifierKeys.MK_LBUTTON))
             if (keys.HasFlag(UnmanagedMethods.ModifierKeys.MK_LBUTTON))
-                modifiers |= InputModifiers.LeftMouseButton;
+                modifiers |= RawInputModifiers.LeftMouseButton;
             if (keys.HasFlag(UnmanagedMethods.ModifierKeys.MK_RBUTTON))
             if (keys.HasFlag(UnmanagedMethods.ModifierKeys.MK_RBUTTON))
-                modifiers |= InputModifiers.RightMouseButton;
+                modifiers |= RawInputModifiers.RightMouseButton;
             if (keys.HasFlag(UnmanagedMethods.ModifierKeys.MK_MBUTTON))
             if (keys.HasFlag(UnmanagedMethods.ModifierKeys.MK_MBUTTON))
-                modifiers |= InputModifiers.MiddleMouseButton;
+                modifiers |= RawInputModifiers.MiddleMouseButton;
             return modifiers;
             return modifiers;
         }
         }
 
 

+ 3 - 3
tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs

@@ -11,14 +11,14 @@ namespace Avalonia.Controls.UnitTests.Platform
     public class DefaultMenuInteractionHandlerTests
     public class DefaultMenuInteractionHandlerTests
     {
     {
         static PointerEventArgs CreateArgs(RoutedEvent ev, IInteractive source) 
         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,
         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);
             default);
         
         
         static PointerReleasedEventArgs CreateReleased(IInteractive source) => new PointerReleasedEventArgs(source,
         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
         public class TopLevel
         {
         {

+ 1 - 1
tests/Avalonia.Input.UnitTests/MouseDeviceTests.cs

@@ -231,7 +231,7 @@ namespace Avalonia.Input.UnitTests
                 root,
                 root,
                 RawPointerEventType.Move,
                 RawPointerEventType.Move,
                 p,
                 p,
-                InputModifiers.None));
+                RawInputModifiers.None));
         }
         }
 
 
         private void SetHit(Mock<IRenderer> renderer, IControl hit)
         private void SetHit(Mock<IRenderer> renderer, IControl hit)

+ 16 - 7
tests/Avalonia.UnitTests/MouseTestHelper.cs

@@ -32,7 +32,8 @@ namespace Avalonia.UnitTests
 
 
         private MouseButton _pressedButton;
         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,
         public void Down(IInteractive target, MouseButton mouseButton = MouseButton.Left, Point position = default,
             InputModifiers modifiers = default, int clickCount = 1)
             InputModifiers modifiers = default, int clickCount = 1)
@@ -44,7 +45,11 @@ namespace Avalonia.UnitTests
             Point position = default, InputModifiers modifiers = default, int clickCount = 1)
             Point position = default, InputModifiers modifiers = default, int clickCount = 1)
         {
         {
             _pressedButtons |= Convert(mouseButton);
             _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)
             if (ButtonCount(props) > 1)
                 Move(target, source, position);
                 Move(target, source, position);
             else
             else
@@ -60,7 +65,7 @@ namespace Avalonia.UnitTests
         public void Move(IInteractive target, IInteractive source, in Point position, InputModifiers modifiers = default)
         public void Move(IInteractive target, IInteractive source, in Point position, InputModifiers modifiers = default)
         {
         {
             target.RaiseEvent(new PointerEventArgs(InputElement.PointerMovedEvent, source, _pointer, (IVisual)target, position,
             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,
         public void Up(IInteractive target, MouseButton mouseButton = MouseButton.Left, Point position = default,
@@ -72,13 +77,17 @@ namespace Avalonia.UnitTests
         {
         {
             var conv = Convert(mouseButton);
             var conv = Convert(mouseButton);
             _pressedButtons = (_pressedButtons | conv) ^ conv;
             _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)
             if (ButtonCount(props) == 0)
             {
             {
                 _pointer.Capture(null);
                 _pointer.Capture(null);
                 target.RaiseEvent(new PointerReleasedEventArgs(source, _pointer, (IVisual)target, position,
                 target.RaiseEvent(new PointerReleasedEventArgs(source, _pointer, (IVisual)target, position,
                     Timestamp(), props,
                     Timestamp(), props,
-                    GetModifiers(modifiers), _pressedButton));
+                    GetModifiers(modifiers)));
             }
             }
             else
             else
                 Move(target, source, position);
                 Move(target, source, position);
@@ -97,13 +106,13 @@ namespace Avalonia.UnitTests
         public void Enter(IInteractive target)
         public void Enter(IInteractive target)
         {
         {
             target.RaiseEvent(new PointerEventArgs(InputElement.PointerEnterEvent, target, _pointer, (IVisual)target, default,
             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)
         public void Leave(IInteractive target)
         {
         {
             target.RaiseEvent(new PointerEventArgs(InputElement.PointerLeaveEvent, target, _pointer, (IVisual)target, default,
             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));
         }
         }
 
 
     }
     }