Browse Source

Added PointerUpdateKind and replaced InputModifiers with KeyModifiers

Nikita Tsukanov 7 years ago
parent
commit
0bad390dac
  1. 4
      src/Avalonia.Controls/MenuItem.cs
  2. 4
      src/Avalonia.Controls/Platform/InProcessDragSource.cs
  3. 18
      src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs
  4. 1
      src/Avalonia.Input/IKeyboardDevice.cs
  5. 85
      src/Avalonia.Input/MouseDevice.cs
  6. 50
      src/Avalonia.Input/PointerEventArgs.cs
  7. 54
      src/Avalonia.Input/PointerPoint.cs
  8. 2
      src/Avalonia.Input/PointerWheelEventArgs.cs
  9. 2
      src/Avalonia.Input/Raw/RawMouseWheelEventArgs.cs
  10. 4
      src/Avalonia.Input/Raw/RawPointerEventArgs.cs
  11. 2
      src/Avalonia.Input/Raw/RawTouchEventArgs.cs
  12. 31
      src/Avalonia.Input/TouchDevice.cs
  13. 4
      src/Avalonia.Native/WindowImplBase.cs
  14. 18
      src/Avalonia.X11/X11Window.cs
  15. 16
      src/Avalonia.X11/XI2Manager.cs
  16. 6
      src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.cs
  17. 14
      src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs
  18. 8
      src/Windows/Avalonia.Win32/WindowImpl.cs
  19. 6
      tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs
  20. 2
      tests/Avalonia.Input.UnitTests/MouseDeviceTests.cs
  21. 23
      tests/Avalonia.UnitTests/MouseTestHelper.cs

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>

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

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

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

1
src/Avalonia.Input/IKeyboardDevice.cs

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

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

50
src/Avalonia.Input/PointerEventArgs.cs

@ -20,7 +20,7 @@ namespace Avalonia.Input
IVisual rootVisual, Point rootVisualPosition,
ulong timestamp,
PointerPointProperties properties,
InputModifiers modifiers)
KeyModifiers modifiers)
: base(routedEvent)
{
Source = source;
@ -29,7 +29,7 @@ namespace Avalonia.Input
_properties = properties;
Pointer = pointer;
Timestamp = timestamp;
InputModifiers = modifiers;
KeyModifiers = modifiers;
}
class EmulatedDevice : IPointerDevice
@ -60,7 +60,39 @@ namespace Avalonia.Input
[Obsolete("Use Pointer to get pointer-specific information")]
public IPointerDevice Device => _device ?? (_device = new EmulatedDevice(this));
public InputModifiers InputModifiers { get; }
[Obsolete("Use KeyModifiers and PointerPointProperties")]
public InputModifiers InputModifiers
{
get
{
var mods = (InputModifiers)KeyModifiers;
if (_properties.IsLeftButtonPressed)
mods |= InputModifiers.LeftMouseButton;
if (_properties.IsMiddleButtonPressed)
mods |= InputModifiers.MiddleMouseButton;
if (_properties.IsRightButtonPressed)
mods |= InputModifiers.RightMouseButton;
// The old InputModifiers has indicated the *previous* state, so we are emulating this legacy behavior
if (_properties.PointerUpdateKind == PointerUpdateKind.LeftButtonPressed)
mods &= ~InputModifiers.LeftMouseButton;
if (_properties.PointerUpdateKind == PointerUpdateKind.MiddleButtonPressed)
mods &= ~InputModifiers.MiddleMouseButton;
if (_properties.PointerUpdateKind == PointerUpdateKind.RightButtonPressed)
mods &= ~InputModifiers.RightMouseButton;
if (_properties.PointerUpdateKind == PointerUpdateKind.LeftButtonReleased)
mods |= InputModifiers.LeftMouseButton;
if (_properties.PointerUpdateKind == PointerUpdateKind.MiddleButtonReleased)
mods |= InputModifiers.MiddleMouseButton;
if (_properties.PointerUpdateKind == PointerUpdateKind.RightButtonReleased)
mods |= InputModifiers.RightMouseButton;
return mods;
}
}
public KeyModifiers KeyModifiers { get; }
public Point GetPosition(IVisual relativeTo)
{
@ -73,6 +105,8 @@ namespace Avalonia.Input
public PointerPoint GetPointerPoint(IVisual relativeTo)
=> new PointerPoint(Pointer, GetPosition(relativeTo), _properties);
protected PointerPointProperties Properties => _properties;
}
public enum MouseButton
@ -93,7 +127,7 @@ namespace Avalonia.Input
IVisual rootVisual, Point rootVisualPosition,
ulong timestamp,
PointerPointProperties properties,
InputModifiers modifiers,
KeyModifiers modifiers,
int obsoleteClickCount = 1)
: base(InputElement.PointerPressedEvent, source, pointer, rootVisual, rootVisualPosition,
timestamp, properties, modifiers)
@ -112,15 +146,15 @@ namespace Avalonia.Input
public PointerReleasedEventArgs(
IInteractive source, IPointer pointer,
IVisual rootVisual, Point rootVisualPosition, ulong timestamp,
PointerPointProperties properties, InputModifiers modifiers, MouseButton obsoleteMouseButton)
PointerPointProperties properties, KeyModifiers modifiers)
: base(InputElement.PointerReleasedEvent, source, pointer, rootVisual, rootVisualPosition,
timestamp, properties, modifiers)
{
MouseButton = obsoleteMouseButton;
}
[Obsolete()]
public MouseButton MouseButton { get; private set; }
[Obsolete("Use PointerUpdateKind")]
public MouseButton MouseButton => Properties.GetObsoleteMouseButton();
}
public class PointerCaptureLostEventArgs : RoutedEventArgs

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

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

4
src/Avalonia.Native/WindowImplBase.cs

@ -223,11 +223,11 @@ namespace Avalonia.Native
switch (type)
{
case AvnRawMouseEventType.Wheel:
Input?.Invoke(new RawMouseWheelEventArgs(_mouse, timeStamp, _inputRoot, point.ToAvaloniaPoint(), new Vector(delta.X, delta.Y), (InputModifiers)modifiers));
Input?.Invoke(new RawMouseWheelEventArgs(_mouse, timeStamp, _inputRoot, point.ToAvaloniaPoint(), new Vector(delta.X, delta.Y), (RawInputModifiers)modifiers));
break;
default:
Input?.Invoke(new RawPointerEventArgs(_mouse, timeStamp, _inputRoot, (RawPointerEventType)type, point.ToAvaloniaPoint(), (InputModifiers)modifiers));
Input?.Invoke(new RawPointerEventArgs(_mouse, timeStamp, _inputRoot, (RawPointerEventType)type, point.ToAvaloniaPoint(), (RawInputModifiers)modifiers));
break;
}
}

18
src/Avalonia.X11/X11Window.cs

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

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

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

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

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

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
{

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