mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-08 15:21:01 +00:00
Compare commits
1 Commits
msbuildcac
...
dev/lhecke
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4120b0aa01 |
@@ -75,10 +75,12 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
// If multiple peasants are added concurrently we keep trying to update
|
||||
// until we get to set the new id.
|
||||
uint64_t current;
|
||||
uint64_t next;
|
||||
do
|
||||
{
|
||||
current = _nextPeasantID.load(std::memory_order_relaxed);
|
||||
} while (current <= providedID && !_nextPeasantID.compare_exchange_weak(current, providedID + 1, std::memory_order_relaxed));
|
||||
next = std::max(current, providedID) + 1;
|
||||
} while (!_nextPeasantID.compare_exchange_weak(current, next, std::memory_order_relaxed));
|
||||
}
|
||||
|
||||
auto newPeasantsId = peasant.GetID();
|
||||
@@ -111,7 +113,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
|
||||
_WindowCreatedHandlers(nullptr, nullptr);
|
||||
_WindowCreatedHandlers(*this, winrt::box_value(newPeasantsId));
|
||||
return newPeasantsId;
|
||||
}
|
||||
catch (...)
|
||||
@@ -207,7 +209,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
std::unique_lock lock{ _peasantsMutex };
|
||||
_peasants.erase(peasantId);
|
||||
}
|
||||
_WindowClosedHandlers(nullptr, nullptr);
|
||||
_WindowClosedHandlers(*this, winrt::box_value(peasantId));
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
||||
@@ -354,8 +354,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
args.ShowWindowCommand(),
|
||||
args.CurrentEnvironment()));
|
||||
|
||||
_monarch.AddPeasant(*p);
|
||||
|
||||
p->GetWindowLayoutRequested({ get_weak(), &WindowManager::_GetWindowLayoutRequestedHandlers });
|
||||
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
@@ -367,6 +365,14 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
return *p;
|
||||
}
|
||||
|
||||
void WindowManager::AddPeasant(const Remoting::Peasant& peasant) const
|
||||
{
|
||||
if (_monarch)
|
||||
{
|
||||
_monarch.AddPeasant(peasant);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowManager::SignalClose(const Remoting::Peasant& peasant)
|
||||
{
|
||||
if (_monarch)
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
winrt::Microsoft::Terminal::Remoting::ProposeCommandlineResult ProposeCommandline(const winrt::Microsoft::Terminal::Remoting::CommandlineArgs& args, const bool isolatedMode);
|
||||
Remoting::Peasant CreatePeasant(const Remoting::WindowRequestedArgs& args);
|
||||
|
||||
void AddPeasant(const Remoting::Peasant& peasant) const;
|
||||
void SignalClose(const Remoting::Peasant& peasant);
|
||||
void SummonWindow(const Remoting::SummonWindowSelectionArgs& args);
|
||||
void SummonAllWindows();
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace Microsoft.Terminal.Remoting
|
||||
ProposeCommandlineResult ProposeCommandline(CommandlineArgs args, Boolean isolatedMode);
|
||||
Peasant CreatePeasant(WindowRequestedArgs args);
|
||||
|
||||
void AddPeasant(Peasant p);
|
||||
void SignalClose(Peasant p);
|
||||
|
||||
void UpdateActiveTabTitle(String title, Peasant p);
|
||||
|
||||
@@ -166,7 +166,8 @@ void AppHost::_HandleCommandlineArgs(const Remoting::WindowRequestedArgs& window
|
||||
|
||||
if (_windowLogic.ShouldExitEarly())
|
||||
{
|
||||
ExitThread(result);
|
||||
TerminateProcess(GetCurrentProcess(), gsl::narrow_cast<UINT>(result));
|
||||
__assume(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -538,23 +539,10 @@ void AppHost::LastTabClosed(const winrt::Windows::Foundation::IInspectable& /*se
|
||||
{
|
||||
_windowLogic.ClearPersistedWindowState();
|
||||
}
|
||||
|
||||
// If the user closes the last tab, in the last window, _by closing the tab_
|
||||
// (not by closing the whole window), we need to manually persist an empty
|
||||
// window state here. That will cause the terminal to re-open with the usual
|
||||
// settings (not the persisted state)
|
||||
if (args.ClearPersistedState() &&
|
||||
_windowManager.GetNumberOfPeasants() == 1)
|
||||
{
|
||||
_windowLogic.ClearPersistedWindowState();
|
||||
}
|
||||
|
||||
// Remove ourself from the list of peasants so that we aren't included in
|
||||
// any future requests. This will also mean we block until any existing
|
||||
// event handler finishes.
|
||||
_windowManager.SignalClose(_peasant);
|
||||
|
||||
PostQuitMessage(0);
|
||||
}
|
||||
|
||||
LaunchPosition AppHost::_GetWindowLaunchPosition()
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pch.h"
|
||||
#include "NonClientIslandWindow.h"
|
||||
#include "NotificationIcon.h"
|
||||
|
||||
@@ -77,7 +77,7 @@ void IslandWindow::Refrigerate() noexcept
|
||||
|
||||
_pfnCreateCallback = nullptr;
|
||||
_pfnSnapDimensionCallback = nullptr;
|
||||
|
||||
|
||||
_rootGrid.Children().Clear();
|
||||
ShowWindow(_window.get(), SW_HIDE);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,11 @@ NonClientIslandWindow::NonClientIslandWindow(const ElementTheme& requestedTheme)
|
||||
{
|
||||
}
|
||||
|
||||
NonClientIslandWindow::~NonClientIslandWindow()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void NonClientIslandWindow::Close()
|
||||
{
|
||||
// Avoid further callbacks into XAML/WinUI-land after we've Close()d the DesktopWindowXamlSource
|
||||
|
||||
@@ -30,6 +30,7 @@ public:
|
||||
static constexpr const int topBorderVisibleHeight = 1;
|
||||
|
||||
NonClientIslandWindow(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme) noexcept;
|
||||
~NonClientIslandWindow() override;
|
||||
|
||||
void Refrigerate() noexcept override;
|
||||
|
||||
|
||||
@@ -5,14 +5,10 @@
|
||||
#include "WindowEmperor.h"
|
||||
|
||||
#include "../inc/WindowingBehavior.h"
|
||||
|
||||
#include "../../types/inc/utils.hpp"
|
||||
|
||||
#include "../WinRTUtils/inc/WtExeUtils.h"
|
||||
|
||||
#include "resource.h"
|
||||
#include "NotificationIcon.h"
|
||||
#include <til/env.h>
|
||||
|
||||
using namespace winrt;
|
||||
using namespace winrt::Microsoft::Terminal;
|
||||
@@ -38,20 +34,6 @@ WindowEmperor::WindowEmperor() noexcept :
|
||||
});
|
||||
|
||||
_dispatcher = winrt::Windows::System::DispatcherQueue::GetForCurrentThread();
|
||||
|
||||
// BODGY
|
||||
//
|
||||
// There's a mysterious crash in XAML on Windows 10 if you just let the App
|
||||
// get dtor'd. By all accounts, it doesn't make sense. To mitigate this, we
|
||||
// need to intentionally leak a reference to our App. Crazily, if you just
|
||||
// let the app get cleaned up with the rest of the process when the process
|
||||
// exits, then it doesn't crash. But if you let it get explicitly dtor'd, it
|
||||
// absolutely will crash on exit.
|
||||
//
|
||||
// GH#15410 has more details.
|
||||
|
||||
auto a{ _app };
|
||||
::winrt::detach_abi(a);
|
||||
}
|
||||
|
||||
WindowEmperor::~WindowEmperor()
|
||||
@@ -82,7 +64,7 @@ void _buildArgsFromCommandline(std::vector<winrt::hstring>& args)
|
||||
}
|
||||
}
|
||||
|
||||
bool WindowEmperor::HandleCommandlineArgs()
|
||||
bool WindowEmperor::HandleCommandlineArgs(int nCmdShow)
|
||||
{
|
||||
std::vector<winrt::hstring> args;
|
||||
_buildArgsFromCommandline(args);
|
||||
@@ -98,28 +80,16 @@ bool WindowEmperor::HandleCommandlineArgs()
|
||||
}
|
||||
}
|
||||
|
||||
// Get the requested initial state of the window from our startup info. For
|
||||
// something like `start /min`, this will set the wShowWindow member to
|
||||
// SW_SHOWMINIMIZED. We'll need to make sure is bubbled all the way through,
|
||||
// so we can open a new window with the same state.
|
||||
STARTUPINFOW si;
|
||||
GetStartupInfoW(&si);
|
||||
const uint32_t showWindow = WI_IsFlagSet(si.dwFlags, STARTF_USESHOWWINDOW) ? si.wShowWindow : SW_SHOW;
|
||||
|
||||
const auto currentEnv{ til::env::from_current_environment() };
|
||||
|
||||
Remoting::CommandlineArgs eventArgs{ { args }, { cwd }, showWindow, winrt::hstring{ currentEnv.to_string() } };
|
||||
|
||||
const Remoting::CommandlineArgs eventArgs{ args, cwd, gsl::narrow_cast<uint32_t>(nCmdShow), GetEnvironmentStringsW() };
|
||||
const auto isolatedMode{ _app.Logic().IsolatedMode() };
|
||||
|
||||
const auto result = _manager.ProposeCommandline(eventArgs, isolatedMode);
|
||||
int exitCode = 0;
|
||||
|
||||
const bool makeWindow = result.ShouldCreateWindow();
|
||||
if (makeWindow)
|
||||
if (result.ShouldCreateWindow())
|
||||
{
|
||||
_createNewWindowThread(Remoting::WindowRequestedArgs{ result, eventArgs });
|
||||
|
||||
_becomeMonarch();
|
||||
WaitForWindows();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -127,11 +97,12 @@ bool WindowEmperor::HandleCommandlineArgs()
|
||||
if (!res.Message.empty())
|
||||
{
|
||||
AppHost::s_DisplayMessageBox(res);
|
||||
std::quick_exit(res.ExitCode);
|
||||
}
|
||||
exitCode = res.ExitCode;
|
||||
}
|
||||
|
||||
return makeWindow;
|
||||
TerminateProcess(GetCurrentProcess(), gsl::narrow_cast<UINT>(exitCode));
|
||||
__assume(false);
|
||||
}
|
||||
|
||||
void WindowEmperor::WaitForWindows()
|
||||
@@ -146,7 +117,6 @@ void WindowEmperor::WaitForWindows()
|
||||
|
||||
void WindowEmperor::_createNewWindowThread(const Remoting::WindowRequestedArgs& args)
|
||||
{
|
||||
Remoting::Peasant peasant{ _manager.CreatePeasant(args) };
|
||||
std::shared_ptr<WindowThread> window{ nullptr };
|
||||
|
||||
// FIRST: Attempt to reheat an existing window that we refrigerated for
|
||||
@@ -168,7 +138,7 @@ void WindowEmperor::_createNewWindowThread(const Remoting::WindowRequestedArgs&
|
||||
// Cool! Let's increment the number of active windows, and re-heat it.
|
||||
_windowThreadInstances.fetch_add(1, std::memory_order_relaxed);
|
||||
|
||||
window->Microwave(args, peasant);
|
||||
window->Microwave(args);
|
||||
// This will unblock the event we're waiting on in KeepWarm, and the
|
||||
// window thread (started below) will continue through it's loop
|
||||
return;
|
||||
@@ -177,9 +147,7 @@ void WindowEmperor::_createNewWindowThread(const Remoting::WindowRequestedArgs&
|
||||
// At this point, there weren't any pending refrigerated threads we could
|
||||
// just use. That's fine. Let's just go create a new one.
|
||||
|
||||
window = std::make_shared<WindowThread>(_app.Logic(), args, _manager, peasant);
|
||||
|
||||
std::weak_ptr<WindowEmperor> weakThis{ weak_from_this() };
|
||||
window = std::make_shared<WindowThread>(_app.Logic(), _manager);
|
||||
|
||||
// Increment our count of window instances _now_, immediately. We're
|
||||
// starting a window now, we shouldn't exit (due to having 0 windows) till
|
||||
@@ -196,70 +164,31 @@ void WindowEmperor::_createNewWindowThread(const Remoting::WindowRequestedArgs&
|
||||
// Hence: increment the number of total windows now.
|
||||
_windowThreadInstances.fetch_add(1, std::memory_order_relaxed);
|
||||
|
||||
std::thread t([weakThis, window]() {
|
||||
std::thread t([weakThis = weak_from_this(), window = std::move(window), args = std::move(args)]() {
|
||||
try
|
||||
{
|
||||
window->CreateHost();
|
||||
winrt::init_apartment(winrt::apartment_type::single_threaded);
|
||||
|
||||
window->CreateHost(std::move(args));
|
||||
|
||||
if (auto self{ weakThis.lock() })
|
||||
{
|
||||
self->_windowStartedHandlerPostXAML(window);
|
||||
}
|
||||
while (window->KeepWarm())
|
||||
|
||||
// Now that the window is ready to go, we can add it to our list of windows,
|
||||
// because we know it will be well behaved.
|
||||
//
|
||||
// Be sure to only modify the list of windows under lock.
|
||||
|
||||
if (auto self{ weakThis.lock() })
|
||||
{
|
||||
// Now that the window is ready to go, we can add it to our list of windows,
|
||||
// because we know it will be well behaved.
|
||||
//
|
||||
// Be sure to only modify the list of windows under lock.
|
||||
|
||||
if (auto self{ weakThis.lock() })
|
||||
{
|
||||
auto lockedWindows{ self->_windows.lock() };
|
||||
lockedWindows->push_back(window);
|
||||
}
|
||||
auto removeWindow = wil::scope_exit([&]() {
|
||||
if (auto self{ weakThis.lock() })
|
||||
{
|
||||
self->_removeWindow(window->PeasantID());
|
||||
}
|
||||
});
|
||||
|
||||
auto decrementWindowCount = wil::scope_exit([&]() {
|
||||
if (auto self{ weakThis.lock() })
|
||||
{
|
||||
self->_decrementWindowCount();
|
||||
}
|
||||
});
|
||||
|
||||
window->RunMessagePump();
|
||||
|
||||
// Manually trigger the cleanup callback. This will ensure that we
|
||||
// remove the window from our list of windows, before we release the
|
||||
// AppHost (and subsequently, the host's Logic() member that we use
|
||||
// elsewhere).
|
||||
removeWindow.reset();
|
||||
|
||||
// On Windows 11, we DONT want to refrigerate the window. There,
|
||||
// we can just close it like normal. Break out of the loop, so
|
||||
// we don't try to put this window in the fridge.
|
||||
if (Utils::IsWindows11())
|
||||
{
|
||||
decrementWindowCount.reset();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
window->Refrigerate();
|
||||
decrementWindowCount.reset();
|
||||
|
||||
if (auto self{ weakThis.lock() })
|
||||
{
|
||||
auto fridge{ self->_oldThreads.lock() };
|
||||
fridge->push_back(window);
|
||||
}
|
||||
}
|
||||
auto lockedWindows{ self->_windows.lock() };
|
||||
lockedWindows->push_back(window);
|
||||
}
|
||||
|
||||
window->RunMessagePump();
|
||||
|
||||
// Now that we no longer care about this thread's window, let it
|
||||
// release it's app host and flush the rest of the XAML queue.
|
||||
window->RundownForExit();
|
||||
@@ -294,17 +223,6 @@ void WindowEmperor::_windowStartedHandlerPostXAML(const std::shared_ptr<WindowTh
|
||||
// before we make the window visible.
|
||||
}
|
||||
|
||||
void WindowEmperor::_removeWindow(uint64_t senderID)
|
||||
{
|
||||
auto lockedWindows{ _windows.lock() };
|
||||
|
||||
// find the window in _windows who's peasant's Id matches the peasant's Id
|
||||
// and remove it
|
||||
std::erase_if(*lockedWindows, [&](const auto& w) {
|
||||
return w->PeasantID() == senderID;
|
||||
});
|
||||
}
|
||||
|
||||
void WindowEmperor::_decrementWindowCount()
|
||||
{
|
||||
// When we run out of windows, exit our process if and only if:
|
||||
@@ -358,8 +276,8 @@ void WindowEmperor::_becomeMonarch()
|
||||
// Set the number of open windows (so we know if we are the last window)
|
||||
// and subscribe for updates if there are any changes to that number.
|
||||
|
||||
_revokers.WindowCreated = _manager.WindowCreated(winrt::auto_revoke, { this, &WindowEmperor::_numberOfWindowsChanged });
|
||||
_revokers.WindowClosed = _manager.WindowClosed(winrt::auto_revoke, { this, &WindowEmperor::_numberOfWindowsChanged });
|
||||
_revokers.WindowCreated = _manager.WindowCreated(winrt::auto_revoke, { this, &WindowEmperor::_windowCreated });
|
||||
_revokers.WindowClosed = _manager.WindowClosed(winrt::auto_revoke, { this, &WindowEmperor::_windowClosed });
|
||||
|
||||
// If the monarch receives a QuitAll event it will signal this event to be
|
||||
// ran before each peasant is closed.
|
||||
@@ -371,9 +289,49 @@ void WindowEmperor::_becomeMonarch()
|
||||
_getWindowLayoutThrottler.value()();
|
||||
}
|
||||
|
||||
// sender and args are always nullptr
|
||||
void WindowEmperor::_numberOfWindowsChanged(const winrt::Windows::Foundation::IInspectable&,
|
||||
const winrt::Windows::Foundation::IInspectable&)
|
||||
void WindowEmperor::_windowCreated(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::Foundation::IInspectable&)
|
||||
{
|
||||
_numberOfWindowsChanged();
|
||||
}
|
||||
|
||||
void WindowEmperor::_windowClosed(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::Foundation::IInspectable& value)
|
||||
{
|
||||
const auto peasantID = winrt::unbox_value<uint64_t>(value);
|
||||
std::shared_ptr<WindowThread> window;
|
||||
|
||||
// Below we'll lock _oldThreads. It would be possible to do it within this block so that we can avoid the window variable above.
|
||||
// But holding both locks simultaneously may result in an ABBA deadlock. Bumping reference counts is cheap and so this is a good solution.
|
||||
{
|
||||
const auto windows = _windows.lock();
|
||||
const auto it = std::find_if(windows->begin(), windows->end(), [&](const auto& w) {
|
||||
return w->PeasantID() == peasantID;
|
||||
});
|
||||
|
||||
if (it == windows->end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
window = *it;
|
||||
windows->erase(it);
|
||||
}
|
||||
|
||||
_decrementWindowCount();
|
||||
|
||||
if (Utils::IsWindows11())
|
||||
{
|
||||
PostQuitMessage(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
window->Refrigerate();
|
||||
_oldThreads.lock()->push_back(std::move(window));
|
||||
}
|
||||
|
||||
_numberOfWindowsChanged();
|
||||
}
|
||||
|
||||
void WindowEmperor::_numberOfWindowsChanged()
|
||||
{
|
||||
if (_getWindowLayoutThrottler)
|
||||
{
|
||||
@@ -584,15 +542,6 @@ LRESULT WindowEmperor::_messageHandler(UINT const message, WPARAM const wParam,
|
||||
// we'll undoubtedly crash.
|
||||
winrt::fire_and_forget WindowEmperor::_close()
|
||||
{
|
||||
{
|
||||
auto fridge{ _oldThreads.lock() };
|
||||
for (auto& window : *fridge)
|
||||
{
|
||||
window->ThrowAway();
|
||||
}
|
||||
fridge->clear();
|
||||
}
|
||||
|
||||
// Important! Switch back to the main thread for the emperor. That way, the
|
||||
// quit will go to the emperor's message pump.
|
||||
co_await wil::resume_foreground(_dispatcher);
|
||||
|
||||
@@ -27,7 +27,7 @@ public:
|
||||
~WindowEmperor();
|
||||
void WaitForWindows();
|
||||
|
||||
bool HandleCommandlineArgs();
|
||||
bool HandleCommandlineArgs(int nCmdShow);
|
||||
|
||||
private:
|
||||
void _createNewWindowThread(const winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs& args);
|
||||
@@ -57,11 +57,12 @@ private:
|
||||
bool _quitting{ false };
|
||||
|
||||
void _windowStartedHandlerPostXAML(const std::shared_ptr<WindowThread>& sender);
|
||||
void _removeWindow(uint64_t senderID);
|
||||
void _decrementWindowCount();
|
||||
|
||||
void _becomeMonarch();
|
||||
void _numberOfWindowsChanged(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::Foundation::IInspectable&);
|
||||
void _windowCreated(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::Foundation::IInspectable&);
|
||||
void _windowClosed(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::Foundation::IInspectable&);
|
||||
void _numberOfWindowsChanged();
|
||||
void _quitAllRequested(const winrt::Windows::Foundation::IInspectable&,
|
||||
const winrt::Microsoft::Terminal::Remoting::QuitAllRequestedArgs&);
|
||||
|
||||
|
||||
@@ -4,38 +4,30 @@
|
||||
#include "pch.h"
|
||||
#include "WindowThread.h"
|
||||
|
||||
WindowThread::WindowThread(winrt::TerminalApp::AppLogic logic,
|
||||
winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs args,
|
||||
winrt::Microsoft::Terminal::Remoting::WindowManager manager,
|
||||
winrt::Microsoft::Terminal::Remoting::Peasant peasant) :
|
||||
_peasant{ std::move(peasant) },
|
||||
using namespace winrt::Microsoft::Terminal::Remoting;
|
||||
|
||||
WindowThread::WindowThread(winrt::TerminalApp::AppLogic logic, WindowManager manager) :
|
||||
_appLogic{ std::move(logic) },
|
||||
_args{ std::move(args) },
|
||||
_manager{ std::move(manager) }
|
||||
{
|
||||
// DO NOT start the AppHost here in the ctor, as that will start XAML on the wrong thread!
|
||||
}
|
||||
|
||||
void WindowThread::CreateHost()
|
||||
void WindowThread::CreateHost(WindowRequestedArgs args)
|
||||
{
|
||||
// Calling this while refrigerated won't work.
|
||||
// * We can't re-initialize our winrt apartment.
|
||||
// * AppHost::Initialize has to be done on the "UI" thread.
|
||||
assert(_warmWindow == nullptr);
|
||||
winrt::init_apartment(winrt::apartment_type::single_threaded);
|
||||
|
||||
// Start the AppHost HERE, on the actual thread we want XAML to run on
|
||||
_host = std::make_shared<::AppHost>(_appLogic,
|
||||
_args,
|
||||
_manager,
|
||||
_peasant);
|
||||
_peasant = _manager.CreatePeasant(args);
|
||||
_host = std::make_shared<::AppHost>(_appLogic, std::move(args), _manager, _peasant);
|
||||
|
||||
_UpdateSettingsRequestedToken = _host->UpdateSettingsRequested([this]() { _UpdateSettingsRequestedHandlers(); });
|
||||
|
||||
winrt::init_apartment(winrt::apartment_type::single_threaded);
|
||||
|
||||
// Initialize the xaml content. This must be called AFTER the
|
||||
// WindowsXamlManager is initialized.
|
||||
_host->Initialize();
|
||||
|
||||
_dispatcher = winrt::Windows::System::DispatcherQueue::GetForCurrentThread();
|
||||
}
|
||||
|
||||
int WindowThread::RunMessagePump()
|
||||
@@ -81,59 +73,6 @@ void WindowThread::RundownForExit()
|
||||
_pumpRemainingXamlMessages();
|
||||
}
|
||||
|
||||
void WindowThread::ThrowAway()
|
||||
{
|
||||
// raise the signal to unblock KeepWarm. We won't have a host, so we'll drop
|
||||
// out of the message loop to eventually RundownForExit.
|
||||
//
|
||||
// This should only be called when the app is fully quitting. After this is
|
||||
// called on any thread, on win10, we won't be able to call into XAML
|
||||
// anymore.
|
||||
_microwaveBuzzer.notify_one();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Check if we should keep this window alive, to try it's message loop again.
|
||||
// If we were refrigerated for later, then this will block the thread on the
|
||||
// _microwaveBuzzer. We'll sit there like that till the emperor decides if
|
||||
// they want to re-use this window thread for a new window.
|
||||
// Return Value:
|
||||
// - true IFF we should enter this thread's message loop
|
||||
// INVARIANT: This must be called on our "ui thread", our window thread.
|
||||
bool WindowThread::KeepWarm()
|
||||
{
|
||||
if (_host != nullptr)
|
||||
{
|
||||
// We're currently hot
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we're refrigerated, then wait on the microwave signal, which will be
|
||||
// raised when we get re-heated by another thread to reactivate us.
|
||||
|
||||
if (_warmWindow != nullptr)
|
||||
{
|
||||
std::unique_lock lock(_microwave);
|
||||
_microwaveBuzzer.wait(lock);
|
||||
|
||||
// If ThrowAway() was called, then the buzzer will be signalled without
|
||||
// setting a new _host. In that case, the app is quitting, for real. We
|
||||
// just want to exit with false.
|
||||
const bool reheated = _host != nullptr;
|
||||
if (reheated)
|
||||
{
|
||||
_UpdateSettingsRequestedToken = _host->UpdateSettingsRequested([this]() { _UpdateSettingsRequestedHandlers(); });
|
||||
// Re-initialize the host here, on the window thread
|
||||
_host->Initialize();
|
||||
}
|
||||
return reheated;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - "Refrigerate" this thread for later reuse. This will refrigerate the window
|
||||
// itself, and tear down our current app host. We'll save our window for
|
||||
@@ -143,12 +82,8 @@ bool WindowThread::KeepWarm()
|
||||
void WindowThread::Refrigerate()
|
||||
{
|
||||
_host->UpdateSettingsRequested(_UpdateSettingsRequestedToken);
|
||||
|
||||
// keep a reference to the HWND and DesktopWindowXamlSource alive.
|
||||
_warmWindow = std::move(_host->Refrigerate());
|
||||
|
||||
// rundown remaining messages before destructing the app host
|
||||
_pumpRemainingXamlMessages();
|
||||
_host = nullptr;
|
||||
}
|
||||
|
||||
@@ -157,21 +92,14 @@ void WindowThread::Refrigerate()
|
||||
// existing window to it. We'll then trigger the _microwaveBuzzer, so KeepWarm
|
||||
// (which is on the UI thread) will get unblocked, and we can initialize this
|
||||
// window.
|
||||
void WindowThread::Microwave(
|
||||
winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs args,
|
||||
winrt::Microsoft::Terminal::Remoting::Peasant peasant)
|
||||
void WindowThread::Microwave(WindowRequestedArgs args)
|
||||
{
|
||||
_peasant = std::move(peasant);
|
||||
_args = std::move(args);
|
||||
|
||||
_host = std::make_shared<::AppHost>(_appLogic,
|
||||
_args,
|
||||
_manager,
|
||||
_peasant,
|
||||
std::move(_warmWindow));
|
||||
|
||||
// raise the signal to unblock KeepWarm and start the window message loop again.
|
||||
_microwaveBuzzer.notify_one();
|
||||
_dispatcher.TryEnqueue(winrt::Windows::System::DispatcherQueuePriority::Normal, [this, args = std::move(args)]() {
|
||||
_peasant = _manager.CreatePeasant(args);
|
||||
_host = std::make_shared<::AppHost>(_appLogic, std::move(args), _manager, _peasant, std::move(_warmWindow));
|
||||
_UpdateSettingsRequestedToken = _host->UpdateSettingsRequested([this]() { _UpdateSettingsRequestedHandlers(); });
|
||||
_host->Initialize();
|
||||
});
|
||||
}
|
||||
|
||||
winrt::TerminalApp::TerminalWindow WindowThread::Logic()
|
||||
|
||||
@@ -7,33 +7,25 @@
|
||||
class WindowThread : public std::enable_shared_from_this<WindowThread>
|
||||
{
|
||||
public:
|
||||
WindowThread(winrt::TerminalApp::AppLogic logic,
|
||||
winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs args,
|
||||
winrt::Microsoft::Terminal::Remoting::WindowManager manager,
|
||||
winrt::Microsoft::Terminal::Remoting::Peasant peasant);
|
||||
WindowThread(winrt::TerminalApp::AppLogic logic, winrt::Microsoft::Terminal::Remoting::WindowManager manager);
|
||||
|
||||
winrt::TerminalApp::TerminalWindow Logic();
|
||||
void CreateHost();
|
||||
void CreateHost(winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs args);
|
||||
int RunMessagePump();
|
||||
void RundownForExit();
|
||||
|
||||
bool KeepWarm();
|
||||
void Refrigerate();
|
||||
void Microwave(
|
||||
winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs args,
|
||||
winrt::Microsoft::Terminal::Remoting::Peasant peasant);
|
||||
void ThrowAway();
|
||||
void Microwave(winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs args);
|
||||
|
||||
uint64_t PeasantID();
|
||||
|
||||
WINRT_CALLBACK(UpdateSettingsRequested, winrt::delegate<void()>);
|
||||
|
||||
private:
|
||||
winrt::Microsoft::Terminal::Remoting::Peasant _peasant{ nullptr };
|
||||
|
||||
winrt::TerminalApp::AppLogic _appLogic{ nullptr };
|
||||
winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs _args{ nullptr };
|
||||
winrt::Microsoft::Terminal::Remoting::WindowManager _manager{ nullptr };
|
||||
winrt::Microsoft::Terminal::Remoting::Peasant _peasant{ nullptr };
|
||||
winrt::Windows::System::DispatcherQueue _dispatcher{ nullptr };
|
||||
|
||||
// This is a "shared_ptr", but it should be treated as a unique, owning ptr.
|
||||
// It's shared, because there are edge cases in refrigeration where internal
|
||||
@@ -43,8 +35,6 @@ private:
|
||||
winrt::event_token _UpdateSettingsRequestedToken;
|
||||
|
||||
std::unique_ptr<::IslandWindow> _warmWindow{ nullptr };
|
||||
std::mutex _microwave;
|
||||
std::condition_variable _microwaveBuzzer;
|
||||
|
||||
int _messagePump();
|
||||
void _pumpRemainingXamlMessages();
|
||||
|
||||
@@ -83,7 +83,7 @@ static void EnsureNativeArchitecture()
|
||||
}
|
||||
}
|
||||
|
||||
int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
|
||||
int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int nCmdShow)
|
||||
{
|
||||
TraceLoggingRegister(g_hWindowsTerminalProvider);
|
||||
::Microsoft::Console::ErrorReporting::EnableFallbackFailureReporting(g_hWindowsTerminalProvider);
|
||||
@@ -115,8 +115,5 @@ int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
|
||||
winrt::init_apartment(winrt::apartment_type::single_threaded);
|
||||
|
||||
const auto emperor = std::make_shared<::WindowEmperor>();
|
||||
if (emperor->HandleCommandlineArgs())
|
||||
{
|
||||
emperor->WaitForWindows();
|
||||
}
|
||||
emperor->HandleCommandlineArgs(nCmdShow);
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ Abstract:
|
||||
#include <wil/cppwinrt.h>
|
||||
|
||||
// Needed just for XamlIslands to work at all:
|
||||
#include <winrt/Windows.system.h>
|
||||
#include <winrt/Windows.System.h>
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#include <winrt/Windows.UI.Xaml.Hosting.h>
|
||||
#include <windows.ui.xaml.hosting.desktopwindowxamlsource.h>
|
||||
@@ -63,7 +63,7 @@ Abstract:
|
||||
#include <winrt/Windows.UI.Xaml.Controls.h>
|
||||
#include <winrt/Windows.UI.Xaml.Controls.Primitives.h>
|
||||
#include <winrt/Windows.UI.Xaml.Data.h>
|
||||
#include <winrt/Windows.ui.xaml.media.h>
|
||||
#include <winrt/Windows.UI.Xaml.Media.h>
|
||||
#include <winrt/Windows.ApplicationModel.h>
|
||||
#include <winrt/Windows.ApplicationModel.Resources.Core.h>
|
||||
#include <winrt/Windows.UI.Composition.h>
|
||||
|
||||
@@ -855,19 +855,20 @@ std::wstring Utils::EvaluateStartingDirectory(
|
||||
|
||||
bool Utils::IsWindows11() noexcept
|
||||
{
|
||||
static const bool isWindows11 = []() noexcept {
|
||||
OSVERSIONINFOEXW osver{};
|
||||
osver.dwOSVersionInfoSize = sizeof(osver);
|
||||
osver.dwBuildNumber = 22000;
|
||||
|
||||
DWORDLONG dwlConditionMask = 0;
|
||||
VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
|
||||
|
||||
if (VerifyVersionInfoW(&osver, VER_BUILDNUMBER, dwlConditionMask) != FALSE)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}();
|
||||
return isWindows11;
|
||||
//static const bool isWindows11 = []() noexcept {
|
||||
// OSVERSIONINFOEXW osver{};
|
||||
// osver.dwOSVersionInfoSize = sizeof(osver);
|
||||
// osver.dwBuildNumber = 22000;
|
||||
//
|
||||
// DWORDLONG dwlConditionMask = 0;
|
||||
// VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
|
||||
//
|
||||
// if (VerifyVersionInfoW(&osver, VER_BUILDNUMBER, dwlConditionMask) != FALSE)
|
||||
// {
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
//}();
|
||||
//return isWindows11;
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user