mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-11 04:38:24 -06:00
Split AppLogic into "App logic" and "Window logic" (#14825)
_And so begins the first chapter in the epic tale of the Terminal's tab tear-out. This commit, though humble in its nature, shall mark the beginning of a grand journey._ _This initial offering, though small in its scope, doth serve to divide the code that currently resides within TerminalPage and AppLogic, moving it unto a new entity known as TerminalWindow. In the ages to come, these classes shall take on separate responsibilities, each with their own purpose._ _The AppLogic shall hold sway over the entire process, shared among all Terminal windows, while the AppHost, TerminalWindow, and TerminalPage shall rule over each individual window._ _This pull request prepares the way for the future, moving state that pertains to the individual windows into the TerminalWindow. This is a task of great labor, for it requires moving much code, but the end result shall bring greater organization to the codebase._ _And so the stage is set, for in the next pull request, the Process Model v3 shall be revealed, unifying all Terminal windows into a single process, a grand accomplishment indeed._ _courtesy of G.P.T. Tolkien_ <details> <summary>Or, as I wrote it originally. </summary> This is the first of the commits in the long saga which will culminate in tab tear-out for the Terminal. This the most functionally trivial of the PRs. It mostly just splits up code that's currently in TerminalPage & AppLogic, and moves it into a new class `TerminalWindow`. In the future, these classes will separate responsibility as such: * There will be one `AppLogic` per process, shared across all Terminal windows. * There will be one `AppHost`, `TerminalWindow`, and `TerminalPage` for each individual window in the process. This PR prepares for that by moving some state that's applicable to _individual windows_ into `TerminalWindow`. This is almost exclusively a code moving PR. There should be minimal functional changes. </details> In the next PR, we'll introduce the actual "Process Model v3", merging all Terminal windows into a single terminal process. Related to #5000. See https://github.com/Microsoft/terminal/issues/5000#issuecomment-1407110045 for my current todo list. Related to #1256. These commits are all artificially broken down pieces. Honestly, I don't want to really merge them till they're all ready, so we know that the work e2e. This my feigned attempt to break it into digestable PRs. Lightly manually tested, things seem to still all work? Most of this code was actually written in deeper branches, it was only today I realized it all needed to come back to this branch. * [x] The window persistence fishy-ness of the subsequent PR isn't present here. So that's something. * [x] Localtests still pass ### Detailed description > Q: Does `AppLogic` not keep track of its windows? Sure doesn't! I didn't think that was something it needed to know. >Q: Why does `TerminalWindow` (per-window) have access to the commandline args (per-process) It's because it's _not_ per process. Commandline args _are_ per-window. Consider - you launch the Terminal, then run a `wt -w -1 -- foo`. That makes its own window. In this process, yes. But that new window has its own commandline args, separate from the ones that started the original process.
This commit is contained in:
parent
8c17475a9f
commit
5b434dcda4
@ -4,6 +4,7 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "../TerminalApp/TerminalPage.h"
|
||||
#include "../TerminalApp/TerminalWindow.h"
|
||||
#include "../TerminalApp/MinMaxCloseControl.h"
|
||||
#include "../TerminalApp/TabRowControl.h"
|
||||
#include "../TerminalApp/ShortcutActionDispatch.h"
|
||||
@ -110,6 +111,7 @@ namespace TerminalAppLocalTests
|
||||
void _initializeTerminalPage(winrt::com_ptr<winrt::TerminalApp::implementation::TerminalPage>& page,
|
||||
CascadiaSettings initialSettings);
|
||||
winrt::com_ptr<winrt::TerminalApp::implementation::TerminalPage> _commonSetup();
|
||||
winrt::com_ptr<winrt::TerminalApp::implementation::WindowProperties> _windowProperties;
|
||||
};
|
||||
|
||||
template<typename TFunction>
|
||||
@ -194,8 +196,11 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
winrt::com_ptr<winrt::TerminalApp::implementation::TerminalPage> page{ nullptr };
|
||||
|
||||
auto result = RunOnUIThread([&page]() {
|
||||
page = winrt::make_self<winrt::TerminalApp::implementation::TerminalPage>();
|
||||
_windowProperties = winrt::make_self<winrt::TerminalApp::implementation::WindowProperties>();
|
||||
winrt::TerminalApp::WindowProperties props = *_windowProperties;
|
||||
|
||||
auto result = RunOnUIThread([&page, props]() {
|
||||
page = winrt::make_self<winrt::TerminalApp::implementation::TerminalPage>(props);
|
||||
VERIFY_IS_NOT_NULL(page);
|
||||
});
|
||||
VERIFY_SUCCEEDED(result);
|
||||
@ -239,9 +244,11 @@ namespace TerminalAppLocalTests
|
||||
// it's weird.
|
||||
winrt::TerminalApp::TerminalPage projectedPage{ nullptr };
|
||||
|
||||
_windowProperties = winrt::make_self<winrt::TerminalApp::implementation::WindowProperties>();
|
||||
winrt::TerminalApp::WindowProperties props = *_windowProperties;
|
||||
Log::Comment(NoThrowString().Format(L"Construct the TerminalPage"));
|
||||
auto result = RunOnUIThread([&projectedPage, &page, initialSettings]() {
|
||||
projectedPage = winrt::TerminalApp::TerminalPage();
|
||||
auto result = RunOnUIThread([&projectedPage, &page, initialSettings, props]() {
|
||||
projectedPage = winrt::TerminalApp::TerminalPage(props);
|
||||
page.copy_from(winrt::get_self<winrt::TerminalApp::implementation::TerminalPage>(projectedPage));
|
||||
page->_settings = initialSettings;
|
||||
});
|
||||
@ -1242,14 +1249,16 @@ namespace TerminalAppLocalTests
|
||||
END_TEST_METHOD_PROPERTIES()
|
||||
|
||||
auto page = _commonSetup();
|
||||
page->RenameWindowRequested([&page](auto&&, const winrt::TerminalApp::RenameWindowRequestedArgs args) {
|
||||
page->RenameWindowRequested([&page, this](auto&&, const winrt::TerminalApp::RenameWindowRequestedArgs args) {
|
||||
// In the real terminal, this would bounce up to the monarch and
|
||||
// come back down. Instead, immediately call back and set the name.
|
||||
page->WindowName(args.ProposedName());
|
||||
//
|
||||
// This replicates how TerminalWindow works
|
||||
_windowProperties->WindowName(args.ProposedName());
|
||||
});
|
||||
|
||||
auto windowNameChanged = false;
|
||||
page->PropertyChanged([&page, &windowNameChanged](auto&&, const winrt::WUX::Data::PropertyChangedEventArgs& args) mutable {
|
||||
_windowProperties->PropertyChanged([&page, &windowNameChanged](auto&&, const winrt::WUX::Data::PropertyChangedEventArgs& args) mutable {
|
||||
if (args.PropertyName() == L"WindowNameForDisplay")
|
||||
{
|
||||
windowNameChanged = true;
|
||||
@ -1260,7 +1269,7 @@ namespace TerminalAppLocalTests
|
||||
page->_RequestWindowRename(winrt::hstring{ L"Foo" });
|
||||
});
|
||||
TestOnUIThread([&]() {
|
||||
VERIFY_ARE_EQUAL(L"Foo", page->_WindowName);
|
||||
VERIFY_ARE_EQUAL(L"Foo", page->WindowProperties().WindowName());
|
||||
VERIFY_IS_TRUE(windowNameChanged,
|
||||
L"The window name should have changed, and we should have raised a notification that WindowNameForDisplay changed");
|
||||
});
|
||||
|
||||
@ -77,22 +77,7 @@ namespace winrt::TerminalApp::implementation
|
||||
/// <param name="e">Details about the launch request and process.</param>
|
||||
void App::OnLaunched(const LaunchActivatedEventArgs& /*e*/)
|
||||
{
|
||||
// if this is a UWP... it means its our problem to hook up the content to the window here.
|
||||
if (_isUwp)
|
||||
{
|
||||
auto content = Window::Current().Content();
|
||||
if (content == nullptr)
|
||||
{
|
||||
auto logic = Logic();
|
||||
logic.RunAsUwp(); // Must set UWP status first, settings might change based on it.
|
||||
logic.ReloadSettings();
|
||||
logic.Create();
|
||||
|
||||
auto page = logic.GetRoot().as<TerminalPage>();
|
||||
|
||||
Window::Current().Content(page);
|
||||
Window::Current().Activate();
|
||||
}
|
||||
}
|
||||
// We used to support a pure UWP version of the Terminal. This method
|
||||
// was only ever used to do UWP-specific setup of our App.
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -5,10 +5,11 @@
|
||||
|
||||
#include "AppLogic.g.h"
|
||||
#include "FindTargetWindowResult.g.h"
|
||||
#include "SystemMenuChangeArgs.g.h"
|
||||
|
||||
#include "Jumplist.h"
|
||||
#include "LanguageProfileNotifier.h"
|
||||
#include "TerminalPage.h"
|
||||
#include "AppCommandlineArgs.h"
|
||||
#include "TerminalWindow.h"
|
||||
|
||||
#include <inc/cppwinrt_utils.h>
|
||||
#include <ThrottledFunc.h>
|
||||
@ -36,18 +37,7 @@ namespace winrt::TerminalApp::implementation
|
||||
FindTargetWindowResult(id, L""){};
|
||||
};
|
||||
|
||||
struct SystemMenuChangeArgs : SystemMenuChangeArgsT<SystemMenuChangeArgs>
|
||||
{
|
||||
WINRT_PROPERTY(winrt::hstring, Name, L"");
|
||||
WINRT_PROPERTY(SystemMenuChangeAction, Action, SystemMenuChangeAction::Add);
|
||||
WINRT_PROPERTY(SystemMenuItemHandler, Handler, nullptr);
|
||||
|
||||
public:
|
||||
SystemMenuChangeArgs(const winrt::hstring& name, SystemMenuChangeAction action, SystemMenuItemHandler handler = nullptr) :
|
||||
_Name{ name }, _Action{ action }, _Handler{ handler } {};
|
||||
};
|
||||
|
||||
struct AppLogic : AppLogicT<AppLogic, IInitializeWithWindow>
|
||||
struct AppLogic : AppLogicT<AppLogic>
|
||||
{
|
||||
public:
|
||||
static AppLogic* Current() noexcept;
|
||||
@ -56,124 +46,47 @@ namespace winrt::TerminalApp::implementation
|
||||
AppLogic();
|
||||
~AppLogic() = default;
|
||||
|
||||
STDMETHODIMP Initialize(HWND hwnd);
|
||||
|
||||
void Create();
|
||||
bool IsUwp() const noexcept;
|
||||
void RunAsUwp();
|
||||
bool IsElevated() const noexcept;
|
||||
void ReloadSettings();
|
||||
|
||||
bool HasSettingsStartupActions() const noexcept;
|
||||
|
||||
bool ShouldUsePersistedLayout() const;
|
||||
void SaveWindowLayoutJsons(const Windows::Foundation::Collections::IVector<hstring>& layouts);
|
||||
|
||||
[[nodiscard]] Microsoft::Terminal::Settings::Model::CascadiaSettings GetSettings() const noexcept;
|
||||
|
||||
void Quit();
|
||||
|
||||
bool HasCommandlineArguments() const noexcept;
|
||||
bool HasSettingsStartupActions() const noexcept;
|
||||
int32_t SetStartupCommandline(array_view<const winrt::hstring> actions);
|
||||
int32_t ExecuteCommandline(array_view<const winrt::hstring> actions, const winrt::hstring& cwd);
|
||||
TerminalApp::FindTargetWindowResult FindTargetWindow(array_view<const winrt::hstring> actions);
|
||||
winrt::hstring ParseCommandlineMessage();
|
||||
bool ShouldExitEarly();
|
||||
|
||||
bool FocusMode() const;
|
||||
bool Fullscreen() const;
|
||||
void Maximized(bool newMaximized);
|
||||
bool AlwaysOnTop() const;
|
||||
bool AutoHideWindow();
|
||||
|
||||
bool ShouldUsePersistedLayout();
|
||||
bool ShouldImmediatelyHandoffToElevated();
|
||||
void HandoffToElevated();
|
||||
hstring GetWindowLayoutJson(Microsoft::Terminal::Settings::Model::LaunchPosition position);
|
||||
void SaveWindowLayoutJsons(const Windows::Foundation::Collections::IVector<hstring>& layouts);
|
||||
void IdentifyWindow();
|
||||
void RenameFailed();
|
||||
winrt::hstring WindowName();
|
||||
void WindowName(const winrt::hstring& name);
|
||||
uint64_t WindowId();
|
||||
void WindowId(const uint64_t& id);
|
||||
void SetPersistedLayoutIdx(const uint32_t idx);
|
||||
void SetNumberOfOpenWindows(const uint64_t num);
|
||||
bool IsQuakeWindow() const noexcept;
|
||||
void RequestExitFullscreen();
|
||||
|
||||
Windows::Foundation::Size GetLaunchDimensions(uint32_t dpi);
|
||||
bool CenterOnLaunch();
|
||||
TerminalApp::InitialPosition GetInitialPosition(int64_t defaultInitialX, int64_t defaultInitialY);
|
||||
winrt::Windows::UI::Xaml::ElementTheme GetRequestedTheme();
|
||||
Microsoft::Terminal::Settings::Model::LaunchMode GetLaunchMode();
|
||||
bool GetShowTabsInTitlebar();
|
||||
bool GetInitialAlwaysOnTop();
|
||||
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
||||
|
||||
Windows::UI::Xaml::UIElement GetRoot() noexcept;
|
||||
|
||||
void SetInboundListener();
|
||||
|
||||
hstring Title();
|
||||
void TitlebarClicked();
|
||||
bool OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down);
|
||||
|
||||
void CloseWindow(Microsoft::Terminal::Settings::Model::LaunchPosition position);
|
||||
void WindowVisibilityChanged(const bool showOrHide);
|
||||
|
||||
winrt::TerminalApp::TaskbarState TaskbarState();
|
||||
winrt::Windows::UI::Xaml::Media::Brush TitlebarBrush();
|
||||
void WindowActivated(const bool activated);
|
||||
|
||||
bool GetMinimizeToNotificationArea();
|
||||
bool GetAlwaysShowNotificationIcon();
|
||||
bool GetShowTitleInTitlebar();
|
||||
|
||||
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> ShowDialog(winrt::Windows::UI::Xaml::Controls::ContentDialog dialog);
|
||||
void DismissDialog();
|
||||
|
||||
Windows::Foundation::Collections::IMapView<Microsoft::Terminal::Control::KeyChord, Microsoft::Terminal::Settings::Model::Command> GlobalHotkeys();
|
||||
|
||||
Microsoft::Terminal::Settings::Model::Theme Theme();
|
||||
|
||||
// -------------------------------- WinRT Events ---------------------------------
|
||||
// PropertyChanged is surprisingly not a typed event, so we'll define that one manually.
|
||||
// Usually we'd just do
|
||||
// WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
||||
//
|
||||
// But what we're doing here is exposing the Page's PropertyChanged _as
|
||||
// our own event_. It's a FORWARDED_CALLBACK, essentially.
|
||||
winrt::event_token PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler) { return _root->PropertyChanged(handler); }
|
||||
void PropertyChanged(winrt::event_token const& token) { _root->PropertyChanged(token); }
|
||||
TerminalApp::TerminalWindow CreateNewWindow();
|
||||
|
||||
TYPED_EVENT(RequestedThemeChanged, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Settings::Model::Theme);
|
||||
TYPED_EVENT(SettingsChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(SystemMenuChangeRequested, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::SystemMenuChangeArgs);
|
||||
TYPED_EVENT(SettingsChanged, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::SettingsLoadEventArgs);
|
||||
|
||||
private:
|
||||
bool _isUwp{ false };
|
||||
bool _isElevated{ false };
|
||||
|
||||
// If you add controls here, but forget to null them either here or in
|
||||
// the ctor, you're going to have a bad time. It'll mysteriously fail to
|
||||
// activate the AppLogic.
|
||||
// ALSO: If you add any UIElements as roots here, make sure they're
|
||||
// updated in _ApplyTheme. The root currently is _root.
|
||||
winrt::com_ptr<TerminalPage> _root{ nullptr };
|
||||
Microsoft::Terminal::Settings::Model::CascadiaSettings _settings{ nullptr };
|
||||
|
||||
winrt::hstring _settingsLoadExceptionText;
|
||||
HRESULT _settingsLoadedResult = S_OK;
|
||||
bool _loadedInitialSettings = false;
|
||||
|
||||
uint64_t _numOpenWindows{ 0 };
|
||||
|
||||
std::shared_mutex _dialogLock;
|
||||
winrt::Windows::UI::Xaml::Controls::ContentDialog _dialog;
|
||||
|
||||
::TerminalApp::AppCommandlineArgs _appArgs;
|
||||
bool _hasSettingsStartupActions{ false };
|
||||
::TerminalApp::AppCommandlineArgs _settingsAppArgs;
|
||||
|
||||
std::shared_ptr<ThrottledFuncTrailing<>> _reloadSettings;
|
||||
til::throttled_func_trailing<> _reloadState;
|
||||
|
||||
std::vector<Microsoft::Terminal::Settings::Model::SettingsLoadWarnings> _warnings{};
|
||||
|
||||
// These fields invoke _reloadSettings and must be destroyed before _reloadSettings.
|
||||
// (C++ destroys members in reverse-declaration-order.)
|
||||
winrt::com_ptr<LanguageProfileNotifier> _languageProfileNotifier;
|
||||
@ -182,46 +95,13 @@ namespace winrt::TerminalApp::implementation
|
||||
static TerminalApp::FindTargetWindowResult _doFindTargetWindow(winrt::array_view<const hstring> args,
|
||||
const Microsoft::Terminal::Settings::Model::WindowingMode& windowingBehavior);
|
||||
|
||||
void _ShowLoadErrorsDialog(const winrt::hstring& titleKey, const winrt::hstring& contentKey, HRESULT settingsLoadedResult);
|
||||
void _ShowLoadWarningsDialog();
|
||||
bool _IsKeyboardServiceEnabled();
|
||||
|
||||
void _ApplyLanguageSettingChange() noexcept;
|
||||
void _RefreshThemeRoutine();
|
||||
fire_and_forget _ApplyStartupTaskStateChange();
|
||||
|
||||
void _OnLoaded(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
|
||||
|
||||
[[nodiscard]] HRESULT _TryLoadSettings() noexcept;
|
||||
void _ProcessLazySettingsChanges();
|
||||
void _RegisterSettingsChange();
|
||||
fire_and_forget _DispatchReloadSettings();
|
||||
void _OpenSettingsUI();
|
||||
|
||||
bool _hasCommandLineArguments{ false };
|
||||
bool _hasSettingsStartupActions{ false };
|
||||
std::vector<Microsoft::Terminal::Settings::Model::SettingsLoadWarnings> _warnings;
|
||||
|
||||
// These are events that are handled by the TerminalPage, but are
|
||||
// exposed through the AppLogic. This macro is used to forward the event
|
||||
// directly to them.
|
||||
FORWARDED_TYPED_EVENT(SetTitleBarContent, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::UIElement, _root, SetTitleBarContent);
|
||||
FORWARDED_TYPED_EVENT(TitleChanged, winrt::Windows::Foundation::IInspectable, winrt::hstring, _root, TitleChanged);
|
||||
FORWARDED_TYPED_EVENT(LastTabClosed, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::LastTabClosedEventArgs, _root, LastTabClosed);
|
||||
FORWARDED_TYPED_EVENT(FocusModeChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, FocusModeChanged);
|
||||
FORWARDED_TYPED_EVENT(FullscreenChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, FullscreenChanged);
|
||||
FORWARDED_TYPED_EVENT(ChangeMaximizeRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, ChangeMaximizeRequested);
|
||||
FORWARDED_TYPED_EVENT(AlwaysOnTopChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, AlwaysOnTopChanged);
|
||||
FORWARDED_TYPED_EVENT(RaiseVisualBell, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, RaiseVisualBell);
|
||||
FORWARDED_TYPED_EVENT(SetTaskbarProgress, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, SetTaskbarProgress);
|
||||
FORWARDED_TYPED_EVENT(IdentifyWindowsRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, IdentifyWindowsRequested);
|
||||
FORWARDED_TYPED_EVENT(RenameWindowRequested, Windows::Foundation::IInspectable, winrt::TerminalApp::RenameWindowRequestedArgs, _root, RenameWindowRequested);
|
||||
FORWARDED_TYPED_EVENT(IsQuakeWindowChanged, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, IsQuakeWindowChanged);
|
||||
FORWARDED_TYPED_EVENT(SummonWindowRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, SummonWindowRequested);
|
||||
FORWARDED_TYPED_EVENT(CloseRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, CloseRequested);
|
||||
FORWARDED_TYPED_EVENT(OpenSystemMenu, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, OpenSystemMenu);
|
||||
FORWARDED_TYPED_EVENT(QuitRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, QuitRequested);
|
||||
FORWARDED_TYPED_EVENT(ShowWindowChanged, Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Control::ShowWindowArgs, _root, ShowWindowChanged);
|
||||
|
||||
#ifdef UNIT_TESTING
|
||||
friend class TerminalAppLocalTests::CommandlineTest;
|
||||
|
||||
@ -1,41 +1,18 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "TerminalPage.idl";
|
||||
import "ShortcutActionDispatch.idl";
|
||||
import "IDirectKeyListener.idl";
|
||||
import "TerminalWindow.idl";
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
struct InitialPosition
|
||||
{
|
||||
Int64 X;
|
||||
Int64 Y;
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass FindTargetWindowResult
|
||||
{
|
||||
Int32 WindowId { get; };
|
||||
String WindowName { get; };
|
||||
};
|
||||
|
||||
delegate void SystemMenuItemHandler();
|
||||
|
||||
enum SystemMenuChangeAction
|
||||
{
|
||||
Add = 0,
|
||||
Remove = 1
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass SystemMenuChangeArgs {
|
||||
String Name { get; };
|
||||
SystemMenuChangeAction Action { get; };
|
||||
SystemMenuItemHandler Handler { get; };
|
||||
};
|
||||
|
||||
// See IDialogPresenter and TerminalPage's DialogPresenter for more
|
||||
// information.
|
||||
[default_interface] runtimeclass AppLogic : IDirectKeyListener, IDialogPresenter, Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
[default_interface] runtimeclass AppLogic
|
||||
{
|
||||
AppLogic();
|
||||
|
||||
@ -50,94 +27,22 @@ namespace TerminalApp
|
||||
void RunAsUwp();
|
||||
Boolean IsElevated();
|
||||
|
||||
Boolean HasCommandlineArguments();
|
||||
Boolean HasSettingsStartupActions();
|
||||
Int32 SetStartupCommandline(String[] commands);
|
||||
Int32 ExecuteCommandline(String[] commands, String cwd);
|
||||
String ParseCommandlineMessage { get; };
|
||||
Boolean ShouldExitEarly { get; };
|
||||
|
||||
void Quit();
|
||||
|
||||
void ReloadSettings();
|
||||
Windows.UI.Xaml.UIElement GetRoot();
|
||||
|
||||
void SetInboundListener();
|
||||
|
||||
String Title { get; };
|
||||
|
||||
Boolean FocusMode { get; };
|
||||
Boolean Fullscreen { get; };
|
||||
void Maximized(Boolean newMaximized);
|
||||
Boolean AlwaysOnTop { get; };
|
||||
Boolean AutoHideWindow { get; };
|
||||
|
||||
void IdentifyWindow();
|
||||
String WindowName;
|
||||
UInt64 WindowId;
|
||||
void SetPersistedLayoutIdx(UInt32 idx);
|
||||
void SetNumberOfOpenWindows(UInt64 num);
|
||||
void RenameFailed();
|
||||
void RequestExitFullscreen();
|
||||
Boolean IsQuakeWindow();
|
||||
|
||||
Windows.Foundation.Size GetLaunchDimensions(UInt32 dpi);
|
||||
Boolean CenterOnLaunch { get; };
|
||||
|
||||
InitialPosition GetInitialPosition(Int64 defaultInitialX, Int64 defaultInitialY);
|
||||
Windows.UI.Xaml.ElementTheme GetRequestedTheme();
|
||||
Microsoft.Terminal.Settings.Model.LaunchMode GetLaunchMode();
|
||||
Boolean GetShowTabsInTitlebar();
|
||||
Boolean GetInitialAlwaysOnTop();
|
||||
Single CalcSnappedDimension(Boolean widthOrHeight, Single dimension);
|
||||
void TitlebarClicked();
|
||||
void CloseWindow(Microsoft.Terminal.Settings.Model.LaunchPosition position);
|
||||
void WindowVisibilityChanged(Boolean showOrHide);
|
||||
|
||||
TaskbarState TaskbarState{ get; };
|
||||
Windows.UI.Xaml.Media.Brush TitlebarBrush { get; };
|
||||
void WindowActivated(Boolean activated);
|
||||
|
||||
Boolean ShouldUsePersistedLayout();
|
||||
Boolean ShouldImmediatelyHandoffToElevated();
|
||||
void HandoffToElevated();
|
||||
String GetWindowLayoutJson(Microsoft.Terminal.Settings.Model.LaunchPosition position);
|
||||
void SaveWindowLayoutJsons(Windows.Foundation.Collections.IVector<String> layouts);
|
||||
|
||||
Boolean GetMinimizeToNotificationArea();
|
||||
Boolean GetAlwaysShowNotificationIcon();
|
||||
Boolean GetShowTitleInTitlebar();
|
||||
void ReloadSettings();
|
||||
|
||||
Microsoft.Terminal.Settings.Model.Theme Theme { get; };
|
||||
|
||||
FindTargetWindowResult FindTargetWindow(String[] args);
|
||||
|
||||
TerminalWindow CreateNewWindow();
|
||||
|
||||
Windows.Foundation.Collections.IMapView<Microsoft.Terminal.Control.KeyChord, Microsoft.Terminal.Settings.Model.Command> GlobalHotkeys();
|
||||
|
||||
// See IDialogPresenter and TerminalPage's DialogPresenter for more
|
||||
// information.
|
||||
Windows.Foundation.IAsyncOperation<Windows.UI.Xaml.Controls.ContentDialogResult> ShowDialog(Windows.UI.Xaml.Controls.ContentDialog dialog);
|
||||
void DismissDialog();
|
||||
event Windows.Foundation.TypedEventHandler<Object, SettingsLoadEventArgs> SettingsChanged;
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, Windows.UI.Xaml.UIElement> SetTitleBarContent;
|
||||
event Windows.Foundation.TypedEventHandler<Object, String> TitleChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, LastTabClosedEventArgs> LastTabClosed;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Microsoft.Terminal.Settings.Model.Theme> RequestedThemeChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> FocusModeChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> FullscreenChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ChangeMaximizeRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> AlwaysOnTopChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> RaiseVisualBell;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> SetTaskbarProgress;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> IdentifyWindowsRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, RenameWindowRequestedArgs> RenameWindowRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> SettingsChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> IsQuakeWindowChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> SummonWindowRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> CloseRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> OpenSystemMenu;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> QuitRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, TerminalApp.SystemMenuChangeArgs> SystemMenuChangeRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Microsoft.Terminal.Control.ShowWindowArgs> ShowWindowChanged;
|
||||
}
|
||||
}
|
||||
|
||||
30
src/cascadia/TerminalApp/SettingsLoadEventArgs.h
Normal file
30
src/cascadia/TerminalApp/SettingsLoadEventArgs.h
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "SettingsLoadEventArgs.g.h"
|
||||
#include <inc/cppwinrt_utils.h>
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct SettingsLoadEventArgs : SettingsLoadEventArgsT<SettingsLoadEventArgs>
|
||||
{
|
||||
WINRT_PROPERTY(bool, Reload, false);
|
||||
WINRT_PROPERTY(uint64_t, Result, S_OK);
|
||||
WINRT_PROPERTY(winrt::hstring, ExceptionText, L"");
|
||||
WINRT_PROPERTY(winrt::Windows::Foundation::Collections::IVector<Microsoft::Terminal::Settings::Model::SettingsLoadWarnings>, Warnings, nullptr);
|
||||
WINRT_PROPERTY(Microsoft::Terminal::Settings::Model::CascadiaSettings, NewSettings, nullptr);
|
||||
|
||||
public:
|
||||
SettingsLoadEventArgs(bool reload,
|
||||
uint64_t result,
|
||||
winrt::hstring exceptionText,
|
||||
winrt::Windows::Foundation::Collections::IVector<Microsoft::Terminal::Settings::Model::SettingsLoadWarnings> warnings,
|
||||
Microsoft::Terminal::Settings::Model::CascadiaSettings newSettings) :
|
||||
_Reload{ reload },
|
||||
_Result{ result },
|
||||
_ExceptionText{ std::move(exceptionText) },
|
||||
_Warnings{ std::move(warnings) },
|
||||
_NewSettings{ std::move(newSettings) } {};
|
||||
};
|
||||
}
|
||||
@ -523,13 +523,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// if the user manually closed all tabs.
|
||||
// Do this only if we are the last window; the monarch will notice
|
||||
// we are missing and remove us that way otherwise.
|
||||
if (!_maintainStateOnTabClose && ShouldUsePersistedLayout(_settings) && _numOpenWindows == 1)
|
||||
{
|
||||
auto state = ApplicationState::SharedInstance();
|
||||
state.PersistedWindowLayouts(nullptr);
|
||||
}
|
||||
|
||||
_LastTabClosedHandlers(*this, nullptr);
|
||||
_LastTabClosedHandlers(*this, winrt::make<LastTabClosedEventArgs>(!_maintainStateOnTabClose));
|
||||
}
|
||||
else if (focusedTabIndex.has_value() && focusedTabIndex.value() == gsl::narrow_cast<uint32_t>(tabIndex))
|
||||
{
|
||||
|
||||
@ -138,6 +138,12 @@
|
||||
<ClInclude Include="AppLogic.h">
|
||||
<DependentUpon>AppLogic.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TerminalWindow.h">
|
||||
<DependentUpon>TerminalWindow.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SettingsLoadEventArgs.h">
|
||||
<DependentUpon>TerminalWindow.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Toast.h" />
|
||||
</ItemGroup>
|
||||
<!-- ========================= Cpp Files ======================== -->
|
||||
@ -231,6 +237,9 @@
|
||||
<ClCompile Include="AppLogic.cpp">
|
||||
<DependentUpon>AppLogic.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TerminalWindow.cpp">
|
||||
<DependentUpon>TerminalWindow.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
<ClCompile Include="Toast.cpp" />
|
||||
</ItemGroup>
|
||||
@ -252,6 +261,7 @@
|
||||
<Midl Include="ShortcutActionDispatch.idl" />
|
||||
<Midl Include="AppKeyBindings.idl" />
|
||||
<Midl Include="AppLogic.idl" />
|
||||
<Midl Include="TerminalWindow.idl" />
|
||||
<Midl Include="MinMaxCloseControl.idl">
|
||||
<DependentUpon>MinMaxCloseControl.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include "pch.h"
|
||||
#include "TerminalPage.h"
|
||||
#include "TerminalPage.g.cpp"
|
||||
#include "LastTabClosedEventArgs.g.cpp"
|
||||
#include "RenameWindowRequestedArgs.g.cpp"
|
||||
|
||||
#include <filesystem>
|
||||
@ -51,13 +52,16 @@ namespace winrt
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
TerminalPage::TerminalPage() :
|
||||
TerminalPage::TerminalPage(TerminalApp::WindowProperties properties) :
|
||||
_tabs{ winrt::single_threaded_observable_vector<TerminalApp::TabBase>() },
|
||||
_mruTabs{ winrt::single_threaded_observable_vector<TerminalApp::TabBase>() },
|
||||
_startupActions{ winrt::single_threaded_vector<ActionAndArgs>() },
|
||||
_hostingHwnd{}
|
||||
_hostingHwnd{},
|
||||
_WindowProperties{ std::move(properties) }
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_WindowProperties.PropertyChanged({ get_weak(), &TerminalPage::_windowPropertyChanged });
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@ -321,18 +325,6 @@ namespace winrt::TerminalApp::implementation
|
||||
ShowSetAsDefaultInfoBar();
|
||||
}
|
||||
|
||||
// Method Description;
|
||||
// - Checks if the current terminal window should load or save its layout information.
|
||||
// Arguments:
|
||||
// - settings: The settings to use as this may be called before the page is
|
||||
// fully initialized.
|
||||
// Return Value:
|
||||
// - true if the ApplicationState should be used.
|
||||
bool TerminalPage::ShouldUsePersistedLayout(CascadiaSettings& settings) const
|
||||
{
|
||||
return settings.GlobalSettings().FirstWindowPreference() == FirstWindowPreference::PersistedWindowLayout;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - This is a bit of trickiness: If we're running unelevated, and the user
|
||||
// passed in only --elevate actions, the we don't _actually_ want to
|
||||
@ -347,7 +339,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// GH#12267: Don't forget about defterm handoff here. If we're being
|
||||
// created for embedding, then _yea_, we don't need to handoff to an
|
||||
// elevated window.
|
||||
if (!_startupActions || IsElevated() || _shouldStartInboundListener)
|
||||
if (!_startupActions || IsElevated() || _shouldStartInboundListener || _startupActions.Size() == 0)
|
||||
{
|
||||
// there aren't startup actions, or we're elevated. In that case, go for it.
|
||||
return false;
|
||||
@ -444,32 +436,6 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description;
|
||||
// - Checks if the current window is configured to load a particular layout
|
||||
// Arguments:
|
||||
// - settings: The settings to use as this may be called before the page is
|
||||
// fully initialized.
|
||||
// Return Value:
|
||||
// - non-null if there is a particular saved layout to use
|
||||
std::optional<uint32_t> TerminalPage::LoadPersistedLayoutIdx(CascadiaSettings& settings) const
|
||||
{
|
||||
return ShouldUsePersistedLayout(settings) ? _loadFromPersistedLayoutIdx : std::nullopt;
|
||||
}
|
||||
|
||||
WindowLayout TerminalPage::LoadPersistedLayout(CascadiaSettings& settings) const
|
||||
{
|
||||
if (const auto idx = LoadPersistedLayoutIdx(settings))
|
||||
{
|
||||
const auto i = idx.value();
|
||||
const auto layouts = ApplicationState::SharedInstance().PersistedWindowLayouts();
|
||||
if (layouts && layouts.Size() > i)
|
||||
{
|
||||
return layouts.GetAt(i);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
winrt::fire_and_forget TerminalPage::NewTerminalByDrop(winrt::Windows::UI::Xaml::DragEventArgs& e)
|
||||
{
|
||||
Windows::Foundation::Collections::IVectorView<Windows::Storage::IStorageItem> items;
|
||||
@ -553,16 +519,6 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
_startupState = StartupState::InStartup;
|
||||
|
||||
// If we are provided with an index, the cases where we have
|
||||
// commandline args and startup actions are already handled.
|
||||
if (const auto layout = LoadPersistedLayout(_settings))
|
||||
{
|
||||
if (layout.TabLayout().Size() > 0)
|
||||
{
|
||||
_startupActions = layout.TabLayout();
|
||||
}
|
||||
}
|
||||
|
||||
ProcessStartupActions(_startupActions, true);
|
||||
|
||||
// If we were told that the COM server needs to be started to listen for incoming
|
||||
@ -704,7 +660,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// have a tab yet, but will once we're initialized.
|
||||
if (_tabs.Size() == 0 && !(_shouldStartInboundListener || _isEmbeddingInboundListener))
|
||||
{
|
||||
_LastTabClosedHandlers(*this, nullptr);
|
||||
_LastTabClosedHandlers(*this, winrt::make<LastTabClosedEventArgs>(false));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1847,11 +1803,11 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
|
||||
// If the user set a custom name, save it
|
||||
if (_WindowName != L"")
|
||||
if (const auto& windowName{ _WindowProperties.WindowName() }; !windowName.empty())
|
||||
{
|
||||
ActionAndArgs action;
|
||||
action.Action(ShortcutAction::RenameWindow);
|
||||
RenameWindowArgs args{ _WindowName };
|
||||
RenameWindowArgs args{ windowName };
|
||||
action.Args(args);
|
||||
|
||||
actions.emplace_back(std::move(action));
|
||||
@ -1901,7 +1857,7 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
if (ShouldUsePersistedLayout(_settings))
|
||||
if (_settings.GlobalSettings().ShouldUsePersistedLayout())
|
||||
{
|
||||
// Don't delete the ApplicationState when all of the tabs are removed.
|
||||
// If there is still a monarch living they will get the event that
|
||||
@ -3856,105 +3812,6 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
// WindowName is a otherwise generic WINRT_OBSERVABLE_PROPERTY, but it needs
|
||||
// to raise a PropertyChanged for WindowNameForDisplay, instead of
|
||||
// WindowName.
|
||||
winrt::hstring TerminalPage::WindowName() const noexcept
|
||||
{
|
||||
return _WindowName;
|
||||
}
|
||||
|
||||
winrt::fire_and_forget TerminalPage::WindowName(const winrt::hstring& value)
|
||||
{
|
||||
const auto oldIsQuakeMode = IsQuakeWindow();
|
||||
const auto changed = _WindowName != value;
|
||||
if (changed)
|
||||
{
|
||||
_WindowName = value;
|
||||
}
|
||||
auto weakThis{ get_weak() };
|
||||
// On the foreground thread, raise property changed notifications, and
|
||||
// display the success toast.
|
||||
co_await wil::resume_foreground(Dispatcher());
|
||||
if (auto page{ weakThis.get() })
|
||||
{
|
||||
if (changed)
|
||||
{
|
||||
page->_PropertyChangedHandlers(*this, WUX::Data::PropertyChangedEventArgs{ L"WindowName" });
|
||||
page->_PropertyChangedHandlers(*this, WUX::Data::PropertyChangedEventArgs{ L"WindowNameForDisplay" });
|
||||
|
||||
// DON'T display the confirmation if this is the name we were
|
||||
// given on startup!
|
||||
if (page->_startupState == StartupState::Initialized)
|
||||
{
|
||||
page->IdentifyWindow();
|
||||
|
||||
// If we're entering quake mode, or leaving it
|
||||
if (IsQuakeWindow() != oldIsQuakeMode)
|
||||
{
|
||||
// If we're entering Quake Mode from ~Focus Mode, then this will enter Focus Mode
|
||||
// If we're entering Quake Mode from Focus Mode, then this will do nothing
|
||||
// If we're leaving Quake Mode (we're already in Focus Mode), then this will do nothing
|
||||
SetFocusMode(true);
|
||||
_IsQuakeWindowChangedHandlers(*this, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WindowId is a otherwise generic WINRT_OBSERVABLE_PROPERTY, but it needs
|
||||
// to raise a PropertyChanged for WindowIdForDisplay, instead of
|
||||
// WindowId.
|
||||
uint64_t TerminalPage::WindowId() const noexcept
|
||||
{
|
||||
return _WindowId;
|
||||
}
|
||||
void TerminalPage::WindowId(const uint64_t& value)
|
||||
{
|
||||
if (_WindowId != value)
|
||||
{
|
||||
_WindowId = value;
|
||||
_PropertyChangedHandlers(*this, WUX::Data::PropertyChangedEventArgs{ L"WindowIdForDisplay" });
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPage::SetPersistedLayoutIdx(const uint32_t idx)
|
||||
{
|
||||
_loadFromPersistedLayoutIdx = idx;
|
||||
}
|
||||
|
||||
void TerminalPage::SetNumberOfOpenWindows(const uint64_t num)
|
||||
{
|
||||
_numOpenWindows = num;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Returns a label like "Window: 1234" for the ID of this window
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - a string for displaying the name of the window.
|
||||
winrt::hstring TerminalPage::WindowIdForDisplay() const noexcept
|
||||
{
|
||||
return winrt::hstring{ fmt::format(L"{}: {}",
|
||||
std::wstring_view(RS_(L"WindowIdLabel")),
|
||||
_WindowId) };
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Returns a label like "<unnamed window>" when the window has no name, or the name of the window.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - a string for displaying the name of the window.
|
||||
winrt::hstring TerminalPage::WindowNameForDisplay() const noexcept
|
||||
{
|
||||
return _WindowName.empty() ?
|
||||
winrt::hstring{ fmt::format(L"<{}>", RS_(L"UnnamedWindowName")) } :
|
||||
_WindowName;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Called when an attempt to rename the window has failed. This will open
|
||||
// the toast displaying a message to the user that the attempt to rename
|
||||
@ -4066,17 +3923,12 @@ namespace winrt::TerminalApp::implementation
|
||||
else if (key == Windows::System::VirtualKey::Escape)
|
||||
{
|
||||
// User wants to discard the changes they made
|
||||
WindowRenamerTextBox().Text(WindowName());
|
||||
WindowRenamerTextBox().Text(_WindowProperties.WindowName());
|
||||
WindowRenamer().IsOpen(false);
|
||||
_renamerPressedEnter = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool TerminalPage::IsQuakeWindow() const noexcept
|
||||
{
|
||||
return WindowName() == QuakeWindowName;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - This function stops people from duplicating the base profile, because
|
||||
// it gets ~ ~ weird ~ ~ when they do. Remove when TODO GH#5047 is done.
|
||||
@ -4452,4 +4304,28 @@ namespace winrt::TerminalApp::implementation
|
||||
_activated = activated;
|
||||
_updateThemeColors();
|
||||
}
|
||||
|
||||
// Handler for our WindowProperties's PropertyChanged event. We'll use this
|
||||
// to pop the "Identify Window" toast when the user renames our window.
|
||||
winrt::fire_and_forget TerminalPage::_windowPropertyChanged(const IInspectable& /*sender*/,
|
||||
const WUX::Data::PropertyChangedEventArgs& args)
|
||||
{
|
||||
if (args.PropertyName() != L"WindowName")
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
auto weakThis{ get_weak() };
|
||||
// On the foreground thread, raise property changed notifications, and
|
||||
// display the success toast.
|
||||
co_await wil::resume_foreground(Dispatcher());
|
||||
if (auto page{ weakThis.get() })
|
||||
{
|
||||
// DON'T display the confirmation if this is the name we were
|
||||
// given on startup!
|
||||
if (page->_startupState == StartupState::Initialized)
|
||||
{
|
||||
page->IdentifyWindow();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include "TerminalTab.h"
|
||||
#include "AppKeyBindings.h"
|
||||
#include "AppCommandlineArgs.h"
|
||||
#include "LastTabClosedEventArgs.g.h"
|
||||
#include "RenameWindowRequestedArgs.g.h"
|
||||
#include "Toast.h"
|
||||
|
||||
@ -41,6 +42,15 @@ namespace winrt::TerminalApp::implementation
|
||||
ScrollDown = 1
|
||||
};
|
||||
|
||||
struct LastTabClosedEventArgs : LastTabClosedEventArgsT<LastTabClosedEventArgs>
|
||||
{
|
||||
WINRT_PROPERTY(bool, ClearPersistedState);
|
||||
|
||||
public:
|
||||
LastTabClosedEventArgs(const bool& shouldClear) :
|
||||
_ClearPersistedState{ shouldClear } {};
|
||||
};
|
||||
|
||||
struct RenameWindowRequestedArgs : RenameWindowRequestedArgsT<RenameWindowRequestedArgs>
|
||||
{
|
||||
WINRT_PROPERTY(winrt::hstring, ProposedName);
|
||||
@ -53,7 +63,7 @@ namespace winrt::TerminalApp::implementation
|
||||
struct TerminalPage : TerminalPageT<TerminalPage>
|
||||
{
|
||||
public:
|
||||
TerminalPage();
|
||||
TerminalPage(TerminalApp::WindowProperties properties);
|
||||
|
||||
// This implements shobjidl's IInitializeWithWindow, but due to a XAML Compiler bug we cannot
|
||||
// put it in our inheritance graph. https://github.com/microsoft/microsoft-ui-xaml/issues/3331
|
||||
@ -63,11 +73,8 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
void Create();
|
||||
|
||||
bool ShouldUsePersistedLayout(Microsoft::Terminal::Settings::Model::CascadiaSettings& settings) const;
|
||||
bool ShouldImmediatelyHandoffToElevated(const Microsoft::Terminal::Settings::Model::CascadiaSettings& settings) const;
|
||||
void HandoffToElevated(const Microsoft::Terminal::Settings::Model::CascadiaSettings& settings);
|
||||
std::optional<uint32_t> LoadPersistedLayoutIdx(Microsoft::Terminal::Settings::Model::CascadiaSettings& settings) const;
|
||||
winrt::Microsoft::Terminal::Settings::Model::WindowLayout LoadPersistedLayout(Microsoft::Terminal::Settings::Model::CascadiaSettings& settings) const;
|
||||
Microsoft::Terminal::Settings::Model::WindowLayout GetWindowLayout();
|
||||
|
||||
winrt::fire_and_forget NewTerminalByDrop(winrt::Windows::UI::Xaml::DragEventArgs& e);
|
||||
@ -117,20 +124,8 @@ namespace winrt::TerminalApp::implementation
|
||||
const bool initial,
|
||||
const winrt::hstring cwd = L"");
|
||||
|
||||
// Normally, WindowName and WindowId would be
|
||||
// WINRT_OBSERVABLE_PROPERTY's, but we want them to raise
|
||||
// WindowNameForDisplay and WindowIdForDisplay instead
|
||||
winrt::hstring WindowName() const noexcept;
|
||||
winrt::fire_and_forget WindowName(const winrt::hstring& value);
|
||||
uint64_t WindowId() const noexcept;
|
||||
void WindowId(const uint64_t& value);
|
||||
TerminalApp::WindowProperties WindowProperties() const noexcept { return _WindowProperties; };
|
||||
|
||||
void SetNumberOfOpenWindows(const uint64_t value);
|
||||
void SetPersistedLayoutIdx(const uint32_t value);
|
||||
|
||||
winrt::hstring WindowIdForDisplay() const noexcept;
|
||||
winrt::hstring WindowNameForDisplay() const noexcept;
|
||||
bool IsQuakeWindow() const noexcept;
|
||||
bool IsElevated() const noexcept;
|
||||
|
||||
void OpenSettingsUI();
|
||||
@ -153,7 +148,6 @@ namespace winrt::TerminalApp::implementation
|
||||
TYPED_EVENT(Initialized, IInspectable, winrt::Windows::UI::Xaml::RoutedEventArgs);
|
||||
TYPED_EVENT(IdentifyWindowsRequested, IInspectable, IInspectable);
|
||||
TYPED_EVENT(RenameWindowRequested, Windows::Foundation::IInspectable, winrt::TerminalApp::RenameWindowRequestedArgs);
|
||||
TYPED_EVENT(IsQuakeWindowChanged, IInspectable, IInspectable);
|
||||
TYPED_EVENT(SummonWindowRequested, IInspectable, IInspectable);
|
||||
TYPED_EVENT(CloseRequested, IInspectable, IInspectable);
|
||||
TYPED_EVENT(OpenSystemMenu, IInspectable, IInspectable);
|
||||
@ -192,10 +186,8 @@ namespace winrt::TerminalApp::implementation
|
||||
bool _isFullscreen{ false };
|
||||
bool _isMaximized{ false };
|
||||
bool _isAlwaysOnTop{ false };
|
||||
winrt::hstring _WindowName{};
|
||||
uint64_t _WindowId{ 0 };
|
||||
|
||||
std::optional<uint32_t> _loadFromPersistedLayoutIdx{};
|
||||
uint64_t _numOpenWindows{ 0 };
|
||||
|
||||
bool _maintainStateOnTabClose{ false };
|
||||
bool _rearranging{ false };
|
||||
@ -230,6 +222,8 @@ namespace winrt::TerminalApp::implementation
|
||||
int _renamerLayoutCount{ 0 };
|
||||
bool _renamerPressedEnter{ false };
|
||||
|
||||
TerminalApp::WindowProperties _WindowProperties{ nullptr };
|
||||
|
||||
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> _ShowDialogHelper(const std::wstring_view& name);
|
||||
|
||||
void _ShowAboutDialog();
|
||||
@ -461,6 +455,7 @@ namespace winrt::TerminalApp::implementation
|
||||
void _updateTabCloseButton(const winrt::Microsoft::UI::Xaml::Controls::TabViewItem& tabViewItem);
|
||||
|
||||
winrt::fire_and_forget _ShowWindowChangedHandler(const IInspectable sender, const winrt::Microsoft::Terminal::Control::ShowWindowArgs args);
|
||||
winrt::fire_and_forget _windowPropertyChanged(const IInspectable& sender, const winrt::Windows::UI::Xaml::Data::PropertyChangedEventArgs& args);
|
||||
|
||||
#pragma region ActionHandlers
|
||||
// These are all defined in AppActionHandlers.cpp
|
||||
|
||||
@ -5,7 +5,11 @@ import "IDirectKeyListener.idl";
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
delegate void LastTabClosedEventArgs();
|
||||
|
||||
[default_interface] runtimeclass LastTabClosedEventArgs
|
||||
{
|
||||
Boolean ClearPersistedState { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass RenameWindowRequestedArgs
|
||||
{
|
||||
@ -17,9 +21,19 @@ namespace TerminalApp
|
||||
Windows.Foundation.IAsyncOperation<Windows.UI.Xaml.Controls.ContentDialogResult> ShowDialog(Windows.UI.Xaml.Controls.ContentDialog dialog);
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass WindowProperties : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
String WindowName { get; };
|
||||
UInt64 WindowId { get; };
|
||||
String WindowNameForDisplay { get; };
|
||||
String WindowIdForDisplay { get; };
|
||||
|
||||
Boolean IsQuakeWindow();
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass TerminalPage : Windows.UI.Xaml.Controls.Page, Windows.UI.Xaml.Data.INotifyPropertyChanged, IDirectKeyListener
|
||||
{
|
||||
TerminalPage();
|
||||
TerminalPage(WindowProperties properties);
|
||||
|
||||
// XAML bound properties
|
||||
String ApplicationDisplayName { get; };
|
||||
@ -29,13 +43,9 @@ namespace TerminalApp
|
||||
Boolean Fullscreen { get; };
|
||||
Boolean AlwaysOnTop { get; };
|
||||
|
||||
WindowProperties WindowProperties { get; };
|
||||
void IdentifyWindow();
|
||||
String WindowName;
|
||||
UInt64 WindowId;
|
||||
String WindowNameForDisplay { get; };
|
||||
String WindowIdForDisplay { get; };
|
||||
void RenameFailed();
|
||||
Boolean IsQuakeWindow();
|
||||
|
||||
// We cannot use the default XAML APIs because we want to make sure
|
||||
// that there's only one application-global dialog visible at a time,
|
||||
@ -59,7 +69,6 @@ namespace TerminalApp
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> SetTaskbarProgress;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> IdentifyWindowsRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, RenameWindowRequestedArgs> RenameWindowRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> IsQuakeWindowChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> SummonWindowRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> CloseRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> OpenSystemMenu;
|
||||
|
||||
@ -201,10 +201,10 @@
|
||||
tracked by MUX#4382
|
||||
-->
|
||||
<mux:TeachingTip x:Name="WindowIdToast"
|
||||
Title="{x:Bind WindowIdForDisplay}"
|
||||
Title="{x:Bind WindowProperties.WindowIdForDisplay}"
|
||||
x:Load="False"
|
||||
IsLightDismissEnabled="True"
|
||||
Subtitle="{x:Bind WindowNameForDisplay, Mode=OneWay}" />
|
||||
Subtitle="{x:Bind WindowProperties.WindowNameForDisplay, Mode=OneWay}" />
|
||||
|
||||
<mux:TeachingTip x:Name="RenameFailedToast"
|
||||
x:Uid="RenameFailedToast"
|
||||
@ -213,7 +213,7 @@
|
||||
|
||||
<mux:TeachingTip x:Name="WindowRenamer"
|
||||
x:Uid="WindowRenamer"
|
||||
Title="{x:Bind WindowIdForDisplay}"
|
||||
Title="{x:Bind WindowProperties.WindowIdForDisplay}"
|
||||
x:Load="False"
|
||||
ActionButtonClick="_WindowRenamerActionClick"
|
||||
ActionButtonStyle="{ThemeResource AccentButtonStyle}"
|
||||
@ -222,7 +222,7 @@
|
||||
<TextBox x:Name="WindowRenamerTextBox"
|
||||
KeyDown="_WindowRenamerKeyDown"
|
||||
KeyUp="_WindowRenamerKeyUp"
|
||||
Text="{x:Bind WindowName, Mode=OneWay}" />
|
||||
Text="{x:Bind WindowProperties.WindowName, Mode=OneWay}" />
|
||||
</mux:TeachingTip.Content>
|
||||
</mux:TeachingTip>
|
||||
</Grid>
|
||||
|
||||
1280
src/cascadia/TerminalApp/TerminalWindow.cpp
Normal file
1280
src/cascadia/TerminalApp/TerminalWindow.cpp
Normal file
File diff suppressed because it is too large
Load Diff
223
src/cascadia/TerminalApp/TerminalWindow.h
Normal file
223
src/cascadia/TerminalApp/TerminalWindow.h
Normal file
@ -0,0 +1,223 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "TerminalWindow.g.h"
|
||||
#include "SystemMenuChangeArgs.g.h"
|
||||
#include "WindowProperties.g.h"
|
||||
|
||||
#include "SettingsLoadEventArgs.h"
|
||||
#include "TerminalPage.h"
|
||||
|
||||
#include <inc/cppwinrt_utils.h>
|
||||
#include <ThrottledFunc.h>
|
||||
|
||||
#ifdef UNIT_TESTING
|
||||
// fwdecl unittest classes
|
||||
namespace TerminalAppLocalTests
|
||||
{
|
||||
class CommandlineTest;
|
||||
};
|
||||
#endif
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct SystemMenuChangeArgs : SystemMenuChangeArgsT<SystemMenuChangeArgs>
|
||||
{
|
||||
WINRT_PROPERTY(winrt::hstring, Name, L"");
|
||||
WINRT_PROPERTY(SystemMenuChangeAction, Action, SystemMenuChangeAction::Add);
|
||||
WINRT_PROPERTY(SystemMenuItemHandler, Handler, nullptr);
|
||||
|
||||
public:
|
||||
SystemMenuChangeArgs(const winrt::hstring& name, SystemMenuChangeAction action, SystemMenuItemHandler handler = nullptr) :
|
||||
_Name{ name }, _Action{ action }, _Handler{ handler } {};
|
||||
};
|
||||
|
||||
struct WindowProperties : WindowPropertiesT<WindowProperties>
|
||||
{
|
||||
// Normally, WindowName and WindowId would be
|
||||
// WINRT_OBSERVABLE_PROPERTY's, but we want them to raise
|
||||
// WindowNameForDisplay and WindowIdForDisplay instead
|
||||
winrt::hstring WindowName() const noexcept;
|
||||
void WindowName(const winrt::hstring& value);
|
||||
uint64_t WindowId() const noexcept;
|
||||
void WindowId(const uint64_t& value);
|
||||
winrt::hstring WindowIdForDisplay() const noexcept;
|
||||
winrt::hstring WindowNameForDisplay() const noexcept;
|
||||
bool IsQuakeWindow() const noexcept;
|
||||
|
||||
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
||||
|
||||
private:
|
||||
winrt::hstring _WindowName{};
|
||||
uint64_t _WindowId{ 0 };
|
||||
};
|
||||
|
||||
struct TerminalWindow : TerminalWindowT<TerminalWindow, IInitializeWithWindow>
|
||||
{
|
||||
public:
|
||||
TerminalWindow(const TerminalApp::SettingsLoadEventArgs& settingsLoadedResult);
|
||||
~TerminalWindow() = default;
|
||||
|
||||
STDMETHODIMP Initialize(HWND hwnd);
|
||||
|
||||
void Create();
|
||||
|
||||
bool IsUwp() const noexcept;
|
||||
bool IsElevated() const noexcept;
|
||||
|
||||
void Quit();
|
||||
|
||||
winrt::fire_and_forget UpdateSettings(winrt::TerminalApp::SettingsLoadEventArgs args);
|
||||
|
||||
bool HasCommandlineArguments() const noexcept;
|
||||
|
||||
int32_t SetStartupCommandline(array_view<const winrt::hstring> actions);
|
||||
int32_t ExecuteCommandline(array_view<const winrt::hstring> actions, const winrt::hstring& cwd);
|
||||
void SetSettingsStartupArgs(const std::vector<winrt::Microsoft::Terminal::Settings::Model::ActionAndArgs>& actions);
|
||||
winrt::hstring ParseCommandlineMessage();
|
||||
bool ShouldExitEarly();
|
||||
|
||||
bool ShouldImmediatelyHandoffToElevated();
|
||||
void HandoffToElevated();
|
||||
|
||||
bool FocusMode() const;
|
||||
bool Fullscreen() const;
|
||||
void Maximized(bool newMaximized);
|
||||
bool AlwaysOnTop() const;
|
||||
bool AutoHideWindow();
|
||||
|
||||
hstring GetWindowLayoutJson(Microsoft::Terminal::Settings::Model::LaunchPosition position);
|
||||
void IdentifyWindow();
|
||||
void RenameFailed();
|
||||
|
||||
std::optional<uint32_t> LoadPersistedLayoutIdx() const;
|
||||
winrt::Microsoft::Terminal::Settings::Model::WindowLayout LoadPersistedLayout();
|
||||
|
||||
void SetPersistedLayoutIdx(const uint32_t idx);
|
||||
void SetNumberOfOpenWindows(const uint64_t num);
|
||||
bool ShouldUsePersistedLayout() const;
|
||||
void ClearPersistedWindowState();
|
||||
|
||||
void RequestExitFullscreen();
|
||||
|
||||
Windows::Foundation::Size GetLaunchDimensions(uint32_t dpi);
|
||||
bool CenterOnLaunch();
|
||||
TerminalApp::InitialPosition GetInitialPosition(int64_t defaultInitialX, int64_t defaultInitialY);
|
||||
winrt::Windows::UI::Xaml::ElementTheme GetRequestedTheme();
|
||||
Microsoft::Terminal::Settings::Model::LaunchMode GetLaunchMode();
|
||||
bool GetShowTabsInTitlebar();
|
||||
bool GetInitialAlwaysOnTop();
|
||||
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
||||
|
||||
Windows::UI::Xaml::UIElement GetRoot() noexcept;
|
||||
|
||||
hstring Title();
|
||||
void TitlebarClicked();
|
||||
bool OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down);
|
||||
|
||||
void CloseWindow(Microsoft::Terminal::Settings::Model::LaunchPosition position, const bool isLastWindow);
|
||||
void WindowVisibilityChanged(const bool showOrHide);
|
||||
|
||||
winrt::TerminalApp::TaskbarState TaskbarState();
|
||||
winrt::Windows::UI::Xaml::Media::Brush TitlebarBrush();
|
||||
void WindowActivated(const bool activated);
|
||||
|
||||
bool GetMinimizeToNotificationArea();
|
||||
bool GetAlwaysShowNotificationIcon();
|
||||
bool GetShowTitleInTitlebar();
|
||||
|
||||
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> ShowDialog(winrt::Windows::UI::Xaml::Controls::ContentDialog dialog);
|
||||
void DismissDialog();
|
||||
|
||||
Microsoft::Terminal::Settings::Model::Theme Theme();
|
||||
void UpdateSettingsHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::TerminalApp::SettingsLoadEventArgs& arg);
|
||||
|
||||
void WindowName(const winrt::hstring& value);
|
||||
void WindowId(const uint64_t& value);
|
||||
bool IsQuakeWindow() const noexcept { return _WindowProperties->IsQuakeWindow(); }
|
||||
TerminalApp::WindowProperties WindowProperties() { return *_WindowProperties; }
|
||||
|
||||
// -------------------------------- WinRT Events ---------------------------------
|
||||
// PropertyChanged is surprisingly not a typed event, so we'll define that one manually.
|
||||
// Usually we'd just do
|
||||
// WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
||||
//
|
||||
// But what we're doing here is exposing the Page's PropertyChanged _as
|
||||
// our own event_. It's a FORWARDED_CALLBACK, essentially.
|
||||
winrt::event_token PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler) { return _root->PropertyChanged(handler); }
|
||||
void PropertyChanged(winrt::event_token const& token) { _root->PropertyChanged(token); }
|
||||
|
||||
TYPED_EVENT(RequestedThemeChanged, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Settings::Model::Theme);
|
||||
|
||||
private:
|
||||
// If you add controls here, but forget to null them either here or in
|
||||
// the ctor, you're going to have a bad time. It'll mysteriously fail to
|
||||
// activate the AppLogic.
|
||||
// ALSO: If you add any UIElements as roots here, make sure they're
|
||||
// updated in _ApplyTheme. The root currently is _root.
|
||||
winrt::com_ptr<TerminalPage> _root{ nullptr };
|
||||
winrt::Windows::UI::Xaml::Controls::ContentDialog _dialog{ nullptr };
|
||||
std::shared_mutex _dialogLock;
|
||||
|
||||
bool _hasCommandLineArguments{ false };
|
||||
::TerminalApp::AppCommandlineArgs _appArgs;
|
||||
bool _gotSettingsStartupActions{ false };
|
||||
std::vector<winrt::Microsoft::Terminal::Settings::Model::ActionAndArgs> _settingsStartupArgs{};
|
||||
|
||||
winrt::com_ptr<TerminalApp::implementation::WindowProperties> _WindowProperties{ nullptr };
|
||||
|
||||
std::optional<uint32_t> _loadFromPersistedLayoutIdx{};
|
||||
std::optional<winrt::Microsoft::Terminal::Settings::Model::WindowLayout> _cachedLayout{ std::nullopt };
|
||||
|
||||
Microsoft::Terminal::Settings::Model::CascadiaSettings _settings{ nullptr };
|
||||
TerminalApp::SettingsLoadEventArgs _initialLoadResult{ nullptr };
|
||||
|
||||
void _ShowLoadErrorsDialog(const winrt::hstring& titleKey,
|
||||
const winrt::hstring& contentKey,
|
||||
HRESULT settingsLoadedResult,
|
||||
const winrt::hstring& exceptionText);
|
||||
void _ShowLoadWarningsDialog(const Windows::Foundation::Collections::IVector<Microsoft::Terminal::Settings::Model::SettingsLoadWarnings>& warnings);
|
||||
|
||||
bool _IsKeyboardServiceEnabled();
|
||||
|
||||
void _RefreshThemeRoutine();
|
||||
void _OnLoaded(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
|
||||
void _OpenSettingsUI();
|
||||
// These are events that are handled by the TerminalPage, but are
|
||||
// exposed through the AppLogic. This macro is used to forward the event
|
||||
// directly to them.
|
||||
FORWARDED_TYPED_EVENT(SetTitleBarContent, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::UIElement, _root, SetTitleBarContent);
|
||||
FORWARDED_TYPED_EVENT(TitleChanged, winrt::Windows::Foundation::IInspectable, winrt::hstring, _root, TitleChanged);
|
||||
FORWARDED_TYPED_EVENT(LastTabClosed, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::LastTabClosedEventArgs, _root, LastTabClosed);
|
||||
FORWARDED_TYPED_EVENT(FocusModeChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, FocusModeChanged);
|
||||
FORWARDED_TYPED_EVENT(FullscreenChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, FullscreenChanged);
|
||||
FORWARDED_TYPED_EVENT(ChangeMaximizeRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, ChangeMaximizeRequested);
|
||||
FORWARDED_TYPED_EVENT(AlwaysOnTopChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, AlwaysOnTopChanged);
|
||||
FORWARDED_TYPED_EVENT(RaiseVisualBell, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, RaiseVisualBell);
|
||||
FORWARDED_TYPED_EVENT(SetTaskbarProgress, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, SetTaskbarProgress);
|
||||
FORWARDED_TYPED_EVENT(IdentifyWindowsRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, IdentifyWindowsRequested);
|
||||
FORWARDED_TYPED_EVENT(RenameWindowRequested, Windows::Foundation::IInspectable, winrt::TerminalApp::RenameWindowRequestedArgs, _root, RenameWindowRequested);
|
||||
FORWARDED_TYPED_EVENT(SummonWindowRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, SummonWindowRequested);
|
||||
FORWARDED_TYPED_EVENT(CloseRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, CloseRequested);
|
||||
FORWARDED_TYPED_EVENT(OpenSystemMenu, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, OpenSystemMenu);
|
||||
FORWARDED_TYPED_EVENT(QuitRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, QuitRequested);
|
||||
FORWARDED_TYPED_EVENT(ShowWindowChanged, Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Control::ShowWindowArgs, _root, ShowWindowChanged);
|
||||
|
||||
TYPED_EVENT(IsQuakeWindowChanged, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable);
|
||||
|
||||
TYPED_EVENT(SystemMenuChangeRequested, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::SystemMenuChangeArgs);
|
||||
|
||||
TYPED_EVENT(SettingsChanged, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::SettingsLoadEventArgs);
|
||||
|
||||
#ifdef UNIT_TESTING
|
||||
friend class TerminalAppLocalTests::CommandlineTest;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::TerminalApp::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(TerminalWindow);
|
||||
}
|
||||
142
src/cascadia/TerminalApp/TerminalWindow.idl
Normal file
142
src/cascadia/TerminalApp/TerminalWindow.idl
Normal file
@ -0,0 +1,142 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "TerminalPage.idl";
|
||||
import "ShortcutActionDispatch.idl";
|
||||
import "IDirectKeyListener.idl";
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
struct InitialPosition
|
||||
{
|
||||
Int64 X;
|
||||
Int64 Y;
|
||||
};
|
||||
|
||||
delegate void SystemMenuItemHandler();
|
||||
|
||||
enum SystemMenuChangeAction
|
||||
{
|
||||
Add = 0,
|
||||
Remove = 1
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass SystemMenuChangeArgs {
|
||||
String Name { get; };
|
||||
SystemMenuChangeAction Action { get; };
|
||||
SystemMenuItemHandler Handler { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass SettingsLoadEventArgs
|
||||
{
|
||||
Boolean Reload { get; };
|
||||
UInt64 Result { get; };
|
||||
IVector<Microsoft.Terminal.Settings.Model.SettingsLoadWarnings> Warnings { get; };
|
||||
String ExceptionText { get; };
|
||||
|
||||
Microsoft.Terminal.Settings.Model.CascadiaSettings NewSettings { get; };
|
||||
|
||||
};
|
||||
|
||||
// See IDialogPresenter and TerminalPage's DialogPresenter for more
|
||||
// information.
|
||||
[default_interface] runtimeclass TerminalWindow : IDirectKeyListener, IDialogPresenter, Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
TerminalWindow(SettingsLoadEventArgs result);
|
||||
|
||||
// For your own sanity, it's better to do setup outside the ctor.
|
||||
// If you do any setup in the ctor that ends up throwing an exception,
|
||||
// then it might look like TermApp just failed to activate, which will
|
||||
// cause you to chase down the rabbit hole of "why is TermApp not
|
||||
// registered?" when it definitely is.
|
||||
void Create();
|
||||
|
||||
Boolean IsElevated();
|
||||
|
||||
Boolean HasCommandlineArguments();
|
||||
|
||||
Int32 SetStartupCommandline(String[] commands);
|
||||
|
||||
Int32 ExecuteCommandline(String[] commands, String cwd);
|
||||
String ParseCommandlineMessage { get; };
|
||||
Boolean ShouldExitEarly { get; };
|
||||
|
||||
Boolean ShouldImmediatelyHandoffToElevated();
|
||||
void HandoffToElevated();
|
||||
|
||||
void Quit();
|
||||
|
||||
Windows.UI.Xaml.UIElement GetRoot();
|
||||
|
||||
String Title { get; };
|
||||
Boolean FocusMode { get; };
|
||||
Boolean Fullscreen { get; };
|
||||
void Maximized(Boolean newMaximized);
|
||||
Boolean AlwaysOnTop { get; };
|
||||
Boolean AutoHideWindow { get; };
|
||||
|
||||
void IdentifyWindow();
|
||||
void SetPersistedLayoutIdx(UInt32 idx);
|
||||
void ClearPersistedWindowState();
|
||||
|
||||
void RenameFailed();
|
||||
void RequestExitFullscreen();
|
||||
|
||||
Windows.Foundation.Size GetLaunchDimensions(UInt32 dpi);
|
||||
Boolean CenterOnLaunch { get; };
|
||||
|
||||
InitialPosition GetInitialPosition(Int64 defaultInitialX, Int64 defaultInitialY);
|
||||
Windows.UI.Xaml.ElementTheme GetRequestedTheme();
|
||||
Microsoft.Terminal.Settings.Model.LaunchMode GetLaunchMode();
|
||||
Boolean GetShowTabsInTitlebar();
|
||||
Boolean GetInitialAlwaysOnTop();
|
||||
Single CalcSnappedDimension(Boolean widthOrHeight, Single dimension);
|
||||
void TitlebarClicked();
|
||||
void CloseWindow(Microsoft.Terminal.Settings.Model.LaunchPosition position, Boolean isLastWindow);
|
||||
void WindowVisibilityChanged(Boolean showOrHide);
|
||||
|
||||
TaskbarState TaskbarState{ get; };
|
||||
Windows.UI.Xaml.Media.Brush TitlebarBrush { get; };
|
||||
void WindowActivated(Boolean activated);
|
||||
|
||||
String GetWindowLayoutJson(Microsoft.Terminal.Settings.Model.LaunchPosition position);
|
||||
|
||||
Boolean GetMinimizeToNotificationArea();
|
||||
Boolean GetAlwaysShowNotificationIcon();
|
||||
Boolean GetShowTitleInTitlebar();
|
||||
|
||||
// These already have accessors as a part of IWindowProperties, but we
|
||||
// also want to be able to set them.
|
||||
WindowProperties WindowProperties { get; };
|
||||
void WindowName(String name);
|
||||
void WindowId(UInt64 id);
|
||||
Boolean IsQuakeWindow();
|
||||
|
||||
// See IDialogPresenter and TerminalPage's DialogPresenter for more
|
||||
// information.
|
||||
void DismissDialog();
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, Windows.UI.Xaml.UIElement> SetTitleBarContent;
|
||||
event Windows.Foundation.TypedEventHandler<Object, String> TitleChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, LastTabClosedEventArgs> LastTabClosed;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Microsoft.Terminal.Settings.Model.Theme> RequestedThemeChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> FocusModeChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> FullscreenChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ChangeMaximizeRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> AlwaysOnTopChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> RaiseVisualBell;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> SetTaskbarProgress;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> IdentifyWindowsRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, RenameWindowRequestedArgs> RenameWindowRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> IsQuakeWindowChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> SummonWindowRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> CloseRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> OpenSystemMenu;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> QuitRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, TerminalApp.SystemMenuChangeArgs> SystemMenuChangeRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Microsoft.Terminal.Control.ShowWindowArgs> ShowWindowChanged;
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, SettingsLoadEventArgs> SettingsChanged;
|
||||
|
||||
}
|
||||
}
|
||||
@ -239,3 +239,8 @@ winrt::Windows::Foundation::Collections::IMapView<winrt::hstring, winrt::Microso
|
||||
{
|
||||
return _themes.GetView();
|
||||
}
|
||||
|
||||
bool GlobalAppSettings::ShouldUsePersistedLayout() const
|
||||
{
|
||||
return FirstWindowPreference() == FirstWindowPreference::PersistedWindowLayout;
|
||||
}
|
||||
|
||||
@ -62,6 +62,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
Windows::Foundation::Collections::IMapView<hstring, Model::Theme> Themes() noexcept;
|
||||
void AddTheme(const Model::Theme& theme);
|
||||
Model::Theme CurrentTheme() noexcept;
|
||||
bool ShouldUsePersistedLayout() const;
|
||||
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, UnparsedDefaultProfile, L"");
|
||||
|
||||
|
||||
@ -108,5 +108,6 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
void AddTheme(Theme theme);
|
||||
INHERITABLE_SETTING(ThemePair, Theme);
|
||||
Theme CurrentTheme { get; };
|
||||
Boolean ShouldUsePersistedLayout();
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,11 +31,12 @@ static constexpr short KeyPressed{ gsl::narrow_cast<short>(0x8000) };
|
||||
AppHost::AppHost() noexcept :
|
||||
_app{},
|
||||
_windowManager{},
|
||||
_logic{ nullptr }, // don't make one, we're going to take a ref on app's
|
||||
_appLogic{ nullptr }, // don't make one, we're going to take a ref on app's
|
||||
_windowLogic{ nullptr },
|
||||
_window{ nullptr },
|
||||
_getWindowLayoutThrottler{} // this will get set if we become the monarch
|
||||
{
|
||||
_logic = _app.Logic(); // get a ref to app's logic
|
||||
_appLogic = _app.Logic(); // get a ref to app's logic
|
||||
|
||||
// Inform the WindowManager that it can use us to find the target window for
|
||||
// a set of commandline args. This needs to be done before
|
||||
@ -54,10 +55,11 @@ AppHost::AppHost() noexcept :
|
||||
return;
|
||||
}
|
||||
|
||||
_useNonClientArea = _logic.GetShowTabsInTitlebar();
|
||||
// _HandleCommandlineArgs will create a _windowLogic
|
||||
_useNonClientArea = _windowLogic.GetShowTabsInTitlebar();
|
||||
if (_useNonClientArea)
|
||||
{
|
||||
_window = std::make_unique<NonClientIslandWindow>(_logic.GetRequestedTheme());
|
||||
_window = std::make_unique<NonClientIslandWindow>(_windowLogic.GetRequestedTheme());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -67,7 +69,7 @@ AppHost::AppHost() noexcept :
|
||||
// Update our own internal state tracking if we're in quake mode or not.
|
||||
_IsQuakeWindowChanged(nullptr, nullptr);
|
||||
|
||||
_window->SetMinimizeToNotificationAreaBehavior(_logic.GetMinimizeToNotificationArea());
|
||||
_window->SetMinimizeToNotificationAreaBehavior(_windowLogic.GetMinimizeToNotificationArea());
|
||||
|
||||
// Tell the window to callback to us when it's about to handle a WM_CREATE
|
||||
auto pfn = std::bind(&AppHost::_HandleCreateWindow,
|
||||
@ -77,11 +79,6 @@ AppHost::AppHost() noexcept :
|
||||
std::placeholders::_3);
|
||||
_window->SetCreateCallback(pfn);
|
||||
|
||||
_window->SetSnapDimensionCallback(std::bind(&winrt::TerminalApp::AppLogic::CalcSnappedDimension,
|
||||
_logic,
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2));
|
||||
|
||||
// Event handlers:
|
||||
// MAKE SURE THEY ARE ALL:
|
||||
// * winrt::auto_revoke
|
||||
@ -100,10 +97,10 @@ AppHost::AppHost() noexcept :
|
||||
_window->WindowActivated({ this, &AppHost::_WindowActivated });
|
||||
_window->WindowMoved({ this, &AppHost::_WindowMoved });
|
||||
_window->HotkeyPressed({ this, &AppHost::_GlobalHotkeyPressed });
|
||||
_window->ShouldExitFullscreen({ &_logic, &winrt::TerminalApp::AppLogic::RequestExitFullscreen });
|
||||
_window->ShouldExitFullscreen({ &_windowLogic, &winrt::TerminalApp::TerminalWindow::RequestExitFullscreen });
|
||||
|
||||
_window->SetAlwaysOnTop(_logic.GetInitialAlwaysOnTop());
|
||||
_window->SetAutoHideWindow(_logic.AutoHideWindow());
|
||||
_window->SetAlwaysOnTop(_windowLogic.GetInitialAlwaysOnTop());
|
||||
_window->SetAutoHideWindow(_windowLogic.AutoHideWindow());
|
||||
|
||||
_window->MakeWindow();
|
||||
|
||||
@ -118,19 +115,6 @@ AppHost::AppHost() noexcept :
|
||||
{
|
||||
_BecomeMonarch(nullptr, nullptr);
|
||||
}
|
||||
|
||||
// Create a throttled function for updating the window state, to match the
|
||||
// one requested by the pty. A 200ms delay was chosen because it's the
|
||||
// typical animation timeout in Windows. This does result in a delay between
|
||||
// the PTY requesting a change to the window state and the Terminal
|
||||
// realizing it, but should mitigate issues where the Terminal and PTY get
|
||||
// de-sync'd.
|
||||
_showHideWindowThrottler = std::make_shared<ThrottledFuncTrailing<bool>>(
|
||||
winrt::Windows::System::DispatcherQueue::GetForCurrentThread(),
|
||||
std::chrono::milliseconds(200),
|
||||
[this](const bool show) {
|
||||
_window->ShowWindowChanged(show);
|
||||
});
|
||||
}
|
||||
|
||||
AppHost::~AppHost()
|
||||
@ -152,9 +136,9 @@ AppHost::~AppHost()
|
||||
|
||||
bool AppHost::OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down)
|
||||
{
|
||||
if (_logic)
|
||||
if (_windowLogic)
|
||||
{
|
||||
return _logic.OnDirectKeyEvent(vkey, scanCode, down);
|
||||
return _windowLogic.OnDirectKeyEvent(vkey, scanCode, down);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -169,9 +153,9 @@ bool AppHost::OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, cons
|
||||
void AppHost::SetTaskbarProgress(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
||||
const winrt::Windows::Foundation::IInspectable& /*args*/)
|
||||
{
|
||||
if (_logic)
|
||||
if (_windowLogic)
|
||||
{
|
||||
const auto state = _logic.TaskbarState();
|
||||
const auto state = _windowLogic.TaskbarState();
|
||||
_window->SetTaskbarProgress(gsl::narrow_cast<size_t>(state.State()),
|
||||
gsl::narrow_cast<size_t>(state.Progress()));
|
||||
}
|
||||
@ -231,12 +215,16 @@ void AppHost::_HandleCommandlineArgs()
|
||||
return;
|
||||
}
|
||||
|
||||
// We did want to make a window, so let's instantiate it here.
|
||||
// We don't have XAML yet, but we do have other stuff.
|
||||
_windowLogic = _appLogic.CreateNewWindow();
|
||||
|
||||
if (auto peasant{ _windowManager.CurrentWindow() })
|
||||
{
|
||||
if (auto args{ peasant.InitialArgs() })
|
||||
{
|
||||
const auto result = _logic.SetStartupCommandline(args.Commandline());
|
||||
const auto message = _logic.ParseCommandlineMessage();
|
||||
const auto result = _windowLogic.SetStartupCommandline(args.Commandline());
|
||||
const auto message = _windowLogic.ParseCommandlineMessage();
|
||||
if (!message.empty())
|
||||
{
|
||||
const auto displayHelp = result == 0;
|
||||
@ -249,7 +237,7 @@ void AppHost::_HandleCommandlineArgs()
|
||||
GetStringResource(messageTitle).data(),
|
||||
MB_OK | messageIcon);
|
||||
|
||||
if (_logic.ShouldExitEarly())
|
||||
if (_windowLogic.ShouldExitEarly())
|
||||
{
|
||||
ExitProcess(result);
|
||||
}
|
||||
@ -263,10 +251,10 @@ void AppHost::_HandleCommandlineArgs()
|
||||
// the window at all here. In that case, we're going through this
|
||||
// special escape hatch to dispatch all the calls to elevate-shim, and
|
||||
// then we're going to exit immediately.
|
||||
if (_logic.ShouldImmediatelyHandoffToElevated())
|
||||
if (_windowLogic.ShouldImmediatelyHandoffToElevated())
|
||||
{
|
||||
_shouldCreateWindow = false;
|
||||
_logic.HandoffToElevated();
|
||||
_windowLogic.HandoffToElevated();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -288,7 +276,7 @@ void AppHost::_HandleCommandlineArgs()
|
||||
{
|
||||
const auto numPeasants = _windowManager.GetNumberOfPeasants();
|
||||
const auto layouts = ApplicationState::SharedInstance().PersistedWindowLayouts();
|
||||
if (_logic.ShouldUsePersistedLayout() &&
|
||||
if (_appLogic.ShouldUsePersistedLayout() &&
|
||||
layouts &&
|
||||
layouts.Size() > 0)
|
||||
{
|
||||
@ -299,9 +287,9 @@ void AppHost::_HandleCommandlineArgs()
|
||||
// Otherwise create this window normally with its commandline, and create
|
||||
// a new window using the first saved layout information.
|
||||
// The 2nd+ layout will always get a new window.
|
||||
if (numPeasants == 1 && !_logic.HasCommandlineArguments() && !_logic.HasSettingsStartupActions())
|
||||
if (numPeasants == 1 && !_windowLogic.HasCommandlineArguments() && !_appLogic.HasSettingsStartupActions())
|
||||
{
|
||||
_logic.SetPersistedLayoutIdx(startIdx);
|
||||
_windowLogic.SetPersistedLayoutIdx(startIdx);
|
||||
startIdx += 1;
|
||||
}
|
||||
|
||||
@ -328,10 +316,9 @@ void AppHost::_HandleCommandlineArgs()
|
||||
));
|
||||
}
|
||||
}
|
||||
_logic.SetNumberOfOpenWindows(numPeasants);
|
||||
}
|
||||
_logic.WindowName(peasant.WindowName());
|
||||
_logic.WindowId(peasant.GetID());
|
||||
_windowLogic.WindowName(peasant.WindowName());
|
||||
_windowLogic.WindowId(peasant.GetID());
|
||||
}
|
||||
}
|
||||
|
||||
@ -350,7 +337,7 @@ void AppHost::Initialize()
|
||||
{
|
||||
_window->Initialize();
|
||||
|
||||
if (auto withWindow{ _logic.try_as<IInitializeWithWindow>() })
|
||||
if (auto withWindow{ _windowLogic.try_as<IInitializeWithWindow>() })
|
||||
{
|
||||
withWindow->Initialize(_window->GetHandle());
|
||||
}
|
||||
@ -360,7 +347,7 @@ void AppHost::Initialize()
|
||||
// Register our callback for when the app's non-client content changes.
|
||||
// This has to be done _before_ App::Create, as the app might set the
|
||||
// content in Create.
|
||||
_logic.SetTitleBarContent({ this, &AppHost::_UpdateTitleBarContent });
|
||||
_windowLogic.SetTitleBarContent({ this, &AppHost::_UpdateTitleBarContent });
|
||||
}
|
||||
|
||||
// MORE EVENT HANDLERS HERE!
|
||||
@ -383,27 +370,27 @@ void AppHost::Initialize()
|
||||
});
|
||||
// If the user requests a close in another way handle the same as if the 'X'
|
||||
// was clicked.
|
||||
_revokers.CloseRequested = _logic.CloseRequested(winrt::auto_revoke, { this, &AppHost::_CloseRequested });
|
||||
_revokers.CloseRequested = _windowLogic.CloseRequested(winrt::auto_revoke, { this, &AppHost::_CloseRequested });
|
||||
|
||||
// Add an event handler to plumb clicks in the titlebar area down to the
|
||||
// application layer.
|
||||
_window->DragRegionClicked([this]() { _logic.TitlebarClicked(); });
|
||||
_window->DragRegionClicked([this]() { _windowLogic.TitlebarClicked(); });
|
||||
|
||||
_window->WindowVisibilityChanged([this](bool showOrHide) { _logic.WindowVisibilityChanged(showOrHide); });
|
||||
_window->UpdateSettingsRequested([this]() { _logic.ReloadSettings(); });
|
||||
_window->WindowVisibilityChanged([this](bool showOrHide) { _windowLogic.WindowVisibilityChanged(showOrHide); });
|
||||
_window->UpdateSettingsRequested([this]() { _appLogic.ReloadSettings(); });
|
||||
|
||||
_revokers.RequestedThemeChanged = _logic.RequestedThemeChanged(winrt::auto_revoke, { this, &AppHost::_UpdateTheme });
|
||||
_revokers.FullscreenChanged = _logic.FullscreenChanged(winrt::auto_revoke, { this, &AppHost::_FullscreenChanged });
|
||||
_revokers.FocusModeChanged = _logic.FocusModeChanged(winrt::auto_revoke, { this, &AppHost::_FocusModeChanged });
|
||||
_revokers.AlwaysOnTopChanged = _logic.AlwaysOnTopChanged(winrt::auto_revoke, { this, &AppHost::_AlwaysOnTopChanged });
|
||||
_revokers.RaiseVisualBell = _logic.RaiseVisualBell(winrt::auto_revoke, { this, &AppHost::_RaiseVisualBell });
|
||||
_revokers.SystemMenuChangeRequested = _logic.SystemMenuChangeRequested(winrt::auto_revoke, { this, &AppHost::_SystemMenuChangeRequested });
|
||||
_revokers.ChangeMaximizeRequested = _logic.ChangeMaximizeRequested(winrt::auto_revoke, { this, &AppHost::_ChangeMaximizeRequested });
|
||||
_revokers.RequestedThemeChanged = _windowLogic.RequestedThemeChanged(winrt::auto_revoke, { this, &AppHost::_UpdateTheme });
|
||||
_revokers.FullscreenChanged = _windowLogic.FullscreenChanged(winrt::auto_revoke, { this, &AppHost::_FullscreenChanged });
|
||||
_revokers.FocusModeChanged = _windowLogic.FocusModeChanged(winrt::auto_revoke, { this, &AppHost::_FocusModeChanged });
|
||||
_revokers.AlwaysOnTopChanged = _windowLogic.AlwaysOnTopChanged(winrt::auto_revoke, { this, &AppHost::_AlwaysOnTopChanged });
|
||||
_revokers.RaiseVisualBell = _windowLogic.RaiseVisualBell(winrt::auto_revoke, { this, &AppHost::_RaiseVisualBell });
|
||||
_revokers.SystemMenuChangeRequested = _windowLogic.SystemMenuChangeRequested(winrt::auto_revoke, { this, &AppHost::_SystemMenuChangeRequested });
|
||||
_revokers.ChangeMaximizeRequested = _windowLogic.ChangeMaximizeRequested(winrt::auto_revoke, { this, &AppHost::_ChangeMaximizeRequested });
|
||||
|
||||
_window->MaximizeChanged([this](bool newMaximize) {
|
||||
if (_logic)
|
||||
if (_windowLogic)
|
||||
{
|
||||
_logic.Maximized(newMaximize);
|
||||
_windowLogic.Maximized(newMaximize);
|
||||
}
|
||||
});
|
||||
|
||||
@ -416,21 +403,28 @@ void AppHost::Initialize()
|
||||
// Load bearing: make sure the PropertyChanged handler is added before we
|
||||
// call Create, so that when the app sets up the titlebar brush, we're
|
||||
// already prepared to listen for the change notification
|
||||
_revokers.PropertyChanged = _logic.PropertyChanged(winrt::auto_revoke, { this, &AppHost::_PropertyChangedHandler });
|
||||
_revokers.PropertyChanged = _windowLogic.PropertyChanged(winrt::auto_revoke, { this, &AppHost::_PropertyChangedHandler });
|
||||
|
||||
_logic.Create();
|
||||
_appLogic.Create();
|
||||
_windowLogic.Create();
|
||||
|
||||
_revokers.TitleChanged = _logic.TitleChanged(winrt::auto_revoke, { this, &AppHost::AppTitleChanged });
|
||||
_revokers.LastTabClosed = _logic.LastTabClosed(winrt::auto_revoke, { this, &AppHost::LastTabClosed });
|
||||
_revokers.SetTaskbarProgress = _logic.SetTaskbarProgress(winrt::auto_revoke, { this, &AppHost::SetTaskbarProgress });
|
||||
_revokers.IdentifyWindowsRequested = _logic.IdentifyWindowsRequested(winrt::auto_revoke, { this, &AppHost::_IdentifyWindowsRequested });
|
||||
_revokers.RenameWindowRequested = _logic.RenameWindowRequested(winrt::auto_revoke, { this, &AppHost::_RenameWindowRequested });
|
||||
_revokers.SettingsChanged = _logic.SettingsChanged(winrt::auto_revoke, { this, &AppHost::_HandleSettingsChanged });
|
||||
_revokers.IsQuakeWindowChanged = _logic.IsQuakeWindowChanged(winrt::auto_revoke, { this, &AppHost::_IsQuakeWindowChanged });
|
||||
_revokers.SummonWindowRequested = _logic.SummonWindowRequested(winrt::auto_revoke, { this, &AppHost::_SummonWindowRequested });
|
||||
_revokers.OpenSystemMenu = _logic.OpenSystemMenu(winrt::auto_revoke, { this, &AppHost::_OpenSystemMenu });
|
||||
_revokers.QuitRequested = _logic.QuitRequested(winrt::auto_revoke, { this, &AppHost::_RequestQuitAll });
|
||||
_revokers.ShowWindowChanged = _logic.ShowWindowChanged(winrt::auto_revoke, { this, &AppHost::_ShowWindowChanged });
|
||||
_revokers.TitleChanged = _windowLogic.TitleChanged(winrt::auto_revoke, { this, &AppHost::AppTitleChanged });
|
||||
_revokers.LastTabClosed = _windowLogic.LastTabClosed(winrt::auto_revoke, { this, &AppHost::LastTabClosed });
|
||||
_revokers.SetTaskbarProgress = _windowLogic.SetTaskbarProgress(winrt::auto_revoke, { this, &AppHost::SetTaskbarProgress });
|
||||
_revokers.IdentifyWindowsRequested = _windowLogic.IdentifyWindowsRequested(winrt::auto_revoke, { this, &AppHost::_IdentifyWindowsRequested });
|
||||
_revokers.RenameWindowRequested = _windowLogic.RenameWindowRequested(winrt::auto_revoke, { this, &AppHost::_RenameWindowRequested });
|
||||
|
||||
// A note: make sure to listen to our _window_'s settings changed, not the
|
||||
// AppLogic's. We want to make sure the event has gone through the window
|
||||
// logic _before_ we handle it, so we can ask the window about it's newest
|
||||
// properties.
|
||||
_revokers.SettingsChanged = _windowLogic.SettingsChanged(winrt::auto_revoke, { this, &AppHost::_HandleSettingsChanged });
|
||||
|
||||
_revokers.IsQuakeWindowChanged = _windowLogic.IsQuakeWindowChanged(winrt::auto_revoke, { this, &AppHost::_IsQuakeWindowChanged });
|
||||
_revokers.SummonWindowRequested = _windowLogic.SummonWindowRequested(winrt::auto_revoke, { this, &AppHost::_SummonWindowRequested });
|
||||
_revokers.OpenSystemMenu = _windowLogic.OpenSystemMenu(winrt::auto_revoke, { this, &AppHost::_OpenSystemMenu });
|
||||
_revokers.QuitRequested = _windowLogic.QuitRequested(winrt::auto_revoke, { this, &AppHost::_RequestQuitAll });
|
||||
_revokers.ShowWindowChanged = _windowLogic.ShowWindowChanged(winrt::auto_revoke, { this, &AppHost::_ShowWindowChanged });
|
||||
|
||||
// BODGY
|
||||
// On certain builds of Windows, when Terminal is set as the default
|
||||
@ -439,13 +433,31 @@ void AppHost::Initialize()
|
||||
// applications. This call into TerminalThemeHelpers will tell our
|
||||
// compositor to automatically complete animations that are scheduled
|
||||
// while the screen is off.
|
||||
TerminalTrySetAutoCompleteAnimationsWhenOccluded(static_cast<::IUnknown*>(winrt::get_abi(_logic.GetRoot())), true);
|
||||
TerminalTrySetAutoCompleteAnimationsWhenOccluded(static_cast<::IUnknown*>(winrt::get_abi(_windowLogic.GetRoot())), true);
|
||||
|
||||
_window->UpdateTitle(_logic.Title());
|
||||
_window->SetSnapDimensionCallback(std::bind(&winrt::TerminalApp::TerminalWindow::CalcSnappedDimension,
|
||||
_windowLogic,
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2));
|
||||
|
||||
// Create a throttled function for updating the window state, to match the
|
||||
// one requested by the pty. A 200ms delay was chosen because it's the
|
||||
// typical animation timeout in Windows. This does result in a delay between
|
||||
// the PTY requesting a change to the window state and the Terminal
|
||||
// realizing it, but should mitigate issues where the Terminal and PTY get
|
||||
// de-sync'd.
|
||||
_showHideWindowThrottler = std::make_shared<ThrottledFuncTrailing<bool>>(
|
||||
winrt::Windows::System::DispatcherQueue::GetForCurrentThread(),
|
||||
std::chrono::milliseconds(200),
|
||||
[this](const bool show) {
|
||||
_window->ShowWindowChanged(show);
|
||||
});
|
||||
|
||||
_window->UpdateTitle(_windowLogic.Title());
|
||||
|
||||
// Set up the content of the application. If the app has a custom titlebar,
|
||||
// set that content as well.
|
||||
_window->SetContent(_logic.GetRoot());
|
||||
_window->SetContent(_windowLogic.GetRoot());
|
||||
_window->OnAppInitialized();
|
||||
|
||||
// BODGY
|
||||
@ -478,7 +490,7 @@ void AppHost::Initialize()
|
||||
// - <none>
|
||||
void AppHost::AppTitleChanged(const winrt::Windows::Foundation::IInspectable& /*sender*/, winrt::hstring newTitle)
|
||||
{
|
||||
if (_logic.GetShowTitleInTitlebar())
|
||||
if (_windowLogic.GetShowTitleInTitlebar())
|
||||
{
|
||||
_window->UpdateTitle(newTitle);
|
||||
}
|
||||
@ -492,7 +504,7 @@ void AppHost::AppTitleChanged(const winrt::Windows::Foundation::IInspectable& /*
|
||||
// - LastTabClosedEventArgs: unused
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void AppHost::LastTabClosed(const winrt::Windows::Foundation::IInspectable& /*sender*/, const winrt::TerminalApp::LastTabClosedEventArgs& /*args*/)
|
||||
void AppHost::LastTabClosed(const winrt::Windows::Foundation::IInspectable& /*sender*/, const winrt::TerminalApp::LastTabClosedEventArgs& args)
|
||||
{
|
||||
if (_windowManager.IsMonarch() && _notificationIcon)
|
||||
{
|
||||
@ -511,6 +523,16 @@ void AppHost::LastTabClosed(const winrt::Windows::Foundation::IInspectable& /*se
|
||||
_windowManager.WindowCreated(_WindowCreatedToken);
|
||||
_windowManager.WindowClosed(_WindowClosedToken);
|
||||
|
||||
// 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.
|
||||
@ -564,11 +586,11 @@ LaunchPosition AppHost::_GetWindowLaunchPosition()
|
||||
// - None
|
||||
void AppHost::_HandleCreateWindow(const HWND hwnd, til::rect proposedRect, LaunchMode& launchMode)
|
||||
{
|
||||
launchMode = _logic.GetLaunchMode();
|
||||
launchMode = _windowLogic.GetLaunchMode();
|
||||
|
||||
// Acquire the actual initial position
|
||||
auto initialPos = _logic.GetInitialPosition(proposedRect.left, proposedRect.top);
|
||||
const auto centerOnLaunch = _logic.CenterOnLaunch();
|
||||
auto initialPos = _windowLogic.GetInitialPosition(proposedRect.left, proposedRect.top);
|
||||
const auto centerOnLaunch = _windowLogic.CenterOnLaunch();
|
||||
proposedRect.left = gsl::narrow<til::CoordType>(initialPos.X);
|
||||
proposedRect.top = gsl::narrow<til::CoordType>(initialPos.Y);
|
||||
|
||||
@ -615,7 +637,7 @@ void AppHost::_HandleCreateWindow(const HWND hwnd, til::rect proposedRect, Launc
|
||||
proposedRect.top = monitorInfo.rcWork.top;
|
||||
}
|
||||
|
||||
auto initialSize = _logic.GetLaunchDimensions(dpix);
|
||||
auto initialSize = _windowLogic.GetLaunchDimensions(dpix);
|
||||
|
||||
const auto islandWidth = Utils::ClampToShortMax(
|
||||
static_cast<long>(ceil(initialSize.Width)), 1);
|
||||
@ -649,7 +671,7 @@ void AppHost::_HandleCreateWindow(const HWND hwnd, til::rect proposedRect, Launc
|
||||
til::point origin{ (proposedRect.left + nonClientFrame.left),
|
||||
(proposedRect.top) };
|
||||
|
||||
if (_logic.IsQuakeWindow())
|
||||
if (_windowLogic.IsQuakeWindow())
|
||||
{
|
||||
// If we just use rcWork by itself, we'll fail to account for the invisible
|
||||
// space reserved for the resize handles. So retrieve that size here.
|
||||
@ -706,7 +728,7 @@ void AppHost::_UpdateTitleBarContent(const winrt::Windows::Foundation::IInspecta
|
||||
{
|
||||
auto nonClientWindow{ static_cast<NonClientIslandWindow*>(_window.get()) };
|
||||
nonClientWindow->SetTitlebarContent(arg);
|
||||
nonClientWindow->SetTitlebarBackground(_logic.TitlebarBrush());
|
||||
nonClientWindow->SetTitlebarBackground(_windowLogic.TitlebarBrush());
|
||||
}
|
||||
|
||||
_updateTheme();
|
||||
@ -729,13 +751,13 @@ void AppHost::_UpdateTheme(const winrt::Windows::Foundation::IInspectable&,
|
||||
void AppHost::_FocusModeChanged(const winrt::Windows::Foundation::IInspectable&,
|
||||
const winrt::Windows::Foundation::IInspectable&)
|
||||
{
|
||||
_window->FocusModeChanged(_logic.FocusMode());
|
||||
_window->FocusModeChanged(_windowLogic.FocusMode());
|
||||
}
|
||||
|
||||
void AppHost::_FullscreenChanged(const winrt::Windows::Foundation::IInspectable&,
|
||||
const winrt::Windows::Foundation::IInspectable&)
|
||||
{
|
||||
_window->FullscreenChanged(_logic.Fullscreen());
|
||||
_window->FullscreenChanged(_windowLogic.Fullscreen());
|
||||
}
|
||||
|
||||
void AppHost::_ChangeMaximizeRequested(const winrt::Windows::Foundation::IInspectable&,
|
||||
@ -773,7 +795,7 @@ void AppHost::_AlwaysOnTopChanged(const winrt::Windows::Foundation::IInspectable
|
||||
return;
|
||||
}
|
||||
|
||||
_window->SetAlwaysOnTop(_logic.AlwaysOnTop());
|
||||
_window->SetAlwaysOnTop(_windowLogic.AlwaysOnTop());
|
||||
}
|
||||
|
||||
// Method Description
|
||||
@ -801,14 +823,14 @@ void AppHost::_RaiseVisualBell(const winrt::Windows::Foundation::IInspectable&,
|
||||
// - <none>
|
||||
void AppHost::_WindowMouseWheeled(const til::point coord, const int32_t delta)
|
||||
{
|
||||
if (_logic)
|
||||
if (_windowLogic)
|
||||
{
|
||||
// Find all the elements that are underneath the mouse
|
||||
auto elems = winrt::Windows::UI::Xaml::Media::VisualTreeHelper::FindElementsInHostCoordinates(coord.to_winrt_point(), _logic.GetRoot());
|
||||
auto elems = Xaml::Media::VisualTreeHelper::FindElementsInHostCoordinates(coord.to_winrt_point(), _windowLogic.GetRoot());
|
||||
for (const auto& e : elems)
|
||||
{
|
||||
// If that element has implemented IMouseWheelListener, call OnMouseWheel on that element.
|
||||
if (auto control{ e.try_as<winrt::Microsoft::Terminal::Control::IMouseWheelListener>() })
|
||||
if (auto control{ e.try_as<Control::IMouseWheelListener>() })
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -862,7 +884,7 @@ void AppHost::_DispatchCommandline(winrt::Windows::Foundation::IInspectable send
|
||||
// Summon the window whenever we dispatch a commandline to it. This will
|
||||
// make it obvious when a new tab/pane is created in a window.
|
||||
_HandleSummon(sender, summonArgs);
|
||||
_logic.ExecuteCommandline(args.Commandline(), args.CurrentDirectory());
|
||||
_windowLogic.ExecuteCommandline(args.Commandline(), args.CurrentDirectory());
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@ -881,11 +903,11 @@ winrt::Windows::Foundation::IAsyncOperation<winrt::hstring> AppHost::_GetWindowL
|
||||
|
||||
winrt::hstring layoutJson = L"";
|
||||
// Use the main thread since we are accessing controls.
|
||||
co_await wil::resume_foreground(_logic.GetRoot().Dispatcher());
|
||||
co_await wil::resume_foreground(_windowLogic.GetRoot().Dispatcher());
|
||||
try
|
||||
{
|
||||
const auto pos = _GetWindowLaunchPosition();
|
||||
layoutJson = _logic.GetWindowLayoutJson(pos);
|
||||
layoutJson = _windowLogic.GetWindowLayoutJson(pos);
|
||||
}
|
||||
CATCH_LOG()
|
||||
|
||||
@ -908,14 +930,14 @@ winrt::Windows::Foundation::IAsyncOperation<winrt::hstring> AppHost::_GetWindowL
|
||||
void AppHost::_FindTargetWindow(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
||||
const Remoting::FindTargetWindowArgs& args)
|
||||
{
|
||||
const auto targetWindow = _logic.FindTargetWindow(args.Args().Commandline());
|
||||
const auto targetWindow = _appLogic.FindTargetWindow(args.Args().Commandline());
|
||||
args.ResultTargetWindow(targetWindow.WindowId());
|
||||
args.ResultTargetWindowName(targetWindow.WindowName());
|
||||
}
|
||||
|
||||
winrt::fire_and_forget AppHost::_WindowActivated(bool activated)
|
||||
{
|
||||
_logic.WindowActivated(activated);
|
||||
_windowLogic.WindowActivated(activated);
|
||||
|
||||
if (!activated)
|
||||
{
|
||||
@ -955,27 +977,23 @@ void AppHost::_BecomeMonarch(const winrt::Windows::Foundation::IInspectable& /*s
|
||||
|
||||
if (_windowManager.DoesQuakeWindowExist() ||
|
||||
_window->IsQuakeWindow() ||
|
||||
(_logic.GetAlwaysShowNotificationIcon() || _logic.GetMinimizeToNotificationArea()))
|
||||
(_windowLogic.GetAlwaysShowNotificationIcon() || _windowLogic.GetMinimizeToNotificationArea()))
|
||||
{
|
||||
_CreateNotificationIcon();
|
||||
}
|
||||
|
||||
// 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.
|
||||
_logic.SetNumberOfOpenWindows(_windowManager.GetNumberOfPeasants());
|
||||
|
||||
_WindowCreatedToken = _windowManager.WindowCreated([this](auto&&, auto&&) {
|
||||
if (_getWindowLayoutThrottler) {
|
||||
if (_getWindowLayoutThrottler)
|
||||
{
|
||||
_getWindowLayoutThrottler.value()();
|
||||
}
|
||||
_logic.SetNumberOfOpenWindows(_windowManager.GetNumberOfPeasants()); });
|
||||
});
|
||||
|
||||
_WindowClosedToken = _windowManager.WindowClosed([this](auto&&, auto&&) {
|
||||
if (_getWindowLayoutThrottler)
|
||||
{
|
||||
_getWindowLayoutThrottler.value()();
|
||||
}
|
||||
_logic.SetNumberOfOpenWindows(_windowManager.GetNumberOfPeasants());
|
||||
});
|
||||
|
||||
// These events are coming from peasants that become or un-become quake windows.
|
||||
@ -1000,7 +1018,7 @@ winrt::Windows::Foundation::IAsyncAction AppHost::_SaveWindowLayouts()
|
||||
// Make sure we run on a background thread to not block anything.
|
||||
co_await winrt::resume_background();
|
||||
|
||||
if (_logic.ShouldUsePersistedLayout())
|
||||
if (_appLogic.ShouldUsePersistedLayout())
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -1015,7 +1033,7 @@ winrt::Windows::Foundation::IAsyncAction AppHost::_SaveWindowLayouts()
|
||||
TraceLoggingDescription("Logged when writing window state"),
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
_logic.SaveWindowLayoutJsons(layoutJsons);
|
||||
_appLogic.SaveWindowLayoutJsons(layoutJsons);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@ -1056,15 +1074,10 @@ winrt::fire_and_forget AppHost::_SaveWindowLayoutsRepeat()
|
||||
}
|
||||
}
|
||||
|
||||
void AppHost::_listenForInboundConnections()
|
||||
{
|
||||
_logic.SetInboundListener();
|
||||
}
|
||||
|
||||
winrt::fire_and_forget AppHost::_setupGlobalHotkeys()
|
||||
{
|
||||
// The hotkey MUST be registered on the main thread. It will fail otherwise!
|
||||
co_await wil::resume_foreground(_logic.GetRoot().Dispatcher());
|
||||
co_await wil::resume_foreground(_windowLogic.GetRoot().Dispatcher());
|
||||
|
||||
if (!_window)
|
||||
{
|
||||
@ -1089,7 +1102,7 @@ winrt::fire_and_forget AppHost::_setupGlobalHotkeys()
|
||||
_hotkeys.clear();
|
||||
|
||||
// Re-register all current hotkeys.
|
||||
for (const auto& [keyChord, cmd] : _logic.GlobalHotkeys())
|
||||
for (const auto& [keyChord, cmd] : _appLogic.GlobalHotkeys())
|
||||
{
|
||||
if (auto summonArgs = cmd.ActionAndArgs().Args().try_as<Settings::Model::GlobalSummonArgs>())
|
||||
{
|
||||
@ -1311,7 +1324,7 @@ winrt::fire_and_forget AppHost::_IdentifyWindowsRequested(const winrt::Windows::
|
||||
void AppHost::_DisplayWindowId(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
||||
const winrt::Windows::Foundation::IInspectable& /*args*/)
|
||||
{
|
||||
_logic.IdentifyWindow();
|
||||
_windowLogic.IdentifyWindow();
|
||||
}
|
||||
|
||||
winrt::fire_and_forget AppHost::_RenameWindowRequested(const winrt::Windows::Foundation::IInspectable /*sender*/,
|
||||
@ -1335,11 +1348,11 @@ winrt::fire_and_forget AppHost::_RenameWindowRequested(const winrt::Windows::Fou
|
||||
|
||||
if (requestArgs.Succeeded())
|
||||
{
|
||||
_logic.WindowName(args.ProposedName());
|
||||
_windowLogic.WindowName(args.ProposedName());
|
||||
}
|
||||
else
|
||||
{
|
||||
_logic.RenameFailed();
|
||||
_windowLogic.RenameFailed();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1373,11 +1386,11 @@ static bool _isActuallyDarkTheme(const auto requestedTheme)
|
||||
|
||||
void AppHost::_updateTheme()
|
||||
{
|
||||
auto theme = _logic.Theme();
|
||||
auto theme = _appLogic.Theme();
|
||||
|
||||
_window->OnApplicationThemeChanged(theme.RequestedTheme());
|
||||
|
||||
const auto b = _logic.TitlebarBrush();
|
||||
const auto b = _windowLogic.TitlebarBrush();
|
||||
const auto color = ThemeColor::ColorFromBrush(b);
|
||||
const auto colorOpacity = b ? color.A / 255.0 : 0.0;
|
||||
const auto brushOpacity = _opacityFromBrush(b);
|
||||
@ -1392,7 +1405,7 @@ void AppHost::_updateTheme()
|
||||
}
|
||||
|
||||
void AppHost::_HandleSettingsChanged(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
||||
const winrt::Windows::Foundation::IInspectable& /*args*/)
|
||||
const winrt::TerminalApp::SettingsLoadEventArgs& /*args*/)
|
||||
{
|
||||
_setupGlobalHotkeys();
|
||||
|
||||
@ -1409,11 +1422,11 @@ void AppHost::_HandleSettingsChanged(const winrt::Windows::Foundation::IInspecta
|
||||
{
|
||||
if (!_windowManager.DoesQuakeWindowExist())
|
||||
{
|
||||
if (!_notificationIcon && (_logic.GetMinimizeToNotificationArea() || _logic.GetAlwaysShowNotificationIcon()))
|
||||
if (!_notificationIcon && (_windowLogic.GetMinimizeToNotificationArea() || _windowLogic.GetAlwaysShowNotificationIcon()))
|
||||
{
|
||||
_CreateNotificationIcon();
|
||||
}
|
||||
else if (_notificationIcon && !_logic.GetMinimizeToNotificationArea() && !_logic.GetAlwaysShowNotificationIcon())
|
||||
else if (_notificationIcon && !_windowLogic.GetMinimizeToNotificationArea() && !_windowLogic.GetAlwaysShowNotificationIcon())
|
||||
{
|
||||
_windowManager.SummonAllWindows();
|
||||
_DestroyNotificationIcon();
|
||||
@ -1421,8 +1434,8 @@ void AppHost::_HandleSettingsChanged(const winrt::Windows::Foundation::IInspecta
|
||||
}
|
||||
}
|
||||
|
||||
_window->SetMinimizeToNotificationAreaBehavior(_logic.GetMinimizeToNotificationArea());
|
||||
_window->SetAutoHideWindow(_logic.AutoHideWindow());
|
||||
_window->SetMinimizeToNotificationAreaBehavior(_windowLogic.GetMinimizeToNotificationArea());
|
||||
_window->SetAutoHideWindow(_windowLogic.AutoHideWindow());
|
||||
_updateTheme();
|
||||
}
|
||||
|
||||
@ -1434,25 +1447,25 @@ void AppHost::_IsQuakeWindowChanged(const winrt::Windows::Foundation::IInspectab
|
||||
// to show regardless of the notification icon settings.
|
||||
// This also means we'll need to destroy the notification icon if it was created
|
||||
// specifically for the quake window. If not, it should not be destroyed.
|
||||
if (!_window->IsQuakeWindow() && _logic.IsQuakeWindow())
|
||||
if (!_window->IsQuakeWindow() && _windowLogic.IsQuakeWindow())
|
||||
{
|
||||
_ShowNotificationIconRequested(nullptr, nullptr);
|
||||
}
|
||||
else if (_window->IsQuakeWindow() && !_logic.IsQuakeWindow())
|
||||
else if (_window->IsQuakeWindow() && !_windowLogic.IsQuakeWindow())
|
||||
{
|
||||
_HideNotificationIconRequested(nullptr, nullptr);
|
||||
}
|
||||
|
||||
_window->IsQuakeWindow(_logic.IsQuakeWindow());
|
||||
_window->IsQuakeWindow(_windowLogic.IsQuakeWindow());
|
||||
}
|
||||
|
||||
winrt::fire_and_forget AppHost::_QuitRequested(const winrt::Windows::Foundation::IInspectable&,
|
||||
const winrt::Windows::Foundation::IInspectable&)
|
||||
{
|
||||
// Need to be on the main thread to close out all of the tabs.
|
||||
co_await wil::resume_foreground(_logic.GetRoot().Dispatcher());
|
||||
co_await wil::resume_foreground(_windowLogic.GetRoot().Dispatcher());
|
||||
|
||||
_logic.Quit();
|
||||
_windowLogic.Quit();
|
||||
}
|
||||
|
||||
void AppHost::_RequestQuitAll(const winrt::Windows::Foundation::IInspectable&,
|
||||
@ -1585,8 +1598,8 @@ void AppHost::_HideNotificationIconRequested(const winrt::Windows::Foundation::I
|
||||
{
|
||||
// Destroy it only if our settings allow it
|
||||
if (_notificationIcon &&
|
||||
!_logic.GetAlwaysShowNotificationIcon() &&
|
||||
!_logic.GetMinimizeToNotificationArea())
|
||||
!_windowLogic.GetAlwaysShowNotificationIcon() &&
|
||||
!_windowLogic.GetMinimizeToNotificationArea())
|
||||
{
|
||||
_DestroyNotificationIcon();
|
||||
}
|
||||
@ -1607,14 +1620,14 @@ void AppHost::_HideNotificationIconRequested(const winrt::Windows::Foundation::I
|
||||
// - <none>
|
||||
void AppHost::_WindowMoved()
|
||||
{
|
||||
if (_logic)
|
||||
if (_windowLogic)
|
||||
{
|
||||
// Ensure any open ContentDialog is dismissed.
|
||||
// Closing the popup in the UI tree as done below is not sufficient because
|
||||
// it does not terminate the dialog's async operation.
|
||||
_logic.DismissDialog();
|
||||
_windowLogic.DismissDialog();
|
||||
|
||||
const auto root{ _logic.GetRoot() };
|
||||
const auto root{ _windowLogic.GetRoot() };
|
||||
if (root && root.XamlRoot())
|
||||
{
|
||||
try
|
||||
@ -1643,7 +1656,8 @@ void AppHost::_CloseRequested(const winrt::Windows::Foundation::IInspectable& /*
|
||||
const winrt::Windows::Foundation::IInspectable& /*args*/)
|
||||
{
|
||||
const auto pos = _GetWindowLaunchPosition();
|
||||
_logic.CloseWindow(pos);
|
||||
const bool isLastWindow = _windowManager.GetNumberOfPeasants() == 1;
|
||||
_windowLogic.CloseWindow(pos, isLastWindow);
|
||||
}
|
||||
|
||||
void AppHost::_PropertyChangedHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
||||
@ -1654,7 +1668,7 @@ void AppHost::_PropertyChangedHandler(const winrt::Windows::Foundation::IInspect
|
||||
if (_useNonClientArea)
|
||||
{
|
||||
auto nonClientWindow{ static_cast<NonClientIslandWindow*>(_window.get()) };
|
||||
nonClientWindow->SetTitlebarBackground(_logic.TitlebarBrush());
|
||||
nonClientWindow->SetTitlebarBackground(_windowLogic.TitlebarBrush());
|
||||
_updateTheme();
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,12 +19,15 @@ public:
|
||||
void SetTaskbarProgress(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args);
|
||||
|
||||
bool HasWindow();
|
||||
winrt::TerminalApp::TerminalWindow Logic();
|
||||
|
||||
private:
|
||||
std::unique_ptr<IslandWindow> _window;
|
||||
winrt::TerminalApp::App _app;
|
||||
winrt::TerminalApp::AppLogic _logic;
|
||||
winrt::TerminalApp::AppLogic _appLogic;
|
||||
winrt::TerminalApp::TerminalWindow _windowLogic;
|
||||
winrt::Microsoft::Terminal::Remoting::WindowManager _windowManager{ nullptr };
|
||||
winrt::Microsoft::Terminal::Remoting::Peasant _peasant{ nullptr };
|
||||
|
||||
std::vector<winrt::Microsoft::Terminal::Settings::Model::GlobalSummonArgs> _hotkeys;
|
||||
winrt::com_ptr<IVirtualDesktopManager> _desktopManager{ nullptr };
|
||||
@ -88,7 +91,7 @@ private:
|
||||
winrt::fire_and_forget _setupGlobalHotkeys();
|
||||
winrt::fire_and_forget _createNewTerminalWindow(winrt::Microsoft::Terminal::Settings::Model::GlobalSummonArgs args);
|
||||
void _HandleSettingsChanged(const winrt::Windows::Foundation::IInspectable& sender,
|
||||
const winrt::Windows::Foundation::IInspectable& args);
|
||||
const winrt::TerminalApp::SettingsLoadEventArgs& args);
|
||||
|
||||
void _IsQuakeWindowChanged(const winrt::Windows::Foundation::IInspectable& sender,
|
||||
const winrt::Windows::Foundation::IInspectable& args);
|
||||
@ -151,28 +154,28 @@ private:
|
||||
winrt::Microsoft::Terminal::Remoting::Peasant::SummonRequested_revoker peasantSummonRequested;
|
||||
winrt::Microsoft::Terminal::Remoting::Peasant::DisplayWindowIdRequested_revoker peasantDisplayWindowIdRequested;
|
||||
winrt::Microsoft::Terminal::Remoting::Peasant::QuitRequested_revoker peasantQuitRequested;
|
||||
winrt::TerminalApp::AppLogic::CloseRequested_revoker CloseRequested;
|
||||
winrt::TerminalApp::AppLogic::RequestedThemeChanged_revoker RequestedThemeChanged;
|
||||
winrt::TerminalApp::AppLogic::FullscreenChanged_revoker FullscreenChanged;
|
||||
winrt::TerminalApp::AppLogic::FocusModeChanged_revoker FocusModeChanged;
|
||||
winrt::TerminalApp::AppLogic::AlwaysOnTopChanged_revoker AlwaysOnTopChanged;
|
||||
winrt::TerminalApp::AppLogic::RaiseVisualBell_revoker RaiseVisualBell;
|
||||
winrt::TerminalApp::AppLogic::SystemMenuChangeRequested_revoker SystemMenuChangeRequested;
|
||||
winrt::TerminalApp::AppLogic::ChangeMaximizeRequested_revoker ChangeMaximizeRequested;
|
||||
winrt::TerminalApp::AppLogic::TitleChanged_revoker TitleChanged;
|
||||
winrt::TerminalApp::AppLogic::LastTabClosed_revoker LastTabClosed;
|
||||
winrt::TerminalApp::AppLogic::SetTaskbarProgress_revoker SetTaskbarProgress;
|
||||
winrt::TerminalApp::AppLogic::IdentifyWindowsRequested_revoker IdentifyWindowsRequested;
|
||||
winrt::TerminalApp::AppLogic::RenameWindowRequested_revoker RenameWindowRequested;
|
||||
winrt::TerminalApp::AppLogic::SettingsChanged_revoker SettingsChanged;
|
||||
winrt::TerminalApp::AppLogic::IsQuakeWindowChanged_revoker IsQuakeWindowChanged;
|
||||
winrt::TerminalApp::AppLogic::SummonWindowRequested_revoker SummonWindowRequested;
|
||||
winrt::TerminalApp::AppLogic::OpenSystemMenu_revoker OpenSystemMenu;
|
||||
winrt::TerminalApp::AppLogic::QuitRequested_revoker QuitRequested;
|
||||
winrt::TerminalApp::AppLogic::ShowWindowChanged_revoker ShowWindowChanged;
|
||||
winrt::TerminalApp::TerminalWindow::CloseRequested_revoker CloseRequested;
|
||||
winrt::TerminalApp::TerminalWindow::RequestedThemeChanged_revoker RequestedThemeChanged;
|
||||
winrt::TerminalApp::TerminalWindow::FullscreenChanged_revoker FullscreenChanged;
|
||||
winrt::TerminalApp::TerminalWindow::FocusModeChanged_revoker FocusModeChanged;
|
||||
winrt::TerminalApp::TerminalWindow::AlwaysOnTopChanged_revoker AlwaysOnTopChanged;
|
||||
winrt::TerminalApp::TerminalWindow::RaiseVisualBell_revoker RaiseVisualBell;
|
||||
winrt::TerminalApp::TerminalWindow::SystemMenuChangeRequested_revoker SystemMenuChangeRequested;
|
||||
winrt::TerminalApp::TerminalWindow::ChangeMaximizeRequested_revoker ChangeMaximizeRequested;
|
||||
winrt::TerminalApp::TerminalWindow::TitleChanged_revoker TitleChanged;
|
||||
winrt::TerminalApp::TerminalWindow::LastTabClosed_revoker LastTabClosed;
|
||||
winrt::TerminalApp::TerminalWindow::SetTaskbarProgress_revoker SetTaskbarProgress;
|
||||
winrt::TerminalApp::TerminalWindow::IdentifyWindowsRequested_revoker IdentifyWindowsRequested;
|
||||
winrt::TerminalApp::TerminalWindow::RenameWindowRequested_revoker RenameWindowRequested;
|
||||
winrt::TerminalApp::TerminalWindow::IsQuakeWindowChanged_revoker IsQuakeWindowChanged;
|
||||
winrt::TerminalApp::TerminalWindow::SummonWindowRequested_revoker SummonWindowRequested;
|
||||
winrt::TerminalApp::TerminalWindow::OpenSystemMenu_revoker OpenSystemMenu;
|
||||
winrt::TerminalApp::TerminalWindow::QuitRequested_revoker QuitRequested;
|
||||
winrt::TerminalApp::TerminalWindow::ShowWindowChanged_revoker ShowWindowChanged;
|
||||
winrt::TerminalApp::TerminalWindow::PropertyChanged_revoker PropertyChanged;
|
||||
winrt::TerminalApp::TerminalWindow::SettingsChanged_revoker SettingsChanged;
|
||||
winrt::Microsoft::Terminal::Remoting::WindowManager::ShowNotificationIconRequested_revoker ShowNotificationIconRequested;
|
||||
winrt::Microsoft::Terminal::Remoting::WindowManager::HideNotificationIconRequested_revoker HideNotificationIconRequested;
|
||||
winrt::Microsoft::Terminal::Remoting::WindowManager::QuitAllRequested_revoker QuitAllRequested;
|
||||
winrt::TerminalApp::AppLogic::PropertyChanged_revoker PropertyChanged;
|
||||
} _revokers{};
|
||||
};
|
||||
|
||||
@ -405,7 +405,13 @@ void IslandWindow::_OnGetMinMaxInfo(const WPARAM /*wParam*/, const LPARAM lParam
|
||||
// - The total dimension
|
||||
long IslandWindow::_calculateTotalSize(const bool isWidth, const long clientSize, const long nonClientSize)
|
||||
{
|
||||
return gsl::narrow_cast<int>(_pfnSnapDimensionCallback(isWidth, gsl::narrow_cast<float>(clientSize)) + nonClientSize);
|
||||
if (_pfnSnapDimensionCallback)
|
||||
{
|
||||
return gsl::narrow_cast<int>(_pfnSnapDimensionCallback(isWidth, gsl::narrow_cast<float>(clientSize)) + nonClientSize);
|
||||
}
|
||||
// We might have been called in WM_CREATE, before we've initialized XAML or
|
||||
// our page. That's okay.
|
||||
return clientSize + nonClientSize;
|
||||
}
|
||||
|
||||
[[nodiscard]] LRESULT IslandWindow::MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user