6
6
7
7
#include " AppWindow.h"
8
8
9
+ #include < DispatcherQueue.h>
9
10
#include < functional>
10
11
#include < string>
11
12
#include < vector>
12
13
#include < ShObjIdl_core.h>
13
14
#include < Shellapi.h>
14
15
#include < ShlObj_core.h>
16
+ #include < winrt/windows.system.h>
15
17
#include " App.h"
16
18
#include " CheckFailure.h"
17
19
#include " ControlComponent.h"
@@ -40,6 +42,7 @@ static constexpr int s_minNewWindowSize = 100;
40
42
AppWindow::AppWindow (
41
43
UINT creationModeId,
42
44
std::wstring initialUri,
45
+ bool isMainWindow,
43
46
std::function<void ()> webviewCreatedCallback,
44
47
bool customWindowRect,
45
48
RECT windowRect,
@@ -48,6 +51,9 @@ AppWindow::AppWindow(
48
51
m_initialUri(initialUri),
49
52
m_onWebViewFirstInitialized(webviewCreatedCallback)
50
53
{
54
+ // Initialize COM as STA.
55
+ CHECK_FAILURE (CoInitializeEx (NULL , COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE));
56
+
51
57
++s_appInstances;
52
58
53
59
WCHAR szTitle[s_maxLoadString]; // The title bar text
@@ -68,13 +74,15 @@ AppWindow::AppWindow(
68
74
69
75
SetWindowLongPtr (m_mainWindow, GWLP_USERDATA, (LONG_PTR)this );
70
76
77
+ #ifdef USE_WEBVIEW2_WIN10
71
78
// ! [TextScaleChanged1]
72
79
if (winrt::try_get_activation_factory<winrt::Windows::UI::ViewManagement::UISettings>())
73
80
{
74
81
m_uiSettings = winrt::Windows::UI::ViewManagement::UISettings ();
75
82
m_uiSettings.TextScaleFactorChanged ({ this , &AppWindow::OnTextScaleChanged });
76
83
}
77
84
// ! [TextScaleChanged1]
85
+ #endif
78
86
79
87
if (shouldHaveToolbar)
80
88
{
@@ -84,12 +92,10 @@ AppWindow::AppWindow(
84
92
UpdateCreationModeMenu ();
85
93
ShowWindow (m_mainWindow, g_nCmdShow);
86
94
UpdateWindow (m_mainWindow);
87
-
88
- RunAsync ([this ] {
89
- InitializeWebView ();
90
- });
95
+ RunAsync ([this ] {
96
+ InitializeWebView ();
97
+ });
91
98
}
92
-
93
99
// Register the Win32 window class for the app window.
94
100
PCWSTR AppWindow::GetWindowClass ()
95
101
{
@@ -194,7 +200,7 @@ bool AppWindow::HandleWindowMessage(
194
200
{
195
201
int retValue = 0 ;
196
202
SetWindowLongPtr (hWnd, GWLP_USERDATA, NULL );
197
- delete this ;
203
+ NotifyClosed () ;
198
204
if (--s_appInstances == 0 )
199
205
{
200
206
PostQuitMessage (retValue);
@@ -328,7 +334,10 @@ bool AppWindow::ExecuteAppCommands(WPARAM wParam, LPARAM lParam)
328
334
return true ;
329
335
case IDM_CREATION_MODE_WINDOWED:
330
336
case IDM_CREATION_MODE_VISUAL_DCOMP:
337
+ case IDM_CREATION_MODE_TARGET_DCOMP:
338
+ #ifdef USE_WEBVIEW2_WIN10
331
339
case IDM_CREATION_MODE_VISUAL_WINCOMP:
340
+ #endif
332
341
m_creationModeId = LOWORD (wParam);
333
342
UpdateCreationModeMenu ();
334
343
return true ;
@@ -446,10 +455,13 @@ void AppWindow::InitializeWebView()
446
455
// getting created which will apply the browser switches.
447
456
CloseWebView ();
448
457
m_dcompDevice = nullptr ;
449
- m_wincompHelper = nullptr ;
458
+ #ifdef USE_WEBVIEW2_WIN10
459
+ m_wincompCompositor = nullptr ;
460
+ #endif
450
461
LPCWSTR subFolder = nullptr ;
451
462
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)
453
465
{
454
466
HRESULT hr = DCompositionCreateDevice2 (nullptr , IID_PPV_ARGS (&m_dcompDevice));
455
467
if (!SUCCEEDED (hr))
@@ -463,9 +475,10 @@ void AppWindow::InitializeWebView()
463
475
return ;
464
476
}
465
477
}
478
+ #ifdef USE_WEBVIEW2_WIN10
466
479
else if (m_creationModeId == IDM_CREATION_MODE_VISUAL_WINCOMP)
467
480
{
468
- HRESULT hr = CreateWinCompCompositor ();
481
+ HRESULT hr = TryCreateDispatcherQueue ();
469
482
if (!SUCCEEDED (hr))
470
483
{
471
484
MessageBox (
@@ -476,10 +489,12 @@ void AppWindow::InitializeWebView()
476
489
L" Create with Windowless WinComp Visual Failed" , MB_OK);
477
490
return ;
478
491
}
492
+ m_wincompCompositor = winrtComp::Compositor ();
479
493
}
494
+ #endif
480
495
// ! [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 (
483
498
m_AADSSOEnabled ? TRUE : FALSE ));
484
499
if (!m_language.empty ())
485
500
CHECK_FAILURE (options->put_Language (m_language.c_str ()));
@@ -516,7 +531,11 @@ HRESULT AppWindow::OnCreateEnvironmentCompleted(
516
531
517
532
auto webViewExperimentalEnvironment =
518
533
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
520
539
{
521
540
CHECK_FAILURE (webViewExperimentalEnvironment->CreateCoreWebView2CompositionController (
522
541
m_mainWindow,
@@ -565,7 +584,12 @@ HRESULT AppWindow::OnCreateCoreWebView2ControllerCompleted(HRESULT result, ICore
565
584
NewComponent<SettingsComponent>(
566
585
this , m_webViewEnvironment.get (), m_oldSettingsComponent.get ());
567
586
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);
569
593
NewComponent<ControlComponent>(this , &m_toolbar);
570
594
571
595
// We have a few of our own event handlers to register here as well
@@ -694,11 +718,8 @@ void AppWindow::RegisterEventHandlers()
694
718
CHECK_FAILURE (args->GetDeferral (&deferral));
695
719
AppWindow* newAppWindow;
696
720
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));
702
723
703
724
RECT windowRect = {0 };
704
725
UINT32 left = 0 ;
@@ -731,7 +752,7 @@ void AppWindow::RegisterEventHandlers()
731
752
732
753
if (!useDefaultWindow)
733
754
{
734
- newAppWindow = new AppWindow (m_creationModeId, L" " , nullptr , true , windowRect, !!shouldHaveToolbar);
755
+ newAppWindow = new AppWindow (m_creationModeId, L" " , false , nullptr , true , windowRect, !!shouldHaveToolbar);
735
756
}
736
757
else
737
758
{
@@ -840,7 +861,7 @@ void AppWindow::CloseWebView(bool cleanupUserDataFolder)
840
861
// developers specify userDataFolder during WebView environment
841
862
// creation, they would need to pass in that explicit value here.
842
863
// 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
844
865
WCHAR userDataFolder[MAX_PATH] = L" " ;
845
866
// Obtain the absolute path for relative paths that include "./" or "../"
846
867
_wfullpath (
@@ -863,9 +884,6 @@ void AppWindow::CloseWebView(bool cleanupUserDataFolder)
863
884
864
885
HRESULT AppWindow::DeleteFileRecursive (std::wstring path)
865
886
{
866
- // Initialize COM as STA.
867
- CHECK_FAILURE (CoInitializeEx (NULL , COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE));
868
-
869
887
wil::com_ptr<IFileOperation> fileOperation;
870
888
CHECK_FAILURE (
871
889
CoCreateInstance (CLSID_FileOperation, NULL , CLSCTX_ALL, IID_PPV_ARGS (&fileOperation)));
@@ -1030,40 +1048,53 @@ HRESULT AppWindow::DCompositionCreateDevice2(IUnknown* renderingDevice, REFIID r
1030
1048
return hr;
1031
1049
}
1032
1050
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 ()
1040
1057
{
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 )
1044
1064
{
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 )
1050
1069
{
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
+ }
1053
1077
}
1054
- SetErrorMode (0 );
1055
- }
1056
- if (fnCreateWinCompHelper != nullptr )
1057
- {
1058
- hr = fnCreateWinCompHelper (&m_wincompHelper);
1059
- if (SUCCEEDED (hr))
1078
+ if (fnCreateDispatcherQueueController != nullptr )
1060
1079
{
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;
1062
1091
}
1063
1092
}
1093
+
1064
1094
return hr;
1065
1095
}
1066
1096
1097
+ #ifdef USE_WEBVIEW2_WIN10
1067
1098
// ! [TextScaleChanged2]
1068
1099
void AppWindow::OnTextScaleChanged (
1069
1100
winrt::Windows::UI::ViewManagement::UISettings const & settings,
@@ -1074,13 +1105,18 @@ void AppWindow::OnTextScaleChanged(
1074
1105
});
1075
1106
}
1076
1107
// ! [TextScaleChanged2]
1108
+ #endif
1077
1109
void AppWindow::UpdateCreationModeMenu ()
1078
1110
{
1079
1111
HMENU hMenu = GetMenu (m_mainWindow);
1080
1112
CheckMenuRadioItem (
1081
1113
hMenu,
1082
1114
IDM_CREATION_MODE_WINDOWED,
1115
+ #ifdef USE_WEBVIEW2_WIN10
1083
1116
IDM_CREATION_MODE_VISUAL_WINCOMP,
1117
+ #else
1118
+ IDM_CREATION_MODE_TARGET_DCOMP,
1119
+ #endif
1084
1120
m_creationModeId,
1085
1121
MF_BYCOMMAND);
1086
1122
}
@@ -1090,7 +1126,28 @@ double AppWindow::GetDpiScale()
1090
1126
return DpiUtil::GetDpiForWindow (m_mainWindow) * 1 .0f / USER_DEFAULT_SCREEN_DPI;
1091
1127
}
1092
1128
1129
+ #ifdef USE_WEBVIEW2_WIN10
1093
1130
double AppWindow::GetTextScale ()
1094
1131
{
1095
1132
return m_uiSettings ? m_uiSettings.TextScaleFactor () : 1 .0f ;
1096
1133
}
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