Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Implemented textAlign in TextInput for Fabric",
"packageName": "react-native-windows",
"email": "14967941+danielayala94@users.noreply.github.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Allow TextInput to scroll",
"packageName": "react-native-windows",
"email": "30809111+acoates-ms@users.noreply.github.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Button should pass onAccessibilityTap to native",
"packageName": "react-native-windows",
"email": "34109996+chiaramooney@users.noreply.github.com",
"dependentChangeType": "patch"
}
19 changes: 19 additions & 0 deletions packages/playground/Samples/textinput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,25 @@ export default class Bootstrap extends React.Component<{}, any> {
placeholder={'autoCapitalize characters'}
/>
<TextInput
style={styles.input}
textAlign={'left'}
autoCapitalize="none"
placeholder={'Text aligned to the left'}
/>
<TextInput
style={styles.input}
textAlign={'center'}
autoCapitalize="none"
placeholder={'Text aligned to the center'}
/>
<TextInput
style={styles.input}
textAlign={'right'}
autoCapitalize="none"
placeholder={'Text aligned to the right'}
/>
<TextInput
// @ts-ignore
ref={ref => (textInputRef = ref)}
onFocus={() => setTimeout(() => textInputRef?.blur(), 5000)}
placeholder={'blurs after 5 seconds'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,44 +158,6 @@ struct WindowData {
return m_instanceSettings;
}

winrt::Microsoft::UI::WindowId
CreateChildWindow(winrt::Microsoft::UI::WindowId parentWindowId, LPCWSTR title, int x, int y, int w, int h) {
LPCWSTR childWindowClassName = L"TestChildWindowClass";

// Register child window class
static std::once_flag onceFlag;
std::call_once(onceFlag, [&childWindowClassName]() {
WNDCLASSEX childWindowClass = {};

childWindowClass.cbSize = sizeof(WNDCLASSEX);
childWindowClass.style = CS_HREDRAW | CS_VREDRAW;
childWindowClass.lpfnWndProc = ::DefWindowProc;
childWindowClass.hInstance = GetModuleHandle(nullptr);
childWindowClass.lpszClassName = childWindowClassName;

RegisterClassEx(&childWindowClass);
});

HWND parentHwnd;
parentHwnd = winrt::Microsoft::UI::GetWindowFromWindowId(parentWindowId);

HWND childHwnd = ::CreateWindowEx(
0 /* dwExStyle */,
childWindowClassName,
title,
WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
x,
y,
w,
h,
parentHwnd /* hWndParent */,
nullptr /* hMenu */,
GetModuleHandle(nullptr),
nullptr /* lpParam */);

return winrt::Microsoft::UI::GetWindowIdFromWindow(childHwnd);
}

void ApplyConstraintsForContentSizedWindow(winrt::Microsoft::ReactNative::LayoutConstraints &constraints) {
constraints.MinimumSize = {300, 300};
constraints.MaximumSize = {1000, 1000};
Expand Down Expand Up @@ -274,21 +236,28 @@ struct WindowData {
// Disable user sizing of the hwnd
::SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SIZEBOX);
m_compRootView.SizeChanged(
[hwnd](auto sender, const winrt::Microsoft::ReactNative::RootViewSizeChangedEventArgs &args) {
RECT rcClient, rcWindow;
GetClientRect(hwnd, &rcClient);
GetWindowRect(hwnd, &rcWindow);

SetWindowPos(
hwnd,
nullptr,
0,
0,
static_cast<int>(args.Size().Width) + rcClient.left - rcClient.right + rcWindow.right -
rcWindow.left,
static_cast<int>(args.Size().Height) + rcClient.top - rcClient.bottom + rcWindow.bottom -
rcWindow.top,
SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER);
[hwnd, props = InstanceSettings().Properties()](
auto sender, const winrt::Microsoft::ReactNative::RootViewSizeChangedEventArgs &args) {
auto compositor =
winrt::Microsoft::ReactNative::Composition::CompositionUIService::GetCompositor(props);
auto async = compositor.RequestCommitAsync();
async.Completed([hwnd, size = args.Size()](
auto asyncInfo, winrt::Windows::Foundation::AsyncStatus /*asyncStatus*/) {
RECT rcClient, rcWindow;
GetClientRect(hwnd, &rcClient);
GetWindowRect(hwnd, &rcWindow);

SetWindowPos(
hwnd,
nullptr,
0,
0,
static_cast<int>(size.Width) + rcClient.left - rcClient.right + rcWindow.right -
rcWindow.left,
static_cast<int>(size.Height) + rcClient.top - rcClient.bottom + rcWindow.bottom -
rcWindow.top,
SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER);
});
});
}
m_compRootView.Arrange(constraints, {0, 0});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,25 +116,25 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {

//@cmember Show the scroll bar
BOOL TxShowScrollBar(INT fnBar, BOOL fShow) override {
assert(false);
// assert(false);
return {};
}

//@cmember Enable the scroll bar
BOOL TxEnableScrollBar(INT fuSBFlags, INT fuArrowflags) override {
assert(false);
// assert(false);
return {};
}

//@cmember Set the scroll range
BOOL TxSetScrollRange(INT fnBar, LONG nMinPos, INT nMaxPos, BOOL fRedraw) override {
assert(false);
// assert(false);
return {};
}

//@cmember Set the scroll position
BOOL TxSetScrollPos(INT fnBar, INT nPos, BOOL fRedraw) override {
assert(false);
// assert(false);
return {};
}

Expand Down Expand Up @@ -377,8 +377,11 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {

//@cmember Get the bits representing requested scroll bars for the window
HRESULT TxGetScrollBars(DWORD *pdwScrollBar) override {
// TODO support scrolling
*pdwScrollBar = 0;
if (m_outer->m_multiline) {
*pdwScrollBar = WS_VSCROLL | WS_HSCROLL | ES_AUTOVSCROLL | ES_AUTOHSCROLL;
} else {
*pdwScrollBar = WS_HSCROLL | ES_AUTOHSCROLL;
}
return S_OK;
}

Expand Down Expand Up @@ -1042,6 +1045,12 @@ void WindowsTextInputComponentView::updateProps(
autoCapitalizeOnUpdateProps(oldTextInputProps.autoCapitalize, newTextInputProps.autoCapitalize);
}

if (oldTextInputProps.textAlign != newTextInputProps.textAlign) {
// Let UpdateParaFormat() to refresh the text field with the new text alignment.
m_propBitsMask |= TXTBIT_PARAFORMATCHANGE;
m_propBits |= TXTBIT_PARAFORMATCHANGE;
}

UpdatePropertyBits();
}

Expand Down Expand Up @@ -1305,7 +1314,15 @@ void WindowsTextInputComponentView::UpdateParaFormat() noexcept {
m_pf.cbSize = sizeof(PARAFORMAT2);
m_pf.dwMask = PFM_ALL;

m_pf.wAlignment = PFA_LEFT;
auto &textAlign = windowsTextInputProps().textAlign;

if (textAlign == facebook::react::TextAlignment::Center) {
m_pf.wAlignment = PFA_CENTER;
} else if (textAlign == facebook::react::TextAlignment::Right) {
m_pf.wAlignment = PFA_RIGHT;
} else {
m_pf.wAlignment = PFA_LEFT;
}

m_pf.cTabCount = 1;
m_pf.rgxTabs[0] = lDefaultTab;
Expand Down Expand Up @@ -1475,6 +1492,9 @@ WindowsTextInputComponentView::createVisual() noexcept {
winrt::check_hresult(g_pfnCreateTextServices(nullptr, m_textHost.get(), spUnk.put()));
spUnk.as(m_textServices);

LRESULT res;
winrt::check_hresult(m_textServices->TxSendMessage(EM_SETTEXTMODE, TM_PLAINTEXT, 0, &res));

m_caretVisual = m_compContext.CreateCaretVisual();
visual.InsertAt(m_caretVisual.InnerVisual(), 0);
m_caretVisual.IsVisible(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

#include "WindowsTextInputEventEmitter.h"

#include <react/renderer/core/graphicsConversions.h>

namespace facebook::react {

void WindowsTextInputEventEmitter::onChange(OnChange event) const {
Expand Down Expand Up @@ -46,4 +48,23 @@ void WindowsTextInputEventEmitter::onKeyPress(OnKeyPress event) const {
});
}

static jsi::Value textInputMetricsContentSizePayload(
jsi::Runtime &runtime,
const WindowsTextInputEventEmitter::OnContentSizeChange &event) {
auto payload = jsi::Object(runtime);
{
auto contentSize = jsi::Object(runtime);
contentSize.setProperty(runtime, "width", event.contentSize.width);
contentSize.setProperty(runtime, "height", event.contentSize.height);
payload.setProperty(runtime, "contentSize", contentSize);
}
return payload;
};

void WindowsTextInputEventEmitter::onContentSizeChange(OnContentSizeChange event) const {
dispatchEvent("textInputContentSizeChange", [event = std::move(event)](jsi::Runtime &runtime) {
return textInputMetricsContentSizePayload(runtime, event);
});
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,16 @@ class WindowsTextInputEventEmitter : public ViewEventEmitter {
std::string key;
};

struct OnContentSizeChange {
int target;
facebook::react::Size contentSize;
};

void onChange(OnChange value) const;
void onSelectionChange(const OnSelectionChange &value) const;
void onSubmitEditing(OnSubmitEditing value) const;
void onKeyPress(OnKeyPress value) const;
void onContentSizeChange(OnContentSizeChange value) const;
};

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ WindowsTextInputProps::WindowsTextInputProps(
autoCapitalize(convertRawProp(context, rawProps, "autoCapitalize", sourceProps.autoCapitalize, {})),
clearTextOnSubmit(convertRawProp(context, rawProps, "clearTextOnSubmit", sourceProps.clearTextOnSubmit, {false})),
submitKeyEvents(convertRawProp(context, rawProps, "submitKeyEvents", sourceProps.submitKeyEvents, {})),
autoFocus(convertRawProp(context, rawProps, "autoFocus", sourceProps.autoFocus, {false})) {}
autoFocus(convertRawProp(context, rawProps, "autoFocus", sourceProps.autoFocus, {false})),
textAlign(
convertRawProp(context, rawProps, "textAlign", sourceProps.textAlign, facebook::react::TextAlignment::Left)) {
}

void WindowsTextInputProps::setProp(
const PropsParserContext &context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#pragma once

#include <react/components/rnwcore/Props.h>
#include <react/renderer/attributedstring/conversions.h>
#include <react/renderer/components/text/BaseTextProps.h>
#include <react/renderer/core/propsConversions.h>

Expand Down Expand Up @@ -118,6 +119,7 @@ class WindowsTextInputProps final : public ViewProps, public BaseTextProps {
bool clearTextOnSubmit{false};
std::vector<CompWindowsTextInputSubmitKeyEventsStruct> submitKeyEvents{};
bool autoFocus{false};
facebook::react::TextAlignment textAlign{};
};

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,10 @@ Size WindowsTextInputShadowNode::measureContent(
const LayoutContext &layoutContext,
const LayoutConstraints &layoutConstraints) const {
if (getStateData().cachedAttributedStringId != 0) {
facebook::react::ParagraphAttributes paragraphAttributes{};
paragraphAttributes.maximumNumberOfLines = getConcreteProps().multiline ? 0 : 1;
return m_textLayoutManager
->measureCachedSpannableById(
getStateData().cachedAttributedStringId,
{}, // TODO getConcreteProps().paragraphAttributes
layoutConstraints)
->measureCachedSpannableById(getStateData().cachedAttributedStringId, paragraphAttributes, layoutConstraints)
.size;
}

Expand All @@ -183,13 +182,11 @@ Size WindowsTextInputShadowNode::measureContent(

TextLayoutContext textLayoutContext;
textLayoutContext.pointScaleFactor = layoutContext.pointScaleFactor;
facebook::react::ParagraphAttributes paragraphAttributes{};
paragraphAttributes.maximumNumberOfLines = getConcreteProps().multiline ? 0 : 1;
return m_textLayoutManager
->measure(
AttributedStringBox{attributedString},
{}, // TODO getConcreteProps().paragraphAttributes,
textLayoutContext,
layoutConstraints,
nullptr)
AttributedStringBox{attributedString}, paragraphAttributes, textLayoutContext, layoutConstraints, nullptr)
.size;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ void AnimationDriver::StartAnimation() {
animatedValue->PropertySet().StartAnimation(ValueAnimatedNode::s_valueName, animation);
animatedValue->AddActiveAnimation(m_id);
}
scopedBatch.End();

m_scopedBatchCompletedToken = scopedBatch.Completed(
[weakSelf = weak_from_this(), weakManager = m_manager, id = m_id, tag = m_animatedValueTag](auto sender, auto) {
Expand All @@ -74,6 +73,8 @@ void AnimationDriver::StartAnimation() {
}
});

scopedBatch.End();

m_animation = animation;
m_scopedBatch = scopedBatch;
}
Expand Down
3 changes: 3 additions & 0 deletions vnext/src-win/Libraries/Components/Button.windows.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ type ButtonProps = $ReadOnly<{|
accessible?: ?boolean,
accessibilityActions?: ?$ReadOnlyArray<AccessibilityActionInfo>,
onAccessibilityAction?: ?(event: AccessibilityActionEvent) => mixed,
onAccessibilityTap?: ?() => void, // Windows
accessibilityState?: ?AccessibilityState,

/**
Expand Down Expand Up @@ -331,6 +332,7 @@ const Button: React.AbstractComponent<
accessibilityHint,
accessibilityLanguage,
onAccessibilityAction,
onAccessibilityTap, // Windows
tabIndex,
} = props;
const buttonStyles: Array<ViewStyleProp> = [styles.button];
Expand Down Expand Up @@ -389,6 +391,7 @@ const Button: React.AbstractComponent<
accessibilityLanguage={accessibilityLanguage}
accessibilityRole="button"
accessibilityState={_accessibilityState}
onAccessibilityTap={onAccessibilityTap} // Windows
importantForAccessibility={_importantForAccessibility}
hasTVPreferredFocus={hasTVPreferredFocus}
nextFocusDown={nextFocusDown}
Expand Down