Compare commits
44 commits
main
...
dev/miniks
Author | SHA1 | Date | |
---|---|---|---|
d96d72dc03 | |||
51fd5ccf0f | |||
0f25531550 | |||
a6271ed4c5 | |||
776d81866c | |||
660b4d9645 | |||
cec074ba3e | |||
48859a0259 | |||
ce55b0b810 | |||
3e9ee865d6 | |||
880f739c30 | |||
07337dd2cc | |||
0e41d8adc0 | |||
3b67f34e6b | |||
b8a324fd2b | |||
752ab6ce71 | |||
4176523139 | |||
91f1cf1eb3 | |||
4642ccfa15 | |||
daf815f38e | |||
5795247486 | |||
3691791751 | |||
93831f1bbc | |||
a99a430950 | |||
0a7d3a9744 | |||
8b21babbb7 | |||
23445c7407 | |||
fdd80177ba | |||
7551212f26 | |||
fe40978f86 | |||
48f619992c | |||
5bcbde25a4 | |||
326decb0e9 | |||
9f9af2eb94 | |||
384bf498f1 | |||
12e8d6c958 | |||
041e5ce3ae | |||
e4fced6810 | |||
f8003d32c4 | |||
7b1eefe50a | |||
0c8168be92 | |||
d1c974830b | |||
da2cad83a6 | |||
6373bae6c3 |
7
.github/actions/spelling/allow/math.txt
vendored
7
.github/actions/spelling/allow/math.txt
vendored
|
@ -1,3 +1,10 @@
|
|||
atan
|
||||
CPrime
|
||||
HBar
|
||||
HPrime
|
||||
isnan
|
||||
LPrime
|
||||
LStep
|
||||
powf
|
||||
RSub
|
||||
sqrtf
|
||||
|
|
6
.github/actions/spelling/expect/expect.txt
vendored
6
.github/actions/spelling/expect/expect.txt
vendored
|
@ -189,13 +189,12 @@ cacafire
|
|||
callee
|
||||
capslock
|
||||
CARETBLINKINGENABLED
|
||||
carlos
|
||||
CARRIAGERETURN
|
||||
cascadia
|
||||
cassert
|
||||
castsi
|
||||
catid
|
||||
carlos
|
||||
zamora
|
||||
cazamor
|
||||
CBash
|
||||
cbegin
|
||||
|
@ -1232,6 +1231,7 @@ KLF
|
|||
KLMNO
|
||||
KLMNOPQRST
|
||||
KLMNOPQRSTQQQQQ
|
||||
KPRIORITY
|
||||
KVM
|
||||
langid
|
||||
LANGUAGELIST
|
||||
|
@ -1803,6 +1803,7 @@ POSX
|
|||
POSXSCROLL
|
||||
POSYSCROLL
|
||||
ppci
|
||||
PPEB
|
||||
ppf
|
||||
ppguid
|
||||
ppidl
|
||||
|
@ -2850,6 +2851,7 @@ YSize
|
|||
YSubstantial
|
||||
YVIRTUALSCREEN
|
||||
YWalk
|
||||
zamora
|
||||
ZCmd
|
||||
ZCtrl
|
||||
zsh
|
||||
|
|
2
.github/actions/spelling/expect/web.txt
vendored
2
.github/actions/spelling/expect/web.txt
vendored
|
@ -1,5 +1,7 @@
|
|||
http
|
||||
www
|
||||
easyrgb
|
||||
php
|
||||
ecma
|
||||
rapidtables
|
||||
WCAG
|
||||
|
|
37
NOTICE.md
37
NOTICE.md
|
@ -252,6 +252,43 @@ DEALINGS IN THE SOFTWARE.
|
|||
|
||||
```
|
||||
|
||||
## ConEmu
|
||||
**Source**: [https://github.com/Maximus5/ConEmu](https://github.com/Maximus5/ConEmu)
|
||||
|
||||
### License
|
||||
|
||||
```
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2009-2017, Maximus5 <ConEmu.Maximus5@gmail.com>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
```
|
||||
|
||||
# Microsoft Open Source
|
||||
|
||||
This product also incorporates source code from other Microsoft open source projects, all licensed under the MIT license.
|
||||
|
|
|
@ -188,6 +188,10 @@
|
|||
],
|
||||
"type": "string"
|
||||
},
|
||||
"perceptualColorNudging": {
|
||||
"description": "When set to true, we will (when necessary) 'nudge' the foreground color to make it more visible, based on the background color.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"experimental.retroTerminalEffect": {
|
||||
"description": "When set to true, enable retro terminal effects when unfocused. This is an experimental feature, and its continued existence is not guaranteed.",
|
||||
"type": "boolean"
|
||||
|
@ -1973,6 +1977,10 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"perceptualColorNudging": {
|
||||
"description": "When set to true, we will (when necessary) 'nudge' the foreground color to make it more visible, based on the background color.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"scrollbarState": {
|
||||
"default": "visible",
|
||||
"description": "Defines the visibility of the scrollbar.",
|
||||
|
|
|
@ -718,6 +718,9 @@
|
|||
<data name="CloseOnExitInfoBar.Message" xml:space="preserve">
|
||||
<value>Termination behavior can be configured in advanced profile settings.</value>
|
||||
</data>
|
||||
<data name="SetAsDefaultInfoBar.Message" xml:space="preserve">
|
||||
<value>Windows Terminal can be set as your default terminal application in your settings.</value>
|
||||
</data>
|
||||
<data name="InfoBarDismissButton.Content" xml:space="preserve">
|
||||
<value>Don't show again</value>
|
||||
</data>
|
||||
|
|
|
@ -218,7 +218,7 @@ namespace winrt::TerminalApp::implementation
|
|||
_RegisterActionCallbacks();
|
||||
|
||||
// Hook up inbound connection event handler
|
||||
TerminalConnection::ConptyConnection::NewConnection({ this, &TerminalPage::_OnNewConnection });
|
||||
ConptyConnection::NewConnection({ this, &TerminalPage::_OnNewConnection });
|
||||
|
||||
//Event Bindings (Early)
|
||||
_newTabButton.Click([weakThis{ get_weak() }](auto&&, auto&&) {
|
||||
|
@ -287,6 +287,11 @@ namespace winrt::TerminalApp::implementation
|
|||
_defaultPointerCursor = CoreWindow::GetForCurrentThread().PointerCursor();
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
if (CascadiaSettings::IsDefaultTerminalAvailable())
|
||||
{
|
||||
ShowSetAsDefaultInfoBar();
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description;
|
||||
|
@ -2695,38 +2700,13 @@ namespace winrt::TerminalApp::implementation
|
|||
return _isAlwaysOnTop;
|
||||
}
|
||||
|
||||
HRESULT TerminalPage::_OnNewConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection connection)
|
||||
HRESULT TerminalPage::_OnNewConnection(const ConptyConnection& 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())
|
||||
{
|
||||
try
|
||||
{
|
||||
NewTerminalArgs newTerminalArgs{};
|
||||
// TODO GH#10952: When we pass the actual commandline (or originating application), the
|
||||
// settings model can choose the right settings based on command matching, or synthesize
|
||||
// a profile from the registry/link settings (TODO GH#9458).
|
||||
// TODO GH#9458: Get and pass the LNK/EXE filenames.
|
||||
// Passing in a commandline forces GetProfileForArgs to use Base Layer instead of Default Profile;
|
||||
// in the future, it can make a better decision based on the value we pull out of the process handle.
|
||||
// TODO GH#5047: When we hang on to the N.T.A., try not to spawn "default... .exe" :)
|
||||
newTerminalArgs.Commandline(L"default-terminal-invocation-placeholder");
|
||||
const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) };
|
||||
const auto settings{ TerminalSettings::CreateWithProfile(_settings, profile, *_bindings) };
|
||||
|
||||
_CreateNewTabWithProfileAndSettings(profile, settings, connection);
|
||||
|
||||
// Request a summon of this window to the foreground
|
||||
_SummonWindowRequestedHandlers(*this, nullptr);
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
if (!Dispatcher().HasThreadAccess())
|
||||
{
|
||||
til::latch latch{ 1 };
|
||||
HRESULT finalVal = S_OK;
|
||||
|
@ -2734,13 +2714,27 @@ namespace winrt::TerminalApp::implementation
|
|||
Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [&]() {
|
||||
// Re-running ourselves under the dispatcher will cause us to take the first branch above.
|
||||
finalVal = _OnNewConnection(connection);
|
||||
|
||||
latch.count_down();
|
||||
});
|
||||
|
||||
latch.wait();
|
||||
return finalVal;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
NewTerminalArgs newTerminalArgs;
|
||||
newTerminalArgs.Commandline(connection.Commandline());
|
||||
const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) };
|
||||
const auto settings{ TerminalSettings::CreateWithProfile(_settings, profile, *_bindings) };
|
||||
|
||||
_CreateNewTabWithProfileAndSettings(profile, settings, connection);
|
||||
|
||||
// Request a summon of this window to the foreground
|
||||
_SummonWindowRequestedHandlers(*this, nullptr);
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN()
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -2893,6 +2887,19 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Displays a info popup guiding the user into setting their default terminal.
|
||||
void TerminalPage::ShowSetAsDefaultInfoBar() const
|
||||
{
|
||||
if (!_IsMessageDismissed(InfoBarMessage::SetAsDefault))
|
||||
{
|
||||
if (const auto infoBar = FindName(L"SetAsDefaultInfoBar").try_as<MUX::Controls::InfoBar>())
|
||||
{
|
||||
infoBar.IsOpen(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Helper function to get the OS-localized name for the "Touch Keyboard
|
||||
// and Handwriting Panel Service". If we can't open up the service for any
|
||||
|
@ -3313,6 +3320,22 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Persists the user's choice not to show the information bar warning about "Windows Terminal can be set as your default terminal application"
|
||||
// Then hides this information buffer.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalPage::_SetAsDefaultDismissHandler(const IInspectable& /*sender*/, const IInspectable& /*args*/) const
|
||||
{
|
||||
_DismissMessage(InfoBarMessage::SetAsDefault);
|
||||
if (const auto infoBar = FindName(L"SetAsDefaultInfoBar").try_as<MUX::Controls::InfoBar>())
|
||||
{
|
||||
infoBar.IsOpen(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Checks whether information bar message was dismissed earlier (in the application state)
|
||||
// Arguments:
|
||||
|
@ -3342,13 +3365,20 @@ namespace winrt::TerminalApp::implementation
|
|||
// - <none>
|
||||
void TerminalPage::_DismissMessage(const InfoBarMessage& message)
|
||||
{
|
||||
auto dismissedMessages = ApplicationState::SharedInstance().DismissedMessages();
|
||||
if (!dismissedMessages)
|
||||
const auto applicationState = ApplicationState::SharedInstance();
|
||||
std::vector<InfoBarMessage> messages;
|
||||
|
||||
if (const auto values = applicationState.DismissedMessages())
|
||||
{
|
||||
dismissedMessages = winrt::single_threaded_vector<InfoBarMessage>();
|
||||
messages.resize(values.Size());
|
||||
values.GetMany(0, messages);
|
||||
}
|
||||
|
||||
dismissedMessages.Append(message);
|
||||
ApplicationState::SharedInstance().DismissedMessages(dismissedMessages);
|
||||
if (std::none_of(messages.begin(), messages.end(), [&](const auto& m) { return m == message; }))
|
||||
{
|
||||
messages.emplace_back(message);
|
||||
}
|
||||
|
||||
applicationState.DismissedMessages(std::move(messages));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,6 +95,7 @@ namespace winrt::TerminalApp::implementation
|
|||
winrt::TerminalApp::TaskbarState TaskbarState() const;
|
||||
|
||||
void ShowKeyboardServiceWarning() const;
|
||||
void ShowSetAsDefaultInfoBar() const;
|
||||
winrt::hstring KeyboardServiceDisabledText();
|
||||
|
||||
winrt::fire_and_forget IdentifyWindow();
|
||||
|
@ -387,7 +388,7 @@ namespace winrt::TerminalApp::implementation
|
|||
winrt::Microsoft::Terminal::Settings::Model::Command _lastPreviewedCommand{ nullptr };
|
||||
std::vector<std::function<void()>> _restorePreviewFuncs{};
|
||||
|
||||
HRESULT _OnNewConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection connection);
|
||||
HRESULT _OnNewConnection(const winrt::Microsoft::Terminal::TerminalConnection::ConptyConnection& connection);
|
||||
void _HandleToggleInboundPty(const IInspectable& sender, const Microsoft::Terminal::Settings::Model::ActionEventArgs& args);
|
||||
|
||||
void _WindowRenamerActionClick(const IInspectable& sender, const IInspectable& eventArgs);
|
||||
|
@ -403,6 +404,7 @@ namespace winrt::TerminalApp::implementation
|
|||
winrt::fire_and_forget _ConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
|
||||
void _CloseOnExitInfoDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
|
||||
void _KeyboardServiceWarningInfoDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
|
||||
void _SetAsDefaultDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
|
||||
static bool _IsMessageDismissed(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message);
|
||||
static void _DismissMessage(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message);
|
||||
|
||||
|
|
|
@ -141,6 +141,19 @@
|
|||
Click="_CloseOnExitInfoDismissHandler" />
|
||||
</mux:InfoBar.ActionButton>
|
||||
</mux:InfoBar>
|
||||
|
||||
<mux:InfoBar x:Name="SetAsDefaultInfoBar"
|
||||
x:Uid="SetAsDefaultInfoBar"
|
||||
x:Load="False"
|
||||
IsClosable="True"
|
||||
IsIconVisible="True"
|
||||
IsOpen="False"
|
||||
Severity="Informational">
|
||||
<mux:InfoBar.ActionButton>
|
||||
<Button x:Uid="InfoBarDismissButton"
|
||||
Click="_SetAsDefaultDismissHandler" />
|
||||
</mux:InfoBar.ActionButton>
|
||||
</mux:InfoBar>
|
||||
</StackPanel>
|
||||
|
||||
<!--
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include "ConptyConnection.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <userenv.h>
|
||||
#include <UserEnv.h>
|
||||
#include <winternl.h>
|
||||
|
||||
#include "ConptyConnection.g.cpp"
|
||||
#include "CTerminalHandoff.h"
|
||||
|
@ -276,24 +276,17 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
const HANDLE hClientProcess) :
|
||||
_initialRows{ 25 },
|
||||
_initialCols{ 80 },
|
||||
_commandline{ L"" },
|
||||
_startingDirectory{ L"" },
|
||||
_startingTitle{ L"" },
|
||||
_environment{ nullptr },
|
||||
_guid{},
|
||||
_u8State{},
|
||||
_u16Str{},
|
||||
_buffer{},
|
||||
_inPipe{ hIn },
|
||||
_outPipe{ hOut }
|
||||
{
|
||||
THROW_IF_FAILED(ConptyPackPseudoConsole(hServerProcess, hRef, hSig, &_hPC));
|
||||
if (_guid == guid{})
|
||||
{
|
||||
_guid = Utils::CreateGuid();
|
||||
}
|
||||
|
||||
_piClient.hProcess = hClientProcess;
|
||||
|
||||
try
|
||||
{
|
||||
_commandline = _commandlineFromProcess(hClientProcess);
|
||||
}
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
|
@ -355,6 +348,11 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
return _guid;
|
||||
}
|
||||
|
||||
winrt::hstring ConptyConnection::Commandline() const
|
||||
{
|
||||
return _commandline;
|
||||
}
|
||||
|
||||
void ConptyConnection::Start()
|
||||
try
|
||||
{
|
||||
|
@ -560,6 +558,41 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
}
|
||||
CATCH_LOG()
|
||||
|
||||
// Returns the command line of the given process.
|
||||
// Requires PROCESS_BASIC_INFORMATION | PROCESS_VM_READ privileges.
|
||||
winrt::hstring ConptyConnection::_commandlineFromProcess(HANDLE process)
|
||||
{
|
||||
// I know MSDN documents NtQueryInformationProcess with Reserved1/2/3
|
||||
// fields, but... uh... that feels like security by obfuscation.
|
||||
// .NET kindly published this struct before us.
|
||||
struct PROCESS_BASIC_INFORMATION
|
||||
{
|
||||
NTSTATUS ExitStatus;
|
||||
PPEB PebBaseAddress;
|
||||
ULONG_PTR AffinityMask;
|
||||
KPRIORITY BasePriority;
|
||||
ULONG_PTR UniqueProcessId;
|
||||
ULONG_PTR InheritedFromUniqueProcessId;
|
||||
} info;
|
||||
THROW_IF_NTSTATUS_FAILED(NtQueryInformationProcess(process, ProcessBasicInformation, &info, sizeof(info), nullptr));
|
||||
|
||||
// PEB: Process Environment Block
|
||||
// This is a funny structure allocated by the kernel which contains all sorts of useful
|
||||
// information, only a tiny fraction of which are documented publicly unfortunately.
|
||||
// Fortunately however it contains a copy of the command line the process launched with.
|
||||
PEB peb;
|
||||
THROW_IF_WIN32_BOOL_FALSE(ReadProcessMemory(process, info.PebBaseAddress, &peb, sizeof(peb), nullptr));
|
||||
|
||||
RTL_USER_PROCESS_PARAMETERS params;
|
||||
THROW_IF_WIN32_BOOL_FALSE(ReadProcessMemory(process, peb.ProcessParameters, ¶ms, sizeof(params), nullptr));
|
||||
|
||||
// Yeah I know... Don't use "impl" stuff... But why do you make something _that_ useful private? :(
|
||||
// The hstring_builder allows us to create a hstring without intermediate copies. Neat!
|
||||
winrt::impl::hstring_builder commandline{ params.CommandLine.Length / 2u };
|
||||
THROW_IF_WIN32_BOOL_FALSE(ReadProcessMemory(process, params.CommandLine.Buffer, commandline.data(), params.CommandLine.Length, nullptr));
|
||||
return commandline.to_hstring();
|
||||
}
|
||||
|
||||
DWORD ConptyConnection::_OutputThread()
|
||||
{
|
||||
// Keep us alive until the output thread terminates; the destructor
|
||||
|
@ -636,8 +669,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
HRESULT ConptyConnection::NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client) noexcept
|
||||
try
|
||||
{
|
||||
auto conn = winrt::make<implementation::ConptyConnection>(signal, in, out, ref, server, client);
|
||||
_newConnectionHandlers(conn);
|
||||
_newConnectionHandlers(winrt::make<ConptyConnection>(signal, in, out, ref, server, client));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
void ClearBuffer();
|
||||
|
||||
winrt::guid Guid() const noexcept;
|
||||
winrt::hstring Commandline() const;
|
||||
|
||||
static void StartInboundListener();
|
||||
static void StopInboundListener();
|
||||
|
@ -56,12 +57,13 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
WINRT_CALLBACK(TerminalOutput, TerminalOutputHandler);
|
||||
|
||||
private:
|
||||
static HRESULT NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client) noexcept;
|
||||
static winrt::hstring _commandlineFromProcess(HANDLE process);
|
||||
|
||||
HRESULT _LaunchAttachedClient() noexcept;
|
||||
void _indicateExitWithStatus(unsigned int status) noexcept;
|
||||
void _ClientTerminated() noexcept;
|
||||
|
||||
static HRESULT NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client) noexcept;
|
||||
|
||||
uint32_t _initialRows{};
|
||||
uint32_t _initialCols{};
|
||||
hstring _commandline{};
|
||||
|
|
|
@ -5,10 +5,13 @@ import "ITerminalConnection.idl";
|
|||
|
||||
namespace Microsoft.Terminal.TerminalConnection
|
||||
{
|
||||
delegate void NewConnectionHandler(ConptyConnection connection);
|
||||
|
||||
[default_interface] runtimeclass ConptyConnection : ITerminalConnection
|
||||
{
|
||||
ConptyConnection();
|
||||
Guid Guid { get; };
|
||||
String Commandline { get; };
|
||||
void ClearBuffer();
|
||||
|
||||
static event NewConnectionHandler NewConnection;
|
||||
|
|
|
@ -29,6 +29,4 @@ namespace Microsoft.Terminal.TerminalConnection
|
|||
event Windows.Foundation.TypedEventHandler<ITerminalConnection, Object> StateChanged;
|
||||
ConnectionState State { get; };
|
||||
};
|
||||
|
||||
delegate void NewConnectionHandler(ITerminalConnection connection);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,22 @@ constexpr const auto UpdatePatternLocationsInterval = std::chrono::milliseconds(
|
|||
|
||||
namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
{
|
||||
// Helper to check if we're on Windows 11 or not. This is used to check if
|
||||
// we need to use acrylic to achieve transparency, because vintage opacity
|
||||
// doesn't work in islands on win10.
|
||||
// Remove when we can remove the rest of GH#11285
|
||||
static bool _isVintageOpacityAvailable() noexcept
|
||||
{
|
||||
OSVERSIONINFOEXW osver{};
|
||||
osver.dwOSVersionInfoSize = sizeof(osver);
|
||||
osver.dwBuildNumber = 22000; // TODO! switch me to 22000
|
||||
|
||||
DWORDLONG dwlConditionMask = 0;
|
||||
VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
|
||||
|
||||
return VerifyVersionInfoW(&osver, VER_BUILDNUMBER, dwlConditionMask) != FALSE;
|
||||
}
|
||||
|
||||
// Helper static function to ensure that all ambiguous-width glyphs are reported as narrow.
|
||||
// See microsoft/terminal#2066 for more info.
|
||||
static bool _IsGlyphWideForceNarrowFallback(const std::wstring_view /* glyph */)
|
||||
|
@ -442,6 +458,24 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
_settings.Opacity(newOpacity);
|
||||
|
||||
// GH#11285 - If the user is on Windows 10, and they changed the
|
||||
// transparency of the control s.t. it should be partially opaque, then
|
||||
// opt them in to acrylic. It's the only way to have transparency on
|
||||
// Windows 10.
|
||||
// We'll also turn the acrylic back off when they're fully opaque, which
|
||||
// is what the Terminal did prior to 1.12.
|
||||
if (!_isVintageOpacityAvailable())
|
||||
{
|
||||
if (newOpacity < 1.0)
|
||||
{
|
||||
_settings.UseAcrylic(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
_settings.UseAcrylic(false);
|
||||
}
|
||||
}
|
||||
|
||||
auto eventArgs = winrt::make_self<TransparencyChangedEventArgs>(newOpacity);
|
||||
_TransparencyChangedHandlers(*this, *eventArgs);
|
||||
}
|
||||
|
@ -570,6 +604,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
_settings = settings;
|
||||
|
||||
// GH#11285 - If the user is on Windows 10, and they wanted opacity, but
|
||||
// didn't explicitly request acrylic, then opt them in to acrylic.
|
||||
// On Windows 11+, this isn't needed, because we can have vintage opacity.
|
||||
if (!_isVintageOpacityAvailable() && _settings.Opacity() < 1.0 && !_settings.UseAcrylic())
|
||||
{
|
||||
_settings.UseAcrylic(true);
|
||||
}
|
||||
|
||||
// Initialize our font information.
|
||||
const auto fontFace = _settings.FontFace();
|
||||
const short fontHeight = ::base::saturated_cast<short>(_settings.FontSize());
|
||||
|
|
233
src/cascadia/TerminalCore/ColorFix.cpp
Normal file
233
src/cascadia/TerminalCore/ColorFix.cpp
Normal file
|
@ -0,0 +1,233 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
// A lot of code was taken from
|
||||
// https://github.com/Maximus5/ConEmu/blob/master/src/ConEmu/ColorFix.cpp
|
||||
// and then adjusted to fit our style guidelines
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include "ColorFix.hpp"
|
||||
|
||||
static constexpr double gMinThreshold = 12.0;
|
||||
static constexpr double gExpThreshold = 20.0;
|
||||
static constexpr double gLStep = 5.0;
|
||||
|
||||
static constexpr double rad006 = 0.104719755119659774;
|
||||
static constexpr double rad025 = 0.436332312998582394;
|
||||
static constexpr double rad030 = 0.523598775598298873;
|
||||
static constexpr double rad060 = 1.047197551196597746;
|
||||
static constexpr double rad063 = 1.099557428756427633;
|
||||
static constexpr double rad180 = 3.141592653589793238;
|
||||
static constexpr double rad275 = 4.799655442984406336;
|
||||
static constexpr double rad360 = 6.283185307179586476;
|
||||
|
||||
ColorFix::ColorFix(COLORREF color)
|
||||
{
|
||||
rgb = color;
|
||||
_ToLab();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Helper function to calculate HPrime
|
||||
double ColorFix::_GetHPrimeFn(double x, double y)
|
||||
{
|
||||
if (x == 0 && y == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const auto hueAngle = atan2(x, y);
|
||||
return hueAngle >= 0 ? hueAngle : hueAngle + rad360;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Given 2 colors, computes the DeltaE value between them
|
||||
// Arguments:
|
||||
// - x1: the first color
|
||||
// - x2: the second color
|
||||
// Return Value:
|
||||
// - The DeltaE value between x1 and x2
|
||||
double ColorFix::_GetDeltaE(ColorFix x1, ColorFix x2)
|
||||
{
|
||||
constexpr double kSubL = 1;
|
||||
constexpr double kSubC = 1;
|
||||
constexpr double kSubH = 1;
|
||||
|
||||
// Delta L Prime
|
||||
const double deltaLPrime = x2.L - x1.L;
|
||||
|
||||
// L Bar
|
||||
const double lBar = (x1.L + x2.L) / 2;
|
||||
|
||||
// C1 & C2
|
||||
const double c1 = sqrt(pow(x1.A, 2) + pow(x1.B, 2));
|
||||
const double c2 = sqrt(pow(x2.A, 2) + pow(x2.B, 2));
|
||||
|
||||
// C Bar
|
||||
const double cBar = (c1 + c2) / 2;
|
||||
|
||||
// A Prime 1
|
||||
const double aPrime1 = x1.A + (x1.A / 2) * (1 - sqrt(pow(cBar, 7) / (pow(cBar, 7) + pow(25.0, 7))));
|
||||
|
||||
// A Prime 2
|
||||
const double aPrime2 = x2.A + (x2.A / 2) * (1 - sqrt(pow(cBar, 7) / (pow(cBar, 7) + pow(25.0, 7))));
|
||||
|
||||
// C Prime 1
|
||||
const double cPrime1 = sqrt(pow(aPrime1, 2) + pow(x1.B, 2));
|
||||
|
||||
// C Prime 2
|
||||
const double cPrime2 = sqrt(pow(aPrime2, 2) + pow(x2.B, 2));
|
||||
|
||||
// C Bar Prime
|
||||
const double cBarPrime = (cPrime1 + cPrime2) / 2;
|
||||
|
||||
// Delta C Prime
|
||||
const double deltaCPrime = cPrime2 - cPrime1;
|
||||
|
||||
// S sub L
|
||||
const double sSubL = 1 + ((0.015 * pow(lBar - 50, 2)) / sqrt(20 + pow(lBar - 50, 2)));
|
||||
|
||||
// S sub C
|
||||
const double sSubC = 1 + 0.045 * cBarPrime;
|
||||
|
||||
// h Prime 1
|
||||
const double hPrime1 = _GetHPrimeFn(x1.B, aPrime1);
|
||||
|
||||
// h Prime 2
|
||||
const double hPrime2 = _GetHPrimeFn(x2.B, aPrime2);
|
||||
|
||||
// Delta H Prime
|
||||
const double deltaHPrime = 0 == c1 || 0 == c2 ? 0 : 2 * sqrt(cPrime1 * cPrime2) * sin(abs(hPrime1 - hPrime2) <= rad180 ? hPrime2 - hPrime1 : (hPrime2 <= hPrime1 ? hPrime2 - hPrime1 + rad360 : hPrime2 - hPrime1 - rad360) / 2);
|
||||
|
||||
// H Bar Prime
|
||||
const double hBarPrime = (abs(hPrime1 - hPrime2) > rad180) ? (hPrime1 + hPrime2 + rad360) / 2 : (hPrime1 + hPrime2) / 2;
|
||||
|
||||
// T
|
||||
const double t = 1 - 0.17 * cos(hBarPrime - rad030) + 0.24 * cos(2 * hBarPrime) + 0.32 * cos(3 * hBarPrime + rad006) - 0.20 * cos(4 * hBarPrime - rad063);
|
||||
|
||||
// S sub H
|
||||
const double sSubH = 1 + 0.015 * cBarPrime * t;
|
||||
|
||||
// R sub T
|
||||
const double rSubT = -2 * sqrt(pow(cBarPrime, 7) / (pow(cBarPrime, 7) + pow(25.0, 7))) * sin(rad060 * exp(-pow((hBarPrime - rad275) / rad025, 2)));
|
||||
|
||||
// Put it all together!
|
||||
const double lightness = deltaLPrime / (kSubL * sSubL);
|
||||
const double chroma = deltaCPrime / (kSubC * sSubC);
|
||||
const double hue = deltaHPrime / (kSubH * sSubH);
|
||||
|
||||
return sqrt(pow(lightness, 2) + pow(chroma, 2) + pow(hue, 2) + rSubT * chroma * hue);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Populates our L, A, B values, based on our r, g, b values
|
||||
// - Converts a color in rgb format to a color in lab format
|
||||
// - Reference: http://www.easyrgb.com/index.php?X=MATH&H=01#text1
|
||||
void ColorFix::_ToLab()
|
||||
{
|
||||
double var_R = r / 255.0;
|
||||
double var_G = g / 255.0;
|
||||
double var_B = b / 255.0;
|
||||
|
||||
var_R = var_R > 0.04045 ? pow(((var_R + 0.055) / 1.055), 2.4) : var_R / 12.92;
|
||||
var_G = var_G > 0.04045 ? pow(((var_G + 0.055) / 1.055), 2.4) : var_G / 12.92;
|
||||
var_B = var_B > 0.04045 ? pow(((var_B + 0.055) / 1.055), 2.4) : var_B / 12.92;
|
||||
|
||||
var_R = var_R * 100.;
|
||||
var_G = var_G * 100.;
|
||||
var_B = var_B * 100.;
|
||||
|
||||
//Observer. = 2 degrees, Illuminant = D65
|
||||
const double X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805;
|
||||
const double Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722;
|
||||
const double Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505;
|
||||
|
||||
double var_X = X / 95.047; //ref_X = 95.047 (Observer= 2 degrees, Illuminant= D65)
|
||||
double var_Y = Y / 100.000; //ref_Y = 100.000
|
||||
double var_Z = Z / 108.883; //ref_Z = 108.883
|
||||
|
||||
var_X = var_X > 0.008856 ? pow(var_X, (1. / 3.)) : (7.787 * var_X) + (16. / 116.);
|
||||
var_Y = var_Y > 0.008856 ? pow(var_Y, (1. / 3.)) : (7.787 * var_Y) + (16. / 116.);
|
||||
var_Z = var_Z > 0.008856 ? pow(var_Z, (1. / 3.)) : (7.787 * var_Z) + (16. / 116.);
|
||||
|
||||
L = (116. * var_Y) - 16.;
|
||||
A = 500. * (var_X - var_Y);
|
||||
B = 200. * (var_Y - var_Z);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Populates our r, g, b values, based on our L, A, B values
|
||||
// - Converts a color in lab format to a color in rgb format
|
||||
// - Reference: http://www.easyrgb.com/index.php?X=MATH&H=01#text1
|
||||
void ColorFix::_ToRGB()
|
||||
{
|
||||
double var_Y = (L + 16.) / 116.;
|
||||
double var_X = A / 500. + var_Y;
|
||||
double var_Z = var_Y - B / 200.;
|
||||
|
||||
var_Y = (pow(var_Y, 3) > 0.008856) ? pow(var_Y, 3) : (var_Y - 16. / 116.) / 7.787;
|
||||
var_X = (pow(var_X, 3) > 0.008856) ? pow(var_X, 3) : (var_X - 16. / 116.) / 7.787;
|
||||
var_Z = (pow(var_Z, 3) > 0.008856) ? pow(var_Z, 3) : (var_Z - 16. / 116.) / 7.787;
|
||||
|
||||
double X = 95.047 * var_X; //ref_X = 95.047 (Observer= 2 degrees, Illuminant= D65)
|
||||
double Y = 100.000 * var_Y; //ref_Y = 100.000
|
||||
double Z = 108.883 * var_Z; //ref_Z = 108.883
|
||||
|
||||
var_X = X / 100.; //X from 0 to 95.047 (Observer = 2 degrees, Illuminant = D65)
|
||||
var_Y = Y / 100.; //Y from 0 to 100.000
|
||||
var_Z = Z / 100.; //Z from 0 to 108.883
|
||||
|
||||
double var_R = var_X * 3.2406 + var_Y * -1.5372 + var_Z * -0.4986;
|
||||
double var_G = var_X * -0.9689 + var_Y * 1.8758 + var_Z * 0.0415;
|
||||
double var_B = var_X * 0.0557 + var_Y * -0.2040 + var_Z * 1.0570;
|
||||
|
||||
var_R = var_R > 0.0031308 ? 1.055 * pow(var_R, (1 / 2.4)) - 0.055 : var_R = 12.92 * var_R;
|
||||
var_G = var_G > 0.0031308 ? 1.055 * pow(var_G, (1 / 2.4)) - 0.055 : var_G = 12.92 * var_G;
|
||||
var_B = var_B > 0.0031308 ? 1.055 * pow(var_B, (1 / 2.4)) - 0.055 : var_B = 12.92 * var_B;
|
||||
|
||||
r = (BYTE)std::clamp(var_R * 255., 0., 255.);
|
||||
g = (BYTE)std::clamp(var_G * 255., 0., 255.);
|
||||
b = (BYTE)std::clamp(var_B * 255., 0., 255.);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Given foreground and background colors, change the foreground color to
|
||||
// make it more perceivable if necessary
|
||||
// - Arguments:
|
||||
// - fg: the foreground color
|
||||
// - bg: the background color
|
||||
// - Return Value:
|
||||
// - The foreground color after performing any necessary changes to make it more perceivable
|
||||
COLORREF ColorFix::GetPerceivableColor(COLORREF fg, COLORREF bg)
|
||||
{
|
||||
// If the colors are the same, don't do any adjusting
|
||||
if (fg == bg)
|
||||
{
|
||||
return fg;
|
||||
}
|
||||
ColorFix backLab(bg);
|
||||
ColorFix frontLab(fg);
|
||||
const double de1 = _GetDeltaE(frontLab, backLab);
|
||||
if (de1 < gMinThreshold)
|
||||
{
|
||||
for (int i = 0; i <= 1; i++)
|
||||
{
|
||||
const double step = (i == 0) ? gLStep : -gLStep;
|
||||
frontLab.L += step;
|
||||
|
||||
while (((i == 0) && (frontLab.L <= 100)) || ((i == 1) && (frontLab.L >= 0)))
|
||||
{
|
||||
const double de2 = _GetDeltaE(frontLab, backLab);
|
||||
if (de2 >= gExpThreshold)
|
||||
{
|
||||
frontLab._ToRGB();
|
||||
return frontLab.rgb;
|
||||
}
|
||||
frontLab.L += step;
|
||||
}
|
||||
}
|
||||
}
|
||||
return frontLab.rgb;
|
||||
}
|
49
src/cascadia/TerminalCore/ColorFix.hpp
Normal file
49
src/cascadia/TerminalCore/ColorFix.hpp
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*++
|
||||
Copyright (c) Microsoft Corporation
|
||||
Licensed under the MIT license.
|
||||
|
||||
Module Name:
|
||||
- ColorFix
|
||||
|
||||
Abstract:
|
||||
- Implementation of perceptual color nudging, which allows the Terminal
|
||||
to slightly shift the foreground color to make it more perceivable on
|
||||
the current background (for cases where the foreground is very close
|
||||
to being imperceivable on the background).
|
||||
|
||||
Author(s):
|
||||
- Pankaj Bhojwani - Sep 2021
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
struct ColorFix
|
||||
{
|
||||
public:
|
||||
ColorFix(COLORREF color);
|
||||
|
||||
static COLORREF GetPerceivableColor(COLORREF fg, COLORREF bg);
|
||||
|
||||
// RGB
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
BYTE r, g, b, dummy;
|
||||
};
|
||||
COLORREF rgb;
|
||||
};
|
||||
|
||||
// Lab
|
||||
struct
|
||||
{
|
||||
double L, A, B;
|
||||
};
|
||||
|
||||
private:
|
||||
static double _GetHPrimeFn(double x, double y);
|
||||
static double _GetDeltaE(ColorFix x1, ColorFix x2);
|
||||
void _ToLab();
|
||||
void _ToRGB();
|
||||
};
|
|
@ -67,5 +67,6 @@ namespace Microsoft.Terminal.Core
|
|||
CursorStyle CursorShape;
|
||||
UInt32 CursorHeight;
|
||||
Boolean IntenseIsBright;
|
||||
Boolean PerceptualColorNudging;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "../../inc/argb.h"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
#include "../../types/inc/colorTable.hpp"
|
||||
#include "ColorFix.hpp"
|
||||
|
||||
#include <winrt/Microsoft.Terminal.Core.h>
|
||||
|
||||
|
@ -53,7 +54,8 @@ Terminal::Terminal() :
|
|||
_taskbarState{ 0 },
|
||||
_taskbarProgress{ 0 },
|
||||
_trimBlockSelection{ false },
|
||||
_intenseIsBright{ true }
|
||||
_intenseIsBright{ true },
|
||||
_perceptualColorNudging{ true }
|
||||
{
|
||||
auto dispatch = std::make_unique<TerminalDispatch>(*this);
|
||||
auto engine = std::make_unique<OutputStateMachineEngine>(std::move(dispatch));
|
||||
|
@ -175,11 +177,16 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
|
|||
_defaultBg = newBackgroundColor.with_alpha(0);
|
||||
_defaultFg = appearance.DefaultForeground();
|
||||
_intenseIsBright = appearance.IntenseIsBright();
|
||||
_perceptualColorNudging = appearance.PerceptualColorNudging();
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
_colorTable.at(i) = til::color{ appearance.GetColorTableEntry(i) };
|
||||
}
|
||||
if (_perceptualColorNudging)
|
||||
{
|
||||
_MakeAdjustedColorArray();
|
||||
}
|
||||
|
||||
CursorType cursorShape = CursorType::VerticalBar;
|
||||
switch (appearance.CursorShape())
|
||||
|
@ -1286,3 +1293,28 @@ const size_t Microsoft::Terminal::Core::Terminal::GetTaskbarProgress() const noe
|
|||
{
|
||||
return _taskbarProgress;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Creates the adjusted color array, which contains the possible foreground colors,
|
||||
// adjusted for perceivability
|
||||
// - The adjusted color array is 2-d, and effectively maps a background and foreground
|
||||
// color pair to the adjusted foreground for that color pair
|
||||
void Terminal::_MakeAdjustedColorArray()
|
||||
{
|
||||
// The color table has 16 colors, but the adjusted color table needs to be 18
|
||||
// to include the default background and default foreground colors
|
||||
std::array<COLORREF, 18> colorTableWithDefaults;
|
||||
std::copy_n(std::begin(_colorTable), 16, std::begin(colorTableWithDefaults));
|
||||
colorTableWithDefaults[DefaultBgIndex] = _defaultBg;
|
||||
colorTableWithDefaults[DefaultFgIndex] = _defaultFg;
|
||||
for (auto fgIndex = 0; fgIndex < 18; ++fgIndex)
|
||||
{
|
||||
//auto fg = colorTableWithDefaults.at(fgIndex);
|
||||
const auto fg = til::at(colorTableWithDefaults, fgIndex);
|
||||
for (auto bgIndex = 0; bgIndex < 18; ++bgIndex)
|
||||
{
|
||||
const auto bg = til::at(colorTableWithDefaults, bgIndex);
|
||||
_adjustedForegroundColors[bgIndex][fgIndex] = ColorFix::GetPerceivableColor(fg, bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
static constexpr std::wstring_view linkPattern{ LR"(\b(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|$!:,.;]*[A-Za-z0-9+&@#/%=~_|$])" };
|
||||
static constexpr size_t TaskbarMinProgress{ 10 };
|
||||
static constexpr size_t DefaultBgIndex{ 16 };
|
||||
static constexpr size_t DefaultFgIndex{ 17 };
|
||||
|
||||
// You have to forward decl the ICoreSettings here, instead of including the header.
|
||||
// If you include the header, there will be compilation errors with other
|
||||
|
@ -301,6 +303,7 @@ private:
|
|||
bool _bracketedPasteMode;
|
||||
bool _trimBlockSelection;
|
||||
bool _intenseIsBright;
|
||||
bool _perceptualColorNudging;
|
||||
|
||||
size_t _taskbarState;
|
||||
size_t _taskbarProgress;
|
||||
|
@ -387,6 +390,9 @@ private:
|
|||
|
||||
void _NotifyTerminalCursorPositionChanged() noexcept;
|
||||
|
||||
std::array<std::array<COLORREF, 18>, 18> _adjustedForegroundColors;
|
||||
void _MakeAdjustedColorArray();
|
||||
|
||||
#pragma region TextSelection
|
||||
// These methods are defined in TerminalSelection.cpp
|
||||
std::vector<SMALL_RECT> _GetSelectionRects() const noexcept;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
<ClCompile Include="..\TerminalSelection.cpp" />
|
||||
<ClCompile Include="..\TerminalApi.cpp" />
|
||||
<ClCompile Include="..\Terminal.cpp" />
|
||||
<ClCompile Include="..\ColorFix.cpp" />
|
||||
<ClCompile Include="..\pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
|
@ -19,6 +20,7 @@
|
|||
<ClInclude Include="..\ITerminalApi.hpp" />
|
||||
<ClInclude Include="..\pch.h" />
|
||||
<ClInclude Include="..\Terminal.hpp" />
|
||||
<ClInclude Include="..\ColorFix.hpp" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "pch.h"
|
||||
#include "Terminal.hpp"
|
||||
#include <DefaultSettings.h>
|
||||
|
||||
using namespace Microsoft::Terminal::Core;
|
||||
using namespace Microsoft::Console::Types;
|
||||
using namespace Microsoft::Console::Render;
|
||||
|
@ -44,14 +45,47 @@ const TextAttribute Terminal::GetDefaultBrushColors() noexcept
|
|||
|
||||
std::pair<COLORREF, COLORREF> Terminal::GetAttributeColors(const TextAttribute& attr) const noexcept
|
||||
{
|
||||
std::pair<COLORREF, COLORREF> colors;
|
||||
_blinkingState.RecordBlinkingUsage(attr);
|
||||
auto colors = attr.CalculateRgbColors(
|
||||
_colorTable,
|
||||
_defaultFg,
|
||||
_defaultBg,
|
||||
_screenReversed,
|
||||
_blinkingState.IsBlinkingFaint(),
|
||||
_intenseIsBright);
|
||||
const auto fgTextColor = attr.GetForeground();
|
||||
const auto bgTextColor = attr.GetBackground();
|
||||
|
||||
// We want to nudge the foreground color to make it more perceivable only for the
|
||||
// default color pairs within the color table
|
||||
if (_perceptualColorNudging &&
|
||||
!(attr.IsFaint() || (attr.IsBlinking() && _blinkingState.IsBlinkingFaint())) &&
|
||||
(fgTextColor.IsDefault() || fgTextColor.IsLegacy()) &&
|
||||
(bgTextColor.IsDefault() || bgTextColor.IsLegacy()))
|
||||
{
|
||||
const auto bgIndex = bgTextColor.IsDefault() ? DefaultBgIndex : bgTextColor.GetIndex();
|
||||
auto fgIndex = fgTextColor.IsDefault() ? DefaultFgIndex : fgTextColor.GetIndex();
|
||||
|
||||
if (fgTextColor.IsIndex16() && (fgIndex < 8) && attr.IsBold() && _intenseIsBright)
|
||||
{
|
||||
// There is a special case for bold here - we need to get the bright version of the foreground color
|
||||
fgIndex += 8;
|
||||
}
|
||||
|
||||
if (attr.IsReverseVideo() ^ _screenReversed)
|
||||
{
|
||||
colors.first = _adjustedForegroundColors[fgIndex][bgIndex];
|
||||
colors.second = fgTextColor.GetColor(_colorTable, _defaultFg);
|
||||
}
|
||||
else
|
||||
{
|
||||
colors.first = _adjustedForegroundColors[bgIndex][fgIndex];
|
||||
colors.second = bgTextColor.GetColor(_colorTable, _defaultBg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
colors = attr.CalculateRgbColors(_colorTable,
|
||||
_defaultFg,
|
||||
_defaultBg,
|
||||
_screenReversed,
|
||||
_blinkingState.IsBlinkingFaint(),
|
||||
_intenseIsBright);
|
||||
}
|
||||
colors.first |= 0xff000000;
|
||||
// We only care about alpha for the default BG (which enables acrylic)
|
||||
// If the bg isn't the default bg color, or reverse video is enabled, make it fully opaque.
|
||||
|
|
|
@ -93,6 +93,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
OBSERVABLE_PROJECTED_SETTING(_appearance, BackgroundImageStretchMode);
|
||||
OBSERVABLE_PROJECTED_SETTING(_appearance, BackgroundImageAlignment);
|
||||
OBSERVABLE_PROJECTED_SETTING(_appearance, IntenseTextStyle);
|
||||
OBSERVABLE_PROJECTED_SETTING(_appearance, PerceptualColorNudging);
|
||||
|
||||
private:
|
||||
Model::AppearanceConfig _appearance;
|
||||
|
|
|
@ -46,6 +46,7 @@ namespace Microsoft.Terminal.Settings.Editor
|
|||
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Windows.UI.Xaml.Media.Stretch, BackgroundImageStretchMode);
|
||||
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Microsoft.Terminal.Settings.Model.ConvergedAlignment, BackgroundImageAlignment);
|
||||
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Microsoft.Terminal.Settings.Model.IntenseStyle, IntenseTextStyle);
|
||||
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Boolean, PerceptualColorNudging);
|
||||
}
|
||||
|
||||
[default_interface] runtimeclass Appearances : Windows.UI.Xaml.Controls.UserControl, Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
|
|
|
@ -153,6 +153,14 @@
|
|||
SettingOverrideSource="{x:Bind Appearance.RetroTerminalEffectOverrideSource, Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind Appearance.RetroTerminalEffect, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Perceptual Color Nudging -->
|
||||
<local:SettingContainer x:Uid="Profile_PerceptualColorNudging"
|
||||
ClearSettingValue="{x:Bind Appearance.ClearPerceptualColorNudging}"
|
||||
HasSettingValue="{x:Bind Appearance.HasPerceptualColorNudging, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Appearance.PerceptualColorNudgingOverrideSource, Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind Appearance.PerceptualColorNudging, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Grouping: Cursor -->
|
||||
|
|
|
@ -799,6 +799,14 @@
|
|||
<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_PerceptualColorNudging.Header" xml:space="preserve">
|
||||
<value>Perceptual color nudging</value>
|
||||
<comment>Header for a control to toggle if we should 'nudge' the foreground color to make it more visible when necessary, based on the background color.</comment>
|
||||
</data>
|
||||
<data name="Profile_PerceptualColorNudging.HelpText" xml:space="preserve">
|
||||
<value>When enabled, enables perceptual color nudging, which will, only when necessary, 'nudge' the foreground color to make it more visible (based on the background color).</value>
|
||||
<comment>A description for what the "perceptual color nudging" setting does. Presented near "Profile_PerceptualColorNudging".</comment>
|
||||
</data>
|
||||
<data name="Profile_ScrollbarVisibility.Header" xml:space="preserve">
|
||||
<value>Scrollbar visibility</value>
|
||||
<comment>Header for a control to select the visibility of the scrollbar in a session.</comment>
|
||||
|
|
|
@ -26,6 +26,7 @@ static constexpr std::string_view BackgroundImageAlignmentKey{ "backgroundImageA
|
|||
static constexpr std::string_view RetroTerminalEffectKey{ "experimental.retroTerminalEffect" };
|
||||
static constexpr std::string_view PixelShaderPathKey{ "experimental.pixelShaderPath" };
|
||||
static constexpr std::string_view IntenseTextStyleKey{ "intenseTextStyle" };
|
||||
static constexpr std::string_view PerceptualColorNudgingKey{ "perceptualColorNudging" };
|
||||
static constexpr std::string_view LegacyAcrylicTransparencyKey{ "acrylicOpacity" };
|
||||
static constexpr std::string_view OpacityKey{ "opacity" };
|
||||
|
||||
|
@ -52,6 +53,7 @@ winrt::com_ptr<AppearanceConfig> AppearanceConfig::CopyAppearance(const Appearan
|
|||
appearance->_PixelShaderPath = source->_PixelShaderPath;
|
||||
appearance->_IntenseTextStyle = source->_IntenseTextStyle;
|
||||
appearance->_Opacity = source->_Opacity;
|
||||
appearance->_PerceptualColorNudging = source->_PerceptualColorNudging;
|
||||
return appearance;
|
||||
}
|
||||
|
||||
|
@ -73,6 +75,7 @@ Json::Value AppearanceConfig::ToJson() const
|
|||
JsonUtils::SetValueForKey(json, RetroTerminalEffectKey, _RetroTerminalEffect);
|
||||
JsonUtils::SetValueForKey(json, PixelShaderPathKey, _PixelShaderPath);
|
||||
JsonUtils::SetValueForKey(json, IntenseTextStyleKey, _IntenseTextStyle);
|
||||
JsonUtils::SetValueForKey(json, PerceptualColorNudgingKey, _PerceptualColorNudging);
|
||||
JsonUtils::SetValueForKey(json, OpacityKey, _Opacity, JsonUtils::OptionalConverter<double, IntAsFloatPercentConversionTrait>{});
|
||||
|
||||
return json;
|
||||
|
@ -105,6 +108,7 @@ void AppearanceConfig::LayerJson(const Json::Value& json)
|
|||
JsonUtils::GetValueForKey(json, RetroTerminalEffectKey, _RetroTerminalEffect);
|
||||
JsonUtils::GetValueForKey(json, PixelShaderPathKey, _PixelShaderPath);
|
||||
JsonUtils::GetValueForKey(json, IntenseTextStyleKey, _IntenseTextStyle);
|
||||
JsonUtils::GetValueForKey(json, PerceptualColorNudgingKey, _PerceptualColorNudging);
|
||||
JsonUtils::GetValueForKey(json, LegacyAcrylicTransparencyKey, _Opacity);
|
||||
JsonUtils::GetValueForKey(json, OpacityKey, _Opacity, JsonUtils::OptionalConverter<double, IntAsFloatPercentConversionTrait>{});
|
||||
}
|
||||
|
|
|
@ -54,6 +54,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
INHERITABLE_SETTING(Model::IAppearanceConfig, Model::IntenseStyle, IntenseTextStyle, Model::IntenseStyle::Bright);
|
||||
INHERITABLE_SETTING(Model::IAppearanceConfig, double, Opacity, 1.0);
|
||||
|
||||
INHERITABLE_SETTING(Model::IAppearanceConfig, bool, PerceptualColorNudging, true);
|
||||
|
||||
private:
|
||||
winrt::weak_ref<Profile> _sourceProfile;
|
||||
};
|
||||
|
|
|
@ -8,7 +8,8 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
enum InfoBarMessage
|
||||
{
|
||||
CloseOnExitInfo = 0,
|
||||
KeyboardServiceWarning
|
||||
KeyboardServiceWarning,
|
||||
SetAsDefault,
|
||||
};
|
||||
|
||||
runtimeclass WindowLayout
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
#include <LibraryResources.h>
|
||||
#include <VersionHelpers.h>
|
||||
|
||||
#include <shellapi.h>
|
||||
#include <shlwapi.h>
|
||||
|
||||
using namespace winrt::Microsoft::Terminal;
|
||||
using namespace winrt::Microsoft::Terminal::Settings;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model::implementation;
|
||||
|
@ -309,6 +312,7 @@ Model::Profile CascadiaSettings::DuplicateProfile(const Model::Profile& source)
|
|||
DUPLICATE_SETTING_MACRO_SUB(appearance, target, RetroTerminalEffect);
|
||||
DUPLICATE_SETTING_MACRO_SUB(appearance, target, CursorShape);
|
||||
DUPLICATE_SETTING_MACRO_SUB(appearance, target, CursorHeight);
|
||||
DUPLICATE_SETTING_MACRO_SUB(appearance, target, PerceptualColorNudging);
|
||||
DUPLICATE_SETTING_MACRO_SUB(appearance, target, Opacity);
|
||||
}
|
||||
|
||||
|
@ -528,9 +532,12 @@ Model::Profile CascadiaSettings::GetProfileForArgs(const Model::NewTerminalArgs&
|
|||
{
|
||||
if (newTerminalArgs)
|
||||
{
|
||||
if (auto profile = GetProfileByName(newTerminalArgs.Profile()))
|
||||
if (const auto name = newTerminalArgs.Profile(); !name.empty())
|
||||
{
|
||||
return profile;
|
||||
if (auto profile = GetProfileByName(name))
|
||||
{
|
||||
return profile;
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto index = newTerminalArgs.ProfileIndex())
|
||||
|
@ -540,6 +547,14 @@ Model::Profile CascadiaSettings::GetProfileForArgs(const Model::NewTerminalArgs&
|
|||
return profile;
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto commandLine = newTerminalArgs.Commandline(); !commandLine.empty())
|
||||
{
|
||||
if (auto profile = _getProfileForCommandLine(commandLine))
|
||||
{
|
||||
return profile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (Feature_ShowProfileDefaultsInSettings::IsEnabled())
|
||||
|
@ -562,6 +577,179 @@ Model::Profile CascadiaSettings::GetProfileForArgs(const Model::NewTerminalArgs&
|
|||
}
|
||||
}
|
||||
|
||||
// The method does some crude command line matching for our console hand-off support.
|
||||
// If you have hand-off enabled and start PowerShell from the start menu we might be called with
|
||||
// "C:\Program Files\PowerShell\7\pwsh.exe -WorkingDirectory ~"
|
||||
// This function then checks all known user profiles for one that's compatible with the commandLine.
|
||||
// In this case we might have a profile with the command line
|
||||
// "C:\Program Files\PowerShell\7\pwsh.exe"
|
||||
// This function will then match this profile return it.
|
||||
//
|
||||
// If no matching profile could be found a nullptr will be returned.
|
||||
Model::Profile CascadiaSettings::_getProfileForCommandLine(const winrt::hstring& commandLine) const
|
||||
{
|
||||
// We're going to cache all the command lines we got, as
|
||||
// _normalizeCommandLine is a relatively heavy operation.
|
||||
std::call_once(_commandLinesCacheOnce, [this]() {
|
||||
_commandLinesCache.reserve(_allProfiles.Size());
|
||||
|
||||
for (const auto& profile : _allProfiles)
|
||||
{
|
||||
if (const auto cmd = profile.Commandline(); !cmd.empty())
|
||||
{
|
||||
_commandLinesCache.emplace_back(_normalizeCommandLine(cmd.c_str()), profile);
|
||||
}
|
||||
}
|
||||
|
||||
// We're trying to find the command line with the longest common prefix below.
|
||||
// Given the commandLine "foo.exe -bar -baz" and these two user profiles:
|
||||
// * "foo.exe"
|
||||
// * "foo.exe -bar"
|
||||
// we want to choose the second one. By sorting the _commandLinesCache in a descending order
|
||||
// by command line length, we can return from this function the moment we found a matching
|
||||
// profile as there cannot possibly be any other profile anymore with a longer command line.
|
||||
std::stable_sort(_commandLinesCache.begin(), _commandLinesCache.end(), [](const auto& lhs, const auto& rhs) {
|
||||
return lhs.first.size() > rhs.first.size();
|
||||
});
|
||||
});
|
||||
|
||||
const auto needle = _normalizeCommandLine(commandLine.c_str());
|
||||
|
||||
// til::starts_with(string, prefix) will always return false if prefix.size() > string.size().
|
||||
// --> Using binary search we can safely skip all items in _commandLinesCache where .first.size() > needle.size().
|
||||
const auto end = _commandLinesCache.end();
|
||||
auto it = std::lower_bound(_commandLinesCache.begin(), end, needle, [&](const auto& lhs, const auto& rhs) {
|
||||
return lhs.first.size() > rhs.size();
|
||||
});
|
||||
|
||||
// `it` is now at a position where it->first.size() <= needle.size().
|
||||
// Hopefully we'll now find a command line with matching prefix.
|
||||
for (; it != end; ++it)
|
||||
{
|
||||
if (til::starts_with(needle, it->first))
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Given a commandLine like the following:
|
||||
// * "C:\WINDOWS\System32\cmd.exe"
|
||||
// * "pwsh -WorkingDirectory ~"
|
||||
// * "C:\Program Files\PowerShell\7\pwsh.exe"
|
||||
// * "C:\Program Files\PowerShell\7\pwsh.exe -WorkingDirectory ~"
|
||||
//
|
||||
// This function returns:
|
||||
// * "C:\Windows\System32\cmd.exe"
|
||||
// * "C:\Program Files\PowerShell\7\pwsh.exe\0-WorkingDirectory\0~"
|
||||
// * "C:\Program Files\PowerShell\7\pwsh.exe"
|
||||
// * "C:\Program Files\PowerShell\7\pwsh.exe\0-WorkingDirectory\0~"
|
||||
//
|
||||
// The resulting strings are then used for comparisons in _getProfileForCommandLine().
|
||||
// For instance a resulting string of
|
||||
// "C:\Program Files\PowerShell\7\pwsh.exe"
|
||||
// is considered a compatible profile with
|
||||
// "C:\Program Files\PowerShell\7\pwsh.exe -WorkingDirectory ~"
|
||||
// as it shares the same (normalized) prefix.
|
||||
std::wstring CascadiaSettings::_normalizeCommandLine(LPCWSTR commandLine)
|
||||
{
|
||||
// Turn "%SystemRoot%\System32\cmd.exe" into "C:\WINDOWS\System32\cmd.exe".
|
||||
// We do this early, as environment variables might occur anywhere in the commandLine.
|
||||
std::wstring normalized;
|
||||
THROW_IF_FAILED(wil::ExpandEnvironmentStringsW(commandLine, normalized));
|
||||
|
||||
// One of the most important things this function does is to strip quotes.
|
||||
// That way the commandLine "foo.exe -bar" and "\"foo.exe\" \"-bar\"" appear identical.
|
||||
// We'll abuse CommandLineToArgvW for that as it's close to what CreateProcessW uses.
|
||||
int argc = 0;
|
||||
const auto argv = CommandLineToArgvW(normalized.c_str(), &argc);
|
||||
THROW_LAST_ERROR_IF(!argc);
|
||||
const auto argvRelease = wil::scope_exit([=]() { LocalFree(argv); });
|
||||
|
||||
// The given commandLine should start with an executable name or path.
|
||||
// For instance given the following argv arrays:
|
||||
// * {"C:\WINDOWS\System32\cmd.exe"}
|
||||
// * {"pwsh", "-WorkingDirectory", "~"}
|
||||
// * {"C:\Program", "Files\PowerShell\7\pwsh.exe"}
|
||||
// ^^^^
|
||||
// Notice how there used to be a space in the path, which was split by ExpandEnvironmentStringsW().
|
||||
// CreateProcessW() supports such atrocities, so we got to do the same.
|
||||
// * {"C:\Program Files\PowerShell\7\pwsh.exe", "-WorkingDirectory", "~"}
|
||||
//
|
||||
// This loop tries to resolve relative paths, as well as executable names in %PATH%
|
||||
// into absolute paths and normalizes them. The results for the above would be:
|
||||
// * "C:\Windows\System32\cmd.exe"
|
||||
// * "C:\Program Files\PowerShell\7\pwsh.exe"
|
||||
// * "C:\Program Files\PowerShell\7\pwsh.exe"
|
||||
// * "C:\Program Files\PowerShell\7\pwsh.exe"
|
||||
for (;;)
|
||||
{
|
||||
// CreateProcessW uses RtlGetExePath to get the lpPath for SearchPathW.
|
||||
// The difference between the behavior of SearchPathW if lpPath is nullptr and what RtlGetExePath returns
|
||||
// seems to be mostly whether SafeProcessSearchMode is respected and the support for relative paths.
|
||||
// Windows Terminal makes the use relative paths rather impractical which is why we simply dropped the call to RtlGetExePath.
|
||||
const auto status = wil::SearchPathW(nullptr, argv[0], L".exe", normalized);
|
||||
|
||||
if (status == S_OK)
|
||||
{
|
||||
std::filesystem::path path{ std::move(normalized) };
|
||||
|
||||
// ExpandEnvironmentStringsW() might have returned a string that's not in the canonical capitalization.
|
||||
// For instance %SystemRoot% is set to C:\WINDOWS on my system (ugh), even though the path is actually C:\Windows.
|
||||
// We need to fix this as case-sensitive path comparisons will fail otherwise (Windows supports case-sensitive file systems).
|
||||
// If we fail to resolve the path for whatever reason (pretty unlikely given that SearchPathW found it)
|
||||
// we fall back to leaving the path as is. Better than throwing a random exception and making this unusable.
|
||||
{
|
||||
std::error_code ec;
|
||||
auto canonicalPath = canonical(path, ec);
|
||||
if (!ec)
|
||||
{
|
||||
path = std::move(canonicalPath);
|
||||
}
|
||||
}
|
||||
|
||||
// std::filesystem::path has no way to extract the internal path.
|
||||
// So about that.... I own you, computer. Give me that path.
|
||||
normalized = std::move(const_cast<std::wstring&>(path.native()));
|
||||
break;
|
||||
}
|
||||
|
||||
// If the file path couldn't be found by SearchPathW this could be the result of us being given a commandLine
|
||||
// like "C:\foo bar\baz.exe -arg" which is resolved to the argv array {"C:\foo", "bar\baz.exe", "-arg"}.
|
||||
// Just like CreateProcessW() we thus try to concatenate arguments until we successfully resolve a valid path.
|
||||
// Of course we can only do that if we have at least 2 remaining arguments in argv.
|
||||
// All other error types aren't handled at the moment.
|
||||
if (argc < 2 || status != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// As described in the comment right above, we concatenate arguments in an attempt to resolve a valid path.
|
||||
// The code below turns argv from {"C:\foo", "bar\baz.exe", "-arg"} into {"C:\foo bar\baz.exe", "-arg"}.
|
||||
// The code abuses the fact that CommandLineToArgvW allocates all arguments back-to-back on the heap separated by '\0'.
|
||||
argv[1][-1] = L' ';
|
||||
--argc;
|
||||
}
|
||||
|
||||
// We've (hopefully) finished resolving the path to the executable.
|
||||
// We're now going to append all remaining arguments to the resulting string.
|
||||
// If argv is {"C:\Program Files\PowerShell\7\pwsh.exe", "-WorkingDirectory", "~"},
|
||||
// then we'll get "C:\Program Files\PowerShell\7\pwsh.exe\0-WorkingDirectory\0~"
|
||||
if (argc > 1)
|
||||
{
|
||||
// normalized contains a canonical form of argv[0] at this point.
|
||||
// -1 allows us to include the \0 between argv[0] and argv[1] in the call to append().
|
||||
const auto beg = argv[1] - 1;
|
||||
const auto lastArg = argv[argc - 1];
|
||||
const auto end = lastArg + wcslen(lastArg);
|
||||
normalized.append(beg, end);
|
||||
}
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Helper to get a profile given a name that could be a guid or an actual name.
|
||||
// Arguments:
|
||||
|
|
|
@ -140,8 +140,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
|
||||
private:
|
||||
static const std::filesystem::path& _settingsPath();
|
||||
static std::wstring _normalizeCommandLine(LPCWSTR commandLine);
|
||||
|
||||
winrt::com_ptr<implementation::Profile> _createNewProfile(const std::wstring_view& name) const;
|
||||
Model::Profile _getProfileForCommandLine(const winrt::hstring& commandLine) const;
|
||||
|
||||
void _resolveDefaultProfile() const;
|
||||
|
||||
|
@ -165,6 +167,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
|
||||
// defterm
|
||||
Model::DefaultTerminal _currentDefaultTerminal{ nullptr };
|
||||
|
||||
// GetProfileForArgs cache
|
||||
mutable std::once_flag _commandLinesCacheOnce;
|
||||
mutable std::vector<std::pair<std::wstring, Model::Profile>> _commandLinesCache;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
INHERITABLE_APPEARANCE_SETTING(Boolean, RetroTerminalEffect);
|
||||
INHERITABLE_APPEARANCE_SETTING(String, PixelShaderPath);
|
||||
INHERITABLE_APPEARANCE_SETTING(IntenseStyle, IntenseTextStyle);
|
||||
INHERITABLE_APPEARANCE_SETTING(Boolean, PerceptualColorNudging);
|
||||
INHERITABLE_APPEARANCE_SETTING(Double, Opacity);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -202,6 +202,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
_IntenseIsBold = WI_IsFlagSet(appearance.IntenseTextStyle(), Microsoft::Terminal::Settings::Model::IntenseStyle::Bold);
|
||||
_IntenseIsBright = WI_IsFlagSet(appearance.IntenseTextStyle(), Microsoft::Terminal::Settings::Model::IntenseStyle::Bright);
|
||||
|
||||
_PerceptualColorNudging = appearance.PerceptualColorNudging();
|
||||
_Opacity = appearance.Opacity();
|
||||
}
|
||||
|
||||
|
|
|
@ -114,6 +114,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
|
||||
INHERITABLE_SETTING(Model::TerminalSettings, bool, IntenseIsBright);
|
||||
|
||||
INHERITABLE_SETTING(Model::TerminalSettings, bool, PerceptualColorNudging);
|
||||
|
||||
// ------------------------ End of Core Settings -----------------------
|
||||
|
||||
INHERITABLE_SETTING(Model::TerminalSettings, hstring, ProfileName);
|
||||
|
|
|
@ -537,8 +537,9 @@ JSON_FLAG_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::IntenseStyle)
|
|||
|
||||
JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage)
|
||||
{
|
||||
JSON_MAPPINGS(2) = {
|
||||
JSON_MAPPINGS(3) = {
|
||||
pair_type{ "closeOnExitInfo", ValueType::CloseOnExitInfo },
|
||||
pair_type{ "keyboardServiceWarning", ValueType::KeyboardServiceWarning },
|
||||
pair_type{ "setAsDefault", ValueType::SetAsDefault },
|
||||
};
|
||||
};
|
||||
|
|
|
@ -265,14 +265,12 @@ static bool getWslNames(const wil::unique_hkey& wslRootKey,
|
|||
|
||||
std::wstring buffer;
|
||||
auto result = wil::AdaptFixedSizeToAllocatedResult<std::wstring, 256>(buffer, [&](PWSTR value, size_t valueLength, size_t* valueLengthNeededWithNull) -> HRESULT {
|
||||
auto length = static_cast<DWORD>(valueLength);
|
||||
auto length = gsl::narrow<DWORD>(valueLength * sizeof(wchar_t));
|
||||
const auto status = RegQueryValueExW(distroKey.get(), RegKeyDistroName, 0, nullptr, reinterpret_cast<BYTE*>(value), &length);
|
||||
// length will receive the number of bytes - convert to a number of
|
||||
// wchar_t's. AdaptFixedSizeToAllocatedResult will resize buffer to
|
||||
// valueLengthNeededWithNull
|
||||
*valueLengthNeededWithNull = (length / sizeof(wchar_t));
|
||||
// If you add one for another trailing null, then there'll actually
|
||||
// be _two_ trailing nulls in the buffer.
|
||||
// length will receive the number of bytes including trailing null byte. Convert to a number of wchar_t's.
|
||||
// AdaptFixedSizeToAllocatedResult will then resize buffer to valueLengthNeededWithNull.
|
||||
// We're rounding up to prevent infinite loops if the data isn't a REG_SZ and length isn't divisible by 2.
|
||||
*valueLengthNeededWithNull = (length + sizeof(wchar_t) - 1) / sizeof(wchar_t);
|
||||
return status == ERROR_MORE_DATA ? S_OK : HRESULT_FROM_WIN32(status);
|
||||
});
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ namespace ControlUnitTests
|
|||
WINRT_PROPERTY(bool, TrimBlockSelection, false);
|
||||
WINRT_PROPERTY(bool, DetectURLs, true);
|
||||
WINRT_PROPERTY(bool, IntenseIsBright, true);
|
||||
WINRT_PROPERTY(bool, PerceptualColorNudging, true);
|
||||
// ------------------------ End of Core Settings -----------------------
|
||||
|
||||
WINRT_PROPERTY(winrt::hstring, ProfileName);
|
||||
|
|
|
@ -74,6 +74,7 @@ namespace TerminalCoreUnitTests
|
|||
void DetectURLs(bool) {}
|
||||
|
||||
WINRT_PROPERTY(bool, IntenseIsBright, true);
|
||||
WINRT_PROPERTY(bool, PerceptualColorNudging, true);
|
||||
|
||||
private:
|
||||
int32_t _historySize;
|
||||
|
|
|
@ -310,6 +310,12 @@ void NonClientIslandWindow::OnSize(const UINT width, const UINT height)
|
|||
{
|
||||
_UpdateIslandPosition(width, height);
|
||||
}
|
||||
|
||||
// GH#11367: We need to do this,
|
||||
// otherwise the titlebar may still be partially visible
|
||||
// when we move between different DPI monitors.
|
||||
RefreshCurrentDPI();
|
||||
_UpdateFrameMargins();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
|
|
@ -453,7 +453,7 @@ try
|
|||
|
||||
RETURN_IF_WIN32_BOOL_FALSE(CreatePipe(outPipeTheirSide.addressof(), outPipeOurSide.addressof(), nullptr, 0));
|
||||
|
||||
wil::unique_handle clientProcess{ OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, TRUE, static_cast<DWORD>(connectMessage->Descriptor.Process)) };
|
||||
wil::unique_handle clientProcess{ OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | SYNCHRONIZE, TRUE, static_cast<DWORD>(connectMessage->Descriptor.Process)) };
|
||||
RETURN_LAST_ERROR_IF_NULL(clientProcess.get());
|
||||
|
||||
wil::unique_handle refHandle;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$pgoBranch = "main"
|
||||
$pgoBranch = "release-1.12"
|
||||
$packageId = "Microsoft.Internal.Windows.Terminal.PGODatabase"
|
||||
|
||||
# Get release version
|
||||
|
|
Loading…
Reference in a new issue