diff --git a/src/Avalonia.Input/ITouchPadDevice.cs b/src/Avalonia.Input/ITouchPadDevice.cs
deleted file mode 100644
index ea6c57f948..0000000000
--- a/src/Avalonia.Input/ITouchPadDevice.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace Avalonia.Input
-{
- ///
- /// Represents a touch pad device.
- ///
- public interface ITouchPadDevice : IPointerDevice
- {
-
- }
-}
diff --git a/src/Avalonia.Input/TouchPadDevice.cs b/src/Avalonia.Input/TouchPadDevice.cs
deleted file mode 100644
index fcd254f588..0000000000
--- a/src/Avalonia.Input/TouchPadDevice.cs
+++ /dev/null
@@ -1,488 +0,0 @@
-using System;
-using System.Linq;
-using System.Reactive.Linq;
-using Avalonia.Input.Raw;
-using Avalonia.Interactivity;
-using Avalonia.Platform;
-using Avalonia.VisualTree;
-
-namespace Avalonia.Input
-{
- ///
- /// Represents a touch pad device.
- ///
- public class TouchPadDevice : ITouchPadDevice, IDisposable
- {
- private int _clickCount;
- private Rect _lastClickRect;
- private ulong _lastClickTime;
-
- private readonly Pointer _pointer;
- private bool _disposed;
- private PixelPoint? _position;
-
- public TouchPadDevice(Pointer? pointer = null)
- {
- _pointer = pointer ?? new Pointer(Pointer.GetNextFreeId(), PointerType.Mouse, true);
- }
-
- ///
- /// Gets the control that is currently capturing by the mouse, if any.
- ///
- ///
- /// When an element captures the mouse, it receives mouse input whether the cursor is
- /// within the control's bounds or not. To set the mouse capture, call the
- /// method.
- ///
- [Obsolete("Use IPointer instead")]
- public IInputElement? Captured => _pointer.Captured;
-
- ///
- /// Gets the mouse position, in screen coordinates.
- ///
- [Obsolete("Use events instead")]
- public PixelPoint Position
- {
- get => _position ?? new PixelPoint(-1, -1);
- protected set => _position = value;
- }
-
- ///
- /// Captures mouse input to the specified control.
- ///
- /// The control.
- ///
- /// When an element captures the mouse, it receives mouse input whether the cursor is
- /// within the control's bounds or not. The current mouse capture control is exposed
- /// by the property.
- ///
- public void Capture(IInputElement? control)
- {
- _pointer.Capture(control);
- }
-
- ///
- /// Gets the mouse position relative to a control.
- ///
- /// The control.
- /// The mouse position in the control's coordinates.
- public Point GetPosition(IVisual relativeTo)
- {
- relativeTo = relativeTo ?? throw new ArgumentNullException(nameof(relativeTo));
-
- if (relativeTo.VisualRoot == null)
- {
- throw new InvalidOperationException("Control is not attached to visual tree.");
- }
-
-#pragma warning disable CS0618 // Type or member is obsolete
- var rootPoint = relativeTo.VisualRoot.PointToClient(Position);
-#pragma warning restore CS0618 // Type or member is obsolete
- var transform = relativeTo.VisualRoot.TransformToVisual(relativeTo);
- return rootPoint * transform!.Value;
- }
-
- public void ProcessRawEvent(RawInputEventArgs e)
- {
- if (!e.Handled && e is RawPointerEventArgs margs)
- ProcessRawEvent(margs);
- }
-
- public void TopLevelClosed(IInputRoot root)
- {
- ClearPointerOver(this, 0, root, PointerPointProperties.None, KeyModifiers.None);
- }
-
- public void SceneInvalidated(IInputRoot root, Rect rect)
- {
- // Pointer is outside of the target area
- if (_position == null )
- {
- if (root.PointerOverElement != null)
- ClearPointerOver(this, 0, root, PointerPointProperties.None, KeyModifiers.None);
- return;
- }
-
-
- var clientPoint = root.PointToClient(_position.Value);
-
- if (rect.Contains(clientPoint))
- {
- if (_pointer.Captured == null)
- {
- SetPointerOver(this, 0 /* TODO: proper timestamp */, root, clientPoint,
- PointerPointProperties.None, KeyModifiers.None);
- }
- else
- {
- SetPointerOver(this, 0 /* TODO: proper timestamp */, root, _pointer.Captured,
- PointerPointProperties.None, KeyModifiers.None);
- }
- }
- }
-
- 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 = (TouchPadDevice)e.Device;
- if(mouse._disposed)
- return;
-
- _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, 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);
- 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);
- 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);
- break;
- }
- }
-
- private void LeaveWindow(ITouchPadDevice device, ulong timestamp, IInputRoot root, PointerPointProperties properties,
- KeyModifiers inputModifiers)
- {
- device = device ?? throw new ArgumentNullException(nameof(device));
- root = root ?? throw new ArgumentNullException(nameof(root));
-
- _position = null;
- ClearPointerOver(this, timestamp, root, properties, inputModifiers);
- }
-
-
- PointerPointProperties CreateProperties(RawPointerEventArgs args)
- {
-
- var kind = PointerUpdateKind.Other;
-
- if (args.Type == RawPointerEventType.LeftButtonDown)
- 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)
- 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(ITouchPadDevice device, ulong timestamp, IInputElement root, Point p,
- PointerPointProperties properties,
- KeyModifiers inputModifiers)
- {
- device = device ?? throw new ArgumentNullException(nameof(device));
- root = root ?? throw new ArgumentNullException(nameof(root));
-
- var hit = HitTest(root, p);
-
- if (hit != null)
- {
- _pointer.Capture(hit);
- var source = GetSource(hit);
- if (source != null)
- {
- var settings = AvaloniaLocator.Current.GetService();
- 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);
- source.RaiseEvent(e);
- return e.Handled;
- }
- }
-
- return false;
- }
-
- private bool MouseMove(ITouchPadDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties properties,
- KeyModifiers inputModifiers)
- {
- device = device ?? throw new ArgumentNullException(nameof(device));
- root = root ?? throw new ArgumentNullException(nameof(root));
-
- IInputElement? source;
-
- if (_pointer.Captured == null)
- {
- source = SetPointerOver(this, timestamp, root, p, properties, inputModifiers);
- }
- else
- {
- SetPointerOver(this, timestamp, root, _pointer.Captured, properties, inputModifiers);
- source = _pointer.Captured;
- }
-
- if (source is object)
- {
- var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, _pointer, root,
- p, timestamp, properties, inputModifiers);
-
- source.RaiseEvent(e);
- return e.Handled;
- }
-
- return false;
- }
-
- private bool MouseUp(ITouchPadDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties props,
- 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 PointerReleasedEventArgs(source, _pointer, root, p, timestamp, props, inputModifiers,
- _lastMouseDownButton);
-
- source?.RaiseEvent(e);
- _pointer.Capture(null);
- return e.Handled;
- }
-
- return false;
- }
-
- private bool MouseWheel(ITouchPadDevice 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)
- return null;
-
- return _pointer.Captured ??
- (hit as IInteractive) ??
- hit.GetSelfAndVisualAncestors().OfType().FirstOrDefault();
- }
-
- private IInputElement? HitTest(IInputElement root, Point p)
- {
- root = root ?? throw new ArgumentNullException(nameof(root));
-
- return _pointer.Captured ?? root.InputHitTest(p);
- }
-
- PointerEventArgs CreateSimpleEvent(RoutedEvent ev, ulong timestamp, IInteractive? source,
- PointerPointProperties properties,
- KeyModifiers inputModifiers)
- {
- return new PointerEventArgs(ev, source, _pointer, null, default,
- timestamp, properties, inputModifiers);
- }
-
- private void ClearPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root,
- PointerPointProperties properties,
- KeyModifiers inputModifiers)
- {
- device = device ?? throw new ArgumentNullException(nameof(device));
- root = root ?? throw new ArgumentNullException(nameof(root));
-
- var element = root.PointerOverElement;
- var e = CreateSimpleEvent(InputElement.PointerLeaveEvent, timestamp, element, properties, inputModifiers);
-
- if (element!=null && !element.IsAttachedToVisualTree)
- {
- // element has been removed from visual tree so do top down cleanup
- if (root.IsPointerOver)
- ClearChildrenPointerOver(e, root,true);
- }
- while (element != null)
- {
- e.Source = element;
- e.Handled = false;
- element.RaiseEvent(e);
- element = (IInputElement?)element.VisualParent;
- }
-
- root.PointerOverElement = null;
- }
-
- private void ClearChildrenPointerOver(PointerEventArgs e, IInputElement element,bool clearRoot)
- {
- foreach (IInputElement el in element.VisualChildren)
- {
- if (el.IsPointerOver)
- {
- ClearChildrenPointerOver(e, el, true);
- break;
- }
- }
- if(clearRoot)
- {
- e.Source = element;
- e.Handled = false;
- element.RaiseEvent(e);
- }
- }
-
- private IInputElement? SetPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root, Point p,
- PointerPointProperties properties,
- KeyModifiers inputModifiers)
- {
- device = device ?? throw new ArgumentNullException(nameof(device));
- root = root ?? throw new ArgumentNullException(nameof(root));
-
- var element = root.InputHitTest(p);
-
- if (element != root.PointerOverElement)
- {
- if (element != null)
- {
- SetPointerOver(device, timestamp, root, element, properties, inputModifiers);
- }
- else
- {
- ClearPointerOver(device, timestamp, root, properties, inputModifiers);
- }
- }
-
- return element;
- }
-
- private void SetPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root, IInputElement element,
- PointerPointProperties properties,
- KeyModifiers inputModifiers)
- {
- device = device ?? throw new ArgumentNullException(nameof(device));
- root = root ?? throw new ArgumentNullException(nameof(root));
- element = element ?? throw new ArgumentNullException(nameof(element));
-
- IInputElement? branch = null;
-
- IInputElement? el = element;
-
- while (el != null)
- {
- if (el.IsPointerOver)
- {
- branch = el;
- break;
- }
- el = (IInputElement?)el.VisualParent;
- }
-
- el = root.PointerOverElement;
-
- var e = CreateSimpleEvent(InputElement.PointerLeaveEvent, timestamp, el, properties, inputModifiers);
- if (el!=null && branch!=null && !el.IsAttachedToVisualTree)
- {
- ClearChildrenPointerOver(e,branch,false);
- }
-
- while (el != null && el != branch)
- {
- e.Source = el;
- e.Handled = false;
- el.RaiseEvent(e);
- el = (IInputElement?)el.VisualParent;
- }
-
- el = root.PointerOverElement = element;
- e.RoutedEvent = InputElement.PointerEnterEvent;
-
- while (el != null && el != branch)
- {
- e.Source = el;
- e.Handled = false;
- el.RaiseEvent(e);
- el = (IInputElement?)el.VisualParent;
- }
- }
-
- public void Dispose()
- {
- _disposed = true;
- _pointer?.Dispose();
- }
- }
-}
diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
index db81e8197f..5aecd8e8f0 100644
--- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
+++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
@@ -225,20 +225,17 @@ namespace Avalonia.Win32.Interop
[Flags]
public enum ModifierKeys
{
- MK_CONTROL = 0x0008,
+ MK_NONE = 0x0001,
MK_LBUTTON = 0x0001,
-
- MK_MBUTTON = 0x0010,
-
MK_RBUTTON = 0x0002,
- MK_SHIFT = 0x0004,
-
- MK_ALT = 0x0020,
+ MK_SHIFT = 0x0004,
+ MK_CONTROL = 0x0008,
+ MK_MBUTTON = 0x0010,
+ MK_ALT = 0x0020,
MK_XBUTTON1 = 0x0020,
-
MK_XBUTTON2 = 0x0040
}
@@ -531,14 +528,14 @@ namespace Avalonia.Win32.Interop
PDC_MODE_ASPECTRATIOPRESERVED = 0x800
}
- public enum InputType
+ public enum PointerInputType
{
- NONE = 0x00000000,
- POINTER = 0x00000001,
- TOUCH = 0x00000002,
- PEN = 0x00000003,
- MOUSE = 0x00000004,
- TOUCHPAD = 0x00000005
+ PT_NONE = 0x00000000,
+ PT_POINTER = 0x00000001,
+ PT_TOUCH = 0x00000002,
+ PT_PEN = 0x00000003,
+ PT_MOUSE = 0x00000004,
+ PT_TOUCHPAD = 0x00000005
}
public enum WindowsMessage : uint
@@ -882,6 +879,134 @@ namespace Avalonia.Win32.Interop
SCF_ISSECURE = 0x00000001,
}
+ [Flags]
+ public enum PointerFlags
+ {
+ POINTER_FLAG_NONE = 0x00000000,
+ POINTER_FLAG_NEW = 0x00000001,
+ POINTER_FLAG_INRANGE = 0x00000002,
+ POINTER_FLAG_INCONTACT = 0x00000004,
+ POINTER_FLAG_FIRSTBUTTON = 0x00000010,
+ POINTER_FLAG_SECONDBUTTON = 0x00000020,
+ POINTER_FLAG_THIRDBUTTON = 0x00000040,
+ POINTER_FLAG_FOURTHBUTTON = 0x00000080,
+ POINTER_FLAG_FIFTHBUTTON = 0x00000100,
+ POINTER_FLAG_PRIMARY = 0x00002000,
+ POINTER_FLAG_CONFIDENCE = 0x00000400,
+ POINTER_FLAG_CANCELED = 0x00000800,
+ POINTER_FLAG_DOWN = 0x00010000,
+ POINTER_FLAG_UPDATE = 0x00020000,
+ POINTER_FLAG_UP = 0x00040000,
+ POINTER_FLAG_WHEEL = 0x00080000,
+ POINTER_FLAG_HWHEEL = 0x00100000,
+ POINTER_FLAG_CAPTURECHANGED = 0x00200000,
+ POINTER_FLAG_HASTRANSFORM = 0x00400000
+ }
+
+ public enum PointerButtonChangeType : ulong
+ {
+ POINTER_CHANGE_NONE,
+ POINTER_CHANGE_FIRSTBUTTON_DOWN,
+ POINTER_CHANGE_FIRSTBUTTON_UP,
+ POINTER_CHANGE_SECONDBUTTON_DOWN,
+ POINTER_CHANGE_SECONDBUTTON_UP,
+ POINTER_CHANGE_THIRDBUTTON_DOWN,
+ POINTER_CHANGE_THIRDBUTTON_UP,
+ POINTER_CHANGE_FOURTHBUTTON_DOWN,
+ POINTER_CHANGE_FOURTHBUTTON_UP,
+ POINTER_CHANGE_FIFTHBUTTON_DOWN,
+ POINTER_CHANGE_FIFTHBUTTON_UP
+ }
+
+ [Flags]
+ public enum PenFlags
+ {
+ PEN_FLAGS_NONE = 0x00000000,
+ PEN_FLAGS_BARREL = 0x00000001,
+ PEN_FLAGS_INVERTED = 0x00000002,
+ PEN_FLAGS_ERASER = 0x00000004,
+ }
+
+ [Flags]
+ public enum PenMask
+ {
+ PEN_MASK_NONE = 0x00000000,
+ PEN_MASK_PRESSURE = 0x00000001,
+ PEN_MASK_ROTATION = 0x00000002,
+ PEN_MASK_TILT_X = 0x00000004,
+ PEN_MASK_TILT_Y = 0x00000008
+ }
+
+ [Flags]
+ public enum TouchFlags
+ {
+ TOUCH_FLAG_NONE = 0x00000000
+ }
+
+ [Flags]
+ public enum TouchMask
+ {
+ TOUCH_MASK_NONE = 0x00000000,
+ TOUCH_MASK_CONTACTAREA = 0x00000001,
+ TOUCH_MASK_ORIENTATION = 0x00000002,
+ TOUCH_MASK_PRESSURE = 0x00000004,
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct POINTER_TOUCH_INFO
+ {
+ public POINTER_INFO pointerInfo;
+ public TouchFlags touchFlags;
+ public TouchMask touchMask;
+ public int rcContactLeft;
+ public int rcContactTop;
+ public int rcContactRight;
+ public int rcContactBottom;
+ public int rcContactRawLeft;
+ public int rcContactRawTop;
+ public int rcContactRawRight;
+ public int rcContactRawBottom;
+ public uint orientation;
+ public uint pressure;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct POINTER_PEN_INFO
+ {
+ public POINTER_INFO pointerInfo;
+ public PenFlags penFlags;
+ public PenMask penMask;
+ public uint pressure;
+ public uint rotation;
+ public int tiltX;
+ public int tiltY;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct POINTER_INFO
+ {
+ public PointerInputType pointerType;
+ public uint pointerId;
+ public uint frameId;
+ public PointerFlags pointerFlags;
+ public IntPtr sourceDevice;
+ public IntPtr hwndTarget;
+ public int ptPixelLocationX;
+ public int ptPixelLocationY;
+ public int ptHimetricLocationX;
+ public int ptHimetricLocationY;
+ public int ptPixelLocationRawX;
+ public int ptPixelLocationRawY;
+ public int ptHimetricLocationRawX;
+ public int ptHimetricLocationRawY;
+ public uint dwTime;
+ public uint historyCount;
+ public int inputData;
+ public ModifierKeys dwKeyStates;
+ public UInt64 PerformanceCount;
+ public PointerButtonChangeType ButtonChangeType;
+ }
+
[StructLayout(LayoutKind.Sequential)]
public struct RGBQUAD
{
@@ -956,7 +1081,16 @@ namespace Avalonia.Win32.Interop
public static extern bool GetPointerCursorId(uint pointerID, out uint cursorId);
[DllImport("user32.dll", SetLastError = true)]
- public static extern bool GetPointerType(uint pointerID, out InputType pointerType);
+ public static extern bool GetPointerType(uint pointerID, out PointerInputType pointerType);
+
+ [DllImport("User32.dll", SetLastError = true)]
+ public static extern bool GetPointerInfo(uint pointerID, out POINTER_INFO pointerInfo);
+
+ [DllImport("User32.dll", SetLastError = true)]
+ public static extern bool GetPointerPenInfo(uint pointerID, out POINTER_PEN_INFO penInfo);
+
+ [DllImport("User32.dll", SetLastError = true)]
+ public static extern bool GetPointerTouchInfo(uint pointerID, out POINTER_TOUCH_INFO touchInfo);
[DllImport("user32.dll", SetLastError = true)]
public static extern void GetUnpredictedMessagePos();
diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs
index e16901af2c..8a0654a9ba 100644
--- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs
+++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs
@@ -427,17 +427,17 @@ namespace Avalonia.Win32
{
var pointerId = ToPointerId(wParam);
GetPointerType(pointerId, out var type);
- IInputDevice device = _mouseDevice;
+ IInputDevice device;
switch (type)
{
- case InputType.PEN:
-
+ case PointerInputType.PT_PEN:
+ device = _penDevice;
break;
- case InputType.TOUCH:
+ case PointerInputType.PT_TOUCH:
device = _touchDevice;
break;
- case InputType.TOUCHPAD:
-
+ default:
+ device = _mouseDevice;
break;
}
@@ -445,7 +445,7 @@ namespace Avalonia.Win32
var delta = GetWheelDelta(wParam);
var point = PointFromLParam(lParam);
e = new RawMouseWheelEventArgs(
- _mouseDevice,
+ device,
timestamp,
_owner,
PointToClient(point),
diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs
index e4f5268285..8f6a7e9741 100644
--- a/src/Windows/Avalonia.Win32/WindowImpl.cs
+++ b/src/Windows/Avalonia.Win32/WindowImpl.cs
@@ -64,6 +64,7 @@ namespace Avalonia.Win32
private const WindowStyles WindowStateMask = (WindowStyles.WS_MAXIMIZE | WindowStyles.WS_MINIMIZE);
private readonly TouchDevice _touchDevice;
private readonly MouseDevice _mouseDevice;
+ private readonly PenDevice _penDevice;
private readonly ManagedDeferredRendererLock _rendererLock;
private readonly FramebufferManager _framebuffer;
private readonly IGlPlatformSurface _gl;
@@ -96,6 +97,7 @@ namespace Avalonia.Win32
{
_touchDevice = new TouchDevice();
_mouseDevice = new WindowsMouseDevice();
+ _penDevice = new PenDevice();
#if USE_MANAGED_DRAG
_managedDrag = new ManagedWindowResizeDragHelper(this, capture =>