react-native-windows 0.78.5 → 0.78.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/Directory.Build.props +6 -4
  2. package/Folly/Folly.vcxproj +46 -6
  3. package/Folly/Folly.vcxproj.filters +16 -4
  4. package/Folly/TEMP_UntilFollyUpdate/ConstexprMath.h +26 -18
  5. package/Folly/TEMP_UntilFollyUpdate/Conv.cpp +1205 -0
  6. package/Folly/TEMP_UntilFollyUpdate/chrono/Hardware.h +155 -0
  7. package/Folly/TEMP_UntilFollyUpdate/concurrency/CacheLocality.cpp +633 -0
  8. package/Folly/TEMP_UntilFollyUpdate/{dynamic-inl.h → json/dynamic-inl.h} +3 -4
  9. package/Folly/TEMP_UntilFollyUpdate/{json.cpp → json/json.cpp} +14 -10
  10. package/Folly/TEMP_UntilFollyUpdate/lang/SafeAssert.h +7 -14
  11. package/Folly/TEMP_UntilFollyUpdate/lang/ToAscii.h +6 -6
  12. package/Folly/ThreadNameStub.cpp +10 -0
  13. package/Folly/cgmanifest.json +11 -1
  14. package/Libraries/Components/View/View.windows.js +107 -56
  15. package/Libraries/Components/View/ViewAccessibility.d.ts +60 -1
  16. package/Libraries/Image/Image.windows.js +42 -21
  17. package/Libraries/Modal/Modal.d.ts +7 -0
  18. package/Libraries/Modal/Modal.windows.js +7 -1
  19. package/Libraries/NativeComponent/BaseViewConfig.windows.js +3 -0
  20. package/Libraries/Text/Text.d.ts +18 -0
  21. package/Microsoft.ReactNative/AsynchronousEventBeat.cpp +4 -25
  22. package/Microsoft.ReactNative/AsynchronousEventBeat.h +0 -3
  23. package/Microsoft.ReactNative/Base/FollyIncludes.h +1 -0
  24. package/Microsoft.ReactNative/CallInvoker.cpp +42 -0
  25. package/Microsoft.ReactNative/CallInvoker.h +34 -0
  26. package/Microsoft.ReactNative/{JSDispatcherWriter.cpp → CallInvokerWriter.cpp} +35 -47
  27. package/Microsoft.ReactNative/CallInvokerWriter.h +74 -0
  28. package/Microsoft.ReactNative/CompositionComponentView.idl +0 -5
  29. package/Microsoft.ReactNative/CompositionSwitcher.idl +7 -0
  30. package/Microsoft.ReactNative/Fabric/AbiViewProps.cpp +8 -10
  31. package/Microsoft.ReactNative/Fabric/ComponentView.cpp +4 -1
  32. package/Microsoft.ReactNative/Fabric/Composition/ActivityIndicatorComponentView.cpp +12 -2
  33. package/Microsoft.ReactNative/Fabric/Composition/ActivityIndicatorComponentView.h +2 -0
  34. package/Microsoft.ReactNative/Fabric/Composition/CompositionAnnotationProvider.cpp +100 -0
  35. package/Microsoft.ReactNative/Fabric/Composition/CompositionAnnotationProvider.h +31 -0
  36. package/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp +77 -11
  37. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +43 -1
  38. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h +7 -0
  39. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +86 -56
  40. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h +5 -1
  41. package/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp +0 -4
  42. package/Microsoft.ReactNative/Fabric/Composition/CompositionUIService.cpp +0 -2
  43. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +118 -63
  44. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +2 -0
  45. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp +133 -8
  46. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h +16 -2
  47. package/Microsoft.ReactNative/Fabric/Composition/FocusManager.cpp +4 -2
  48. package/Microsoft.ReactNative/Fabric/Composition/FocusManager.h +9 -1
  49. package/Microsoft.ReactNative/Fabric/Composition/ImageComponentView.cpp +34 -11
  50. package/Microsoft.ReactNative/Fabric/Composition/ImageComponentView.h +3 -0
  51. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +133 -135
  52. package/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.cpp +9 -6
  53. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +46 -49
  54. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +6 -1
  55. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp +13 -8
  56. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h +5 -2
  57. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +146 -25
  58. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +14 -0
  59. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +160 -12
  60. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +6 -0
  61. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputEventEmitter.cpp +47 -0
  62. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputEventEmitter.h +15 -1
  63. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputProps.cpp +6 -2
  64. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputProps.h +4 -1
  65. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.cpp +7 -9
  66. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.h +4 -1
  67. package/Microsoft.ReactNative/Fabric/Composition/Theme.cpp +5 -0
  68. package/Microsoft.ReactNative/Fabric/Composition/TooltipService.cpp +40 -36
  69. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +68 -0
  70. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h +11 -0
  71. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp +70 -13
  72. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.h +10 -2
  73. package/Microsoft.ReactNative/Fabric/ImageManager.cpp +5 -5
  74. package/Microsoft.ReactNative/Fabric/ImageRequestParams.cpp +26 -0
  75. package/Microsoft.ReactNative/Fabric/WindowsImageManager.cpp +47 -8
  76. package/Microsoft.ReactNative/Fabric/WindowsImageManager.h +10 -1
  77. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/CompositionAccessibilityProps.h +67 -0
  78. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.cpp +22 -4
  79. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.h +15 -2
  80. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.cpp +20 -0
  81. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.h +5 -0
  82. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/MouseEvent.h +20 -0
  83. package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/HostPlatformColor.h +5 -8
  84. package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/PlatformColorParser.h +1 -2
  85. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.cpp +247 -45
  86. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.h +15 -0
  87. package/Microsoft.ReactNative/Fabric/platform/react/threading/MessageQueueThreadImpl.cpp +39 -0
  88. package/Microsoft.ReactNative/Fabric/platform/react/threading/MessageQueueThreadImpl.h +54 -0
  89. package/Microsoft.ReactNative/Fabric/platform/react/threading/TaskDispatchThread.cpp +126 -0
  90. package/Microsoft.ReactNative/Fabric/platform/react/threading/TaskDispatchThread.h +73 -0
  91. package/Microsoft.ReactNative/IReactContext.cpp +17 -0
  92. package/Microsoft.ReactNative/IReactContext.h +1 -0
  93. package/Microsoft.ReactNative/IReactContext.idl +18 -1
  94. package/Microsoft.ReactNative/IReactDispatcher.idl +1 -0
  95. package/Microsoft.ReactNative/IReactModuleBuilder.cpp +12 -0
  96. package/Microsoft.ReactNative/IReactModuleBuilder.h +2 -0
  97. package/Microsoft.ReactNative/IReactModuleBuilder.idl +8 -0
  98. package/Microsoft.ReactNative/JsiApi.cpp +10 -2
  99. package/Microsoft.ReactNative/JsiApi.h +1 -0
  100. package/Microsoft.ReactNative/JsiApi.idl +1 -0
  101. package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +0 -3
  102. package/Microsoft.ReactNative/Modules/AccessibilityInfoModule.cpp +2 -3
  103. package/Microsoft.ReactNative/Modules/AlertModule.cpp +7 -12
  104. package/Microsoft.ReactNative/Modules/Animated/AnimationDriver.cpp +2 -1
  105. package/Microsoft.ReactNative/Modules/Animated/NativeAnimatedModule.cpp +4 -8
  106. package/Microsoft.ReactNative/Modules/AppStateModule.cpp +2 -2
  107. package/Microsoft.ReactNative/Modules/ClipboardModule.cpp +6 -8
  108. package/Microsoft.ReactNative/Modules/ClipboardModule.h +1 -1
  109. package/Microsoft.ReactNative/Modules/ImageViewManagerModule.cpp +6 -15
  110. package/Microsoft.ReactNative/Modules/NativeUIManager.cpp +13 -24
  111. package/Microsoft.ReactNative/QuirkSettings.cpp +0 -16
  112. package/Microsoft.ReactNative/QuirkSettings.h +0 -3
  113. package/Microsoft.ReactNative/ReactHost/ReactHost.cpp +11 -1
  114. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +78 -68
  115. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h +1 -2
  116. package/Microsoft.ReactNative/ReactInstanceSettings.cpp +12 -0
  117. package/Microsoft.ReactNative/ReactInstanceSettings.h +2 -0
  118. package/Microsoft.ReactNative/ReactInstanceSettings.idl +6 -0
  119. package/Microsoft.ReactNative/ReactNativeIsland.idl +3 -0
  120. package/Microsoft.ReactNative/ReactSupport.cpp +44 -11
  121. package/Microsoft.ReactNative/RedBox.cpp +30 -1
  122. package/Microsoft.ReactNative/SchedulerSettings.cpp +4 -4
  123. package/Microsoft.ReactNative/SchedulerSettings.h +1 -1
  124. package/Microsoft.ReactNative/TurboModulesProvider.cpp +30 -12
  125. package/Microsoft.ReactNative/Utils/ImageUtils.h +1 -0
  126. package/Microsoft.ReactNative/Utils/LocalBundleReader.cpp +37 -31
  127. package/Microsoft.ReactNative.Cxx/ApiLoaders/JSRuntimeApi.cpp +1 -0
  128. package/Microsoft.ReactNative.Cxx/ApiLoaders/JSRuntimeApi.inc +2 -0
  129. package/Microsoft.ReactNative.Cxx/ApiLoaders/NodeApi_posix.cpp +1 -1
  130. package/Microsoft.ReactNative.Cxx/JSI/JsiAbiApi.cpp +94 -27
  131. package/Microsoft.ReactNative.Cxx/JSI/JsiAbiApi.h +27 -6
  132. package/Microsoft.ReactNative.Cxx/JSI/JsiApiContext.cpp +45 -11
  133. package/Microsoft.ReactNative.Cxx/JSI/JsiApiContext.h +6 -0
  134. package/Microsoft.ReactNative.Cxx/JSI/decorator.h +220 -0
  135. package/Microsoft.ReactNative.Cxx/JSI/instrumentation.h +28 -0
  136. package/Microsoft.ReactNative.Cxx/JSI/jsi-inl.h +6 -0
  137. package/Microsoft.ReactNative.Cxx/JSI/jsi.cpp +241 -4
  138. package/Microsoft.ReactNative.Cxx/JSI/jsi.h +207 -19
  139. package/Microsoft.ReactNative.Cxx/JSValue.cpp +19 -3
  140. package/Microsoft.ReactNative.Cxx/JSValue.h +15 -7
  141. package/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems +2 -2
  142. package/Microsoft.ReactNative.Cxx/NativeModules.h +60 -2
  143. package/Microsoft.ReactNative.Cxx/NodeApiJsiRuntime.cpp +1267 -614
  144. package/Microsoft.ReactNative.Cxx/NodeApiJsiRuntime.h +4 -2
  145. package/Microsoft.ReactNative.Cxx/ReactContext.h +7 -0
  146. package/Microsoft.ReactNative.Cxx/TurboModuleProvider.cpp +11 -13
  147. package/Microsoft.ReactNative.Cxx/TurboModuleProvider.h +2 -3
  148. package/Microsoft.ReactNative.Cxx/node-api/js_native_api.h +81 -20
  149. package/Microsoft.ReactNative.Cxx/node-api/js_native_api_types.h +47 -2
  150. package/Microsoft.ReactNative.Cxx/node-api/js_runtime_api.h +13 -0
  151. package/Microsoft.ReactNative.Cxx/stubs/glog/logging.h +1 -1
  152. package/Microsoft.ReactNative.Managed/ReactContext.cs +3 -1
  153. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  154. package/PropertySheets/JSEngine.props +1 -1
  155. package/PropertySheets/React.Cpp.props +2 -1
  156. package/PropertySheets/WebView2.props +1 -1
  157. package/PropertySheets/WinUI.props +2 -2
  158. package/ReactCommon/TEMP_UntilReactCommonUpdate/jserrorhandler/JsErrorHandler.cpp +429 -0
  159. package/ReactCommon/cgmanifest.json +1 -1
  160. package/Shared/HermesRuntimeHolder.cpp +6 -0
  161. package/Shared/JSI/ChakraRuntime.cpp +4 -0
  162. package/Shared/JSI/ChakraRuntime.h +2 -0
  163. package/Shared/Modules/BlobModule.cpp +14 -16
  164. package/Shared/Modules/BlobModule.h +3 -1
  165. package/Shared/Shared.vcxitems +11 -7
  166. package/Shared/Shared.vcxitems.filters +6 -1
  167. package/Shared/TurboModuleManager.cpp +0 -15
  168. package/codegen/react/components/rnwcore/ActivityIndicatorView.g.h +6 -6
  169. package/codegen/react/components/rnwcore/AndroidDrawerLayout.g.h +6 -6
  170. package/codegen/react/components/rnwcore/AndroidHorizontalScrollContentView.g.h +6 -6
  171. package/codegen/react/components/rnwcore/AndroidProgressBar.g.h +6 -6
  172. package/codegen/react/components/rnwcore/AndroidSwipeRefreshLayout.g.h +6 -6
  173. package/codegen/react/components/rnwcore/AndroidSwitch.g.h +6 -6
  174. package/codegen/react/components/rnwcore/DebuggingOverlay.g.h +6 -6
  175. package/codegen/react/components/rnwcore/InputAccessory.g.h +6 -6
  176. package/codegen/react/components/rnwcore/ModalHostView.g.h +11 -7
  177. package/codegen/react/components/rnwcore/Props.cpp +2 -1
  178. package/codegen/react/components/rnwcore/Props.h +1 -0
  179. package/codegen/react/components/rnwcore/PullToRefreshView.g.h +6 -6
  180. package/codegen/react/components/rnwcore/SafeAreaView.g.h +6 -6
  181. package/codegen/react/components/rnwcore/Switch.g.h +6 -6
  182. package/codegen/react/components/rnwcore/UnimplementedNativeView.g.h +6 -6
  183. package/index.windows.js +4 -2
  184. package/package.json +3 -4
  185. package/src/private/specs/components/RCTModalHostViewNativeComponent.js +8 -0
  186. package/stubs/glog/logging.h +1 -1
  187. package/Microsoft.ReactNative/JSDispatcherWriter.h +0 -47
  188. package/Microsoft.ReactNative/SynchronousEventBeat.cpp +0 -51
  189. package/Microsoft.ReactNative/SynchronousEventBeat.h +0 -31
@@ -116,25 +116,25 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
116
116
 
117
117
  //@cmember Show the scroll bar
118
118
  BOOL TxShowScrollBar(INT fnBar, BOOL fShow) override {
119
- assert(false);
119
+ // assert(false);
120
120
  return {};
121
121
  }
122
122
 
123
123
  //@cmember Enable the scroll bar
124
124
  BOOL TxEnableScrollBar(INT fuSBFlags, INT fuArrowflags) override {
125
- assert(false);
125
+ // assert(false);
126
126
  return {};
127
127
  }
128
128
 
129
129
  //@cmember Set the scroll range
130
130
  BOOL TxSetScrollRange(INT fnBar, LONG nMinPos, INT nMaxPos, BOOL fRedraw) override {
131
- assert(false);
131
+ // assert(false);
132
132
  return {};
133
133
  }
134
134
 
135
135
  //@cmember Set the scroll position
136
136
  BOOL TxSetScrollPos(INT fnBar, INT nPos, BOOL fRedraw) override {
137
- assert(false);
137
+ // assert(false);
138
138
  return {};
139
139
  }
140
140
 
@@ -377,8 +377,11 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
377
377
 
378
378
  //@cmember Get the bits representing requested scroll bars for the window
379
379
  HRESULT TxGetScrollBars(DWORD *pdwScrollBar) override {
380
- // TODO support scrolling
381
- *pdwScrollBar = 0;
380
+ if (m_outer->m_multiline) {
381
+ *pdwScrollBar = WS_VSCROLL | WS_HSCROLL | ES_AUTOVSCROLL | ES_AUTOHSCROLL;
382
+ } else {
383
+ *pdwScrollBar = WS_HSCROLL | ES_AUTOHSCROLL;
384
+ }
382
385
  return S_OK;
383
386
  }
384
387
 
@@ -460,6 +463,13 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
460
463
  WindowsTextInputComponentView *m_outer;
461
464
  };
462
465
 
466
+ int WINAPI
467
+ AutoCorrectOffCallback(LANGID langid, const WCHAR *pszBefore, WCHAR *pszAfter, LONG cchAfter, LONG *pcchReplaced) {
468
+ wcsncpy_s(pszAfter, cchAfter, pszBefore, _TRUNCATE);
469
+ *pcchReplaced = static_cast<LONG>(wcslen(pszAfter));
470
+ return ATP_CHANGE;
471
+ }
472
+
463
473
  facebook::react::AttributedString WindowsTextInputComponentView::getAttributedString() const {
464
474
  // Use BaseTextShadowNode to get attributed string from children
465
475
 
@@ -611,6 +621,19 @@ WPARAM PointerRoutedEventArgsToMouseWParam(
611
621
  return wParam;
612
622
  }
613
623
 
624
+ bool WindowsTextInputComponentView::IsDoubleClick() {
625
+ using namespace std::chrono;
626
+
627
+ auto now = steady_clock::now();
628
+ auto duration = duration_cast<milliseconds>(now - m_lastClickTime).count();
629
+
630
+ const int DOUBLE_CLICK_TIME_MS = ::GetDoubleClickTime();
631
+
632
+ m_lastClickTime = now;
633
+
634
+ return (duration < DOUBLE_CLICK_TIME_MS);
635
+ }
636
+
614
637
  void WindowsTextInputComponentView::OnPointerPressed(
615
638
  const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept {
616
639
  UINT msg = 0;
@@ -627,7 +650,11 @@ void WindowsTextInputComponentView::OnPointerPressed(
627
650
  if (pp.PointerDeviceType() == winrt::Microsoft::ReactNative::Composition::Input::PointerDeviceType::Mouse) {
628
651
  switch (pp.Properties().PointerUpdateKind()) {
629
652
  case winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::LeftButtonPressed:
630
- msg = WM_LBUTTONDOWN;
653
+ if (IsDoubleClick()) {
654
+ msg = WM_LBUTTONDBLCLK;
655
+ } else {
656
+ msg = WM_LBUTTONDOWN;
657
+ }
631
658
  break;
632
659
  case winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::MiddleButtonPressed:
633
660
  msg = WM_MBUTTONDOWN;
@@ -656,6 +683,24 @@ void WindowsTextInputComponentView::OnPointerPressed(
656
683
  auto hr = m_textServices->TxSendMessage(msg, static_cast<WPARAM>(wParam), static_cast<LPARAM>(lParam), &lresult);
657
684
  args.Handled(hr != S_FALSE);
658
685
  }
686
+
687
+ // Emits the OnPressIn event
688
+ if (m_eventEmitter && !m_comingFromJS) {
689
+ auto emitter = std::static_pointer_cast<const facebook::react::WindowsTextInputEventEmitter>(m_eventEmitter);
690
+ float offsetX = position.X - m_layoutMetrics.frame.origin.x;
691
+ float offsetY = position.Y - m_layoutMetrics.frame.origin.y;
692
+ float neutralX = m_layoutMetrics.frame.origin.x;
693
+ float neutralY = m_layoutMetrics.frame.origin.y;
694
+
695
+ facebook::react::PressEvent pressInArgs;
696
+ pressInArgs.target = m_tag;
697
+ pressInArgs.pagePoint = {position.X, position.Y};
698
+ pressInArgs.offsetPoint = {offsetX, offsetY}; //{LocationX,LocationY}
699
+ pressInArgs.timestamp = static_cast<double>(pp.Timestamp()) / 1000.0;
700
+ pressInArgs.identifier = pp.PointerId();
701
+
702
+ emitter->onPressIn(pressInArgs);
703
+ }
659
704
  }
660
705
 
661
706
  void WindowsTextInputComponentView::OnPointerReleased(
@@ -928,8 +973,25 @@ void WindowsTextInputComponentView::onLostFocus(
928
973
  LRESULT lresult;
929
974
  DrawBlock db(*this);
930
975
  m_textServices->TxSendMessage(WM_KILLFOCUS, 0, 0, &lresult);
976
+ if (windowsTextInputProps().selectTextOnFocus) {
977
+ LRESULT res;
978
+ m_textServices->TxSendMessage(EM_SETSEL, static_cast<WPARAM>(-1), static_cast<WPARAM>(-1), &res);
979
+ }
931
980
  }
932
981
  m_caretVisual.IsVisible(false);
982
+
983
+ // Call onEndEditing when focus is lost
984
+ if (m_eventEmitter && !m_comingFromJS) {
985
+ auto emitter = std::static_pointer_cast<const facebook::react::WindowsTextInputEventEmitter>(m_eventEmitter);
986
+ facebook::react::WindowsTextInputEventEmitter::OnEndEditing onEndEditingArgs;
987
+
988
+ // Set event arguments
989
+ onEndEditingArgs.eventCount = ++m_nativeEventCount;
990
+ onEndEditingArgs.text = GetTextFromRichEdit();
991
+
992
+ // Emit the event
993
+ emitter->onEndEditing(onEndEditingArgs);
994
+ }
933
995
  }
934
996
 
935
997
  void WindowsTextInputComponentView::onGotFocus(
@@ -943,6 +1005,9 @@ void WindowsTextInputComponentView::onGotFocus(
943
1005
 
944
1006
  if (windowsTextInputProps().clearTextOnFocus) {
945
1007
  m_textServices->TxSetText(L"");
1008
+ } else if (windowsTextInputProps().selectTextOnFocus) {
1009
+ LRESULT res;
1010
+ m_textServices->TxSendMessage(EM_SETSEL, static_cast<WPARAM>(0), static_cast<WPARAM>(-1), &res);
946
1011
  }
947
1012
  }
948
1013
  }
@@ -983,7 +1048,10 @@ void WindowsTextInputComponentView::updateProps(
983
1048
  if (!facebook::react::floatEquality(
984
1049
  oldTextInputProps.textAttributes.fontSize, newTextInputProps.textAttributes.fontSize) ||
985
1050
  (oldTextInputProps.textAttributes.allowFontScaling != newTextInputProps.textAttributes.allowFontScaling) ||
986
- oldTextInputProps.textAttributes.fontWeight != newTextInputProps.textAttributes.fontWeight) {
1051
+ oldTextInputProps.textAttributes.fontWeight != newTextInputProps.textAttributes.fontWeight ||
1052
+ !facebook::react::floatEquality(
1053
+ oldTextInputProps.textAttributes.letterSpacing, newTextInputProps.textAttributes.letterSpacing) ||
1054
+ oldTextInputProps.textAttributes.fontFamily != newTextInputProps.textAttributes.fontFamily) {
987
1055
  m_propBitsMask |= TXTBIT_CHARFORMATCHANGE;
988
1056
  m_propBits |= TXTBIT_CHARFORMATCHANGE;
989
1057
  }
@@ -1042,6 +1110,26 @@ void WindowsTextInputComponentView::updateProps(
1042
1110
  autoCapitalizeOnUpdateProps(oldTextInputProps.autoCapitalize, newTextInputProps.autoCapitalize);
1043
1111
  }
1044
1112
 
1113
+ if (oldTextInputProps.textAlign != newTextInputProps.textAlign) {
1114
+ // Let UpdateParaFormat() to refresh the text field with the new text alignment.
1115
+ m_propBitsMask |= TXTBIT_PARAFORMATCHANGE;
1116
+ m_propBits |= TXTBIT_PARAFORMATCHANGE;
1117
+ }
1118
+
1119
+ // Please note: spellcheck performs both red lines and autocorrect as per windows behaviour
1120
+ bool shouldUpdateSpellCheck =
1121
+ (!oldProps || (oldTextInputProps.spellCheck != newTextInputProps.spellCheck) ||
1122
+ (oldTextInputProps.autoCorrect != newTextInputProps.autoCorrect));
1123
+
1124
+ if (shouldUpdateSpellCheck) {
1125
+ bool effectiveSpellCheck = newTextInputProps.spellCheck || newTextInputProps.autoCorrect;
1126
+ updateSpellCheck(effectiveSpellCheck);
1127
+ }
1128
+
1129
+ if (!oldProps || oldTextInputProps.autoCorrect != newTextInputProps.autoCorrect) {
1130
+ updateAutoCorrect(newTextInputProps.autoCorrect);
1131
+ }
1132
+
1045
1133
  UpdatePropertyBits();
1046
1134
  }
1047
1135
 
@@ -1147,10 +1235,10 @@ void WindowsTextInputComponentView::OnTextUpdated() noexcept {
1147
1235
  emitter->onChange(onChangeArgs);
1148
1236
  }
1149
1237
 
1150
- if (m_uiaProvider) {
1238
+ if (UiaClientsAreListening()) {
1151
1239
  auto text = GetTextFromRichEdit();
1152
1240
  winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
1153
- m_uiaProvider, UIA_ValueValuePropertyId, text, text);
1241
+ EnsureUiaProvider(), UIA_ValueValuePropertyId, text, text);
1154
1242
  }
1155
1243
  }
1156
1244
 
@@ -1288,10 +1376,24 @@ void WindowsTextInputComponentView::UpdateCharFormat() noexcept {
1288
1376
  // cfNew.dwEffects |= CFE_UNDERLINE;
1289
1377
  // }
1290
1378
 
1379
+ // set font family
1380
+ if (!props.textAttributes.fontFamily.empty()) {
1381
+ cfNew.dwMask |= CFM_FACE;
1382
+ std::wstring fontFamily =
1383
+ std::wstring(props.textAttributes.fontFamily.begin(), props.textAttributes.fontFamily.end());
1384
+ wcsncpy_s(cfNew.szFaceName, fontFamily.c_str(), LF_FACESIZE);
1385
+ }
1386
+
1291
1387
  // set char offset
1292
1388
  cfNew.dwMask |= CFM_OFFSET;
1293
1389
  cfNew.yOffset = 0;
1294
1390
 
1391
+ // set letter spacing
1392
+ float letterSpacing = props.textAttributes.letterSpacing;
1393
+ if (!std::isnan(letterSpacing)) {
1394
+ updateLetterSpacing(letterSpacing);
1395
+ }
1396
+
1295
1397
  // set charset
1296
1398
  cfNew.dwMask |= CFM_CHARSET;
1297
1399
  cfNew.bCharSet = DEFAULT_CHARSET;
@@ -1305,7 +1407,15 @@ void WindowsTextInputComponentView::UpdateParaFormat() noexcept {
1305
1407
  m_pf.cbSize = sizeof(PARAFORMAT2);
1306
1408
  m_pf.dwMask = PFM_ALL;
1307
1409
 
1308
- m_pf.wAlignment = PFA_LEFT;
1410
+ auto &textAlign = windowsTextInputProps().textAlign;
1411
+
1412
+ if (textAlign == facebook::react::TextAlignment::Center) {
1413
+ m_pf.wAlignment = PFA_CENTER;
1414
+ } else if (textAlign == facebook::react::TextAlignment::Right) {
1415
+ m_pf.wAlignment = PFA_RIGHT;
1416
+ } else {
1417
+ m_pf.wAlignment = PFA_LEFT;
1418
+ }
1309
1419
 
1310
1420
  m_pf.cTabCount = 1;
1311
1421
  m_pf.rgxTabs[0] = lDefaultTab;
@@ -1475,6 +1585,9 @@ WindowsTextInputComponentView::createVisual() noexcept {
1475
1585
  winrt::check_hresult(g_pfnCreateTextServices(nullptr, m_textHost.get(), spUnk.put()));
1476
1586
  spUnk.as(m_textServices);
1477
1587
 
1588
+ LRESULT res;
1589
+ winrt::check_hresult(m_textServices->TxSendMessage(EM_SETTEXTMODE, TM_PLAINTEXT, 0, &res));
1590
+
1478
1591
  m_caretVisual = m_compContext.CreateCaretVisual();
1479
1592
  visual.InsertAt(m_caretVisual.InnerVisual(), 0);
1480
1593
  m_caretVisual.IsVisible(false);
@@ -1525,4 +1638,39 @@ void WindowsTextInputComponentView::autoCapitalizeOnUpdateProps(
1525
1638
  }
1526
1639
  }
1527
1640
 
1528
- } // namespace winrt::Microsoft::ReactNative::Composition::implementation
1641
+ void WindowsTextInputComponentView::updateLetterSpacing(float letterSpacing) noexcept {
1642
+ CHARFORMAT2W cf = {};
1643
+ cf.cbSize = sizeof(CHARFORMAT2W);
1644
+ cf.dwMask = CFM_SPACING;
1645
+ cf.sSpacing = static_cast<SHORT>(letterSpacing * 20); // Convert to TWIPS
1646
+
1647
+ LRESULT res;
1648
+
1649
+ // Apply to all existing text like placeholder
1650
+ winrt::check_hresult(m_textServices->TxSendMessage(EM_SETCHARFORMAT, SCF_ALL, reinterpret_cast<LPARAM>(&cf), &res));
1651
+
1652
+ // Apply to future text input
1653
+ winrt::check_hresult(
1654
+ m_textServices->TxSendMessage(EM_SETCHARFORMAT, SCF_SELECTION, reinterpret_cast<LPARAM>(&cf), &res));
1655
+ }
1656
+
1657
+ void WindowsTextInputComponentView::updateAutoCorrect(bool enable) noexcept {
1658
+ LRESULT lresult;
1659
+ winrt::check_hresult(m_textServices->TxSendMessage(
1660
+ EM_SETAUTOCORRECTPROC, enable ? 0 : reinterpret_cast<WPARAM>(AutoCorrectOffCallback), 0, &lresult));
1661
+ }
1662
+
1663
+ void WindowsTextInputComponentView::updateSpellCheck(bool enable) noexcept {
1664
+ LRESULT currentLangOptions;
1665
+ winrt::check_hresult(m_textServices->TxSendMessage(EM_GETLANGOPTIONS, 0, 0, &currentLangOptions));
1666
+
1667
+ DWORD newLangOptions = static_cast<DWORD>(currentLangOptions);
1668
+ if (enable) {
1669
+ newLangOptions |= IMF_SPELLCHECKING;
1670
+ }
1671
+
1672
+ LRESULT lresult;
1673
+ winrt::check_hresult(
1674
+ m_textServices->TxSendMessage(EM_SETLANGOPTIONS, IMF_SPELLCHECKING, enable ? newLangOptions : 0, &lresult));
1675
+ }
1676
+ } // namespace winrt::Microsoft::ReactNative::Composition::implementation
@@ -70,6 +70,7 @@ struct WindowsTextInputComponentView
70
70
  std::optional<std::string> getAccessiblityValue() noexcept override;
71
71
  void setAcccessiblityValue(std::string &&value) noexcept override;
72
72
  bool getAcccessiblityIsReadOnly() noexcept override;
73
+ bool IsDoubleClick();
73
74
 
74
75
  WindowsTextInputComponentView(
75
76
  const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
@@ -110,6 +111,10 @@ struct WindowsTextInputComponentView
110
111
  const std::string &previousCapitalizationType,
111
112
  const std::string &newcapitalizationType) noexcept;
112
113
 
114
+ void updateLetterSpacing(float letterSpacing) noexcept;
115
+ void updateAutoCorrect(bool value) noexcept;
116
+ void updateSpellCheck(bool value) noexcept;
117
+
113
118
  winrt::Windows::UI::Composition::CompositionSurfaceBrush m_brush{nullptr};
114
119
  winrt::Microsoft::ReactNative::Composition::Experimental::ICaretVisual m_caretVisual{nullptr};
115
120
  winrt::Microsoft::ReactNative::Composition::Experimental::IDrawingSurfaceBrush m_drawingSurface{nullptr};
@@ -136,6 +141,7 @@ struct WindowsTextInputComponentView
136
141
  DWORD m_propBitsMask{0};
137
142
  DWORD m_propBits{0};
138
143
  HCURSOR m_hcursor{nullptr};
144
+ std::chrono::steady_clock::time_point m_lastClickTime{};
139
145
  std::vector<facebook::react::CompWindowsTextInputSubmitKeyEventsStruct> m_submitKeyEvents;
140
146
  };
141
147
 
@@ -5,6 +5,8 @@
5
5
 
6
6
  #include "WindowsTextInputEventEmitter.h"
7
7
 
8
+ #include <react/renderer/core/graphicsConversions.h>
9
+
8
10
  namespace facebook::react {
9
11
 
10
12
  void WindowsTextInputEventEmitter::onChange(OnChange event) const {
@@ -46,4 +48,49 @@ void WindowsTextInputEventEmitter::onKeyPress(OnKeyPress event) const {
46
48
  });
47
49
  }
48
50
 
51
+ static jsi::Value textInputMetricsContentSizePayload(
52
+ jsi::Runtime &runtime,
53
+ const WindowsTextInputEventEmitter::OnContentSizeChange &event) {
54
+ auto payload = jsi::Object(runtime);
55
+ {
56
+ auto contentSize = jsi::Object(runtime);
57
+ contentSize.setProperty(runtime, "width", event.contentSize.width);
58
+ contentSize.setProperty(runtime, "height", event.contentSize.height);
59
+ payload.setProperty(runtime, "contentSize", contentSize);
60
+ }
61
+ return payload;
62
+ };
63
+
64
+ void WindowsTextInputEventEmitter::onContentSizeChange(OnContentSizeChange event) const {
65
+ dispatchEvent("textInputContentSizeChange", [event = std::move(event)](jsi::Runtime &runtime) {
66
+ return textInputMetricsContentSizePayload(runtime, event);
67
+ });
68
+ }
69
+
70
+ void WindowsTextInputEventEmitter::onPressIn(PressEvent event) const {
71
+ dispatchEvent("textInputPressIn", [event = std::move(event)](jsi::Runtime &runtime) {
72
+ auto payload = jsi::Object(runtime);
73
+ auto nativeEvent = jsi::Object(runtime);
74
+ nativeEvent.setProperty(runtime, "target", static_cast<double>(event.target));
75
+ nativeEvent.setProperty(runtime, "pageX", event.pagePoint.x);
76
+ nativeEvent.setProperty(runtime, "pageY", event.pagePoint.y);
77
+ nativeEvent.setProperty(runtime, "locationX", event.offsetPoint.x);
78
+ nativeEvent.setProperty(runtime, "locationY", event.offsetPoint.y);
79
+ nativeEvent.setProperty(runtime, "timestamp", event.timestamp);
80
+ nativeEvent.setProperty(runtime, "identifier", static_cast<double>(event.identifier));
81
+ payload.setProperty(runtime, "nativeEvent", nativeEvent);
82
+ return payload;
83
+ });
84
+ }
85
+
86
+ void WindowsTextInputEventEmitter::onEndEditing(OnEndEditing event) const {
87
+ dispatchEvent("textInputEndEditing", [event = std::move(event)](jsi::Runtime &runtime) {
88
+ auto payload = jsi::Object(runtime);
89
+ payload.setProperty(runtime, "eventCount", event.eventCount);
90
+ payload.setProperty(runtime, "target", event.target);
91
+ payload.setProperty(runtime, "text", event.text);
92
+ return payload;
93
+ });
94
+ }
95
+
49
96
  } // namespace facebook::react
@@ -36,10 +36,24 @@ class WindowsTextInputEventEmitter : public ViewEventEmitter {
36
36
  std::string key;
37
37
  };
38
38
 
39
+ struct OnContentSizeChange {
40
+ int target;
41
+ facebook::react::Size contentSize;
42
+ };
43
+
44
+ struct OnEndEditing {
45
+ int eventCount;
46
+ int target;
47
+ std::string text;
48
+ };
49
+
39
50
  void onChange(OnChange value) const;
40
51
  void onSelectionChange(const OnSelectionChange &value) const;
41
52
  void onSubmitEditing(OnSubmitEditing value) const;
42
53
  void onKeyPress(OnKeyPress value) const;
54
+ void onContentSizeChange(OnContentSizeChange value) const;
55
+ void onPressIn(PressEvent event) const override;
56
+ void onEndEditing(OnEndEditing value) const;
43
57
  };
44
58
 
45
- } // namespace facebook::react
59
+ } // namespace facebook::react
@@ -24,6 +24,7 @@ WindowsTextInputProps::WindowsTextInputProps(
24
24
  */
25
25
 
26
26
  allowFontScaling(convertRawProp(context, rawProps, "allowFontScaling", sourceProps.allowFontScaling, {true})),
27
+ autoCorrect(convertRawProp(context, rawProps, "autoCorrect", sourceProps.autoCorrect, {true})),
27
28
  clearTextOnFocus(convertRawProp(context, rawProps, "clearTextOnFocus", sourceProps.clearTextOnFocus, {false})),
28
29
  editable(convertRawProp(context, rawProps, "editable", sourceProps.editable, {true})),
29
30
  maxLength(convertRawProp(context, rawProps, "maxLength", sourceProps.maxLength, {0})),
@@ -36,7 +37,7 @@ WindowsTextInputProps::WindowsTextInputProps(
36
37
  selection(convertRawProp(context, rawProps, "selection", sourceProps.selection, {})),
37
38
  selectionColor(convertRawProp(context, rawProps, "selectionColor", sourceProps.selectionColor, {})),
38
39
  selectTextOnFocus(convertRawProp(context, rawProps, "selectTextOnFocus", sourceProps.selectTextOnFocus, {false})),
39
- spellCheck(convertRawProp(context, rawProps, "spellCheck", sourceProps.spellCheck, {false})),
40
+ spellCheck(convertRawProp(context, rawProps, "spellCheck", sourceProps.spellCheck, {true})),
40
41
  text(convertRawProp(context, rawProps, "text", sourceProps.text, {})),
41
42
  mostRecentEventCount(
42
43
  convertRawProp(context, rawProps, "mostRecentEventCount", sourceProps.mostRecentEventCount, {0})),
@@ -47,7 +48,10 @@ WindowsTextInputProps::WindowsTextInputProps(
47
48
  autoCapitalize(convertRawProp(context, rawProps, "autoCapitalize", sourceProps.autoCapitalize, {})),
48
49
  clearTextOnSubmit(convertRawProp(context, rawProps, "clearTextOnSubmit", sourceProps.clearTextOnSubmit, {false})),
49
50
  submitKeyEvents(convertRawProp(context, rawProps, "submitKeyEvents", sourceProps.submitKeyEvents, {})),
50
- autoFocus(convertRawProp(context, rawProps, "autoFocus", sourceProps.autoFocus, {false})) {}
51
+ autoFocus(convertRawProp(context, rawProps, "autoFocus", sourceProps.autoFocus, {false})),
52
+ textAlign(
53
+ convertRawProp(context, rawProps, "textAlign", sourceProps.textAlign, facebook::react::TextAlignment::Left)) {
54
+ }
51
55
 
52
56
  void WindowsTextInputProps::setProp(
53
57
  const PropsParserContext &context,
@@ -4,6 +4,7 @@
4
4
  #pragma once
5
5
 
6
6
  #include <react/components/rnwcore/Props.h>
7
+ #include <react/renderer/attributedstring/conversions.h>
7
8
  #include <react/renderer/components/text/BaseTextProps.h>
8
9
  #include <react/renderer/core/propsConversions.h>
9
10
 
@@ -96,6 +97,7 @@ class WindowsTextInputProps final : public ViewProps, public BaseTextProps {
96
97
  setProp(const PropsParserContext &context, RawPropsPropNameHash hash, const char *propName, RawValue const &value);
97
98
 
98
99
  bool allowFontScaling{true};
100
+ bool autoCorrect{true};
99
101
  bool clearTextOnFocus{false};
100
102
  bool editable{true};
101
103
  int maxLength{0};
@@ -107,7 +109,7 @@ class WindowsTextInputProps final : public ViewProps, public BaseTextProps {
107
109
  CompWindowsTextInputSelectionStruct selection{};
108
110
  SharedColor selectionColor{};
109
111
  bool selectTextOnFocus{false};
110
- bool spellCheck{false};
112
+ bool spellCheck{true};
111
113
  std::string text{};
112
114
  int mostRecentEventCount{0};
113
115
  bool secureTextEntry{false};
@@ -118,6 +120,7 @@ class WindowsTextInputProps final : public ViewProps, public BaseTextProps {
118
120
  bool clearTextOnSubmit{false};
119
121
  std::vector<CompWindowsTextInputSubmitKeyEventsStruct> submitKeyEvents{};
120
122
  bool autoFocus{false};
123
+ facebook::react::TextAlignment textAlign{};
121
124
  };
122
125
 
123
126
  } // namespace facebook::react
@@ -25,11 +25,10 @@ Size WindowsTextInputShadowNode::measureContent(
25
25
  const LayoutContext &layoutContext,
26
26
  const LayoutConstraints &layoutConstraints) const {
27
27
  if (getStateData().cachedAttributedStringId != 0) {
28
+ facebook::react::ParagraphAttributes paragraphAttributes{};
29
+ paragraphAttributes.maximumNumberOfLines = getConcreteProps().multiline ? 0 : 1;
28
30
  return textLayoutManager_
29
- ->measureCachedSpannableById(
30
- getStateData().cachedAttributedStringId,
31
- {}, // TODO getConcreteProps().paragraphAttributes
32
- layoutConstraints)
31
+ ->measureCachedSpannableById(getStateData().cachedAttributedStringId, paragraphAttributes, layoutConstraints)
33
32
  .size;
34
33
  }
35
34
 
@@ -62,12 +61,11 @@ Size WindowsTextInputShadowNode::measureContent(
62
61
 
63
62
  TextLayoutContext textLayoutContext;
64
63
  textLayoutContext.pointScaleFactor = layoutContext.pointScaleFactor;
64
+
65
+ facebook::react::ParagraphAttributes paragraphAttributes{};
66
+ paragraphAttributes.maximumNumberOfLines = getConcreteProps().multiline ? 0 : 1;
65
67
  return textLayoutManager_
66
- ->measure(
67
- AttributedStringBox{attributedString},
68
- {}, // TODO getConcreteProps().paragraphAttributes,
69
- textLayoutContext,
70
- layoutConstraints)
68
+ ->measure(AttributedStringBox{attributedString}, paragraphAttributes, textLayoutContext, layoutConstraints)
71
69
  .size;
72
70
  }
73
71
 
@@ -51,7 +51,10 @@ class WindowsTextInputShadowNode final : public ConcreteViewShadowNode<
51
51
 
52
52
  void layout(LayoutContext layoutContext) override;
53
53
 
54
- // Float baseline(const LayoutContext& layoutContext, Size size) const override;
54
+ Float baseline(const LayoutContext &layoutContext, Size size) const override {
55
+ // Calculate baseline as 80% of the text height
56
+ return size.height * 0.8f;
57
+ }
55
58
 
56
59
  std::shared_ptr<const TextLayoutManager> textLayoutManager_;
57
60
 
@@ -241,15 +241,20 @@ bool Theme::TryGetPlatformColor(const std::string &platformColor, winrt::Windows
241
241
  {"ButtonForegroundPressed", "TextFillColorSecondary"},
242
242
  {"ButtonForegroundPointerOver", "TextFillColorPrimary"},
243
243
  {"ButtonBackground", "ControlFillColorDefault"},
244
+ {"ButtonBorderBrush", "ButtonBorder"},
244
245
  {"ButtonBorder", "ControlElevationBorder"},
245
246
  {"ControlElevationBorder",
246
247
  "ControlStrokeColorSecondary"}, // TODO ControlElevationBorderBrush is actually gradient brush
247
248
  {"ButtonForeground", "TextFillColorPrimary"},
249
+ {"SolidBackgroundFillColorBaseBrush", "SolidBackgroundFillColorBase"},
248
250
  {"ButtonBackgroundDisabled", "ControlFillColorDisabled"},
251
+ {"ButtonBorderBrushDisabled", "ButtonBorderDisabled"},
249
252
  {"ButtonBorderDisabled", "ControlStrokeColorDefault"},
250
253
  {"ButtonForegroundDisabled", "TextFillColorDisabled"},
251
254
  {"ButtonBackgroundPointerOver", "ControlFillColorSecondary"},
255
+ {"ButtonBorderBrushPointerOver", "ButtonBorderPointerOver"},
252
256
  {"ButtonBorderPointerOver", "ControlElevationBorder"},
257
+ {"ButtonBorderBrushPressed", "ButtonBorderPressed"},
253
258
  {"ButtonBorderPressed", "ControlFillColorTransparent"},
254
259
  {"ToggleSwitchFillOff", "ControlAltFillColorSecondary"},
255
260
  {"ToggleSwitchFillOffPointerOver", "ControlAltFillColorTertiary"},
@@ -10,6 +10,7 @@
10
10
  #include <react/renderer/core/LayoutConstraints.h>
11
11
  #include <react/renderer/textlayoutmanager/TextLayoutManager.h>
12
12
  #include <winrt/Microsoft.ReactNative.Composition.h>
13
+ #include <winrt/Windows.UI.ViewManagement.h>
13
14
  #include "TextDrawing.h"
14
15
  #include "dwmapi.h"
15
16
 
@@ -49,6 +50,8 @@ facebook::react::AttributedStringBox CreateTooltipAttributedString(const std::st
49
50
  auto fragment = facebook::react::AttributedString::Fragment{};
50
51
  fragment.string = tooltip;
51
52
  fragment.textAttributes.fontSize = tooltipFontSize;
53
+ fragment.textAttributes.fontSizeMultiplier =
54
+ static_cast<float>(winrt::Windows::UI::ViewManagement::UISettings().TextScaleFactor());
52
55
  attributedString.appendFragment(std::move(fragment));
53
56
  return facebook::react::AttributedStringBox{attributedString};
54
57
  }
@@ -231,14 +234,13 @@ void TooltipTracker::OnUnmounted(
231
234
  }
232
235
 
233
236
  void TooltipTracker::ShowTooltip(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
234
- auto viewCompView = view.as<winrt::Microsoft::ReactNative::Composition::ViewComponentView>();
235
-
236
- auto selfView =
237
- winrt::get_self<winrt::Microsoft::ReactNative::Composition::implementation::ViewComponentView>(viewCompView);
238
- auto parentHwnd = selfView->GetHwndForParenting();
239
237
  DestroyTimer();
240
238
 
241
239
  if (!m_hwndTip) {
240
+ auto viewCompView = view.as<winrt::Microsoft::ReactNative::Composition::ViewComponentView>();
241
+ auto selfView =
242
+ winrt::get_self<winrt::Microsoft::ReactNative::Composition::implementation::ViewComponentView>(viewCompView);
243
+ auto parentHwnd = selfView->GetHwndForParenting();
242
244
  auto tooltipData = std::make_unique<TooltipData>(view);
243
245
  tooltipData->attributedString = CreateTooltipAttributedString(*selfView->viewProps()->tooltip);
244
246
 
@@ -256,37 +258,39 @@ void TooltipTracker::ShowTooltip(const winrt::Microsoft::ReactNative::ComponentV
256
258
  facebook::react::TextLayoutManager::GetTextLayout(
257
259
  tooltipData->attributedString, {} /*paragraphAttributes*/, layoutConstraints, tooltipData->textLayout);
258
260
 
259
- DWRITE_TEXT_METRICS tm;
260
- winrt::check_hresult(tooltipData->textLayout->GetMetrics(&tm));
261
-
262
- tooltipData->width =
263
- static_cast<int>(tm.width + ((tooltipHorizontalPadding + tooltipHorizontalPadding) * scaleFactor));
264
- tooltipData->height = static_cast<int>(tm.height + ((tooltipTopPadding + tooltipBottomPadding) * scaleFactor));
265
-
266
- POINT pt = {static_cast<LONG>(m_pos.X), static_cast<LONG>(m_pos.Y)};
267
- ClientToScreen(parentHwnd, &pt);
268
-
269
- RegisterTooltipWndClass();
270
- HINSTANCE hInstance = GetModuleHandle(NULL);
271
- m_hwndTip = CreateWindow(
272
- c_tooltipWindowClassName,
273
- L"Tooltip",
274
- WS_POPUP,
275
- pt.x - tooltipData->width / 2,
276
- static_cast<int>(pt.y - tooltipData->height - (toolTipPlacementMargin * scaleFactor)),
277
- tooltipData->width,
278
- tooltipData->height,
279
- parentHwnd,
280
- NULL,
281
- hInstance,
282
- tooltipData.get());
283
-
284
- DWM_WINDOW_CORNER_PREFERENCE preference = DWMWCP_ROUNDSMALL;
285
- UINT borderThickness = 0;
286
- DwmSetWindowAttribute(m_hwndTip, DWMWA_WINDOW_CORNER_PREFERENCE, &preference, sizeof(preference));
287
-
288
- tooltipData.release();
289
- AnimateWindow(m_hwndTip, toolTipAnimationTimeMs, AW_BLEND);
261
+ if (tooltipData->textLayout) {
262
+ DWRITE_TEXT_METRICS tm;
263
+ winrt::check_hresult(tooltipData->textLayout->GetMetrics(&tm));
264
+
265
+ tooltipData->width =
266
+ static_cast<int>((tm.width + tooltipHorizontalPadding + tooltipHorizontalPadding) * scaleFactor);
267
+ tooltipData->height = static_cast<int>((tm.height + tooltipTopPadding + tooltipBottomPadding) * scaleFactor);
268
+
269
+ POINT pt = {static_cast<LONG>(m_pos.X), static_cast<LONG>(m_pos.Y)};
270
+ ClientToScreen(parentHwnd, &pt);
271
+
272
+ RegisterTooltipWndClass();
273
+ HINSTANCE hInstance = GetModuleHandle(NULL);
274
+ m_hwndTip = CreateWindow(
275
+ c_tooltipWindowClassName,
276
+ L"Tooltip",
277
+ WS_POPUP,
278
+ pt.x - tooltipData->width / 2,
279
+ static_cast<int>(pt.y - tooltipData->height - (toolTipPlacementMargin * scaleFactor)),
280
+ tooltipData->width,
281
+ tooltipData->height,
282
+ parentHwnd,
283
+ NULL,
284
+ hInstance,
285
+ tooltipData.get());
286
+
287
+ DWM_WINDOW_CORNER_PREFERENCE preference = DWMWCP_ROUNDSMALL;
288
+ UINT borderThickness = 0;
289
+ DwmSetWindowAttribute(m_hwndTip, DWMWA_WINDOW_CORNER_PREFERENCE, &preference, sizeof(preference));
290
+
291
+ tooltipData.release();
292
+ AnimateWindow(m_hwndTip, toolTipAnimationTimeMs, AW_BLEND);
293
+ }
290
294
  }
291
295
  }
292
296