Skip to content

Commit f622d80

Browse files
committed
Merge remote-tracking branch 'origin/main' into dev/migrie/fhl/non-terminal-panes-2023
2 parents 4cec7e9 + 077d63e commit f622d80

32 files changed

+178
-966
lines changed

.github/actions/spelling/expect/expect.txt

-1
Original file line numberDiff line numberDiff line change
@@ -1590,7 +1590,6 @@ RIGHTALIGN
15901590
RIGHTBUTTON
15911591
riid
15921592
Rike
1593-
RIPMSG
15941593
RIS
15951594
roadmap
15961595
robomac

doc/COOKED_READ_DATA.md

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# COOKED_READ_DATA, aka conhost's readline implementation
2+
3+
## Test instructions
4+
5+
All of the following ✅ marks must be fulfilled during manual testing:
6+
* ASCII input
7+
* Chinese input (中文維基百科) ❔
8+
* Resizing the window properly wraps/unwraps wide glyphs ❌
9+
Broken due to `TextBuffer::Reflow` bugs
10+
* Surrogate pair input (🙂) ❔
11+
* Resizing the window properly wraps/unwraps surrogate pairs ❌
12+
Broken due to `TextBuffer::Reflow` bugs
13+
* In cmd.exe
14+
* Create 2 file: "a😊b.txt" and "a😟b.txt"
15+
* Press tab: Autocomplete to "a😊b.txt" ✅
16+
* Navigate the cursor right past the "a"
17+
* Press tab twice: Autocomplete to "a😟b.txt" ✅
18+
* Backspace deletes preceding glyphs ✅
19+
* Ctrl+Backspace deletes preceding words ✅
20+
* Escape clears input ✅
21+
* Home navigates to start ✅
22+
* Ctrl+Home deletes text between cursor and start ✅
23+
* End navigates to end ✅
24+
* Ctrl+End deletes text between cursor and end ✅
25+
* Left navigates over previous code points ✅
26+
* Ctrl+Left navigates to previous word-starts ✅
27+
* Right and F1 navigate over next code points ✅
28+
* Pressing right at the end of input copies characters
29+
from the previous command ✅
30+
* Ctrl+Right navigates to next word-ends ✅
31+
* Insert toggles overwrite mode ✅
32+
* Delete deletes next code point ✅
33+
* Up and F5 cycle through history ✅
34+
* Doesn't crash with no history ✅
35+
* Stops at first entry ✅
36+
* Down cycles through history ✅
37+
* Doesn't crash with no history ✅
38+
* Stops at last entry ✅
39+
* PageUp retrieves the oldest command ✅
40+
* PageDown retrieves the newest command ✅
41+
* F2 starts "copy to char" prompt ✅
42+
* Escape dismisses prompt ✅
43+
* Typing a character copies text from the previous command up
44+
until that character into the current buffer (acts identical
45+
to F3, but with automatic character search) ✅
46+
* F3 copies the previous command into the current buffer,
47+
starting at the current cursor position,
48+
for as many characters as possible ✅
49+
* Doesn't erase trailing text if the current buffer
50+
is longer than the previous command ✅
51+
* Puts the cursor at the end of the copied text ✅
52+
* F4 starts "copy from char" prompt ✅
53+
* Escape dismisses prompt ✅
54+
* Erases text between the current cursor position and the
55+
first instance of a given char (but not including it) ✅
56+
* F6 inserts Ctrl+Z ✅
57+
* F7 without modifiers starts "command list" prompt ✅
58+
* Escape dismisses prompt ✅
59+
* Minimum size of 40x10 characters ✅
60+
* Width expands to fit the widest history command ✅
61+
* Height expands up to 20 rows with longer histories ✅
62+
* F9 starts "command number" prompt ✅
63+
* Left/Right paste replace the buffer with the given command ✅
64+
* And put cursor at the end of the buffer ✅
65+
* Up/Down navigate selection through history ✅
66+
* Stops at start/end with <10 entries ✅
67+
* Stops at start/end with >20 entries ✅
68+
* Wide text rendering during pagination with >20 entries ✅
69+
* Shift+Up/Down moves history items around ✅
70+
* Home navigates to first entry ✅
71+
* End navigates to last entry ✅
72+
* PageUp navigates by 20 items at a time or to first ✅
73+
* PageDown navigates by 20 items at a time or to last ✅
74+
* Alt+F7 clears command history ✅
75+
* F8 cycles through commands that start with the same text as
76+
the current buffer up until the current cursor position ✅
77+
* Doesn't crash with no history ✅
78+
* F9 starts "command number" prompt ✅
79+
* Escape dismisses prompt ✅
80+
* Ignores non-ASCII-decimal characters ✅
81+
* Allows entering between 1 and 5 digits ✅
82+
* Pressing Enter fetches the given command from the history ✅
83+
* Alt+F10 clears doskey aliases ✅
84+
* In cmd.exe, with an empty prompt in an empty directory:
85+
Pressing tab produces an audible bing and prints no text ✅
86+
* When Narrator is enabled, in cmd.exe:
87+
* Typing individual characters announces only
88+
exactly each character that is being typed ✅
89+
* Backspacing at the end of a prompt announces
90+
only exactly each deleted character ✅

src/cascadia/CascadiaPackage/Package-Can.appxmanifest

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@
88
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
99
xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4"
1010
xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"
11+
xmlns:uap17="http://schemas.microsoft.com/appx/manifest/uap/windows10/17"
1112
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
1213
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
1314
xmlns:desktop5="http://schemas.microsoft.com/appx/manifest/desktop/windows10/5"
1415
xmlns:desktop6="http://schemas.microsoft.com/appx/manifest/desktop/windows10/6"
1516
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
1617
xmlns:virtualization="http://schemas.microsoft.com/appx/manifest/virtualization/windows10"
17-
IgnorableNamespaces="uap mp rescap uap3 desktop6 virtualization">
18+
IgnorableNamespaces="uap mp rescap uap3 uap17 desktop6 virtualization">
1819

1920
<Identity
2021
Name="Microsoft.WindowsTerminalCanary"
@@ -33,6 +34,7 @@
3334
<virtualization:ExcludedKey>HKEY_CURRENT_USER\Console\%%Startup</virtualization:ExcludedKey>
3435
</virtualization:ExcludedKeys>
3536
</virtualization:RegistryWriteVirtualization>
37+
<uap17:UpdateWhileInUse>defer</uap17:UpdateWhileInUse>
3638
</Properties>
3739

3840
<Dependencies>

src/cascadia/CascadiaPackage/Package-Dev.appxmanifest

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@
77
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
88
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
99
xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4"
10+
xmlns:uap17="http://schemas.microsoft.com/appx/manifest/uap/windows10/17"
1011
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
1112
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
1213
xmlns:desktop5="http://schemas.microsoft.com/appx/manifest/desktop/windows10/5"
1314
xmlns:desktop6="http://schemas.microsoft.com/appx/manifest/desktop/windows10/6"
1415
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
1516
xmlns:virtualization="http://schemas.microsoft.com/appx/manifest/virtualization/windows10"
1617
xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"
17-
IgnorableNamespaces="uap mp rescap uap3 desktop6 virtualization">
18+
IgnorableNamespaces="uap mp rescap uap3 uap17 desktop6 virtualization">
1819

1920
<Identity
2021
Name="WindowsTerminalDev"
@@ -33,6 +34,7 @@
3334
<virtualization:ExcludedKey>HKEY_CURRENT_USER\Console\%%Startup</virtualization:ExcludedKey>
3435
</virtualization:ExcludedKeys>
3536
</virtualization:RegistryWriteVirtualization>
37+
<uap17:UpdateWhileInUse>defer</uap17:UpdateWhileInUse>
3638
</Properties>
3739

3840
<Dependencies>

src/cascadia/CascadiaPackage/Package-Pre.appxmanifest

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@
99
xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4"
1010
xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"
1111
xmlns:uap7="http://schemas.microsoft.com/appx/manifest/uap/windows10/7"
12+
xmlns:uap17="http://schemas.microsoft.com/appx/manifest/uap/windows10/17"
1213
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
1314
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
1415
xmlns:desktop5="http://schemas.microsoft.com/appx/manifest/desktop/windows10/5"
1516
xmlns:desktop6="http://schemas.microsoft.com/appx/manifest/desktop/windows10/6"
1617
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
1718
xmlns:virtualization="http://schemas.microsoft.com/appx/manifest/virtualization/windows10"
18-
IgnorableNamespaces="uap mp rescap uap3 desktop6 virtualization">
19+
IgnorableNamespaces="uap mp rescap uap3 uap17 desktop6 virtualization">
1920

2021
<Identity
2122
Name="Microsoft.WindowsTerminalPreview"
@@ -34,6 +35,7 @@
3435
<virtualization:ExcludedKey>HKEY_CURRENT_USER\Console\%%Startup</virtualization:ExcludedKey>
3536
</virtualization:ExcludedKeys>
3637
</virtualization:RegistryWriteVirtualization>
38+
<uap17:UpdateWhileInUse>defer</uap17:UpdateWhileInUse>
3739
</Properties>
3840

3941
<Dependencies>

src/cascadia/CascadiaPackage/Package.appxmanifest

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@
99
xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4"
1010
xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"
1111
xmlns:uap7="http://schemas.microsoft.com/appx/manifest/uap/windows10/7"
12+
xmlns:uap17="http://schemas.microsoft.com/appx/manifest/uap/windows10/17"
1213
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
1314
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
1415
xmlns:desktop5="http://schemas.microsoft.com/appx/manifest/desktop/windows10/5"
1516
xmlns:desktop6="http://schemas.microsoft.com/appx/manifest/desktop/windows10/6"
1617
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
1718
xmlns:virtualization="http://schemas.microsoft.com/appx/manifest/virtualization/windows10"
18-
IgnorableNamespaces="uap mp rescap uap3 desktop6 virtualization">
19+
IgnorableNamespaces="uap mp rescap uap3 uap17 desktop6 virtualization">
1920

2021
<Identity
2122
Name="Microsoft.WindowsTerminal"
@@ -34,6 +35,7 @@
3435
<virtualization:ExcludedKey>HKEY_CURRENT_USER\Console\%%Startup</virtualization:ExcludedKey>
3536
</virtualization:ExcludedKeys>
3637
</virtualization:RegistryWriteVirtualization>
38+
<uap17:UpdateWhileInUse>defer</uap17:UpdateWhileInUse>
3739
</Properties>
3840

3941
<Dependencies>

src/cascadia/TerminalSettingsModel/defaults.json

+3
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@
174174
"foreground": "#383A42",
175175
"background": "#FAFAFA",
176176
"cursorColor": "#4F525D",
177+
"selectionBackground": "#4F525D",
177178
"black": "#383A42",
178179
"red": "#E45649",
179180
"green": "#50A14F",
@@ -218,6 +219,7 @@
218219
"foreground": "#657B83",
219220
"background": "#FDF6E3",
220221
"cursorColor": "#002B36",
222+
"selectionBackground": "#073642",
221223
"black": "#002B36",
222224
"red": "#DC322F",
223225
"green": "#859900",
@@ -262,6 +264,7 @@
262264
"foreground": "#555753",
263265
"background": "#FFFFFF",
264266
"cursorColor": "#000000",
267+
"selectionBackground": "#555753",
265268
"black": "#000000",
266269
"red": "#CC0000",
267270
"green": "#4E9A06",

src/cascadia/WindowsTerminal/AppHost.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,8 @@ winrt::Windows::Foundation::IAsyncOperation<winrt::hstring> AppHost::_GetWindowL
979979
co_await wil::resume_foreground(_windowLogic.GetRoot().Dispatcher());
980980

981981
const auto strongThis = weakThis.lock();
982-
if (!strongThis)
982+
// GH #16235: If we don't have a window logic, we're already refrigerating, and won't have our _window either.
983+
if (!strongThis || _windowLogic == nullptr)
983984
{
984985
co_return layoutJson;
985986
}
@@ -1267,7 +1268,8 @@ winrt::fire_and_forget AppHost::_QuitRequested(const winrt::Windows::Foundation:
12671268
co_await wil::resume_foreground(_windowLogic.GetRoot().Dispatcher());
12681269

12691270
const auto strongThis = weakThis.lock();
1270-
if (!strongThis)
1271+
// GH #16235: If we don't have a window logic, we're already refrigerating, and won't have our _window either.
1272+
if (!strongThis || _windowLogic == nullptr)
12711273
{
12721274
co_return;
12731275
}
@@ -1431,7 +1433,7 @@ winrt::fire_and_forget AppHost::_WindowInitializedHandler(const winrt::Windows::
14311433

14321434
// If we're gone on the other side of this co_await, well, that's fine. Just bail.
14331435
const auto strongThis = weakThis.lock();
1434-
if (!strongThis)
1436+
if (!strongThis || _window == nullptr)
14351437
{
14361438
co_return;
14371439
}

src/host/consoleInformation.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ ULONG CONSOLE_INFORMATION::GetCSRecursionCount() const noexcept
104104
return STATUS_SUCCESS;
105105
}
106106

107-
RIPMSG1(RIP_WARNING, "Console init failed with status 0x%x", Status);
107+
LOG_NTSTATUS_MSG(Status, "Console init failed");
108108

109109
delete gci.ScreenBuffers;
110110
gci.ScreenBuffers = nullptr;

src/host/directio.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,6 @@ CATCH_RETURN();
841841
_In_ PCD_CREATE_OBJECT_INFORMATION Information,
842842
_In_ PCONSOLE_CREATESCREENBUFFER_MSG a)
843843
{
844-
Telemetry::Instance().LogApiCall(Telemetry::ApiCall::CreateConsoleScreenBuffer);
845844
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
846845

847846
// If any buffer type except the one we support is set, it's invalid.

src/host/exe/exemain.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ int CALLBACK wWinMain(
222222
_In_ PWSTR /*pwszCmdLine*/,
223223
_In_ int /*nCmdShow*/)
224224
{
225+
wil::SetResultLoggingCallback(&Tracing::TraceFailure);
225226
Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().hInstance = hInstance;
226227

227228
ConsoleCheckDebug();

src/host/getset.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ void ApiRoutines::GetConsoleInputModeImpl(InputBuffer& context, ULONG& mode) noe
4141
{
4242
try
4343
{
44-
Telemetry::Instance().LogApiCall(Telemetry::ApiCall::GetConsoleMode);
4544
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
4645
LockConsole();
4746
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });

src/host/init.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ void InitSideBySide()
5050
// OpenConsole anyways, nothing happens and we get ERROR_SXS_PROCESS_DEFAULT_ALREADY_SET.
5151
if (ERROR_SXS_PROCESS_DEFAULT_ALREADY_SET != error)
5252
{
53-
RIPMSG1(RIP_WARNING, "InitSideBySide failed create an activation context. Error: %d\r\n", error);
53+
LOG_WIN32_MSG(error, "InitSideBySide failed create an activation context.");
5454
}
5555
}
5656
}

src/host/input.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ void HandleMenuEvent(const DWORD wParam)
206206
EventsWritten = gci.pInputBuffer->Write(SynthesizeMenuEvent(wParam));
207207
if (EventsWritten != 1)
208208
{
209-
RIPMSG0(RIP_WARNING, "PutInputInBuffer: EventsWritten != 1, 1 expected");
209+
LOG_HR_MSG(E_FAIL, "PutInputInBuffer: EventsWritten != 1, 1 expected");
210210
}
211211
}
212212
catch (...)
@@ -230,7 +230,7 @@ void HandleCtrlEvent(const DWORD EventType)
230230
gci.CtrlFlags |= CONSOLE_CTRL_CLOSE_FLAG;
231231
break;
232232
default:
233-
RIPMSG1(RIP_ERROR, "Invalid EventType: 0x%x", EventType);
233+
LOG_HR_MSG(E_INVALIDARG, "Invalid EventType: 0x%x", EventType);
234234
}
235235
}
236236

src/host/readDataCooked.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -436,14 +436,17 @@ void COOKED_READ_DATA::_handleChar(wchar_t wch, const DWORD modifiers)
436436

437437
if (_ctrlWakeupMask != 0 && wch < L' ' && (_ctrlWakeupMask & (1 << wch)))
438438
{
439-
_flushBuffer();
440-
441439
// The old implementation (all the way since the 90s) overwrote the character at the current cursor position with the given wch.
442440
// But simultaneously it incremented the buffer length, which would have only worked if it was written at the end of the buffer.
443441
// Press tab past the "f" in the string "foo" and you'd get "f\to " (a trailing whitespace; the initial contents of the buffer back then).
444442
// It's unclear whether the original intention was to write at the end of the buffer at all times or to implement an insert mode.
445443
// I went with insert mode.
444+
//
445+
// It is important that we don't actually print that character out though, as it's only for the calling application to see.
446+
// That's why we flush the contents before the insertion and then ensure that the _flushBuffer() call in Read() exits early.
447+
_flushBuffer();
446448
_buffer.Replace(_buffer.GetCursorPosition(), 0, &wch, 1);
449+
_buffer.MarkAsClean();
447450

448451
_controlKeyState = modifiers;
449452
_transitionState(State::DoneWithWakeupMask);

src/host/screenInfo.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1391,7 +1391,7 @@ try
13911391
{
13921392
if ((USHORT)coordNewScreenSize.width >= SHORT_MAX || (USHORT)coordNewScreenSize.height >= SHORT_MAX)
13931393
{
1394-
RIPMSG2(RIP_WARNING, "Invalid screen buffer size (0x%x, 0x%x)", coordNewScreenSize.width, coordNewScreenSize.height);
1394+
LOG_HR_MSG(E_INVALIDARG, "Invalid screen buffer size (0x%x, 0x%x)", coordNewScreenSize.width, coordNewScreenSize.height);
13951395
return STATUS_INVALID_PARAMETER;
13961396
}
13971397

src/host/selectionInput.cpp

-6
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ Selection::KeySelectionEventResult Selection::HandleKeySelectionEvent(const INPU
3737
// C-c, C-Ins. C-S-c Is also handled by this case.
3838
((ctrlPressed) && (wVirtualKeyCode == 'C' || wVirtualKeyCode == VK_INSERT)))
3939
{
40-
Telemetry::Instance().SetKeyboardTextEditingUsed();
41-
4240
// copy selection
4341
return Selection::KeySelectionEventResult::CopyToClipboard;
4442
}
@@ -291,8 +289,6 @@ bool Selection::HandleKeyboardLineSelectionEvent(const INPUT_KEY_INFO* const pIn
291289
return false;
292290
}
293291

294-
Telemetry::Instance().SetKeyboardTextSelectionUsed();
295-
296292
// if we're not currently selecting anything, start a new mouse selection
297293
if (!IsInSelectingState())
298294
{
@@ -704,8 +700,6 @@ bool Selection::_HandleColorSelection(const INPUT_KEY_INFO* const pInputKeyInfo)
704700
// Clear the selection and call the search / mark function.
705701
ClearSelection();
706702

707-
Telemetry::Instance().LogColorSelectionUsed();
708-
709703
const auto& textBuffer = gci.renderData.GetTextBuffer();
710704
const auto hits = textBuffer.SearchText(str, true);
711705
for (const auto& s : hits)

src/host/srvinit.cpp

+1-8
Original file line numberDiff line numberDiff line change
@@ -428,11 +428,6 @@ HRESULT ConsoleCreateIoThread(_In_ HANDLE Server,
428428
[[maybe_unused]] PCONSOLE_API_MSG connectMessage)
429429
try
430430
{
431-
// Create a telemetry instance here - this singleton is responsible for
432-
// setting up the g_hConhostV2EventTraceProvider, which is otherwise not
433-
// initialized in the defterm handoff at this point.
434-
(void)Telemetry::Instance();
435-
436431
#if !TIL_FEATURE_RECEIVEINCOMINGHANDOFF_ENABLED
437432
TraceLoggingWrite(g_hConhostV2EventTraceProvider,
438433
"SrvInit_ReceiveHandoff_Disabled",
@@ -865,8 +860,6 @@ PWSTR TranslateConsoleTitle(_In_ PCWSTR pwszConsoleTitle, const BOOL fUnexpand,
865860
[[nodiscard]] NTSTATUS ConsoleAllocateConsole(PCONSOLE_API_CONNECTINFO p)
866861
{
867862
// AllocConsole is outside our codebase, but we should be able to mostly track the call here.
868-
Telemetry::Instance().LogApiCall(Telemetry::ApiCall::AllocConsole);
869-
870863
auto& g = ServiceLocator::LocateGlobals();
871864

872865
auto& gci = g.getConsoleInformation();
@@ -1050,7 +1043,7 @@ DWORD WINAPI ConsoleIoThread(LPVOID lpParameter)
10501043
// This will not return. Terminate immediately when disconnected.
10511044
ServiceLocator::RundownAndExit(STATUS_SUCCESS);
10521045
}
1053-
RIPMSG1(RIP_WARNING, "DeviceIoControl failed with Result 0x%x", hr);
1046+
LOG_HR_MSG(hr, "DeviceIoControl failed");
10541047
ReplyMsg = nullptr;
10551048
continue;
10561049
}

0 commit comments

Comments
 (0)