From 26f4b0eacbe46e47d89960064edb161f18471d21 Mon Sep 17 00:00:00 2001 From: Dustin Howett Date: Mon, 19 Jul 2021 19:51:47 +0000 Subject: [PATCH 01/23] Merged PR 6269653: Slim down conhost's dependency on shcore An internal change CommandLineToArgVW to an apiset. Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev a71b943e06c009085d6a2bb886dd50c2d0d2c276 Related work items: MSFT-32178383 --- src/host/sources.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/host/sources.inc b/src/host/sources.inc index 3ee3b70c3..e3115bda5 100644 --- a/src/host/sources.inc +++ b/src/host/sources.inc @@ -134,6 +134,7 @@ CRTLIBS = \ TARGETLIBS = \ $(TARGETLIBS) \ + $(MINCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\api-ms-win-core-commandlinetoargv-l1.lib \ $(ONECORE_INTERNAL_SDK_LIB_PATH)\onecoreuuid.lib \ $(ONECOREUAP_INTERNAL_SDK_LIB_PATH)\onecoreuapuuid.lib \ $(ONECORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\onecore_internal.lib \ From dfda41074d8a3735c42a5ee17e1b4997571e00f9 Mon Sep 17 00:00:00 2001 From: Dustin Howett Date: Mon, 19 Jul 2021 20:02:20 +0000 Subject: [PATCH 02/23] Merged PR 6274354: [Git2Git] Fix unbound read of cooked read buffer Fix unbound read of cooked read buffer Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev 756c8dcd4cf9551f5bf090b98bf3fba5498f8eff Related work items: MSFT-32957145 --- src/host/readDataCooked.cpp | 10 +++++----- src/host/tracing.cpp | 5 +++-- src/host/tracing.hpp | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/host/readDataCooked.cpp b/src/host/readDataCooked.cpp index 458f351b3..a85b1bcc3 100644 --- a/src/host/readDataCooked.cpp +++ b/src/host/readDataCooked.cpp @@ -1008,13 +1008,13 @@ void COOKED_READ_DATA::SavePendingInput(const size_t index, const bool multiline { // Figure out where real string ends (at carriage return or end of buffer). PWCHAR StringPtr = _backupLimit; - size_t StringLength = _bytesRead; + size_t StringLength = _bytesRead / sizeof(WCHAR); bool FoundCR = false; - for (size_t i = 0; i < (_bytesRead / sizeof(WCHAR)); i++) + for (size_t i = 0; i < StringLength; i++) { if (*StringPtr++ == UNICODE_CARRIAGERETURN) { - StringLength = i * sizeof(WCHAR); + StringLength = i; FoundCR = true; break; } @@ -1026,11 +1026,11 @@ void COOKED_READ_DATA::SavePendingInput(const size_t index, const bool multiline { // add to command line recall list if we have a history list. CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); - LOG_IF_FAILED(_commandHistory->Add({ _backupLimit, StringLength / sizeof(wchar_t) }, + LOG_IF_FAILED(_commandHistory->Add({ _backupLimit, StringLength }, WI_IsFlagSet(gci.Flags, CONSOLE_HISTORY_NODUP))); } - Tracing::s_TraceCookedRead(_backupLimit); + Tracing::s_TraceCookedRead(_backupLimit, base::saturated_cast(StringLength)); // check for alias ProcessAliases(LineCount); diff --git a/src/host/tracing.cpp b/src/host/tracing.cpp index 6e20fe33e..ebd323a0e 100644 --- a/src/host/tracing.cpp +++ b/src/host/tracing.cpp @@ -405,12 +405,13 @@ void Tracing::s_TraceInputRecord(const INPUT_RECORD& inputRecord) } } -void Tracing::s_TraceCookedRead(_In_z_ const wchar_t* pwszCookedBuffer) +void Tracing::s_TraceCookedRead(_In_reads_(cchCookedBufferLength) const wchar_t* pwchCookedBuffer, _In_ ULONG cchCookedBufferLength) { TraceLoggingWrite( g_hConhostV2EventTraceProvider, "CookedRead", - TraceLoggingWideString(pwszCookedBuffer, "ReadBuffer"), + TraceLoggingCountedWideString(pwchCookedBuffer, cchCookedBufferLength, "ReadBuffer"), + TraceLoggingULong(cchCookedBufferLength, "ReadBufferLength"), TraceLoggingKeyword(TIL_KEYWORD_TRACE), TraceLoggingKeyword(TraceKeywords::CookedRead)); } diff --git a/src/host/tracing.hpp b/src/host/tracing.hpp index 36ae55423..d4bcdf701 100644 --- a/src/host/tracing.hpp +++ b/src/host/tracing.hpp @@ -62,7 +62,7 @@ public: static void s_TraceWindowMessage(const MSG& msg); static void s_TraceInputRecord(const INPUT_RECORD& inputRecord); - static void s_TraceCookedRead(_In_z_ const wchar_t* pwszCookedBuffer); + static void Tracing::s_TraceCookedRead(_In_reads_(cchCookedBufferLength) const wchar_t* pwchCookedBuffer, _In_ ULONG cchCookedBufferLength); static void __stdcall TraceFailure(const wil::FailureInfo& failure) noexcept; From 01b519527548167e96ac5983e1881829429bba6a Mon Sep 17 00:00:00 2001 From: Dustin Howett Date: Wed, 21 Jul 2021 18:41:37 +0000 Subject: [PATCH 03/23] Merged PR 6277720: [Git2Git] Merged PR 6275065: Trace console attach/detatch As identified by Michael Niksa, our MDE heuristics for understanding relationship between conhost and related processes was incorrect. Exposing trace here to assist in correlation. Related work items: MSFT-32957145 Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev 3c886da66d77d1aa36b52794929e388af292539c --- src/host/telemetry.cpp | 5 +++++ src/host/telemetry.hpp | 2 ++ src/host/tracing.cpp | 33 +++++++++++++++++++++++++++++++++ src/host/tracing.hpp | 3 ++- src/server/IoDispatchers.cpp | 4 ++++ src/server/ProcessHandle.cpp | 7 +++++++ src/server/ProcessHandle.h | 2 ++ 7 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/host/telemetry.cpp b/src/host/telemetry.cpp index 7b4ce210b..59080d3a9 100644 --- a/src/host/telemetry.cpp +++ b/src/host/telemetry.cpp @@ -587,3 +587,8 @@ void Telemetry::LogRipMessage(_In_z_ const char* pszMessage, ...) const TraceLoggingString(szMessageEvaluated, "Message")); } } + +bool Telemetry::IsUserInteractive() +{ + return _fUserInteractiveForTelemetry; +} diff --git a/src/host/telemetry.hpp b/src/host/telemetry.hpp index 00f9a0d92..2092115aa 100644 --- a/src/host/telemetry.hpp +++ b/src/host/telemetry.hpp @@ -51,6 +51,8 @@ public: void LogRipMessage(_In_z_ const char* pszMessage, ...) const; + bool IsUserInteractive(); + // Names are from the external API call names. Note that some names can be different // than the internal API calls. // Don't worry about the following APIs, because they are external to our conhost codebase and hard to track through diff --git a/src/host/tracing.cpp b/src/host/tracing.cpp index ebd323a0e..91efc57fc 100644 --- a/src/host/tracing.cpp +++ b/src/host/tracing.cpp @@ -21,6 +21,7 @@ enum TraceKeywords API = 0x400, UIA = 0x800, CookedRead = 0x1000, + ConsoleAttachDetach = 0x2000, All = 0x1FFF }; DEFINE_ENUM_FLAG_OPERATORS(TraceKeywords); @@ -416,6 +417,38 @@ void Tracing::s_TraceCookedRead(_In_reads_(cchCookedBufferLength) const wchar_t* TraceLoggingKeyword(TraceKeywords::CookedRead)); } +void Tracing::s_TraceConsoleAttachDetach(_In_ const ConsoleProcessHandle* pConsoleProcessHandle, _In_ bool bIsAttach) +{ + FILETIME ftCreationTime, ftDummyTime = { 0 }; + ULARGE_INTEGER creationTime = { 0 }; + + if (TraceLoggingProviderEnabled(g_hConhostV2EventTraceProvider, + WINEVENT_LEVEL_LOG_ALWAYS, + TraceKeywords::ConsoleAttachDetach)) { + + if (::GetProcessTimes(pConsoleProcessHandle->GetRawHandle(), + &ftCreationTime, + &ftDummyTime, + &ftDummyTime, + &ftDummyTime)) { + creationTime.HighPart = ftCreationTime.dwHighDateTime; + creationTime.LowPart = ftCreationTime.dwLowDateTime; + } + + bool bIsUserInteractive = Telemetry::Instance().IsUserInteractive(); + + TraceLoggingWrite( + g_hConhostV2EventTraceProvider, + "ConsoleAttachDetach", + TraceLoggingUInt32(pConsoleProcessHandle->dwProcessId, "ProcessId"), + TraceLoggingUInt64(creationTime.QuadPart, "ProcessCreationTime"), + TraceLoggingBool(bIsAttach, "IsAttach"), + TraceLoggingBool(bIsUserInteractive, "IsUserInteractive"), + TraceLoggingKeyword(TIL_KEYWORD_TRACE), + TraceLoggingKeyword(TraceKeywords::ConsoleAttachDetach)); + } +} + void __stdcall Tracing::TraceFailure(const wil::FailureInfo& failure) noexcept { TraceLoggingWrite( diff --git a/src/host/tracing.hpp b/src/host/tracing.hpp index d4bcdf701..d2f8eb150 100644 --- a/src/host/tracing.hpp +++ b/src/host/tracing.hpp @@ -62,7 +62,8 @@ public: static void s_TraceWindowMessage(const MSG& msg); static void s_TraceInputRecord(const INPUT_RECORD& inputRecord); - static void Tracing::s_TraceCookedRead(_In_reads_(cchCookedBufferLength) const wchar_t* pwchCookedBuffer, _In_ ULONG cchCookedBufferLength); + static void s_TraceCookedRead(_In_reads_(cchCookedBufferLength) const wchar_t* pwchCookedBuffer, _In_ ULONG cchCookedBufferLength); + static void s_TraceConsoleAttachDetach(_In_ const ConsoleProcessHandle* pConsoleProcessHandle, _In_ bool bIsAttach); static void __stdcall TraceFailure(const wil::FailureInfo& failure) noexcept; diff --git a/src/server/IoDispatchers.cpp b/src/server/IoDispatchers.cpp index 7ae2e954c..4044c41ca 100644 --- a/src/server/IoDispatchers.cpp +++ b/src/server/IoDispatchers.cpp @@ -431,6 +431,8 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API CommandHistory::s_Free((HANDLE)ProcessData); gci.ProcessHandleList.FreeProcessData(ProcessData); } + + Tracing::s_TraceConsoleAttachDetach(ProcessData, true); UnlockConsole(); @@ -470,6 +472,8 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleClientDisconnectRoutine(_In_ PCONSOLE_API pNotifier->NotifyConsoleEndApplicationEvent(pProcessData->dwProcessId); } + Tracing::s_TraceConsoleAttachDetach(pProcessData, false); + LOG_IF_FAILED(RemoveConsole(pProcessData)); pMessage->SetReplyStatus(STATUS_SUCCESS); diff --git a/src/server/ProcessHandle.cpp b/src/server/ProcessHandle.cpp index 14d9f7603..1b5647bcd 100644 --- a/src/server/ProcessHandle.cpp +++ b/src/server/ProcessHandle.cpp @@ -65,3 +65,10 @@ const ConsoleShimPolicy ConsoleProcessHandle::GetShimPolicy() const { return _shimPolicy; } + +// Routine Description: +// - Retrieves the raw process handle +const HANDLE ConsoleProcessHandle::GetRawHandle() const +{ + return _hProcess.get(); +} diff --git a/src/server/ProcessHandle.h b/src/server/ProcessHandle.h index eeafaebc9..e73706549 100644 --- a/src/server/ProcessHandle.h +++ b/src/server/ProcessHandle.h @@ -40,6 +40,8 @@ public: const ConsoleProcessPolicy GetPolicy() const; const ConsoleShimPolicy GetShimPolicy() const; + const HANDLE GetRawHandle() const; + CD_CONNECTION_INFORMATION GetConnectionInformation(IDeviceComm* deviceComm) const; private: From 184919fb24186b161b40be8e004bf2c0d99ff1ee Mon Sep 17 00:00:00 2001 From: Dustin Howett Date: Thu, 22 Jul 2021 13:39:34 +0000 Subject: [PATCH 04/23] Merged PR 6285331: [Git2Git] Merged PR 6278637: Expose attached client process context to cooked read trace Related work items: MSFT-32957145 Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev bdb25dc99dcb2f1ee483dffe883d0178ea9d18dc --- src/host/readDataCooked.cpp | 17 +++++++----- src/host/readDataCooked.hpp | 8 +++--- src/host/stream.cpp | 5 ++-- src/host/tracing.cpp | 49 ++++++++++++++--------------------- src/host/tracing.hpp | 4 +-- src/inc/test/CommonState.hpp | 4 +-- src/server/ApiDispatchers.cpp | 2 +- src/server/ProcessHandle.cpp | 28 +++++++++++++++++++- src/server/ProcessHandle.h | 4 +++ 9 files changed, 73 insertions(+), 48 deletions(-) diff --git a/src/host/readDataCooked.cpp b/src/host/readDataCooked.cpp index a85b1bcc3..169b09731 100644 --- a/src/host/readDataCooked.cpp +++ b/src/host/readDataCooked.cpp @@ -34,13 +34,13 @@ using Microsoft::Console::Interactivity::ServiceLocator; // - OriginalCursorPosition - // - NumberOfVisibleChars // - CtrlWakeupMask - Special client parameter to interrupt editing, end the wait, and return control to the client application -// - CommandHistory - // - Echo - // - InsertMode - // - Processed - // - Line - // - pTempHandle - A handle to the output buffer to prevent it from being destroyed while we're using it to present 'edit line' text. // - initialData - any text data that should be prepopulated into the buffer +// - pClientProcess - Attached process handle object // Return Value: // - THROW: Throws E_INVALIDARG for invalid pointers. COOKED_READ_DATA::COOKED_READ_DATA(_In_ InputBuffer* const pInputBuffer, @@ -49,9 +49,9 @@ COOKED_READ_DATA::COOKED_READ_DATA(_In_ InputBuffer* const pInputBuffer, _In_ size_t UserBufferSize, _In_ PWCHAR UserBuffer, _In_ ULONG CtrlWakeupMask, - _In_ CommandHistory* CommandHistory, - const std::wstring_view exeName, - const std::string_view initialData) : + _In_ const std::wstring_view exeName, + _In_ const std::string_view initialData, + _In_ ConsoleProcessHandle* const pClientProcess) : ReadData(pInputBuffer, pInputReadHandleData), _screenInfo{ screenInfo }, _bytesRead{ 0 }, @@ -62,7 +62,7 @@ COOKED_READ_DATA::COOKED_READ_DATA(_In_ InputBuffer* const pInputBuffer, _exeName{ exeName }, _pdwNumBytes{ nullptr }, - _commandHistory{ CommandHistory }, + _commandHistory{ CommandHistory::s_Find((HANDLE)pClientProcess) }, _controlKeyState{ 0 }, _ctrlWakeupMask{ CtrlWakeupMask }, _visibleCharCount{ 0 }, @@ -73,7 +73,8 @@ COOKED_READ_DATA::COOKED_READ_DATA(_In_ InputBuffer* const pInputBuffer, _lineInput{ WI_IsFlagSet(pInputBuffer->InputMode, ENABLE_LINE_INPUT) }, _processedInput{ WI_IsFlagSet(pInputBuffer->InputMode, ENABLE_PROCESSED_INPUT) }, _insertMode{ ServiceLocator::LocateGlobals().getConsoleInformation().GetInsertMode() }, - _unicode{ false } + _unicode{ false }, + _clientProcess{ pClientProcess } { #ifndef UNIT_TESTING THROW_IF_FAILED(screenInfo.GetMainBuffer().AllocateIoHandle(ConsoleHandleData::HandleType::Output, @@ -1030,7 +1031,9 @@ void COOKED_READ_DATA::SavePendingInput(const size_t index, const bool multiline WI_IsFlagSet(gci.Flags, CONSOLE_HISTORY_NODUP))); } - Tracing::s_TraceCookedRead(_backupLimit, base::saturated_cast(StringLength)); + Tracing::s_TraceCookedRead(_clientProcess, + _backupLimit, + base::saturated_cast(StringLength)); // check for alias ProcessAliases(LineCount); diff --git a/src/host/readDataCooked.hpp b/src/host/readDataCooked.hpp index 47f7bb2e8..4eccee7f5 100644 --- a/src/host/readDataCooked.hpp +++ b/src/host/readDataCooked.hpp @@ -39,9 +39,9 @@ public: _In_ size_t UserBufferSize, _In_ PWCHAR UserBuffer, _In_ ULONG CtrlWakeupMask, - _In_ CommandHistory* CommandHistory, - const std::wstring_view exeName, - const std::string_view initialData); + _In_ const std::wstring_view exeName, + _In_ const std::string_view initialData, + _In_ ConsoleProcessHandle* const pClientProcess); ~COOKED_READ_DATA() override; COOKED_READ_DATA(COOKED_READ_DATA&&) = default; @@ -156,6 +156,8 @@ private: bool _insertMode; bool _unicode; + ConsoleProcessHandle* const _clientProcess; + [[nodiscard]] NTSTATUS _readCharInputLoop(const bool isUnicode, size_t& numBytes) noexcept; [[nodiscard]] NTSTATUS _handlePostCharInputLoop(const bool isUnicode, size_t& numBytes, ULONG& controlKeyState) noexcept; diff --git a/src/host/stream.cpp b/src/host/stream.cpp index 4b0ba6c67..12806de01 100644 --- a/src/host/stream.cpp +++ b/src/host/stream.cpp @@ -471,7 +471,6 @@ size_t RetrieveNumberOfSpaces(_In_ SHORT sOriginalCursorPositionX, RETURN_HR_IF(E_FAIL, !gci.HasActiveOutputBuffer()); SCREEN_INFORMATION& screenInfo = gci.GetActiveOutputBuffer(); - CommandHistory* const pCommandHistory = CommandHistory::s_Find(processData); try { @@ -481,9 +480,9 @@ size_t RetrieveNumberOfSpaces(_In_ SHORT sOriginalCursorPositionX, buffer.size_bytes(), // UserBufferSize reinterpret_cast(buffer.data()), // UserBuffer ctrlWakeupMask, // CtrlWakeupMask - pCommandHistory, // CommandHistory exeName, // exe name - initialData); + initialData, + reinterpret_cast(processData)); //pClientProcess gci.SetCookedReadData(cookedReadData.get()); bytesRead = buffer.size_bytes(); // This parameter on the way in is the size to read, on the way out, it will be updated to what is actually read. diff --git a/src/host/tracing.cpp b/src/host/tracing.cpp index 91efc57fc..ccd8716c7 100644 --- a/src/host/tracing.cpp +++ b/src/host/tracing.cpp @@ -406,42 +406,33 @@ void Tracing::s_TraceInputRecord(const INPUT_RECORD& inputRecord) } } -void Tracing::s_TraceCookedRead(_In_reads_(cchCookedBufferLength) const wchar_t* pwchCookedBuffer, _In_ ULONG cchCookedBufferLength) -{ - TraceLoggingWrite( - g_hConhostV2EventTraceProvider, - "CookedRead", - TraceLoggingCountedWideString(pwchCookedBuffer, cchCookedBufferLength, "ReadBuffer"), - TraceLoggingULong(cchCookedBufferLength, "ReadBufferLength"), - TraceLoggingKeyword(TIL_KEYWORD_TRACE), - TraceLoggingKeyword(TraceKeywords::CookedRead)); +void Tracing::s_TraceCookedRead(_In_ ConsoleProcessHandle* const pConsoleProcessHandle, _In_reads_(cchCookedBufferLength) const wchar_t* pwchCookedBuffer, _In_ ULONG cchCookedBufferLength) +{ + if (TraceLoggingProviderEnabled(g_hConhostV2EventTraceProvider, 0, TraceKeywords::CookedRead)) { + + TraceLoggingWrite( + g_hConhostV2EventTraceProvider, + "CookedRead", + TraceLoggingCountedWideString(pwchCookedBuffer, cchCookedBufferLength, "ReadBuffer"), + TraceLoggingULong(cchCookedBufferLength, "ReadBufferLength"), + TraceLoggingUInt32(pConsoleProcessHandle->dwProcessId, "AttachedProcessId"), + TraceLoggingUInt64(pConsoleProcessHandle->GetProcessCreationTime(), "AttachedProcessCreationTime"), + TraceLoggingKeyword(TIL_KEYWORD_TRACE), + TraceLoggingKeyword(TraceKeywords::CookedRead)); + } } -void Tracing::s_TraceConsoleAttachDetach(_In_ const ConsoleProcessHandle* pConsoleProcessHandle, _In_ bool bIsAttach) -{ - FILETIME ftCreationTime, ftDummyTime = { 0 }; - ULARGE_INTEGER creationTime = { 0 }; - - if (TraceLoggingProviderEnabled(g_hConhostV2EventTraceProvider, - WINEVENT_LEVEL_LOG_ALWAYS, - TraceKeywords::ConsoleAttachDetach)) { - - if (::GetProcessTimes(pConsoleProcessHandle->GetRawHandle(), - &ftCreationTime, - &ftDummyTime, - &ftDummyTime, - &ftDummyTime)) { - creationTime.HighPart = ftCreationTime.dwHighDateTime; - creationTime.LowPart = ftCreationTime.dwLowDateTime; - } - +void Tracing::s_TraceConsoleAttachDetach(_In_ ConsoleProcessHandle* const pConsoleProcessHandle, _In_ bool bIsAttach) +{ + if (TraceLoggingProviderEnabled(g_hConhostV2EventTraceProvider, 0, TraceKeywords::ConsoleAttachDetach)) { + bool bIsUserInteractive = Telemetry::Instance().IsUserInteractive(); TraceLoggingWrite( g_hConhostV2EventTraceProvider, "ConsoleAttachDetach", - TraceLoggingUInt32(pConsoleProcessHandle->dwProcessId, "ProcessId"), - TraceLoggingUInt64(creationTime.QuadPart, "ProcessCreationTime"), + TraceLoggingUInt32(pConsoleProcessHandle->dwProcessId, "AttachedProcessId"), + TraceLoggingUInt64(pConsoleProcessHandle->GetProcessCreationTime(), "AttachedProcessCreationTime"), TraceLoggingBool(bIsAttach, "IsAttach"), TraceLoggingBool(bIsUserInteractive, "IsUserInteractive"), TraceLoggingKeyword(TIL_KEYWORD_TRACE), diff --git a/src/host/tracing.hpp b/src/host/tracing.hpp index d2f8eb150..a32fc6c3f 100644 --- a/src/host/tracing.hpp +++ b/src/host/tracing.hpp @@ -62,8 +62,8 @@ public: static void s_TraceWindowMessage(const MSG& msg); static void s_TraceInputRecord(const INPUT_RECORD& inputRecord); - static void s_TraceCookedRead(_In_reads_(cchCookedBufferLength) const wchar_t* pwchCookedBuffer, _In_ ULONG cchCookedBufferLength); - static void s_TraceConsoleAttachDetach(_In_ const ConsoleProcessHandle* pConsoleProcessHandle, _In_ bool bIsAttach); + static void s_TraceCookedRead(_In_ ConsoleProcessHandle* const pConsoleProcessHandle, _In_reads_(cchCookedBufferLength) const wchar_t* pwchCookedBuffer, _In_ ULONG cchCookedBufferLength); + static void s_TraceConsoleAttachDetach(_In_ ConsoleProcessHandle* const pConsoleProcessHandle, _In_ bool bIsAttach); static void __stdcall TraceFailure(const wil::FailureInfo& failure) noexcept; diff --git a/src/inc/test/CommonState.hpp b/src/inc/test/CommonState.hpp index 80382837c..6319bb902 100644 --- a/src/inc/test/CommonState.hpp +++ b/src/inc/test/CommonState.hpp @@ -132,9 +132,9 @@ public: 0, nullptr, 0, - nullptr, L"", - initialData); + initialData, + nullptr); gci.SetCookedReadData(readData); } diff --git a/src/server/ApiDispatchers.cpp b/src/server/ApiDispatchers.cpp index 87e64b18f..fff5fc354 100644 --- a/src/server/ApiDispatchers.cpp +++ b/src/server/ApiDispatchers.cpp @@ -312,7 +312,7 @@ } CATCH_RETURN(); - // ReadConsole needs this to get the command history list associated with an attached process, but it can be an opaque value. + // ReadConsole needs this to get details associated with an attached process (such as the command history list, telemetry metadata). HANDLE const hConsoleClient = (HANDLE)m->GetProcessHandle(); // ReadConsole needs this to store context information across "processed reads" e.g. reads on the same handle diff --git a/src/server/ProcessHandle.cpp b/src/server/ProcessHandle.cpp index 1b5647bcd..f4d0a1d7f 100644 --- a/src/server/ProcessHandle.cpp +++ b/src/server/ProcessHandle.cpp @@ -27,7 +27,8 @@ ConsoleProcessHandle::ConsoleProcessHandle(const DWORD dwProcessId, FALSE, dwProcessId))), _policy(ConsoleProcessPolicy::s_CreateInstance(_hProcess.get())), - _shimPolicy(ConsoleShimPolicy::s_CreateInstance(_hProcess.get())) + _shimPolicy(ConsoleShimPolicy::s_CreateInstance(_hProcess.get())), + _processCreationTime(0) { if (nullptr != _hProcess.get()) { @@ -72,3 +73,28 @@ const HANDLE ConsoleProcessHandle::GetRawHandle() const { return _hProcess.get(); } + +// Routine Description: +// - Retrieves the process creation time (currently used in telemetry traces) +// - The creation time is lazily populated on first call +const ULONG64 ConsoleProcessHandle::GetProcessCreationTime() const +{ + if (_processCreationTime == 0 && _hProcess != nullptr) { + + FILETIME ftCreationTime, ftDummyTime = { 0 }; + ULARGE_INTEGER creationTime = { 0 }; + + if (::GetProcessTimes(_hProcess.get(), + &ftCreationTime, + &ftDummyTime, + &ftDummyTime, + &ftDummyTime)) { + creationTime.HighPart = ftCreationTime.dwHighDateTime; + creationTime.LowPart = ftCreationTime.dwLowDateTime; + } + + _processCreationTime = creationTime.QuadPart; + } + + return _processCreationTime; +} diff --git a/src/server/ProcessHandle.h b/src/server/ProcessHandle.h index e73706549..8f35935d9 100644 --- a/src/server/ProcessHandle.h +++ b/src/server/ProcessHandle.h @@ -44,6 +44,8 @@ public: CD_CONNECTION_INFORMATION GetConnectionInformation(IDeviceComm* deviceComm) const; + const ULONG64 GetProcessCreationTime() const; + private: ConsoleProcessHandle(const DWORD dwProcessId, const DWORD dwThreadId, @@ -58,6 +60,8 @@ private: ULONG const _ulProcessGroupId; wil::unique_handle const _hProcess; + mutable ULONG64 _processCreationTime; + const ConsoleProcessPolicy _policy; const ConsoleShimPolicy _shimPolicy; From 431d51de4c7219aa49e12f5468add009a517949b Mon Sep 17 00:00:00 2001 From: Dustin Howett Date: Tue, 21 Sep 2021 20:49:55 +0000 Subject: [PATCH 05/23] Merged PR 6286783: Release unneeded memory more eagerly from conhost This is equivalent to commit 8779249b1, but reflected from the OS repository. Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev a4d67e9b05039f365a1a0c58e9c63474c58073a1 Related work items: MSFT-34777060 --- src/inc/til/u8u16convert.h | 8 ++++++++ src/server/ApiMessage.cpp | 18 ++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/inc/til/u8u16convert.h b/src/inc/til/u8u16convert.h index b4d3cd9f8..af6e4f9b7 100644 --- a/src/inc/til/u8u16convert.h +++ b/src/inc/til/u8u16convert.h @@ -55,6 +55,14 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned" RETURN_HR_IF(E_ABORT, !base::CheckAdd(in.length(), _partialsLen).AssignIfValid(&capacity)); _buffer.clear(); + + // If we were previously called with a huge buffer we have an equally large _buffer. + // We shouldn't just keep this huge buffer around, if no one needs it anymore. + if (_buffer.capacity() > 16 * 1024 && (_buffer.capacity() >> 1) > capacity) + { + _buffer.shrink_to_fit(); + } + _buffer.reserve(capacity); // copy UTF-8 code units that were remaining from the previous call (if any) diff --git a/src/server/ApiMessage.cpp b/src/server/ApiMessage.cpp index 598111c88..9287965d3 100644 --- a/src/server/ApiMessage.cpp +++ b/src/server/ApiMessage.cpp @@ -104,7 +104,14 @@ try { RETURN_HR_IF(E_FAIL, State.ReadOffset > Descriptor.InputSize); - ULONG const cbReadSize = Descriptor.InputSize - State.ReadOffset; + const ULONG cbReadSize = Descriptor.InputSize - State.ReadOffset; + + // If we were previously called with a huge buffer we have an equally large _inputBuffer. + // We shouldn't just keep this huge buffer around, if no one needs it anymore. + if (_inputBuffer.capacity() > 16 * 1024 && (_inputBuffer.capacity() >> 1) > cbReadSize) + { + _inputBuffer.shrink_to_fit(); + } _inputBuffer.resize(cbReadSize); @@ -145,10 +152,17 @@ try ULONG cbWriteSize = Descriptor.OutputSize - State.WriteOffset; RETURN_IF_FAILED(ULongMult(cbWriteSize, cbFactor, &cbWriteSize)); + // If we were previously called with a huge buffer we have an equally large _outputBuffer. + // We shouldn't just keep this huge buffer around, if no one needs it anymore. + if (_outputBuffer.capacity() > 16 * 1024 && (_outputBuffer.capacity() >> 1) > cbWriteSize) + { + _outputBuffer.shrink_to_fit(); + } + _outputBuffer.resize(cbWriteSize); // 0 it out. - std::fill(_outputBuffer.begin(), _outputBuffer.end(), (BYTE)0); + std::fill_n(_outputBuffer.data(), _outputBuffer.size(), BYTE(0)); State.OutputBuffer = _outputBuffer.data(); State.OutputBufferSize = cbWriteSize; From d26353bb32587a38d595ee75fa0b5a737dc3123d Mon Sep 17 00:00:00 2001 From: Dustin Howett Date: Tue, 21 Sep 2021 20:51:44 +0000 Subject: [PATCH 06/23] Merged PR 6303540: Prepare command history before COOKED_READ in tests [Git2Git] Merged PR 6303114: Prepare command history before COOKED_READ in tests PR !6278637 introduced a dependency from COOKED_READ_DATA on the ability to locate a command history for a process handle (here, `nullptr`). The tests were blowing up because no such history had been allocated. Closes MSFT-34812916 Closes MSFT-34813774 Closes MSFT-34815941 Closes MSFT-34817558 Closes MSFT-34817540 (Watson) Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev f7517e686447fc0469f6b83df19760dc3dafd577 --- src/host/ut_host/ApiRoutinesTests.cpp | 10 ++++++++++ src/host/ut_host/CommandLineTests.cpp | 3 ++- src/host/ut_host/CommandListPopupTests.cpp | 3 ++- src/host/ut_host/CommandNumberPopupTests.cpp | 3 ++- src/host/ut_host/CopyFromCharPopupTests.cpp | 9 +++++++++ src/host/ut_host/CopyToCharPopupTests.cpp | 3 ++- src/host/ut_host/SelectionTests.cpp | 9 +++++++++ 7 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/host/ut_host/ApiRoutinesTests.cpp b/src/host/ut_host/ApiRoutinesTests.cpp index bf0f7ed36..cf0e8cd18 100644 --- a/src/host/ut_host/ApiRoutinesTests.cpp +++ b/src/host/ut_host/ApiRoutinesTests.cpp @@ -27,6 +27,7 @@ class ApiRoutinesTests ApiRoutines _Routines; IApiRoutines* _pApiRoutines = &_Routines; + CommandHistory* m_pHistory; TEST_METHOD_SETUP(MethodSetup) { @@ -37,11 +38,20 @@ class ApiRoutinesTests m_state->PrepareGlobalInputBuffer(); + m_pHistory = CommandHistory::s_Allocate(L"cmd.exe", nullptr); + if (!m_pHistory) + { + return false; + } + // History must be prepared before COOKED_READ return true; } TEST_METHOD_CLEANUP(MethodCleanup) { + CommandHistory::s_Free(nullptr); + m_pHistory = nullptr; + m_state->CleanupGlobalInputBuffer(); m_state->CleanupGlobalScreenBuffer(); diff --git a/src/host/ut_host/CommandLineTests.cpp b/src/host/ut_host/CommandLineTests.cpp index c5988c8e9..78f253b1b 100644 --- a/src/host/ut_host/CommandLineTests.cpp +++ b/src/host/ut_host/CommandLineTests.cpp @@ -43,12 +43,13 @@ class CommandLineTests m_state->PrepareGlobalScreenBuffer(); m_state->PrepareGlobalInputBuffer(); m_state->PrepareReadHandle(); - m_state->PrepareCookedReadData(); m_pHistory = CommandHistory::s_Allocate(L"cmd.exe", nullptr); if (!m_pHistory) { return false; } + // History must be prepared before COOKED_READ (as it uses s_Find to get at it) + m_state->PrepareCookedReadData(); return true; } diff --git a/src/host/ut_host/CommandListPopupTests.cpp b/src/host/ut_host/CommandListPopupTests.cpp index 2bd19ebae..b0bfe7425 100644 --- a/src/host/ut_host/CommandListPopupTests.cpp +++ b/src/host/ut_host/CommandListPopupTests.cpp @@ -49,7 +49,6 @@ class CommandListPopupTests m_state->PrepareGlobalScreenBuffer(); m_state->PrepareGlobalInputBuffer(); m_state->PrepareReadHandle(); - m_state->PrepareCookedReadData(); m_pHistory = CommandHistory::s_Allocate(L"cmd.exe", nullptr); // resize command history storage to 50 items so that we don't cycle on accident // when PopupTestHelper::InitLongHistory() is called. @@ -58,6 +57,8 @@ class CommandListPopupTests { return false; } + // History must be prepared before COOKED_READ (as it uses s_Find to get at it) + m_state->PrepareCookedReadData(); return true; } diff --git a/src/host/ut_host/CommandNumberPopupTests.cpp b/src/host/ut_host/CommandNumberPopupTests.cpp index 822045223..871ed5f46 100644 --- a/src/host/ut_host/CommandNumberPopupTests.cpp +++ b/src/host/ut_host/CommandNumberPopupTests.cpp @@ -45,12 +45,13 @@ class CommandNumberPopupTests m_state->PrepareGlobalScreenBuffer(); m_state->PrepareGlobalInputBuffer(); m_state->PrepareReadHandle(); - m_state->PrepareCookedReadData(); m_pHistory = CommandHistory::s_Allocate(L"cmd.exe", nullptr); if (!m_pHistory) { return false; } + // History must be prepared before COOKED_READ (as it uses s_Find to get at it) + m_state->PrepareCookedReadData(); return true; } diff --git a/src/host/ut_host/CopyFromCharPopupTests.cpp b/src/host/ut_host/CopyFromCharPopupTests.cpp index 52b147535..e4a42ee5b 100644 --- a/src/host/ut_host/CopyFromCharPopupTests.cpp +++ b/src/host/ut_host/CopyFromCharPopupTests.cpp @@ -24,6 +24,7 @@ class CopyFromCharPopupTests TEST_CLASS(CopyFromCharPopupTests); std::unique_ptr m_state; + CommandHistory* m_pHistory; TEST_CLASS_SETUP(ClassSetup) { @@ -43,12 +44,20 @@ class CopyFromCharPopupTests m_state->PrepareGlobalScreenBuffer(); m_state->PrepareGlobalInputBuffer(); m_state->PrepareReadHandle(); + m_pHistory = CommandHistory::s_Allocate(L"cmd.exe", nullptr); + if (!m_pHistory) + { + return false; + } + // History must be prepared before COOKED_READ (as it uses s_Find to get at it) m_state->PrepareCookedReadData(); return true; } TEST_METHOD_CLEANUP(MethodCleanup) { + CommandHistory::s_Free(nullptr); + m_pHistory = nullptr; m_state->CleanupCookedReadData(); m_state->CleanupReadHandle(); m_state->CleanupGlobalInputBuffer(); diff --git a/src/host/ut_host/CopyToCharPopupTests.cpp b/src/host/ut_host/CopyToCharPopupTests.cpp index 750991074..752922a91 100644 --- a/src/host/ut_host/CopyToCharPopupTests.cpp +++ b/src/host/ut_host/CopyToCharPopupTests.cpp @@ -44,12 +44,13 @@ class CopyToCharPopupTests m_state->PrepareGlobalScreenBuffer(); m_state->PrepareGlobalInputBuffer(); m_state->PrepareReadHandle(); - m_state->PrepareCookedReadData(); m_pHistory = CommandHistory::s_Allocate(L"cmd.exe", nullptr); if (!m_pHistory) { return false; } + // History must be prepared before COOKED_READ (as it uses s_Find to get at it) + m_state->PrepareCookedReadData(); return true; } diff --git a/src/host/ut_host/SelectionTests.cpp b/src/host/ut_host/SelectionTests.cpp index 80515ceb6..9380990f2 100644 --- a/src/host/ut_host/SelectionTests.cpp +++ b/src/host/ut_host/SelectionTests.cpp @@ -412,6 +412,7 @@ class SelectionInputTests TEST_CLASS(SelectionInputTests); CommonState* m_state; + CommandHistory* m_pHistory; TEST_CLASS_SETUP(ClassSetup) { @@ -420,12 +421,20 @@ class SelectionInputTests m_state->PrepareGlobalFont(); m_state->PrepareGlobalScreenBuffer(); m_state->PrepareGlobalInputBuffer(); + m_pHistory = CommandHistory::s_Allocate(L"cmd.exe", nullptr); + if (!m_pHistory) + { + return false; + } + // History must be prepared before COOKED_READ (as it uses s_Find to get at it) return true; } TEST_CLASS_CLEANUP(ClassCleanup) { + CommandHistory::s_Free(nullptr); + m_pHistory = nullptr; m_state->CleanupGlobalScreenBuffer(); m_state->CleanupGlobalFont(); m_state->CleanupGlobalInputBuffer(); From 27e042b78479c2ec94bdc2bb7f5a03bf3f75fa63 Mon Sep 17 00:00:00 2001 From: James Holderness Date: Wed, 3 Nov 2021 00:48:05 +0000 Subject: [PATCH 07/23] Default all G-sets to ASCII unless ISO-2022 is requested (#11658) ## Summary of the Pull Request There is a non-zero subset of applications that randomly output _Locking Shift_ escape sequences which will invoke a character set from G2 or G3 into the left half of the code table. If those G-sets are mapped to Latin1, that can result in the terminal producing output that appears to be broken. This PR now defaults all G-sets to ASCII, to prevent an unintentional _Locking Shift_ from having any effect. ## PR Checklist * [x] Closes #10408 * [x] CLA signed. * [ ] Tests added/passed * [ ] Documentation updated. * [ ] Schema updated. * [x] I've discussed this with core contributors already. Issue number where discussion took place: #10408 ## Detailed Description of the Pull Request / Additional comments Most other modern terminals also default to ASCII in all G-sets, so this shouldn't break any modern applications. Legacy 8-bit applications may still expect the G2 and G3 sets mapped to Latin1, but they would also need to have the ISO-2022 encoding enabled, so we can keep them happy by setting G2 and G3 correctly when the ISO-2022 encoding is requested. ## Validation Steps Performed I've manually confirmed that `echo -e "\en"` and `echo -e "\eo"` no longer have any visible effect on the output (at least without first invoking another character set into G2 or G3). I've also confirmed that they do still work as expected (i.e. selecting Latin1) after enabling the ISO-2022 encoding. --- src/terminal/adapter/terminalOutput.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/terminal/adapter/terminalOutput.cpp b/src/terminal/adapter/terminalOutput.cpp index 944ff88b7..ac3c5e6d1 100644 --- a/src/terminal/adapter/terminalOutput.cpp +++ b/src/terminal/adapter/terminalOutput.cpp @@ -10,10 +10,16 @@ using namespace Microsoft::Console::VirtualTerminal; TerminalOutput::TerminalOutput() noexcept { + // By default we set all of the G-sets to ASCII, so if someone accidentally + // triggers a locking shift, they won't end up with Latin1 in the GL table, + // making their system unreadable. If ISO-2022 encoding is selected, though, + // we'll reset the G2 and G3 tables to Latin1, so that 8-bit apps will get a + // more meaningful character mapping by default. This is triggered by a DOCS + // sequence, which will call the EnableGrTranslation method below. _gsetTranslationTables.at(0) = Ascii; _gsetTranslationTables.at(1) = Ascii; - _gsetTranslationTables.at(2) = Latin1; - _gsetTranslationTables.at(3) = Latin1; + _gsetTranslationTables.at(2) = Ascii; + _gsetTranslationTables.at(3) = Ascii; } bool TerminalOutput::Designate94Charset(size_t gsetNumber, const VTID charset) @@ -91,7 +97,13 @@ bool TerminalOutput::NeedToTranslate() const noexcept void TerminalOutput::EnableGrTranslation(boolean enabled) { _grTranslationEnabled = enabled; - // We need to reapply the right locking shift to (de)activate the translation table. + // The default table for G2 and G3 is Latin1 when GR translation is enabled, + // and ASCII when disabled. The reason for this is explained in the constructor. + const auto defaultTranslationTable = enabled ? std::wstring_view{ Latin1 } : std::wstring_view{ Ascii }; + _gsetTranslationTables.at(2) = defaultTranslationTable; + _gsetTranslationTables.at(3) = defaultTranslationTable; + // We need to reapply the locking shifts in case the underlying G-sets have changed. + LockingShift(_glSetNumber); LockingShiftRight(_grSetNumber); } From 726b4281840984818d928ed47d4fd6910dea4960 Mon Sep 17 00:00:00 2001 From: PankajBhojwani Date: Wed, 3 Nov 2021 08:01:20 -0700 Subject: [PATCH 08/23] Use X-macros to simplify new setting creation in SettingsModel (#11416) Introduces X-macros to reduce the number of places we need to write essentially the same line of code but for a different setting (declaring it in the header file, in `Copy`, `LayerJson`, `ToJson`, etc). --- .../AppearanceConfig.cpp | 61 ++---- .../TerminalSettingsModel/AppearanceConfig.h | 19 +- .../TerminalSettingsModel/FontConfig.cpp | 34 ++-- .../TerminalSettingsModel/FontConfig.h | 10 +- .../GlobalAppSettings.cpp | 177 ++---------------- .../TerminalSettingsModel/GlobalAppSettings.h | 45 +---- .../TerminalSettingsModel/MTSMSettings.h | 96 ++++++++++ ...crosoft.Terminal.Settings.ModelLib.vcxproj | 1 + ...Terminal.Settings.ModelLib.vcxproj.filters | 1 + .../TerminalSettingsModel/Profile.cpp | 82 ++------ src/cascadia/TerminalSettingsModel/Profile.h | 42 ++--- 11 files changed, 190 insertions(+), 378 deletions(-) create mode 100644 src/cascadia/TerminalSettingsModel/MTSMSettings.h diff --git a/src/cascadia/TerminalSettingsModel/AppearanceConfig.cpp b/src/cascadia/TerminalSettingsModel/AppearanceConfig.cpp index dcc1677e6..d48763eca 100644 --- a/src/cascadia/TerminalSettingsModel/AppearanceConfig.cpp +++ b/src/cascadia/TerminalSettingsModel/AppearanceConfig.cpp @@ -16,17 +16,6 @@ static constexpr std::string_view ForegroundKey{ "foreground" }; static constexpr std::string_view BackgroundKey{ "background" }; static constexpr std::string_view SelectionBackgroundKey{ "selectionBackground" }; static constexpr std::string_view CursorColorKey{ "cursorColor" }; -static constexpr std::string_view CursorShapeKey{ "cursorShape" }; -static constexpr std::string_view CursorHeightKey{ "cursorHeight" }; -static constexpr std::string_view BackgroundImageKey{ "backgroundImage" }; -static constexpr std::string_view ColorSchemeKey{ "colorScheme" }; -static constexpr std::string_view BackgroundImageOpacityKey{ "backgroundImageOpacity" }; -static constexpr std::string_view BackgroundImageStretchModeKey{ "backgroundImageStretchMode" }; -static constexpr std::string_view BackgroundImageAlignmentKey{ "backgroundImageAlignment" }; -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 AdjustIndistinguishableColorsKey{ "adjustIndistinguishableColors" }; static constexpr std::string_view LegacyAcrylicTransparencyKey{ "acrylicOpacity" }; static constexpr std::string_view OpacityKey{ "opacity" }; @@ -38,22 +27,17 @@ AppearanceConfig::AppearanceConfig(winrt::weak_ref sourceProfile) : winrt::com_ptr AppearanceConfig::CopyAppearance(const AppearanceConfig* source, winrt::weak_ref sourceProfile) { auto appearance{ winrt::make_self(std::move(sourceProfile)) }; - appearance->_BackgroundImagePath = source->_BackgroundImagePath; - appearance->_BackgroundImageOpacity = source->_BackgroundImageOpacity; - appearance->_BackgroundImageStretchMode = source->_BackgroundImageStretchMode; - appearance->_ColorSchemeName = source->_ColorSchemeName; appearance->_Foreground = source->_Foreground; appearance->_Background = source->_Background; appearance->_SelectionBackground = source->_SelectionBackground; appearance->_CursorColor = source->_CursorColor; - appearance->_CursorShape = source->_CursorShape; - appearance->_CursorHeight = source->_CursorHeight; - appearance->_BackgroundImageAlignment = source->_BackgroundImageAlignment; - appearance->_RetroTerminalEffect = source->_RetroTerminalEffect; - appearance->_PixelShaderPath = source->_PixelShaderPath; - appearance->_IntenseTextStyle = source->_IntenseTextStyle; appearance->_Opacity = source->_Opacity; - appearance->_AdjustIndistinguishableColors = source->_AdjustIndistinguishableColors; + +#define APPEARANCE_SETTINGS_COPY(type, name, jsonKey, ...) \ + appearance->_##name = source->_##name; + MTSM_APPEARANCE_SETTINGS(APPEARANCE_SETTINGS_COPY) +#undef APPEARANCE_SETTINGS_COPY + return appearance; } @@ -65,19 +49,13 @@ Json::Value AppearanceConfig::ToJson() const JsonUtils::SetValueForKey(json, BackgroundKey, _Background); JsonUtils::SetValueForKey(json, SelectionBackgroundKey, _SelectionBackground); JsonUtils::SetValueForKey(json, CursorColorKey, _CursorColor); - JsonUtils::SetValueForKey(json, ColorSchemeKey, _ColorSchemeName); - JsonUtils::SetValueForKey(json, CursorHeightKey, _CursorHeight); - JsonUtils::SetValueForKey(json, CursorShapeKey, _CursorShape); - JsonUtils::SetValueForKey(json, BackgroundImageKey, _BackgroundImagePath); - JsonUtils::SetValueForKey(json, BackgroundImageOpacityKey, _BackgroundImageOpacity); - JsonUtils::SetValueForKey(json, BackgroundImageStretchModeKey, _BackgroundImageStretchMode); - JsonUtils::SetValueForKey(json, BackgroundImageAlignmentKey, _BackgroundImageAlignment); - JsonUtils::SetValueForKey(json, RetroTerminalEffectKey, _RetroTerminalEffect); - JsonUtils::SetValueForKey(json, PixelShaderPathKey, _PixelShaderPath); - JsonUtils::SetValueForKey(json, IntenseTextStyleKey, _IntenseTextStyle); - JsonUtils::SetValueForKey(json, AdjustIndistinguishableColorsKey, _AdjustIndistinguishableColors); JsonUtils::SetValueForKey(json, OpacityKey, _Opacity, JsonUtils::OptionalConverter{}); +#define APPEARANCE_SETTINGS_TO_JSON(type, name, jsonKey, ...) \ + JsonUtils::SetValueForKey(json, jsonKey, _##name); + MTSM_APPEARANCE_SETTINGS(APPEARANCE_SETTINGS_TO_JSON) +#undef APPEARANCE_SETTINGS_TO_JSON + return json; } @@ -98,19 +76,14 @@ void AppearanceConfig::LayerJson(const Json::Value& json) JsonUtils::GetValueForKey(json, BackgroundKey, _Background); JsonUtils::GetValueForKey(json, SelectionBackgroundKey, _SelectionBackground); JsonUtils::GetValueForKey(json, CursorColorKey, _CursorColor); - JsonUtils::GetValueForKey(json, CursorHeightKey, _CursorHeight); - JsonUtils::GetValueForKey(json, ColorSchemeKey, _ColorSchemeName); - JsonUtils::GetValueForKey(json, CursorShapeKey, _CursorShape); - JsonUtils::GetValueForKey(json, BackgroundImageKey, _BackgroundImagePath); - JsonUtils::GetValueForKey(json, BackgroundImageOpacityKey, _BackgroundImageOpacity); - JsonUtils::GetValueForKey(json, BackgroundImageStretchModeKey, _BackgroundImageStretchMode); - JsonUtils::GetValueForKey(json, BackgroundImageAlignmentKey, _BackgroundImageAlignment); - JsonUtils::GetValueForKey(json, RetroTerminalEffectKey, _RetroTerminalEffect); - JsonUtils::GetValueForKey(json, PixelShaderPathKey, _PixelShaderPath); - JsonUtils::GetValueForKey(json, IntenseTextStyleKey, _IntenseTextStyle); - JsonUtils::GetValueForKey(json, AdjustIndistinguishableColorsKey, _AdjustIndistinguishableColors); + JsonUtils::GetValueForKey(json, LegacyAcrylicTransparencyKey, _Opacity); JsonUtils::GetValueForKey(json, OpacityKey, _Opacity, JsonUtils::OptionalConverter{}); + +#define APPEARANCE_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \ + JsonUtils::GetValueForKey(json, jsonKey, _##name); + MTSM_APPEARANCE_SETTINGS(APPEARANCE_SETTINGS_LAYER_JSON) +#undef APPEARANCE_SETTINGS_LAYER_JSON } winrt::Microsoft::Terminal::Settings::Model::Profile AppearanceConfig::SourceProfile() diff --git a/src/cascadia/TerminalSettingsModel/AppearanceConfig.h b/src/cascadia/TerminalSettingsModel/AppearanceConfig.h index 6cf9a5f2d..bbc30927e 100644 --- a/src/cascadia/TerminalSettingsModel/AppearanceConfig.h +++ b/src/cascadia/TerminalSettingsModel/AppearanceConfig.h @@ -19,6 +19,7 @@ Author(s): #include "AppearanceConfig.g.h" #include "JsonUtils.h" #include "IInheritable.h" +#include "MTSMSettings.h" #include namespace winrt::Microsoft::Terminal::Settings::Model::implementation @@ -35,26 +36,16 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation winrt::hstring ExpandedBackgroundImagePath(); - INHERITABLE_SETTING(Model::IAppearanceConfig, ConvergedAlignment, BackgroundImageAlignment, ConvergedAlignment::Horizontal_Center | ConvergedAlignment::Vertical_Center); - - INHERITABLE_SETTING(Model::IAppearanceConfig, uint32_t, CursorHeight, DEFAULT_CURSOR_HEIGHT); - INHERITABLE_SETTING(Model::IAppearanceConfig, hstring, ColorSchemeName, L"Campbell"); INHERITABLE_NULLABLE_SETTING(Model::IAppearanceConfig, Microsoft::Terminal::Core::Color, Foreground, nullptr); INHERITABLE_NULLABLE_SETTING(Model::IAppearanceConfig, Microsoft::Terminal::Core::Color, Background, nullptr); INHERITABLE_NULLABLE_SETTING(Model::IAppearanceConfig, Microsoft::Terminal::Core::Color, SelectionBackground, nullptr); INHERITABLE_NULLABLE_SETTING(Model::IAppearanceConfig, Microsoft::Terminal::Core::Color, CursorColor, nullptr); - INHERITABLE_SETTING(Model::IAppearanceConfig, Microsoft::Terminal::Core::CursorStyle, CursorShape, Microsoft::Terminal::Core::CursorStyle::Bar); - INHERITABLE_SETTING(Model::IAppearanceConfig, hstring, BackgroundImagePath); - - INHERITABLE_SETTING(Model::IAppearanceConfig, double, BackgroundImageOpacity, 1.0); - INHERITABLE_SETTING(Model::IAppearanceConfig, Windows::UI::Xaml::Media::Stretch, BackgroundImageStretchMode, Windows::UI::Xaml::Media::Stretch::UniformToFill); - - INHERITABLE_SETTING(Model::IAppearanceConfig, bool, RetroTerminalEffect, false); - INHERITABLE_SETTING(Model::IAppearanceConfig, hstring, PixelShaderPath, L""); - INHERITABLE_SETTING(Model::IAppearanceConfig, Model::IntenseStyle, IntenseTextStyle, Model::IntenseStyle::Bright); INHERITABLE_SETTING(Model::IAppearanceConfig, double, Opacity, 1.0); - INHERITABLE_SETTING(Model::IAppearanceConfig, bool, AdjustIndistinguishableColors, true); +#define APPEARANCE_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \ + INHERITABLE_SETTING(Model::IAppearanceConfig, type, name, ##__VA_ARGS__) + MTSM_APPEARANCE_SETTINGS(APPEARANCE_SETTINGS_INITIALIZE) +#undef APPEARANCE_SETTINGS_INITIALIZE private: winrt::weak_ref _sourceProfile; diff --git a/src/cascadia/TerminalSettingsModel/FontConfig.cpp b/src/cascadia/TerminalSettingsModel/FontConfig.cpp index 5d57eb355..62ebc5aac 100644 --- a/src/cascadia/TerminalSettingsModel/FontConfig.cpp +++ b/src/cascadia/TerminalSettingsModel/FontConfig.cpp @@ -12,11 +12,6 @@ using namespace Microsoft::Terminal::Settings::Model; using namespace winrt::Microsoft::Terminal::Settings::Model::implementation; static constexpr std::string_view FontInfoKey{ "font" }; -static constexpr std::string_view FontFaceKey{ "face" }; -static constexpr std::string_view FontSizeKey{ "size" }; -static constexpr std::string_view FontWeightKey{ "weight" }; -static constexpr std::string_view FontFeaturesKey{ "features" }; -static constexpr std::string_view FontAxesKey{ "axes" }; static constexpr std::string_view LegacyFontFaceKey{ "fontFace" }; static constexpr std::string_view LegacyFontSizeKey{ "fontSize" }; static constexpr std::string_view LegacyFontWeightKey{ "fontWeight" }; @@ -29,11 +24,12 @@ winrt::Microsoft::Terminal::Settings::Model::implementation::FontConfig::FontCon winrt::com_ptr FontConfig::CopyFontInfo(const FontConfig* source, winrt::weak_ref sourceProfile) { auto fontInfo{ winrt::make_self(std::move(sourceProfile)) }; - fontInfo->_FontFace = source->_FontFace; - fontInfo->_FontSize = source->_FontSize; - fontInfo->_FontWeight = source->_FontWeight; - fontInfo->_FontAxes = source->_FontAxes; - fontInfo->_FontFeatures = source->_FontFeatures; + +#define FONT_SETTINGS_COPY(type, name, jsonKey, ...) \ + fontInfo->_##name = source->_##name; + MTSM_FONT_SETTINGS(FONT_SETTINGS_COPY) +#undef FONT_SETTINGS_COPY + return fontInfo; } @@ -41,11 +37,10 @@ Json::Value FontConfig::ToJson() const { Json::Value json{ Json::ValueType::objectValue }; - JsonUtils::SetValueForKey(json, FontFaceKey, _FontFace); - JsonUtils::SetValueForKey(json, FontSizeKey, _FontSize); - JsonUtils::SetValueForKey(json, FontWeightKey, _FontWeight); - JsonUtils::SetValueForKey(json, FontAxesKey, _FontAxes); - JsonUtils::SetValueForKey(json, FontFeaturesKey, _FontFeatures); +#define FONT_SETTINGS_TO_JSON(type, name, jsonKey, ...) \ + JsonUtils::SetValueForKey(json, jsonKey, _##name); + MTSM_FONT_SETTINGS(FONT_SETTINGS_TO_JSON) +#undef FONT_SETTINGS_TO_JSON return json; } @@ -69,11 +64,10 @@ void FontConfig::LayerJson(const Json::Value& json) { // A font object is defined, use that const auto fontInfoJson = json[JsonKey(FontInfoKey)]; - JsonUtils::GetValueForKey(fontInfoJson, FontFaceKey, _FontFace); - JsonUtils::GetValueForKey(fontInfoJson, FontSizeKey, _FontSize); - JsonUtils::GetValueForKey(fontInfoJson, FontWeightKey, _FontWeight); - JsonUtils::GetValueForKey(fontInfoJson, FontFeaturesKey, _FontFeatures); - JsonUtils::GetValueForKey(fontInfoJson, FontAxesKey, _FontAxes); +#define FONT_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \ + JsonUtils::GetValueForKey(fontInfoJson, jsonKey, _##name); + MTSM_FONT_SETTINGS(FONT_SETTINGS_LAYER_JSON) +#undef FONT_SETTINGS_LAYER_JSON } else { diff --git a/src/cascadia/TerminalSettingsModel/FontConfig.h b/src/cascadia/TerminalSettingsModel/FontConfig.h index 6c53ed4ea..db69fd08f 100644 --- a/src/cascadia/TerminalSettingsModel/FontConfig.h +++ b/src/cascadia/TerminalSettingsModel/FontConfig.h @@ -19,6 +19,7 @@ Author(s): #include "pch.h" #include "FontConfig.g.h" #include "JsonUtils.h" +#include "MTSMSettings.h" #include "../inc/cppwinrt_utils.h" #include "IInheritable.h" #include @@ -39,11 +40,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation Model::Profile SourceProfile(); - INHERITABLE_SETTING(Model::FontConfig, hstring, FontFace, DEFAULT_FONT_FACE); - INHERITABLE_SETTING(Model::FontConfig, int32_t, FontSize, DEFAULT_FONT_SIZE); - INHERITABLE_SETTING(Model::FontConfig, Windows::UI::Text::FontWeight, FontWeight, DEFAULT_FONT_WEIGHT); - INHERITABLE_SETTING(Model::FontConfig, IFontAxesMap, FontAxes); - INHERITABLE_SETTING(Model::FontConfig, IFontFeatureMap, FontFeatures); +#define FONT_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \ + INHERITABLE_SETTING(Model::FontConfig, type, name, ##__VA_ARGS__) + MTSM_FONT_SETTINGS(FONT_SETTINGS_INITIALIZE) +#undef FONT_SETTINGS_INITIALIZE private: winrt::weak_ref _sourceProfile; diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp index 2680cb857..0ffe584fc 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp @@ -18,48 +18,7 @@ using namespace winrt::Microsoft::UI::Xaml::Controls; static constexpr std::string_view LegacyKeybindingsKey{ "keybindings" }; static constexpr std::string_view ActionsKey{ "actions" }; static constexpr std::string_view DefaultProfileKey{ "defaultProfile" }; -static constexpr std::string_view AlwaysShowTabsKey{ "alwaysShowTabs" }; -static constexpr std::string_view InitialRowsKey{ "initialRows" }; -static constexpr std::string_view InitialColsKey{ "initialCols" }; -static constexpr std::string_view InitialPositionKey{ "initialPosition" }; -static constexpr std::string_view CenterOnLaunchKey{ "centerOnLaunch" }; -static constexpr std::string_view ShowTitleInTitlebarKey{ "showTerminalTitleInTitlebar" }; -static constexpr std::string_view LanguageKey{ "language" }; -static constexpr std::string_view ThemeKey{ "theme" }; -static constexpr std::string_view TabWidthModeKey{ "tabWidthMode" }; -static constexpr std::string_view UseAcrylicInTabRowKey{ "useAcrylicInTabRow" }; -static constexpr std::string_view ShowTabsInTitlebarKey{ "showTabsInTitlebar" }; -static constexpr std::string_view WordDelimitersKey{ "wordDelimiters" }; -static constexpr std::string_view InputServiceWarningKey{ "inputServiceWarning" }; -static constexpr std::string_view CopyOnSelectKey{ "copyOnSelect" }; -static constexpr std::string_view CopyFormattingKey{ "copyFormatting" }; -static constexpr std::string_view WarnAboutLargePasteKey{ "largePasteWarning" }; -static constexpr std::string_view WarnAboutMultiLinePasteKey{ "multiLinePasteWarning" }; -static constexpr std::string_view TrimPasteKey{ "trimPaste" }; -static constexpr std::string_view LaunchModeKey{ "launchMode" }; -static constexpr std::string_view ConfirmCloseAllKey{ "confirmCloseAllTabs" }; -static constexpr std::string_view SnapToGridOnResizeKey{ "snapToGridOnResize" }; -static constexpr std::string_view EnableStartupTaskKey{ "startOnUserLogin" }; -static constexpr std::string_view FirstWindowPreferenceKey{ "firstWindowPreference" }; -static constexpr std::string_view AlwaysOnTopKey{ "alwaysOnTop" }; static constexpr std::string_view LegacyUseTabSwitcherModeKey{ "useTabSwitcher" }; -static constexpr std::string_view TabSwitcherModeKey{ "tabSwitcherMode" }; -static constexpr std::string_view DisableAnimationsKey{ "disableAnimations" }; -static constexpr std::string_view StartupActionsKey{ "startupActions" }; -static constexpr std::string_view FocusFollowMouseKey{ "focusFollowMouse" }; -static constexpr std::string_view WindowingBehaviorKey{ "windowingBehavior" }; -static constexpr std::string_view TrimBlockSelectionKey{ "trimBlockSelection" }; -static constexpr std::string_view AlwaysShowNotificationIconKey{ "alwaysShowNotificationIcon" }; -static constexpr std::string_view MinimizeToNotificationAreaKey{ "minimizeToNotificationArea" }; -static constexpr std::string_view DisabledProfileSourcesKey{ "disabledProfileSources" }; -static constexpr std::string_view ShowAdminShieldKey{ "showAdminShield" }; - -static constexpr std::string_view DebugFeaturesKey{ "debugFeatures" }; - -static constexpr std::string_view ForceFullRepaintRenderingKey{ "experimental.rendering.forceFullRepaint" }; -static constexpr std::string_view SoftwareRenderingKey{ "experimental.rendering.software" }; -static constexpr std::string_view ForceVTInputKey{ "experimental.input.forceVT" }; -static constexpr std::string_view DetectURLsKey{ "experimental.detectURLs" }; // Method Description: // - Copies any extraneous data from the parent before completing a CreateChild call @@ -86,45 +45,6 @@ void GlobalAppSettings::_FinalizeInheritance() winrt::com_ptr GlobalAppSettings::Copy() const { auto globals{ winrt::make_self() }; - globals->_InitialRows = _InitialRows; - globals->_InitialCols = _InitialCols; - globals->_AlwaysShowTabs = _AlwaysShowTabs; - globals->_ShowTitleInTitlebar = _ShowTitleInTitlebar; - globals->_ConfirmCloseAllTabs = _ConfirmCloseAllTabs; - globals->_Language = _Language; - globals->_Theme = _Theme; - globals->_TabWidthMode = _TabWidthMode; - globals->_UseAcrylicInTabRow = _UseAcrylicInTabRow; - globals->_ShowTabsInTitlebar = _ShowTabsInTitlebar; - globals->_WordDelimiters = _WordDelimiters; - globals->_InputServiceWarning = _InputServiceWarning; - globals->_CopyOnSelect = _CopyOnSelect; - globals->_CopyFormatting = _CopyFormatting; - globals->_WarnAboutLargePaste = _WarnAboutLargePaste; - globals->_WarnAboutMultiLinePaste = _WarnAboutMultiLinePaste; - globals->_TrimPaste = _TrimPaste; - globals->_InitialPosition = _InitialPosition; - globals->_CenterOnLaunch = _CenterOnLaunch; - globals->_LaunchMode = _LaunchMode; - globals->_SnapToGridOnResize = _SnapToGridOnResize; - globals->_ForceFullRepaintRendering = _ForceFullRepaintRendering; - globals->_SoftwareRendering = _SoftwareRendering; - globals->_ForceVTInput = _ForceVTInput; - globals->_DebugFeaturesEnabled = _DebugFeaturesEnabled; - globals->_StartOnUserLogin = _StartOnUserLogin; - globals->_FirstWindowPreference = _FirstWindowPreference; - globals->_AlwaysOnTop = _AlwaysOnTop; - globals->_TabSwitcherMode = _TabSwitcherMode; - globals->_DisableAnimations = _DisableAnimations; - globals->_StartupActions = _StartupActions; - globals->_FocusFollowMouse = _FocusFollowMouse; - globals->_WindowingBehavior = _WindowingBehavior; - globals->_TrimBlockSelection = _TrimBlockSelection; - globals->_DetectURLs = _DetectURLs; - globals->_MinimizeToNotificationArea = _MinimizeToNotificationArea; - globals->_AlwaysShowNotificationIcon = _AlwaysShowNotificationIcon; - globals->_DisabledProfileSources = _DisabledProfileSources; - globals->_ShowAdminShield = _ShowAdminShield; globals->_UnparsedDefaultProfile = _UnparsedDefaultProfile; @@ -132,6 +52,11 @@ winrt::com_ptr GlobalAppSettings::Copy() const globals->_actionMap = _actionMap->Copy(); globals->_keybindingsWarnings = _keybindingsWarnings; +#define GLOBAL_SETTINGS_COPY(type, name, jsonKey, ...) \ + globals->_##name = _##name; + MTSM_GLOBAL_SETTINGS(GLOBAL_SETTINGS_COPY) +#undef GLOBAL_SETTINGS_COPY + if (_colorSchemes) { for (auto kv : _colorSchemes) @@ -189,51 +114,15 @@ winrt::com_ptr GlobalAppSettings::FromJson(const Json::Value& void GlobalAppSettings::LayerJson(const Json::Value& json) { JsonUtils::GetValueForKey(json, DefaultProfileKey, _UnparsedDefaultProfile); - JsonUtils::GetValueForKey(json, AlwaysShowTabsKey, _AlwaysShowTabs); - JsonUtils::GetValueForKey(json, ConfirmCloseAllKey, _ConfirmCloseAllTabs); - JsonUtils::GetValueForKey(json, InitialRowsKey, _InitialRows); - JsonUtils::GetValueForKey(json, InitialColsKey, _InitialCols); - JsonUtils::GetValueForKey(json, InitialPositionKey, _InitialPosition); - JsonUtils::GetValueForKey(json, CenterOnLaunchKey, _CenterOnLaunch); - JsonUtils::GetValueForKey(json, ShowTitleInTitlebarKey, _ShowTitleInTitlebar); - JsonUtils::GetValueForKey(json, ShowTabsInTitlebarKey, _ShowTabsInTitlebar); - JsonUtils::GetValueForKey(json, WordDelimitersKey, _WordDelimiters); - JsonUtils::GetValueForKey(json, CopyOnSelectKey, _CopyOnSelect); - JsonUtils::GetValueForKey(json, InputServiceWarningKey, _InputServiceWarning); - JsonUtils::GetValueForKey(json, CopyFormattingKey, _CopyFormatting); - JsonUtils::GetValueForKey(json, WarnAboutLargePasteKey, _WarnAboutLargePaste); - JsonUtils::GetValueForKey(json, WarnAboutMultiLinePasteKey, _WarnAboutMultiLinePaste); - JsonUtils::GetValueForKey(json, TrimPasteKey, _TrimPaste); - JsonUtils::GetValueForKey(json, FirstWindowPreferenceKey, _FirstWindowPreference); - JsonUtils::GetValueForKey(json, LaunchModeKey, _LaunchMode); - JsonUtils::GetValueForKey(json, LanguageKey, _Language); - JsonUtils::GetValueForKey(json, ThemeKey, _Theme); - JsonUtils::GetValueForKey(json, TabWidthModeKey, _TabWidthMode); - JsonUtils::GetValueForKey(json, UseAcrylicInTabRowKey, _UseAcrylicInTabRow); - JsonUtils::GetValueForKey(json, SnapToGridOnResizeKey, _SnapToGridOnResize); - // GetValueForKey will only override the current value if the key exists - JsonUtils::GetValueForKey(json, DebugFeaturesKey, _DebugFeaturesEnabled); - JsonUtils::GetValueForKey(json, ForceFullRepaintRenderingKey, _ForceFullRepaintRendering); - JsonUtils::GetValueForKey(json, SoftwareRenderingKey, _SoftwareRendering); - JsonUtils::GetValueForKey(json, ForceVTInputKey, _ForceVTInput); - JsonUtils::GetValueForKey(json, EnableStartupTaskKey, _StartOnUserLogin); - JsonUtils::GetValueForKey(json, AlwaysOnTopKey, _AlwaysOnTop); // GH#8076 - when adding enum values to this key, we also changed it from // "useTabSwitcher" to "tabSwitcherMode". Continue supporting // "useTabSwitcher", but prefer "tabSwitcherMode" JsonUtils::GetValueForKey(json, LegacyUseTabSwitcherModeKey, _TabSwitcherMode); - JsonUtils::GetValueForKey(json, TabSwitcherModeKey, _TabSwitcherMode); - JsonUtils::GetValueForKey(json, DisableAnimationsKey, _DisableAnimations); - JsonUtils::GetValueForKey(json, StartupActionsKey, _StartupActions); - JsonUtils::GetValueForKey(json, FocusFollowMouseKey, _FocusFollowMouse); - JsonUtils::GetValueForKey(json, WindowingBehaviorKey, _WindowingBehavior); - JsonUtils::GetValueForKey(json, TrimBlockSelectionKey, _TrimBlockSelection); - JsonUtils::GetValueForKey(json, DetectURLsKey, _DetectURLs); - JsonUtils::GetValueForKey(json, MinimizeToNotificationAreaKey, _MinimizeToNotificationArea); - JsonUtils::GetValueForKey(json, AlwaysShowNotificationIconKey, _AlwaysShowNotificationIcon); - JsonUtils::GetValueForKey(json, DisabledProfileSourcesKey, _DisabledProfileSources); - JsonUtils::GetValueForKey(json, ShowAdminShieldKey, _ShowAdminShield); +#define GLOBAL_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \ + JsonUtils::GetValueForKey(json, jsonKey, _##name); + MTSM_GLOBAL_SETTINGS(GLOBAL_SETTINGS_LAYER_JSON) +#undef GLOBAL_SETTINGS_LAYER_JSON static constexpr std::array bindingsKeys{ LegacyKeybindingsKey, ActionsKey }; for (const auto& jsonKey : bindingsKeys) @@ -293,48 +182,12 @@ Json::Value GlobalAppSettings::ToJson() const { Json::Value json{ Json::ValueType::objectValue }; - // clang-format off - JsonUtils::SetValueForKey(json, DefaultProfileKey, _UnparsedDefaultProfile); - JsonUtils::SetValueForKey(json, AlwaysShowTabsKey, _AlwaysShowTabs); - JsonUtils::SetValueForKey(json, ConfirmCloseAllKey, _ConfirmCloseAllTabs); - JsonUtils::SetValueForKey(json, InitialRowsKey, _InitialRows); - JsonUtils::SetValueForKey(json, InitialColsKey, _InitialCols); - JsonUtils::SetValueForKey(json, InitialPositionKey, _InitialPosition); - JsonUtils::SetValueForKey(json, CenterOnLaunchKey, _CenterOnLaunch); - JsonUtils::SetValueForKey(json, ShowTitleInTitlebarKey, _ShowTitleInTitlebar); - JsonUtils::SetValueForKey(json, ShowTabsInTitlebarKey, _ShowTabsInTitlebar); - JsonUtils::SetValueForKey(json, WordDelimitersKey, _WordDelimiters); - JsonUtils::SetValueForKey(json, InputServiceWarningKey, _InputServiceWarning); - JsonUtils::SetValueForKey(json, CopyOnSelectKey, _CopyOnSelect); - JsonUtils::SetValueForKey(json, CopyFormattingKey, _CopyFormatting); - JsonUtils::SetValueForKey(json, WarnAboutLargePasteKey, _WarnAboutLargePaste); - JsonUtils::SetValueForKey(json, WarnAboutMultiLinePasteKey, _WarnAboutMultiLinePaste); - JsonUtils::SetValueForKey(json, TrimPasteKey, _TrimPaste); - JsonUtils::SetValueForKey(json, FirstWindowPreferenceKey, _FirstWindowPreference); - JsonUtils::SetValueForKey(json, LaunchModeKey, _LaunchMode); - JsonUtils::SetValueForKey(json, LanguageKey, _Language); - JsonUtils::SetValueForKey(json, ThemeKey, _Theme); - JsonUtils::SetValueForKey(json, TabWidthModeKey, _TabWidthMode); - JsonUtils::SetValueForKey(json, UseAcrylicInTabRowKey, _UseAcrylicInTabRow); - JsonUtils::SetValueForKey(json, SnapToGridOnResizeKey, _SnapToGridOnResize); - JsonUtils::SetValueForKey(json, DebugFeaturesKey, _DebugFeaturesEnabled); - JsonUtils::SetValueForKey(json, ForceFullRepaintRenderingKey, _ForceFullRepaintRendering); - JsonUtils::SetValueForKey(json, SoftwareRenderingKey, _SoftwareRendering); - JsonUtils::SetValueForKey(json, ForceVTInputKey, _ForceVTInput); - JsonUtils::SetValueForKey(json, EnableStartupTaskKey, _StartOnUserLogin); - JsonUtils::SetValueForKey(json, AlwaysOnTopKey, _AlwaysOnTop); - JsonUtils::SetValueForKey(json, TabSwitcherModeKey, _TabSwitcherMode); - JsonUtils::SetValueForKey(json, DisableAnimationsKey, _DisableAnimations); - JsonUtils::SetValueForKey(json, StartupActionsKey, _StartupActions); - JsonUtils::SetValueForKey(json, FocusFollowMouseKey, _FocusFollowMouse); - JsonUtils::SetValueForKey(json, WindowingBehaviorKey, _WindowingBehavior); - JsonUtils::SetValueForKey(json, TrimBlockSelectionKey, _TrimBlockSelection); - JsonUtils::SetValueForKey(json, DetectURLsKey, _DetectURLs); - JsonUtils::SetValueForKey(json, MinimizeToNotificationAreaKey, _MinimizeToNotificationArea); - JsonUtils::SetValueForKey(json, AlwaysShowNotificationIconKey, _AlwaysShowNotificationIcon); - JsonUtils::SetValueForKey(json, DisabledProfileSourcesKey, _DisabledProfileSources); - JsonUtils::SetValueForKey(json, ShowAdminShieldKey, _ShowAdminShield); - // clang-format on + JsonUtils::SetValueForKey(json, DefaultProfileKey, _UnparsedDefaultProfile); + +#define GLOBAL_SETTINGS_TO_JSON(type, name, jsonKey, ...) \ + JsonUtils::SetValueForKey(json, jsonKey, _##name); + MTSM_GLOBAL_SETTINGS(GLOBAL_SETTINGS_TO_JSON) +#undef GLOBAL_SETTINGS_TO_JSON json[JsonKey(ActionsKey)] = _actionMap->ToJson(); return json; diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h index 022700264..14584b26a 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h @@ -17,6 +17,7 @@ Author(s): #include "GlobalAppSettings.g.h" #include "IInheritable.h" +#include "MTSMSettings.h" #include "ActionMap.h" #include "Command.h" @@ -61,46 +62,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation 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); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, ShowTitleInTitlebar, true); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, ConfirmCloseAllTabs, true); - INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, Language); - INHERITABLE_SETTING(Model::GlobalAppSettings, winrt::Windows::UI::Xaml::ElementTheme, Theme, winrt::Windows::UI::Xaml::ElementTheme::Default); - INHERITABLE_SETTING(Model::GlobalAppSettings, winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, TabWidthMode, winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode::Equal); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, UseAcrylicInTabRow, false); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, ShowTabsInTitlebar, true); - INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, WordDelimiters, DEFAULT_WORD_DELIMITERS); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, CopyOnSelect, false); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, InputServiceWarning, true); - INHERITABLE_SETTING(Model::GlobalAppSettings, winrt::Microsoft::Terminal::Control::CopyFormat, CopyFormatting, 0); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, WarnAboutLargePaste, true); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, WarnAboutMultiLinePaste, true); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, TrimPaste, true); - INHERITABLE_SETTING(Model::GlobalAppSettings, Model::LaunchPosition, InitialPosition, nullptr, nullptr); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, CenterOnLaunch, false); - INHERITABLE_SETTING(Model::GlobalAppSettings, Model::FirstWindowPreference, FirstWindowPreference, FirstWindowPreference::DefaultProfile); - INHERITABLE_SETTING(Model::GlobalAppSettings, Model::LaunchMode, LaunchMode, LaunchMode::DefaultMode); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, SnapToGridOnResize, true); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, ForceFullRepaintRendering, false); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, SoftwareRendering, false); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, ForceVTInput, false); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, DebugFeaturesEnabled, debugFeaturesDefault); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, StartOnUserLogin, false); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, AlwaysOnTop, false); - INHERITABLE_SETTING(Model::GlobalAppSettings, Model::TabSwitcherMode, TabSwitcherMode, Model::TabSwitcherMode::InOrder); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, DisableAnimations, false); - INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, StartupActions, L""); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, FocusFollowMouse, false); - INHERITABLE_SETTING(Model::GlobalAppSettings, Model::WindowingMode, WindowingBehavior, Model::WindowingMode::UseNew); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, TrimBlockSelection, false); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, DetectURLs, true); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, MinimizeToNotificationArea, false); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, AlwaysShowNotificationIcon, false); - INHERITABLE_SETTING(Model::GlobalAppSettings, winrt::Windows::Foundation::Collections::IVector, DisabledProfileSources, nullptr); INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, UnparsedDefaultProfile, L""); - INHERITABLE_SETTING(Model::GlobalAppSettings, bool, ShowAdminShield, true); + +#define GLOBAL_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \ + INHERITABLE_SETTING(Model::GlobalAppSettings, type, name, ##__VA_ARGS__) + MTSM_GLOBAL_SETTINGS(GLOBAL_SETTINGS_INITIALIZE) +#undef GLOBAL_SETTINGS_INITIALIZE private: #ifdef NDEBUG diff --git a/src/cascadia/TerminalSettingsModel/MTSMSettings.h b/src/cascadia/TerminalSettingsModel/MTSMSettings.h new file mode 100644 index 000000000..6719818e7 --- /dev/null +++ b/src/cascadia/TerminalSettingsModel/MTSMSettings.h @@ -0,0 +1,96 @@ +/*++ +Copyright (c) Microsoft Corporation +Licensed under the MIT license. + +Module Name: +- MTSMSettings.h + +Abstract: +- Contains most of the settings within Terminal Settings Model (global, profile, font, appearance) +- To add a new setting to any one of those classes, simply add it to the respective list below, following the macro format + +Author(s): +- Pankaj Bhojwani - October 2021 + +--*/ +#pragma once + +// Macro format (defaultArgs are optional): +// (type, name, jsonKey, defaultArgs) + +#define MTSM_GLOBAL_SETTINGS(X) \ + X(int32_t, InitialRows, "initialRows", 30) \ + X(int32_t, InitialCols, "initialCols", 80) \ + X(hstring, WordDelimiters, "wordDelimiters", DEFAULT_WORD_DELIMITERS) \ + X(bool, CopyOnSelect, "copyOnSelect", false) \ + X(bool, FocusFollowMouse, "focusFollowMouse", false) \ + X(bool, ForceFullRepaintRendering, "experimental.rendering.forceFullRepaint", false) \ + X(bool, SoftwareRendering, "experimental.rendering.software", false) \ + X(bool, ForceVTInput, "experimental.input.forceVT", false) \ + X(bool, TrimBlockSelection, "trimBlockSelection", false) \ + X(bool, DetectURLs, "experimental.detectURLs", true) \ + X(bool, AlwaysShowTabs, "alwaysShowTabs", true) \ + X(bool, ShowTitleInTitlebar, "showTerminalTitleInTitlebar", true) \ + X(bool, ConfirmCloseAllTabs, "confirmCloseAllTabs", true) \ + X(hstring, Language, "language") \ + X(winrt::Windows::UI::Xaml::ElementTheme, Theme, "theme", winrt::Windows::UI::Xaml::ElementTheme::Default) \ + X(winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, TabWidthMode, "tabWidthMode", winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode::Equal) \ + X(bool, UseAcrylicInTabRow, "useAcrylicInTabRow", false) \ + X(bool, ShowTabsInTitlebar, "showTabsInTitlebar", true) \ + X(bool, InputServiceWarning, "inputServiceWarning", true) \ + X(winrt::Microsoft::Terminal::Control::CopyFormat, CopyFormatting, "copyFormatting", 0) \ + X(bool, WarnAboutLargePaste, "largePasteWarning", true) \ + X(bool, WarnAboutMultiLinePaste, "multiLinePasteWarning", true) \ + X(Model::LaunchPosition, InitialPosition, "initialPosition", nullptr, nullptr) \ + X(bool, CenterOnLaunch, "centerOnLaunch", false) \ + X(Model::FirstWindowPreference, FirstWindowPreference, "firstWindowPreference", FirstWindowPreference::DefaultProfile) \ + X(Model::LaunchMode, LaunchMode, "launchMode", LaunchMode::DefaultMode) \ + X(bool, SnapToGridOnResize, "snapToGridOnResize", true) \ + X(bool, DebugFeaturesEnabled, "debugFeatures", debugFeaturesDefault) \ + X(bool, StartOnUserLogin, "startOnUserLogin", false) \ + X(bool, AlwaysOnTop, "alwaysOnTop", false) \ + X(Model::TabSwitcherMode, TabSwitcherMode, "tabSwitcherMode", Model::TabSwitcherMode::InOrder) \ + X(bool, DisableAnimations, "disableAnimations", false) \ + X(hstring, StartupActions, "startupActions", L"") \ + X(Model::WindowingMode, WindowingBehavior, "windowingBehavior", Model::WindowingMode::UseNew) \ + X(bool, MinimizeToNotificationArea, "minimizeToNotificationArea", false) \ + X(bool, AlwaysShowNotificationIcon, "alwaysShowNotificationIcon", false) \ + X(winrt::Windows::Foundation::Collections::IVector, DisabledProfileSources, "disabledProfileSources", nullptr) \ + X(bool, ShowAdminShield, "showAdminShield", true) \ + X(bool, TrimPaste, "trimPaste", true) + +#define MTSM_PROFILE_SETTINGS(X) \ + X(int32_t, HistorySize, "historySize", DEFAULT_HISTORY_SIZE) \ + X(bool, SnapOnInput, "snapOnInput", true) \ + X(bool, AltGrAliasing, "altGrAliasing", true) \ + X(bool, UseAcrylic, "useAcrylic", false) \ + X(hstring, Commandline, "commandline", L"%SystemRoot%\\System32\\cmd.exe") \ + X(Microsoft::Terminal::Control::ScrollbarState, ScrollState, "scrollbarState", Microsoft::Terminal::Control::ScrollbarState::Visible) \ + X(Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, "antialiasingMode", Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale) \ + X(hstring, StartingDirectory, "startingDirectory") \ + X(bool, SuppressApplicationTitle, "suppressApplicationTitle", false) \ + X(guid, ConnectionType, "connectionType") \ + X(hstring, Icon, "icon", L"\uE756") \ + X(CloseOnExitMode, CloseOnExit, "closeOnExit", CloseOnExitMode::Graceful) \ + X(hstring, TabTitle, "tabTitle") \ + X(Model::BellStyle, BellStyle, "bellStyle", BellStyle::Audible) + +#define MTSM_FONT_SETTINGS(X) \ + X(hstring, FontFace, "face", DEFAULT_FONT_FACE) \ + X(int32_t, FontSize, "size", DEFAULT_FONT_SIZE) \ + X(winrt::Windows::UI::Text::FontWeight, FontWeight, "weight", DEFAULT_FONT_WEIGHT) \ + X(IFontAxesMap, FontAxes, "axes") \ + X(IFontFeatureMap, FontFeatures, "features") + +#define MTSM_APPEARANCE_SETTINGS(X) \ + X(Core::CursorStyle, CursorShape, "cursorShape", Core::CursorStyle::Bar) \ + X(uint32_t, CursorHeight, "cursorHeight", DEFAULT_CURSOR_HEIGHT) \ + X(double, BackgroundImageOpacity, "backgroundImageOpacity", 1.0) \ + X(winrt::Windows::UI::Xaml::Media::Stretch, BackgroundImageStretchMode, "backgroundImageStretchMode", winrt::Windows::UI::Xaml::Media::Stretch::UniformToFill) \ + X(bool, RetroTerminalEffect, "experimental.retroTerminalEffect", false) \ + X(hstring, PixelShaderPath, "experimental.pixelShaderPath") \ + X(ConvergedAlignment, BackgroundImageAlignment, "backgroundImageAlignment", ConvergedAlignment::Horizontal_Center | ConvergedAlignment::Vertical_Center) \ + X(hstring, ColorSchemeName, "colorScheme", L"Campbell") \ + X(hstring, BackgroundImagePath, "backgroundImage") \ + X(Model::IntenseStyle, IntenseTextStyle, "intenseTextStyle", Model::IntenseStyle::Bright) \ + X(bool, AdjustIndistinguishableColors, "adjustIndistinguishableColors", true) diff --git a/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj b/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj index 60de4fd1c..5afc82375 100644 --- a/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj +++ b/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj @@ -50,6 +50,7 @@ GlobalAppSettings.idl + diff --git a/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj.filters b/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj.filters index a99f5e654..287892c4a 100644 --- a/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj.filters +++ b/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj.filters @@ -76,6 +76,7 @@ json + diff --git a/src/cascadia/TerminalSettingsModel/Profile.cpp b/src/cascadia/TerminalSettingsModel/Profile.cpp index 287ce8970..c7b104e9a 100644 --- a/src/cascadia/TerminalSettingsModel/Profile.cpp +++ b/src/cascadia/TerminalSettingsModel/Profile.cpp @@ -26,24 +26,9 @@ static constexpr std::string_view GuidKey{ "guid" }; static constexpr std::string_view SourceKey{ "source" }; static constexpr std::string_view HiddenKey{ "hidden" }; -static constexpr std::string_view TabTitleKey{ "tabTitle" }; -static constexpr std::string_view SuppressApplicationTitleKey{ "suppressApplicationTitle" }; -static constexpr std::string_view HistorySizeKey{ "historySize" }; -static constexpr std::string_view SnapOnInputKey{ "snapOnInput" }; -static constexpr std::string_view AltGrAliasingKey{ "altGrAliasing" }; - -static constexpr std::string_view ConnectionTypeKey{ "connectionType" }; -static constexpr std::string_view CommandlineKey{ "commandline" }; static constexpr std::string_view FontInfoKey{ "font" }; -static constexpr std::string_view UseAcrylicKey{ "useAcrylic" }; -static constexpr std::string_view ScrollbarStateKey{ "scrollbarState" }; -static constexpr std::string_view CloseOnExitKey{ "closeOnExit" }; static constexpr std::string_view PaddingKey{ "padding" }; -static constexpr std::string_view StartingDirectoryKey{ "startingDirectory" }; -static constexpr std::string_view IconKey{ "icon" }; -static constexpr std::string_view AntialiasingModeKey{ "antialiasingMode" }; static constexpr std::string_view TabColorKey{ "tabColor" }; -static constexpr std::string_view BellStyleKey{ "bellStyle" }; static constexpr std::string_view UnfocusedAppearanceKey{ "unfocusedAppearance" }; Profile::Profile(guid guid) noexcept : @@ -117,28 +102,19 @@ winrt::com_ptr Profile::CopySettings() const profile->_Name = _Name; profile->_Source = _Source; profile->_Hidden = _Hidden; - profile->_Icon = _Icon; - profile->_CloseOnExit = _CloseOnExit; - profile->_TabTitle = _TabTitle; profile->_TabColor = _TabColor; - profile->_SuppressApplicationTitle = _SuppressApplicationTitle; - profile->_UseAcrylic = _UseAcrylic; - profile->_ScrollState = _ScrollState; profile->_Padding = _Padding; - profile->_Commandline = _Commandline; - profile->_StartingDirectory = _StartingDirectory; - profile->_AntialiasingMode = _AntialiasingMode; profile->_ForceFullRepaintRendering = _ForceFullRepaintRendering; profile->_SoftwareRendering = _SoftwareRendering; - profile->_HistorySize = _HistorySize; - profile->_SnapOnInput = _SnapOnInput; - profile->_AltGrAliasing = _AltGrAliasing; - profile->_BellStyle = _BellStyle; - profile->_ConnectionType = _ConnectionType; profile->_Origin = _Origin; profile->_FontInfo = *fontInfo; profile->_DefaultAppearance = *defaultAppearance; +#define PROFILE_SETTINGS_COPY(type, name, jsonKey, ...) \ + profile->_##name = _##name; + MTSM_PROFILE_SETTINGS(PROFILE_SETTINGS_COPY) +#undef PROFILE_SETTINGS_COPY + if (_UnfocusedAppearance) { Model::AppearanceConfig unfocused{ nullptr }; @@ -196,31 +172,16 @@ void Profile::LayerJson(const Json::Value& json) JsonUtils::GetValueForKey(json, HiddenKey, _Hidden); JsonUtils::GetValueForKey(json, SourceKey, _Source); - // TODO:MSFT:20642297 - Use a sentinel value (-1) for "Infinite scrollback" - JsonUtils::GetValueForKey(json, HistorySizeKey, _HistorySize); - JsonUtils::GetValueForKey(json, SnapOnInputKey, _SnapOnInput); - JsonUtils::GetValueForKey(json, AltGrAliasingKey, _AltGrAliasing); - JsonUtils::GetValueForKey(json, TabTitleKey, _TabTitle); - - // Control Settings - JsonUtils::GetValueForKey(json, ConnectionTypeKey, _ConnectionType); - JsonUtils::GetValueForKey(json, CommandlineKey, _Commandline); - JsonUtils::GetValueForKey(json, UseAcrylicKey, _UseAcrylic); - JsonUtils::GetValueForKey(json, SuppressApplicationTitleKey, _SuppressApplicationTitle); - JsonUtils::GetValueForKey(json, CloseOnExitKey, _CloseOnExit); - // Padding was never specified as an integer, but it was a common working mistake. // Allow it to be permissive. JsonUtils::GetValueForKey(json, PaddingKey, _Padding, JsonUtils::OptionalConverter>{}); - JsonUtils::GetValueForKey(json, ScrollbarStateKey, _ScrollState); - - JsonUtils::GetValueForKey(json, StartingDirectoryKey, _StartingDirectory); - - JsonUtils::GetValueForKey(json, IconKey, _Icon); - JsonUtils::GetValueForKey(json, AntialiasingModeKey, _AntialiasingMode); JsonUtils::GetValueForKey(json, TabColorKey, _TabColor); - JsonUtils::GetValueForKey(json, BellStyleKey, _BellStyle); + +#define PROFILE_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \ + JsonUtils::GetValueForKey(json, jsonKey, _##name); + MTSM_PROFILE_SETTINGS(PROFILE_SETTINGS_LAYER_JSON) +#undef PROFILE_SETTINGS_LAYER_JSON if (json.isMember(JsonKey(UnfocusedAppearanceKey))) { @@ -352,28 +313,15 @@ Json::Value Profile::ToJson() const JsonUtils::SetValueForKey(json, HiddenKey, writeBasicSettings ? Hidden() : _Hidden); JsonUtils::SetValueForKey(json, SourceKey, writeBasicSettings ? Source() : _Source); - // TODO:MSFT:20642297 - Use a sentinel value (-1) for "Infinite scrollback" - JsonUtils::SetValueForKey(json, HistorySizeKey, _HistorySize); - JsonUtils::SetValueForKey(json, SnapOnInputKey, _SnapOnInput); - JsonUtils::SetValueForKey(json, AltGrAliasingKey, _AltGrAliasing); - JsonUtils::SetValueForKey(json, TabTitleKey, _TabTitle); - - // Control Settings - JsonUtils::SetValueForKey(json, ConnectionTypeKey, _ConnectionType); - JsonUtils::SetValueForKey(json, CommandlineKey, _Commandline); - JsonUtils::SetValueForKey(json, UseAcrylicKey, _UseAcrylic); - JsonUtils::SetValueForKey(json, SuppressApplicationTitleKey, _SuppressApplicationTitle); - JsonUtils::SetValueForKey(json, CloseOnExitKey, _CloseOnExit); - // PermissiveStringConverter is unnecessary for serialization JsonUtils::SetValueForKey(json, PaddingKey, _Padding); - JsonUtils::SetValueForKey(json, ScrollbarStateKey, _ScrollState); - JsonUtils::SetValueForKey(json, StartingDirectoryKey, _StartingDirectory); - JsonUtils::SetValueForKey(json, IconKey, _Icon); - JsonUtils::SetValueForKey(json, AntialiasingModeKey, _AntialiasingMode); JsonUtils::SetValueForKey(json, TabColorKey, _TabColor); - JsonUtils::SetValueForKey(json, BellStyleKey, _BellStyle); + +#define PROFILE_SETTINGS_TO_JSON(type, name, jsonKey, ...) \ + JsonUtils::SetValueForKey(json, jsonKey, _##name); + MTSM_PROFILE_SETTINGS(PROFILE_SETTINGS_TO_JSON) +#undef PROFILE_SETTINGS_TO_JSON // Font settings const auto fontInfoImpl = winrt::get_self(_FontInfo); diff --git a/src/cascadia/TerminalSettingsModel/Profile.h b/src/cascadia/TerminalSettingsModel/Profile.h index f69471332..b828165a2 100644 --- a/src/cascadia/TerminalSettingsModel/Profile.h +++ b/src/cascadia/TerminalSettingsModel/Profile.h @@ -46,6 +46,7 @@ Author(s): #include "Profile.g.h" #include "IInheritable.h" +#include "MTSMSettings.h" #include "../inc/cppwinrt_utils.h" #include "JsonUtils.h" @@ -102,43 +103,30 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation void _FinalizeInheritance() override; + // Special fields WINRT_PROPERTY(bool, Deleted, false); WINRT_PROPERTY(OriginTag, Origin, OriginTag::None); - WINRT_PROPERTY(guid, Updates); - INHERITABLE_SETTING(Model::Profile, guid, Guid, _GenerateGuidForProfile(Name(), Source())); - INHERITABLE_SETTING(Model::Profile, hstring, Name, L"Default"); - INHERITABLE_SETTING(Model::Profile, hstring, Source); - INHERITABLE_SETTING(Model::Profile, bool, Hidden, false); - INHERITABLE_SETTING(Model::Profile, guid, ConnectionType); - // Default Icon: Segoe MDL2 CommandPrompt icon - INHERITABLE_SETTING(Model::Profile, hstring, Icon, L"\uE756"); - - INHERITABLE_SETTING(Model::Profile, CloseOnExitMode, CloseOnExit, CloseOnExitMode::Graceful); - INHERITABLE_SETTING(Model::Profile, hstring, TabTitle); + // Nullable/optional settings INHERITABLE_NULLABLE_SETTING(Model::Profile, Microsoft::Terminal::Core::Color, TabColor, nullptr); - INHERITABLE_SETTING(Model::Profile, bool, SuppressApplicationTitle, false); + INHERITABLE_SETTING(Model::Profile, Model::IAppearanceConfig, UnfocusedAppearance, nullptr); - INHERITABLE_SETTING(Model::Profile, bool, UseAcrylic, false); - INHERITABLE_SETTING(Model::Profile, Microsoft::Terminal::Control::ScrollbarState, ScrollState, Microsoft::Terminal::Control::ScrollbarState::Visible); - - INHERITABLE_SETTING(Model::Profile, hstring, Padding, DEFAULT_PADDING); - - INHERITABLE_SETTING(Model::Profile, hstring, Commandline, L"%SystemRoot%\\System32\\cmd.exe"); - INHERITABLE_SETTING(Model::Profile, hstring, StartingDirectory); - - INHERITABLE_SETTING(Model::Profile, Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale); + // Global settings INHERITABLE_SETTING(Model::Profile, bool, ForceFullRepaintRendering, false); INHERITABLE_SETTING(Model::Profile, bool, SoftwareRendering, false); - INHERITABLE_SETTING(Model::Profile, int32_t, HistorySize, DEFAULT_HISTORY_SIZE); - INHERITABLE_SETTING(Model::Profile, bool, SnapOnInput, true); - INHERITABLE_SETTING(Model::Profile, bool, AltGrAliasing, true); + // Settings that cannot be put in the macro because of how they are handled in ToJson/LayerJson + INHERITABLE_SETTING(Model::Profile, hstring, Name, L"Default"); + INHERITABLE_SETTING(Model::Profile, hstring, Source); + INHERITABLE_SETTING(Model::Profile, bool, Hidden, false); + INHERITABLE_SETTING(Model::Profile, guid, Guid, _GenerateGuidForProfile(Name(), Source())); + INHERITABLE_SETTING(Model::Profile, hstring, Padding, DEFAULT_PADDING); - INHERITABLE_SETTING(Model::Profile, Model::BellStyle, BellStyle, BellStyle::Audible); - - INHERITABLE_SETTING(Model::Profile, Model::IAppearanceConfig, UnfocusedAppearance, nullptr); +#define PROFILE_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \ + INHERITABLE_SETTING(Model::Profile, type, name, ##__VA_ARGS__) + MTSM_PROFILE_SETTINGS(PROFILE_SETTINGS_INITIALIZE) +#undef PROFILE_SETTINGS_INITIALIZE private: Model::IAppearanceConfig _DefaultAppearance{ winrt::make(weak_ref(*this)) }; From d3ca0e787840e8910bc3f240344142d889eb58d5 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 3 Nov 2021 10:55:16 -0500 Subject: [PATCH 09/23] Add trimPaste to the schema, too (#11644) Closes #11642 See also https://github.com/MicrosoftDocs/terminal/pull/435 --- doc/cascadia/profiles.schema.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index 98f3de653..874667793 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -1478,6 +1478,11 @@ "description": "When set to true, trailing white-spaces will be removed from text in rectangular (block) selection while copied to your clipboard. When set to false, the white-spaces will be preserved.", "type": "boolean" }, + "trimPaste": { + "default": true, + "description": "When enabled, the Terminal will automatically trim trailing whitespace characters when pasting text", + "type": "boolean" + }, "experimental.detectURLs": { "default": true, "description": "When set to true, URLs will be detected by the Terminal. This will cause URLs to underline on hover and be clickable by pressing Ctrl.", From 8826cc028b0e34215aa060a378da4845a2ea9e36 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 3 Nov 2021 17:27:41 -0500 Subject: [PATCH 10/23] Make sure to format the error message with an UNSIGNED int (#11667) Closes #11556 ![image](https://user-images.githubusercontent.com/18356694/139715591-b18ef7c1-2967-42a5-9528-2522220aa177.png) --- src/cascadia/TerminalConnection/ConptyConnection.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cascadia/TerminalConnection/ConptyConnection.cpp b/src/cascadia/TerminalConnection/ConptyConnection.cpp index 9135f8024..a6dcbd3b4 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.cpp +++ b/src/cascadia/TerminalConnection/ConptyConnection.cpp @@ -429,8 +429,9 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation // EXIT POINT const auto hr = wil::ResultFromCaughtException(); + // GH#11556 - make sure to format the error code to this string as an UNSIGNED int winrt::hstring failureText{ fmt::format(std::wstring_view{ RS_(L"ProcessFailedToLaunch") }, - fmt::format(_errorFormat, hr), + fmt::format(_errorFormat, static_cast(hr)), _commandline) }; _TerminalOutputHandlers(failureText); @@ -457,6 +458,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation { try { + // GH#11556 - make sure to format the error code to this string as an UNSIGNED int winrt::hstring exitText{ fmt::format(std::wstring_view{ RS_(L"ProcessExited") }, fmt::format(_errorFormat, status)) }; _TerminalOutputHandlers(L"\r\n"); _TerminalOutputHandlers(exitText); From ab6ba9bdbbbc8a47e5ed194721321fbfc75aaf5f Mon Sep 17 00:00:00 2001 From: Sergey <45919738+serd2011@users.noreply.github.com> Date: Thu, 4 Nov 2021 19:47:58 +0300 Subject: [PATCH 11/23] Add settings entry into titlebar context menu (#11404) ## Summary of the Pull Request Adds ability for app to change system context menu ## PR Checklist * [x] Closes #9666 * [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * [ ] Tests added/passed * [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx * [ ] Schema updated. * [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx ## Validation Steps Performed --- .github/actions/spelling/allow/apis.txt | 2 + src/cascadia/TerminalApp/AppLogic.cpp | 8 +++ src/cascadia/TerminalApp/AppLogic.h | 14 +++++ src/cascadia/TerminalApp/AppLogic.idl | 15 +++++ src/cascadia/TerminalApp/TerminalPage.cpp | 4 +- src/cascadia/TerminalApp/TerminalPage.h | 4 +- src/cascadia/WindowsTerminal/AppHost.cpp | 22 +++++++ src/cascadia/WindowsTerminal/AppHost.h | 3 + src/cascadia/WindowsTerminal/IslandWindow.cpp | 57 +++++++++++++++++++ src/cascadia/WindowsTerminal/IslandWindow.h | 11 ++++ 10 files changed, 136 insertions(+), 4 deletions(-) diff --git a/.github/actions/spelling/allow/apis.txt b/.github/actions/spelling/allow/apis.txt index 19f5fb487..b17163a05 100644 --- a/.github/actions/spelling/allow/apis.txt +++ b/.github/actions/spelling/allow/apis.txt @@ -9,6 +9,7 @@ BUILDBRANCH BUILDMSG BUILDNUMBER BYPOSITION +BYCOMMAND charconv CLASSNOTAVAILABLE cmdletbinding @@ -85,6 +86,7 @@ LSHIFT MENUCOMMAND MENUDATA MENUINFO +MENUITEMINFOW memicmp mptt mov diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index b7e1c0ff3..c2b24d029 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -334,6 +334,9 @@ namespace winrt::TerminalApp::implementation _RefreshThemeRoutine(); _ApplyStartupTaskStateChange(); + auto args = winrt::make_self(RS_(L"SettingsMenuItem"), SystemMenuChangeAction::Add, SystemMenuItemHandler(this, &AppLogic::_OpenSettingsUI)); + _SystemMenuChangeRequestedHandlers(*this, *args); + TraceLoggingWrite( g_hTerminalAppProvider, "AppCreated", @@ -1051,6 +1054,11 @@ namespace winrt::TerminalApp::implementation _SettingsChangedHandlers(*this, nullptr); } + void AppLogic::_OpenSettingsUI() + { + _root->OpenSettingsUI(); + } + // Method Description: // - Returns a pointer to the global shared settings. [[nodiscard]] CascadiaSettings AppLogic::GetSettings() const noexcept diff --git a/src/cascadia/TerminalApp/AppLogic.h b/src/cascadia/TerminalApp/AppLogic.h index e121043d1..9301a6698 100644 --- a/src/cascadia/TerminalApp/AppLogic.h +++ b/src/cascadia/TerminalApp/AppLogic.h @@ -5,6 +5,7 @@ #include "AppLogic.g.h" #include "FindTargetWindowResult.g.h" +#include "SystemMenuChangeArgs.g.h" #include "Jumplist.h" #include "LanguageProfileNotifier.h" #include "TerminalPage.h" @@ -35,6 +36,17 @@ namespace winrt::TerminalApp::implementation FindTargetWindowResult(id, L""){}; }; + struct SystemMenuChangeArgs : SystemMenuChangeArgsT + { + WINRT_PROPERTY(winrt::hstring, Name, L""); + WINRT_PROPERTY(SystemMenuChangeAction, Action, SystemMenuChangeAction::Add); + WINRT_PROPERTY(SystemMenuItemHandler, Handler, nullptr); + + public: + SystemMenuChangeArgs(const winrt::hstring& name, SystemMenuChangeAction action, SystemMenuItemHandler handler = nullptr) : + _Name{ name }, _Action{ action }, _Handler{ handler } {}; + }; + struct AppLogic : AppLogicT { public: @@ -113,6 +125,7 @@ namespace winrt::TerminalApp::implementation // -------------------------------- WinRT Events --------------------------------- TYPED_EVENT(RequestedThemeChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::ElementTheme); TYPED_EVENT(SettingsChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); + TYPED_EVENT(SystemMenuChangeRequested, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::SystemMenuChangeArgs); private: bool _isUwp{ false }; @@ -163,6 +176,7 @@ namespace winrt::TerminalApp::implementation void _RegisterSettingsChange(); fire_and_forget _DispatchReloadSettings(); void _ReloadSettings(); + void _OpenSettingsUI(); void _ApplyTheme(const Windows::UI::Xaml::ElementTheme& newTheme); diff --git a/src/cascadia/TerminalApp/AppLogic.idl b/src/cascadia/TerminalApp/AppLogic.idl index 674322d35..e6aa40788 100644 --- a/src/cascadia/TerminalApp/AppLogic.idl +++ b/src/cascadia/TerminalApp/AppLogic.idl @@ -19,6 +19,20 @@ namespace TerminalApp String WindowName { get; }; }; + delegate void SystemMenuItemHandler(); + + enum SystemMenuChangeAction + { + Add = 0, + Remove = 1 + }; + + [default_interface] runtimeclass SystemMenuChangeArgs { + String Name { get; }; + SystemMenuChangeAction Action { get; }; + SystemMenuItemHandler Handler { get; }; + }; + [default_interface] runtimeclass AppLogic : IDirectKeyListener, IDialogPresenter { AppLogic(); @@ -110,5 +124,6 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler CloseRequested; event Windows.Foundation.TypedEventHandler OpenSystemMenu; event Windows.Foundation.TypedEventHandler QuitRequested; + event Windows.Foundation.TypedEventHandler SystemMenuChangeRequested; } } diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 4c16c1a0a..044ae308b 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -2111,7 +2111,7 @@ namespace winrt::TerminalApp::implementation { if (target == SettingsTarget::SettingsUI) { - _OpenSettingsUI(); + OpenSettingsUI(); } else { @@ -2759,7 +2759,7 @@ namespace winrt::TerminalApp::implementation // - // Return Value: // - - void TerminalPage::_OpenSettingsUI() + void TerminalPage::OpenSettingsUI() { // If we're holding the settings tab's switch command, don't create a new one, switch to the existing one. if (!_settingsTab) diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index f6de6a28b..28a156f79 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -121,6 +121,8 @@ namespace winrt::TerminalApp::implementation bool IsQuakeWindow() const noexcept; bool IsElevated() const noexcept; + void OpenSettingsUI(); + WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler); // -------------------------------- WinRT Events --------------------------------- @@ -366,8 +368,6 @@ namespace winrt::TerminalApp::implementation void _UnZoomIfNeeded(); - void _OpenSettingsUI(); - static int _ComputeScrollDelta(ScrollDirection scrollDirection, const uint32_t rowsToScroll); static uint32_t _ReadSystemRowsToScroll(); diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index 7b6e74ef3..849c4e804 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -325,6 +325,7 @@ void AppHost::Initialize() _logic.FocusModeChanged({ this, &AppHost::_FocusModeChanged }); _logic.AlwaysOnTopChanged({ this, &AppHost::_AlwaysOnTopChanged }); _logic.RaiseVisualBell({ this, &AppHost::_RaiseVisualBell }); + _logic.SystemMenuChangeRequested({ this, &AppHost::_SystemMenuChangeRequested }); _logic.Create(); @@ -1248,6 +1249,27 @@ void AppHost::_OpenSystemMenu(const winrt::Windows::Foundation::IInspectable&, _window->OpenSystemMenu(std::nullopt, std::nullopt); } +void AppHost::_SystemMenuChangeRequested(const winrt::Windows::Foundation::IInspectable&, const winrt::TerminalApp::SystemMenuChangeArgs& args) +{ + switch (args.Action()) + { + case winrt::TerminalApp::SystemMenuChangeAction::Add: + { + auto handler = args.Handler(); + _window->AddToSystemMenu(args.Name(), [handler]() { handler(); }); + break; + } + case winrt::TerminalApp::SystemMenuChangeAction::Remove: + { + _window->RemoveFromSystemMenu(args.Name()); + break; + } + default: + { + } + } +} + // Method Description: // - Creates a Notification Icon and hooks up its handlers // Arguments: diff --git a/src/cascadia/WindowsTerminal/AppHost.h b/src/cascadia/WindowsTerminal/AppHost.h index 149c65705..6675e8209 100644 --- a/src/cascadia/WindowsTerminal/AppHost.h +++ b/src/cascadia/WindowsTerminal/AppHost.h @@ -96,6 +96,9 @@ private: void _OpenSystemMenu(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args); + void _SystemMenuChangeRequested(const winrt::Windows::Foundation::IInspectable& sender, + const winrt::TerminalApp::SystemMenuChangeArgs& args); + winrt::fire_and_forget _QuitRequested(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args); diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index 16ac019af..a28ccaa21 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -24,6 +24,7 @@ using namespace ::Microsoft::Console::Types; using VirtualKeyModifiers = winrt::Windows::System::VirtualKeyModifiers; #define XAML_HOSTING_WINDOW_CLASS_NAME L"CASCADIA_HOSTING_WINDOW_CLASS" +#define IDM_SYSTEM_MENU_BEGIN 0x1000 const UINT WM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated"); @@ -321,6 +322,8 @@ void IslandWindow::Initialize() } } + _systemMenuNextItemId = IDM_SYSTEM_MENU_BEGIN; + // Enable vintage opacity by removing the XAML emergency backstop, GH#603. // We don't really care if this failed or not. TerminalTrySetTransparentBackground(true); @@ -608,6 +611,15 @@ long IslandWindow::_calculateTotalSize(const bool isWidth, const long clientSize _NotifyNotificationIconMenuItemSelectedHandlers((HMENU)lparam, (UINT)wparam); return 0; } + case WM_SYSCOMMAND: + { + auto search = _systemMenuItems.find(LOWORD(wparam)); + if (search != _systemMenuItems.end()) + { + search->second.callback(); + } + break; + } default: // We'll want to receive this message when explorer.exe restarts // so that we can re-add our icon to the notification area. @@ -1717,5 +1729,50 @@ void IslandWindow::OpenSystemMenu(const std::optional mouseX, const std::op } } +void IslandWindow::AddToSystemMenu(const winrt::hstring& itemLabel, winrt::delegate callback) +{ + const HMENU systemMenu = GetSystemMenu(_window.get(), FALSE); + UINT wID = _systemMenuNextItemId; + + MENUITEMINFOW item; + item.cbSize = sizeof(MENUITEMINFOW); + item.fMask = MIIM_STATE | MIIM_ID | MIIM_STRING; + item.fState = MF_ENABLED; + item.wID = wID; + item.dwTypeData = const_cast(itemLabel.c_str()); + item.cch = static_cast(itemLabel.size()); + + if (LOG_LAST_ERROR_IF(!InsertMenuItemW(systemMenu, wID, FALSE, &item))) + { + return; + } + _systemMenuItems.insert({ wID, { itemLabel, callback } }); + _systemMenuNextItemId++; +} + +void IslandWindow::RemoveFromSystemMenu(const winrt::hstring& itemLabel) +{ + const HMENU systemMenu = GetSystemMenu(_window.get(), FALSE); + int itemCount = GetMenuItemCount(systemMenu); + if (LOG_LAST_ERROR_IF(itemCount == -1)) + { + return; + } + + auto it = std::find_if(_systemMenuItems.begin(), _systemMenuItems.end(), [&itemLabel](const std::pair& elem) { + return elem.second.label == itemLabel; + }); + if (it == _systemMenuItems.end()) + { + return; + } + + if (LOG_LAST_ERROR_IF(!DeleteMenu(systemMenu, it->first, MF_BYCOMMAND))) + { + return; + } + _systemMenuItems.erase(it->first); +} + DEFINE_EVENT(IslandWindow, DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>); DEFINE_EVENT(IslandWindow, WindowCloseButtonClicked, _windowCloseButtonClickedHandler, winrt::delegate<>); diff --git a/src/cascadia/WindowsTerminal/IslandWindow.h b/src/cascadia/WindowsTerminal/IslandWindow.h index 8f6b283c1..0ac7b1e0b 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.h +++ b/src/cascadia/WindowsTerminal/IslandWindow.h @@ -8,6 +8,12 @@ void SetWindowLongWHelper(const HWND hWnd, const int nIndex, const LONG dwNewLong) noexcept; +struct SystemMenuItemInfo +{ + winrt::hstring label; + winrt::delegate callback; +}; + class IslandWindow : public BaseWindow { @@ -54,6 +60,8 @@ public: void SetMinimizeToNotificationAreaBehavior(bool MinimizeToNotificationArea) noexcept; void OpenSystemMenu(const std::optional mouseX, const std::optional mouseY) const noexcept; + void AddToSystemMenu(const winrt::hstring& itemLabel, winrt::delegate callback); + void RemoveFromSystemMenu(const winrt::hstring& itemLabel); DECLARE_EVENT(DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>); DECLARE_EVENT(WindowCloseButtonClicked, _windowCloseButtonClickedHandler, winrt::delegate<>); @@ -131,6 +139,9 @@ protected: bool _minimizeToNotificationArea{ false }; + std::unordered_map _systemMenuItems; + UINT _systemMenuNextItemId; + private: // This minimum width allows for width the tabs fit static constexpr long minimumWidth = 460L; From 4241d1c19efc05b70b39f099a20c3b909bf8c049 Mon Sep 17 00:00:00 2001 From: PankajBhojwani Date: Thu, 4 Nov 2021 12:49:22 -0700 Subject: [PATCH 12/23] Update _OpenSettingsUI to OpenSettingsUI (#11686) #11404 changed `_OpenSettingsUI` to `OpenSettingsUI` in `TerminalPage`, but there is still one leftover reference to `_OpenSettingsUI`. This commit fixes that. --- src/cascadia/TerminalApp/TerminalPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 044ae308b..9eacd638b 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -3377,7 +3377,7 @@ namespace winrt::TerminalApp::implementation TraceLoggingWrite(g_hTerminalAppProvider, "SetAsDefaultTipInteracted", TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage)); - _OpenSettingsUI(); + OpenSettingsUI(); } // Method Description: From 761203d95e94987aaaa20cff28fdf01268d3604b Mon Sep 17 00:00:00 2001 From: PankajBhojwani Date: Thu, 4 Nov 2021 12:50:59 -0700 Subject: [PATCH 13/23] Remove unused rendering settings from profile (#11685) The `ForceFullRepaintRendering` and `SoftwareRendering` are global only and for some reason were in profile. This commit removes them. Reference: https://github.com/microsoft/terminal/pull/11416#discussion_r742030103 --- src/cascadia/TerminalSettingsEditor/Profiles.h | 2 -- src/cascadia/TerminalSettingsEditor/Profiles.idl | 2 -- src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp | 2 -- src/cascadia/TerminalSettingsModel/Profile.cpp | 2 -- src/cascadia/TerminalSettingsModel/Profile.h | 4 ---- src/cascadia/TerminalSettingsModel/Profile.idl | 2 -- 6 files changed, 14 deletions(-) diff --git a/src/cascadia/TerminalSettingsEditor/Profiles.h b/src/cascadia/TerminalSettingsEditor/Profiles.h index 2bcbb1ca3..40ecd9c45 100644 --- a/src/cascadia/TerminalSettingsEditor/Profiles.h +++ b/src/cascadia/TerminalSettingsEditor/Profiles.h @@ -86,8 +86,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation OBSERVABLE_PROJECTED_SETTING(_profile, Commandline); OBSERVABLE_PROJECTED_SETTING(_profile, StartingDirectory); OBSERVABLE_PROJECTED_SETTING(_profile, AntialiasingMode); - OBSERVABLE_PROJECTED_SETTING(_profile, ForceFullRepaintRendering); - OBSERVABLE_PROJECTED_SETTING(_profile, SoftwareRendering); OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Foreground); OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Background); OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), SelectionBackground); diff --git a/src/cascadia/TerminalSettingsEditor/Profiles.idl b/src/cascadia/TerminalSettingsEditor/Profiles.idl index 482a19671..5d45a612c 100644 --- a/src/cascadia/TerminalSettingsEditor/Profiles.idl +++ b/src/cascadia/TerminalSettingsEditor/Profiles.idl @@ -53,8 +53,6 @@ namespace Microsoft.Terminal.Settings.Editor OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Commandline); OBSERVABLE_PROJECTED_PROFILE_SETTING(String, StartingDirectory); OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.TextAntialiasingMode, AntialiasingMode); - OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, ForceFullRepaintRendering); - OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, SoftwareRendering); OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference, Foreground); OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference, Background); OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference, SelectionBackground); diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp index e35b3e4b7..2d397ad55 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp @@ -287,8 +287,6 @@ Model::Profile CascadiaSettings::DuplicateProfile(const Model::Profile& source) DUPLICATE_SETTING_MACRO(Commandline); DUPLICATE_SETTING_MACRO(StartingDirectory); DUPLICATE_SETTING_MACRO(AntialiasingMode); - DUPLICATE_SETTING_MACRO(ForceFullRepaintRendering); - DUPLICATE_SETTING_MACRO(SoftwareRendering); DUPLICATE_SETTING_MACRO(HistorySize); DUPLICATE_SETTING_MACRO(SnapOnInput); DUPLICATE_SETTING_MACRO(AltGrAliasing); diff --git a/src/cascadia/TerminalSettingsModel/Profile.cpp b/src/cascadia/TerminalSettingsModel/Profile.cpp index c7b104e9a..f56e99d4a 100644 --- a/src/cascadia/TerminalSettingsModel/Profile.cpp +++ b/src/cascadia/TerminalSettingsModel/Profile.cpp @@ -104,8 +104,6 @@ winrt::com_ptr Profile::CopySettings() const profile->_Hidden = _Hidden; profile->_TabColor = _TabColor; profile->_Padding = _Padding; - profile->_ForceFullRepaintRendering = _ForceFullRepaintRendering; - profile->_SoftwareRendering = _SoftwareRendering; profile->_Origin = _Origin; profile->_FontInfo = *fontInfo; profile->_DefaultAppearance = *defaultAppearance; diff --git a/src/cascadia/TerminalSettingsModel/Profile.h b/src/cascadia/TerminalSettingsModel/Profile.h index b828165a2..db715f07a 100644 --- a/src/cascadia/TerminalSettingsModel/Profile.h +++ b/src/cascadia/TerminalSettingsModel/Profile.h @@ -112,10 +112,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation INHERITABLE_NULLABLE_SETTING(Model::Profile, Microsoft::Terminal::Core::Color, TabColor, nullptr); INHERITABLE_SETTING(Model::Profile, Model::IAppearanceConfig, UnfocusedAppearance, nullptr); - // Global settings - INHERITABLE_SETTING(Model::Profile, bool, ForceFullRepaintRendering, false); - INHERITABLE_SETTING(Model::Profile, bool, SoftwareRendering, false); - // Settings that cannot be put in the macro because of how they are handled in ToJson/LayerJson INHERITABLE_SETTING(Model::Profile, hstring, Name, L"Default"); INHERITABLE_SETTING(Model::Profile, hstring, Source); diff --git a/src/cascadia/TerminalSettingsModel/Profile.idl b/src/cascadia/TerminalSettingsModel/Profile.idl index 670303ff1..746caad25 100644 --- a/src/cascadia/TerminalSettingsModel/Profile.idl +++ b/src/cascadia/TerminalSettingsModel/Profile.idl @@ -74,8 +74,6 @@ namespace Microsoft.Terminal.Settings.Model INHERITABLE_PROFILE_SETTING(IAppearanceConfig, UnfocusedAppearance); INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.Control.TextAntialiasingMode, AntialiasingMode); - INHERITABLE_PROFILE_SETTING(Boolean, ForceFullRepaintRendering); - INHERITABLE_PROFILE_SETTING(Boolean, SoftwareRendering); INHERITABLE_PROFILE_SETTING(Int32, HistorySize); INHERITABLE_PROFILE_SETTING(Boolean, SnapOnInput); From b604117421f92ac01c8a7119fb1985fee383b8d1 Mon Sep 17 00:00:00 2001 From: James Holderness Date: Thu, 4 Nov 2021 22:13:22 +0000 Subject: [PATCH 14/23] Standardize the color table order (#11602) ## Summary of the Pull Request In the original implementation, we used two different orderings for the color tables. The WT color table used ANSI order, while the conhost color table used a Windows-specific order. This PR standardizes on the ANSI color order everywhere, so the usage of indexed colors is consistent across both parts of the code base, which will hopefully allow more of the code to be shared one day. ## References This is another small step towards de-duplicating `AdaptDispatch` and `TerminalDispatch` for issue #3849, and is essentially a followup to the SGR dispatch refactoring in PR #6728. ## PR Checklist * [x] Closes #11461 * [x] CLA signed. * [x] Tests added/passed * [ ] Documentation updated. * [ ] Schema updated. * [x] I've discussed this with core contributors already. Issue number where discussion took place: #11461 ## Detailed Description of the Pull Request / Additional comments Conhost still needs to deal with legacy attributes using Windows color order, so those values now need to be transposed to ANSI colors order when creating a `TextAttribute` object. This is done with a simple mapping table, which also handles the translation of the default color entries, so it's actually slightly faster than the original code. And when converting `TextAttribute` values back to legacy console attributes, we were already using a mapping table to handle the narrowing of 256-color values down to 16 colors, so we just needed to adjust that table to account for the translation from ANSI to Windows, and then could make use of the same table for both 256-color and 16-color values. There are also a few places in conhost that read from or write to the color tables, and those now need to transpose the index values. I've addressed this by creating separate `SetLegacyColorTableEntry` and `GetLegacyColorTableEntry` methods in the `Settings` class which take care of the mapping, so it's now clearer in which cases the code is dealing with legacy values, and which are ANSI values. These methods are used in the `SetConsoleScreenBufferInfoEx` and `GetConsoleScreenBufferInfoEx` APIs, as well as a few place where color preferences are handled (the registry, shortcut links, and the properties dialog), none of which are particularly sensitive to performance. However, we also use the legacy table when looking up the default colors for rendering (which happens a lot), so I've refactored that code so the default color calculations now only occur once per frame. The plus side of all of this is that the VT code doesn't need to do the index translation anymore, so we can finally get rid of all the calls to `XTermToWindowsIndex`, and we no longer need a separate color table initialization method for conhost, so I was able to merge a number of color initialization methods into one. We also no longer need to translate from legacy values to ANSI when generating VT sequences for conpty. The one exception to that is the 16-color VT renderer, which uses the `TextColor::GetLegacyIndex` method to approximate 16-color equivalents for RGB and 256-color values. Since that method returns a legacy index, it still needs to be translated to ANSI before it can be used in a VT sequence. But this should be no worse than it was before. One more special case is conhost's secret _Color Selection_ feature. That uses `Ctrl`+Number and `Alt`+Number key sequences to highlight parts of the buffer, and the mapping from number to color is based on the Windows color order. So that mapping now needs to be transposed, but that's also not performance sensitive. The only thing that I haven't bothered to update is the trace logging code in the `Telemetry` class, which logs the first 16 entries in the color table. Those entries are now going to be in a different order, but I didn't think that would be of great concern to anyone. ## Validation Steps Performed A lot of unit tests needed to be updated to use ANSI color constants when setting indexed colors, where before they might have been expecting values in Windows order. But this replaced a wild mix of different constants, sometimes having to use bit shifting, as well as values mapped with `XTermToWindowsIndex`, so I think the tests are a whole lot clearer now. Only a few cases have been left with literal numbers where that seemed more appropriate. In addition to getting the unit tests working, I've also manually tested the behaviour of all the console APIs which I thought could be affected by these changes, and confirmed that they produced the same results in the new code as they did in the original implementation. This includes: - `WriteConsoleOutput` - `ReadConsoleOutput` - `SetConsoleTextAttribute` with `WriteConsoleOutputCharacter` - `FillConsoleOutputAttribute` and `FillConsoleOutputCharacter` - `ScrollConsoleScreenBuffer` - `GetConsoleScreenBufferInfo` - `GetConsoleScreenBufferInfoEx` - `SetConsoleScreenBufferInfoEx` I've also manually tested changing colors via the console properties menu, the registry, and shortcut links, including setting default colors and popup colors. And I've tested that the "Quirks Mode" is still working as expected in PowerShell. In terms of performance, I wrote a little test app that filled a 80x9999 buffer with random color combinations using `WriteConsoleOutput`, which I figured was likely to be the most performance sensitive call, and I think it now actually performs slightly better than the original implementation. I've also tested similar code - just filling the visible window - with SGR VT sequences of various types, and the performance seems about the same as it was before. --- src/buffer/out/TextAttribute.cpp | 46 ++++++- src/buffer/out/TextAttribute.hpp | 13 +- src/buffer/out/TextColor.cpp | 8 +- src/buffer/out/TextColor.h | 27 ++++ .../out/ut_textbuffer/TextAttributeTests.cpp | 10 +- .../ColorSchemeTests.cpp | 2 +- src/cascadia/TerminalCore/Terminal.cpp | 4 +- .../TerminalCore/TerminalDispatchGraphics.cpp | 87 +++++------- .../ConptyRoundtripTests.cpp | 24 ++-- src/host/conattrs.cpp | 52 ------- src/host/consoleInformation.cpp | 24 +++- src/host/getset.cpp | 6 +- src/host/host-common.vcxitems | 1 - src/host/lib/hostlib.vcxproj.filters | 3 - src/host/registry.cpp | 2 +- src/host/renderData.cpp | 4 +- src/host/renderData.hpp | 5 + src/host/screenInfo.cpp | 2 +- src/host/selectionInput.cpp | 6 +- src/host/server.h | 1 + src/host/settings.cpp | 31 +++-- src/host/settings.hpp | 2 + src/host/sources.inc | 1 - src/host/ut_host/ScreenBufferTests.cpp | 72 +++++----- src/host/ut_host/TextBufferTests.cpp | 36 ++--- src/host/ut_host/VtRendererTests.cpp | 24 ++-- src/inc/conattrs.hpp | 14 -- src/interactivity/win32/Clipboard.cpp | 6 +- src/interactivity/win32/menu.cpp | 4 +- src/renderer/vt/VtSequences.cpp | 23 ++-- src/renderer/vt/paint.cpp | 7 +- src/renderer/vt/vtrenderer.hpp | 4 +- src/terminal/adapter/adaptDispatch.cpp | 4 +- .../adapter/adaptDispatchGraphics.cpp | 89 +++++------- .../adapter/ut_adapter/adapterTest.cpp | 130 +++++++++--------- src/types/colorTable.cpp | 87 ++---------- src/types/inc/colorTable.hpp | 6 +- src/types/ut_types/UtilsTests.cpp | 30 ---- 38 files changed, 377 insertions(+), 520 deletions(-) delete mode 100644 src/host/conattrs.cpp diff --git a/src/buffer/out/TextAttribute.cpp b/src/buffer/out/TextAttribute.cpp index c44724846..b99c3121d 100644 --- a/src/buffer/out/TextAttribute.cpp +++ b/src/buffer/out/TextAttribute.cpp @@ -12,8 +12,30 @@ static_assert(alignof(TextAttribute) == 2); // Ensure that we can memcpy() and memmove() the struct for performance. static_assert(std::is_trivially_copyable_v); -BYTE TextAttribute::s_legacyDefaultForeground = 7; -BYTE TextAttribute::s_legacyDefaultBackground = 0; +namespace +{ + constexpr std::array s_initLegacyColorMap(const BYTE defaultIndex) + { + std::array legacyColorMap; + for (auto i = 0u; i < legacyColorMap.size(); i++) + { + const auto legacyIndex = TextColor::TransposeLegacyIndex(i); + gsl::at(legacyColorMap, i) = i == defaultIndex ? TextColor{} : TextColor{ legacyIndex, true }; + } + return legacyColorMap; + } + + BYTE s_legacyDefaultForeground = 7; + BYTE s_legacyDefaultBackground = 0; + BYTE s_ansiDefaultForeground = 7; + BYTE s_ansiDefaultBackground = 0; +} + +// These maps allow for an efficient conversion from a legacy attribute index +// to a TextColor with the corresponding ANSI index, also taking into account +// the legacy index values that need to be converted to a default TextColor. +std::array TextAttribute::s_legacyForegroundColorMap = s_initLegacyColorMap(7); +std::array TextAttribute::s_legacyBackgroundColorMap = s_initLegacyColorMap(0); // Routine Description: // - Sets the legacy attributes which map to and from the default colors. @@ -23,8 +45,22 @@ BYTE TextAttribute::s_legacyDefaultBackground = 0; // - None void TextAttribute::SetLegacyDefaultAttributes(const WORD defaultAttributes) noexcept { + // First we reset the current default color map entries to what they should + // be for a regular translation from a legacy index to an ANSI TextColor. + gsl::at(s_legacyForegroundColorMap, s_legacyDefaultForeground) = TextColor{ s_ansiDefaultForeground, true }; + gsl::at(s_legacyBackgroundColorMap, s_legacyDefaultBackground) = TextColor{ s_ansiDefaultBackground, true }; + + // Then we save the new default attribute values and their corresponding + // ANSI translations. We use the latter values to more efficiently handle + // the "VT Quirk" conversion below. s_legacyDefaultForeground = defaultAttributes & FG_ATTRS; s_legacyDefaultBackground = (defaultAttributes & BG_ATTRS) >> 4; + s_ansiDefaultForeground = TextColor::TransposeLegacyIndex(s_legacyDefaultForeground); + s_ansiDefaultBackground = TextColor::TransposeLegacyIndex(s_legacyDefaultBackground); + + // Finally we set the new default color map entries. + gsl::at(s_legacyForegroundColorMap, s_legacyDefaultForeground) = TextColor{}; + gsl::at(s_legacyBackgroundColorMap, s_legacyDefaultBackground) = TextColor{}; } // Routine Description: @@ -55,13 +91,13 @@ TextAttribute TextAttribute::StripErroneousVT16VersionsOfLegacyDefaults(const Te const auto bg{ attribute.GetBackground() }; auto copy{ attribute }; if (fg.IsIndex16() && - attribute.IsBold() == WI_IsFlagSet(s_legacyDefaultForeground, FOREGROUND_INTENSITY) && - fg.GetIndex() == (s_legacyDefaultForeground & ~FOREGROUND_INTENSITY)) + attribute.IsBold() == WI_IsFlagSet(s_ansiDefaultForeground, FOREGROUND_INTENSITY) && + fg.GetIndex() == (s_ansiDefaultForeground & ~FOREGROUND_INTENSITY)) { // We don't want to turn 1;37m into 39m (or even 1;39m), as this was meant to mimic a legacy color. copy.SetDefaultForeground(); } - if (bg.IsIndex16() && bg.GetIndex() == s_legacyDefaultBackground) + if (bg.IsIndex16() && bg.GetIndex() == s_ansiDefaultBackground) { copy.SetDefaultBackground(); } diff --git a/src/buffer/out/TextAttribute.hpp b/src/buffer/out/TextAttribute.hpp index 00f8a2266..e973a9cd3 100644 --- a/src/buffer/out/TextAttribute.hpp +++ b/src/buffer/out/TextAttribute.hpp @@ -41,8 +41,8 @@ public: explicit constexpr TextAttribute(const WORD wLegacyAttr) noexcept : _wAttrLegacy{ gsl::narrow_cast(wLegacyAttr & META_ATTRS) }, - _foreground{ s_LegacyIndexOrDefault(wLegacyAttr & FG_ATTRS, s_legacyDefaultForeground) }, - _background{ s_LegacyIndexOrDefault((wLegacyAttr & BG_ATTRS) >> 4, s_legacyDefaultBackground) }, + _foreground{ gsl::at(s_legacyForegroundColorMap, wLegacyAttr & FG_ATTRS) }, + _background{ gsl::at(s_legacyBackgroundColorMap, (wLegacyAttr & BG_ATTRS) >> 4) }, _extendedAttrs{ ExtendedAttributes::Normal }, _hyperlinkId{ 0 } { @@ -167,13 +167,8 @@ public: } private: - static constexpr TextColor s_LegacyIndexOrDefault(const BYTE requestedIndex, const BYTE defaultIndex) - { - return requestedIndex == defaultIndex ? TextColor{} : TextColor{ requestedIndex, true }; - } - - static BYTE s_legacyDefaultForeground; - static BYTE s_legacyDefaultBackground; + static std::array s_legacyForegroundColorMap; + static std::array s_legacyBackgroundColorMap; uint16_t _wAttrLegacy; // sizeof: 2, alignof: 2 uint16_t _hyperlinkId; // sizeof: 2, alignof: 2 diff --git a/src/buffer/out/TextColor.cpp b/src/buffer/out/TextColor.cpp index 7c05dd200..88bc8657f 100644 --- a/src/buffer/out/TextColor.cpp +++ b/src/buffer/out/TextColor.cpp @@ -32,7 +32,7 @@ constexpr std::array CompressedRgbToIndex16 = { // A table mapping indexed colors from the 256-color palette, // down to one of the 16 colors in the legacy palette. constexpr std::array Index256ToIndex16 = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15, 0, 1, 1, 1, 9, 9, 2, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 2, 2, 11, 11, 3, 3, 10, 10, 11, 11, 11, 11, 10, 10, 10, 10, 11, 11, 5, 5, 5, 5, 1, 1, 8, 8, 1, 1, 9, 9, @@ -252,11 +252,7 @@ BYTE TextColor::GetLegacyIndex(const BYTE defaultIndex) const noexcept { return defaultIndex; } - else if (IsIndex16()) - { - return GetIndex(); - } - else if (IsIndex256()) + else if (IsIndex16() || IsIndex256()) { return til::at(Index256ToIndex16, GetIndex()); } diff --git a/src/buffer/out/TextColor.h b/src/buffer/out/TextColor.h index ad984702f..35b62ff65 100644 --- a/src/buffer/out/TextColor.h +++ b/src/buffer/out/TextColor.h @@ -48,6 +48,23 @@ enum class ColorType : BYTE struct TextColor { public: + static constexpr BYTE DARK_BLACK = 0; + static constexpr BYTE DARK_RED = 1; + static constexpr BYTE DARK_GREEN = 2; + static constexpr BYTE DARK_YELLOW = 3; + static constexpr BYTE DARK_BLUE = 4; + static constexpr BYTE DARK_MAGENTA = 5; + static constexpr BYTE DARK_CYAN = 6; + static constexpr BYTE DARK_WHITE = 7; + static constexpr BYTE BRIGHT_BLACK = 8; + static constexpr BYTE BRIGHT_RED = 9; + static constexpr BYTE BRIGHT_GREEN = 10; + static constexpr BYTE BRIGHT_YELLOW = 11; + static constexpr BYTE BRIGHT_BLUE = 12; + static constexpr BYTE BRIGHT_MAGENTA = 13; + static constexpr BYTE BRIGHT_CYAN = 14; + static constexpr BYTE BRIGHT_WHITE = 15; + constexpr TextColor() noexcept : _meta{ ColorType::IsDefault }, _red{ 0 }, @@ -96,6 +113,16 @@ public: COLORREF GetRGB() const noexcept; + static constexpr BYTE TransposeLegacyIndex(const size_t index) + { + // When converting a 16-color index in the legacy Windows order to or + // from an ANSI-compatible order, we need to swap the bits in positions + // 0 and 2. We do this by XORing the index with 00000101, but only if + // one (but not both) of those bit positions is set. + const auto oneBitSet = (index ^ (index >> 2)) & 1; + return gsl::narrow_cast(index ^ oneBitSet ^ (oneBitSet << 2)); + } + private: union { diff --git a/src/buffer/out/ut_textbuffer/TextAttributeTests.cpp b/src/buffer/out/ut_textbuffer/TextAttributeTests.cpp index 65aba47f7..1b61955bb 100644 --- a/src/buffer/out/ut_textbuffer/TextAttributeTests.cpp +++ b/src/buffer/out/ut_textbuffer/TextAttributeTests.cpp @@ -237,7 +237,7 @@ void TextAttributeTests::TestRoundtripDefaultColors() Log::Comment(L"Foreground legacy default index should map to default text color."); legacyAttribute = fgLegacyDefault | BACKGROUND_GREEN; textAttribute.SetDefaultForeground(); - textAttribute.SetIndexedBackground256(BACKGROUND_GREEN >> 4); + textAttribute.SetIndexedBackground256(TextColor::DARK_GREEN); VERIFY_ARE_EQUAL(textAttribute, TextAttribute{ legacyAttribute }); Log::Comment(L"Default foreground text color should map back to legacy default index."); @@ -245,7 +245,7 @@ void TextAttributeTests::TestRoundtripDefaultColors() Log::Comment(L"Background legacy default index should map to default text color."); legacyAttribute = FOREGROUND_GREEN | bgLegacyDefault; - textAttribute.SetIndexedForeground256(FOREGROUND_GREEN); + textAttribute.SetIndexedForeground256(TextColor::DARK_GREEN); textAttribute.SetDefaultBackground(); VERIFY_ARE_EQUAL(textAttribute, TextAttribute{ legacyAttribute }); @@ -288,7 +288,7 @@ void TextAttributeTests::TestBoldAsBright() VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true)); VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false)); - attr.SetIndexedForeground(0); + attr.SetIndexedForeground(TextColor::DARK_BLACK); VERIFY_IS_TRUE(attr.IsBold()); Log::Comment(L"Foreground should be bright black when bold is bright is enabled"); @@ -297,7 +297,7 @@ void TextAttributeTests::TestBoldAsBright() Log::Comment(L"Foreground should be dark black when bold is bright is disabled"); VERIFY_ARE_EQUAL(std::make_pair(darkBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false)); - attr.SetIndexedBackground(2); + attr.SetIndexedBackground(TextColor::DARK_GREEN); VERIFY_IS_TRUE(attr.IsBold()); Log::Comment(L"background should be unaffected by 'bold is bright'"); @@ -312,7 +312,7 @@ void TextAttributeTests::TestBoldAsBright() Log::Comment(L"When set to a bright color, and bold, 'bold is bright' changes nothing"); attr.SetBold(true); - attr.SetIndexedForeground(8); + attr.SetIndexedForeground(TextColor::BRIGHT_BLACK); VERIFY_IS_TRUE(attr.IsBold()); VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true)); VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false)); diff --git a/src/cascadia/LocalTests_SettingsModel/ColorSchemeTests.cpp b/src/cascadia/LocalTests_SettingsModel/ColorSchemeTests.cpp index 85a9dd34a..682bee5f2 100644 --- a/src/cascadia/LocalTests_SettingsModel/ColorSchemeTests.cpp +++ b/src/cascadia/LocalTests_SettingsModel/ColorSchemeTests.cpp @@ -80,7 +80,7 @@ namespace SettingsModelLocalTests std::array expectedCampbellTable; const auto campbellSpan = gsl::make_span(expectedCampbellTable); - Utils::InitializeCampbellColorTable(campbellSpan); + Utils::InitializeColorTable(campbellSpan); Utils::SetColorTableAlpha(campbellSpan, 0); for (size_t i = 0; i < expectedCampbellTable.size(); i++) diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index 3433b60d9..c12a02f6d 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -1210,9 +1210,7 @@ try { const gsl::span tableView = { _colorTable.data(), _colorTable.size() }; // First set up the basic 256 colors - Utils::Initialize256ColorTable(tableView); - // Then use fill the first 16 values with the Campbell scheme - Utils::InitializeCampbellColorTable(tableView); + Utils::InitializeColorTable(tableView); // Then make sure all the values have an alpha of 255 Utils::SetColorTableAlpha(tableView, 0xff); } diff --git a/src/cascadia/TerminalCore/TerminalDispatchGraphics.cpp b/src/cascadia/TerminalCore/TerminalDispatchGraphics.cpp index c70d61b05..3f34e768c 100644 --- a/src/cascadia/TerminalCore/TerminalDispatchGraphics.cpp +++ b/src/cascadia/TerminalCore/TerminalDispatchGraphics.cpp @@ -7,29 +7,6 @@ using namespace Microsoft::Console::VirtualTerminal; using namespace Microsoft::Console::VirtualTerminal::DispatchTypes; -// clang-format off -const BYTE RED_ATTR = 0x01; -const BYTE GREEN_ATTR = 0x02; -const BYTE BLUE_ATTR = 0x04; -const BYTE BRIGHT_ATTR = 0x08; -const BYTE DARK_BLACK = 0; -const BYTE DARK_RED = RED_ATTR; -const BYTE DARK_GREEN = GREEN_ATTR; -const BYTE DARK_YELLOW = RED_ATTR | GREEN_ATTR; -const BYTE DARK_BLUE = BLUE_ATTR; -const BYTE DARK_MAGENTA = RED_ATTR | BLUE_ATTR; -const BYTE DARK_CYAN = GREEN_ATTR | BLUE_ATTR; -const BYTE DARK_WHITE = RED_ATTR | GREEN_ATTR | BLUE_ATTR; -const BYTE BRIGHT_BLACK = BRIGHT_ATTR; -const BYTE BRIGHT_RED = BRIGHT_ATTR | RED_ATTR; -const BYTE BRIGHT_GREEN = BRIGHT_ATTR | GREEN_ATTR; -const BYTE BRIGHT_YELLOW = BRIGHT_ATTR | RED_ATTR | GREEN_ATTR; -const BYTE BRIGHT_BLUE = BRIGHT_ATTR | BLUE_ATTR; -const BYTE BRIGHT_MAGENTA = BRIGHT_ATTR | RED_ATTR | BLUE_ATTR; -const BYTE BRIGHT_CYAN = BRIGHT_ATTR | GREEN_ATTR | BLUE_ATTR; -const BYTE BRIGHT_WHITE = BRIGHT_ATTR | RED_ATTR | GREEN_ATTR | BLUE_ATTR; -// clang-format on - // Routine Description: // - Helper to parse extended graphics options, which start with 38 (FG) or 48 (BG) // These options are followed by either a 2 (RGB) or 5 (xterm index) @@ -169,100 +146,100 @@ bool TerminalDispatch::SetGraphicsRendition(const VTParameters options) noexcept attr.SetOverlined(false); break; case ForegroundBlack: - attr.SetIndexedForeground(DARK_BLACK); + attr.SetIndexedForeground(TextColor::DARK_BLACK); break; case ForegroundBlue: - attr.SetIndexedForeground(DARK_BLUE); + attr.SetIndexedForeground(TextColor::DARK_BLUE); break; case ForegroundGreen: - attr.SetIndexedForeground(DARK_GREEN); + attr.SetIndexedForeground(TextColor::DARK_GREEN); break; case ForegroundCyan: - attr.SetIndexedForeground(DARK_CYAN); + attr.SetIndexedForeground(TextColor::DARK_CYAN); break; case ForegroundRed: - attr.SetIndexedForeground(DARK_RED); + attr.SetIndexedForeground(TextColor::DARK_RED); break; case ForegroundMagenta: - attr.SetIndexedForeground(DARK_MAGENTA); + attr.SetIndexedForeground(TextColor::DARK_MAGENTA); break; case ForegroundYellow: - attr.SetIndexedForeground(DARK_YELLOW); + attr.SetIndexedForeground(TextColor::DARK_YELLOW); break; case ForegroundWhite: - attr.SetIndexedForeground(DARK_WHITE); + attr.SetIndexedForeground(TextColor::DARK_WHITE); break; case BackgroundBlack: - attr.SetIndexedBackground(DARK_BLACK); + attr.SetIndexedBackground(TextColor::DARK_BLACK); break; case BackgroundBlue: - attr.SetIndexedBackground(DARK_BLUE); + attr.SetIndexedBackground(TextColor::DARK_BLUE); break; case BackgroundGreen: - attr.SetIndexedBackground(DARK_GREEN); + attr.SetIndexedBackground(TextColor::DARK_GREEN); break; case BackgroundCyan: - attr.SetIndexedBackground(DARK_CYAN); + attr.SetIndexedBackground(TextColor::DARK_CYAN); break; case BackgroundRed: - attr.SetIndexedBackground(DARK_RED); + attr.SetIndexedBackground(TextColor::DARK_RED); break; case BackgroundMagenta: - attr.SetIndexedBackground(DARK_MAGENTA); + attr.SetIndexedBackground(TextColor::DARK_MAGENTA); break; case BackgroundYellow: - attr.SetIndexedBackground(DARK_YELLOW); + attr.SetIndexedBackground(TextColor::DARK_YELLOW); break; case BackgroundWhite: - attr.SetIndexedBackground(DARK_WHITE); + attr.SetIndexedBackground(TextColor::DARK_WHITE); break; case BrightForegroundBlack: - attr.SetIndexedForeground(BRIGHT_BLACK); + attr.SetIndexedForeground(TextColor::BRIGHT_BLACK); break; case BrightForegroundBlue: - attr.SetIndexedForeground(BRIGHT_BLUE); + attr.SetIndexedForeground(TextColor::BRIGHT_BLUE); break; case BrightForegroundGreen: - attr.SetIndexedForeground(BRIGHT_GREEN); + attr.SetIndexedForeground(TextColor::BRIGHT_GREEN); break; case BrightForegroundCyan: - attr.SetIndexedForeground(BRIGHT_CYAN); + attr.SetIndexedForeground(TextColor::BRIGHT_CYAN); break; case BrightForegroundRed: - attr.SetIndexedForeground(BRIGHT_RED); + attr.SetIndexedForeground(TextColor::BRIGHT_RED); break; case BrightForegroundMagenta: - attr.SetIndexedForeground(BRIGHT_MAGENTA); + attr.SetIndexedForeground(TextColor::BRIGHT_MAGENTA); break; case BrightForegroundYellow: - attr.SetIndexedForeground(BRIGHT_YELLOW); + attr.SetIndexedForeground(TextColor::BRIGHT_YELLOW); break; case BrightForegroundWhite: - attr.SetIndexedForeground(BRIGHT_WHITE); + attr.SetIndexedForeground(TextColor::BRIGHT_WHITE); break; case BrightBackgroundBlack: - attr.SetIndexedBackground(BRIGHT_BLACK); + attr.SetIndexedBackground(TextColor::BRIGHT_BLACK); break; case BrightBackgroundBlue: - attr.SetIndexedBackground(BRIGHT_BLUE); + attr.SetIndexedBackground(TextColor::BRIGHT_BLUE); break; case BrightBackgroundGreen: - attr.SetIndexedBackground(BRIGHT_GREEN); + attr.SetIndexedBackground(TextColor::BRIGHT_GREEN); break; case BrightBackgroundCyan: - attr.SetIndexedBackground(BRIGHT_CYAN); + attr.SetIndexedBackground(TextColor::BRIGHT_CYAN); break; case BrightBackgroundRed: - attr.SetIndexedBackground(BRIGHT_RED); + attr.SetIndexedBackground(TextColor::BRIGHT_RED); break; case BrightBackgroundMagenta: - attr.SetIndexedBackground(BRIGHT_MAGENTA); + attr.SetIndexedBackground(TextColor::BRIGHT_MAGENTA); break; case BrightBackgroundYellow: - attr.SetIndexedBackground(BRIGHT_YELLOW); + attr.SetIndexedBackground(TextColor::BRIGHT_YELLOW); break; case BrightBackgroundWhite: - attr.SetIndexedBackground(BRIGHT_WHITE); + attr.SetIndexedBackground(TextColor::BRIGHT_WHITE); break; case ForegroundExtended: i += _SetRgbColorsHelper(options.subspan(i + 1), attr, true); diff --git a/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp b/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp index fe671a65a..2145032fd 100644 --- a/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp +++ b/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp @@ -2901,15 +2901,9 @@ void ConptyRoundtripTests::ResizeInitializeBufferWithDefaultAttrs() auto defaultAttrs = si.GetAttributes(); auto conhostGreenAttrs = TextAttribute(); - - // Conhost and Terminal store attributes in different bits. - // conhostGreenAttrs.SetIndexedAttributes(std::nullopt, - // { static_cast(FOREGROUND_GREEN) }); - conhostGreenAttrs.SetIndexedBackground(FOREGROUND_GREEN); + conhostGreenAttrs.SetIndexedBackground(TextColor::DARK_GREEN); auto terminalGreenAttrs = TextAttribute(); - // terminalGreenAttrs.SetIndexedAttributes(std::nullopt, - // { static_cast(XTERM_GREEN_ATTR) }); - terminalGreenAttrs.SetIndexedBackground(XTERM_GREEN_ATTR); + terminalGreenAttrs.SetIndexedBackground(TextColor::DARK_GREEN); // Use an initial ^[[m to start printing with default-on-default sm.ProcessString(L"\x1b[m"); @@ -2942,7 +2936,7 @@ void ConptyRoundtripTests::ResizeInitializeBufferWithDefaultAttrs() auto verifyBuffer = [&](const TextBuffer& tb, const til::rectangle viewport, const bool isTerminal, const bool afterResize) { const auto width = viewport.width(); - // Conhost and Terminal store attributes in different bits. + // Conhost and Terminal attributes are potentially different. const auto greenAttrs = isTerminal ? terminalGreenAttrs : conhostGreenAttrs; for (short row = 0; row < tb.GetSize().Height(); row++) @@ -3034,13 +3028,11 @@ void ConptyRoundtripTests::NewLinesAtBottomWithBackground() auto defaultAttrs = si.GetAttributes(); auto conhostBlueAttrs = defaultAttrs; - - // Conhost and Terminal store attributes in different bits. - conhostBlueAttrs.SetIndexedForeground(FOREGROUND_GREEN); - conhostBlueAttrs.SetIndexedBackground(FOREGROUND_BLUE); + conhostBlueAttrs.SetIndexedForeground(TextColor::DARK_GREEN); + conhostBlueAttrs.SetIndexedBackground(TextColor::DARK_BLUE); auto terminalBlueAttrs = TextAttribute(); - terminalBlueAttrs.SetIndexedForeground(XTERM_GREEN_ATTR); - terminalBlueAttrs.SetIndexedBackground(XTERM_BLUE_ATTR); + terminalBlueAttrs.SetIndexedForeground(TextColor::DARK_GREEN); + terminalBlueAttrs.SetIndexedBackground(TextColor::DARK_BLUE); // We're going to print 4 more rows than the entire height of the viewport, // causing the buffer to circle 4 times. This is 2 extra iterations of the @@ -3083,7 +3075,7 @@ void ConptyRoundtripTests::NewLinesAtBottomWithBackground() const auto width = viewport.width(); const auto isTerminal = viewport.top() != 0; - // Conhost and Terminal store attributes in different bits. + // Conhost and Terminal attributes are potentially different. const auto blueAttrs = isTerminal ? terminalBlueAttrs : conhostBlueAttrs; for (short row = 0; row < viewport.bottom() - 2; row++) diff --git a/src/host/conattrs.cpp b/src/host/conattrs.cpp deleted file mode 100644 index 07d1f21f2..000000000 --- a/src/host/conattrs.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/*++ -Copyright (c) Microsoft Corporation -Licensed under the MIT license. - -Module Name: -- conattrs.cpp - -Abstract: -- Defines common operations on console attributes, especially in regards to - finding the nearest color from a color table. - -Author(s): -- Mike Griese (migrie) 01-Sept-2017 ---*/ - -#include "precomp.h" -#include "../inc/conattrs.hpp" -#include - -// Function Description: -// - Converts the value of a xterm color table index to the windows color table equivalent. -// Arguments: -// - xtermTableEntry: the xterm color table index -// Return Value: -// - The windows color table equivalent. -WORD XtermToWindowsIndex(const size_t xtermTableEntry) noexcept -{ - const bool fRed = WI_IsFlagSet(xtermTableEntry, XTERM_RED_ATTR); - const bool fGreen = WI_IsFlagSet(xtermTableEntry, XTERM_GREEN_ATTR); - const bool fBlue = WI_IsFlagSet(xtermTableEntry, XTERM_BLUE_ATTR); - const bool fBright = WI_IsFlagSet(xtermTableEntry, XTERM_BRIGHT_ATTR); - - return (fRed ? WINDOWS_RED_ATTR : 0x0) + - (fGreen ? WINDOWS_GREEN_ATTR : 0x0) + - (fBlue ? WINDOWS_BLUE_ATTR : 0x0) + - (fBright ? WINDOWS_BRIGHT_ATTR : 0x0); -} - -// Function Description: -// - Converts the value of a xterm color table index to the windows color table -// equivalent. The range of values is [0, 255], where the lowest 16 are -// mapped to the equivalent Windows index, and the rest of the values are -// passed through. -// Arguments: -// - xtermTableEntry: the xterm color table index -// Return Value: -// - The windows color table equivalent. -WORD Xterm256ToWindowsIndex(const size_t xtermTableEntry) noexcept -{ - return xtermTableEntry < 16 ? XtermToWindowsIndex(xtermTableEntry) : - static_cast(xtermTableEntry); -} diff --git a/src/host/consoleInformation.cpp b/src/host/consoleInformation.cpp index 112905921..51ed7de9b 100644 --- a/src/host/consoleInformation.cpp +++ b/src/host/consoleInformation.cpp @@ -231,7 +231,7 @@ InputBuffer* const CONSOLE_INFORMATION::GetActiveInputBuffer() const COLORREF CONSOLE_INFORMATION::GetDefaultForeground() const noexcept { const auto fg = GetDefaultForegroundColor(); - return fg != INVALID_COLOR ? fg : GetColorTableEntry(LOBYTE(GetFillAttribute()) & FG_ATTRS); + return fg != INVALID_COLOR ? fg : GetLegacyColorTableEntry(LOBYTE(GetFillAttribute()) & FG_ATTRS); } // Method Description: @@ -246,23 +246,37 @@ COLORREF CONSOLE_INFORMATION::GetDefaultForeground() const noexcept COLORREF CONSOLE_INFORMATION::GetDefaultBackground() const noexcept { const auto bg = GetDefaultBackgroundColor(); - return bg != INVALID_COLOR ? bg : GetColorTableEntry((LOBYTE(GetFillAttribute()) & BG_ATTRS) >> 4); + return bg != INVALID_COLOR ? bg : GetLegacyColorTableEntry((LOBYTE(GetFillAttribute()) & BG_ATTRS) >> 4); } // Method Description: // - Get the colors of a particular text attribute, using our color table, // and our configured default attributes. // Arguments: -// - attr: the TextAttribute to retrieve the foreground color of. +// - attr: the TextAttribute to retrieve the foreground and background color of. // Return Value: // - The color values of the attribute's foreground and background. std::pair CONSOLE_INFORMATION::LookupAttributeColors(const TextAttribute& attr) const noexcept +{ + return LookupAttributeColors(attr, GetDefaultForeground(), GetDefaultBackground()); +} + +// Method Description: +// - Get the colors of a particular text attribute, using our color table, +// and the given default color values. +// Arguments: +// - attr: the TextAttribute to retrieve the foreground and background color of. +// - defaultFg: the COLORREF to use for a default foreground color. +// - defaultBg: the COLORREF to use for a default background color. +// Return Value: +// - The color values of the attribute's foreground and background. +std::pair CONSOLE_INFORMATION::LookupAttributeColors(const TextAttribute& attr, const COLORREF defaultFg, const COLORREF defaultBg) const noexcept { _blinkingState.RecordBlinkingUsage(attr); return attr.CalculateRgbColors( GetColorTable(), - GetDefaultForeground(), - GetDefaultBackground(), + defaultFg, + defaultBg, IsScreenReversed(), _blinkingState.IsBlinkingFaint()); } diff --git a/src/host/getset.cpp b/src/host/getset.cpp index 6203aef0e..4f85d4a5b 100644 --- a/src/host/getset.cpp +++ b/src/host/getset.cpp @@ -605,7 +605,7 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont for (size_t i = 0; i < std::size(data.ColorTable); i++) { - gci.SetColorTableEntry(i, data.ColorTable[i]); + gci.SetLegacyColorTableEntry(i, data.ColorTable[i]); } context.SetDefaultAttributes(TextAttribute{ data.wAttributes }, TextAttribute{ data.wPopupAttributes }); @@ -1978,7 +1978,7 @@ void DoSrvPrivateMoveToBottom(SCREEN_INFORMATION& screenInfo) Globals& g = ServiceLocator::LocateGlobals(); CONSOLE_INFORMATION& gci = g.getConsoleInformation(); - value = gci.GetColorTableEntry(::Xterm256ToWindowsIndex(index)); + value = gci.GetColorTableEntry(index); return S_OK; } @@ -2004,7 +2004,7 @@ void DoSrvPrivateMoveToBottom(SCREEN_INFORMATION& screenInfo) Globals& g = ServiceLocator::LocateGlobals(); CONSOLE_INFORMATION& gci = g.getConsoleInformation(); - gci.SetColorTableEntry(::Xterm256ToWindowsIndex(index), value); + gci.SetColorTableEntry(index, value); // Update the screen colors if we're not a pty // No need to force a redraw in pty mode. diff --git a/src/host/host-common.vcxitems b/src/host/host-common.vcxitems index 190eef792..7645ced09 100644 --- a/src/host/host-common.vcxitems +++ b/src/host/host-common.vcxitems @@ -7,7 +7,6 @@ - diff --git a/src/host/lib/hostlib.vcxproj.filters b/src/host/lib/hostlib.vcxproj.filters index e8877f96c..11256b620 100644 --- a/src/host/lib/hostlib.vcxproj.filters +++ b/src/host/lib/hostlib.vcxproj.filters @@ -138,9 +138,6 @@ Source Files - - Source Files - Source Files diff --git a/src/host/registry.cpp b/src/host/registry.cpp index 9b022d983..49bd06423 100644 --- a/src/host/registry.cpp +++ b/src/host/registry.cpp @@ -310,7 +310,7 @@ void Registry::LoadFromRegistry(_In_ PCWSTR const pwszConsoleTitle) nullptr); if (NT_SUCCESS(Status)) { - _pSettings->SetColorTableEntry(i, dwValue); + _pSettings->SetLegacyColorTableEntry(i, dwValue); } } diff --git a/src/host/renderData.cpp b/src/host/renderData.cpp index c860b3da3..1eb6090d7 100644 --- a/src/host/renderData.cpp +++ b/src/host/renderData.cpp @@ -110,6 +110,8 @@ void RenderData::UnlockConsole() noexcept const TextAttribute RenderData::GetDefaultBrushColors() noexcept { const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); + _defaultForeground = gci.GetDefaultForeground(); + _defaultBackground = gci.GetDefaultBackground(); return gci.GetActiveOutputBuffer().GetAttributes(); } @@ -362,7 +364,7 @@ const std::vector RenderData::GetPatternId(const COORD /*location*/) con std::pair RenderData::GetAttributeColors(const TextAttribute& attr) const noexcept { const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); - return gci.LookupAttributeColors(attr); + return gci.LookupAttributeColors(attr, _defaultForeground, _defaultBackground); } #pragma endregion diff --git a/src/host/renderData.hpp b/src/host/renderData.hpp index b1699531d..9b5ab7f6d 100644 --- a/src/host/renderData.hpp +++ b/src/host/renderData.hpp @@ -15,6 +15,7 @@ Author(s): #pragma once #include "../renderer/inc/IRenderData.hpp" +#include "../types/inc/colorTable.hpp" #include "../types/IUiaData.h" class RenderData final : @@ -71,4 +72,8 @@ public: void ColorSelection(const COORD coordSelectionStart, const COORD coordSelectionEnd, const TextAttribute attr); const bool IsUiaDataInitialized() const noexcept override { return true; } #pragma endregion + +private: + COLORREF _defaultForeground = gsl::at(Microsoft::Console::Utils::CampbellColorTable(), 7); + COLORREF _defaultBackground = gsl::at(Microsoft::Console::Utils::CampbellColorTable(), 0); }; diff --git a/src/host/screenInfo.cpp b/src/host/screenInfo.cpp index 320e1148d..cc06df4ca 100644 --- a/src/host/screenInfo.cpp +++ b/src/host/screenInfo.cpp @@ -364,7 +364,7 @@ void SCREEN_INFORMATION::GetScreenBufferInformation(_Out_ PCOORD pcoordSize, // the copy length must be constant for now to keep OACR happy with buffer overruns. for (size_t i = 0; i < COLOR_TABLE_SIZE; i++) { - lpColorTable[i] = gci.GetColorTableEntry(i); + lpColorTable[i] = gci.GetLegacyColorTableEntry(i); } *pcoordMaximumWindowSize = GetMaxWindowSizeInCharacters(); diff --git a/src/host/selectionInput.cpp b/src/host/selectionInput.cpp index 70b4d4f38..cab5aa88b 100644 --- a/src/host/selectionInput.cpp +++ b/src/host/selectionInput.cpp @@ -661,13 +661,15 @@ bool Selection::_HandleColorSelection(const INPUT_KEY_INFO* const pInputKeyInfo) if (fAltPressed || fCtrlPressed) { TextAttribute selectionAttr; - const BYTE colorIndex = gsl::narrow_cast(wVirtualKeyCode - '0' + 6); + // The key number corresponds to the Windows color table order, so the value + // need to be transposed to obtain the index in an ANSI-compatible order. + const auto colorIndex = TextColor::TransposeLegacyIndex(wVirtualKeyCode - '0' + 6); if (fCtrlPressed) { // Setting background color. Set fg color to black. selectionAttr.SetIndexedBackground256(colorIndex); - selectionAttr.SetIndexedForeground256(0); + selectionAttr.SetIndexedForeground256(TextColor::DARK_BLACK); } else { diff --git a/src/host/server.h b/src/host/server.h index 91ea54537..2d8fa0d15 100644 --- a/src/host/server.h +++ b/src/host/server.h @@ -127,6 +127,7 @@ public: COLORREF GetDefaultForeground() const noexcept; COLORREF GetDefaultBackground() const noexcept; std::pair LookupAttributeColors(const TextAttribute& attr) const noexcept; + std::pair LookupAttributeColors(const TextAttribute& attr, const COLORREF defaultFg, const COLORREF defaultBg) const noexcept; void SetTitle(const std::wstring_view newTitle); void SetTitlePrefix(const std::wstring_view newTitlePrefix); diff --git a/src/host/settings.cpp b/src/host/settings.cpp index a9fb5d093..d1443cb32 100644 --- a/src/host/settings.cpp +++ b/src/host/settings.cpp @@ -82,8 +82,7 @@ Settings::Settings() : _CursorType = CursorType::Legacy; gsl::span tableView = { _colorTable.data(), _colorTable.size() }; - ::Microsoft::Console::Utils::Initialize256ColorTable(tableView); - ::Microsoft::Console::Utils::InitializeCampbellColorTableForConhost(tableView); + ::Microsoft::Console::Utils::InitializeColorTable(tableView); } // Routine Description: @@ -122,8 +121,8 @@ void Settings::ApplyDesktopSpecificDefaults() _uNumberOfHistoryBuffers = 4; _bHistoryNoDup = FALSE; - gsl::span tableView = { _colorTable.data(), _colorTable.size() }; - ::Microsoft::Console::Utils::InitializeCampbellColorTableForConhost(tableView); + gsl::span tableView = { _colorTable.data(), 16 }; + ::Microsoft::Console::Utils::InitializeColorTable(tableView); _fTrimLeadingZeros = false; _fEnableColorSelection = false; @@ -222,7 +221,7 @@ void Settings::InitFromStateInfo(_In_ PCONSOLE_STATE_INFO pStateInfo) _uNumberOfHistoryBuffers = pStateInfo->NumberOfHistoryBuffers; for (size_t i = 0; i < std::size(pStateInfo->ColorTable); i++) { - SetColorTableEntry(i, pStateInfo->ColorTable[i]); + SetLegacyColorTableEntry(i, pStateInfo->ColorTable[i]); } _uCodePage = pStateInfo->CodePage; _bWrapText = !!pStateInfo->fWrapText; @@ -267,7 +266,7 @@ CONSOLE_STATE_INFO Settings::CreateConsoleStateInfo() const csi.NumberOfHistoryBuffers = _uNumberOfHistoryBuffers; for (size_t i = 0; i < std::size(csi.ColorTable); i++) { - csi.ColorTable[i] = GetColorTableEntry(i); + csi.ColorTable[i] = GetLegacyColorTableEntry(i); } csi.CodePage = _uCodePage; csi.fWrapText = !!_bWrapText; @@ -726,11 +725,6 @@ void Settings::SetHistoryNoDup(const bool bHistoryNoDup) _bHistoryNoDup = bHistoryNoDup; } -void Settings::SetColorTableEntry(const size_t index, const COLORREF ColorValue) -{ - _colorTable.at(index) = ColorValue; -} - bool Settings::IsStartupTitleIsLinkNameSet() const { return WI_IsFlagSet(_dwStartupFlags, STARTF_TITLEISLINKNAME); @@ -746,11 +740,26 @@ void Settings::UnsetStartupFlag(const DWORD dwFlagToUnset) _dwStartupFlags &= ~dwFlagToUnset; } +void Settings::SetColorTableEntry(const size_t index, const COLORREF ColorValue) +{ + _colorTable.at(index) = ColorValue; +} + COLORREF Settings::GetColorTableEntry(const size_t index) const { return _colorTable.at(index); } +void Settings::SetLegacyColorTableEntry(const size_t index, const COLORREF ColorValue) +{ + _colorTable.at(TextColor::TransposeLegacyIndex(index)) = ColorValue; +} + +COLORREF Settings::GetLegacyColorTableEntry(const size_t index) const +{ + return _colorTable.at(TextColor::TransposeLegacyIndex(index)); +} + COLORREF Settings::GetCursorColor() const noexcept { return _CursorColor; diff --git a/src/host/settings.hpp b/src/host/settings.hpp index e8468da6b..896de0e20 100644 --- a/src/host/settings.hpp +++ b/src/host/settings.hpp @@ -167,6 +167,8 @@ public: void SetColorTableEntry(const size_t index, const COLORREF ColorValue); COLORREF GetColorTableEntry(const size_t index) const; + void SetLegacyColorTableEntry(const size_t index, const COLORREF ColorValue); + COLORREF GetLegacyColorTableEntry(const size_t index) const; COLORREF GetCursorColor() const noexcept; CursorType GetCursorType() const noexcept; diff --git a/src/host/sources.inc b/src/host/sources.inc index 3ee3b70c3..700fda72a 100644 --- a/src/host/sources.inc +++ b/src/host/sources.inc @@ -89,7 +89,6 @@ SOURCES = \ ..\utf8ToWideCharParser.cpp \ ..\conareainfo.cpp \ ..\conimeinfo.cpp \ - ..\conattrs.cpp \ ..\ConsoleArguments.cpp \ ..\CommandNumberPopup.cpp \ ..\CommandListPopup.cpp \ diff --git a/src/host/ut_host/ScreenBufferTests.cpp b/src/host/ut_host/ScreenBufferTests.cpp index 0e31c2b32..83ba0c502 100644 --- a/src/host/ut_host/ScreenBufferTests.cpp +++ b/src/host/ut_host/ScreenBufferTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT license. #include "precomp.h" @@ -1634,74 +1634,74 @@ void ScreenBufferTests::VtSetColorTable() L"Process some valid sequences for setting the table")); stateMachine.ProcessString(L"\x1b]4;0;rgb:1/1/1\x7"); - VERIFY_ARE_EQUAL(RGB(0x11, 0x11, 0x11), gci.GetColorTableEntry(::XtermToWindowsIndex(0))); + VERIFY_ARE_EQUAL(RGB(0x11, 0x11, 0x11), gci.GetColorTableEntry(0)); stateMachine.ProcessString(L"\x1b]4;1;rgb:1/23/1\x7"); - VERIFY_ARE_EQUAL(RGB(0x11, 0x23, 0x11), gci.GetColorTableEntry(::XtermToWindowsIndex(1))); + VERIFY_ARE_EQUAL(RGB(0x11, 0x23, 0x11), gci.GetColorTableEntry(1)); stateMachine.ProcessString(L"\x1b]4;2;rgb:1/23/12\x7"); - VERIFY_ARE_EQUAL(RGB(0x11, 0x23, 0x12), gci.GetColorTableEntry(::XtermToWindowsIndex(2))); + VERIFY_ARE_EQUAL(RGB(0x11, 0x23, 0x12), gci.GetColorTableEntry(2)); stateMachine.ProcessString(L"\x1b]4;3;rgb:12/23/12\x7"); - VERIFY_ARE_EQUAL(RGB(0x12, 0x23, 0x12), gci.GetColorTableEntry(::XtermToWindowsIndex(3))); + VERIFY_ARE_EQUAL(RGB(0x12, 0x23, 0x12), gci.GetColorTableEntry(3)); stateMachine.ProcessString(L"\x1b]4;4;rgb:ff/a1/1b\x7"); - VERIFY_ARE_EQUAL(RGB(0xff, 0xa1, 0x1b), gci.GetColorTableEntry(::XtermToWindowsIndex(4))); + VERIFY_ARE_EQUAL(RGB(0xff, 0xa1, 0x1b), gci.GetColorTableEntry(4)); stateMachine.ProcessString(L"\x1b]4;5;rgb:ff/a1/1b\x1b\\"); - VERIFY_ARE_EQUAL(RGB(0xff, 0xa1, 0x1b), gci.GetColorTableEntry(::XtermToWindowsIndex(5))); + VERIFY_ARE_EQUAL(RGB(0xff, 0xa1, 0x1b), gci.GetColorTableEntry(5)); Log::Comment(NoThrowString().Format( L"Try a bunch of invalid sequences.")); Log::Comment(NoThrowString().Format( L"First start by setting an entry to a known value to compare to.")); stateMachine.ProcessString(L"\x1b]4;5;rgb:09/09/09\x1b\\"); - VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5))); + VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(5)); Log::Comment(NoThrowString().Format( L"invalid: Missing the first component")); stateMachine.ProcessString(L"\x1b]4;5;rgb:/1/1\x1b\\"); - VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5))); + VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(5)); Log::Comment(NoThrowString().Format( L"invalid: too many components")); stateMachine.ProcessString(L"\x1b]4;5;rgb:1/1/1/1\x1b\\"); - VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5))); + VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(5)); Log::Comment(NoThrowString().Format( L"invalid: no second component")); stateMachine.ProcessString(L"\x1b]4;5;rgb:1//1\x1b\\"); - VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5))); + VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(5)); Log::Comment(NoThrowString().Format( L"invalid: no components")); stateMachine.ProcessString(L"\x1b]4;5;rgb://\x1b\\"); - VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5))); + VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(5)); Log::Comment(NoThrowString().Format( L"invalid: no third component")); stateMachine.ProcessString(L"\x1b]4;5;rgb:1/11/\x1b\\"); - VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5))); + VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(5)); Log::Comment(NoThrowString().Format( L"invalid: rgbi is not a supported color space")); stateMachine.ProcessString(L"\x1b]4;5;rgbi:1/1/1\x1b\\"); - VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5))); + VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(5)); Log::Comment(NoThrowString().Format( L"invalid: cmyk is not a supported color space")); stateMachine.ProcessString(L"\x1b]4;5;cmyk:1/1/1\x1b\\"); - VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5))); + VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(5)); Log::Comment(NoThrowString().Format( L"invalid: no table index should do nothing")); stateMachine.ProcessString(L"\x1b]4;;rgb:1/1/1\x1b\\"); - VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5))); + VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(5)); Log::Comment(NoThrowString().Format( L"invalid: need to specify a color space")); stateMachine.ProcessString(L"\x1b]4;5;1/1/1\x1b\\"); - VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5))); + VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(5)); } void ScreenBufferTests::ResizeTraditionalDoesNotDoubleFreeAttrRows() @@ -1912,8 +1912,8 @@ void ScreenBufferTests::VtEraseAllPersistCursorFillColor() L"The viewport should be full of dark_red on bright_blue")); auto expectedAttr = TextAttribute{}; - expectedAttr.SetIndexedForeground((BYTE)XtermToWindowsIndex(1)); - expectedAttr.SetIndexedBackground((BYTE)XtermToWindowsIndex(12)); + expectedAttr.SetIndexedForeground(TextColor::DARK_RED); + expectedAttr.SetIndexedBackground(TextColor::BRIGHT_BLUE); stateMachine.ProcessString(L"\x1b[31;104m"); VERIFY_ARE_EQUAL(expectedAttr, si.GetAttributes()); @@ -2256,8 +2256,8 @@ void ScreenBufferTests::SetDefaultsIndividuallyBothDefault() COLORREF magenta = RGB(255, 0, 255); COLORREF yellow = RGB(255, 255, 0); - COLORREF brightGreen = gci.GetColorTableEntry(::XtermToWindowsIndex(10)); - COLORREF darkBlue = gci.GetColorTableEntry(::XtermToWindowsIndex(4)); + COLORREF brightGreen = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN); + COLORREF darkBlue = gci.GetColorTableEntry(TextColor::DARK_BLUE); gci.SetDefaultForegroundColor(yellow); gci.SetDefaultBackgroundColor(magenta); @@ -2292,8 +2292,8 @@ void ScreenBufferTests::SetDefaultsIndividuallyBothDefault() // See the log comment above for description of these values. TextAttribute expectedDefaults{}; TextAttribute expectedTwo; - expectedTwo.SetIndexedForeground((BYTE)XtermToWindowsIndex(10)); - expectedTwo.SetIndexedBackground((BYTE)XtermToWindowsIndex(4)); + expectedTwo.SetIndexedForeground(TextColor::BRIGHT_GREEN); + expectedTwo.SetIndexedBackground(TextColor::DARK_BLUE); TextAttribute expectedThree = expectedTwo; expectedThree.SetDefaultForeground(); // Four is the same as Defaults @@ -2705,7 +2705,7 @@ void ScreenBufferTests::SetGlobalColorTable() VERIFY_SUCCEEDED(mainBuffer.SetViewportOrigin(true, COORD({ 0, 0 }), true)); mainCursor.SetPosition({ 0, 0 }); - const COLORREF originalRed = gci.GetColorTableEntry(4); + const COLORREF originalRed = gci.GetColorTableEntry(TextColor::DARK_RED); const COLORREF testColor = RGB(0x11, 0x22, 0x33); VERIFY_ARE_NOT_EQUAL(originalRed, testColor); @@ -3209,10 +3209,10 @@ void ScreenBufferTests::DontResetColorsAboveVirtualBottom() L"cursor=%s", VerifyOutputTraits::ToString(cursor.GetPosition()).GetBuffer())); Log::Comment(NoThrowString().Format( L"viewport=%s", VerifyOutputTraits::ToString(si.GetViewport().ToInclusive()).GetBuffer())); - const auto darkRed = gci.GetColorTableEntry(::XtermToWindowsIndex(1)); - const auto darkBlue = gci.GetColorTableEntry(::XtermToWindowsIndex(4)); - const auto darkBlack = gci.GetColorTableEntry(::XtermToWindowsIndex(0)); - const auto darkWhite = gci.GetColorTableEntry(::XtermToWindowsIndex(7)); + const auto darkRed = gci.GetColorTableEntry(TextColor::DARK_RED); + const auto darkBlue = gci.GetColorTableEntry(TextColor::DARK_BLUE); + const auto darkBlack = gci.GetColorTableEntry(TextColor::DARK_BLACK); + const auto darkWhite = gci.GetColorTableEntry(TextColor::DARK_WHITE); stateMachine.ProcessString(L"\x1b[31;44m"); stateMachine.ProcessString(L"X"); stateMachine.ProcessString(L"\x1b[m"); @@ -6168,8 +6168,8 @@ void ScreenBufferTests::TestWriteConsoleVTQuirkMode() /* Write red on blue, verify that it comes through */ { TextAttribute vtRedOnBlueAttribute{}; - vtRedOnBlueAttribute.SetForeground(TextColor{ gsl::narrow_cast(XtermToWindowsIndex(1)), false }); - vtRedOnBlueAttribute.SetBackground(TextColor{ gsl::narrow_cast(XtermToWindowsIndex(4)), false }); + vtRedOnBlueAttribute.SetForeground(TextColor{ TextColor::DARK_RED, false }); + vtRedOnBlueAttribute.SetBackground(TextColor{ TextColor::DARK_BLUE, false }); seq = L"\x1b[31;44m"; seqCb = 2 * seq.size(); @@ -6187,8 +6187,8 @@ void ScreenBufferTests::TestWriteConsoleVTQuirkMode() /* Write white on black, verify that it acts as expected for the quirk mode */ { TextAttribute vtWhiteOnBlackAttribute{}; - vtWhiteOnBlackAttribute.SetForeground(TextColor{ gsl::narrow_cast(XtermToWindowsIndex(7)), false }); - vtWhiteOnBlackAttribute.SetBackground(TextColor{ gsl::narrow_cast(XtermToWindowsIndex(0)), false }); + vtWhiteOnBlackAttribute.SetForeground(TextColor{ TextColor::DARK_WHITE, false }); + vtWhiteOnBlackAttribute.SetBackground(TextColor{ TextColor::DARK_BLACK, false }); const TextAttribute quirkExpectedAttribute{ useQuirk ? defaultAttribute : vtWhiteOnBlackAttribute }; @@ -6208,8 +6208,8 @@ void ScreenBufferTests::TestWriteConsoleVTQuirkMode() /* Write bright white on black, verify that it acts as expected for the quirk mode */ { TextAttribute vtBrightWhiteOnBlackAttribute{}; - vtBrightWhiteOnBlackAttribute.SetForeground(TextColor{ gsl::narrow_cast(XtermToWindowsIndex(7)), false }); - vtBrightWhiteOnBlackAttribute.SetBackground(TextColor{ gsl::narrow_cast(XtermToWindowsIndex(0)), false }); + vtBrightWhiteOnBlackAttribute.SetForeground(TextColor{ TextColor::DARK_WHITE, false }); + vtBrightWhiteOnBlackAttribute.SetBackground(TextColor{ TextColor::DARK_BLACK, false }); vtBrightWhiteOnBlackAttribute.SetBold(true); TextAttribute vtBrightWhiteOnDefaultAttribute{ vtBrightWhiteOnBlackAttribute }; // copy the above attribute @@ -6233,8 +6233,8 @@ void ScreenBufferTests::TestWriteConsoleVTQuirkMode() /* Write a 256-color white on a 256-color black, make sure the quirk does not suppress it */ { TextAttribute vtWhiteOnBlack256Attribute{}; - vtWhiteOnBlack256Attribute.SetForeground(TextColor{ gsl::narrow_cast(XtermToWindowsIndex(7)), true }); - vtWhiteOnBlack256Attribute.SetBackground(TextColor{ gsl::narrow_cast(XtermToWindowsIndex(0)), true }); + vtWhiteOnBlack256Attribute.SetForeground(TextColor{ TextColor::DARK_WHITE, true }); + vtWhiteOnBlack256Attribute.SetBackground(TextColor{ TextColor::DARK_BLACK, true }); // reset (disable bold from the last test) before setting both colors seq = L"\x1b[m\x1b[38;5;7;48;5;0m"; // the quirk should *not* suppress this (!) diff --git a/src/host/ut_host/TextBufferTests.cpp b/src/host/ut_host/TextBufferTests.cpp index c8dd06793..2872c9421 100644 --- a/src/host/ut_host/TextBufferTests.cpp +++ b/src/host/ut_host/TextBufferTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT license. #include "precomp.h" @@ -779,8 +779,8 @@ void TextBufferTests::TestMixedRgbAndLegacyBrightness() // '\E[m\E[32mX\E[1mX' // Make sure that the second X is a BRIGHT green, not white. Log::Comment(L"Case 4 ;\"\\E[m\\E[32mX\\E[1mX\""); - const auto dark_green = gci.GetColorTableEntry(2); - const auto bright_green = gci.GetColorTableEntry(10); + const auto dark_green = gci.GetColorTableEntry(TextColor::DARK_GREEN); + const auto bright_green = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN); VERIFY_ARE_NOT_EQUAL(dark_green, bright_green); wchar_t* sequence = L"\x1b[m\x1b[32mX\x1b[1mX"; @@ -887,8 +887,8 @@ void TextBufferTests::TestUnBold() const auto x = cursor.GetPosition().X; const auto y = cursor.GetPosition().Y; - const auto dark_green = gci.GetColorTableEntry(2); - const auto bright_green = gci.GetColorTableEntry(10); + const auto dark_green = gci.GetColorTableEntry(TextColor::DARK_GREEN); + const auto bright_green = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN); Log::Comment(NoThrowString().Format( L"cursor={X:%d,Y:%d}", @@ -938,8 +938,8 @@ void TextBufferTests::TestUnBoldRgb() const auto x = cursor.GetPosition().X; const auto y = cursor.GetPosition().Y; - const auto dark_green = gci.GetColorTableEntry(2); - const auto bright_green = gci.GetColorTableEntry(10); + const auto dark_green = gci.GetColorTableEntry(TextColor::DARK_GREEN); + const auto bright_green = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN); Log::Comment(NoThrowString().Format( L"cursor={X:%d,Y:%d}", @@ -997,8 +997,8 @@ void TextBufferTests::TestComplexUnBold() const auto x = cursor.GetPosition().X; const auto y = cursor.GetPosition().Y; - const auto dark_green = gci.GetColorTableEntry(2); - const auto bright_green = gci.GetColorTableEntry(10); + const auto dark_green = gci.GetColorTableEntry(TextColor::DARK_GREEN); + const auto bright_green = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN); Log::Comment(NoThrowString().Format( L"cursor={X:%d,Y:%d}", @@ -1079,8 +1079,8 @@ void TextBufferTests::CopyAttrs() const auto x = cursor.GetPosition().X; const auto y = cursor.GetPosition().Y; - const auto dark_blue = gci.GetColorTableEntry(1); - const auto dark_magenta = gci.GetColorTableEntry(5); + const auto dark_blue = gci.GetColorTableEntry(TextColor::DARK_BLUE); + const auto dark_magenta = gci.GetColorTableEntry(TextColor::DARK_MAGENTA); Log::Comment(NoThrowString().Format( L"cursor={X:%d,Y:%d}", @@ -1133,7 +1133,7 @@ void TextBufferTests::EmptySgrTest() const auto x = cursor.GetPosition().X; const auto y = cursor.GetPosition().Y; - const COLORREF darkRed = gci.GetColorTableEntry(4); + const COLORREF darkRed = gci.GetColorTableEntry(TextColor::DARK_RED); Log::Comment(NoThrowString().Format( L"cursor={X:%d,Y:%d}", x, @@ -1192,7 +1192,7 @@ void TextBufferTests::TestReverseReset() const auto x = cursor.GetPosition().X; const auto y = cursor.GetPosition().Y; - const auto dark_green = gci.GetColorTableEntry(2); + const auto dark_green = gci.GetColorTableEntry(TextColor::DARK_GREEN); const COLORREF rgbColor = RGB(128, 5, 255); Log::Comment(NoThrowString().Format( @@ -1258,9 +1258,9 @@ void TextBufferTests::CopyLastAttr() const COLORREF defaultBrightYellow = RGB(249, 241, 165); const COLORREF defaultBrightCyan = RGB(97, 214, 214); - gci.SetColorTableEntry(8, defaultBrightBlack); - gci.SetColorTableEntry(14, defaultBrightYellow); - gci.SetColorTableEntry(11, defaultBrightCyan); + gci.SetColorTableEntry(TextColor::BRIGHT_BLACK, defaultBrightBlack); + gci.SetColorTableEntry(TextColor::BRIGHT_YELLOW, defaultBrightYellow); + gci.SetColorTableEntry(TextColor::BRIGHT_CYAN, defaultBrightCyan); // Write (solFg, solBG) X \n // (solFg, solBG) X (solCyan, solBG) X \n @@ -1405,8 +1405,8 @@ void TextBufferTests::TestResetClearsBoldness() si.SetAttributes(defaultAttribute); const auto [defaultFg, defaultBg] = gci.LookupAttributeColors(si.GetAttributes()); - const auto dark_green = gci.GetColorTableEntry(2); - const auto bright_green = gci.GetColorTableEntry(10); + const auto dark_green = gci.GetColorTableEntry(TextColor::DARK_GREEN); + const auto bright_green = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN); wchar_t* sequence = L"\x1b[32mA\x1b[1mB\x1b[0mC\x1b[32mD"; Log::Comment(NoThrowString().Format(sequence)); diff --git a/src/host/ut_host/VtRendererTests.cpp b/src/host/ut_host/VtRendererTests.cpp index a12dd8673..3d9a5b8aa 100644 --- a/src/host/ut_host/VtRendererTests.cpp +++ b/src/host/ut_host/VtRendererTests.cpp @@ -470,7 +470,7 @@ void VtRendererTest::Xterm256TestColors() Log::Comment(NoThrowString().Format( L"----Change only the BG----")); - textAttributes.SetIndexedBackground(FOREGROUND_RED); + textAttributes.SetIndexedBackground(TextColor::DARK_RED); qExpectedInput.push_back("\x1b[41m"); // Background DARK_RED VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, @@ -479,7 +479,7 @@ void VtRendererTest::Xterm256TestColors() Log::Comment(NoThrowString().Format( L"----Change only the FG----")); - textAttributes.SetIndexedForeground(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + textAttributes.SetIndexedForeground(TextColor::DARK_WHITE); qExpectedInput.push_back("\x1b[37m"); // Foreground DARK_WHITE VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, @@ -515,7 +515,7 @@ void VtRendererTest::Xterm256TestColors() Log::Comment(NoThrowString().Format( L"----Change only the FG to a 256-color index----")); - textAttributes.SetIndexedForeground256(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + textAttributes.SetIndexedForeground256(TextColor::DARK_WHITE); qExpectedInput.push_back("\x1b[38;5;7m"); // Foreground DARK_WHITE (256-Color Index) VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, @@ -524,7 +524,7 @@ void VtRendererTest::Xterm256TestColors() Log::Comment(NoThrowString().Format( L"----Change only the BG to a 256-color index----")); - textAttributes.SetIndexedBackground256(FOREGROUND_RED); + textAttributes.SetIndexedBackground256(TextColor::DARK_RED); qExpectedInput.push_back("\x1b[48;5;1m"); // Background DARK_RED (256-Color Index) VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, @@ -859,7 +859,7 @@ void VtRendererTest::Xterm256TestAttributesAcrossReset() VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false)); Log::Comment(L"----Set Green Foreground----"); - textAttributes.SetIndexedForeground(FOREGROUND_GREEN); + textAttributes.SetIndexedForeground(TextColor::DARK_GREEN); qExpectedInput.push_back("\x1b[32m"); VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false)); @@ -870,7 +870,7 @@ void VtRendererTest::Xterm256TestAttributesAcrossReset() VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false)); Log::Comment(L"----Set Green Background----"); - textAttributes.SetIndexedBackground(FOREGROUND_GREEN); + textAttributes.SetIndexedBackground(TextColor::DARK_GREEN); qExpectedInput.push_back("\x1b[42m"); VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false)); @@ -1104,7 +1104,7 @@ void VtRendererTest::XtermTestColors() Log::Comment(NoThrowString().Format( L"----Change only the BG----")); - textAttributes.SetIndexedBackground(FOREGROUND_RED); + textAttributes.SetIndexedBackground(TextColor::DARK_RED); qExpectedInput.push_back("\x1b[41m"); // Background DARK_RED VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, @@ -1113,7 +1113,7 @@ void VtRendererTest::XtermTestColors() Log::Comment(NoThrowString().Format( L"----Change only the FG----")); - textAttributes.SetIndexedForeground(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + textAttributes.SetIndexedForeground(TextColor::DARK_WHITE); qExpectedInput.push_back("\x1b[37m"); // Foreground DARK_WHITE VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, @@ -1150,7 +1150,7 @@ void VtRendererTest::XtermTestColors() Log::Comment(NoThrowString().Format( L"----Change only the FG to a 256-color index----")); - textAttributes.SetIndexedForeground256(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + textAttributes.SetIndexedForeground256(TextColor::DARK_WHITE); qExpectedInput.push_back("\x1b[37m"); // Foreground DARK_WHITE VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, @@ -1159,7 +1159,7 @@ void VtRendererTest::XtermTestColors() Log::Comment(NoThrowString().Format( L"----Change only the BG to a 256-color index----")); - textAttributes.SetIndexedBackground256(FOREGROUND_RED); + textAttributes.SetIndexedBackground256(TextColor::DARK_RED); qExpectedInput.push_back("\x1b[41m"); // Background DARK_RED VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, @@ -1351,7 +1351,7 @@ void VtRendererTest::XtermTestAttributesAcrossReset() VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false)); Log::Comment(L"----Set Green Foreground----"); - textAttributes.SetIndexedForeground(FOREGROUND_GREEN); + textAttributes.SetIndexedForeground(TextColor::DARK_GREEN); qExpectedInput.push_back("\x1b[32m"); VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false)); @@ -1362,7 +1362,7 @@ void VtRendererTest::XtermTestAttributesAcrossReset() VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false)); Log::Comment(L"----Set Green Background----"); - textAttributes.SetIndexedBackground(FOREGROUND_GREEN); + textAttributes.SetIndexedBackground(TextColor::DARK_GREEN); qExpectedInput.push_back("\x1b[42m"); VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false)); diff --git a/src/inc/conattrs.hpp b/src/inc/conattrs.hpp index cb9110064..8589590d4 100644 --- a/src/inc/conattrs.hpp +++ b/src/inc/conattrs.hpp @@ -22,20 +22,6 @@ enum class ExtendedAttributes : BYTE }; DEFINE_ENUM_FLAG_OPERATORS(ExtendedAttributes); -WORD XtermToWindowsIndex(const size_t index) noexcept; -WORD Xterm256ToWindowsIndex(const size_t index) noexcept; -WORD XtermToLegacy(const size_t xtermForeground, const size_t xtermBackground); - -constexpr WORD WINDOWS_RED_ATTR = FOREGROUND_RED; -constexpr WORD WINDOWS_GREEN_ATTR = FOREGROUND_GREEN; -constexpr WORD WINDOWS_BLUE_ATTR = FOREGROUND_BLUE; -constexpr WORD WINDOWS_BRIGHT_ATTR = FOREGROUND_INTENSITY; - -constexpr WORD XTERM_RED_ATTR = 0x01; -constexpr WORD XTERM_GREEN_ATTR = 0x02; -constexpr WORD XTERM_BLUE_ATTR = 0x04; -constexpr WORD XTERM_BRIGHT_ATTR = 0x08; - enum class CursorType : unsigned int { Legacy = 0x0, // uses the cursor's height value to range from underscore-like to full box diff --git a/src/interactivity/win32/Clipboard.cpp b/src/interactivity/win32/Clipboard.cpp index b12161ccf..8e05e7827 100644 --- a/src/interactivity/win32/Clipboard.cpp +++ b/src/interactivity/win32/Clipboard.cpp @@ -208,7 +208,11 @@ void Clipboard::StoreSelectionToClipboard(bool const copyFormatting) const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); const auto& buffer = gci.GetActiveOutputBuffer().GetTextBuffer(); - const auto GetAttributeColors = std::bind(&CONSOLE_INFORMATION::LookupAttributeColors, &gci, std::placeholders::_1); + const auto defaultForeground = gci.GetDefaultForeground(); + const auto defaultBackground = gci.GetDefaultBackground(); + const auto GetAttributeColors = [=, &gci](const auto& attr) { + return gci.LookupAttributeColors(attr, defaultForeground, defaultBackground); + }; bool includeCRLF, trimTrailingWhitespace; if (WI_IsFlagSet(GetKeyState(VK_SHIFT), KEY_PRESSED)) diff --git a/src/interactivity/win32/menu.cpp b/src/interactivity/win32/menu.cpp index 3229f5663..9364e6364 100644 --- a/src/interactivity/win32/menu.cpp +++ b/src/interactivity/win32/menu.cpp @@ -337,7 +337,7 @@ void Menu::s_ShowPropertiesDialog(HWND const hwnd, BOOL const Defaults) for (size_t i = 0; i < std::size(pStateInfo->ColorTable); i++) { - pStateInfo->ColorTable[i] = gci.GetColorTableEntry(i); + pStateInfo->ColorTable[i] = gci.GetLegacyColorTableEntry(i); } // Create mutable copies of the titles so the propsheet can do something with them. @@ -566,7 +566,7 @@ void Menu::s_PropertiesUpdate(PCONSOLE_STATE_INFO pStateInfo) for (size_t i = 0; i < std::size(pStateInfo->ColorTable); i++) { - gci.SetColorTableEntry(i, pStateInfo->ColorTable[i]); + gci.SetLegacyColorTableEntry(i, pStateInfo->ColorTable[i]); } // Ensure that attributes only contain color specification. diff --git a/src/renderer/vt/VtSequences.cpp b/src/renderer/vt/VtSequences.cpp index efd16e2cb..c11e8cc4d 100644 --- a/src/renderer/vt/VtSequences.cpp +++ b/src/renderer/vt/VtSequences.cpp @@ -199,13 +199,14 @@ using namespace Microsoft::Console::Render; } // Method Description: -// - Formats and writes a sequence to change the current text attributes. +// - Formats and writes a sequence to change the current text attributes to an +// indexed color from the 16-color table. // Arguments: -// - wAttr: Windows color table index to emit as a VT sequence +// - index: color table index to emit as a VT sequence // - fIsForeground: true if we should emit the foreground sequence, false for background // Return Value: // - S_OK if we succeeded, else an appropriate HRESULT for failing to allocate or write. -[[nodiscard]] HRESULT VtEngine::_SetGraphicsRendition16Color(const WORD wAttr, +[[nodiscard]] HRESULT VtEngine::_SetGraphicsRendition16Color(const BYTE index, const bool fIsForeground) noexcept { // Always check using the foreground flags, because the bg flags constants @@ -220,28 +221,22 @@ using namespace Microsoft::Console::Render; // terminals display the bright color when displaying bolded text. // By specifying the boldness and brightness separately, we'll make sure the // terminal has an accurate representation of our buffer. - const int vtIndex = 30 + - (fIsForeground ? 0 : 10) + - ((WI_IsFlagSet(wAttr, FOREGROUND_INTENSITY)) ? 60 : 0) + - (WI_IsFlagSet(wAttr, FOREGROUND_RED) ? 1 : 0) + - (WI_IsFlagSet(wAttr, FOREGROUND_GREEN) ? 2 : 0) + - (WI_IsFlagSet(wAttr, FOREGROUND_BLUE) ? 4 : 0); - - return _WriteFormatted(FMT_COMPILE("\x1b[{}m"), vtIndex); + const auto prefix = WI_IsFlagSet(index, FOREGROUND_INTENSITY) ? (fIsForeground ? 90 : 100) : (fIsForeground ? 30 : 40); + return _WriteFormatted(FMT_COMPILE("\x1b[{}m"), prefix + (index & 7)); } // Method Description: // - Formats and writes a sequence to change the current text attributes to an // indexed color from the 256-color table. // Arguments: -// - wAttr: Windows color table index to emit as a VT sequence +// - index: color table index to emit as a VT sequence // - fIsForeground: true if we should emit the foreground sequence, false for background // Return Value: // - S_OK if we succeeded, else an appropriate HRESULT for failing to allocate or write. -[[nodiscard]] HRESULT VtEngine::_SetGraphicsRendition256Color(const WORD index, +[[nodiscard]] HRESULT VtEngine::_SetGraphicsRendition256Color(const BYTE index, const bool fIsForeground) noexcept { - return _WriteFormatted(FMT_COMPILE("\x1b[{}8;5;{}m"), fIsForeground ? '3' : '4', ::Xterm256ToWindowsIndex(index)); + return _WriteFormatted(FMT_COMPILE("\x1b[{}8;5;{}m"), fIsForeground ? '3' : '4', index); } // Method Description: diff --git a/src/renderer/vt/paint.cpp b/src/renderer/vt/paint.cpp index 1b9efb35e..adb0c90d1 100644 --- a/src/renderer/vt/paint.cpp +++ b/src/renderer/vt/paint.cpp @@ -287,9 +287,10 @@ using namespace Microsoft::Console::Types; } // We use the legacy color calculations to generate an approximation of the - // colors in the 16-color table. - auto fgIndex = fg.GetLegacyIndex(0); - auto bgIndex = bg.GetLegacyIndex(0); + // colors in the Windows 16-color table, but we need to transpose those + // values to obtain an index in an ANSI-compatible order. + auto fgIndex = TextColor::TransposeLegacyIndex(fg.GetLegacyIndex(0)); + auto bgIndex = TextColor::TransposeLegacyIndex(bg.GetLegacyIndex(0)); // If the bold attribute is set, and the foreground can be brightened, then do so. const bool brighten = textAttributes.IsBold() && fg.CanBeBrightened(); diff --git a/src/renderer/vt/vtrenderer.hpp b/src/renderer/vt/vtrenderer.hpp index 1965034db..f78adf647 100644 --- a/src/renderer/vt/vtrenderer.hpp +++ b/src/renderer/vt/vtrenderer.hpp @@ -185,9 +185,9 @@ namespace Microsoft::Console::Render [[nodiscard]] HRESULT _ClearScreen() noexcept; [[nodiscard]] HRESULT _ClearScrollback() noexcept; [[nodiscard]] HRESULT _ChangeTitle(const std::string& title) noexcept; - [[nodiscard]] HRESULT _SetGraphicsRendition16Color(const WORD wAttr, + [[nodiscard]] HRESULT _SetGraphicsRendition16Color(const BYTE index, const bool fIsForeground) noexcept; - [[nodiscard]] HRESULT _SetGraphicsRendition256Color(const WORD index, + [[nodiscard]] HRESULT _SetGraphicsRendition256Color(const BYTE index, const bool fIsForeground) noexcept; [[nodiscard]] HRESULT _SetGraphicsRenditionRGBColor(const COLORREF color, const bool fIsForeground) noexcept; diff --git a/src/terminal/adapter/adaptDispatch.cpp b/src/terminal/adapter/adaptDispatch.cpp index 49a3f71a9..8ffe4c202 100644 --- a/src/terminal/adapter/adaptDispatch.cpp +++ b/src/terminal/adapter/adaptDispatch.cpp @@ -2541,13 +2541,13 @@ void AdaptDispatch::_ReportSGRSetting() const const auto iterator = std::back_insert_iterator(response); if (color.IsIndex16()) { - const auto index = XtermToWindowsIndex(color.GetIndex()); + const auto index = color.GetIndex(); const auto colorParameter = base + (index >= 8 ? 60 : 0) + (index % 8); fmt::format_to(iterator, FMT_STRING(L";{}"), colorParameter); } else if (color.IsIndex256()) { - const auto index = Xterm256ToWindowsIndex(color.GetIndex()); + const auto index = color.GetIndex(); fmt::format_to(iterator, FMT_STRING(L";{};5;{}"), base + 8, index); } else if (color.IsRgb()) diff --git a/src/terminal/adapter/adaptDispatchGraphics.cpp b/src/terminal/adapter/adaptDispatchGraphics.cpp index c258c2c44..6d586cce6 100644 --- a/src/terminal/adapter/adaptDispatchGraphics.cpp +++ b/src/terminal/adapter/adaptDispatchGraphics.cpp @@ -13,29 +13,6 @@ using namespace Microsoft::Console::VirtualTerminal; using namespace Microsoft::Console::VirtualTerminal::DispatchTypes; -// clang-format off -constexpr BYTE BLUE_ATTR = 0x01; -constexpr BYTE GREEN_ATTR = 0x02; -constexpr BYTE RED_ATTR = 0x04; -constexpr BYTE BRIGHT_ATTR = 0x08; -constexpr BYTE DARK_BLACK = 0; -constexpr BYTE DARK_RED = RED_ATTR; -constexpr BYTE DARK_GREEN = GREEN_ATTR; -constexpr BYTE DARK_YELLOW = RED_ATTR | GREEN_ATTR; -constexpr BYTE DARK_BLUE = BLUE_ATTR; -constexpr BYTE DARK_MAGENTA = RED_ATTR | BLUE_ATTR; -constexpr BYTE DARK_CYAN = GREEN_ATTR | BLUE_ATTR; -constexpr BYTE DARK_WHITE = RED_ATTR | GREEN_ATTR | BLUE_ATTR; -constexpr BYTE BRIGHT_BLACK = BRIGHT_ATTR; -constexpr BYTE BRIGHT_RED = BRIGHT_ATTR | RED_ATTR; -constexpr BYTE BRIGHT_GREEN = BRIGHT_ATTR | GREEN_ATTR; -constexpr BYTE BRIGHT_YELLOW = BRIGHT_ATTR | RED_ATTR | GREEN_ATTR; -constexpr BYTE BRIGHT_BLUE = BRIGHT_ATTR | BLUE_ATTR; -constexpr BYTE BRIGHT_MAGENTA = BRIGHT_ATTR | RED_ATTR | BLUE_ATTR; -constexpr BYTE BRIGHT_CYAN = BRIGHT_ATTR | GREEN_ATTR | BLUE_ATTR; -constexpr BYTE BRIGHT_WHITE = BRIGHT_ATTR | RED_ATTR | GREEN_ATTR | BLUE_ATTR; -// clang-format on - // Routine Description: // - Helper to parse extended graphics options, which start with 38 (FG) or 48 (BG) // These options are followed by either a 2 (RGB) or 5 (xterm index) @@ -72,7 +49,7 @@ size_t AdaptDispatch::_SetRgbColorsHelper(const VTParameters options, const size_t tableIndex = options.at(1).value_or(0); if (tableIndex <= 255) { - const auto adjustedIndex = gsl::narrow_cast(::Xterm256ToWindowsIndex(tableIndex)); + const auto adjustedIndex = gsl::narrow_cast(tableIndex); if (isForeground) { attr.SetIndexedForeground256(adjustedIndex); @@ -178,100 +155,100 @@ bool AdaptDispatch::SetGraphicsRendition(const VTParameters options) attr.SetOverlined(false); break; case ForegroundBlack: - attr.SetIndexedForeground(DARK_BLACK); + attr.SetIndexedForeground(TextColor::DARK_BLACK); break; case ForegroundBlue: - attr.SetIndexedForeground(DARK_BLUE); + attr.SetIndexedForeground(TextColor::DARK_BLUE); break; case ForegroundGreen: - attr.SetIndexedForeground(DARK_GREEN); + attr.SetIndexedForeground(TextColor::DARK_GREEN); break; case ForegroundCyan: - attr.SetIndexedForeground(DARK_CYAN); + attr.SetIndexedForeground(TextColor::DARK_CYAN); break; case ForegroundRed: - attr.SetIndexedForeground(DARK_RED); + attr.SetIndexedForeground(TextColor::DARK_RED); break; case ForegroundMagenta: - attr.SetIndexedForeground(DARK_MAGENTA); + attr.SetIndexedForeground(TextColor::DARK_MAGENTA); break; case ForegroundYellow: - attr.SetIndexedForeground(DARK_YELLOW); + attr.SetIndexedForeground(TextColor::DARK_YELLOW); break; case ForegroundWhite: - attr.SetIndexedForeground(DARK_WHITE); + attr.SetIndexedForeground(TextColor::DARK_WHITE); break; case BackgroundBlack: - attr.SetIndexedBackground(DARK_BLACK); + attr.SetIndexedBackground(TextColor::DARK_BLACK); break; case BackgroundBlue: - attr.SetIndexedBackground(DARK_BLUE); + attr.SetIndexedBackground(TextColor::DARK_BLUE); break; case BackgroundGreen: - attr.SetIndexedBackground(DARK_GREEN); + attr.SetIndexedBackground(TextColor::DARK_GREEN); break; case BackgroundCyan: - attr.SetIndexedBackground(DARK_CYAN); + attr.SetIndexedBackground(TextColor::DARK_CYAN); break; case BackgroundRed: - attr.SetIndexedBackground(DARK_RED); + attr.SetIndexedBackground(TextColor::DARK_RED); break; case BackgroundMagenta: - attr.SetIndexedBackground(DARK_MAGENTA); + attr.SetIndexedBackground(TextColor::DARK_MAGENTA); break; case BackgroundYellow: - attr.SetIndexedBackground(DARK_YELLOW); + attr.SetIndexedBackground(TextColor::DARK_YELLOW); break; case BackgroundWhite: - attr.SetIndexedBackground(DARK_WHITE); + attr.SetIndexedBackground(TextColor::DARK_WHITE); break; case BrightForegroundBlack: - attr.SetIndexedForeground(BRIGHT_BLACK); + attr.SetIndexedForeground(TextColor::BRIGHT_BLACK); break; case BrightForegroundBlue: - attr.SetIndexedForeground(BRIGHT_BLUE); + attr.SetIndexedForeground(TextColor::BRIGHT_BLUE); break; case BrightForegroundGreen: - attr.SetIndexedForeground(BRIGHT_GREEN); + attr.SetIndexedForeground(TextColor::BRIGHT_GREEN); break; case BrightForegroundCyan: - attr.SetIndexedForeground(BRIGHT_CYAN); + attr.SetIndexedForeground(TextColor::BRIGHT_CYAN); break; case BrightForegroundRed: - attr.SetIndexedForeground(BRIGHT_RED); + attr.SetIndexedForeground(TextColor::BRIGHT_RED); break; case BrightForegroundMagenta: - attr.SetIndexedForeground(BRIGHT_MAGENTA); + attr.SetIndexedForeground(TextColor::BRIGHT_MAGENTA); break; case BrightForegroundYellow: - attr.SetIndexedForeground(BRIGHT_YELLOW); + attr.SetIndexedForeground(TextColor::BRIGHT_YELLOW); break; case BrightForegroundWhite: - attr.SetIndexedForeground(BRIGHT_WHITE); + attr.SetIndexedForeground(TextColor::BRIGHT_WHITE); break; case BrightBackgroundBlack: - attr.SetIndexedBackground(BRIGHT_BLACK); + attr.SetIndexedBackground(TextColor::BRIGHT_BLACK); break; case BrightBackgroundBlue: - attr.SetIndexedBackground(BRIGHT_BLUE); + attr.SetIndexedBackground(TextColor::BRIGHT_BLUE); break; case BrightBackgroundGreen: - attr.SetIndexedBackground(BRIGHT_GREEN); + attr.SetIndexedBackground(TextColor::BRIGHT_GREEN); break; case BrightBackgroundCyan: - attr.SetIndexedBackground(BRIGHT_CYAN); + attr.SetIndexedBackground(TextColor::BRIGHT_CYAN); break; case BrightBackgroundRed: - attr.SetIndexedBackground(BRIGHT_RED); + attr.SetIndexedBackground(TextColor::BRIGHT_RED); break; case BrightBackgroundMagenta: - attr.SetIndexedBackground(BRIGHT_MAGENTA); + attr.SetIndexedBackground(TextColor::BRIGHT_MAGENTA); break; case BrightBackgroundYellow: - attr.SetIndexedBackground(BRIGHT_YELLOW); + attr.SetIndexedBackground(TextColor::BRIGHT_YELLOW); break; case BrightBackgroundWhite: - attr.SetIndexedBackground(BRIGHT_WHITE); + attr.SetIndexedBackground(TextColor::BRIGHT_WHITE); break; case ForegroundExtended: i += _SetRgbColorsHelper(options.subspan(i + 1), attr, true); diff --git a/src/terminal/adapter/ut_adapter/adapterTest.cpp b/src/terminal/adapter/ut_adapter/adapterTest.cpp index b775f4c7a..d494b2deb 100644 --- a/src/terminal/adapter/ut_adapter/adapterTest.cpp +++ b/src/terminal/adapter/ut_adapter/adapterTest.cpp @@ -1307,49 +1307,49 @@ public: Log::Comment(L"Testing graphics 'Foreground Color Black'"); _testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedForeground(0); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_BLACK); break; case DispatchTypes::GraphicsOptions::ForegroundBlue: Log::Comment(L"Testing graphics 'Foreground Color Blue'"); _testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_BLUE); break; case DispatchTypes::GraphicsOptions::ForegroundGreen: Log::Comment(L"Testing graphics 'Foreground Color Green'"); _testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_GREEN); break; case DispatchTypes::GraphicsOptions::ForegroundCyan: Log::Comment(L"Testing graphics 'Foreground Color Cyan'"); _testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_INTENSITY }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE | FOREGROUND_GREEN); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_CYAN); break; case DispatchTypes::GraphicsOptions::ForegroundRed: Log::Comment(L"Testing graphics 'Foreground Color Red'"); _testGetSet->_attribute = TextAttribute{ FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_RED); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_RED); break; case DispatchTypes::GraphicsOptions::ForegroundMagenta: Log::Comment(L"Testing graphics 'Foreground Color Magenta'"); _testGetSet->_attribute = TextAttribute{ FOREGROUND_GREEN | FOREGROUND_INTENSITY }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE | FOREGROUND_RED); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_MAGENTA); break; case DispatchTypes::GraphicsOptions::ForegroundYellow: Log::Comment(L"Testing graphics 'Foreground Color Yellow'"); _testGetSet->_attribute = TextAttribute{ FOREGROUND_BLUE | FOREGROUND_INTENSITY }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN | FOREGROUND_RED); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_YELLOW); break; case DispatchTypes::GraphicsOptions::ForegroundWhite: Log::Comment(L"Testing graphics 'Foreground Color White'"); _testGetSet->_attribute = TextAttribute{ FOREGROUND_INTENSITY }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_WHITE); break; case DispatchTypes::GraphicsOptions::ForegroundDefault: Log::Comment(L"Testing graphics 'Foreground Color Default'"); @@ -1362,49 +1362,49 @@ public: Log::Comment(L"Testing graphics 'Background Color Black'"); _testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedBackground(0); + _testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_BLACK); break; case DispatchTypes::GraphicsOptions::BackgroundBlue: Log::Comment(L"Testing graphics 'Background Color Blue'"); _testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_INTENSITY }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_BLUE >> 4); + _testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_BLUE); break; case DispatchTypes::GraphicsOptions::BackgroundGreen: Log::Comment(L"Testing graphics 'Background Color Green'"); _testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_GREEN >> 4); + _testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_GREEN); break; case DispatchTypes::GraphicsOptions::BackgroundCyan: Log::Comment(L"Testing graphics 'Background Color Cyan'"); _testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_INTENSITY }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_BLUE | BACKGROUND_GREEN) >> 4); + _testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_CYAN); break; case DispatchTypes::GraphicsOptions::BackgroundRed: Log::Comment(L"Testing graphics 'Background Color Red'"); _testGetSet->_attribute = TextAttribute{ BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_RED >> 4); + _testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_RED); break; case DispatchTypes::GraphicsOptions::BackgroundMagenta: Log::Comment(L"Testing graphics 'Background Color Magenta'"); _testGetSet->_attribute = TextAttribute{ BACKGROUND_GREEN | BACKGROUND_INTENSITY }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_BLUE | BACKGROUND_RED) >> 4); + _testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_MAGENTA); break; case DispatchTypes::GraphicsOptions::BackgroundYellow: Log::Comment(L"Testing graphics 'Background Color Yellow'"); _testGetSet->_attribute = TextAttribute{ BACKGROUND_BLUE | BACKGROUND_INTENSITY }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_GREEN | BACKGROUND_RED) >> 4); + _testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_YELLOW); break; case DispatchTypes::GraphicsOptions::BackgroundWhite: Log::Comment(L"Testing graphics 'Background Color White'"); _testGetSet->_attribute = TextAttribute{ BACKGROUND_INTENSITY }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED) >> 4); + _testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_WHITE); break; case DispatchTypes::GraphicsOptions::BackgroundDefault: Log::Comment(L"Testing graphics 'Background Color Default'"); @@ -1417,97 +1417,97 @@ public: Log::Comment(L"Testing graphics 'Bright Foreground Color Black'"); _testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_BLACK); break; case DispatchTypes::GraphicsOptions::BrightForegroundBlue: Log::Comment(L"Testing graphics 'Bright Foreground Color Blue'"); _testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_GREEN }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_BLUE); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_BLUE); break; case DispatchTypes::GraphicsOptions::BrightForegroundGreen: Log::Comment(L"Testing graphics 'Bright Foreground Color Green'"); _testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_BLUE }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_GREEN); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_GREEN); break; case DispatchTypes::GraphicsOptions::BrightForegroundCyan: Log::Comment(L"Testing graphics 'Bright Foreground Color Cyan'"); _testGetSet->_attribute = TextAttribute{ FOREGROUND_RED }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_GREEN); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_CYAN); break; case DispatchTypes::GraphicsOptions::BrightForegroundRed: Log::Comment(L"Testing graphics 'Bright Foreground Color Red'"); _testGetSet->_attribute = TextAttribute{ FOREGROUND_BLUE | FOREGROUND_GREEN }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_RED); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_RED); break; case DispatchTypes::GraphicsOptions::BrightForegroundMagenta: Log::Comment(L"Testing graphics 'Bright Foreground Color Magenta'"); _testGetSet->_attribute = TextAttribute{ FOREGROUND_GREEN }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_RED); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_MAGENTA); break; case DispatchTypes::GraphicsOptions::BrightForegroundYellow: Log::Comment(L"Testing graphics 'Bright Foreground Color Yellow'"); _testGetSet->_attribute = TextAttribute{ FOREGROUND_BLUE }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_YELLOW); break; case DispatchTypes::GraphicsOptions::BrightForegroundWhite: Log::Comment(L"Testing graphics 'Bright Foreground Color White'"); _testGetSet->_attribute = TextAttribute{ 0 }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_WHITE); break; case DispatchTypes::GraphicsOptions::BrightBackgroundBlack: Log::Comment(L"Testing graphics 'Bright Background Color Black'"); _testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_INTENSITY >> 4); + _testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_BLACK); break; case DispatchTypes::GraphicsOptions::BrightBackgroundBlue: Log::Comment(L"Testing graphics 'Bright Background Color Blue'"); _testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_GREEN }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_BLUE) >> 4); + _testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_BLUE); break; case DispatchTypes::GraphicsOptions::BrightBackgroundGreen: Log::Comment(L"Testing graphics 'Bright Background Color Green'"); _testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_BLUE }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_GREEN) >> 4); + _testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_GREEN); break; case DispatchTypes::GraphicsOptions::BrightBackgroundCyan: Log::Comment(L"Testing graphics 'Bright Background Color Cyan'"); _testGetSet->_attribute = TextAttribute{ BACKGROUND_RED }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_BLUE | BACKGROUND_GREEN) >> 4); + _testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_CYAN); break; case DispatchTypes::GraphicsOptions::BrightBackgroundRed: Log::Comment(L"Testing graphics 'Bright Background Color Red'"); _testGetSet->_attribute = TextAttribute{ BACKGROUND_BLUE | BACKGROUND_GREEN }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_RED) >> 4); + _testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_RED); break; case DispatchTypes::GraphicsOptions::BrightBackgroundMagenta: Log::Comment(L"Testing graphics 'Bright Background Color Magenta'"); _testGetSet->_attribute = TextAttribute{ BACKGROUND_GREEN }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_BLUE | BACKGROUND_RED) >> 4); + _testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_MAGENTA); break; case DispatchTypes::GraphicsOptions::BrightBackgroundYellow: Log::Comment(L"Testing graphics 'Bright Background Color Yellow'"); _testGetSet->_attribute = TextAttribute{ BACKGROUND_BLUE }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_GREEN | BACKGROUND_RED) >> 4); + _testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_YELLOW); break; case DispatchTypes::GraphicsOptions::BrightBackgroundWhite: Log::Comment(L"Testing graphics 'Bright Background Color White'"); _testGetSet->_attribute = TextAttribute{ 0 }; _testGetSet->_expectedAttribute = _testGetSet->_attribute; - _testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED) >> 4); + _testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_WHITE); break; default: VERIFY_FAIL(L"Test not implemented yet!"); @@ -1545,7 +1545,7 @@ public: cOptions = 1; rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundCyan; _testGetSet->_expectedAttribute = {}; - _testGetSet->_expectedAttribute.SetIndexedForeground(3); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_CYAN); _testGetSet->_expectedAttribute.SetDefaultBackground(); VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions })); @@ -1561,7 +1561,7 @@ public: cOptions = 1; rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundRed; _testGetSet->_expectedAttribute = {}; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_RED); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_RED); _testGetSet->_expectedAttribute.SetDefaultBackground(); VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions })); @@ -1572,14 +1572,14 @@ public: cOptions = 1; rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundGreen; _testGetSet->_expectedAttribute = {}; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_GREEN); _testGetSet->_expectedAttribute.SetDefaultBackground(); VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions })); // First pop: cOptions = 0; _testGetSet->_expectedAttribute = {}; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_RED); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_RED); _testGetSet->_expectedAttribute.SetDefaultBackground(); VERIFY_IS_TRUE(_pDispatch->PopGraphicsRendition()); @@ -1593,22 +1593,22 @@ public: cOptions = 1; rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundGreen; _testGetSet->_expectedAttribute = {}; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_GREEN); _testGetSet->_expectedAttribute.SetDefaultBackground(); VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions })); cOptions = 1; rgOptions[0] = DispatchTypes::GraphicsOptions::BoldBright; _testGetSet->_expectedAttribute = {}; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_GREEN); _testGetSet->_expectedAttribute.SetBold(true); _testGetSet->_expectedAttribute.SetDefaultBackground(); VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions })); rgOptions[0] = DispatchTypes::GraphicsOptions::BackgroundBlue; _testGetSet->_expectedAttribute = {}; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN); - _testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_BLUE >> 4); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_GREEN); + _testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_BLUE); _testGetSet->_expectedAttribute.SetBold(true); VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions })); @@ -1624,8 +1624,8 @@ public: rgOptions[0] = DispatchTypes::GraphicsOptions::BackgroundGreen; rgOptions[1] = DispatchTypes::GraphicsOptions::DoublyUnderlined; _testGetSet->_expectedAttribute = {}; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN); - _testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_GREEN >> 4); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_GREEN); + _testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_GREEN); _testGetSet->_expectedAttribute.SetBold(true); _testGetSet->_expectedAttribute.SetDoublyUnderlined(true); VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions })); @@ -1633,24 +1633,24 @@ public: cOptions = 1; rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundRed; _testGetSet->_expectedAttribute = {}; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_RED); - _testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_GREEN >> 4); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_RED); + _testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_GREEN); _testGetSet->_expectedAttribute.SetBold(true); _testGetSet->_expectedAttribute.SetDoublyUnderlined(true); VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions })); rgOptions[0] = DispatchTypes::GraphicsOptions::NotBoldOrFaint; _testGetSet->_expectedAttribute = {}; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_RED); - _testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_GREEN >> 4); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_RED); + _testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_GREEN); _testGetSet->_expectedAttribute.SetDoublyUnderlined(true); VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions })); // And then restore... cOptions = 0; _testGetSet->_expectedAttribute = {}; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_RED); - _testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_BLUE >> 4); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_RED); + _testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_BLUE); _testGetSet->_expectedAttribute.SetBold(true); VERIFY_IS_TRUE(_pDispatch->PopGraphicsRendition()); } @@ -1672,7 +1672,7 @@ public: Log::Comment(L"Testing graphics 'Foreground Color Blue'"); rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundBlue; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_BLUE); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions })); Log::Comment(L"Enabling brightness"); @@ -1683,7 +1683,7 @@ public: Log::Comment(L"Testing graphics 'Foreground Color Green, with brightness'"); rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundGreen; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_GREEN); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions })); VERIFY_IS_TRUE(WI_IsFlagSet(_testGetSet->_attribute.GetLegacyAttributes(), FOREGROUND_GREEN)); VERIFY_IS_TRUE(_testGetSet->_attribute.IsBold()); @@ -1698,13 +1698,13 @@ public: Log::Comment(L"Testing graphics 'Foreground Color Bright Blue'"); rgOptions[0] = DispatchTypes::GraphicsOptions::BrightForegroundBlue; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE | FOREGROUND_INTENSITY); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_BLUE); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions })); VERIFY_IS_FALSE(_testGetSet->_attribute.IsBold()); Log::Comment(L"Testing graphics 'Foreground Color Blue', brightness of 9x series doesn't persist"); rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundBlue; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_BLUE); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions })); VERIFY_IS_FALSE(_testGetSet->_attribute.IsBold()); @@ -1717,7 +1717,7 @@ public: Log::Comment(L"Testing graphics 'Foreground Color Blue'"); rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundBlue; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_BLUE); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions })); VERIFY_IS_FALSE(_testGetSet->_attribute.IsBold()); @@ -1729,19 +1729,19 @@ public: Log::Comment(L"Testing graphics 'Foreground Color Bright Blue'"); rgOptions[0] = DispatchTypes::GraphicsOptions::BrightForegroundBlue; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE | FOREGROUND_INTENSITY); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_BLUE); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions })); VERIFY_IS_TRUE(_testGetSet->_attribute.IsBold()); Log::Comment(L"Testing graphics 'Foreground Color Blue, with brightness', brightness of 9x series doesn't affect brightness"); rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundBlue; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_BLUE); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions })); VERIFY_IS_TRUE(_testGetSet->_attribute.IsBold()); Log::Comment(L"Testing graphics 'Foreground Color Green, with brightness'"); rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundGreen; - _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN); + _testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_GREEN); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions })); VERIFY_IS_TRUE(_testGetSet->_attribute.IsBold()); } @@ -1971,16 +1971,16 @@ public: Log::Comment(L"Requesting SGR attributes (standard colors)."); _testGetSet->PrepData(); _testGetSet->_attribute = {}; - _testGetSet->_attribute.SetIndexedForeground((BYTE)::XtermToWindowsIndex(3)); - _testGetSet->_attribute.SetIndexedBackground((BYTE)::XtermToWindowsIndex(6)); + _testGetSet->_attribute.SetIndexedForeground(TextColor::DARK_YELLOW); + _testGetSet->_attribute.SetIndexedBackground(TextColor::DARK_CYAN); requestSetting(L"m"); _testGetSet->ValidateInputEvent(L"\033P1$r0;33;46m\033\\"); Log::Comment(L"Requesting SGR attributes (AIX colors)."); _testGetSet->PrepData(); _testGetSet->_attribute = {}; - _testGetSet->_attribute.SetIndexedForeground((BYTE)::XtermToWindowsIndex(14)); - _testGetSet->_attribute.SetIndexedBackground((BYTE)::XtermToWindowsIndex(11)); + _testGetSet->_attribute.SetIndexedForeground(TextColor::BRIGHT_CYAN); + _testGetSet->_attribute.SetIndexedBackground(TextColor::BRIGHT_YELLOW); requestSetting(L"m"); _testGetSet->ValidateInputEvent(L"\033P1$r0;96;103m\033\\"); @@ -2297,14 +2297,14 @@ public: rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundExtended; rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index; rgOptions[2] = (DispatchTypes::GraphicsOptions)2; // Green - _testGetSet->_expectedAttribute.SetIndexedForeground256((BYTE)::XtermToWindowsIndex(2)); + _testGetSet->_expectedAttribute.SetIndexedForeground256(TextColor::DARK_GREEN); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions })); Log::Comment(L"Test 2: Change Background"); rgOptions[0] = DispatchTypes::GraphicsOptions::BackgroundExtended; rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index; rgOptions[2] = (DispatchTypes::GraphicsOptions)9; // Bright Red - _testGetSet->_expectedAttribute.SetIndexedBackground256((BYTE)::XtermToWindowsIndex(9)); + _testGetSet->_expectedAttribute.SetIndexedBackground256(TextColor::BRIGHT_RED); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions })); Log::Comment(L"Test 3: Change Foreground to RGB color"); @@ -2328,7 +2328,7 @@ public: rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundExtended; rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index; rgOptions[2] = (DispatchTypes::GraphicsOptions)9; // Bright Red - _testGetSet->_expectedAttribute.SetIndexedForeground256((BYTE)::XtermToWindowsIndex(9)); + _testGetSet->_expectedAttribute.SetIndexedForeground256(TextColor::BRIGHT_RED); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions })); } @@ -2346,14 +2346,14 @@ public: Log::Comment(L"Test 1: Change Indexed Foreground with missing index parameter"); rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundExtended; rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index; - _testGetSet->_expectedAttribute.SetIndexedForeground256(0); + _testGetSet->_expectedAttribute.SetIndexedForeground256(TextColor::DARK_BLACK); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, 2 })); Log::Comment(L"Test 2: Change Indexed Background with default index parameter"); rgOptions[0] = DispatchTypes::GraphicsOptions::BackgroundExtended; rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index; rgOptions[2] = {}; - _testGetSet->_expectedAttribute.SetIndexedBackground256(0); + _testGetSet->_expectedAttribute.SetIndexedBackground256(TextColor::DARK_BLACK); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, 3 })); Log::Comment(L"Test 3: Change RGB Foreground with all RGB parameters missing"); diff --git a/src/types/colorTable.cpp b/src/types/colorTable.cpp index 630674549..0fa05ae3c 100644 --- a/src/types/colorTable.cpp +++ b/src/types/colorTable.cpp @@ -8,7 +8,7 @@ using namespace Microsoft::Console; using namespace std::string_view_literals; -static constexpr std::array campbellColorTable{ +static constexpr std::array standard256ColorTable{ til::color{ 0x0C, 0x0C, 0x0C }, til::color{ 0xC5, 0x0F, 0x1F }, til::color{ 0x13, 0xA1, 0x0E }, @@ -25,25 +25,6 @@ static constexpr std::array campbellColorTable{ til::color{ 0xB4, 0x00, 0x9E }, til::color{ 0x61, 0xD6, 0xD6 }, til::color{ 0xF2, 0xF2, 0xF2 }, -}; - -static constexpr std::array standardXterm256ColorTable{ - til::color{ 0x00, 0x00, 0x00 }, - til::color{ 0x80, 0x00, 0x00 }, - til::color{ 0x00, 0x80, 0x00 }, - til::color{ 0x80, 0x80, 0x00 }, - til::color{ 0x00, 0x00, 0x80 }, - til::color{ 0x80, 0x00, 0x80 }, - til::color{ 0x00, 0x80, 0x80 }, - til::color{ 0xC0, 0xC0, 0xC0 }, - til::color{ 0x80, 0x80, 0x80 }, - til::color{ 0xFF, 0x00, 0x00 }, - til::color{ 0x00, 0xFF, 0x00 }, - til::color{ 0xFF, 0xFF, 0x00 }, - til::color{ 0x00, 0x00, 0xFF }, - til::color{ 0xFF, 0x00, 0xFF }, - til::color{ 0x00, 0xFF, 0xFF }, - til::color{ 0xFF, 0xFF, 0xFF }, til::color{ 0x00, 0x00, 0x00 }, til::color{ 0x00, 0x00, 0x5F }, til::color{ 0x00, 0x00, 0x87 }, @@ -454,73 +435,21 @@ static constexpr til::presorted_static_map xorgAppColorTable{ std::pair{ "yellowgreen"sv, til::color{ 154, 205, 50 } } }; -// Function Description: -// - Fill the first 16 entries of a given color table with the Campbell color -// scheme, in the ANSI/VT RGB order. -// Arguments: -// - table: a color table with at least 16 entries -// Return Value: -// - , throws if the table has less that 16 entries -void Utils::InitializeCampbellColorTable(const gsl::span table) -{ - THROW_HR_IF(E_INVALIDARG, table.size() < 16); - - std::copy(campbellColorTable.begin(), campbellColorTable.end(), table.begin()); -} - -void Utils::InitializeCampbellColorTable(const gsl::span table) -{ - THROW_HR_IF(E_INVALIDARG, table.size() < 16); - - std::copy(campbellColorTable.begin(), campbellColorTable.end(), table.begin()); -} - gsl::span Utils::CampbellColorTable() { - return gsl::make_span(campbellColorTable); + return gsl::make_span(standard256ColorTable).first(16); } // Function Description: -// - Fill the first 16 entries of a given color table with the Campbell color -// scheme, in the Windows BGR order. +// - Fill up to 256 entries of a given color table with the default values // Arguments: -// - table: a color table with at least 16 entries +// - table: a color table to be filled // Return Value: -// - , throws if the table has less that 16 entries -void Utils::InitializeCampbellColorTableForConhost(const gsl::span table) +// - +void Utils::InitializeColorTable(const gsl::span table) { - THROW_HR_IF(E_INVALIDARG, table.size() < 16); - InitializeCampbellColorTable(table); - SwapANSIColorOrderForConhost(table); -} - -// Function Description: -// - modifies in-place the given color table from ANSI (RGB) order to Console order (BRG). -// Arguments: -// - table: a color table with at least 16 entries -// Return Value: -// - , throws if the table has less that 16 entries -void Utils::SwapANSIColorOrderForConhost(const gsl::span table) -{ - THROW_HR_IF(E_INVALIDARG, table.size() < 16); - std::swap(til::at(table, 1), til::at(table, 4)); - std::swap(til::at(table, 3), til::at(table, 6)); - std::swap(til::at(table, 9), til::at(table, 12)); - std::swap(til::at(table, 11), til::at(table, 14)); -} - -// Function Description: -// - Fill the first 255 entries of a given color table with the default values -// of a full 256-color table -// Arguments: -// - table: a color table with at least 256 entries -// Return Value: -// - , throws if the table has less that 256 entries -void Utils::Initialize256ColorTable(const gsl::span table) -{ - THROW_HR_IF(E_INVALIDARG, table.size() < 256); - - std::copy(standardXterm256ColorTable.begin(), standardXterm256ColorTable.end(), table.begin()); + const auto tableSize = std::min(table.size(), standard256ColorTable.size()); + std::copy_n(standard256ColorTable.begin(), tableSize, table.begin()); } #pragma warning(push) diff --git a/src/types/inc/colorTable.hpp b/src/types/inc/colorTable.hpp index 9754fc362..9999c3768 100644 --- a/src/types/inc/colorTable.hpp +++ b/src/types/inc/colorTable.hpp @@ -12,11 +12,7 @@ Abstract: namespace Microsoft::Console::Utils { - void InitializeCampbellColorTable(const gsl::span table); - void InitializeCampbellColorTable(const gsl::span table); - void InitializeCampbellColorTableForConhost(const gsl::span table); - void SwapANSIColorOrderForConhost(const gsl::span table); - void Initialize256ColorTable(const gsl::span table); + void InitializeColorTable(const gsl::span table); gsl::span CampbellColorTable(); std::optional ColorFromXOrgAppColorName(const std::wstring_view wstr) noexcept; diff --git a/src/types/ut_types/UtilsTests.cpp b/src/types/ut_types/UtilsTests.cpp index 88b8926f6..ac8b5e974 100644 --- a/src/types/ut_types/UtilsTests.cpp +++ b/src/types/ut_types/UtilsTests.cpp @@ -20,7 +20,6 @@ class UtilsTests TEST_CLASS(UtilsTests); TEST_METHOD(TestClampToShortMax); - TEST_METHOD(TestSwapColorPalette); TEST_METHOD(TestGuidToString); TEST_METHOD(TestSplitString); TEST_METHOD(TestFilterStringForPaste); @@ -55,35 +54,6 @@ void UtilsTests::TestClampToShortMax() auto withinRangeActual = ClampToShortMax(withinRangeExpected, min); VERIFY_ARE_EQUAL(withinRangeExpected, withinRangeActual); } -void UtilsTests::TestSwapColorPalette() -{ - std::array terminalTable; - std::array consoleTable; - - gsl::span terminalTableView = { &terminalTable[0], terminalTable.size() }; - gsl::span consoleTableView = { &consoleTable[0], consoleTable.size() }; - - // First set up the colors - InitializeCampbellColorTable(terminalTableView); - InitializeCampbellColorTableForConhost(consoleTableView); - - VERIFY_ARE_EQUAL(terminalTable[0], consoleTable[0]); - VERIFY_ARE_EQUAL(terminalTable[1], consoleTable[4]); - VERIFY_ARE_EQUAL(terminalTable[2], consoleTable[2]); - VERIFY_ARE_EQUAL(terminalTable[3], consoleTable[6]); - VERIFY_ARE_EQUAL(terminalTable[4], consoleTable[1]); - VERIFY_ARE_EQUAL(terminalTable[5], consoleTable[5]); - VERIFY_ARE_EQUAL(terminalTable[6], consoleTable[3]); - VERIFY_ARE_EQUAL(terminalTable[7], consoleTable[7]); - VERIFY_ARE_EQUAL(terminalTable[8], consoleTable[8]); - VERIFY_ARE_EQUAL(terminalTable[9], consoleTable[12]); - VERIFY_ARE_EQUAL(terminalTable[10], consoleTable[10]); - VERIFY_ARE_EQUAL(terminalTable[11], consoleTable[14]); - VERIFY_ARE_EQUAL(terminalTable[12], consoleTable[9]); - VERIFY_ARE_EQUAL(terminalTable[13], consoleTable[13]); - VERIFY_ARE_EQUAL(terminalTable[14], consoleTable[11]); - VERIFY_ARE_EQUAL(terminalTable[15], consoleTable[15]); -} void UtilsTests::TestGuidToString() { From 52b4bb760f87cd3d1e38330c9df4ee7e5d971e34 Mon Sep 17 00:00:00 2001 From: PankajBhojwani Date: Thu, 4 Nov 2021 15:29:58 -0700 Subject: [PATCH 15/23] Unify splitting panes and creating new tabs (#11305) Implements `_MakePane` in `TerminalPage`, which creates a pane that then can be used to pass into another pane to split or to create a new tab with. Places where we split pane or create a new tab now use `_MakePane`. ## PR Checklist * [x] Closes #11021 * [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * [x] I work here ## Validation Steps Performed Stands up to manual testing with multiple new pane/new tab commands as well as startup actions --- .../LocalTests_TerminalApp/TabTests.cpp | 10 +- .../TerminalApp/AppActionHandlers.cpp | 3 +- src/cascadia/TerminalApp/Pane.cpp | 17 +- src/cascadia/TerminalApp/Pane.h | 3 +- src/cascadia/TerminalApp/TabManagement.cpp | 80 +----- src/cascadia/TerminalApp/TerminalPage.cpp | 234 ++++++++++-------- src/cascadia/TerminalApp/TerminalPage.h | 15 +- src/cascadia/TerminalApp/TerminalTab.cpp | 48 ++-- src/cascadia/TerminalApp/TerminalTab.h | 4 +- 9 files changed, 189 insertions(+), 225 deletions(-) diff --git a/src/cascadia/LocalTests_TerminalApp/TabTests.cpp b/src/cascadia/LocalTests_TerminalApp/TabTests.cpp index ecb40c3eb..4afa3a03b 100644 --- a/src/cascadia/LocalTests_TerminalApp/TabTests.cpp +++ b/src/cascadia/LocalTests_TerminalApp/TabTests.cpp @@ -508,7 +508,7 @@ namespace TerminalAppLocalTests Log::Comment(NoThrowString().Format(L"Duplicate the first pane")); result = RunOnUIThread([&page]() { - page->_SplitPane(SplitDirection::Automatic, SplitType::Duplicate, 0.5f, nullptr); + page->_SplitPane(SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, true, nullptr)); VERIFY_ARE_EQUAL(1u, page->_tabs.Size()); auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); @@ -526,7 +526,7 @@ namespace TerminalAppLocalTests Log::Comment(NoThrowString().Format(L"Duplicate the pane, and don't crash")); result = RunOnUIThread([&page]() { - page->_SplitPane(SplitDirection::Automatic, SplitType::Duplicate, 0.5f, nullptr); + page->_SplitPane(SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, true, nullptr)); VERIFY_ARE_EQUAL(1u, page->_tabs.Size()); auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); @@ -844,7 +844,7 @@ namespace TerminalAppLocalTests // | 1 | 2 | // | | | // ------------------- - page->_SplitPane(SplitDirection::Right, SplitType::Duplicate, 0.5f, nullptr); + page->_SplitPane(SplitDirection::Right, 0.5f, page->_MakePane(nullptr, true, nullptr)); secondId = tab->_activePane->Id().value(); }); Sleep(250); @@ -862,7 +862,7 @@ namespace TerminalAppLocalTests // | 3 | | // | | | // ------------------- - page->_SplitPane(SplitDirection::Down, SplitType::Duplicate, 0.5f, nullptr); + page->_SplitPane(SplitDirection::Down, 0.5f, page->_MakePane(nullptr, true, nullptr)); auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); // Split again to make the 3rd tab thirdId = tab->_activePane->Id().value(); @@ -882,7 +882,7 @@ namespace TerminalAppLocalTests // | 3 | 4 | // | | | // ------------------- - page->_SplitPane(SplitDirection::Down, SplitType::Duplicate, 0.5f, nullptr); + page->_SplitPane(SplitDirection::Down, 0.5f, page->_MakePane(nullptr, true, nullptr)); auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); fourthId = tab->_activePane->Id().value(); }); diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index d9d4a1ca1..3feed58a0 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -174,10 +174,9 @@ namespace winrt::TerminalApp::implementation else if (const auto& realArgs = args.ActionArgs().try_as()) { _SplitPane(realArgs.SplitDirection(), - realArgs.SplitMode(), // This is safe, we're already filtering so the value is (0, 1) ::base::saturated_cast(realArgs.SplitSize()), - realArgs.TerminalArgs()); + _MakePane(realArgs.TerminalArgs(), realArgs.SplitMode() == SplitType::Duplicate)); args.Handled(true); } } diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index e04f558f6..ef8e12522 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -2351,35 +2351,32 @@ std::optional Pane::PreCalculateCanSplit(const std::shared_ptr targe } // Method Description: -// - Split the focused pane in our tree of panes, and place the given -// TermControl into the newly created pane. If we're the focused pane, then -// we'll create two new children, and place them side-by-side in our Grid. +// - The same as above, except this takes in the pane directly instead of a +// profile and control to make a pane with // Arguments: // - splitType: what type of split we want to create. -// - profile: The profile to associate with the newly created pane. -// - control: A TermControl to use in the new pane. +// - splitSize: the desired size of the split +// - newPane: the new pane // Return Value: // - The two newly created Panes, with the original pane first std::pair, std::shared_ptr> Pane::Split(SplitDirection splitType, const float splitSize, - const Profile& profile, - const TermControl& control) + std::shared_ptr newPane) { if (!_lastActive) { if (_firstChild && _firstChild->_HasFocusedChild()) { - return _firstChild->Split(splitType, splitSize, profile, control); + return _firstChild->Split(splitType, splitSize, newPane); } else if (_secondChild && _secondChild->_HasFocusedChild()) { - return _secondChild->Split(splitType, splitSize, profile, control); + return _secondChild->Split(splitType, splitSize, newPane); } return { nullptr, nullptr }; } - auto newPane = std::make_shared(profile, control); return _Split(splitType, splitSize, newPane); } diff --git a/src/cascadia/TerminalApp/Pane.h b/src/cascadia/TerminalApp/Pane.h index 9892a6e8a..920124c33 100644 --- a/src/cascadia/TerminalApp/Pane.h +++ b/src/cascadia/TerminalApp/Pane.h @@ -110,8 +110,7 @@ public: std::pair, std::shared_ptr> Split(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType, const float splitSize, - const winrt::Microsoft::Terminal::Settings::Model::Profile& profile, - const winrt::Microsoft::Terminal::Control::TermControl& control); + std::shared_ptr pane); bool ToggleSplitOrientation(); float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const; std::optional PreCalculateAutoSplit(const std::shared_ptr target, diff --git a/src/cascadia/TerminalApp/TabManagement.cpp b/src/cascadia/TerminalApp/TabManagement.cpp index b99af3236..e67ad7780 100644 --- a/src/cascadia/TerminalApp/TabManagement.cpp +++ b/src/cascadia/TerminalApp/TabManagement.cpp @@ -68,7 +68,7 @@ namespace winrt::TerminalApp::implementation const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) }; const auto settings{ TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings) }; - _CreateNewTabWithProfileAndSettings(profile, settings, existingConnection); + _CreateNewTabFromPane(_MakePane(newTerminalArgs, false, existingConnection)); const uint32_t tabCount = _tabs.Size(); const bool usedManualProfile = (newTerminalArgs != nullptr) && @@ -244,58 +244,6 @@ namespace winrt::TerminalApp::implementation _InitializeTab(newTabImpl); } - // Method Description: - // - Creates a new tab with the given settings. If the tab bar is not being - // currently displayed, it will be shown. - // Arguments: - // - profile: profile settings for this connection - // - settings: the TerminalSettings object to use to create the TerminalControl with. - // - existingConnection: optionally receives a connection from the outside world instead of attempting to create one - void TerminalPage::_CreateNewTabWithProfileAndSettings(const Profile& profile, const TerminalSettingsCreateResult& settings, TerminalConnection::ITerminalConnection existingConnection) - { - // Initialize the new tab - // Create a connection based on the values in our settings object if we weren't given one. - auto connection = existingConnection ? existingConnection : _CreateConnectionFromSettings(profile, settings.DefaultSettings()); - - // If we had an `existingConnection`, then this is an inbound handoff from somewhere else. - // We need to tell it about our size information so it can match the dimensions of what - // we are about to present. - if (existingConnection) - { - connection.Resize(settings.DefaultSettings().InitialRows(), settings.DefaultSettings().InitialCols()); - } - - TerminalConnection::ITerminalConnection debugConnection{ nullptr }; - if (_settings.GlobalSettings().DebugFeaturesEnabled()) - { - const CoreWindow window = CoreWindow::GetForCurrentThread(); - const auto rAltState = window.GetKeyState(VirtualKey::RightMenu); - const auto lAltState = window.GetKeyState(VirtualKey::LeftMenu); - const bool bothAltsPressed = WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) && - WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down); - if (bothAltsPressed) - { - std::tie(connection, debugConnection) = OpenDebugTapConnection(connection); - } - } - - // Give term control a child of the settings so that any overrides go in the child - // This way, when we do a settings reload we just update the parent and the overrides remain - auto term = _InitControl(settings, connection); - - auto newTabImpl = winrt::make_self(profile, term); - _RegisterTerminalEvents(term); - _InitializeTab(newTabImpl); - - if (debugConnection) // this will only be set if global debugging is on and tap is active - { - auto newControl = _InitControl(settings, debugConnection); - _RegisterTerminalEvents(newControl); - // Split (auto) with the debug tap. - newTabImpl->SplitPane(SplitDirection::Automatic, 0.5f, profile, newControl); - } - } - // Method Description: // - Get the icon of the currently focused terminal control, and set its // tab's icon to that icon. @@ -365,28 +313,14 @@ namespace winrt::TerminalApp::implementation // In the future, it may be preferable to just duplicate the // current control's live settings (which will include changes // made through VT). + _CreateNewTabFromPane(_MakePane(nullptr, true, nullptr)); - if (auto profile = tab.GetFocusedProfile()) + const auto runtimeTabText{ tab.GetTabText() }; + if (!runtimeTabText.empty()) { - // TODO GH#5047 If we cache the NewTerminalArgs, we no longer need to do this. - profile = GetClosestProfileForDuplicationOfProfile(profile); - const auto settingsCreateResult{ TerminalSettings::CreateWithProfile(_settings, profile, *_bindings) }; - const auto workingDirectory = tab.GetActiveTerminalControl().WorkingDirectory(); - const auto validWorkingDirectory = !workingDirectory.empty(); - if (validWorkingDirectory) + if (auto newTab{ _GetFocusedTabImpl() }) { - settingsCreateResult.DefaultSettings().StartingDirectory(workingDirectory); - } - - _CreateNewTabWithProfileAndSettings(profile, settingsCreateResult); - - const auto runtimeTabText{ tab.GetTabText() }; - if (!runtimeTabText.empty()) - { - if (auto newTab{ _GetFocusedTabImpl() }) - { - newTab->SetTabText(runtimeTabText); - } + newTab->SetTabText(runtimeTabText); } } } @@ -402,7 +336,7 @@ namespace winrt::TerminalApp::implementation try { _SetFocusedTab(tab); - _SplitPane(tab, SplitDirection::Automatic, SplitType::Duplicate); + _SplitPane(tab, SplitDirection::Automatic, 0.5f, _MakePane(nullptr, true)); } CATCH_LOG(); } diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 9eacd638b..03d798e8c 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -850,14 +850,7 @@ namespace winrt::TerminalApp::implementation WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) && WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down); - if (altPressed && !debugTap) - { - this->_SplitPane(SplitDirection::Automatic, - SplitType::Manual, - 0.5f, - newTerminalArgs); - } - else if (shiftPressed && !debugTap) + if (shiftPressed && !debugTap) { // Manually fill in the evaluated profile. if (newTerminalArgs.ProfileIndex() != nullptr) @@ -873,7 +866,17 @@ namespace winrt::TerminalApp::implementation } else { - LOG_IF_FAILED(this->_OpenNewTab(newTerminalArgs)); + const auto newPane = _MakePane(newTerminalArgs); + if (altPressed && !debugTap) + { + this->_SplitPane(SplitDirection::Automatic, + 0.5f, + newPane); + } + else + { + _CreateNewTabFromPane(newPane); + } } } @@ -1485,18 +1488,15 @@ namespace winrt::TerminalApp::implementation // Method Description: // - Split the focused pane either horizontally or vertically, and place the - // given TermControl into the newly created pane. + // given pane accordingly in the tree // Arguments: + // - newPane: the pane to add to our tree of panes // - splitDirection: one value from the TerminalApp::SplitDirection 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. + // - splitSize: the size of the split void TerminalPage::_SplitPane(const SplitDirection splitDirection, - const SplitType splitMode, const float splitSize, - const NewTerminalArgs& newTerminalArgs) + std::shared_ptr newPane) { const auto focusedTab{ _GetFocusedTabImpl() }; @@ -1506,104 +1506,52 @@ namespace winrt::TerminalApp::implementation return; } - _SplitPane(*focusedTab, splitDirection, splitMode, splitSize, newTerminalArgs); + _SplitPane(*focusedTab, splitDirection, splitSize, newPane); } // Method Description: // - Split the focused pane of the given tab, either horizontally or vertically, and place the - // given TermControl into the newly created pane. + // given pane accordingly // Arguments: // - tab: The tab that is going to be split. + // - newPane: the pane to add to our tree of panes // - splitDirection: one value from the TerminalApp::SplitDirection 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. + // - splitSize: the size of the split void TerminalPage::_SplitPane(TerminalTab& tab, const SplitDirection splitDirection, - const SplitType splitMode, const float splitSize, - const NewTerminalArgs& newTerminalArgs) + std::shared_ptr newPane) { - try + const float contentWidth = ::base::saturated_cast(_tabContent.ActualWidth()); + const float contentHeight = ::base::saturated_cast(_tabContent.ActualHeight()); + const winrt::Windows::Foundation::Size availableSpace{ contentWidth, contentHeight }; + + auto realSplitType = splitDirection; + if (realSplitType == SplitDirection::Automatic) { - TerminalSettingsCreateResult controlSettings{ nullptr }; - Profile profile{ nullptr }; + realSplitType = tab.PreCalculateAutoSplit(availableSpace); + } - if (splitMode == SplitType::Duplicate) + const auto canSplit = tab.PreCalculateCanSplit(realSplitType, splitSize, availableSpace); + if (!canSplit) + { + return; + } + + _UnZoomIfNeeded(); + tab.SplitPane(realSplitType, splitSize, newPane); + + // After GH#6586, the control will no longer focus itself + // automatically when it's finished being laid out. Manually focus + // the control here instead. + if (_startupState == StartupState::Initialized) + { + if (const auto control = _GetActiveControl()) { - profile = tab.GetFocusedProfile(); - if (profile) - { - // TODO GH#5047 If we cache the NewTerminalArgs, we no longer need to do this. - profile = GetClosestProfileForDuplicationOfProfile(profile); - controlSettings = TerminalSettings::CreateWithProfile(_settings, profile, *_bindings); - const auto workingDirectory = tab.GetActiveTerminalControl().WorkingDirectory(); - const auto validWorkingDirectory = !workingDirectory.empty(); - if (validWorkingDirectory) - { - controlSettings.DefaultSettings().StartingDirectory(workingDirectory); - } - } - // TODO: GH#5047 - In the future, we should get the Profile of - // the focused pane, and use that to build a new instance of the - // settings so we can duplicate this tab/pane. - // - // Currently, if the profile doesn't exist anymore in our - // settings, we'll silently do nothing. - // - // In the future, it will be preferable to just duplicate the - // current control's settings, but we can't do that currently, - // because we won't be able to create a new instance of the - // connection without keeping an instance of the original Profile - // object around. - } - if (!profile) - { - profile = _settings.GetProfileForArgs(newTerminalArgs); - controlSettings = TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings); - } - - const auto controlConnection = _CreateConnectionFromSettings(profile, controlSettings.DefaultSettings()); - - const float contentWidth = ::base::saturated_cast(_tabContent.ActualWidth()); - const float contentHeight = ::base::saturated_cast(_tabContent.ActualHeight()); - const winrt::Windows::Foundation::Size availableSpace{ contentWidth, contentHeight }; - - auto realSplitType = splitDirection; - if (realSplitType == SplitDirection::Automatic) - { - realSplitType = tab.PreCalculateAutoSplit(availableSpace); - } - - const auto canSplit = tab.PreCalculateCanSplit(realSplitType, splitSize, availableSpace); - if (!canSplit) - { - return; - } - - auto newControl = _InitControl(controlSettings, controlConnection); - - // Hookup our event handlers to the new terminal - _RegisterTerminalEvents(newControl); - - _UnZoomIfNeeded(); - - tab.SplitPane(realSplitType, splitSize, profile, newControl); - - // After GH#6586, the control will no longer focus itself - // automatically when it's finished being laid out. Manually focus - // the control here instead. - if (_startupState == StartupState::Initialized) - { - if (const auto control = _GetActiveControl()) - { - control.Focus(FocusState::Programmatic); - } + control.Focus(FocusState::Programmatic); } } - CATCH_LOG(); } // Method Description: @@ -2188,6 +2136,96 @@ namespace winrt::TerminalApp::implementation return term; } + // Method Description: + // - Creates a pane and returns a shared_ptr to it + // - The caller should handle where the pane goes after creation, + // either to split an already existing pane or to create a new tab with it + // Arguments: + // - 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. + // - duplicate: a boolean to indicate whether the pane we create should be + // a duplicate of the currently focused pane + // - existingConnection: optionally receives a connection from the outside + // world instead of attempting to create one + std::shared_ptr TerminalPage::_MakePane(const NewTerminalArgs& newTerminalArgs, const bool duplicate, TerminalConnection::ITerminalConnection existingConnection) + { + TerminalSettingsCreateResult controlSettings{ nullptr }; + Profile profile{ nullptr }; + + if (duplicate) + { + const auto focusedTab{ _GetFocusedTabImpl() }; + if (focusedTab) + { + profile = focusedTab->GetFocusedProfile(); + if (profile) + { + // TODO GH#5047 If we cache the NewTerminalArgs, we no longer need to do this. + profile = GetClosestProfileForDuplicationOfProfile(profile); + controlSettings = TerminalSettings::CreateWithProfile(_settings, profile, *_bindings); + const auto workingDirectory = focusedTab->GetActiveTerminalControl().WorkingDirectory(); + const auto validWorkingDirectory = !workingDirectory.empty(); + if (validWorkingDirectory) + { + controlSettings.DefaultSettings().StartingDirectory(workingDirectory); + } + } + } + } + if (!profile) + { + profile = _settings.GetProfileForArgs(newTerminalArgs); + controlSettings = TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings); + } + + auto connection = existingConnection ? existingConnection : _CreateConnectionFromSettings(profile, controlSettings.DefaultSettings()); + if (existingConnection) + { + connection.Resize(controlSettings.DefaultSettings().InitialRows(), controlSettings.DefaultSettings().InitialCols()); + } + + TerminalConnection::ITerminalConnection debugConnection{ nullptr }; + if (_settings.GlobalSettings().DebugFeaturesEnabled()) + { + const CoreWindow window = CoreWindow::GetForCurrentThread(); + const auto rAltState = window.GetKeyState(VirtualKey::RightMenu); + const auto lAltState = window.GetKeyState(VirtualKey::LeftMenu); + const bool bothAltsPressed = WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) && + WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down); + if (bothAltsPressed) + { + std::tie(connection, debugConnection) = OpenDebugTapConnection(connection); + } + } + + const auto control = _InitControl(controlSettings, connection); + _RegisterTerminalEvents(control); + + auto resultPane = std::make_shared(profile, control); + + if (debugConnection) // this will only be set if global debugging is on and tap is active + { + auto newControl = _InitControl(controlSettings, debugConnection); + _RegisterTerminalEvents(newControl); + // Split (auto) with the debug tap. + auto debugPane = std::make_shared(profile, newControl); + + // Since we're doing this split directly on the pane (instead of going through TerminalTab, + // we need to handle the panes 'active' states + + // Set the pane we're splitting to active (otherwise Split will not do anything) + resultPane->SetActive(); + auto [original, _] = resultPane->Split(SplitDirection::Automatic, 0.5f, debugPane); + + // Set the non-debug pane as active + resultPane->ClearActive(); + original->SetActive(); + } + + return resultPane; + } + // Method Description: // - Hook up keybindings, and refresh the UI of the terminal. // This includes update the settings of all the tabs according @@ -2743,7 +2781,7 @@ namespace winrt::TerminalApp::implementation const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) }; const auto settings{ TerminalSettings::CreateWithProfile(_settings, profile, *_bindings) }; - _CreateNewTabWithProfileAndSettings(profile, settings, connection); + _CreateNewTabFromPane(_MakePane(newTerminalArgs, false, connection)); // Request a summon of this window to the foreground _SummonWindowRequestedHandlers(*this, nullptr); diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 28a156f79..291efb6a7 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -211,7 +211,6 @@ namespace winrt::TerminalApp::implementation void _OpenNewTabDropdown(); HRESULT _OpenNewTab(const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr); void _CreateNewTabFromPane(std::shared_ptr pane); - void _CreateNewTabWithProfileAndSettings(const Microsoft::Terminal::Settings::Model::Profile& profile, const Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr); winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection _CreateConnectionFromSettings(Microsoft::Terminal::Settings::Model::Profile profile, Microsoft::Terminal::Settings::Model::TerminalSettings settings); winrt::fire_and_forget _OpenNewWindow(const bool elevate, const Microsoft::Terminal::Settings::Model::NewTerminalArgs newTerminalArgs); @@ -299,14 +298,12 @@ namespace winrt::TerminalApp::implementation void _Scroll(ScrollDirection scrollDirection, const Windows::Foundation::IReference& rowsToScroll); void _SplitPane(const Microsoft::Terminal::Settings::Model::SplitDirection 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); + const float splitSize, + std::shared_ptr newPane); void _SplitPane(TerminalTab& tab, const Microsoft::Terminal::Settings::Model::SplitDirection 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); + const float splitSize, + std::shared_ptr newPane); void _ResizePane(const Microsoft::Terminal::Settings::Model::ResizeDirection& direction); void _ToggleSplitOrientation(); @@ -353,6 +350,10 @@ namespace winrt::TerminalApp::implementation winrt::Microsoft::Terminal::Control::TermControl _InitControl(const winrt::Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings, const winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection& connection); + std::shared_ptr _MakePane(const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs = nullptr, + const bool duplicate = false, + winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr); + void _RefreshUIForSettingsReload(); void _SetNonClientAreaColors(const Windows::UI::Color& selectedTabColor); diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index eb223e0ab..411693254 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -25,18 +25,6 @@ namespace winrt namespace winrt::TerminalApp::implementation { - TerminalTab::TerminalTab(const Profile& profile, const TermControl& control) - { - _rootPane = std::make_shared(profile, control, true); - - _rootPane->Id(_nextPaneId); - _activePane = _rootPane; - _mruPanes.insert(_mruPanes.begin(), _nextPaneId); - ++_nextPaneId; - - _Setup(); - } - TerminalTab::TerminalTab(std::shared_ptr rootPane) { _rootPane = rootPane; @@ -64,8 +52,9 @@ namespace winrt::TerminalApp::implementation // focus the first one. if (_activePane == nullptr) { - _rootPane->FocusPane(firstId); - _activePane = _rootPane->GetActivePane(); + const auto firstPane = _rootPane->FindPane(firstId); + firstPane->SetActive(); + _activePane = firstPane; } // If the focused pane is a leaf, add it to the MRU panes if (const auto id = _activePane->Id()) @@ -503,39 +492,48 @@ namespace winrt::TerminalApp::implementation // Method Description: // - Split the focused pane in our tree of panes, and place the - // given TermControl into the newly created pane. + // given pane into the tree of panes according to the split // Arguments: - // - splitType: The type of split we want to create. - // - profile: The profile GUID to associate with the newly created pane. - // - control: A TermControl to use in the new pane. + // - splitType: The type of split we want to create + // - splitSize: The size of the split we want to create + // - pane: The new pane to add to the tree of panes; note that this pane + // could itself be a parent pane/the root node of a tree of panes // Return Value: // - void TerminalTab::SplitPane(SplitDirection splitType, const float splitSize, - const Profile& profile, - TermControl& control) + std::shared_ptr pane) { + // Add the new event handlers to the new pane(s) + // and update their ids. + pane->WalkTree([&](auto p) { + _AttachEventHandlersToPane(p); + if (p->_IsLeaf()) + { + p->Id(_nextPaneId); + _AttachEventHandlersToControl(p->Id().value(), p->_control); + _nextPaneId++; + } + return false; + }); // Make sure to take the ID before calling Split() - Split() will clear out the active pane's ID const auto activePaneId = _activePane->Id(); // Depending on which direction will be split, the new pane can be // either the first or second child, but this will always return the // original pane first. - auto [original, newPane] = _activePane->Split(splitType, splitSize, profile, control); + auto [original, newPane] = _activePane->Split(splitType, splitSize, pane); + // The active pane has an id if it is a leaf if (activePaneId) { original->Id(activePaneId.value()); } - newPane->Id(_nextPaneId); - ++_nextPaneId; _activePane = original; // Add a event handlers to the new panes' GotFocus event. When the pane // gains focus, we'll mark it as the new active pane. - _AttachEventHandlersToControl(newPane->Id().value(), control); _AttachEventHandlersToPane(original); - _AttachEventHandlersToPane(newPane); // Immediately update our tracker of the focused pane now. If we're // splitting panes during startup (from a commandline), then it's diff --git a/src/cascadia/TerminalApp/TerminalTab.h b/src/cascadia/TerminalApp/TerminalTab.h index 4c071c0b0..4b5fe9ef4 100644 --- a/src/cascadia/TerminalApp/TerminalTab.h +++ b/src/cascadia/TerminalApp/TerminalTab.h @@ -21,7 +21,6 @@ namespace winrt::TerminalApp::implementation struct TerminalTab : TerminalTabT { public: - TerminalTab(const winrt::Microsoft::Terminal::Settings::Model::Profile& profile, const winrt::Microsoft::Terminal::Control::TermControl& control); TerminalTab(std::shared_ptr rootPane); // Called after construction to perform the necessary setup, which relies on weak_ptr @@ -40,8 +39,7 @@ namespace winrt::TerminalApp::implementation void SplitPane(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType, const float splitSize, - const winrt::Microsoft::Terminal::Settings::Model::Profile& profile, - winrt::Microsoft::Terminal::Control::TermControl& control); + std::shared_ptr newPane); void ToggleSplitOrientation(); winrt::fire_and_forget UpdateIcon(const winrt::hstring iconPath); From 74d21afacf319cf420480bf5fbb338eb0bb573be Mon Sep 17 00:00:00 2001 From: Kai Date: Thu, 4 Nov 2021 23:45:19 +0100 Subject: [PATCH 16/23] README.md: HTTP => HTTPS (#11671) ## Summary of the Pull Request Checked the link, skipping the redirect HTTP => HTTPS this way 0:-) This one http://azuredevopspodcast.clear-measure.com/kayla-cinnamon-and-rich-turner-on-devops-on-the-windows-terminal-team-episode-54 is still only available via HTTP, sadly. ## References is being redirected to ## PR Checklist * N/A Closes #xxx * [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * N/A Tests added/passed * N/A Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx * N/A Schema updated. * [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx ## ~~Detailed Description of the Pull Request / Additional comments~~ ## Validation Steps Performed Opened the link. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ca416b82c..18523b63b 100644 --- a/README.md +++ b/README.md @@ -214,7 +214,7 @@ resources useful and interesting: * Windows Terminal Launch: [Build 2019 Session](https://www.youtube.com/watch?v=KMudkRcwjCw) * Run As Radio: [Show 645 - Windows Terminal with Richard - Turner](http://www.runasradio.com/Shows/Show/645) + Turner](https://www.runasradio.com/Shows/Show/645) * Azure Devops Podcast: [Episode 54 - Kayla Cinnamon and Rich Turner on DevOps on the Windows Terminal](http://azuredevopspodcast.clear-measure.com/kayla-cinnamon-and-rich-turner-on-devops-on-the-windows-terminal-team-episode-54) From 7aae2e9100c392b0c98b1120152bcf9709fcf9f6 Mon Sep 17 00:00:00 2001 From: Sergey <45919738+serd2011@users.noreply.github.com> Date: Fri, 5 Nov 2021 02:46:57 +0300 Subject: [PATCH 17/23] Fix missing window border when use "win+arrow down" in fullscreen mode in Terminal (#11653) Window sends an event that requests exit from fullscreen then SC_RESTORE messages is sent and it is in fullscreen mode. Closes #10607 ## Validation Steps Performed Border and tabbar now appear after exiting fullscreen via "win+arrow down". --- src/cascadia/TerminalApp/AppLogic.cpp | 5 +++++ src/cascadia/TerminalApp/AppLogic.h | 1 + src/cascadia/TerminalApp/AppLogic.idl | 1 + src/cascadia/TerminalApp/TerminalPage.cpp | 15 ++++++++++++--- src/cascadia/TerminalApp/TerminalPage.h | 1 + src/cascadia/WindowsTerminal/AppHost.cpp | 1 + src/cascadia/WindowsTerminal/IslandWindow.cpp | 9 +++++++++ src/cascadia/WindowsTerminal/IslandWindow.h | 1 + 8 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index c2b24d029..7e5949577 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -1565,6 +1565,11 @@ namespace winrt::TerminalApp::implementation return _root->IsQuakeWindow(); } + void AppLogic::RequestExitFullscreen() + { + _root->SetFullscreen(false); + } + bool AppLogic::GetMinimizeToNotificationArea() { if constexpr (Feature_NotificationIcon::IsEnabled()) diff --git a/src/cascadia/TerminalApp/AppLogic.h b/src/cascadia/TerminalApp/AppLogic.h index 9301a6698..7c1681db1 100644 --- a/src/cascadia/TerminalApp/AppLogic.h +++ b/src/cascadia/TerminalApp/AppLogic.h @@ -91,6 +91,7 @@ namespace winrt::TerminalApp::implementation void SetPersistedLayoutIdx(const uint32_t idx); void SetNumberOfOpenWindows(const uint64_t num); bool IsQuakeWindow() const noexcept; + void RequestExitFullscreen(); Windows::Foundation::Size GetLaunchDimensions(uint32_t dpi); bool CenterOnLaunch(); diff --git a/src/cascadia/TerminalApp/AppLogic.idl b/src/cascadia/TerminalApp/AppLogic.idl index e6aa40788..973e8aa1a 100644 --- a/src/cascadia/TerminalApp/AppLogic.idl +++ b/src/cascadia/TerminalApp/AppLogic.idl @@ -74,6 +74,7 @@ namespace TerminalApp void SetPersistedLayoutIdx(UInt32 idx); void SetNumberOfOpenWindows(UInt64 num); void RenameFailed(); + void RequestExitFullscreen(); Boolean IsQuakeWindow(); Windows.Foundation.Size GetLaunchDimensions(UInt32 dpi); diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 03d798e8c..bd9787f04 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -2535,9 +2535,7 @@ namespace winrt::TerminalApp::implementation // - void TerminalPage::ToggleFullscreen() { - _isFullscreen = !_isFullscreen; - _UpdateTabView(); - _FullscreenChangedHandlers(*this, nullptr); + SetFullscreen(!_isFullscreen); } // Method Description: @@ -2754,6 +2752,17 @@ namespace winrt::TerminalApp::implementation return _isAlwaysOnTop; } + void TerminalPage::SetFullscreen(bool newFullscreen) + { + if (_isFullscreen == newFullscreen) + { + return; + } + _isFullscreen = newFullscreen; + _UpdateTabView(); + _FullscreenChangedHandlers(*this, nullptr); + } + HRESULT TerminalPage::_OnNewConnection(const ConptyConnection& connection) { // We need to be on the UI thread in order for _OpenNewTab to run successfully. diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 291efb6a7..cf9477d2e 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -83,6 +83,7 @@ namespace winrt::TerminalApp::implementation bool FocusMode() const; bool Fullscreen() const; bool AlwaysOnTop() const; + void SetFullscreen(bool); void SetStartupActions(std::vector& actions); diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index 849c4e804..544c33e55 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -84,6 +84,7 @@ AppHost::AppHost() noexcept : _window->WindowMoved({ this, &AppHost::_WindowMoved }); _window->HotkeyPressed({ this, &AppHost::_GlobalHotkeyPressed }); _window->SetAlwaysOnTop(_logic.GetInitialAlwaysOnTop()); + _window->ShouldExitFullscreen({ &_logic, &winrt::TerminalApp::AppLogic::RequestExitFullscreen }); _window->MakeWindow(); _GetWindowLayoutRequestedToken = _windowManager.GetWindowLayoutRequested([this](auto&&, const winrt::Microsoft::Terminal::Remoting::GetWindowLayoutArgs& args) { diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index a28ccaa21..a9c2dbb4b 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -606,6 +606,15 @@ long IslandWindow::_calculateTotalSize(const bool isWidth, const long clientSize } break; } + case WM_SYSCOMMAND: + { + if (wparam == SC_RESTORE && _fullscreen) + { + _ShouldExitFullscreenHandlers(); + return 0; + } + break; + } case WM_MENUCOMMAND: { _NotifyNotificationIconMenuItemSelectedHandlers((HMENU)lparam, (UINT)wparam); diff --git a/src/cascadia/WindowsTerminal/IslandWindow.h b/src/cascadia/WindowsTerminal/IslandWindow.h index 0ac7b1e0b..15d652551 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.h +++ b/src/cascadia/WindowsTerminal/IslandWindow.h @@ -73,6 +73,7 @@ public: WINRT_CALLBACK(NotifyShowNotificationIconContextMenu, winrt::delegate); WINRT_CALLBACK(NotifyNotificationIconMenuItemSelected, winrt::delegate); WINRT_CALLBACK(NotifyReAddNotificationIcon, winrt::delegate); + WINRT_CALLBACK(ShouldExitFullscreen, winrt::delegate); WINRT_CALLBACK(WindowMoved, winrt::delegate); From 55dbda02a5a84400977c42ac039403b6b5d7c430 Mon Sep 17 00:00:00 2001 From: Sergey <45919738+serd2011@users.noreply.github.com> Date: Fri, 5 Nov 2021 22:26:03 +0300 Subject: [PATCH 18/23] fix build error at 74d21af (#11691) #11404 and #11653 both added WM_SYSCOMMAND which prevents build. This fixes it. --- src/cascadia/WindowsTerminal/IslandWindow.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index a9c2dbb4b..8ea325a42 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -606,15 +606,6 @@ long IslandWindow::_calculateTotalSize(const bool isWidth, const long clientSize } break; } - case WM_SYSCOMMAND: - { - if (wparam == SC_RESTORE && _fullscreen) - { - _ShouldExitFullscreenHandlers(); - return 0; - } - break; - } case WM_MENUCOMMAND: { _NotifyNotificationIconMenuItemSelectedHandlers((HMENU)lparam, (UINT)wparam); @@ -622,6 +613,11 @@ long IslandWindow::_calculateTotalSize(const bool isWidth, const long clientSize } case WM_SYSCOMMAND: { + if (wparam == SC_RESTORE && _fullscreen) + { + _ShouldExitFullscreenHandlers(); + return 0; + } auto search = _systemMenuItems.find(LOWORD(wparam)); if (search != _systemMenuItems.end()) { From a74c37bbcd699ce2cd90bb5d81412663a6236fcc Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 5 Nov 2021 14:26:59 -0500 Subject: [PATCH 19/23] Don't crash if we fail to BeginBufferedPaint (#11674) Fixes MSFT:34673647, at least I'm pretty sure. That's only ever hit a few times externally, and internally it's hitting a lot on 1.9.1942 builds, which doesn't really make any sense. --- src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp index 60dd263a2..7eee80e77 100644 --- a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp @@ -843,7 +843,11 @@ void NonClientIslandWindow::_UpdateFrameMargins() const noexcept HPAINTBUFFER buf = BeginBufferedPaint(hdc.get(), &rcRest, BPBF_TOPDOWNDIB, ¶ms, &opaqueDc); if (!buf || !opaqueDc) { - winrt::throw_last_error(); + // MSFT:34673647 - BeginBufferedPaint can fail, but it probably + // shouldn't bring the whole Terminal down with it. So don't + // throw_last_error here. + LOG_LAST_ERROR(); + return 0; } ::FillRect(opaqueDc, &rcRest, _backgroundBrush.get()); From f9b97c4880f63af8d034234f4d23c24b8704f8a7 Mon Sep 17 00:00:00 2001 From: Ikko Ashimine Date: Tue, 9 Nov 2021 05:18:50 +0900 Subject: [PATCH 20/23] doc: Fix typo in #885 - Terminal Settings Model.md (#11657) Fixed typo: ocurred -> occurred * [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA --- .../#885 - Terminal Settings Model.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/specs/#885 - Terminal Settings Model/#885 - Terminal Settings Model.md b/doc/specs/#885 - Terminal Settings Model/#885 - Terminal Settings Model.md index 37b1fe4cb..c7dbefeab 100644 --- a/doc/specs/#885 - Terminal Settings Model/#885 - Terminal Settings Model.md +++ b/doc/specs/#885 - Terminal Settings Model/#885 - Terminal Settings Model.md @@ -268,7 +268,7 @@ Today, if the deserialization of `CascadiaSettings` encounters any errors, an ex To get around this issue, when `CascadiaSettings` encounters a serialization error, it must internally record any pertinent information for that error, and return the simple `CascadiaSettings` as if nothing happened. The consumer must then call `CascadiaSettings::GetErrors()` and `CascadiaSettings::GetWarnings()` to properly - understand whether an error ocurred and how to present that to the user. + understand whether an error occurred and how to present that to the user. #### TerminalApp: Loading and Reloading Changes From a89b66f770ea877e7f9d00167d6b11b7f5e5866b Mon Sep 17 00:00:00 2001 From: Dustin Howett Date: Tue, 9 Nov 2021 19:21:35 +0000 Subject: [PATCH 21/23] Merged PR 6598109: [Git2Git] Pull Request 6508625: Update TAEF to vPack 10.63 (latest) A change required significant changes in TAEF published headers. This PR consumes those changes. Related work items: #20301352 --- src/host/ft_host/API_AliasTests.cpp | 2 +- src/host/ft_host/API_BufferTests.cpp | 2 +- src/host/ft_host/API_DimensionsTests.cpp | 2 +- src/host/ft_host/API_FileTests.cpp | 2 +- src/host/ft_host/API_FontTests.cpp | 2 +- src/host/ft_host/API_InputTests.cpp | 2 +- src/host/ft_host/API_OutputTests.cpp | 2 +- src/host/ft_host/API_PolicyTests.cpp | 2 +- src/host/ft_host/API_TitleTests.cpp | 2 +- src/host/ft_host/CJK_DbcsTests.cpp | 2 +- src/host/ft_host/CanaryTests.cpp | 2 +- src/host/ft_host/Common.cpp | 2 +- src/host/ft_host/Message_KeyPressTests.cpp | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/host/ft_host/API_AliasTests.cpp b/src/host/ft_host/API_AliasTests.cpp index ec274528a..d7a9d9ebd 100644 --- a/src/host/ft_host/API_AliasTests.cpp +++ b/src/host/ft_host/API_AliasTests.cpp @@ -30,7 +30,7 @@ // GetConsoleAlias using namespace WEX::TestExecution; using namespace WEX::Common; -using WEX::Logging::Log; +using namespace WEX::Logging; class AliasTests { diff --git a/src/host/ft_host/API_BufferTests.cpp b/src/host/ft_host/API_BufferTests.cpp index fc1a70b51..ff5e662a2 100644 --- a/src/host/ft_host/API_BufferTests.cpp +++ b/src/host/ft_host/API_BufferTests.cpp @@ -5,7 +5,7 @@ extern "C" IMAGE_DOS_HEADER __ImageBase; -using WEX::Logging::Log; +using namespace WEX::Logging; using namespace WEX::Common; // This class is intended to test boundary conditions for: diff --git a/src/host/ft_host/API_DimensionsTests.cpp b/src/host/ft_host/API_DimensionsTests.cpp index c41415c78..f8efba4d9 100644 --- a/src/host/ft_host/API_DimensionsTests.cpp +++ b/src/host/ft_host/API_DimensionsTests.cpp @@ -4,7 +4,7 @@ #include "precomp.h" using namespace WEX::TestExecution; -using WEX::Logging::Log; +using namespace WEX::Logging; using namespace WEX::Common; // This class is intended to test: diff --git a/src/host/ft_host/API_FileTests.cpp b/src/host/ft_host/API_FileTests.cpp index 1aaa790bd..ed0ed5afc 100644 --- a/src/host/ft_host/API_FileTests.cpp +++ b/src/host/ft_host/API_FileTests.cpp @@ -7,7 +7,7 @@ #include -using WEX::Logging::Log; +using namespace WEX::Logging; using WEX::TestExecution::TestData; using namespace WEX::Common; diff --git a/src/host/ft_host/API_FontTests.cpp b/src/host/ft_host/API_FontTests.cpp index 6222769a9..1c6f10f1d 100644 --- a/src/host/ft_host/API_FontTests.cpp +++ b/src/host/ft_host/API_FontTests.cpp @@ -5,7 +5,7 @@ using namespace WEX::TestExecution; using namespace WEX::Common; -using WEX::Logging::Log; +using namespace WEX::Logging; static const COORD c_coordZero = { 0, 0 }; diff --git a/src/host/ft_host/API_InputTests.cpp b/src/host/ft_host/API_InputTests.cpp index 6eed16bbc..c789de578 100644 --- a/src/host/ft_host/API_InputTests.cpp +++ b/src/host/ft_host/API_InputTests.cpp @@ -11,7 +11,7 @@ #define NUMBER_OF_SCENARIO_INPUTS 10 #define READ_BATCH 3 -using WEX::Logging::Log; +using namespace WEX::Logging; using namespace WEX::Common; // This class is intended to test: diff --git a/src/host/ft_host/API_OutputTests.cpp b/src/host/ft_host/API_OutputTests.cpp index e64517886..2453b71a4 100644 --- a/src/host/ft_host/API_OutputTests.cpp +++ b/src/host/ft_host/API_OutputTests.cpp @@ -11,7 +11,7 @@ using namespace Microsoft::Console::Types; using namespace WEX::TestExecution; -using WEX::Logging::Log; +using namespace WEX::Logging; using namespace WEX::Common; class OutputTests diff --git a/src/host/ft_host/API_PolicyTests.cpp b/src/host/ft_host/API_PolicyTests.cpp index 89f2bef1c..500ae1471 100644 --- a/src/host/ft_host/API_PolicyTests.cpp +++ b/src/host/ft_host/API_PolicyTests.cpp @@ -3,7 +3,7 @@ #include "precomp.h" -using WEX::Logging::Log; +using namespace WEX::Logging; // This class is intended to test restrictions placed on APIs from within a UWP application context class PolicyTests diff --git a/src/host/ft_host/API_TitleTests.cpp b/src/host/ft_host/API_TitleTests.cpp index b78f0e162..880b667ec 100644 --- a/src/host/ft_host/API_TitleTests.cpp +++ b/src/host/ft_host/API_TitleTests.cpp @@ -3,7 +3,7 @@ #include "precomp.h" -using WEX::Logging::Log; +using namespace WEX::Logging; using namespace WEX::Common; // This class is intended to test: diff --git a/src/host/ft_host/CJK_DbcsTests.cpp b/src/host/ft_host/CJK_DbcsTests.cpp index 4b8612004..499549944 100644 --- a/src/host/ft_host/CJK_DbcsTests.cpp +++ b/src/host/ft_host/CJK_DbcsTests.cpp @@ -10,7 +10,7 @@ #define ENGLISH_US_CP 437u #define JAPANESE_CP 932u -using WEX::Logging::Log; +using namespace WEX::Logging; using WEX::TestExecution::TestData; using namespace WEX::Common; diff --git a/src/host/ft_host/CanaryTests.cpp b/src/host/ft_host/CanaryTests.cpp index d174732c8..1c51fa49f 100644 --- a/src/host/ft_host/CanaryTests.cpp +++ b/src/host/ft_host/CanaryTests.cpp @@ -3,7 +3,7 @@ #include "precomp.h" -using WEX::Logging::Log; +using namespace WEX::Logging; using namespace WEX::Common; // This class is intended to provide a canary (simple launch test) diff --git a/src/host/ft_host/Common.cpp b/src/host/ft_host/Common.cpp index df34f101a..1250c5db2 100644 --- a/src/host/ft_host/Common.cpp +++ b/src/host/ft_host/Common.cpp @@ -3,7 +3,7 @@ #include "precomp.h" -using WEX::Logging::Log; +using namespace WEX::Logging; using namespace WEX::Common; HANDLE Common::_hConsole = INVALID_HANDLE_VALUE; diff --git a/src/host/ft_host/Message_KeyPressTests.cpp b/src/host/ft_host/Message_KeyPressTests.cpp index 3b2bb2174..2be78dee1 100644 --- a/src/host/ft_host/Message_KeyPressTests.cpp +++ b/src/host/ft_host/Message_KeyPressTests.cpp @@ -25,7 +25,7 @@ using namespace WEX::TestExecution; using namespace WEX::Common; -using WEX::Logging::Log; +using namespace WEX::Logging; class KeyPressTests { From 92643c1d34876cf0dd71b0eda89f1d1ea2bc67f8 Mon Sep 17 00:00:00 2001 From: Dustin Howett Date: Tue, 9 Nov 2021 23:16:26 +0000 Subject: [PATCH 22/23] Merged PR 6654362: [Git2Git] OS build fixes for f9b97c488 Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev 063b86ac10af16cade5c0754adcbf27e7e9ae266 Related work items: MSFT-34534216, MSFT-36986009, MSFT-36986203 --- src/project.inc | 1 + src/terminal/parser/ut_parser/Base64Test.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/project.inc b/src/project.inc index 4a0c674ab..38b99674e 100644 --- a/src/project.inc +++ b/src/project.inc @@ -49,6 +49,7 @@ INCLUDES= \ $(CONSOLE_SRC_PATH)\..\oss\fmt\include; \ $(CONSOLE_SRC_PATH)\..\oss\interval_tree; \ $(CONSOLE_SRC_PATH)\..\oss\boost\boost_1_73_0; \ + $(CONSOLE_SRC_PATH)\..\oss\pcg\include; \ $(MINWIN_INTERNAL_PRIV_SDK_INC_PATH_L); \ $(MINWIN_RESTRICTED_PRIV_SDK_INC_PATH_L); \ $(MINCORE_INTERNAL_PRIV_SDK_INC_PATH_L); \ diff --git a/src/terminal/parser/ut_parser/Base64Test.cpp b/src/terminal/parser/ut_parser/Base64Test.cpp index 5374a303a..137d0a7f4 100644 --- a/src/terminal/parser/ut_parser/Base64Test.cpp +++ b/src/terminal/parser/ut_parser/Base64Test.cpp @@ -5,6 +5,7 @@ #include "WexTestClass.h" #include +#include #include "base64.hpp" From 7db7ba1ac9c1ee65f7b389f1893f985f10e68c17 Mon Sep 17 00:00:00 2001 From: Dustin Howett Date: Tue, 9 Nov 2021 17:22:55 -0600 Subject: [PATCH 23/23] ci: fix spelling for inbox merge --- .github/actions/spelling/allow/apis.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/actions/spelling/allow/apis.txt b/.github/actions/spelling/allow/apis.txt index b17163a05..45f4e02f1 100644 --- a/.github/actions/spelling/allow/apis.txt +++ b/.github/actions/spelling/allow/apis.txt @@ -17,6 +17,7 @@ COLORPROPERTY colspan COMDLG comparand +commandlinetoargv cstdint CXICON CYICON @@ -161,6 +162,7 @@ toupper TTask TVal UChar +ULARGE UPDATEINIFILE userenv wcsstr