Compare commits

...

18 Commits

Author SHA1 Message Date
Kayla Cinnamon
b22f77b76d Update Cascadia Code to v1910.04 (#3048)
Updates the font to microsoft/cascadia-code@d3b1adacf2
2019-10-03 15:46:53 -07:00
Mike Griese
e035c8fe93 Render the cursor state to VT (#2829)
* Render the cursor state to VT
* Remove TestPaintXterm entirely, as it's unused now
2019-10-03 13:13:58 -07:00
Dustin L. Howett (MSFT)
5b33c6692b Propagate window style changes to the titlebar and minmax (#3025)
Fixes #1780
2019-10-03 13:13:58 -07:00
Dustin L. Howett (MSFT)
42e281deed Simplify non-client hit testing in NCIslandWindow to fix doubleclick (#3024)
It turns out that our WM_LBUTTONDOWN handler wasn't even necessary, as
our NCHITTEST tells win32 that all of the titlebar is actually
non-client area. This brings the code in line with
NonNonClientIslandWindow.

Fixes #2513
2019-10-03 13:13:58 -07:00
Rich Turner
f4e19e07ab Update cmd's default profile to disable acrylic (#3020)
As per prior agreement with WinUI team, disabling acrylic for Cmd (and Windows PowerShell, already complete) by default. 

PowerShell Core/7 and WSL distros allowed to have Acrylic enabled by default.
2019-10-03 13:13:58 -07:00
Dustin L. Howett (MSFT)
d85689c1a8 Remove a stray inclusion of an old Windows.ImplementationLibrary package (#3026)
Fixes a build error.
2019-10-03 13:13:55 -07:00
Mike Griese
c0ee499c71 do not allow CUU and CUD to move "across" margins. (#2996)
If we're moving the cursor up, its vertical movement should be stopped
at the top margin. It should not magically jump up to the bottom margin.
Similarly, this applies to moving down and the bottom margin.
Furthermore, this constraint should always apply, not just when the
start position is within BOTH margins

Fixes #2929.
2019-10-03 13:13:12 -07:00
Leonard Hecker
3bae3c102a Partially fix mapping of virtual keys to characters (#2836) 2019-10-03 13:13:12 -07:00
Mike Griese
b61f1d3aea When reverse indexing, preserve RGB/256 attributes (#2987) 2019-10-03 13:13:11 -07:00
Michael Niksa
776b9a5103 Patch fix for #1360 until WriteStream (#780) can be implemented. (#2924)
* Patch fix for #1360 until WriteStream (#780) can be implemented.

* Add a test that hangs in the broken state and passes in the success stat. Writes a bisecting character to the right most cell in the window.

* Code format! *shakes fist at sky*

* Update src/cascadia/TerminalCore/Terminal.cpp
2019-10-03 13:13:11 -07:00
Carlos Zamora
f081a95db0 make filling chars (and, thus, erase line/char) unset wrap (#2831)
EraseInLine calls `FillConsoleOutputCharacterW()`. In filling the row with
chars, we were setting the wrap flag. We need to specifically not do this on
ANY _FILL_ operation. Now a fill operation UNSETS the wrap flag if we fill to
the end of the line.

Originally, we had a boolean `setWrap` that would mean...
- **true**: if writing to the end of the row, SET the wrap value to true
- **false**: if writing to the end of the row, DON'T CHANGE the wrap value

Now we're making this bool a std::optional to allow for a ternary state. This
allows for us to handle the following cases completely. Refer to the table
below:

,- current wrap value
|     ,- are we filling the last cell in the row?
|     |     ,- new wrap value
|     |     |     ,- comments
|--   |--   |--   |
| 0   | 0   | 0   |
| 0   | 1   | 0   |
| 0   | 1   | 1   | THIS CASE WAS HANDLED CORRECTLY
| 1   | 0   | 0   | THIS CASE WAS UNHANDLED
| 1   | 0   | 1   |
| 1   | 1   | 1   |

To handle that special case (1-0-0), we need to UNSET the wrap. So now, we have
~setWrap~ `wrap` mean the following:
- **true**: if writing to the end of the row, SET the wrap value to TRUE
- **false**: if writing to the end of the row, SET the wrap value to FALSE
- **nullopt**: leave the wrap value as it is

Closes #1126
2019-10-03 13:13:11 -07:00
Dustin L. Howett (MSFT)
9461df9fa3 teach wil about c++/winrt exceptions by including cppwinrt.h (#2927)
It turns out that if you CATCH_LOG without including this file, and you
end up catching a C++/WinRT hresult_exception, IT TURNS IT INTO A
FAILFAST.

Fixes #2591.
Fixes #2881.
Fixes #2807.
2019-10-03 13:13:11 -07:00
Mike Griese
a5a8b41303 Passthrough BEL in conpty (#2990)
🔔
[insert Chorus of the Bells here -DHowett]

Fixes #2952.
2019-10-03 13:13:11 -07:00
Mike Griese
8195efa225 Give powershell its own scheme (#2936)
Fixes #2883.
2019-10-03 13:13:10 -07:00
Michael Niksa
d745063feb inbox: console: consolidated build break fixes from vb_release_dep_dev1
- Merged PR 3815980: FIX BUILD BREAK - console: propagate input eventing changes to onecore interactivity
- Merged PR 3816007: FIX BUILD BREAK - console: api_ptytests must use SIZE_T for InitProcThreadAttrList

Retrieved from https://microsoft.visualstudio.com os OS official/rs_onecore_dep_uxp c06af1c985955b67b8b6824e264064a6244f8d34

(cherry picked from commit cc46a618ff27b8fb866be660fcad3b043681e5f8)
2019-10-03 13:13:10 -07:00
Michael Niksa
495a29cc3e inbox: merge rs_onecore_dep_uxp b4fc3a535 2019-10-03 13:13:10 -07:00
Michael Niksa
906c6e7882 Add source linking information during the build (#2857)
Copies source linking scripts and processes from Microsoft/Microsoft-UI-XAML. This embeds source information inside the PDBs in two formats: One for WinDBG using a PowerShell script that runs during the build, and one for Visual Studio using the Microsoft.SourceLink.GitHub NuGet pacakge. Sources are automatically pulled from raw.githubusercontent.com when debugging a release build inside either of these utilities as of this change.
2019-10-03 13:13:10 -07:00
Chester Liu
88d7502c73 Retarget VtPipeTerm & terminalcore-lib to 18362 (#2885) 2019-10-03 13:13:10 -07:00
71 changed files with 1268 additions and 274 deletions

View File

@@ -54,6 +54,14 @@ steps:
$Package = Get-ChildItem -Recurse -Filter "CascadiaPackage_*.msix"
.\build\scripts\Test-WindowsTerminalPackage.ps1 -Verbose -Path $Package.FullName
- task: powershell@2
displayName: 'Source Index PDBs'
inputs:
targetType: filePath
filePath: build\scripts\Index-Pdbs.ps1
arguments: -SearchDir '$(Build.SourcesDirectory)' -SourceRoot '$(Build.SourcesDirectory)' -recursive -Verbose -CommitId $(Build.SourceVersion)
errorActionPreference: silentlyContinue
- task: VSTest@2
displayName: 'Run Unit Tests'
inputs:
@@ -81,7 +89,7 @@ steps:
platform: '$(BuildPlatform)'
configuration: '$(BuildConfiguration)'
condition: and(succeeded(), eq(variables['BuildPlatform'], 'x64'))
- task: CopyFiles@2
displayName: 'Copy *.appx/*.msix to Artifacts (Non-PR builds only)'
inputs:
@@ -101,3 +109,4 @@ steps:
PathtoPublish: '$(Build.ArtifactStagingDirectory)/appx'
ArtifactName: 'appx-$(BuildConfiguration)'
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))

View File

@@ -0,0 +1,85 @@
[CmdLetBinding()]
Param(
[Parameter(Mandatory=$true, Position=0)][string]$SearchDir,
[Parameter(Mandatory=$true, Position=1)][string]$SourceRoot,
[Parameter(Mandatory=$true, Position=2)][string]$CommitId,
[string]$Organization = "microsoft",
[string]$Repo = "terminal",
[switch]$recursive
)
$debuggerPath = (Get-ItemProperty -path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows Kits\Installed Roots" -name WindowsDebuggersRoot10).WindowsDebuggersRoot10
$srcsrvPath = Join-Path $debuggerPath "x64\srcsrv"
$srctoolExe = Join-Path $srcsrvPath "srctool.exe"
$pdbstrExe = Join-Path $srcsrvPath "pdbstr.exe"
$fileTable = @{}
foreach ($gitFile in & git ls-files)
{
$fileTable[$gitFile] = $gitFile
}
$mappedFiles = New-Object System.Collections.ArrayList
foreach ($file in (Get-ChildItem -r:$recursive "$SearchDir\*.pdb"))
{
Write-Verbose "Found $file"
$ErrorActionPreference = "Continue" # Azure Pipelines defaults to "Stop", continue past errors in this script.
$allFiles = & $srctoolExe -r "$file"
# If the pdb didn't have enough files then skip it (the srctool output has a blank line even when there's no info
# so check for less than 2 lines)
if ($allFiles.Length -lt 2)
{
continue
}
for ($i = 0; $i -lt $allFiles.Length; $i++)
{
if ($allFiles[$i].StartsWith($SourceRoot, [StringComparison]::OrdinalIgnoreCase))
{
$relative = $allFiles[$i].Substring($SourceRoot.Length).TrimStart("\")
$relative = $relative.Replace("\", "/")
# Git urls are case-sensitive but the PDB might contain a lowercased version of the file path.
# Look up the relative url in the output of "ls-files". If it's not there then it's not something
# in git, so don't index it.
$relative = $fileTable[$relative]
if ($relative)
{
$mapping = $allFiles[$i] + "*$relative"
$mappedFiles.Add($mapping)
Write-Verbose "Mapped path $($i): $mapping"
}
}
}
$pdbstrFile = Join-Path "$env:TEMP" "pdbstr.txt"
Write-Verbose "pdbstr.txt = $pdbstrFile"
@"
SRCSRV: ini ------------------------------------------------
VERSION=2
VERCTRL=http
SRCSRV: variables ------------------------------------------
ORGANIZATION=$Organization
REPO=$Repo
COMMITID=$CommitId
HTTP_ALIAS=https://raw.githubusercontent.com/%ORGANIZATION%/%REPO%/%COMMITID%/
HTTP_EXTRACT_TARGET=%HTTP_ALIAS%%var2%
SRCSRVTRG=%HTTP_EXTRACT_TARGET%
SRC_INDEX=public
SRCSRV: source files ---------------------------------------
$($mappedFiles -join "`r`n")
SRCSRV: end ------------------------------------------------
"@ | Set-Content $pdbstrFile
& $pdbstrExe -p:"$file" -w -s:srcsrv -i:$pdbstrFile
}
# Return with exit 0 to override any weird error code from other tools
Exit 0

Binary file not shown.

View File

@@ -18,4 +18,4 @@ Please consult the [license](https://raw.githubusercontent.com/microsoft/cascadi
### Fonts Included
* Cascadia Code
* from microsoft/cascadia-code@5f91b87e12c9af709fa406c22a79145879edc3d2
* from microsoft/cascadia-code@d3b1adacf2691dfadf8ebd8a08936d3ad8a062d0

View File

@@ -147,11 +147,11 @@ const UnicodeStorage& ROW::GetUnicodeStorage() const noexcept
// Arguments:
// - it - custom console iterator to use for seeking input data. bool() false when it becomes invalid while seeking.
// - index - column in row to start writing at
// - setWrap - set the wrap flags if we hit the end of the row while writing and there's still more data in the iterator.
// - wrap - change the wrap flag if we hit the end of the row while writing and there's still more data in the iterator.
// - limitRight - right inclusive column ID for the last write in this row. (optional, will just write to the end of row if nullopt)
// Return Value:
// - iterator to first cell that was not written to this row.
OutputCellIterator ROW::WriteCells(OutputCellIterator it, const size_t index, const bool setWrap, std::optional<size_t> limitRight)
OutputCellIterator ROW::WriteCells(OutputCellIterator it, const size_t index, const std::optional<bool> wrap, std::optional<size_t> limitRight)
{
THROW_HR_IF(E_INVALIDARG, index >= _charRow.size());
THROW_HR_IF(E_INVALIDARG, limitRight.value_or(0) >= _charRow.size());
@@ -202,10 +202,15 @@ OutputCellIterator ROW::WriteCells(OutputCellIterator it, const size_t index, co
++it;
}
// If we're asked to set the wrap status and we just filled the last column with some text, set wrap status on the row.
if (setWrap && fillingLastColumn)
// If we're asked to (un)set the wrap status and we just filled the last column with some text...
// NOTE:
// - wrap = std::nullopt --> don't change the wrap value
// - wrap = true --> we're filling cells as a steam, consider this a wrap
// - wrap = false --> we're filling cells as a block, unwrap
if (wrap.has_value() && fillingLastColumn)
{
_charRow.SetWrapForced(true);
// set wrap status on the row to parameter's value.
_charRow.SetWrapForced(wrap.value());
}
}
else

View File

@@ -57,7 +57,7 @@ public:
UnicodeStorage& GetUnicodeStorage() noexcept;
const UnicodeStorage& GetUnicodeStorage() const noexcept;
OutputCellIterator WriteCells(OutputCellIterator it, const size_t index, const bool setWrap, std::optional<size_t> limitRight = std::nullopt);
OutputCellIterator WriteCells(OutputCellIterator it, const size_t index, const std::optional<bool> wrap = std::nullopt, std::optional<size_t> limitRight = std::nullopt);
friend bool operator==(const ROW& a, const ROW& b) noexcept;

View File

@@ -318,10 +318,12 @@ OutputCellIterator TextBuffer::Write(const OutputCellIterator givenIt)
// Arguments:
// - givenIt - Iterator representing output cell data to write
// - target - the row/column to start writing the text to
// - wrap - change the wrap flag if we hit the end of the row while writing and there's still more data
// Return Value:
// - The final position of the iterator
OutputCellIterator TextBuffer::Write(const OutputCellIterator givenIt,
const COORD target)
const COORD target,
const std::optional<bool> wrap)
{
// Make mutable copy so we can walk.
auto it = givenIt;
@@ -336,7 +338,8 @@ OutputCellIterator TextBuffer::Write(const OutputCellIterator givenIt,
while (it && size.IsInBounds(lineTarget))
{
// Attempt to write as much data as possible onto this line.
it = WriteLine(it, lineTarget, true);
// NOTE: if wrap = true/false, we want to set the line's wrap to true/false (respectively) if we reach the end of the line
it = WriteLine(it, lineTarget, wrap);
// Move to the next line down.
lineTarget.X = 0;
@@ -351,13 +354,13 @@ OutputCellIterator TextBuffer::Write(const OutputCellIterator givenIt,
// Arguments:
// - givenIt - The iterator that will dereference into cell data to insert
// - target - Coordinate targeted within output buffer
// - setWrap - Whether we should try to set the wrap flag if we write up to the end of the line and have more data
// - wrap - change the wrap flag if we hit the end of the row while writing and there's still more data in the iterator.
// - limitRight - Optionally restrict the right boundary for writing (e.g. stop writing earlier than the end of line)
// Return Value:
// - The iterator, but advanced to where we stopped writing. Use to find input consumed length or cells written length.
OutputCellIterator TextBuffer::WriteLine(const OutputCellIterator givenIt,
const COORD target,
const bool setWrap,
const std::optional<bool> wrap,
std::optional<size_t> limitRight)
{
// If we're not in bounds, exit early.
@@ -368,7 +371,7 @@ OutputCellIterator TextBuffer::WriteLine(const OutputCellIterator givenIt,
// Get the row and write the cells
ROW& row = GetRowByOffset(target.Y);
const auto newIt = row.WriteCells(givenIt, target.X, setWrap, limitRight);
const auto newIt = row.WriteCells(givenIt, target.X, wrap, limitRight);
// Take the cell distance written and notify that it needs to be repainted.
const auto written = newIt.GetCellDistance(givenIt);

View File

@@ -89,11 +89,12 @@ public:
OutputCellIterator Write(const OutputCellIterator givenIt);
OutputCellIterator Write(const OutputCellIterator givenIt,
const COORD target);
const COORD target,
const std::optional<bool> wrap = true);
OutputCellIterator WriteLine(const OutputCellIterator givenIt,
const COORD target,
const bool setWrap = false,
const std::optional<bool> setWrap = std::nullopt,
const std::optional<size_t> limitRight = std::nullopt);
bool InsertCharacter(const wchar_t wch, const DbcsAttribute dbcsAttribute, const TextAttribute attr);

View File

@@ -19,16 +19,6 @@ namespace winrt::TerminalApp::implementation
InitializeComponent();
}
void MinMaxCloseControl::Maximize()
{
VisualStateManager::GoToState(MaximizeButton(), L"WindowStateMaximized", false);
}
void MinMaxCloseControl::RestoreDown()
{
VisualStateManager::GoToState(MaximizeButton(), L"WindowStateNormal", false);
}
// These event handlers simply forward each buttons click events up to the
// events we've exposed.
void MinMaxCloseControl::_MinimizeClick(winrt::Windows::Foundation::IInspectable const& sender,
@@ -48,6 +38,21 @@ namespace winrt::TerminalApp::implementation
_closeClickHandlers(*this, e);
}
void MinMaxCloseControl::SetWindowVisualState(WindowVisualState visualState)
{
switch (visualState)
{
case WindowVisualState::WindowVisualStateMaximized:
winrt::Windows::UI::Xaml::VisualStateManager::GoToState(MaximizeButton(), L"WindowStateMaximized", false);
break;
case WindowVisualState::WindowVisualStateNormal:
case WindowVisualState::WindowVisualStateIconified:
default:
winrt::Windows::UI::Xaml::VisualStateManager::GoToState(MaximizeButton(), L"WindowStateNormal", false);
break;
}
}
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(MinMaxCloseControl, MinimizeClick, _minimizeClickHandlers, TerminalApp::MinMaxCloseControl, RoutedEventArgs);
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(MinMaxCloseControl, MaximizeClick, _maximizeClickHandlers, TerminalApp::MinMaxCloseControl, RoutedEventArgs);
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(MinMaxCloseControl, CloseClick, _closeClickHandlers, TerminalApp::MinMaxCloseControl, RoutedEventArgs);

View File

@@ -18,8 +18,7 @@ namespace winrt::TerminalApp::implementation
{
MinMaxCloseControl();
void Maximize();
void RestoreDown();
void SetWindowVisualState(WindowVisualState visualState);
void _MinimizeClick(winrt::Windows::Foundation::IInspectable const& sender,
winrt::Windows::UI::Xaml::RoutedEventArgs const& e);

View File

@@ -1,14 +1,15 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import "..\TitlebarControl.idl";
namespace TerminalApp
{
[default_interface] runtimeclass MinMaxCloseControl : Windows.UI.Xaml.Controls.StackPanel
{
MinMaxCloseControl();
void Maximize();
void RestoreDown();
void SetWindowVisualState(WindowVisualState visualState);
event Windows.Foundation.TypedEventHandler<MinMaxCloseControl, Windows.UI.Xaml.RoutedEventArgs> MinimizeClick;
event Windows.Foundation.TypedEventHandler<MinMaxCloseControl, Windows.UI.Xaml.RoutedEventArgs> MaximizeClick;

View File

@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props')" />
<Import Project="..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props')" />
<Import Project="..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props" Condition="Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props')" />
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<PropertyGroup>
<!-- cppwinrt.build.pre.props depends on these settings: -->
<!-- build a dll, not exe (Application) -->
@@ -21,7 +22,6 @@
<ItemGroup>
<!-- DON'T PUT XAML FILES HERE! Put them in TerminalAppLib.vcxproj -->
</ItemGroup>
<!-- ========================= Headers ======================== -->
<ItemGroup>
<!-- Only put headers for winrt types in here. Don't put other header files
@@ -60,31 +60,25 @@
<ProjectReference Include="$(OpenConsoleDir)src\types\lib\types.vcxproj">
<Project>{18D09A24-8240-42D6-8CB6-236EEE820263}</Project>
</ProjectReference>
<!-- The midl compiler however, _will_ aggregate our winmd dependencies
somehow. So make sure to only include top-level dependencies here (don't
include Settings and Connection, since Control will include them for us) -->
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalSettings\TerminalSettings.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalConnection\TerminalConnection.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\TerminalControl.vcxproj" />
<!-- Reference TerminalAppLib here, so we can use it's TerminalApp.winmd as
our TerminalApp.winmd. This didn't work correctly in VS2017, you'd need to
manually reference the lib -->
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalApp\lib\TerminalAppLib.vcxproj" >
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalApp\lib\TerminalAppLib.vcxproj">
<Private>true</Private>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
</ProjectReference>
</ItemGroup>
<PropertyGroup>
<!-- A small helper for paths to the compiled cppwinrt projects -->
<_BinRoot Condition="'$(Platform)' != 'Win32'">$(OpenConsoleDir)$(Platform)\$(Configuration)\</_BinRoot>
<_BinRoot Condition="'$(Platform)' == 'Win32'">$(OpenConsoleDir)$(Configuration)\</_BinRoot>
</PropertyGroup>
<PropertyGroup>
<!--
DON'T REDIRECT OUR OUTPUT.
@@ -99,18 +93,28 @@
</ClCompile>
<Link>
<AdditionalDependencies>User32.lib;WindowsApp.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<!-- TerminalAppLib contains a DllMain that we need to force the use of. -->
<AdditionalOptions Condition="'$(Platform)'=='Win32'">/INCLUDE:_DllMain@12</AdditionalOptions>
<AdditionalOptions Condition="'$(Platform)'!='Win32'">/INCLUDE:DllMain</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<Import Project="$(OpenConsoleDir)src\common.build.post.props" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<!-- Import this set of targets that fixes a VS bug that manifests when using
the TerminalAppLib project -->
<Import Project="FixVisualStudioBug.targets" />
</Project>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets'))" />
</Target>
<Import Project="..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets" Condition="Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets')" />
<Import Project="..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets')" />
<Import Project="..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets')" />
</Project>

View File

@@ -59,12 +59,10 @@ namespace winrt::TerminalApp::implementation
::GetWindowPlacement(_window, &placement);
if (placement.showCmd == SW_SHOWNORMAL)
{
MinMaxCloseControl().Maximize();
::PostMessage(_window, WM_SYSCOMMAND, SC_MAXIMIZE | flag, lParam);
}
else if (placement.showCmd == SW_SHOWMAXIMIZED)
{
MinMaxCloseControl().RestoreDown();
::PostMessage(_window, WM_SYSCOMMAND, SC_RESTORE | flag, lParam);
}
}
@@ -92,4 +90,9 @@ namespace winrt::TerminalApp::implementation
::PostQuitMessage(0);
}
void TitlebarControl::SetWindowVisualState(WindowVisualState visualState)
{
MinMaxCloseControl().SetWindowVisualState(visualState);
}
}

View File

@@ -20,6 +20,8 @@ namespace winrt::TerminalApp::implementation
Windows::UI::Xaml::UIElement Content();
void Content(Windows::UI::Xaml::UIElement content);
void SetWindowVisualState(WindowVisualState visualState);
void Root_SizeChanged(const IInspectable& sender, Windows::UI::Xaml::SizeChangedEventArgs const& e);
void Minimize_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);

View File

@@ -3,9 +3,17 @@
namespace TerminalApp
{
enum WindowVisualState
{
WindowVisualStateNormal = 0,
WindowVisualStateMaximized,
WindowVisualStateIconified
};
[default_interface] runtimeclass TitlebarControl : Windows.UI.Xaml.Controls.Grid
{
TitlebarControl(UInt64 parentWindowHandle);
void SetWindowVisualState(WindowVisualState visualState);
Windows.UI.Xaml.UIElement Content;
Windows.UI.Xaml.Controls.Border DragBar { get; };

View File

@@ -17,9 +17,8 @@
"commandline": "powershell.exe",
"hidden": false,
"startingDirectory": "%USERPROFILE%",
"background": "#012456",
"closeOnExit": true,
"colorScheme": "Campbell",
"colorScheme": "Campbell Powershell",
"cursorColor": "#FFFFFF",
"cursorShape": "bar",
"fontFace": "Consolas",
@@ -46,8 +45,7 @@
"icon": "ms-appx:///ProfileIcons/{0caa0dad-35be-5f56-a8ff-afceeeaa6101}.png",
"padding": "8, 8, 8, 8",
"snapOnInput": true,
"useAcrylic": true,
"acrylicOpacity": 0.75
"useAcrylic": false
}
],
"schemes":
@@ -73,6 +71,27 @@
"brightCyan": "#61D6D6",
"brightWhite": "#F2F2F2"
},
{
"name": "Campbell Powershell",
"foreground": "#CCCCCC",
"background": "#012456",
"black": "#0C0C0C",
"red": "#C50F1F",
"green": "#13A10E",
"yellow": "#C19C00",
"blue": "#0037DA",
"purple": "#881798",
"cyan": "#3A96DD",
"white": "#CCCCCC",
"brightBlack": "#767676",
"brightRed": "#E74856",
"brightGreen": "#16C60C",
"brightYellow": "#F9F1A5",
"brightBlue": "#3B78FF",
"brightPurple": "#B4009E",
"brightCyan": "#61D6D6",
"brightWhite": "#F2F2F2"
},
{
"name": "Vintage",
"foreground": "#C0C0C0",

View File

@@ -18,6 +18,8 @@
#undef GetCurrentTime
#endif
#include <wil/cppwinrt.h>
#include <unknwn.h>
#include <hstring.h>

View File

@@ -1,6 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Build.Tasks.Git" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.SourceLink.Common" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.SourceLink.GitHub" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.0.0-preview7" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.2.190611001-prerelease" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.190730.2" targetFramework="native" />
</packages>
</packages>

View File

@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props')" />
<Import Project="..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props')" />
<Import Project="..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props" Condition="Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props')" />
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<PropertyGroup>
<ConfigurationType>DynamicLibrary</ConfigurationType>
@@ -35,7 +38,7 @@
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="init.cpp"/>
<ClCompile Include="init.cpp" />
<ClCompile Include="AzureConnection.cpp" Condition="'$(Platform)'!='ARM64'" />
<ClCompile Include="AzureConnection-ARM64.cpp" Condition="'$(Platform)'=='ARM64'" />
<ClCompile Include="pch.cpp">
@@ -90,5 +93,14 @@
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\vcpkg-cpprestsdk.2.10.0\build\native\vcpkg-cpprestsdk.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\vcpkg-cpprestsdk.2.10.0\build\native\vcpkg-cpprestsdk.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets'))" />
</Target>
</Project>
<Import Project="..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets" Condition="Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets')" />
<Import Project="..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets')" />
<Import Project="..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets')" />
</Project>

View File

@@ -15,6 +15,7 @@
<ClCompile Include="ConhostConnection.cpp" />
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
<ClCompile Include="AzureConnection.cpp" />
<ClCompile Include="init.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />

View File

@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Build.Tasks.Git" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.SourceLink.Common" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.SourceLink.GitHub" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.190730.2" targetFramework="native" />
<package id="vcpkg-cpprestsdk" version="2.10.0" targetFramework="native" />
</packages>
</packages>

View File

@@ -15,6 +15,8 @@
// Must be included before any WinRT headers.
#include <unknwn.h>
#include <wil/cppwinrt.h>
#include "winrt/Windows.Foundation.h"
#include "winrt/Windows.Security.Credentials.h"
#include "winrt/Windows.Foundation.Collections.h"

View File

@@ -638,41 +638,29 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
}
const auto modifiers = _GetPressedModifierKeys();
// AltGr key combinations don't always contain any meaningful,
// pretranslated unicode character during WM_KEYDOWN.
// E.g. on a German keyboard AltGr+Q should result in a "@" character,
// but actually results in "Q" with Alt and Ctrl modifier states.
// By returning false though, we can abort handling this WM_KEYDOWN
// event and let the WM_CHAR handler kick in, which will be
// provided with an appropriate unicode character.
//
// GH#2235: Make sure to handle AltGr before trying keybindings,
// so Ctrl+Alt keybindings won't eat an AltGr keypress.
if (modifiers.IsAltGrPressed())
{
_HandleVoidKeyEvent();
e.Handled(false);
return;
}
const auto vkey = static_cast<WORD>(e.OriginalKey());
const auto scanCode = e.KeyStatus().ScanCode;
bool handled = false;
auto bindings = _settings.KeyBindings();
if (bindings)
// GH#2235: Terminal::Settings hasn't been modified to differentiate between AltGr and Ctrl+Alt yet.
// -> Don't check for key bindings if this is an AltGr key combination.
if (!modifiers.IsAltGrPressed())
{
handled = bindings.TryKeyChord({
modifiers.IsCtrlPressed(),
modifiers.IsAltPressed(),
modifiers.IsShiftPressed(),
vkey,
});
auto bindings = _settings.KeyBindings();
if (bindings)
{
handled = bindings.TryKeyChord({
modifiers.IsCtrlPressed(),
modifiers.IsAltPressed(),
modifiers.IsShiftPressed(),
vkey,
});
}
}
if (!handled)
{
handled = _TrySendKeyEvent(vkey, modifiers);
handled = _TrySendKeyEvent(vkey, scanCode, modifiers);
}
// Manually prevent keyboard navigation with tab. We want to send tab to
@@ -686,17 +674,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
e.Handled(handled);
}
// Method Description:
// - Some key events cannot be handled (e.g. AltGr combinations) and are
// delegated to the character handler. Just like with _TrySendKeyEvent(),
// the character handler counts on us though to:
// - Clears the current selection.
// - Makes the cursor briefly visible during typing.
void TermControl::_HandleVoidKeyEvent()
{
_TrySendKeyEvent(0, {});
}
// Method Description:
// - Send this particular key event to the terminal.
// See Terminal::SendKeyEvent for more information.
@@ -705,14 +682,14 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
// Arguments:
// - vkey: The vkey of the key pressed.
// - states: The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states.
bool TermControl::_TrySendKeyEvent(WORD vkey, const ControlKeyStates modifiers)
bool TermControl::_TrySendKeyEvent(const WORD vkey, const WORD scanCode, const ControlKeyStates modifiers)
{
_terminal->ClearSelection();
// If the terminal translated the key, mark the event as handled.
// This will prevent the system from trying to get the character out
// of it and sending us a CharacterRecieved event.
const auto handled = vkey ? _terminal->SendKeyEvent(vkey, modifiers) : true;
const auto handled = vkey ? _terminal->SendKeyEvent(vkey, scanCode, modifiers) : true;
if (_cursorTimer.has_value())
{

View File

@@ -184,8 +184,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
static Windows::UI::Xaml::Thickness _ParseThicknessFromPadding(const hstring padding);
::Microsoft::Terminal::Core::ControlKeyStates _GetPressedModifierKeys() const;
void _HandleVoidKeyEvent();
bool _TrySendKeyEvent(WORD vkey, ::Microsoft::Terminal::Core::ControlKeyStates modifiers);
bool _TrySendKeyEvent(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers);
const COORD _GetTerminalPosition(winrt::Windows::Foundation::Point cursorPosition);
const unsigned int _NumberOfClicks(winrt::Windows::Foundation::Point clickPos, Timestamp clickTime);

View File

@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props')" />
<Import Project="..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props')" />
<Import Project="..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props" Condition="Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props')" />
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<PropertyGroup>
<!-- cppwinrt.build.pre.props depends on these settings: -->
@@ -86,4 +89,18 @@
</PropertyGroup>
<Import Project="$(OpenConsoleDir)src\common.build.post.props" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
</Project>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets'))" />
</Target>
<Import Project="..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets" Condition="Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets')" />
<Import Project="..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets')" />
<Import Project="..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets')" />
</Project>

View File

@@ -17,6 +17,7 @@
<ClCompile Include="XamlUiaTextRange.cpp" />
<ClCompile Include="TermControlUiaProvider.cpp" />
<ClCompile Include="UiaTextRange.cpp" />
<ClCompile Include="init.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
@@ -37,4 +38,4 @@
<ItemGroup>
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
</ItemGroup>
</Project>
</Project>

View File

@@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Build.Tasks.Git" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.SourceLink.Common" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.SourceLink.GitHub" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.190730.2" targetFramework="native" />
</packages>
</packages>

View File

@@ -18,6 +18,8 @@
#undef GetCurrentTime
#endif
#include <wil/cppwinrt.h>
#include <unknwn.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>

View File

@@ -12,7 +12,7 @@ namespace Microsoft::Terminal::Core
public:
virtual ~ITerminalInput() {}
virtual bool SendKeyEvent(const WORD vkey, const ControlKeyStates states) = 0;
virtual bool SendKeyEvent(const WORD vkey, const WORD scanCode, const ControlKeyStates states) = 0;
// void SendMouseEvent(uint row, uint col, KeyModifiers modifiers);
[[nodiscard]] virtual HRESULT UserResize(const COORD size) noexcept = 0;

View File

@@ -205,7 +205,7 @@ void Terminal::Write(std::wstring_view stringView)
// Return Value:
// - true if we translated the key event, and it should not be processed any further.
// - false if we did not translate the key, and it should be processed into a character.
bool Terminal::SendKeyEvent(const WORD vkey, const ControlKeyStates states)
bool Terminal::SendKeyEvent(const WORD vkey, const WORD scanCode, const ControlKeyStates states)
{
if (_snapOnInput && _scrollOffset != 0)
{
@@ -222,14 +222,7 @@ bool Terminal::SendKeyEvent(const WORD vkey, const ControlKeyStates states)
wchar_t ch = UNICODE_NULL;
if (states.IsAltPressed() && vkey != VK_SPACE)
{
ch = static_cast<wchar_t>(LOWORD(MapVirtualKey(vkey, MAPVK_VK_TO_CHAR)));
// MapVirtualKey will give us the capitalized version of the char.
// However, if shift isn't pressed, we want to send the lowercase version.
// (See GH#637)
if (!states.IsShiftPressed())
{
ch = towlower(ch);
}
ch = _CharacterFromKeyEvent(vkey, scanCode, states);
}
if (states.IsCtrlPressed())
@@ -260,12 +253,54 @@ bool Terminal::SendKeyEvent(const WORD vkey, const ControlKeyStates states)
const bool manuallyHandled = ch != UNICODE_NULL;
KeyEvent keyEv{ true, 0, vkey, 0, ch, states.Value() };
KeyEvent keyEv{ true, 0, vkey, scanCode, ch, states.Value() };
const bool translated = _terminalInput->HandleKey(&keyEv);
return translated && manuallyHandled;
}
// Method Description:
// - Returns the keyboard's scan code for the given virtual key code.
// Arguments:
// - vkey: The virtual key code.
// Return Value:
// - The keyboard's scan code.
WORD Terminal::_ScanCodeFromVirtualKey(const WORD vkey) noexcept
{
return LOWORD(MapVirtualKeyW(vkey, MAPVK_VK_TO_VSC));
}
// Method Description:
// - Translates the specified virtual key code and keyboard state to the corresponding character.
// Arguments:
// - vkey: The virtual key code that initiated this keyboard event.
// - scanCode: The scan code that initiated this keyboard event.
// - states: The current keyboard state.
// Return Value:
// - The character that would result from this virtual key code and keyboard state.
wchar_t Terminal::_CharacterFromKeyEvent(const WORD vkey, const WORD scanCode, const ControlKeyStates states) noexcept
{
const auto sc = scanCode != 0 ? scanCode : _ScanCodeFromVirtualKey(vkey);
// We might want to use GetKeyboardState() instead of building our own keyState.
// The question is whether that's necessary though. For now it seems to work fine as it is.
BYTE keyState[256] = {};
keyState[VK_SHIFT] = states.IsShiftPressed() ? 0x80 : 0;
keyState[VK_CONTROL] = states.IsCtrlPressed() ? 0x80 : 0;
keyState[VK_MENU] = states.IsAltPressed() ? 0x80 : 0;
// Technically ToUnicodeEx() can produce arbitrarily long sequences of diacritics etc.
// Since we only handle the case of a single UTF-16 code point, we can set the buffer size to 2 though.
constexpr size_t bufferSize = 2;
wchar_t buffer[bufferSize];
// wFlags: If bit 2 is set, keyboard state is not changed (Windows 10, version 1607 and newer)
const auto result = ToUnicodeEx(vkey, sc, keyState, buffer, bufferSize, 0b100, nullptr);
// TODO:GH#2853 We're only handling single UTF-16 code points right now, since that's the only thing KeyEvent supports.
return result == 1 || result == -1 ? buffer[0] : 0;
}
// Method Description:
// - Aquire a read lock on the terminal.
// Return Value:
@@ -381,6 +416,18 @@ void Terminal::_WriteBuffer(const std::wstring_view& stringView)
}
}
// If we're about to try to place the cursor past the right edge of the buffer, move it down a row
// This is another patch that GH#780 should supersede. This is really correcting for other bad situations
// like bisecting (writing only the leading half because there's no room for the trailing) a wide character
// into the buffer. However, it's not really all-up correctable without implementing a full WriteStream here.
// Also, this particular code RIGHT HERE shouldn't need to know anything about the cursor or the cells advanced
// which also will be solved by GH#780 (hopefully).
if (proposedCursorPosition.X > bufferSize.RightInclusive())
{
proposedCursorPosition.X = 0;
proposedCursorPosition.Y++;
}
// If we're about to scroll past the bottom of the buffer, instead cycle the buffer.
const auto newRows = proposedCursorPosition.Y - bufferSize.Height() + 1;
if (newRows > 0)

View File

@@ -82,7 +82,7 @@ public:
#pragma region ITerminalInput
// These methods are defined in Terminal.cpp
bool SendKeyEvent(const WORD vkey, const Microsoft::Terminal::Core::ControlKeyStates states) override;
bool SendKeyEvent(const WORD vkey, const WORD scanCode, const Microsoft::Terminal::Core::ControlKeyStates states) override;
[[nodiscard]] HRESULT UserResize(const COORD viewportSize) noexcept override;
void UserScrollViewport(const int viewTop) override;
int GetScrollOffset() override;
@@ -207,6 +207,9 @@ private:
// underneath them, while others would prefer to anchor it in place.
// Either way, we sohould make this behavior controlled by a setting.
static WORD _ScanCodeFromVirtualKey(const WORD vkey) noexcept;
static wchar_t _CharacterFromKeyEvent(const WORD vkey, const WORD scanCode, const ControlKeyStates states) noexcept;
int _ViewStartIndex() const noexcept;
int _VisibleStartIndex() const noexcept;

View File

@@ -13,7 +13,7 @@
<ProjectName>TerminalCore</ProjectName>
<TargetName>TerminalCore</TargetName>
<WindowsTargetPlatformMinVersion>10.0.17763.0</WindowsTargetPlatformMinVersion>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
<RootNamespace>Microsoft.Terminal.Core</RootNamespace>
</PropertyGroup>
<!-- ============================ References ============================ -->

View File

@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props')" />
<Import Project="..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props')" />
<Import Project="..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props" Condition="Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props')" />
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<PropertyGroup>
<!-- cppwinrt.build.pre.props depends on these settings: -->
@@ -47,7 +50,6 @@
<None Include="packages.config" />
<None Include="TerminalSettings.def" />
</ItemGroup>
<PropertyGroup>
<!--
DON'T REDIRECT OUR OUTPUT.
@@ -58,4 +60,18 @@
</PropertyGroup>
<Import Project="$(OpenConsoleDir)src\common.build.post.props" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
</Project>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets'))" />
</Target>
<Import Project="..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets" Condition="Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets')" />
<Import Project="..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets')" />
<Import Project="..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets')" />
</Project>

View File

@@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Build.Tasks.Git" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.SourceLink.Common" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.SourceLink.GitHub" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.190730.2" targetFramework="native" />
</packages>
</packages>

View File

@@ -19,4 +19,5 @@
#endif
#include <unknwn.h>
#include <wil/cppwinrt.h>
#include <winrt/Windows.Foundation.h>

View File

@@ -48,12 +48,12 @@ namespace TerminalCoreUnitTests
// Verify that Alt+a generates a lowercase a on the input
expectedinput = L"\x1b"
"a";
VERIFY_IS_TRUE(term.SendKeyEvent(L'A', ControlKeyStates::LeftAltPressed));
VERIFY_IS_TRUE(term.SendKeyEvent(L'A', 0, ControlKeyStates::LeftAltPressed));
// Verify that Alt+shift+a generates a uppercase a on the input
expectedinput = L"\x1b"
"A";
VERIFY_IS_TRUE(term.SendKeyEvent(L'A', ControlKeyStates::LeftAltPressed | ControlKeyStates::ShiftPressed));
VERIFY_IS_TRUE(term.SendKeyEvent(L'A', 0, ControlKeyStates::LeftAltPressed | ControlKeyStates::ShiftPressed));
}
void InputTest::AltSpace()
@@ -61,6 +61,6 @@ namespace TerminalCoreUnitTests
// Make sure we don't handle Alt+Space. The system will use this to
// bring up the system menu for restore, min/maximimize, size, move,
// close
VERIFY_IS_FALSE(term.SendKeyEvent(L' ', ControlKeyStates::LeftAltPressed));
VERIFY_IS_FALSE(term.SendKeyEvent(L' ', 0, ControlKeyStates::LeftAltPressed));
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT license.
*/
#include "precomp.h"
#include <WexTestClass.h>
#include "../cascadia/TerminalCore/Terminal.hpp"
#include "../cascadia/UnitTests_TerminalCore/MockTermSettings.h"
#include "../renderer/inc/DummyRenderTarget.hpp"
#include "consoletaeftemplates.hpp"
using namespace WEX::Logging;
using namespace WEX::TestExecution;
using namespace Microsoft::Terminal::Core;
using namespace winrt::Microsoft::Terminal::Settings;
namespace TerminalCoreUnitTests
{
class TerminalApiTests
{
TEST_CLASS(TerminalApiTests);
struct Baton
{
HANDLE ev;
std::wstring text;
Terminal* pTerm;
};
TEST_METHOD(PrintStringOfEmojiBisectingFinalColumn)
{
Terminal term;
DummyRenderTarget emptyRT;
term.Create({ 100, 100 }, 0, emptyRT);
std::wstring textToPrint;
textToPrint.push_back(L'A'); // A is half-width, push it in.
// Put a ton of copies of a full-width emoji here.
const wchar_t* emoji = L"\xD83D\xDE00"; // 1F600 is wide in https://www.unicode.org/Public/UCD/latest/ucd/EastAsianWidth.txt
for (size_t i = 0; i < 120; ++i)
{
textToPrint = textToPrint.append(emoji);
}
Baton b;
b.ev = CreateEventW(nullptr, TRUE, FALSE, L"It is an event");
b.text = textToPrint;
b.pTerm = &term;
Log::Comment(L"Launching thread to write data.");
HANDLE hThread = CreateThread(
nullptr, 0, [](LPVOID c) -> DWORD {
Baton& b = *reinterpret_cast<Baton*>(c);
Log::Comment(L"Writing data.");
b.pTerm->PrintString(b.text);
Log::Comment(L"Setting event.");
SetEvent(b.ev);
return 0;
},
(LPVOID)&b,
0,
nullptr);
Log::Comment(L"Waiting for the write.");
switch (WaitForSingleObject(b.ev, 2000))
{
case WAIT_OBJECT_0:
Log::Comment(L"Didn't get stuck. Success.");
break;
case WAIT_TIMEOUT:
Log::Comment(L"Wait timed out. It got stuck.");
Log::Result(WEX::Logging::TestResults::Failed);
break;
case WAIT_FAILED:
Log::Comment(L"Wait failed for some reason. We didn't expect this.");
Log::Result(WEX::Logging::TestResults::Failed);
break;
default:
Log::Comment(L"Wait return code that no one expected. Fail.");
Log::Result(WEX::Logging::TestResults::Failed);
break;
}
TerminateThread(hThread, 0);
return;
}
};
}

View File

@@ -9,6 +9,7 @@
<ClCompile Include="precomp.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="TerminalApiTests.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\buffer\out\lib\bufferout.vcxproj">

View File

@@ -263,8 +263,6 @@ void NonClientIslandWindow::_UpdateDragRegion()
// - Hit test the frame for resizing and moving.
// Arguments:
// - ptMouse: the mouse point being tested, in absolute (NOT WINDOW) coordinates.
// - titlebarIsCaption: If true, we want to treat the titlebar area as
// HTCAPTION, otherwise we'll return HTNOWHERE for the titlebar.
// Return Value:
// - one of the values from
// https://docs.microsoft.com/en-us/windows/desktop/inputdev/wm-nchittest#return-value
@@ -272,13 +270,7 @@ void NonClientIslandWindow::_UpdateDragRegion()
// NOTE:
// - Largely taken from code on:
// https://docs.microsoft.com/en-us/windows/desktop/dwm/customframe
// NOTE[2]: Concerning `titlebarIsCaption`
// - We want HTNOWHERE as the return value for WM_NCHITTEST, so that we can get
// mouse presses in the titlebar area. If we return HTCAPTION there, we won't
// get any mouse WMs. However, when we're handling the mouse events, we need
// to know if the mouse was in that are or not, so we'll return HTCAPTION in
// that handler, to differentiate from the rest of the window.
[[nodiscard]] LRESULT NonClientIslandWindow::HitTestNCA(POINT ptMouse, const bool titlebarIsCaption) const noexcept
[[nodiscard]] LRESULT NonClientIslandWindow::HitTestNCA(POINT ptMouse) const noexcept
{
// Get the window rectangle.
RECT rcWindow = BaseWindow::GetWindowRect();
@@ -319,7 +311,7 @@ void NonClientIslandWindow::_UpdateDragRegion()
// clang-format off
// Hit test (HTTOPLEFT, ... HTBOTTOMRIGHT)
const auto topHt = fOnResizeBorder ? HTTOP : (titlebarIsCaption ? HTCAPTION : HTNOWHERE);
const auto topHt = fOnResizeBorder ? HTTOP : HTCAPTION;
LRESULT hitTests[3][3] = {
{ HTTOPLEFT, topHt, HTTOPRIGHT },
{ HTLEFT, HTNOWHERE, HTRIGHT },
@@ -520,7 +512,7 @@ RECT NonClientIslandWindow::GetMaxWindowRectInPixels(const RECT* const prcSugges
// Handle hit testing in the NCA if not handled by DwmDefWindowProc.
if (lRet == 0)
{
lRet = HitTestNCA({ GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }, false);
lRet = HitTestNCA({ GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) });
if (lRet != HTNOWHERE)
{
return lRet;
@@ -598,22 +590,18 @@ RECT NonClientIslandWindow::GetMaxWindowRectInPixels(const RECT* const prcSugges
return 0;
}
case WM_LBUTTONDOWN:
case WM_NCLBUTTONDOWN:
case WM_NCLBUTTONUP:
case WM_NCMBUTTONDOWN:
case WM_NCMBUTTONUP:
case WM_NCRBUTTONDOWN:
case WM_NCRBUTTONUP:
case WM_NCXBUTTONDOWN:
case WM_NCXBUTTONUP:
{
POINT point1 = {};
::GetCursorPos(&point1);
const auto region = HitTestNCA(point1, true);
if (region == HTCAPTION)
{
// If we clicked in the titlebar, raise an event so the app host can
// dispatch an appropriate event.
_DragRegionClickedHandlers();
const auto longParam = MAKELPARAM(point1.x, point1.y);
::SetActiveWindow(_window.get());
::PostMessage(_window.get(), WM_SYSCOMMAND, SC_MOVE | HTCAPTION, longParam);
}
// If we clicked in the titlebar, raise an event so the app host can
// dispatch an appropriate event.
_DragRegionClickedHandlers();
break;
}
@@ -679,6 +667,17 @@ bool NonClientIslandWindow::_HandleWindowPosChanging(WINDOWPOS* const windowPos)
return false;
}
const auto windowStyle = GetWindowStyle(_window.get());
const auto isMaximized = WI_IsFlagSet(windowStyle, WS_MAXIMIZE);
const auto isIconified = WI_IsFlagSet(windowStyle, WS_ICONIC);
if (_titlebar)
{
_titlebar.SetWindowVisualState(isMaximized ? winrt::TerminalApp::WindowVisualState::WindowVisualStateMaximized :
isIconified ? winrt::TerminalApp::WindowVisualState::WindowVisualStateIconified :
winrt::TerminalApp::WindowVisualState::WindowVisualStateNormal);
}
// Figure out the suggested dimensions
RECT rcSuggested;
rcSuggested.left = windowPos->x;
@@ -726,9 +725,6 @@ bool NonClientIslandWindow::_HandleWindowPosChanging(WINDOWPOS* const windowPos)
}
}
const auto windowStyle = GetWindowStyle(_window.get());
const auto isMaximized = WI_IsFlagSet(windowStyle, WS_MAXIMIZE);
// If we're about to maximize the window, determine how much we're about to
// overhang by, and adjust for that.
// We need to do this because maximized windows will typically overhang the

View File

@@ -55,7 +55,7 @@ private:
RECT GetDragAreaRect() const noexcept;
[[nodiscard]] LRESULT HitTestNCA(POINT ptMouse, const bool titlebarIsCaption) const noexcept;
[[nodiscard]] LRESULT HitTestNCA(POINT ptMouse) const noexcept;
[[nodiscard]] HRESULT _UpdateFrameMargins() const noexcept;

View File

@@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props')" />
<Import Project="..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props')" />
<Import Project="..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props" Condition="Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props')" />
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview7\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview7\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<PropertyGroup>
<ConfigurationType>Application</ConfigurationType>
<SubSystem>Windows</SubSystem>
@@ -77,16 +78,13 @@
<!-- Dependencies -->
<ItemGroup>
<!-- Even though we do have proper recursive dependencies, we want to keep some of these here
so that the AppX Manifest contains their activatable classes. -->
so that the AppX Manifest contains their activatable classes. -->
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalSettings\TerminalSettings.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\TerminalControl.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalConnection\TerminalConnection.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalApp\TerminalApp.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\types\lib\types.vcxproj" />
</ItemGroup>
<!--
This ItemGroup and the Globals PropertyGroup below it are required in order
to enable F5 debugging for the unpackaged application
@@ -102,26 +100,27 @@
<!-- DON'T REDIRECT OUR OUTPUT -->
<NoOutputRedirection>true</NoOutputRedirection>
</PropertyGroup>
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.2.190611001-prerelease\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.2.190611001-prerelease\build\native\Microsoft.UI.Xaml.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.2.190611001-prerelease\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.2.190611001-prerelease\build\native\Microsoft.UI.Xaml.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.190521.3\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.190521.3\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview7\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview7\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview7\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview7\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.1-rc\build\native\Microsoft.VCRTForwarders.140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.1-rc\build\native\Microsoft.VCRTForwarders.140.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets'))" />
</Target>
<Import Project="$(OpenConsoleDir)src\common.build.post.props" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<Import Project="..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.190521.3\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.190521.3\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview7\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview7\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Import Project="..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.1-rc\build\native\Microsoft.VCRTForwarders.140.targets" Condition="Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.1-rc\build\native\Microsoft.VCRTForwarders.140.targets')" />
<!-- Override GetPackagingOutputs to roll up all our dependencies.
This ensures that when the WAP packaging project asks what files go into
the package, we tell it.
@@ -143,11 +142,12 @@
ContinueOnError="$(_ContinueOnError)">
<Output TaskParameter="TargetOutputs" ItemName="_PackagingOutputsFromOtherProjects"/>
</MSBuild>
<ItemGroup>
<PackagingOutputs Include="@(_PackagingOutputsFromOtherProjects)" />
</ItemGroup>
</Target>
<Import Project="$(OpenConsoleDir)\build\rules\GenerateSxsManifestsFromWinmds.targets" />
</Project>
<Import Project="..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets" Condition="Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets')" />
<Import Project="..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets')" />
<Import Project="..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets')" />
</Project>

View File

@@ -1,7 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.190730.2" targetFramework="native" />
<package id="Microsoft.Build.Tasks.Git" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.SourceLink.Common" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.SourceLink.GitHub" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.0.0-preview7" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.2.190611001-prerelease" targetFramework="native" />
<package id="Microsoft.VCRTForwarders.140" version="1.0.1-rc" targetFramework="native" />
</packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.190730.2" targetFramework="native" />
</packages>

View File

@@ -38,6 +38,9 @@ Abstract:
#ifdef GetCurrentTime
#undef GetCurrentTime
#endif
#include <wil/cppwinrt.h>
// Needed just for XamlIslands to work at all:
#include <winrt/Windows.system.h>
#include <winrt/Windows.Foundation.Collections.h>

View File

@@ -290,7 +290,10 @@ void WriteToScreen(SCREEN_INFORMATION& screenInfo, const Viewport& region)
try
{
const OutputCellIterator it(character, lengthToWrite);
const auto done = screenInfo.Write(it, startingCoordinate);
// when writing to the buffer, specifically unset wrap if we get to the last column.
// a fill operation should UNSET wrap in that scenario. See GH #1126 for more details.
const auto done = screenInfo.Write(it, startingCoordinate, false);
cellsModified = done.GetInputDistance(it);
// Notify accessibility

View File

@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props')" />
<Import Project="..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props')" />
<Import Project="..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props" Condition="Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props')" />
<Import Project="..\..\common.build.pre.props" />
<ItemGroup>
<ClInclude Include="..\precomp.h" />
@@ -65,6 +68,9 @@
<ItemGroup>
<Manifest Include="openconsole.exe.manifest" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<PropertyGroup>
<ProjectGuid>{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
@@ -88,4 +94,18 @@
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
<Import Project="..\..\common.build.exe.props" />
<Import Project="..\..\common.build.post.props" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets'))" />
</Target>
<Import Project="..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets" Condition="Exists('..\..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets')" />
<Import Project="..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets')" />
<Import Project="..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets')" />
</Project>

View File

@@ -38,4 +38,10 @@
<ItemGroup>
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
</ItemGroup>
<ItemGroup>
<Manifest Include="openconsole.exe.manifest" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Build.Tasks.Git" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.SourceLink.Common" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.SourceLink.GitHub" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
</packages>

View File

@@ -58,4 +58,125 @@ class FillOutputTests
&charsWritten));
VERIFY_ARE_EQUAL(1u, charsWritten);
}
TEST_METHOD(UnsetWrap)
{
// WARNING: If this test suddenly decides to start failing,
// this is because the wrap registry key is not set.
// TODO GH #2859: Get/Set Registry Key for Wrap
HANDLE hConsole = GetStdOutputHandle();
DWORD charsWritten = 0;
CONSOLE_SCREEN_BUFFER_INFOEX sbiex = { 0 };
sbiex.cbSize = sizeof(sbiex);
VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hConsole, &sbiex));
const auto consoleWidth = sbiex.dwSize.X;
std::wstring input(consoleWidth + 2, L'a');
std::wstring filled(consoleWidth, L'b');
// Write until a wrap occurs
VERIFY_WIN32_BOOL_SUCCEEDED(WriteConsoleW(hConsole,
input.data(),
gsl::narrow_cast<DWORD>(input.size()),
&charsWritten,
nullptr));
// Verify wrap occurred
std::unique_ptr<wchar_t[]> bufferText = std::make_unique<wchar_t[]>(consoleWidth);
DWORD readSize = 0;
VERIFY_WIN32_BOOL_SUCCEEDED(ReadConsoleOutputCharacterW(hConsole,
bufferText.get(),
consoleWidth,
{ 0, 0 },
&readSize));
WEX::Common::String expected(input.c_str(), readSize);
WEX::Common::String actual(bufferText.get(), readSize);
VERIFY_ARE_EQUAL(expected, actual);
bufferText = std::make_unique<wchar_t[]>(2);
VERIFY_WIN32_BOOL_SUCCEEDED(ReadConsoleOutputCharacterW(hConsole,
bufferText.get(),
2,
{ 0, 1 },
&readSize));
VERIFY_ARE_EQUAL(2u, readSize);
expected = WEX::Common::String(input.c_str(), readSize);
actual = WEX::Common::String(bufferText.get(), readSize);
VERIFY_ARE_EQUAL(expected, actual);
// Fill Console Line with 'b's
VERIFY_WIN32_BOOL_SUCCEEDED(FillConsoleOutputCharacterW(hConsole,
L'b',
consoleWidth,
{ 2, 0 },
&charsWritten));
// Verify first line is full of 'a's then 'b's
bufferText = std::make_unique<wchar_t[]>(consoleWidth);
VERIFY_WIN32_BOOL_SUCCEEDED(ReadConsoleOutputCharacterW(hConsole,
bufferText.get(),
consoleWidth,
{ 0, 0 },
&readSize));
expected = WEX::Common::String(input.c_str(), 2);
actual = WEX::Common::String(bufferText.get(), 2);
VERIFY_ARE_EQUAL(expected, actual);
expected = WEX::Common::String(filled.c_str(), consoleWidth - 2);
actual = WEX::Common::String(&bufferText[2], readSize - 2);
VERIFY_ARE_EQUAL(expected, actual);
// Verify second line is still has 'a's that wrapped over
bufferText = std::make_unique<wchar_t[]>(2);
VERIFY_WIN32_BOOL_SUCCEEDED(ReadConsoleOutputCharacterW(hConsole,
bufferText.get(),
static_cast<SHORT>(2),
{ 0, 0 },
&readSize));
VERIFY_ARE_EQUAL(2u, readSize);
expected = WEX::Common::String(input.c_str(), 2);
actual = WEX::Common::String(bufferText.get(), readSize);
VERIFY_ARE_EQUAL(expected, actual);
// Resize to be smaller by 2
sbiex.srWindow.Right -= 2;
sbiex.dwSize.X -= 2;
VERIFY_WIN32_BOOL_SUCCEEDED(SetConsoleScreenBufferInfoEx(hConsole, &sbiex));
// Verify first line is full of 'a's then 'b's
bufferText = std::make_unique<wchar_t[]>(consoleWidth - 2);
VERIFY_WIN32_BOOL_SUCCEEDED(ReadConsoleOutputCharacterW(hConsole,
bufferText.get(),
consoleWidth - static_cast<SHORT>(2),
{ 0, 0 },
&readSize));
expected = WEX::Common::String(input.c_str(), 2);
actual = WEX::Common::String(bufferText.get(), 2);
VERIFY_ARE_EQUAL(expected, actual);
expected = WEX::Common::String(filled.c_str(), consoleWidth - 4);
actual = WEX::Common::String(&bufferText[2], readSize - 2);
VERIFY_ARE_EQUAL(expected, actual);
// Verify second line is still has 'a's ('b's didn't wrap over)
bufferText = std::make_unique<wchar_t[]>(static_cast<SHORT>(2));
VERIFY_WIN32_BOOL_SUCCEEDED(ReadConsoleOutputCharacterW(hConsole,
bufferText.get(),
static_cast<SHORT>(2),
{ 0, 0 },
&readSize));
VERIFY_ARE_EQUAL(2u, readSize);
expected = WEX::Common::String(input.c_str(), 2);
actual = WEX::Common::String(bufferText.get(), readSize);
VERIFY_ARE_EQUAL(expected, actual);
}
};

View File

@@ -183,7 +183,7 @@ class PtyTests
if (pStartupInfo)
{
size_t attrListSize{};
SIZE_T attrListSize{};
pStartupInfo->StartupInfo.cb = sizeof(STARTUPINFOEXW);

View File

@@ -1378,12 +1378,25 @@ void DoSrvPrivateAllowCursorBlinking(SCREEN_INFORMATION& screenInfo, const bool
coordDestination.X = 0;
coordDestination.Y = viewport.Top + 1;
Status = NTSTATUS_FROM_HRESULT(ServiceLocator::LocateGlobals().api.ScrollConsoleScreenBufferWImpl(screenInfo,
srScroll,
coordDestination,
srScroll,
UNICODE_SPACE,
screenInfo.GetAttributes().GetLegacyAttributes()));
// Here we previously called to ScrollConsoleScreenBufferWImpl to
// perform the scrolling operation. However, that function only
// accepts a WORD for the fill attributes. That means we'd lose
// 256/RGB fidelity for fill attributes. So instead, we'll just call
// ScrollRegion ourselves, with the same params that
// ScrollConsoleScreenBufferWImpl would have.
// See microsoft/terminal#832, #2702 for more context.
try
{
LockConsole();
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
ScrollRegion(screenInfo,
srScroll,
srScroll,
coordDestination,
UNICODE_SPACE,
screenInfo.GetAttributes());
}
CATCH_LOG();
}
}
return Status;
@@ -1406,18 +1419,44 @@ void DoSrvPrivateAllowCursorBlinking(SCREEN_INFORMATION& screenInfo, const bool
// Make sure the cursor doesn't move outside the viewport.
screenInfo.GetViewport().Clamp(clampedPos);
// Make sure the cursor stays inside the margins, but only if it started there
if (screenInfo.AreMarginsSet() && screenInfo.IsCursorInMargins(cursor.GetPosition()))
// Make sure the cursor stays inside the margins
if (screenInfo.AreMarginsSet())
{
try
const auto margins = screenInfo.GetAbsoluteScrollMargins().ToInclusive();
const auto cursorY = cursor.GetPosition().Y;
const auto lo = margins.Top;
const auto hi = margins.Bottom;
// See microsoft/terminal#2929 - If the cursor is _below_ the top
// margin, it should stay below the top margin. If it's _above_ the
// bottom, it should stay above the bottom. Cursor movements that stay
// outside the margins shouldn't necessarily be affected. For example,
// moving up while below the bottom margin shouldn't just jump straight
// to the bottom margin. See
// ScreenBufferTests::CursorUpDownOutsideMargins for a test of that
// behavior.
const bool cursorBelowTop = cursorY >= lo;
const bool cursorAboveBottom = cursorY <= hi;
if (cursorBelowTop)
{
const auto margins = screenInfo.GetAbsoluteScrollMargins().ToInclusive();
const auto v = clampedPos.Y;
const auto lo = margins.Top;
const auto hi = margins.Bottom;
clampedPos.Y = std::clamp(v, lo, hi);
try
{
clampedPos.Y = std::max(clampedPos.Y, lo);
}
CATCH_RETURN();
}
if (cursorAboveBottom)
{
try
{
clampedPos.Y = std::min(clampedPos.Y, hi);
}
CATCH_RETURN();
}
CATCH_RETURN();
}
cursor.SetPosition(clampedPos);

View File

@@ -2599,14 +2599,17 @@ OutputCellIterator SCREEN_INFORMATION::Write(const OutputCellIterator it)
// Arguments:
// - it - Iterator representing output cell data to write.
// - target - The position to start writing at
// - wrap - change the wrap flag if we hit the end of the row while writing and there's still more data
// Return Value:
// - the iterator at its final position
// Note:
// - will throw exception on error.
OutputCellIterator SCREEN_INFORMATION::Write(const OutputCellIterator it,
const COORD target)
const COORD target,
const std::optional<bool> wrap)
{
return _textBuffer->Write(it, target);
// NOTE: if wrap = true/false, we want to set the line's wrap to true/false (respectively) if we reach the end of the line
return _textBuffer->Write(it, target, wrap);
}
// Routine Description:

View File

@@ -131,7 +131,8 @@ public:
OutputCellIterator Write(const OutputCellIterator it);
OutputCellIterator Write(const OutputCellIterator it,
const COORD target);
const COORD target,
const std::optional<bool> wrap = true);
OutputCellIterator WriteRect(const OutputCellIterator it,
const Microsoft::Console::Types::Viewport viewport);

View File

@@ -180,6 +180,7 @@ TARGETLIBS = \
$(MINCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-rtcore-ntuser-window-ext-l1.lib \
$(MINCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-shell-shell32-l1.lib \
$(MINCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-uxtheme-themes-l1.lib \
$(ONECORESHELL_INTERNAL_LIB_VPATH_L)\api-ms-win-shell-namespace-l1.lib \
$(MODERNCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-uiacore-l1.lib \
$(WINCORE_OBJ_PATH)\console\open\src\host\lib\$(O)\conhostv2.lib \
$(WINCORE_OBJ_PATH)\console\conint\$(O)\conint.lib \

View File

@@ -171,7 +171,7 @@ class ScreenBufferTests
TEST_METHOD(DeleteLinesInMargins);
TEST_METHOD(ReverseLineFeedInMargins);
TEST_METHOD(InsertDeleteLines256Colors);
TEST_METHOD(ScrollLines256Colors);
TEST_METHOD(SetOriginMode);
@@ -182,6 +182,10 @@ class ScreenBufferTests
TEST_METHOD(ClearAlternateBuffer);
TEST_METHOD(InitializeTabStopsInVTMode);
TEST_METHOD(CursorUpDownAcrossMargins);
TEST_METHOD(CursorUpDownOutsideMargins);
TEST_METHOD(CursorUpDownExactlyAtMargins);
};
void ScreenBufferTests::SingleAlternateBufferCreationTest()
@@ -3994,10 +3998,10 @@ void ScreenBufferTests::ReverseLineFeedInMargins()
}
}
void ScreenBufferTests::InsertDeleteLines256Colors()
void ScreenBufferTests::ScrollLines256Colors()
{
BEGIN_TEST_METHOD_PROPERTIES()
TEST_METHOD_PROPERTY(L"Data:insert", L"{false, true}")
TEST_METHOD_PROPERTY(L"Data:scrollType", L"{0, 1, 2}")
TEST_METHOD_PROPERTY(L"Data:colorStyle", L"{0, 1, 2}")
END_TEST_METHOD_PROPERTIES();
@@ -4007,16 +4011,22 @@ void ScreenBufferTests::InsertDeleteLines256Colors()
const int Use256Color = 1;
const int UseRGBColor = 2;
bool insert;
// scrollType will be used to control whether we use InsertLines,
// DeleteLines, or ReverseIndex to scroll the contents of the buffer.
const int InsertLines = 0;
const int DeleteLines = 1;
const int ReverseLineFeed = 2;
int scrollType;
int colorStyle;
VERIFY_SUCCEEDED(TestData::TryGetValue(L"insert", insert), L"whether to insert(true) or delete(false) lines");
VERIFY_SUCCEEDED(TestData::TryGetValue(L"scrollType", scrollType), L"controls whether to use InsertLines, DeleteLines ot ReverseLineFeed");
VERIFY_SUCCEEDED(TestData::TryGetValue(L"colorStyle", colorStyle), L"controls whether to use the 16 color table, 256 table, or RGB colors");
// This test is largely taken from repro code from
// https://github.com/microsoft/terminal/issues/832#issuecomment-507447272
Log::Comment(
L"Sets the attributes to a 256/RGB color, then scrolls some lines with"
L" DL. Verifies the rows are cleared with the attributes we'd expect.");
L" IL/DL/RI. Verifies the rows are cleared with the attributes we'd expect.");
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
auto& si = gci.GetActiveOutputBuffer();
@@ -4052,8 +4062,22 @@ void ScreenBufferTests::InsertDeleteLines256Colors()
// Move to home
stateMachine.ProcessString(L"\x1b[H");
// Insert/Delete 10 lines
stateMachine.ProcessString(insert ? L"\x1b[10L" : L"\x1b[10M");
// Insert/Delete/Reverse Index 10 lines
std::wstring scrollSeq = L"";
if (scrollType == InsertLines)
{
scrollSeq = L"\x1b[10L";
}
if (scrollType == DeleteLines)
{
scrollSeq = L"\x1b[10M";
}
if (scrollType == ReverseLineFeed)
{
// This is 10 "Reverse Index" commands, which don't accept a parameter.
scrollSeq = L"\x1bM\x1bM\x1bM\x1bM\x1bM\x1bM\x1bM\x1bM\x1bM\x1bM";
}
stateMachine.ProcessString(scrollSeq);
Log::Comment(NoThrowString().Format(
L"cursor=%s", VerifyOutputTraits<COORD>::ToString(cursor.GetPosition()).GetBuffer()));
@@ -4403,3 +4427,170 @@ void ScreenBufferTests::InitializeTabStopsInVTMode()
VERIFY_IS_TRUE(gci.GetActiveOutputBuffer().AreTabsSet());
}
void ScreenBufferTests::CursorUpDownAcrossMargins()
{
// Test inspired by: https://github.com/microsoft/terminal/issues/2929
// echo -e "\e[6;19r\e[24H\e[99AX\e[1H\e[99BY\e[r"
// This does the following:
// * sets the top and bottom DECSTBM margins to 6 and 19
// * moves to line 24 (i.e. below the bottom margin)
// * executes the CUU sequence with a count of 99, to move up 99 lines
// * writes out X
// * moves to line 1 (i.e. above the top margin)
// * executes the CUD sequence with a count of 99, to move down 99 lines
// * writes out Y
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
auto& si = gci.GetActiveOutputBuffer();
auto& tbi = si.GetTextBuffer();
auto& stateMachine = si.GetStateMachine();
auto& cursor = si.GetTextBuffer().GetCursor();
VERIFY_IS_TRUE(si.GetViewport().BottomInclusive() > 24);
// Set some scrolling margins
stateMachine.ProcessString(L"\x1b[6;19r");
stateMachine.ProcessString(L"\x1b[24H");
VERIFY_ARE_EQUAL(23, cursor.GetPosition().Y);
stateMachine.ProcessString(L"\x1b[99A");
VERIFY_ARE_EQUAL(5, cursor.GetPosition().Y);
stateMachine.ProcessString(L"X");
{
auto iter = tbi.GetCellDataAt({ 0, 5 });
VERIFY_ARE_EQUAL(L"X", iter->Chars());
}
stateMachine.ProcessString(L"\x1b[1H");
VERIFY_ARE_EQUAL(0, cursor.GetPosition().Y);
stateMachine.ProcessString(L"\x1b[99B");
VERIFY_ARE_EQUAL(18, cursor.GetPosition().Y);
stateMachine.ProcessString(L"Y");
{
auto iter = tbi.GetCellDataAt({ 0, 18 });
VERIFY_ARE_EQUAL(L"Y", iter->Chars());
}
stateMachine.ProcessString(L"\x1b[r");
}
void ScreenBufferTests::CursorUpDownOutsideMargins()
{
// Test inspired by the CursorUpDownAcrossMargins test.
// echo -e "\e[6;19r\e[24H\e[1AX\e[1H\e[1BY\e[r"
// This does the following:
// * sets the top and bottom DECSTBM margins to 6 and 19
// * moves to line 24 (i.e. below the bottom margin)
// * executes the CUU sequence with a count of 1, to move up 1 lines (still below margins)
// * writes out X
// * moves to line 1 (i.e. above the top margin)
// * executes the CUD sequence with a count of 1, to move down 1 lines (still above margins)
// * writes out Y
// This test is different becasue the end location of the vertical movement
// should not be within the margins at all. We should not clamp this
// movement to be within the margins.
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
auto& si = gci.GetActiveOutputBuffer();
auto& tbi = si.GetTextBuffer();
auto& stateMachine = si.GetStateMachine();
auto& cursor = si.GetTextBuffer().GetCursor();
VERIFY_IS_TRUE(si.GetViewport().BottomInclusive() > 24);
// Set some scrolling margins
stateMachine.ProcessString(L"\x1b[6;19r");
stateMachine.ProcessString(L"\x1b[24H");
VERIFY_ARE_EQUAL(23, cursor.GetPosition().Y);
stateMachine.ProcessString(L"\x1b[1A");
VERIFY_ARE_EQUAL(22, cursor.GetPosition().Y);
stateMachine.ProcessString(L"X");
{
auto iter = tbi.GetCellDataAt({ 0, 22 });
VERIFY_ARE_EQUAL(L"X", iter->Chars());
}
stateMachine.ProcessString(L"\x1b[1H");
VERIFY_ARE_EQUAL(0, cursor.GetPosition().Y);
stateMachine.ProcessString(L"\x1b[1B");
VERIFY_ARE_EQUAL(1, cursor.GetPosition().Y);
stateMachine.ProcessString(L"Y");
{
auto iter = tbi.GetCellDataAt({ 0, 1 });
VERIFY_ARE_EQUAL(L"Y", iter->Chars());
}
stateMachine.ProcessString(L"\x1b[r");
}
void ScreenBufferTests::CursorUpDownExactlyAtMargins()
{
// Test inspired by the CursorUpDownAcrossMargins test.
// echo -e "\e[6;19r\e[19H\e[1B1\e[1A2\e[6H\e[1A3\e[1B4\e[r"
// This does the following:
// * sets the top and bottom DECSTBM margins to 6 and 19
// * moves to line 19 (i.e. on the bottom margin)
// * executes the CUD sequence with a count of 1, to move down 1 lines (still on the margin)
// * writes out 1
// * executes the CUU sequence with a count of 1, to move up 1 lines (now inside margins)
// * writes out 2
// * moves to line 6 (i.e. on the top margin)
// * executes the CUU sequence with a count of 1, to move up 1 lines (still on the margin)
// * writes out 3
// * executes the CUD sequence with a count of 1, to move down 1 lines (still above margins)
// * writes out 4
// This test is different becasue the starting location for these scroll
// operations is _exactly_ on the margins
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
auto& si = gci.GetActiveOutputBuffer();
auto& tbi = si.GetTextBuffer();
auto& stateMachine = si.GetStateMachine();
auto& cursor = si.GetTextBuffer().GetCursor();
VERIFY_IS_TRUE(si.GetViewport().BottomInclusive() > 24);
// Set some scrolling margins
stateMachine.ProcessString(L"\x1b[6;19r");
stateMachine.ProcessString(L"\x1b[19;1H");
VERIFY_ARE_EQUAL(18, cursor.GetPosition().Y);
stateMachine.ProcessString(L"\x1b[1B");
VERIFY_ARE_EQUAL(18, cursor.GetPosition().Y);
stateMachine.ProcessString(L"1");
{
auto iter = tbi.GetCellDataAt({ 0, 18 });
VERIFY_ARE_EQUAL(L"1", iter->Chars());
}
stateMachine.ProcessString(L"\x1b[1A");
VERIFY_ARE_EQUAL(17, cursor.GetPosition().Y);
stateMachine.ProcessString(L"2");
{
auto iter = tbi.GetCellDataAt({ 1, 17 });
VERIFY_ARE_EQUAL(L"2", iter->Chars());
}
stateMachine.ProcessString(L"\x1b[6;1H");
VERIFY_ARE_EQUAL(5, cursor.GetPosition().Y);
stateMachine.ProcessString(L"\x1b[1A");
VERIFY_ARE_EQUAL(5, cursor.GetPosition().Y);
stateMachine.ProcessString(L"3");
{
auto iter = tbi.GetCellDataAt({ 0, 5 });
VERIFY_ARE_EQUAL(L"3", iter->Chars());
}
stateMachine.ProcessString(L"\x1b[1B");
VERIFY_ARE_EQUAL(6, cursor.GetPosition().Y);
stateMachine.ProcessString(L"4");
{
auto iter = tbi.GetCellDataAt({ 1, 6 });
VERIFY_ARE_EQUAL(L"4", iter->Chars());
}
stateMachine.ProcessString(L"\x1b[r");
}

View File

@@ -77,6 +77,8 @@ class TextBufferTests
TEST_METHOD(TestWrapFlag);
TEST_METHOD(TestWrapThroughWriteLine);
TEST_METHOD(TestDoubleBytePadFlag);
void DoBoundaryTest(PWCHAR const pwszInputString,
@@ -197,6 +199,78 @@ void TextBufferTests::TestWrapFlag()
VERIFY_IS_FALSE(Row.GetCharRow().WasWrapForced());
}
void TextBufferTests::TestWrapThroughWriteLine()
{
TextBuffer& textBuffer = GetTbi();
auto VerifyWrap = [&](bool expected) {
ROW& Row = textBuffer._GetFirstRow();
if (expected)
{
VERIFY_IS_TRUE(Row.GetCharRow().WasWrapForced());
}
else
{
VERIFY_IS_FALSE(Row.GetCharRow().WasWrapForced());
}
};
// Construct string for testing
const auto width = textBuffer.GetSize().Width();
std::wstring chars = L"";
for (auto i = 0; i < width; i++)
{
chars.append(L"a");
}
const auto lineOfText = std::move(chars);
Log::Comment(L"Case 1 : Implicit wrap (false)");
{
TextAttribute expectedAttr(FOREGROUND_RED);
OutputCellIterator it(lineOfText, expectedAttr);
textBuffer.WriteLine(it, { 0, 0 });
VerifyWrap(false);
}
Log::Comment(L"Case 2 : wrap = true");
{
TextAttribute expectedAttr(FOREGROUND_RED);
OutputCellIterator it(lineOfText, expectedAttr);
textBuffer.WriteLine(it, { 0, 0 }, true);
VerifyWrap(true);
}
Log::Comment(L"Case 3: wrap = nullopt (remain as TRUE)");
{
TextAttribute expectedAttr(FOREGROUND_RED);
OutputCellIterator it(lineOfText, expectedAttr);
textBuffer.WriteLine(it, { 0, 0 }, std::nullopt);
VerifyWrap(true);
}
Log::Comment(L"Case 4: wrap = false");
{
TextAttribute expectedAttr(FOREGROUND_RED);
OutputCellIterator it(lineOfText, expectedAttr);
textBuffer.WriteLine(it, { 0, 0 }, false);
VerifyWrap(false);
}
Log::Comment(L"Case 5: wrap = nullopt (remain as false)");
{
TextAttribute expectedAttr(FOREGROUND_RED);
OutputCellIterator it(lineOfText, expectedAttr);
textBuffer.WriteLine(it, { 0, 0 }, std::nullopt);
VerifyWrap(false);
}
}
void TextBufferTests::TestDoubleBytePadFlag()
{
TextBuffer& textBuffer = GetTbi();

View File

@@ -121,12 +121,13 @@ class Microsoft::Console::Render::VtRendererTest
TEST_METHOD(TestResize);
TEST_METHOD(TestCursorVisibility);
void Test16Colors(VtEngine* engine);
std::deque<std::string> qExpectedInput;
bool WriteCallback(const char* const pch, size_t const cch);
void TestPaint(VtEngine& engine, std::function<void()> pfn);
void TestPaintXterm(XtermEngine& engine, std::function<void()> pfn);
Viewport SetUpViewport();
};
@@ -173,38 +174,6 @@ void VtRendererTest::TestPaint(VtEngine& engine, std::function<void()> pfn)
VERIFY_SUCCEEDED(engine.EndPaint());
}
// Function Description:
// - Small helper to do a series of testing wrapped by StartPaint/EndPaint calls
// Also expects \x1b[?25l and \x1b[?25h on start/stop, for cursor visibility
// Arguments:
// - engine: the engine to operate on
// - pfn: A function pointer to some test code to run.
// Return Value:
// - <none>
void VtRendererTest::TestPaintXterm(XtermEngine& engine, std::function<void()> pfn)
{
HRESULT hr = engine.StartPaint();
pfn();
// If we didn't have anything to do on this frame, still execute our
// callback, but don't check for the following ?25h
if (hr != S_FALSE)
{
// If the engine has decided that it needs to disble the cursor, it'll
// insert ?25l to the front of the buffer (which won't hit this
// callback) and write ?25h to the end of the frame
if (engine._needToDisableCursor)
{
qExpectedInput.push_back("\x1b[?25h");
}
}
VERIFY_SUCCEEDED(engine.EndPaint());
VERIFY_ARE_EQUAL(qExpectedInput.size(),
static_cast<size_t>(0),
L"Done painting, there shouldn't be any output we're still expecting");
}
void VtRendererTest::VtSequenceHelperTests()
{
wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE);
@@ -298,7 +267,7 @@ void VtRendererTest::Xterm256TestInvalidate()
L"Make sure that scrolling only invalidates part of the viewport, and sends the right sequences"));
COORD scrollDelta = { 0, 1 };
VERIFY_SUCCEEDED(engine->InvalidateScroll(&scrollDelta));
TestPaintXterm(*engine, [&]() {
TestPaint(*engine, [&]() {
Log::Comment(NoThrowString().Format(
L"---- Scrolled one down, only top line is invalid. ----"));
invalid = view.ToExclusive();
@@ -314,7 +283,7 @@ void VtRendererTest::Xterm256TestInvalidate()
scrollDelta = { 0, 3 };
VERIFY_SUCCEEDED(engine->InvalidateScroll(&scrollDelta));
TestPaintXterm(*engine, [&]() {
TestPaint(*engine, [&]() {
Log::Comment(NoThrowString().Format(
L"---- Scrolled three down, only top 3 lines are invalid. ----"));
invalid = view.ToExclusive();
@@ -328,7 +297,7 @@ void VtRendererTest::Xterm256TestInvalidate()
scrollDelta = { 0, -1 };
VERIFY_SUCCEEDED(engine->InvalidateScroll(&scrollDelta));
TestPaintXterm(*engine, [&]() {
TestPaint(*engine, [&]() {
Log::Comment(NoThrowString().Format(
L"---- Scrolled one up, only bottom line is invalid. ----"));
invalid = view.ToExclusive();
@@ -343,7 +312,7 @@ void VtRendererTest::Xterm256TestInvalidate()
scrollDelta = { 0, -3 };
VERIFY_SUCCEEDED(engine->InvalidateScroll(&scrollDelta));
TestPaintXterm(*engine, [&]() {
TestPaint(*engine, [&]() {
Log::Comment(NoThrowString().Format(
L"---- Scrolled three up, only bottom 3 lines are invalid. ----"));
invalid = view.ToExclusive();
@@ -363,7 +332,7 @@ void VtRendererTest::Xterm256TestInvalidate()
VERIFY_SUCCEEDED(engine->InvalidateScroll(&scrollDelta));
scrollDelta = { 0, 2 };
VERIFY_SUCCEEDED(engine->InvalidateScroll(&scrollDelta));
TestPaintXterm(*engine, [&]() {
TestPaint(*engine, [&]() {
Log::Comment(NoThrowString().Format(
L"---- Scrolled three down, only top 3 lines are invalid. ----"));
invalid = view.ToExclusive();
@@ -557,8 +526,6 @@ void VtRendererTest::Xterm256TestCursor()
L"----move to the start of this line (y stays the same)----"));
qExpectedInput.push_back("\r");
VERIFY_SUCCEEDED(engine->_MoveCursor({ 0, 1 }));
qExpectedInput.push_back("\x1b[?25h");
});
TestPaint(*engine, [&]() {
@@ -629,7 +596,7 @@ void VtRendererTest::XtermTestInvalidate()
L"Make sure that invalidating anything only invalidates that portion"));
SMALL_RECT invalid = { 1, 1, 1, 1 };
VERIFY_SUCCEEDED(engine->Invalidate(&invalid));
TestPaintXterm(*engine, [&]() {
TestPaint(*engine, [&]() {
VERIFY_ARE_EQUAL(invalid, engine->_invalidRect.ToExclusive());
});
@@ -637,7 +604,7 @@ void VtRendererTest::XtermTestInvalidate()
L"Make sure that scrolling only invalidates part of the viewport, and sends the right sequences"));
COORD scrollDelta = { 0, 1 };
VERIFY_SUCCEEDED(engine->InvalidateScroll(&scrollDelta));
TestPaintXterm(*engine, [&]() {
TestPaint(*engine, [&]() {
Log::Comment(NoThrowString().Format(
L"---- Scrolled one down, only top line is invalid. ----"));
invalid = view.ToExclusive();
@@ -652,7 +619,7 @@ void VtRendererTest::XtermTestInvalidate()
scrollDelta = { 0, 3 };
VERIFY_SUCCEEDED(engine->InvalidateScroll(&scrollDelta));
TestPaintXterm(*engine, [&]() {
TestPaint(*engine, [&]() {
Log::Comment(NoThrowString().Format(
L"---- Scrolled three down, only top 3 lines are invalid. ----"));
invalid = view.ToExclusive();
@@ -666,7 +633,7 @@ void VtRendererTest::XtermTestInvalidate()
scrollDelta = { 0, -1 };
VERIFY_SUCCEEDED(engine->InvalidateScroll(&scrollDelta));
TestPaintXterm(*engine, [&]() {
TestPaint(*engine, [&]() {
Log::Comment(NoThrowString().Format(
L"---- Scrolled one up, only bottom line is invalid. ----"));
invalid = view.ToExclusive();
@@ -681,7 +648,7 @@ void VtRendererTest::XtermTestInvalidate()
scrollDelta = { 0, -3 };
VERIFY_SUCCEEDED(engine->InvalidateScroll(&scrollDelta));
TestPaintXterm(*engine, [&]() {
TestPaint(*engine, [&]() {
Log::Comment(NoThrowString().Format(
L"---- Scrolled three up, only bottom 3 lines are invalid. ----"));
invalid = view.ToExclusive();
@@ -701,7 +668,7 @@ void VtRendererTest::XtermTestInvalidate()
VERIFY_SUCCEEDED(engine->InvalidateScroll(&scrollDelta));
scrollDelta = { 0, 2 };
VERIFY_SUCCEEDED(engine->InvalidateScroll(&scrollDelta));
TestPaintXterm(*engine, [&]() {
TestPaint(*engine, [&]() {
Log::Comment(NoThrowString().Format(
L"---- Scrolled three down, only top 3 lines are invalid. ----"));
invalid = view.ToExclusive();
@@ -864,8 +831,6 @@ void VtRendererTest::XtermTestCursor()
L"----move to the start of this line (y stays the same)----"));
qExpectedInput.push_back("\r");
VERIFY_SUCCEEDED(engine->_MoveCursor({ 0, 1 }));
qExpectedInput.push_back("\x1b[?25h");
});
TestPaint(*engine, [&]() {
@@ -1130,14 +1095,14 @@ void VtRendererTest::TestWrapping()
Viewport view = SetUpViewport();
TestPaintXterm(*engine, [&]() {
TestPaint(*engine, [&]() {
Log::Comment(NoThrowString().Format(
L"Make sure the cursor is at 0,0"));
qExpectedInput.push_back("\x1b[H");
VERIFY_SUCCEEDED(engine->_MoveCursor({ 0, 0 }));
});
TestPaintXterm(*engine, [&]() {
TestPaint(*engine, [&]() {
Log::Comment(NoThrowString().Format(
L"Painting a line that wrapped, then painting another line, and "
L"making sure we don't manually move the cursor between those paints."));
@@ -1196,9 +1161,125 @@ void VtRendererTest::TestResize()
VERIFY_SUCCEEDED(engine->UpdateViewport(newView.ToInclusive()));
TestPaintXterm(*engine, [&]() {
TestPaint(*engine, [&]() {
VERIFY_ARE_EQUAL(newView, engine->_invalidRect);
VERIFY_IS_FALSE(engine->_firstPaint);
VERIFY_IS_FALSE(engine->_suppressResizeRepaint);
});
}
void VtRendererTest::TestCursorVisibility()
{
Viewport view = SetUpViewport();
wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE);
auto engine = std::make_unique<Xterm256Engine>(std::move(hFile), _shutdownEvent, p, view, g_ColorTable, static_cast<WORD>(COLOR_TABLE_SIZE));
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn);
// Verify the first paint emits a clear
qExpectedInput.push_back("\x1b[2J");
VERIFY_IS_TRUE(engine->_firstPaint);
VERIFY_IS_FALSE(engine->_lastCursorIsVisible);
VERIFY_IS_TRUE(engine->_nextCursorIsVisible);
TestPaint(*engine, [&]() {
// During StartPaint, we'll mark the cursor as off. make sure that happens.
VERIFY_IS_FALSE(engine->_nextCursorIsVisible);
VERIFY_IS_FALSE(engine->_firstPaint);
});
// The cursor wasn't painted in the last frame.
VERIFY_IS_FALSE(engine->_lastCursorIsVisible);
VERIFY_IS_FALSE(engine->_nextCursorIsVisible);
COORD origin{ 0, 0 };
VERIFY_ARE_NOT_EQUAL(origin, engine->_lastText);
IRenderEngine::CursorOptions options{};
options.coordCursor = origin;
// Frame 1: Paint the cursor at the home position. At the end of the frame,
// the cursor should be on. Because we're moving the cursor with CUP, we
// need to disable the cursor during this frame.
TestPaint(*engine, [&]() {
VERIFY_IS_FALSE(engine->_lastCursorIsVisible);
VERIFY_IS_FALSE(engine->_nextCursorIsVisible);
VERIFY_IS_FALSE(engine->_needToDisableCursor);
Log::Comment(NoThrowString().Format(L"Make sure the cursor is at 0,0"));
qExpectedInput.push_back("\x1b[H");
VERIFY_SUCCEEDED(engine->PaintCursor(options));
VERIFY_IS_TRUE(engine->_nextCursorIsVisible);
VERIFY_IS_TRUE(engine->_needToDisableCursor);
qExpectedInput.push_back("\x1b[?25h");
});
VERIFY_IS_TRUE(engine->_lastCursorIsVisible);
VERIFY_IS_TRUE(engine->_nextCursorIsVisible);
VERIFY_IS_FALSE(engine->_needToDisableCursor);
// Frame 2: Paint the cursor again at the home position. At the end of the
// frame, the cursor should be on, the same as before. We aren't moving the
// cursor during this frame, so _needToDisableCursor will stay false.
TestPaint(*engine, [&]() {
VERIFY_IS_TRUE(engine->_lastCursorIsVisible);
VERIFY_IS_FALSE(engine->_nextCursorIsVisible);
VERIFY_IS_FALSE(engine->_needToDisableCursor);
Log::Comment(NoThrowString().Format(L"If we just paint the cursor again at the same position, the cursor should not need to be disabled"));
VERIFY_SUCCEEDED(engine->PaintCursor(options));
VERIFY_IS_TRUE(engine->_nextCursorIsVisible);
VERIFY_IS_FALSE(engine->_needToDisableCursor);
});
VERIFY_IS_TRUE(engine->_lastCursorIsVisible);
VERIFY_IS_TRUE(engine->_nextCursorIsVisible);
VERIFY_IS_FALSE(engine->_needToDisableCursor);
// Frame 3: Paint the cursor at 2,2. At the end of the frame, the cursor
// should be on, the same as before. Because we're moving the cursor with
// CUP, we need to disable the cursor during this frame.
TestPaint(*engine, [&]() {
VERIFY_IS_TRUE(engine->_lastCursorIsVisible);
VERIFY_IS_FALSE(engine->_nextCursorIsVisible);
VERIFY_IS_FALSE(engine->_needToDisableCursor);
Log::Comment(NoThrowString().Format(L"Move the cursor to 2,2"));
qExpectedInput.push_back("\x1b[3;3H");
options.coordCursor = { 2, 2 };
VERIFY_SUCCEEDED(engine->PaintCursor(options));
VERIFY_IS_TRUE(engine->_lastCursorIsVisible);
VERIFY_IS_TRUE(engine->_nextCursorIsVisible);
VERIFY_IS_TRUE(engine->_needToDisableCursor);
// Because _needToDisableCursor is true, we'll insert a ?25l at the
// start of the frame. Unfortunately, we can't test to make sure that
// it's there, but we can ensure that the matching ?25h is printed:
qExpectedInput.push_back("\x1b[?25h");
});
VERIFY_IS_TRUE(engine->_lastCursorIsVisible);
VERIFY_IS_TRUE(engine->_nextCursorIsVisible);
VERIFY_IS_FALSE(engine->_needToDisableCursor);
// Frame 4: Don't paint the cursor. At the end of the frame, the cursor
// should be off.
Log::Comment(NoThrowString().Format(L"Painting without calling PaintCursor will hide the cursor"));
TestPaint(*engine, [&]() {
VERIFY_IS_TRUE(engine->_lastCursorIsVisible);
VERIFY_IS_FALSE(engine->_nextCursorIsVisible);
VERIFY_IS_FALSE(engine->_needToDisableCursor);
qExpectedInput.push_back("\x1b[?25l");
});
VERIFY_IS_FALSE(engine->_lastCursorIsVisible);
VERIFY_IS_FALSE(engine->_nextCursorIsVisible);
VERIFY_IS_FALSE(engine->_needToDisableCursor);
}

View File

@@ -454,7 +454,7 @@ VOID ConIoSrvComm::CleanupForHeadless(const NTSTATUS status)
ServiceLocator::LocateGlobals().ntstatusConsoleInputInitStatus = status;
// Signal that input is ready to go.
ServiceLocator::LocateGlobals().hConsoleInputInitEvent.SetEvent();
ServiceLocator::LocateGlobals().consoleInputInitializedEvent.SetEvent();
_fIsInputInitialized = true;
}

View File

@@ -54,10 +54,13 @@ DWORD WINAPI ConsoleInputThreadProcOneCore(LPVOID /*lpParam*/)
if (NT_SUCCESS(Status))
{
globals.getConsoleInformation().GetActiveOutputBuffer().RefreshFontWithRenderer();
}
globals.ntstatusConsoleInputInitStatus = Status;
globals.hConsoleInputInitEvent.SetEvent();
globals.ntstatusConsoleInputInitStatus = Status;
globals.consoleInputInitializedEvent.SetEvent();
if (NT_SUCCESS(Status))
{
try
{
// Start listening for input (returns on failure only).

View File

@@ -70,6 +70,7 @@ TARGETLIBS = \
$(MINCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-rtcore-ntuser-window-ext-l1.lib \
$(MINCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-shell-shell32-l1.lib \
$(MINCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-uxtheme-themes-l1.lib \
$(ONECORESHELL_INTERNAL_LIB_VPATH_L)\api-ms-win-shell-namespace-l1.lib \
$(MODERNCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-uiacore-l1.lib \
$(WINCORE_OBJ_PATH)\console\conint\$(O)\conint.lib \
$(WINCORE_OBJ_PATH)\console\open\src\buffer\out\lib\$(O)\conbufferout.lib \

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Build.Tasks.Git" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.SourceLink.Common" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.SourceLink.GitHub" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
</packages>

View File

@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props" Condition="Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props')" />
<Import Project="..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props" Condition="Exists('..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props')" />
<Import Project="..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props" Condition="Exists('..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props')" />
<Import Project="..\common.build.pre.props" />
<ItemGroup>
<ClCompile Include="console.cpp" />
@@ -48,6 +51,7 @@
</ItemGroup>
<ItemGroup>
<None Include="console.def" />
<None Include="packages.config" />
</ItemGroup>
<PropertyGroup Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
@@ -83,4 +87,18 @@
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
<Import Project="..\common.build.dll.props" />
<Import Project="..\common.build.post.props" />
</Project>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets'))" />
</Target>
<Import Project="..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets" Condition="Exists('..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets')" />
<Import Project="..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets" Condition="Exists('..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets')" />
<Import Project="..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets" Condition="Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets')" />
</Project>

View File

@@ -45,9 +45,6 @@
<ClCompile Include="PropSheetHandler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="readLink.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="registry.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -63,6 +60,12 @@
<ClCompile Include="LayoutPage.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ColorControl.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TerminalPage.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="globals.h">
@@ -95,6 +98,12 @@
<ClInclude Include="LayoutPage.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ColorControl.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="TerminalPage.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="console.rc">
@@ -110,5 +119,9 @@
<None Include="console.def">
<Filter>Source Files</Filter>
</None>
<None Include="packages.config" />
</ItemGroup>
</Project>
<ItemGroup>
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
</ItemGroup>
</Project>

View File

@@ -22,7 +22,9 @@ XtermEngine::XtermEngine(_In_ wil::unique_hfile hPipe,
_fUseAsciiOnly(fUseAsciiOnly),
_previousLineWrapped(false),
_usingUnderLine(false),
_needToDisableCursor(false)
_needToDisableCursor(false),
_lastCursorIsVisible(false),
_nextCursorIsVisible(true)
{
// Set out initial cursor position to -1, -1. This will force our initial
// paint to manually move the cursor to 0, 0, not just ignore it.
@@ -45,6 +47,11 @@ XtermEngine::XtermEngine(_In_ wil::unique_hfile hPipe,
_trace.TraceLastText(_lastText);
// Prep us to think that the cursor is not visible this frame. If it _is_
// visible, then PaintCursor will be called, and we'll set this to true
// during the frame.
_nextCursorIsVisible = false;
if (_firstPaint)
{
// MSFT:17815688
@@ -73,14 +80,7 @@ XtermEngine::XtermEngine(_In_ wil::unique_hfile hPipe,
if (!_quickReturn)
{
if (!_WillWriteSingleChar())
{
// MSFT:TODO:20331739
// Make sure to match the cursor visibility in the terminal to the console's
// // Turn off cursor
// RETURN_IF_FAILED(_HideCursor());
}
else
if (_WillWriteSingleChar())
{
// Don't re-enable the cursor.
_quickReturn = true;
@@ -99,22 +99,38 @@ XtermEngine::XtermEngine(_In_ wil::unique_hfile hPipe,
// - S_OK if we succeeded, else an appropriate HRESULT for failing to allocate or write.
[[nodiscard]] HRESULT XtermEngine::EndPaint() noexcept
{
// MSFT:TODO:20331739
// Make sure to match the cursor visibility in the terminal to the console's
// if (!_quickReturn)
// {
// // Turn on cursor
// RETURN_IF_FAILED(_ShowCursor());
// }
// If during the frame we determined that the cursor needed to be disabled,
// then insert a cursor off at the start of the buffer, and re-enable
// the cursor here.
if (_needToDisableCursor)
{
_buffer.insert(0, "\x1b[25l");
// If the cursor was previously visible, let's hide it for this frame,
// by prepending a cursor off.
if (_lastCursorIsVisible)
{
_buffer.insert(0, "\x1b[25l");
_lastCursorIsVisible = false;
}
// If the cursor was NOT previously visible, then that's fine! we don't
// need to worry, it's already off.
}
// If the cursor is moving from off -> on (including cases where we just
// disabled if for this frame), show the cursor at the end of the frame
if (_nextCursorIsVisible && !_lastCursorIsVisible)
{
RETURN_IF_FAILED(_ShowCursor());
}
// Otherwise, if the cursor previously was visible, and it should be hidden
// (on -> off), hide it at the end of the frame.
else if (!_nextCursorIsVisible && _lastCursorIsVisible)
{
RETURN_IF_FAILED(_HideCursor());
}
// Update our tracker of what we thought the last cursor state of the
// terminal was.
_lastCursorIsVisible = _nextCursorIsVisible;
RETURN_IF_FAILED(VtEngine::EndPaint());
@@ -178,6 +194,27 @@ XtermEngine::XtermEngine(_In_ wil::unique_hfile hPipe,
return VtEngine::_16ColorUpdateDrawingBrushes(colorForeground, colorBackground, isBold, _ColorTable, _cColorTable);
}
// Routine Description:
// - Draws the cursor on the screen
// Arguments:
// - options - Options that affect the presentation of the cursor
// Return Value:
// - S_OK or suitable HRESULT error from writing pipe.
[[nodiscard]] HRESULT XtermEngine::PaintCursor(const IRenderEngine::CursorOptions& options) noexcept
{
// PaintCursor is only called when the cursor is in fact visible in a single
// frame. When this is called, mark _nextCursorIsVisible as true. At the end
// of the frame, we'll decide to either turn the cursor on or not, based
// upon the previous state.
// When this method is not called during a frame, it's because the cursor
// was not visible. In that case, at the end of the frame,
// _nextCursorIsVisible will still be false (from when we set it during
// StartPaint)
_nextCursorIsVisible = true;
return VtEngine::PaintCursor(options);
}
// Routine Description:
// - Write a VT sequence to move the cursor to the specified coordinates. We
// also store the last place we left the cursor for future optimizations.

View File

@@ -40,6 +40,8 @@ namespace Microsoft::Console::Render
[[nodiscard]] HRESULT StartPaint() noexcept override;
[[nodiscard]] HRESULT EndPaint() noexcept override;
[[nodiscard]] HRESULT PaintCursor(const CursorOptions& options) noexcept override;
[[nodiscard]] virtual HRESULT UpdateDrawingBrushes(const COLORREF colorForeground,
const COLORREF colorBackground,
const WORD legacyColorAttribute,
@@ -61,6 +63,8 @@ namespace Microsoft::Console::Render
bool _previousLineWrapped;
bool _usingUnderLine;
bool _needToDisableCursor;
bool _lastCursorIsVisible;
bool _nextCursorIsVisible;
[[nodiscard]] HRESULT _MoveCursor(const COORD coord) noexcept override;

View File

@@ -64,7 +64,7 @@ namespace Microsoft::Console::Render
const COORD coordTarget) noexcept override;
[[nodiscard]] HRESULT PaintSelection(const SMALL_RECT rect) noexcept override;
[[nodiscard]] HRESULT PaintCursor(const CursorOptions& options) noexcept override;
[[nodiscard]] virtual HRESULT PaintCursor(const CursorOptions& options) noexcept override;
[[nodiscard]] virtual HRESULT UpdateDrawingBrushes(const COLORREF colorForeground,
const COLORREF colorBackground,

View File

@@ -73,6 +73,7 @@ TARGETLIBS = \
$(MINCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-rtcore-ntuser-window-ext-l1.lib \
$(MINCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-shell-shell32-l1.lib \
$(MINCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-uxtheme-themes-l1.lib \
$(ONECORESHELL_INTERNAL_LIB_VPATH_L)\api-ms-win-shell-namespace-l1.lib \
$(MODERNCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-uiacore-l1.lib \
$(WINCORE_OBJ_PATH)\console\conint\$(O)\conint.lib \
$(WINCORE_OBJ_PATH)\console\open\src\buffer\out\lib\$(O)\conbufferout.lib \

View File

@@ -44,6 +44,17 @@ bool OutputStateMachineEngine::ActionExecute(const wchar_t wch)
{
_dispatch->Execute(wch);
_ClearLastChar();
if (wch == AsciiChars::BEL)
{
// microsoft/terminal#2952
// If we're attached to a terminal, let's also pass the BEL through.
if (_pfnFlushToTerminal != nullptr)
{
_pfnFlushToTerminal();
}
}
return true;
}

View File

@@ -65,6 +65,7 @@ TARGETLIBS = \
$(MINCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-rtcore-ntuser-window-ext-l1.lib \
$(MINCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-shell-shell32-l1.lib \
$(MINCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-uxtheme-themes-l1.lib \
$(ONECORESHELL_INTERNAL_LIB_VPATH_L)\api-ms-win-shell-namespace-l1.lib \
$(MODERNCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-uiacore-l1.lib \
$(WINCORE_OBJ_PATH)\console\conint\$(O)\conint.lib \
$(CONSOLE_OBJ_PATH)\buffer\out\lib\$(O)\conbufferout.lib \

View File

@@ -14,7 +14,7 @@
<RootNamespace>VtPipeTerm</RootNamespace>
<ProjectName>VtPipeTerm</ProjectName>
<TargetName>VtPipeTerm</TargetName>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Build.Tasks.Git" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.SourceLink.Common" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.SourceLink.GitHub" version="1.0.0-beta2-19367-01" targetFramework="native" developmentDependency="true" />
</packages>

View File

@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props" Condition="Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props')" />
<Import Project="..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props" Condition="Exists('..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props')" />
<Import Project="..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props" Condition="Exists('..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props')" />
<Import Project="$(SolutionDir)src\common.build.pre.props" />
<ItemGroup>
<ClCompile Include="winconpty.cpp" />
@@ -8,6 +11,7 @@
</ClCompile>
<ClCompile Include="../server/DeviceHandle.cpp" />
<ClCompile Include="../server/WinNTControl.cpp" />
<None Include="packages.config" />
<None Include="winconpty.def" />
</ItemGroup>
<ItemDefinitionGroup>
@@ -25,13 +29,25 @@
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
<Import Project="$(SolutionDir)src\common.build.dll.props" />
<Import Project="$(SolutionDir)src\common.build.post.props" />
<ItemDefinitionGroup>
<Link>
<ModuleDefinitionFile>winconpty.def</ModuleDefinitionFile>
<!-- Force APISet to the beginning of the link line; GH#922 -->
<AdditionalDependencies>onecoreuap_apiset.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
</Project>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets'))" />
</Target>
<Import Project="..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets" Condition="Exists('..\..\packages\Microsoft.Build.Tasks.Git.1.0.0-beta2-19367-01\build\Microsoft.Build.Tasks.Git.targets')" />
<Import Project="..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets" Condition="Exists('..\..\packages\Microsoft.SourceLink.Common.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.Common.targets')" />
<Import Project="..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets" Condition="Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0-beta2-19367-01\build\Microsoft.SourceLink.GitHub.targets')" />
</Project>