|
12 | 12 | #include <Views/ShadowNodeBase.h> |
13 | 13 | #include <windows.h> |
14 | 14 | #include <windowsx.h> |
| 15 | +#include <winrt/Windows.UI.Core.h> |
15 | 16 | #include <winrt/Windows.UI.Input.h> |
16 | 17 | #include "Composition.Input.h" |
17 | 18 | #include "CompositionViewComponentView.h" |
18 | 19 | #include "ReactNativeIsland.h" |
19 | 20 | #include "RootComponentView.h" |
20 | 21 |
|
21 | | -#ifdef USE_WINUI3 |
22 | | -#include <winrt/Microsoft.UI.Input.h> |
23 | | -#endif |
| 22 | +namespace ABI::Microsoft::UI::Input { |
| 23 | +struct IInputCursor; |
| 24 | +} |
| 25 | + |
| 26 | +#include <Microsoft.UI.Input.InputCursor.Interop.h> |
24 | 27 |
|
25 | 28 | namespace Microsoft::ReactNative { |
26 | 29 |
|
@@ -328,6 +331,11 @@ CompositionEventHandler::~CompositionEventHandler() { |
328 | 331 | } |
329 | 332 | } |
330 | 333 | #endif |
| 334 | + |
| 335 | + if (m_hcursorOwned) { |
| 336 | + ::DestroyCursor(m_hcursor); |
| 337 | + m_hcursor = nullptr; |
| 338 | + } |
331 | 339 | } |
332 | 340 |
|
333 | 341 | facebook::react::SurfaceId CompositionEventHandler::SurfaceId() const noexcept { |
@@ -507,6 +515,10 @@ int64_t CompositionEventHandler::SendMessage(HWND hwnd, uint32_t msg, uint64_t w |
507 | 515 | } |
508 | 516 | break; |
509 | 517 | } |
| 518 | + case WM_SETCURSOR: { |
| 519 | + UpdateCursor(); |
| 520 | + return 1; |
| 521 | + } |
510 | 522 | } |
511 | 523 |
|
512 | 524 | return 0; |
@@ -753,6 +765,151 @@ void CompositionEventHandler::HandleIncomingPointerEvent( |
753 | 765 | hoveredViews.emplace_back(ReactTaggedView(componentViewDescriptor.view)); |
754 | 766 | } |
755 | 767 | m_currentlyHoveredViewsPerPointer[pointerId] = std::move(hoveredViews); |
| 768 | + |
| 769 | + if (IsMousePointerEvent(event)) { |
| 770 | + UpdateCursor(); |
| 771 | + } |
| 772 | +} |
| 773 | + |
| 774 | +void CompositionEventHandler::UpdateCursor() noexcept { |
| 775 | + for (auto &taggedView : m_currentlyHoveredViewsPerPointer[MOUSE_POINTER_ID]) { |
| 776 | + if (auto view = taggedView.view()) { |
| 777 | + if (auto viewcomponent = |
| 778 | + view.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ComponentView>()) { |
| 779 | + auto cursorInfo = viewcomponent->cursor(); |
| 780 | + if (cursorInfo.first != facebook::react::Cursor::Auto || cursorInfo.second != nullptr) { |
| 781 | + SetCursor(cursorInfo.first, cursorInfo.second); |
| 782 | + return; |
| 783 | + } |
| 784 | + } |
| 785 | + } |
| 786 | + } |
| 787 | + |
| 788 | + SetCursor(facebook::react::Cursor::Auto, nullptr); |
| 789 | +} |
| 790 | + |
| 791 | +void CompositionEventHandler::SetCursor(facebook::react::Cursor cursor, HCURSOR hcur) noexcept { |
| 792 | + if (m_currentCursor == cursor && m_hcursor == hcur) |
| 793 | + return; |
| 794 | + |
| 795 | + if (auto strongRootView = m_wkRootView.get()) { |
| 796 | + if (auto island = strongRootView.Island()) { |
| 797 | + auto pointerSource = winrt::Microsoft::UI::Input::InputPointerSource::GetForIsland(island); |
| 798 | + |
| 799 | + if (!hcur) { |
| 800 | + winrt::Windows::UI::Core::CoreCursorType type = winrt::Windows::UI::Core::CoreCursorType::Arrow; |
| 801 | + switch (cursor) { |
| 802 | + case facebook::react::Cursor::Pointer: |
| 803 | + type = winrt::Windows::UI::Core::CoreCursorType::Hand; |
| 804 | + break; |
| 805 | + case facebook::react::Cursor::Help: |
| 806 | + type = winrt::Windows::UI::Core::CoreCursorType::Help; |
| 807 | + break; |
| 808 | + case facebook::react::Cursor::NotAllowed: |
| 809 | + type = winrt::Windows::UI::Core::CoreCursorType::UniversalNo; |
| 810 | + break; |
| 811 | + case facebook::react::Cursor::Wait: |
| 812 | + type = winrt::Windows::UI::Core::CoreCursorType::Wait; |
| 813 | + break; |
| 814 | + case facebook::react::Cursor::Move: |
| 815 | + type = winrt::Windows::UI::Core::CoreCursorType::SizeAll; |
| 816 | + break; |
| 817 | + case facebook::react::Cursor::NESWResize: |
| 818 | + type = winrt::Windows::UI::Core::CoreCursorType::SizeNortheastSouthwest; |
| 819 | + break; |
| 820 | + case facebook::react::Cursor::NSResize: |
| 821 | + type = winrt::Windows::UI::Core::CoreCursorType::SizeNorthSouth; |
| 822 | + break; |
| 823 | + case facebook::react::Cursor::NWSEResize: |
| 824 | + type = winrt::Windows::UI::Core::CoreCursorType::SizeNorthwestSoutheast; |
| 825 | + break; |
| 826 | + case facebook::react::Cursor::EWResize: |
| 827 | + type = winrt::Windows::UI::Core::CoreCursorType::SizeWestEast; |
| 828 | + break; |
| 829 | + case facebook::react::Cursor::Text: |
| 830 | + type = winrt::Windows::UI::Core::CoreCursorType::IBeam; |
| 831 | + break; |
| 832 | + case facebook::react::Cursor::Progress: |
| 833 | + type = winrt::Windows::UI::Core::CoreCursorType::Wait; // IDC_APPSTARTING not mapped to CoreCursor? |
| 834 | + break; |
| 835 | + case facebook::react::Cursor::Crosshair: |
| 836 | + type = winrt::Windows::UI::Core::CoreCursorType::Cross; |
| 837 | + break; |
| 838 | + default: |
| 839 | + break; |
| 840 | + } |
| 841 | + |
| 842 | + m_inputCursor = winrt::Microsoft::UI::Input::InputCursor::CreateFromCoreCursor( |
| 843 | + winrt::Windows::UI::Core::CoreCursor(type, 0)); |
| 844 | + m_hcursor = hcur; |
| 845 | + } else { |
| 846 | + auto cursorInterop = winrt::get_activation_factory< |
| 847 | + winrt::Microsoft::UI::Input::InputCursor, |
| 848 | + ABI::Microsoft::UI::Input::IInputCursorStaticsInterop>(); |
| 849 | + winrt::com_ptr<IUnknown> spunk; |
| 850 | + winrt::check_hresult(cursorInterop->CreateFromHCursor( |
| 851 | + hcur, reinterpret_cast<ABI::Microsoft::UI::Input::IInputCursor **>(spunk.put_void()))); |
| 852 | + m_hcursor = hcur; |
| 853 | + m_inputCursor = spunk.as<winrt::Microsoft::UI::Input::InputCursor>(); |
| 854 | + } |
| 855 | + |
| 856 | + pointerSource.Cursor(m_inputCursor); |
| 857 | + } else { |
| 858 | + if (m_hcursorOwned) { |
| 859 | + ::DestroyCursor(m_hcursor); |
| 860 | + m_hcursorOwned = false; |
| 861 | + } |
| 862 | + if (hcur == nullptr) { |
| 863 | + const WCHAR *idc = IDC_ARROW; |
| 864 | + switch (cursor) { |
| 865 | + case facebook::react::Cursor::Pointer: |
| 866 | + idc = IDC_HAND; |
| 867 | + break; |
| 868 | + case facebook::react::Cursor::Help: |
| 869 | + idc = IDC_HELP; |
| 870 | + break; |
| 871 | + case facebook::react::Cursor::NotAllowed: |
| 872 | + idc = IDC_NO; |
| 873 | + break; |
| 874 | + case facebook::react::Cursor::Wait: |
| 875 | + idc = IDC_WAIT; |
| 876 | + break; |
| 877 | + case facebook::react::Cursor::Move: |
| 878 | + idc = IDC_SIZEALL; |
| 879 | + break; |
| 880 | + case facebook::react::Cursor::NESWResize: |
| 881 | + idc = IDC_SIZENESW; |
| 882 | + break; |
| 883 | + case facebook::react::Cursor::NSResize: |
| 884 | + idc = IDC_SIZENS; |
| 885 | + break; |
| 886 | + case facebook::react::Cursor::NWSEResize: |
| 887 | + idc = IDC_SIZENWSE; |
| 888 | + break; |
| 889 | + case facebook::react::Cursor::EWResize: |
| 890 | + idc = IDC_SIZEWE; |
| 891 | + break; |
| 892 | + case facebook::react::Cursor::Text: |
| 893 | + idc = IDC_IBEAM; |
| 894 | + break; |
| 895 | + case facebook::react::Cursor::Progress: |
| 896 | + idc = IDC_APPSTARTING; |
| 897 | + break; |
| 898 | + case facebook::react::Cursor::Crosshair: |
| 899 | + idc = IDC_CROSS; |
| 900 | + break; |
| 901 | + default: |
| 902 | + break; |
| 903 | + } |
| 904 | + m_hcursor = ::LoadCursor(nullptr, idc); |
| 905 | + m_hcursorOwned = true; |
| 906 | + } else { |
| 907 | + m_hcursor = hcur; |
| 908 | + } |
| 909 | + ::SetCursor(m_hcursor); |
| 910 | + } |
| 911 | + m_currentCursor = cursor; |
| 912 | + } |
756 | 913 | } |
757 | 914 |
|
758 | 915 | void CompositionEventHandler::UpdateActiveTouch( |
|
0 commit comments