Browse Source

PenDevice tuning, Add pen properties to the PointerPointProperties

Stylus
Sergey Mikolaytis 4 years ago
parent
commit
4cea62fd13
  1. 2
      src/Avalonia.Input/IKeyboardDevice.cs
  2. 3
      src/Avalonia.Input/IPointer.cs
  3. 134
      src/Avalonia.Input/PenDevice.cs
  4. 30
      src/Avalonia.Input/PointerPoint.cs
  5. 8
      src/Avalonia.Input/Raw/RawPointerEventArgs.cs
  6. 64
      src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs

2
src/Avalonia.Input/IKeyboardDevice.cs

@ -47,6 +47,8 @@ namespace Avalonia.Input
MiddleMouseButton = 64,
XButton1MouseButton = 128,
XButton2MouseButton = 256,
BarrelPenButton = 512,
PenEraser = 1024,
KeyboardMask = Alt | Control | Shift | Meta
}

3
src/Avalonia.Input/IPointer.cs

@ -13,6 +13,7 @@ namespace Avalonia.Input
public enum PointerType
{
Mouse,
Touch
Touch,
Pen
}
}

134
src/Avalonia.Input/PenDevice.cs

@ -3,7 +3,6 @@ using System.Linq;
using System.Reactive.Linq;
using Avalonia.Input.Raw;
using Avalonia.Interactivity;
using Avalonia.Platform;
using Avalonia.VisualTree;
namespace Avalonia.Input
@ -13,17 +12,13 @@ namespace Avalonia.Input
/// </summary>
public class PenDevice : IPenDevice, IDisposable
{
private int _clickCount;
private Rect _lastClickRect;
private ulong _lastClickTime;
private readonly Pointer _pointer;
private bool _disposed;
private PixelPoint? _position;
public PenDevice(Pointer? pointer = null)
{
_pointer = pointer ?? new Pointer(Pointer.GetNextFreeId(), PointerType.Mouse, true);
_pointer = pointer ?? new Pointer(Pointer.GetNextFreeId(), PointerType.Pen, true);
}
/// <summary>
@ -37,16 +32,6 @@ namespace Avalonia.Input
[Obsolete("Use IPointer instead")]
public IInputElement? Captured => _pointer.Captured;
/// <summary>
/// Gets the mouse position, in screen coordinates.
/// </summary>
[Obsolete("Use events instead")]
public PixelPoint Position
{
get => _position ?? new PixelPoint(-1, -1);
protected set => _position = value;
}
/// <summary>
/// Captures mouse input to the specified control.
/// </summary>
@ -76,7 +61,7 @@ namespace Avalonia.Input
}
#pragma warning disable CS0618 // Type or member is obsolete
var rootPoint = relativeTo.VisualRoot.PointToClient(Position);
var rootPoint = relativeTo.VisualRoot.PointToClient(_position ?? new PixelPoint(-1, -1));
#pragma warning restore CS0618 // Type or member is obsolete
var transform = relativeTo.VisualRoot.TransformToVisual(relativeTo);
return rootPoint * transform!.Value;
@ -120,29 +105,13 @@ namespace Avalonia.Input
}
}
}
int ButtonCount(PointerPointProperties props)
{
var rv = 0;
if (props.IsLeftButtonPressed)
rv++;
if (props.IsMiddleButtonPressed)
rv++;
if (props.IsRightButtonPressed)
rv++;
if (props.IsXButton1Pressed)
rv++;
if (props.IsXButton2Pressed)
rv++;
return rv;
}
private void ProcessRawEvent(RawPointerEventArgs e)
{
e = e ?? throw new ArgumentNullException(nameof(e));
var mouse = (PenDevice)e.Device;
if(mouse._disposed)
var pen = (PenDevice)e.Device;
if(pen._disposed)
return;
_position = e.Root.PointToScreen(e.Position);
@ -151,34 +120,16 @@ namespace Avalonia.Input
switch (e.Type)
{
case RawPointerEventType.LeaveWindow:
LeaveWindow(mouse, e.Timestamp, e.Root, props, keyModifiers);
LeaveWindow(pen, e.Timestamp, e.Root, props, keyModifiers);
break;
case RawPointerEventType.LeftButtonDown:
case RawPointerEventType.RightButtonDown:
case RawPointerEventType.MiddleButtonDown:
case RawPointerEventType.XButton1Down:
case RawPointerEventType.XButton2Down:
if (ButtonCount(props) > 1)
e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers);
else
e.Handled = MouseDown(mouse, e.Timestamp, e.Root, e.Position,
props, keyModifiers);
case RawPointerEventType.PenBegin:
e.Handled = PenDown(pen, e.Timestamp, e.Root, e.Position, props, keyModifiers);
break;
case RawPointerEventType.LeftButtonUp:
case RawPointerEventType.RightButtonUp:
case RawPointerEventType.MiddleButtonUp:
case RawPointerEventType.XButton1Up:
case RawPointerEventType.XButton2Up:
if (ButtonCount(props) != 0)
e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers);
else
e.Handled = MouseUp(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers);
case RawPointerEventType.PenEnd:
e.Handled = PenUp(pen, e.Timestamp, e.Root, e.Position, props, keyModifiers);
break;
case RawPointerEventType.Move:
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, keyModifiers);
case RawPointerEventType.PenUpdate:
e.Handled = PenMove(pen, e.Timestamp, e.Root, e.Position, props, keyModifiers);
break;
}
}
@ -196,35 +147,18 @@ namespace Avalonia.Input
PointerPointProperties CreateProperties(RawPointerEventArgs args)
{
var kind = PointerUpdateKind.Other;
if (args.Type == RawPointerEventType.LeftButtonDown)
if (args.Type == RawPointerEventType.PenBegin)
kind = PointerUpdateKind.LeftButtonPressed;
if (args.Type == RawPointerEventType.MiddleButtonDown)
kind = PointerUpdateKind.MiddleButtonPressed;
if (args.Type == RawPointerEventType.RightButtonDown)
kind = PointerUpdateKind.RightButtonPressed;
if (args.Type == RawPointerEventType.XButton1Down)
kind = PointerUpdateKind.XButton1Pressed;
if (args.Type == RawPointerEventType.XButton2Down)
kind = PointerUpdateKind.XButton2Pressed;
if (args.Type == RawPointerEventType.LeftButtonUp)
if (args.Type == RawPointerEventType.PenEnd)
kind = PointerUpdateKind.LeftButtonReleased;
if (args.Type == RawPointerEventType.MiddleButtonUp)
kind = PointerUpdateKind.MiddleButtonReleased;
if (args.Type == RawPointerEventType.RightButtonUp)
kind = PointerUpdateKind.RightButtonReleased;
if (args.Type == RawPointerEventType.XButton1Up)
kind = PointerUpdateKind.XButton1Released;
if (args.Type == RawPointerEventType.XButton2Up)
kind = PointerUpdateKind.XButton2Released;
return new PointerPointProperties(args.InputModifiers, kind);
}
private MouseButton _lastMouseDownButton;
private bool MouseDown(IPenDevice device, ulong timestamp, IInputElement root, Point p,
private bool PenDown(IPenDevice device, ulong timestamp, IInputElement root, Point p,
PointerPointProperties properties,
KeyModifiers inputModifiers)
{
@ -239,21 +173,8 @@ namespace Avalonia.Input
var source = GetSource(hit);
if (source != null)
{
var settings = AvaloniaLocator.Current.GetService<IPlatformSettings>();
var doubleClickTime = settings?.DoubleClickTime.TotalMilliseconds ?? 500;
var doubleClickSize = settings?.DoubleClickSize ?? new Size(4, 4);
if (!_lastClickRect.Contains(p) || timestamp - _lastClickTime > doubleClickTime)
{
_clickCount = 0;
}
++_clickCount;
_lastClickTime = timestamp;
_lastClickRect = new Rect(p, new Size())
.Inflate(new Thickness(doubleClickSize.Width / 2, doubleClickSize.Height / 2));
_lastMouseDownButton = properties.PointerUpdateKind.GetMouseButton();
var e = new PointerPressedEventArgs(source, _pointer, root, p, timestamp, properties, inputModifiers, _clickCount);
var e = new PointerPressedEventArgs(source, _pointer, root, p, timestamp, properties, inputModifiers, 1);
source.RaiseEvent(e);
return e.Handled;
}
@ -262,7 +183,7 @@ namespace Avalonia.Input
return false;
}
private bool MouseMove(IPenDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties properties,
private bool PenMove(IPenDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties properties,
KeyModifiers inputModifiers)
{
device = device ?? throw new ArgumentNullException(nameof(device));
@ -292,7 +213,7 @@ namespace Avalonia.Input
return false;
}
private bool MouseUp(IPenDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties props,
private bool PenUp(IPenDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties props,
KeyModifiers inputModifiers)
{
device = device ?? throw new ArgumentNullException(nameof(device));
@ -314,27 +235,6 @@ namespace Avalonia.Input
return false;
}
private bool MouseWheel(IPenDevice device, ulong timestamp, IInputRoot root, Point p,
PointerPointProperties props,
Vector delta, KeyModifiers inputModifiers)
{
device = device ?? throw new ArgumentNullException(nameof(device));
root = root ?? throw new ArgumentNullException(nameof(root));
var hit = HitTest(root, p);
var source = GetSource(hit);
if (source is not null)
{
var e = new PointerWheelEventArgs(source, _pointer, root, p, timestamp, props, inputModifiers, delta);
source?.RaiseEvent(e);
return e.Handled;
}
return false;
}
private IInteractive? GetSource(IVisual? hit)
{
if (hit is null)

30
src/Avalonia.Input/PointerPoint.cs

@ -20,6 +20,14 @@ namespace Avalonia.Input
public bool IsRightButtonPressed { get; }
public bool IsXButton1Pressed { get; }
public bool IsXButton2Pressed { get; }
public bool IsBarrelButtonPressed { get; }
public bool IsEraser { get; }
public float Twist { get; }
public float Pressure { get; }
public float XTilt { get; }
public float YTilt { get; }
public PointerUpdateKind PointerUpdateKind { get; }
@ -36,10 +44,12 @@ namespace Avalonia.Input
IsRightButtonPressed = modifiers.HasAllFlags(RawInputModifiers.RightMouseButton);
IsXButton1Pressed = modifiers.HasAllFlags(RawInputModifiers.XButton1MouseButton);
IsXButton2Pressed = modifiers.HasAllFlags(RawInputModifiers.XButton2MouseButton);
IsBarrelButtonPressed = modifiers.HasAllFlags(RawInputModifiers.BarrelPenButton);
IsEraser = modifiers.HasAllFlags(RawInputModifiers.PenEraser);
// 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)
@ -60,6 +70,20 @@ namespace Avalonia.Input
IsXButton2Pressed = true;
if (kind == PointerUpdateKind.XButton2Released)
IsXButton2Pressed = false;
if (kind == PointerUpdateKind.BarrelButtonPressed)
IsBarrelButtonPressed = true;
if (kind == PointerUpdateKind.BarrelButtonReleased)
IsBarrelButtonPressed = false;
}
public PointerPointProperties(RawInputModifiers modifiers, PointerUpdateKind kind,
float twist, float pressure, float xTilt, float yTilt
) : this (modifiers, kind)
{
Twist = twist;
Pressure = pressure;
XTilt = xTilt;
YTilt = yTilt;
}
public static PointerPointProperties None { get; } = new PointerPointProperties();
@ -77,7 +101,9 @@ namespace Avalonia.Input
RightButtonReleased,
XButton1Released,
XButton2Released,
Other
Other,
BarrelButtonPressed,
BarrelButtonReleased
}
public static class PointerUpdateKindExtensions

8
src/Avalonia.Input/Raw/RawPointerEventArgs.cs

@ -21,7 +21,13 @@ namespace Avalonia.Input.Raw
TouchBegin,
TouchUpdate,
TouchEnd,
TouchCancel
TouchCancel,
PenBegin,
PenUpdate,
PenEnd,
PenCancel,
BarrelUp,
BarrelDown,
}
/// <summary>

64
src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs

@ -374,17 +374,6 @@ namespace Avalonia.Win32
break;
}
case WindowsMessage.WM_POINTERDEVICECHANGE:
{
//notifies about changes in the settings of a monitor that has a digitizer attached to it.
@ -414,7 +403,10 @@ namespace Avalonia.Win32
GetDeviceInfo(wParam, out var device, out var info);
var point = PointToClient(PointFromLParam(lParam));
var modifiers = GetInputModifiers(info.dwKeyStates);
var eventType = info.ButtonChangeType switch
if (info.ButtonChangeType != PointerButtonChangeType.POINTER_CHANGE_NONE)
{
var eventType = info.ButtonChangeType switch
{
PointerButtonChangeType.POINTER_CHANGE_FIRSTBUTTON_DOWN => RawPointerEventType.LeftButtonDown,
PointerButtonChangeType.POINTER_CHANGE_SECONDBUTTON_DOWN => RawPointerEventType.RightButtonDown,
@ -428,12 +420,13 @@ namespace Avalonia.Win32
PointerButtonChangeType.POINTER_CHANGE_FOURTHBUTTON_UP => RawPointerEventType.XButton1Up,
PointerButtonChangeType.POINTER_CHANGE_FIFTHBUTTON_UP => RawPointerEventType.XButton2Up,
};
if (eventType == RawPointerEventType.NonClientLeftButtonDown &&
(WindowsMessage)msg == WindowsMessage.WM_NCPOINTERDOWN)
{
eventType = RawPointerEventType.NonClientLeftButtonDown;
if (eventType == RawPointerEventType.NonClientLeftButtonDown &&
(WindowsMessage)msg == WindowsMessage.WM_NCPOINTERDOWN)
{
eventType = RawPointerEventType.NonClientLeftButtonDown;
}
e = new RawPointerEventArgs(device, timestamp, _owner, eventType, point, modifiers);
}
e = new RawPointerEventArgs(device, timestamp, _owner, eventType, point, modifiers);
break;
}
case WindowsMessage.WM_POINTERUPDATE:
@ -446,7 +439,8 @@ namespace Avalonia.Win32
var point = PointToClient(PointFromLParam(lParam));
var modifiers = GetInputModifiers(info.dwKeyStates);
e = new RawPointerEventArgs(device, timestamp, _owner, RawPointerEventType.Move, point, modifiers);
e = new RawPointerEventArgs(
device, timestamp, _owner, RawPointerEventType.Move, point, modifiers);
break;
}
case WindowsMessage.WM_POINTERENTER:
@ -462,14 +456,10 @@ namespace Avalonia.Win32
{
GetDeviceInfo(wParam, out var device, out var info);
var point = PointToClient(PointFromLParam(lParam));
var modifiers = GetInputModifiers(info.dwKeyStates);
e = new RawPointerEventArgs(
device,
timestamp,
_owner,
RawPointerEventType.LeaveWindow,
point,
WindowsKeyboardDevice.Instance.Modifiers);
device, timestamp, _owner, RawPointerEventType.LeaveWindow, point, modifiers);
break;
}
case WindowsMessage.WM_POINTERACTIVATE:
@ -520,33 +510,11 @@ namespace Avalonia.Win32
}
case WindowsMessage.WM_PARENTNOTIFY:
{
//This message is sent in a dialog scenarios. Contains mouse position in an old-way,
//but listed in the wm_pointer reference
//This message is sent in a dialog scenarios. Contains mouse position.
//Old message, but listed in the wm_pointer reference
//https://docs.microsoft.com/en-us/previous-versions/windows/desktop/inputmsg/wm-parentnotify
break;
}
case WindowsMessage.WM_NCPAINT:
{
if (!HasFullDecorations)

Loading…
Cancel
Save