react-native-windows 0.74.21 → 0.74.22

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 (74) hide show
  1. package/Microsoft.ReactNative/ComponentView.idl +11 -0
  2. package/Microsoft.ReactNative/Composition.Input.idl +1 -0
  3. package/Microsoft.ReactNative/CompositionSwitcher.idl +3 -0
  4. package/Microsoft.ReactNative/Fabric/ComponentView.cpp +18 -8
  5. package/Microsoft.ReactNative/Fabric/ComponentView.h +7 -5
  6. package/Microsoft.ReactNative/Fabric/Composition/Composition.Input.cpp +4 -0
  7. package/Microsoft.ReactNative/Fabric/Composition/Composition.Input.h +1 -0
  8. package/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp +44 -13
  9. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +75 -0
  10. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h +8 -2
  11. package/Microsoft.ReactNative/Fabric/Composition/CompositionHwndHost.cpp +1 -0
  12. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +34 -7
  13. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +3 -2
  14. package/Microsoft.ReactNative/Fabric/Composition/DebuggingOverlayComponentView.cpp +8 -6
  15. package/Microsoft.ReactNative/Fabric/Composition/DebuggingOverlayComponentView.h +1 -2
  16. package/Microsoft.ReactNative/Fabric/Composition/FocusManager.cpp +20 -6
  17. package/Microsoft.ReactNative/Fabric/Composition/FocusManager.h +13 -6
  18. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +2 -3
  19. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h +1 -2
  20. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +80 -55
  21. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +15 -4
  22. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp +37 -8
  23. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h +7 -2
  24. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +14 -7
  25. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +1 -2
  26. package/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.cpp +6 -6
  27. package/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.h +1 -2
  28. package/Microsoft.ReactNative/Fabric/Composition/TextDrawing.cpp +1 -2
  29. package/Microsoft.ReactNative/Fabric/Composition/TextDrawing.h +1 -1
  30. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +104 -152
  31. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +7 -3
  32. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.cpp +14 -11
  33. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.h +4 -4
  34. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputState.cpp +0 -13
  35. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputState.h +0 -3
  36. package/Microsoft.ReactNative/Fabric/Composition/Theme.cpp +12 -4
  37. package/Microsoft.ReactNative/Fabric/Composition/TooltipService.cpp +338 -0
  38. package/Microsoft.ReactNative/Fabric/Composition/TooltipService.h +66 -0
  39. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +37 -4
  40. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h +3 -0
  41. package/Microsoft.ReactNative/Fabric/Composition/UnimplementedNativeViewComponentView.cpp +1 -2
  42. package/Microsoft.ReactNative/Fabric/Composition/UnimplementedNativeViewComponentView.h +1 -2
  43. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp +31 -3
  44. package/Microsoft.ReactNative/Fabric/ReactTaggedView.h +4 -0
  45. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.cpp +5 -0
  46. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.h +1 -1
  47. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewTraitsInitializer.h +1 -1
  48. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.cpp +9 -2
  49. package/Microsoft.ReactNative/IReactViewComponentBuilder.idl +8 -1
  50. package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +1 -1
  51. package/Microsoft.ReactNative/Modules/LogBoxModule.cpp +9 -0
  52. package/Microsoft.ReactNative/Modules/LogBoxModule.h +2 -0
  53. package/Microsoft.ReactNative/Modules/SampleTurboModule.cpp +104 -0
  54. package/Microsoft.ReactNative/Modules/SampleTurboModule.h +78 -0
  55. package/Microsoft.ReactNative/ReactCoreInjection.h +0 -1
  56. package/Microsoft.ReactNative/ReactHost/MsoReactContext.cpp +0 -7
  57. package/Microsoft.ReactNative/ReactHost/MsoReactContext.h +0 -5
  58. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +17 -1
  59. package/Microsoft.ReactNative/ReactInstanceSettingsBuilder.cpp +59 -0
  60. package/Microsoft.ReactNative/ReactInstanceSettingsBuilder.h +23 -0
  61. package/Microsoft.ReactNative/ReactNativeAppBuilder.cpp +179 -0
  62. package/Microsoft.ReactNative/ReactNativeAppBuilder.h +35 -0
  63. package/Microsoft.ReactNative/ReactNativeAppBuilder.idl +69 -0
  64. package/Microsoft.ReactNative/ReactNativeIsland.idl +2 -0
  65. package/Microsoft.ReactNative/ReactNativeWin32App.cpp +82 -0
  66. package/Microsoft.ReactNative/ReactNativeWin32App.h +38 -0
  67. package/Microsoft.ReactNative/Timer.idl +1 -1
  68. package/Microsoft.ReactNative/packages.lock.json +0 -10
  69. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  70. package/Shared/Shared.vcxitems +36 -0
  71. package/Shared/Shared.vcxitems.filters +2 -0
  72. package/Shared/TurboModuleManager.cpp +0 -3
  73. package/package.json +3 -3
  74. package/templates/cpp-app/windows/MyApp/MyApp.cpp +1 -0
@@ -16,7 +16,7 @@
16
16
  namespace winrt::Microsoft::ReactNative::Composition {
17
17
 
18
18
  void RenderText(
19
- ID2D1DeviceContext &deviceContext,
19
+ ID2D1RenderTarget &deviceContext,
20
20
  ::IDWriteTextLayout &textLayout,
21
21
  const facebook::react::AttributedString &attributedString,
22
22
  const facebook::react::TextAttributes &textAttributes,
@@ -26,7 +26,6 @@ void RenderText(
26
26
  float offsetX = offset.x / pointScaleFactor;
27
27
  float offsetY = offset.y / pointScaleFactor;
28
28
 
29
- assert(deviceContext.GetUnitMode() == D2D1_UNIT_MODE_DIPS);
30
29
  const auto dpi = pointScaleFactor * 96.0f;
31
30
  float oldDpiX, oldDpiY;
32
31
  deviceContext.GetDpi(&oldDpiX, &oldDpiY);
@@ -14,7 +14,7 @@
14
14
  namespace winrt::Microsoft::ReactNative::Composition {
15
15
 
16
16
  void RenderText(
17
- ID2D1DeviceContext &deviceContext,
17
+ ID2D1RenderTarget &deviceContext,
18
18
  ::IDWriteTextLayout &textLayout,
19
19
  const facebook::react::AttributedString &attributedString,
20
20
  const facebook::react::TextAttributes &textAttributes,
@@ -176,9 +176,8 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
176
176
  return false;
177
177
  }
178
178
 
179
- m_outer->m_caretVisual.Position(
180
- {x - (m_outer->m_layoutMetrics.frame.origin.x * m_outer->m_layoutMetrics.pointScaleFactor),
181
- y - (m_outer->m_layoutMetrics.frame.origin.y * m_outer->m_layoutMetrics.pointScaleFactor)});
179
+ auto pt = m_outer->getClientOffset();
180
+ m_outer->m_caretVisual.Position({x - pt.x, y - pt.y});
182
181
  return true;
183
182
  }
184
183
 
@@ -225,7 +224,8 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
225
224
  winrt::Microsoft::ReactNative::ComponentView view{nullptr};
226
225
  winrt::check_hresult(
227
226
  m_outer->QueryInterface(winrt::guid_of<winrt::Microsoft::ReactNative::ComponentView>(), winrt::put_abi(view)));
228
- m_outer->rootComponentView()->TrySetFocusedComponent(view);
227
+ m_outer->rootComponentView()->TrySetFocusedComponent(
228
+ view, winrt::Microsoft::ReactNative::FocusNavigationDirection::None);
229
229
  // assert(false);
230
230
  // TODO focus
231
231
  }
@@ -261,7 +261,7 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
261
261
 
262
262
  //@cmember Retrieves the coordinates of a window's client area
263
263
  HRESULT TxGetClientRect(LPRECT prc) override {
264
- *prc = m_outer->m_rcClient;
264
+ *prc = m_outer->getClientRect();
265
265
  return S_OK;
266
266
  }
267
267
 
@@ -454,6 +454,7 @@ facebook::react::AttributedString WindowsTextInputComponentView::getAttributedSt
454
454
  // Use BaseTextShadowNode to get attributed string from children
455
455
 
456
456
  auto childTextAttributes = facebook::react::TextAttributes::defaultTextAttributes();
457
+ childTextAttributes.fontSizeMultiplier = m_fontSizeMultiplier;
457
458
 
458
459
  childTextAttributes.apply(windowsTextInputProps().textAttributes);
459
460
 
@@ -463,9 +464,9 @@ facebook::react::AttributedString WindowsTextInputComponentView::getAttributedSt
463
464
  // BaseTextShadowNode only gets children. We must detect and prepend text
464
465
  // value attributes manually.
465
466
  auto text = GetTextFromRichEdit();
466
- // if (!m_props->text.empty()) {
467
467
  if (!text.empty()) {
468
468
  auto textAttributes = facebook::react::TextAttributes::defaultTextAttributes();
469
+ textAttributes.fontSizeMultiplier = m_fontSizeMultiplier;
469
470
  textAttributes.apply(windowsTextInputProps().textAttributes);
470
471
  auto fragment = facebook::react::AttributedString::Fragment{};
471
472
  fragment.string = text;
@@ -491,66 +492,41 @@ WindowsTextInputComponentView::WindowsTextInputComponentView(
491
492
  compContext,
492
493
  tag,
493
494
  reactContext,
494
- ComponentViewFeatures::Default & ~ComponentViewFeatures::Background) {
495
- /*
496
- m_textChangedRevoker =
497
- m_element.TextChanged(winrt::auto_revoke, [this](auto sender, xaml::Controls::TextChangedEventArgs args) {
498
- auto data = m_state->getData();
499
- data.attributedString = getAttributedString();
500
- data.mostRecentEventCount = m_nativeEventCount;
501
- m_state->updateState(std::move(data));
502
-
503
- if (m_eventEmitter && !m_comingFromJS) {
504
- auto emitter = std::static_pointer_cast<const facebook::react::WindowsTextInputEventEmitter>(m_eventEmitter);
505
- facebook::react::WindowsTextInputEventEmitter::OnChange onChangeArgs;
506
- onChangeArgs.text = winrt::to_string(m_element.Text());
507
- onChangeArgs.eventCount = ++m_nativeEventCount;
508
- emitter->onChange(onChangeArgs);
509
- }
510
- });
511
-
512
- m_SelectionChangedRevoker = m_element.SelectionChanged(winrt::auto_revoke, [this](auto sender, auto args) {
513
- if (m_eventEmitter) {
514
- auto emitter = std::static_pointer_cast<const facebook::react::WindowsTextInputEventEmitter>(m_eventEmitter);
515
- facebook::react::WindowsTextInputEventEmitter::OnSelectionChange onSelectionChangeArgs;
516
- onSelectionChangeArgs.selection.start = m_element.SelectionStart();
517
- onSelectionChangeArgs.selection.end = m_element.SelectionStart() + m_element.SelectionLength();
518
- emitter->onSelectionChange(onSelectionChangeArgs);
519
- }
520
- });
521
- */
522
- }
495
+ ComponentViewFeatures::Default & ~ComponentViewFeatures::Background) {}
523
496
 
524
497
  void WindowsTextInputComponentView::HandleCommand(
525
- winrt::hstring commandName,
526
- const winrt::Microsoft::ReactNative::IJSValueReader &args) noexcept {
498
+ const winrt::Microsoft::ReactNative::HandleCommandArgs &args) noexcept {
499
+ Super::HandleCommand(args);
500
+ if (args.Handled())
501
+ return;
502
+
503
+ auto commandName = args.CommandName();
527
504
  if (commandName == L"setTextAndSelection") {
528
505
  int eventCount, begin, end;
529
- winrt::hstring text;
506
+ std::optional<winrt::hstring> text;
530
507
 
531
- winrt::Microsoft::ReactNative::ReadArgs(args, eventCount, text, begin, end);
508
+ winrt::Microsoft::ReactNative::ReadArgs(args.CommandArgs(), eventCount, text, begin, end);
532
509
  if (eventCount >= m_nativeEventCount) {
533
510
  m_comingFromJS = true;
534
- UpdateText(winrt::to_string(text));
535
-
536
- SELCHANGE sc;
537
- memset(&sc, 0, sizeof(sc));
538
- sc.chrg.cpMin = static_cast<LONG>(begin);
539
- sc.chrg.cpMax = static_cast<LONG>(end);
540
- sc.seltyp = (begin == end) ? SEL_EMPTY : SEL_TEXT;
541
-
542
- LRESULT res;
543
- /*
544
- winrt::check_hresult(m_textServices->TxSendMessage(
545
- EM_SELCHANGE, 0 , reinterpret_cast<WPARAM>(&sc), &res));
546
- */
547
- winrt::check_hresult(
548
- m_textServices->TxSendMessage(EM_SETSEL, static_cast<WPARAM>(begin), static_cast<LPARAM>(end), &res));
511
+ {
512
+ if (text.has_value()) {
513
+ DrawBlock db(*this);
514
+ UpdateText(winrt::to_string(text.value()));
515
+ }
516
+
517
+ SELCHANGE sc;
518
+ memset(&sc, 0, sizeof(sc));
519
+ sc.chrg.cpMin = static_cast<LONG>(begin);
520
+ sc.chrg.cpMax = static_cast<LONG>(end);
521
+ sc.seltyp = (begin == end) ? SEL_EMPTY : SEL_TEXT;
522
+
523
+ LRESULT res;
524
+ winrt::check_hresult(
525
+ m_textServices->TxSendMessage(EM_SETSEL, static_cast<WPARAM>(begin), static_cast<LPARAM>(end), &res));
526
+ }
549
527
 
550
528
  m_comingFromJS = false;
551
529
  }
552
- } else {
553
- Super::HandleCommand(commandName, args);
554
530
  }
555
531
  }
556
532
 
@@ -948,6 +924,10 @@ void WindowsTextInputComponentView::onGotFocus(
948
924
  LRESULT lresult;
949
925
  DrawBlock db(*this);
950
926
  m_textServices->TxSendMessage(WM_SETFOCUS, 0, 0, &lresult);
927
+
928
+ if (windowsTextInputProps().clearTextOnFocus) {
929
+ m_textServices->TxSetText(L"");
930
+ }
951
931
  }
952
932
  }
953
933
 
@@ -982,37 +962,35 @@ void WindowsTextInputComponentView::updateProps(
982
962
  *std::static_pointer_cast<const facebook::react::WindowsTextInputProps>(oldProps ? oldProps : viewProps());
983
963
  const auto &newTextInputProps = *std::static_pointer_cast<const facebook::react::WindowsTextInputProps>(props);
984
964
 
985
- DWORD propBitsMask = 0;
986
- DWORD propBits = 0;
987
-
988
965
  Super::updateProps(props, oldProps);
989
966
 
990
967
  if (!facebook::react::floatEquality(
991
968
  oldTextInputProps.textAttributes.fontSize, newTextInputProps.textAttributes.fontSize) ||
969
+ (oldTextInputProps.textAttributes.allowFontScaling != newTextInputProps.textAttributes.allowFontScaling) ||
992
970
  oldTextInputProps.textAttributes.fontWeight != newTextInputProps.textAttributes.fontWeight) {
993
- propBitsMask |= TXTBIT_CHARFORMATCHANGE;
994
- propBits |= TXTBIT_CHARFORMATCHANGE;
971
+ m_propBitsMask |= TXTBIT_CHARFORMATCHANGE;
972
+ m_propBits |= TXTBIT_CHARFORMATCHANGE;
995
973
  }
996
974
 
997
975
  if (oldTextInputProps.secureTextEntry != newTextInputProps.secureTextEntry) {
998
- propBitsMask |= TXTBIT_USEPASSWORD;
976
+ m_propBitsMask |= TXTBIT_USEPASSWORD;
999
977
  if (newTextInputProps.secureTextEntry) {
1000
- propBits |= TXTBIT_USEPASSWORD;
978
+ m_propBits |= TXTBIT_USEPASSWORD;
1001
979
  }
1002
980
  }
1003
981
 
1004
982
  if (oldTextInputProps.multiline != newTextInputProps.multiline) {
1005
983
  m_multiline = newTextInputProps.multiline;
1006
- propBitsMask |= TXTBIT_MULTILINE | TXTBIT_WORDWRAP;
984
+ m_propBitsMask |= TXTBIT_MULTILINE | TXTBIT_WORDWRAP;
1007
985
  if (newTextInputProps.multiline) {
1008
- propBits |= TXTBIT_MULTILINE | TXTBIT_WORDWRAP;
986
+ m_propBits |= TXTBIT_MULTILINE | TXTBIT_WORDWRAP;
1009
987
  }
1010
988
  }
1011
989
 
1012
990
  if (oldTextInputProps.editable != newTextInputProps.editable) {
1013
- propBitsMask |= TXTBIT_READONLY;
991
+ m_propBitsMask |= TXTBIT_READONLY;
1014
992
  if (!newTextInputProps.editable) {
1015
- propBits |= TXTBIT_READONLY;
993
+ m_propBits |= TXTBIT_READONLY;
1016
994
  }
1017
995
  }
1018
996
 
@@ -1044,62 +1022,7 @@ void WindowsTextInputComponentView::updateProps(
1044
1022
  m_submitKeyEvents.clear();
1045
1023
  }
1046
1024
 
1047
- /*
1048
- if (oldTextInputProps.textAttributes.foregroundColor != newTextInputProps.textAttributes.foregroundColor) {
1049
- if (newTextInputProps.textAttributes.foregroundColor)
1050
- m_element.Foreground(newTextInputProps.textAttributes.foregroundColor.AsWindowsBrush());
1051
- else
1052
- m_element.ClearValue(::xaml::Controls::TextBlock::ForegroundProperty());
1053
- }
1054
-
1055
- if (oldTextInputProps.textAttributes.fontStyle != newTextInputProps.textAttributes.fontStyle) {
1056
- switch (newTextInputProps.textAttributes.fontStyle.value_or(facebook::react::FontStyle::Normal)) {
1057
- case facebook::react::FontStyle::Italic:
1058
- m_element.FontStyle(winrt::Windows::UI::Text::FontStyle::Italic);
1059
- break;
1060
- case facebook::react::FontStyle::Normal:
1061
- m_element.FontStyle(winrt::Windows::UI::Text::FontStyle::Normal);
1062
- break;
1063
- case facebook::react::FontStyle::Oblique:
1064
- m_element.FontStyle(winrt::Windows::UI::Text::FontStyle::Oblique);
1065
- break;
1066
- default:
1067
- assert(false);
1068
- }
1069
- }
1070
-
1071
- if (oldTextInputProps.textAttributes.fontFamily != newTextInputProps.textAttributes.fontFamily) {
1072
- if (newTextInputProps.textAttributes.fontFamily.empty())
1073
- m_element.FontFamily(xaml::Media::FontFamily(L"Segoe UI"));
1074
- else
1075
- m_element.FontFamily(xaml::Media::FontFamily(
1076
- Microsoft::Common::Unicode::Utf8ToUtf16(newTextInputProps.textAttributes.fontFamily)));
1077
- }
1078
-
1079
- if (oldTextInputProps.allowFontScaling != newTextInputProps.allowFontScaling) {
1080
- m_element.IsTextScaleFactorEnabled(newTextInputProps.allowFontScaling);
1081
- }
1082
-
1083
- if (oldTextInputProps.selection.start != newTextInputProps.selection.start ||
1084
- oldTextInputProps.selection.end != newTextInputProps.selection.end) {
1085
- m_element.Select(
1086
- newTextInputProps.selection.start, newTextInputProps.selection.end - newTextInputProps.selection.start);
1087
- }
1088
-
1089
- if (oldTextInputProps.autoCapitalize != newTextInputProps.autoCapitalize) {
1090
- if (newTextInputProps.autoCapitalize == "characters") {
1091
- m_element.CharacterCasing(xaml::Controls::CharacterCasing::Upper);
1092
- } else { // anything else turns off autoCap (should be "None" but
1093
- // we don't support "words"/"sentences" yet)
1094
- m_element.CharacterCasing(xaml::Controls::CharacterCasing::Normal);
1095
- }
1096
- }
1097
- */
1098
-
1099
- if (propBitsMask != 0) {
1100
- DrawBlock db(*this);
1101
- winrt::check_hresult(m_textServices->OnTxPropertyBitsChange(propBitsMask, propBits));
1102
- }
1025
+ UpdatePropertyBits();
1103
1026
  }
1104
1027
 
1105
1028
  void WindowsTextInputComponentView::updateState(
@@ -1109,32 +1032,26 @@ void WindowsTextInputComponentView::updateState(
1109
1032
 
1110
1033
  if (!m_state) {
1111
1034
  assert(false && "State is `null` for <TextInput> component.");
1112
- // m_element.Text(L"");
1113
1035
  return;
1114
1036
  }
1115
1037
 
1116
- auto data = m_state->getData();
1117
-
1118
1038
  if (!oldState) {
1119
1039
  m_mostRecentEventCount = m_state->getData().mostRecentEventCount;
1120
1040
  }
1121
1041
 
1042
+ if (auto root = rootComponentView()) {
1043
+ auto fontSizeMultiplier = root->FontSizeMultiplier();
1044
+ if (fontSizeMultiplier != m_fontSizeMultiplier) {
1045
+ fontSizeMultiplier = m_fontSizeMultiplier;
1046
+ m_propBitsMask |= TXTBIT_CHARFORMATCHANGE;
1047
+ m_propBits |= TXTBIT_CHARFORMATCHANGE;
1048
+ }
1049
+ }
1050
+
1122
1051
  if (m_mostRecentEventCount == m_state->getData().mostRecentEventCount) {
1123
1052
  m_comingFromState = true;
1124
- // Only handle single/empty fragments right now -- ignore the other fragments
1125
-
1126
- LRESULT res;
1127
- CHARRANGE cr;
1128
- cr.cpMin = cr.cpMax = 0;
1129
- winrt::check_hresult(m_textServices->TxSendMessage(EM_EXGETSEL, 0, reinterpret_cast<LPARAM>(&cr), &res));
1130
-
1131
- UpdateText(
1132
- m_state->getData().attributedString.getFragments().size()
1133
- ? m_state->getData().attributedString.getFragments()[0].string
1134
- : "");
1135
-
1136
- winrt::check_hresult(
1137
- m_textServices->TxSendMessage(EM_SETSEL, static_cast<WPARAM>(cr.cpMin), static_cast<LPARAM>(cr.cpMax), &res));
1053
+ auto &fragments = m_state->getData().attributedString.getFragments();
1054
+ UpdateText(fragments.size() ? fragments[0].string : "");
1138
1055
 
1139
1056
  m_comingFromState = false;
1140
1057
  }
@@ -1154,7 +1071,8 @@ void WindowsTextInputComponentView::UpdateText(const std::string &str) noexcept
1154
1071
  winrt::check_hresult(m_textServices->TxSendMessage(
1155
1072
  EM_SETTEXTEX, reinterpret_cast<WPARAM>(&stt), reinterpret_cast<LPARAM>(str.c_str()), &res));
1156
1073
 
1157
- winrt::check_hresult(m_textServices->TxSendMessage(EM_EXGETSEL, 0, reinterpret_cast<LPARAM>(&cr), &res));
1074
+ winrt::check_hresult(
1075
+ m_textServices->TxSendMessage(EM_SETSEL, static_cast<WPARAM>(cr.cpMin), static_cast<LPARAM>(cr.cpMax), &res));
1158
1076
 
1159
1077
  // enable colored emojis
1160
1078
  winrt::check_hresult(
@@ -1217,7 +1135,7 @@ void WindowsTextInputComponentView::OnTextUpdated() noexcept {
1217
1135
  }
1218
1136
 
1219
1137
  void WindowsTextInputComponentView::OnSelectionChanged(LONG start, LONG end) noexcept {
1220
- if (m_eventEmitter /* && !m_comingFromJS ?? */) {
1138
+ if (m_eventEmitter && !m_comingFromState /* && !m_comingFromJS ?? */) {
1221
1139
  auto emitter = std::static_pointer_cast<const facebook::react::WindowsTextInputEventEmitter>(m_eventEmitter);
1222
1140
  facebook::react::WindowsTextInputEventEmitter::OnSelectionChange onSelectionChangeArgs;
1223
1141
  onSelectionChangeArgs.selection.start = start;
@@ -1248,10 +1166,39 @@ std::string WindowsTextInputComponentView::GetTextFromRichEdit() const noexcept
1248
1166
  void WindowsTextInputComponentView::FinalizeUpdates(
1249
1167
  winrt::Microsoft::ReactNative::ComponentViewUpdateMask updateMask) noexcept {
1250
1168
  Super::FinalizeUpdates(updateMask);
1251
- ensureDrawingSurface();
1252
- if (m_needsRedraw) {
1253
- DrawText();
1169
+ InternalFinalize();
1170
+ }
1171
+
1172
+ void WindowsTextInputComponentView::UpdatePropertyBits() noexcept {
1173
+ if (m_propBitsMask != 0) {
1174
+ DrawBlock db(*this);
1175
+ winrt::check_hresult(m_textServices->OnTxPropertyBitsChange(m_propBitsMask, m_propBits));
1176
+ m_propBitsMask = 0;
1177
+ m_propBits = 0;
1178
+ }
1179
+ }
1180
+
1181
+ void WindowsTextInputComponentView::InternalFinalize() noexcept {
1182
+ if (m_mounted) {
1183
+ UpdatePropertyBits();
1184
+
1185
+ ensureDrawingSurface();
1186
+ if (m_needsRedraw) {
1187
+ DrawText();
1188
+ }
1189
+ }
1190
+ }
1191
+
1192
+ void WindowsTextInputComponentView::onMounted() noexcept {
1193
+ Super::onMounted();
1194
+
1195
+ auto fontSizeMultiplier = rootComponentView()->FontSizeMultiplier();
1196
+ if (m_fontSizeMultiplier != fontSizeMultiplier) {
1197
+ m_fontSizeMultiplier = fontSizeMultiplier;
1198
+ m_propBitsMask |= TXTBIT_CHARFORMATCHANGE;
1199
+ m_propBits |= TXTBIT_CHARFORMATCHANGE;
1254
1200
  }
1201
+ InternalFinalize();
1255
1202
  }
1256
1203
 
1257
1204
  std::optional<std::string> WindowsTextInputComponentView::getAcccessiblityValue() noexcept {
@@ -1296,9 +1243,9 @@ void WindowsTextInputComponentView::UpdateCharFormat() noexcept {
1296
1243
 
1297
1244
  // set font size -- 15 to convert twips to pt
1298
1245
  const auto &props = windowsTextInputProps();
1299
- float fontSize = props.textAttributes.fontSize;
1300
- if (std::isnan(fontSize))
1301
- fontSize = facebook::react::TextAttributes::defaultTextAttributes().fontSize;
1246
+ float fontSize = m_fontSizeMultiplier *
1247
+ (std::isnan(props.textAttributes.fontSize) ? facebook::react::TextAttributes::defaultTextAttributes().fontSize
1248
+ : props.textAttributes.fontSize);
1302
1249
  // TODO get fontSize from props.textAttributes, or defaultTextAttributes, or fragment?
1303
1250
  cfNew.dwMask |= CFM_SIZE;
1304
1251
  cfNew.yHeight = static_cast<LONG>(fontSize * 15);
@@ -1365,8 +1312,8 @@ void WindowsTextInputComponentView::ensureDrawingSurface() noexcept {
1365
1312
  winrt::Windows::Graphics::DirectX::DirectXPixelFormat::B8G8R8A8UIntNormalized,
1366
1313
  winrt::Windows::Graphics::DirectX::DirectXAlphaMode::Premultiplied);
1367
1314
 
1368
- m_rcClient = getClientRect();
1369
- winrt::check_hresult(m_textServices->OnTxInPlaceActivate(&m_rcClient));
1315
+ auto rc = getClientRect();
1316
+ winrt::check_hresult(m_textServices->OnTxInPlaceActivate(&rc));
1370
1317
 
1371
1318
  LRESULT lresult;
1372
1319
  winrt::check_hresult(
@@ -1396,6 +1343,7 @@ winrt::com_ptr<::IDWriteTextLayout> WindowsTextInputComponentView::CreatePlaceho
1396
1343
  if (std::isnan(props.textAttributes.fontSize)) {
1397
1344
  textAttributes.fontSize = 12.0f;
1398
1345
  }
1346
+ textAttributes.fontSizeMultiplier = m_fontSizeMultiplier;
1399
1347
  fragment1.string = props.placeholder;
1400
1348
  fragment1.textAttributes = textAttributes;
1401
1349
  attributedString.appendFragment(fragment1);
@@ -1445,7 +1393,11 @@ void WindowsTextInputComponentView::DrawText() noexcept {
1445
1393
  static_cast<LONG>(offset.x) + static_cast<LONG>(m_imgWidth),
1446
1394
  static_cast<LONG>(offset.y) + static_cast<LONG>(m_imgHeight)};
1447
1395
 
1448
- winrt::check_hresult(m_textServices->OnTxInPlaceActivate(&rcClient));
1396
+ {
1397
+ m_cDrawBlock++; // Dont use AutoDrawBlock as we are already in draw, and dont need to draw again.
1398
+ winrt::check_hresult(m_textServices->OnTxInPlaceActivate(&rcClient));
1399
+ m_cDrawBlock--;
1400
+ }
1449
1401
 
1450
1402
  const auto &props = windowsTextInputProps();
1451
1403
  if (facebook::react::isColorMeaningful(props.backgroundColor)) {
@@ -1524,4 +1476,4 @@ winrt::Microsoft::ReactNative::ComponentView WindowsTextInputComponentView::Crea
1524
1476
  return winrt::make<WindowsTextInputComponentView>(compContext, tag, reactContext);
1525
1477
  }
1526
1478
 
1527
- } // namespace winrt::Microsoft::ReactNative::Composition::implementation
1479
+ } // namespace winrt::Microsoft::ReactNative::Composition::implementation
@@ -46,8 +46,7 @@ struct WindowsTextInputComponentView
46
46
  void FinalizeUpdates(winrt::Microsoft::ReactNative::ComponentViewUpdateMask updateMask) noexcept override;
47
47
  static facebook::react::SharedViewProps defaultProps() noexcept;
48
48
  const facebook::react::WindowsTextInputProps &windowsTextInputProps() const noexcept;
49
- void HandleCommand(winrt::hstring commandName, const winrt::Microsoft::ReactNative::IJSValueReader &args) noexcept
50
- override;
49
+ void HandleCommand(const winrt::Microsoft::ReactNative::HandleCommandArgs &args) noexcept override;
51
50
  void OnRenderingDeviceLost() noexcept override;
52
51
  void onLostFocus(const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept override;
53
52
  void onGotFocus(const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept override;
@@ -66,6 +65,7 @@ struct WindowsTextInputComponentView
66
65
  void OnKeyUp(const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept override;
67
66
  void OnCharacterReceived(const winrt::Microsoft::ReactNative::Composition::Input::CharacterReceivedRoutedEventArgs
68
67
  &args) noexcept override;
68
+ void onMounted() noexcept override;
69
69
 
70
70
  std::optional<std::string> getAcccessiblityValue() noexcept override;
71
71
  void setAcccessiblityValue(std::string &&value) noexcept override;
@@ -101,6 +101,8 @@ struct WindowsTextInputComponentView
101
101
  const facebook::react::SharedColor &foregroundColor) noexcept;
102
102
  bool ShouldSubmit(
103
103
  const winrt::Microsoft::ReactNative::Composition::Input::CharacterReceivedRoutedEventArgs &args) noexcept;
104
+ void InternalFinalize() noexcept;
105
+ void UpdatePropertyBits() noexcept;
104
106
 
105
107
  winrt::Windows::UI::Composition::CompositionSurfaceBrush m_brush{nullptr};
106
108
  winrt::Microsoft::ReactNative::Composition::Experimental::ICaretVisual m_caretVisual{nullptr};
@@ -114,7 +116,7 @@ struct WindowsTextInputComponentView
114
116
  winrt::com_ptr<ITextServices2> m_textServices;
115
117
  unsigned int m_imgWidth{0}, m_imgHeight{0};
116
118
  std::shared_ptr<facebook::react::WindowsTextInputShadowNode::ConcreteState const> m_state;
117
- RECT m_rcClient;
119
+ float m_fontSizeMultiplier{1.0};
118
120
  int64_t m_mostRecentEventCount{0};
119
121
  int m_nativeEventCount{0};
120
122
  bool m_comingFromJS{false};
@@ -124,6 +126,8 @@ struct WindowsTextInputComponentView
124
126
  bool m_drawing{false};
125
127
  bool m_clearTextOnSubmit{false};
126
128
  bool m_multiline{false};
129
+ DWORD m_propBitsMask{0};
130
+ DWORD m_propBits{0};
127
131
  std::vector<facebook::react::CompWindowsTextInputSubmitKeyEventsStruct> m_submitKeyEvents;
128
132
  };
129
133
 
@@ -23,10 +23,11 @@ void WindowsTextInputShadowNode::setContextContainer(ContextContainer *contextCo
23
23
  m_contextContainer = contextContainer;
24
24
  }
25
25
 
26
- AttributedString WindowsTextInputShadowNode::getAttributedString() const {
26
+ AttributedString WindowsTextInputShadowNode::getAttributedString(const LayoutContext &layoutContext) const {
27
27
  // Use BaseTextShadowNode to get attributed string from children
28
28
 
29
29
  auto childTextAttributes = TextAttributes::defaultTextAttributes();
30
+ childTextAttributes.fontSizeMultiplier = layoutContext.fontSizeMultiplier;
30
31
 
31
32
  childTextAttributes.apply(getConcreteProps().textAttributes);
32
33
 
@@ -38,6 +39,7 @@ AttributedString WindowsTextInputShadowNode::getAttributedString() const {
38
39
  // value attributes manually.
39
40
  if (!getConcreteProps().text.empty()) {
40
41
  auto textAttributes = TextAttributes::defaultTextAttributes();
42
+ textAttributes.fontSizeMultiplier = layoutContext.fontSizeMultiplier;
41
43
  textAttributes.apply(getConcreteProps().textAttributes);
42
44
  auto fragment = AttributedString::Fragment{};
43
45
  fragment.string = getConcreteProps().text;
@@ -59,7 +61,7 @@ AttributedString WindowsTextInputShadowNode::getAttributedString() const {
59
61
  // display at all.
60
62
  // TODO T67606511: We will redefine the measurement of empty strings as part
61
63
  // of T67606511
62
- AttributedString WindowsTextInputShadowNode::getPlaceholderAttributedString() const {
64
+ AttributedString WindowsTextInputShadowNode::getPlaceholderAttributedString(const LayoutContext &layoutContext) const {
63
65
  // Return placeholder text, since text and children are empty.
64
66
  auto textAttributedString = AttributedString{};
65
67
  auto fragment = AttributedString::Fragment{};
@@ -70,6 +72,7 @@ AttributedString WindowsTextInputShadowNode::getPlaceholderAttributedString() co
70
72
  }
71
73
 
72
74
  auto textAttributes = TextAttributes::defaultTextAttributes();
75
+ textAttributes.fontSizeMultiplier = layoutContext.fontSizeMultiplier;
73
76
  textAttributes.apply(getConcreteProps().textAttributes);
74
77
 
75
78
  // If there's no text, it's possible that this Fragment isn't actually
@@ -86,10 +89,10 @@ void WindowsTextInputShadowNode::setTextLayoutManager(SharedTextLayoutManager te
86
89
  m_textLayoutManager = std::move(textLayoutManager);
87
90
  }
88
91
 
89
- AttributedString WindowsTextInputShadowNode::getMostRecentAttributedString() const {
92
+ AttributedString WindowsTextInputShadowNode::getMostRecentAttributedString(const LayoutContext &layoutContext) const {
90
93
  const auto &state = getStateData();
91
94
 
92
- auto reactTreeAttributedString = getAttributedString();
95
+ auto reactTreeAttributedString = getAttributedString(layoutContext);
93
96
 
94
97
  // Sometimes the treeAttributedString will only differ from the state
95
98
  // not by inherent properties (string or prop attributes), but by the frame of
@@ -101,10 +104,10 @@ AttributedString WindowsTextInputShadowNode::getMostRecentAttributedString() con
101
104
  return (!treeAttributedStringChanged ? state.attributedString : reactTreeAttributedString);
102
105
  }
103
106
 
104
- void WindowsTextInputShadowNode::updateStateIfNeeded() {
107
+ void WindowsTextInputShadowNode::updateStateIfNeeded(const LayoutContext &layoutContext) {
105
108
  ensureUnsealed();
106
109
 
107
- auto reactTreeAttributedString = getAttributedString();
110
+ auto reactTreeAttributedString = getAttributedString(layoutContext);
108
111
  const auto &state = getStateData();
109
112
 
110
113
  // Tree is often out of sync with the value of the TextInput.
@@ -125,13 +128,13 @@ void WindowsTextInputShadowNode::updateStateIfNeeded() {
125
128
  // in the AttributedString, and when State is updated, it needs some way to
126
129
  // reconstruct a Fragment with default TextAttributes.
127
130
  auto defaultTextAttributes = TextAttributes::defaultTextAttributes();
128
-
131
+ defaultTextAttributes.fontSizeMultiplier = layoutContext.fontSizeMultiplier;
129
132
  defaultTextAttributes.apply(getConcreteProps().textAttributes);
130
133
 
131
134
  auto newEventCount = state.reactTreeAttributedString.isContentEqual(reactTreeAttributedString)
132
135
  ? 0
133
136
  : getConcreteProps().mostRecentEventCount;
134
- auto newAttributedString = getMostRecentAttributedString();
137
+ auto newAttributedString = getMostRecentAttributedString(layoutContext);
135
138
 
136
139
  // Even if we're here and updating state, it may be only to update the layout
137
140
  // manager If that is the case, make sure we don't update text: pass in the
@@ -168,10 +171,10 @@ Size WindowsTextInputShadowNode::measureContent(
168
171
  // during layout, but not during `measure`. If State is out-of-date in layout,
169
172
  // it's too late: measure will have already operated on old State. Thus, we
170
173
  // use the same value here that we *will* use in layout to update the state.
171
- AttributedString attributedString = getMostRecentAttributedString();
174
+ AttributedString attributedString = getMostRecentAttributedString(layoutContext);
172
175
 
173
176
  if (attributedString.isEmpty()) {
174
- attributedString = getPlaceholderAttributedString();
177
+ attributedString = getPlaceholderAttributedString(layoutContext);
175
178
  }
176
179
 
177
180
  if (attributedString.isEmpty() && getStateData().mostRecentEventCount != 0) {
@@ -191,7 +194,7 @@ Size WindowsTextInputShadowNode::measureContent(
191
194
  }
192
195
 
193
196
  void WindowsTextInputShadowNode::layout(LayoutContext layoutContext) {
194
- updateStateIfNeeded();
197
+ updateStateIfNeeded(layoutContext);
195
198
  ConcreteViewShadowNode::layout(layoutContext);
196
199
  }
197
200
 
@@ -41,8 +41,8 @@ class WindowsTextInputShadowNode final : public ConcreteViewShadowNode<
41
41
  /*
42
42
  * Returns a `AttributedString` which represents text content of the node.
43
43
  */
44
- AttributedString getAttributedString() const;
45
- AttributedString getPlaceholderAttributedString() const;
44
+ AttributedString getAttributedString(const LayoutContext &layoutContext) const;
45
+ AttributedString getPlaceholderAttributedString(const LayoutContext &layoutContext) const;
46
46
 
47
47
  /*
48
48
  * Associates a shared TextLayoutManager with the node.
@@ -62,13 +62,13 @@ class WindowsTextInputShadowNode final : public ConcreteViewShadowNode<
62
62
  /**
63
63
  * Get the most up-to-date attributed string for measurement and State.
64
64
  */
65
- AttributedString getMostRecentAttributedString() const;
65
+ AttributedString getMostRecentAttributedString(const LayoutContext &layoutContext) const;
66
66
 
67
67
  /*
68
68
  * Creates a `State` object (with `AttributedText` and
69
69
  * `TextLayoutManager`) if needed.
70
70
  */
71
- void updateStateIfNeeded();
71
+ void updateStateIfNeeded(const LayoutContext &layoutContext);
72
72
 
73
73
  SharedTextLayoutManager m_textLayoutManager;
74
74
 
@@ -31,17 +31,4 @@ WindowsTextInputState::WindowsTextInputState(
31
31
  defaultThemePaddingTop(defaultThemePaddingTop),
32
32
  defaultThemePaddingBottom(defaultThemePaddingBottom) {}
33
33
 
34
- WindowsTextInputState::WindowsTextInputState(const WindowsTextInputState &previousState, const folly::dynamic &data)
35
- : mostRecentEventCount(data.getDefault("mostRecentEventCount", previousState.mostRecentEventCount).getInt()),
36
- cachedAttributedStringId(data.getDefault("opaqueCacheId", previousState.cachedAttributedStringId).getInt()),
37
- attributedString(previousState.attributedString),
38
- reactTreeAttributedString(previousState.reactTreeAttributedString),
39
- paragraphAttributes(previousState.paragraphAttributes),
40
- defaultThemePaddingStart(
41
- data.getDefault("themePaddingStart", previousState.defaultThemePaddingStart).getDouble()),
42
- defaultThemePaddingEnd(data.getDefault("themePaddingEnd", previousState.defaultThemePaddingEnd).getDouble()),
43
- defaultThemePaddingTop(data.getDefault("themePaddingTop", previousState.defaultThemePaddingTop).getDouble()),
44
- defaultThemePaddingBottom(
45
- data.getDefault("themePaddingBottom", previousState.defaultThemePaddingBottom).getDouble()){};
46
-
47
34
  } // namespace facebook::react
@@ -66,9 +66,6 @@ class WindowsTextInputState final {
66
66
  double defaultThemePaddingBottom);
67
67
 
68
68
  WindowsTextInputState() = default;
69
- WindowsTextInputState(const WindowsTextInputState &previousState, const folly::dynamic &data);
70
- folly::dynamic getDynamic() const;
71
- MapBuffer getMapBuffer() const;
72
69
  };
73
70
 
74
71
  } // namespace facebook::react