Browse Source

Merge branch 'master' into managed-file-dialog

pull/2777/head
danwalmsley 7 years ago
committed by GitHub
parent
commit
0dde1082e3
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs
  2. 6
      src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs
  3. 4
      src/Avalonia.Controls/MenuItem.cs
  4. 23
      src/Avalonia.Controls/Platform/InProcessDragSource.cs
  5. 24
      src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs
  6. 4
      src/Avalonia.Diagnostics/DevTools.xaml.cs
  7. 32
      src/Avalonia.Input/IKeyboardDevice.cs
  8. 5
      src/Avalonia.Input/KeyEventArgs.cs
  9. 9
      src/Avalonia.Input/KeyGesture.cs
  10. 2
      src/Avalonia.Input/KeyboardDevice.cs
  11. 85
      src/Avalonia.Input/MouseDevice.cs
  12. 38
      src/Avalonia.Input/PointerEventArgs.cs
  13. 54
      src/Avalonia.Input/PointerPoint.cs
  14. 2
      src/Avalonia.Input/PointerWheelEventArgs.cs
  15. 4
      src/Avalonia.Input/Raw/RawDragEvent.cs
  16. 4
      src/Avalonia.Input/Raw/RawKeyEventArgs.cs
  17. 2
      src/Avalonia.Input/Raw/RawMouseWheelEventArgs.cs
  18. 4
      src/Avalonia.Input/Raw/RawPointerEventArgs.cs
  19. 2
      src/Avalonia.Input/Raw/RawTouchEventArgs.cs
  20. 31
      src/Avalonia.Input/TouchDevice.cs
  21. 6
      src/Avalonia.Native/WindowImplBase.cs
  22. 19
      src/Avalonia.X11/X11Window.cs
  23. 16
      src/Avalonia.X11/XI2Manager.cs
  24. 6
      src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.cs
  25. 32
      src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs
  26. 12
      src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs
  27. 18
      src/Windows/Avalonia.Win32/OleDropTarget.cs
  28. 8
      src/Windows/Avalonia.Win32/WindowImpl.cs
  29. 2
      src/iOS/Avalonia.iOS/Specific/KeyboardEventsHelper.cs
  30. 10
      src/iOS/Avalonia.iOS/TopLevelImpl.cs
  31. 6
      tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs
  32. 30
      tests/Avalonia.Controls.UnitTests/TextBoxTests.cs
  33. 2
      tests/Avalonia.Controls.UnitTests/TopLevelTests.cs
  34. 6
      tests/Avalonia.Controls.UnitTests/TreeViewTests.cs
  35. 2
      tests/Avalonia.Input.UnitTests/MouseDeviceTests.cs
  36. 23
      tests/Avalonia.UnitTests/MouseTestHelper.cs

8
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;
}

6
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;

4
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));
}
/// <inheritdoc/>
@ -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));
}
/// <summary>

23
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<DragDropEffects> _result = new Subject<DragDropEffects>();
@ -25,7 +25,7 @@ namespace Avalonia.Platform
private Point _lastPosition;
private StandardCursorType _lastCursorType;
private object _originalCursor;
private InputModifiers? _initialInputModifiers;
private RawInputModifiers? _initialInputModifiers;
public InProcessDragSource()
{
@ -56,8 +56,7 @@ namespace Avalonia.Platform
return DragDropEffects.None;
}
private DragDropEffects RaiseEventAndUpdateCursor(RawDragEventType type, IInputElement root, Point pt, InputModifiers modifiers)
private DragDropEffects RaiseEventAndUpdateCursor(RawDragEventType type, IInputElement root, Point pt, RawInputModifiers modifiers)
{
_lastPosition = pt;
@ -70,13 +69,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 +131,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);
}
@ -160,7 +159,7 @@ namespace Avalonia.Platform
_initialInputModifiers = e.InputModifiers & MOUSE_INPUTMODIFIERS;
void CheckDraggingAccepted(InputModifiers changedMouseButton)
void CheckDraggingAccepted(RawInputModifiers changedMouseButton)
{
if (_initialInputModifiers.Value.HasFlag(changedMouseButton))
{
@ -185,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)

24
src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs

@ -57,9 +57,13 @@ namespace Avalonia.Controls.Remote.Server
}
}
private static InputModifiers GetAvaloniaInputModifiers (Avalonia.Remote.Protocol.Input.InputModifiers[] modifiers)
private static RawInputModifiers GetAvaloniaRawInputModifiers(
Avalonia.Remote.Protocol.Input.InputModifiers[] modifiers)
=> (RawInputModifiers)GetAvaloniaInputModifiers(modifiers);
private static RawInputModifiers GetAvaloniaInputModifiers (Avalonia.Remote.Protocol.Input.InputModifiers[] modifiers)
{
var result = InputModifiers.None;
var result = RawInputModifiers.None;
if (modifiers == null)
{
@ -71,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;
}
}
@ -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)

4
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))

32
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,26 @@ namespace Avalonia.Input
Toggled = 2,
}
[Flags]
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; }

5
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; }
}
}

9
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<string, Key> KeySynonyms = new Dictionary<string, Key>

2
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,
};

85
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<ArgumentNullException>(device != null);
Contract.Requires<ArgumentNullException>(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<ArgumentNullException>(device != 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,
InputModifiers inputModifiers)
KeyModifiers inputModifiers)
{
Contract.Requires<ArgumentNullException>(device != null);
Contract.Requires<ArgumentNullException>(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<ArgumentNullException>(device != null);
Contract.Requires<ArgumentNullException>(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<ArgumentNullException>(device != null);
Contract.Requires<ArgumentNullException>(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<ArgumentNullException>(device != null);
Contract.Requires<ArgumentNullException>(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<ArgumentNullException>(device != null);
Contract.Requires<ArgumentNullException>(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<ArgumentNullException>(device != null);
Contract.Requires<ArgumentNullException>(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);

38
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,24 @@ 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;
return mods;
}
}
public KeyModifiers KeyModifiers { get; }
public Point GetPosition(IVisual relativeTo)
{
@ -73,6 +90,8 @@ namespace Avalonia.Input
public PointerPoint GetPointerPoint(IVisual relativeTo)
=> new PointerPoint(Pointer, GetPosition(relativeTo), _properties);
protected PointerPointProperties Properties => _properties;
}
public enum MouseButton
@ -93,7 +112,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)
@ -104,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
@ -112,15 +132,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

54
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
}
}

2
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)
{

4
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;
}
}
}

4
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; }
}

2
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;

4
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<ArgumentNullException>(device != null);
@ -73,6 +73,6 @@ namespace Avalonia.Input.Raw
/// <summary>
/// Gets the input modifiers.
/// </summary>
public InputModifiers InputModifiers { get; private set; }
public RawInputModifiers InputModifiers { get; private set; }
}
}

2
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)
{

31
src/Avalonia.Input/TouchDevice.cs

@ -15,14 +15,15 @@ namespace Avalonia.Input
{
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)
@ -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)));
}

6
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);
@ -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;
}
}

19
src/Avalonia.X11/X11Window.cs

@ -558,24 +558,23 @@ namespace Avalonia.X11
}
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;
}

16
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<int, double>();

6
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));
}
}

32
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));

12
src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs

@ -14,31 +14,31 @@ namespace Avalonia.Win32.Input
public new static WindowsKeyboardDevice Instance { get; } = new WindowsKeyboardDevice();
public InputModifiers 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;

18
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;
}

8
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;
}

2
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);
}

10
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;
}

6
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
{

30
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
});
}

2
tests/Avalonia.Controls.UnitTests/TopLevelTests.cs

@ -183,7 +183,7 @@ namespace Avalonia.Controls.UnitTests
new Mock<IKeyboardDevice>().Object,
0,
RawKeyEventType.KeyDown,
Key.A, InputModifiers.None);
Key.A, RawInputModifiers.None);
impl.Object.Input(input);
inputManagerMock.Verify(x => x.ProcessInput(input));

6
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);

2
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<IRenderer> renderer, IControl hit)

23
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));
}
}

Loading…
Cancel
Save