Skip to content

Commit fef23b6

Browse files
authored
Simplify Playground-Composition (#15308)
* Simplify Playground-Composition * format
1 parent 3c72af8 commit fef23b6

File tree

3 files changed

+70
-199
lines changed

3 files changed

+70
-199
lines changed

packages/playground/windows/playground-composition/Playground-Composition.cpp

Lines changed: 59 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,11 @@
44
#include <windows.h>
55
#include <windowsx.h>
66

7-
#include <memory>
8-
#include <mutex>
9-
107
// Disabled until we have a 3rd party story for custom components
118
// #include "AutolinkedNativeModules.g.h"
129

13-
#include <winrt/Windows.Foundation.Collections.h>
14-
15-
#include <DispatcherQueue.h>
16-
#include <UIAutomation.h>
17-
#include <windows.ui.composition.interop.h>
18-
1910
#include <winrt/Microsoft.ReactNative.Composition.Experimental.h>
2011
#include <winrt/Microsoft.ReactNative.Composition.h>
21-
#include <winrt/Windows.UI.Composition.Desktop.h>
22-
#include <winrt/Windows.UI.Composition.h>
2312

2413
#include <DesktopWindowBridge.h>
2514
#include "App.xaml.h"
@@ -108,12 +97,9 @@ struct CompReactPackageProvider
10897
}
10998
};
11099

111-
winrt::Windows::System::DispatcherQueueController g_dispatcherQueueController{nullptr};
112-
winrt::Windows::UI::Composition::Compositor g_compositor{nullptr};
113-
114100
constexpr auto WindowDataProperty = L"WindowData";
115101

116-
int RunPlayground(int showCmd, bool useWebDebugger);
102+
int RunPlayground(int showCmd);
117103

118104
struct WindowData {
119105
static HINSTANCE s_instance;
@@ -124,10 +110,8 @@ struct WindowData {
124110
winrt::Microsoft::UI::Content::DesktopChildSiteBridge m_bridge{nullptr};
125111
winrt::Microsoft::ReactNative::ReactNativeHost m_host{nullptr};
126112
winrt::Microsoft::ReactNative::ReactInstanceSettings m_instanceSettings{nullptr};
127-
bool m_useLiftedComposition{true};
128113
bool m_sizeToContent{false};
129114
bool m_forceRTL{false};
130-
winrt::Windows::UI::Composition::Desktop::DesktopWindowTarget m_target{nullptr};
131115
LONG m_height{0};
132116
LONG m_width{0};
133117

@@ -196,114 +180,66 @@ struct WindowData {
196180

197181
winrt::Microsoft::ReactNative::ReactViewOptions viewOptions;
198182
viewOptions.ComponentName(appName);
199-
auto windowData = WindowData::GetFromWindow(hwnd);
200183

201184
if (!m_compRootView) {
202-
if (windowData->m_useLiftedComposition) {
203-
m_compRootView = winrt::Microsoft::ReactNative::ReactNativeIsland(g_liftedCompositor);
204-
} else {
205-
m_compRootView = winrt::Microsoft::ReactNative::ReactNativeIsland();
185+
m_compRootView = winrt::Microsoft::ReactNative::ReactNativeIsland(g_liftedCompositor);
186+
187+
// By setting the compositor here we opt into using the new architecture.
188+
winrt::Microsoft::ReactNative::Composition::CompositionUIService::SetCompositor(
189+
InstanceSettings(), g_liftedCompositor);
190+
191+
// Register ellipse:// uri hander for images
192+
host.PackageProviders().Append(winrt::make<EllipseReactPackageProvider>());
193+
194+
m_bridge = winrt::Microsoft::UI::Content::DesktopChildSiteBridge::Create(
195+
g_liftedCompositor, winrt::Microsoft::UI::GetWindowIdFromWindow(hwnd));
196+
197+
if (m_forceRTL) {
198+
m_bridge.LayoutDirectionOverride(winrt::Microsoft::UI::Content::ContentLayoutDirection::RightToLeft);
206199
}
207200

208-
if (windowData->m_useLiftedComposition) {
209-
// By setting the compositor here we opt into using the new architecture.
210-
winrt::Microsoft::ReactNative::Composition::CompositionUIService::SetCompositor(
211-
InstanceSettings(), g_liftedCompositor);
212-
213-
// Register ellipse:// uri hander for images
214-
host.PackageProviders().Append(winrt::make<EllipseReactPackageProvider>());
215-
216-
m_bridge = winrt::Microsoft::UI::Content::DesktopChildSiteBridge::Create(
217-
g_liftedCompositor, winrt::Microsoft::UI::GetWindowIdFromWindow(hwnd));
218-
219-
if (m_forceRTL) {
220-
m_bridge.LayoutDirectionOverride(winrt::Microsoft::UI::Content::ContentLayoutDirection::RightToLeft);
221-
}
222-
223-
auto appContent = m_compRootView.Island();
224-
225-
m_bridge.Connect(appContent);
226-
m_bridge.Show();
227-
228-
m_compRootView.ScaleFactor(ScaleFactor(hwnd));
229-
winrt::Microsoft::ReactNative::LayoutConstraints constraints;
230-
constraints.LayoutDirection = winrt::Microsoft::ReactNative::LayoutDirection::Undefined;
231-
constraints.MaximumSize =
232-
constraints.MinimumSize = {m_width / ScaleFactor(hwnd), m_height / ScaleFactor(hwnd)};
233-
234-
if (m_sizeToContent) {
235-
ApplyConstraintsForContentSizedWindow(constraints);
236-
237-
// Disable user sizing of the hwnd
238-
::SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SIZEBOX);
239-
m_compRootView.SizeChanged(
240-
[hwnd, props = InstanceSettings().Properties()](
241-
auto /*sender*/, const winrt::Microsoft::ReactNative::RootViewSizeChangedEventArgs &args) {
242-
auto compositor =
243-
winrt::Microsoft::ReactNative::Composition::CompositionUIService::GetCompositor(props);
244-
auto async = compositor.RequestCommitAsync();
245-
async.Completed([hwnd, size = args.Size()](
246-
auto /*asyncInfo*/, winrt::Windows::Foundation::AsyncStatus /*asyncStatus*/) {
247-
RECT rcClient, rcWindow;
248-
GetClientRect(hwnd, &rcClient);
249-
GetWindowRect(hwnd, &rcWindow);
250-
251-
SetWindowPos(
252-
hwnd,
253-
nullptr,
254-
0,
255-
0,
256-
static_cast<int>(size.Width) + rcClient.left - rcClient.right + rcWindow.right -
257-
rcWindow.left,
258-
static_cast<int>(size.Height) + rcClient.top - rcClient.bottom + rcWindow.bottom -
259-
rcWindow.top,
260-
SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER);
261-
});
262-
});
263-
}
264-
m_compRootView.Arrange(constraints, {0, 0});
265-
266-
m_bridge.ResizePolicy(winrt::Microsoft::UI::Content::ContentSizePolicy::ResizeContentToParentWindow);
267-
268-
} else if (!m_target) {
269-
// General users of RNW should never set CompositionContext - this is an advanced usage to inject another
270-
// composition implementation. By using the SystemCompositionContextHelper here, React Native Windows will
271-
// use System Visuals for its tree.
272-
winrt::Microsoft::ReactNative::ReactPropertyBag(InstanceSettings().Properties())
273-
.Set(
274-
winrt::Microsoft::ReactNative::ReactPropertyId<
275-
winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext>{
276-
L"ReactNative.Composition", L"CompositionContext"},
277-
winrt::Microsoft::ReactNative::Composition::Experimental::SystemCompositionContextHelper::
278-
CreateContext(g_compositor));
279-
280-
auto interop = g_compositor.as<ABI::Windows::UI::Composition::Desktop::ICompositorDesktopInterop>();
281-
winrt::Windows::UI::Composition::Desktop::DesktopWindowTarget target{nullptr};
282-
winrt::check_hresult(interop->CreateDesktopWindowTarget(
283-
hwnd,
284-
false,
285-
reinterpret_cast<ABI::Windows::UI::Composition::Desktop::IDesktopWindowTarget **>(
286-
winrt::put_abi(target))));
287-
m_target = target;
288-
289-
auto root = g_compositor.CreateContainerVisual();
290-
root.RelativeSizeAdjustment({1.0f, 1.0f});
291-
root.Offset({0, 0, 0});
292-
m_target.Root(root);
293-
m_compRootView
294-
.as<winrt::Microsoft::ReactNative::Composition::Experimental::IInternalCompositionRootView>()
295-
.SetWindow(reinterpret_cast<uint64_t>(hwnd));
296-
m_compRootView
297-
.as<winrt::Microsoft::ReactNative::Composition::Experimental::IInternalCompositionRootView>()
298-
.InternalRootVisual(winrt::Microsoft::ReactNative::Composition::Experimental::
299-
SystemCompositionContextHelper::CreateVisual(root));
300-
m_compRootView.ScaleFactor(ScaleFactor(hwnd));
301-
winrt::Microsoft::ReactNative::LayoutConstraints contraints;
302-
contraints.LayoutDirection = winrt::Microsoft::ReactNative::LayoutDirection::Undefined;
303-
contraints.MaximumSize =
304-
contraints.MinimumSize = {m_width / ScaleFactor(hwnd), m_height / ScaleFactor(hwnd)};
305-
m_compRootView.Arrange(contraints, {0, 0});
201+
auto appContent = m_compRootView.Island();
202+
203+
m_bridge.Connect(appContent);
204+
m_bridge.Show();
205+
206+
m_compRootView.ScaleFactor(ScaleFactor(hwnd));
207+
winrt::Microsoft::ReactNative::LayoutConstraints constraints;
208+
constraints.LayoutDirection = winrt::Microsoft::ReactNative::LayoutDirection::Undefined;
209+
constraints.MaximumSize =
210+
constraints.MinimumSize = {m_width / ScaleFactor(hwnd), m_height / ScaleFactor(hwnd)};
211+
212+
if (m_sizeToContent) {
213+
ApplyConstraintsForContentSizedWindow(constraints);
214+
215+
// Disable user sizing of the hwnd
216+
::SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SIZEBOX);
217+
m_compRootView.SizeChanged([hwnd, props = InstanceSettings().Properties()](
218+
auto /*sender*/,
219+
const winrt::Microsoft::ReactNative::RootViewSizeChangedEventArgs &args) {
220+
auto compositor =
221+
winrt::Microsoft::ReactNative::Composition::CompositionUIService::GetCompositor(props);
222+
auto async = compositor.RequestCommitAsync();
223+
async.Completed([hwnd, size = args.Size()](
224+
auto /*asyncInfo*/, winrt::Windows::Foundation::AsyncStatus /*asyncStatus*/) {
225+
RECT rcClient, rcWindow;
226+
GetClientRect(hwnd, &rcClient);
227+
GetWindowRect(hwnd, &rcWindow);
228+
229+
SetWindowPos(
230+
hwnd,
231+
nullptr,
232+
0,
233+
0,
234+
static_cast<int>(size.Width) + rcClient.left - rcClient.right + rcWindow.right - rcWindow.left,
235+
static_cast<int>(size.Height) + rcClient.top - rcClient.bottom + rcWindow.bottom - rcWindow.top,
236+
SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER);
237+
});
238+
});
306239
}
240+
m_compRootView.Arrange(constraints, {0, 0});
241+
242+
m_bridge.ResizePolicy(winrt::Microsoft::UI::Content::ContentSizePolicy::ResizeContentToParentWindow);
307243
}
308244

309245
// Nudge the ReactNativeHost to create the instance and wrapping context
@@ -319,7 +255,7 @@ struct WindowData {
319255
std::thread playgroundThread{([]() {
320256
// For subsequent RN windows do not use the web debugger by default,
321257
// since one instance can be connected to it at a time.
322-
RunPlayground(SW_SHOW, false);
258+
RunPlayground(SW_SHOW);
323259
})};
324260
playgroundThread.detach();
325261
break;
@@ -404,15 +340,6 @@ struct WindowData {
404340
}
405341
}
406342

407-
LRESULT TranslateMessage(HWND /*hwnd*/, UINT message, WPARAM wparam, LPARAM lparam) noexcept {
408-
if (!m_useLiftedComposition && m_compRootView) {
409-
return static_cast<LRESULT>(
410-
m_compRootView.as<winrt::Microsoft::ReactNative::Composition::Experimental::IInternalCompositionRootView>()
411-
.SendMessage(message, wparam, lparam));
412-
}
413-
return 0;
414-
}
415-
416343
/// Message handler for about box.
417344
static INT_PTR CALLBACK About(HWND hwnd, UINT message, WPARAM wparam, LPARAM /* lparam */) noexcept {
418345
switch (message) {
@@ -488,7 +415,6 @@ struct WindowData {
488415
case WM_INITDIALOG: {
489416
auto boolToCheck = [](bool b) { return b ? BST_CHECKED : BST_UNCHECKED; };
490417
auto self = reinterpret_cast<WindowData *>(lparam);
491-
CheckDlgButton(hwnd, IDC_LIFTEDCOMPOSITION, boolToCheck(self->m_useLiftedComposition));
492418
CheckDlgButton(hwnd, IDC_FASTREFRESH, boolToCheck(self->InstanceSettings().UseFastRefresh()));
493419
CheckDlgButton(hwnd, IDC_DIRECTDEBUGGER, boolToCheck(self->InstanceSettings().UseDirectDebugger()));
494420
CheckDlgButton(hwnd, IDC_BREAKONNEXTLINE, boolToCheck(self->InstanceSettings().DebuggerBreakOnNextLine()));
@@ -498,20 +424,12 @@ struct WindowData {
498424
SetWindowTextW(portEditControl, std::to_wstring(self->InstanceSettings().DebuggerPort()).c_str());
499425
SendMessageW(portEditControl, (UINT)EM_SETLIMITTEXT, (WPARAM)5, (LPARAM)0);
500426

501-
auto cmbEngines = GetDlgItem(hwnd, IDC_JSENGINE);
502-
SendMessageW(cmbEngines, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)TEXT("Chakra"));
503-
SendMessageW(cmbEngines, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)TEXT("Hermes"));
504-
SendMessageW(cmbEngines, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)TEXT("V8"));
505-
// Fabric only supports Hermes right now - So dont actually set JS engine override
506-
// SendMessageW(cmbEngines, CB_SETCURSEL, (WPARAM) static_cast<int32_t>(self->m_jsEngine), (LPARAM)0);
507-
508427
return TRUE;
509428
}
510429
case WM_COMMAND: {
511430
switch (LOWORD(wparam)) {
512431
case IDOK: {
513432
auto self = GetFromWindow(GetParent(hwnd));
514-
self->m_useLiftedComposition = (IsDlgButtonChecked(hwnd, IDC_LIFTEDCOMPOSITION) == BST_CHECKED);
515433
self->InstanceSettings().UseFastRefresh(IsDlgButtonChecked(hwnd, IDC_FASTREFRESH) == BST_CHECKED);
516434
self->InstanceSettings().UseDirectDebugger(IsDlgButtonChecked(hwnd, IDC_DIRECTDEBUGGER) == BST_CHECKED);
517435
self->InstanceSettings().DebuggerBreakOnNextLine(
@@ -533,11 +451,6 @@ struct WindowData {
533451
// Don't update the debugger port if the new value can't be parsed
534452
// (E.g. includes letters or symbols).
535453
}
536-
537-
// Fabric only supports Hermes right now - So dont actually set JS engine override
538-
// auto cmbEngines = GetDlgItem(hwnd, IDC_JSENGINE);
539-
// int itemIndex = (int)SendMessageW(cmbEngines, (UINT)CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
540-
// self->m_jsEngine = static_cast<Microsoft::ReactNative::JSIEngine>(itemIndex);
541454
}
542455
[[fallthrough]];
543456
case IDCANCEL:
@@ -557,11 +470,6 @@ HINSTANCE WindowData::s_instance = reinterpret_cast<HINSTANCE>(&__ImageBase);
557470

558471
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) noexcept {
559472
auto windowData = WindowData::GetFromWindow(hwnd);
560-
if (windowData) {
561-
auto result = WindowData::GetFromWindow(hwnd)->TranslateMessage(hwnd, message, wparam, lparam);
562-
if (result)
563-
return result;
564-
}
565473

566474
switch (message) {
567475
case WM_COMMAND: {
@@ -606,20 +514,6 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
606514
SetProp(hwnd, WindowDataProperty, reinterpret_cast<HANDLE>(windowData));
607515
break;
608516
}
609-
case WM_GETOBJECT: {
610-
if (!windowData->m_useLiftedComposition && lparam == UiaRootObjectId) {
611-
if (windowData == nullptr || !windowData->m_compRootView)
612-
break;
613-
614-
auto rootView = windowData->m_compRootView;
615-
winrt::com_ptr<IRawElementProviderSimple> spReps;
616-
if (!rootView.GetUiaProvider().try_as(spReps)) {
617-
break;
618-
}
619-
LRESULT lResult = UiaReturnRawElementProvider(hwnd, wparam, lparam, spReps.get());
620-
return lResult;
621-
}
622-
}
623517
case WM_WINDOWPOSCHANGED: {
624518
windowData->UpdateSize(hwnd);
625519

@@ -634,7 +528,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
634528

635529
constexpr PCWSTR c_windowClassName = L"MS_REACTNATIVE_PLAYGROUND_COMPOSITION";
636530

637-
int RunPlayground(int showCmd, bool /*useWebDebugger*/) {
531+
int RunPlayground(int showCmd) {
638532
constexpr PCWSTR appName = L"React Native Playground (Composition)";
639533

640534
auto windowData = std::make_unique<WindowData>();
@@ -665,10 +559,6 @@ int RunPlayground(int showCmd, bool /*useWebDebugger*/) {
665559
// know the message loop has finished.
666560
g_liftedDispatcherQueueController.ShutdownQueue();
667561

668-
// Destroy all Composition objects
669-
g_compositor.Close();
670-
g_compositor = nullptr;
671-
672562
return 0;
673563
}
674564

@@ -692,19 +582,6 @@ _Use_decl_annotations_ int CALLBACK WinMain(HINSTANCE instance, HINSTANCE, PSTR
692582
WINRT_VERIFY(classId);
693583
winrt::check_win32(!classId);
694584

695-
DispatcherQueueOptions options{
696-
sizeof(DispatcherQueueOptions), /* dwSize */
697-
DQTYPE_THREAD_CURRENT, /* threadType */
698-
DQTAT_COM_ASTA /* apartmentType */
699-
};
700-
701-
// Need to have a Dispatcher on the current thread to be able to create a Compositor
702-
winrt::check_hresult(CreateDispatcherQueueController(
703-
options,
704-
reinterpret_cast<ABI::Windows::System::IDispatcherQueueController **>(
705-
winrt::put_abi(g_dispatcherQueueController))));
706-
g_compositor = winrt::Windows::UI::Composition::Compositor();
707-
708585
// Create a Lifted (WinAppSDK) DispatcherQueue for this thread. This is needed for
709586
// Microsoft.UI.Composition, Content, and Input APIs.
710587
g_liftedDispatcherQueueController =
@@ -715,5 +592,5 @@ _Use_decl_annotations_ int CALLBACK WinMain(HINSTANCE instance, HINSTANCE, PSTR
715592
// in Microsoft.ui.xaml.controls.dll.
716593
auto playgroundApp{winrt::make<winrt::Playground::implementation::App>()};
717594

718-
return RunPlayground(showCmd, false);
595+
return RunPlayground(showCmd);
719596
}

packages/playground/windows/playground-composition/Playground-Composition.rc

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -103,24 +103,21 @@ BEGIN
103103
DEFPUSHBUTTON "OK",IDOK,201,96,50,14,WS_GROUP
104104
END
105105

106-
IDD_SETTINGSBOX DIALOGEX 0, 0, 192, 178
106+
IDD_SETTINGSBOX DIALOGEX 0, 0, 192, 138
107107
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
108108
CAPTION "Settings"
109109
FONT 8, "MS Shell Dlg", 400, 0, 0x1
110110
BEGIN
111-
CONTROL "&Lifted Composition",IDC_LIFTEDCOMPOSITION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,8,104,10
112-
CONTROL "&Fast Refresh",IDC_FASTREFRESH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,26,104,10
113-
CONTROL "&Direct Debugger",IDC_DIRECTDEBUGGER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,44,104,10
114-
CONTROL "&Break On Next Line",IDC_BREAKONNEXTLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,63,104,10
115-
CONTROL "&Size Window To React Content",IDC_SIZETOCONTENT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,82,104,10
116-
LTEXT "Debugger Port",IDC_DEBUGGERPORTLABEL,8,100,50,10
117-
EDITTEXT IDC_DEBUGGERPORT,59,98,28,14,ES_AUTOHSCROLL | ES_NUMBER
118-
LTEXT "JS Engine",IDC_JSENGINELABEL,8,119,50,10
119-
COMBOBOX IDC_JSENGINE,59,116,104,10,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_TABSTOP
120-
COMBOBOX IDC_THEME,59,136,104,10,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_TABSTOP
121-
LTEXT "Theme",IDC_THEMELABEL,8,138,50,10
122-
DEFPUSHBUTTON "OK",IDOK,75,157,50,14,WS_GROUP
123-
PUSHBUTTON "Cancel",IDCANCEL,130,157,50,14
111+
CONTROL "&Fast Refresh",IDC_FASTREFRESH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,8,104,10
112+
CONTROL "&Direct Debugger",IDC_DIRECTDEBUGGER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,26,104,10
113+
CONTROL "&Break On Next Line",IDC_BREAKONNEXTLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,44,104,10
114+
CONTROL "&Size Window To React Content",IDC_SIZETOCONTENT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,63,104,10
115+
LTEXT "Debugger Port",IDC_DEBUGGERPORTLABEL,8,80,50,10
116+
EDITTEXT IDC_DEBUGGERPORT,59,78,28,14,ES_AUTOHSCROLL | ES_NUMBER
117+
COMBOBOX IDC_THEME,59,98,104,10,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_TABSTOP
118+
LTEXT "Theme",IDC_THEMELABEL,8,100,50,10
119+
DEFPUSHBUTTON "OK",IDOK,75,118,50,14,WS_GROUP
120+
PUSHBUTTON "Cancel",IDCANCEL,130,118,50,14
124121
END
125122

126123
IDD_OPENJSBUNDLEBOX DIALOGEX 0, 0, 256, 177

0 commit comments

Comments
 (0)