Skip to content

Commit 4ad063f

Browse files
authored
[0.74] Cherry-pick: High dpi tooltips, platformcolor fix and clang codegen fix (#14406)
* Fix tooltips in high dpi (#14397) * Fix tooltips in high dpi * Change files * format * tooltips dont respect textscalefactor * Fix build issue building component codegen using clang (#14393) * Fix build issue building component codegen using clang * Change files * Property updates switching between PlatformColors would no-op (#14398) * Property updates switching between PlatformColors would no-op * Change files * format * update change files
1 parent 4dc7e13 commit 4ad063f

24 files changed

+174
-141
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "Fix build issue building component codegen using clang",
4+
"packageName": "@react-native-windows/codegen",
5+
"email": "30809111+acoates-ms@users.noreply.github.com",
6+
"dependentChangeType": "patch"
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "Fix tooltips in high dpi",
4+
"packageName": "react-native-windows",
5+
"email": "30809111+acoates-ms@users.noreply.github.com",
6+
"dependentChangeType": "patch"
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "Fix build issue building component codegen using clang",
4+
"packageName": "react-native-windows",
5+
"email": "30809111+acoates-ms@users.noreply.github.com",
6+
"dependentChangeType": "patch"
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "Property updates switching between PlatformColors would no-op",
4+
"packageName": "react-native-windows",
5+
"email": "30809111+acoates-ms@users.noreply.github.com",
6+
"dependentChangeType": "patch"
7+
}

packages/@react-native-windows/codegen/src/generators/GenerateComponentWindows.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -184,15 +184,15 @@ void Register::_COMPONENT_NAME_::NativeComponent(
184184
userData->UpdateEventEmitter(std::make_shared<::_COMPONENT_NAME_::EventEmitter>(eventEmitter));
185185
});
186186
187-
if constexpr (&TUserData::FinalizeUpdate != &Base::_COMPONENT_NAME_::<TUserData>::FinalizeUpdate) {
187+
if CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::FinalizeUpdate != &Base::_COMPONENT_NAME_::<TUserData>::FinalizeUpdate) {
188188
builder.SetFinalizeUpdateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
189189
winrt::Microsoft::ReactNative::ComponentViewUpdateMask mask) noexcept {
190190
auto userData = view.UserData().as<TUserData>();
191191
userData->FinalizeUpdate(view, mask);
192192
});
193193
}
194194
195-
if constexpr (&TUserData::UpdateState != &Base::_COMPONENT_NAME_::<TUserData>::UpdateState) {
195+
if CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::UpdateState != &Base::_COMPONENT_NAME_::<TUserData>::UpdateState) {
196196
builder.SetUpdateStateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
197197
const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept {
198198
auto userData = view.UserData().as<TUserData>();
@@ -202,15 +202,15 @@ void Register::_COMPONENT_NAME_::NativeComponent(
202202
203203
::_REGISTER_CUSTOM_COMMAND_HANDLER_::
204204
205-
if constexpr (&TUserData::MountChildComponentView != &Base::_COMPONENT_NAME_::<TUserData>::MountChildComponentView) {
205+
if CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::MountChildComponentView != &Base::_COMPONENT_NAME_::<TUserData>::MountChildComponentView) {
206206
builder.SetMountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
207207
const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &args) noexcept {
208208
auto userData = view.UserData().as<TUserData>();
209209
return userData->MountChildComponentView(view, args);
210210
});
211211
}
212212
213-
if constexpr (&TUserData::UnmountChildComponentView != &Base::_COMPONENT_NAME_::<TUserData>::UnmountChildComponentView) {
213+
if CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::UnmountChildComponentView != &Base::_COMPONENT_NAME_::<TUserData>::UnmountChildComponentView) {
214214
builder.SetUnmountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
215215
const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &args) noexcept {
216216
auto userData = view.UserData().as<TUserData>();
@@ -220,13 +220,13 @@ void Register::_COMPONENT_NAME_::NativeComponent(
220220
221221
compBuilder.SetViewComponentViewInitializer([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
222222
auto userData = winrt::make_self<TUserData>();
223-
if constexpr (&TUserData::Initialize != &Base::_COMPONENT_NAME_::<TUserData>::Initialize) {
223+
if CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::Initialize != &Base::_COMPONENT_NAME_::<TUserData>::Initialize) {
224224
userData->Initialize(view);
225225
}
226226
view.UserData(*userData);
227227
});
228228
229-
if constexpr (&TUserData::CreateVisual != &Base::_COMPONENT_NAME_::<TUserData>::CreateVisual) {
229+
if CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::CreateVisual != &Base::_COMPONENT_NAME_::<TUserData>::CreateVisual) {
230230
compBuilder.SetCreateVisualHandler([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
231231
auto userData = view.UserData().as<TUserData>();
232232
return userData->CreateVisual(view);

vnext/Microsoft.ReactNative.Cxx/NativeModules.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,6 +1360,15 @@ inline ReactModuleProvider MakeTurboModuleProvider() noexcept {
13601360
return MakeModuleProvider<TModule>();
13611361
}
13621362

1363+
// Clang does not allow a virtual function address to be a constexpr statement
1364+
#if !defined(CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS)
1365+
#if defined(__clang__)
1366+
#define CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS
1367+
#else
1368+
#define CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS constexpr
1369+
#endif
1370+
#endif
1371+
13631372
} // namespace winrt::Microsoft::ReactNative
13641373

13651374
namespace React {

vnext/Microsoft.ReactNative/Fabric/AbiViewProps.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,12 @@ winrt::Microsoft::ReactNative::Color Color::ReadValue(
7777
switch (reader.ValueType()) {
7878
case JSValueType::Int64: {
7979
auto argb = reader.GetInt64();
80-
return winrt::make<Color>(facebook::react::Color{
81-
/*m_isDefined*/ true,
82-
/*color*/
83-
{static_cast<uint8_t>((argb >> 24) & 0xFF),
84-
static_cast<uint8_t>((argb >> 16) & 0xFF),
85-
static_cast<uint8_t>((argb >> 8) & 0xFF),
86-
static_cast<uint8_t>(argb & 0xFF)},
87-
{}});
80+
return winrt::make<Color>(facebook::react::Color{/*color*/
81+
{static_cast<uint8_t>((argb >> 24) & 0xFF),
82+
static_cast<uint8_t>((argb >> 16) & 0xFF),
83+
static_cast<uint8_t>((argb >> 8) & 0xFF),
84+
static_cast<uint8_t>(argb & 0xFF)},
85+
{}});
8886
}
8987
case JSValueType::Object: {
9088
std::vector<std::string> platformColors;
@@ -96,10 +94,10 @@ winrt::Microsoft::ReactNative::Color Color::ReadValue(
9694
SkipValue<JSValue>(reader); // Skip this property
9795
}
9896
}
99-
return winrt::make<Color>(facebook::react::Color{/*m_isDefined*/ true, /*color*/ {}, std::move(platformColors)});
97+
return winrt::make<Color>(facebook::react::Color{/*color*/ {}, std::move(platformColors)});
10098
}
10199
default:
102-
return winrt::make<Color>(facebook::react::Color{/*m_isDefined*/ false, /*color*/ {0, 0, 0, 0}, {}});
100+
return winrt::make<Color>(facebook::react::Color{/*color*/ {0, 0, 0, 0}, {}});
103101
}
104102
}
105103

vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ void ComponentView::updateProps(
183183
updateShadowProps(oldViewProps, newViewProps);
184184
}
185185
if (oldViewProps.tooltip != newViewProps.tooltip) {
186-
if (!m_tooltipTracked && newViewProps.tooltip) {
186+
if (!m_tooltipTracked && newViewProps.tooltip && !newViewProps.tooltip->empty()) {
187187
TooltipService::GetCurrent(m_reactContext.Properties())->StartTracking(*this);
188188
m_tooltipTracked = true;
189189
} else if (m_tooltipTracked && !newViewProps.tooltip) {

vnext/Microsoft.ReactNative/Fabric/Composition/TooltipService.cpp

Lines changed: 41 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <react/renderer/core/LayoutConstraints.h>
1111
#include <react/renderer/textlayoutmanager/TextLayoutManager.h>
1212
#include <winrt/Microsoft.ReactNative.Composition.h>
13+
#include <winrt/Windows.UI.ViewManagement.h>
1314
#include "TextDrawing.h"
1415
#include "dwmapi.h"
1516

@@ -49,7 +50,9 @@ facebook::react::AttributedStringBox CreateTooltipAttributedString(const std::st
4950
auto fragment = facebook::react::AttributedString::Fragment{};
5051
fragment.string = tooltip;
5152
fragment.textAttributes.fontSize = tooltipFontSize;
52-
attributedString.appendFragment(fragment);
53+
fragment.textAttributes.fontSizeMultiplier =
54+
static_cast<float>(winrt::Windows::UI::ViewManagement::UISettings().TextScaleFactor());
55+
attributedString.appendFragment(std::move(fragment));
5356
return facebook::react::AttributedStringBox{attributedString};
5457
}
5558

@@ -231,14 +234,13 @@ void TooltipTracker::OnUnmounted(
231234
}
232235

233236
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();
239237
DestroyTimer();
240238

241239
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();
242244
auto tooltipData = std::make_unique<TooltipData>(view);
243245
tooltipData->attributedString = CreateTooltipAttributedString(*selfView->viewProps()->tooltip);
244246

@@ -256,37 +258,39 @@ void TooltipTracker::ShowTooltip(const winrt::Microsoft::ReactNative::ComponentV
256258
facebook::react::TextLayoutManager::GetTextLayout(
257259
tooltipData->attributedString, {} /*paragraphAttributes*/, layoutConstraints, tooltipData->textLayout);
258260

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+
}
290294
}
291295
}
292296

vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/HostPlatformColor.h

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,10 @@ namespace facebook::react {
1212

1313
struct Color {
1414
bool operator==(const Color &otherColor) const {
15-
return m_isUndefined && otherColor.m_isUndefined ||
16-
(m_isUndefined == otherColor.m_isUndefined && m_color == otherColor.m_color &&
17-
m_platformColor == otherColor.m_platformColor);
15+
return m_color == otherColor.m_color && m_platformColor == otherColor.m_platformColor;
1816
}
1917
bool operator!=(const Color &otherColor) const {
20-
return m_isUndefined != otherColor.m_isUndefined || m_color != otherColor.m_color ||
21-
m_platformColor != otherColor.m_platformColor;
18+
return m_color != otherColor.m_color || m_platformColor != otherColor.m_platformColor;
2219
}
2320

2421
winrt::Windows::UI::Color AsWindowsColor() const {
@@ -36,13 +33,12 @@ struct Color {
3633
return RGB(m_color.R, m_color.G, m_color.B) | (m_color.A << 24);
3734
}
3835

39-
bool m_isUndefined;
4036
winrt::Windows::UI::Color m_color;
4137
std::vector<std::string> m_platformColor;
4238
};
4339

4440
namespace HostPlatformColor {
45-
static const facebook::react::Color UndefinedColor{true};
41+
static const facebook::react::Color UndefinedColor{{0, 0, 0, 0} /*Black*/, {} /*Empty PlatformColors*/};
4642
} // namespace HostPlatformColor
4743

4844
inline Color hostPlatformColorFromComponents(ColorComponents components) {
@@ -53,7 +49,6 @@ inline Color hostPlatformColorFromComponents(ColorComponents components) {
5349
static_cast<uint8_t>((int)round(components.green * ratio) & 0xff),
5450
static_cast<uint8_t>((int)round(components.blue * ratio) & 0xff)};
5551
return {
56-
/* .m_isUndefined = */ false,
5752
/* .m_color = */ color,
5853
/* .m_platformColor = */ {}};
5954
}

0 commit comments

Comments
 (0)