66
77#include " AppWindow.h"
88
9+ #include < DispatcherQueue.h>
910#include < functional>
1011#include < string>
1112#include < vector>
1213#include < ShObjIdl_core.h>
1314#include < Shellapi.h>
1415#include < ShlObj_core.h>
16+ #include < winrt/windows.system.h>
1517#include " App.h"
1618#include " CheckFailure.h"
1719#include " ControlComponent.h"
@@ -40,6 +42,7 @@ static constexpr int s_minNewWindowSize = 100;
4042AppWindow::AppWindow (
4143 UINT creationModeId,
4244 std::wstring initialUri,
45+ bool isMainWindow,
4346 std::function<void ()> webviewCreatedCallback,
4447 bool customWindowRect,
4548 RECT windowRect,
@@ -48,6 +51,9 @@ AppWindow::AppWindow(
4851 m_initialUri(initialUri),
4952 m_onWebViewFirstInitialized(webviewCreatedCallback)
5053{
54+ // Initialize COM as STA.
55+ CHECK_FAILURE (CoInitializeEx (NULL , COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE));
56+
5157 ++s_appInstances;
5258
5359 WCHAR szTitle[s_maxLoadString]; // The title bar text
@@ -68,13 +74,15 @@ AppWindow::AppWindow(
6874
6975 SetWindowLongPtr (m_mainWindow, GWLP_USERDATA, (LONG_PTR)this );
7076
77+ #ifdef USE_WEBVIEW2_WIN10
7178 // ! [TextScaleChanged1]
7279 if (winrt::try_get_activation_factory<winrt::Windows::UI::ViewManagement::UISettings>())
7380 {
7481 m_uiSettings = winrt::Windows::UI::ViewManagement::UISettings ();
7582 m_uiSettings.TextScaleFactorChanged ({ this , &AppWindow::OnTextScaleChanged });
7683 }
7784 // ! [TextScaleChanged1]
85+ #endif
7886
7987 if (shouldHaveToolbar)
8088 {
@@ -84,12 +92,10 @@ AppWindow::AppWindow(
8492 UpdateCreationModeMenu ();
8593 ShowWindow (m_mainWindow, g_nCmdShow);
8694 UpdateWindow (m_mainWindow);
87-
88- RunAsync ([this ] {
89- InitializeWebView ();
90- });
95+ RunAsync ([this ] {
96+ InitializeWebView ();
97+ });
9198}
92-
9399// Register the Win32 window class for the app window.
94100PCWSTR AppWindow::GetWindowClass ()
95101{
@@ -194,7 +200,7 @@ bool AppWindow::HandleWindowMessage(
194200 {
195201 int retValue = 0 ;
196202 SetWindowLongPtr (hWnd, GWLP_USERDATA, NULL );
197- delete this ;
203+ NotifyClosed () ;
198204 if (--s_appInstances == 0 )
199205 {
200206 PostQuitMessage (retValue);
@@ -328,7 +334,10 @@ bool AppWindow::ExecuteAppCommands(WPARAM wParam, LPARAM lParam)
328334 return true ;
329335 case IDM_CREATION_MODE_WINDOWED:
330336 case IDM_CREATION_MODE_VISUAL_DCOMP:
337+ case IDM_CREATION_MODE_TARGET_DCOMP:
338+ #ifdef USE_WEBVIEW2_WIN10
331339 case IDM_CREATION_MODE_VISUAL_WINCOMP:
340+ #endif
332341 m_creationModeId = LOWORD (wParam);
333342 UpdateCreationModeMenu ();
334343 return true ;
@@ -446,10 +455,13 @@ void AppWindow::InitializeWebView()
446455 // getting created which will apply the browser switches.
447456 CloseWebView ();
448457 m_dcompDevice = nullptr ;
449- m_wincompHelper = nullptr ;
458+ #ifdef USE_WEBVIEW2_WIN10
459+ m_wincompCompositor = nullptr ;
460+ #endif
450461 LPCWSTR subFolder = nullptr ;
451462
452- if (m_creationModeId == IDM_CREATION_MODE_VISUAL_DCOMP)
463+ if (m_creationModeId == IDM_CREATION_MODE_VISUAL_DCOMP ||
464+ m_creationModeId == IDM_CREATION_MODE_TARGET_DCOMP)
453465 {
454466 HRESULT hr = DCompositionCreateDevice2 (nullptr , IID_PPV_ARGS (&m_dcompDevice));
455467 if (!SUCCEEDED (hr))
@@ -463,9 +475,10 @@ void AppWindow::InitializeWebView()
463475 return ;
464476 }
465477 }
478+ #ifdef USE_WEBVIEW2_WIN10
466479 else if (m_creationModeId == IDM_CREATION_MODE_VISUAL_WINCOMP)
467480 {
468- HRESULT hr = CreateWinCompCompositor ();
481+ HRESULT hr = TryCreateDispatcherQueue ();
469482 if (!SUCCEEDED (hr))
470483 {
471484 MessageBox (
@@ -476,10 +489,12 @@ void AppWindow::InitializeWebView()
476489 L" Create with Windowless WinComp Visual Failed" , MB_OK);
477490 return ;
478491 }
492+ m_wincompCompositor = winrtComp::Compositor ();
479493 }
494+ #endif
480495 // ! [CreateCoreWebView2EnvironmentWithOptions]
481- auto options = Microsoft::WRL::Make<CoreWebView2ExperimentalEnvironmentOptions >();
482- CHECK_FAILURE (options->put_IsSingleSignOnUsingOSPrimaryAccountEnabled (
496+ auto options = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions >();
497+ CHECK_FAILURE (options->put_AllowSingleSignOnUsingOSPrimaryAccount (
483498 m_AADSSOEnabled ? TRUE : FALSE ));
484499 if (!m_language.empty ())
485500 CHECK_FAILURE (options->put_Language (m_language.c_str ()));
@@ -516,7 +531,11 @@ HRESULT AppWindow::OnCreateEnvironmentCompleted(
516531
517532 auto webViewExperimentalEnvironment =
518533 m_webViewEnvironment.try_query <ICoreWebView2ExperimentalEnvironment>();
519- if (webViewExperimentalEnvironment && (m_dcompDevice || m_wincompHelper))
534+ #ifdef USE_WEBVIEW2_WIN10
535+ if (webViewExperimentalEnvironment && (m_dcompDevice || m_wincompCompositor))
536+ #else
537+ if (webViewExperimentalEnvironment && m_dcompDevice)
538+ #endif
520539 {
521540 CHECK_FAILURE (webViewExperimentalEnvironment->CreateCoreWebView2CompositionController (
522541 m_mainWindow,
@@ -565,7 +584,12 @@ HRESULT AppWindow::OnCreateCoreWebView2ControllerCompleted(HRESULT result, ICore
565584 NewComponent<SettingsComponent>(
566585 this , m_webViewEnvironment.get (), m_oldSettingsComponent.get ());
567586 m_oldSettingsComponent = nullptr ;
568- NewComponent<ViewComponent>(this , m_dcompDevice.get (), m_wincompHelper.get ());
587+ NewComponent<ViewComponent>(
588+ this , m_dcompDevice.get (),
589+ #ifdef USE_WEBVIEW2_WIN10
590+ m_wincompCompositor,
591+ #endif
592+ m_creationModeId == IDM_CREATION_MODE_TARGET_DCOMP);
569593 NewComponent<ControlComponent>(this , &m_toolbar);
570594
571595 // We have a few of our own event handlers to register here as well
@@ -694,11 +718,8 @@ void AppWindow::RegisterEventHandlers()
694718 CHECK_FAILURE (args->GetDeferral (&deferral));
695719 AppWindow* newAppWindow;
696720
697- wil::com_ptr<ICoreWebView2ExperimentalNewWindowRequestedEventArgs>
698- experimentalArgs;
699- CHECK_FAILURE (args->QueryInterface (IID_PPV_ARGS (&experimentalArgs)));
700- wil::com_ptr<ICoreWebView2ExperimentalWindowFeatures> windowFeatures;
701- CHECK_FAILURE (experimentalArgs->get_WindowFeatures (&windowFeatures));
721+ wil::com_ptr<ICoreWebView2WindowFeatures> windowFeatures;
722+ CHECK_FAILURE (args->get_WindowFeatures (&windowFeatures));
702723
703724 RECT windowRect = {0 };
704725 UINT32 left = 0 ;
@@ -731,7 +752,7 @@ void AppWindow::RegisterEventHandlers()
731752
732753 if (!useDefaultWindow)
733754 {
734- newAppWindow = new AppWindow (m_creationModeId, L" " , nullptr , true , windowRect, !!shouldHaveToolbar);
755+ newAppWindow = new AppWindow (m_creationModeId, L" " , false , nullptr , true , windowRect, !!shouldHaveToolbar);
735756 }
736757 else
737758 {
@@ -840,7 +861,7 @@ void AppWindow::CloseWebView(bool cleanupUserDataFolder)
840861 // developers specify userDataFolder during WebView environment
841862 // creation, they would need to pass in that explicit value here.
842863 // For more information about userDataFolder:
843- // https://docs.microsoft.com/microsoft-edge/webview2/reference/win32/0-9-538 /webview2-idl#createcorewebview2environmentwithoptions
864+ // https://docs.microsoft.com/microsoft-edge/webview2/reference/win32/0-9-622 /webview2-idl#createcorewebview2environmentwithoptions
844865 WCHAR userDataFolder[MAX_PATH] = L" " ;
845866 // Obtain the absolute path for relative paths that include "./" or "../"
846867 _wfullpath (
@@ -863,9 +884,6 @@ void AppWindow::CloseWebView(bool cleanupUserDataFolder)
863884
864885HRESULT AppWindow::DeleteFileRecursive (std::wstring path)
865886{
866- // Initialize COM as STA.
867- CHECK_FAILURE (CoInitializeEx (NULL , COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE));
868-
869887 wil::com_ptr<IFileOperation> fileOperation;
870888 CHECK_FAILURE (
871889 CoCreateInstance (CLSID_FileOperation, NULL , CLSCTX_ALL, IID_PPV_ARGS (&fileOperation)));
@@ -1030,40 +1048,53 @@ HRESULT AppWindow::DCompositionCreateDevice2(IUnknown* renderingDevice, REFIID r
10301048 return hr;
10311049}
10321050
1033- // Helper function that loads WebView2APISampleWinCompHelper.dll which provides an
1034- // IWinCompHelper abstraction for building a WinComp visual tree. The DLL is dynamically
1035- // loaded to create the helper interface and create the compositor. Not having a static
1036- // dependency on WebView2APISampleWinCompHelper.dll enables the sample app to run on
1037- // versions of Windows that don't support WinComp (since the DLL has a static dependency on
1038- // WinComp).
1039- HRESULT AppWindow::CreateWinCompCompositor ()
1051+ // WinRT APIs cannot run without a DispatcherQueue. This helper function creates a
1052+ // DispatcherQueueController (which instantiates a DispatcherQueue under the covers) that will
1053+ // manage tasks for the WinRT APIs. The DispatcherQueue implementation lives in
1054+ // CoreMessaging.dll Similar to dcomp.dll, we load CoreMessaging.dll dynamically so the sample
1055+ // app can run on versions of windows that don't have CoreMessaging.
1056+ HRESULT AppWindow::TryCreateDispatcherQueue ()
10401057{
1041- HRESULT hr = E_FAIL;
1042- static decltype (::CreateWinCompHelper)* fnCreateWinCompHelper = nullptr ;
1043- if (fnCreateWinCompHelper == nullptr )
1058+ namespace winSystem = winrt::Windows::System;
1059+
1060+ HRESULT hr = S_OK;
1061+ thread_local winSystem::DispatcherQueueController dispatcherQueueController{ nullptr };
1062+
1063+ if (dispatcherQueueController == nullptr )
10441064 {
1045- // Use SetErrorMode to ensure an error dialog doesn't pop up if the
1046- // WebView2APISampleWinCompHelper.dll fails to load for a missing dependency.
1047- SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
1048- HMODULE hmod = ::LoadLibraryEx (L" WebView2APISampleWinCompHelper.dll" , nullptr , 0 );
1049- if (hmod != nullptr )
1065+ hr = E_FAIL;
1066+ static decltype (::CreateDispatcherQueueController)* fnCreateDispatcherQueueController =
1067+ nullptr ;
1068+ if (fnCreateDispatcherQueueController == nullptr )
10501069 {
1051- fnCreateWinCompHelper = reinterpret_cast <decltype (::CreateWinCompHelper)*>(
1052- ::GetProcAddress (hmod, " CreateWinCompHelper" ));
1070+ HMODULE hmod = ::LoadLibraryEx (L" CoreMessaging.dll" , nullptr , 0 );
1071+ if (hmod != nullptr )
1072+ {
1073+ fnCreateDispatcherQueueController =
1074+ reinterpret_cast <decltype (::CreateDispatcherQueueController)*>(
1075+ ::GetProcAddress (hmod, " CreateDispatcherQueueController" ));
1076+ }
10531077 }
1054- SetErrorMode (0 );
1055- }
1056- if (fnCreateWinCompHelper != nullptr )
1057- {
1058- hr = fnCreateWinCompHelper (&m_wincompHelper);
1059- if (SUCCEEDED (hr))
1078+ if (fnCreateDispatcherQueueController != nullptr )
10601079 {
1061- hr = m_wincompHelper->CreateCompositor ();
1080+ winSystem::DispatcherQueueController controller{ nullptr };
1081+ DispatcherQueueOptions options
1082+ {
1083+ sizeof (DispatcherQueueOptions),
1084+ DQTYPE_THREAD_CURRENT,
1085+ DQTAT_COM_STA
1086+ };
1087+ hr = fnCreateDispatcherQueueController (
1088+ options, reinterpret_cast <ABI::Windows::System::IDispatcherQueueController**>(
1089+ winrt::put_abi (controller)));
1090+ dispatcherQueueController = controller;
10621091 }
10631092 }
1093+
10641094 return hr;
10651095}
10661096
1097+ #ifdef USE_WEBVIEW2_WIN10
10671098// ! [TextScaleChanged2]
10681099void AppWindow::OnTextScaleChanged (
10691100 winrt::Windows::UI::ViewManagement::UISettings const & settings,
@@ -1074,13 +1105,18 @@ void AppWindow::OnTextScaleChanged(
10741105 });
10751106}
10761107// ! [TextScaleChanged2]
1108+ #endif
10771109void AppWindow::UpdateCreationModeMenu ()
10781110{
10791111 HMENU hMenu = GetMenu (m_mainWindow);
10801112 CheckMenuRadioItem (
10811113 hMenu,
10821114 IDM_CREATION_MODE_WINDOWED,
1115+ #ifdef USE_WEBVIEW2_WIN10
10831116 IDM_CREATION_MODE_VISUAL_WINCOMP,
1117+ #else
1118+ IDM_CREATION_MODE_TARGET_DCOMP,
1119+ #endif
10841120 m_creationModeId,
10851121 MF_BYCOMMAND);
10861122}
@@ -1090,7 +1126,28 @@ double AppWindow::GetDpiScale()
10901126 return DpiUtil::GetDpiForWindow (m_mainWindow) * 1 .0f / USER_DEFAULT_SCREEN_DPI;
10911127}
10921128
1129+ #ifdef USE_WEBVIEW2_WIN10
10931130double AppWindow::GetTextScale ()
10941131{
10951132 return m_uiSettings ? m_uiSettings.TextScaleFactor () : 1 .0f ;
10961133}
1134+ #endif
1135+
1136+ void AppWindow::AddRef ()
1137+ {
1138+ InterlockedIncrement ((LONG *)&m_refCount);
1139+ }
1140+
1141+ void AppWindow::Release ()
1142+ {
1143+ uint32_t refCount = InterlockedDecrement ((LONG *)&m_refCount);
1144+ if (refCount == 0 )
1145+ {
1146+ delete this ;
1147+ }
1148+ }
1149+
1150+ void AppWindow::NotifyClosed ()
1151+ {
1152+ m_isClosed = true ;
1153+ }
0 commit comments