I think this merges the-whole-thing
into this branch. The remote control doesn't render right, but I think that's because the actual HEAD of all this work is in connection-factory
This commit is contained in:
parent
9f2d40614b
commit
d8dcb6f570
|
@ -3,9 +3,11 @@
|
|||
|
||||
#include "pch.h"
|
||||
#include "MyPage.h"
|
||||
#include "MySettings.h"
|
||||
#include <LibraryResources.h>
|
||||
#include "MyPage.g.cpp"
|
||||
#include "MySettings.h"
|
||||
#include "..\..\..\src\cascadia\UnitTests_Control\MockControlSettings.h"
|
||||
#include "..\..\..\src\types\inc\utils.hpp"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
using namespace winrt::Microsoft::Terminal;
|
||||
|
@ -26,24 +28,151 @@ namespace winrt::SampleApp::implementation
|
|||
|
||||
void MyPage::Create()
|
||||
{
|
||||
auto settings = winrt::make_self<implementation::MySettings>();
|
||||
TerminalConnection::EchoConnection conn{};
|
||||
auto settings = winrt::make_self<ControlUnitTests::MockControlSettings>();
|
||||
|
||||
auto connectionSettings{ TerminalConnection::ConptyConnection::CreateSettings(L"cmd.exe /k echo This TermControl is hosted in-proc...",
|
||||
winrt::hstring{},
|
||||
L"",
|
||||
nullptr,
|
||||
32,
|
||||
80,
|
||||
winrt::guid()) };
|
||||
|
||||
// "Microsoft.Terminal.TerminalConnection.ConptyConnection"
|
||||
winrt::hstring myClass{ winrt::name_of<TerminalConnection::ConptyConnection>() };
|
||||
TerminalConnection::ConnectionInformation connectInfo{ myClass, connectionSettings };
|
||||
|
||||
TerminalConnection::ITerminalConnection conn{ TerminalConnection::ConnectionInformation::CreateConnection(connectInfo) };
|
||||
Control::TermControl control{ *settings, conn };
|
||||
|
||||
InProcContent().Children().Append(control);
|
||||
|
||||
// Once the control loads (and not before that), write some text for debugging:
|
||||
control.Initialized([conn](auto&&, auto&&) {
|
||||
conn.WriteInput(L"This TermControl is hosted in-proc...");
|
||||
});
|
||||
}
|
||||
|
||||
static wil::unique_process_information _createHostClassProcess(const winrt::guid& g)
|
||||
{
|
||||
auto guidStr{ ::Microsoft::Console::Utils::GuidToString(g) };
|
||||
std::wstring commandline{ fmt::format(L"windowsterminal.exe --content {}", guidStr) };
|
||||
STARTUPINFO siOne{ 0 };
|
||||
siOne.cb = sizeof(STARTUPINFOW);
|
||||
wil::unique_process_information piOne;
|
||||
auto succeeded = CreateProcessW(
|
||||
nullptr,
|
||||
commandline.data(),
|
||||
nullptr, // lpProcessAttributes
|
||||
nullptr, // lpThreadAttributes
|
||||
false, // bInheritHandles
|
||||
CREATE_UNICODE_ENVIRONMENT, // dwCreationFlags
|
||||
nullptr, // lpEnvironment
|
||||
nullptr, // startingDirectory
|
||||
&siOne, // lpStartupInfo
|
||||
&piOne // lpProcessInformation
|
||||
);
|
||||
THROW_IF_WIN32_BOOL_FALSE(succeeded);
|
||||
// if (!succeeded)
|
||||
// {
|
||||
// printf("Failed to create host process\n");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Ooof this is dumb, but we need a sleep here to make the server starts.
|
||||
// That's _sub par_. Maybe we could use the host's stdout to have them emit
|
||||
// a byte when they're set up?
|
||||
Sleep(2000);
|
||||
|
||||
// TODO MONDAY - It seems like it takes conhost too long to start up to
|
||||
// host the ScratchWinRTServer that even a sleep 100 is too short. However,
|
||||
// any longer, and XAML will just crash, because some frame took too long.
|
||||
// So we _need_ to do the "have the server explicitly tell us it's ready"
|
||||
// thing, and maybe also do it on a bg thread (and signal to the UI thread
|
||||
// that it can attach now)
|
||||
|
||||
return std::move(piOne);
|
||||
}
|
||||
|
||||
winrt::fire_and_forget MyPage::CreateClicked(const IInspectable& sender, const Windows::UI::Xaml::Input::TappedRoutedEventArgs& eventArgs)
|
||||
{
|
||||
auto guidString = GuidInput().Text();
|
||||
|
||||
// Capture calling context.
|
||||
winrt::apartment_context ui_thread;
|
||||
co_await winrt::resume_background();
|
||||
|
||||
auto canConvert = guidString.size() == 38 && guidString.front() == '{' && guidString.back() == '}';
|
||||
bool attached = false;
|
||||
winrt::guid contentGuid{ ::Microsoft::Console::Utils::CreateGuid() };
|
||||
|
||||
if (canConvert)
|
||||
{
|
||||
GUID result{};
|
||||
if (SUCCEEDED(IIDFromString(guidString.c_str(), &result)))
|
||||
{
|
||||
contentGuid = result;
|
||||
attached = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!attached)
|
||||
{
|
||||
// 2. Spawn a Server.exe, with the guid on the commandline
|
||||
auto piContent{ std::move(_createHostClassProcess(contentGuid)) };
|
||||
}
|
||||
|
||||
Control::ContentProcess content = create_instance<Control::ContentProcess>(contentGuid, CLSCTX_LOCAL_SERVER);
|
||||
|
||||
TerminalConnection::ITerminalConnection conn{ nullptr };
|
||||
Control::IControlSettings settings{ nullptr };
|
||||
|
||||
settings = *winrt::make_self<implementation::MySettings>();
|
||||
|
||||
if (!attached)
|
||||
{
|
||||
conn = TerminalConnection::EchoConnection{};
|
||||
// settings = *winrt::make_self<implementation::MySettings>();
|
||||
content.Initialize(settings, conn);
|
||||
}
|
||||
|
||||
// Switch back to the UI thread.
|
||||
co_await ui_thread;
|
||||
|
||||
Control::TermControl control{ contentGuid, settings, conn };
|
||||
|
||||
OutOfProcContent().Children().Append(control);
|
||||
|
||||
if (!attached)
|
||||
{
|
||||
auto guidStr{ ::Microsoft::Console::Utils::GuidToString(contentGuid) };
|
||||
GuidInput().Text(guidStr);
|
||||
}
|
||||
}
|
||||
|
||||
/*winrt::fire_and_forget MyPage::_attachToContent(winrt::guid contentGuid)
|
||||
{
|
||||
Control::ContentProcess content = create_instance<Control::ContentProcess>(contentGuid, CLSCTX_LOCAL_SERVER);
|
||||
|
||||
}*/
|
||||
|
||||
winrt::fire_and_forget MyPage::CreateOutOfProcTerminal()
|
||||
{
|
||||
// 1. Generate a GUID.
|
||||
winrt::guid contentGuid{ ::Microsoft::Console::Utils::CreateGuid() };
|
||||
|
||||
// Capture calling context.
|
||||
winrt::apartment_context ui_thread;
|
||||
co_await winrt::resume_background();
|
||||
|
||||
// 2. Spawn a Server.exe, with the guid on the commandline
|
||||
auto piContent{ std::move(_createHostClassProcess(contentGuid)) };
|
||||
|
||||
Control::ContentProcess content = create_instance<Control::ContentProcess>(contentGuid, CLSCTX_LOCAL_SERVER);
|
||||
|
||||
TerminalConnection::EchoConnection conn{};
|
||||
auto settings = winrt::make_self<implementation::MySettings>();
|
||||
Control::IControlSettings s = *settings;
|
||||
|
||||
if (s)
|
||||
{
|
||||
content.Initialize(s, conn);
|
||||
|
||||
// Switch back to the UI thread.
|
||||
co_await ui_thread;
|
||||
|
||||
Control::TermControl control{ contentGuid, s, conn };
|
||||
|
||||
OutOfProcContent().Children().Append(control);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
|
|
@ -16,6 +16,9 @@ namespace winrt::SampleApp::implementation
|
|||
void Create();
|
||||
|
||||
hstring Title();
|
||||
winrt::fire_and_forget CreateOutOfProcTerminal();
|
||||
|
||||
winrt::fire_and_forget CreateClicked(const IInspectable& sender, const Windows::UI::Xaml::Input::TappedRoutedEventArgs& eventArgs);
|
||||
|
||||
private:
|
||||
friend struct MyPageT<MyPage>; // for Xaml to bind events
|
||||
|
|
|
@ -23,7 +23,9 @@
|
|||
<TextBox x:Name="GuidInput"
|
||||
Width="400"
|
||||
PlaceholderText="{}{guid here}" />
|
||||
<Button Grid.Row="0">
|
||||
<Button x:Name="CreateOopControl"
|
||||
Grid.Row="0"
|
||||
Tapped="CreateClicked">
|
||||
Create
|
||||
</Button>
|
||||
|
||||
|
@ -53,8 +55,6 @@
|
|||
VerticalAlignment="Stretch"
|
||||
Background="#0000ff" />
|
||||
|
||||
|
||||
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
|
|
|
@ -10,6 +10,9 @@ Licensed under the MIT license.
|
|||
#include <conattrs.hpp>
|
||||
#include "MySettings.g.h"
|
||||
|
||||
using IFontFeatureMap = winrt::Windows::Foundation::Collections::IMap<winrt::hstring, uint32_t>;
|
||||
using IFontAxesMap = winrt::Windows::Foundation::Collections::IMap<winrt::hstring, float>;
|
||||
|
||||
namespace winrt::SampleApp::implementation
|
||||
{
|
||||
struct MySettings : MySettingsT<MySettings>
|
||||
|
@ -41,6 +44,7 @@ namespace winrt::SampleApp::implementation
|
|||
winrt::Microsoft::Terminal::Core::ICoreAppearance UnfocusedAppearance() { return {}; };
|
||||
|
||||
WINRT_PROPERTY(bool, TrimBlockSelection, false);
|
||||
WINRT_PROPERTY(bool, DetectURLs, true);
|
||||
// ------------------------ End of Core Settings -----------------------
|
||||
|
||||
WINRT_PROPERTY(winrt::hstring, ProfileName);
|
||||
|
@ -78,7 +82,8 @@ namespace winrt::SampleApp::implementation
|
|||
|
||||
WINRT_PROPERTY(winrt::hstring, PixelShaderPath);
|
||||
|
||||
WINRT_PROPERTY(bool, DetectURLs, true);
|
||||
WINRT_PROPERTY(IFontFeatureMap, FontFeatures);
|
||||
WINRT_PROPERTY(IFontAxesMap, FontAxes);
|
||||
|
||||
private:
|
||||
std::array<winrt::Microsoft::Terminal::Core::Color, COLOR_TABLE_SIZE> _ColorTable;
|
||||
|
|
60
src/cascadia/TerminalControl/ContentProcess.cpp
Normal file
60
src/cascadia/TerminalControl/ContentProcess.cpp
Normal file
|
@ -0,0 +1,60 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "ContentProcess.h"
|
||||
#include "ContentProcess.g.cpp"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
{
|
||||
ContentProcess::ContentProcess() {}
|
||||
|
||||
void ContentProcess::Initialize(Control::IControlSettings settings, TerminalConnection::ITerminalConnection connection)
|
||||
{
|
||||
_interactivity = winrt::make<implementation::ControlInteractivity>(settings, connection);
|
||||
}
|
||||
|
||||
Control::ControlInteractivity ContentProcess::GetInteractivity()
|
||||
{
|
||||
return _interactivity;
|
||||
}
|
||||
|
||||
uint64_t ContentProcess::RequestSwapChainHandle(const uint64_t pid)
|
||||
{
|
||||
auto ourPid = GetCurrentProcessId();
|
||||
HANDLE ourHandle = reinterpret_cast<HANDLE>(_interactivity.Core().SwapChainHandle());
|
||||
if (pid == ourPid)
|
||||
{
|
||||
return reinterpret_cast<uint64_t>(ourHandle);
|
||||
}
|
||||
|
||||
wil::unique_handle hWindowProcess{ OpenProcess(PROCESS_ALL_ACCESS,
|
||||
FALSE,
|
||||
static_cast<DWORD>(pid)) };
|
||||
if (hWindowProcess.get() == nullptr)
|
||||
{
|
||||
const auto gle = GetLastError();
|
||||
gle;
|
||||
// TODO! tracelog an error here
|
||||
return 0;
|
||||
}
|
||||
|
||||
HANDLE theirHandle{ nullptr };
|
||||
BOOL success = DuplicateHandle(GetCurrentProcess(),
|
||||
ourHandle,
|
||||
hWindowProcess.get(),
|
||||
&theirHandle,
|
||||
0,
|
||||
FALSE,
|
||||
DUPLICATE_SAME_ACCESS);
|
||||
if (!success)
|
||||
{
|
||||
const auto gle = GetLastError();
|
||||
gle;
|
||||
// TODO! tracelog an error here
|
||||
return 0;
|
||||
}
|
||||
return reinterpret_cast<uint64_t>(theirHandle);
|
||||
}
|
||||
|
||||
}
|
28
src/cascadia/TerminalControl/ContentProcess.h
Normal file
28
src/cascadia/TerminalControl/ContentProcess.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ContentProcess.g.h"
|
||||
#include "ControlInteractivity.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
{
|
||||
struct ContentProcess : ContentProcessT<ContentProcess>
|
||||
|
||||
{
|
||||
ContentProcess();
|
||||
void Initialize(Control::IControlSettings settings, TerminalConnection::ITerminalConnection connection);
|
||||
Control::ControlInteractivity GetInteractivity();
|
||||
|
||||
uint64_t RequestSwapChainHandle(const uint64_t pid);
|
||||
|
||||
private:
|
||||
Control::ControlInteractivity _interactivity{ nullptr };
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Control::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(ContentProcess);
|
||||
}
|
19
src/cascadia/TerminalControl/ContentProcess.idl
Normal file
19
src/cascadia/TerminalControl/ContentProcess.idl
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "ControlInteractivity.idl";
|
||||
|
||||
namespace Microsoft.Terminal.Control
|
||||
{
|
||||
runtimeclass ContentProcess {
|
||||
|
||||
ContentProcess();
|
||||
|
||||
void Initialize(IControlSettings settings,
|
||||
Microsoft.Terminal.TerminalConnection.ITerminalConnection connection);
|
||||
|
||||
ControlInteractivity GetInteractivity();
|
||||
|
||||
UInt64 RequestSwapChainHandle(UInt64 pid);
|
||||
};
|
||||
}
|
|
@ -50,7 +50,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
{
|
||||
TermControl::TermControl(IControlSettings settings,
|
||||
TerminalConnection::ITerminalConnection connection) :
|
||||
TermControl(winrt::guid{}, settings, connection) {}
|
||||
|
||||
TermControl::TermControl(winrt::guid contentGuid,
|
||||
IControlSettings settings,
|
||||
TerminalConnection::ITerminalConnection connection) :
|
||||
_initializedTerminal{ false },
|
||||
_settings{ settings },
|
||||
_closing{ false },
|
||||
_isInternalScrollBarUpdate{ false },
|
||||
_autoScrollVelocity{ 0 },
|
||||
_autoScrollingPointerPoint{ std::nullopt },
|
||||
|
@ -62,7 +69,19 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
{
|
||||
InitializeComponent();
|
||||
|
||||
_interactivity = winrt::make<implementation::ControlInteractivity>(settings, connection);
|
||||
if (contentGuid != winrt::guid{})
|
||||
{
|
||||
_contentProc = create_instance<Control::ContentProcess>(contentGuid, CLSCTX_LOCAL_SERVER);
|
||||
if (_contentProc != nullptr)
|
||||
{
|
||||
_interactivity = _contentProc.GetInteractivity();
|
||||
}
|
||||
}
|
||||
|
||||
if (_interactivity == nullptr)
|
||||
{
|
||||
_interactivity = winrt::make<implementation::ControlInteractivity>(settings, connection);
|
||||
}
|
||||
_core = _interactivity.Core();
|
||||
|
||||
// These events might all be triggered by the connection, but that
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
{
|
||||
struct TermControl : TermControlT<TermControl>
|
||||
{
|
||||
TermControl(winrt::guid contentGuid, IControlSettings settings, TerminalConnection::ITerminalConnection connection);
|
||||
TermControl(IControlSettings settings, TerminalConnection::ITerminalConnection connection);
|
||||
|
||||
winrt::fire_and_forget UpdateSettings();
|
||||
|
@ -145,6 +146,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
Control::TermControlAutomationPeer _automationPeer{ nullptr };
|
||||
Control::ControlInteractivity _interactivity{ nullptr };
|
||||
Control::ControlCore _core{ nullptr };
|
||||
Control::ContentProcess _contentProc{ nullptr };
|
||||
|
||||
winrt::com_ptr<SearchBoxControl> _searchBox;
|
||||
|
||||
|
|
|
@ -15,6 +15,10 @@ namespace Microsoft.Terminal.Control
|
|||
IMouseWheelListener,
|
||||
ICoreState
|
||||
{
|
||||
TermControl(Guid contentGuid,
|
||||
IControlSettings settings,
|
||||
Microsoft.Terminal.TerminalConnection.ITerminalConnection connection);
|
||||
|
||||
TermControl(IControlSettings settings,
|
||||
Microsoft.Terminal.TerminalConnection.ITerminalConnection connection);
|
||||
|
||||
|
|
|
@ -28,6 +28,9 @@
|
|||
<!-- ========================= Headers ======================== -->
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="ContentProcess.h">
|
||||
<DependentUpon>ContentProcess.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ControlCore.h">
|
||||
<DependentUpon>ControlCore.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
|
@ -65,6 +68,9 @@
|
|||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ContentProcess.cpp">
|
||||
<DependentUpon>ContentProcess.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ControlCore.cpp">
|
||||
<DependentUpon>ControlCore.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
|
@ -101,6 +107,7 @@
|
|||
</ItemGroup>
|
||||
<!-- ========================= idl Files ======================== -->
|
||||
<ItemGroup>
|
||||
<Midl Include="ContentProcess.idl" />
|
||||
<Midl Include="ControlCore.idl" />
|
||||
<Midl Include="ControlInteractivity.idl" />
|
||||
<Midl Include="ICoreState.idl" />
|
||||
|
|
|
@ -83,6 +83,96 @@ static bool _messageIsAltKeyup(const MSG& message)
|
|||
return (message.message == WM_KEYUP || message.message == WM_SYSKEYUP) && message.wParam == VK_MENU;
|
||||
}
|
||||
|
||||
static bool checkIfContentProcess(winrt::guid& contentProcessGuid)
|
||||
{
|
||||
std::vector<std::wstring> args;
|
||||
|
||||
if (auto commandline{ GetCommandLineW() })
|
||||
{
|
||||
int argc = 0;
|
||||
|
||||
// Get the argv, and turn them into a hstring array to pass to the app.
|
||||
wil::unique_any<LPWSTR*, decltype(&::LocalFree), ::LocalFree> argv{ CommandLineToArgvW(commandline, &argc) };
|
||||
if (argv)
|
||||
{
|
||||
for (auto& elem : wil::make_range(argv.get(), argc))
|
||||
{
|
||||
args.emplace_back(elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (args.size() > 2 && args.at(1) == L"--content")
|
||||
{
|
||||
auto& guidString{ args.at(2) };
|
||||
auto canConvert = guidString.length() == 38 && guidString.front() == '{' && guidString.back() == '}';
|
||||
if (canConvert)
|
||||
{
|
||||
GUID result{};
|
||||
THROW_IF_FAILED(IIDFromString(guidString.c_str(), &result));
|
||||
contentProcessGuid = result;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::mutex m;
|
||||
std::condition_variable cv;
|
||||
bool dtored = false;
|
||||
winrt::weak_ref<winrt::Microsoft::Terminal::Control::ContentProcess> g_weak{ nullptr };
|
||||
|
||||
struct HostClassFactory : implements<HostClassFactory, IClassFactory>
|
||||
{
|
||||
HostClassFactory(winrt::guid g) :
|
||||
_guid{ g } {};
|
||||
|
||||
HRESULT __stdcall CreateInstance(IUnknown* outer, GUID const& iid, void** result) noexcept final
|
||||
{
|
||||
*result = nullptr;
|
||||
if (outer)
|
||||
{
|
||||
return CLASS_E_NOAGGREGATION;
|
||||
}
|
||||
|
||||
if (!g_weak)
|
||||
{
|
||||
winrt::Microsoft::Terminal::Control::ContentProcess strong{}; // = winrt::make<winrt::Microsoft::Terminal::Control::ContentProcess>();
|
||||
winrt::weak_ref<winrt::Microsoft::Terminal::Control::ContentProcess> weak{ strong };
|
||||
g_weak = weak;
|
||||
return strong.as(iid, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto strong = g_weak.get();
|
||||
return strong.as(iid, result);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT __stdcall LockServer(BOOL) noexcept final
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
winrt::guid _guid;
|
||||
};
|
||||
|
||||
static void doContentProcessThing(const winrt::guid& contentProcessGuid)
|
||||
{
|
||||
// !! LOAD BEARING !! - important to be a MTA
|
||||
winrt::init_apartment();
|
||||
|
||||
DWORD registrationHostClass{};
|
||||
check_hresult(CoRegisterClassObject(contentProcessGuid,
|
||||
make<HostClassFactory>(contentProcessGuid).get(),
|
||||
CLSCTX_LOCAL_SERVER,
|
||||
REGCLS_MULTIPLEUSE,
|
||||
®istrationHostClass));
|
||||
|
||||
std::unique_lock<std::mutex> lk(m);
|
||||
cv.wait(lk, [] { return dtored; });
|
||||
}
|
||||
|
||||
int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
|
||||
{
|
||||
TraceLoggingRegister(g_hWindowsTerminalProvider);
|
||||
|
@ -106,6 +196,17 @@ int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
|
|||
// should choose and install the correct one from the bundle.
|
||||
EnsureNativeArchitecture();
|
||||
|
||||
winrt::guid contentProcessGuid{};
|
||||
if (checkIfContentProcess(contentProcessGuid))
|
||||
{
|
||||
doContentProcessThing(contentProcessGuid);
|
||||
// If we were told to not have a window, exit early. Make sure to use
|
||||
// ExitProcess to die here. If you try just `return 0`, then
|
||||
// the XAML app host will crash during teardown. ExitProcess avoids
|
||||
// that.
|
||||
ExitProcess(0);
|
||||
}
|
||||
|
||||
// Make sure to call this so we get WM_POINTER messages.
|
||||
EnableMouseInPointer(true);
|
||||
|
||||
|
|
Loading…
Reference in a new issue