Compare commits

..

1 Commits

Author SHA1 Message Date
Carlos Zamora
540154066d [broken] Add screen reader confirmation announcements to SUI 2024-09-11 14:51:28 -07:00
127 changed files with 5540 additions and 1389 deletions

View File

@@ -864,7 +864,6 @@ INLINEPREFIX
inproc
Inputkeyinfo
Inputreadhandledata
INPUTSCOPE
INSERTMODE
INTERACTIVITYBASE
INTERCEPTCOPYPASTE
@@ -1291,7 +1290,6 @@ parms
PATCOPY
pathcch
PATTERNID
pbstr
pcb
pcch
PCCHAR
@@ -1377,11 +1375,9 @@ POSTCHARBREAKS
POSX
POSXSCROLL
POSYSCROLL
ppbstr
PPEB
ppf
ppidl
pprg
PPROC
ppropvar
ppsi
@@ -1697,7 +1693,6 @@ srcsrv
SRCSRVTRG
srctool
srect
SRGS
srvinit
srvpipe
ssa
@@ -1844,6 +1839,7 @@ triaging
TRIMZEROHEADINGS
trx
tsa
tsattrs
tsgr
tsm
TStr
@@ -1971,8 +1967,10 @@ vswhere
vtapp
VTE
VTID
vtio
vtmode
vtpipeterm
vtpt
VTRGB
VTRGBTo
vtseq

View File

@@ -1,6 +1,6 @@
{
"instanceUrl": "https://microsoft.visualstudio.com",
"projectName": "OS",
"areaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\SHINE\\Terminal",
"areaPath": "OS\\Windows Client and Services\\ADEPT\\E4D-Engineered for Developers\\SHINE\\Terminal",
"notificationAliases": ["condev@microsoft.com", "duhowett@microsoft.com"]
}

View File

@@ -2340,7 +2340,7 @@
"description": "When set to `true`, the terminal window will auto-center itself on the display it opens on. The terminal will use the \"initialPosition\" to determine which display to open on.",
"type": "boolean"
},
"warning.inputService": {
"inputServiceWarning": {
"default": true,
"description": "Warning if 'Touch Keyboard and Handwriting Panel Service' is disabled.",
"type": "boolean"
@@ -2390,12 +2390,12 @@
"description": "When set to `true`, visual animations will be disabled across the application.",
"type": "boolean"
},
"warning.largePaste": {
"largePasteWarning": {
"default": true,
"description": "When set to true, trying to paste text with more than 5 KiB of characters will display a warning asking you whether to continue or not with the paste.",
"type": "boolean"
},
"warning.multiLinePaste": {
"multiLinePasteWarning": {
"default": true,
"description": "When set to true, trying to paste text with a \"new line\" character will display a warning asking you whether to continue or not with the paste.",
"type": "boolean"
@@ -2593,7 +2593,7 @@
"description": "Determines the delimiters used in a double click selection.",
"type": "string"
},
"warning.confirmCloseAllTabs": {
"confirmCloseAllTabs": {
"default": true,
"description": "When set to \"true\" closing a window with multiple tabs open will require confirmation. When set to \"false\", the confirmation dialog will not appear.",
"type": "boolean"

View File

@@ -175,7 +175,7 @@ void Cursor::_RedrawCursor() noexcept
// - <none>
void Cursor::_RedrawCursorAlways() noexcept
{
_parentBuffer.TriggerRedraw();
_parentBuffer.NotifyPaintFrame();
}
void Cursor::SetPosition(const til::point cPosition) noexcept

View File

@@ -10,18 +10,35 @@ using namespace Microsoft::Console::Types;
bool Search::IsStale(const Microsoft::Console::Render::IRenderData& renderData, const std::wstring_view& needle, SearchFlag flags) const noexcept
{
UNREFERENCED_PARAMETER(renderData);
UNREFERENCED_PARAMETER(needle);
UNREFERENCED_PARAMETER(flags);
return false;
return _renderData != &renderData ||
_needle != needle ||
_flags != flags ||
_lastMutationId != renderData.GetTextBuffer().GetLastMutationId();
}
void Search::Reset(Microsoft::Console::Render::IRenderData& renderData, const std::wstring_view& needle, SearchFlag flags, bool reverse)
bool Search::Reset(Microsoft::Console::Render::IRenderData& renderData, const std::wstring_view& needle, SearchFlag flags, bool reverse)
{
UNREFERENCED_PARAMETER(renderData);
UNREFERENCED_PARAMETER(needle);
UNREFERENCED_PARAMETER(flags);
UNREFERENCED_PARAMETER(reverse);
const auto& textBuffer = renderData.GetTextBuffer();
_renderData = &renderData;
_needle = needle;
_flags = flags;
_lastMutationId = textBuffer.GetLastMutationId();
auto result = textBuffer.SearchText(needle, _flags);
_ok = result.has_value();
_results = std::move(result).value_or(std::vector<til::point_span>{});
_index = reverse ? gsl::narrow_cast<ptrdiff_t>(_results.size()) - 1 : 0;
_step = reverse ? -1 : 1;
return true;
}
void Search::MoveToCurrentSelection()
{
if (_renderData->IsSelectionActive())
{
MoveToPoint(_renderData->GetTextBuffer().ScreenToBufferPosition(_renderData->GetSelectionAnchor()));
}
}
void Search::MoveToPoint(const til::point anchor) noexcept
@@ -100,6 +117,18 @@ const til::point_span* Search::GetCurrent() const noexcept
bool Search::SelectCurrent() const
{
if (const auto s = GetCurrent())
{
// Convert buffer selection offsets into the equivalent screen coordinates
// required by SelectNewRegion, taking line renditions into account.
const auto& textBuffer = _renderData->GetTextBuffer();
const auto selStart = textBuffer.BufferToScreenPosition(s->start);
const auto selEnd = textBuffer.BufferToScreenPosition(s->end);
_renderData->SelectNewRegion(selStart, selEnd);
return true;
}
_renderData->ClearSelection();
return false;
}

View File

@@ -36,8 +36,9 @@ public:
Search() = default;
bool IsStale(const Microsoft::Console::Render::IRenderData& renderData, const std::wstring_view& needle, SearchFlag flags) const noexcept;
void Reset(Microsoft::Console::Render::IRenderData& renderData, const std::wstring_view& needle, SearchFlag flags, bool reverse);
bool Reset(Microsoft::Console::Render::IRenderData& renderData, const std::wstring_view& needle, SearchFlag flags, bool reverse);
void MoveToCurrentSelection();
void MoveToPoint(til::point anchor) noexcept;
void MovePastPoint(til::point anchor) noexcept;
void FindNext(bool reverse) noexcept;

View File

@@ -451,9 +451,14 @@ size_t TextBuffer::FitTextIntoColumns(const std::wstring_view& chars, til::Coord
cwd.GraphemeNext(state, chars);
col += state.width;
// If we ran out of columns, we need to always return `columnLimit` and not `cols`,
// because if we tried inserting a wide glyph into just 1 remaining column it will
// fail to fit, but that remaining column still has been used up. When the caller sees
// `columns == columnLimit` they will line-wrap and continue inserting into the next row.
if (col > columnLimit)
{
break;
columns = columnLimit;
return dist;
}
dist += state.len;
@@ -461,7 +466,7 @@ size_t TextBuffer::FitTextIntoColumns(const std::wstring_view& chars, til::Coord
// But if we simply ran out of text we just need to return the actual number of columns.
columns = col;
return dist;
return chars.size();
}
// Pretend as if `position` is a regular cursor in the TextBuffer.
@@ -530,7 +535,7 @@ void TextBuffer::Replace(til::CoordType row, const TextAttribute& attributes, Ro
r.ReplaceText(state);
r.ReplaceAttributes(state.columnBegin, state.columnEnd, attributes);
ImageSlice::EraseCells(r, state.columnBegin, state.columnEnd);
TriggerRedraw();
TriggerRedraw(Viewport::FromExclusive({ state.columnBeginDirty, row, state.columnEndDirty, row + 1 }));
}
void TextBuffer::Insert(til::CoordType row, const TextAttribute& attributes, RowWriteState& state)
@@ -564,7 +569,7 @@ void TextBuffer::Insert(til::CoordType row, const TextAttribute& attributes, Row
// Image content at the insert position needs to be erased.
ImageSlice::EraseCells(r, state.columnBegin, restoreState.columnBegin);
TriggerRedraw();
TriggerRedraw(Viewport::FromExclusive({ state.columnBeginDirty, row, restoreState.columnEndDirty, row + 1 }));
}
// Fills an area of the buffer with a given fill character(s) and attributes.
@@ -618,7 +623,7 @@ void TextBuffer::FillRect(const til::rect& rect, const std::wstring_view& fill,
r.CopyTextFrom(state);
r.ReplaceAttributes(rect.left, rect.right, attributes);
ImageSlice::EraseCells(r, rect.left, rect.right);
TriggerRedraw();
TriggerRedraw(Viewport::FromExclusive({ state.columnBeginDirty, y, state.columnEndDirty, y + 1 }));
}
}
}
@@ -699,7 +704,10 @@ OutputCellIterator TextBuffer::WriteLine(const OutputCellIterator givenIt,
auto& row = GetMutableRowByOffset(target.y);
const auto newIt = row.WriteCells(givenIt, target.x, wrap, limitRight);
TriggerRedraw();
// Take the cell distance written and notify that it needs to be repainted.
const auto written = newIt.GetCellDistance(givenIt);
const auto paint = Viewport::FromDimensions(target, { written, 1 });
TriggerRedraw(paint);
return newIt;
}
@@ -916,7 +924,7 @@ void TextBuffer::SetCurrentLineRendition(const LineRendition lineRendition, cons
// We also need to make sure the cursor is clamped within the new width.
GetCursor().SetPosition(ClampPositionWithinLine(cursorPosition));
}
TriggerRedraw();
TriggerRedraw(Viewport::FromDimensions({ 0, rowIndex }, { GetSize().Width(), 1 }));
}
}
@@ -1067,17 +1075,52 @@ Microsoft::Console::Render::Renderer* TextBuffer::GetRenderer() noexcept
return _renderer;
}
void TextBuffer::TriggerRedraw() noexcept
void TextBuffer::NotifyPaintFrame() noexcept
{
if (_isActiveBuffer && _renderer)
{
_renderer->TriggerRedraw();
_renderer->NotifyPaintFrame();
}
}
void TextBuffer::TriggerRedraw(const Viewport& viewport)
{
if (_isActiveBuffer && _renderer)
{
_renderer->TriggerRedraw(viewport);
}
}
void TextBuffer::TriggerRedrawAll()
{
if (_isActiveBuffer && _renderer)
{
_renderer->TriggerRedrawAll();
}
}
void TextBuffer::TriggerScroll()
{
if (_isActiveBuffer && _renderer)
{
_renderer->TriggerScroll();
}
}
void TextBuffer::TriggerScroll(const til::point delta)
{
if (_isActiveBuffer && _renderer)
{
_renderer->TriggerScroll(&delta);
}
}
void TextBuffer::TriggerNewTextNotification(const std::wstring_view newText)
{
UNREFERENCED_PARAMETER(newText);
if (_isActiveBuffer && _renderer)
{
_renderer->TriggerNewTextNotification(newText);
}
}
// Method Description:

View File

@@ -68,7 +68,6 @@ namespace Microsoft::Console::Render
class TextBuffer final
{
public:
TextBuffer() = default;
TextBuffer(const til::size screenBufferSize,
const TextAttribute defaultAttributes,
const UINT cursorSize,
@@ -165,7 +164,11 @@ public:
Microsoft::Console::Render::Renderer* GetRenderer() noexcept;
void TriggerRedraw() noexcept;
void NotifyPaintFrame() noexcept;
void TriggerRedraw(const Microsoft::Console::Types::Viewport& viewport);
void TriggerRedrawAll();
void TriggerScroll();
void TriggerScroll(const til::point delta);
void TriggerNewTextNotification(const std::wstring_view newText);
til::point GetWordStart(const til::point target, const std::wstring_view wordDelimiters, bool accessibilityMode = false, std::optional<til::point> limitOptional = std::nullopt) const;
@@ -398,7 +401,7 @@ private:
til::CoordType _firstRow = 0; // indexes top row (not necessarily 0)
uint64_t _lastMutationId = 0;
Cursor _cursor{ 25, *this };
Cursor _cursor;
bool _isActiveBuffer = false;
#ifdef UNIT_TESTING

View File

@@ -154,7 +154,7 @@
<comment>{Locked=qps-ploc,qps-ploca,qps-plocm}</comment>
</data>
<data name="AppDescription" xml:space="preserve">
<value>Nový Terminál Windows</value>
<value>Nová Terminál Windows</value>
</data>
<data name="AppDescriptionPre" xml:space="preserve">
<value>Terminál Windows s náhledem připravovaných funkcí</value>
@@ -164,7 +164,7 @@
<comment>This is a menu item that will be displayed in the Windows File Explorer that launches the Canary version of Windows Terminal. Please mark one of the characters to be an accelerator key.</comment>
</data>
<data name="ShellExtension_OpenInTerminalMenuItem_Preview" xml:space="preserve">
<value>Otevřít &amp;náhled Terminálu</value>
<value>Otevřít náhled &amp;aplikace Terminal</value>
<comment>This is a menu item that will be displayed in the Windows File Explorer that launches the Preview version of Windows Terminal. Please mark one of the characters to be an accelerator key.</comment>
</data>
<data name="ShellExtension_OpenInTerminalMenuItem" xml:space="preserve">

View File

@@ -2956,13 +2956,13 @@ bool Pane::ContainsReadOnly() const
// - <none>
void Pane::CollectTaskbarStates(std::vector<winrt::TerminalApp::TaskbarState>& states)
{
if (_content)
if (_IsLeaf())
{
auto tbState{ winrt::make<winrt::TerminalApp::implementation::TaskbarState>(_content.TaskbarState(),
_content.TaskbarProgress()) };
states.push_back(tbState);
}
else if (_firstChild && _secondChild)
else
{
_firstChild->CollectTaskbarStates(states);
_secondChild->CollectTaskbarStates(states);

View File

@@ -154,7 +154,7 @@
<comment>{Locked=qps-ploc,qps-ploca,qps-plocm}</comment>
</data>
<data name="AppDescription" xml:space="preserve">
<value>Nový Terminál Windows</value>
<value>Nová Terminál Windows</value>
</data>
<data name="AppDescriptionPre" xml:space="preserve">
<value>Terminál Windows s náhledem připravovaných funkcí</value>
@@ -164,7 +164,7 @@
<comment>This is a menu item that will be displayed in the Windows File Explorer that launches the Canary version of Windows Terminal. Please mark one of the characters to be an accelerator key.</comment>
</data>
<data name="ShellExtension_OpenInTerminalMenuItem_Preview" xml:space="preserve">
<value>Otevřít &amp;náhled Terminálu</value>
<value>Otevřít náhled &amp;aplikace Terminal</value>
<comment>This is a menu item that will be displayed in the Windows File Explorer that launches the Preview version of Windows Terminal. Please mark one of the characters to be an accelerator key.</comment>
</data>
<data name="ShellExtension_OpenInTerminalMenuItem" xml:space="preserve">

View File

@@ -118,7 +118,7 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="InitialJsonParseErrorText" xml:space="preserve">
<value>파일에서 설정을 로드하지 못했습니다. 후행 쉼표를 포함여 구문 오류가 있는지 확인합니다.</value>
<value>파일에서 설정을 로드 하지 못했습니다. 후행 쉼표를 포함여 구문 오류가 있는지 확인 합니다.</value>
</data>
<data name="MissingDefaultProfileText" xml:space="preserve">
<value>첫 번째 프로필을 사용하여 프로필 목록에서 기본 프로필을 찾을 수 없습니다. "defaultProfile"이 프로필 중 하나의 GUID와 일치하는지 확인합니다.</value>
@@ -319,7 +319,7 @@
<value>상위 창의 백분율로 크기를 지정합니다. (0,1) 사이 값만 유효합니다.</value>
</data>
<data name="CmdNewTabDesc" xml:space="preserve">
<value>새 만들기</value>
<value>새 작업 만들기</value>
</data>
<data name="CmdNTDesc" xml:space="preserve">
<value>"new-tab" 하위 명령의 별칭입니다.</value>
@@ -524,7 +524,7 @@
<value>경고</value>
</data>
<data name="CloseReadOnlyDialog.Content" xml:space="preserve">
<value>읽기 전용 터미널을 닫으려고 합니다. 계속하시겠습니까?</value>
<value>읽기 전용 터미널을 닫으려고 합니다. 계속하시겠어요?</value>
</data>
<data name="LargePasteDialog.CloseButtonText" xml:space="preserve">
<value>취소</value>
@@ -616,7 +616,7 @@
<comment>{0} will be replaced with a number.</comment>
</data>
<data name="CrimsonColorButton.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>홍</value>
<value>홍</value>
</data>
<data name="SteelBlueColorButton.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>강철색</value>

View File

@@ -1697,41 +1697,38 @@ namespace winrt::Microsoft::Terminal::Control::implementation
SearchResults ControlCore::Search(SearchRequest request)
{
const auto lock = _terminal->LockForWriting();
SearchFlag flags{};
WI_SetFlagIf(flags, SearchFlag::CaseInsensitive, !request.CaseSensitive);
WI_SetFlagIf(flags, SearchFlag::RegularExpression, request.RegularExpression);
const auto searchInvalidated = _searcher.IsStale(*_terminal.get(), request.Text, flags);
if (searchInvalidated || !request.ResetOnly)
if (searchInvalidated || !request.Reset)
{
std::vector<til::point_span> oldResults;
til::point_span oldFocused;
if (const auto focused = _terminal->GetSearchHighlightFocused())
{
oldFocused = *focused;
}
if (searchInvalidated)
{
oldResults = _searcher.ExtractResults();
_searcher.Reset(*_terminal.get(), request.Text, flags, !request.GoForward);
if (SnapSearchResultToSelection())
{
_searcher.MoveToCurrentSelection();
SnapSearchResultToSelection(false);
}
_terminal->SetSearchHighlights(_searcher.Results());
}
if (!request.ResetOnly)
else
{
_searcher.FindNext(!request.GoForward);
}
_terminal->SetSearchHighlightFocused(gsl::narrow<size_t>(std::max<ptrdiff_t>(0, _searcher.CurrentMatch())));
_renderer->TriggerSearchHighlight(oldResults);
if (const auto focused = _terminal->GetSearchHighlightFocused(); focused && *focused != oldFocused)
if (const auto idx = _searcher.CurrentMatch(); idx >= 0)
{
_terminal->ScrollToSearchHighlight(request.ScrollOffset);
_terminal->SetSearchHighlightFocused(gsl::narrow<size_t>(idx), request.ScrollOffset);
}
_renderer->TriggerSearchHighlight(oldResults);
}
int32_t totalMatches = 0;
@@ -1759,11 +1756,27 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
const auto lock = _terminal->LockForWriting();
_terminal->SetSearchHighlights({});
_terminal->SetSearchHighlightFocused(0);
_terminal->SetSearchHighlightFocused({}, 0);
_renderer->TriggerSearchHighlight(_searcher.Results());
_searcher = {};
}
// Method Description:
// - Tells ControlCore to snap the current search result index to currently
// selected text if the search was started using it.
void ControlCore::SnapSearchResultToSelection(bool shouldSnap) noexcept
{
_snapSearchResultToSelection = shouldSnap;
}
// Method Description:
// - Returns true, if we should snap the current search result index to
// the currently selected text after a new search is started, else false.
bool ControlCore::SnapSearchResultToSelection() const noexcept
{
return _snapSearchResultToSelection;
}
void ControlCore::Close()
{
if (!_IsClosing())
@@ -2208,32 +2221,19 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - <none>
void ControlCore::ClearBuffer(Control::ClearBufferType clearType)
{
std::wstring_view command;
switch (clearType)
{
case ClearBufferType::Screen:
command = L"\x1b[H\x1b[2J";
break;
case ClearBufferType::Scrollback:
command = L"\x1b[3J";
break;
case ClearBufferType::All:
command = L"\x1b[H\x1b[2J\x1b[3J";
break;
}
if (clearType == Control::ClearBufferType::Scrollback || clearType == Control::ClearBufferType::All)
{
const auto lock = _terminal->LockForWriting();
_terminal->Write(command);
_terminal->EraseScrollback();
}
if (clearType == Control::ClearBufferType::Screen || clearType == Control::ClearBufferType::All)
{
// Send a signal to conpty to clear the buffer.
if (auto conpty{ _connection.try_as<TerminalConnection::ConptyConnection>() })
{
// Since the clearing of ConPTY occurs asynchronously, this call can result weird issues,
// where a console application still sees contents that we've already deleted, etc.
// The correct way would be for ConPTY to emit the appropriate CSI n J sequences.
// ConPTY will emit sequences to sync up our buffer with its new
// contents.
conpty.ClearBuffer();
}
}

View File

@@ -228,6 +228,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
SearchResults Search(SearchRequest request);
const std::vector<til::point_span>& SearchResultRows() const noexcept;
void ClearSearch();
void SnapSearchResultToSelection(bool snap) noexcept;
bool SnapSearchResultToSelection() const noexcept;
void LeftClickOnTerminal(const til::point terminalPosition,
const int numberOfClicks,

View File

@@ -55,7 +55,7 @@ namespace Microsoft.Terminal.Control
Boolean GoForward;
Boolean CaseSensitive;
Boolean RegularExpression;
Boolean ResetOnly;
Boolean Reset;
Int32 ScrollOffset;
};
@@ -148,6 +148,7 @@ namespace Microsoft.Terminal.Control
SearchResults Search(SearchRequest request);
void ClearSearch();
Boolean SnapSearchResultToSelection;
Microsoft.Terminal.Core.Color ForegroundColor { get; };
Microsoft.Terminal.Core.Color BackgroundColor { get; };

View File

@@ -25,12 +25,6 @@ namespace Microsoft.Terminal.Control
Console,
};
enum DefaultInputScope
{
Default,
AlphanumericHalfWidth,
};
runtimeclass FontSizeChangedArgs
{
Int32 Width { get; };

View File

@@ -891,9 +891,6 @@ void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR font
renderSettings.SetColorTableEntry(tableIndex, gsl::at(theme.ColorTable, tableIndex));
}
// Save these values as the new default render settings.
renderSettings.SaveDefaultSettings();
publicTerminal->_terminal->SetCursorStyle(static_cast<Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle>(theme.CursorStyle));
publicTerminal->_desiredFont = { fontFamily, 0, DEFAULT_FONT_WEIGHT, static_cast<float>(fontSize), CP_UTF8 };

View File

@@ -63,7 +63,6 @@ namespace Microsoft.Terminal.Control
Boolean DisablePartialInvalidation { get; };
Boolean SoftwareRendering { get; };
Microsoft.Terminal.Control.TextMeasurement TextMeasurement { get; };
Microsoft.Terminal.Control.DefaultInputScope DefaultInputScope { get; };
Boolean ShowMarks { get; };
Boolean UseBackgroundImageForWindow { get; };
Boolean RightClickContextMenu { get; };

View File

@@ -576,6 +576,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// but since code paths differ, extra work is required to ensure correctness.
if (!_core.HasMultiLineSelection())
{
_core.SnapSearchResultToSelection(true);
const auto selectedLine{ _core.SelectedText(true) };
_searchBox->PopulateTextbox(selectedLine);
}
@@ -862,11 +863,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
_interactivity.UpdateSettings();
{
const auto inputScope = settings.DefaultInputScope();
const auto alpha = inputScope == DefaultInputScope::AlphanumericHalfWidth;
::Microsoft::Console::TSF::Handle::SetDefaultScopeAlphanumericHalfWidth(alpha);
}
if (_automationPeer)
{
_automationPeer.SetControlPadding(Core::Padding{
@@ -1635,29 +1631,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
if (vkey == VK_ADD)
{
static const auto enabled = []() {
wchar_t buffer[4]{};
DWORD size = sizeof(buffer);
RegGetValueW(
HKEY_CURRENT_USER,
L"Control Panel\\Input Method",
L"EnableHexNumpad",
RRF_RT_REG_SZ,
nullptr,
&buffer[0],
&size);
return size == 4 && memcmp(&buffer[0], L"1", 4) == 0;
}();
if (enabled)
{
// Alt '+' <number> is used to input Unicode code points.
// Every time you press + it resets the entire state
// in the original OS implementation as well.
s.encoding = AltNumpadEncoding::Unicode;
s.accumulator = 0;
s.active = true;
}
// Alt '+' <number> is used to input Unicode code points.
// Every time you press + it resets the entire state
// in the original OS implementation as well.
s.encoding = AltNumpadEncoding::Unicode;
s.accumulator = 0;
s.active = true;
}
else if (vkey == VK_NUMPAD0 && s.encoding == AltNumpadEncoding::OEM && s.accumulator == 0)
{
@@ -3865,7 +3844,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto goForward = _searchBox->GoForward();
const auto caseSensitive = _searchBox->CaseSensitive();
const auto regularExpression = _searchBox->RegularExpression();
const auto request = SearchRequest{ text, goForward, caseSensitive, regularExpression, true, _searchScrollOffset };
const auto request = SearchRequest{ text, goForward, caseSensitive, regularExpression, true, _calculateSearchScrollOffset() };
_handleSearchResults(_core.Search(request));
}

View File

@@ -101,9 +101,6 @@ void Terminal::UpdateSettings(ICoreSettings settings)
GetRenderSettings().SetColorTableEntry(TextColor::FRAME_BACKGROUND, til::color{ settings.TabColor().Value() });
}
// Save the changes made above and in UpdateAppearance as the new default render settings.
GetRenderSettings().SaveDefaultSettings();
if (!_startingTabColor && settings.StartingTabColor())
{
_startingTabColor = settings.StartingTabColor().Value();
@@ -212,6 +209,12 @@ void Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle)
engine.Dispatch().SetCursorStyle(cursorStyle);
}
void Terminal::EraseScrollback()
{
auto& engine = reinterpret_cast<OutputStateMachineEngine&>(_stateMachine->Engine());
engine.Dispatch().EraseInDisplay(DispatchTypes::EraseType::Scrollback);
}
bool Terminal::IsXtermBracketedPasteModeEnabled() const noexcept
{
return _systemMode.test(Mode::BracketedPaste);
@@ -1256,17 +1259,15 @@ void Terminal::SetSearchHighlights(const std::vector<til::point_span>& highlight
// Method Description:
// - Stores the focused search highlighted region in the terminal
// - If the region isn't empty, it will be brought into view
void Terminal::SetSearchHighlightFocused(const size_t focusedIdx) noexcept
void Terminal::SetSearchHighlightFocused(const size_t focusedIdx, til::CoordType searchScrollOffset)
{
_assertLocked();
_searchHighlightFocused = focusedIdx;
}
void Terminal::ScrollToSearchHighlight(til::CoordType searchScrollOffset)
{
if (_searchHighlightFocused < _searchHighlights.size())
// bring the focused region into the view if the index is in valid range
if (focusedIdx < _searchHighlights.size())
{
const auto focused = til::at(_searchHighlights, _searchHighlightFocused);
const auto focused = til::at(_searchHighlights, focusedIdx);
const auto adjustedStart = til::point{ focused.start.x, std::max(0, focused.start.y - searchScrollOffset) };
const auto adjustedEnd = til::point{ focused.end.x, std::max(0, focused.end.y - searchScrollOffset) };
_ScrollToPoints(adjustedStart, adjustedEnd);

View File

@@ -94,6 +94,7 @@ public:
void UpdateAppearance(const winrt::Microsoft::Terminal::Core::ICoreAppearance& appearance);
void SetFontInfo(const FontInfo& fontInfo);
void SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle);
void EraseScrollback();
bool IsXtermBracketedPasteModeEnabled() const noexcept;
std::wstring_view GetWorkingDirectory() noexcept;
@@ -233,8 +234,7 @@ public:
void SetClearQuickFixCallback(std::function<void()> pfn) noexcept;
void SetWindowSizeChangedCallback(std::function<void(int32_t, int32_t)> pfn) noexcept;
void SetSearchHighlights(const std::vector<til::point_span>& highlights) noexcept;
void SetSearchHighlightFocused(size_t focusedIdx) noexcept;
void ScrollToSearchHighlight(til::CoordType searchScrollOffset);
void SetSearchHighlightFocused(const size_t focusedIdx, til::CoordType searchScrollOffset);
void BlinkCursor() noexcept;
void SetCursorOn(const bool isOn) noexcept;

View File

@@ -178,7 +178,7 @@
<!-- command name -->
<ColumnDefinition Width="*" />
<!-- key chord -->
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="150" />
<!-- edit buttons -->
<!--
This needs to be 112 because that is the width of the row of buttons in edit mode + padding.
@@ -307,7 +307,7 @@
Glyph="&#xE74D;" />
</Button.Content>
<Button.Flyout>
<Flyout FlyoutPresenterStyle="{StaticResource CustomFlyoutPresenterStyle}">
<Flyout>
<StackPanel>
<TextBlock x:Uid="Actions_DeleteConfirmationMessage"
Style="{StaticResource CustomFlyoutTextStyle}" />

View File

@@ -289,17 +289,14 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
// Display a confirmation dialog.
TextBlock errorMessageTB{};
errorMessageTB.Text(RS_(L"Actions_RenameConflictConfirmationMessage"));
errorMessageTB.TextWrapping(TextWrapping::Wrap);
const auto conflictingCmdName{ conflictingCmd.Name() };
TextBlock conflictingCommandNameTB{};
conflictingCommandNameTB.Text(fmt::format(L"\"{}\"", conflictingCmdName.empty() ? RS_(L"Actions_UnnamedCommandName") : conflictingCmdName));
conflictingCommandNameTB.FontStyle(Windows::UI::Text::FontStyle::Italic);
conflictingCommandNameTB.TextWrapping(TextWrapping::Wrap);
TextBlock confirmationQuestionTB{};
confirmationQuestionTB.Text(RS_(L"Actions_RenameConflictConfirmationQuestion"));
confirmationQuestionTB.TextWrapping(TextWrapping::Wrap);
Button acceptBTN{};
acceptBTN.Content(box_value(RS_(L"Actions_RenameConflictConfirmationAcceptButton")));
@@ -323,17 +320,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
flyoutStack.Children().Append(confirmationQuestionTB);
flyoutStack.Children().Append(acceptBTN);
// This should match CustomFlyoutPresenterStyle in CommonResources.xaml!
// We don't have access to those resources here, so it's easier to just copy them over.
// This allows the flyout text to wrap
Style acceptChangesFlyoutStyle{ winrt::xaml_typename<FlyoutPresenter>() };
Setter horizontalScrollModeStyleSetter{ ScrollViewer::HorizontalScrollModeProperty(), box_value(ScrollMode::Disabled) };
Setter horizontalScrollBarVisibilityStyleSetter{ ScrollViewer::HorizontalScrollBarVisibilityProperty(), box_value(ScrollBarVisibility::Disabled) };
acceptChangesFlyoutStyle.Setters().Append(horizontalScrollModeStyleSetter);
acceptChangesFlyoutStyle.Setters().Append(horizontalScrollBarVisibilityStyleSetter);
Flyout acceptChangesFlyout{};
acceptChangesFlyout.FlyoutPresenterStyle(acceptChangesFlyoutStyle);
acceptChangesFlyout.Content(flyoutStack);
senderVM.AcceptChangesFlyout(acceptChangesFlyout);
}

View File

@@ -1030,9 +1030,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
}
void Appearances::FontFaceBox_QuerySubmitted(const AutoSuggestBox& sender, const AutoSuggestBoxQuerySubmittedEventArgs& args)
void Appearances::FontFaceBox_SuggestionChosen(const AutoSuggestBox& sender, const AutoSuggestBoxSuggestionChosenEventArgs& args)
{
const auto font = unbox_value<Editor::Font>(args.ChosenSuggestion());
const auto font = unbox_value<Editor::Font>(args.SelectedItem());
const auto fontName = font.Name();
auto fontSpec = sender.Text();

View File

@@ -179,7 +179,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void FontFaceBox_GotFocus(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
void FontFaceBox_LostFocus(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
void FontFaceBox_QuerySubmitted(const winrt::Windows::UI::Xaml::Controls::AutoSuggestBox&, const winrt::Windows::UI::Xaml::Controls::AutoSuggestBoxQuerySubmittedEventArgs&);
void FontFaceBox_SuggestionChosen(const winrt::Windows::UI::Xaml::Controls::AutoSuggestBox&, const winrt::Windows::UI::Xaml::Controls::AutoSuggestBoxSuggestionChosenEventArgs&);
void FontFaceBox_TextChanged(const winrt::Windows::UI::Xaml::Controls::AutoSuggestBox&, const winrt::Windows::UI::Xaml::Controls::AutoSuggestBoxTextChangedEventArgs&);
void DeleteFontKeyValuePair_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
safe_void_coroutine BackgroundImage_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);

View File

@@ -214,11 +214,10 @@
ItemTemplate="{StaticResource FontFaceComboBoxItemTemplate}"
ItemsSource="{x:Bind FilteredFontList, Mode=OneWay}"
LostFocus="FontFaceBox_LostFocus"
QuerySubmitted="FontFaceBox_QuerySubmitted"
SuggestionChosen="FontFaceBox_SuggestionChosen"
Text="{x:Bind Appearance.FontFace, Mode=OneWay}"
TextBoxStyle="{StaticResource TextBoxSettingStyle}"
TextChanged="FontFaceBox_TextChanged"
UpdateTextOnSelect="False" />
TextChanged="FontFaceBox_TextChanged" />
<CheckBox x:Name="ShowAllFontsCheckbox"
x:Uid="Profile_FontFaceShowAllFonts"
IsChecked="{x:Bind ShowAllFonts, Mode=TwoWay}" />

View File

@@ -139,7 +139,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
}
void ColorSchemeViewModel::DeleteConfirmation_Click(const IInspectable& /*sender*/, const Windows::UI::Xaml::RoutedEventArgs& /*e*/)
void ColorSchemeViewModel::RequestDeleteCurrentScheme()
{
if (const auto parentPageVM{ _parentPageVM.get() })
{

View File

@@ -28,13 +28,13 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
hstring ToString();
bool RequestRename(winrt::hstring newName);
void RequestDeleteCurrentScheme();
Editor::ColorTableEntry ColorEntryAt(uint32_t index);
bool IsDefaultScheme();
void RefreshIsDefault();
bool IsEditable() const;
void DeleteConfirmation_Click(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& e);
void SetAsDefault_Click(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& e);
void Duplicate_Click(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& e);

View File

@@ -25,7 +25,6 @@ namespace Microsoft.Terminal.Settings.Editor
ColorTableEntry CursorColor;
ColorTableEntry SelectionBackgroundColor;
void DeleteConfirmation_Click(IInspectable sender, Windows.UI.Xaml.RoutedEventArgs args);
void SetAsDefault_Click(IInspectable sender, Windows.UI.Xaml.RoutedEventArgs args);
void Duplicate_Click(IInspectable sender, Windows.UI.Xaml.RoutedEventArgs args);
}

View File

@@ -46,12 +46,20 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
});
}
void ColorSchemes::AddNew_Click(const IInspectable& /*sender*/, const RoutedEventArgs& /*e*/)
void ColorSchemes::AddNew_Click(const IInspectable& sender, const RoutedEventArgs& /*e*/)
{
if (const auto newSchemeVM{ _ViewModel.RequestAddNew() })
{
ColorSchemeListView().SelectedItem(newSchemeVM);
_ViewModel.RequestEditSelectedScheme();
if (auto automationPeer{ Automation::Peers::FrameworkElementAutomationPeer::FromElement(sender.as<UIElement>()) })
{
automationPeer.RaiseNotificationEvent(Automation::Peers::AutomationNotificationKind::ActionCompleted,
Automation::Peers::AutomationNotificationProcessing::ImportantAll,
RS_fmt(L"ColorScheme_AddNewButton_ConfirmationMessage", newSchemeVM.Name()),
L"ColorSchemeAdded");
}
}
}

View File

@@ -115,7 +115,7 @@
<!-- Used for disclaimers -->
<Style x:Key="DisclaimerStyle"
TargetType="TextBlock">
<Setter Property="TextWrapping" Value="Wrap" />
<Setter Property="TextWrapping" Value="WrapWholeWords" />
<Setter Property="MaxWidth" Value="1000" />
</Style>
@@ -125,14 +125,6 @@
TargetType="TextBlock">
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Margin" Value="0,0,0,10" />
<Setter Property="TextWrapping" Value="Wrap" />
</Style>
<!-- Used for the flyout itself. Removes scroll bar to allow for text wrapping. -->
<Style x:Key="CustomFlyoutPresenterStyle"
TargetType="FlyoutPresenter">
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
</Style>
<!-- Number Box -->
@@ -153,7 +145,7 @@
BasedOn="{StaticResource BaseButtonStyle}"
TargetType="Button">
<Setter Property="Margin" Value="10,0,0,0" />
<Setter Property="MinHeight" Value="33" />
<Setter Property="Height" Value="33" />
</Style>
<!-- Delete button based on Accent button template -->

View File

@@ -115,12 +115,21 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void EditColorScheme::_RenameCurrentScheme(hstring newName)
{
const auto oldName = _ViewModel.Name();
if (_ViewModel.RequestRename(newName))
{
// update the UI
RenameErrorTip().IsOpen(false);
NameBox().Focus(FocusState::Programmatic);
if (auto automationPeer{ Automation::Peers::FrameworkElementAutomationPeer::FromElement(*this) })
{
automationPeer.RaiseNotificationEvent(Automation::Peers::AutomationNotificationKind::ActionCompleted,
Automation::Peers::AutomationNotificationProcessing::ImportantAll,
RS_fmt(L"ColorScheme_Rename_ConfirmationMessage", oldName, newName),
L"ColorSchemeAdded");
}
}
else
{
@@ -132,4 +141,17 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
NameBox().SelectAll();
}
}
void EditColorScheme::DeleteConfirmation_Click(const IInspectable& /*sender*/, const RoutedEventArgs& /*e*/)
{
winrt::get_self<ColorSchemeViewModel>(_ViewModel)->RequestDeleteCurrentScheme();
if (auto automationPeer{ Automation::Peers::FrameworkElementAutomationPeer::FromElement(*this) })
{
automationPeer.RaiseNotificationEvent(Automation::Peers::AutomationNotificationKind::ActionCompleted,
Automation::Peers::AutomationNotificationProcessing::ImportantAll,
RS_fmt(L"ColorScheme_Delete_ConfirmationMessage", _ViewModel.Name()),
L"ColorSchemeDeleted");
}
}
}

View File

@@ -19,6 +19,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void RenameAccept_Click(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& e);
void RenameCancel_Click(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& e);
void NameBox_PreviewKeyDown(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::Input::KeyRoutedEventArgs& e);
void DeleteConfirmation_Click(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& e);
til::property_changed_event PropertyChanged;

View File

@@ -488,12 +488,12 @@
</StackPanel>
</Button.Content>
<Button.Flyout>
<Flyout FlyoutPresenterStyle="{StaticResource CustomFlyoutPresenterStyle}">
<Flyout>
<StackPanel>
<TextBlock x:Uid="ColorScheme_DeleteConfirmationMessage"
Style="{StaticResource CustomFlyoutTextStyle}" />
<Button x:Uid="ColorScheme_DeleteConfirmationButton"
Click="{x:Bind ViewModel.DeleteConfirmation_Click}" />
Click="DeleteConfirmation_Click" />
</StackPanel>
</Flyout>
</Button.Flyout>

View File

@@ -27,6 +27,20 @@
</Page.Resources>
<StackPanel Style="{StaticResource SettingsStackStyle}">
<!-- Language -->
<local:SettingContainer x:Uid="Globals_Language"
Visibility="{x:Bind ViewModel.LanguageSelectorAvailable}">
<ComboBox ItemsSource="{x:Bind ViewModel.LanguageList}"
SelectedItem="{x:Bind ViewModel.CurrentLanguage, Mode=TwoWay}"
Style="{StaticResource ComboBoxSettingStyle}">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="x:String">
<TextBlock Text="{x:Bind local:GlobalAppearanceViewModel.LanguageDisplayConverter((x:String))}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</local:SettingContainer>
<!-- Theme -->
<local:SettingContainer x:Uid="Globals_Theme">
<ComboBox AutomationProperties.AccessibilityView="Content"

View File

@@ -7,6 +7,7 @@
#include "EnumEntry.h"
#include <LibraryResources.h>
#include <WtExeUtils.h>
using namespace winrt;
using namespace winrt::Windows::UI::Xaml;
@@ -17,6 +18,28 @@ using namespace winrt::Windows::Foundation::Collections;
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
// For ComboBox an empty SelectedItem string denotes no selection.
// What we want instead is for "Use system language" to be selected by default.
// --> "und" is synonymous for "Use system language".
constexpr std::wstring_view systemLanguageTag{ L"und" };
static constexpr std::array appLanguageTags{
L"en-US",
L"de-DE",
L"es-ES",
L"fr-FR",
L"it-IT",
L"ja",
L"ko",
L"pt-BR",
L"qps-PLOC",
L"qps-PLOCA",
L"qps-PLOCM",
L"ru",
L"zh-Hans",
L"zh-Hant",
};
constexpr std::wstring_view systemThemeName{ L"system" };
constexpr std::wstring_view darkThemeName{ L"dark" };
constexpr std::wstring_view lightThemeName{ L"light" };
@@ -33,6 +56,146 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
_UpdateThemeList();
}
winrt::hstring GlobalAppearanceViewModel::LanguageDisplayConverter(const winrt::hstring& tag)
{
if (tag == systemLanguageTag)
{
return RS_(L"Globals_LanguageDefault");
}
winrt::Windows::Globalization::Language language{ tag };
return language.NativeName();
}
// Returns whether the language selector is available/shown.
//
// winrt::Windows::Globalization::ApplicationLanguages::PrimaryLanguageOverride()
// doesn't work for unpackaged applications. The corresponding code in TerminalApp is disabled.
// It would be confusing for our users if we presented a dysfunctional language selector.
bool GlobalAppearanceViewModel::LanguageSelectorAvailable()
{
return IsPackaged();
}
// Returns the list of languages the user may override the application language with.
// The returned list are BCP 47 language tags like {"und", "en-US", "de-DE", "es-ES", ...}.
// "und" is short for "undefined" and is synonymous for "Use system language" in this code.
winrt::Windows::Foundation::Collections::IObservableVector<winrt::hstring> GlobalAppearanceViewModel::LanguageList()
{
if (_languageList)
{
return _languageList;
}
if (!LanguageSelectorAvailable())
{
_languageList = {};
return _languageList;
}
// In order to return the language list this code does the following:
// [1] Get all possible languages we want to allow the user to choose.
// We have to acquire languages from multiple sources, creating duplicates. See below at [1].
// [2] Sort languages by their ASCII tags, forcing the UI in a consistent/stable order.
// I wanted to sort the localized language names initially, but it turned out to be complex.
// [3] Remove potential duplicates in our language list from [1].
// We don't want to have en-US twice in the list, do we?
// [4] Optionally remove unwanted language tags (like pseudo-localizations).
std::vector<winrt::hstring> tags;
// [1]:
{
// ManifestLanguages contains languages the app ships with.
// Unfortunately, we cannot use this source. Our manifest must contain the
// ~100 languages that are localized for the shell extension and start menu
// presentation so we align with Windows display languages for those surfaces.
// However, the actual content of our application is limited to a much smaller
// subset of approximately 14 languages. As such, we will code the limited
// subset of languages that we support for selection within the Settings
// dropdown to steer users towards the ones that we can display in the app.
// As per the function definition, the first item
// is always "Use system language" ("und").
tags.emplace_back(systemLanguageTag);
// Add our hard-coded languages after the system definition.
for (const auto& v : appLanguageTags)
{
tags.push_back(v);
}
}
// NOTE: The size of tags is always >0, due to tags[0] being hard-coded to "und".
const auto tagsBegin = ++tags.begin();
const auto tagsEnd = tags.end();
// [2]:
std::sort(tagsBegin, tagsEnd);
// I'd love for both, std::unique and std::remove_if, to occur in a single loop,
// but the code turned out to be complex and even less maintainable, so I gave up.
{
// [3] part 1:
auto it = std::unique(tagsBegin, tagsEnd);
// The qps- languages are useful for testing ("pseudo-localization").
// --> Leave them in if debug features are enabled.
if (!_GlobalSettings.DebugFeaturesEnabled())
{
// [4] part 1:
it = std::remove_if(tagsBegin, it, [](const winrt::hstring& tag) -> bool {
return til::starts_with(tag, L"qps-");
});
}
// [3], [4] part 2 (completing the so called "erase-remove idiom"):
tags.erase(it, tagsEnd);
}
_languageList = winrt::single_threaded_observable_vector(std::move(tags));
return _languageList;
}
winrt::Windows::Foundation::IInspectable GlobalAppearanceViewModel::CurrentLanguage()
{
if (_currentLanguage)
{
return _currentLanguage;
}
if (!LanguageSelectorAvailable())
{
_currentLanguage = {};
return _currentLanguage;
}
// NOTE: PrimaryLanguageOverride throws if this instance is unpackaged.
auto currentLanguage = winrt::Windows::Globalization::ApplicationLanguages::PrimaryLanguageOverride();
if (currentLanguage.empty())
{
currentLanguage = systemLanguageTag;
}
_currentLanguage = winrt::box_value(currentLanguage);
return _currentLanguage;
}
void GlobalAppearanceViewModel::CurrentLanguage(const winrt::Windows::Foundation::IInspectable& tag)
{
_currentLanguage = tag;
const auto currentLanguage = winrt::unbox_value<winrt::hstring>(_currentLanguage);
if (currentLanguage == systemLanguageTag)
{
_GlobalSettings.ClearLanguage();
}
else
{
_GlobalSettings.Language(currentLanguage);
}
}
// Function Description:
// - Updates the list of all themes available to choose from.
void GlobalAppearanceViewModel::_UpdateThemeList()

View File

@@ -22,6 +22,16 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
GETSET_BINDABLE_ENUM_SETTING(TabWidthMode, winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, _GlobalSettings.TabWidthMode);
public:
// LanguageDisplayConverter maps the given BCP 47 tag to a localized string.
// For instance "en-US" produces "English (United States)", while "de-DE" produces
// "Deutsch (Deutschland)". This works independently of the user's locale.
static winrt::hstring LanguageDisplayConverter(const winrt::hstring& tag);
bool LanguageSelectorAvailable();
winrt::Windows::Foundation::Collections::IObservableVector<winrt::hstring> LanguageList();
winrt::Windows::Foundation::IInspectable CurrentLanguage();
void CurrentLanguage(const winrt::Windows::Foundation::IInspectable& tag);
winrt::Windows::Foundation::IInspectable CurrentTheme();
void CurrentTheme(const winrt::Windows::Foundation::IInspectable& tag);
static winrt::hstring ThemeNameConverter(const Model::Theme& theme);
@@ -42,6 +52,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
private:
Model::GlobalAppSettings _GlobalSettings;
winrt::Windows::Foundation::Collections::IObservableVector<winrt::hstring> _languageList;
winrt::Windows::Foundation::IInspectable _currentLanguage;
winrt::Windows::Foundation::IInspectable _currentTheme;
void _UpdateThemeList();

View File

@@ -11,6 +11,11 @@ namespace Microsoft.Terminal.Settings.Editor
{
GlobalAppearanceViewModel(Microsoft.Terminal.Settings.Model.GlobalAppSettings globalSettings);
static String LanguageDisplayConverter(String tag);
Boolean LanguageSelectorAvailable { get; };
Windows.Foundation.Collections.IObservableVector<String> LanguageList { get; };
IInspectable CurrentLanguage;
IInspectable CurrentTheme;
static String ThemeNameConverter(Microsoft.Terminal.Settings.Model.Theme theme);
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Model.Theme> ThemeList { get; };

View File

@@ -24,101 +24,73 @@
</ResourceDictionary>
</Page.Resources>
<StackPanel>
<StackPanel Style="{StaticResource SettingsStackStyle}">
<!-- Copy On Select -->
<local:SettingContainer x:Uid="Globals_CopyOnSelect">
<ToggleSwitch IsOn="{x:Bind ViewModel.CopyOnSelect, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<StackPanel Style="{StaticResource SettingsStackStyle}">
<!-- Copy On Select -->
<local:SettingContainer x:Uid="Globals_CopyOnSelect">
<ToggleSwitch IsOn="{x:Bind ViewModel.CopyOnSelect, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Copy Format -->
<local:SettingContainer x:Uid="Globals_CopyFormat">
<ComboBox AutomationProperties.AccessibilityView="Content"
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
ItemsSource="{x:Bind ViewModel.CopyFormatList, Mode=OneWay}"
SelectedItem="{x:Bind ViewModel.CurrentCopyFormat, Mode=TwoWay}"
Style="{StaticResource ComboBoxSettingStyle}" />
</local:SettingContainer>
<!-- Copy Format -->
<local:SettingContainer x:Uid="Globals_CopyFormat">
<ComboBox AutomationProperties.AccessibilityView="Content"
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
ItemsSource="{x:Bind ViewModel.CopyFormatList, Mode=OneWay}"
SelectedItem="{x:Bind ViewModel.CurrentCopyFormat, Mode=TwoWay}"
Style="{StaticResource ComboBoxSettingStyle}" />
</local:SettingContainer>
<!-- Trim Block Selection -->
<local:SettingContainer x:Uid="Globals_TrimBlockSelection">
<ToggleSwitch IsOn="{x:Bind ViewModel.TrimBlockSelection, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Trim Block Selection -->
<local:SettingContainer x:Uid="Globals_TrimBlockSelection">
<ToggleSwitch IsOn="{x:Bind ViewModel.TrimBlockSelection, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Trim Paste -->
<local:SettingContainer x:Uid="Globals_TrimPaste">
<ToggleSwitch IsOn="{x:Bind ViewModel.TrimPaste, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Trim Paste -->
<local:SettingContainer x:Uid="Globals_TrimPaste">
<ToggleSwitch IsOn="{x:Bind ViewModel.TrimPaste, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Word Delimiters -->
<local:SettingContainer x:Uid="Globals_WordDelimiters"
CurrentValue="{x:Bind ViewModel.WordDelimiters, Mode=OneWay}"
Style="{StaticResource ExpanderSettingContainerStyle}">
<TextBox IsSpellCheckEnabled="False"
Style="{StaticResource TextBoxSettingStyle}"
Text="{x:Bind ViewModel.WordDelimiters, Mode=TwoWay}" />
</local:SettingContainer>
<!-- Word Delimiters -->
<local:SettingContainer x:Uid="Globals_WordDelimiters"
CurrentValue="{x:Bind ViewModel.WordDelimiters, Mode=OneWay}"
Style="{StaticResource ExpanderSettingContainerStyle}">
<TextBox IsSpellCheckEnabled="False"
Style="{StaticResource TextBoxSettingStyle}"
Text="{x:Bind ViewModel.WordDelimiters, Mode=TwoWay}" />
</local:SettingContainer>
<!-- Snap On Resize -->
<local:SettingContainer x:Uid="Globals_SnapToGridOnResize">
<ToggleSwitch IsOn="{x:Bind ViewModel.SnapToGridOnResize, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Snap On Resize -->
<local:SettingContainer x:Uid="Globals_SnapToGridOnResize">
<ToggleSwitch IsOn="{x:Bind ViewModel.SnapToGridOnResize, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Tab Switcher Mode -->
<local:SettingContainer x:Uid="Globals_TabSwitcherMode">
<ComboBox AutomationProperties.AccessibilityView="Content"
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
ItemsSource="{x:Bind ViewModel.TabSwitcherModeList}"
SelectedItem="{x:Bind ViewModel.CurrentTabSwitcherMode, Mode=TwoWay}"
Style="{StaticResource ComboBoxSettingStyle}" />
</local:SettingContainer>
<!-- Tab Switcher Mode -->
<local:SettingContainer x:Uid="Globals_TabSwitcherMode">
<ComboBox AutomationProperties.AccessibilityView="Content"
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
ItemsSource="{x:Bind ViewModel.TabSwitcherModeList}"
SelectedItem="{x:Bind ViewModel.CurrentTabSwitcherMode, Mode=TwoWay}"
Style="{StaticResource ComboBoxSettingStyle}" />
</local:SettingContainer>
<!-- Focus Follow Mouse Mode -->
<local:SettingContainer x:Uid="Globals_FocusFollowMouse">
<ToggleSwitch IsOn="{x:Bind ViewModel.FocusFollowMouse, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Focus Follow Mouse Mode -->
<local:SettingContainer x:Uid="Globals_FocusFollowMouse">
<ToggleSwitch IsOn="{x:Bind ViewModel.FocusFollowMouse, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Detect URLs -->
<local:SettingContainer x:Uid="Globals_DetectURLs">
<ToggleSwitch IsOn="{x:Bind ViewModel.DetectURLs, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
</StackPanel>
<!-- Detect URLs -->
<local:SettingContainer x:Uid="Globals_DetectURLs">
<ToggleSwitch IsOn="{x:Bind ViewModel.DetectURLs, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<StackPanel Style="{StaticResource SettingsStackStyle}">
<!-- Grouping: Warnings -->
<TextBlock x:Uid="Globals_WarningsHeader"
Style="{StaticResource TextBlockSubHeaderStyle}" />
<!-- Close All Tabs Warning -->
<local:SettingContainer x:Uid="Globals_ConfirmCloseAllTabs">
<ToggleSwitch IsOn="{x:Bind ViewModel.ConfirmCloseAllTabs, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Input Service Warning -->
<local:SettingContainer x:Uid="Globals_InputServiceWarning">
<ToggleSwitch IsOn="{x:Bind ViewModel.InputServiceWarning, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Large Paste Warning -->
<local:SettingContainer x:Uid="Globals_WarnAboutLargePaste">
<ToggleSwitch IsOn="{x:Bind ViewModel.WarnAboutLargePaste, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Multi Line Paste Warning -->
<local:SettingContainer x:Uid="Globals_WarnAboutMultiLinePaste">
<ToggleSwitch IsOn="{x:Bind ViewModel.WarnAboutMultiLinePaste, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
</StackPanel>
<local:SettingContainer x:Uid="Globals_ConfirmCloseAllTabs">
<ToggleSwitch IsOn="{x:Bind ViewModel.ConfirmCloseAllTabs, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
</StackPanel>
</Page>

View File

@@ -28,9 +28,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, DetectURLs);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, WordDelimiters);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, ConfirmCloseAllTabs);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, InputServiceWarning);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, WarnAboutLargePaste);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, WarnAboutMultiLinePaste);
private:
Model::GlobalAppSettings _GlobalSettings;

View File

@@ -25,8 +25,5 @@ namespace Microsoft.Terminal.Settings.Editor
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, DetectURLs);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(String, WordDelimiters);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, ConfirmCloseAllTabs);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, InputServiceWarning);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, WarnAboutLargePaste);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, WarnAboutMultiLinePaste);
}
}

View File

@@ -139,29 +139,6 @@
</ComboBox>
</local:SettingContainer>
<!-- Language -->
<local:SettingContainer x:Uid="Globals_Language"
Visibility="{x:Bind ViewModel.LanguageSelectorAvailable}">
<ComboBox ItemsSource="{x:Bind ViewModel.LanguageList}"
SelectedItem="{x:Bind ViewModel.CurrentLanguage, Mode=TwoWay}"
Style="{StaticResource ComboBoxSettingStyle}">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="x:String">
<TextBlock Text="{x:Bind local:LaunchViewModel.LanguageDisplayConverter((x:String))}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</local:SettingContainer>
<!-- Language -->
<local:SettingContainer x:Uid="Globals_DefaultInputScope">
<ComboBox AutomationProperties.AccessibilityView="Content"
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
ItemsSource="{x:Bind ViewModel.DefaultInputScopeList}"
SelectedItem="{x:Bind ViewModel.CurrentDefaultInputScope, Mode=TwoWay}"
Style="{StaticResource ComboBoxSettingStyle}" />
</local:SettingContainer>
<!-- Start on User Login -->
<local:SettingContainer x:Uid="Globals_StartOnUserLogin">
<ToggleSwitch IsOn="{x:Bind ViewModel.StartOnUserLogin, Mode=TwoWay}"

View File

@@ -5,9 +5,7 @@
#include "LaunchViewModel.h"
#include "LaunchViewModel.g.cpp"
#include "EnumEntry.h"
#include <LibraryResources.h>
#include <WtExeUtils.h>
using namespace winrt::Windows::UI::Xaml::Navigation;
using namespace winrt::Windows::Foundation;
@@ -16,34 +14,11 @@ using namespace winrt::Windows::UI::Xaml::Data;
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
// For ComboBox an empty SelectedItem string denotes no selection.
// What we want instead is for "Use system language" to be selected by default.
// --> "und" is synonymous for "Use system language".
constexpr std::wstring_view systemLanguageTag{ L"und" };
static constexpr std::array appLanguageTags{
L"en-US",
L"de-DE",
L"es-ES",
L"fr-FR",
L"it-IT",
L"ja",
L"ko",
L"pt-BR",
L"qps-PLOC",
L"qps-PLOCA",
L"qps-PLOCM",
L"ru",
L"zh-Hans",
L"zh-Hant",
};
LaunchViewModel::LaunchViewModel(Model::CascadiaSettings settings) :
_Settings{ settings }
{
_useDefaultLaunchPosition = isnan(InitialPosX()) && isnan(InitialPosY());
INITIALIZE_BINDABLE_ENUM_SETTING(DefaultInputScope, DefaultInputScope, winrt::Microsoft::Terminal::Control::DefaultInputScope, L"Globals_DefaultInputScope", L"Content");
INITIALIZE_BINDABLE_ENUM_SETTING(FirstWindowPreference, FirstWindowPreference, FirstWindowPreference, L"Globals_FirstWindowPreference", L"Content");
INITIALIZE_BINDABLE_ENUM_SETTING(LaunchMode, LaunchMode, LaunchMode, L"Globals_LaunchMode", L"Content");
// More options were added to the JSON mapper when the enum was made into [Flags]
@@ -65,146 +40,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
});
}
winrt::hstring LaunchViewModel::LanguageDisplayConverter(const winrt::hstring& tag)
{
if (tag == systemLanguageTag)
{
return RS_(L"Globals_LanguageDefault");
}
winrt::Windows::Globalization::Language language{ tag };
return language.NativeName();
}
// Returns whether the language selector is available/shown.
//
// winrt::Windows::Globalization::ApplicationLanguages::PrimaryLanguageOverride()
// doesn't work for unpackaged applications. The corresponding code in TerminalApp is disabled.
// It would be confusing for our users if we presented a dysfunctional language selector.
bool LaunchViewModel::LanguageSelectorAvailable()
{
return IsPackaged();
}
// Returns the list of languages the user may override the application language with.
// The returned list are BCP 47 language tags like {"und", "en-US", "de-DE", "es-ES", ...}.
// "und" is short for "undefined" and is synonymous for "Use system language" in this code.
winrt::Windows::Foundation::Collections::IObservableVector<winrt::hstring> LaunchViewModel::LanguageList()
{
if (_languageList)
{
return _languageList;
}
if (!LanguageSelectorAvailable())
{
_languageList = {};
return _languageList;
}
// In order to return the language list this code does the following:
// [1] Get all possible languages we want to allow the user to choose.
// We have to acquire languages from multiple sources, creating duplicates. See below at [1].
// [2] Sort languages by their ASCII tags, forcing the UI in a consistent/stable order.
// I wanted to sort the localized language names initially, but it turned out to be complex.
// [3] Remove potential duplicates in our language list from [1].
// We don't want to have en-US twice in the list, do we?
// [4] Optionally remove unwanted language tags (like pseudo-localizations).
std::vector<winrt::hstring> tags;
// [1]:
{
// ManifestLanguages contains languages the app ships with.
// Unfortunately, we cannot use this source. Our manifest must contain the
// ~100 languages that are localized for the shell extension and start menu
// presentation so we align with Windows display languages for those surfaces.
// However, the actual content of our application is limited to a much smaller
// subset of approximately 14 languages. As such, we will code the limited
// subset of languages that we support for selection within the Settings
// dropdown to steer users towards the ones that we can display in the app.
// As per the function definition, the first item
// is always "Use system language" ("und").
tags.emplace_back(systemLanguageTag);
// Add our hard-coded languages after the system definition.
for (const auto& v : appLanguageTags)
{
tags.push_back(v);
}
}
// NOTE: The size of tags is always >0, due to tags[0] being hard-coded to "und".
const auto tagsBegin = ++tags.begin();
const auto tagsEnd = tags.end();
// [2]:
std::sort(tagsBegin, tagsEnd);
// I'd love for both, std::unique and std::remove_if, to occur in a single loop,
// but the code turned out to be complex and even less maintainable, so I gave up.
{
// [3] part 1:
auto it = std::unique(tagsBegin, tagsEnd);
// The qps- languages are useful for testing ("pseudo-localization").
// --> Leave them in if debug features are enabled.
if (!_Settings.GlobalSettings().DebugFeaturesEnabled())
{
// [4] part 1:
it = std::remove_if(tagsBegin, it, [](const winrt::hstring& tag) -> bool {
return til::starts_with(tag, L"qps-");
});
}
// [3], [4] part 2 (completing the so called "erase-remove idiom"):
tags.erase(it, tagsEnd);
}
_languageList = winrt::single_threaded_observable_vector(std::move(tags));
return _languageList;
}
winrt::Windows::Foundation::IInspectable LaunchViewModel::CurrentLanguage()
{
if (_currentLanguage)
{
return _currentLanguage;
}
if (!LanguageSelectorAvailable())
{
_currentLanguage = {};
return _currentLanguage;
}
// NOTE: PrimaryLanguageOverride throws if this instance is unpackaged.
auto currentLanguage = winrt::Windows::Globalization::ApplicationLanguages::PrimaryLanguageOverride();
if (currentLanguage.empty())
{
currentLanguage = systemLanguageTag;
}
_currentLanguage = winrt::box_value(currentLanguage);
return _currentLanguage;
}
void LaunchViewModel::CurrentLanguage(const winrt::Windows::Foundation::IInspectable& tag)
{
_currentLanguage = tag;
const auto currentLanguage = winrt::unbox_value<winrt::hstring>(_currentLanguage);
if (currentLanguage == systemLanguageTag)
{
_Settings.GlobalSettings().ClearLanguage();
}
else
{
_Settings.GlobalSettings().Language(currentLanguage);
}
}
winrt::hstring LaunchViewModel::LaunchParametersCurrentValue()
{
const auto launchModeString = CurrentLaunchMode().as<EnumEntry>()->EnumName();

View File

@@ -14,16 +14,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
public:
LaunchViewModel(Model::CascadiaSettings settings);
// LanguageDisplayConverter maps the given BCP 47 tag to a localized string.
// For instance "en-US" produces "English (United States)", while "de-DE" produces
// "Deutsch (Deutschland)". This works independently of the user's locale.
static winrt::hstring LanguageDisplayConverter(const winrt::hstring& tag);
bool LanguageSelectorAvailable();
winrt::Windows::Foundation::Collections::IObservableVector<winrt::hstring> LanguageList();
winrt::Windows::Foundation::IInspectable CurrentLanguage();
void CurrentLanguage(const winrt::Windows::Foundation::IInspectable& tag);
winrt::hstring LaunchParametersCurrentValue();
double InitialPosX();
double InitialPosY();
@@ -45,7 +35,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void CurrentLaunchMode(const winrt::Windows::Foundation::IInspectable& enumEntry);
winrt::Windows::Foundation::Collections::IObservableVector<winrt::Microsoft::Terminal::Settings::Editor::EnumEntry> LaunchModeList();
GETSET_BINDABLE_ENUM_SETTING(DefaultInputScope, winrt::Microsoft::Terminal::Control::DefaultInputScope, _Settings.GlobalSettings().DefaultInputScope);
GETSET_BINDABLE_ENUM_SETTING(FirstWindowPreference, Model::FirstWindowPreference, _Settings.GlobalSettings().FirstWindowPreference);
GETSET_BINDABLE_ENUM_SETTING(WindowingBehavior, Model::WindowingMode, _Settings.GlobalSettings().WindowingBehavior);
@@ -56,8 +45,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
private:
Model::CascadiaSettings _Settings;
winrt::Windows::Foundation::Collections::IObservableVector<winrt::hstring> _languageList;
winrt::Windows::Foundation::IInspectable _currentLanguage;
bool _useDefaultLaunchPosition;
winrt::Windows::Foundation::Collections::IObservableVector<winrt::Microsoft::Terminal::Settings::Editor::EnumEntry> _LaunchModeList;

View File

@@ -11,14 +11,6 @@ namespace Microsoft.Terminal.Settings.Editor
{
LaunchViewModel(Microsoft.Terminal.Settings.Model.CascadiaSettings settings);
static String LanguageDisplayConverter(String tag);
Boolean LanguageSelectorAvailable { get; };
Windows.Foundation.Collections.IObservableVector<String> LanguageList { get; };
IInspectable CurrentLanguage;
IInspectable CurrentDefaultInputScope;
IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> DefaultInputScopeList { get; };
String LaunchParametersCurrentValue { get; };
Double InitialPosX;
Double InitialPosY;

View File

@@ -246,22 +246,9 @@
<comment>A description explaining how this control changes the app's language. {Locked="Windows"}</comment>
</data>
<data name="Globals_LanguageDefault" xml:space="preserve">
<value>Standard</value>
<value>Systemstandard verwenden</value>
<comment>The app contains a control allowing users to choose the app's language. If this value is chosen, the language preference list of the system settings is used instead.</comment>
</data>
<data name="Globals_DefaultInputScope.Header" xml:space="preserve">
<value>Standard-IME-Eingabemodus</value>
<comment>The "input scope" of an IME tells it what type of characters should be available for input. A Chinese IME for instance may show English letters instead of Chinese ones. It's a technical term. We're using "input mode" instead of "input scope" to make it easier to understand for users.</comment>
</data>
<data name="Globals_DefaultInputScope.HelpText" xml:space="preserve">
<value>Informiert den IME, welche Sprache standardmäßig verwendet werden soll. Für Sprachen, die auf einem IME basieren und standardmäßig keine lateinischen Zeichen verwenden, kann diese Einstellung verwendet werden, um beim Start die Eingabe in Englisch zu erzwingen.</value>
</data>
<data name="Globals_DefaultInputScopeDefault.Content" xml:space="preserve">
<value>Standard</value>
</data>
<data name="Globals_DefaultInputScopeAlphanumericHalfWidth.Content" xml:space="preserve">
<value>Alphanumerische Halbbreite (Englisch)</value>
</data>
<data name="Globals_AlwaysShowTabs.Header" xml:space="preserve">
<value>Registerkarten immer anzeigen</value>
<comment>Header for a control to toggle if the app should always show the tabs (similar to a website browser).</comment>

View File

@@ -246,22 +246,9 @@
<comment>A description explaining how this control changes the app's language. {Locked="Windows"}</comment>
</data>
<data name="Globals_LanguageDefault" xml:space="preserve">
<value>Default</value>
<value>Use system default</value>
<comment>The app contains a control allowing users to choose the app's language. If this value is chosen, the language preference list of the system settings is used instead.</comment>
</data>
<data name="Globals_DefaultInputScope.Header" xml:space="preserve">
<value>Default IME input mode</value>
<comment>The "input scope" of an IME tells it what type of characters should be available for input. A Chinese IME for instance may show English letters instead of Chinese ones. It's a technical term. We're using "input mode" instead of "input scope" to make it easier to understand for users.</comment>
</data>
<data name="Globals_DefaultInputScope.HelpText" xml:space="preserve">
<value>Informs the IME what language to use by default. For languages that rely on an IME and don't use Latin characters by default, this setting can be used to force English input on startup.</value>
</data>
<data name="Globals_DefaultInputScopeDefault.Content" xml:space="preserve">
<value>Default</value>
</data>
<data name="Globals_DefaultInputScopeAlphanumericHalfWidth.Content" xml:space="preserve">
<value>Alphanumeric Half-Width (English)</value>
</data>
<data name="Globals_AlwaysShowTabs.Header" xml:space="preserve">
<value>Always show tabs</value>
<comment>Header for a control to toggle if the app should always show the tabs (similar to a website browser).</comment>
@@ -1496,6 +1483,18 @@
<value>Add new</value>
<comment>Button label that creates a new color scheme.</comment>
</data>
<data name="ColorScheme_AddNewButton_ConfirmationMessage" xml:space="preserve">
<value>{} added</value>
<comment>{Locked="{}"} Confirmation message announced by the screen reader that the color scheme was successfully added. "{}" will be replaced with the color scheme's name.</comment>
</data>
<data name="ColorScheme_Rename_ConfirmationMessage" xml:space="preserve">
<value>{} renamed to {}</value>
<comment>{Locked="{}"} Confirmation message announced by the screen reader that the color scheme was successfully renamed. "{}" will be replaced with the color scheme's old and new name respectively.</comment>
</data>
<data name="ColorScheme_Delete_ConfirmationMessage" xml:space="preserve">
<value>{} deleted</value>
<comment>{Locked="{}"} Confirmation message announced by the screen reader that the color scheme was successfully deleted. "{}" will be replaced with the color scheme's name.</comment>
</data>
<data name="ColorScheme_DeleteButton.Text" xml:space="preserve">
<value>Delete color scheme</value>
<comment>Button label that deletes the selected color scheme.</comment>
@@ -1552,10 +1551,6 @@
<value>Text</value>
<comment>Header for a group of settings that control the appearance of text in the app.</comment>
</data>
<data name="Globals_WarningsHeader.Text" xml:space="preserve">
<value>Warnings</value>
<comment>Header for a group of settings that control the warnings in the app.</comment>
</data>
<data name="Profile_WindowHeader.Text" xml:space="preserve">
<value>Window</value>
<comment>Header for a group of settings that control the appearance of the window frame of the app.</comment>
@@ -1836,15 +1831,6 @@
<value>Warn when closing more than one tab</value>
<comment>Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open.</comment>
</data>
<data name="Globals_InputServiceWarning.Header" xml:space="preserve">
<value>Warn when "Touch Keyboard and Handwriting Panel Service" is disabled</value>
</data>
<data name="Globals_WarnAboutLargePaste.Header" xml:space="preserve">
<value>Warn when trying to paste more than 5 KiB of characters</value>
</data>
<data name="Globals_WarnAboutMultiLinePaste.Header" xml:space="preserve">
<value>Warn when trying to paste a "new line" character</value>
</data>
<data name="Settings_PortableModeNote.Text" xml:space="preserve">
<value>Windows Terminal is running in portable mode.</value>
<comment>A disclaimer that indicates that Terminal is running in a mode that saves settings to a different folder.</comment>

View File

@@ -246,22 +246,9 @@
<comment>A description explaining how this control changes the app's language. {Locked="Windows"}</comment>
</data>
<data name="Globals_LanguageDefault" xml:space="preserve">
<value>Predeterminado</value>
<value>Usar los valores predeterminados del sistema</value>
<comment>The app contains a control allowing users to choose the app's language. If this value is chosen, the language preference list of the system settings is used instead.</comment>
</data>
<data name="Globals_DefaultInputScope.Header" xml:space="preserve">
<value>Modo de entrada IME predeterminado</value>
<comment>The "input scope" of an IME tells it what type of characters should be available for input. A Chinese IME for instance may show English letters instead of Chinese ones. It's a technical term. We're using "input mode" instead of "input scope" to make it easier to understand for users.</comment>
</data>
<data name="Globals_DefaultInputScope.HelpText" xml:space="preserve">
<value>Informa al IME qué idioma usar de forma predeterminada. Para los idiomas que dependen de un IME y no usan caracteres latinos de forma predeterminada, esta configuración se puede usar para forzar la entrada de inglés al iniciar.</value>
</data>
<data name="Globals_DefaultInputScopeDefault.Content" xml:space="preserve">
<value>Predeterminado</value>
</data>
<data name="Globals_DefaultInputScopeAlphanumericHalfWidth.Content" xml:space="preserve">
<value>Ancho medio alfanumérico (inglés)</value>
</data>
<data name="Globals_AlwaysShowTabs.Header" xml:space="preserve">
<value>Mostrar pestañas siempre</value>
<comment>Header for a control to toggle if the app should always show the tabs (similar to a website browser).</comment>
@@ -1552,10 +1539,6 @@
<value>Texto</value>
<comment>Header for a group of settings that control the appearance of text in the app.</comment>
</data>
<data name="Globals_WarningsHeader.Text" xml:space="preserve">
<value>Advertencias</value>
<comment>Header for a group of settings that control the warnings in the app.</comment>
</data>
<data name="Profile_WindowHeader.Text" xml:space="preserve">
<value>Ventana</value>
<comment>Header for a group of settings that control the appearance of the window frame of the app.</comment>
@@ -1836,15 +1819,6 @@
<value>Advertir al cerrar más de una pestaña</value>
<comment>Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open.</comment>
</data>
<data name="Globals_InputServiceWarning.Header" xml:space="preserve">
<value>Advertir cuando el servicio "Panel de escritura a mano y teclado táctil" está deshabilitado</value>
</data>
<data name="Globals_WarnAboutLargePaste.Header" xml:space="preserve">
<value>Advertir al intentar pegar más de 5 KiB de caracteres</value>
</data>
<data name="Globals_WarnAboutMultiLinePaste.Header" xml:space="preserve">
<value>Advertir al intentar pegar un carácter de "nueva línea"</value>
</data>
<data name="Settings_PortableModeNote.Text" xml:space="preserve">
<value>Terminal Windows se ejecuta en modo portátil.</value>
<comment>A disclaimer that indicates that Terminal is running in a mode that saves settings to a different folder.</comment>

View File

@@ -246,22 +246,9 @@
<comment>A description explaining how this control changes the app's language. {Locked="Windows"}</comment>
</data>
<data name="Globals_LanguageDefault" xml:space="preserve">
<value>Par défaut</value>
<value>Utiliser la valeur par défaut du système</value>
<comment>The app contains a control allowing users to choose the app's language. If this value is chosen, the language preference list of the system settings is used instead.</comment>
</data>
<data name="Globals_DefaultInputScope.Header" xml:space="preserve">
<value>Mode dentrée IME par défaut</value>
<comment>The "input scope" of an IME tells it what type of characters should be available for input. A Chinese IME for instance may show English letters instead of Chinese ones. It's a technical term. We're using "input mode" instead of "input scope" to make it easier to understand for users.</comment>
</data>
<data name="Globals_DefaultInputScope.HelpText" xml:space="preserve">
<value>Indique à IME la langue à utiliser par défaut. Pour les langues qui s'appuient sur un IME et qui n'utilisent pas les caractères latins par défaut, ce paramètre peut être utilisé pour forcer la saisie de l'anglais au démarrage.</value>
</data>
<data name="Globals_DefaultInputScopeDefault.Content" xml:space="preserve">
<value>Par défaut</value>
</data>
<data name="Globals_DefaultInputScopeAlphanumericHalfWidth.Content" xml:space="preserve">
<value>Demi-largeur alphanumérique (anglais)</value>
</data>
<data name="Globals_AlwaysShowTabs.Header" xml:space="preserve">
<value>Toujours afficher les onglets</value>
<comment>Header for a control to toggle if the app should always show the tabs (similar to a website browser).</comment>
@@ -1552,10 +1539,6 @@
<value>Texte</value>
<comment>Header for a group of settings that control the appearance of text in the app.</comment>
</data>
<data name="Globals_WarningsHeader.Text" xml:space="preserve">
<value>Avertissements</value>
<comment>Header for a group of settings that control the warnings in the app.</comment>
</data>
<data name="Profile_WindowHeader.Text" xml:space="preserve">
<value>Fenêtre</value>
<comment>Header for a group of settings that control the appearance of the window frame of the app.</comment>
@@ -1836,15 +1819,6 @@
<value>M'avertir lorsque je ferme plusieurs onglets</value>
<comment>Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open.</comment>
</data>
<data name="Globals_InputServiceWarning.Header" xml:space="preserve">
<value>Avertir lorsque le « service clavier tactile et volet décriture manuscrite » est désactivé</value>
</data>
<data name="Globals_WarnAboutLargePaste.Header" xml:space="preserve">
<value>Avertissement lors de la tentative de collage de plus de 5 Kio de caractères</value>
</data>
<data name="Globals_WarnAboutMultiLinePaste.Header" xml:space="preserve">
<value>Avertir lors de la tentative de collage dun caractère « nouvelle ligne »</value>
</data>
<data name="Settings_PortableModeNote.Text" xml:space="preserve">
<value>Terminal Windows sexécute en mode portable.</value>
<comment>A disclaimer that indicates that Terminal is running in a mode that saves settings to a different folder.</comment>

View File

@@ -246,22 +246,9 @@
<comment>A description explaining how this control changes the app's language. {Locked="Windows"}</comment>
</data>
<data name="Globals_LanguageDefault" xml:space="preserve">
<value>Impostazione predefinita</value>
<value>Usa impostazioni predefinite di sistema</value>
<comment>The app contains a control allowing users to choose the app's language. If this value is chosen, the language preference list of the system settings is used instead.</comment>
</data>
<data name="Globals_DefaultInputScope.Header" xml:space="preserve">
<value>Modalità di input IME predefinita</value>
<comment>The "input scope" of an IME tells it what type of characters should be available for input. A Chinese IME for instance may show English letters instead of Chinese ones. It's a technical term. We're using "input mode" instead of "input scope" to make it easier to understand for users.</comment>
</data>
<data name="Globals_DefaultInputScope.HelpText" xml:space="preserve">
<value>Informa l'IME della lingua da usare per impostazione predefinita. Per le lingue che si affidano a un IME e che non usano i caratteri latini per impostazione predefinita, questa impostazione può essere usata per forzare l'inserimento dell'inglese all'avvio.</value>
</data>
<data name="Globals_DefaultInputScopeDefault.Content" xml:space="preserve">
<value>Impostazione predefinita</value>
</data>
<data name="Globals_DefaultInputScopeAlphanumericHalfWidth.Content" xml:space="preserve">
<value>Mezza larghezza alfanumerica (inglese)</value>
</data>
<data name="Globals_AlwaysShowTabs.Header" xml:space="preserve">
<value>Mostra sempre le schede</value>
<comment>Header for a control to toggle if the app should always show the tabs (similar to a website browser).</comment>
@@ -1552,10 +1539,6 @@
<value>Testo</value>
<comment>Header for a group of settings that control the appearance of text in the app.</comment>
</data>
<data name="Globals_WarningsHeader.Text" xml:space="preserve">
<value>Avvisi</value>
<comment>Header for a group of settings that control the warnings in the app.</comment>
</data>
<data name="Profile_WindowHeader.Text" xml:space="preserve">
<value>Finestra</value>
<comment>Header for a group of settings that control the appearance of the window frame of the app.</comment>
@@ -1836,15 +1819,6 @@
<value>Avvisa in caso di chiusura di più schede</value>
<comment>Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open.</comment>
</data>
<data name="Globals_InputServiceWarning.Header" xml:space="preserve">
<value>Avvisa quando il servizio "Tastiera virtuale e pannello per la grafia" è disabilitato</value>
</data>
<data name="Globals_WarnAboutLargePaste.Header" xml:space="preserve">
<value>Avvisa quando si tenta di incollare più di 5 KiB di caratteri</value>
</data>
<data name="Globals_WarnAboutMultiLinePaste.Header" xml:space="preserve">
<value>Avvisa quando si prova a incollare un carattere "nuova riga"</value>
</data>
<data name="Settings_PortableModeNote.Text" xml:space="preserve">
<value>Terminale Windows è in esecuzione in modalità portatile.</value>
<comment>A disclaimer that indicates that Terminal is running in a mode that saves settings to a different folder.</comment>

View File

@@ -246,22 +246,9 @@
<comment>A description explaining how this control changes the app's language. {Locked="Windows"}</comment>
</data>
<data name="Globals_LanguageDefault" xml:space="preserve">
<value>既定値</value>
<value>システムの既定値を使用</value>
<comment>The app contains a control allowing users to choose the app's language. If this value is chosen, the language preference list of the system settings is used instead.</comment>
</data>
<data name="Globals_DefaultInputScope.Header" xml:space="preserve">
<value>既定の IME 入力モード</value>
<comment>The "input scope" of an IME tells it what type of characters should be available for input. A Chinese IME for instance may show English letters instead of Chinese ones. It's a technical term. We're using "input mode" instead of "input scope" to make it easier to understand for users.</comment>
</data>
<data name="Globals_DefaultInputScope.HelpText" xml:space="preserve">
<value>既定で使用する言語を IME に通知します。IME に依存し、既定ではラテン文字を使用しない言語では、スタートアップ時に英語入力を強制するためにこの設定を使用できます。</value>
</data>
<data name="Globals_DefaultInputScopeDefault.Content" xml:space="preserve">
<value>既定値</value>
</data>
<data name="Globals_DefaultInputScopeAlphanumericHalfWidth.Content" xml:space="preserve">
<value>半角英数字 (英語)</value>
</data>
<data name="Globals_AlwaysShowTabs.Header" xml:space="preserve">
<value>常にタブを表示する</value>
<comment>Header for a control to toggle if the app should always show the tabs (similar to a website browser).</comment>
@@ -1552,10 +1539,6 @@
<value>テキスト</value>
<comment>Header for a group of settings that control the appearance of text in the app.</comment>
</data>
<data name="Globals_WarningsHeader.Text" xml:space="preserve">
<value>警告</value>
<comment>Header for a group of settings that control the warnings in the app.</comment>
</data>
<data name="Profile_WindowHeader.Text" xml:space="preserve">
<value>ウィンドウ</value>
<comment>Header for a group of settings that control the appearance of the window frame of the app.</comment>
@@ -1836,15 +1819,6 @@
<value>複数のタブを閉じるときに警告する</value>
<comment>Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open.</comment>
</data>
<data name="Globals_InputServiceWarning.Header" xml:space="preserve">
<value>[タッチ キーボードと手書きパネル サービス] が無効になっている場合に警告する</value>
</data>
<data name="Globals_WarnAboutLargePaste.Header" xml:space="preserve">
<value>5 KiB を超える文字を貼り付けようとしたときに警告する</value>
</data>
<data name="Globals_WarnAboutMultiLinePaste.Header" xml:space="preserve">
<value>"改行" 文字を貼り付けようとしたときに警告する</value>
</data>
<data name="Settings_PortableModeNote.Text" xml:space="preserve">
<value>Windows ターミナルはポータブル モードで実行されています。</value>
<comment>A disclaimer that indicates that Terminal is running in a mode that saves settings to a different folder.</comment>

View File

@@ -246,22 +246,9 @@
<comment>A description explaining how this control changes the app's language. {Locked="Windows"}</comment>
</data>
<data name="Globals_LanguageDefault" xml:space="preserve">
<value>기본값</value>
<value>시스템 기본값 사용</value>
<comment>The app contains a control allowing users to choose the app's language. If this value is chosen, the language preference list of the system settings is used instead.</comment>
</data>
<data name="Globals_DefaultInputScope.Header" xml:space="preserve">
<value>기본 IME 입력 모드</value>
<comment>The "input scope" of an IME tells it what type of characters should be available for input. A Chinese IME for instance may show English letters instead of Chinese ones. It's a technical term. We're using "input mode" instead of "input scope" to make it easier to understand for users.</comment>
</data>
<data name="Globals_DefaultInputScope.HelpText" xml:space="preserve">
<value>기본적으로 사용할 언어를 IME에 알릴 수 있습니다. IME를 사용하고 기본적으로 라틴 문자를 사용하지 않는 언어의 경우 이 설정을 사용하여 시작할 때 영어 입력을 강제 적용할 수 있습니다.</value>
</data>
<data name="Globals_DefaultInputScopeDefault.Content" xml:space="preserve">
<value>기본값</value>
</data>
<data name="Globals_DefaultInputScopeAlphanumericHalfWidth.Content" xml:space="preserve">
<value>영숫자 반자(영어)</value>
</data>
<data name="Globals_AlwaysShowTabs.Header" xml:space="preserve">
<value>항상 탭 표시</value>
<comment>Header for a control to toggle if the app should always show the tabs (similar to a website browser).</comment>
@@ -1552,10 +1539,6 @@
<value>텍스트</value>
<comment>Header for a group of settings that control the appearance of text in the app.</comment>
</data>
<data name="Globals_WarningsHeader.Text" xml:space="preserve">
<value>경고</value>
<comment>Header for a group of settings that control the warnings in the app.</comment>
</data>
<data name="Profile_WindowHeader.Text" xml:space="preserve">
<value>창</value>
<comment>Header for a group of settings that control the appearance of the window frame of the app.</comment>
@@ -1836,15 +1819,6 @@
<value>두 개 이상의 탭을 닫을 때 경고</value>
<comment>Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open.</comment>
</data>
<data name="Globals_InputServiceWarning.Header" xml:space="preserve">
<value>"터치 키보드 및 필기 패널 서비스"를 사용할 수 없는 경우 경고</value>
</data>
<data name="Globals_WarnAboutLargePaste.Header" xml:space="preserve">
<value>5KiB가 넘는 문자를 붙여넣으려고 할 때 경고</value>
</data>
<data name="Globals_WarnAboutMultiLinePaste.Header" xml:space="preserve">
<value>"줄 바꾸기" 문자를 붙여넣을 때 경고</value>
</data>
<data name="Settings_PortableModeNote.Text" xml:space="preserve">
<value>Windows 터미널이 이식 가능 모드에서 실행되고 있습니다.</value>
<comment>A disclaimer that indicates that Terminal is running in a mode that saves settings to a different folder.</comment>

View File

@@ -246,22 +246,9 @@
<comment>A description explaining how this control changes the app's language. {Locked="Windows"}</comment>
</data>
<data name="Globals_LanguageDefault" xml:space="preserve">
<value>Padrão</value>
<value>Usar o padrão do sistema</value>
<comment>The app contains a control allowing users to choose the app's language. If this value is chosen, the language preference list of the system settings is used instead.</comment>
</data>
<data name="Globals_DefaultInputScope.Header" xml:space="preserve">
<value>Modo de entrada padrão do IME</value>
<comment>The "input scope" of an IME tells it what type of characters should be available for input. A Chinese IME for instance may show English letters instead of Chinese ones. It's a technical term. We're using "input mode" instead of "input scope" to make it easier to understand for users.</comment>
</data>
<data name="Globals_DefaultInputScope.HelpText" xml:space="preserve">
<value>Informa ao IME qual idioma usar por padrão. Para idiomas que dependem de um IME e não utilizam caracteres latinos por padrão, essa configuração pode forçar a entrada em inglês na inicialização.</value>
</data>
<data name="Globals_DefaultInputScopeDefault.Content" xml:space="preserve">
<value>Padrão</value>
</data>
<data name="Globals_DefaultInputScopeAlphanumericHalfWidth.Content" xml:space="preserve">
<value>Alfanumérico Meia-Largura (Inglês)</value>
</data>
<data name="Globals_AlwaysShowTabs.Header" xml:space="preserve">
<value>Sempre mostrar as guias</value>
<comment>Header for a control to toggle if the app should always show the tabs (similar to a website browser).</comment>

View File

@@ -246,22 +246,9 @@
<comment>A description explaining how this control changes the app's language. {Locked="Windows"}</comment>
</data>
<data name="Globals_LanguageDefault" xml:space="preserve">
<value>Ďėƒąūļτ !!</value>
<value>Ůŝê ѕŷŝτėм đєƒāùľŧ !!! !!</value>
<comment>The app contains a control allowing users to choose the app's language. If this value is chosen, the language preference list of the system settings is used instead.</comment>
</data>
<data name="Globals_DefaultInputScope.Header" xml:space="preserve">
<value>Đέƒàųŀт ĨΜЗ ΐήрũŧ mоδę !!! !!! </value>
<comment>The "input scope" of an IME tells it what type of characters should be available for input. A Chinese IME for instance may show English letters instead of Chinese ones. It's a technical term. We're using "input mode" instead of "input scope" to make it easier to understand for users.</comment>
</data>
<data name="Globals_DefaultInputScope.HelpText" xml:space="preserve">
<value>Íŋƒбгмş ţђе ÎМЕ ẁћдŧ ļàņĝŭªġé ŧб üśе ьý ðěƒαűľŧ. ₣òѓ ļάņģųαģєś ţћáŧ ґ℮ŀу öŋ àи ĪΜÊ ǻйð δŏй'т цѕέ £âтĩŋ çħãѓâćтèřš ъγ ðėƒāџľŧ, ţнϊś ŝэťтĭñġ ċάń ье цѕёð τό ƒóřċε ∑ήģĺîѕħ îήρüт οŋ şŧªřťúр. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !</value>
</data>
<data name="Globals_DefaultInputScopeDefault.Content" xml:space="preserve">
<value>Ðеƒãϋĺţ !!</value>
</data>
<data name="Globals_DefaultInputScopeAlphanumericHalfWidth.Content" xml:space="preserve">
<value>Дĺρħăпυмегїç Ηâŀƒ-Щιδτĥ (Ęñģℓîšĥ) !!! !!! !!! </value>
</data>
<data name="Globals_AlwaysShowTabs.Header" xml:space="preserve">
<value>Άľώāŷš şђǿŵ тãвŝ !!! !</value>
<comment>Header for a control to toggle if the app should always show the tabs (similar to a website browser).</comment>
@@ -1552,10 +1539,6 @@
<value>Ţέхţ !</value>
<comment>Header for a group of settings that control the appearance of text in the app.</comment>
</data>
<data name="Globals_WarningsHeader.Text" xml:space="preserve">
<value>Ẅåŕⁿįņğѕ !!</value>
<comment>Header for a group of settings that control the warnings in the app.</comment>
</data>
<data name="Profile_WindowHeader.Text" xml:space="preserve">
<value>Щіňďош !</value>
<comment>Header for a group of settings that control the appearance of the window frame of the app.</comment>
@@ -1836,15 +1819,6 @@
<value>Ẃářй ẅђëπ ĉľôśĩήĝ mǿѓĕ тĥąπ òπё τάь !!! !!! !!! !</value>
<comment>Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open.</comment>
</data>
<data name="Globals_InputServiceWarning.Header" xml:space="preserve">
<value>Ẃǻґņ ώћĕπ "Ŧõũčђ Κзγьοдгď ąʼnð Нáлđẅŕīťίńģ Ρàňεℓ Śεŕνîçé" íš đìşāъŀêδ !!! !!! !!! !!! !!! !!! !!</value>
</data>
<data name="Globals_WarnAboutLargePaste.Header" xml:space="preserve">
<value>Ẃăґи ẅнěπ тґўіήĝ τø рáŝťё mοřé ţħäή 5 ΚĩВ òƒ ĉħāґąćτєґѕ !!! !!! !!! !!! !!! !</value>
</data>
<data name="Globals_WarnAboutMultiLinePaste.Header" xml:space="preserve">
<value>Щāřπ ẃĥєи ťгýīлğ ţõ ρäşŧè ª "пėщ ľїл℮" ςћářǻ¢ţēř !!! !!! !!! !!! !!</value>
</data>
<data name="Settings_PortableModeNote.Text" xml:space="preserve">
<value>Ẅїηðσшѕ Ţеřmíńăľ īѕ ґϋййïʼnģ ĭņ рόѓťáъℓė mōďе. !!! !!! !!! !!! !</value>
<comment>A disclaimer that indicates that Terminal is running in a mode that saves settings to a different folder.</comment>

View File

@@ -246,22 +246,9 @@
<comment>A description explaining how this control changes the app's language. {Locked="Windows"}</comment>
</data>
<data name="Globals_LanguageDefault" xml:space="preserve">
<value>Ďėƒąūļτ !!</value>
<value>Ůŝê ѕŷŝτėм đєƒāùľŧ !!! !!</value>
<comment>The app contains a control allowing users to choose the app's language. If this value is chosen, the language preference list of the system settings is used instead.</comment>
</data>
<data name="Globals_DefaultInputScope.Header" xml:space="preserve">
<value>Đέƒàųŀт ĨΜЗ ΐήрũŧ mоδę !!! !!! </value>
<comment>The "input scope" of an IME tells it what type of characters should be available for input. A Chinese IME for instance may show English letters instead of Chinese ones. It's a technical term. We're using "input mode" instead of "input scope" to make it easier to understand for users.</comment>
</data>
<data name="Globals_DefaultInputScope.HelpText" xml:space="preserve">
<value>Íŋƒбгмş ţђе ÎМЕ ẁћдŧ ļàņĝŭªġé ŧб üśе ьý ðěƒαűľŧ. ₣òѓ ļάņģųαģєś ţћáŧ ґ℮ŀу öŋ àи ĪΜÊ ǻйð δŏй'т цѕέ £âтĩŋ çħãѓâćтèřš ъγ ðėƒāџľŧ, ţнϊś ŝэťтĭñġ ċάń ье цѕёð τό ƒóřċε ∑ήģĺîѕħ îήρüт οŋ şŧªřťúр. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !</value>
</data>
<data name="Globals_DefaultInputScopeDefault.Content" xml:space="preserve">
<value>Ðеƒãϋĺţ !!</value>
</data>
<data name="Globals_DefaultInputScopeAlphanumericHalfWidth.Content" xml:space="preserve">
<value>Дĺρħăпυмегїç Ηâŀƒ-Щιδτĥ (Ęñģℓîšĥ) !!! !!! !!! </value>
</data>
<data name="Globals_AlwaysShowTabs.Header" xml:space="preserve">
<value>Άľώāŷš şђǿŵ тãвŝ !!! !</value>
<comment>Header for a control to toggle if the app should always show the tabs (similar to a website browser).</comment>
@@ -1552,10 +1539,6 @@
<value>Ţέхţ !</value>
<comment>Header for a group of settings that control the appearance of text in the app.</comment>
</data>
<data name="Globals_WarningsHeader.Text" xml:space="preserve">
<value>Ẅåŕⁿįņğѕ !!</value>
<comment>Header for a group of settings that control the warnings in the app.</comment>
</data>
<data name="Profile_WindowHeader.Text" xml:space="preserve">
<value>Щіňďош !</value>
<comment>Header for a group of settings that control the appearance of the window frame of the app.</comment>
@@ -1836,15 +1819,6 @@
<value>Ẃářй ẅђëπ ĉľôśĩήĝ mǿѓĕ тĥąπ òπё τάь !!! !!! !!! !</value>
<comment>Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open.</comment>
</data>
<data name="Globals_InputServiceWarning.Header" xml:space="preserve">
<value>Ẃǻґņ ώћĕπ "Ŧõũčђ Κзγьοдгď ąʼnð Нáлđẅŕīťίńģ Ρàňεℓ Śεŕνîçé" íš đìşāъŀêδ !!! !!! !!! !!! !!! !!! !!</value>
</data>
<data name="Globals_WarnAboutLargePaste.Header" xml:space="preserve">
<value>Ẃăґи ẅнěπ тґўіήĝ τø рáŝťё mοřé ţħäή 5 ΚĩВ òƒ ĉħāґąćτєґѕ !!! !!! !!! !!! !!! !</value>
</data>
<data name="Globals_WarnAboutMultiLinePaste.Header" xml:space="preserve">
<value>Щāřπ ẃĥєи ťгýīлğ ţõ ρäşŧè ª "пėщ ľїл℮" ςћářǻ¢ţēř !!! !!! !!! !!! !!</value>
</data>
<data name="Settings_PortableModeNote.Text" xml:space="preserve">
<value>Ẅїηðσшѕ Ţеřmíńăľ īѕ ґϋййïʼnģ ĭņ рόѓťáъℓė mōďе. !!! !!! !!! !!! !</value>
<comment>A disclaimer that indicates that Terminal is running in a mode that saves settings to a different folder.</comment>

View File

@@ -246,22 +246,9 @@
<comment>A description explaining how this control changes the app's language. {Locked="Windows"}</comment>
</data>
<data name="Globals_LanguageDefault" xml:space="preserve">
<value>Ďėƒąūļτ !!</value>
<value>Ůŝê ѕŷŝτėм đєƒāùľŧ !!! !!</value>
<comment>The app contains a control allowing users to choose the app's language. If this value is chosen, the language preference list of the system settings is used instead.</comment>
</data>
<data name="Globals_DefaultInputScope.Header" xml:space="preserve">
<value>Đέƒàųŀт ĨΜЗ ΐήрũŧ mоδę !!! !!! </value>
<comment>The "input scope" of an IME tells it what type of characters should be available for input. A Chinese IME for instance may show English letters instead of Chinese ones. It's a technical term. We're using "input mode" instead of "input scope" to make it easier to understand for users.</comment>
</data>
<data name="Globals_DefaultInputScope.HelpText" xml:space="preserve">
<value>Íŋƒбгмş ţђе ÎМЕ ẁћдŧ ļàņĝŭªġé ŧб üśе ьý ðěƒαűľŧ. ₣òѓ ļάņģųαģєś ţћáŧ ґ℮ŀу öŋ àи ĪΜÊ ǻйð δŏй'т цѕέ £âтĩŋ çħãѓâćтèřš ъγ ðėƒāџľŧ, ţнϊś ŝэťтĭñġ ċάń ье цѕёð τό ƒóřċε ∑ήģĺîѕħ îήρüт οŋ şŧªřťúр. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !</value>
</data>
<data name="Globals_DefaultInputScopeDefault.Content" xml:space="preserve">
<value>Ðеƒãϋĺţ !!</value>
</data>
<data name="Globals_DefaultInputScopeAlphanumericHalfWidth.Content" xml:space="preserve">
<value>Дĺρħăпυмегїç Ηâŀƒ-Щιδτĥ (Ęñģℓîšĥ) !!! !!! !!! </value>
</data>
<data name="Globals_AlwaysShowTabs.Header" xml:space="preserve">
<value>Άľώāŷš şђǿŵ тãвŝ !!! !</value>
<comment>Header for a control to toggle if the app should always show the tabs (similar to a website browser).</comment>
@@ -1552,10 +1539,6 @@
<value>Ţέхţ !</value>
<comment>Header for a group of settings that control the appearance of text in the app.</comment>
</data>
<data name="Globals_WarningsHeader.Text" xml:space="preserve">
<value>Ẅåŕⁿįņğѕ !!</value>
<comment>Header for a group of settings that control the warnings in the app.</comment>
</data>
<data name="Profile_WindowHeader.Text" xml:space="preserve">
<value>Щіňďош !</value>
<comment>Header for a group of settings that control the appearance of the window frame of the app.</comment>
@@ -1836,15 +1819,6 @@
<value>Ẃářй ẅђëπ ĉľôśĩήĝ mǿѓĕ тĥąπ òπё τάь !!! !!! !!! !</value>
<comment>Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open.</comment>
</data>
<data name="Globals_InputServiceWarning.Header" xml:space="preserve">
<value>Ẃǻґņ ώћĕπ "Ŧõũčђ Κзγьοдгď ąʼnð Нáлđẅŕīťίńģ Ρàňεℓ Śεŕνîçé" íš đìşāъŀêδ !!! !!! !!! !!! !!! !!! !!</value>
</data>
<data name="Globals_WarnAboutLargePaste.Header" xml:space="preserve">
<value>Ẃăґи ẅнěπ тґўіήĝ τø рáŝťё mοřé ţħäή 5 ΚĩВ òƒ ĉħāґąćτєґѕ !!! !!! !!! !!! !!! !</value>
</data>
<data name="Globals_WarnAboutMultiLinePaste.Header" xml:space="preserve">
<value>Щāřπ ẃĥєи ťгýīлğ ţõ ρäşŧè ª "пėщ ľїл℮" ςћářǻ¢ţēř !!! !!! !!! !!! !!</value>
</data>
<data name="Settings_PortableModeNote.Text" xml:space="preserve">
<value>Ẅїηðσшѕ Ţеřmíńăľ īѕ ґϋййïʼnģ ĭņ рόѓťáъℓė mōďе. !!! !!! !!! !!! !</value>
<comment>A disclaimer that indicates that Terminal is running in a mode that saves settings to a different folder.</comment>

View File

@@ -246,22 +246,9 @@
<comment>A description explaining how this control changes the app's language. {Locked="Windows"}</comment>
</data>
<data name="Globals_LanguageDefault" xml:space="preserve">
<value>По умолчанию</value>
<value>Использовать системные параметры по умолчанию</value>
<comment>The app contains a control allowing users to choose the app's language. If this value is chosen, the language preference list of the system settings is used instead.</comment>
</data>
<data name="Globals_DefaultInputScope.Header" xml:space="preserve">
<value>Режим ввода IME по умолчанию</value>
<comment>The "input scope" of an IME tells it what type of characters should be available for input. A Chinese IME for instance may show English letters instead of Chinese ones. It's a technical term. We're using "input mode" instead of "input scope" to make it easier to understand for users.</comment>
</data>
<data name="Globals_DefaultInputScope.HelpText" xml:space="preserve">
<value>Сообщает IME, какой язык нужно использовать по умолчанию. Для языков, которые применяют IME и не используют латинские символы по умолчанию, этот параметр можно использовать для принудительного ввода на английском языке при запуске.</value>
</data>
<data name="Globals_DefaultInputScopeDefault.Content" xml:space="preserve">
<value>По умолчанию</value>
</data>
<data name="Globals_DefaultInputScopeAlphanumericHalfWidth.Content" xml:space="preserve">
<value>Буквенно-цифровой полуширинный (английский)</value>
</data>
<data name="Globals_AlwaysShowTabs.Header" xml:space="preserve">
<value>Всегда отображать вкладки</value>
<comment>Header for a control to toggle if the app should always show the tabs (similar to a website browser).</comment>
@@ -1552,10 +1539,6 @@
<value>Текст</value>
<comment>Header for a group of settings that control the appearance of text in the app.</comment>
</data>
<data name="Globals_WarningsHeader.Text" xml:space="preserve">
<value>Предупреждения</value>
<comment>Header for a group of settings that control the warnings in the app.</comment>
</data>
<data name="Profile_WindowHeader.Text" xml:space="preserve">
<value>Окно</value>
<comment>Header for a group of settings that control the appearance of the window frame of the app.</comment>
@@ -1836,15 +1819,6 @@
<value>Предупреждать при закрытии нескольких вкладок</value>
<comment>Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open.</comment>
</data>
<data name="Globals_InputServiceWarning.Header" xml:space="preserve">
<value>Предупреждать, если параметр "Служба сенсорной клавиатуры и панели рукописного ввода" отключен</value>
</data>
<data name="Globals_WarnAboutLargePaste.Header" xml:space="preserve">
<value>Предупреждать при попытке вставки более 5 КиБ символов</value>
</data>
<data name="Globals_WarnAboutMultiLinePaste.Header" xml:space="preserve">
<value>Предупреждать при попытке вставки символа "новая строка"</value>
</data>
<data name="Settings_PortableModeNote.Text" xml:space="preserve">
<value>Терминал Windows работает в переносном режиме.</value>
<comment>A disclaimer that indicates that Terminal is running in a mode that saves settings to a different folder.</comment>

View File

@@ -246,22 +246,9 @@
<comment>A description explaining how this control changes the app's language. {Locked="Windows"}</comment>
</data>
<data name="Globals_LanguageDefault" xml:space="preserve">
<value>默认</value>
<value>使用系统默认</value>
<comment>The app contains a control allowing users to choose the app's language. If this value is chosen, the language preference list of the system settings is used instead.</comment>
</data>
<data name="Globals_DefaultInputScope.Header" xml:space="preserve">
<value>默认输入法输入模式</value>
<comment>The "input scope" of an IME tells it what type of characters should be available for input. A Chinese IME for instance may show English letters instead of Chinese ones. It's a technical term. We're using "input mode" instead of "input scope" to make it easier to understand for users.</comment>
</data>
<data name="Globals_DefaultInputScope.HelpText" xml:space="preserve">
<value>告知输入法默认使用的语言。对于依赖于输入法且默认不使用拉丁字符的语言,此设置可用于在启动时强制进行英语输入。</value>
</data>
<data name="Globals_DefaultInputScopeDefault.Content" xml:space="preserve">
<value>默认</value>
</data>
<data name="Globals_DefaultInputScopeAlphanumericHalfWidth.Content" xml:space="preserve">
<value>字母数字半角(英语)</value>
</data>
<data name="Globals_AlwaysShowTabs.Header" xml:space="preserve">
<value>始终显示选项卡</value>
<comment>Header for a control to toggle if the app should always show the tabs (similar to a website browser).</comment>
@@ -1170,7 +1157,7 @@
<comment>Header for a control to determine the title of the tab. This is represented using a text box.</comment>
</data>
<data name="Profile_TabTitle.HelpText" xml:space="preserve">
<value>将配置文件名称替换为标题,以在启动时传递给 shell。</value>
<value>将配置文件名称替换为标题,以在启动时传递给外壳。</value>
<comment>A description for what the "tab title" setting does. Presented near "Profile_TabTitle".</comment>
</data>
<data name="Profile_UnfocusedAppearanceTextBlock.Text" xml:space="preserve">
@@ -1552,10 +1539,6 @@
<value>文本</value>
<comment>Header for a group of settings that control the appearance of text in the app.</comment>
</data>
<data name="Globals_WarningsHeader.Text" xml:space="preserve">
<value>警告</value>
<comment>Header for a group of settings that control the warnings in the app.</comment>
</data>
<data name="Profile_WindowHeader.Text" xml:space="preserve">
<value>窗口</value>
<comment>Header for a group of settings that control the appearance of the window frame of the app.</comment>
@@ -1836,15 +1819,6 @@
<value>关闭多个选项卡时发出警告</value>
<comment>Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open.</comment>
</data>
<data name="Globals_InputServiceWarning.Header" xml:space="preserve">
<value>禁用“触摸键盘和手写面板服务”时发出警告</value>
</data>
<data name="Globals_WarnAboutLargePaste.Header" xml:space="preserve">
<value>尝试粘贴超过 5 KiB 字符时发出警告</value>
</data>
<data name="Globals_WarnAboutMultiLinePaste.Header" xml:space="preserve">
<value>尝试粘贴“新行”字符时发出警告</value>
</data>
<data name="Settings_PortableModeNote.Text" xml:space="preserve">
<value>Windows 终端正在便携模式下运行。</value>
<comment>A disclaimer that indicates that Terminal is running in a mode that saves settings to a different folder.</comment>

View File

@@ -246,22 +246,9 @@
<comment>A description explaining how this control changes the app's language. {Locked="Windows"}</comment>
</data>
<data name="Globals_LanguageDefault" xml:space="preserve">
<value>預設</value>
<value>使用系統預設</value>
<comment>The app contains a control allowing users to choose the app's language. If this value is chosen, the language preference list of the system settings is used instead.</comment>
</data>
<data name="Globals_DefaultInputScope.Header" xml:space="preserve">
<value>預設 IME 輸入模式</value>
<comment>The "input scope" of an IME tells it what type of characters should be available for input. A Chinese IME for instance may show English letters instead of Chinese ones. It's a technical term. We're using "input mode" instead of "input scope" to make it easier to understand for users.</comment>
</data>
<data name="Globals_DefaultInputScope.HelpText" xml:space="preserve">
<value>通知 IME 預設使用的語言。對於依賴 IME 且預設不使用拉丁字元的語言,此設定可用來強制啟動英文輸入。</value>
</data>
<data name="Globals_DefaultInputScopeDefault.Content" xml:space="preserve">
<value>預設</value>
</data>
<data name="Globals_DefaultInputScopeAlphanumericHalfWidth.Content" xml:space="preserve">
<value>英數字元半寬 (英文)</value>
</data>
<data name="Globals_AlwaysShowTabs.Header" xml:space="preserve">
<value>永遠顯示索引標籤</value>
<comment>Header for a control to toggle if the app should always show the tabs (similar to a website browser).</comment>
@@ -1552,10 +1539,6 @@
<value>文字</value>
<comment>Header for a group of settings that control the appearance of text in the app.</comment>
</data>
<data name="Globals_WarningsHeader.Text" xml:space="preserve">
<value>警告</value>
<comment>Header for a group of settings that control the warnings in the app.</comment>
</data>
<data name="Profile_WindowHeader.Text" xml:space="preserve">
<value>視窗</value>
<comment>Header for a group of settings that control the appearance of the window frame of the app.</comment>
@@ -1836,15 +1819,6 @@
<value>關閉多個索引標籤時發出警告</value>
<comment>Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open.</comment>
</data>
<data name="Globals_InputServiceWarning.Header" xml:space="preserve">
<value>停用「觸控式鍵盤和手寫面板服務」時發出警告</value>
</data>
<data name="Globals_WarnAboutLargePaste.Header" xml:space="preserve">
<value>嘗試貼上超過 5 個 KiB 字元時發出警告</value>
</data>
<data name="Globals_WarnAboutMultiLinePaste.Header" xml:space="preserve">
<value>嘗試貼上「新行」字元時發出警告</value>
</data>
<data name="Settings_PortableModeNote.Text" xml:space="preserve">
<value>Windows 終端機正以可攜式模式執行。</value>
<comment>A disclaimer that indicates that Terminal is running in a mode that saves settings to a different folder.</comment>

View File

@@ -44,9 +44,6 @@
<StaticResource x:Key="SettingContainerMessageForeground"
ResourceKey="TextFillColorPrimaryBrush" />
<StaticResource x:Key="SettingContainerResetButtonIconForeground"
ResourceKey="SystemAccentColorDark2" />
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<Style x:Key="SecondaryTextBlockStyle"
@@ -76,9 +73,6 @@
ResourceKey="SystemColorWindowTextColorBrush" />
<StaticResource x:Key="SettingContainerMessageForeground"
ResourceKey="SystemColorWindowTextColorBrush" />
<StaticResource x:Key="SettingContainerResetButtonIconForeground"
ResourceKey="SystemAccentColorLight1" />
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<Style x:Key="SecondaryTextBlockStyle"
@@ -112,9 +106,6 @@
ResourceKey="TextFillColorPrimaryBrush" />
<StaticResource x:Key="SettingContainerMessageForeground"
ResourceKey="TextFillColorPrimaryBrush" />
<StaticResource x:Key="SettingContainerResetButtonIconForeground"
ResourceKey="SystemAccentColorLight2" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
@@ -145,7 +136,7 @@
<Style x:Key="SettingContainerFontIconStyle"
TargetType="FontIcon">
<Setter Property="Foreground" Value="{ThemeResource SettingContainerResetButtonIconForeground}" />
<Setter Property="Foreground" Value="{StaticResource SystemAccentColor}" />
<Setter Property="FontSize" Value="11" />
<Setter Property="FontFamily" Value="{ThemeResource SymbolThemeFontFamily}" />
</Style>

View File

@@ -33,7 +33,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
DEFINE_ENUM_MAP(winrt::Windows::UI::Xaml::ElementTheme, ElementTheme);
DEFINE_ENUM_MAP(Model::NewTabPosition, NewTabPosition);
DEFINE_ENUM_MAP(winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, TabViewWidthMode);
DEFINE_ENUM_MAP(Microsoft::Terminal::Control::DefaultInputScope, DefaultInputScope);
DEFINE_ENUM_MAP(Model::FirstWindowPreference, FirstWindowPreference);
DEFINE_ENUM_MAP(Model::LaunchMode, LaunchMode);
DEFINE_ENUM_MAP(Model::TabSwitcherMode, TabSwitcherMode);

View File

@@ -29,7 +29,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Windows::UI::Xaml::ElementTheme> ElementTheme();
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, NewTabPosition> NewTabPosition();
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode> TabViewWidthMode();
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Control::DefaultInputScope> DefaultInputScope();
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, FirstWindowPreference> FirstWindowPreference();
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, LaunchMode> LaunchMode();
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, TabSwitcherMode> TabSwitcherMode();

View File

@@ -11,7 +11,6 @@ namespace Microsoft.Terminal.Settings.Model
static Windows.Foundation.Collections.IMap<String, Windows.UI.Xaml.ElementTheme> ElementTheme { get; };
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.NewTabPosition> NewTabPosition { get; };
static Windows.Foundation.Collections.IMap<String, Microsoft.UI.Xaml.Controls.TabViewWidthMode> TabViewWidthMode { get; };
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Control.DefaultInputScope> DefaultInputScope { get; };
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.FirstWindowPreference> FirstWindowPreference { get; };
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.LaunchMode> LaunchMode { get; };
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.TabSwitcherMode> TabSwitcherMode { get; };

View File

@@ -23,10 +23,6 @@ static constexpr std::string_view ThemeKey{ "theme" };
static constexpr std::string_view DefaultProfileKey{ "defaultProfile" };
static constexpr std::string_view LegacyUseTabSwitcherModeKey{ "useTabSwitcher" };
static constexpr std::string_view LegacyReloadEnvironmentVariablesKey{ "compatibility.reloadEnvironmentVariables" };
static constexpr std::string_view LegacyInputServiceWarningKey{ "inputServiceWarning" };
static constexpr std::string_view LegacyWarnAboutLargePasteKey{ "largePasteWarning" };
static constexpr std::string_view LegacyWarnAboutMultiLinePasteKey{ "multiLinePasteWarning" };
static constexpr std::string_view LegacyConfirmCloseAllTabsKey{ "confirmCloseAllTabs" };
// Method Description:
// - Copies any extraneous data from the parent before completing a CreateChild call
@@ -136,12 +132,7 @@ void GlobalAppSettings::LayerJson(const Json::Value& json, const OriginTag origi
// GH#8076 - when adding enum values to this key, we also changed it from
// "useTabSwitcher" to "tabSwitcherMode". Continue supporting
// "useTabSwitcher", but prefer "tabSwitcherMode"
_fixupsAppliedDuringLoad = JsonUtils::GetValueForKey(json, LegacyUseTabSwitcherModeKey, _TabSwitcherMode) || _fixupsAppliedDuringLoad;
_fixupsAppliedDuringLoad = JsonUtils::GetValueForKey(json, LegacyInputServiceWarningKey, _InputServiceWarning) || _fixupsAppliedDuringLoad;
_fixupsAppliedDuringLoad = JsonUtils::GetValueForKey(json, LegacyWarnAboutLargePasteKey, _WarnAboutLargePaste) || _fixupsAppliedDuringLoad;
_fixupsAppliedDuringLoad = JsonUtils::GetValueForKey(json, LegacyWarnAboutMultiLinePasteKey, _WarnAboutMultiLinePaste) || _fixupsAppliedDuringLoad;
_fixupsAppliedDuringLoad = JsonUtils::GetValueForKey(json, LegacyConfirmCloseAllTabsKey, _ConfirmCloseAllTabs) || _fixupsAppliedDuringLoad;
JsonUtils::GetValueForKey(json, LegacyUseTabSwitcherModeKey, _TabSwitcherMode);
#define GLOBAL_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \
JsonUtils::GetValueForKey(json, jsonKey, _##name); \
@@ -163,8 +154,6 @@ void GlobalAppSettings::LayerJson(const Json::Value& json, const OriginTag origi
}
LayerActionsFrom(json, origin, true);
// No need to update _fixupsAppliedDuringLoad here.
// We already handle this in SettingsLoader::FixupUserSettings().
JsonUtils::GetValueForKey(json, LegacyReloadEnvironmentVariablesKey, _legacyReloadEnvironmentVariables);
if (json[LegacyReloadEnvironmentVariablesKey.data()])
{
@@ -280,10 +269,6 @@ Json::Value GlobalAppSettings::ToJson()
{
_TextMeasurement.reset();
}
if (_DefaultInputScope == Control::DefaultInputScope::Default)
{
_DefaultInputScope.reset();
}
if (_DisablePartialInvalidation == false)
{
@@ -311,7 +296,7 @@ Json::Value GlobalAppSettings::ToJson()
bool GlobalAppSettings::FixupsAppliedDuringLoad()
{
return _fixupsAppliedDuringLoad || _actionMap->FixupsAppliedDuringLoad();
return _actionMap->FixupsAppliedDuringLoad();
}
winrt::Microsoft::Terminal::Settings::Model::Theme GlobalAppSettings::CurrentTheme() noexcept

View File

@@ -89,7 +89,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
#endif
winrt::guid _defaultProfile{};
bool _fixupsAppliedDuringLoad{ false };
bool _legacyReloadEnvironmentVariables{ true };
winrt::com_ptr<implementation::ActionMap> _actionMap{ winrt::make_self<implementation::ActionMap>() };
std::set<std::string> _changeLog;

View File

@@ -73,7 +73,6 @@ namespace Microsoft.Terminal.Settings.Model
INHERITABLE_SETTING(Boolean, TrimPaste);
INHERITABLE_SETTING(LaunchPosition, InitialPosition);
INHERITABLE_SETTING(Boolean, CenterOnLaunch);
INHERITABLE_SETTING(Microsoft.Terminal.Control.DefaultInputScope, DefaultInputScope);
INHERITABLE_SETTING(FirstWindowPreference, FirstWindowPreference);
INHERITABLE_SETTING(LaunchMode, LaunchMode);
INHERITABLE_SETTING(Boolean, SnapToGridOnResize);

View File

@@ -28,7 +28,6 @@ Author(s):
X(bool, DisablePartialInvalidation, "rendering.disablePartialInvalidation", false) \
X(bool, SoftwareRendering, "rendering.software", false) \
X(winrt::Microsoft::Terminal::Control::TextMeasurement, TextMeasurement, "compatibility.textMeasurement") \
X(winrt::Microsoft::Terminal::Control::DefaultInputScope, DefaultInputScope, "defaultInputScope") \
X(bool, UseBackgroundImageForWindow, "experimental.useBackgroundImageForWindow", false) \
X(bool, ForceVTInput, "experimental.input.forceVT", false) \
X(bool, TrimBlockSelection, "trimBlockSelection", true) \
@@ -36,16 +35,16 @@ Author(s):
X(bool, AlwaysShowTabs, "alwaysShowTabs", true) \
X(Model::NewTabPosition, NewTabPosition, "newTabPosition", Model::NewTabPosition::AfterLastTab) \
X(bool, ShowTitleInTitlebar, "showTerminalTitleInTitlebar", true) \
X(bool, ConfirmCloseAllTabs, "warning.confirmCloseAllTabs", true) \
X(bool, ConfirmCloseAllTabs, "confirmCloseAllTabs", true) \
X(Model::ThemePair, Theme, "theme") \
X(hstring, Language, "language") \
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, "warning.inputService", true) \
X(bool, InputServiceWarning, "inputServiceWarning", true) \
X(winrt::Microsoft::Terminal::Control::CopyFormat, CopyFormatting, "copyFormatting", 0) \
X(bool, WarnAboutLargePaste, "warning.largePaste", true) \
X(bool, WarnAboutMultiLinePaste, "warning.multiLinePaste", true) \
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) \

View File

@@ -368,7 +368,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
_DisablePartialInvalidation = globalSettings.DisablePartialInvalidation();
_SoftwareRendering = globalSettings.SoftwareRendering();
_TextMeasurement = globalSettings.TextMeasurement();
_DefaultInputScope = globalSettings.DefaultInputScope();
_UseBackgroundImageForWindow = globalSettings.UseBackgroundImageForWindow();
_ForceVTInput = globalSettings.ForceVTInput();
_TrimBlockSelection = globalSettings.TrimBlockSelection();

View File

@@ -161,7 +161,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
INHERITABLE_SETTING(Model::TerminalSettings, bool, DisablePartialInvalidation, false);
INHERITABLE_SETTING(Model::TerminalSettings, bool, SoftwareRendering, false);
INHERITABLE_SETTING(Model::TerminalSettings, Microsoft::Terminal::Control::TextMeasurement, TextMeasurement);
INHERITABLE_SETTING(Model::TerminalSettings, Microsoft::Terminal::Control::DefaultInputScope, DefaultInputScope);
INHERITABLE_SETTING(Model::TerminalSettings, bool, UseBackgroundImageForWindow, false);
INHERITABLE_SETTING(Model::TerminalSettings, bool, ForceVTInput, false);

View File

@@ -782,11 +782,3 @@ JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Control::TextMeasurement)
pair_type{ "console", ValueType::Console },
};
};
JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Control::DefaultInputScope)
{
JSON_MAPPINGS(2) = {
pair_type{ "default", ValueType::Default },
pair_type{ "alphanumericHalfWidth", ValueType::AlphanumericHalfWidth },
};
};

View File

@@ -304,9 +304,9 @@ namespace ControlUnitTests
Log::Comment(L"Check the buffer after the clear");
VERIFY_ARE_EQUAL(20, core->_terminal->GetViewport().Height());
VERIFY_ARE_EQUAL(41, core->ScrollOffset());
VERIFY_ARE_EQUAL(21, core->ScrollOffset());
VERIFY_ARE_EQUAL(20, core->ViewHeight());
VERIFY_ARE_EQUAL(61, core->BufferHeight());
VERIFY_ARE_EQUAL(41, core->BufferHeight());
// In this test, we can't actually check if we cleared the buffer
// contents. ConPTY will handle the actual clearing of the buffer

View File

@@ -107,6 +107,7 @@ namespace SettingsModelUnitTests
"initialPosition": ",",
"launchMode": "default",
"alwaysOnTop": false,
"inputServiceWarning": true,
"copyOnSelect": false,
"copyFormatting": "all",
"wordDelimiters": " /\\()\"'-.,:;<>~!@#$%^&*|+=[]{}~?\u2502",
@@ -122,15 +123,13 @@ namespace SettingsModelUnitTests
"snapToGridOnResize": true,
"disableAnimations": false,
"confirmCloseAllTabs": true,
"largePasteWarning": true,
"multiLinePasteWarning": true,
"trimPaste": true,
"experimental.input.forceVT": false,
"warning.confirmCloseAllTabs" : true,
"warning.inputService" : true,
"warning.largePaste" : true,
"warning.multiLinePaste" : true,
"actions": [],
"keybindings": []
})" };

View File

@@ -1,26 +1,22 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
constexpr std::wstring_view WtExe{ L"wt.exe" };
constexpr std::wstring_view WtdExe{ L"wtd.exe" };
constexpr std::wstring_view WindowsTerminalExe{ L"WindowsTerminal.exe" };
constexpr std::wstring_view LocalAppDataAppsPath{ L"%LOCALAPPDATA%\\Microsoft\\WindowsApps\\" };
constexpr std::wstring_view ElevateShimExe{ L"elevate-shim.exe" };
// Forward declared from appmodel.h so that we don't need to pull in that header everywhere.
extern "C" {
WINBASEAPI LONG WINAPI GetCurrentPackageId(UINT32* bufferLength, BYTE* buffer);
}
#ifdef WINRT_Windows_ApplicationModel_H
_TIL_INLINEPREFIX bool IsPackaged()
{
static const auto isPackaged = []() {
UINT32 bufferLength = 0;
const auto hr = GetCurrentPackageId(&bufferLength, nullptr);
return hr != APPMODEL_ERROR_NO_PACKAGE;
static const auto isPackaged = []() -> bool {
try
{
const auto package = winrt::Windows::ApplicationModel::Package::Current();
return true;
}
catch (...)
{
return false;
}
}();
return isPackaged;
}

View File

@@ -79,7 +79,6 @@
X(bool, DisablePartialInvalidation, false) \
X(bool, SoftwareRendering, false) \
X(winrt::Microsoft::Terminal::Control::TextMeasurement, TextMeasurement) \
X(winrt::Microsoft::Terminal::Control::DefaultInputScope, DefaultInputScope, winrt::Microsoft::Terminal::Control::DefaultInputScope::Default) \
X(bool, UseBackgroundImageForWindow, false) \
X(bool, ShowMarks, false) \
X(winrt::Microsoft::Terminal::Control::CopyFormat, CopyFormatting, 0) \

View File

@@ -7,7 +7,6 @@
#include "output.h"
#include "handle.h"
#include "_stream.h"
#include "../interactivity/inc/ServiceLocator.hpp"
using namespace Microsoft::Console;
@@ -198,9 +197,7 @@ void PtySignalInputThread::_DoClearBuffer() const
}
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
auto& screenInfo = gci.GetActiveOutputBuffer();
auto& stateMachine = screenInfo.GetStateMachine();
stateMachine.ProcessString(L"\x1b[H\x1b[2J");
THROW_IF_FAILED(gci.GetActiveOutputBuffer().ClearBuffer());
}
void PtySignalInputThread::_DoShowHide(const ShowHideData& data)

View File

@@ -44,6 +44,9 @@
<ProjectReference Include="..\..\renderer\base\lib\base.vcxproj">
<Project>{af0a096a-8b3a-4949-81ef-7df8f0fee91f}</Project>
</ProjectReference>
<ProjectReference Include="..\..\renderer\atlas\atlas.vcxproj">
<Project>{8222900C-8B6C-452A-91AC-BE95DB04B95F}</Project>
</ProjectReference>
<ProjectReference Include="..\..\renderer\gdi\lib\gdi.vcxproj">
<Project>{1c959542-bac2-4e55-9a6d-13251914cbb9}</Project>
</ProjectReference>
@@ -89,4 +92,4 @@
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
<Import Project="$(SolutionDir)src\common.build.post.props" />
<Import Project="$(SolutionDir)src\common.nugetversions.targets" />
</Project>
</Project>

View File

@@ -43,7 +43,6 @@
</ItemGroup>
<ItemGroup>
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
</ItemGroup>
<ItemGroup>
<Manifest Include="openconsole.exe.manifest" />

View File

@@ -1267,30 +1267,17 @@ COOKED_READ_DATA::LayoutResult COOKED_READ_DATA::_layoutLine(std::wstring& outpu
output.append(text, 0, len);
column += cols;
it += len;
if (it != nextControlChar)
{
// The only reason that not all text could be fit into the line is if the last character was a wide glyph.
// In that case we want to return the columnLimit, to indicate that the row is full and a line wrap is required,
// BUT DON'T want to pad the line with a whitespace to actually fill the line to the columnLimit.
// This is because copying the prompt contents (Ctrl-A, Ctrl-C) should not copy any trailing padding whitespace.
//
// Thanks to this lie, the _redisplay() code will not use a CRLF sequence or similar to move to the next line,
// as it thinks that this row has naturally wrapped. This causes it to print the wide glyph on the preceding line
// which causes the terminal to insert the padding whitespace for us.
column = columnLimit;
break;
}
if (column >= columnLimit)
{
break;
}
}
const auto nextPlainChar = std::find_if(it, end, [](const auto& wch) { return wch >= L' '; });
for (; it != nextPlainChar; ++it)
{
if (column >= columnLimit)
{
column = columnLimit;
goto outerLoopExit;
}
const auto wch = *it;
wchar_t buf[8];
til::CoordType len = 0;
@@ -1310,20 +1297,11 @@ COOKED_READ_DATA::LayoutResult COOKED_READ_DATA::_layoutLine(std::wstring& outpu
if (column + len > columnLimit)
{
// Unlike above with regular text we can't avoid padding the line with whitespace, because a string
// like "^A" is not a wide glyph, and so we cannot trick the terminal to insert the padding for us.
output.append(columnLimit - column, L' ');
column = columnLimit;
goto outerLoopExit;
}
output.append(buf, len);
column += len;
if (column >= columnLimit)
{
goto outerLoopExit;
}
}
}

View File

@@ -2129,6 +2129,38 @@ void SCREEN_INFORMATION::SetViewport(const Viewport& newViewport,
Tracing::s_TraceWindowViewport(_viewport);
}
// Method Description:
// - Clear the entire contents of the viewport, except for the cursor's row,
// which is moved to the top line of the viewport.
// - This is used exclusively by ConPTY to support GH#1193, GH#1882. This allows
// a terminal to clear the contents of the ConPTY buffer, which is important
// if the user would like to be able to clear the terminal-side buffer.
// Arguments:
// - <none>
// Return Value:
// - S_OK
[[nodiscard]] HRESULT SCREEN_INFORMATION::ClearBuffer()
{
// Rotate the buffer to bring the cursor row to the top of the viewport.
const auto cursorPos = _textBuffer->GetCursor().GetPosition();
for (auto i = 0; i < cursorPos.y; i++)
{
_textBuffer->IncrementCircularBuffer();
}
// Erase everything below that point.
RETURN_IF_FAILED(SetCursorPosition({ 0, 1 }, false));
auto& engine = reinterpret_cast<OutputStateMachineEngine&>(_stateMachine->Engine());
engine.Dispatch().EraseInDisplay(DispatchTypes::EraseType::ToEnd);
// Restore the original cursor x offset, but now on the first row.
RETURN_IF_FAILED(SetCursorPosition({ cursorPos.x, 0 }, false));
_textBuffer->TriggerRedrawAll();
return S_OK;
}
// Routine Description:
// - Writes cells to the output buffer at the cursor position.
// Arguments:

View File

@@ -203,6 +203,8 @@ public:
void SetDefaultAttributes(const TextAttribute& attributes,
const TextAttribute& popupAttributes);
[[nodiscard]] HRESULT ClearBuffer();
void UpdateBottom();
FontInfo& GetCurrentFont() noexcept;

View File

@@ -349,8 +349,6 @@ void Settings::Validate()
TextAttribute::SetLegacyDefaultAttributes(_wFillAttribute);
// And calculate the position of the default colors in the color table.
CalculateDefaultColorIndices();
// We can also then save these values as the default render settings.
SaveDefaultRenderSettings();
FAIL_FAST_IF(!(_dwWindowSize.X > 0));
FAIL_FAST_IF(!(_dwWindowSize.Y > 0));
@@ -757,11 +755,6 @@ void Settings::CalculateDefaultColorIndices() noexcept
_renderSettings.SetColorAliasIndex(ColorAlias::DefaultBackground, backgroundAlias);
}
void Settings::SaveDefaultRenderSettings() noexcept
{
_renderSettings.SaveDefaultSettings();
}
bool Settings::IsTerminalScrolling() const noexcept
{
return _TerminalScrolling;

View File

@@ -172,7 +172,6 @@ public:
void SetInterceptCopyPaste(const bool interceptCopyPaste) noexcept;
void CalculateDefaultColorIndices() noexcept;
void SaveDefaultRenderSettings() noexcept;
bool IsTerminalScrolling() const noexcept;
void SetTerminalScrolling(const bool terminalScrollingEnabled) noexcept;

View File

@@ -16,7 +16,6 @@
#include "../interactivity/inc/ServiceLocator.hpp"
#include "../../inc/conattrs.hpp"
#include "../../types/inc/colorTable.hpp"
#include "../../types/inc/Viewport.hpp"
#include "../../inc/TestUtils.h"
@@ -2071,15 +2070,6 @@ void ScreenBufferTests::VtRestoreColorTableReport()
// Blue component is clamped at 100%, so 150% interpreted as 100%
stateMachine.ProcessString(L"\033P2$p14;2;0;0;150\033\\");
VERIFY_ARE_EQUAL(RGB(0, 0, 255), gci.GetColorTableEntry(14));
Log::Comment(L"RIS restores initial Campbell color scheme");
stateMachine.ProcessString(L"\033c");
for (auto i = 0; i < 16; i++)
{
const COLORREF expectedColor = Microsoft::Console::Utils::CampbellColorTable()[i];
VERIFY_ARE_EQUAL(expectedColor, gci.GetColorTableEntry(i));
}
}
void ScreenBufferTests::ResizeTraditionalDoesNotDoubleFreeAttrRows()
@@ -3362,13 +3352,6 @@ void ScreenBufferTests::AssignColorAliases()
stateMachine.ProcessString(L"\033[2;34;56,|");
VERIFY_ARE_EQUAL(34u, renderSettings.GetColorAliasIndex(ColorAlias::FrameForeground));
VERIFY_ARE_EQUAL(56u, renderSettings.GetColorAliasIndex(ColorAlias::FrameBackground));
Log::Comment(L"Test RIS restores initial color assignments");
stateMachine.ProcessString(L"\033c");
VERIFY_ARE_EQUAL(defaultFg, renderSettings.GetColorAliasIndex(ColorAlias::DefaultForeground));
VERIFY_ARE_EQUAL(defaultBg, renderSettings.GetColorAliasIndex(ColorAlias::DefaultBackground));
VERIFY_ARE_EQUAL(frameFg, renderSettings.GetColorAliasIndex(ColorAlias::FrameForeground));
VERIFY_ARE_EQUAL(frameBg, renderSettings.GetColorAliasIndex(ColorAlias::FrameBackground));
}
void ScreenBufferTests::DeleteCharsNearEndOfLine()

View File

@@ -57,6 +57,7 @@ INT_PTR CALLBACK FindDialogProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM l
if (searcher.IsStale(gci.renderData, lastFindString, flags))
{
searcher.Reset(gci.renderData, lastFindString, flags, reverse);
searcher.MoveToCurrentSelection();
}
else
{

View File

@@ -57,6 +57,11 @@
<ClInclude Include="..\WindowIo.hpp" />
<ClInclude Include="..\windowUiaProvider.hpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\renderer\atlas\atlas.vcxproj">
<Project>{8222900C-8B6C-452A-91AC-BE95DB04B95F}</Project>
</ProjectReference>
</ItemGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>..\..\..\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
@@ -65,4 +70,4 @@
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
<Import Project="$(SolutionDir)src\common.build.post.props" />
<Import Project="$(SolutionDir)src\common.nugetversions.targets" />
</Project>
</Project>

View File

@@ -128,6 +128,5 @@
</ItemGroup>
<ItemGroup>
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
</ItemGroup>
</Project>
</Project>

View File

@@ -576,8 +576,6 @@ void Menu::s_PropertiesUpdate(PCONSOLE_STATE_INFO pStateInfo)
TextAttribute::SetLegacyDefaultAttributes(pStateInfo->ScreenAttributes);
// And recalculate the position of the default colors in the color table.
gci.CalculateDefaultColorIndices();
// Then save these values as the new default render settings.
gci.SaveDefaultRenderSettings();
// Set the screen info's default text attributes to defaults -
ScreenInfo.SetDefaultAttributes({}, TextAttribute{ gci.GetPopupFillAttribute() });

View File

@@ -0,0 +1,99 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "precomp.h"
#include "../inc/RenderEngineBase.hpp"
#pragma hdrstop
using namespace Microsoft::Console;
using namespace Microsoft::Console::Render;
[[nodiscard]] HRESULT RenderEngineBase::InvalidateSelection(std::span<const til::rect> /*selections*/) noexcept
{
return S_OK;
}
[[nodiscard]] HRESULT RenderEngineBase::InvalidateHighlight(std::span<const til::point_span> /*highlights*/, const TextBuffer& /*renditions*/) noexcept
{
return S_OK;
}
HRESULT RenderEngineBase::InvalidateTitle(const std::wstring_view proposedTitle) noexcept
{
if (proposedTitle != _lastFrameTitle)
{
_titleChanged = true;
}
return S_OK;
}
HRESULT RenderEngineBase::UpdateTitle(const std::wstring_view newTitle) noexcept
{
auto hr = S_FALSE;
if (newTitle != _lastFrameTitle)
{
RETURN_IF_FAILED(_DoUpdateTitle(newTitle));
_lastFrameTitle = newTitle;
_titleChanged = false;
hr = S_OK;
}
return hr;
}
HRESULT RenderEngineBase::NotifyNewText(const std::wstring_view /*newText*/) noexcept
{
return S_FALSE;
}
HRESULT RenderEngineBase::UpdateSoftFont(const std::span<const uint16_t> /*bitPattern*/,
const til::size /*cellSize*/,
const size_t /*centeringHint*/) noexcept
{
return S_FALSE;
}
HRESULT RenderEngineBase::PrepareRenderInfo(RenderFrameInfo /*info*/) noexcept
{
return S_FALSE;
}
HRESULT RenderEngineBase::ResetLineTransform() noexcept
{
return S_FALSE;
}
HRESULT RenderEngineBase::PrepareLineTransform(const LineRendition /*lineRendition*/,
const til::CoordType /*targetRow*/,
const til::CoordType /*viewportLeft*/) noexcept
{
return S_FALSE;
}
HRESULT RenderEngineBase::PaintImageSlice(const ImageSlice& /*imageSlice*/,
const til::CoordType /*targetRow*/,
const til::CoordType /*viewportLeft*/) noexcept
{
return S_FALSE;
}
// Method Description:
// - By default, no one should need continuous redraw. It ruins performance
// in terms of CPU, memory, and battery life to just paint forever.
// That's why we sleep when there's nothing to draw.
// But if you REALLY WANT to do special effects... you need to keep painting.
[[nodiscard]] bool RenderEngineBase::RequiresContinuousRedraw() noexcept
{
return false;
}
// Method Description:
// - Blocks until the engine is able to render without blocking.
void RenderEngineBase::WaitUntilCanRender() noexcept
{
// Throttle the render loop a bit by default (~60 FPS), improving throughput.
Sleep(8);
}
void RenderEngineBase::UpdateHyperlinkHoveredId(const uint16_t /*hoveredId*/) noexcept
{
}

View File

@@ -26,29 +26,6 @@ RenderSettings::RenderSettings() noexcept
SetColorAliasIndex(ColorAlias::DefaultBackground, TextColor::DARK_BLACK);
SetColorAliasIndex(ColorAlias::FrameForeground, TextColor::FRAME_FOREGROUND);
SetColorAliasIndex(ColorAlias::FrameBackground, TextColor::FRAME_BACKGROUND);
SaveDefaultSettings();
}
// Routine Description:
// - Saves the current color table and color aliases as the default values, so
// we can later restore them when a hard reset (RIS) is requested.
void RenderSettings::SaveDefaultSettings() noexcept
{
_defaultColorTable = _colorTable;
_defaultColorAliasIndices = _colorAliasIndices;
}
// Routine Description:
// - Resets the render settings to their default values. which is typically
// what they were set to at startup.
void RenderSettings::RestoreDefaultSettings() noexcept
{
_colorTable = _defaultColorTable;
_colorAliasIndices = _defaultColorAliasIndices;
// For now, DECSCNM is the only render mode we need to reset. The others are
// all user preferences that can't be changed programmatically.
_renderMode.reset(Mode::ScreenReversed);
}
// Routine Description:
@@ -303,7 +280,7 @@ try
_blinkIsInUse = false;
if (renderer)
{
renderer->TriggerRedraw();
renderer->TriggerRedrawAll();
}
}
}

View File

@@ -12,24 +12,36 @@
<Import Project="$(SolutionDir)src\common.nugetversions.props" />
<ItemGroup>
<ClCompile Include="..\CSSLengthPercentage.cpp" />
<ClCompile Include="..\FontInfo.cpp" />
<ClCompile Include="..\FontInfoBase.cpp" />
<ClCompile Include="..\FontInfoDesired.cpp" />
<ClCompile Include="..\FontResource.cpp" />
<ClCompile Include="..\RenderEngineBase.cpp" />
<ClCompile Include="..\RenderSettings.cpp" />
<ClCompile Include="..\renderer.cpp" />
<ClCompile Include="..\thread.cpp" />
<ClCompile Include="..\precomp.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\inc\Cluster.hpp" />
<ClInclude Include="..\..\inc\CSSLengthPercentage.h" />
<ClInclude Include="..\..\inc\FontInfo.hpp" />
<ClInclude Include="..\..\inc\FontInfoBase.hpp" />
<ClInclude Include="..\..\inc\FontInfoDesired.hpp" />
<ClInclude Include="..\..\inc\FontResource.hpp" />
<ClInclude Include="..\..\inc\IFontDefaultList.hpp" />
<ClInclude Include="..\..\inc\IRenderData.hpp" />
<ClInclude Include="..\..\inc\IRenderEngine.hpp" />
<ClInclude Include="..\..\inc\RenderEngineBase.hpp" />
<ClInclude Include="..\..\inc\RenderSettings.hpp" />
<ClInclude Include="..\FontCache.h" />
<ClInclude Include="..\precomp.h" />
<ClInclude Include="..\renderer.hpp" />
<ClInclude Include="..\thread.hpp" />
</ItemGroup>
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
<Import Project="$(SolutionDir)src\common.build.post.props" />
<Import Project="$(SolutionDir)src\common.nugetversions.targets" />
</Project>
</Project>

View File

@@ -18,15 +18,30 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\FontInfo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\FontInfoBase.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\FontInfoDesired.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\FontResource.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\renderer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\thread.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\precomp.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\RenderEngineBase.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\RenderSettings.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -41,15 +56,36 @@
<ClInclude Include="..\renderer.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\thread.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\FontInfo.hpp">
<Filter>Header Files\inc</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\FontInfoBase.hpp">
<Filter>Header Files\inc</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\FontInfoDesired.hpp">
<Filter>Header Files\inc</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\FontResource.hpp">
<Filter>Header Files\inc</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\IFontDefaultList.hpp">
<Filter>Header Files\inc</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\IRenderData.hpp">
<Filter>Header Files\inc</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\IRenderEngine.hpp">
<Filter>Header Files\inc</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\RenderEngineBase.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\Cluster.hpp">
<Filter>Header Files\inc</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\RenderSettings.hpp">
<Filter>Header Files\inc</Filter>
</ClInclude>
@@ -62,6 +98,5 @@
</ItemGroup>
<ItemGroup>
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
</ItemGroup>
</Project>
</Project>

File diff suppressed because it is too large Load Diff

View File

@@ -1,30 +1,143 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- Renderer.hpp
Abstract:
- This is the definition of our renderer.
- It provides interfaces for the console application to notify when various portions of the console state have changed and need to be redrawn.
- It requires a data interface to fetch relevant console structures required for drawing and a drawing engine target for output.
Author(s):
- Michael Niksa (MiNiksa) 17-Nov-2015
--*/
#pragma once
#include "../inc/IRenderEngine.hpp"
#include "../inc/RenderSettings.hpp"
#include "thread.hpp"
#include "../../buffer/out/textBuffer.hpp"
namespace Microsoft::Console::Render
{
class Renderer
{
public:
Renderer(IRenderData* renderData);
Renderer(const RenderSettings& renderSettings,
IRenderData* pData,
_In_reads_(cEngines) IRenderEngine** const pEngine,
const size_t cEngines,
std::unique_ptr<RenderThread> thread);
~Renderer();
void AddRenderEngine(_In_ IRenderEngine* pEngine);
void RemoveRenderEngine(_In_ IRenderEngine* pEngine);
void TriggerRedraw() noexcept;
IRenderData* GetRenderData() const noexcept;
bool IsGlyphWideByFont(std::wstring_view glyph);
void SetRendererEnteredErrorStateCallback(std::function<void()> callback);
[[nodiscard]] HRESULT PaintFrame();
void NotifyPaintFrame() noexcept;
void TriggerSystemRedraw(const til::rect* const prcDirtyClient);
void TriggerRedraw(const Microsoft::Console::Types::Viewport& region);
void TriggerRedraw(const til::point* const pcoord);
void TriggerRedrawAll(const bool backgroundChanged = false, const bool frameChanged = false);
void TriggerTeardown() noexcept;
void TriggerSelection();
void TriggerSearchHighlight(const std::vector<til::point_span>& oldHighlights);
void TriggerScroll();
void TriggerScroll(const til::point* const pcoordDelta);
void TriggerTitleChange();
void TriggerNewTextNotification(const std::wstring_view newText);
void TriggerFontChange(const int iDpi,
const FontInfoDesired& FontInfoDesired,
_Out_ FontInfo& FontInfo);
void UpdateSoftFont(const std::span<const uint16_t> bitPattern,
const til::size cellSize,
const size_t centeringHint);
[[nodiscard]] HRESULT GetProposedFont(const int iDpi,
const FontInfoDesired& FontInfoDesired,
_Out_ FontInfo& FontInfo);
bool IsGlyphWideByFont(const std::wstring_view glyph);
void EnablePainting();
void WaitForPaintCompletionAndDisable(const DWORD dwTimeoutMs);
void WaitUntilCanRender();
void AddRenderEngine(_In_ IRenderEngine* const pEngine);
void RemoveRenderEngine(_In_ IRenderEngine* const pEngine);
void SetBackgroundColorChangedCallback(std::function<void()> pfn);
void SetFrameColorChangedCallback(std::function<void()> pfn);
void SetRendererEnteredErrorStateCallback(std::function<void()> pfn);
void ResetErrorStateAndResume();
void UpdateHyperlinkHoveredId(uint16_t id) noexcept;
void UpdateLastHoveredInterval(const std::optional<interval_tree::IntervalTree<til::point, size_t>::interval>& newInterval);
private:
IRenderData* _renderData;
til::small_vector<IRenderEngine*, 2> _renderEngines;
std::function<void()> _errorStateCallback;
// Caches some essential information about the active composition.
// This allows us to properly invalidate it between frames, etc.
struct CompositionCache
{
til::point absoluteOrigin;
TextAttribute baseAttribute;
};
static GridLineSet s_GetGridlines(const TextAttribute& textAttribute) noexcept;
static bool s_IsSoftFontChar(const std::wstring_view& v, const size_t firstSoftFontChar, const size_t lastSoftFontChar);
[[nodiscard]] HRESULT _PaintFrame() noexcept;
[[nodiscard]] HRESULT _PaintFrameForEngine(_In_ IRenderEngine* const pEngine) noexcept;
bool _CheckViewportAndScroll();
[[nodiscard]] HRESULT _PaintBackground(_In_ IRenderEngine* const pEngine);
void _PaintBufferOutput(_In_ IRenderEngine* const pEngine);
void _PaintBufferOutputHelper(_In_ IRenderEngine* const pEngine, TextBufferCellIterator it, const til::point target, const bool lineWrapped);
void _PaintBufferOutputGridLineHelper(_In_ IRenderEngine* const pEngine, const TextAttribute textAttribute, const size_t cchLine, const til::point coordTarget);
bool _isHoveredHyperlink(const TextAttribute& textAttribute) const noexcept;
void _PaintSelection(_In_ IRenderEngine* const pEngine);
void _PaintCursor(_In_ IRenderEngine* const pEngine);
[[nodiscard]] HRESULT _UpdateDrawingBrushes(_In_ IRenderEngine* const pEngine, const TextAttribute attr, const bool usingSoftFont, const bool isSettingDefaultBrushes);
[[nodiscard]] HRESULT _PerformScrolling(_In_ IRenderEngine* const pEngine);
void _ScrollPreviousSelection(const til::point delta);
[[nodiscard]] HRESULT _PaintTitle(IRenderEngine* const pEngine);
bool _isInHoveredInterval(til::point coordTarget) const noexcept;
void _updateCursorInfo();
void _invalidateCurrentCursor() const;
void _invalidateOldComposition() const;
void _prepareNewComposition();
[[nodiscard]] HRESULT _PrepareRenderInfo(_In_ IRenderEngine* const pEngine);
const RenderSettings& _renderSettings;
std::array<IRenderEngine*, 2> _engines{};
IRenderData* _pData = nullptr; // Non-ownership pointer
std::unique_ptr<RenderThread> _pThread;
static constexpr size_t _firstSoftFontChar = 0xEF20;
size_t _lastSoftFontChar = 0;
uint16_t _hyperlinkHoveredId = 0;
std::optional<interval_tree::IntervalTree<til::point, size_t>::interval> _hoveredInterval;
Microsoft::Console::Types::Viewport _viewport;
CursorOptions _currentCursorOptions;
std::optional<CompositionCache> _compositionCache;
std::vector<Cluster> _clusterBuffer;
std::function<void()> _pfnBackgroundColorChanged;
std::function<void()> _pfnFrameColorChanged;
std::function<void()> _pfnRendererEnteredErrorState;
bool _destructing = false;
bool _forceUpdateViewport = false;
til::point_span _lastSelectionPaintSpan{};
size_t _lastSelectionPaintSize{};
std::vector<til::rect> _lastSelectionRectsByViewport{};
};
}

View File

@@ -0,0 +1,301 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "precomp.h"
#include "thread.hpp"
#include "renderer.hpp"
#pragma hdrstop
using namespace Microsoft::Console::Render;
RenderThread::RenderThread() :
_pRenderer(nullptr),
_hThread(nullptr),
_hEvent(nullptr),
_hPaintCompletedEvent(nullptr),
_fKeepRunning(true),
_hPaintEnabledEvent(nullptr),
_fNextFrameRequested(false),
_fWaiting(false)
{
}
RenderThread::~RenderThread()
{
if (_hThread)
{
_fKeepRunning = false; // stop loop after final run
EnablePainting(); // if we want to get the last frame out, we need to make sure it's enabled
SignalObjectAndWait(_hEvent, _hThread, INFINITE, FALSE); // signal final paint and wait for thread to finish.
CloseHandle(_hThread);
_hThread = nullptr;
}
if (_hEvent)
{
CloseHandle(_hEvent);
_hEvent = nullptr;
}
if (_hPaintEnabledEvent)
{
CloseHandle(_hPaintEnabledEvent);
_hPaintEnabledEvent = nullptr;
}
if (_hPaintCompletedEvent)
{
CloseHandle(_hPaintCompletedEvent);
_hPaintCompletedEvent = nullptr;
}
}
// Method Description:
// - Create all of the Events we'll need, and the actual thread we'll be doing
// work on.
// Arguments:
// - pRendererParent: the Renderer that owns this thread, and which we should
// trigger frames for.
// Return Value:
// - S_OK if we succeeded, else an HRESULT corresponding to a failure to create
// an Event or Thread.
[[nodiscard]] HRESULT RenderThread::Initialize(Renderer* const pRendererParent) noexcept
{
_pRenderer = pRendererParent;
auto hr = S_OK;
// Create event before thread as thread will start immediately.
if (SUCCEEDED(hr))
{
auto hEvent = CreateEventW(nullptr, // non-inheritable security attributes
FALSE, // auto reset event
FALSE, // initially unsignaled
nullptr // no name
);
if (hEvent == nullptr)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
else
{
_hEvent = hEvent;
}
}
if (SUCCEEDED(hr))
{
auto hPaintEnabledEvent = CreateEventW(nullptr,
TRUE, // manual reset event
FALSE, // initially signaled
nullptr);
if (hPaintEnabledEvent == nullptr)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
else
{
_hPaintEnabledEvent = hPaintEnabledEvent;
}
}
if (SUCCEEDED(hr))
{
auto hPaintCompletedEvent = CreateEventW(nullptr,
TRUE, // manual reset event
TRUE, // initially signaled
nullptr);
if (hPaintCompletedEvent == nullptr)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
else
{
_hPaintCompletedEvent = hPaintCompletedEvent;
}
}
if (SUCCEEDED(hr))
{
auto hThread = CreateThread(nullptr, // non-inheritable security attributes
0, // use default stack size
s_ThreadProc,
this,
0, // create immediately
nullptr // we don't need the thread ID
);
if (hThread == nullptr)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
else
{
_hThread = hThread;
// SetThreadDescription only works on 1607 and higher. If we cannot find it,
// then it's no big deal. Just skip setting the description.
auto func = GetProcAddressByFunctionDeclaration(GetModuleHandleW(L"kernel32.dll"), SetThreadDescription);
if (func)
{
LOG_IF_FAILED(func(hThread, L"Rendering Output Thread"));
}
}
}
return hr;
}
DWORD WINAPI RenderThread::s_ThreadProc(_In_ LPVOID lpParameter)
{
const auto pContext = static_cast<RenderThread*>(lpParameter);
if (pContext != nullptr)
{
return pContext->_ThreadProc();
}
else
{
return (DWORD)E_INVALIDARG;
}
}
DWORD WINAPI RenderThread::_ThreadProc()
{
while (_fKeepRunning)
{
// Between waiting on _hEvent and calling PaintFrame() there should be a minimal delay,
// so that a key press progresses to a drawing operation as quickly as possible.
// As such, we wait for the renderer to complete _before_ waiting on _hEvent.
_pRenderer->WaitUntilCanRender();
WaitForSingleObject(_hPaintEnabledEvent, INFINITE);
if (!_fNextFrameRequested.exchange(false, std::memory_order_acq_rel))
{
// <--
// If `NotifyPaint` is called at this point, then it will not
// set the event because `_fWaiting` is not `true` yet so we have
// to check again below.
_fWaiting.store(true, std::memory_order_release);
// check again now (see comment above)
if (!_fNextFrameRequested.exchange(false, std::memory_order_acq_rel))
{
// Wait until a next frame is requested.
WaitForSingleObject(_hEvent, INFINITE);
}
// <--
// If `NotifyPaint` is called at this point, then it _will_ set
// the event because `_fWaiting` is `true`, but we're not waiting
// anymore!
// This can probably happen quite often: imagine a scenario where
// we are waiting, and the terminal calls `NotifyPaint` twice
// very quickly.
// In that case, both calls might end up calling `SetEvent`. The
// first one will resume this thread and the second one will
// `SetEvent` the event. So the next time we wait, the event will
// already be set and we won't actually wait.
// Because it can happen often, and because rendering is an
// expensive operation, we should reset the event to not render
// again if nothing changed.
_fWaiting.store(false, std::memory_order_release);
// see comment above
ResetEvent(_hEvent);
}
ResetEvent(_hPaintCompletedEvent);
LOG_IF_FAILED(_pRenderer->PaintFrame());
SetEvent(_hPaintCompletedEvent);
}
return S_OK;
}
void RenderThread::NotifyPaint() noexcept
{
if (_fWaiting.load(std::memory_order_acquire))
{
SetEvent(_hEvent);
}
else
{
_fNextFrameRequested.store(true, std::memory_order_release);
}
}
void RenderThread::EnablePainting() noexcept
{
SetEvent(_hPaintEnabledEvent);
}
void RenderThread::DisablePainting() noexcept
{
ResetEvent(_hPaintEnabledEvent);
}
void RenderThread::WaitForPaintCompletionAndDisable(const DWORD dwTimeoutMs) noexcept
{
// When rendering takes place via DirectX, and a console application
// currently owns the screen, and a new console application is launched (or
// the user switches to another console application), the new application
// cannot take over the screen until the active one relinquishes it. This
// blocking mechanism goes as follows:
//
// 1. The console input thread of the new console application connects to
// ConIoSrv;
// 2. While servicing the new connection request, ConIoSrv sends an event to
// the active application letting it know that it has lost focus;
// 3.1 ConIoSrv waits for a reply from the client application;
// 3.2 Meanwhile, the active application receives the focus event and calls
// this method, waiting for the current paint operation to
// finish.
//
// This means that the new application is waiting on the connection request
// reply from ConIoSrv, ConIoSrv is waiting on the active application to
// acknowledge the lost focus event to reply to the new application, and the
// console input thread in the active application is waiting on the renderer
// thread to finish its current paint operation.
//
// Question: what should happen if the wait on the paint operation times
// out?
//
// There are three options:
//
// 1. On timeout, the active console application could reply with an error
// message and terminate itself, effectively relinquishing control of the
// display;
//
// 2. ConIoSrv itself could time out on waiting for a reply, and forcibly
// terminate the active console application;
//
// 3. Let the wait time out and let the user deal with it. Because the wait
// occurs on a single iteration of the renderer thread, it seemed to me that
// the likelihood of failure is extremely small, especially since the client
// console application that the active conhost instance is servicing has no
// say over what happens in the renderer thread, only by proxy. Thus, the
// chance of failure (timeout) is minimal and since the OneCoreUAP console
// is not a massively used piece of software, it didnt seem that it would
// be a good use of time to build the requisite infrastructure to deal with
// a timeout here, at least not for now. In case of a timeout DirectX will
// catch the mistake of a new application attempting to acquire the display
// while another one still owns it and will flag it as a DWM bug. Right now,
// the active application will wait one second for the paint operation to
// finish.
//
// TODO: MSFT: 11833883 - Determine action when wait on paint operation via
// DirectX on OneCoreUAP times out while switching console
// applications.
ResetEvent(_hPaintEnabledEvent);
WaitForSingleObject(_hPaintCompletedEvent, dwTimeoutMs);
}

View File

@@ -0,0 +1,50 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- Thread.hpp
Abstract:
- This is the definition of our rendering thread designed to throttle and compartmentalize drawing operations.
Author(s):
- Michael Niksa (MiNiksa) Feb 2016
--*/
#pragma once
namespace Microsoft::Console::Render
{
class Renderer;
class RenderThread
{
public:
RenderThread();
~RenderThread();
[[nodiscard]] HRESULT Initialize(Renderer* const pRendererParent) noexcept;
void NotifyPaint() noexcept;
void EnablePainting() noexcept;
void DisablePainting() noexcept;
void WaitForPaintCompletionAndDisable(const DWORD dwTimeoutMs) noexcept;
private:
static DWORD WINAPI s_ThreadProc(_In_ LPVOID lpParameter);
DWORD WINAPI _ThreadProc();
HANDLE _hThread;
HANDLE _hEvent;
HANDLE _hPaintEnabledEvent;
HANDLE _hPaintCompletedEvent;
Renderer* _pRenderer; // Non-ownership pointer
bool _fKeepRunning;
std::atomic<bool> _fNextFrameRequested;
std::atomic<bool> _fWaiting;
};
}

View File

@@ -1,26 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "precomp.h"
#include "GdiEngine.h"
using namespace Microsoft::Console::Types;
using namespace Microsoft::Console::Render;
GdiEngine::GdiEngine()
{
}
GdiEngine::~GdiEngine()
{
}
void GdiEngine::WaitUntilCanRender()
{
}
void GdiEngine::Render(RenderingPayload& payload)
{
UNREFERENCED_PARAMETER(payload);
}

View File

@@ -1,19 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "../inc/IRenderEngine.hpp"
namespace Microsoft::Console::Render
{
class GdiEngine final : public IRenderEngine
{
public:
GdiEngine();
~GdiEngine() override;
void WaitUntilCanRender() override;
void Render(RenderingPayload& payload) override;
};
}

View File

@@ -0,0 +1,225 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- GdiRenderer.hpp
Abstract:
- This is the definition of the GDI specific implementation of the renderer.
Author(s):
- Michael Niksa (MiNiksa) 17-Nov-2015
--*/
#pragma once
#include "../inc/RenderEngineBase.hpp"
#include "../inc/FontResource.hpp"
namespace Microsoft::Console::Render
{
class GdiEngine final : public RenderEngineBase
{
public:
GdiEngine();
~GdiEngine() override;
[[nodiscard]] HRESULT SetHwnd(const HWND hwnd) noexcept;
[[nodiscard]] HRESULT InvalidateSelection(std::span<const til::rect> selections) noexcept override;
[[nodiscard]] HRESULT InvalidateScroll(const til::point* const pcoordDelta) noexcept override;
[[nodiscard]] HRESULT InvalidateSystem(const til::rect* const prcDirtyClient) noexcept override;
[[nodiscard]] HRESULT Invalidate(const til::rect* const psrRegion) noexcept override;
[[nodiscard]] HRESULT InvalidateCursor(const til::rect* const psrRegion) noexcept override;
[[nodiscard]] HRESULT InvalidateAll() noexcept override;
[[nodiscard]] HRESULT StartPaint() noexcept override;
[[nodiscard]] HRESULT EndPaint() noexcept override;
[[nodiscard]] HRESULT Present() noexcept override;
[[nodiscard]] HRESULT ScrollFrame() noexcept override;
[[nodiscard]] HRESULT ResetLineTransform() noexcept override;
[[nodiscard]] HRESULT PrepareLineTransform(const LineRendition lineRendition,
const til::CoordType targetRow,
const til::CoordType viewportLeft) noexcept override;
[[nodiscard]] HRESULT PaintBackground() noexcept override;
[[nodiscard]] HRESULT PaintBufferLine(const std::span<const Cluster> clusters,
const til::point coord,
const bool trimLeft,
const bool lineWrapped) noexcept override;
[[nodiscard]] HRESULT PaintBufferGridLines(const GridLineSet lines,
const COLORREF gridlineColor,
const COLORREF underlineColor,
const size_t cchLine,
const til::point coordTarget) noexcept override;
[[nodiscard]] HRESULT PaintImageSlice(const ImageSlice& imageSlice,
const til::CoordType targetRow,
const til::CoordType viewportLeft) noexcept override;
[[nodiscard]] HRESULT PaintSelection(const til::rect& rect) noexcept override;
[[nodiscard]] HRESULT PaintCursor(const CursorOptions& options) noexcept override;
[[nodiscard]] HRESULT UpdateDrawingBrushes(const TextAttribute& textAttributes,
const RenderSettings& renderSettings,
const gsl::not_null<IRenderData*> pData,
const bool usingSoftFont,
const bool isSettingDefaultBrushes) noexcept override;
[[nodiscard]] HRESULT UpdateFont(const FontInfoDesired& FontInfoDesired,
_Out_ FontInfo& FontInfo) noexcept override;
[[nodiscard]] HRESULT UpdateSoftFont(const std::span<const uint16_t> bitPattern,
const til::size cellSize,
const size_t centeringHint) noexcept override;
[[nodiscard]] HRESULT UpdateDpi(const int iDpi) noexcept override;
[[nodiscard]] HRESULT UpdateViewport(const til::inclusive_rect& srNewViewport) noexcept override;
[[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& FontDesired,
_Out_ FontInfo& Font,
const int iDpi) noexcept override;
[[nodiscard]] HRESULT GetDirtyArea(std::span<const til::rect>& area) noexcept override;
[[nodiscard]] HRESULT GetFontSize(_Out_ til::size* const pFontSize) noexcept override;
[[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override;
protected:
[[nodiscard]] HRESULT _DoUpdateTitle(_In_ const std::wstring_view newTitle) noexcept override;
private:
HWND _hwndTargetWindow;
[[nodiscard]] static HRESULT s_SetWindowLongWHelper(const HWND hWnd,
const int nIndex,
const LONG dwNewLong) noexcept;
static bool FontHasWesternScript(HDC hdc);
bool _fPaintStarted;
til::rect _invalidCharacters;
PAINTSTRUCT _psInvalidData;
HDC _hdcMemoryContext;
bool _isTrueTypeFont;
UINT _fontCodepage;
HFONT _hfont;
HFONT _hfontItalic;
TEXTMETRICW _tmFontMetrics;
FontResource _softFont;
static const size_t s_cPolyTextCache = 80;
POLYTEXTW _pPolyText[s_cPolyTextCache];
size_t _cPolyText;
[[nodiscard]] HRESULT _FlushBufferLines() noexcept;
std::vector<RECT> cursorInvertRects;
XFORM cursorInvertTransform;
struct LineMetrics
{
int gridlineWidth;
int underlineCenter;
int underlineWidth;
int doubleUnderlinePosTop;
int doubleUnderlinePosBottom;
int doubleUnderlineWidth;
int strikethroughOffset;
int strikethroughWidth;
int curlyLineCenter;
int curlyLinePeriod;
int curlyLineControlPointOffset;
};
LineMetrics _lineMetrics;
til::size _coordFontLast;
int _iCurrentDpi;
static const int s_iBaseDpi = USER_DEFAULT_SCREEN_DPI;
til::size _szMemorySurface;
HBITMAP _hbitmapMemorySurface;
[[nodiscard]] HRESULT _PrepareMemoryBitmap(const HWND hwnd) noexcept;
til::size _szInvalidScroll;
til::rect _rcInvalid;
bool _fInvalidRectUsed;
COLORREF _lastFg;
COLORREF _lastBg;
enum class FontType : uint8_t
{
Undefined,
Default,
Italic,
Soft
};
FontType _lastFontType;
bool _fontHasWesternScript = false;
XFORM _currentLineTransform;
LineRendition _currentLineRendition;
// Memory pooling to save alloc/free work to the OS for things
// frequently created and dropped.
// It's important the pool is first so it can be given to the others on construction.
std::pmr::unsynchronized_pool_resource _pool;
std::pmr::vector<std::pmr::wstring> _polyStrings;
std::pmr::vector<std::pmr::basic_string<int>> _polyWidths;
std::vector<DWORD> _imageMask;
[[nodiscard]] HRESULT _InvalidCombine(const til::rect* const prc) noexcept;
[[nodiscard]] HRESULT _InvalidOffset(const til::point* const ppt) noexcept;
[[nodiscard]] HRESULT _InvalidRestrict() noexcept;
[[nodiscard]] HRESULT _InvalidateRect(const til::rect* const prc) noexcept;
[[nodiscard]] HRESULT _PaintBackgroundColor(const RECT* const prc) noexcept;
static const ULONG s_ulMinCursorHeightPercent = 25;
static const ULONG s_ulMaxCursorHeightPercent = 100;
static int s_ScaleByDpi(const int iPx, const int iDpi);
static int s_ShrinkByDpi(const int iPx, const int iDpi);
til::point _GetInvalidRectPoint() const;
til::size _GetInvalidRectSize() const;
til::size _GetRectSize(const RECT* const pRect) const;
void _OrRect(_In_ til::rect* const pRectExisting, const til::rect* const pRectToOr) const;
bool _IsFontTrueType() const;
[[nodiscard]] HRESULT _GetProposedFont(const FontInfoDesired& FontDesired,
_Out_ FontInfo& Font,
const int iDpi,
_Inout_ wil::unique_hfont& hFont,
_Inout_ wil::unique_hfont& hFontItalic) noexcept;
til::size _GetFontSize() const;
bool _IsMinimized() const;
bool _IsWindowValid() const;
#ifdef DBG
// Helper functions to diagnose issues with painting from the in-memory buffer.
// These are only actually effective/on in Debug builds when the flag is set using an attached debugger.
bool _fDebug = false;
void _PaintDebugRect(const RECT* const prc) const;
void _DoDebugBlt(const RECT* const prc) const;
void _DebugBltAll() const;
HWND _debugWindow;
void _CreateDebugWindow();
HDC _debugContext;
#endif
};
constexpr XFORM IDENTITY_XFORM = { 1, 0, 0, 1 };
inline bool operator==(const XFORM& lhs, const XFORM& rhs) noexcept
{
return ::memcmp(&lhs, &rhs, sizeof(XFORM)) == 0;
};
}

View File

@@ -0,0 +1,185 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "precomp.h"
#include "gdirenderer.hpp"
#include "../../types/inc/Viewport.hpp"
#include "../buffer/out/textBuffer.hpp"
#pragma hdrstop
using namespace Microsoft::Console::Types;
using namespace Microsoft::Console::Render;
// Routine Description:
// - Notifies us that the system has requested a particular pixel area of the client rectangle should be redrawn. (On WM_PAINT)
// Arguments:
// - prcDirtyClient - Pointer to pixel area (til::rect) of client region the system believes is dirty
// Return Value:
// - HRESULT S_OK, GDI-based error code, or safemath error
HRESULT GdiEngine::InvalidateSystem(const til::rect* const prcDirtyClient) noexcept
{
RETURN_HR(_InvalidCombine(prcDirtyClient));
}
// Routine Description:
// - Notifies us that the console is attempting to scroll the existing screen area
// Arguments:
// - pcoordDelta - Pointer to character dimension (til::point) of the distance the console would like us to move while scrolling.
// Return Value:
// - HRESULT S_OK, GDI-based error code, or safemath error
HRESULT GdiEngine::InvalidateScroll(const til::point* const pcoordDelta) noexcept
{
if (pcoordDelta->x != 0 || pcoordDelta->y != 0)
{
const auto ptDelta = *pcoordDelta * _GetFontSize();
RETURN_IF_FAILED(_InvalidOffset(&ptDelta));
_szInvalidScroll = _szInvalidScroll + ptDelta;
}
return S_OK;
}
// Routine Description:
// - Notifies us that the console has changed the selection region and would like it updated
// Arguments:
// - rectangles - Vector of rectangles to draw, line by line
// Return Value:
// - HRESULT S_OK or GDI-based error code
HRESULT GdiEngine::InvalidateSelection(std::span<const til::rect> selections) noexcept
{
for (auto&& rect : selections)
{
RETURN_IF_FAILED(Invalidate(&rect));
}
return S_OK;
}
// Routine Description:
// - Notifies us that the console has changed the character region specified.
// - NOTE: This typically triggers on cursor or text buffer changes
// Arguments:
// - psrRegion - Character region (til::rect) that has been changed
// Return Value:
// - S_OK, GDI related failure, or safemath failure.
HRESULT GdiEngine::Invalidate(const til::rect* const psrRegion) noexcept
{
const auto rcRegion = psrRegion->scale_up(_GetFontSize());
RETURN_HR(_InvalidateRect(&rcRegion));
}
// Routine Description:
// - Notifies us that the console has changed the position of the cursor.
// Arguments:
// - psrRegion - the region covered by the cursor
// Return Value:
// - S_OK, else an appropriate HRESULT for failing to allocate or write.
HRESULT GdiEngine::InvalidateCursor(const til::rect* const psrRegion) noexcept
{
return this->Invalidate(psrRegion);
}
// Routine Description:
// - Notifies to repaint everything.
// - NOTE: Use sparingly. Only use when something that could affect the entire frame simultaneously occurs.
// Arguments:
// - <none>
// Return Value:
// - S_OK, S_FALSE (if no window yet), GDI related failure, or safemath failure.
HRESULT GdiEngine::InvalidateAll() noexcept
{
// If we don't have a window, don't bother.
if (!_IsWindowValid())
{
return S_FALSE;
}
til::rect rc;
RETURN_HR_IF(E_FAIL, !(GetClientRect(_hwndTargetWindow, rc.as_win32_rect())));
RETURN_HR(InvalidateSystem(&rc));
}
// Routine Description:
// - Helper to combine the given rectangle into the invalid region to be updated on the next paint
// Arguments:
// - prc - Pixel region (til::rect) that should be repainted on the next frame
// Return Value:
// - S_OK, GDI related failure, or safemath failure.
HRESULT GdiEngine::_InvalidCombine(const til::rect* const prc) noexcept
{
if (!_fInvalidRectUsed)
{
_rcInvalid = *prc;
_fInvalidRectUsed = true;
}
else
{
_OrRect(&_rcInvalid, prc);
}
// Ensure invalid areas remain within bounds of window.
RETURN_IF_FAILED(_InvalidRestrict());
return S_OK;
}
// Routine Description:
// - Helper to adjust the invalid region by the given offset such as when a scroll operation occurs.
// Arguments:
// - ppt - Distances by which we should move the invalid region in response to a scroll
// Return Value:
// - S_OK, GDI related failure, or safemath failure.
HRESULT GdiEngine::_InvalidOffset(const til::point* ppt) noexcept
{
if (_fInvalidRectUsed)
{
til::rect rcInvalidNew;
rcInvalidNew.left = _rcInvalid.left + ppt->x;
rcInvalidNew.right = _rcInvalid.right + ppt->x;
rcInvalidNew.top = _rcInvalid.top + ppt->y;
rcInvalidNew.bottom = _rcInvalid.bottom + ppt->y;
// Add the scrolled invalid rectangle to what was left behind to get the new invalid area.
// This is the equivalent of adding in the "update rectangle" that we would get out of ScrollWindowEx/ScrollDC.
_rcInvalid |= rcInvalidNew;
// Ensure invalid areas remain within bounds of window.
RETURN_IF_FAILED(_InvalidRestrict());
}
return S_OK;
}
// Routine Description:
// - Helper to ensure the invalid region remains within the bounds of the window.
// Arguments:
// - <none>
// Return Value:
// - S_OK, GDI related failure, or safemath failure.
HRESULT GdiEngine::_InvalidRestrict() noexcept
{
// Ensure that the invalid area remains within the bounds of the client area
til::rect rcClient;
// Do restriction only if retrieving the client rect was successful.
RETURN_HR_IF(E_FAIL, !(GetClientRect(_hwndTargetWindow, rcClient.as_win32_rect())));
_rcInvalid.left = rcClient.left;
_rcInvalid.right = rcClient.right;
_rcInvalid.top = std::clamp(_rcInvalid.top, rcClient.top, rcClient.bottom);
_rcInvalid.bottom = std::clamp(_rcInvalid.bottom, rcClient.top, rcClient.bottom);
return S_OK;
}
// Routine Description:
// - Helper to add a pixel rectangle to the invalid area
// Arguments:
// - prc - Pointer to pixel rectangle representing invalid area to add to next paint frame
// Return Value:
// - S_OK, GDI related failure, or safemath failure.
HRESULT GdiEngine::_InvalidateRect(const til::rect* const prc) noexcept
{
RETURN_HR(_InvalidCombine(prc));
}

View File

@@ -11,13 +11,16 @@
<Import Project="$(SolutionDir)src\common.build.pre.props" />
<Import Project="$(SolutionDir)src\common.nugetversions.props" />
<ItemGroup>
<ClCompile Include="..\GdiEngine.cpp" />
<ClCompile Include="..\invalidate.cpp" />
<ClCompile Include="..\math.cpp" />
<ClCompile Include="..\paint.cpp" />
<ClCompile Include="..\state.cpp" />
<ClCompile Include="..\precomp.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\GdiEngine.h" />
<ClInclude Include="..\gdirenderer.hpp" />
<ClInclude Include="..\precomp.h" />
</ItemGroup>
<ItemDefinitionGroup>
@@ -28,4 +31,4 @@
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
<Import Project="$(SolutionDir)src\common.build.post.props" />
<Import Project="$(SolutionDir)src\common.nugetversions.targets" />
</Project>
</Project>

Some files were not shown because too many files have changed in this diff Show More