merge main
This commit is contained in:
commit
08905d91ca
1
.github/actions/spelling/allow/apis.txt
vendored
1
.github/actions/spelling/allow/apis.txt
vendored
|
@ -133,6 +133,7 @@ SRWLOCK
|
|||
STDCPP
|
||||
STDMETHOD
|
||||
strchr
|
||||
strcpy
|
||||
streambuf
|
||||
strtoul
|
||||
Stubless
|
||||
|
|
14
.github/actions/spelling/expect/expect.txt
vendored
14
.github/actions/spelling/expect/expect.txt
vendored
|
@ -169,6 +169,7 @@ brandings
|
|||
BRK
|
||||
Browsable
|
||||
bsearch
|
||||
Bspace
|
||||
bstr
|
||||
BTNFACE
|
||||
buf
|
||||
|
@ -270,10 +271,12 @@ cmder
|
|||
CMDEXT
|
||||
Cmdlet
|
||||
cmdline
|
||||
cmh
|
||||
CMOUSEBUTTONS
|
||||
cmp
|
||||
cmpeq
|
||||
cmt
|
||||
cmw
|
||||
cmyk
|
||||
CNL
|
||||
cnt
|
||||
|
@ -406,11 +409,13 @@ csbiex
|
|||
csharp
|
||||
CSHORT
|
||||
CSIDL
|
||||
Cspace
|
||||
csproj
|
||||
Csr
|
||||
csrmsg
|
||||
CSRSS
|
||||
csrutil
|
||||
css
|
||||
cstdarg
|
||||
cstddef
|
||||
cstdio
|
||||
|
@ -509,6 +514,7 @@ DECAWM
|
|||
DECCKM
|
||||
DECCOLM
|
||||
DECDHL
|
||||
DECDLD
|
||||
DECDWL
|
||||
DECEKBD
|
||||
DECID
|
||||
|
@ -789,6 +795,7 @@ FONTENUMPROC
|
|||
FONTFACE
|
||||
FONTFAMILY
|
||||
FONTHEIGHT
|
||||
FONTINFO
|
||||
fontlist
|
||||
FONTOK
|
||||
FONTSIZE
|
||||
|
@ -902,6 +909,7 @@ github
|
|||
gitlab
|
||||
gle
|
||||
globals
|
||||
GLYPHENTRY
|
||||
gmail
|
||||
GMEM
|
||||
GNUC
|
||||
|
@ -950,6 +958,7 @@ hdrstop
|
|||
HEIGHTSCROLL
|
||||
hfile
|
||||
hfont
|
||||
hfontresource
|
||||
hglobal
|
||||
hhh
|
||||
HHmm
|
||||
|
@ -1272,6 +1281,7 @@ locsrc
|
|||
locstudio
|
||||
Loewen
|
||||
LOGFONT
|
||||
LOGFONTA
|
||||
LOGFONTW
|
||||
logissue
|
||||
lowercased
|
||||
|
@ -1935,6 +1945,7 @@ realloc
|
|||
reamapping
|
||||
rects
|
||||
redef
|
||||
redefinable
|
||||
Redir
|
||||
redirector
|
||||
redist
|
||||
|
@ -1980,6 +1991,7 @@ rfc
|
|||
rftp
|
||||
rgb
|
||||
rgba
|
||||
RGBCOLOR
|
||||
rgbi
|
||||
rgci
|
||||
rgfae
|
||||
|
@ -2149,6 +2161,7 @@ SIGDN
|
|||
SINGLEFLAG
|
||||
SINGLETHREADED
|
||||
siup
|
||||
sixel
|
||||
SIZEBOX
|
||||
sizeof
|
||||
SIZESCROLL
|
||||
|
@ -2754,6 +2767,7 @@ WTo
|
|||
wtof
|
||||
wtoi
|
||||
WTs
|
||||
WTSOFTFONT
|
||||
wtw
|
||||
wtypes
|
||||
Wubi
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
trigger: none
|
||||
pr: none
|
||||
|
||||
pool:
|
||||
name: Package ES Standard Build
|
||||
pool:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS16-latest
|
||||
|
||||
parameters:
|
||||
- name: branding
|
||||
|
@ -70,11 +71,9 @@ jobs:
|
|||
clean: true
|
||||
submodules: true
|
||||
persistCredentials: True
|
||||
- task: PkgESSetupBuild@10
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
useDfs: false
|
||||
productName: OpenConsole
|
||||
disableOutputRedirect: true
|
||||
- task: PowerShell@2
|
||||
displayName: Rationalize Build Platform
|
||||
|
@ -275,11 +274,9 @@ jobs:
|
|||
clean: true
|
||||
submodules: true
|
||||
persistCredentials: True
|
||||
- task: PkgESSetupBuild@10
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
useDfs: false
|
||||
productName: OpenConsole
|
||||
disableOutputRedirect: true
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Artifacts (*.appx, *.msix)
|
||||
|
@ -354,11 +351,9 @@ jobs:
|
|||
clean: true
|
||||
submodules: true
|
||||
persistCredentials: True
|
||||
- task: PkgESSetupBuild@10
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
useDfs: false
|
||||
productName: OpenConsole
|
||||
disableOutputRedirect: true
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download x86 PublicTerminalCore
|
||||
|
@ -480,7 +475,7 @@ jobs:
|
|||
|
||||
mv Microsoft.WindowsTerminal_8wekyb3d8bbwe.msixbundle .\WindowsTerminal.app\
|
||||
workingDirectory: $(System.ArtifactsDirectory)\appxbundle-signed
|
||||
- task: PkgESVPack@10
|
||||
- task: PkgESVPack@12
|
||||
displayName: 'Package ES - VPack'
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
|
|
|
@ -8,9 +8,12 @@ jobs:
|
|||
variables:
|
||||
BuildConfiguration: AuditMode
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
pool: "windevbuildagents"
|
||||
# The public pool is also an option!
|
||||
# pool: { vmImage: windows-2019 }
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPoolOSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS16-latest
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
|
|
|
@ -11,9 +11,12 @@ jobs:
|
|||
variables:
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
pool: "windevbuildagents"
|
||||
# The public pool is also an option!
|
||||
# pool: { vmImage: windows-2019 }
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPoolOSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS16-latest
|
||||
|
||||
steps:
|
||||
- template: build-console-steps.yml
|
||||
|
|
|
@ -12,9 +12,12 @@ jobs:
|
|||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
PGOBuildMode: 'Instrument'
|
||||
pool: "windevbuildagents"
|
||||
# The public pool is also an option!
|
||||
# pool: { vmImage: windows-2019 }
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPoolOSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS16-latest
|
||||
|
||||
steps:
|
||||
- template: build-console-steps.yml
|
||||
|
|
|
@ -192,21 +192,24 @@ COLORREF TextColor::GetColor(const std::array<COLORREF, 256>& colorTable, const
|
|||
unsigned long index;
|
||||
return _BitScanForward(&index, mask) ? til::at(colorTable, static_cast<size_t>(index) + 8) : defaultColor; // 5.
|
||||
#elif _M_AMD64
|
||||
// If you look closely this SSE2 algorithm is the exact same as the AVX one.
|
||||
// If you look closely this SSE2 algorithm is the same as the AVX one.
|
||||
// The two differences are that we need to:
|
||||
// * do everything twice, because SSE is limited to 128 bits and not 256.
|
||||
// * use _mm_packs_epi32 to merge two 128 bits vectors into one in step 3.5.
|
||||
// _mm_packs_epi32 takes two SSE registers and truncates all 8 DWORDs into 8 WORDs,
|
||||
// the latter of which fits into a single register (which is then used in the identical step 4).
|
||||
// * since the result are now 8 WORDs, we need to use _mm_movemask_epi8 (there's no 16-bit variant),
|
||||
// which unlike AVX's step 4 results in in something like 0b0000110000000000.
|
||||
// --> the index returned by _BitScanForward must be divided by 2.
|
||||
const auto haystack1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(colorTable.data() + 0));
|
||||
const auto haystack2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(colorTable.data() + 4));
|
||||
const auto needle = _mm_set1_epi32(__builtin_bit_cast(int, defaultColor));
|
||||
const auto result1 = _mm_cmpeq_epi32(haystack1, needle);
|
||||
const auto result2 = _mm_cmpeq_epi32(haystack2, needle);
|
||||
const auto result = _mm_packs_epi32(result1, result2); // 3.5
|
||||
const auto mask = _mm_movemask_ps(_mm_castsi128_ps(result));
|
||||
const auto mask = _mm_movemask_epi8(result);
|
||||
unsigned long index;
|
||||
return _BitScanForward(&index, mask) ? til::at(colorTable, static_cast<size_t>(index) + 8) : defaultColor;
|
||||
return _BitScanForward(&index, mask) ? til::at(colorTable, static_cast<size_t>(index / 2) + 8) : defaultColor;
|
||||
#else
|
||||
for (size_t i = 0; i < 8; i++)
|
||||
{
|
||||
|
|
|
@ -397,6 +397,10 @@ namespace SettingsModelLocalTests
|
|||
"name":"action6",
|
||||
"command": { "action": "newWindow", "startingDirectory":"C:\\foo", "commandline": "bar.exe" }
|
||||
},
|
||||
{
|
||||
"name":"action7_startingDirectoryWithTrailingSlash",
|
||||
"command": { "action": "newWindow", "startingDirectory":"C:\\", "commandline": "bar.exe" }
|
||||
},
|
||||
])" };
|
||||
|
||||
const auto commands0Json = VerifyParseSucceeded(commands0String);
|
||||
|
@ -405,7 +409,7 @@ namespace SettingsModelLocalTests
|
|||
VERIFY_ARE_EQUAL(0u, commands.Size());
|
||||
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
|
||||
VERIFY_ARE_EQUAL(0u, warnings.size());
|
||||
VERIFY_ARE_EQUAL(7u, commands.Size());
|
||||
VERIFY_ARE_EQUAL(8u, commands.Size());
|
||||
|
||||
{
|
||||
auto command = commands.Lookup(L"action0");
|
||||
|
@ -503,5 +507,20 @@ namespace SettingsModelLocalTests
|
|||
L"cmdline: \"%s\"", cmdline.c_str()));
|
||||
VERIFY_ARE_EQUAL(L"--startingDirectory \"C:\\foo\" -- \"bar.exe\"", terminalArgs.ToCommandline());
|
||||
}
|
||||
|
||||
{
|
||||
auto command = commands.Lookup(L"action7_startingDirectoryWithTrailingSlash");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewWindowArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& terminalArgs = realArgs.TerminalArgs();
|
||||
VERIFY_IS_NOT_NULL(terminalArgs);
|
||||
auto cmdline = terminalArgs.ToCommandline();
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"cmdline: \"%s\"", cmdline.c_str()));
|
||||
VERIFY_ARE_EQUAL(L"--startingDirectory \"C:\\\\\" -- \"bar.exe\"", terminalArgs.ToCommandline());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace SettingsModelLocalTests
|
|||
TEST_METHOD(ManyKeysSameAction);
|
||||
TEST_METHOD(LayerKeybindings);
|
||||
TEST_METHOD(UnbindKeybindings);
|
||||
|
||||
TEST_METHOD(TestExplicitUnbind);
|
||||
TEST_METHOD(TestArbitraryArgs);
|
||||
TEST_METHOD(TestSplitPaneArgs);
|
||||
|
||||
|
@ -232,6 +232,31 @@ namespace SettingsModelLocalTests
|
|||
VERIFY_IS_NULL(actionMap->GetActionByKeyChord({ VirtualKeyModifiers::Control, static_cast<int32_t>('C'), 0 }));
|
||||
}
|
||||
|
||||
void KeyBindingsTests::TestExplicitUnbind()
|
||||
{
|
||||
const std::string bindings0String{ R"([ { "command": "copy", "keys": ["ctrl+c"] } ])" };
|
||||
const std::string bindings1String{ R"([ { "command": "unbound", "keys": ["ctrl+c"] } ])" };
|
||||
const std::string bindings2String{ R"([ { "command": "copy", "keys": ["ctrl+c"] } ])" };
|
||||
|
||||
const auto bindings0Json = VerifyParseSucceeded(bindings0String);
|
||||
const auto bindings1Json = VerifyParseSucceeded(bindings1String);
|
||||
const auto bindings2Json = VerifyParseSucceeded(bindings2String);
|
||||
|
||||
const KeyChord keyChord{ VirtualKeyModifiers::Control, static_cast<int32_t>('C'), 0 };
|
||||
|
||||
auto actionMap = winrt::make_self<implementation::ActionMap>();
|
||||
VERIFY_IS_FALSE(actionMap->IsKeyChordExplicitlyUnbound(keyChord));
|
||||
|
||||
actionMap->LayerJson(bindings0Json);
|
||||
VERIFY_IS_FALSE(actionMap->IsKeyChordExplicitlyUnbound(keyChord));
|
||||
|
||||
actionMap->LayerJson(bindings1Json);
|
||||
VERIFY_IS_TRUE(actionMap->IsKeyChordExplicitlyUnbound(keyChord));
|
||||
|
||||
actionMap->LayerJson(bindings2Json);
|
||||
VERIFY_IS_FALSE(actionMap->IsKeyChordExplicitlyUnbound(keyChord));
|
||||
}
|
||||
|
||||
void KeyBindingsTests::TestArbitraryArgs()
|
||||
{
|
||||
const std::string bindings0String{ R"([
|
||||
|
|
|
@ -264,12 +264,12 @@ namespace winrt::TerminalApp::implementation
|
|||
{
|
||||
if (args == nullptr)
|
||||
{
|
||||
_OpenNewTab(nullptr);
|
||||
LOG_IF_FAILED(_OpenNewTab(nullptr));
|
||||
args.Handled(true);
|
||||
}
|
||||
else if (const auto& realArgs = args.ActionArgs().try_as<NewTabArgs>())
|
||||
{
|
||||
_OpenNewTab(realArgs.TerminalArgs());
|
||||
LOG_IF_FAILED(_OpenNewTab(realArgs.TerminalArgs()));
|
||||
args.Handled(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,11 @@ namespace winrt::TerminalApp::implementation
|
|||
return false;
|
||||
}
|
||||
|
||||
bool AppKeyBindings::IsKeyChordExplicitlyUnbound(const KeyChord& kc)
|
||||
{
|
||||
return _actionMap.IsKeyChordExplicitlyUnbound(kc);
|
||||
}
|
||||
|
||||
void AppKeyBindings::SetDispatch(const winrt::TerminalApp::ShortcutActionDispatch& dispatch)
|
||||
{
|
||||
_dispatch = dispatch;
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace winrt::TerminalApp::implementation
|
|||
AppKeyBindings() = default;
|
||||
|
||||
bool TryKeyChord(winrt::Microsoft::Terminal::Control::KeyChord const& kc);
|
||||
bool IsKeyChordExplicitlyUnbound(winrt::Microsoft::Terminal::Control::KeyChord const& kc);
|
||||
|
||||
void SetDispatch(const winrt::TerminalApp::ShortcutActionDispatch& dispatch);
|
||||
void SetActionMap(const Microsoft::Terminal::Settings::Model::IActionMapView& actionMap);
|
||||
|
|
|
@ -203,12 +203,16 @@ namespace winrt::TerminalApp::implementation
|
|||
_isElevated = _isUserAdmin();
|
||||
_root = winrt::make_self<TerminalPage>();
|
||||
|
||||
_reloadSettings = std::make_shared<ThrottledFuncTrailing<>>(_root->Dispatcher(), std::chrono::milliseconds(100), [weakSelf = get_weak()]() {
|
||||
_reloadSettings = std::make_shared<ThrottledFuncTrailing<>>(winrt::Windows::System::DispatcherQueue::GetForCurrentThread(), std::chrono::milliseconds(100), [weakSelf = get_weak()]() {
|
||||
if (auto self{ weakSelf.get() })
|
||||
{
|
||||
self->_ReloadSettings();
|
||||
}
|
||||
});
|
||||
|
||||
_languageProfileNotifier = winrt::make_self<LanguageProfileNotifier>([this]() {
|
||||
_reloadSettings->Run();
|
||||
});
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -1125,28 +1129,11 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Gets the taskbar state value from the last active control
|
||||
// Return Value:
|
||||
// - The taskbar state of the last active control
|
||||
uint64_t AppLogic::GetLastActiveControlTaskbarState()
|
||||
winrt::TerminalApp::TaskbarState AppLogic::TaskbarState()
|
||||
{
|
||||
if (_root)
|
||||
{
|
||||
return _root->GetLastActiveControlTaskbarState();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Gets the taskbar progress value from the last active control
|
||||
// Return Value:
|
||||
// - The taskbar progress of the last active control
|
||||
uint64_t AppLogic::GetLastActiveControlTaskbarProgress()
|
||||
{
|
||||
if (_root)
|
||||
{
|
||||
return _root->GetLastActiveControlTaskbarProgress();
|
||||
return _root->TaskbarState();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
@ -1229,6 +1216,11 @@ namespace winrt::TerminalApp::implementation
|
|||
auto actions = winrt::single_threaded_vector<ActionAndArgs>(std::move(appArgs.GetStartupActions()));
|
||||
|
||||
_root->ProcessStartupActions(actions, false, cwd);
|
||||
|
||||
if (appArgs.IsHandoffListener())
|
||||
{
|
||||
_root->SetInboundListener(true);
|
||||
}
|
||||
}
|
||||
// Return the result of parsing with commandline, though it may or may not be used.
|
||||
return result;
|
||||
|
|
|
@ -5,8 +5,9 @@
|
|||
|
||||
#include "AppLogic.g.h"
|
||||
#include "FindTargetWindowResult.g.h"
|
||||
#include "TerminalPage.h"
|
||||
#include "Jumplist.h"
|
||||
#include "LanguageProfileNotifier.h"
|
||||
#include "TerminalPage.h"
|
||||
|
||||
#include <inc/cppwinrt_utils.h>
|
||||
#include <ThrottledFunc.h>
|
||||
|
@ -89,8 +90,7 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
void WindowCloseButtonClicked();
|
||||
|
||||
uint64_t GetLastActiveControlTaskbarState();
|
||||
uint64_t GetLastActiveControlTaskbarProgress();
|
||||
winrt::TerminalApp::TaskbarState TaskbarState();
|
||||
|
||||
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> ShowDialog(winrt::Windows::UI::Xaml::Controls::ContentDialog dialog);
|
||||
|
||||
|
@ -110,12 +110,8 @@ namespace winrt::TerminalApp::implementation
|
|||
// 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 };
|
||||
|
||||
wil::unique_folder_change_reader_nothrow _reader;
|
||||
std::shared_ptr<ThrottledFuncTrailing<>> _reloadSettings;
|
||||
til::throttled_func_trailing<> _reloadState;
|
||||
winrt::hstring _settingsLoadExceptionText;
|
||||
HRESULT _settingsLoadedResult = S_OK;
|
||||
bool _loadedInitialSettings = false;
|
||||
|
@ -124,6 +120,15 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
::TerminalApp::AppCommandlineArgs _appArgs;
|
||||
::TerminalApp::AppCommandlineArgs _settingsAppArgs;
|
||||
|
||||
std::shared_ptr<ThrottledFuncTrailing<>> _reloadSettings;
|
||||
til::throttled_func_trailing<> _reloadState;
|
||||
|
||||
// These fields invoke _reloadSettings and must be destroyed before _reloadSettings.
|
||||
// (C++ destroys members in reverse-declaration-order.)
|
||||
winrt::com_ptr<LanguageProfileNotifier> _languageProfileNotifier;
|
||||
wil::unique_folder_change_reader_nothrow _reader;
|
||||
|
||||
static TerminalApp::FindTargetWindowResult _doFindTargetWindow(winrt::array_view<const hstring> args,
|
||||
const Microsoft::Terminal::Settings::Model::WindowingMode& windowingBehavior);
|
||||
|
||||
|
|
|
@ -68,8 +68,7 @@ namespace TerminalApp
|
|||
void TitlebarClicked();
|
||||
void WindowCloseButtonClicked();
|
||||
|
||||
UInt64 GetLastActiveControlTaskbarState();
|
||||
UInt64 GetLastActiveControlTaskbarProgress();
|
||||
TaskbarState TaskbarState{ get; };
|
||||
|
||||
FindTargetWindowResult FindTargetWindow(String[] args);
|
||||
|
||||
|
|
42
src/cascadia/TerminalApp/LanguageProfileNotifier.cpp
Normal file
42
src/cascadia/TerminalApp/LanguageProfileNotifier.cpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "LanguageProfileNotifier.h"
|
||||
|
||||
using namespace winrt::TerminalApp::implementation;
|
||||
|
||||
LanguageProfileNotifier::LanguageProfileNotifier(std::function<void()>&& callback) :
|
||||
_callback{ std::move(callback) },
|
||||
_currentKeyboardLayout{ GetKeyboardLayout(0) }
|
||||
{
|
||||
const auto manager = wil::CoCreateInstance<ITfThreadMgr>(CLSID_TF_ThreadMgr);
|
||||
_source = manager.query<ITfSource>();
|
||||
if (FAILED(_source->AdviseSink(IID_ITfInputProcessorProfileActivationSink, static_cast<ITfInputProcessorProfileActivationSink*>(this), &_cookie)))
|
||||
{
|
||||
_cookie = TF_INVALID_COOKIE;
|
||||
THROW_LAST_ERROR();
|
||||
}
|
||||
}
|
||||
|
||||
LanguageProfileNotifier::~LanguageProfileNotifier()
|
||||
{
|
||||
if (_cookie != TF_INVALID_COOKIE)
|
||||
{
|
||||
_source->UnadviseSink(_cookie);
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP LanguageProfileNotifier::OnActivated(DWORD /*dwProfileType*/, LANGID /*langid*/, REFCLSID /*clsid*/, REFGUID /*catid*/, REFGUID /*guidProfile*/, HKL hkl, DWORD /*dwFlags*/)
|
||||
{
|
||||
if (hkl && hkl != _currentKeyboardLayout)
|
||||
{
|
||||
_currentKeyboardLayout = hkl;
|
||||
try
|
||||
{
|
||||
_callback();
|
||||
}
|
||||
CATCH_RETURN();
|
||||
}
|
||||
return S_OK;
|
||||
}
|
21
src/cascadia/TerminalApp/LanguageProfileNotifier.h
Normal file
21
src/cascadia/TerminalApp/LanguageProfileNotifier.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
class LanguageProfileNotifier : public winrt::implements<LanguageProfileNotifier, ITfInputProcessorProfileActivationSink>
|
||||
{
|
||||
public:
|
||||
explicit LanguageProfileNotifier(std::function<void()>&& callback);
|
||||
~LanguageProfileNotifier();
|
||||
STDMETHODIMP OnActivated(DWORD dwProfileType, LANGID langid, REFCLSID clsid, REFGUID catid, REFGUID guidProfile, HKL hkl, DWORD dwFlags);
|
||||
|
||||
private:
|
||||
std::function<void()> _callback;
|
||||
wil::com_ptr<ITfSource> _source;
|
||||
DWORD _cookie = TF_INVALID_COOKIE;
|
||||
HKL _currentKeyboardLayout;
|
||||
};
|
||||
}
|
|
@ -2548,6 +2548,29 @@ bool Pane::ContainsReadOnly() const
|
|||
return _IsLeaf() ? _control.ReadOnly() : (_firstChild->ContainsReadOnly() || _secondChild->ContainsReadOnly());
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - If we're a parent, place the taskbar state for all our leaves into the
|
||||
// provided vector.
|
||||
// - If we're a leaf, place our own state into the vector.
|
||||
// Arguments:
|
||||
// - states: a vector that will receive all the states of all leaves in the tree
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void Pane::CollectTaskbarStates(std::vector<winrt::TerminalApp::TaskbarState>& states)
|
||||
{
|
||||
if (_IsLeaf())
|
||||
{
|
||||
auto tbState{ winrt::make<winrt::TerminalApp::implementation::TaskbarState>(_control.TaskbarState(),
|
||||
_control.TaskbarProgress()) };
|
||||
states.push_back(tbState);
|
||||
}
|
||||
else
|
||||
{
|
||||
_firstChild->CollectTaskbarStates(states);
|
||||
_secondChild->CollectTaskbarStates(states);
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_EVENT(Pane, GotFocus, _GotFocusHandlers, winrt::delegate<std::shared_ptr<Pane>>);
|
||||
DEFINE_EVENT(Pane, LostFocus, _LostFocusHandlers, winrt::delegate<std::shared_ptr<Pane>>);
|
||||
DEFINE_EVENT(Pane, PaneRaiseBell, _PaneRaiseBellHandlers, winrt::Windows::Foundation::EventHandler<bool>);
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../cascadia/inc/cppwinrt_utils.h"
|
||||
#include "TaskbarState.h"
|
||||
|
||||
// fwdecl unittest classes
|
||||
namespace TerminalAppLocalTests
|
||||
|
@ -92,6 +93,8 @@ public:
|
|||
|
||||
bool ContainsReadOnly() const;
|
||||
|
||||
void CollectTaskbarStates(std::vector<winrt::TerminalApp::TaskbarState>& states);
|
||||
|
||||
WINRT_CALLBACK(Closed, winrt::Windows::Foundation::EventHandler<winrt::Windows::Foundation::IInspectable>);
|
||||
DECLARE_EVENT(GotFocus, _GotFocusHandlers, winrt::delegate<std::shared_ptr<Pane>>);
|
||||
DECLARE_EVENT(LostFocus, _LostFocusHandlers, winrt::delegate<std::shared_ptr<Pane>>);
|
||||
|
|
|
@ -665,6 +665,9 @@
|
|||
<data name="FindText" xml:space="preserve">
|
||||
<value>Find...</value>
|
||||
</data>
|
||||
<data name="SplitTabText" xml:space="preserve">
|
||||
<value>Split Tab</value>
|
||||
</data>
|
||||
<data name="DropPathTabNewWindow.Text" xml:space="preserve">
|
||||
<value>Open a new window with given starting directory</value>
|
||||
</data>
|
||||
|
|
|
@ -56,7 +56,7 @@ namespace winrt::TerminalApp::implementation
|
|||
// - existingConnection: An optional connection that is already established to a PTY
|
||||
// for this tab to host instead of creating one.
|
||||
// If not defined, the tab will create the connection.
|
||||
void TerminalPage::_OpenNewTab(const NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection)
|
||||
HRESULT TerminalPage::_OpenNewTab(const NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection)
|
||||
try
|
||||
{
|
||||
const auto profileGuid{ _settings.GetProfileForArgs(newTerminalArgs) };
|
||||
|
@ -89,8 +89,10 @@ namespace winrt::TerminalApp::implementation
|
|||
TraceLoggingWideString(schemeName.data(), "SchemeName", "Color scheme set in the settings"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_LOG();
|
||||
CATCH_RETURN();
|
||||
|
||||
// Method Description:
|
||||
// - Creates a new tab with the given settings. If the tab bar is not being
|
||||
|
@ -192,6 +194,16 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
});
|
||||
|
||||
newTabImpl->SplitTabRequested([weakTab, weakThis{ get_weak() }]() {
|
||||
auto page{ weakThis.get() };
|
||||
auto tab{ weakTab.get() };
|
||||
|
||||
if (page && tab)
|
||||
{
|
||||
page->_SplitTab(*tab);
|
||||
}
|
||||
});
|
||||
|
||||
newTabImpl->FindRequested([weakTab, weakThis{ get_weak() }]() {
|
||||
auto page{ weakThis.get() };
|
||||
auto tab{ weakTab.get() };
|
||||
|
@ -367,6 +379,20 @@ namespace winrt::TerminalApp::implementation
|
|||
CATCH_LOG();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Sets the specified tab as the focused tab and splits its active pane
|
||||
// Arguments:
|
||||
// - tab: tab to split
|
||||
void TerminalPage::_SplitTab(TerminalTab& tab)
|
||||
{
|
||||
try
|
||||
{
|
||||
_SetFocusedTab(tab);
|
||||
_SplitPane(tab, SplitState::Automatic, SplitType::Duplicate);
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Removes the tab (both TerminalControl and XAML) after prompting for approval
|
||||
// Arguments:
|
||||
|
|
45
src/cascadia/TerminalApp/TaskbarState.cpp
Normal file
45
src/cascadia/TerminalApp/TaskbarState.cpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "TaskbarState.h"
|
||||
#include "TaskbarState.g.cpp"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
// Default to unset, 0%.
|
||||
TaskbarState::TaskbarState() :
|
||||
TaskbarState(0, 0){};
|
||||
|
||||
TaskbarState::TaskbarState(const uint64_t dispatchTypesState, const uint64_t progressParam) :
|
||||
_State{ dispatchTypesState },
|
||||
_Progress{ progressParam } {}
|
||||
|
||||
uint64_t TaskbarState::Priority() const
|
||||
{
|
||||
// This seemingly nonsensical ordering is from
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-itaskbarlist3-setprogressstate#how-the-taskbar-button-chooses-the-progress-indicator-for-a-group
|
||||
switch (_State)
|
||||
{
|
||||
case 0: // Clear = 0,
|
||||
return 5;
|
||||
case 1: // Set = 1,
|
||||
return 3;
|
||||
case 2: // Error = 2,
|
||||
return 1;
|
||||
case 3: // Indeterminate = 3,
|
||||
return 4;
|
||||
case 4: // Paused = 4
|
||||
return 2;
|
||||
}
|
||||
// Here, return 6, to definitely be greater than all the other valid values.
|
||||
// This should never really happen.
|
||||
return 6;
|
||||
}
|
||||
|
||||
int TaskbarState::ComparePriority(const winrt::TerminalApp::TaskbarState& lhs, const winrt::TerminalApp::TaskbarState& rhs)
|
||||
{
|
||||
return lhs.Priority() < rhs.Priority();
|
||||
}
|
||||
|
||||
}
|
34
src/cascadia/TerminalApp/TaskbarState.h
Normal file
34
src/cascadia/TerminalApp/TaskbarState.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
#include "inc/cppwinrt_utils.h"
|
||||
#include "TaskbarState.g.h"
|
||||
|
||||
// fwdecl unittest classes
|
||||
namespace TerminalAppLocalTests
|
||||
{
|
||||
class TabTests;
|
||||
};
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct TaskbarState : TaskbarStateT<TaskbarState>
|
||||
{
|
||||
public:
|
||||
TaskbarState();
|
||||
TaskbarState(const uint64_t dispatchTypesState, const uint64_t progress);
|
||||
|
||||
static int ComparePriority(const winrt::TerminalApp::TaskbarState& lhs, const winrt::TerminalApp::TaskbarState& rhs);
|
||||
|
||||
uint64_t Priority() const;
|
||||
|
||||
WINRT_PROPERTY(uint64_t, State, 0);
|
||||
WINRT_PROPERTY(uint64_t, Progress, 0);
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::TerminalApp::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(TaskbarState);
|
||||
}
|
15
src/cascadia/TerminalApp/TaskbarState.idl
Normal file
15
src/cascadia/TerminalApp/TaskbarState.idl
Normal file
|
@ -0,0 +1,15 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
[default_interface] runtimeclass TaskbarState
|
||||
{
|
||||
TaskbarState();
|
||||
TaskbarState(UInt64 dispatchTypesState, UInt64 progress);
|
||||
|
||||
UInt64 State{ get; };
|
||||
UInt64 Progress{ get; };
|
||||
UInt64 Priority { get; };
|
||||
}
|
||||
}
|
|
@ -53,7 +53,7 @@
|
|||
<Page Include="TabRowControl.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="TabHeaderControl.xaml">
|
||||
<Page Include="TabHeaderControl.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="HighlightedTextControl.xaml">
|
||||
|
@ -74,6 +74,7 @@
|
|||
<ClInclude Include="Commandline.h" />
|
||||
<ClInclude Include="CommandLinePaletteItem.h" />
|
||||
<ClInclude Include="Jumplist.h" />
|
||||
<ClInclude Include="LanguageProfileNotifier.h" />
|
||||
<ClInclude Include="MinMaxCloseControl.h">
|
||||
<DependentUpon>MinMaxCloseControl.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
|
@ -89,6 +90,9 @@
|
|||
<DependentUpon>TabBase.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TabPaletteItem.h" />
|
||||
<ClInclude Include="TaskbarState.h">
|
||||
<DependentUpon>TaskbarState.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TerminalTab.h">
|
||||
<DependentUpon>TerminalTab.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
|
@ -112,7 +116,7 @@
|
|||
<ClInclude Include="HighlightedTextControl.h">
|
||||
<DependentUpon>HighlightedTextControl.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HighlightedText.h" />
|
||||
<ClInclude Include="HighlightedText.h" />
|
||||
<ClInclude Include="ColorPickupFlyout.h">
|
||||
<DependentUpon>ColorPickupFlyout.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
|
@ -139,7 +143,7 @@
|
|||
<ClInclude Include="AppLogic.h">
|
||||
<DependentUpon>AppLogic.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Toast.h"/>
|
||||
<ClInclude Include="Toast.h" />
|
||||
</ItemGroup>
|
||||
<!-- ========================= Cpp Files ======================== -->
|
||||
<ItemGroup>
|
||||
|
@ -149,6 +153,7 @@
|
|||
<ClCompile Include="AppCommandlineArgs.cpp" />
|
||||
<ClCompile Include="Commandline.cpp" />
|
||||
<ClCompile Include="Jumplist.cpp" />
|
||||
<ClCompile Include="LanguageProfileNotifier.cpp" />
|
||||
<ClCompile Include="MinMaxCloseControl.cpp">
|
||||
<DependentUpon>MinMaxCloseControl.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
|
@ -164,6 +169,9 @@
|
|||
<DependentUpon>TabBase.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TabPaletteItem.cpp" />
|
||||
<ClCompile Include="TaskbarState.cpp">
|
||||
<DependentUpon>TaskbarState.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TerminalTab.cpp">
|
||||
<DependentUpon>TerminalTab.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
|
@ -195,7 +203,7 @@
|
|||
<ClCompile Include="HighlightedTextControl.cpp">
|
||||
<DependentUpon>HighlightedTextControl.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HighlightedText.cpp" />
|
||||
<ClCompile Include="HighlightedText.cpp" />
|
||||
<ClCompile Include="ColorPickupFlyout.cpp">
|
||||
<DependentUpon>ColorPickupFlyout.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
|
@ -256,6 +264,7 @@
|
|||
</Midl>
|
||||
<Midl Include="TabBase.idl" />
|
||||
<Midl Include="TabPaletteItem.idl" />
|
||||
<Midl Include="TaskbarState.idl" />
|
||||
<Midl Include="TerminalTab.idl" />
|
||||
<Midl Include="TerminalPage.idl">
|
||||
<DependentUpon>TerminalPage.xaml</DependentUpon>
|
||||
|
@ -280,7 +289,7 @@
|
|||
<DependentUpon>HighlightedTextControl.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Midl>
|
||||
<Midl Include="HighlightedText.idl" />
|
||||
<Midl Include="HighlightedText.idl" />
|
||||
<Midl Include="ColorPickupFlyout.idl">
|
||||
<DependentUpon>ColorPickupFlyout.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
|
|
|
@ -13,9 +13,6 @@
|
|||
<ClCompile Include="Pane.cpp">
|
||||
<Filter>pane</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Tab.cpp">
|
||||
<Filter>tab</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Pane.LayoutSizeNode.cpp">
|
||||
<Filter>pane</Filter>
|
||||
</ClCompile>
|
||||
|
@ -23,7 +20,6 @@
|
|||
<ClCompile Include="Commandline.cpp" />
|
||||
<ClCompile Include="ColorHelper.cpp" />
|
||||
<ClCompile Include="DebugTapConnection.cpp" />
|
||||
<ClCompile Include="Utils.cpp" />
|
||||
<ClCompile Include="Jumplist.cpp" />
|
||||
<ClCompile Include="Tab.cpp">
|
||||
<Filter>tab</Filter>
|
||||
|
@ -49,10 +45,10 @@
|
|||
<ClCompile Include="HighlightedText.cpp">
|
||||
<Filter>highlightedText</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Toast.cpp" />
|
||||
<ClCompile Include="LanguageProfileNotifier.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Utils.h" />
|
||||
<ClInclude Include="TerminalWarnings.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="App.base.h">
|
||||
<Filter>app</Filter>
|
||||
|
@ -60,9 +56,6 @@
|
|||
<ClInclude Include="Pane.h">
|
||||
<Filter>pane</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Tab.h">
|
||||
<Filter>tab</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="AppCommandlineArgs.h" />
|
||||
<ClInclude Include="Commandline.h" />
|
||||
<ClInclude Include="DebugTapConnection.h" />
|
||||
|
@ -92,14 +85,13 @@
|
|||
<ClInclude Include="HighlightedText.h">
|
||||
<Filter>highlightedText</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Toast.h" />
|
||||
<ClInclude Include="LanguageProfileNotifier.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="AppLogic.idl">
|
||||
<Filter>app</Filter>
|
||||
</Midl>
|
||||
<Midl Include="ActionArgs.idl">
|
||||
<Filter>settings</Filter>
|
||||
</Midl>
|
||||
<Midl Include="AppKeyBindings.idl">
|
||||
<Filter>settings</Filter>
|
||||
</Midl>
|
||||
|
@ -107,9 +99,6 @@
|
|||
<Filter>settings</Filter>
|
||||
</Midl>
|
||||
<Midl Include="IDirectKeyListener.idl" />
|
||||
<Midl Include="ITab.idl">
|
||||
<Filter>tab</Filter>
|
||||
</Midl>
|
||||
<Midl Include="SettingsTab.idl">
|
||||
<Filter>tab</Filter>
|
||||
</Midl>
|
||||
|
@ -125,6 +114,9 @@
|
|||
<Midl Include="TerminalTabStatus.idl">
|
||||
<Filter>tab</Filter>
|
||||
</Midl>
|
||||
<Midl Include="PaletteItemTemplateSelector.idl" />
|
||||
<Midl Include="TabBase.idl" />
|
||||
<Midl Include="EmptyStringVisibilityConverter.idl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
@ -160,9 +152,6 @@
|
|||
<Midl Include="ActionPaletteItem.idl">
|
||||
<Filter>commandPalette</Filter>
|
||||
</Midl>
|
||||
<Midl Include="FilterableListItem.idl">
|
||||
<Filter>commandPalette</Filter>
|
||||
</Midl>
|
||||
<Midl Include="CommandLinePaletteItem.idl">
|
||||
<Filter>commandPalette</Filter>
|
||||
</Midl>
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include "RenameWindowRequestedArgs.g.cpp"
|
||||
#include "../inc/WindowingBehavior.h"
|
||||
|
||||
#include <til/latch.h>
|
||||
|
||||
using namespace winrt;
|
||||
using namespace winrt::Windows::Foundation::Collections;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
|
@ -253,16 +255,8 @@ namespace winrt::TerminalApp::implementation
|
|||
path = path.parent_path();
|
||||
}
|
||||
|
||||
std::wstring pathText = path.wstring();
|
||||
|
||||
// Handle edge case of "C:\\", seems like the "StartingDirectory" doesn't like path which ends with '\'
|
||||
if (pathText.back() == L'\\')
|
||||
{
|
||||
pathText.erase(std::prev(pathText.end()));
|
||||
}
|
||||
|
||||
NewTerminalArgs args;
|
||||
args.StartingDirectory(winrt::hstring{ pathText });
|
||||
args.StartingDirectory(winrt::hstring{ path.wstring() });
|
||||
this->_OpenNewTerminal(args);
|
||||
|
||||
TraceLoggingWrite(
|
||||
|
@ -356,34 +350,12 @@ namespace winrt::TerminalApp::implementation
|
|||
winrt::Microsoft::Terminal::TerminalConnection::ConptyConnection::StartInboundListener();
|
||||
}
|
||||
// If we failed to start the listener, it will throw.
|
||||
// We should fail fast here or the Terminal will be in a very strange state.
|
||||
// We only start the listener if the Terminal was started with the COM server
|
||||
// `-Embedding` flag and we make no tabs as a result.
|
||||
// Therefore, if the listener cannot start itself up to make that tab with
|
||||
// the inbound connection that caused the COM activation in the first place...
|
||||
// we would be left with an empty terminal frame with no tabs.
|
||||
// Instead, crash out so COM sees the server die and things unwind
|
||||
// without a weird empty frame window.
|
||||
// We don't want to fail fast here because if a peasant has some trouble with
|
||||
// starting the listener, we don't want it to crash and take all its tabs down
|
||||
// with it.
|
||||
catch (...)
|
||||
{
|
||||
// However, we cannot always fail fast because of MSFT:33501832. Sometimes the COM catalog
|
||||
// tears the state between old and new versions and fails here for that reason.
|
||||
// As we're always becoming an inbound server in the monarch, even when COM didn't strictly
|
||||
// ask us yet...we might just crash always.
|
||||
// Instead... we're going to differentiate. If COM started us... we will fail fast
|
||||
// so it sees the process die and falls back.
|
||||
// If we were just starting normally as a Monarch and opportunistically listening for
|
||||
// inbound connections... then we'll just log the failure and move on assuming
|
||||
// the version state is torn and will fix itself whenever the packaging upgrade
|
||||
// tasks decide to clean up.
|
||||
if (_isEmbeddingInboundListener)
|
||||
{
|
||||
FAIL_FAST_CAUGHT_EXCEPTION();
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
}
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -767,7 +739,7 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
else
|
||||
{
|
||||
this->_OpenNewTab(newTerminalArgs);
|
||||
LOG_IF_FAILED(this->_OpenNewTab(newTerminalArgs));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1246,6 +1218,33 @@ namespace winrt::TerminalApp::implementation
|
|||
return;
|
||||
}
|
||||
|
||||
_SplitPane(*focusedTab, splitType, splitMode, splitSize, newTerminalArgs);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Split the focused pane of the given tab, either horizontally or vertically, and place the
|
||||
// given TermControl into the newly created pane.
|
||||
// - If splitType == SplitState::None, this method does nothing.
|
||||
// Arguments:
|
||||
// - tab: The tab that is going to be split.
|
||||
// - splitType: one value from the TerminalApp::SplitState enum, indicating how the
|
||||
// new pane should be split from its parent.
|
||||
// - splitMode: value from TerminalApp::SplitType enum, indicating the profile to be used in the newly split pane.
|
||||
// - newTerminalArgs: An object that may contain a blob of parameters to
|
||||
// control which profile is created and with possible other
|
||||
// configurations. See CascadiaSettings::BuildSettings for more details.
|
||||
void TerminalPage::_SplitPane(TerminalTab& tab,
|
||||
const SplitState splitType,
|
||||
const SplitType splitMode,
|
||||
const float splitSize,
|
||||
const NewTerminalArgs& newTerminalArgs)
|
||||
{
|
||||
// Do nothing if we're requesting no split.
|
||||
if (splitType == SplitState::None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
TerminalSettingsCreateResult controlSettings{ nullptr };
|
||||
|
@ -1254,12 +1253,12 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
if (splitMode == SplitType::Duplicate)
|
||||
{
|
||||
std::optional<GUID> current_guid = focusedTab->GetFocusedProfile();
|
||||
std::optional<GUID> current_guid = tab.GetFocusedProfile();
|
||||
if (current_guid)
|
||||
{
|
||||
profileFound = true;
|
||||
controlSettings = TerminalSettings::CreateWithProfileByID(_settings, current_guid.value(), *_bindings);
|
||||
const auto workingDirectory = focusedTab->GetActiveTerminalControl().WorkingDirectory();
|
||||
const auto workingDirectory = tab.GetActiveTerminalControl().WorkingDirectory();
|
||||
const auto validWorkingDirectory = !workingDirectory.empty();
|
||||
if (validWorkingDirectory)
|
||||
{
|
||||
|
@ -1295,10 +1294,10 @@ namespace winrt::TerminalApp::implementation
|
|||
auto realSplitType = splitType;
|
||||
if (realSplitType == SplitState::Automatic)
|
||||
{
|
||||
realSplitType = focusedTab->PreCalculateAutoSplit(availableSpace);
|
||||
realSplitType = tab.PreCalculateAutoSplit(availableSpace);
|
||||
}
|
||||
|
||||
const auto canSplit = focusedTab->PreCalculateCanSplit(realSplitType, splitSize, availableSpace);
|
||||
const auto canSplit = tab.PreCalculateCanSplit(realSplitType, splitSize, availableSpace);
|
||||
if (!canSplit)
|
||||
{
|
||||
return;
|
||||
|
@ -1307,11 +1306,11 @@ namespace winrt::TerminalApp::implementation
|
|||
auto newControl = _InitControl(controlSettings, controlConnection);
|
||||
|
||||
// Hookup our event handlers to the new terminal
|
||||
_RegisterTerminalEvents(newControl, *focusedTab);
|
||||
_RegisterTerminalEvents(newControl, tab);
|
||||
|
||||
_UnZoomIfNeeded();
|
||||
|
||||
focusedTab->SplitPane(realSplitType, splitSize, realGuid, newControl);
|
||||
tab.SplitPane(realSplitType, splitSize, realGuid, newControl);
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
@ -2078,29 +2077,35 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
|
||||
// Method Description:
|
||||
// - Gets the taskbar state value from the last active control
|
||||
// - Get the combined taskbar state for the page. This is the combination of
|
||||
// all the states of all the tabs, which are themselves a combination of
|
||||
// all their panes. Taskbar states are given a priority based on the rules
|
||||
// in:
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-itaskbarlist3-setprogressstate
|
||||
// under "How the Taskbar Button Chooses the Progress Indicator for a Group"
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - The taskbar state of the last active control
|
||||
uint64_t TerminalPage::GetLastActiveControlTaskbarState()
|
||||
// - A TaskbarState object representing the combined taskbar state and
|
||||
// progress percentage of all our tabs.
|
||||
winrt::TerminalApp::TaskbarState TerminalPage::TaskbarState() const
|
||||
{
|
||||
if (auto control{ _GetActiveControl() })
|
||||
{
|
||||
return control.TaskbarState();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
auto state{ winrt::make<winrt::TerminalApp::implementation::TaskbarState>() };
|
||||
|
||||
// Method Description:
|
||||
// - Gets the taskbar progress value from the last active control
|
||||
// Return Value:
|
||||
// - The taskbar progress of the last active control
|
||||
uint64_t TerminalPage::GetLastActiveControlTaskbarProgress()
|
||||
{
|
||||
if (auto control{ _GetActiveControl() })
|
||||
for (const auto& tab : _tabs)
|
||||
{
|
||||
return control.TaskbarProgress();
|
||||
if (auto tabImpl{ _GetTerminalTabImpl(tab) })
|
||||
{
|
||||
auto tabState{ tabImpl->GetCombinedTaskbarState() };
|
||||
// lowest priority wins
|
||||
if (tabState.Priority() < state.Priority())
|
||||
{
|
||||
state = tabState;
|
||||
}
|
||||
}
|
||||
}
|
||||
return {};
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -2386,13 +2391,38 @@ namespace winrt::TerminalApp::implementation
|
|||
return _isAlwaysOnTop;
|
||||
}
|
||||
|
||||
void TerminalPage::_OnNewConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection connection)
|
||||
HRESULT TerminalPage::_OnNewConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection connection)
|
||||
{
|
||||
// TODO: GH 9458 will give us more context so we can try to choose a better profile.
|
||||
_OpenNewTab(nullptr, connection);
|
||||
// We need to be on the UI thread in order for _OpenNewTab to run successfully.
|
||||
// HasThreadAccess will return true if we're currently on a UI thread and false otherwise.
|
||||
// When we're on a COM thread, we'll need to dispatch the calls to the UI thread
|
||||
// and wait on it hence the locking mechanism.
|
||||
if (Dispatcher().HasThreadAccess())
|
||||
{
|
||||
// TODO: GH 9458 will give us more context so we can try to choose a better profile.
|
||||
auto hr = _OpenNewTab(nullptr, connection);
|
||||
|
||||
// Request a summon of this window to the foreground
|
||||
_SummonWindowRequestedHandlers(*this, nullptr);
|
||||
// Request a summon of this window to the foreground
|
||||
_SummonWindowRequestedHandlers(*this, nullptr);
|
||||
|
||||
return hr;
|
||||
}
|
||||
else
|
||||
{
|
||||
til::latch latch{ 1 };
|
||||
HRESULT finalVal = S_OK;
|
||||
|
||||
Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [&]() {
|
||||
finalVal = _OpenNewTab(nullptr, connection);
|
||||
|
||||
_SummonWindowRequestedHandlers(*this, nullptr);
|
||||
|
||||
latch.count_down();
|
||||
});
|
||||
|
||||
latch.wait();
|
||||
return finalVal;
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
|
|
@ -85,8 +85,7 @@ namespace winrt::TerminalApp::implementation
|
|||
winrt::TerminalApp::IDialogPresenter DialogPresenter() const;
|
||||
void DialogPresenter(winrt::TerminalApp::IDialogPresenter dialogPresenter);
|
||||
|
||||
uint64_t GetLastActiveControlTaskbarState();
|
||||
uint64_t GetLastActiveControlTaskbarProgress();
|
||||
winrt::TerminalApp::TaskbarState TaskbarState() const;
|
||||
|
||||
void ShowKeyboardServiceWarning();
|
||||
winrt::hstring KeyboardServiceDisabledText();
|
||||
|
@ -188,7 +187,7 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
void _CreateNewTabFlyout();
|
||||
void _OpenNewTabDropdown();
|
||||
void _OpenNewTab(const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr);
|
||||
HRESULT _OpenNewTab(const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr);
|
||||
void _CreateNewTabFromSettings(GUID profileGuid, const Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr);
|
||||
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection _CreateConnectionFromSettings(GUID profileGuid, Microsoft::Terminal::Settings::Model::TerminalSettings settings);
|
||||
|
||||
|
@ -219,6 +218,8 @@ namespace winrt::TerminalApp::implementation
|
|||
void _DuplicateFocusedTab();
|
||||
void _DuplicateTab(const TerminalTab& tab);
|
||||
|
||||
void _SplitTab(TerminalTab& tab);
|
||||
|
||||
winrt::Windows::Foundation::IAsyncAction _HandleCloseTabRequested(winrt::TerminalApp::TabBase tab);
|
||||
void _CloseTabAtIndex(uint32_t index);
|
||||
void _RemoveTab(const winrt::TerminalApp::TabBase& tab);
|
||||
|
@ -254,6 +255,11 @@ namespace winrt::TerminalApp::implementation
|
|||
const Microsoft::Terminal::Settings::Model::SplitType splitMode = Microsoft::Terminal::Settings::Model::SplitType::Manual,
|
||||
const float splitSize = 0.5f,
|
||||
const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs = nullptr);
|
||||
void _SplitPane(TerminalTab& tab,
|
||||
const Microsoft::Terminal::Settings::Model::SplitState splitType,
|
||||
const Microsoft::Terminal::Settings::Model::SplitType splitMode = Microsoft::Terminal::Settings::Model::SplitType::Manual,
|
||||
const float splitSize = 0.5f,
|
||||
const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs = nullptr);
|
||||
void _ResizePane(const Microsoft::Terminal::Settings::Model::ResizeDirection& direction);
|
||||
void _ToggleSplitOrientation();
|
||||
|
||||
|
@ -337,7 +343,7 @@ namespace winrt::TerminalApp::implementation
|
|||
winrt::Microsoft::Terminal::Settings::Model::Command _lastPreviewedCommand{ nullptr };
|
||||
winrt::Microsoft::Terminal::Settings::Model::TerminalSettings _originalSettings{ nullptr };
|
||||
|
||||
void _OnNewConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection connection);
|
||||
HRESULT _OnNewConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection connection);
|
||||
void _HandleToggleInboundPty(const IInspectable& sender, const Microsoft::Terminal::Settings::Model::ActionEventArgs& args);
|
||||
|
||||
void _WindowRenamerActionClick(const IInspectable& sender, const IInspectable& eventArgs);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
import "TaskbarState.idl";
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
|
@ -42,8 +43,7 @@ namespace TerminalApp
|
|||
void ShowKeyboardServiceWarning();
|
||||
String KeyboardServiceDisabledText { get; };
|
||||
|
||||
UInt64 GetLastActiveControlTaskbarState();
|
||||
UInt64 GetLastActiveControlTaskbarProgress();
|
||||
TaskbarState TaskbarState{ get; };
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, String> TitleChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, LastTabClosedEventArgs> LastTabClosed;
|
||||
|
|
|
@ -177,10 +177,9 @@ namespace winrt::TerminalApp::implementation
|
|||
{
|
||||
lastFocusedControl.Focus(_focusState);
|
||||
|
||||
// Update our own progress state, and fire an event signaling
|
||||
// Update our own progress state. This will fire an event signaling
|
||||
// that our taskbar progress changed.
|
||||
_UpdateProgressState();
|
||||
_TaskbarProgressChangedHandlers(lastFocusedControl, nullptr);
|
||||
}
|
||||
// When we gain focus, remove the bell indicator if it is active
|
||||
if (_tabStatus.BellIndicator())
|
||||
|
@ -675,6 +674,26 @@ namespace winrt::TerminalApp::implementation
|
|||
});
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Get the combined taskbar state for the tab. This is the combination of
|
||||
// all the states of all our panes. Taskbar states are given a priority
|
||||
// based on the rules in:
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-itaskbarlist3-setprogressstate
|
||||
// under "How the Taskbar Button Chooses the Progress Indicator for a
|
||||
// Group"
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - A TaskbarState object representing the combined taskbar state and
|
||||
// progress percentage of all our panes.
|
||||
winrt::TerminalApp::TaskbarState TerminalTab::GetCombinedTaskbarState() const
|
||||
{
|
||||
std::vector<winrt::TerminalApp::TaskbarState> states;
|
||||
_rootPane->CollectTaskbarStates(states);
|
||||
return states.empty() ? winrt::make<winrt::TerminalApp::implementation::TaskbarState>() :
|
||||
*std::min_element(states.begin(), states.end(), TerminalApp::implementation::TaskbarState::ComparePriority);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - This should be called on the UI thread. If you don't, then it might
|
||||
// silently do nothing.
|
||||
|
@ -690,37 +709,39 @@ namespace winrt::TerminalApp::implementation
|
|||
// - <none>
|
||||
void TerminalTab::_UpdateProgressState()
|
||||
{
|
||||
if (const auto& activeControl{ GetActiveTerminalControl() })
|
||||
{
|
||||
const auto taskbarState = activeControl.TaskbarState();
|
||||
// The progress of the control changed, but not necessarily the progress of the tab.
|
||||
// Set the tab's progress ring to the active pane's progress
|
||||
if (taskbarState > 0)
|
||||
{
|
||||
if (taskbarState == 3)
|
||||
{
|
||||
// 3 is the indeterminate state, set the progress ring as such
|
||||
_tabStatus.IsProgressRingIndeterminate(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// any non-indeterminate state has a value, set the progress ring as such
|
||||
_tabStatus.IsProgressRingIndeterminate(false);
|
||||
const auto state{ GetCombinedTaskbarState() };
|
||||
|
||||
const auto progressValue = gsl::narrow<uint32_t>(activeControl.TaskbarProgress());
|
||||
_tabStatus.ProgressValue(progressValue);
|
||||
}
|
||||
// Hide the tab icon (the progress ring is placed over it)
|
||||
HideIcon(true);
|
||||
_tabStatus.IsProgressRingActive(true);
|
||||
const auto taskbarState = state.State();
|
||||
// The progress of the control changed, but not necessarily the progress of the tab.
|
||||
// Set the tab's progress ring to the active pane's progress
|
||||
if (taskbarState > 0)
|
||||
{
|
||||
if (taskbarState == 3)
|
||||
{
|
||||
// 3 is the indeterminate state, set the progress ring as such
|
||||
_tabStatus.IsProgressRingIndeterminate(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Show the tab icon
|
||||
HideIcon(false);
|
||||
_tabStatus.IsProgressRingActive(false);
|
||||
// any non-indeterminate state has a value, set the progress ring as such
|
||||
_tabStatus.IsProgressRingIndeterminate(false);
|
||||
|
||||
const auto progressValue = gsl::narrow<uint32_t>(state.Progress());
|
||||
_tabStatus.ProgressValue(progressValue);
|
||||
}
|
||||
// Hide the tab icon (the progress ring is placed over it)
|
||||
HideIcon(true);
|
||||
_tabStatus.IsProgressRingActive(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Show the tab icon
|
||||
HideIcon(false);
|
||||
_tabStatus.IsProgressRingActive(false);
|
||||
}
|
||||
|
||||
// fire an event signaling that our taskbar progress changed.
|
||||
_TaskbarProgressChangedHandlers(nullptr, nullptr);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -953,6 +974,23 @@ namespace winrt::TerminalApp::implementation
|
|||
findMenuItem.Icon(findSymbol);
|
||||
}
|
||||
|
||||
Controls::MenuFlyoutItem splitTabMenuItem;
|
||||
{
|
||||
// "Split Tab"
|
||||
Controls::FontIcon splitTabSymbol;
|
||||
splitTabSymbol.FontFamily(Media::FontFamily{ L"Segoe MDL2 Assets" });
|
||||
splitTabSymbol.Glyph(L"\xF246"); // ViewDashboard
|
||||
|
||||
splitTabMenuItem.Click([weakThis](auto&&, auto&&) {
|
||||
if (auto tab{ weakThis.get() })
|
||||
{
|
||||
tab->_SplitTabRequestedHandlers();
|
||||
}
|
||||
});
|
||||
splitTabMenuItem.Text(RS_(L"SplitTabText"));
|
||||
splitTabMenuItem.Icon(splitTabSymbol);
|
||||
}
|
||||
|
||||
// Build the menu
|
||||
Controls::MenuFlyout contextMenuFlyout;
|
||||
Controls::MenuFlyoutSeparator menuSeparator;
|
||||
|
@ -960,6 +998,7 @@ namespace winrt::TerminalApp::implementation
|
|||
contextMenuFlyout.Items().Append(chooseColorMenuItem);
|
||||
contextMenuFlyout.Items().Append(renameTabMenuItem);
|
||||
contextMenuFlyout.Items().Append(duplicateTabMenuItem);
|
||||
contextMenuFlyout.Items().Append(splitTabMenuItem);
|
||||
contextMenuFlyout.Items().Append(menuSeparator);
|
||||
contextMenuFlyout.Items().Append(findMenuItem);
|
||||
contextMenuFlyout.Items().Append(menuSeparator2);
|
||||
|
@ -1336,4 +1375,5 @@ namespace winrt::TerminalApp::implementation
|
|||
DEFINE_EVENT(TerminalTab, TabRaiseVisualBell, _TabRaiseVisualBellHandlers, winrt::delegate<>);
|
||||
DEFINE_EVENT(TerminalTab, DuplicateRequested, _DuplicateRequestedHandlers, winrt::delegate<>);
|
||||
DEFINE_EVENT(TerminalTab, FindRequested, _FindRequestedHandlers, winrt::delegate<>);
|
||||
DEFINE_EVENT(TerminalTab, SplitTabRequested, _SplitTabRequestedHandlers, winrt::delegate<>);
|
||||
}
|
||||
|
|
|
@ -83,6 +83,7 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
void TogglePaneReadOnly();
|
||||
std::shared_ptr<Pane> GetActivePane() const;
|
||||
winrt::TerminalApp::TaskbarState GetCombinedTaskbarState() const;
|
||||
|
||||
winrt::TerminalApp::TerminalTabStatus TabStatus()
|
||||
{
|
||||
|
@ -95,6 +96,7 @@ namespace winrt::TerminalApp::implementation
|
|||
DECLARE_EVENT(TabRaiseVisualBell, _TabRaiseVisualBellHandlers, winrt::delegate<>);
|
||||
DECLARE_EVENT(DuplicateRequested, _DuplicateRequestedHandlers, winrt::delegate<>);
|
||||
DECLARE_EVENT(FindRequested, _FindRequestedHandlers, winrt::delegate<>);
|
||||
DECLARE_EVENT(SplitTabRequested, _SplitTabRequestedHandlers, winrt::delegate<>);
|
||||
TYPED_EVENT(TaskbarProgressChanged, IInspectable, IInspectable);
|
||||
|
||||
private:
|
||||
|
|
|
@ -66,6 +66,7 @@ TRACELOGGING_DECLARE_PROVIDER(g_hTerminalAppProvider);
|
|||
#include <telemetry/ProjectTelemetry.h>
|
||||
#include <TraceLoggingActivity.h>
|
||||
|
||||
#include <msctf.h>
|
||||
#include <shellapi.h>
|
||||
#include <shobjidl_core.h>
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@ using namespace Microsoft::WRL;
|
|||
static NewHandoffFunction _pfnHandoff = nullptr;
|
||||
// The registration ID of the class object for clean up later
|
||||
static DWORD g_cTerminalHandoffRegistration = 0;
|
||||
// Mutex so we only do start/stop/establish one at a time.
|
||||
static std::shared_mutex _mtx;
|
||||
|
||||
// Routine Description:
|
||||
// - Starts listening for TerminalHandoff requests by registering
|
||||
|
@ -19,9 +21,11 @@ static DWORD g_cTerminalHandoffRegistration = 0;
|
|||
// - pfnHandoff - Function to callback when a handoff is received
|
||||
// Return Value:
|
||||
// - S_OK, E_NOT_VALID_STATE (start called when already started) or relevant COM registration error.
|
||||
HRESULT CTerminalHandoff::s_StartListening(NewHandoffFunction pfnHandoff) noexcept
|
||||
HRESULT CTerminalHandoff::s_StartListening(NewHandoffFunction pfnHandoff)
|
||||
try
|
||||
{
|
||||
std::unique_lock lock{ _mtx };
|
||||
|
||||
RETURN_HR_IF(E_NOT_VALID_STATE, _pfnHandoff != nullptr);
|
||||
|
||||
const auto classFactory = Make<SimpleClassFactory<CTerminalHandoff>>();
|
||||
|
@ -31,7 +35,7 @@ try
|
|||
ComPtr<IUnknown> unk;
|
||||
RETURN_IF_FAILED(classFactory.As(&unk));
|
||||
|
||||
RETURN_IF_FAILED(CoRegisterClassObject(__uuidof(CTerminalHandoff), unk.Get(), CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &g_cTerminalHandoffRegistration));
|
||||
RETURN_IF_FAILED(CoRegisterClassObject(__uuidof(CTerminalHandoff), unk.Get(), CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &g_cTerminalHandoffRegistration));
|
||||
|
||||
_pfnHandoff = pfnHandoff;
|
||||
|
||||
|
@ -46,8 +50,10 @@ CATCH_RETURN()
|
|||
// - <none>
|
||||
// Return Value:
|
||||
// - S_OK, E_NOT_VALID_STATE (stop called when not started), or relevant COM class revoke error
|
||||
HRESULT CTerminalHandoff::s_StopListening() noexcept
|
||||
HRESULT CTerminalHandoff::s_StopListening()
|
||||
{
|
||||
std::unique_lock lock{ _mtx };
|
||||
|
||||
RETURN_HR_IF_NULL(E_NOT_VALID_STATE, _pfnHandoff);
|
||||
|
||||
_pfnHandoff = nullptr;
|
||||
|
@ -91,10 +97,19 @@ static HRESULT _duplicateHandle(const HANDLE in, HANDLE& out) noexcept
|
|||
// - E_NOT_VALID_STATE if a event handler is not registered before calling. `::DuplicateHandle`
|
||||
// error codes if we cannot manage to make our own copy of handles to retain. Or S_OK/error
|
||||
// from the registered handler event function.
|
||||
HRESULT CTerminalHandoff::EstablishPtyHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client) noexcept
|
||||
HRESULT CTerminalHandoff::EstablishPtyHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client)
|
||||
{
|
||||
// Stash a local copy of _pfnHandoff before we stop listening.
|
||||
auto localPfnHandoff = _pfnHandoff;
|
||||
|
||||
// Because we are REGCLS_SINGLEUSE... we need to `CoRevokeClassObject` after we handle this ONE call.
|
||||
// COM does not automatically clean that up for us. We must do it.
|
||||
s_StopListening();
|
||||
|
||||
std::unique_lock lock{ _mtx };
|
||||
|
||||
// Report an error if no one registered a handoff function before calling this.
|
||||
RETURN_HR_IF_NULL(E_NOT_VALID_STATE, _pfnHandoff);
|
||||
RETURN_HR_IF_NULL(E_NOT_VALID_STATE, localPfnHandoff);
|
||||
|
||||
// Duplicate the handles from what we received.
|
||||
// The contract with COM specifies that any HANDLEs we receive from the caller belong
|
||||
|
@ -108,5 +123,5 @@ HRESULT CTerminalHandoff::EstablishPtyHandoff(HANDLE in, HANDLE out, HANDLE sign
|
|||
RETURN_IF_FAILED(_duplicateHandle(client, client));
|
||||
|
||||
// Call registered handler from when we started listening.
|
||||
return _pfnHandoff(in, out, signal, ref, server, client);
|
||||
return localPfnHandoff(in, out, signal, ref, server, client);
|
||||
}
|
||||
|
|
|
@ -37,12 +37,12 @@ struct __declspec(uuid(__CLSID_CTerminalHandoff))
|
|||
HANDLE signal,
|
||||
HANDLE ref,
|
||||
HANDLE server,
|
||||
HANDLE client) noexcept override;
|
||||
HANDLE client) override;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
static HRESULT s_StartListening(NewHandoffFunction pfnHandoff) noexcept;
|
||||
static HRESULT s_StopListening() noexcept;
|
||||
static HRESULT s_StartListening(NewHandoffFunction pfnHandoff);
|
||||
static HRESULT s_StopListening();
|
||||
};
|
||||
|
||||
// Disable warnings from the CoCreatableClass macro as the value it provides for
|
||||
|
|
|
@ -23,6 +23,16 @@ using namespace winrt::Windows::Graphics::Display;
|
|||
using namespace winrt::Windows::System;
|
||||
using namespace winrt::Windows::ApplicationModel::DataTransfer;
|
||||
|
||||
// The minimum delay between updates to the scroll bar's values.
|
||||
// The updates are throttled to limit power usage.
|
||||
constexpr const auto ScrollBarUpdateInterval = std::chrono::milliseconds(8);
|
||||
|
||||
// The minimum delay between updating the TSF input control.
|
||||
constexpr const auto TsfRedrawInterval = std::chrono::milliseconds(100);
|
||||
|
||||
// The minimum delay between updating the locations of regex patterns
|
||||
constexpr const auto UpdatePatternLocationsInterval = std::chrono::milliseconds(500);
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
{
|
||||
// Helper static function to ensure that all ambiguous-width glyphs are reported as narrow.
|
||||
|
@ -94,6 +104,61 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
auto pfnTerminalTaskbarProgressChanged = std::bind(&ControlCore::_terminalTaskbarProgressChanged, this);
|
||||
_terminal->TaskbarProgressChangedCallback(pfnTerminalTaskbarProgressChanged);
|
||||
|
||||
// Get our dispatcher. If we're hosted in-proc with XAML, this will get
|
||||
// us the same dispatcher as TermControl::Dispatcher(). If we're out of
|
||||
// proc, this'll return null. We'll need to instead make a new
|
||||
// DispatcherQueue (on a new thread), so we can use that for throttled
|
||||
// functions.
|
||||
_dispatcher = winrt::Windows::System::DispatcherQueue::GetForCurrentThread();
|
||||
if (!_dispatcher)
|
||||
{
|
||||
auto controller{ winrt::Windows::System::DispatcherQueueController::CreateOnDedicatedThread() };
|
||||
_dispatcher = controller.DispatcherQueue();
|
||||
}
|
||||
|
||||
// A few different events should be throttled, so they don't fire absolutely all the time:
|
||||
// * _tsfTryRedrawCanvas: When the cursor position moves, we need to
|
||||
// inform TSF, so it can move the canvas for the composition. We
|
||||
// throttle this so that we're not hopping across the process boundary
|
||||
// every time that the cursor moves.
|
||||
// * _updatePatternLocations: When there's new output, or we scroll the
|
||||
// viewport, we should re-check if there are any visible hyperlinks.
|
||||
// But we don't really need to do this every single time text is
|
||||
// output, we can limit this update to once every 500ms.
|
||||
// * _updateScrollBar: Same idea as the TSF update - we don't _really_
|
||||
// need to hop across the process boundary every time text is output.
|
||||
// We can throttle this to once every 8ms, which will get us out of
|
||||
// the way of the main output & rendering threads.
|
||||
_tsfTryRedrawCanvas = std::make_shared<ThrottledFuncTrailing<>>(
|
||||
_dispatcher,
|
||||
TsfRedrawInterval,
|
||||
[weakThis = get_weak()]() {
|
||||
if (auto core{ weakThis.get() }; !core->_IsClosing())
|
||||
{
|
||||
core->_CursorPositionChangedHandlers(*core, nullptr);
|
||||
}
|
||||
});
|
||||
|
||||
_updatePatternLocations = std::make_shared<ThrottledFuncTrailing<>>(
|
||||
_dispatcher,
|
||||
UpdatePatternLocationsInterval,
|
||||
[weakThis = get_weak()]() {
|
||||
if (auto core{ weakThis.get() }; !core->_IsClosing())
|
||||
{
|
||||
core->UpdatePatternLocations();
|
||||
}
|
||||
});
|
||||
|
||||
_updateScrollBar = std::make_shared<ThrottledFuncTrailing<Control::ScrollPositionChangedArgs>>(
|
||||
_dispatcher,
|
||||
ScrollBarUpdateInterval,
|
||||
[weakThis = get_weak()](const auto& update) {
|
||||
if (auto core{ weakThis.get() }; !core->_IsClosing())
|
||||
{
|
||||
core->_ScrollPositionChangedHandlers(*core, update);
|
||||
}
|
||||
});
|
||||
|
||||
UpdateSettings(settings);
|
||||
}
|
||||
|
||||
|
@ -739,6 +804,18 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
return;
|
||||
}
|
||||
|
||||
// Convert our new dimensions to characters
|
||||
const auto viewInPixels = Viewport::FromDimensions({ 0, 0 },
|
||||
{ static_cast<short>(size.cx), static_cast<short>(size.cy) });
|
||||
const auto vp = _renderEngine->GetViewportInCharacters(viewInPixels);
|
||||
const auto currentVP = _terminal->GetViewport();
|
||||
|
||||
// Don't actually resize if viewport dimensions didn't change
|
||||
if (vp.Height() == currentVP.Height() && vp.Width() == currentVP.Width())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_terminal->ClearSelection();
|
||||
|
||||
// Tell the dx engine that our window is now the new size.
|
||||
|
@ -747,11 +824,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// Invalidate everything
|
||||
_renderer->TriggerRedrawAll();
|
||||
|
||||
// Convert our new dimensions to characters
|
||||
const auto viewInPixels = Viewport::FromDimensions({ 0, 0 },
|
||||
{ static_cast<short>(size.cx), static_cast<short>(size.cy) });
|
||||
const auto vp = _renderEngine->GetViewportInCharacters(viewInPixels);
|
||||
|
||||
// If this function succeeds with S_FALSE, then the terminal didn't
|
||||
// actually change size. No need to notify the connection of this no-op.
|
||||
const HRESULT hr = _terminal->UserResize({ vp.Width(), vp.Height() });
|
||||
|
@ -1103,15 +1175,28 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// TODO GH#9617: refine locking around pattern tree
|
||||
_terminal->ClearPatternTree();
|
||||
|
||||
_ScrollPositionChangedHandlers(*this,
|
||||
winrt::make<ScrollPositionChangedArgs>(viewTop,
|
||||
viewHeight,
|
||||
bufferSize));
|
||||
// Start the throttled update of our scrollbar.
|
||||
auto update{ winrt::make<ScrollPositionChangedArgs>(viewTop,
|
||||
viewHeight,
|
||||
bufferSize) };
|
||||
if (!_inUnitTests)
|
||||
{
|
||||
_updateScrollBar->Run(update);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ScrollPositionChangedHandlers(*this, update);
|
||||
}
|
||||
|
||||
// Additionally, start the throttled update of where our links are.
|
||||
_updatePatternLocations->Run();
|
||||
}
|
||||
|
||||
void ControlCore::_terminalCursorPositionChanged()
|
||||
{
|
||||
_CursorPositionChangedHandlers(*this, nullptr);
|
||||
// When the buffer's cursor moves, start the throttled func to
|
||||
// eventually dispatch a CursorPositionChanged event.
|
||||
_tsfTryRedrawCanvas->Run();
|
||||
}
|
||||
|
||||
void ControlCore::_terminalTaskbarProgressChanged()
|
||||
|
@ -1221,8 +1306,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
void ControlCore::Close()
|
||||
{
|
||||
if (!_closing.exchange(true))
|
||||
if (!_IsClosing())
|
||||
{
|
||||
_closing = true;
|
||||
|
||||
// Stop accepting new output and state changes before we disconnect everything.
|
||||
_connection.TerminalOutput(_connectionOutputEventToken);
|
||||
_connectionStateChangedRevoker.revoke();
|
||||
|
@ -1400,18 +1487,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
{
|
||||
_terminal->Write(hstr);
|
||||
|
||||
// NOTE: We're raising an event here to inform the TermControl that
|
||||
// output has been received, so it can queue up a throttled
|
||||
// UpdatePatternLocations call. In the future, we should have the
|
||||
// _updatePatternLocations ThrottledFunc internal to this class, and
|
||||
// run on this object's dispatcher queue.
|
||||
//
|
||||
// We're not doing that quite yet, because the Core will eventually
|
||||
// be out-of-proc from the UI thread, and won't be able to just use
|
||||
// the UI thread as the dispatcher queue thread.
|
||||
//
|
||||
// See TODO: https://github.com/microsoft/terminal/projects/5#card-50760282
|
||||
_ReceivedOutputHandlers(*this, nullptr);
|
||||
// Start the throttled update of where our hyperlinks are.
|
||||
_updatePatternLocations->Run();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -168,7 +168,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
private:
|
||||
bool _initializedTerminal{ false };
|
||||
std::atomic<bool> _closing{ false };
|
||||
bool _closing{ false };
|
||||
|
||||
TerminalConnection::ITerminalConnection _connection{ nullptr };
|
||||
event_token _connectionOutputEventToken;
|
||||
|
@ -206,6 +206,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
double _panelHeight{ 0 };
|
||||
double _compositionScale{ 0 };
|
||||
|
||||
winrt::Windows::System::DispatcherQueue _dispatcher{ nullptr };
|
||||
std::shared_ptr<ThrottledFuncTrailing<>> _tsfTryRedrawCanvas;
|
||||
std::shared_ptr<ThrottledFuncTrailing<>> _updatePatternLocations;
|
||||
std::shared_ptr<ThrottledFuncTrailing<Control::ScrollPositionChangedArgs>> _updateScrollBar;
|
||||
|
||||
winrt::fire_and_forget _asyncCloseConnection();
|
||||
|
||||
void _setFontSize(int fontSize);
|
||||
|
@ -239,8 +244,24 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
void _connectionOutputHandler(const hstring& hstr);
|
||||
void _updateHoveredCell(const std::optional<til::point> terminalPosition);
|
||||
|
||||
inline bool _IsClosing() const noexcept
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (_dispatcher)
|
||||
{
|
||||
// _closing isn't atomic and may only be accessed from the main thread.
|
||||
//
|
||||
// Though, the unit tests don't actually run in TAEF's main
|
||||
// thread, so we don't care when we're running in tests.
|
||||
assert(_inUnitTests || _dispatcher.HasThreadAccess());
|
||||
}
|
||||
#endif
|
||||
return _closing;
|
||||
}
|
||||
|
||||
friend class ControlUnitTests::ControlCoreTests;
|
||||
friend class ControlUnitTests::ControlInteractivityTests;
|
||||
bool _inUnitTests{ false };
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -9,5 +9,6 @@ namespace Microsoft.Terminal.Control
|
|||
interface IKeyBindings
|
||||
{
|
||||
Boolean TryKeyChord(KeyChord kc);
|
||||
Boolean IsKeyChordExplicitlyUnbound(KeyChord kc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,8 @@ using namespace winrt::Windows::ApplicationModel::DataTransfer;
|
|||
constexpr const auto ScrollBarUpdateInterval = std::chrono::milliseconds(8);
|
||||
|
||||
// The minimum delay between updating the TSF input control.
|
||||
constexpr const auto TsfRedrawInterval = std::chrono::milliseconds(100);
|
||||
// This is already throttled primarily in the ControlCore, with a timeout of 100ms. We're adding another smaller one here, as the (potentially x-proc) call will come in off the UI thread
|
||||
constexpr const auto TsfRedrawInterval = std::chrono::milliseconds(8);
|
||||
|
||||
// The minimum delay between updating the locations of regex patterns
|
||||
constexpr const auto UpdatePatternLocationsInterval = std::chrono::milliseconds(500);
|
||||
|
@ -64,10 +65,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
_interactivity = winrt::make<implementation::ControlInteractivity>(settings, connection);
|
||||
_core = _interactivity.Core();
|
||||
|
||||
// Use a manual revoker on the output event, so we can immediately stop
|
||||
// worrying about it on destruction.
|
||||
_coreOutputEventToken = _core.ReceivedOutput({ this, &TermControl::_coreReceivedOutput });
|
||||
|
||||
// These events might all be triggered by the connection, but that
|
||||
// should be drained and closed before we complete destruction. So these
|
||||
// are safe.
|
||||
|
@ -104,37 +101,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
}
|
||||
});
|
||||
|
||||
// Many of these ThrottledFunc's should be inside ControlCore. However,
|
||||
// currently they depend on the Dispatcher() of the UI thread, which the
|
||||
// Core eventually won't have access to. When we get to
|
||||
// https://github.com/microsoft/terminal/projects/5#card-50760282
|
||||
// then we'll move the applicable ones.
|
||||
//
|
||||
// These four throttled functions are triggered by terminal output and interact with the UI.
|
||||
// Get our dispatcher. This will get us the same dispatcher as
|
||||
// TermControl::Dispatcher().
|
||||
auto dispatcher = winrt::Windows::System::DispatcherQueue::GetForCurrentThread();
|
||||
|
||||
// These three throttled functions are triggered by terminal output and interact with the UI.
|
||||
// Since Close() is the point after which we are removed from the UI, but before the
|
||||
// destructor has run, we MUST check control->_IsClosing() before actually doing anything.
|
||||
_tsfTryRedrawCanvas = std::make_shared<ThrottledFuncTrailing<>>(
|
||||
Dispatcher(),
|
||||
TsfRedrawInterval,
|
||||
[weakThis = get_weak()]() {
|
||||
if (auto control{ weakThis.get() }; !control->_IsClosing())
|
||||
{
|
||||
control->TSFInputControl().TryRedrawCanvas();
|
||||
}
|
||||
});
|
||||
|
||||
_updatePatternLocations = std::make_shared<ThrottledFuncTrailing<>>(
|
||||
Dispatcher(),
|
||||
UpdatePatternLocationsInterval,
|
||||
[weakThis = get_weak()]() {
|
||||
if (auto control{ weakThis.get() }; !control->_IsClosing())
|
||||
{
|
||||
control->_core.UpdatePatternLocations();
|
||||
}
|
||||
});
|
||||
|
||||
_playWarningBell = std::make_shared<ThrottledFuncLeading>(
|
||||
Dispatcher(),
|
||||
dispatcher,
|
||||
TerminalWarningBellInterval,
|
||||
[weakThis = get_weak()]() {
|
||||
if (auto control{ weakThis.get() }; !control->_IsClosing())
|
||||
|
@ -144,7 +119,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
});
|
||||
|
||||
_updateScrollBar = std::make_shared<ThrottledFuncTrailing<ScrollBarUpdate>>(
|
||||
Dispatcher(),
|
||||
dispatcher,
|
||||
ScrollBarUpdateInterval,
|
||||
[weakThis = get_weak()](const auto& update) {
|
||||
if (auto control{ weakThis.get() }; !control->_IsClosing())
|
||||
|
@ -540,7 +515,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
{
|
||||
// create a custom automation peer with this code pattern:
|
||||
// (https://docs.microsoft.com/en-us/windows/uwp/design/accessibility/custom-automation-peers)
|
||||
if (const auto& interactivityAutoPeer = _interactivity.OnCreateAutomationPeer())
|
||||
if (const auto& interactivityAutoPeer{ _interactivity.OnCreateAutomationPeer() })
|
||||
{
|
||||
_automationPeer = winrt::make<implementation::TermControlAutomationPeer>(this, interactivityAutoPeer);
|
||||
return _automationPeer;
|
||||
|
@ -786,28 +761,39 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
(void)_TrySendKeyEvent(VK_MENU, scanCode, modifiers, false);
|
||||
handled = true;
|
||||
}
|
||||
else if (vkey == VK_F7 && down)
|
||||
else if ((vkey == VK_F7 || vkey == VK_SPACE) && down)
|
||||
{
|
||||
// Manually generate an F7 event into the key bindings or terminal.
|
||||
// This is required as part of GH#638.
|
||||
// Or do so for alt+space; only send to terminal when explicitly unbound
|
||||
// That is part of #GH7125
|
||||
auto bindings{ _settings.KeyBindings() };
|
||||
bool isUnbound = false;
|
||||
const KeyChord kc = {
|
||||
modifiers.IsCtrlPressed(),
|
||||
modifiers.IsAltPressed(),
|
||||
modifiers.IsShiftPressed(),
|
||||
modifiers.IsWinPressed(),
|
||||
gsl::narrow_cast<WORD>(vkey),
|
||||
0
|
||||
};
|
||||
|
||||
if (bindings)
|
||||
{
|
||||
handled = bindings.TryKeyChord({
|
||||
modifiers.IsCtrlPressed(),
|
||||
modifiers.IsAltPressed(),
|
||||
modifiers.IsShiftPressed(),
|
||||
modifiers.IsWinPressed(),
|
||||
VK_F7,
|
||||
0,
|
||||
});
|
||||
handled = bindings.TryKeyChord(kc);
|
||||
|
||||
if (!handled)
|
||||
{
|
||||
isUnbound = bindings.IsKeyChordExplicitlyUnbound(kc);
|
||||
}
|
||||
}
|
||||
|
||||
if (!handled)
|
||||
const bool sendToTerminal = vkey == VK_F7 || (vkey == VK_SPACE && isUnbound);
|
||||
|
||||
if (!handled && sendToTerminal)
|
||||
{
|
||||
// _TrySendKeyEvent pretends it didn't handle F7 for some unknown reason.
|
||||
(void)_TrySendKeyEvent(VK_F7, scanCode, modifiers, true);
|
||||
(void)_TrySendKeyEvent(gsl::narrow_cast<WORD>(vkey), scanCode, modifiers, true);
|
||||
// GH#6438: Note that we're _not_ sending the key up here - that'll
|
||||
// get passed through XAML to our KeyUp handler normally.
|
||||
handled = true;
|
||||
|
@ -1276,23 +1262,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
CATCH_LOG();
|
||||
}
|
||||
|
||||
void TermControl::_coreReceivedOutput(const IInspectable& /*sender*/,
|
||||
const IInspectable& /*args*/)
|
||||
{
|
||||
// Queue up a throttled UpdatePatternLocations call. In the future, we
|
||||
// should have the _updatePatternLocations ThrottledFunc internal to
|
||||
// ControlCore, and run on that object's dispatcher queue.
|
||||
//
|
||||
// We're not doing that quite yet, because the Core will eventually
|
||||
// be out-of-proc from the UI thread, and won't be able to just use
|
||||
// the UI thread as the dispatcher queue thread.
|
||||
//
|
||||
// THIS IS CALLED ON EVERY STRING OF TEXT OUTPUT TO THE TERMINAL. Think
|
||||
// twice before adding anything here.
|
||||
|
||||
_updatePatternLocations->Run();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Reset the font size of the terminal to its default size.
|
||||
// Arguments:
|
||||
|
@ -1330,8 +1299,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
_updateScrollBar->ModifyPending([](auto& update) {
|
||||
update.newValue.reset();
|
||||
});
|
||||
|
||||
_updatePatternLocations->Run();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -1665,7 +1632,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
update.newValue = args.ViewTop();
|
||||
|
||||
_updateScrollBar->Run(update);
|
||||
_updatePatternLocations->Run();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -1673,10 +1639,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// to be where the current cursor position is.
|
||||
// Arguments:
|
||||
// - N/A
|
||||
void TermControl::_CursorPositionChanged(const IInspectable& /*sender*/,
|
||||
const IInspectable& /*args*/)
|
||||
winrt::fire_and_forget TermControl::_CursorPositionChanged(const IInspectable& /*sender*/,
|
||||
const IInspectable& /*args*/)
|
||||
{
|
||||
_tsfTryRedrawCanvas->Run();
|
||||
// Prior to GH#10187, this fired a trailing throttled func to update the
|
||||
// TSF canvas only every 100ms. Now, the throttling occurs on the
|
||||
// ControlCore side. If we're told to update the cursor position, we can
|
||||
// just go ahead and do it.
|
||||
// This can come in off the COM thread - hop back to the UI thread.
|
||||
auto weakThis{ get_weak() };
|
||||
co_await resume_foreground(Dispatcher());
|
||||
if (auto control{ weakThis.get() }; !control->_IsClosing())
|
||||
{
|
||||
control->TSFInputControl().TryRedrawCanvas();
|
||||
}
|
||||
}
|
||||
|
||||
hstring TermControl::Title()
|
||||
|
@ -1730,8 +1706,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
{
|
||||
_closing = true;
|
||||
|
||||
_core.ReceivedOutput(_coreOutputEventToken);
|
||||
_RestorePointerCursorHandlers(*this, nullptr);
|
||||
|
||||
// Disconnect the TSF input control so it doesn't receive EditContext events.
|
||||
TSFInputControl().Close();
|
||||
_autoScrollTimer.Stop();
|
||||
|
|
|
@ -153,8 +153,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
bool _focused{ false };
|
||||
bool _initializedTerminal{ false };
|
||||
|
||||
std::shared_ptr<ThrottledFuncTrailing<>> _tsfTryRedrawCanvas;
|
||||
std::shared_ptr<ThrottledFuncTrailing<>> _updatePatternLocations;
|
||||
std::shared_ptr<ThrottledFuncLeading> _playWarningBell;
|
||||
|
||||
struct ScrollBarUpdate
|
||||
|
@ -164,7 +162,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
double newMinimum;
|
||||
double newViewportSize;
|
||||
};
|
||||
|
||||
std::shared_ptr<ThrottledFuncTrailing<ScrollBarUpdate>> _updateScrollBar;
|
||||
|
||||
bool _isInternalScrollBarUpdate;
|
||||
|
||||
// Auto scroll occurs when user, while selecting, drags cursor outside
|
||||
|
@ -181,8 +181,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
std::optional<Windows::UI::Xaml::DispatcherTimer> _cursorTimer;
|
||||
std::optional<Windows::UI::Xaml::DispatcherTimer> _blinkTimer;
|
||||
|
||||
event_token _coreOutputEventToken;
|
||||
|
||||
winrt::Windows::UI::Xaml::Controls::SwapChainPanel::LayoutUpdated_revoker _layoutUpdatedRevoker;
|
||||
|
||||
inline bool _IsClosing() const noexcept
|
||||
|
@ -233,7 +231,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
void _TerminalTabColorChanged(const std::optional<til::color> color);
|
||||
|
||||
void _ScrollPositionChanged(const IInspectable& sender, const Control::ScrollPositionChangedArgs& args);
|
||||
void _CursorPositionChanged(const IInspectable& sender, const IInspectable& args);
|
||||
winrt::fire_and_forget _CursorPositionChanged(const IInspectable& sender, const IInspectable& args);
|
||||
|
||||
bool _CapturePointer(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e);
|
||||
bool _ReleasePointerCapture(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e);
|
||||
|
@ -265,7 +263,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
const int fontHeight,
|
||||
const bool isInitialChange);
|
||||
winrt::fire_and_forget _coreTransparencyChanged(IInspectable sender, Control::TransparencyChangedEventArgs args);
|
||||
void _coreReceivedOutput(const IInspectable& sender, const IInspectable& args);
|
||||
void _coreRaisedNotice(const IInspectable& s, const Control::NoticeEventArgs& args);
|
||||
void _coreWarningBell(const IInspectable& sender, const IInspectable& args);
|
||||
};
|
||||
|
|
|
@ -594,14 +594,6 @@ bool Terminal::SendKeyEvent(const WORD vkey,
|
|||
|
||||
const auto isAltOnlyPressed = states.IsAltPressed() && !states.IsCtrlPressed();
|
||||
|
||||
// DON'T manually handle Alt+Space - the system will use this to bring up
|
||||
// the system menu for restore, min/maximize, size, move, close.
|
||||
// (This doesn't apply to Ctrl+Alt+Space.)
|
||||
if (isAltOnlyPressed && vkey == VK_SPACE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// By default Windows treats Ctrl+Alt as an alias for AltGr.
|
||||
// When the altGrAliasing setting is set to false, this behaviour should be disabled.
|
||||
//
|
||||
|
@ -672,13 +664,6 @@ bool Terminal::SendMouseEvent(const COORD viewportPos, const unsigned int uiButt
|
|||
// - false otherwise.
|
||||
bool Terminal::SendCharEvent(const wchar_t ch, const WORD scanCode, const ControlKeyStates states)
|
||||
{
|
||||
// DON'T manually handle Alt+Space - the system will use this to bring up
|
||||
// the system menu for restore, min/maximize, size, move, close.
|
||||
if (ch == L' ' && states.IsAltPressed() && !states.IsCtrlPressed())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto vkey = _TakeVirtualKeyFromLastKeyEvent(scanCode);
|
||||
if (vkey == 0 && scanCode != 0)
|
||||
{
|
||||
|
|
|
@ -16,7 +16,7 @@ try
|
|||
_WriteBuffer(stringView);
|
||||
return true;
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
bool Terminal::ExecuteChar(wchar_t wch) noexcept
|
||||
try
|
||||
|
@ -24,7 +24,7 @@ try
|
|||
_WriteBuffer({ &wch, 1 });
|
||||
return true;
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
TextAttribute Terminal::GetTextAttributes() const noexcept
|
||||
{
|
||||
|
@ -54,7 +54,7 @@ try
|
|||
|
||||
return true;
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
COORD Terminal::GetCursorPosition() noexcept
|
||||
{
|
||||
|
@ -75,7 +75,7 @@ try
|
|||
_buffer->GetCursor().SetColor(color);
|
||||
return true;
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
// Method Description:
|
||||
// - Moves the cursor down one line, and possibly also to the leftmost column.
|
||||
|
@ -101,7 +101,7 @@ try
|
|||
|
||||
return true;
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
// Method Description:
|
||||
// - deletes count characters starting from the cursor's current position
|
||||
|
@ -150,7 +150,7 @@ try
|
|||
|
||||
return true;
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
// Method Description:
|
||||
// - Inserts count spaces starting from the cursor's current position, moving over the existing text
|
||||
|
@ -205,7 +205,7 @@ try
|
|||
|
||||
return true;
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
bool Terminal::EraseCharacters(const size_t numChars) noexcept
|
||||
try
|
||||
|
@ -218,7 +218,7 @@ try
|
|||
_buffer->Write(eraseIter, absoluteCursorPos);
|
||||
return true;
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
// Method description:
|
||||
// - erases a line of text, either from
|
||||
|
@ -264,7 +264,7 @@ try
|
|||
_buffer->Write(eraseIter, startPos, false);
|
||||
return true;
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
// Method description:
|
||||
// - erases text in the buffer in two ways depending on erase type
|
||||
|
@ -348,7 +348,7 @@ try
|
|||
|
||||
return true;
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
bool Terminal::WarningBell() noexcept
|
||||
try
|
||||
|
@ -356,7 +356,7 @@ try
|
|||
_pfnWarningBell();
|
||||
return true;
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
bool Terminal::SetWindowTitle(std::wstring_view title) noexcept
|
||||
try
|
||||
|
@ -368,7 +368,7 @@ try
|
|||
}
|
||||
return true;
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
// Method Description:
|
||||
// - Updates the value in the colortable at index tableIndex to the new color
|
||||
|
@ -387,7 +387,7 @@ try
|
|||
_buffer->GetRenderTarget().TriggerRedrawAll();
|
||||
return true;
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
// Method Description:
|
||||
// - Sets the cursor style to the given style.
|
||||
|
@ -457,7 +457,7 @@ try
|
|||
_buffer->GetRenderTarget().TriggerRedrawAll();
|
||||
return true;
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
// Method Description:
|
||||
// - Updates the default background color from a COLORREF, format 0x00BBGGRR.
|
||||
|
@ -475,7 +475,7 @@ try
|
|||
_buffer->GetRenderTarget().TriggerRedrawAll();
|
||||
return true;
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
til::color Terminal::GetDefaultBackground() const noexcept
|
||||
{
|
||||
|
@ -509,7 +509,7 @@ try
|
|||
_buffer->GetRenderTarget().TriggerRedrawAll();
|
||||
return true;
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
bool Terminal::EnableVT200MouseMode(const bool enabled) noexcept
|
||||
{
|
||||
|
@ -591,7 +591,7 @@ try
|
|||
|
||||
return true;
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
// Method Description:
|
||||
// - Updates the buffer's current text attributes to start a hyperlink
|
||||
|
|
|
@ -158,7 +158,6 @@
|
|||
|
||||
<!-- Converters & Misc. -->
|
||||
<model:IconPathConverter x:Key="IconSourceConverter" />
|
||||
<local:InvertedBooleanToVisibilityConverter x:Key="InvertedBooleanToVisibilityConverter" />
|
||||
<SolidColorBrush x:Key="ActionContainerBackgroundEditing"
|
||||
Color="{ThemeResource SystemListMediumColor}" />
|
||||
<SolidColorBrush x:Key="ActionContainerBackground"
|
||||
|
@ -195,7 +194,7 @@
|
|||
<TextBlock Grid.Column="0"
|
||||
Style="{StaticResource KeyBindingNameTextBlockStyle}"
|
||||
Text="{x:Bind Name, Mode=OneWay}"
|
||||
Visibility="{x:Bind IsInEditMode, Mode=OneWay, Converter={StaticResource InvertedBooleanToVisibilityConverter}}" />
|
||||
Visibility="{x:Bind local:Converters.InvertedBooleanToVisibility(IsInEditMode), Mode=OneWay}" />
|
||||
|
||||
<!-- Edit Mode: Action Combo-box -->
|
||||
<ComboBox x:Uid="Actions_ActionComboBox"
|
||||
|
@ -211,7 +210,7 @@
|
|||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Style="{ThemeResource KeyChordBorderStyle}"
|
||||
Visibility="{x:Bind IsInEditMode, Mode=OneWay, Converter={StaticResource InvertedBooleanToVisibilityConverter}}">
|
||||
Visibility="{x:Bind local:Converters.InvertedBooleanToVisibility(IsInEditMode), Mode=OneWay}">
|
||||
|
||||
<TextBlock FontSize="14"
|
||||
Style="{ThemeResource KeyChordTextBlockStyle}"
|
||||
|
@ -303,7 +302,7 @@
|
|||
Margin="8,0,0,0"
|
||||
AutomationProperties.Name="{x:Bind DeleteButtonName}"
|
||||
Style="{StaticResource EditButtonStyle}"
|
||||
Visibility="{x:Bind IsNewlyAdded, Mode=OneWay, Converter={StaticResource InvertedBooleanToVisibilityConverter}}">
|
||||
Visibility="{x:Bind local:Converters.InvertedBooleanToVisibility(IsNewlyAdded), Mode=OneWay}">
|
||||
<Button.Content>
|
||||
<FontIcon FontSize="{StaticResource EditButtonIconSize}"
|
||||
Glyph="" />
|
||||
|
|
|
@ -51,6 +51,19 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
public:
|
||||
AppearanceViewModel(const Model::AppearanceConfig& appearance);
|
||||
|
||||
void SetFontWeightFromDouble(double fontWeight)
|
||||
{
|
||||
FontWeight(winrt::Microsoft::Terminal::Settings::Editor::Converters::DoubleToFontWeight(fontWeight));
|
||||
}
|
||||
void SetBackgroundImageOpacityFromPercentageValue(double percentageValue)
|
||||
{
|
||||
BackgroundImageOpacity(winrt::Microsoft::Terminal::Settings::Editor::Converters::PercentageValueToPercentage(percentageValue));
|
||||
}
|
||||
void SetBackgroundImagePath(winrt::hstring path)
|
||||
{
|
||||
BackgroundImagePath(path);
|
||||
}
|
||||
|
||||
// background image
|
||||
bool UseDesktopBGImage();
|
||||
void UseDesktopBGImage(const bool useDesktop);
|
||||
|
|
|
@ -23,6 +23,10 @@ namespace Microsoft.Terminal.Settings.Editor
|
|||
{
|
||||
Boolean IsDefault;
|
||||
|
||||
void SetFontWeightFromDouble(Double fontWeight);
|
||||
void SetBackgroundImageOpacityFromPercentageValue(Double percentageValue);
|
||||
void SetBackgroundImagePath(String path);
|
||||
|
||||
Boolean UseDesktopBGImage;
|
||||
Boolean BackgroundImageSettingsVisible { get; };
|
||||
|
||||
|
@ -68,5 +72,6 @@ namespace Microsoft.Terminal.Settings.Editor
|
|||
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> FontWeightList { get; };
|
||||
|
||||
IInspectable CurrentFontFace { get; };
|
||||
Windows.UI.Xaml.Controls.Slider BIOpacitySlider { get; };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,16 +34,6 @@
|
|||
<TextBlock FontFamily="{x:Bind Name}"
|
||||
Text="{x:Bind LocalizedName}" />
|
||||
</DataTemplate>
|
||||
|
||||
<local:ColorToBrushConverter x:Key="ColorToBrushConverter" />
|
||||
<local:PercentageConverter x:Key="PercentageConverter" />
|
||||
<local:PercentageSignConverter x:Key="PercentageSignConverter" />
|
||||
<local:FontWeightConverter x:Key="FontWeightConverter" />
|
||||
<local:InvertedBooleanToVisibilityConverter x:Key="InvertedBooleanToVisibilityConverter" />
|
||||
<local:StringIsEmptyConverter x:Key="StringIsEmptyConverter" />
|
||||
<local:PaddingConverter x:Key="PaddingConverter" />
|
||||
<local:StringIsNotDesktopConverter x:Key="StringIsNotDesktopConverter" />
|
||||
<local:DesktopWallpaperToEmptyStringConverter x:Key="DesktopWallpaperToEmptyStringConverter" />
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
|
||||
|
@ -87,7 +77,7 @@
|
|||
SelectedItem="{x:Bind CurrentFontFace, Mode=OneWay}"
|
||||
SelectionChanged="FontFace_SelectionChanged"
|
||||
Style="{StaticResource ComboBoxSettingStyle}"
|
||||
Visibility="{x:Bind ShowAllFonts, Mode=OneWay, Converter={StaticResource InvertedBooleanToVisibilityConverter}}" />
|
||||
Visibility="{x:Bind local:Converters.InvertedBooleanToVisibility(ShowAllFonts), Mode=OneWay}" />
|
||||
<ComboBox ItemTemplate="{StaticResource FontFaceComboBoxItemTemplate}"
|
||||
ItemsSource="{x:Bind SourceProfile.CompleteFontList, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind CurrentFontFace, Mode=OneWay}"
|
||||
|
@ -144,7 +134,7 @@
|
|||
Minimum="0"
|
||||
TickFrequency="50"
|
||||
TickPlacement="Outside"
|
||||
Value="{x:Bind Appearance.FontWeight, Converter={StaticResource FontWeightConverter}, Mode=TwoWay}" />
|
||||
Value="{x:Bind local:Converters.FontWeightToDouble(Appearance.FontWeight), BindBack=Appearance.SetFontWeightFromDouble, Mode=TwoWay}" />
|
||||
<TextBlock Grid.Column="1"
|
||||
Margin="10,0,0,0"
|
||||
Style="{StaticResource SliderValueLabelStyle}"
|
||||
|
@ -215,12 +205,12 @@
|
|||
SettingOverrideSource="{x:Bind Appearance.BackgroundImagePathOverrideSource, Mode=OneWay}">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox IsEnabled="{x:Bind Appearance.BackgroundImagePath, Mode=OneWay, Converter={StaticResource StringIsNotDesktopConverter}}"
|
||||
<TextBox IsEnabled="{x:Bind local:Converters.StringsAreNotEqual('desktopWallpaper', Appearance.BackgroundImagePath), Mode=OneWay}"
|
||||
Style="{StaticResource TextBoxSettingStyle}"
|
||||
Text="{x:Bind Appearance.BackgroundImagePath, Mode=TwoWay, Converter={StaticResource DesktopWallpaperToEmptyStringConverter}}" />
|
||||
Text="{x:Bind local:Converters.StringFallBackToEmptyString('desktopWallpaper', Appearance.BackgroundImagePath), Mode=TwoWay, BindBack=Appearance.SetBackgroundImagePath}" />
|
||||
<Button x:Uid="Profile_BackgroundImageBrowse"
|
||||
Click="BackgroundImage_Click"
|
||||
IsEnabled="{x:Bind Appearance.BackgroundImagePath, Mode=OneWay, Converter={StaticResource StringIsNotDesktopConverter}}"
|
||||
IsEnabled="{x:Bind local:Converters.StringsAreNotEqual('desktopWallpaper', Appearance.BackgroundImagePath), Mode=OneWay}"
|
||||
Style="{StaticResource BrowseButtonStyle}" />
|
||||
</StackPanel>
|
||||
<CheckBox x:Name="UseDesktopImageCheckBox"
|
||||
|
@ -431,10 +421,10 @@
|
|||
</Grid.ColumnDefinitions>
|
||||
<Slider x:Name="BIOpacitySlider"
|
||||
Grid.Column="0"
|
||||
Value="{x:Bind Appearance.BackgroundImageOpacity, Converter={StaticResource PercentageConverter}, Mode=TwoWay}" />
|
||||
Value="{x:Bind local:Converters.PercentageToPercentageValue(Appearance.BackgroundImageOpacity), BindBack=Appearance.SetBackgroundImageOpacityFromPercentageValue, Mode=TwoWay}" />
|
||||
<TextBlock Grid.Column="1"
|
||||
Style="{StaticResource SliderValueLabelStyle}"
|
||||
Text="{Binding ElementName=BIOpacitySlider, Path=Value, Mode=OneWay, Converter={StaticResource PercentageSignConverter}}" />
|
||||
Text="{x:Bind local:Converters.AppendPercentageSign(BIOpacitySlider.Value), Mode=OneWay}" />
|
||||
</Grid>
|
||||
</local:SettingContainer>
|
||||
</StackPanel>
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "ColorLightenConverter.h"
|
||||
#include "ColorLightenConverter.g.cpp"
|
||||
|
||||
using namespace winrt::Windows;
|
||||
using namespace winrt::Windows::UI;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
using namespace winrt::Windows::UI::Text;
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
Foundation::IInspectable ColorLightenConverter::Convert(Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
|
||||
Foundation::IInspectable const& /* parameter */,
|
||||
hstring const& /* language */)
|
||||
{
|
||||
auto original = winrt::unbox_value_or<Color>(value, Color{ 255, 0, 0, 0 });
|
||||
auto result = original;
|
||||
result.A = 128; // halfway transparent
|
||||
return winrt::box_value(result);
|
||||
}
|
||||
|
||||
Foundation::IInspectable ColorLightenConverter::ConvertBack(Foundation::IInspectable const& /*value*/,
|
||||
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
|
||||
Foundation::IInspectable const& /*parameter*/,
|
||||
hstring const& /* language */)
|
||||
{
|
||||
throw hresult_not_implemented();
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ColorLightenConverter.g.h"
|
||||
#include "../inc/cppwinrt_utils.h"
|
||||
|
||||
DECLARE_CONVERTER(winrt::Microsoft::Terminal::Settings::Editor, ColorLightenConverter);
|
|
@ -60,7 +60,7 @@
|
|||
<DataTemplate x:Key="ColorTableEntryTemplate"
|
||||
x:DataType="local:ColorTableEntry">
|
||||
<Button AutomationProperties.Name="{x:Bind Name}"
|
||||
Background="{x:Bind Color, Converter={StaticResource ColorToBrushConverter}, Mode=OneWay}"
|
||||
Background="{x:Bind local:Converters.ColorToBrush(Color), Mode=OneWay}"
|
||||
Style="{StaticResource ColorButtonStyle}"
|
||||
ToolTipService.ToolTip="{x:Bind Name}">
|
||||
<Button.Resources>
|
||||
|
@ -69,11 +69,11 @@
|
|||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<SolidColorBrush x:Key="ButtonBackgroundPointerOver"
|
||||
Color="{x:Bind Color, Converter={StaticResource ColorLightenConverter}, Mode=OneWay}" />
|
||||
Color="{x:Bind local:Converters.LightenColor(Color), Mode=OneWay}" />
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<SolidColorBrush x:Key="ButtonBackgroundPointerOver"
|
||||
Color="{x:Bind Color, Converter={StaticResource ColorLightenConverter}, Mode=OneWay}" />
|
||||
Color="{x:Bind local:Converters.LightenColor(Color), Mode=OneWay}" />
|
||||
</ResourceDictionary>
|
||||
<!-- No High contrast dictionary, let's just leave that unchanged. -->
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
@ -90,11 +90,6 @@
|
|||
</Button>
|
||||
</DataTemplate>
|
||||
|
||||
<local:ColorToBrushConverter x:Key="ColorToBrushConverter" />
|
||||
<local:ColorToHexConverter x:Key="ColorToHexConverter" />
|
||||
<local:InvertedBooleanToVisibilityConverter x:Key="InvertedBooleanToVisibilityConverter" />
|
||||
<local:ColorLightenConverter x:Key="ColorLightenConverter" />
|
||||
|
||||
</ResourceDictionary>
|
||||
</Page.Resources>
|
||||
|
||||
|
@ -106,7 +101,7 @@
|
|||
<StackPanel Orientation="Horizontal">
|
||||
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Visibility="{x:Bind IsRenaming, Converter={StaticResource InvertedBooleanToVisibilityConverter}, Mode=OneWay}">
|
||||
Visibility="{x:Bind local:Converters.InvertedBooleanToVisibility(IsRenaming), Mode=OneWay}">
|
||||
<!-- Select a color scheme -->
|
||||
<ComboBox x:Name="ColorSchemeComboBox"
|
||||
ItemsSource="{x:Bind ColorSchemeList, Mode=OneWay}"
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "ColorToBrushConverter.h"
|
||||
#include "ColorToBrushConverter.g.cpp"
|
||||
|
||||
using namespace winrt::Windows;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
Foundation::IInspectable ColorToBrushConverter::Convert(Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
|
||||
Foundation::IInspectable const& /* parameter */,
|
||||
hstring const& /* language */)
|
||||
{
|
||||
return winrt::box_value(Windows::UI::Xaml::Media::SolidColorBrush(winrt::unbox_value<Windows::UI::Color>(value)));
|
||||
}
|
||||
|
||||
Foundation::IInspectable ColorToBrushConverter::ConvertBack(Foundation::IInspectable const& /*value*/,
|
||||
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
|
||||
Foundation::IInspectable const& /*parameter*/,
|
||||
hstring const& /* language */)
|
||||
{
|
||||
throw hresult_not_implemented();
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ColorToBrushConverter.g.h"
|
||||
#include "Utils.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
struct ColorToBrushConverter : ColorToBrushConverterT<ColorToBrushConverter>
|
||||
{
|
||||
ColorToBrushConverter() = default;
|
||||
|
||||
Windows::Foundation::IInspectable Convert(Windows::Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& targetType,
|
||||
Windows::Foundation::IInspectable const& parameter,
|
||||
hstring const& language);
|
||||
|
||||
Windows::Foundation::IInspectable ConvertBack(Windows::Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& targetType,
|
||||
Windows::Foundation::IInspectable const& parameter,
|
||||
hstring const& language);
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(ColorToBrushConverter);
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "ColorToHexConverter.h"
|
||||
#include "ColorToHexConverter.g.cpp"
|
||||
|
||||
using namespace winrt::Windows;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
Foundation::IInspectable ColorToHexConverter::Convert(Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
|
||||
Foundation::IInspectable const& /* parameter */,
|
||||
hstring const& /* language */)
|
||||
{
|
||||
til::color color{ winrt::unbox_value<winrt::Windows::UI::Color>(value) };
|
||||
auto hex = winrt::to_hstring(color.ToHexString().data());
|
||||
return winrt::box_value(hex);
|
||||
}
|
||||
|
||||
Foundation::IInspectable ColorToHexConverter::ConvertBack(Foundation::IInspectable const& /*value*/,
|
||||
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
|
||||
Foundation::IInspectable const& /*parameter*/,
|
||||
hstring const& /* language */)
|
||||
{
|
||||
throw hresult_not_implemented();
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ColorToHexConverter.g.h"
|
||||
#include "Utils.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
struct ColorToHexConverter : ColorToHexConverterT<ColorToHexConverter>
|
||||
{
|
||||
ColorToHexConverter() = default;
|
||||
|
||||
Windows::Foundation::IInspectable Convert(Windows::Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& targetType,
|
||||
Windows::Foundation::IInspectable const& parameter,
|
||||
hstring const& language);
|
||||
|
||||
Windows::Foundation::IInspectable ConvertBack(Windows::Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& targetType,
|
||||
Windows::Foundation::IInspectable const& parameter,
|
||||
hstring const& language);
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(ColorToHexConverter);
|
||||
}
|
106
src/cascadia/TerminalSettingsEditor/Converters.cpp
Normal file
106
src/cascadia/TerminalSettingsEditor/Converters.cpp
Normal file
|
@ -0,0 +1,106 @@
|
|||
#include "pch.h"
|
||||
#include "Converters.h"
|
||||
#if __has_include("Converters.g.cpp")
|
||||
#include "Converters.g.cpp"
|
||||
#endif
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
winrt::hstring Converters::AppendPercentageSign(double value)
|
||||
{
|
||||
const auto number{ value };
|
||||
return to_hstring((int)number) + L"%";
|
||||
}
|
||||
|
||||
winrt::Windows::UI::Xaml::Media::SolidColorBrush Converters::ColorToBrush(winrt::Windows::UI::Color color)
|
||||
{
|
||||
return Windows::UI::Xaml::Media::SolidColorBrush(color);
|
||||
}
|
||||
|
||||
winrt::Windows::UI::Text::FontWeight Converters::DoubleToFontWeight(double value)
|
||||
{
|
||||
return winrt::Windows::UI::Text::FontWeight{ base::ClampedNumeric<uint16_t>(value) };
|
||||
}
|
||||
|
||||
double Converters::FontWeightToDouble(winrt::Windows::UI::Text::FontWeight fontWeight)
|
||||
{
|
||||
return fontWeight.Weight;
|
||||
}
|
||||
|
||||
bool Converters::InvertBoolean(bool value)
|
||||
{
|
||||
return !value;
|
||||
}
|
||||
|
||||
winrt::Windows::UI::Xaml::Visibility Converters::InvertedBooleanToVisibility(bool value)
|
||||
{
|
||||
return value ? winrt::Windows::UI::Xaml::Visibility::Collapsed : winrt::Windows::UI::Xaml::Visibility::Visible;
|
||||
}
|
||||
|
||||
winrt::Windows::UI::Color Converters::LightenColor(winrt::Windows::UI::Color color)
|
||||
{
|
||||
color.A = 128; // halfway transparent
|
||||
return color;
|
||||
}
|
||||
|
||||
double Converters::MaxValueFromPaddingString(winrt::hstring paddingString)
|
||||
{
|
||||
const wchar_t singleCharDelim = L',';
|
||||
std::wstringstream tokenStream(paddingString.c_str());
|
||||
std::wstring token;
|
||||
double maxVal = 0;
|
||||
size_t* idx = nullptr;
|
||||
|
||||
// Get padding values till we run out of delimiter separated values in the stream
|
||||
// Non-numeral values detected will default to 0
|
||||
// std::getline will not throw exception unless flags are set on the wstringstream
|
||||
// std::stod will throw invalid_argument exception if the input is an invalid double value
|
||||
// std::stod will throw out_of_range exception if the input value is more than DBL_MAX
|
||||
try
|
||||
{
|
||||
while (std::getline(tokenStream, token, singleCharDelim))
|
||||
{
|
||||
// std::stod internally calls wcstod which handles whitespace prefix (which is ignored)
|
||||
// & stops the scan when first char outside the range of radix is encountered
|
||||
// We'll be permissive till the extent that stod function allows us to be by default
|
||||
// Ex. a value like 100.3#535w2 will be read as 100.3, but ;df25 will fail
|
||||
const auto curVal = std::stod(token, idx);
|
||||
if (curVal > maxVal)
|
||||
{
|
||||
maxVal = curVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// If something goes wrong, even if due to a single bad padding value, we'll return default 0 padding
|
||||
maxVal = 0;
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
}
|
||||
|
||||
return maxVal;
|
||||
}
|
||||
|
||||
int Converters::PercentageToPercentageValue(double value)
|
||||
{
|
||||
return base::ClampMul(value, 100u);
|
||||
}
|
||||
|
||||
double Converters::PercentageValueToPercentage(double value)
|
||||
{
|
||||
return base::ClampDiv<double, double>(value, 100);
|
||||
}
|
||||
|
||||
bool Converters::StringsAreNotEqual(winrt::hstring expected, winrt::hstring actual)
|
||||
{
|
||||
return expected != actual;
|
||||
}
|
||||
winrt::Windows::UI::Xaml::Visibility Converters::StringNotEmptyToVisibility(winrt::hstring value)
|
||||
{
|
||||
return value.empty() ? winrt::Windows::UI::Xaml::Visibility::Collapsed : winrt::Windows::UI::Xaml::Visibility::Visible;
|
||||
}
|
||||
winrt::hstring Converters::StringFallBackToEmptyString(winrt::hstring expected, winrt::hstring actual)
|
||||
{
|
||||
return expected == actual ? expected : L"";
|
||||
}
|
||||
}
|
33
src/cascadia/TerminalSettingsEditor/Converters.h
Normal file
33
src/cascadia/TerminalSettingsEditor/Converters.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Converters.g.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
struct Converters : ConvertersT<Converters>
|
||||
{
|
||||
static winrt::hstring AppendPercentageSign(double value);
|
||||
static winrt::Windows::UI::Text::FontWeight DoubleToFontWeight(double value);
|
||||
static winrt::Windows::UI::Xaml::Media::SolidColorBrush ColorToBrush(winrt::Windows::UI::Color color);
|
||||
static double FontWeightToDouble(winrt::Windows::UI::Text::FontWeight fontWeight);
|
||||
static bool InvertBoolean(bool value);
|
||||
static winrt::Windows::UI::Xaml::Visibility InvertedBooleanToVisibility(bool value);
|
||||
static winrt::Windows::UI::Color LightenColor(winrt::Windows::UI::Color color);
|
||||
static double MaxValueFromPaddingString(winrt::hstring paddingString);
|
||||
static int PercentageToPercentageValue(double value);
|
||||
static double PercentageValueToPercentage(double value);
|
||||
static bool StringsAreNotEqual(winrt::hstring expected, winrt::hstring actual);
|
||||
static winrt::Windows::UI::Xaml::Visibility StringNotEmptyToVisibility(winrt::hstring value);
|
||||
static winrt::hstring StringFallBackToEmptyString(winrt::hstring expected, winrt::hstring actual);
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
|
||||
{
|
||||
struct Converters : ConvertersT<Converters, implementation::Converters>
|
||||
{
|
||||
};
|
||||
}
|
|
@ -4,63 +4,22 @@
|
|||
namespace Microsoft.Terminal.Settings.Editor
|
||||
{
|
||||
|
||||
runtimeclass ColorLightenConverter : [default] Windows.UI.Xaml.Data.IValueConverter
|
||||
[bindable]
|
||||
[default_interface] static runtimeclass Converters
|
||||
{
|
||||
ColorLightenConverter();
|
||||
};
|
||||
|
||||
runtimeclass FontWeightConverter : [default] Windows.UI.Xaml.Data.IValueConverter
|
||||
{
|
||||
FontWeightConverter();
|
||||
};
|
||||
|
||||
runtimeclass InvertedBooleanConverter : [default] Windows.UI.Xaml.Data.IValueConverter
|
||||
{
|
||||
InvertedBooleanConverter();
|
||||
};
|
||||
|
||||
runtimeclass InvertedBooleanToVisibilityConverter : [default] Windows.UI.Xaml.Data.IValueConverter
|
||||
{
|
||||
InvertedBooleanToVisibilityConverter();
|
||||
};
|
||||
|
||||
runtimeclass ColorToBrushConverter : [default] Windows.UI.Xaml.Data.IValueConverter
|
||||
{
|
||||
ColorToBrushConverter();
|
||||
};
|
||||
|
||||
runtimeclass ColorToHexConverter : [default] Windows.UI.Xaml.Data.IValueConverter
|
||||
{
|
||||
ColorToHexConverter();
|
||||
};
|
||||
|
||||
runtimeclass PercentageConverter : [default] Windows.UI.Xaml.Data.IValueConverter
|
||||
{
|
||||
PercentageConverter();
|
||||
};
|
||||
|
||||
runtimeclass PercentageSignConverter : [default] Windows.UI.Xaml.Data.IValueConverter
|
||||
{
|
||||
PercentageSignConverter();
|
||||
};
|
||||
|
||||
runtimeclass StringIsEmptyConverter : [default] Windows.UI.Xaml.Data.IValueConverter
|
||||
{
|
||||
StringIsEmptyConverter();
|
||||
};
|
||||
|
||||
runtimeclass PaddingConverter : [default] Windows.UI.Xaml.Data.IValueConverter
|
||||
{
|
||||
PaddingConverter();
|
||||
};
|
||||
|
||||
runtimeclass StringIsNotDesktopConverter : [default] Windows.UI.Xaml.Data.IValueConverter
|
||||
{
|
||||
StringIsNotDesktopConverter();
|
||||
};
|
||||
|
||||
runtimeclass DesktopWallpaperToEmptyStringConverter : [default] Windows.UI.Xaml.Data.IValueConverter
|
||||
{
|
||||
DesktopWallpaperToEmptyStringConverter();
|
||||
};
|
||||
static String AppendPercentageSign(Double value);
|
||||
static Windows.UI.Text.FontWeight DoubleToFontWeight(Double value);
|
||||
static Windows.UI.Xaml.Media.SolidColorBrush ColorToBrush(Windows.UI.Color color);
|
||||
static Double FontWeightToDouble(Windows.UI.Text.FontWeight fontWeight);
|
||||
static Boolean InvertBoolean(Boolean value);
|
||||
static Windows.UI.Xaml.Visibility InvertedBooleanToVisibility(Boolean value);
|
||||
static Windows.UI.Color LightenColor(Windows.UI.Color color);
|
||||
static Double MaxValueFromPaddingString(String paddingString);
|
||||
static Int32 PercentageToPercentageValue(Double value);
|
||||
static Double PercentageValueToPercentage(Double value);
|
||||
static Boolean StringsAreNotEqual(String expected, String actual);
|
||||
static Windows.UI.Xaml.Visibility StringNotEmptyToVisibility(String value);
|
||||
static String StringFallBackToEmptyString(String expected, String actual);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "FontWeightConverter.h"
|
||||
#include "FontWeightConverter.g.cpp"
|
||||
|
||||
using namespace winrt::Windows;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
using namespace winrt::Windows::UI::Text;
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
Foundation::IInspectable FontWeightConverter::Convert(Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
|
||||
Foundation::IInspectable const& /* parameter */,
|
||||
hstring const& /* language */)
|
||||
{
|
||||
const auto weight{ winrt::unbox_value<FontWeight>(value) };
|
||||
return winrt::box_value<double>(weight.Weight);
|
||||
}
|
||||
|
||||
Foundation::IInspectable FontWeightConverter::ConvertBack(Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
|
||||
Foundation::IInspectable const& /*parameter*/,
|
||||
hstring const& /* language */)
|
||||
{
|
||||
const auto sliderVal{ winrt::unbox_value<double>(value) };
|
||||
FontWeight weight{ base::ClampedNumeric<uint16_t>(sliderVal) };
|
||||
return winrt::box_value<FontWeight>(weight);
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "FontWeightConverter.g.h"
|
||||
#include "Utils.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
struct FontWeightConverter : FontWeightConverterT<FontWeightConverter>
|
||||
{
|
||||
FontWeightConverter() = default;
|
||||
|
||||
Windows::Foundation::IInspectable Convert(Windows::Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& targetType,
|
||||
Windows::Foundation::IInspectable const& parameter,
|
||||
hstring const& language);
|
||||
|
||||
Windows::Foundation::IInspectable ConvertBack(Windows::Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& targetType,
|
||||
Windows::Foundation::IInspectable const& parameter,
|
||||
hstring const& language);
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(FontWeightConverter);
|
||||
}
|
|
@ -21,8 +21,6 @@
|
|||
x:DataType="local:EnumEntry">
|
||||
<RadioButton Content="{x:Bind EnumName, Mode=OneWay}" />
|
||||
</DataTemplate>
|
||||
|
||||
<local:InvertedBooleanConverter x:Key="InvertedBooleanConverter" />
|
||||
</ResourceDictionary>
|
||||
</Page.Resources>
|
||||
|
||||
|
@ -79,7 +77,7 @@
|
|||
<!-- Disable Animations -->
|
||||
<!-- NOTE: the UID is "DisablePaneAnimationsReversed" not "DisablePaneAnimations". See GH#9124 for more details. -->
|
||||
<local:SettingContainer x:Uid="Globals_DisableAnimationsReversed">
|
||||
<ToggleSwitch IsOn="{x:Bind State.Globals.DisableAnimations, Mode=TwoWay, Converter={StaticResource InvertedBooleanConverter}}" />
|
||||
<ToggleSwitch IsOn="{x:Bind local:Converters.InvertBoolean(State.Globals.DisableAnimations), BindBack=State.Globals.SetInvertedDisableAnimationsValue, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "InvertedBooleanConverter.h"
|
||||
#include "InvertedBooleanConverter.g.cpp"
|
||||
|
||||
using namespace winrt::Windows;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
Foundation::IInspectable InvertedBooleanConverter::Convert(Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
|
||||
Foundation::IInspectable const& /* parameter */,
|
||||
hstring const& /* language */)
|
||||
{
|
||||
return winrt::box_value(!winrt::unbox_value<bool>(value));
|
||||
}
|
||||
|
||||
Foundation::IInspectable InvertedBooleanConverter::ConvertBack(Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
|
||||
Foundation::IInspectable const& /*parameter*/,
|
||||
hstring const& /* language */)
|
||||
{
|
||||
return winrt::box_value(!winrt::unbox_value<bool>(value));
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "InvertedBooleanConverter.g.h"
|
||||
#include "../inc/cppwinrt_utils.h"
|
||||
|
||||
DECLARE_CONVERTER(winrt::Microsoft::Terminal::Settings::Editor, InvertedBooleanConverter);
|
|
@ -1,28 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "InvertedBooleanToVisibilityConverter.h"
|
||||
#include "InvertedBooleanToVisibilityConverter.g.cpp"
|
||||
|
||||
using namespace winrt::Windows;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
Foundation::IInspectable InvertedBooleanToVisibilityConverter::Convert(Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
|
||||
Foundation::IInspectable const& /* parameter */,
|
||||
hstring const& /* language */)
|
||||
{
|
||||
return winrt::box_value(winrt::unbox_value<bool>(value) ? Visibility::Collapsed : Visibility::Visible);
|
||||
}
|
||||
|
||||
Foundation::IInspectable InvertedBooleanToVisibilityConverter::ConvertBack(Foundation::IInspectable const& /*value*/,
|
||||
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
|
||||
Foundation::IInspectable const& /*parameter*/,
|
||||
hstring const& /* language */)
|
||||
{
|
||||
throw hresult_not_implemented();
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "InvertedBooleanToVisibilityConverter.g.h"
|
||||
#include "../inc/cppwinrt_utils.h"
|
||||
|
||||
DECLARE_CONVERTER(winrt::Microsoft::Terminal::Settings::Editor, InvertedBooleanToVisibilityConverter);
|
|
@ -42,41 +42,9 @@
|
|||
<ClInclude Include="AddProfile.h">
|
||||
<DependentUpon>AddProfile.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ColorToBrushConverter.h">
|
||||
<DependentUpon>Converters.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ColorLightenConverter.h">
|
||||
<DependentUpon>Converters.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ColorToHexConverter.h">
|
||||
<DependentUpon>Converters.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FontWeightConverter.h">
|
||||
<DependentUpon>Converters.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="InvertedBooleanConverter.h">
|
||||
<DependentUpon>Converters.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="InvertedBooleanToVisibilityConverter.h">
|
||||
<DependentUpon>Converters.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="KeyChordListener.h">
|
||||
<DependentUpon>KeyChordListener.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PercentageSignConverter.h">
|
||||
<DependentUpon>Converters.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="StringIsEmptyConverter.h">
|
||||
<DependentUpon>Converters.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PaddingConverter.h">
|
||||
<DependentUpon>Converters.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="StringIsNotDesktopConverter.h">
|
||||
<DependentUpon>Converters.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PercentageConverter.h">
|
||||
<ClInclude Include="Converters.h">
|
||||
<DependentUpon>Converters.idl</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="EnumEntry.h">
|
||||
<DependentUpon>EnumEntry.idl</DependentUpon>
|
||||
|
@ -91,6 +59,9 @@
|
|||
<ClInclude Include="Interaction.h">
|
||||
<DependentUpon>Interaction.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="KeyChordListener.h">
|
||||
<DependentUpon>KeyChordListener.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Launch.h">
|
||||
<DependentUpon>Launch.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
|
@ -171,41 +142,9 @@
|
|||
<ClCompile Include="AddProfile.cpp">
|
||||
<DependentUpon>AddProfile.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ColorToBrushConverter.cpp">
|
||||
<DependentUpon>Converters.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ColorLightenConverter.cpp">
|
||||
<DependentUpon>Converters.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ColorToHexConverter.cpp">
|
||||
<DependentUpon>Converters.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FontWeightConverter.cpp">
|
||||
<DependentUpon>Converters.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="InvertedBooleanConverter.cpp">
|
||||
<DependentUpon>Converters.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="InvertedBooleanToVisibilityConverter.cpp">
|
||||
<DependentUpon>Converters.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="KeyChordListener.cpp">
|
||||
<DependentUpon>KeyChordListener.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PercentageSignConverter.cpp">
|
||||
<DependentUpon>Converters.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="StringIsEmptyConverter.cpp">
|
||||
<DependentUpon>Converters.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PaddingConverter.cpp">
|
||||
<DependentUpon>Converters.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="StringIsNotDesktopConverter.cpp">
|
||||
<DependentUpon>Converters.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PercentageConverter.cpp">
|
||||
<ClCompile Include="Converters.cpp">
|
||||
<DependentUpon>Converters.idl</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GlobalAppearance.cpp">
|
||||
<DependentUpon>GlobalAppearance.xaml</DependentUpon>
|
||||
|
@ -217,6 +156,9 @@
|
|||
<ClCompile Include="Interaction.cpp">
|
||||
<DependentUpon>Interaction.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="KeyChordListener.cpp">
|
||||
<DependentUpon>KeyChordListener.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Launch.cpp">
|
||||
<DependentUpon>Launch.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
|
@ -339,7 +281,6 @@
|
|||
<Private>true</Private>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalSettingsModel\dll\Microsoft.Terminal.Settings.Model.vcxproj">
|
||||
<Private>false</Private>
|
||||
</ProjectReference>
|
||||
|
@ -379,4 +320,4 @@
|
|||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
</Target>
|
||||
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
|
||||
</Project>
|
||||
</Project>
|
|
@ -10,16 +10,10 @@
|
|||
<ClCompile Include="pch.cpp" />
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
<ClCompile Include="Utils.cpp" />
|
||||
<ClCompile Include="PercentageSignConverter.cpp">
|
||||
<Filter>Converters</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="Utils.h" />
|
||||
<ClInclude Include="PercentageSignConverter.h">
|
||||
<Filter>Converters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PreviewConnection.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -49,9 +43,4 @@
|
|||
<Page Include="ReadOnlyActions.xaml" />
|
||||
<Page Include="KeyChordListener.xaml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Converters">
|
||||
<UniqueIdentifier>{00f725c8-41b4-40a8-995e-8ee2e49a4a4c}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
|
@ -1,65 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "PaddingConverter.h"
|
||||
#include "PaddingConverter.g.cpp"
|
||||
|
||||
using namespace winrt::Windows;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
using namespace winrt::Windows::UI::Text;
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
Foundation::IInspectable PaddingConverter::Convert(Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
|
||||
Foundation::IInspectable const& /* parameter */,
|
||||
hstring const& /* language */)
|
||||
{
|
||||
const auto& padding = winrt::unbox_value<hstring>(value);
|
||||
|
||||
const wchar_t singleCharDelim = L',';
|
||||
std::wstringstream tokenStream(padding.c_str());
|
||||
std::wstring token;
|
||||
double maxVal = 0;
|
||||
size_t* idx = nullptr;
|
||||
|
||||
// Get padding values till we run out of delimiter separated values in the stream
|
||||
// Non-numeral values detected will default to 0
|
||||
// std::getline will not throw exception unless flags are set on the wstringstream
|
||||
// std::stod will throw invalid_argument exception if the input is an invalid double value
|
||||
// std::stod will throw out_of_range exception if the input value is more than DBL_MAX
|
||||
try
|
||||
{
|
||||
while (std::getline(tokenStream, token, singleCharDelim))
|
||||
{
|
||||
// std::stod internally calls wcstod which handles whitespace prefix (which is ignored)
|
||||
// & stops the scan when first char outside the range of radix is encountered
|
||||
// We'll be permissive till the extent that stod function allows us to be by default
|
||||
// Ex. a value like 100.3#535w2 will be read as 100.3, but ;df25 will fail
|
||||
const auto curVal = std::stod(token, idx);
|
||||
if (curVal > maxVal)
|
||||
{
|
||||
maxVal = curVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// If something goes wrong, even if due to a single bad padding value, we'll return default 0 padding
|
||||
maxVal = 0;
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
}
|
||||
|
||||
return winrt::box_value<double>(maxVal);
|
||||
}
|
||||
|
||||
Foundation::IInspectable PaddingConverter::ConvertBack(Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
|
||||
Foundation::IInspectable const& /*parameter*/,
|
||||
hstring const& /* language */)
|
||||
{
|
||||
const auto padding{ winrt::unbox_value<double>(value) };
|
||||
return winrt::box_value(winrt::to_hstring(padding));
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "PaddingConverter.g.h"
|
||||
#include "../inc/cppwinrt_utils.h"
|
||||
|
||||
DECLARE_CONVERTER(winrt::Microsoft::Terminal::Settings::Editor, PaddingConverter);
|
|
@ -1,32 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "PercentageConverter.h"
|
||||
#include "PercentageConverter.g.cpp"
|
||||
|
||||
using namespace winrt::Windows;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
Foundation::IInspectable PercentageConverter::Convert(Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
|
||||
Foundation::IInspectable const& /* parameter */,
|
||||
hstring const& /* language */)
|
||||
{
|
||||
const auto decimal{ winrt::unbox_value<double>(value) };
|
||||
const unsigned int number{ base::ClampMul(decimal, 100u) };
|
||||
return winrt::box_value<double>(number);
|
||||
}
|
||||
|
||||
Foundation::IInspectable PercentageConverter::ConvertBack(Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
|
||||
Foundation::IInspectable const& /*parameter*/,
|
||||
hstring const& /* language */)
|
||||
{
|
||||
const auto number{ winrt::unbox_value<double>(value) };
|
||||
const auto decimal{ base::ClampDiv<double, double>(number, 100) };
|
||||
return winrt::box_value<double>(decimal);
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "PercentageConverter.g.h"
|
||||
#include "Utils.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
struct PercentageConverter : PercentageConverterT<PercentageConverter>
|
||||
{
|
||||
PercentageConverter() = default;
|
||||
|
||||
Windows::Foundation::IInspectable Convert(Windows::Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& targetType,
|
||||
Windows::Foundation::IInspectable const& parameter,
|
||||
hstring const& language);
|
||||
|
||||
Windows::Foundation::IInspectable ConvertBack(Windows::Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& targetType,
|
||||
Windows::Foundation::IInspectable const& parameter,
|
||||
hstring const& language);
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(PercentageConverter);
|
||||
}
|
|
@ -20,6 +20,16 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
|
||||
Model::TerminalSettings TermSettings() const;
|
||||
|
||||
void SetAcrylicOpacityPercentageValue(double value)
|
||||
{
|
||||
AcrylicOpacity(winrt::Microsoft::Terminal::Settings::Editor::Converters::PercentageValueToPercentage(value));
|
||||
};
|
||||
|
||||
void SetPadding(double value)
|
||||
{
|
||||
Padding(to_hstring(value));
|
||||
}
|
||||
|
||||
// starting directory
|
||||
bool UseParentProcessDirectory();
|
||||
void UseParentProcessDirectory(const bool useParent);
|
||||
|
|
|
@ -19,6 +19,9 @@ namespace Microsoft.Terminal.Settings.Editor
|
|||
Windows.Foundation.Collections.IObservableVector<Font> MonospaceFontList { get; };
|
||||
Microsoft.Terminal.Settings.Model.TerminalSettings TermSettings { get; };
|
||||
|
||||
void SetAcrylicOpacityPercentageValue(Double value);
|
||||
void SetPadding(Double value);
|
||||
|
||||
Boolean CanDeleteProfile { get; };
|
||||
Boolean IsBaseLayer;
|
||||
Boolean UseParentProcessDirectory;
|
||||
|
@ -105,5 +108,7 @@ namespace Microsoft.Terminal.Settings.Editor
|
|||
|
||||
IInspectable CurrentScrollState;
|
||||
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> ScrollStateList { get; };
|
||||
|
||||
Windows.UI.Xaml.Controls.Slider AcrylicOpacitySlider { get; };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,17 +33,6 @@
|
|||
<TextBlock FontFamily="{x:Bind Name}"
|
||||
Text="{x:Bind LocalizedName}" />
|
||||
</DataTemplate>
|
||||
|
||||
<local:ColorToBrushConverter x:Key="ColorToBrushConverter" />
|
||||
<local:PercentageConverter x:Key="PercentageConverter" />
|
||||
<local:PercentageSignConverter x:Key="PercentageSignConverter" />
|
||||
<local:FontWeightConverter x:Key="FontWeightConverter" />
|
||||
<local:InvertedBooleanToVisibilityConverter x:Key="InvertedBooleanToVisibilityConverter" />
|
||||
<local:StringIsEmptyConverter x:Key="StringIsEmptyConverter" />
|
||||
<local:PaddingConverter x:Key="PaddingConverter" />
|
||||
<local:StringIsNotDesktopConverter x:Key="StringIsNotDesktopConverter" />
|
||||
<local:DesktopWallpaperToEmptyStringConverter x:Key="DesktopWallpaperToEmptyStringConverter" />
|
||||
|
||||
</ResourceDictionary>
|
||||
</Page.Resources>
|
||||
|
||||
|
@ -78,7 +67,7 @@
|
|||
-->
|
||||
<local:SettingContainer x:Uid="Profile_Name"
|
||||
Margin="0,0,0,24"
|
||||
Visibility="{x:Bind State.Profile.IsBaseLayer, Mode=OneWay, Converter={StaticResource InvertedBooleanToVisibilityConverter}}">
|
||||
Visibility="{x:Bind local:Converters.InvertedBooleanToVisibility(State.Profile.IsBaseLayer), Mode=OneWay}">
|
||||
<TextBox Style="{StaticResource TextBoxSettingStyle}"
|
||||
Text="{x:Bind State.Profile.Name, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
@ -90,7 +79,7 @@
|
|||
ClearSettingValue="{x:Bind State.Profile.ClearCommandline}"
|
||||
HasSettingValue="{x:Bind State.Profile.HasCommandline, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind State.Profile.CommandlineOverrideSource, Mode=OneWay}"
|
||||
Visibility="{x:Bind State.Profile.IsBaseLayer, Mode=OneWay, Converter={StaticResource InvertedBooleanToVisibilityConverter}}">
|
||||
Visibility="{x:Bind local:Converters.InvertedBooleanToVisibility(State.Profile.IsBaseLayer), Mode=OneWay}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox Style="{StaticResource TextBoxSettingStyle}"
|
||||
Text="{x:Bind State.Profile.Commandline, Mode=TwoWay}" />
|
||||
|
@ -150,7 +139,7 @@
|
|||
|
||||
<!-- Hidden -->
|
||||
<local:SettingContainer x:Uid="Profile_Hidden"
|
||||
Visibility="{x:Bind State.Profile.IsBaseLayer, Mode=OneWay, Converter={StaticResource InvertedBooleanToVisibilityConverter}}">
|
||||
Visibility="{x:Bind local:Converters.InvertedBooleanToVisibility(State.Profile.IsBaseLayer), Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind State.Profile.Hidden, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
|
@ -280,10 +269,10 @@
|
|||
</Grid.ColumnDefinitions>
|
||||
<Slider x:Name="AcrylicOpacitySlider"
|
||||
Grid.Column="0"
|
||||
Value="{x:Bind State.Profile.AcrylicOpacity, Converter={StaticResource PercentageConverter}, Mode=TwoWay}" />
|
||||
Value="{x:Bind local:Converters.PercentageToPercentageValue(State.Profile.AcrylicOpacity), BindBack=State.Profile.SetAcrylicOpacityPercentageValue, Mode=TwoWay}" />
|
||||
<TextBlock Grid.Column="1"
|
||||
Style="{StaticResource SliderValueLabelStyle}"
|
||||
Text="{Binding ElementName=AcrylicOpacitySlider, Path=Value, Mode=OneWay, Converter={StaticResource PercentageSignConverter}}" />
|
||||
Text="{x:Bind local:Converters.AppendPercentageSign(AcrylicOpacitySlider.Value), Mode=OneWay}" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</local:SettingContainer>
|
||||
|
@ -307,7 +296,7 @@
|
|||
</Grid.ColumnDefinitions>
|
||||
<Slider x:Name="PaddingSlider"
|
||||
Grid.Column="0"
|
||||
Value="{x:Bind State.Profile.Padding, Converter={StaticResource PaddingConverter}, Mode=TwoWay}" />
|
||||
Value="{x:Bind local:Converters.MaxValueFromPaddingString(State.Profile.Padding), BindBack=State.Profile.SetPadding, Mode=TwoWay}" />
|
||||
<TextBlock Grid.Column="1"
|
||||
Style="{StaticResource SliderValueLabelStyle}"
|
||||
Text="{Binding ElementName=PaddingSlider, Path=Value, Mode=OneWay}" />
|
||||
|
@ -333,7 +322,7 @@
|
|||
Margin="32,0,0,0"
|
||||
Click="CreateUnfocusedAppearance_Click"
|
||||
Style="{StaticResource BaseButtonStyle}"
|
||||
Visibility="{x:Bind State.Profile.HasUnfocusedAppearance, Mode=OneWay, Converter={StaticResource InvertedBooleanToVisibilityConverter}}">
|
||||
Visibility="{x:Bind local:Converters.InvertedBooleanToVisibility(State.Profile.HasUnfocusedAppearance), Mode=OneWay}">
|
||||
<Button.Content>
|
||||
<FontIcon FontSize="{StaticResource StandardIconSize}"
|
||||
Glyph="" />
|
||||
|
|
|
@ -17,9 +17,6 @@
|
|||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="CommonResources.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<local:StringIsEmptyConverter x:Key="CommandKeyChordVisibilityConverter" />
|
||||
|
||||
<!--
|
||||
Template for actions. This is _heavily_ copied from the command
|
||||
palette, with modifications:
|
||||
|
|
|
@ -232,7 +232,7 @@
|
|||
<comment>Header for a control to toggle if the app should always show the tabs (similar to a website browser).</comment>
|
||||
</data>
|
||||
<data name="Globals_AlwaysShowTabs.HelpText" xml:space="preserve">
|
||||
<value>When unchecked, the tab bar will appear when a new tab is created.</value>
|
||||
<value>When disabled, the tab bar will appear when a new tab is created.</value>
|
||||
<comment>A description for what the "always show tabs" setting does. Presented near "Globals_AlwaysShowTabs.Header".</comment>
|
||||
</data>
|
||||
<data name="Globals_CopyOnSelect.Header" xml:space="preserve">
|
||||
|
@ -272,7 +272,7 @@
|
|||
<comment>Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames.</comment>
|
||||
</data>
|
||||
<data name="Globals_ForceFullRepaint.HelpText" xml:space="preserve">
|
||||
<value>When unchecked, the terminal will render only the updates to the screen between frames.</value>
|
||||
<value>When disabled, the terminal will render only the updates to the screen between frames.</value>
|
||||
<comment>A description for what the "force full repaint" setting does. Presented near "Globals_ForceFullRepaint.Header".</comment>
|
||||
</data>
|
||||
<data name="Globals_InitialCols.Header" xml:space="preserve">
|
||||
|
@ -340,7 +340,7 @@
|
|||
<comment>Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app.</comment>
|
||||
</data>
|
||||
<data name="Globals_ShowTitlebar.HelpText" xml:space="preserve">
|
||||
<value>When unchecked, the title bar will appear above the tabs.</value>
|
||||
<value>When disabled, the title bar will appear above the tabs.</value>
|
||||
<comment>A description for what the "show titlebar" setting does. Presented near "Globals_ShowTitlebar.Header".</comment>
|
||||
</data>
|
||||
<data name="Globals_ShowTitleInTitlebar.Header" xml:space="preserve">
|
||||
|
@ -348,7 +348,7 @@
|
|||
<comment>Header for a control to toggle whether the terminal's title is shown as the application title, or not.</comment>
|
||||
</data>
|
||||
<data name="Globals_ShowTitleInTitlebar.HelpText" xml:space="preserve">
|
||||
<value>When unchecked, the title bar will be 'Windows Terminal'.</value>
|
||||
<value>When disabled, the title bar will be 'Windows Terminal'.</value>
|
||||
<comment>A description for what the "show title in titlebar" setting does. Presented near "Globals_ShowTitleInTitlebar.Header".{Locked="Windows"}</comment>
|
||||
</data>
|
||||
<data name="Globals_SnapToGridOnResize.Header" xml:space="preserve">
|
||||
|
@ -356,7 +356,7 @@
|
|||
<comment>Header for a control to toggle whether the terminal snaps the window to the character grid when resizing, or not.</comment>
|
||||
</data>
|
||||
<data name="Globals_SnapToGridOnResize.HelpText" xml:space="preserve">
|
||||
<value>When unchecked, the window will resize smoothly.</value>
|
||||
<value>When disabled, the window will resize smoothly.</value>
|
||||
<comment>A description for what the "snap to grid on resize" setting does. Presented near "Globals_SnapToGridOnResize.Header".</comment>
|
||||
</data>
|
||||
<data name="Globals_SoftwareRendering.Header" xml:space="preserve">
|
||||
|
@ -364,7 +364,7 @@
|
|||
<comment>Header for a control to toggle whether the terminal should use software to render content instead of the hardware.</comment>
|
||||
</data>
|
||||
<data name="Globals_SoftwareRendering.HelpText" xml:space="preserve">
|
||||
<value>When checked, the terminal will use the software renderer (a.k.a. WARP) instead of the hardware one.</value>
|
||||
<value>When enabled, the terminal will use the software renderer (a.k.a. WARP) instead of the hardware one.</value>
|
||||
<comment>A description for what the "software rendering" setting does. Presented near "Globals_SoftwareRendering.Header".</comment>
|
||||
</data>
|
||||
<data name="Globals_StartOnUserLogin.Header" xml:space="preserve">
|
||||
|
@ -372,7 +372,7 @@
|
|||
<comment>Header for a control to toggle whether the app should launch when the user's machine starts up, or not.</comment>
|
||||
</data>
|
||||
<data name="Globals_StartOnUserLogin.HelpText" xml:space="preserve">
|
||||
<value>When checked, this enables the launch of Windows Terminal at machine startup.</value>
|
||||
<value>When enabled, this enables the launch of Windows Terminal at machine startup.</value>
|
||||
<comment>A description for what the "start on user login" setting does. Presented near "Globals_StartOnUserLogin.Header".</comment>
|
||||
</data>
|
||||
<data name="Globals_AlwaysOnTop.Header" xml:space="preserve">
|
||||
|
@ -480,7 +480,7 @@
|
|||
<comment>Header for a control to toggle whether the app treats ctrl+alt as the AltGr (also known as the Alt Graph) modifier key found on keyboards. {Locked="AltGr"}</comment>
|
||||
</data>
|
||||
<data name="Profile_AltGrAliasing.HelpText" xml:space="preserve">
|
||||
<value>By default Windows treats Ctrl+Alt as an alias for AltGr. When unchecked, this behavior will be disabled.</value>
|
||||
<value>By default Windows treats Ctrl+Alt as an alias for AltGr. When disabled, this behavior will be disabled.</value>
|
||||
<comment>A description for what the "AltGr aliasing" setting does. Presented near "Profile_AltGrAliasing.Header".</comment>
|
||||
</data>
|
||||
<data name="Profile_AntialiasingMode.Header" xml:space="preserve">
|
||||
|
@ -700,7 +700,7 @@
|
|||
<comment>Header for a control to toggle whether the profile is shown in a dropdown menu, or not.</comment>
|
||||
</data>
|
||||
<data name="Profile_Hidden.HelpText" xml:space="preserve">
|
||||
<value>If checked, the profile will not appear in the list of profiles. This can be used to hide default profiles and dynamically generated profiles, while leaving them in your settings file.</value>
|
||||
<value>If enabled, the profile will not appear in the list of profiles. This can be used to hide default profiles and dynamically generated profiles, while leaving them in your settings file.</value>
|
||||
<comment>A description for what the "hidden" setting does. Presented near "Profile_Hidden".</comment>
|
||||
</data>
|
||||
<data name="Profile_HistorySize.Header" xml:space="preserve">
|
||||
|
@ -736,7 +736,7 @@
|
|||
<comment>Header for a control to toggle classic CRT display effects, which gives the terminal a retro look.</comment>
|
||||
</data>
|
||||
<data name="Profile_RetroTerminalEffect.HelpText" xml:space="preserve">
|
||||
<value>When checked, enables retro terminal effects such as glowing text and scan lines.</value>
|
||||
<value>When enabled, enables retro terminal effects such as glowing text and scan lines.</value>
|
||||
<comment>A description for what the "retro terminal effects" setting does. Presented near "Profile_RetroTerminalEffect".</comment>
|
||||
</data>
|
||||
<data name="Profile_ScrollbarVisibility.Header" xml:space="preserve">
|
||||
|
@ -772,7 +772,7 @@
|
|||
<comment>A supplementary setting to the "starting directory" setting. "Parent" refers to the parent process of the current process.</comment>
|
||||
</data>
|
||||
<data name="Profile_StartingDirectoryUseParentCheckbox.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
|
||||
<value>If checked, this profile will spawn in the directory from which Windows Terminal was launched.</value>
|
||||
<value>If enabled, this profile will spawn in the directory from which Windows Terminal was launched.</value>
|
||||
<comment>A description for what the supplementary "use parent process directory" setting does. Presented near "Profile_StartingDirectoryUseParentCheckbox".</comment>
|
||||
</data>
|
||||
<data name="Profile_SuppressApplicationTitle.Header" xml:space="preserve">
|
||||
|
@ -808,7 +808,7 @@
|
|||
<comment>A supplementary setting to the "background image" setting. When enabled, the OS desktop wallpaper is used as the background image. Presented near "Profile_BackgroundImage".</comment>
|
||||
</data>
|
||||
<data name="Profile_UseDesktopImage.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
|
||||
<value>When checked, use the desktop wallpaper image as the background image for the terminal.</value>
|
||||
<value>When enabled, use the desktop wallpaper image as the background image for the terminal.</value>
|
||||
<comment>A description for what the supplementary "use desktop image" setting does. Presented near "Profile_UseDesktopImage".</comment>
|
||||
</data>
|
||||
<data name="Settings_ResetSettingsButton.Content" xml:space="preserve">
|
||||
|
@ -1111,7 +1111,7 @@
|
|||
<comment>A supplementary setting to the "font face" setting. Toggling this control updates the font face control to show all of the fonts installed.</comment>
|
||||
</data>
|
||||
<data name="Profile_FontFaceShowAllFonts.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
|
||||
<value>If checked, show all installed fonts in the list above. Otherwise, only show the list of monospace fonts.</value>
|
||||
<value>If enabled, show all installed fonts in the list above. Otherwise, only show the list of monospace fonts.</value>
|
||||
<comment>A description for what the supplementary "show all fonts" setting does. Presented near "Profile_FontFaceShowAllFonts".</comment>
|
||||
</data>
|
||||
<data name="Profile_CreateUnfocusedAppearanceButton.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "StringIsEmptyConverter.h"
|
||||
#include "StringIsEmptyConverter.g.cpp"
|
||||
|
||||
using namespace winrt::Windows;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
using namespace winrt::Windows::UI::Text;
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
Foundation::IInspectable StringIsEmptyConverter::Convert(Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
|
||||
Foundation::IInspectable const& /* parameter */,
|
||||
hstring const& /* language */)
|
||||
{
|
||||
const auto& name = winrt::unbox_value_or<hstring>(value, L"");
|
||||
return winrt::box_value(name.empty() ? Visibility::Collapsed : Visibility::Visible);
|
||||
}
|
||||
|
||||
Foundation::IInspectable StringIsEmptyConverter::ConvertBack(Foundation::IInspectable const& /*value*/,
|
||||
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
|
||||
Foundation::IInspectable const& /*parameter*/,
|
||||
hstring const& /* language */)
|
||||
{
|
||||
throw hresult_not_implemented();
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "StringIsEmptyConverter.g.h"
|
||||
#include "../inc/cppwinrt_utils.h"
|
||||
|
||||
DECLARE_CONVERTER(winrt::Microsoft::Terminal::Settings::Editor, StringIsEmptyConverter);
|
|
@ -1,50 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "StringIsNotDesktopConverter.h"
|
||||
#include "StringIsNotDesktopConverter.g.cpp"
|
||||
#include "DesktopWallpaperToEmptyStringConverter.g.cpp"
|
||||
|
||||
using namespace winrt::Windows;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
using namespace winrt::Windows::UI::Text;
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
Foundation::IInspectable StringIsNotDesktopConverter::Convert(Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
|
||||
Foundation::IInspectable const& /* parameter */,
|
||||
hstring const& /* language */)
|
||||
{
|
||||
// Returns Visible if the string is _not_ "desktopWallpaper", else returns Collapsed
|
||||
const auto& name = winrt::unbox_value_or<hstring>(value, L"");
|
||||
return winrt::box_value(name != L"desktopWallpaper");
|
||||
}
|
||||
|
||||
Foundation::IInspectable StringIsNotDesktopConverter::ConvertBack(Foundation::IInspectable const& /*value*/,
|
||||
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
|
||||
Foundation::IInspectable const& /*parameter*/,
|
||||
hstring const& /* language */)
|
||||
{
|
||||
throw hresult_not_implemented();
|
||||
}
|
||||
|
||||
Foundation::IInspectable DesktopWallpaperToEmptyStringConverter::Convert(Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
|
||||
Foundation::IInspectable const& /* parameter */,
|
||||
hstring const& /* language */)
|
||||
{
|
||||
// Returns the empty string if the string is "desktopWallpaper", else returns the original value.
|
||||
const auto& name = winrt::unbox_value_or<hstring>(value, L"");
|
||||
return winrt::box_value(name == L"desktopWallpaper" ? L"" : name);
|
||||
}
|
||||
|
||||
Foundation::IInspectable DesktopWallpaperToEmptyStringConverter::ConvertBack(Foundation::IInspectable const& value,
|
||||
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
|
||||
Foundation::IInspectable const& /*parameter*/,
|
||||
hstring const& /* language */)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "StringIsNotDesktopConverter.g.h"
|
||||
#include "DesktopWallpaperToEmptyStringConverter.g.h"
|
||||
#include "../inc/cppwinrt_utils.h"
|
||||
|
||||
DECLARE_CONVERTER(winrt::Microsoft::Terminal::Settings::Editor, StringIsNotDesktopConverter);
|
||||
DECLARE_CONVERTER(winrt::Microsoft::Terminal::Settings::Editor, DesktopWallpaperToEmptyStringConverter);
|
|
@ -118,7 +118,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
|
||||
if (!StartingDirectory().empty())
|
||||
{
|
||||
ss << fmt::format(L"--startingDirectory \"{}\" ", StartingDirectory());
|
||||
// If the directory ends in a '\', we need to add another one on so that the enclosing quote added
|
||||
// afterwards isn't escaped
|
||||
const auto trailingBackslashEscape = StartingDirectory().back() == L'\\' ? L"\\" : L"";
|
||||
ss << fmt::format(L"--startingDirectory \"{}{}\" ", StartingDirectory(), trailingBackslashEscape);
|
||||
}
|
||||
|
||||
if (!TabTitle().empty())
|
||||
|
|
|
@ -677,6 +677,32 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Determines whether the given key chord is explicitly unbound
|
||||
// Arguments:
|
||||
// - keys: the key chord to check
|
||||
// Return value:
|
||||
// - true if the keychord is explicitly unbound
|
||||
// - false if either the keychord is bound, or not bound at all
|
||||
bool ActionMap::IsKeyChordExplicitlyUnbound(Control::KeyChord const& keys) const
|
||||
{
|
||||
const auto modifiers = keys.Modifiers();
|
||||
|
||||
// The "keys" given to us can contain both a Vkey, as well as a ScanCode.
|
||||
// For instance our UI code fills out a KeyChord with all available information.
|
||||
// But our _KeyMap only contains KeyChords that contain _either_ a Vkey or ScanCode.
|
||||
// Due to this we'll have to call _GetActionByKeyChordInternal twice.
|
||||
if (auto vkey = keys.Vkey())
|
||||
{
|
||||
// We use the fact that the ..Internal call returns nullptr for explicitly unbound
|
||||
// key chords, and nullopt for keychord that are not bound - it allows us to distinguish
|
||||
// between unbound and lack of binding.
|
||||
return nullptr == _GetActionByKeyChordInternal({ modifiers, vkey, 0 });
|
||||
}
|
||||
|
||||
return nullptr == _GetActionByKeyChordInternal({ modifiers, 0, keys.ScanCode() });
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Retrieves the assigned command that can be invoked with the given key chord
|
||||
// Arguments:
|
||||
|
|
|
@ -61,6 +61,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
|
||||
// queries
|
||||
Model::Command GetActionByKeyChord(Control::KeyChord const& keys) const;
|
||||
bool IsKeyChordExplicitlyUnbound(Control::KeyChord const& keys) const;
|
||||
Control::KeyChord GetKeyBindingForAction(ShortcutAction const& action) const;
|
||||
Control::KeyChord GetKeyBindingForAction(ShortcutAction const& action, IActionArgs const& actionArgs) const;
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
// This interface ensures that no changes are made to ActionMap
|
||||
interface IActionMapView
|
||||
{
|
||||
Boolean IsKeyChordExplicitlyUnbound(Microsoft.Terminal.Control.KeyChord keys);
|
||||
|
||||
Command GetActionByKeyChord(Microsoft.Terminal.Control.KeyChord keys);
|
||||
|
||||
Microsoft.Terminal.Control.KeyChord GetKeyBindingForAction(ShortcutAction action);
|
||||
|
|
|
@ -60,6 +60,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
void UnparsedDefaultProfile(const hstring& value);
|
||||
void ClearUnparsedDefaultProfile();
|
||||
|
||||
// TODO GH#9207: Remove this once we have a GlobalAppSettingsViewModel in TerminalSettingsEditor
|
||||
void SetInvertedDisableAnimationsValue(bool invertedDisableAnimationsValue)
|
||||
{
|
||||
DisableAnimations(!invertedDisableAnimationsValue);
|
||||
}
|
||||
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, int32_t, InitialRows, DEFAULT_ROWS);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, int32_t, InitialCols, DEFAULT_COLS);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, AlwaysShowTabs, true);
|
||||
|
|
|
@ -36,6 +36,9 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
|
||||
[default_interface] runtimeclass GlobalAppSettings {
|
||||
Guid DefaultProfile;
|
||||
|
||||
void SetInvertedDisableAnimationsValue(Boolean invertedDisableAnimationsValue);
|
||||
|
||||
INHERITABLE_SETTING(String, UnparsedDefaultProfile);
|
||||
|
||||
INHERITABLE_SETTING(Int32, InitialRows);
|
||||
|
|
|
@ -56,6 +56,16 @@ namespace ControlUnitTests
|
|||
|
||||
return { settings, conn };
|
||||
}
|
||||
|
||||
winrt::com_ptr<Control::implementation::ControlCore> createCore(Control::IControlSettings settings,
|
||||
TerminalConnection::ITerminalConnection conn)
|
||||
{
|
||||
Log::Comment(L"Create ControlCore object");
|
||||
|
||||
auto core = winrt::make_self<Control::implementation::ControlCore>(settings, conn);
|
||||
core->_inUnitTests = true;
|
||||
return core;
|
||||
}
|
||||
};
|
||||
|
||||
void ControlCoreTests::ComPtrSettings()
|
||||
|
@ -71,8 +81,7 @@ namespace ControlUnitTests
|
|||
{
|
||||
auto [settings, conn] = _createSettingsAndConnection();
|
||||
|
||||
Log::Comment(L"Create ControlCore object");
|
||||
auto core = winrt::make_self<Control::implementation::ControlCore>(*settings, *conn);
|
||||
auto core = createCore(*settings, *conn);
|
||||
VERIFY_IS_NOT_NULL(core);
|
||||
}
|
||||
|
||||
|
@ -80,8 +89,7 @@ namespace ControlUnitTests
|
|||
{
|
||||
auto [settings, conn] = _createSettingsAndConnection();
|
||||
|
||||
Log::Comment(L"Create ControlCore object");
|
||||
auto core = winrt::make_self<Control::implementation::ControlCore>(*settings, *conn);
|
||||
auto core = createCore(*settings, *conn);
|
||||
VERIFY_IS_NOT_NULL(core);
|
||||
|
||||
VERIFY_IS_FALSE(core->_initializedTerminal);
|
||||
|
@ -99,8 +107,7 @@ namespace ControlUnitTests
|
|||
settings->UseAcrylic(true);
|
||||
settings->TintOpacity(0.5f);
|
||||
|
||||
Log::Comment(L"Create ControlCore object");
|
||||
auto core = winrt::make_self<Control::implementation::ControlCore>(*settings, *conn);
|
||||
auto core = createCore(*settings, *conn);
|
||||
VERIFY_IS_NOT_NULL(core);
|
||||
|
||||
// A callback to make sure that we're raising TransparencyChanged events
|
||||
|
@ -167,8 +174,7 @@ namespace ControlUnitTests
|
|||
{
|
||||
auto [settings, conn] = _createSettingsAndConnection();
|
||||
|
||||
Log::Comment(L"Create ControlCore object");
|
||||
auto core = winrt::make_self<Control::implementation::ControlCore>(*settings, *conn);
|
||||
auto core = createCore(*settings, *conn);
|
||||
VERIFY_IS_NOT_NULL(core);
|
||||
|
||||
Log::Comment(L"Close the Core, like a TermControl would");
|
||||
|
@ -190,8 +196,7 @@ namespace ControlUnitTests
|
|||
// that you don't default to Cascadia*
|
||||
settings->FontFace(L"Impact");
|
||||
|
||||
Log::Comment(L"Create ControlCore object");
|
||||
auto core = winrt::make_self<Control::implementation::ControlCore>(*settings, *conn);
|
||||
auto core = createCore(*settings, *conn);
|
||||
VERIFY_IS_NOT_NULL(core);
|
||||
|
||||
VERIFY_ARE_EQUAL(L"Impact", std::wstring_view{ core->_actualFont.GetFaceName() });
|
||||
|
|
|
@ -73,6 +73,7 @@ namespace ControlUnitTests
|
|||
auto interactivity = winrt::make_self<Control::implementation::ControlInteractivity>(settings, conn);
|
||||
VERIFY_IS_NOT_NULL(interactivity);
|
||||
auto core = interactivity->_core;
|
||||
core->_inUnitTests = true;
|
||||
VERIFY_IS_NOT_NULL(core);
|
||||
|
||||
return { core, interactivity };
|
||||
|
@ -163,6 +164,10 @@ namespace ControlUnitTests
|
|||
|
||||
void ControlInteractivityTests::TestScrollWithMouse()
|
||||
{
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
TEST_METHOD_PROPERTY(L"IsolationLevel", L"Method")
|
||||
END_TEST_METHOD_PROPERTIES()
|
||||
|
||||
WEX::TestExecution::DisableVerifyExceptions disableVerifyExceptions{};
|
||||
|
||||
auto [settings, conn] = _createSettingsAndConnection();
|
||||
|
@ -243,7 +248,7 @@ namespace ControlUnitTests
|
|||
buttonState);
|
||||
Log::Comment(NoThrowString().Format(L"internal scrollbar pos:%f", interactivity->_internalScrollbarPosition));
|
||||
}
|
||||
Log::Comment(L"Scrolling up more should do nothing");
|
||||
Log::Comment(L"Scrolling down more should do nothing");
|
||||
expectedTop = 21;
|
||||
interactivity->MouseWheel(modifiers,
|
||||
-WHEEL_DELTA,
|
||||
|
@ -257,6 +262,10 @@ namespace ControlUnitTests
|
|||
|
||||
void ControlInteractivityTests::CreateSubsequentSelectionWithDragging()
|
||||
{
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
TEST_METHOD_PROPERTY(L"IsolationLevel", L"Method")
|
||||
END_TEST_METHOD_PROPERTIES()
|
||||
|
||||
// This is a test for GH#9725
|
||||
WEX::TestExecution::DisableVerifyExceptions disableVerifyExceptions{};
|
||||
|
||||
|
|
|
@ -47,6 +47,8 @@ Licensed under the MIT license.
|
|||
// Manually include til after we include Windows.Foundation to give it winrt superpowers
|
||||
#include "til.h"
|
||||
|
||||
#include "ThrottledFunc.h"
|
||||
|
||||
// Common includes for most tests:
|
||||
#include "../../inc/argb.h"
|
||||
#include "../../inc/conattrs.hpp"
|
||||
|
|
|
@ -29,7 +29,6 @@ namespace TerminalCoreUnitTests
|
|||
};
|
||||
|
||||
TEST_METHOD(AltShiftKey);
|
||||
TEST_METHOD(AltSpace);
|
||||
TEST_METHOD(InvalidKeyEvent);
|
||||
|
||||
void _VerifyExpectedInput(std::wstring& actualInput)
|
||||
|
@ -57,16 +56,6 @@ namespace TerminalCoreUnitTests
|
|||
VERIFY_IS_TRUE(term.SendCharEvent(L'A', 0, ControlKeyStates::LeftAltPressed | ControlKeyStates::ShiftPressed));
|
||||
}
|
||||
|
||||
void InputTest::AltSpace()
|
||||
{
|
||||
// Make sure we don't handle Alt+Space. The system will use this to
|
||||
// bring up the system menu for restore, min/maximize, size, move,
|
||||
// close
|
||||
VERIFY_IS_FALSE(term.SendKeyEvent(L' ', 0, ControlKeyStates::LeftAltPressed, true));
|
||||
VERIFY_IS_FALSE(term.SendKeyEvent(L' ', 0, ControlKeyStates::LeftAltPressed, false));
|
||||
VERIFY_IS_FALSE(term.SendCharEvent(L' ', 0, ControlKeyStates::LeftAltPressed));
|
||||
}
|
||||
|
||||
void InputTest::InvalidKeyEvent()
|
||||
{
|
||||
// Certain applications like AutoHotKey and its keyboard remapping feature,
|
||||
|
|
|
@ -24,7 +24,7 @@ public:
|
|||
//
|
||||
// After `func` was invoked the state is reset and this cycle is repeated again.
|
||||
ThrottledFunc(
|
||||
winrt::Windows::UI::Core::CoreDispatcher dispatcher,
|
||||
winrt::Windows::System::DispatcherQueue dispatcher,
|
||||
filetime_duration delay,
|
||||
function func) :
|
||||
_dispatcher{ std::move(dispatcher) },
|
||||
|
@ -81,7 +81,7 @@ private:
|
|||
{
|
||||
if constexpr (leading)
|
||||
{
|
||||
_dispatcher.RunAsync(winrt::Windows::UI::Core::CoreDispatcherPriority::Normal, [weakSelf = this->weak_from_this()]() {
|
||||
_dispatcher.TryEnqueue(winrt::Windows::System::DispatcherQueuePriority::Normal, [weakSelf = this->weak_from_this()]() {
|
||||
if (auto self{ weakSelf.lock() })
|
||||
{
|
||||
try
|
||||
|
@ -108,7 +108,7 @@ private:
|
|||
}
|
||||
else
|
||||
{
|
||||
_dispatcher.RunAsync(winrt::Windows::UI::Core::CoreDispatcherPriority::Normal, [weakSelf = this->weak_from_this()]() {
|
||||
_dispatcher.TryEnqueue(winrt::Windows::System::DispatcherQueuePriority::Normal, [weakSelf = this->weak_from_this()]() {
|
||||
if (auto self{ weakSelf.lock() })
|
||||
{
|
||||
try
|
||||
|
@ -129,7 +129,7 @@ private:
|
|||
}
|
||||
|
||||
FILETIME _delay;
|
||||
winrt::Windows::UI::Core::CoreDispatcher _dispatcher;
|
||||
winrt::Windows::System::DispatcherQueue _dispatcher;
|
||||
function _func;
|
||||
|
||||
wil::unique_threadpool_timer _timer;
|
||||
|
|
|
@ -126,13 +126,14 @@ bool AppHost::OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, cons
|
|||
// Arguments:
|
||||
// - sender: not used
|
||||
// - args: not used
|
||||
void AppHost::SetTaskbarProgress(const winrt::Windows::Foundation::IInspectable& /*sender*/, const winrt::Windows::Foundation::IInspectable& /*args*/)
|
||||
void AppHost::SetTaskbarProgress(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
||||
const winrt::Windows::Foundation::IInspectable& /*args*/)
|
||||
{
|
||||
if (_logic)
|
||||
{
|
||||
const auto state = gsl::narrow_cast<size_t>(_logic.GetLastActiveControlTaskbarState());
|
||||
const auto progress = gsl::narrow_cast<size_t>(_logic.GetLastActiveControlTaskbarProgress());
|
||||
_window->SetTaskbarProgress(state, progress);
|
||||
const auto state = _logic.TaskbarState();
|
||||
_window->SetTaskbarProgress(gsl::narrow_cast<size_t>(state.State()),
|
||||
gsl::narrow_cast<size_t>(state.Progress()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -410,6 +411,7 @@ void AppHost::_HandleCreateWindow(const HWND hwnd, RECT proposedRect, LaunchMode
|
|||
// Get the size of a window we'd need to host that client rect. This will
|
||||
// add the titlebar space.
|
||||
const til::size nonClientSize = _window->GetTotalNonClientExclusiveSize(dpix);
|
||||
const til::rectangle nonClientFrame = _window->GetNonClientFrame(dpix);
|
||||
adjustedWidth = islandWidth + nonClientSize.width<long>();
|
||||
adjustedHeight = islandHeight + nonClientSize.height<long>();
|
||||
|
||||
|
@ -425,14 +427,18 @@ void AppHost::_HandleCreateWindow(const HWND hwnd, RECT proposedRect, LaunchMode
|
|||
const til::size desktopDimensions{ gsl::narrow<short>(nearestMonitorInfo.rcWork.right - nearestMonitorInfo.rcWork.left),
|
||||
gsl::narrow<short>(nearestMonitorInfo.rcWork.bottom - nearestMonitorInfo.rcWork.top) };
|
||||
|
||||
til::point origin{ (proposedRect.left),
|
||||
// GH#10583 - Adjust the position of the rectangle to account for the size
|
||||
// of the invisible borders on the left/right. We DON'T want to adjust this
|
||||
// for the top here - the IslandWindow includes the titlebar in
|
||||
// nonClientFrame.top, so adjusting for that would actually place the
|
||||
// titlebar _off_ the monitor.
|
||||
til::point origin{ (proposedRect.left + nonClientFrame.left<LONG>()),
|
||||
(proposedRect.top) };
|
||||
|
||||
if (_logic.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.
|
||||
const til::size ncSize{ _window->GetTotalNonClientExclusiveSize(dpix) };
|
||||
const til::size availableSpace = desktopDimensions + nonClientSize;
|
||||
|
||||
origin = til::point{
|
||||
|
@ -656,9 +662,6 @@ void AppHost::_BecomeMonarch(const winrt::Windows::Foundation::IInspectable& /*s
|
|||
const winrt::Windows::Foundation::IInspectable& /*args*/)
|
||||
{
|
||||
_setupGlobalHotkeys();
|
||||
|
||||
// The monarch is just going to be THE listener for inbound connections.
|
||||
_listenForInboundConnections();
|
||||
}
|
||||
|
||||
void AppHost::_listenForInboundConnections()
|
||||
|
|
|
@ -616,12 +616,20 @@ void IslandWindow::SetContent(winrt::Windows::UI::Xaml::UIElement content)
|
|||
}
|
||||
|
||||
// Method Description:
|
||||
// - Gets the difference between window and client area size.
|
||||
// - Get the dimensions of our non-client area, as a rect where each component
|
||||
// represents that side.
|
||||
// - The .left will be a negative number, to represent that the actual side of
|
||||
// the non-client area is outside the border of our window. It's roughly 8px (
|
||||
// * DPI scaling) to the left of the visible border.
|
||||
// - The .right component will be positive, indicating that the nonclient border
|
||||
// is in the positive-x direction from the edge of our client area.
|
||||
// - This will also include our titlebar! It's in the nonclient area for us.
|
||||
// Arguments:
|
||||
// - dpi: dpi of a monitor on which the window is placed
|
||||
// Return Value
|
||||
// - The size difference
|
||||
SIZE IslandWindow::GetTotalNonClientExclusiveSize(const UINT dpi) const noexcept
|
||||
// - dpi: the scaling that we should use to calculate the border sizes.
|
||||
// Return Value:
|
||||
// - a RECT whose components represent the margins of the nonclient area,
|
||||
// relative to the client area.
|
||||
RECT IslandWindow::GetNonClientFrame(const UINT dpi) const noexcept
|
||||
{
|
||||
const auto windowStyle = static_cast<DWORD>(GetWindowLong(_window.get(), GWL_STYLE));
|
||||
RECT islandFrame{};
|
||||
|
@ -630,7 +638,18 @@ SIZE IslandWindow::GetTotalNonClientExclusiveSize(const UINT dpi) const noexcept
|
|||
// the error and go on. We'll use whatever the control proposed as the
|
||||
// size of our window, which will be at least close.
|
||||
LOG_IF_WIN32_BOOL_FALSE(AdjustWindowRectExForDpi(&islandFrame, windowStyle, false, 0, dpi));
|
||||
return islandFrame;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Gets the difference between window and client area size.
|
||||
// Arguments:
|
||||
// - dpi: dpi of a monitor on which the window is placed
|
||||
// Return Value
|
||||
// - The size difference
|
||||
SIZE IslandWindow::GetTotalNonClientExclusiveSize(const UINT dpi) const noexcept
|
||||
{
|
||||
const auto islandFrame{ GetNonClientFrame(dpi) };
|
||||
return {
|
||||
islandFrame.right - islandFrame.left,
|
||||
islandFrame.bottom - islandFrame.top
|
||||
|
@ -757,7 +776,12 @@ void IslandWindow::SetTaskbarProgress(const size_t state, const size_t progress)
|
|||
_taskbar->SetProgressValue(_window.get(), progress, 100);
|
||||
break;
|
||||
case 3:
|
||||
// sets the progress indicator to an indeterminate state
|
||||
// sets the progress indicator to an indeterminate state.
|
||||
// FIRST, set the progress to "no progress". That'll clear out any
|
||||
// progress value from the previous state. Otherwise, a transition
|
||||
// from (error,x%) or (warning,x%) to indeterminate will leave the
|
||||
// progress value unchanged, and not show the spinner.
|
||||
_taskbar->SetProgressState(_window.get(), TBPF_NOPROGRESS);
|
||||
_taskbar->SetProgressState(_window.get(), TBPF_INDETERMINATE);
|
||||
break;
|
||||
case 4:
|
||||
|
|
|
@ -24,6 +24,7 @@ public:
|
|||
virtual void OnAppInitialized();
|
||||
virtual void SetContent(winrt::Windows::UI::Xaml::UIElement content);
|
||||
virtual void OnApplicationThemeChanged(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme);
|
||||
virtual RECT GetNonClientFrame(const UINT dpi) const noexcept;
|
||||
virtual SIZE GetTotalNonClientExclusiveSize(const UINT dpi) const noexcept;
|
||||
|
||||
virtual void Initialize();
|
||||
|
|
|
@ -629,14 +629,21 @@ int NonClientIslandWindow::_GetResizeHandleHeight() const noexcept
|
|||
|
||||
return DefWindowProc(GetHandle(), WM_SETCURSOR, wParam, lParam);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Gets the difference between window and client area size.
|
||||
// - Get the dimensions of our non-client area, as a rect where each component
|
||||
// represents that side.
|
||||
// - The .left will be a negative number, to represent that the actual side of
|
||||
// the non-client area is outside the border of our window. It's roughly 8px (
|
||||
// * DPI scaling) to the left of the visible border.
|
||||
// - The .right component will be positive, indicating that the nonclient border
|
||||
// is in the positive-x direction from the edge of our client area.
|
||||
// - This DOES NOT include our titlebar! It's in the client area for us.
|
||||
// Arguments:
|
||||
// - dpi: dpi of a monitor on which the window is placed
|
||||
// Return Value
|
||||
// - The size difference
|
||||
SIZE NonClientIslandWindow::GetTotalNonClientExclusiveSize(UINT dpi) const noexcept
|
||||
// - dpi: the scaling that we should use to calculate the border sizes.
|
||||
// Return Value:
|
||||
// - a RECT whose components represent the margins of the nonclient area,
|
||||
// relative to the client area.
|
||||
RECT NonClientIslandWindow::GetNonClientFrame(UINT dpi) const noexcept
|
||||
{
|
||||
const auto windowStyle = static_cast<DWORD>(GetWindowLong(_window.get(), GWL_STYLE));
|
||||
RECT islandFrame{};
|
||||
|
@ -647,6 +654,18 @@ SIZE NonClientIslandWindow::GetTotalNonClientExclusiveSize(UINT dpi) const noexc
|
|||
LOG_IF_WIN32_BOOL_FALSE(AdjustWindowRectExForDpi(&islandFrame, windowStyle, false, 0, dpi));
|
||||
|
||||
islandFrame.top = -topBorderVisibleHeight;
|
||||
return islandFrame;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Gets the difference between window and client area size.
|
||||
// Arguments:
|
||||
// - dpi: dpi of a monitor on which the window is placed
|
||||
// Return Value
|
||||
// - The size difference
|
||||
SIZE NonClientIslandWindow::GetTotalNonClientExclusiveSize(UINT dpi) const noexcept
|
||||
{
|
||||
const auto islandFrame{ GetNonClientFrame(dpi) };
|
||||
|
||||
// If we have a titlebar, this is being called after we've initialized, and
|
||||
// we can just ask that titlebar how big it wants to be.
|
||||
|
|
|
@ -37,6 +37,7 @@ public:
|
|||
|
||||
[[nodiscard]] virtual LRESULT MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept override;
|
||||
|
||||
virtual RECT GetNonClientFrame(UINT dpi) const noexcept override;
|
||||
virtual SIZE GetTotalNonClientExclusiveSize(UINT dpi) const noexcept override;
|
||||
|
||||
void Initialize() override;
|
||||
|
|
|
@ -82,6 +82,10 @@ static bool _messageIsAltKeyup(const MSG& message)
|
|||
{
|
||||
return (message.message == WM_KEYUP || message.message == WM_SYSKEYUP) && message.wParam == VK_MENU;
|
||||
}
|
||||
static bool _messageIsAltSpaceKeypress(const MSG& message)
|
||||
{
|
||||
return message.message == WM_SYSKEYDOWN && message.wParam == VK_SPACE;
|
||||
}
|
||||
|
||||
int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
|
||||
{
|
||||
|
@ -171,6 +175,18 @@ int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
|
|||
}
|
||||
}
|
||||
|
||||
// GH#7125 = System XAML will show a system dialog on Alt Space. We might want to
|
||||
// explicitly prevent that - for example when an action is bound to it. So similar to
|
||||
// above, we steal the event and hand it off to the host. When the host does not process
|
||||
// it, we will still dispatch like normal.
|
||||
if (_messageIsAltSpaceKeypress(message))
|
||||
{
|
||||
if (host.OnDirectKeyEvent(VK_SPACE, LOBYTE(HIWORD(message.lParam)), true))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
TranslateMessage(&message);
|
||||
DispatchMessage(&message);
|
||||
}
|
||||
|
|
|
@ -1639,6 +1639,30 @@ void DoSrvEndHyperlink(SCREEN_INFORMATION& screenInfo)
|
|||
screenInfo.GetTextBuffer().SetCurrentAttributes(attr);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - A private API call for updating the active soft font.
|
||||
// Arguments:
|
||||
// - bitPattern - An array of scanlines representing all the glyphs in the font.
|
||||
// - cellSize - The cell size for an individual glyph.
|
||||
// - centeringHint - The horizontal extent that glyphs are offset from center.
|
||||
// Return Value:
|
||||
// - S_OK if we succeeded, otherwise the HRESULT of the failure.
|
||||
[[nodiscard]] HRESULT DoSrvUpdateSoftFont(const gsl::span<const uint16_t> bitPattern,
|
||||
const SIZE cellSize,
|
||||
const size_t centeringHint) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
auto* pRender = ServiceLocator::LocateGlobals().pRender;
|
||||
if (pRender)
|
||||
{
|
||||
pRender->UpdateSoftFont(bitPattern, cellSize, centeringHint);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN();
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - A private API call for forcing the renderer to repaint the screen. If the
|
||||
// input screen buffer is not the active one, then just do nothing. We only
|
||||
|
|
|
@ -55,6 +55,10 @@ void DoSrvAddHyperlink(SCREEN_INFORMATION& screenInfo,
|
|||
|
||||
void DoSrvEndHyperlink(SCREEN_INFORMATION& screenInfo);
|
||||
|
||||
[[nodiscard]] HRESULT DoSrvUpdateSoftFont(const gsl::span<const uint16_t> bitPattern,
|
||||
const SIZE cellSize,
|
||||
const size_t centeringHint) noexcept;
|
||||
|
||||
void DoSrvPrivateRefreshWindow(const SCREEN_INFORMATION& screenInfo);
|
||||
|
||||
[[nodiscard]] HRESULT DoSrvSetConsoleOutputCodePage(const unsigned int codepage);
|
||||
|
|
|
@ -818,3 +818,18 @@ bool ConhostInternalGetSet::PrivateEndHyperlink() const
|
|||
DoSrvEndHyperlink(_io.GetActiveOutputBuffer());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Replaces the active soft font with the given bit pattern.
|
||||
// Arguments:
|
||||
// - bitPattern - An array of scanlines representing all the glyphs in the font.
|
||||
// - cellSize - The cell size for an individual glyph.
|
||||
// - centeringHint - The horizontal extent that glyphs are offset from center.
|
||||
// Return Value:
|
||||
// - true if successful (see DoSrvUpdateSoftFont). false otherwise.
|
||||
bool ConhostInternalGetSet::PrivateUpdateSoftFont(const gsl::span<const uint16_t> bitPattern,
|
||||
const SIZE cellSize,
|
||||
const size_t centeringHint) noexcept
|
||||
{
|
||||
return SUCCEEDED(DoSrvUpdateSoftFont(bitPattern, cellSize, centeringHint));
|
||||
}
|
||||
|
|
|
@ -147,6 +147,10 @@ public:
|
|||
bool PrivateAddHyperlink(const std::wstring_view uri, const std::wstring_view params) const override;
|
||||
bool PrivateEndHyperlink() const override;
|
||||
|
||||
bool PrivateUpdateSoftFont(const gsl::span<const uint16_t> bitPattern,
|
||||
const SIZE cellSize,
|
||||
const size_t centeringHint) noexcept override;
|
||||
|
||||
private:
|
||||
Microsoft::Console::IIoProvider& _io;
|
||||
};
|
||||
|
|
|
@ -2002,8 +2002,6 @@ void SCREEN_INFORMATION::UseMainScreenBuffer()
|
|||
|
||||
SCREEN_INFORMATION* psiAlt = psiMain->_psiAlternateBuffer;
|
||||
psiMain->_psiAlternateBuffer = nullptr;
|
||||
s_RemoveScreenBuffer(psiAlt); // this will also delete the alt buffer
|
||||
// deleting the alt buffer will give the GetSet back to its main
|
||||
|
||||
// Copy the alt buffer's cursor style and visibility back to the main buffer.
|
||||
const auto& altCursor = psiAlt->GetTextBuffer().GetCursor();
|
||||
|
@ -2012,6 +2010,9 @@ void SCREEN_INFORMATION::UseMainScreenBuffer()
|
|||
mainCursor.SetIsVisible(altCursor.IsVisible());
|
||||
mainCursor.SetBlinkingAllowed(altCursor.IsBlinkingAllowed());
|
||||
|
||||
s_RemoveScreenBuffer(psiAlt); // this will also delete the alt buffer
|
||||
// deleting the alt buffer will give the GetSet back to its main
|
||||
|
||||
// Tell the VT MouseInput handler that we're in the main buffer now
|
||||
gci.GetActiveInputBuffer()->GetTerminalInput().UseMainScreenBuffer();
|
||||
}
|
||||
|
|
|
@ -420,6 +420,7 @@ void VtRendererTest::Xterm256TestColors()
|
|||
qExpectedInput.push_back("\x1b[48;2;5;6;7m");
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes({ 0x00030201, 0x00070605 },
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
|
||||
TestPaint(*engine, [&]() {
|
||||
|
@ -428,6 +429,7 @@ void VtRendererTest::Xterm256TestColors()
|
|||
qExpectedInput.push_back("\x1b[48;2;7;8;9m");
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes({ 0x00030201, 0x00090807 },
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
|
@ -435,6 +437,7 @@ void VtRendererTest::Xterm256TestColors()
|
|||
qExpectedInput.push_back("\x1b[38;2;10;11;12m");
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes({ 0x000c0b0a, 0x00090807 },
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
});
|
||||
|
||||
|
@ -444,6 +447,7 @@ void VtRendererTest::Xterm256TestColors()
|
|||
qExpectedInput.push_back(EMPTY_CALLBACK_SENTINEL);
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes({ 0x000c0b0a, 0x00090807 },
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
WriteCallback(EMPTY_CALLBACK_SENTINEL, 1); // This will make sure nothing was written to the callback
|
||||
});
|
||||
|
@ -458,6 +462,7 @@ void VtRendererTest::Xterm256TestColors()
|
|||
qExpectedInput.push_back("\x1b[m");
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes({},
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
|
||||
TestPaint(*engine, [&]() {
|
||||
|
@ -469,6 +474,7 @@ void VtRendererTest::Xterm256TestColors()
|
|||
qExpectedInput.push_back("\x1b[41m"); // Background DARK_RED
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
|
@ -477,6 +483,7 @@ void VtRendererTest::Xterm256TestColors()
|
|||
qExpectedInput.push_back("\x1b[37m"); // Foreground DARK_WHITE
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
|
@ -485,6 +492,7 @@ void VtRendererTest::Xterm256TestColors()
|
|||
qExpectedInput.push_back("\x1b[48;2;19;161;14m"); // Background RGB(19,161,14)
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
|
@ -493,6 +501,7 @@ void VtRendererTest::Xterm256TestColors()
|
|||
qExpectedInput.push_back("\x1b[38;2;193;156;0m"); // Foreground RGB(193,156,0)
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
|
@ -501,6 +510,7 @@ void VtRendererTest::Xterm256TestColors()
|
|||
qExpectedInput.push_back("\x1b[49m"); // Background default
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
|
@ -509,6 +519,7 @@ void VtRendererTest::Xterm256TestColors()
|
|||
qExpectedInput.push_back("\x1b[38;5;7m"); // Foreground DARK_WHITE (256-Color Index)
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
|
@ -517,6 +528,7 @@ void VtRendererTest::Xterm256TestColors()
|
|||
qExpectedInput.push_back("\x1b[48;5;1m"); // Background DARK_RED (256-Color Index)
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
|
@ -525,6 +537,7 @@ void VtRendererTest::Xterm256TestColors()
|
|||
qExpectedInput.push_back("\x1b[39m"); // Background default
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
|
@ -533,6 +546,7 @@ void VtRendererTest::Xterm256TestColors()
|
|||
qExpectedInput.push_back("\x1b[m");
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
});
|
||||
|
||||
|
@ -542,6 +556,7 @@ void VtRendererTest::Xterm256TestColors()
|
|||
qExpectedInput.push_back(EMPTY_CALLBACK_SENTINEL);
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes({},
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
WriteCallback(EMPTY_CALLBACK_SENTINEL, 1); // This will make sure nothing was written to the callback
|
||||
});
|
||||
|
@ -795,7 +810,7 @@ void VtRendererTest::Xterm256TestAttributesAcrossReset()
|
|||
Log::Comment(L"----Start With All Attributes Reset----");
|
||||
TextAttribute textAttributes = {};
|
||||
qExpectedInput.push_back("\x1b[m");
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false));
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
||||
|
||||
switch (renditionAttribute)
|
||||
{
|
||||
|
@ -841,29 +856,29 @@ void VtRendererTest::Xterm256TestAttributesAcrossReset()
|
|||
break;
|
||||
}
|
||||
qExpectedInput.push_back(renditionSequence.str());
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false));
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
||||
|
||||
Log::Comment(L"----Set Green Foreground----");
|
||||
textAttributes.SetIndexedForeground(FOREGROUND_GREEN);
|
||||
qExpectedInput.push_back("\x1b[32m");
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false));
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
||||
|
||||
Log::Comment(L"----Reset Default Foreground and Retain Rendition----");
|
||||
textAttributes.SetDefaultForeground();
|
||||
qExpectedInput.push_back("\x1b[m");
|
||||
qExpectedInput.push_back(renditionSequence.str());
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false));
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
||||
|
||||
Log::Comment(L"----Set Green Background----");
|
||||
textAttributes.SetIndexedBackground(FOREGROUND_GREEN);
|
||||
qExpectedInput.push_back("\x1b[42m");
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false));
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
||||
|
||||
Log::Comment(L"----Reset Default Background and Retain Rendition----");
|
||||
textAttributes.SetDefaultBackground();
|
||||
qExpectedInput.push_back("\x1b[m");
|
||||
qExpectedInput.push_back(renditionSequence.str());
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false));
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
||||
|
||||
VerifyExpectedInputsDrained();
|
||||
}
|
||||
|
@ -1081,6 +1096,7 @@ void VtRendererTest::XtermTestColors()
|
|||
qExpectedInput.push_back("\x1b[m");
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes({},
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
|
||||
TestPaint(*engine, [&]() {
|
||||
|
@ -1092,6 +1108,7 @@ void VtRendererTest::XtermTestColors()
|
|||
qExpectedInput.push_back("\x1b[41m"); // Background DARK_RED
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
|
@ -1100,6 +1117,7 @@ void VtRendererTest::XtermTestColors()
|
|||
qExpectedInput.push_back("\x1b[37m"); // Foreground DARK_WHITE
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
|
@ -1108,6 +1126,7 @@ void VtRendererTest::XtermTestColors()
|
|||
qExpectedInput.push_back("\x1b[42m"); // Background DARK_GREEN
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
|
@ -1116,6 +1135,7 @@ void VtRendererTest::XtermTestColors()
|
|||
qExpectedInput.push_back("\x1b[33m"); // Foreground DARK_YELLOW
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
|
@ -1125,6 +1145,7 @@ void VtRendererTest::XtermTestColors()
|
|||
qExpectedInput.push_back("\x1b[33m"); // Reapply foreground DARK_YELLOW
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
|
@ -1133,6 +1154,7 @@ void VtRendererTest::XtermTestColors()
|
|||
qExpectedInput.push_back("\x1b[37m"); // Foreground DARK_WHITE
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
|
@ -1141,6 +1163,7 @@ void VtRendererTest::XtermTestColors()
|
|||
qExpectedInput.push_back("\x1b[41m"); // Background DARK_RED
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
|
@ -1150,6 +1173,7 @@ void VtRendererTest::XtermTestColors()
|
|||
qExpectedInput.push_back("\x1b[41m"); // Reapply background DARK_RED
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
|
@ -1158,6 +1182,7 @@ void VtRendererTest::XtermTestColors()
|
|||
qExpectedInput.push_back("\x1b[m");
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
});
|
||||
|
||||
|
@ -1167,6 +1192,7 @@ void VtRendererTest::XtermTestColors()
|
|||
qExpectedInput.push_back(EMPTY_CALLBACK_SENTINEL);
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes({},
|
||||
&renderData,
|
||||
false,
|
||||
false));
|
||||
WriteCallback(EMPTY_CALLBACK_SENTINEL, 1); // This will make sure nothing was written to the callback
|
||||
});
|
||||
|
@ -1304,7 +1330,7 @@ void VtRendererTest::XtermTestAttributesAcrossReset()
|
|||
Log::Comment(L"----Start With All Attributes Reset----");
|
||||
TextAttribute textAttributes = {};
|
||||
qExpectedInput.push_back("\x1b[m");
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false));
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
||||
|
||||
switch (renditionAttribute)
|
||||
{
|
||||
|
@ -1322,29 +1348,29 @@ void VtRendererTest::XtermTestAttributesAcrossReset()
|
|||
break;
|
||||
}
|
||||
qExpectedInput.push_back(renditionSequence.str());
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false));
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
||||
|
||||
Log::Comment(L"----Set Green Foreground----");
|
||||
textAttributes.SetIndexedForeground(FOREGROUND_GREEN);
|
||||
qExpectedInput.push_back("\x1b[32m");
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false));
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
||||
|
||||
Log::Comment(L"----Reset Default Foreground and Retain Rendition----");
|
||||
textAttributes.SetDefaultForeground();
|
||||
qExpectedInput.push_back("\x1b[m");
|
||||
qExpectedInput.push_back(renditionSequence.str());
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false));
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
||||
|
||||
Log::Comment(L"----Set Green Background----");
|
||||
textAttributes.SetIndexedBackground(FOREGROUND_GREEN);
|
||||
qExpectedInput.push_back("\x1b[42m");
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false));
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
||||
|
||||
Log::Comment(L"----Reset Default Background and Retain Rendition----");
|
||||
textAttributes.SetDefaultBackground();
|
||||
qExpectedInput.push_back("\x1b[m");
|
||||
qExpectedInput.push_back(renditionSequence.str());
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false));
|
||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
||||
|
||||
VerifyExpectedInputsDrained();
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue