react-native-windows 0.81.5 → 0.81.6

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.
@@ -246,6 +246,8 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
246
246
  //@cmember Converts screen coordinates of a specified point to the client coordinates
247
247
  BOOL TxScreenToClient(LPPOINT lppt) override {
248
248
  winrt::Windows::Foundation::Point pt{static_cast<float>(lppt->x), static_cast<float>(lppt->y)};
249
+ pt.X -= m_outer->m_contentOffsetPx.x;
250
+ pt.Y -= m_outer->m_contentOffsetPx.y;
249
251
  auto localpt = m_outer->ScreenToLocal(pt);
250
252
  lppt->x = static_cast<LONG>(localpt.X);
251
253
  lppt->y = static_cast<LONG>(localpt.Y);
@@ -255,9 +257,14 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
255
257
  //@cmember Converts the client coordinates of a specified point to screen coordinates
256
258
  BOOL TxClientToScreen(LPPOINT lppt) override {
257
259
  winrt::Windows::Foundation::Point pt{static_cast<float>(lppt->x), static_cast<float>(lppt->y)};
260
+
261
+ if (!m_outer->m_parent) {
262
+ return false;
263
+ }
264
+
258
265
  auto screenpt = m_outer->LocalToScreen(pt);
259
- lppt->x = static_cast<LONG>(screenpt.X);
260
- lppt->y = static_cast<LONG>(screenpt.Y);
266
+ lppt->x = static_cast<LONG>(screenpt.X) + m_outer->m_contentOffsetPx.x;
267
+ lppt->y = static_cast<LONG>(screenpt.Y) + m_outer->m_contentOffsetPx.y;
261
268
  return true;
262
269
  }
263
270
 
@@ -276,20 +283,25 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
276
283
  //@cmember Retrieves the coordinates of a window's client area
277
284
  HRESULT TxGetClientRect(LPRECT prc) override {
278
285
  *prc = m_outer->getClientRect();
286
+
287
+ prc->top += m_outer->m_contentOffsetPx.y;
288
+ prc->bottom += m_outer->m_contentOffsetPx.y -
289
+ static_cast<LONG>(m_outer->m_layoutMetrics.contentInsets.bottom * m_outer->m_layoutMetrics.pointScaleFactor);
290
+ prc->left += m_outer->m_contentOffsetPx.x;
291
+ prc->right += m_outer->m_contentOffsetPx.x -
292
+ static_cast<LONG>(m_outer->m_layoutMetrics.contentInsets.right * m_outer->m_layoutMetrics.pointScaleFactor);
293
+
279
294
  return S_OK;
280
295
  }
281
296
 
282
297
  //@cmember Get the view rectangle relative to the inset
283
298
  HRESULT TxGetViewInset(LPRECT prc) override {
284
299
  // Inset is in HIMETRIC
285
- constexpr float HmPerInchF = 2540.0f;
286
- constexpr float PointsPerInch = 96.0f;
287
- constexpr float dipToHm = HmPerInchF / PointsPerInch;
288
300
 
289
- prc->left = static_cast<LONG>(m_outer->m_layoutMetrics.contentInsets.left * dipToHm);
290
- prc->top = static_cast<LONG>(m_outer->m_layoutMetrics.contentInsets.top * dipToHm);
291
- prc->bottom = static_cast<LONG>(m_outer->m_layoutMetrics.contentInsets.bottom * dipToHm);
292
- prc->right = static_cast<LONG>(m_outer->m_layoutMetrics.contentInsets.right * dipToHm);
301
+ prc->left = 0;
302
+ prc->top = 0;
303
+ prc->bottom = 0;
304
+ prc->right = 0;
293
305
 
294
306
  return NOERROR;
295
307
  }
@@ -492,11 +504,6 @@ AutoCorrectOffCallback(LANGID langid, const WCHAR *pszBefore, WCHAR *pszAfter, L
492
504
  facebook::react::AttributedString WindowsTextInputComponentView::getAttributedString() const {
493
505
  // Use BaseTextShadowNode to get attributed string from children
494
506
 
495
- auto childTextAttributes = facebook::react::TextAttributes::defaultTextAttributes();
496
- childTextAttributes.fontSizeMultiplier = m_fontSizeMultiplier;
497
-
498
- childTextAttributes.apply(windowsTextInputProps().textAttributes);
499
-
500
507
  auto attributedString = facebook::react::AttributedString{};
501
508
  // auto attachments = facebook::react::BaseTextShadowNode::Attachments{};
502
509
 
@@ -1114,6 +1121,9 @@ void WindowsTextInputComponentView::updateProps(
1114
1121
  !facebook::react::floatEquality(
1115
1122
  oldTextInputProps.textAttributes.letterSpacing, newTextInputProps.textAttributes.letterSpacing) ||
1116
1123
  oldTextInputProps.textAttributes.fontFamily != newTextInputProps.textAttributes.fontFamily ||
1124
+ oldTextInputProps.textAttributes.fontStyle != newTextInputProps.textAttributes.fontStyle ||
1125
+ oldTextInputProps.textAttributes.textDecorationLineType !=
1126
+ newTextInputProps.textAttributes.textDecorationLineType ||
1117
1127
  !facebook::react::floatEquality(
1118
1128
  oldTextInputProps.textAttributes.maxFontSizeMultiplier,
1119
1129
  newTextInputProps.textAttributes.maxFontSizeMultiplier)) {
@@ -1129,6 +1139,7 @@ void WindowsTextInputComponentView::updateProps(
1129
1139
  }
1130
1140
 
1131
1141
  if (oldTextInputProps.multiline != newTextInputProps.multiline) {
1142
+ m_recalculateContentVerticalOffset = true;
1132
1143
  m_multiline = newTextInputProps.multiline;
1133
1144
  m_propBitsMask |= TXTBIT_MULTILINE | TXTBIT_WORDWRAP;
1134
1145
  if (newTextInputProps.multiline) {
@@ -1278,6 +1289,10 @@ void WindowsTextInputComponentView::updateLayoutMetrics(
1278
1289
  unsigned int newWidth = static_cast<unsigned int>(layoutMetrics.frame.size.width * layoutMetrics.pointScaleFactor);
1279
1290
  unsigned int newHeight = static_cast<unsigned int>(layoutMetrics.frame.size.height * layoutMetrics.pointScaleFactor);
1280
1291
 
1292
+ if (newHeight != m_imgHeight || oldLayoutMetrics.pointScaleFactor != layoutMetrics.pointScaleFactor) {
1293
+ m_recalculateContentVerticalOffset = true;
1294
+ }
1295
+
1281
1296
  if (newWidth != m_imgWidth || newHeight != m_imgHeight) {
1282
1297
  m_drawingSurface = nullptr; // Invalidate surface if we get a size change
1283
1298
  }
@@ -1416,6 +1431,8 @@ void WindowsTextInputComponentView::FinalizeUpdates(
1416
1431
 
1417
1432
  void WindowsTextInputComponentView::UpdatePropertyBits() noexcept {
1418
1433
  if (m_propBitsMask != 0) {
1434
+ if ((m_propBits & TXTBIT_CHARFORMATCHANGE) == TXTBIT_CHARFORMATCHANGE)
1435
+ m_recalculateContentVerticalOffset = true;
1419
1436
  DrawBlock db(*this);
1420
1437
  winrt::check_hresult(m_textServices->OnTxPropertyBitsChange(m_propBitsMask, m_propBits));
1421
1438
  m_propBitsMask = 0;
@@ -1427,6 +1444,10 @@ void WindowsTextInputComponentView::InternalFinalize() noexcept {
1427
1444
  if (m_mounted) {
1428
1445
  UpdatePropertyBits();
1429
1446
 
1447
+ if (m_recalculateContentVerticalOffset) {
1448
+ calculateContentVerticalOffset();
1449
+ }
1450
+
1430
1451
  ensureDrawingSurface();
1431
1452
  if (m_needsRedraw) {
1432
1453
  DrawText();
@@ -1488,12 +1509,6 @@ void WindowsTextInputComponentView::UpdateCharFormat() noexcept {
1488
1509
  // m_crText = RemoveAlpha(fontDetails.FontColor);
1489
1510
  // }
1490
1511
 
1491
- // set font face
1492
- // cfNew.dwMask |= CFM_FACE;
1493
- // NetUIWzCchCopy(cfNew.szFaceName, _countof(cfNew.szFaceName), fontDetails.FontName.c_str());
1494
- // cfNew.bPitchAndFamily = FF_DONTCARE;
1495
-
1496
- // set font size -- 15 to convert twips to pt
1497
1512
  const auto &props = windowsTextInputProps();
1498
1513
  float fontSize =
1499
1514
  (std::isnan(props.textAttributes.fontSize) ? facebook::react::TextAttributes::defaultTextAttributes().fontSize
@@ -1504,8 +1519,8 @@ void WindowsTextInputComponentView::UpdateCharFormat() noexcept {
1504
1519
  fontSize *=
1505
1520
  (maxFontSizeMultiplier >= 1.0f) ? std::min(maxFontSizeMultiplier, m_fontSizeMultiplier) : m_fontSizeMultiplier;
1506
1521
 
1507
- // TODO get fontSize from props.textAttributes, or defaultTextAttributes, or fragment?
1508
1522
  cfNew.dwMask |= CFM_SIZE;
1523
+ // set font size -- 15 to convert twips to pt
1509
1524
  cfNew.yHeight = static_cast<LONG>(fontSize * 15);
1510
1525
 
1511
1526
  // set bold
@@ -1513,18 +1528,26 @@ void WindowsTextInputComponentView::UpdateCharFormat() noexcept {
1513
1528
  cfNew.wWeight =
1514
1529
  props.textAttributes.fontWeight ? static_cast<WORD>(*props.textAttributes.fontWeight) : DWRITE_FONT_WEIGHT_NORMAL;
1515
1530
 
1516
- // set font style
1517
- // cfNew.dwMask |= (CFM_ITALIC | CFM_STRIKEOUT | CFM_UNDERLINE);
1518
- // int dFontStyle = fontDetails.FontStyle;
1519
- // if (dFontStyle & FS_Italic) {
1520
- // cfNew.dwEffects |= CFE_ITALIC;
1521
- // }
1522
- // if (dFontStyle & FS_StrikeOut) {
1523
- // cfNew.dwEffects |= CFE_STRIKEOUT;
1524
- //}
1525
- // if (dFontStyle & FS_Underline) {
1526
- // cfNew.dwEffects |= CFE_UNDERLINE;
1527
- // }
1531
+ // set font style (italic)
1532
+ cfNew.dwMask |= CFM_ITALIC;
1533
+ if (props.textAttributes.fontStyle == facebook::react::FontStyle::Italic ||
1534
+ props.textAttributes.fontStyle == facebook::react::FontStyle::Oblique) {
1535
+ cfNew.dwEffects |= CFE_ITALIC;
1536
+ }
1537
+
1538
+ // set text decoration (underline and strikethrough)
1539
+ cfNew.dwMask |= (CFM_UNDERLINE | CFM_STRIKEOUT);
1540
+ if (props.textAttributes.textDecorationLineType.has_value()) {
1541
+ auto decorationType = *props.textAttributes.textDecorationLineType;
1542
+ if (decorationType == facebook::react::TextDecorationLineType::Underline ||
1543
+ decorationType == facebook::react::TextDecorationLineType::UnderlineStrikethrough) {
1544
+ cfNew.dwEffects |= CFE_UNDERLINE;
1545
+ }
1546
+ if (decorationType == facebook::react::TextDecorationLineType::Strikethrough ||
1547
+ decorationType == facebook::react::TextDecorationLineType::UnderlineStrikethrough) {
1548
+ cfNew.dwEffects |= CFE_STRIKEOUT;
1549
+ }
1550
+ }
1528
1551
 
1529
1552
  // set font family
1530
1553
  if (!props.textAttributes.fontFamily.empty()) {
@@ -1532,7 +1555,11 @@ void WindowsTextInputComponentView::UpdateCharFormat() noexcept {
1532
1555
  std::wstring fontFamily =
1533
1556
  std::wstring(props.textAttributes.fontFamily.begin(), props.textAttributes.fontFamily.end());
1534
1557
  wcsncpy_s(cfNew.szFaceName, fontFamily.c_str(), LF_FACESIZE);
1558
+ } else {
1559
+ cfNew.dwMask |= CFM_FACE;
1560
+ wcsncpy_s(cfNew.szFaceName, L"Segoe UI\0", LF_FACESIZE);
1535
1561
  }
1562
+ cfNew.bPitchAndFamily = FF_DONTCARE;
1536
1563
 
1537
1564
  // set char offset
1538
1565
  cfNew.dwMask |= CFM_OFFSET;
@@ -1541,7 +1568,8 @@ void WindowsTextInputComponentView::UpdateCharFormat() noexcept {
1541
1568
  // set letter spacing
1542
1569
  float letterSpacing = props.textAttributes.letterSpacing;
1543
1570
  if (!std::isnan(letterSpacing)) {
1544
- updateLetterSpacing(letterSpacing);
1571
+ cfNew.dwMask |= CFM_SPACING;
1572
+ cfNew.sSpacing = static_cast<SHORT>(letterSpacing * 20); // Convert to TWIPS
1545
1573
  }
1546
1574
 
1547
1575
  // set charset
@@ -1657,7 +1685,7 @@ winrt::com_ptr<::IDWriteTextLayout> WindowsTextInputComponentView::CreatePlaceho
1657
1685
  const auto &props = windowsTextInputProps();
1658
1686
  facebook::react::TextAttributes textAttributes = props.textAttributes;
1659
1687
  if (std::isnan(props.textAttributes.fontSize)) {
1660
- textAttributes.fontSize = 12.0f;
1688
+ facebook::react::TextAttributes::defaultTextAttributes().fontSize;
1661
1689
  }
1662
1690
  textAttributes.fontSizeMultiplier = m_fontSizeMultiplier;
1663
1691
  fragment1.string = props.placeholder;
@@ -1674,6 +1702,26 @@ winrt::com_ptr<::IDWriteTextLayout> WindowsTextInputComponentView::CreatePlaceho
1674
1702
  return textLayout;
1675
1703
  }
1676
1704
 
1705
+ void WindowsTextInputComponentView::calculateContentVerticalOffset() noexcept {
1706
+ m_recalculateContentVerticalOffset = false;
1707
+
1708
+ const auto &props = windowsTextInputProps();
1709
+
1710
+ m_contentOffsetPx = {
1711
+ static_cast<LONG>(m_layoutMetrics.contentInsets.left * m_layoutMetrics.pointScaleFactor),
1712
+ static_cast<LONG>(m_layoutMetrics.contentInsets.top * m_layoutMetrics.pointScaleFactor)};
1713
+
1714
+ if (props.multiline) {
1715
+ // Align to the top for multiline
1716
+ return;
1717
+ }
1718
+
1719
+ auto [contentWidth, contentHeight] = GetContentSize();
1720
+
1721
+ m_contentOffsetPx.y += static_cast<LONG>(std::round(
1722
+ ((m_layoutMetrics.getContentFrame().size.height - contentHeight) / 2) * m_layoutMetrics.pointScaleFactor));
1723
+ }
1724
+
1677
1725
  void WindowsTextInputComponentView::DrawText() noexcept {
1678
1726
  m_needsRedraw = true;
1679
1727
  if (m_cDrawBlock || theme()->IsEmpty() || !m_textServices) {
@@ -1699,16 +1747,13 @@ void WindowsTextInputComponentView::DrawText() noexcept {
1699
1747
  assert(d2dDeviceContext->GetUnitMode() == D2D1_UNIT_MODE_DIPS);
1700
1748
 
1701
1749
  RECTL rc{
1702
- static_cast<LONG>(offset.x),
1703
- static_cast<LONG>(offset.y),
1704
- static_cast<LONG>(offset.x) + static_cast<LONG>(m_imgWidth),
1705
- static_cast<LONG>(offset.y) + static_cast<LONG>(m_imgHeight)};
1750
+ offset.x + m_contentOffsetPx.x,
1751
+ offset.y + m_contentOffsetPx.y,
1752
+ offset.x + m_contentOffsetPx.x + static_cast<LONG>(m_imgWidth),
1753
+ offset.y + m_contentOffsetPx.y + static_cast<LONG>(m_imgHeight)};
1706
1754
 
1707
1755
  RECT rcClient{
1708
- static_cast<LONG>(offset.x),
1709
- static_cast<LONG>(offset.y),
1710
- static_cast<LONG>(offset.x) + static_cast<LONG>(m_imgWidth),
1711
- static_cast<LONG>(offset.y) + static_cast<LONG>(m_imgHeight)};
1756
+ offset.x, offset.y, offset.x + static_cast<LONG>(m_imgWidth), offset.y + static_cast<LONG>(m_imgHeight)};
1712
1757
 
1713
1758
  {
1714
1759
  m_cDrawBlock++; // Dont use AutoDrawBlock as we are already in draw, and dont need to draw again.
@@ -1763,8 +1808,8 @@ void WindowsTextInputComponentView::DrawText() noexcept {
1763
1808
  // draw text
1764
1809
  d2dDeviceContext->DrawTextLayout(
1765
1810
  D2D1::Point2F(
1766
- static_cast<FLOAT>((offset.x + m_layoutMetrics.contentInsets.left) / m_layoutMetrics.pointScaleFactor),
1767
- static_cast<FLOAT>((offset.y + m_layoutMetrics.contentInsets.top) / m_layoutMetrics.pointScaleFactor)),
1811
+ static_cast<FLOAT>(offset.x + m_contentOffsetPx.x) / m_layoutMetrics.pointScaleFactor,
1812
+ static_cast<FLOAT>(offset.y + m_contentOffsetPx.y) / m_layoutMetrics.pointScaleFactor),
1768
1813
  textLayout.get(),
1769
1814
  brush.get(),
1770
1815
  D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT);
@@ -1840,22 +1885,6 @@ void WindowsTextInputComponentView::autoCapitalizeOnUpdateProps(
1840
1885
  }
1841
1886
  }
1842
1887
 
1843
- void WindowsTextInputComponentView::updateLetterSpacing(float letterSpacing) noexcept {
1844
- CHARFORMAT2W cf = {};
1845
- cf.cbSize = sizeof(CHARFORMAT2W);
1846
- cf.dwMask = CFM_SPACING;
1847
- cf.sSpacing = static_cast<SHORT>(letterSpacing * 20); // Convert to TWIPS
1848
-
1849
- LRESULT res;
1850
-
1851
- // Apply to all existing text like placeholder
1852
- winrt::check_hresult(m_textServices->TxSendMessage(EM_SETCHARFORMAT, SCF_ALL, reinterpret_cast<LPARAM>(&cf), &res));
1853
-
1854
- // Apply to future text input
1855
- winrt::check_hresult(
1856
- m_textServices->TxSendMessage(EM_SETCHARFORMAT, SCF_SELECTION, reinterpret_cast<LPARAM>(&cf), &res));
1857
- }
1858
-
1859
1888
  void WindowsTextInputComponentView::updateAutoCorrect(bool enable) noexcept {
1860
1889
  LRESULT lresult;
1861
1890
  winrt::check_hresult(m_textServices->TxSendMessage(
@@ -117,10 +117,10 @@ struct WindowsTextInputComponentView
117
117
  const std::string &previousCapitalizationType,
118
118
  const std::string &newcapitalizationType) noexcept;
119
119
 
120
- void updateLetterSpacing(float letterSpacing) noexcept;
121
120
  void updateAutoCorrect(bool value) noexcept;
122
121
  void updateSpellCheck(bool value) noexcept;
123
122
  void ShowContextMenu(const winrt::Windows::Foundation::Point &position) noexcept;
123
+ void calculateContentVerticalOffset() noexcept;
124
124
 
125
125
  winrt::Windows::UI::Composition::CompositionSurfaceBrush m_brush{nullptr};
126
126
  winrt::Microsoft::ReactNative::Composition::Experimental::ICaretVisual m_caretVisual{nullptr};
@@ -145,6 +145,9 @@ struct WindowsTextInputComponentView
145
145
  bool m_hasFocus{false};
146
146
  bool m_clearTextOnSubmit{false};
147
147
  bool m_multiline{false};
148
+ LONG m_contentVerticalOffsetPx{0}; // Used to center single line text within the client rect
149
+ bool m_recalculateContentVerticalOffset{true};
150
+ POINT m_contentOffsetPx{0, 0};
148
151
  DWORD m_propBitsMask{0};
149
152
  DWORD m_propBits{0};
150
153
  HCURSOR m_hcursor{nullptr};
@@ -96,7 +96,10 @@ void WindowsTextLayoutManager::GetTextLayout(
96
96
 
97
97
  winrt::com_ptr<IDWriteTextFormat> spTextFormat;
98
98
 
99
- float fontSizeText = outerFragment.textAttributes.fontSize;
99
+ float fontSizeText =
100
+ (std::isnan(outerFragment.textAttributes.fontSize)
101
+ ? facebook::react::TextAttributes::defaultTextAttributes().fontSize
102
+ : outerFragment.textAttributes.fontSize);
100
103
  if (outerFragment.textAttributes.allowFontScaling.value_or(true) &&
101
104
  !std::isnan(outerFragment.textAttributes.fontSizeMultiplier)) {
102
105
  float maxFontSizeMultiplierText = cDefaultMaxFontSizeMultiplier;
@@ -287,7 +290,9 @@ void WindowsTextLayoutManager::GetTextLayout(
287
290
  maxFontSizeMultiplier =
288
291
  (!std::isnan(attributes.maxFontSizeMultiplier) ? attributes.maxFontSizeMultiplier
289
292
  : cDefaultMaxFontSizeMultiplier);
290
- float fontSize = attributes.fontSize;
293
+ float fontSize =
294
+ (std::isnan(attributes.fontSize) ? facebook::react::TextAttributes::defaultTextAttributes().fontSize
295
+ : attributes.fontSize);
291
296
  if (attributes.allowFontScaling.value_or(true) && (!std::isnan(attributes.fontSizeMultiplier))) {
292
297
  fontSize *= (maxFontSizeMultiplier >= 1.0f) ? std::min(maxFontSizeMultiplier, attributes.fontSizeMultiplier)
293
298
  : attributes.fontSizeMultiplier;
@@ -10,11 +10,11 @@
10
10
  -->
11
11
  <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
12
12
  <PropertyGroup>
13
- <ReactNativeWindowsVersion>0.81.5</ReactNativeWindowsVersion>
13
+ <ReactNativeWindowsVersion>0.81.6</ReactNativeWindowsVersion>
14
14
  <ReactNativeWindowsMajor>0</ReactNativeWindowsMajor>
15
15
  <ReactNativeWindowsMinor>81</ReactNativeWindowsMinor>
16
- <ReactNativeWindowsPatch>5</ReactNativeWindowsPatch>
16
+ <ReactNativeWindowsPatch>6</ReactNativeWindowsPatch>
17
17
  <ReactNativeWindowsCanary>false</ReactNativeWindowsCanary>
18
- <ReactNativeWindowsCommitId>ff246e07a1fca3e9925f60981d8a9b9d75ceb87d</ReactNativeWindowsCommitId>
18
+ <ReactNativeWindowsCommitId>176577ae34cb8938133a533257b3027aea4a6291</ReactNativeWindowsCommitId>
19
19
  </PropertyGroup>
20
20
  </Project>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-windows",
3
- "version": "0.81.5",
3
+ "version": "0.81.6",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",