diff --git a/native/Avalonia.Native/src/OSX/AvnView.mm b/native/Avalonia.Native/src/OSX/AvnView.mm index b1688282d63..06b084b7a25 100644 --- a/native/Avalonia.Native/src/OSX/AvnView.mm +++ b/native/Avalonia.Native/src/OSX/AvnView.mm @@ -290,6 +290,40 @@ - (void)mouseEvent:(NSEvent *)event withType:(AvnRawMouseEventType) type delta.Y = [event deltaY]; } + float pressure = 0.5f; + float xTilt = 0.0f; + float yTilt = 0.0f; + AvnPointerDeviceType pointerType = AvnPointerDeviceType::Mouse; + + switch(event.subtype) + { + case NSEventSubtypeTabletPoint: + switch(event.type) + { + case NSEventTypeLeftMouseDown: + case NSEventTypeLeftMouseDragged: + case NSEventTypeRightMouseDown: + case NSEventTypeRightMouseDragged: + case NSEventTypeOtherMouseDown: + case NSEventTypeOtherMouseDragged: + pressure = event.pressure; + break; + default: + pressure = 0.0f; + break; + } + xTilt = event.tilt.x * 90; + yTilt = -event.tilt.y * 90; + pointerType = AvnPointerDeviceType::Pen; + break; + case NSEventSubtypeTabletProximity: + pressure = 0.0f; + pointerType = AvnPointerDeviceType::Pen; + break; + default: + break; + } + uint64_t timestamp = static_cast([event timestamp] * 1000); auto modifiers = [self getModifiers:[event modifierFlags]]; @@ -322,7 +356,7 @@ - (void)mouseEvent:(NSEvent *)event withType:(AvnRawMouseEventType) type auto parent = _parent.tryGet(); if(parent != nullptr) { - parent->TopLevelEvents->RawMouseEvent(type, timestamp, modifiers, point, delta); + parent->TopLevelEvents->RawMouseEvent(type, pointerType, timestamp, modifiers, point, delta, pressure, xTilt, yTilt); } [super mouseMoved:event]; diff --git a/native/Avalonia.Native/src/OSX/AvnWindow.mm b/native/Avalonia.Native/src/OSX/AvnWindow.mm index 6ccb902cd9a..2dee90bfa3c 100644 --- a/native/Avalonia.Native/src/OSX/AvnWindow.mm +++ b/native/Avalonia.Native/src/OSX/AvnWindow.mm @@ -492,7 +492,7 @@ - (void)sendEvent:(NSEvent *_Nonnull)event auto point = [self translateLocalPoint:avnPoint]; AvnVector delta = { 0, 0 }; - parent->BaseEvents->RawMouseEvent(NonClientLeftButtonDown, static_cast([event timestamp] * 1000), AvnInputModifiersNone, point, delta); + parent->BaseEvents->RawMouseEvent(NonClientLeftButtonDown, AvnPointerDeviceType::Mouse, static_cast([event timestamp] * 1000), AvnInputModifiersNone, point, delta, .5f, .0f, .0f); } if(!_isTransitioningToFullScreen) diff --git a/src/Avalonia.Native/TopLevelImpl.cs b/src/Avalonia.Native/TopLevelImpl.cs index 812307d991e..32d51718d00 100644 --- a/src/Avalonia.Native/TopLevelImpl.cs +++ b/src/Avalonia.Native/TopLevelImpl.cs @@ -68,6 +68,8 @@ internal class TopLevelImpl : ITopLevelImpl, IFramebufferPlatformSurface private PlatformBehaviorInhibition? _platformBehaviorInhibition; private readonly MouseDevice? _mouse; + private readonly PenDevice? _pen; + private readonly IKeyboardDevice? _keyboard; private readonly ICursorFactory? _cursorFactory; @@ -88,6 +90,7 @@ public TopLevelImpl(IAvaloniaNativeFactory factory) _keyboard = AvaloniaLocator.Current.GetService(); _mouse = new MouseDevice(); + _pen = new PenDevice(); _cursorFactory = AvaloniaLocator.Current.GetService(); } @@ -213,7 +216,7 @@ public bool RawKeyEvent( return args.Handled; } - public void RawMouseEvent(AvnRawMouseEventType type, ulong timeStamp, AvnInputModifiers modifiers, AvnPoint point, AvnVector delta) + public void RawMouseEvent(AvnRawMouseEventType type, AvnPointerDeviceType deviceType, ulong timeStamp, AvnInputModifiers modifiers, AvnPoint point, AvnVector delta, float pressure, float xTilt, float yTilt) { if (_inputRoot is null) return; @@ -248,8 +251,15 @@ public void RawMouseEvent(AvnRawMouseEventType type, ulong timeStamp, AvnInputMo break; default: - var e = new RawPointerEventArgs(_mouse, timeStamp, _inputRoot, (RawPointerEventType)type, - point.ToAvaloniaPoint(), (RawInputModifiers)modifiers); + IInputDevice device = deviceType == AvnPointerDeviceType.Pen && _pen != null ? _pen : _mouse; + var e = new RawPointerEventArgs(device, timeStamp, _inputRoot, (RawPointerEventType)type, + new RawPointerPoint + { + Position = point.ToAvaloniaPoint(), + Pressure = pressure, + XTilt = xTilt, + YTilt = yTilt + }, (RawInputModifiers)modifiers); if (!ChromeHitTest(e)) { @@ -435,9 +445,9 @@ void IAvnTopLevelEvents.Resized(AvnSize* size, AvnPlatformResizeReason reason) _parent.Resized?.Invoke(s, (WindowResizeReason)reason); } - void IAvnTopLevelEvents.RawMouseEvent(AvnRawMouseEventType type, ulong timeStamp, AvnInputModifiers modifiers, AvnPoint point, AvnVector delta) + void IAvnTopLevelEvents.RawMouseEvent(AvnRawMouseEventType type, AvnPointerDeviceType pointerDeviceType, ulong timeStamp, AvnInputModifiers modifiers, AvnPoint point, AvnVector delta, float pressure, float xTilt, float yTilt) { - _parent.RawMouseEvent(type, timeStamp, modifiers, point, delta); + _parent.RawMouseEvent(type, pointerDeviceType, timeStamp, modifiers, point, delta, pressure, xTilt, yTilt); } int IAvnTopLevelEvents.RawKeyEvent(AvnRawKeyEventType type, ulong timeStamp, AvnInputModifiers modifiers, AvnKey key, AvnPhysicalKey physicalKey, string keySymbol) diff --git a/src/Avalonia.Native/avn.idl b/src/Avalonia.Native/avn.idl index 91c8c9c23ce..f913aaac776 100644 --- a/src/Avalonia.Native/avn.idl +++ b/src/Avalonia.Native/avn.idl @@ -667,6 +667,12 @@ enum AvnPlatformThemeVariant HighContrastDark, } +enum AvnPointerDeviceType +{ + Mouse, + Pen, +} + [uuid(809c652e-7396-11d2-9771-00a0c9b4d50c)] interface IAvaloniaNativeFactory : IUnknown { @@ -786,10 +792,15 @@ interface IAvnTopLevelEvents : IUnknown HRESULT Paint(); void Resized([const] AvnSize& size, AvnPlatformResizeReason reason); void RawMouseEvent(AvnRawMouseEventType type, + AvnPointerDeviceType deviceType, u_int64_t timeStamp, AvnInputModifiers modifiers, AvnPoint point, - AvnVector delta); + AvnVector delta, + float pressure, + float xTilt, + float yTilt + ); bool RawKeyEvent(AvnRawKeyEventType type, u_int64_t timeStamp, AvnInputModifiers modifiers, AvnKey key, AvnPhysicalKey physicalKey, [const] char* keySymbol); bool RawTextInputEvent(u_int64_t timeStamp, [const] char* text);