[Fabric] Fix Modal position, disable input to parent hwnd, and add onShow event (#14109)

* default to Modal opening in middle of app

* add onShow event

* Change files

* disable input to parent hwnd

* fix changefile
This commit is contained in:
Tatiana Kapos 2024-11-18 10:16:37 -08:00 коммит произвёл GitHub
Родитель ef3d7e9a4a
Коммит 83ac05d14f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
3 изменённых файлов: 47 добавлений и 7 удалений

Просмотреть файл

@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Fix Modal position, disable input to parent hwnd, and add onShow",
"packageName": "react-native-windows",
"email": "tatianakapos@microsoft.com",
"dependentChangeType": "patch"
}

Просмотреть файл

@ -24,6 +24,7 @@
#include "IReactContext.h"
#include "ReactHost/ReactInstanceWin.h"
#include "ReactNativeHost.h"
#include "WindowsModalHostViewShadowNode.h"
namespace winrt::Microsoft::ReactNative::Composition::implementation {
WindowsModalHostComponentView::WindowsModalHostComponentView(
@ -33,6 +34,18 @@ WindowsModalHostComponentView::WindowsModalHostComponentView(
: Super(compContext, tag, reactContext) {}
WindowsModalHostComponentView::~WindowsModalHostComponentView() {
// reset the topWindowID
if (m_prevWindowID) {
auto host =
winrt::Microsoft::ReactNative::implementation::ReactNativeHost::GetReactNativeHost(m_reactContext.Properties());
winrt::Microsoft::ReactNative::ReactCoreInjection::SetTopLevelWindowId(
host.InstanceSettings().Properties(), m_prevWindowID);
m_prevWindowID = 0;
}
// enable input to parent
EnableWindow(m_parentHwnd, true);
// Check if the window handle (m_hwnd) exists and destroy it if necessary
if (m_hwnd) {
// Close/Destroy the modal window
@ -77,7 +90,7 @@ void WindowsModalHostComponentView::EnsureModalCreated() {
m_prevWindowID =
winrt::Microsoft::ReactNative::ReactCoreInjection::GetTopLevelWindowId(m_reactContext.Properties().Handle());
auto roothwnd = GetHwndForParenting();
m_parentHwnd = GetHwndForParenting();
m_hwnd = CreateWindow(
c_modalWindowClassName,
@ -87,7 +100,7 @@ void WindowsModalHostComponentView::EnsureModalCreated() {
CW_USEDEFAULT,
MODAL_MIN_WIDTH,
MODAL_MIN_HEIGHT,
roothwnd, // parent
m_parentHwnd, // parent
nullptr,
hInstance,
spunk.get());
@ -126,7 +139,7 @@ void WindowsModalHostComponentView::EnsureModalCreated() {
constraints.LayoutDirection = winrt::Microsoft::ReactNative::LayoutDirection::Undefined;
RECT rc;
GetClientRect(roothwnd, &rc);
GetClientRect(m_parentHwnd, &rc);
// Maximum size is set to size of parent hwnd
constraints.MaximumSize = {(rc.right - rc.left) * ScaleFactor(m_hwnd), (rc.bottom - rc.top) / ScaleFactor(m_hwnd)};
constraints.MinimumSize = {MODAL_MIN_WIDTH * ScaleFactor(m_hwnd), MODAL_MIN_HEIGHT * ScaleFactor(m_hwnd)};
@ -141,6 +154,14 @@ void WindowsModalHostComponentView::ShowOnUIThread() {
ShowWindow(m_hwnd, SW_NORMAL);
BringWindowToTop(m_hwnd);
SetFocus(m_hwnd);
// disable input to parent
EnableWindow(m_parentHwnd, false);
// dispatch onShow event
auto emitter = std::static_pointer_cast<const facebook::react::ModalHostViewEventEmitter>(m_eventEmitter);
facebook::react::ModalHostViewEventEmitter::OnShow onShowArgs;
emitter->onShow(onShowArgs);
}
}
@ -149,12 +170,16 @@ void WindowsModalHostComponentView::HideOnUIThread() noexcept {
SendMessage(m_hwnd, WM_CLOSE, 0, 0);
}
// enable input to parent
EnableWindow(m_parentHwnd, true);
// reset the topWindowID
if (m_prevWindowID) {
auto host =
winrt::Microsoft::ReactNative::implementation::ReactNativeHost::GetReactNativeHost(m_reactContext.Properties());
winrt::Microsoft::ReactNative::ReactCoreInjection::SetTopLevelWindowId(
host.InstanceSettings().Properties(), m_prevWindowID);
m_prevWindowID = 0;
}
}
@ -266,6 +291,7 @@ void WindowsModalHostComponentView::AdjustWindowSize() noexcept {
if (m_layoutMetrics.overflowInset.right == 0 && m_layoutMetrics.overflowInset.bottom == 0) {
return;
}
// Modal's size is based on it's children, use the overflow to calculate the width/height
float xPos = (-m_layoutMetrics.overflowInset.right * (m_layoutMetrics.pointScaleFactor));
float yPos = (-m_layoutMetrics.overflowInset.bottom * (m_layoutMetrics.pointScaleFactor));
@ -273,15 +299,21 @@ void WindowsModalHostComponentView::AdjustWindowSize() noexcept {
GetClientRect(m_hwnd, &rc);
RECT rect = {0, 0, (int)xPos, (int)yPos};
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE); // Adjust for title bar and borders
MoveWindow(m_hwnd, 0, 0, (int)(rect.right - rect.left), (int)(rect.bottom - rect.top), true);
// set the layoutMetrics
m_layoutMetrics.frame.size = {
(float)rect.right - rect.left + m_layoutMetrics.frame.origin.x,
(float)rect.bottom - rect.top + m_layoutMetrics.frame.origin.y};
m_layoutMetrics.frame.size = {(float)rect.right - rect.left, (float)rect.bottom - rect.top};
m_layoutMetrics.overflowInset.right = 0;
m_layoutMetrics.overflowInset.bottom = 0;
// get Modal's position based on parent
RECT parentRC;
GetWindowRect(m_parentHwnd, &parentRC);
float xCor = (parentRC.left + parentRC.right - m_layoutMetrics.frame.size.width) / 2; // midpointx - width / 2
float yCor = (parentRC.top + parentRC.bottom - m_layoutMetrics.frame.size.height) / 2; // midpointy - height / 2
// Adjust window position and size
MoveWindow(m_hwnd, (int)xCor, (int)yCor, (int)(rect.right - rect.left), (int)(rect.bottom - rect.top), true);
// Let RNWIsland know that Modal's size has changed
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ReactNativeIsland>(m_reactNativeIsland)
->NotifySizeChanged();

Просмотреть файл

@ -60,6 +60,7 @@ struct WindowsModalHostComponentView
static void RegisterWndClass() noexcept;
private:
HWND m_parentHwnd{nullptr};
HWND m_hwnd{nullptr};
uint64_t m_prevWindowID;
bool m_isVisible{false};