From c215014efa65bc0a58e978faf7ca0017bdc3e6c5 Mon Sep 17 00:00:00 2001 From: Andrew Coates <30809111+acoates-ms@users.noreply.github.com> Date: Mon, 2 Oct 2023 07:17:33 -0700 Subject: [PATCH 1/5] Start comp pointer events --- .../Composition.Input.idl | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/vnext/Microsoft.ReactNative/Composition.Input.idl b/vnext/Microsoft.ReactNative/Composition.Input.idl index e36e84cebda..e89ae6602c3 100644 --- a/vnext/Microsoft.ReactNative/Composition.Input.idl +++ b/vnext/Microsoft.ReactNative/Composition.Input.idl @@ -25,4 +25,82 @@ namespace Microsoft.ReactNative.Composition.Input Windows.System.VirtualKey OriginalKey { get; }; } + interface IPointerPointTransform + { + IPointerPointTransform Inverse { get; }; + Boolean TryTransform(Windows.Foundation.Point inPoint, out Windows.Foundation.Point outPoint); + Boolean TryTransformBounds(Windows.Foundation.Rect inRect, out Windows.Foundation.Rect outRect); + }; + + enum PointerDeviceType + { + Touch = 0, + Pen, + Mouse, + Touchpad, + }; + + enum PointerUpdateKind + { + Other = 0, + LeftButtonPressed, + LeftButtonReleased, + RightButtonPressed, + RightButtonReleased, + MiddleButtonPressed, + MiddleButtonReleased, + XButton1Pressed, + XButton1Released, + XButton2Pressed, + XButton2Released, + }; + + runtimeclass PointerPointProperties + { + Windows.Foundation.Rect ContactRect { get; }; + Boolean IsBarrelButtonPressed { get; }; + Boolean IsCanceled { get; }; + Boolean IsEraser { get; }; + Boolean IsHorizontalMouseWheel { get; }; + Boolean IsInRange { get; }; + Boolean IsInverted { get; }; + Boolean IsLeftButtonPressed { get; }; + Boolean IsMiddleButtonPressed { get; }; + Boolean IsPrimary { get; }; + Boolean IsRightButtonPressed { get; }; + Boolean IsXButton1Pressed { get; }; + Boolean IsXButton2Pressed { get; }; + Int32 MouseWheelDelta { get; }; + Single Orientation { get; }; + PointerUpdateKind PointerUpdateKind{ get; }; + Single Pressure { get; }; + Boolean TouchConfidence { get; }; + Single Twist { get; }; + Single XTilt { get; }; + Single YTilt { get; }; + }; + + runtimeclass PointerPoint + { + UInt32 FrameId { get; }; + Boolean IsInContact{ get; }; + PointerDeviceType PointerDeviceType { get; }; + UInt32 PointerId{ get; }; + Windows.Foundation.Point Position { get; }; + PointerPointProperties Properties{ get; }; + UInt64 Timestamp { get; }; + PointerPoint GetTransformedPoint( + IPointerPointTransform transform); + }; + + runtimeclass PointerRoutedEventArgs : RoutedEventArgs + { + PointerPoint CurrentPoint { get; }; + Boolean Handled; + Windows.System.VirtualKeyModifiers KeyModifiers { get; }; + Windows.Foundation.Collections.IVector GetIntermediatePoints(); + Windows.Foundation.Collections.IVector GetIntermediateTransformedPoints( + IPointerPointTransform transform); + }; + } // namespace Microsoft.ReactNative.Composition.Input From f36ead3fef455f1cf976dafdac38203c6732089c Mon Sep 17 00:00:00 2001 From: Andrew Coates <30809111+acoates-ms@users.noreply.github.com> Date: Mon, 2 Oct 2023 14:25:04 -0700 Subject: [PATCH 2/5] more fix --- .../Composition.Input.idl | 5 +- .../Fabric/Composition/Composition.Input.cpp | 150 ++++++++++++++++++ .../Fabric/Composition/Composition.Input.h | 65 ++++++++ .../Composition/CompositionEventHandler.cpp | 20 +++ 4 files changed, 236 insertions(+), 4 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Composition.Input.idl b/vnext/Microsoft.ReactNative/Composition.Input.idl index e89ae6602c3..f6f2a67564a 100644 --- a/vnext/Microsoft.ReactNative/Composition.Input.idl +++ b/vnext/Microsoft.ReactNative/Composition.Input.idl @@ -95,12 +95,9 @@ namespace Microsoft.ReactNative.Composition.Input runtimeclass PointerRoutedEventArgs : RoutedEventArgs { - PointerPoint CurrentPoint { get; }; + PointerPoint GetCurrentPoint(Int32 tag); Boolean Handled; Windows.System.VirtualKeyModifiers KeyModifiers { get; }; - Windows.Foundation.Collections.IVector GetIntermediatePoints(); - Windows.Foundation.Collections.IVector GetIntermediateTransformedPoints( - IPointerPointTransform transform); }; } // namespace Microsoft.ReactNative.Composition.Input diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.cpp index 58052125f1b..b2e6c4b6c48 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.cpp @@ -3,6 +3,8 @@ #pragma once #include "Composition.Input.h" +#include +#include namespace winrt::Microsoft::ReactNative::Composition::Input::implementation { @@ -58,4 +60,152 @@ winrt::Windows::System::VirtualKey KeyRoutedEventArgs::OriginalKey() noexcept { return m_key; } +PointerPointProperties::PointerPointProperties(const winrt::Windows::UI::Input::PointerPointProperties& ppp) +: m_systemPPP(ppp) {} + +winrt::Windows::Foundation::Rect PointerPointProperties::ContactRect() noexcept{ + return m_systemPPP.ContactRect(); +} + +bool PointerPointProperties::IsBarrelButtonPressed() noexcept { + return m_systemPPP.IsBarrelButtonPressed(); +} + +bool PointerPointProperties::IsCanceled() noexcept { + return m_systemPPP.IsCanceled(); +} + +bool PointerPointProperties::IsEraser() noexcept { + return m_systemPPP.IsEraser(); +} + +bool PointerPointProperties::IsHorizontalMouseWheel() noexcept { + return m_systemPPP.IsHorizontalMouseWheel(); +} + +bool PointerPointProperties::IsInRange() noexcept { + return m_systemPPP.IsInRange(); +} + +bool PointerPointProperties::IsInverted() noexcept { + return m_systemPPP.IsInverted(); +} + +bool PointerPointProperties::IsLeftButtonPressed() noexcept { + return m_systemPPP.IsLeftButtonPressed(); +} + +bool PointerPointProperties::IsMiddleButtonPressed() noexcept { + return m_systemPPP.IsMiddleButtonPressed(); +} + +bool PointerPointProperties::IsPrimary() noexcept { + return m_systemPPP.IsPrimary(); +} + +bool PointerPointProperties::IsRightButtonPressed() noexcept { + return m_systemPPP.IsRightButtonPressed(); +} + +bool PointerPointProperties::IsXButton1Pressed() noexcept { + return m_systemPPP.IsXButton1Pressed(); +} + +bool PointerPointProperties::IsXButton2Pressed() noexcept { + return m_systemPPP.IsXButton2Pressed(); +} + +int32_t PointerPointProperties::MouseWheelDelta() noexcept { + return m_systemPPP.MouseWheelDelta(); +} + +float PointerPointProperties::Orientation() noexcept { + return m_systemPPP.Orientation(); +} + +PointerUpdateKind PointerPointProperties::PointerUpdateKind() noexcept { + return static_cast(m_systemPPP.PointerUpdateKind()); +} + +float PointerPointProperties::Pressure() noexcept { + return m_systemPPP.Pressure(); +} + +bool PointerPointProperties::TouchConfidence() noexcept { + return m_systemPPP.TouchConfidence(); +} + +float PointerPointProperties::Twist() noexcept { + return m_systemPPP.Twist(); +} + +float PointerPointProperties::XTilt() noexcept { + return m_systemPPP.XTilt(); +} + +float PointerPointProperties::YTilt() noexcept { + return m_systemPPP.YTilt(); +} + +PointerPoint::PointerPoint(const winrt::Windows::UI::Input::PointerPoint& pp) : m_systemPP(pp) {} + +uint32_t PointerPoint::FrameId() noexcept { + return m_systemPP.FrameId(); +} + +bool PointerPoint::IsInContact() noexcept { + return m_systemPP.IsInContact(); +} + +winrt::Microsoft::ReactNative::Composition::Input::PointerDeviceType PointerPoint::PointerDeviceType() noexcept { + return static_cast(m_systemPP.PointerDevice().PointerDeviceType()); +} + +uint32_t PointerPoint::PointerId() noexcept { + return m_systemPP.PointerId(); +} + +winrt::Windows::Foundation::Point PointerPoint::Position() noexcept { + return m_systemPP.Position(); +} + +winrt::Microsoft::ReactNative::Composition::Input::PointerPointProperties PointerPoint::Properties() noexcept { + return winrt::make(m_systemPP.Properties()); +} + +uint64_t PointerPoint::Timestamp() noexcept { + return m_systemPP.Timestamp(); +} + +winrt::Microsoft::ReactNative::Composition::Input::PointerPoint PointerPoint::GetTransformedPoint( + const IPointerPointTransform& transform) noexcept { + //return winrt::make< PointerPoint>(m_systemPP.GetTransformedPoint(transform)); // TODO pass transform on + return winrt::make(m_systemPP); +} + +PointerRoutedEventArgs::PointerRoutedEventArgs(facebook::react::Tag tag, const winrt::Windows::UI::Input::PointerPoint& pp) : m_tag(tag) { + m_pp = winrt::make(pp); // TODO transform? +} + +int32_t PointerRoutedEventArgs::OriginalSource() noexcept { + return m_tag; +} + +winrt::Microsoft::ReactNative::Composition::Input::PointerPoint PointerRoutedEventArgs::GetCurrentPoint(int32_t tag) noexcept { + return m_pp; // Apply transform? +} + +bool PointerRoutedEventArgs::Handled() noexcept { + return m_handled; +} + +void PointerRoutedEventArgs::Handled(bool value) noexcept { + m_handled = value; +} + +winrt::Windows::System::VirtualKeyModifiers PointerRoutedEventArgs::KeyModifiers() noexcept { + assert(false); + return winrt::Windows::System::VirtualKeyModifiers::None; +} + } // namespace winrt::Microsoft::ReactNative::Composition::Input::implementation diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.h b/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.h index 3a5ce8695da..69feabf9f53 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.h @@ -4,6 +4,9 @@ #pragma once #include #include +#include "Composition.Input.PointerPointProperties.g.h" +#include "Composition.Input.PointerPoint.g.h" +#include "Composition.Input.PointerRoutedEventArgs.g.h" namespace winrt::Microsoft::ReactNative::Composition::Input::implementation { @@ -28,4 +31,66 @@ struct KeyRoutedEventArgs : winrt::implements< winrt::Windows::UI::Core::CorePhysicalKeyStatus m_keyStatus; }; +struct PointerPointProperties : PointerPointPropertiesT { + PointerPointProperties(const winrt::Windows::UI::Input::PointerPointProperties& ppp); + + winrt::Windows::Foundation::Rect ContactRect() noexcept; + bool IsBarrelButtonPressed() noexcept; + bool IsCanceled() noexcept; + bool IsEraser() noexcept; + bool IsHorizontalMouseWheel() noexcept; + bool IsInRange() noexcept; + bool IsInverted() noexcept; + bool IsLeftButtonPressed() noexcept; + bool IsMiddleButtonPressed() noexcept; + bool IsPrimary() noexcept; + bool IsRightButtonPressed() noexcept; + bool IsXButton1Pressed() noexcept; + bool IsXButton2Pressed() noexcept; + int32_t MouseWheelDelta() noexcept; + float Orientation() noexcept; + PointerUpdateKind PointerUpdateKind() noexcept; + float Pressure() noexcept; + bool TouchConfidence() noexcept; + float Twist() noexcept; + float XTilt() noexcept; + float YTilt() noexcept; + +private: + winrt::Windows::UI::Input::PointerPointProperties m_systemPPP; +}; + +struct PointerPoint : PointerPointT +{ + PointerPoint(const winrt::Windows::UI::Input::PointerPoint& pp); + + uint32_t FrameId() noexcept; + bool IsInContact() noexcept; + PointerDeviceType PointerDeviceType() noexcept; + uint32_t PointerId() noexcept; + winrt::Windows::Foundation::Point Position() noexcept; + winrt::Microsoft::ReactNative::Composition::Input::PointerPointProperties Properties() noexcept; + uint64_t Timestamp() noexcept; + winrt::Microsoft::ReactNative::Composition::Input::PointerPoint GetTransformedPoint( + const IPointerPointTransform& transform) noexcept; + +private: + winrt::Windows::UI::Input::PointerPoint m_systemPP; +}; + +struct PointerRoutedEventArgs : PointerRoutedEventArgsT +{ + PointerRoutedEventArgs(facebook::react::Tag tag, const winrt::Windows::UI::Input::PointerPoint& pp); + + int32_t OriginalSource() noexcept; + winrt::Microsoft::ReactNative::Composition::Input::PointerPoint GetCurrentPoint(int32_t tag) noexcept; + bool Handled() noexcept; + void Handled(bool value) noexcept; + winrt::Windows::System::VirtualKeyModifiers KeyModifiers() noexcept; + private: + facebook::react::Tag m_tag{-1}; + bool m_handled{false}; + winrt::Microsoft::ReactNative::Composition::Input::PointerPoint m_pp{nullptr}; +}; + } // namespace winrt::Microsoft::ReactNative::Composition::Input::implementation diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp index d2a88909df4..efec383115b 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp @@ -179,7 +179,27 @@ winrt::Windows::UI::Core::CoreVirtualKeyStates CompositionEventHandler::GetKeySt int64_t CompositionEventHandler::SendMessage(uint32_t msg, uint64_t wParam, int64_t lParam) noexcept { switch (msg) { + case WM_POINTERCAPTURECHANGED: + case WM_POINTERENTER: + case WM_POINTERLEAVE: + case WM_POINTERUPDATE: + case WM_POINTERROUTEDAWAY: + case WM_POINTERROUTEDRELEASED: + case WM_POINTERROUTEDTO: + case WM_POINTERWHEEL: + case WM_POINTERHWHEEL: + case DM_POINTERHITTEST: + case WM_SETCURSOR: + case WM_CAPTURECHANGED: + { + return 0; + } + case WM_LBUTTONDOWN: { + + // This pointer point should be in rootview coords - or we need an offset args for the rootview (which islands would provide) + //auto pp = winrt::make(winrt::Windows::UI::Input::GetCurrentPoint(uint32_t const& pointerId)) + ButtonDown(msg, wParam, lParam); return 0; } From 08bb0d093f396cd75622190a80e3d38370e4c391 Mon Sep 17 00:00:00 2001 From: Andrew Coates <30809111+acoates-ms@users.noreply.github.com> Date: Tue, 3 Oct 2023 17:54:36 -0700 Subject: [PATCH 3/5] Pointer events --- .../CompositionRootView.idl | 4 - .../Fabric/ComponentView.h | 9 +- .../AbiCompositionViewComponentView.cpp | 24 ++ .../AbiCompositionViewComponentView.h | 8 + .../Fabric/Composition/Composition.Input.cpp | 289 +++++++++++++++--- .../Fabric/Composition/Composition.Input.h | 89 +++++- .../Composition/CompositionContextHelper.cpp | 3 + .../Composition/CompositionEventHandler.cpp | 281 ++++++----------- .../Composition/CompositionEventHandler.h | 19 +- .../Composition/CompositionHwndHost.cpp | 17 -- .../Composition/CompositionRootView.cpp | 9 - .../Fabric/Composition/CompositionRootView.h | 1 - .../CompositionRootView_emptyimpl.cpp | 2 - .../CompositionViewComponentView.cpp | 37 ++- .../CompositionViewComponentView.h | 10 +- .../ReactCompositionViewComponentBuilder.cpp | 44 +++ .../ReactCompositionViewComponentBuilder.h | 15 + .../Composition/ScrollViewComponentView.cpp | 71 +++-- .../Composition/ScrollViewComponentView.h | 6 +- .../Composition/SwitchComponentView.cpp | 25 +- .../Fabric/Composition/SwitchComponentView.h | 5 +- .../WindowsTextInputComponentView.cpp | 189 ++++++++++++ .../TextInput/WindowsTextInputComponentView.h | 7 + .../IReactCompositionViewComponentBuilder.idl | 8 + 24 files changed, 827 insertions(+), 345 deletions(-) diff --git a/vnext/Microsoft.ReactNative/CompositionRootView.idl b/vnext/Microsoft.ReactNative/CompositionRootView.idl index 677a14bdcb6..54ba69979ab 100644 --- a/vnext/Microsoft.ReactNative/CompositionRootView.idl +++ b/vnext/Microsoft.ReactNative/CompositionRootView.idl @@ -71,10 +71,6 @@ namespace Microsoft.ReactNative Int64 SendMessage(UInt32 Msg, UInt64 WParam, Int64 LParam); Object GetUiaProvider(); - - //void OnPointerPressed(PointerPressedArgs args); - //void OnMouseUp(Windows.Foundation.Point point); - void OnScrollWheel(Windows.Foundation.Point point, Int32 delta); } } // namespace Microsoft.ReactNative diff --git a/vnext/Microsoft.ReactNative/Fabric/ComponentView.h b/vnext/Microsoft.ReactNative/Fabric/ComponentView.h index f46270927e1..9277f0e00da 100644 --- a/vnext/Microsoft.ReactNative/Fabric/ComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/ComponentView.h @@ -69,13 +69,20 @@ struct IComponentView { virtual RECT getClientRect() const noexcept = 0; virtual void onFocusLost() noexcept = 0; virtual void onFocusGained() noexcept = 0; + virtual void onPointerPressed( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept = 0; + virtual void onPointerReleased( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept = 0; + virtual void onPointerMoved( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept = 0; + virtual void onPointerWheelChanged( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept = 0; virtual void onKeyDown( const winrt::Microsoft::ReactNative::Composition::Input::KeyboardSource &source, const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept = 0; virtual void onKeyUp( const winrt::Microsoft::ReactNative::Composition::Input::KeyboardSource &source, const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept = 0; - virtual bool ScrollWheel(facebook::react::Point pt, int32_t delta) noexcept = 0; virtual bool focusable() const noexcept = 0; virtual facebook::react::SharedViewEventEmitter eventEmitterAtPoint(facebook::react::Point pt) noexcept = 0; virtual facebook::react::SharedViewEventEmitter eventEmitter() noexcept = 0; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/AbiCompositionViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/AbiCompositionViewComponentView.cpp index 286dceceaa6..edd0589224e 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/AbiCompositionViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/AbiCompositionViewComponentView.cpp @@ -119,6 +119,30 @@ void AbiCompositionViewComponentView::onKeyUp( Super::onKeyUp(source, args); } +void AbiCompositionViewComponentView::onPointerPressed( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept { + Builder().OnPointerPressed(args); + Super::onPointerPressed(args); +} + +void AbiCompositionViewComponentView::onPointerReleased( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept { + Builder().OnPointerReleased(args); + Super::onPointerReleased(args); +} + +void AbiCompositionViewComponentView::onPointerMoved( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept { + Builder().OnPointerMoved(args); + Super::onPointerMoved(args); +} + +void AbiCompositionViewComponentView::onPointerWheelChanged( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept { + Builder().OnPointerWheelChanged(args); + Super::onPointerWheelChanged(args); +} + std::vector AbiCompositionViewComponentView::supplementalComponentDescriptorProviders() noexcept { return {}; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/AbiCompositionViewComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/AbiCompositionViewComponentView.h index f56c75aa5b5..6e06fa5ef3a 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/AbiCompositionViewComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/AbiCompositionViewComponentView.h @@ -47,6 +47,14 @@ struct AbiCompositionViewComponentView : CompositionBaseComponentView { void onKeyUp( const winrt::Microsoft::ReactNative::Composition::Input::KeyboardSource &source, const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept override; + void onPointerPressed( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept override; + void onPointerReleased( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept override; + void onPointerMoved( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept override; + void onPointerWheelChanged( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept override; std::vector supplementalComponentDescriptorProviders() noexcept override; facebook::react::Props::Shared props() noexcept override; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.cpp index b2e6c4b6c48..9c116c93365 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.cpp @@ -3,6 +3,7 @@ #pragma once #include "Composition.Input.h" +#include #include #include @@ -60,139 +61,348 @@ winrt::Windows::System::VirtualKey KeyRoutedEventArgs::OriginalKey() noexcept { return m_key; } -PointerPointProperties::PointerPointProperties(const winrt::Windows::UI::Input::PointerPointProperties& ppp) -: m_systemPPP(ppp) {} - -winrt::Windows::Foundation::Rect PointerPointProperties::ContactRect() noexcept{ +PointerPointProperties::PointerPointProperties(const winrt::Windows::UI::Input::PointerPointProperties &ppp) + : m_systemPPP(ppp) {} + +PointerPointProperties::PointerPointProperties( + bool isBarrelButtonPressed, + bool isCanceled, + bool isEraser, + bool isHorizontalMouseWheel, + bool isInRange, + bool isInverted, + bool isLeftButtonPressed, + bool isMiddleButtonPressed, + bool isPrimary, + bool isRightButtonPressed, + bool isXButton1Pressed, + bool isXButton2Pressed, + bool touchConfidence, + int32_t mouseWheelDelta, + float orientation, + winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind pointerUpdateKind, + float pressure, + float twist, + float xTilt, + float yTilt) + : m_isBarrelButtonPressed(isBarrelButtonPressed), + m_isCanceled(isCanceled), + m_isEraser(isEraser), + m_isHorizontalMouseWheel(isHorizontalMouseWheel), + m_isInRange(isInRange), + m_isInverted(isInverted), + m_isLeftButtonPressed(isLeftButtonPressed), + m_isMiddleButtonPressed(isMiddleButtonPressed), + m_isPrimary(isPrimary), + m_isRightButtonPressed(isRightButtonPressed), + m_isXButton1Pressed(isXButton1Pressed), + m_isXButton2Pressed(isXButton2Pressed), + m_touchConfidence(touchConfidence), + m_mouseWheelDelta(mouseWheelDelta), + m_orientation(orientation), + m_pointerUpdateKind(pointerUpdateKind), + m_pressure(pressure), + m_twist(twist), + m_xTilt(xTilt), + m_yTilt(yTilt) {} + +winrt::Windows::Foundation::Rect PointerPointProperties::ContactRect() noexcept { return m_systemPPP.ContactRect(); } bool PointerPointProperties::IsBarrelButtonPressed() noexcept { - return m_systemPPP.IsBarrelButtonPressed(); + return m_systemPPP ? m_systemPPP.IsBarrelButtonPressed() : m_isBarrelButtonPressed; } bool PointerPointProperties::IsCanceled() noexcept { - return m_systemPPP.IsCanceled(); + return m_systemPPP ? m_systemPPP.IsCanceled() : m_isCanceled; } bool PointerPointProperties::IsEraser() noexcept { - return m_systemPPP.IsEraser(); + return m_systemPPP ? m_systemPPP.IsEraser() : m_isEraser; } bool PointerPointProperties::IsHorizontalMouseWheel() noexcept { - return m_systemPPP.IsHorizontalMouseWheel(); + return m_systemPPP ? m_systemPPP.IsHorizontalMouseWheel() : m_isHorizontalMouseWheel; } bool PointerPointProperties::IsInRange() noexcept { - return m_systemPPP.IsInRange(); + return m_systemPPP ? m_systemPPP.IsInRange() : m_isInRange; } bool PointerPointProperties::IsInverted() noexcept { - return m_systemPPP.IsInverted(); + return m_systemPPP ? m_systemPPP.IsInverted() : m_isInverted; } bool PointerPointProperties::IsLeftButtonPressed() noexcept { - return m_systemPPP.IsLeftButtonPressed(); + return m_systemPPP ? m_systemPPP.IsLeftButtonPressed() : m_isLeftButtonPressed; } bool PointerPointProperties::IsMiddleButtonPressed() noexcept { - return m_systemPPP.IsMiddleButtonPressed(); + return m_systemPPP ? m_systemPPP.IsMiddleButtonPressed() : m_isMiddleButtonPressed; } bool PointerPointProperties::IsPrimary() noexcept { - return m_systemPPP.IsPrimary(); + return m_systemPPP ? m_systemPPP.IsPrimary() : m_isPrimary; } bool PointerPointProperties::IsRightButtonPressed() noexcept { - return m_systemPPP.IsRightButtonPressed(); + return m_systemPPP ? m_systemPPP.IsRightButtonPressed() : m_isRightButtonPressed; } bool PointerPointProperties::IsXButton1Pressed() noexcept { - return m_systemPPP.IsXButton1Pressed(); + return m_systemPPP ? m_systemPPP.IsXButton1Pressed() : m_isXButton1Pressed; } bool PointerPointProperties::IsXButton2Pressed() noexcept { - return m_systemPPP.IsXButton2Pressed(); + return m_systemPPP ? m_systemPPP.IsXButton2Pressed() : m_isXButton2Pressed; } int32_t PointerPointProperties::MouseWheelDelta() noexcept { - return m_systemPPP.MouseWheelDelta(); + return m_systemPPP ? m_systemPPP.MouseWheelDelta() : m_mouseWheelDelta; } float PointerPointProperties::Orientation() noexcept { - return m_systemPPP.Orientation(); + return m_systemPPP ? m_systemPPP.Orientation() : m_orientation; } PointerUpdateKind PointerPointProperties::PointerUpdateKind() noexcept { - return static_cast(m_systemPPP.PointerUpdateKind()); + return m_systemPPP ? static_cast( + m_systemPPP.PointerUpdateKind()) + : m_pointerUpdateKind; } float PointerPointProperties::Pressure() noexcept { - return m_systemPPP.Pressure(); + return m_systemPPP ? m_systemPPP.Pressure() : m_pressure; } bool PointerPointProperties::TouchConfidence() noexcept { - return m_systemPPP.TouchConfidence(); + return m_systemPPP ? m_systemPPP.TouchConfidence() : m_touchConfidence; } float PointerPointProperties::Twist() noexcept { - return m_systemPPP.Twist(); + return m_systemPPP ? m_systemPPP.Twist() : m_twist; } float PointerPointProperties::XTilt() noexcept { - return m_systemPPP.XTilt(); + return m_systemPPP ? m_systemPPP.XTilt() : m_xTilt; } float PointerPointProperties::YTilt() noexcept { - return m_systemPPP.YTilt(); + return m_systemPPP ? m_systemPPP.YTilt() : m_yTilt; } -PointerPoint::PointerPoint(const winrt::Windows::UI::Input::PointerPoint& pp) : m_systemPP(pp) {} +PointerPoint::PointerPoint(const winrt::Windows::UI::Input::PointerPoint &pp) : m_systemPP(pp) {} + +PointerPoint::PointerPoint(uint32_t msg, uint64_t wParam, int64_t lParam) { + m_msg = msg; + m_wParam = wParam; + m_lParam = lParam; + if (IsPointerMessage(msg)) { + const unsigned int pointerId = GET_POINTERID_WPARAM(wParam); + bool result = ::GetPointerInfo(pointerId, &m_pi); + assert(result); + } +} uint32_t PointerPoint::FrameId() noexcept { - return m_systemPP.FrameId(); + return m_systemPP ? m_systemPP.FrameId() : m_pi.frameId; } bool PointerPoint::IsInContact() noexcept { - return m_systemPP.IsInContact(); + return m_systemPP ? m_systemPP.IsInContact() + : ((m_pi.pointerFlags & POINTER_FLAG_INCONTACT) == POINTER_FLAG_INCONTACT); } winrt::Microsoft::ReactNative::Composition::Input::PointerDeviceType PointerPoint::PointerDeviceType() noexcept { - return static_cast(m_systemPP.PointerDevice().PointerDeviceType()); + if (m_systemPP) { + return static_cast( + m_systemPP.PointerDevice().PointerDeviceType()); + } + + if (m_pi.pointerId) { + switch (m_pi.pointerType) { + case PT_MOUSE: + return winrt::Microsoft::ReactNative::Composition::Input::PointerDeviceType::Mouse; + case PT_PEN: + return winrt::Microsoft::ReactNative::Composition::Input::PointerDeviceType::Pen; + case PT_TOUCHPAD: + return winrt::Microsoft::ReactNative::Composition::Input::PointerDeviceType::Touchpad; + case PT_TOUCH: + case PT_POINTER: + default: + return winrt::Microsoft::ReactNative::Composition::Input::PointerDeviceType::Touchpad; + } + } + + return winrt::Microsoft::ReactNative::Composition::Input::PointerDeviceType::Mouse; } uint32_t PointerPoint::PointerId() noexcept { - return m_systemPP.PointerId(); + return m_systemPP ? m_systemPP.PointerId() : (m_pi.pointerId ? m_pi.pointerId : 1 /* MOUSE */); } winrt::Windows::Foundation::Point PointerPoint::Position() noexcept { - return m_systemPP.Position(); + return m_systemPP + ? m_systemPP.Position() + : (m_pi.pointerId + ? winrt::Windows::Foundation:: + Point{static_cast(m_pi.ptPixelLocation.x), static_cast(m_pi.ptPixelLocation.y)} + : winrt::Windows::Foundation::Point{ + static_cast(GET_X_LPARAM(m_lParam)), static_cast(GET_Y_LPARAM(m_lParam))}); } winrt::Microsoft::ReactNative::Composition::Input::PointerPointProperties PointerPoint::Properties() noexcept { - return winrt::make(m_systemPP.Properties()); + if (m_systemPP) { + return winrt::make(m_systemPP.Properties()); + } + + if (m_pi.pointerId) { + auto pointerUpdateKind = winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::Other; + switch (m_pi.ButtonChangeType) { + case POINTER_CHANGE_FIRSTBUTTON_DOWN: + pointerUpdateKind = winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::LeftButtonPressed; + break; + case POINTER_CHANGE_FIRSTBUTTON_UP: + pointerUpdateKind = winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::LeftButtonReleased; + break; + case POINTER_CHANGE_SECONDBUTTON_DOWN: + pointerUpdateKind = winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::RightButtonPressed; + break; + case POINTER_CHANGE_SECONDBUTTON_UP: + pointerUpdateKind = winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::RightButtonReleased; + break; + case POINTER_CHANGE_THIRDBUTTON_DOWN: + pointerUpdateKind = winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::MiddleButtonPressed; + break; + case POINTER_CHANGE_THIRDBUTTON_UP: + pointerUpdateKind = winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::MiddleButtonReleased; + break; + case POINTER_CHANGE_FOURTHBUTTON_DOWN: + pointerUpdateKind = winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::XButton1Pressed; + break; + case POINTER_CHANGE_FOURTHBUTTON_UP: + pointerUpdateKind = winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::XButton1Released; + break; + case POINTER_CHANGE_FIFTHBUTTON_DOWN: + pointerUpdateKind = winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::XButton2Pressed; + break; + case POINTER_CHANGE_FIFTHBUTTON_UP: + pointerUpdateKind = winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::XButton2Released; + break; + } + + return winrt::make( + false, // TODO isBarrelButtonPressed, + (m_pi.pointerFlags & POINTER_FLAG_CANCELED) == POINTER_FLAG_CANCELED, // isCanceled + false, // TODO isEraser, + (m_pi.pointerFlags & POINTER_FLAG_HWHEEL) == POINTER_FLAG_HWHEEL, // isHorizontalMouseWheel + (m_pi.pointerFlags & POINTER_FLAG_INRANGE) == POINTER_FLAG_INRANGE, // isInRange + false, // TODO isInverted, + (m_pi.pointerFlags & POINTER_FLAG_FIRSTBUTTON) == POINTER_FLAG_FIRSTBUTTON, // isLeftButtonPressed + (m_pi.pointerFlags & POINTER_FLAG_THIRDBUTTON) == POINTER_FLAG_THIRDBUTTON, // isMiddleButtonPressed + (m_pi.pointerFlags & POINTER_FLAG_PRIMARY) == POINTER_FLAG_PRIMARY, // isPrimary + (m_pi.pointerFlags & POINTER_FLAG_SECONDBUTTON) == POINTER_FLAG_SECONDBUTTON, // isRightButtonPressed + (m_pi.pointerFlags & POINTER_FLAG_FOURTHBUTTON) == POINTER_FLAG_FOURTHBUTTON, // isXButton1Pressed + (m_pi.pointerFlags & POINTER_FLAG_FIFTHBUTTON) == POINTER_FLAG_FIFTHBUTTON, // isXButton2Pressed + (m_pi.pointerFlags & POINTER_FLAG_CONFIDENCE) == POINTER_FLAG_CONFIDENCE, // touchConfidence + false, // TODO mouseWheelDelta, + 0.0f, // TODO orientation, + pointerUpdateKind, + 0.0f, // TODO pressure, + 0.0f, // TODO twist, + 0.0f, // TODO xTilt, + 0.0f // TODO yTilt + ); + } + + auto pointerUpdateKind = winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::Other; + switch (m_msg) { + case WM_LBUTTONDOWN: + pointerUpdateKind = winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::LeftButtonPressed; + break; + case WM_LBUTTONUP: + pointerUpdateKind = winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::LeftButtonReleased; + break; + case WM_RBUTTONDOWN: + pointerUpdateKind = winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::RightButtonPressed; + break; + case WM_RBUTTONUP: + pointerUpdateKind = winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::RightButtonReleased; + break; + case WM_MBUTTONDOWN: + pointerUpdateKind = winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::MiddleButtonPressed; + break; + case WM_MBUTTONUP: + pointerUpdateKind = winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::MiddleButtonReleased; + break; + case WM_XBUTTONDOWN: + pointerUpdateKind = (GET_XBUTTON_WPARAM(m_wParam) == XBUTTON1) + ? winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::XButton1Pressed + : winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::XButton2Pressed; + break; + case WM_XBUTTONUP: + pointerUpdateKind = (GET_XBUTTON_WPARAM(m_wParam) == XBUTTON1) + ? winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::XButton1Released + : winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::XButton2Released; + break; + } + + return winrt::make( + false, // isBarrelButtonPressed, + false, // isCanceled, + false, // isEraser, + m_msg == WM_MOUSEHWHEEL, // isHorizontalMouseWheel, + false, // isInRange, + false, // isInverted, + (m_wParam & MK_LBUTTON) == MK_LBUTTON, + (m_wParam & MK_MBUTTON) == MK_MBUTTON, + true, // isPrimary, + (m_wParam & MK_RBUTTON) == MK_RBUTTON, + (m_wParam & MK_XBUTTON1) == MK_XBUTTON1, + (m_wParam & MK_XBUTTON2) == MK_XBUTTON2, + true, // touchConfidence, + (m_msg == WM_MOUSEWHEEL || m_msg == WM_MOUSEHWHEEL) ? GET_WHEEL_DELTA_WPARAM(m_wParam) : 0, // mouseWheelDelta, + 0.0f, // orientation, + pointerUpdateKind, + 0.0f, // pressure, + 0.0f, // twist, + 0.0f, // xTilt, + 0.0f // yTilt + ); } uint64_t PointerPoint::Timestamp() noexcept { - return m_systemPP.Timestamp(); + return m_systemPP ? m_systemPP.Timestamp() : m_pi.dwTime; } winrt::Microsoft::ReactNative::Composition::Input::PointerPoint PointerPoint::GetTransformedPoint( - const IPointerPointTransform& transform) noexcept { - //return winrt::make< PointerPoint>(m_systemPP.GetTransformedPoint(transform)); // TODO pass transform on + const IPointerPointTransform &transform) noexcept { return winrt::make(m_systemPP); } -PointerRoutedEventArgs::PointerRoutedEventArgs(facebook::react::Tag tag, const winrt::Windows::UI::Input::PointerPoint& pp) : m_tag(tag) { - m_pp = winrt::make(pp); // TODO transform? +bool PointerPoint::IsPointerMessage(uint32_t message) noexcept { + constexpr uint32_t WM_POINTERFIRST = 0x0245; + constexpr uint32_t WM_POINTERLAST = 0x0257; + return (message >= WM_POINTERFIRST && message <= WM_POINTERLAST); +} + +PointerRoutedEventArgs::PointerRoutedEventArgs( + facebook::react::Tag tag, + const winrt::Microsoft::ReactNative::Composition::Input::PointerPoint &pp, + const winrt::Windows::System::VirtualKeyModifiers &virtualKeyModifiers) + : m_tag(tag), m_virtualKeyModifiers(virtualKeyModifiers) { + m_pp = pp; } int32_t PointerRoutedEventArgs::OriginalSource() noexcept { return m_tag; } -winrt::Microsoft::ReactNative::Composition::Input::PointerPoint PointerRoutedEventArgs::GetCurrentPoint(int32_t tag) noexcept { - return m_pp; // Apply transform? +winrt::Microsoft::ReactNative::Composition::Input::PointerPoint PointerRoutedEventArgs::GetCurrentPoint( + int32_t tag) noexcept { + assert(tag == -1); // TODO: Non-null tags need to apply a transform + return m_pp; } bool PointerRoutedEventArgs::Handled() noexcept { @@ -204,8 +414,7 @@ void PointerRoutedEventArgs::Handled(bool value) noexcept { } winrt::Windows::System::VirtualKeyModifiers PointerRoutedEventArgs::KeyModifiers() noexcept { - assert(false); - return winrt::Windows::System::VirtualKeyModifiers::None; + return m_virtualKeyModifiers; } } // namespace winrt::Microsoft::ReactNative::Composition::Input::implementation diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.h b/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.h index 69feabf9f53..357c2049355 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.h @@ -2,11 +2,13 @@ // Licensed under the MIT License. #pragma once -#include -#include -#include "Composition.Input.PointerPointProperties.g.h" #include "Composition.Input.PointerPoint.g.h" +#include "Composition.Input.PointerPointProperties.g.h" #include "Composition.Input.PointerRoutedEventArgs.g.h" +#include +#include +#include +#include namespace winrt::Microsoft::ReactNative::Composition::Input::implementation { @@ -32,7 +34,29 @@ struct KeyRoutedEventArgs : winrt::implements< }; struct PointerPointProperties : PointerPointPropertiesT { - PointerPointProperties(const winrt::Windows::UI::Input::PointerPointProperties& ppp); + PointerPointProperties(const winrt::Windows::UI::Input::PointerPointProperties &ppp); + + PointerPointProperties( + bool isBarrelButtonPressed, + bool isCanceled, + bool isEraser, + bool isHorizontalMouseWheel, + bool isInRange, + bool isInverted, + bool isLeftButtonPressed, + bool isMiddleButtonPressed, + bool isPrimary, + bool isRightButtonPressed, + bool isXButton1Pressed, + bool isXButton2Pressed, + bool touchConfidence, + int32_t mouseWheelDelta, + float orientation, + PointerUpdateKind pointerUpdateKind, + float pressure, + float twist, + float xTilt, + float yTilt); winrt::Windows::Foundation::Rect ContactRect() noexcept; bool IsBarrelButtonPressed() noexcept; @@ -56,13 +80,35 @@ struct PointerPointProperties : PointerPointPropertiesT float XTilt() noexcept; float YTilt() noexcept; -private: - winrt::Windows::UI::Input::PointerPointProperties m_systemPPP; + private: + winrt::Windows::UI::Input::PointerPointProperties m_systemPPP{nullptr}; + + // When not using m_systemPPP + bool m_isBarrelButtonPressed : 1; + bool m_isCanceled : 1; + bool m_isEraser : 1; + bool m_isHorizontalMouseWheel : 1; + bool m_isInRange : 1; + bool m_isInverted : 1; + bool m_isLeftButtonPressed : 1; + bool m_isMiddleButtonPressed : 1; + bool m_isPrimary : 1; + bool m_isRightButtonPressed : 1; + bool m_isXButton1Pressed : 1; + bool m_isXButton2Pressed : 1; + bool m_touchConfidence : 1; + int32_t m_mouseWheelDelta; + float m_orientation; + winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind m_pointerUpdateKind; + float m_pressure; + float m_twist; + float m_xTilt; + float m_yTilt; }; -struct PointerPoint : PointerPointT -{ - PointerPoint(const winrt::Windows::UI::Input::PointerPoint& pp); +struct PointerPoint : PointerPointT { + PointerPoint(const winrt::Windows::UI::Input::PointerPoint &pp); + PointerPoint(uint32_t msg, uint64_t wParam, int64_t lParam); uint32_t FrameId() noexcept; bool IsInContact() noexcept; @@ -72,25 +118,38 @@ struct PointerPoint : PointerPointT winrt::Microsoft::ReactNative::Composition::Input::PointerPointProperties Properties() noexcept; uint64_t Timestamp() noexcept; winrt::Microsoft::ReactNative::Composition::Input::PointerPoint GetTransformedPoint( - const IPointerPointTransform& transform) noexcept; + const IPointerPointTransform &transform) noexcept; -private: - winrt::Windows::UI::Input::PointerPoint m_systemPP; + private: + bool IsPointerMessage(uint32_t message) noexcept; + + // Windows::Input + winrt::Windows::UI::Input::PointerPoint m_systemPP{nullptr}; + // WM_POINTER* + POINTER_INFO m_pi = {0}; + // WM_*MOUSE + uint32_t m_msg; + uint64_t m_wParam; + int64_t m_lParam; }; -struct PointerRoutedEventArgs : PointerRoutedEventArgsT -{ - PointerRoutedEventArgs(facebook::react::Tag tag, const winrt::Windows::UI::Input::PointerPoint& pp); +struct PointerRoutedEventArgs : PointerRoutedEventArgsT { + PointerRoutedEventArgs( + facebook::react::Tag tag, + const winrt::Microsoft::ReactNative::Composition::Input::PointerPoint &pp, + const winrt::Windows::System::VirtualKeyModifiers &virtualKeyModifiers); int32_t OriginalSource() noexcept; winrt::Microsoft::ReactNative::Composition::Input::PointerPoint GetCurrentPoint(int32_t tag) noexcept; bool Handled() noexcept; void Handled(bool value) noexcept; winrt::Windows::System::VirtualKeyModifiers KeyModifiers() noexcept; + private: facebook::react::Tag m_tag{-1}; bool m_handled{false}; winrt::Microsoft::ReactNative::Composition::Input::PointerPoint m_pp{nullptr}; + winrt::Windows::System::VirtualKeyModifiers m_virtualKeyModifiers; }; } // namespace winrt::Microsoft::ReactNative::Composition::Input::implementation diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp index 421199d2279..1347425db26 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp @@ -1047,6 +1047,9 @@ struct CompCaretVisual } void IsVisible(bool value) noexcept { + if (m_isVisible == value) + return; + m_isVisible = value; if (value) { m_compVisual.StartAnimation(L"opacity", m_opacityAnimation); } else { diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp index 95049024f60..9860ab6af3c 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include "Composition.Input.h" #include "CompositionRootView.h" #include "CompositionViewComponentView.h" @@ -19,7 +20,7 @@ namespace Microsoft::ReactNative { -const PointerId MOUSE_POINTER_ID = 1; // TODO ensure this is something that does not conflict with pointer point IDs. +const PointerId MOUSE_POINTER_ID = 1; bool IsMousePointerEvent(const facebook::react::PointerEvent &pointerEvent) { return pointerEvent.pointerId == MOUSE_POINTER_ID; @@ -124,49 +125,28 @@ ::Microsoft::ReactNative::RootComponentView &CompositionEventHandler::RootCompon return static_cast<::Microsoft::ReactNative::RootComponentView &>(*(rootComponentViewDescriptor.view)); } -// For DM -/* -void CompositionEventHandler::PointerDown(facebook::react::SurfaceId surfaceId, uint32_t pointerId) { - if (std::shared_ptr fabricuiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties( - winrt::Microsoft::ReactNative::ReactPropertyBag(m_context->Properties()))) { - facebook::react::Point ptLocal; - - - auto pp = winrt::Windows::UI::Input::PointerPoint::GetCurrentPoint(pointerId); - - - auto rootComponentViewDescriptor = fabricuiManager->GetViewRegistry().componentViewDescriptorWithTag(surfaceId); - auto tag = rootComponentViewDescriptor.view->hitTest({pp.Position().X, pp.Position().Y}, ptLocal); - - if (tag != -1) { - auto hitComponentViewDescriptor = fabricuiManager->GetViewRegistry().componentViewDescriptorWithTag(tag); - static_cast(*hitComponentViewDescriptor.view).OnPointerDown(pp); - } - - //fabricuiManager - - } - -} -*/ - -void CompositionEventHandler::ScrollWheel(facebook::react::Point pt, uint32_t delta) { +void CompositionEventHandler::onPointerWheelChanged( + const winrt::Microsoft::ReactNative::Composition::Input::PointerPoint &pointerPoint, + winrt::Windows::System::VirtualKeyModifiers keyModifiers) noexcept { if (std::shared_ptr fabricuiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(m_context.Properties())) { - facebook::react::Point ptLocal; + auto position = pointerPoint.Position(); + facebook::react::Point ptLocal; facebook::react::Point ptScaled = { - static_cast(pt.x / m_compRootView.ScaleFactor()), - static_cast(pt.y / m_compRootView.ScaleFactor())}; + static_cast(position.X / m_compRootView.ScaleFactor()), + static_cast(position.Y / m_compRootView.ScaleFactor())}; + auto tag = RootComponentView().hitTest(ptScaled, ptLocal); - if (tag == -1) { + if (tag == -1) return; - } - IComponentView *targetComponentView = - fabricuiManager->GetViewRegistry().componentViewDescriptorWithTag(tag).view.get(); - static_cast(targetComponentView)->ScrollWheel(ptLocal, delta); + auto targetComponentView = fabricuiManager->GetViewRegistry().componentViewDescriptorWithTag(tag).view; + auto args = winrt::make( + tag, pointerPoint, keyModifiers); + + std::static_pointer_cast(targetComponentView)->onPointerWheelChanged(args); } } @@ -185,48 +165,60 @@ winrt::Windows::UI::Core::CoreVirtualKeyStates CompositionEventHandler::GetKeySt return coreKeyState; } +winrt::Windows::System::VirtualKeyModifiers GetKeyModifiers(uint64_t wParam) { + auto keyModifiers = winrt::Windows::System::VirtualKeyModifiers::None; + if ((wParam & MK_CONTROL) == MK_CONTROL) { + keyModifiers |= winrt::Windows::System::VirtualKeyModifiers::Control; + } + if ((wParam & MK_SHIFT) == MK_SHIFT) { + keyModifiers |= winrt::Windows::System::VirtualKeyModifiers::Shift; + } + if (::GetKeyState(VK_MENU) < 0) { + keyModifiers |= winrt::Windows::System::VirtualKeyModifiers::Menu; + } + if (::GetKeyState(VK_LWIN) < 0 || ::GetKeyState(VK_RWIN) < 0) { + keyModifiers |= winrt::Windows::System::VirtualKeyModifiers::Windows; + } + return keyModifiers; +} + int64_t CompositionEventHandler::SendMessage(uint32_t msg, uint64_t wParam, int64_t lParam) noexcept { switch (msg) { - case WM_POINTERCAPTURECHANGED: - case WM_POINTERENTER: - case WM_POINTERLEAVE: - case WM_POINTERUPDATE: - case WM_POINTERROUTEDAWAY: - case WM_POINTERROUTEDRELEASED: - case WM_POINTERROUTEDTO: - case WM_POINTERWHEEL: - case WM_POINTERHWHEEL: - case DM_POINTERHITTEST: - case WM_SETCURSOR: - case WM_CAPTURECHANGED: - { - return 0; - } - case WM_LBUTTONDOWN: { - - // This pointer point should be in rootview coords - or we need an offset args for the rootview (which islands would provide) - //auto pp = winrt::make(winrt::Windows::UI::Input::GetCurrentPoint(uint32_t const& pointerId)) - - ButtonDown(msg, wParam, lParam); + auto pp = winrt::make( + msg, wParam, lParam); + onPointerPressed(pp, GetKeyModifiers(wParam)); return 0; } case WM_POINTERDOWN: { - PointerPressed(msg, wParam, lParam); + auto pp = winrt::make( + msg, wParam, lParam); + onPointerPressed(pp, GetKeyModifiers(wParam)); return 0; } case WM_LBUTTONUP: { - ButtonUp(msg, wParam, lParam); + auto pp = winrt::make( + msg, wParam, lParam); + onPointerReleased(pp, GetKeyModifiers(wParam)); return 0; } case WM_POINTERUP: { - PointerUp(msg, wParam, lParam); + auto pp = winrt::make( + msg, wParam, lParam); + onPointerReleased(pp, GetKeyModifiers(wParam)); return 0; } case WM_MOUSEMOVE: { - MouseMove(msg, wParam, lParam); + auto pp = winrt::make( + msg, wParam, lParam); + onPointerMoved(pp, GetKeyModifiers(wParam)); return 0; } + case WM_MOUSEWHEEL: { + auto pp = winrt::make( + msg, wParam, lParam); + onPointerWheelChanged(pp, GetKeyModifiers(wParam)); + } case WM_CHAR: case WM_SYSCHAR: { // TODO full bubbling of events @@ -516,23 +508,32 @@ facebook::react::PointerEvent CreatePointerEventFromIncompleteHoverData( return pointerEvent; } -void CompositionEventHandler::MouseMove(uint32_t msg, uint64_t wParam, int64_t lParam) { - int pointerId = MOUSE_POINTER_ID; // TODO pointerId +void CompositionEventHandler::onPointerMoved( + const winrt::Microsoft::ReactNative::Composition::Input::PointerPoint &pointerPoint, + winrt::Windows::System::VirtualKeyModifiers keyModifiers) noexcept { + int pointerId = pointerPoint.PointerId(); - auto x = GET_X_LPARAM(lParam); - auto y = GET_Y_LPARAM(lParam); + auto position = pointerPoint.Position(); if (std::shared_ptr fabricuiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(m_context.Properties())) { facebook::react::Point ptLocal; facebook::react::Point ptScaled = { - static_cast(x / m_compRootView.ScaleFactor()), static_cast(y / m_compRootView.ScaleFactor())}; + static_cast(position.X / m_compRootView.ScaleFactor()), + static_cast(position.Y / m_compRootView.ScaleFactor())}; auto tag = RootComponentView().hitTest(ptScaled, ptLocal); if (tag == -1) return; + auto args = winrt::make( + tag, pointerPoint, keyModifiers); + IComponentView *targetComponentView = + fabricuiManager->GetViewRegistry().componentViewDescriptorWithTag(tag).view.get(); + + static_cast(targetComponentView)->onPointerMoved(args); + auto targetView = FindClosestFabricManagedTouchableView( fabricuiManager->GetViewRegistry().componentViewDescriptorWithTag(tag).view.get()); @@ -552,87 +553,10 @@ void CompositionEventHandler::MouseMove(uint32_t msg, uint64_t wParam, int64_t l } } -void CompositionEventHandler::PointerPressed(uint32_t msg, uint64_t wParam, int64_t lParam) { - POINTER_INFO pi; - PointerId pointerId = GET_POINTERID_WPARAM(wParam); - GetPointerInfo(pointerId, &pi); - POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; - ::ScreenToClient(pi.hwndTarget, &pt); - - auto staleTouch = std::find_if(m_activeTouches.begin(), m_activeTouches.end(), [pointerId](const auto &pair) { - return pair.second.touch.identifier == pointerId; - }); - - if (staleTouch != m_activeTouches.end()) { - // A pointer with this ID already exists - Should we fire a button cancel or something? - assert(false); - return; - } - - const auto eventType = TouchEventType::Start; - - if (std::shared_ptr fabricuiManager = - ::Microsoft::ReactNative::FabricUIManager::FromProperties(m_context.Properties())) { - facebook::react::Point ptLocal; - - facebook::react::Point ptScaled = { - static_cast(pt.x / m_compRootView.ScaleFactor()), - static_cast(pt.y / m_compRootView.ScaleFactor())}; - auto tag = RootComponentView().hitTest(ptScaled, ptLocal); - - if (tag == -1) - return; - - IComponentView *targetComponentView = - fabricuiManager->GetViewRegistry().componentViewDescriptorWithTag(tag).view.get(); - static_cast(targetComponentView)->sendMessage(msg, wParam, lParam); - - ActiveTouch activeTouch{0}; - switch (pi.pointerType) { - case PT_POINTER: - case PT_TOUCH: - activeTouch.touchType = UITouchType::Touch; - break; - case PT_PEN: - activeTouch.touchType = UITouchType::Pen; - break; - case PT_TOUCHPAD: - case PT_MOUSE: - activeTouch.touchType = UITouchType::Mouse; - break; - } - - auto componentView = targetComponentView; - while (componentView) { - if (auto eventEmitter = componentView->eventEmitter()) { - activeTouch.eventEmitter = eventEmitter; - activeTouch.touch.target = componentView->tag(); - // activeTouch.componentView = componentView; - break; - } - componentView = componentView->parent(); - } - - UpdateActiveTouch(activeTouch, ptScaled, ptLocal); - - // activeTouch.touch.isPrimary = true; - activeTouch.touch.identifier = pointerId; - - // If the pointer has not been marked as hovering over views before the touch started, we register - // that the activeTouch should not maintain its hovered state once the pointer has been lifted. - auto currentlyHoveredTags = m_currentlyHoveredViewsPerPointer.find(activeTouch.touch.identifier); - if (currentlyHoveredTags == m_currentlyHoveredViewsPerPointer.end() || currentlyHoveredTags->second.empty()) { - activeTouch.shouldLeaveWhenReleased = true; - } - - m_activeTouches.emplace(pointerId, activeTouch); - - DispatchTouchEvent(eventType, pointerId); - } -} - -void CompositionEventHandler::ButtonDown(uint32_t msg, uint64_t wParam, int64_t lParam) { - PointerId pointerId = MOUSE_POINTER_ID; +void CompositionEventHandler::onPointerPressed( + const winrt::Microsoft::ReactNative::Composition::Input::PointerPoint &pointerPoint, + winrt::Windows::System::VirtualKeyModifiers keyModifiers) noexcept { + PointerId pointerId = pointerPoint.PointerId(); auto staleTouch = std::find_if(m_activeTouches.begin(), m_activeTouches.end(), [pointerId](const auto &pair) { return pair.second.touch.identifier == pointerId; @@ -644,8 +568,7 @@ void CompositionEventHandler::ButtonDown(uint32_t msg, uint64_t wParam, int64_t return; } - auto x = GET_X_LPARAM(lParam); - auto y = GET_Y_LPARAM(lParam); + auto position = pointerPoint.Position(); const auto eventType = TouchEventType::Start; if (std::shared_ptr fabricuiManager = @@ -653,7 +576,8 @@ void CompositionEventHandler::ButtonDown(uint32_t msg, uint64_t wParam, int64_t facebook::react::Point ptLocal; facebook::react::Point ptScaled = { - static_cast(x / m_compRootView.ScaleFactor()), static_cast(y / m_compRootView.ScaleFactor())}; + static_cast(position.X / m_compRootView.ScaleFactor()), + static_cast(position.Y / m_compRootView.ScaleFactor())}; auto tag = RootComponentView().hitTest(ptScaled, ptLocal); if (tag == -1) @@ -661,7 +585,9 @@ void CompositionEventHandler::ButtonDown(uint32_t msg, uint64_t wParam, int64_t IComponentView *targetComponentView = fabricuiManager->GetViewRegistry().componentViewDescriptorWithTag(tag).view.get(); - static_cast(targetComponentView)->sendMessage(msg, wParam, lParam); + auto args = winrt::make( + tag, pointerPoint, keyModifiers); + static_cast(targetComponentView)->onPointerPressed(args); ActiveTouch activeTouch{0}; activeTouch.touchType = UITouchType::Mouse; @@ -695,12 +621,10 @@ void CompositionEventHandler::ButtonDown(uint32_t msg, uint64_t wParam, int64_t } } -void CompositionEventHandler::PointerUp(uint32_t msg, uint64_t wParam, int64_t lParam) { - POINTER_INFO pi; - PointerId pointerId = GET_POINTERID_WPARAM(wParam); - GetPointerInfo(pointerId, &pi); - POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; - ::ScreenToClient(pi.hwndTarget, &pt); +void CompositionEventHandler::onPointerReleased( + const winrt::Microsoft::ReactNative::Composition::Input::PointerPoint &pointerPoint, + winrt::Windows::System::VirtualKeyModifiers keyModifiers) noexcept { + int pointerId = pointerPoint.PointerId(); auto activeTouch = std::find_if(m_activeTouches.begin(), m_activeTouches.end(), [pointerId](const auto &pair) { return pair.second.touch.identifier == pointerId; @@ -710,56 +634,25 @@ void CompositionEventHandler::PointerUp(uint32_t msg, uint64_t wParam, int64_t l return; } - const auto eventType = TouchEventType::Start; + auto position = pointerPoint.Position(); if (std::shared_ptr fabricuiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(m_context.Properties())) { facebook::react::Point ptLocal; facebook::react::Point ptScaled = { - static_cast(pt.x / m_compRootView.ScaleFactor()), - static_cast(pt.y / m_compRootView.ScaleFactor())}; + static_cast(position.X / m_compRootView.ScaleFactor()), + static_cast(position.Y / m_compRootView.ScaleFactor())}; auto tag = RootComponentView().hitTest(ptScaled, ptLocal); if (tag == -1) return; auto targetComponentView = fabricuiManager->GetViewRegistry().componentViewDescriptorWithTag(tag).view; - std::static_pointer_cast(targetComponentView)->sendMessage(msg, wParam, lParam); - - UpdateActiveTouch(activeTouch->second, ptScaled, ptLocal); - DispatchTouchEvent(TouchEventType::End, pointerId); - m_activeTouches.erase(pointerId); - } -} - -void CompositionEventHandler::ButtonUp(uint32_t msg, uint64_t wParam, int64_t lParam) { - int pointerId = MOUSE_POINTER_ID; - - auto activeTouch = std::find_if(m_activeTouches.begin(), m_activeTouches.end(), [pointerId](const auto &pair) { - return pair.second.touch.identifier == pointerId; - }); + auto args = winrt::make( + tag, pointerPoint, keyModifiers); - if (activeTouch == m_activeTouches.end()) { - return; - } - - auto x = GET_X_LPARAM(lParam); - auto y = GET_Y_LPARAM(lParam); - - if (std::shared_ptr fabricuiManager = - ::Microsoft::ReactNative::FabricUIManager::FromProperties(m_context.Properties())) { - facebook::react::Point ptLocal; - - facebook::react::Point ptScaled = { - static_cast(x / m_compRootView.ScaleFactor()), static_cast(y / m_compRootView.ScaleFactor())}; - auto tag = RootComponentView().hitTest(ptScaled, ptLocal); - - if (tag == -1) - return; - - auto targetComponentView = fabricuiManager->GetViewRegistry().componentViewDescriptorWithTag(tag).view; - std::static_pointer_cast(targetComponentView)->sendMessage(msg, wParam, lParam); + std::static_pointer_cast(targetComponentView)->onPointerReleased(args); UpdateActiveTouch(activeTouch->second, ptScaled, ptLocal); DispatchTouchEvent(TouchEventType::End, pointerId); diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h index 604c68ea90b..7e5b7f81e2b 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h @@ -35,17 +35,22 @@ class CompositionEventHandler { virtual ~CompositionEventHandler(); int64_t SendMessage(uint32_t msg, uint64_t wParam, int64_t lParam) noexcept; - void ScrollWheel(facebook::react::Point pt, uint32_t delta); void RemoveTouchHandlers(); winrt::Windows::UI::Core::CoreVirtualKeyStates GetKeyState(winrt::Windows::System::VirtualKey key) noexcept; private: - void ButtonDown(uint32_t msg, uint64_t wParam, int64_t lParam); - void PointerPressed(uint32_t msg, uint64_t wParam, int64_t lParam); - void ButtonUp(uint32_t msg, uint64_t wParam, int64_t lParam); - void PointerUp(uint32_t msg, uint64_t wParam, int64_t lParam); - void MouseMove(uint32_t msg, uint64_t wParam, int64_t lParam); - + void onPointerPressed( + const winrt::Microsoft::ReactNative::Composition::Input::PointerPoint &pointerPoint, + winrt::Windows::System::VirtualKeyModifiers keyModifiers) noexcept; + void onPointerReleased( + const winrt::Microsoft::ReactNative::Composition::Input::PointerPoint &pointerPoint, + winrt::Windows::System::VirtualKeyModifiers keyModifiers) noexcept; + void onPointerMoved( + const winrt::Microsoft::ReactNative::Composition::Input::PointerPoint &pointerPoint, + winrt::Windows::System::VirtualKeyModifiers keyModifiers) noexcept; + void onPointerWheelChanged( + const winrt::Microsoft::ReactNative::Composition::Input::PointerPoint &pointerPoint, + winrt::Windows::System::VirtualKeyModifiers keyModifiers) noexcept; void onKeyDown( const winrt::Microsoft::ReactNative::Composition::Input::KeyboardSource &source, const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionHwndHost.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionHwndHost.cpp index 725ffd7873a..a9746c9955d 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionHwndHost.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionHwndHost.cpp @@ -91,23 +91,6 @@ LRESULT CompositionHwndHost::TranslateMessage(int msg, uint64_t wParam, int64_t return 0; switch (msg) { - case WM_MOUSEWHEEL: { - POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; - ::ScreenToClient(m_hwnd, &pt); - int32_t delta = GET_WHEEL_DELTA_WPARAM(wParam); - m_compRootView.OnScrollWheel({static_cast(pt.x), static_cast(pt.y)}, delta); - return 0; - } - /* - case WM_POINTERDOWN: { - m_compRootView.OnPointerPressed({GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}); - return 0; - } - case WM_LBUTTONUP: { - m_compRootView.OnMouseUp({static_cast(GET_X_LPARAM(lParam)), static_cast(GET_Y_LPARAM(lParam))}); - return 0; - } - */ case WM_WINDOWPOSCHANGED: { UpdateSize(); /* diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootView.cpp index f7c6c775342..6413aeb6ce8 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootView.cpp @@ -191,15 +191,6 @@ int64_t CompositionRootView::SendMessage(uint32_t msg, uint64_t wParam, int64_t return 0; } -void CompositionRootView::OnScrollWheel(winrt::Windows::Foundation::Point point, int32_t delta) noexcept { - if (m_rootTag == -1) - return; - - if (m_CompositionEventHandler) { - m_CompositionEventHandler->ScrollWheel({point.X, point.Y}, delta); - } -} - void CompositionRootView::InitRootView( winrt::Microsoft::ReactNative::IReactContext &&context, winrt::Microsoft::ReactNative::ReactViewOptions &&viewOptions) noexcept { diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootView.h index 37688efdd86..15806b902a5 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootView.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootView.h @@ -70,7 +70,6 @@ struct CompositionRootView : CompositionRootViewT, ::Micros IInspectable GetUiaProvider() noexcept; int64_t SendMessage(uint32_t msg, uint64_t wParam, int64_t lParam) noexcept; - void OnScrollWheel(winrt::Windows::Foundation::Point point, int32_t delta) noexcept; public: // ICompositionRootView winrt::Microsoft::ReactNative::Composition::IVisual GetVisual() const noexcept override; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootView_emptyimpl.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootView_emptyimpl.cpp index e1c6a76d3d9..6bb2bbf0fd4 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootView_emptyimpl.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootView_emptyimpl.cpp @@ -83,8 +83,6 @@ int64_t CompositionRootView::SendMessage(uint32_t, uint64_t, int64_t) noexcept { return 0; } -void CompositionRootView::OnScrollWheel(Windows::Foundation::Point, int32_t) noexcept {} - void CompositionRootView::InitRootView( winrt::Microsoft::ReactNative::IReactContext &&, winrt::Microsoft::ReactNative::ReactViewOptions &&) noexcept {} diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp index 8b5c0c457f5..86cfaaf448a 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp @@ -158,6 +158,34 @@ void CompositionBaseComponentView::onKeyUp( } } +void CompositionBaseComponentView::onPointerPressed( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept { + if (m_parent && !args.Handled()) { + m_parent->onPointerPressed(args); + } +} + +void CompositionBaseComponentView::onPointerReleased( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept { + if (m_parent && !args.Handled()) { + m_parent->onPointerReleased(args); + } +} + +void CompositionBaseComponentView::onPointerMoved( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept { + if (m_parent && !args.Handled()) { + m_parent->onPointerMoved(args); + } +} + +void CompositionBaseComponentView::onPointerWheelChanged( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept { + if (m_parent && !args.Handled()) { + m_parent->onPointerWheelChanged(args); + } +} + RECT CompositionBaseComponentView::getClientRect() const noexcept { RECT rc{0}; if (m_parent) { @@ -175,15 +203,6 @@ const facebook::react::SharedViewEventEmitter &CompositionBaseComponentView::Get return m_eventEmitter; } -bool CompositionBaseComponentView::ScrollWheel(facebook::react::Point pt, int32_t delta) noexcept { - if (m_parent) { - pt.x += m_layoutMetrics.frame.origin.x * m_layoutMetrics.pointScaleFactor; - pt.y += m_layoutMetrics.frame.origin.y * m_layoutMetrics.pointScaleFactor; - return m_parent->ScrollWheel(pt, delta); - } - return false; -} - std::array< winrt::Microsoft::ReactNative::Composition::ISpriteVisual, CompositionBaseComponentView::SpecialBorderLayerCount> diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h index 290c3c94be7..5ea382c2c7e 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h @@ -35,6 +35,15 @@ struct CompositionBaseComponentView : public IComponentView, bool runOnChildren(bool forward, Mso::Functor &fn) noexcept override; void onFocusLost() noexcept override; void onFocusGained() noexcept override; + void onPointerPressed( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept override; + void onPointerReleased( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept override; + void onPointerMoved( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept override; + void onPointerWheelChanged( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept override; + void onKeyDown( const winrt::Microsoft::ReactNative::Composition::Input::KeyboardSource &source, const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept override; @@ -49,7 +58,6 @@ struct CompositionBaseComponentView : public IComponentView, facebook::react::Tag tag() const noexcept override; int64_t sendMessage(uint32_t msg, uint64_t wParam, int64_t lParam) noexcept override; - bool ScrollWheel(facebook::react::Point pt, int32_t delta) noexcept override; RECT getClientRect() const noexcept override; void indexOffsetForBorder(uint32_t &index) const noexcept; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp index 4235f458859..740bc4325f6 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp @@ -59,6 +59,22 @@ void ReactCompositionViewComponentBuilder::SetKeyUpHandler(KeyHandler impl) noex m_keyUp = impl; } +void ReactCompositionViewComponentBuilder::SetPointerReleasedHandler(PointerHandler impl) noexcept { + m_pointerReleased = impl; +} + +void ReactCompositionViewComponentBuilder::SetPointerPressedHandler(PointerHandler impl) noexcept { + m_pointerPressed = impl; +} + +void ReactCompositionViewComponentBuilder::SetPointerMovedHandler(PointerHandler impl) noexcept { + m_pointerMoved = impl; +} + +void ReactCompositionViewComponentBuilder::SetPointerWheelChangedHandler(PointerHandler impl) noexcept { + m_pointerWheelChanged = impl; +} + winrt::Windows::Foundation::IInspectable ReactCompositionViewComponentBuilder::CreateView( IReactContext reactContext, ICompositionContext context) noexcept { @@ -128,4 +144,32 @@ void ReactCompositionViewComponentBuilder::OnKeyUp( } } +void ReactCompositionViewComponentBuilder::OnPointerPressed( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept { + if (m_pointerPressed) { + m_pointerPressed(args); + } +} + +void ReactCompositionViewComponentBuilder::OnPointerReleased( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept { + if (m_pointerReleased) { + m_pointerReleased(args); + } +} + +void ReactCompositionViewComponentBuilder::OnPointerMoved( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept { + if (m_pointerMoved) { + m_pointerMoved(args); + } +} + +void ReactCompositionViewComponentBuilder::OnPointerWheelChanged( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept { + if (m_pointerWheelChanged) { + m_pointerWheelChanged(args); + } +} + } // namespace winrt::Microsoft::ReactNative::Composition diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h b/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h index bb09cdbe301..4530ad6c522 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h @@ -36,6 +36,11 @@ struct ReactCompositionViewComponentBuilder : winrt::implements< void SetKeyDownHandler(KeyHandler impl) noexcept; void SetKeyUpHandler(KeyHandler impl) noexcept; + void SetPointerReleasedHandler(PointerHandler impl) noexcept; + void SetPointerPressedHandler(PointerHandler impl) noexcept; + void SetPointerMovedHandler(PointerHandler impl) noexcept; + void SetPointerWheelChangedHandler(PointerHandler impl) noexcept; + public: IComponentProps CreateProps(ViewProps props) noexcept; @@ -56,6 +61,12 @@ struct ReactCompositionViewComponentBuilder : winrt::implements< void OnKeyUp( const winrt::Microsoft::ReactNative::Composition::Input::KeyboardSource &source, const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept; + void OnPointerPressed(const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept; + void OnPointerReleased( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept; + void OnPointerMoved(const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept; + void OnPointerWheelChanged( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept; private: ViewPropsFactory m_propsFactory; @@ -69,6 +80,10 @@ struct ReactCompositionViewComponentBuilder : winrt::implements< MessageHandler m_messageHandler; KeyHandler m_keyUp; KeyHandler m_keyDown; + PointerHandler m_pointerReleased; + PointerHandler m_pointerPressed; + PointerHandler m_pointerMoved; + PointerHandler m_pointerWheelChanged; }; } // namespace winrt::Microsoft::ReactNative::Composition diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp index 2bbbe8779cc..127478f67e8 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp @@ -257,21 +257,31 @@ void ScrollViewComponentView::OnPointerDown(const winrt::Windows::UI::Input::Poi } */ -bool ScrollViewComponentView::ScrollWheel(facebook::react::Point pt, int32_t delta) noexcept { - if (delta > 0) { - if (scrollUp(static_cast(delta) * m_layoutMetrics.pointScaleFactor, true)) { - return true; +void ScrollViewComponentView::onPointerWheelChanged( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept { + auto ppp = args.GetCurrentPoint(-1).Properties(); + auto delta = static_cast(ppp.MouseWheelDelta()); + if (ppp.IsHorizontalMouseWheel()) { + if (delta > 0) { + if (scrollLeft(delta * m_layoutMetrics.pointScaleFactor, true)) { + args.Handled(true); + } + } else if (delta < 0) { + if (scrollRight(-delta * m_layoutMetrics.pointScaleFactor, true)) { + args.Handled(true); + } + } + } else { + if (delta > 0) { + if (scrollUp(delta * m_layoutMetrics.pointScaleFactor, true)) { + args.Handled(true); + } + } else if (delta < 0) { + if (scrollDown(-delta * m_layoutMetrics.pointScaleFactor, true)) { + args.Handled(true); + } } - } else if (delta < 0) { - if (scrollDown(-static_cast(delta) * m_layoutMetrics.pointScaleFactor, true)) { - return true; - }; } - - // Adjust pt for viewport before it goes to the parent - pt.x -= m_scrollVisual.ScrollPosition().x; - pt.y -= m_scrollVisual.ScrollPosition().y; - return Super::ScrollWheel(pt, delta); } void ScrollViewComponentView::onKeyDown( @@ -339,22 +349,11 @@ bool ScrollViewComponentView::lineDown(bool animate) noexcept { } bool ScrollViewComponentView::lineLeft(bool animate) noexcept { - if (m_scrollVisual.ScrollPosition().x <= 0.0f) { - return false; - } - - m_scrollVisual.ScrollBy({-c_scrollerLineDelta * m_layoutMetrics.pointScaleFactor, 0, 0}, animate); - return true; + return scrollLeft(c_scrollerLineDelta * m_layoutMetrics.pointScaleFactor, animate); } bool ScrollViewComponentView::lineRight(bool animate) noexcept { - if ((((m_contentSize.width - m_layoutMetrics.frame.size.width) * m_layoutMetrics.pointScaleFactor) - - m_scrollVisual.ScrollPosition().x) < 1.0f) { - return false; - } - - m_scrollVisual.ScrollBy({c_scrollerLineDelta * m_layoutMetrics.pointScaleFactor, 0, 0}, animate); - return true; + return scrollRight(c_scrollerLineDelta * m_layoutMetrics.pointScaleFactor, animate); } bool ScrollViewComponentView::scrollDown(float delta, bool animate) noexcept { @@ -377,6 +376,26 @@ bool ScrollViewComponentView::scrollUp(float delta, bool animate) noexcept { return true; } +bool ScrollViewComponentView::scrollLeft(float delta, bool animate) noexcept { + if (m_scrollVisual.ScrollPosition().x <= 0.0f) { + return false; + } + + m_scrollVisual.ScrollBy({delta, 0, 0}, animate); + return true; +} + +bool ScrollViewComponentView::scrollRight(float delta, bool animate) noexcept { + if (((m_contentSize.width - m_layoutMetrics.frame.size.width) * m_layoutMetrics.pointScaleFactor) - + m_scrollVisual.ScrollPosition().x < + 1.0f) { + return false; + } + + m_scrollVisual.ScrollBy({delta, 0, 0}, animate); + return true; +} + void ScrollViewComponentView::handleCommand(std::string const &commandName, folly::dynamic const &arg) noexcept { if (commandName == "scrollTo") { auto x = arg[0].asDouble() * m_layoutMetrics.pointScaleFactor; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h index 33525770745..970a3a237a0 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h @@ -77,8 +77,8 @@ struct ScrollInteractionTrackerOwner : public winrt::implements< const noexcept override; winrt::Microsoft::ReactNative::Composition::IVisual Visual() const noexcept override; - // void OnPointerDown(const winrt::Windows::UI::Input::PointerPoint &pp) noexcept override; - bool ScrollWheel(facebook::react::Point pt, int32_t delta) noexcept override; + void onPointerWheelChanged( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept override; void StartBringIntoView(BringIntoViewOptions &&args) noexcept override; virtual std::string DefaultControlType() const noexcept; @@ -100,6 +100,8 @@ struct ScrollInteractionTrackerOwner : public winrt::implements< bool lineRight(bool animate) noexcept; bool scrollDown(float delta, bool animate) noexcept; bool scrollUp(float delta, bool animate) noexcept; + bool scrollLeft(float delta, bool aniamte) noexcept; + bool scrollRight(float delta, bool animate) noexcept; facebook::react::Size m_contentSize; winrt::Microsoft::ReactNative::Composition::ISpriteVisual m_visual{nullptr}; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.cpp index 9fe432f0a09..81d602a6849 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.cpp @@ -233,23 +233,18 @@ winrt::Microsoft::ReactNative::Composition::IVisual SwitchComponentView::Visual( return m_visual; } -int64_t SwitchComponentView::sendMessage(uint32_t msg, uint64_t wParam, int64_t lParam) noexcept { - switch (msg) { - case WM_LBUTTONDOWN: - case WM_POINTERDOWN: { - const auto switchProps = std::static_pointer_cast(m_props); - - if (!switchProps->disabled) { - if (auto root = rootComponentView()) { - root->TrySetFocusedComponent(*this); - } - toggle(); - } - break; +void SwitchComponentView::onPointerPressed( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept { + const auto switchProps = std::static_pointer_cast(m_props); + + if (!switchProps->disabled) { + if (auto root = rootComponentView()) { + root->TrySetFocusedComponent(*this); + } + if (toggle()) { + args.Handled(true); } } - - return 0; } void SwitchComponentView::onKeyUp( diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.h index 8fb3886d8e0..07ea416c541 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.h @@ -39,12 +39,13 @@ struct SwitchComponentView : CompositionBaseComponentView { bool focusable() const noexcept override; void onKeyUp( const winrt::Microsoft::ReactNative::Composition::Input::KeyboardSource &source, - const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept; + const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept override; + void onPointerPressed( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept override; facebook::react::Tag hitTest(facebook::react::Point pt, facebook::react::Point &localPt, bool ignorePointerEvents) const noexcept override; winrt::Microsoft::ReactNative::Composition::IVisual Visual() const noexcept override; - int64_t sendMessage(uint32_t msg, uint64_t wParam, int64_t lParam) noexcept override; std::string DefaultControlType() const noexcept override; private: diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp index c0b16dcc1d5..2b93050c4a1 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "../CompositionHelpers.h" #include "../RootComponentView.h" @@ -566,6 +567,194 @@ int64_t WindowsTextInputComponentView::sendMessage(uint32_t msg, uint64_t wParam return Super::sendMessage(msg, wParam, lParam); } +WPARAM PointerPointToPointerWParam(const winrt::Microsoft::ReactNative::Composition::Input::PointerPoint &pp) noexcept { + WPARAM wParam = pp.PointerId(); + wParam |= (POINTER_MESSAGE_FLAG_NEW << 16); + auto ppp = pp.Properties(); + if (ppp.IsInRange()) { + wParam |= (POINTER_MESSAGE_FLAG_INRANGE << 16); + } + if (pp.IsInContact()) { + wParam |= (POINTER_MESSAGE_FLAG_INCONTACT << 16); + } + if (ppp.IsLeftButtonPressed()) { + wParam |= (POINTER_MESSAGE_FLAG_FIRSTBUTTON << 16); + } + if (ppp.IsRightButtonPressed()) { + wParam |= (POINTER_MESSAGE_FLAG_SECONDBUTTON << 16); + } + if (ppp.IsMiddleButtonPressed()) { + wParam |= (POINTER_MESSAGE_FLAG_THIRDBUTTON << 16); + } + if (ppp.IsXButton1Pressed()) { + wParam |= (POINTER_MESSAGE_FLAG_FOURTHBUTTON << 16); + } + if (ppp.IsXButton2Pressed()) { + wParam |= (POINTER_MESSAGE_FLAG_FIFTHBUTTON << 16); + } + if (ppp.IsPrimary()) { + wParam |= (POINTER_MESSAGE_FLAG_PRIMARY << 16); + } + if (ppp.TouchConfidence()) { + wParam |= (POINTER_MESSAGE_FLAG_CONFIDENCE << 16); + } + if (ppp.IsCanceled()) { + wParam |= (POINTER_MESSAGE_FLAG_CANCELED << 16); + } + return wParam; +} + +WPARAM PointerRoutedEventArgsToMouseWParam( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept { + WPARAM wParam = 0; + auto pp = args.GetCurrentPoint(-1); + + auto keyModifiers = args.KeyModifiers(); + if ((keyModifiers & winrt::Windows::System::VirtualKeyModifiers::Control) == + winrt::Windows::System::VirtualKeyModifiers::Control) { + wParam |= MK_CONTROL; + } + if ((keyModifiers & winrt::Windows::System::VirtualKeyModifiers::Shift) == + winrt::Windows::System::VirtualKeyModifiers::Shift) { + wParam |= MK_SHIFT; + } + + auto ppp = pp.Properties(); + if (ppp.IsLeftButtonPressed()) { + wParam |= MK_LBUTTON; + } + if (ppp.IsMiddleButtonPressed()) { + wParam |= MK_MBUTTON; + } + if (ppp.IsRightButtonPressed()) { + wParam |= MK_RBUTTON; + } + if (ppp.IsXButton1Pressed()) { + wParam |= MK_XBUTTON1; + } + if (ppp.IsXButton2Pressed()) { + wParam |= MK_XBUTTON2; + } + return wParam; +} + +void WindowsTextInputComponentView::onPointerPressed( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept { + UINT msg = 0; + LPARAM lParam = 0; + WPARAM wParam = 0; + + auto pp = args.GetCurrentPoint(-1); // TODO use local coords? + auto position = pp.Position(); + POINT ptContainer = {static_cast(position.X), static_cast(position.Y)}; + lParam = static_cast(POINTTOPOINTS(ptContainer)); + + if (pp.PointerDeviceType() == winrt::Microsoft::ReactNative::Composition::Input::PointerDeviceType::Mouse) { + switch (pp.Properties().PointerUpdateKind()) { + case winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::LeftButtonPressed: + msg = WM_LBUTTONDOWN; + break; + case winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::MiddleButtonPressed: + msg = WM_MBUTTONDOWN; + break; + case winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::RightButtonPressed: + msg = WM_RBUTTONDOWN; + break; + case winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::XButton1Pressed: + msg = WM_XBUTTONDOWN; + wParam |= (XBUTTON1 << 16); + break; + case winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::XButton2Pressed: + msg = WM_XBUTTONDOWN; + wParam |= (XBUTTON2 << 16); + break; + } + wParam = PointerRoutedEventArgsToMouseWParam(args); + } else { + msg = WM_POINTERDOWN; + wParam = PointerPointToPointerWParam(pp); + } + + if (m_textServices && msg) { + LRESULT lresult; + DrawBlock db(*this); + auto hr = m_textServices->TxSendMessage(msg, static_cast(wParam), static_cast(lParam), &lresult); + args.Handled(hr != S_FALSE); + } +} + +void WindowsTextInputComponentView::onPointerReleased( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept { + UINT msg = 0; + LPARAM lParam = 0; + WPARAM wParam = 0; + + auto pp = args.GetCurrentPoint(-1); + auto position = pp.Position(); + POINT ptContainer = {static_cast(position.X), static_cast(position.Y)}; + lParam = static_cast(POINTTOPOINTS(ptContainer)); + + if (pp.PointerDeviceType() == winrt::Microsoft::ReactNative::Composition::Input::PointerDeviceType::Mouse) { + switch (pp.Properties().PointerUpdateKind()) { + case winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::LeftButtonReleased: + msg = WM_LBUTTONUP; + break; + case winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::MiddleButtonReleased: + msg = WM_MBUTTONUP; + break; + case winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::RightButtonReleased: + msg = WM_RBUTTONUP; + break; + case winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::XButton1Released: + msg = WM_XBUTTONUP; + wParam |= (XBUTTON1 << 16); + break; + case winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::XButton2Released: + msg = WM_XBUTTONUP; + wParam |= (XBUTTON2 << 16); + break; + } + wParam = PointerRoutedEventArgsToMouseWParam(args); + } else { + msg = WM_POINTERUP; + wParam = PointerPointToPointerWParam(pp); + } + + if (m_textServices && msg) { + LRESULT lresult; + DrawBlock db(*this); + auto hr = m_textServices->TxSendMessage(msg, static_cast(wParam), static_cast(lParam), &lresult); + args.Handled(hr != S_FALSE); + } +} + +void WindowsTextInputComponentView::onPointerMoved( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept { + UINT msg = 0; + LPARAM lParam = 0; + WPARAM wParam = 0; + + auto pp = args.GetCurrentPoint(-1); + auto position = pp.Position(); + POINT ptContainer = {static_cast(position.X), static_cast(position.Y)}; + lParam = static_cast(POINTTOPOINTS(ptContainer)); + + if (pp.PointerDeviceType() == winrt::Microsoft::ReactNative::Composition::Input::PointerDeviceType::Mouse) { + msg = WM_MOUSEMOVE; + wParam = PointerRoutedEventArgsToMouseWParam(args); + } else { + msg = WM_POINTERUP; + wParam = PointerPointToPointerWParam(pp); + } + + if (m_textServices) { + LRESULT lresult; + DrawBlock db(*this); + auto hr = m_textServices->TxSendMessage(msg, static_cast(wParam), static_cast(lParam), &lresult); + args.Handled(hr != S_FALSE); + } +} + void WindowsTextInputComponentView::onKeyDown( const winrt::Microsoft::ReactNative::Composition::Input::KeyboardSource &source, const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept { diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h index 7f537f59f93..9052eb3b2d9 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h @@ -55,6 +55,13 @@ struct WindowsTextInputComponentView : CompositionBaseComponentView { std::string DefaultControlType() const noexcept override; std::string DefaultAccessibleName() const noexcept override; std::string DefaultHelpText() const noexcept override; + void onPointerPressed( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept override; + void onPointerReleased( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept override; + void onPointerMoved( + const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept override; + void onKeyDown( const winrt::Microsoft::ReactNative::Composition::Input::KeyboardSource &source, const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept; diff --git a/vnext/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl b/vnext/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl index f60c60bb390..52cd4881f77 100644 --- a/vnext/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl +++ b/vnext/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl @@ -49,6 +49,9 @@ namespace Microsoft.ReactNative.Composition [experimental] delegate void KeyHandler(Microsoft.ReactNative.Composition.Input.KeyboardSource source, Microsoft.ReactNative.Composition.Input.KeyRoutedEventArgs args); + [experimental] + delegate void PointerHandler(Microsoft.ReactNative.Composition.Input.PointerRoutedEventArgs args); + [webhosthidden] [experimental] DOC_STRING(".") @@ -90,6 +93,11 @@ namespace Microsoft.ReactNative.Composition DOC_STRING("Used to handle key up events when this component is focused, or if a child component did not handle the key up") void SetKeyUpHandler(KeyHandler impl); + + void SetPointerPressedHandler(PointerHandler impl); + void SetPointerReleasedHandler(PointerHandler impl); + void SetPointerMovedHandler(PointerHandler impl); + void SetPointerWheelChangedHandler(PointerHandler impl); }; From a64e799f1fe28cba2e8adad45150b078e567f8e7 Mon Sep 17 00:00:00 2001 From: Andrew Coates <30809111+acoates-ms@users.noreply.github.com> Date: Tue, 3 Oct 2023 17:55:18 -0700 Subject: [PATCH 4/5] Change files --- ...ative-windows-3ddf28c1-6a2e-4a05-82be-34e61421cde5.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/react-native-windows-3ddf28c1-6a2e-4a05-82be-34e61421cde5.json diff --git a/change/react-native-windows-3ddf28c1-6a2e-4a05-82be-34e61421cde5.json b/change/react-native-windows-3ddf28c1-6a2e-4a05-82be-34e61421cde5.json new file mode 100644 index 00000000000..bd4c62c9ae9 --- /dev/null +++ b/change/react-native-windows-3ddf28c1-6a2e-4a05-82be-34e61421cde5.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "[Fabric] Add pointer pressed, released, moved and wheelch changed events", + "packageName": "react-native-windows", + "email": "30809111+acoates-ms@users.noreply.github.com", + "dependentChangeType": "patch" +} From e5eab6e6fc9dfc485182965f58c5fa582afa2007 Mon Sep 17 00:00:00 2001 From: Andrew Coates <30809111+acoates-ms@users.noreply.github.com> Date: Fri, 6 Oct 2023 13:49:35 -0700 Subject: [PATCH 5/5] feedback --- .../Fabric/Composition/Composition.Input.cpp | 80 +++++++++---------- .../Fabric/Composition/Composition.Input.h | 8 +- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.cpp index 9c116c93365..12d4ecf0c9d 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.cpp @@ -62,7 +62,7 @@ winrt::Windows::System::VirtualKey KeyRoutedEventArgs::OriginalKey() noexcept { } PointerPointProperties::PointerPointProperties(const winrt::Windows::UI::Input::PointerPointProperties &ppp) - : m_systemPPP(ppp) {} + : m_sysPointerPointProps(ppp) {} PointerPointProperties::PointerPointProperties( bool isBarrelButtonPressed, @@ -107,92 +107,92 @@ PointerPointProperties::PointerPointProperties( m_yTilt(yTilt) {} winrt::Windows::Foundation::Rect PointerPointProperties::ContactRect() noexcept { - return m_systemPPP.ContactRect(); + return m_sysPointerPointProps.ContactRect(); } bool PointerPointProperties::IsBarrelButtonPressed() noexcept { - return m_systemPPP ? m_systemPPP.IsBarrelButtonPressed() : m_isBarrelButtonPressed; + return m_sysPointerPointProps ? m_sysPointerPointProps.IsBarrelButtonPressed() : m_isBarrelButtonPressed; } bool PointerPointProperties::IsCanceled() noexcept { - return m_systemPPP ? m_systemPPP.IsCanceled() : m_isCanceled; + return m_sysPointerPointProps ? m_sysPointerPointProps.IsCanceled() : m_isCanceled; } bool PointerPointProperties::IsEraser() noexcept { - return m_systemPPP ? m_systemPPP.IsEraser() : m_isEraser; + return m_sysPointerPointProps ? m_sysPointerPointProps.IsEraser() : m_isEraser; } bool PointerPointProperties::IsHorizontalMouseWheel() noexcept { - return m_systemPPP ? m_systemPPP.IsHorizontalMouseWheel() : m_isHorizontalMouseWheel; + return m_sysPointerPointProps ? m_sysPointerPointProps.IsHorizontalMouseWheel() : m_isHorizontalMouseWheel; } bool PointerPointProperties::IsInRange() noexcept { - return m_systemPPP ? m_systemPPP.IsInRange() : m_isInRange; + return m_sysPointerPointProps ? m_sysPointerPointProps.IsInRange() : m_isInRange; } bool PointerPointProperties::IsInverted() noexcept { - return m_systemPPP ? m_systemPPP.IsInverted() : m_isInverted; + return m_sysPointerPointProps ? m_sysPointerPointProps.IsInverted() : m_isInverted; } bool PointerPointProperties::IsLeftButtonPressed() noexcept { - return m_systemPPP ? m_systemPPP.IsLeftButtonPressed() : m_isLeftButtonPressed; + return m_sysPointerPointProps ? m_sysPointerPointProps.IsLeftButtonPressed() : m_isLeftButtonPressed; } bool PointerPointProperties::IsMiddleButtonPressed() noexcept { - return m_systemPPP ? m_systemPPP.IsMiddleButtonPressed() : m_isMiddleButtonPressed; + return m_sysPointerPointProps ? m_sysPointerPointProps.IsMiddleButtonPressed() : m_isMiddleButtonPressed; } bool PointerPointProperties::IsPrimary() noexcept { - return m_systemPPP ? m_systemPPP.IsPrimary() : m_isPrimary; + return m_sysPointerPointProps ? m_sysPointerPointProps.IsPrimary() : m_isPrimary; } bool PointerPointProperties::IsRightButtonPressed() noexcept { - return m_systemPPP ? m_systemPPP.IsRightButtonPressed() : m_isRightButtonPressed; + return m_sysPointerPointProps ? m_sysPointerPointProps.IsRightButtonPressed() : m_isRightButtonPressed; } bool PointerPointProperties::IsXButton1Pressed() noexcept { - return m_systemPPP ? m_systemPPP.IsXButton1Pressed() : m_isXButton1Pressed; + return m_sysPointerPointProps ? m_sysPointerPointProps.IsXButton1Pressed() : m_isXButton1Pressed; } bool PointerPointProperties::IsXButton2Pressed() noexcept { - return m_systemPPP ? m_systemPPP.IsXButton2Pressed() : m_isXButton2Pressed; + return m_sysPointerPointProps ? m_sysPointerPointProps.IsXButton2Pressed() : m_isXButton2Pressed; } int32_t PointerPointProperties::MouseWheelDelta() noexcept { - return m_systemPPP ? m_systemPPP.MouseWheelDelta() : m_mouseWheelDelta; + return m_sysPointerPointProps ? m_sysPointerPointProps.MouseWheelDelta() : m_mouseWheelDelta; } float PointerPointProperties::Orientation() noexcept { - return m_systemPPP ? m_systemPPP.Orientation() : m_orientation; + return m_sysPointerPointProps ? m_sysPointerPointProps.Orientation() : m_orientation; } PointerUpdateKind PointerPointProperties::PointerUpdateKind() noexcept { - return m_systemPPP ? static_cast( - m_systemPPP.PointerUpdateKind()) - : m_pointerUpdateKind; + return m_sysPointerPointProps ? static_cast( + m_sysPointerPointProps.PointerUpdateKind()) + : m_pointerUpdateKind; } float PointerPointProperties::Pressure() noexcept { - return m_systemPPP ? m_systemPPP.Pressure() : m_pressure; + return m_sysPointerPointProps ? m_sysPointerPointProps.Pressure() : m_pressure; } bool PointerPointProperties::TouchConfidence() noexcept { - return m_systemPPP ? m_systemPPP.TouchConfidence() : m_touchConfidence; + return m_sysPointerPointProps ? m_sysPointerPointProps.TouchConfidence() : m_touchConfidence; } float PointerPointProperties::Twist() noexcept { - return m_systemPPP ? m_systemPPP.Twist() : m_twist; + return m_sysPointerPointProps ? m_sysPointerPointProps.Twist() : m_twist; } float PointerPointProperties::XTilt() noexcept { - return m_systemPPP ? m_systemPPP.XTilt() : m_xTilt; + return m_sysPointerPointProps ? m_sysPointerPointProps.XTilt() : m_xTilt; } float PointerPointProperties::YTilt() noexcept { - return m_systemPPP ? m_systemPPP.YTilt() : m_yTilt; + return m_sysPointerPointProps ? m_sysPointerPointProps.YTilt() : m_yTilt; } -PointerPoint::PointerPoint(const winrt::Windows::UI::Input::PointerPoint &pp) : m_systemPP(pp) {} +PointerPoint::PointerPoint(const winrt::Windows::UI::Input::PointerPoint &pp) : m_sysPointerPoint(pp) {} PointerPoint::PointerPoint(uint32_t msg, uint64_t wParam, int64_t lParam) { m_msg = msg; @@ -206,18 +206,18 @@ PointerPoint::PointerPoint(uint32_t msg, uint64_t wParam, int64_t lParam) { } uint32_t PointerPoint::FrameId() noexcept { - return m_systemPP ? m_systemPP.FrameId() : m_pi.frameId; + return m_sysPointerPoint ? m_sysPointerPoint.FrameId() : m_pi.frameId; } bool PointerPoint::IsInContact() noexcept { - return m_systemPP ? m_systemPP.IsInContact() - : ((m_pi.pointerFlags & POINTER_FLAG_INCONTACT) == POINTER_FLAG_INCONTACT); + return m_sysPointerPoint ? m_sysPointerPoint.IsInContact() + : ((m_pi.pointerFlags & POINTER_FLAG_INCONTACT) == POINTER_FLAG_INCONTACT); } winrt::Microsoft::ReactNative::Composition::Input::PointerDeviceType PointerPoint::PointerDeviceType() noexcept { - if (m_systemPP) { + if (m_sysPointerPoint) { return static_cast( - m_systemPP.PointerDevice().PointerDeviceType()); + m_sysPointerPoint.PointerDevice().PointerDeviceType()); } if (m_pi.pointerId) { @@ -239,12 +239,12 @@ winrt::Microsoft::ReactNative::Composition::Input::PointerDeviceType PointerPoin } uint32_t PointerPoint::PointerId() noexcept { - return m_systemPP ? m_systemPP.PointerId() : (m_pi.pointerId ? m_pi.pointerId : 1 /* MOUSE */); + return m_sysPointerPoint ? m_sysPointerPoint.PointerId() : (m_pi.pointerId ? m_pi.pointerId : 1 /* MOUSE */); } winrt::Windows::Foundation::Point PointerPoint::Position() noexcept { - return m_systemPP - ? m_systemPP.Position() + return m_sysPointerPoint + ? m_sysPointerPoint.Position() : (m_pi.pointerId ? winrt::Windows::Foundation:: Point{static_cast(m_pi.ptPixelLocation.x), static_cast(m_pi.ptPixelLocation.y)} @@ -253,8 +253,8 @@ winrt::Windows::Foundation::Point PointerPoint::Position() noexcept { } winrt::Microsoft::ReactNative::Composition::Input::PointerPointProperties PointerPoint::Properties() noexcept { - if (m_systemPP) { - return winrt::make(m_systemPP.Properties()); + if (m_sysPointerPoint) { + return winrt::make(m_sysPointerPoint.Properties()); } if (m_pi.pointerId) { @@ -306,7 +306,7 @@ winrt::Microsoft::ReactNative::Composition::Input::PointerPointProperties Pointe (m_pi.pointerFlags & POINTER_FLAG_FOURTHBUTTON) == POINTER_FLAG_FOURTHBUTTON, // isXButton1Pressed (m_pi.pointerFlags & POINTER_FLAG_FIFTHBUTTON) == POINTER_FLAG_FIFTHBUTTON, // isXButton2Pressed (m_pi.pointerFlags & POINTER_FLAG_CONFIDENCE) == POINTER_FLAG_CONFIDENCE, // touchConfidence - false, // TODO mouseWheelDelta, + 0, // mouseWheelDelta would come through a WM_(H)MOUSEWHEEL message, which wont have a POINTER_INFO struct, 0.0f, // TODO orientation, pointerUpdateKind, 0.0f, // TODO pressure, @@ -373,12 +373,12 @@ winrt::Microsoft::ReactNative::Composition::Input::PointerPointProperties Pointe } uint64_t PointerPoint::Timestamp() noexcept { - return m_systemPP ? m_systemPP.Timestamp() : m_pi.dwTime; + return m_sysPointerPoint ? m_sysPointerPoint.Timestamp() : m_pi.dwTime; } winrt::Microsoft::ReactNative::Composition::Input::PointerPoint PointerPoint::GetTransformedPoint( const IPointerPointTransform &transform) noexcept { - return winrt::make(m_systemPP); + return winrt::make(m_sysPointerPoint); } bool PointerPoint::IsPointerMessage(uint32_t message) noexcept { @@ -392,7 +392,7 @@ PointerRoutedEventArgs::PointerRoutedEventArgs( const winrt::Microsoft::ReactNative::Composition::Input::PointerPoint &pp, const winrt::Windows::System::VirtualKeyModifiers &virtualKeyModifiers) : m_tag(tag), m_virtualKeyModifiers(virtualKeyModifiers) { - m_pp = pp; + m_pointerPoint = pp; } int32_t PointerRoutedEventArgs::OriginalSource() noexcept { @@ -402,7 +402,7 @@ int32_t PointerRoutedEventArgs::OriginalSource() noexcept { winrt::Microsoft::ReactNative::Composition::Input::PointerPoint PointerRoutedEventArgs::GetCurrentPoint( int32_t tag) noexcept { assert(tag == -1); // TODO: Non-null tags need to apply a transform - return m_pp; + return m_pointerPoint; } bool PointerRoutedEventArgs::Handled() noexcept { diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.h b/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.h index 357c2049355..62c207bd646 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Composition.Input.h @@ -81,9 +81,9 @@ struct PointerPointProperties : PointerPointPropertiesT float YTilt() noexcept; private: - winrt::Windows::UI::Input::PointerPointProperties m_systemPPP{nullptr}; + winrt::Windows::UI::Input::PointerPointProperties m_sysPointerPointProps{nullptr}; - // When not using m_systemPPP + // When not using m_sysPointerPointProps bool m_isBarrelButtonPressed : 1; bool m_isCanceled : 1; bool m_isEraser : 1; @@ -124,7 +124,7 @@ struct PointerPoint : PointerPointT { bool IsPointerMessage(uint32_t message) noexcept; // Windows::Input - winrt::Windows::UI::Input::PointerPoint m_systemPP{nullptr}; + winrt::Windows::UI::Input::PointerPoint m_sysPointerPoint{nullptr}; // WM_POINTER* POINTER_INFO m_pi = {0}; // WM_*MOUSE @@ -148,7 +148,7 @@ struct PointerRoutedEventArgs : PointerRoutedEventArgsT private: facebook::react::Tag m_tag{-1}; bool m_handled{false}; - winrt::Microsoft::ReactNative::Composition::Input::PointerPoint m_pp{nullptr}; + winrt::Microsoft::ReactNative::Composition::Input::PointerPoint m_pointerPoint{nullptr}; winrt::Windows::System::VirtualKeyModifiers m_virtualKeyModifiers; };